コード例 #1
0
ファイル: SaveLoad.cs プロジェクト: mahoep/BannerlordCoop
        public static SaveOutput SaveGame(TaleWorlds.Core.Game game, ISaveDriver driver)
        {
            EntitySystem <GameHandler> entitySystem =
                Utils.GetPrivateField <EntitySystem <GameHandler> >(
                    typeof(TaleWorlds.Core.Game),
                    "_gameEntitySystem",
                    game);
            MetaData metaData = GetMetaData();

            // Code copied from TaleWorlds.Game.Save(MetaData, ISaveDriver)
            foreach (GameHandler gameHandler in entitySystem.Components)
            {
                gameHandler.OnBeforeSave();
            }

            SaveOutput saveOutput = SaveManager.Save(game, metaData, driver);

            saveOutput.PrintStatus();
            foreach (GameHandler gameHandler2 in entitySystem.Components)
            {
                gameHandler2.OnAfterSave();
            }
            // End code copy

            return(saveOutput);
        }
コード例 #2
0
        protected override async Task <List <int> > SaveExecuteAsync(List <EntryTypeForSave> entities, bool returnIds)
        {
            SaveOutput result = await _behavior.Repository.EntryTypes__Save(
                entities : entities,
                returnIds : returnIds,
                validateOnly : ModelState.IsError,
                top : ModelState.RemainingErrors,
                userId : UserId);

            AddErrorsAndThrowIfInvalid(result.Errors);

            return(result.Ids);
        }
コード例 #3
0
        protected override async Task <List <int> > SaveExecuteAsync(List <DocumentDefinitionForSave> entities, bool returnIds)
        {
            #region Validate

            foreach (var(docDef, docDefIndex) in entities.Indexed())
            {
                if (docDef.LineDefinitions == null || docDef.LineDefinitions.Count == 0)
                {
                    string path = $"[{docDefIndex}].{nameof(DocumentDefinition.LineDefinitions)}";
                    string msg  = _localizer["Error_OneLineDefinitionIsRquired"];

                    ModelState.AddError(path, msg);
                }
                else
                {
                    // Line Definitions that are duplicated within the same document
                    var duplicateIndices = docDef.LineDefinitions
                                           .Select((entity, index) => (entity.LineDefinitionId, index))
                                           .GroupBy(pair => pair.LineDefinitionId)
                                           .Where(g => g.Count() > 1)
                                           .SelectMany(g => g)
                                           .Select((_, index) => index);

                    foreach (var index in duplicateIndices)
                    {
                        string path = $"[{docDefIndex}].{nameof(DocumentDefinition.LineDefinitions)}[{index}].{nameof(DocumentDefinitionLineDefinition.LineDefinitionId)}";
                        string msg  = _localizer["Error_DuplicateLineDefinition"];

                        ModelState.AddError(path, msg);
                    }
                }
            }

            #endregion

            #region Save

            SaveOutput result = await _behavior.Repository.DocumentDefinitions__Save(
                entities : entities,
                returnIds : returnIds,
                validateOnly : ModelState.IsError,
                top : ModelState.RemainingErrors,
                userId : UserId);

            AddErrorsAndThrowIfInvalid(result.Errors);

            return(result.Ids);

            #endregion
        }
コード例 #4
0
        public static string ToFriendlyString(this SaveOutput save)
        {
            if (save.Successful)
            {
                return("Successful save.");
            }

            string sRet = "Errors during save:";

            for (int i = 0; i < save.Errors.Length; i++)
            {
                sRet += Environment.NewLine + $"[{i}] {save.Errors[i]}";
            }

            return(sRet);
        }
コード例 #5
0
 public static SaveOutput Save(object target, MetaData metaData, ISaveDriver driver)
 {
     if (SaveManager._definitionContext == null)
     {
         SaveManager.InitializeGlobalDefinitionContext();
     }
     if (SaveManager._definitionContext.GotError)
     {
         List <SaveError> saveErrorList = new List <SaveError>();
         foreach (string error in SaveManager._definitionContext.Errors)
         {
             saveErrorList.Add(new SaveError(error));
         }
         return(SaveOutput.CreateFailed((IEnumerable <SaveError>)saveErrorList));
     }
     using (new PerformanceTestBlock("Save Context"))
     {
         Debug.Print("Saving with new context");
         SaveContext saveContext = new SaveContext(SaveManager._definitionContext);
         if (saveContext.Save(target, metaData))
         {
             try
             {
                 driver.Save(1, metaData, saveContext.SaveData);
                 return(SaveOutput.CreateSuccessful(saveContext.SaveData));
             }
             catch (Exception ex)
             {
                 return(SaveOutput.CreateFailed((IEnumerable <SaveError>) new SaveError[1]
                 {
                     new SaveError(ex.Message)
                 }));
             }
         }
         else
         {
             return(SaveOutput.CreateFailed((IEnumerable <SaveError>) new SaveError[1]
             {
                 new SaveError("Not implemented")
             }));
         }
     }
 }
コード例 #6
0
ファイル: SaveData.cs プロジェクト: mahoep/BannerlordCoop
        public byte[] SerializeInitialWorldState()
        {
            CampaignEventDispatcher.Instance.OnBeforeSave();

            // Save to memory
            InMemDriver memStream = new InMemDriver();
            SaveOutput  save      = null;

            GameLoopRunner.RunOnMainThread(
                () => save = SaveLoad.SaveGame(TaleWorlds.Core.Game.Current, memStream));
            Logger.Info(save.ToFriendlyString());

            // Write packet
            ByteWriter writer = new ByteWriter();

            writer.Binary.Write((int)ECommand.InitialWorldState);
            writer.Binary.Write(save.Data.GetData());
            return(writer.ToArray());
        }
コード例 #7
0
        protected override async Task <List <int> > SaveExecuteAsync(List <ReportDefinitionForSave> entities, bool returnIds)
        {
            var defs = await _behavior.Definitions();

            var settings = await _behavior.Settings();

            foreach (var(entity, index) in entities.Indexed())
            {
                if (entity.Roles.Any())
                {
                    if (string.IsNullOrWhiteSpace(entity.Title))
                    {
                        string path = $"[{index}].{nameof(entity.Title)}";
                        string msg  = _localizer["Error_TitleIsRequiredWhenShowInMainMenu"];

                        ModelState.AddError(path, msg);
                    }
                }

                foreach (var(parameter, paramIndex) in entity.Parameters.Indexed())
                {
                    // TODO: Need to figure out how to retrieve the default control
                    var errors = ApplicationUtil.ValidateControlOptions(parameter.Control, parameter.ControlOptions, _localizer, settings, defs);
                    foreach (var msg in errors)
                    {
                        ModelState.AddError($"[{index}].{nameof(entity.Parameters)}[{paramIndex}].{nameof(parameter.ControlOptions)}", msg);
                    }
                }
            }

            SaveOutput result = await _behavior.Repository.ReportDefinitions__Save(
                entities : entities,
                returnIds : returnIds,
                validateOnly : ModelState.IsError,
                top : ModelState.RemainingErrors,
                userId : UserId);

            AddErrorsAndThrowIfInvalid(result.Errors);

            return(result.Ids);
        }
コード例 #8
0
        protected override async Task <List <int> > SaveExecuteAsync(List <ResourceDefinitionForSave> entities, bool returnIds)
        {
            foreach (var(entity, index) in entities.Select((e, i) => (e, i)))
            {
                if (entity.DefaultVatRate < 0m || entity.DefaultVatRate > 1m)
                {
                    var path = $"[{index}].{nameof(ResourceDefinition.DefaultVatRate)}";
                    var msg  = _localizer["Error_VatRateMustBeBetweenZeroAndOne"];

                    ModelState.AddError(path, msg);
                }
            }

            SaveOutput result = await _behavior.Repository.ResourceDefinitions__Save(
                entities : entities,
                returnIds : returnIds,
                validateOnly : ModelState.IsError,
                top : ModelState.RemainingErrors,
                userId : UserId);

            AddErrorsAndThrowIfInvalid(result.Errors);

            return(result.Ids);
        }
コード例 #9
0
        public SaveOutput Execute(SaveInput input)
        {
            var output = new SaveOutput();

            if (this.dbFileAccessService.Exists(input.currentDbFile) == false)
            {
                this.dbFileAccessService.CopyDbFile(input.masterDbFile, input.currentDbFile);
            }

            this.dbMigrationService.Upgrade();

            this.projectSettingsAccessService.Update(
                input.StartDate,
                input.EndDate,
                input.Processes,
                input.Functions,
                input.Holidays,
                input.RestDays);

            this.memberAccessService.Update(
                input.Members);

            this.taskAccessService.Update(
                input.Tasks);

            this.processDependencyAccessService.Update(
                input.ProcessDependencies);

            this.functionDependencyAccessService.Update(
                input.FunctionDependencies);

            this.pertAccessService.Update(
                input.Edges);

            return(output);
        }
コード例 #10
0
ファイル: SaveLoad.cs プロジェクト: evorios/BannerlordCoop
        public static SaveGameData SaveGame(Game game, ISaveDriver driver)
        {
            EntitySystem <GameHandler> entitySystem =
                Utils.GetPrivateField <EntitySystem <GameHandler> >(
                    typeof(Game),
                    "_gameEntitySystem",
                    game);
            MetaData metaData = GetMetaData();

            foreach (GameHandler gameHandler in entitySystem.Components)
            {
                gameHandler.OnBeforeSave();
            }

            SaveOutput saveOutput = SaveManager.Save(game, metaData, driver);

            saveOutput.PrintStatus();
            foreach (GameHandler gameHandler2 in entitySystem.Components)
            {
                gameHandler2.OnAfterSave();
            }

            return(new SaveGameData(metaData, saveOutput));
        }
コード例 #11
0
        protected override async Task <List <int> > SaveExecuteAsync(List <DashboardDefinitionForSave> entities, bool returnIds)
        {
            #region Validate

            const int maxOffset = 1000;
            const int maxSize   = 16;

            var defs = await _behavior.Definitions();

            var settings = await _behavior.Settings();

            foreach (var(entity, index) in entities.Indexed())
            {
                if (entity.Roles.Any())
                {
                    if (string.IsNullOrWhiteSpace(entity.Title))
                    {
                        string path = $"[{index}].{nameof(entity.Title)}";
                        string msg  = _localizer["Error_TitleIsRequiredWhenShowInMainMenu"];

                        ModelState.AddError(path, msg);
                    }
                }

                var duplicateReportIds = entity.Widgets
                                         .GroupBy(e => e.ReportDefinitionId)
                                         .Where(g => g.Count() > 1)
                                         .Select(g => g.Key)
                                         .ToHashSet();

                foreach (var(widget, widgetIndex) in entity.Widgets.Indexed())
                {
                    if (widget.OffsetX < 0)
                    {
                        string path = $"[{index}].{nameof(entity.Widgets)}[{widgetIndex}].{nameof(widget.OffsetX)}";
                        string msg  = _localizer["Error_TheField0CannotBeNegative", _localizer["DashboardDefinition_OffsetX"]];

                        ModelState.AddError(path, msg);
                    }

                    if (widget.OffsetX >= maxOffset)
                    {
                        string path = $"[{index}].{nameof(entity.Widgets)}[{widgetIndex}].{nameof(widget.OffsetX)}";
                        string msg  = _localizer["Error_Field0MaximumIs1", _localizer["DashboardDefinition_OffsetX"], maxOffset];

                        ModelState.AddError(path, msg);
                    }

                    if (widget.OffsetY < 0)
                    {
                        string path = $"[{index}].{nameof(entity.Widgets)}[{widgetIndex}].{nameof(widget.OffsetY)}";
                        string msg  = _localizer["Error_TheField0CannotBeNegative", _localizer["DashboardDefinition_OffsetY"]];

                        ModelState.AddError(path, msg);
                    }

                    if (widget.OffsetY >= maxOffset)
                    {
                        string path = $"[{index}].{nameof(entity.Widgets)}[{widgetIndex}].{nameof(widget.OffsetY)}";
                        string msg  = _localizer["Error_Field0MaximumIs1", _localizer["DashboardDefinition_OffsetY"], maxOffset];

                        ModelState.AddError(path, msg);
                    }

                    if (widget.Width < 0)
                    {
                        string path = $"[{index}].{nameof(entity.Widgets)}[{widgetIndex}].{nameof(widget.Width)}";
                        string msg  = _localizer["Error_TheField0CannotBeNegative", _localizer["DashboardDefinition_Width"]];

                        ModelState.AddError(path, msg);
                    }

                    if (widget.Width >= maxSize)
                    {
                        string path = $"[{index}].{nameof(entity.Widgets)}[{widgetIndex}].{nameof(widget.Width)}";
                        string msg  = _localizer["Error_Field0MaximumIs1", _localizer["DashboardDefinition_Width"], maxSize];

                        ModelState.AddError(path, msg);
                    }

                    if (widget.Height < 0)
                    {
                        string path = $"[{index}].{nameof(entity.Widgets)}[{widgetIndex}].{nameof(widget.Height)}";
                        string msg  = _localizer["Error_TheField0CannotBeNegative", _localizer["DashboardDefinition_Height"]];

                        ModelState.AddError(path, msg);
                    }

                    if (widget.Height >= maxSize)
                    {
                        string path = $"[{index}].{nameof(entity.Widgets)}[{widgetIndex}].{nameof(widget.Height)}";
                        string msg  = _localizer["Error_Field0MaximumIs1", _localizer["DashboardDefinition_Height"], maxSize];

                        ModelState.AddError(path, msg);
                    }

                    if (duplicateReportIds.Contains(widget.ReportDefinitionId))
                    {
                        defs.Reports.TryGetValue(widget.ReportDefinitionId.Value, out ReportDefinitionForClient reportDef);
                        string reportName = reportDef == null ? null : settings.Localize(reportDef.Title, reportDef.Title2, reportDef.Title3);
                        string path       = $"[{index}].{nameof(entity.Widgets)}[{widgetIndex}].{nameof(widget.ReportDefinitionId)}";
                        string msg        = _localizer["Error_The01IsDuplicated", _localizer["DashboardDefinition_ReportDefinition"], reportName ?? widget.ReportDefinitionId.ToString()];

                        ModelState.AddError(path, msg);
                    }
                }
            }

            #endregion

            #region Save

            // Save
            SaveOutput result = await _behavior.Repository.DashboardDefinitions__Save(
                entities : entities,
                returnIds : returnIds,
                validateOnly : ModelState.IsError,
                top : ModelState.RemainingErrors,
                userId : UserId);

            AddErrorsAndThrowIfInvalid(result.Errors);

            // Return
            return(result.Ids);

            #endregion
        }
コード例 #12
0
        protected override async Task <List <int> > SaveExecuteAsync(List <PrintingTemplateForSave> entities, bool returnIds)
        {
            var definitionedCollections = new string[]
            {
                nameof(Document),
                nameof(Resource),
                nameof(Agent),
                nameof(Lookup)
            };

            foreach (var(entity, index) in entities.Indexed())
            {
                if (entity.Usage == TemplateUsages.FromSearchAndDetails || entity.Usage == TemplateUsages.FromDetails)
                {
                    if (entity.Collection == null)
                    {
                        ModelState.AddError($"[{index}].Collection", _localizer[ErrorMessages.Error_Field0IsRequired, _localizer["Template_Collection"]]);
                    }
                    else
                    {
                        if (definitionedCollections.Contains(entity.Collection))
                        {
                            // DefinitionId is required when querying by Id
                            if (entity.Usage == TemplateUsages.FromDetails && entity.DefinitionId == null)
                            {
                                ModelState.AddError($"[{index}].DefinitionId", _localizer[ErrorMessages.Error_Field0IsRequired, _localizer["Template_DefinitionId"]]);
                            }
                        }
                        else
                        {
                            entity.DefinitionId = null;
                        }
                    }
                }

                if (entity.Usage == TemplateUsages.FromReport)
                {
                    if (entity.ReportDefinitionId == null)
                    {
                        ModelState.AddError($"[{index}].ReportDefinitionId", _localizer[ErrorMessages.Error_Field0IsRequired, _localizer["Template_ReportDefinitionId"]]);
                    }
                }

                // TODO Check that DefinitionId is compatible with Collection


                var duplicateKeys = entity
                                    .Parameters
                                    .Select(e => e.Key)
                                    .GroupBy(e => e)
                                    .Where(e => e.Count() > 1)
                                    .Select(e => e.FirstOrDefault())
                                    .ToHashSet();

                // Validate parameters
                foreach (var(parameter, parameterIndex) in entity.Parameters.Indexed())
                {
                    if (!TemplexVariable.IsValidVariableName(parameter.Key))
                    {
                        var path = $"[{index}].{nameof(entity.Parameters)}[{parameterIndex}].{nameof(parameter.Key)}";
                        var msg  = "Invalid Key. Valid keys contain only alphanumeric characters, dollar symbols, and underscores and do not start with a number.";
                        ModelState.AddError(path, msg);
                    }
                    else if (duplicateKeys.Contains(parameter.Key))
                    {
                        var path = $"[{index}].{nameof(entity.Parameters)}[{parameterIndex}].{nameof(parameter.Key)}";
                        var msg  = $"The Key '{parameter.Key}' is used more than once.";
                        ModelState.AddError(path, msg);
                    }
                }
            }

            SaveOutput result = await _behavior.Repository.PrintingTemplates__Save(
                entities : entities,
                returnIds : returnIds,
                validateOnly : ModelState.IsError,
                top : ModelState.RemainingErrors,
                userId : UserId);

            AddErrorsAndThrowIfInvalid(result.Errors);

            return(result.Ids);
        }
コード例 #13
0
        protected override async Task <List <int> > SaveExecuteAsync(List <ExchangeRateForSave> entities, bool returnIds)
        {
            #region Validate

            var settings = await _behavior.Settings();

            var functionalId = settings.FunctionalCurrencyId;

            var currencyDateHash = entities
                                   .GroupBy(e => new { e.CurrencyId, e.ValidAsOf })
                                   .Where(g => g.Count() > 1)
                                   .SelectMany(g => g)
                                   .ToHashSet();

            // Get the currencies that contribute to duplications, so that we can put their names in the error message
            // Get them outside the loop in a single DB query (for performance)
            string[]        duplicateCurrenciesIdArray = null;
            List <Currency> duplicateCurrencies        = null;
            Dictionary <string, Currency> duplicateCurrenciesDictionary = null;

            foreach (var(entity, index) in entities.Select((e, i) => (e, i)))
            {
                // Currency cannot be functional
                if (entity.CurrencyId == functionalId)
                {
                    ModelState.AddError($"[{index}].{nameof(ExchangeRate.CurrencyId)}",
                                        _localizer["Error_TheCurrencyMustBeDifferentThanFunctional"]);
                }

                if (entity.ValidAsOf > DateTime.Today.AddDays(1))
                {
                    ModelState.AddError($"[{index}].{nameof(ExchangeRate.ValidAsOf)}",
                                        _localizer["Error_TheValidAsOfDateCannotBeInTheFuture"]);
                }

                // Amounts must be >= 1
                if (entity.AmountInCurrency <= 0m)
                {
                    ModelState.AddError($"[{index}].{nameof(ExchangeRate.AmountInCurrency)}",
                                        _localizer["Error_TheAmountInCurrencyMustBeGreaterThanZero"]);
                }

                // Amounts must be >= 1
                if (entity.AmountInFunctional <= 0m)
                {
                    ModelState.AddError($"[{index}].{nameof(ExchangeRate.AmountInFunctional)}",
                                        _localizer["Error_TheAmountInFunctionalMustBeGreaterThanZero"]);
                }

                // Currency and date must not be duplicated in the uploaded list
                if (currencyDateHash.Contains(entity))
                {
                    // Populate these ones for efficient subsequent passes
                    duplicateCurrenciesIdArray ??= currencyDateHash.Select(e => e.CurrencyId).Distinct().ToArray();
                    duplicateCurrencies ??= await _behavior.Repository.Currencies.FilterByIds(duplicateCurrenciesIdArray).ToListAsync(QueryContext, cancellation: default);

                    duplicateCurrenciesDictionary ??= duplicateCurrencies.ToDictionary(e => e.Id);

                    var currency     = duplicateCurrenciesDictionary[entity.CurrencyId];
                    var currencyName = settings.Localize(currency.Name, currency.Name2, currency.Name3);

                    ModelState.AddError($"[{index}].{nameof(ExchangeRate.CurrencyId)}",
                                        _localizer["Error_TheCurrency0Date1AreDuplicated", currencyName, entity.ValidAsOf.Value.ToString("yyyy-MM-dd")]);
                }
            }

            #endregion

            #region Save

            SaveOutput result = await _behavior.Repository.ExchangeRates__Save(
                entities : entities,
                returnIds : returnIds,
                validateOnly : ModelState.IsError,
                top : ModelState.RemainingErrors,
                userId : UserId);

            AddErrorsAndThrowIfInvalid(result.Errors);

            return(result.Ids);

            #endregion
        }
コード例 #14
0
        protected override async Task <List <int> > SaveExecuteAsync(List <NotificationTemplateForSave> entities, bool returnIds)
        {
            #region Validation

            var definitionedCollections = new string[]
            {
                nameof(Document),
                nameof(Resource),
                nameof(Agent),
                nameof(Lookup)
            };

            foreach (var(entity, index) in entities.Indexed())
            {
                if (entity.Cardinality == Cardinalities.Bulk)
                {
                    // ListExpression
                    if (string.IsNullOrWhiteSpace(entity.ListExpression))
                    {
                        var path = $"[{index}].{nameof(entity.ListExpression)}";
                        var msg  = _localizer[ErrorMessages.Error_Field0IsRequired, _localizer["NotificationTemplate_ListExpression"]];
                        ModelState.AddError(path, msg);
                    }
                    else
                    {
                        try
                        {
                            TemplexBase.Parse(entity.ListExpression);
                        }
                        catch
                        {
                            var path = $"[{index}].{nameof(entity.ListExpression)}";
                            var msg  = _localizer["Error_InvalidTemplateExpression0", entity.ListExpression];
                            ModelState.AddError(path, msg);
                        }
                    }

                    // AddressExpression
                    if (string.IsNullOrWhiteSpace(entity.AddressExpression))
                    {
                        var path = $"[{index}].{nameof(entity.AddressExpression)}";
                        var msg  = _localizer[ErrorMessages.Error_Field0IsRequired, _localizer["NotificationTemplate_AddressExpression"]];
                        ModelState.AddError(path, msg);
                    }
                    else
                    {
                        try
                        {
                            TemplexBase.Parse(entity.AddressExpression);
                        }
                        catch
                        {
                            var path = $"[{index}].{nameof(entity.AddressExpression)}";
                            var msg  = _localizer["Error_InvalidTemplateExpression0", entity.AddressExpression];
                            ModelState.AddError(path, msg);
                        }
                    }
                }

                if (entity.Trigger == Triggers.Automatic)
                {
                    // Schedule
                    if (string.IsNullOrWhiteSpace(entity.Schedule))
                    {
                        var path = $"[{index}].{nameof(entity.Schedule)}";
                        var msg  = _localizer[ErrorMessages.Error_Field0IsRequired, _localizer["NotificationTemplate_Schedule"]];
                        ModelState.AddError(path, msg);
                    }
                    else
                    {
                        string faultyCron = null;
                        try
                        {
                            var crons = entity.Schedule.Split(';')
                                        .Where(e => !string.IsNullOrWhiteSpace(e))
                                        .Select(e => e.Trim());

                            foreach (var cron in crons)
                            {
                                faultyCron = cron;
                                CronExpression.Parse(cron);
                            }
                        }
                        catch
                        {
                            var path = $"[{index}].{nameof(entity.Schedule)}";
                            var msg  = _localizer["Error_InvalidCronExpression0", faultyCron];
                            ModelState.AddError(path, msg);
                        }
                    }

                    if (string.IsNullOrWhiteSpace(entity.ConditionExpression))
                    {
                        // Doesn't matter
                    }
                    else
                    {
                        try
                        {
                            TemplexBase.Parse(entity.ConditionExpression);
                        }
                        catch
                        {
                            var path = $"[{index}].{nameof(entity.ConditionExpression)}";
                            var msg  = _localizer["Error_InvalidTemplateExpression0", entity.ConditionExpression];
                            ModelState.AddError(path, msg);
                        }
                    }
                }

                if (entity.Trigger == Triggers.Manual)
                {
                    // Usage
                    if (string.IsNullOrWhiteSpace(entity.Usage))
                    {
                        var path = $"[{index}].{nameof(entity.Usage)}";
                        var msg  = _localizer[ErrorMessages.Error_Field0IsRequired, _localizer["Template_Usage"]];
                        ModelState.AddError(path, msg);
                    }
                    else if (entity.Usage == TemplateUsages.FromSearchAndDetails || entity.Usage == TemplateUsages.FromDetails)
                    {
                        if (string.IsNullOrWhiteSpace(entity.Collection))
                        {
                            var path = $"[{index}].{nameof(entity.Collection)}";
                            var msg  = _localizer[ErrorMessages.Error_Field0IsRequired, _localizer["Template_Collection"]];
                            ModelState.AddError(path, msg);
                        }
                        else
                        {
                            if (definitionedCollections.Contains(entity.Collection))
                            {
                                // DefinitionId is required when querying by Id
                                if (entity.Usage == TemplateUsages.FromDetails && entity.DefinitionId == null)
                                {
                                    var path = $"[{index}].{nameof(entity.DefinitionId)}";
                                    var msg  = _localizer[ErrorMessages.Error_Field0IsRequired, _localizer["Template_DefinitionId"]];
                                    ModelState.AddError(path, msg);
                                }
                            }
                            else
                            {
                                entity.DefinitionId = null;
                            }
                        }
                    }
                    else if (entity.Usage == TemplateUsages.FromReport)
                    {
                        if (entity.ReportDefinitionId == null)
                        {
                            var path = $"[{index}].{nameof(entity.ReportDefinitionId)}";
                            var msg  = _localizer[ErrorMessages.Error_Field0IsRequired, _localizer["Template_ReportDefinitionId"]];
                            ModelState.AddError(path, msg);
                        }
                    }

                    // TODO Check that DefinitionId is compatible with Collection
                }

                if (entity.Channel == Channels.Email)
                {
                    // Subject
                    if (string.IsNullOrWhiteSpace(entity.Subject))
                    {
                        var path = $"[{index}].{nameof(entity.Subject)}";
                        var msg  = _localizer[ErrorMessages.Error_Field0IsRequired, _localizer["NotificationTemplate_Subject"]];
                        ModelState.AddError(path, msg);
                    }
                    else
                    {
                        try
                        {
                            TemplateTree.Parse(entity.Subject);
                        }
                        catch
                        {
                            var path = $"[{index}].{nameof(entity.Subject)}";
                            var msg  = _localizer["Error_InvalidTemplate"];
                            ModelState.AddError(path, msg);
                        }
                    }
                }

                // Body
                if (!string.IsNullOrWhiteSpace(entity.Body))
                {
                    if (entity.Channel == Channels.Sms)
                    {
                        const int maxSmsExpressionLength = 1024;
                        if (entity.Body.Length > maxSmsExpressionLength)
                        {
                            var path = $"[{index}].{nameof(entity.Body)}";
                            var msg  = _localizer[ErrorMessages.Error_Field0LengthMaximumOf1, _localizer["Template_Body"], maxSmsExpressionLength];
                            ModelState.AddError(path, msg);
                        }
                    }

                    try
                    {
                        TemplateTree.Parse(entity.Body);
                    }
                    catch
                    {
                        var path = $"[{index}].{nameof(entity.Body)}";
                        var msg  = _localizer["Error_InvalidTemplate"];
                        ModelState.AddError(path, msg);
                    }
                }

                // Caption
                try
                {
                    TemplateTree.Parse(entity.Caption);
                }
                catch
                {
                    var path = $"[{index}].{nameof(entity.Caption)}";
                    var msg  = _localizer["Error_InvalidTemplate"];
                    ModelState.AddError(path, msg);
                }

                var duplicateKeys = entity
                                    .Parameters
                                    .Select(e => e.Key)
                                    .GroupBy(e => e)
                                    .Where(e => e.Count() > 1)
                                    .Select(e => e.FirstOrDefault())
                                    .ToHashSet();

                // Parameters
                foreach (var(parameter, parameterIndex) in entity.Parameters.Indexed())
                {
                    if (!TemplexVariable.IsValidVariableName(parameter.Key))
                    {
                        var path = $"[{index}].{nameof(entity.Parameters)}[{parameterIndex}].{nameof(parameter.Key)}";
                        var msg  = "Invalid Key. Valid keys contain only alphanumeric characters, dollar symbols, and underscores and do not start with a number.";
                        ModelState.AddError(path, msg);
                    }
                    else if (duplicateKeys.Contains(parameter.Key))
                    {
                        var path = $"[{index}].{nameof(entity.Parameters)}[{parameterIndex}].{nameof(parameter.Key)}";
                        var msg  = $"The Key '{parameter.Key}' is used more than once.";
                        ModelState.AddError(path, msg);
                    }
                }

                // Attachments
                foreach (var(attachment, attachmentIndex) in entity.Attachments.Indexed())
                {
                    if (!string.IsNullOrWhiteSpace(attachment.ContextOverride))
                    {
                        try
                        {
                            TemplexBase.Parse(attachment.ContextOverride);
                        }
                        catch
                        {
                            var path = $"[{index}].{nameof(entity.Attachments)}[{attachmentIndex}].{nameof(attachment.ContextOverride)}";
                            var msg  = _localizer["Error_InvalidTemplateExpression0", attachment.ContextOverride];
                            ModelState.AddError(path, msg);
                        }
                    }

                    if (!string.IsNullOrWhiteSpace(attachment.DownloadNameOverride))
                    {
                        try
                        {
                            TemplateTree.Parse(attachment.DownloadNameOverride);
                        }
                        catch
                        {
                            var path = $"[{index}].{nameof(entity.Attachments)}[{attachmentIndex}].{nameof(attachment.DownloadNameOverride)}";
                            var msg  = _localizer["Error_InvalidTemplate0", attachment.DownloadNameOverride];
                            ModelState.AddError(path, msg);
                        }
                    }
                }

                // Subscribers
                foreach (var(subscriber, subscriberIndex) in entity.Subscribers.Indexed())
                {
                    if (subscriber.AddressType == AddressTypes.User)
                    {
                        if (subscriber.UserId == null)
                        {
                            var path = $"[{index}].{nameof(entity.Subscribers)}[{subscriberIndex}].{nameof(subscriber.UserId)}";
                            var msg  = _localizer[ErrorMessages.Error_Field0IsRequired, _localizer["NotificationTemplate_User"]];
                            ModelState.AddError(path, msg);
                        }
                    }

                    if (subscriber.AddressType == AddressTypes.Text)
                    {
                        if (entity.Channel == Channels.Email)
                        {
                            if (string.IsNullOrWhiteSpace(subscriber.Email))
                            {
                                var path = $"[{index}].{nameof(entity.Subscribers)}[{subscriberIndex}].{nameof(subscriber.Email)}";
                                var msg  = _localizer[ErrorMessages.Error_Field0IsRequired, _localizer["NotificationTemplate_Email"]];
                                ModelState.AddError(path, msg);
                            }
                            else
                            {
                                try
                                {
                                    TemplateTree.Parse(subscriber.Email);
                                }
                                catch
                                {
                                    var path = $"[{index}].{nameof(entity.Subscribers)}[{subscriberIndex}].{nameof(subscriber.Email)}";
                                    var msg  = _localizer["Error_InvalidTemplate"];
                                    ModelState.AddError(path, msg);
                                }
                            }
                        }

                        if (entity.Channel == Channels.Sms)
                        {
                            if (string.IsNullOrWhiteSpace(subscriber.Phone))
                            {
                                var path = $"[{index}].{nameof(entity.Subscribers)}[{subscriberIndex}].{nameof(subscriber.Phone)}";
                                var msg  = _localizer[ErrorMessages.Error_Field0IsRequired, _localizer["NotificationTemplate_Phone"]];
                                ModelState.AddError(path, msg);
                            }
                            else
                            {
                                try
                                {
                                    TemplateTree.Parse(subscriber.Phone);
                                }
                                catch
                                {
                                    var path = $"[{index}].{nameof(entity.Subscribers)}[{subscriberIndex}].{nameof(subscriber.Phone)}";
                                    var msg  = _localizer["Error_InvalidTemplate"];
                                    ModelState.AddError(path, msg);
                                }
                            }
                        }
                    }
                }
            }

            #endregion

            SaveOutput result = await _behavior.Repository.NotificationTemplates__Save(
                entities : entities,
                returnIds : returnIds,
                validateOnly : ModelState.IsError,
                top : ModelState.RemainingErrors,
                userId : UserId);

            AddErrorsAndThrowIfInvalid(result.Errors);

            return(result.Ids);
        }
コード例 #15
0
 public SaveGameData([NotNull] MetaData metaData, [NotNull] SaveOutput saveOutput)
 {
     MetaData   = metaData;
     SaveOutput = saveOutput;
 }
コード例 #16
0
ファイル: RolesService.cs プロジェクト: tellma-ltd/tellma
        protected override async Task <List <int> > SaveExecuteAsync(List <RoleForSave> entities, bool returnIds)
        {
            // Hash the indices for performance
            var indices = entities.ToIndexDictionary();

            // Check that line ids are unique
            entities.ForEach(e => { if (e.Permissions == null)
                                    {
                                        e.Permissions = new List <PermissionForSave>();
                                    }
                             });
            var duplicatePermissionId = entities.SelectMany(e => e.Permissions)                             // All lines
                                        .Where(e => e.Id != 0).GroupBy(e => e.Id).Where(g => g.Count() > 1) // Duplicate Ids
                                        .SelectMany(g => g).ToDictionary(e => e, e => e.Id);                // to dictionary

            // Check that line ids are unique
            entities.ForEach(e => { if (e.Members == null)
                                    {
                                        e.Members = new List <RoleMembershipForSave>();
                                    }
                             });
            var duplicateMembershipId = entities.SelectMany(e => e.Members)                                 // All lines
                                        .Where(e => e.Id != 0).GroupBy(e => e.Id).Where(g => g.Count() > 1) // Duplicate Ids
                                        .SelectMany(g => g).ToDictionary(e => e, e => e.Id);                // to dictionary

            foreach (var entity in entities)
            {
                var permissionIndices = entity.Permissions.ToIndexDictionary();
                foreach (var line in entity.Permissions)
                {
                    if (duplicatePermissionId.ContainsKey(line))
                    {
                        // This error indicates a bug
                        var index     = indices[entity];
                        var lineIndex = permissionIndices[line];
                        var id        = duplicatePermissionId[line];
                        ModelState.AddError($"[{index}].{nameof(entity.Permissions)}[{lineIndex}].{nameof(entity.Id)}",
                                            _localizer["Error_TheEntityWithId0IsSpecifiedMoreThanOnce", id]);
                    }
                }

                var membersIndices = entity.Members.ToIndexDictionary();
                foreach (var line in entity.Members)
                {
                    if (duplicateMembershipId.ContainsKey(line))
                    {
                        // This error indicates a bug
                        var index     = indices[entity];
                        var lineIndex = membersIndices[line];
                        var id        = duplicateMembershipId[line];
                        ModelState.AddError($"[{index}].{nameof(entity.Members)}[{lineIndex}].{nameof(entity.Id)}",
                                            _localizer["Error_TheEntityWithId0IsSpecifiedMoreThanOnce", id]);
                    }
                }
            }

            // TODO Validate Criteria

            // Save
            SaveOutput result = await _behavior.Repository.Roles__Save(
                entities : entities,
                returnIds : returnIds,
                validateOnly : ModelState.IsError,
                top : ModelState.RemainingErrors,
                userId : UserId);

            AddErrorsAndThrowIfInvalid(result.Errors);

            return(result.Ids);
        }