예제 #1
0
        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());
        }
예제 #2
0
        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());
        }
예제 #3
0
        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());
        }
예제 #4
0
        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());
        }
예제 #5
0
        // ----------

        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());
        }
예제 #6
0
        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());
        }
예제 #7
0
        // ----------

        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());
        }
예제 #8
0
        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());
        }
예제 #9
0
        // ------------------

        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());
        }
예제 #10
0
        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());
        }
예제 #11
0
        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());
        }
예제 #12
0
        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());
        }
예제 #13
0
        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());
        }
예제 #14
0
        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());
        }
예제 #15
0
        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());
        }
예제 #16
0
        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));
            }
        }
예제 #17
0
        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());
        }
예제 #18
0
        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());
        }
예제 #19
0
        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());
        }
예제 #20
0
        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());
        }
예제 #21
0
        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());
        }
예제 #22
0
        // ------------------------

        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());
        }
예제 #23
0
        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());
        }
예제 #24
0
        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());
        }
예제 #25
0
        // ----------

        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());
        }
예제 #26
0
        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());
        }
예제 #27
0
        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());
        }
예제 #28
0
        // ----------

        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());
        }
예제 #29
0
        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());
        }
예제 #30
0
        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());
        }