async Task <CommandResultBase> UpdateShellFeatureVersionAsync(IShellFeature feature, string newVersion) { var result = new CommandResultBase(); // Ensure the version is valid if (newVersion.ToVersion() == null) { return(result.Failed( $"The version '{newVersion}' for feature '{feature.ModuleId}' is not a valid version. Versions must contain major, minor & build numbers. For example 1.0.0, 2.4.0 or 3.2.1")); } // Update version feature.Version = newVersion; // Update shell features var shellFeature = await _shellFeatureStore.UpdateAsync((ShellFeature)feature); // Ensure the update was successful before updating shell descriptor if (shellFeature == null) { return(result.Failed( $"Could not update shell feature. An error occurred whilst updating the version for feature {feature.ModuleId} to version {newVersion}.")); } // First get all existing enabled features var enabledFeatures = await _shellDescriptorManager.GetEnabledFeaturesAsync(); // Update version for enabled feature var descriptor = new ShellDescriptor(); foreach (var enabledFeature in enabledFeatures) { if (enabledFeature.ModuleId.Equals(feature.ModuleId, StringComparison.OrdinalIgnoreCase)) { enabledFeature.Version = newVersion; } descriptor.Modules.Add(new ShellModule(enabledFeature)); } // Ensure we have a descriptor if (descriptor.Modules?.Count == 0) { return(result.Failed("A valid shell descriptor could not be constructed.")); } // Update shell descriptor var updatedDescriptor = await _shellDescriptorStore.SaveAsync(descriptor); if (updatedDescriptor == null) { return(result.Failed( $"Could not update shell descriptor. An error occurred whilst updating the version for feature {feature.ModuleId} to version {newVersion}.")); } return(result.Success()); }
async Task <ICommandResultBase> CreateIndexesInternalAsync(string catalogName) { // Build result var result = new CommandResultBase(); // Get installed indexes from database var installedIndexes = await _fullTextIndexStore.SelectIndexesAsync(); // Get all provided indexes var providedIndexes = _fullTextIndexManager.GetIndexes(); // Interate provided indexes foreach (var providedIndex in providedIndexes) { // Attempt to get existing index within database var existingIndex = installedIndexes?.FirstOrDefault(i => i.TableName == providedIndex.TableName && providedIndex.ColumnNames.Contains(i.ColumnName)); // Index does not already exist within the database if (existingIndex == null) { // Get table name with prefix var tableName = GetTableName(providedIndex.TableName); // Get primary key constraint for table var primaryKey = await _constraintStore.GetPrimaryKeyConstraint(tableName); if (primaryKey == null) { return(result.Failed($"Could not find a primary key constraint for table {tableName}")); } // Create the index var createIndex = await _fullTextIndexCommand.CreateAsync(new SchemaFullTextIndex() { PrimaryKeyName = primaryKey.ConstraintName, TableName = providedIndex.TableName, ColumnNames = providedIndex.ColumnNames, LanguageCode = providedIndex.LanguageCode, FillFactor = providedIndex.FillFactor, CatalogName = catalogName }); if (!createIndex.Succeeded) { return(result.Failed(createIndex.Errors.ToArray())); } } } return(result.Success()); }
async Task <ICommandResultBase> AuthorizeAsync(IEntity entity) { // Our result var result = new CommandResultBase(); // Generic failure message const string error = "Unauthorized"; // IsHidden if (entity.IsHidden) { if (!await _authorizationService.AuthorizeAsync(HttpContext.User, entity.CategoryId, Permissions.ViewHiddenArticles)) { return(result.Failed(error)); } } // IsPrivate if (entity.IsPrivate) { if (!await _authorizationService.AuthorizeAsync(HttpContext.User, entity.CategoryId, Permissions.ViewPrivateArticles)) { return(result.Failed(error)); } } // IsSpam if (entity.IsSpam) { if (!await _authorizationService.AuthorizeAsync(HttpContext.User, entity.CategoryId, Permissions.ViewSpamArticles)) { return(result.Failed(error)); } } // IsDeleted if (entity.IsDeleted) { if (!await _authorizationService.AuthorizeAsync(HttpContext.User, entity.CategoryId, Permissions.ViewDeletedArticles)) { return(result.Failed(error)); } } return(result.Success()); }
async Task <ICommandResultBase> InstallInternalAsync(IShellFeature feature, string tag) { // Validate if (feature == null) { throw new ArgumentNullException(nameof(feature)); } if (string.IsNullOrEmpty(feature.ModuleId)) { throw new ArgumentNullException(nameof(feature.ModuleId)); } var user = await _contextFacade.GetAuthenticatedUserAsync(); // Our result var result = new CommandResultBase(); var categoryResult = await _tagManager.CreateAsync(new TagBase() { FeatureId = feature.Id, Name = tag, Description = $"An example desccription for the '{tag}' tag within '{feature.ModuleId}'.", CreatedUserId = user?.Id ?? 0, CreatedDate = DateTimeOffset.UtcNow }); if (!categoryResult.Succeeded) { return(result.Failed(result.Errors.ToArray())); } return(result.Success()); }
// ---------- async Task <ICommandResultBase> InstallCategoriesAsync(IShellFeature feature) { // Validate if (feature == null) { throw new ArgumentNullException(nameof(feature)); } if (string.IsNullOrEmpty(feature.ModuleId)) { throw new ArgumentNullException(nameof(feature.ModuleId)); } // Our result var result = new CommandResultBase(); foreach (var tag in ExampleTags) { var categoryResult = await InstallInternalAsync(feature, tag); if (!categoryResult.Succeeded) { return(result.Failed(categoryResult.Errors.ToArray())); } } return(result.Success()); }
public async Task <ICommandResultBase> InstallAsync() { var output = new CommandResultBase(); foreach (var descriptor in Descriptors) { var feature = await _featureFacade.GetFeatureByIdAsync(descriptor.ModuleId); if (feature == null) { continue; } var result = await InstallCategoriesAsync(feature); if (result.Succeeded) { // Install default roles for all feature categories await _defaultCategoryRolesManager.InstallAsync(feature.Id); } else { return(output.Failed(result.Errors.ToArray())); } } return(output.Success()); }
// ---------- async Task <ICommandResultBase> InstallLabelsAsync(IShellFeature feature) { // Validate if (feature == null) { throw new ArgumentNullException(nameof(feature)); } if (string.IsNullOrEmpty(feature.ModuleId)) { throw new ArgumentNullException(nameof(feature.ModuleId)); } // Our result var result = new CommandResultBase(); for (var i = 0; i < 10; i++) { var categoryResult = await InstallLabelAsync(feature, i); if (!categoryResult.Succeeded) { return(result.Failed(categoryResult.Errors.ToArray())); } } return(result.Success()); }
async Task <ICommandResultBase> UninstallInternalAsync() { var sb = new StringBuilder(); var i = 0; foreach (var userName in Usernames) { sb.Append("'") .Append(userName.Replace("'", "''")) .Append("'"); if (i < Usernames.Length - 1) { sb.Append(", "); } i++; } // Replacements for SQL script var replacements = new Dictionary <string, string>() { ["{userNames}"] = sb.ToString() }; var sql = @" DELETE FROM {prefix}_UserBadges WHERE UserId IN ( SELECT Id FROM {prefix}_Users WHERE UserName IN ({userNames}) ); DELETE FROM {prefix}_UserPhoto WHERE UserId IN ( SELECT Id FROM {prefix}_Users WHERE UserName IN ({userNames}) ); DELETE FROM {prefix}_UserData WHERE UserId IN ( SELECT Id FROM {prefix}_Users WHERE UserName IN ({userNames}) ); DELETE FROM {prefix}_Users WHERE UserName IN ({userNames}); "; // Our result var result = new CommandResultBase(); // Execute and return result var error = string.Empty; try { await _dbHelper.ExecuteScalarAsync <int>(sql, replacements); } catch (Exception e) { error = e.Message; } return(!string.IsNullOrEmpty(error) ? result.Failed(error) : result.Success()); }
// ------------------ async Task <ICommandResultBase> InstallEntitiesAsync(SampleDataDescriptor descriptor) { var output = new CommandResultBase(); // Get sample users var users = await _platoUserStore.QueryAsync() .OrderBy("LastLoginDate", OrderBy.Desc) .ToList(); // We need sample users to create sample entities if (users == null || users.Data == null) { return(output.Failed("You must create sample users first!")); } // Ensure the feature is enabled var feature = await _featureFacade.GetFeatureByIdAsync(descriptor.ModuleId); if (feature == null) { // Skip faeture if not enabled return(output.Success()); } // If we add sample entities multiple times ensure the sort order // for new entities is always incremented starting from the highest // existing sort order for any existing entities var sortOrder = await GetStartingEntitySortOrderAsync(feature.Id); for (var i = 0; i < descriptor.EntitiesToCreate; i++) { var result = await InstallEntityInternalAsync(descriptor, users?.Data, sortOrder + i); if (!result.Succeeded) { return(output.Failed(result.Errors.ToArray())); } } return(output.Success()); }
ICommandResultBase ValidateUserName(string username, UserNameOptions options) { var result = new CommandResultBase(); var friendlyBlackList = BuildFriendlyBlackList(options.BlackListedCharacters.ToArray()); if (string.IsNullOrWhiteSpace(username) || username.Length < options.RequiredLength) { result.Failed($"The username must be at least {options.RequiredLength} characters in length"); } foreach (var character in options.BlackListedCharacters) { if (username.IndexOf(character) >= 0) { result.Failed($"The username cannot contain {friendlyBlackList} characters"); } } return(result.Errors.Any() ? result.Failed() : result.Success()); }
async Task <ICommandResultBase> UninstallCategoriesAsync(IShellFeature feature) { // Validate if (feature == null) { throw new ArgumentNullException(nameof(feature)); } if (string.IsNullOrEmpty(feature.ModuleId)) { throw new ArgumentNullException(nameof(feature.ModuleId)); } // Our result var result = new CommandResultBase(); // Replacements for SQL script var replacements = new Dictionary <string, string>() { ["{featureId}"] = feature.Id.ToString() }; // Sql to execute var sql = @" DELETE FROM {prefix}_CategoryData WHERE CategoryId IN ( SELECT Id FROM {prefix}_Categories WHERE FeatureId = {featureId} ); DELETE FROM {prefix}_CategoryRoles WHERE CategoryId IN ( SELECT Id FROM {prefix}_Categories WHERE FeatureId = {featureId} ); DELETE FROM {prefix}_Categories WHERE FeatureId = {featureId}; "; // Execute and return result var error = string.Empty; try { await _dbHelper.ExecuteScalarAsync <int>(sql, replacements); } catch (Exception e) { error = e.Message; } return(!string.IsNullOrEmpty(error) ? result.Failed(error) : result.Success()); }
public async Task <ICommandResultBase> RebuildCatalogAsync() { // Build result var result = new CommandResultBase(); // Create indexes var createIndexes = await CreateIndexesInternalAsync(GetCatalogName()); if (!createIndexes.Succeeded) { return(result.Failed(createIndexes.Errors.ToArray())); } // Rebuild the catalog var rebuildCatalog = await RebuildCatalogInternalAsync(); if (!rebuildCatalog.Succeeded) { return(result.Failed(rebuildCatalog.Errors.ToArray())); } return(result.Success()); }
public async Task <ICommandResultBase> DropCatalogAsync() { // Build result var result = new CommandResultBase(); // Drop indexes var dropIndexes = await DropIndexesInternalAsync(); if (!dropIndexes.Succeeded) { return(result.Failed(dropIndexes.Errors.ToArray())); } // Drop catalog var dropCatalog = await DropCatalogInternalAsync(); if (!dropCatalog.Succeeded) { return(result.Failed(dropCatalog.Errors.ToArray())); } return(result.Success()); }
public async Task <ICommandResultBase> InitialMigrationsAsync() { // Our result var output = new CommandResultBase(); // Get all installed features var features = await _shellFeatureStore.SelectFeatures(); // We need features to upgrade if (features == null) { return(output.Failed("No features could be found within the shell features store.")); } // Attempt to update each found feature and compile any errors var errors = new List <CommandError>(); foreach (var feature in features) { var result = await _shellFeatureUpdater.UpdateAsync(feature.ModuleId); if (result.Errors.Any()) { errors.AddRange(result.Errors); } } // Did any feature upgrade encounter errors? if (errors.Count > 0) { return(output.Failed(errors.ToArray())); } // Return success return(output.Success()); }
public async Task <ICommandResultBase> InstallAsync() { var output = new CommandResultBase(); foreach (var descriptor in Descriptors) { var result = await InstallEntitiesAsync(descriptor); if (!result.Succeeded) { return(output.Failed(result.Errors.ToArray())); } } return(output.Success()); }
public async Task <ICommandResultBase> UninstallAsync(IShellSettings shellSettings) { if (shellSettings == null) { throw new ArgumentNullException(nameof(shellSettings)); } var result = new CommandResultBase(); try { return(await UninstallInternalAsync(shellSettings)); } catch (Exception ex) { return(result.Failed(ex.Message)); } }
async Task <ICommandResultBase> DropCatalogInternalAsync() { // Build result var result = new CommandResultBase(); // Drop catalog var deleteCatalog = await _fullTextCatalogCommand.DeleteAsync(new SchemaFullTextCatalog() { Name = GetCatalogName() }); if (!deleteCatalog.Succeeded) { return(result.Failed(deleteCatalog.Errors.ToArray())); } return(result.Success()); }
async Task <ICommandResultBase> RebuildCatalogInternalAsync() { // Build result var result = new CommandResultBase(); // Rebuild the catalog var rebuildCatalog = await _fullTextCatalogCommand.UpdateAsync(new SchemaFullTextCatalog() { Name = GetCatalogName() }); if (!rebuildCatalog.Succeeded) { return(result.Failed(rebuildCatalog.Errors.ToArray())); } return(result.Success()); }
async Task <ICommandResultBase> InstallCategoryAsync(IShellFeature feature, int sortOrder = 0) { // Validate if (feature == null) { throw new ArgumentNullException(nameof(feature)); } if (string.IsNullOrEmpty(feature.ModuleId)) { throw new ArgumentNullException(nameof(feature.ModuleId)); } // Our result var result = new CommandResultBase(); var icons = new DefaultIcons(); var foreColor = "#ffffff"; var backColor = $"#{_colorProvider.GetColor()}"; var iconCss = $"fal fa-{icons.GetIcon()}"; var categoryResult = await _categoryManager.CreateAsync(new CategoryBase() { FeatureId = feature.Id, ParentId = 0, Name = $"Example Category {_random.Next(0, 2000).ToString()}", Description = $"This is just an example category desccription.", ForeColor = foreColor, BackColor = backColor, IconCss = iconCss, SortOrder = sortOrder }); if (!categoryResult.Succeeded) { return(result.Failed(result.Errors.ToArray())); } return(result.Success()); }
async Task <ICommandResultBase> InstallLabelAsync(IShellFeature feature, int sortOrder = 0) { // Validate if (feature == null) { throw new ArgumentNullException(nameof(feature)); } if (string.IsNullOrEmpty(feature.ModuleId)) { throw new ArgumentNullException(nameof(feature.ModuleId)); } var user = await _contextFacade.GetAuthenticatedUserAsync(); // Our result var result = new CommandResultBase(); var foreColor = "#ffffff"; var backColor = $"#{_colorProvider.GetColor()}"; var categoryResult = await _labelManager.CreateAsync(new LabelBase() { FeatureId = feature.Id, ParentId = 0, Name = $"Example Label {_random.Next(0, 2000).ToString()}", Description = $"This is an example label description.", ForeColor = foreColor, BackColor = backColor, SortOrder = sortOrder, CreatedUserId = user?.Id ?? 0, CreatedDate = DateTimeOffset.UtcNow }); if (!categoryResult.Succeeded) { return(result.Failed(result.Errors.ToArray())); } return(result.Success()); }
private async Task <ICommandResultBase> InstallByIdAsync(string id) { var result = new CommandResultBase(); var errors = new List <CommandError>(); var contexts = await _shellFeatureManager.EnableFeatureAsync(id); foreach (var context in contexts) { if (context.Errors.Any()) { foreach (var error in context.Errors) { errors.Add(new CommandError($"{context.Feature.ModuleId} could not be enabled. {error.Key} - {error.Value}")); } } } return(errors.Count > 0 ? result.Failed(errors.ToArray()) : result.Success()); }
// ------------------------ private async Task <ICommandResultBase> InstallByCategoryAsync(string categoryName) { // Our result var result = new CommandResultBase(); // Get all available features var features = await _shellDescriptorManager.GetFeaturesAsync(); // Get all features in feature category var categoryFeatures = features? .Where(f => f.Descriptor.Category.Equals(categoryName, StringComparison.OrdinalIgnoreCase)) .OrderBy(f => f.Descriptor.Id); var errors = new List <CommandError>(); if (categoryFeatures != null) { foreach (var feature in categoryFeatures) { var contexts = await _shellFeatureManager.EnableFeatureAsync(feature.Descriptor.Id); foreach (var context in contexts) { if (context.Errors.Any()) { foreach (var error in context.Errors) { errors.Add(new CommandError($"{context.Feature.ModuleId} could not be enabled. {error.Key} - {error.Value}")); } } } } } return(errors.Count > 0 ? result.Failed(errors.ToArray()) : result.Success()); }
public async Task <ICommandResultBase> InstallAsync() { var output = new CommandResultBase(); foreach (var descriptor in Descriptors) { var feature = await _featureFacade.GetFeatureByIdAsync(descriptor.ModuleId); if (feature == null) { continue; } var result = await InstallLabelsAsync(feature); if (!result.Succeeded) { return(output.Failed(result.Errors.ToArray())); } } return(output.Success()); }
async Task <ICommandResultBase> DropIndexesInternalAsync() { // Build result var result = new CommandResultBase(); // Get provided indexes var providedIndexes = _fullTextIndexManager.GetIndexes(); // Drop all provided indexes foreach (var providedIndex in providedIndexes) { var deleteIndex = await _fullTextIndexCommand.DeleteAsync(new SchemaFullTextIndex() { TableName = providedIndex.TableName }); if (!deleteIndex.Succeeded) { return(result.Failed(deleteIndex.Errors.ToArray())); } } return(result.Success()); }
// ---------- async Task <ICommandResultBase> InstallInternalAsync(IShellFeature feature) { // Validate if (feature == null) { throw new ArgumentNullException(nameof(feature)); } if (string.IsNullOrEmpty(feature.ModuleId)) { throw new ArgumentNullException(nameof(feature.ModuleId)); } var user = await _contextFacade.GetAuthenticatedUserAsync(); // Get all feature tags var categories = await _categoryStore.QueryAsync() .Select <CategoryQueryParams>(Q => { Q.FeatureId.Equals(feature.Id); }) .ToList(); // Associate every category with at least 1 entity var output = new CommandResultBase(); if (categories != null) { var entityFeature = await GetEntityFeatureAsync(feature); if (entityFeature == null) { return(output.Failed($"A feature named {feature.ModuleId.Replace(".Categories", "")} is not enabled!")); } // Get entities for feature var entities = await _entityStore.QueryAsync() .Select <EntityQueryParams>(q => { q.FeatureId.Equals(entityFeature.Id); q.CategoryId.Equals(0); }) .ToList(); // Keeps track of entities already added to categories var alreadyAdded = new Dictionary <int, Entity>(); // Interate categories building random entities // not already added to a category and adding // those random entities to the current category foreach (var category in categories?.Data) { // Get random entities var randomEntities = GetRandomEntities(entities?.Data, alreadyAdded); // Ensure we have some random entities, they may have already al been added if (randomEntities == null) { return(output.Success()); } // Add random entities to category foreach (var randomEntity in randomEntities) { // Get the full entity var entity = await _entityStore.GetByIdAsync(randomEntity.Id); // Update entity.CategoryId = category.Id; entity.ModifiedUserId = user?.Id ?? 0; entity.ModifiedDate = DateTime.UtcNow; // Persist var entityResult = await _entityManager.UpdateAsync(entity); if (entityResult.Succeeded) { // Add entity / category relationship var result = await _entityCategoryManager.CreateAsync(new EntityCategory() { EntityId = entityResult.Response.Id, CategoryId = category.Id, CreatedUserId = user?.Id ?? 0, CreatedDate = DateTime.UtcNow }); if (!result.Succeeded) { return(output.Failed(result.Errors.ToArray())); } } else { return(output.Failed(entityResult.Errors.ToArray())); } } } } return(output.Success()); }
private async Task <ICommandResultBase> UninstallInternalAsync(IShellSettings shellSettings) { // Our result var result = new CommandResultBase(); var errors = new List <CommandError>(); // ---------------------- // 1. Attempt to delete App_Data/{SiteName} folder // ---------------------- var deleted = true; try { deleted = _shellSettingsManager.DeleteSettings(shellSettings); } catch (Exception e) { errors.Add(new CommandError(e.Message)); } // Report any errors if (errors.Count > 0) { return(result.Failed(errors.ToArray())); } // Ensure we could delete the directory if (deleted == false) { return(result.Failed($"Cannot delete tenant folder with the name \"{shellSettings.Location}\"!")); } // ---------------------- // 2. Attempt to drop all tables and stored procedures with our table prefix // ---------------------- using (var shellContext = _shellContextFactory.CreateMinimalShellContext(shellSettings)) { using (var scope = shellContext.ServiceProvider.CreateScope()) { using (var dbContext = scope.ServiceProvider.GetRequiredService <IDbContext>()) { // update dbContext confirmation dbContext.Configure(options => { options.ConnectionString = shellSettings.ConnectionString; options.DatabaseProvider = shellSettings.DatabaseProvider; options.TablePrefix = shellSettings.TablePrefix; }); var logger = scope.ServiceProvider.GetRequiredService <ILogger <TenantSetUpService> >(); var dbHelper = scope.ServiceProvider.GetRequiredService <IDbHelper>(); try { await dbHelper.ExecuteScalarAsync <int>(UninstallSql, new Dictionary <string, string>() { ["{prefix}"] = shellSettings.TablePrefix }); } catch (Exception e) { errors.Add(new CommandError(e.Message)); } } } } // ---------------------- // 3. Dispose the tenant // ---------------------- // Ensure no errors occurred if (errors.Count == 0) { _platoHost.DisposeShell(shellSettings); } return(errors.Count > 0 ? result.Failed(errors.ToArray()) : result.Success()); }
public async Task <ICommandResultBase> UpdateAsync(string moduleId) { var output = new CommandResultBase(); // Get installed feature var feature = await _featureFacade.GetFeatureByIdAsync(moduleId); // Ensure we found the feature if (feature == null) { return(output.Failed( $"A feature named '{moduleId}' could not be found within the ShellFeatures table.")); } // Get available module var module = await _shellDescriptorManager.GetFeatureAsync(moduleId); // Ensure we found the module if (module == null) { return(output.Failed($"A module named '{moduleId}' could not be found on the file system. Please ensure the '{moduleId}' module exists within the root/modules folder.")); } // ------------------------------------------------------------------ // 1. Check to ensure we have a newer version of the module // ------------------------------------------------------------------ var from = feature.Version.ToVersion(); var to = module.Descriptor.Version.ToVersion(); if (from == null) { return(output.Failed( $"Could not convert version for feature {feature.ModuleId} of {feature.Version} to a valid version. Please check the version within the shell features database table.")); } if (to == null) { return(output.Failed( $"Could not convert version for module {module.Descriptor.Id} of {module.Descriptor.Version} to a valid version. Please check the version within the modules manifest file.")); } // No newer version simply return if (from >= to) { return(output.Success()); } // ------------------------------------------------------------------ // 2. Check to ensure the module we are updating is compatible // with the current version of Plato we are running // ------------------------------------------------------------------ var modulePlatoVersion = module.Descriptor.PlatoVersion.ToVersion(); // Does the module have a Plato version defined? if (modulePlatoVersion != null) { // Get current Plato version var currentPlatoVersion = _platoOptions.Value.Version.ToVersion(); if (currentPlatoVersion != null) { // Does the module require a newer version of Plato? if (modulePlatoVersion > currentPlatoVersion) { return(output.Failed( $"{moduleId} {module.Descriptor.Version} requires Plato {modulePlatoVersion.ToString()} whilst you are running Plato {currentPlatoVersion.ToString()}. Please upgrade to Plato {modulePlatoVersion.ToString()} and try updating {moduleId} again.")); } } } // ------------------------------------------------------------------ // 3. Invoke FeatureEventHandlers & database migrations // ------------------------------------------------------------------ var results = await InvokeFeatureEventHandlersAsync( feature, async context => { // The result to return var result = new CommandResultBase(); // Perform migrations from current installed feature version // to latest available version defined via the modules IMigrationProvider // All versions between from and to var versions = from.GetVersionsBetween(to); // Compile versions to search var versionsToSearch = versions != null ? versions?.ToList().Select(v => v.ToString()) : new List <string>(); // Build migrations for feature & versions var migrations = _migrationBuilder.BuildMigrations(moduleId, versionsToSearch.ToArray()); // Apply migrations var migrationResults = await migrations.ApplyMigrationsAsync(); // We may not have migrations if (migrationResults != null) { // Did any errors occur whilst applying the migration? if (migrationResults.Errors.Any()) { var errors = new List <CommandError>(); foreach (var error in migrationResults.Errors) { errors.Add(new CommandError(error.Message)); } return(result.Failed(errors.ToArray())); } } // If we reach this point everything went OK, Migrations applied // successfully and no errors occurred within the features update handlers. // Finally update the features version within the ShellFeatures table to reflect // the new version of the module we've just updated to, also update // shell descriptor to reflect version changes within dictionary store var updateResult = await UpdateShellFeatureVersionAsync(feature, module.Descriptor.Version); if (updateResult.Errors.Any()) { return(result.Failed(updateResult.Errors.ToArray())); } // Return success return(result.Success()); }); // Did any errors occur? var handlerErrors = results .Where(c => c.Value.Errors.Any()) .SelectMany(h => h.Value.Errors) .ToList(); if (handlerErrors.Count > 0) { var errors = new List <CommandError>(); foreach (var error in handlerErrors) { errors.Add(new CommandError(error.Value)); } return(output.Failed(errors.ToArray())); } // No errors, recycle shell context to apply updates RecycleShell(); return(output.Success()); }
// ---------- async Task <ICommandResultBase> InstallInternalAsync(IShellFeature feature) { // Validate if (feature == null) { throw new ArgumentNullException(nameof(feature)); } if (string.IsNullOrEmpty(feature.ModuleId)) { throw new ArgumentNullException(nameof(feature.ModuleId)); } var user = await _contextFacade.GetAuthenticatedUserAsync(); // Get all feature tags var labels = await _labelStore.QueryAsync() .Select <LabelQueryParams>(Q => { Q.FeatureId.Equals(feature.Id); }) .ToList(); // Associate every tag with at least 1 entity var output = new CommandResultBase(); if (labels != null) { var entities = await _entityStore.QueryAsync() .Select <EntityQueryParams>(q => { q.FeatureId.Equals(feature.Id); }) .ToList(); var alreadyAdded = new Dictionary <int, Entity>(); foreach (var label in labels?.Data) { var randomEntities = GetRandomEntities(entities?.Data, alreadyAdded); if (randomEntities == null) { return(output.Success()); } foreach (var entity in randomEntities) { var result = await _entityLabelManager.CreateAsync(new EntityLabel() { EntityId = entity.Id, LabelId = label.Id, CreatedUserId = user?.Id ?? 0, CreatedDate = DateTime.UtcNow }); if (!result.Succeeded) { return(output.Failed(result.Errors.ToArray())); } } } } return(output.Success()); }
public async Task <ICommandResultBase> ValidateCompanyNameAsync(string companyName) { var result = new CommandResultBase(); var error = "The company name is invalid or is already in use. Please try a different company name."; // We always need a company name if (string.IsNullOrEmpty(companyName)) { return(result.Failed("A company name is required!")); } // Validate characters var valid = true; foreach (var c in companyName) { // Not a letter, digit or space if (!c.IsLetterDigitOrSpace()) { valid = false; break; } } // Only allow letters digits and spaces if (valid == false) { return(result.Failed("The company name cannot contain special characters. Only letters, numbers and spaces are allowed. Please try a different company name.")); } // Create the company name alias to compare with our blacklist var companyNameAlias = _aliasCrator.Create(companyName); // We need an alias if (string.IsNullOrEmpty(companyNameAlias)) { return(result.Failed(error)); } // Does the company name appear in the blacklist? var blackList = GetBlackListedCompanyNames(); foreach (var item in blackList) { if (item.Equals(companyName, StringComparison.OrdinalIgnoreCase)) { return(result.Failed(error)); } if (item.Equals(companyNameAlias, StringComparison.OrdinalIgnoreCase)) { return(result.Failed(error)); } } // --------------- // Does the company name already exist? // We need company names to be unique as the // tenant RequestedPrefixUrl uses CompanyNameAlias // --------------- var signUps = await _signUpStore.QueryAsync() .Select <SignUpQueryParams>(q => { q.CompanyName.Or().Equals(companyName); q.CompanyNameAlias.Or().Equals(companyName); }) .ToList(); if (signUps?.Data != null) { return(result.Failed(error)); } return(result.Success()); }
async Task <ICommandResultBase> InstallEntityInternalAsync(SampleDataDescriptor descriptor, IList <User> users, int sortOrder = 0) { // Validate if (descriptor == null) { throw new ArgumentNullException(nameof(descriptor)); } if (string.IsNullOrEmpty(descriptor.ModuleId)) { throw new ArgumentNullException(nameof(descriptor.ModuleId)); } // Our result var result = new CommandResultBase(); // Ensure the feature is enabled var feature = await _featureFacade.GetFeatureByIdAsync(descriptor.ModuleId); if (feature == null) { return(result.Failed($"The feature {descriptor.ModuleId} is not enabled!")); } // Get a random user for the post var randomUser = users[_random.Next(0, users.Count)]; // Capitalize the first character of our entity type var entityTypeCapitalized = char.ToUpper(descriptor.EntityType[0]).ToString() + descriptor.EntityType.Substring(1); // Create the post var entity = new Entity() { Title = $"Example {entityTypeCapitalized} {_random.Next(0, 2000).ToString()}", Message = GetEntityText(descriptor), FeatureId = feature?.Id ?? 0, SortOrder = sortOrder + 1, CreatedUserId = randomUser?.Id ?? 0, CreatedDate = DateTimeOffset.UtcNow }; // Create entity var entityResult = await _entityManager.CreateAsync(entity); if (entityResult.Succeeded) { var lastReplyId = string.Empty; var lastReplyUserName = string.Empty; var lastReplyMessage = string.Empty; // Create entity replies for (var i = 0; i < descriptor.EntityRepliesToCreate; i++) { randomUser = users[_random.Next(0, users.Count - 1)]; var message = GetReplyText(descriptor); message = message.Replace("{replyUserName}", randomUser?.UserName ?? ""); message = message.Replace("{lastReplyId}", lastReplyId ?? ""); message = message.Replace("{lastReplyMessage}", lastReplyMessage ?? ""); message = message.Replace("{lastReplyQuotedMessage}", lastReplyMessage.Replace(System.Environment.NewLine, System.Environment.NewLine + "> ") ?? ""); message = message.Replace("{lastReplyUserName}", lastReplyUserName ?? ""); message = message.Replace("{entityId}", entityResult.Response.Id.ToString() ?? ""); message = message.Replace("{entityTitle}", entityResult.Response.Title ?? ""); message = message.Replace("{entityUserName}", entityResult.Response.CreatedBy.UserName); message = message.Replace("{mentionSample}", BuildMentionSampleMarkUp()); message = message.Replace("{lastReplyUrl}", _contextFacade.GetRouteUrl(new RouteValueDictionary() { ["area"] = descriptor.ModuleId, ["controller"] = "Home", ["action"] = "Reply", ["opts.id"] = entityResult.Response.Id.ToString() ?? "", ["opts.alias"] = entityResult.Response.Alias.ToString() ?? "", ["opts.replyId"] = lastReplyId ?? "" })); // Create reply var reply = new EntityReply() { EntityId = entityResult.Response.Id, Message = message, CreatedUserId = randomUser?.Id ?? 0, CreatedDate = DateTimeOffset.UtcNow }; // Add reply var replyResult = await _entityReplyManager.CreateAsync(reply); if (!replyResult.Succeeded) { return(result.Failed()); } lastReplyId = replyResult.Response.Id.ToString(); lastReplyMessage = replyResult.Response.Message; lastReplyUserName = replyResult.Response.CreatedBy.UserName; } } else { return(result.Failed(result.Errors.ToArray())); } return(result.Success()); }