diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index 8c5d40803..40a396a72 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -109,6 +109,7 @@ jobs: with: image: squidex/build environment: | + CONFIG__BACKUPURL=http://localhost:5000 CONFIG__WAIT=60 CONFIG__SERVER__URL=http://localhost:8080 WEBHOOKCATCHER__HOST__ENDPOINT=webhookcatcher @@ -122,6 +123,7 @@ jobs: with: image: squidex/build environment: | + CONFIG__BACKUPURL=http://localhost:5000 CONFIG__WAIT=60 CONFIG__SERVER__URL=http://localhost:8081/squidex WEBHOOKCATCHER__HOST__ENDPOINT=webhookcatcher diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 13c3f6c42..3b088e38e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -92,6 +92,7 @@ jobs: with: image: squidex/build environment: | + CONFIG__BACKUPURL=http://localhost:5000 CONFIG__WAIT=60 CONFIG__SERVER__URL=http://localhost:8080 WEBHOOKCATCHER__HOST__ENDPOINT=webhookcatcher @@ -105,6 +106,7 @@ jobs: with: image: squidex/build environment: | + CONFIG__BACKUPURL=http://localhost:5000 CONFIG__WAIT=60 CONFIG__SERVER__URL=http://localhost:8081/squidex WEBHOOKCATCHER__HOST__ENDPOINT=webhookcatcher diff --git a/backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository.cs b/backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository.cs index 1d0f5d00e..33b1e06c0 100644 --- a/backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository.cs +++ b/backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository.cs @@ -257,7 +257,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets return Filter.And( Filter.Gt(x => x.LastModified, default), Filter.Gt(x => x.Id, DomainId.Create(string.Empty)), - Filter.Gt(x => x.IndexedAppId, appId), + Filter.Eq(x => x.IndexedAppId, appId), Filter.Ne(x => x.IsDeleted, true), Filter.Ne(x => x.ParentId, parentId)); } diff --git a/backend/src/Squidex.Domain.Apps.Entities/Assets/RecursiveDeleter.cs b/backend/src/Squidex.Domain.Apps.Entities/Assets/RecursiveDeleter.cs index 32f948c88..17527dc9d 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Assets/RecursiveDeleter.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Assets/RecursiveDeleter.cs @@ -9,6 +9,7 @@ using Microsoft.Extensions.Logging; using Squidex.Domain.Apps.Entities.Assets.Commands; using Squidex.Domain.Apps.Entities.Assets.Repositories; using Squidex.Domain.Apps.Events.Assets; +using Squidex.Infrastructure; using Squidex.Infrastructure.Commands; using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.Reflection; @@ -71,10 +72,20 @@ namespace Squidex.Domain.Apps.Entities.Assets { try { + if (command is IAppCommand appCommand) + { + // Unfortunately, the commands to not share a base class. + appCommand.AppId = folderDeleted.AppId; + } + command.Actor = folderDeleted.Actor; await commandBus.PublishAsync(command, default); } + catch (DomainObjectNotFoundException) + { + // The asset could already be deleted by another operation. + } catch (Exception ex) { log.LogError(ex, "Failed to delete asset recursively."); @@ -87,14 +98,16 @@ namespace Squidex.Domain.Apps.Entities.Assets foreach (var assetFolderId in childAssetFolders) { - await PublishAsync(new DeleteAssetFolder { AppId = appId, AssetFolderId = assetFolderId }); + // These deletions will create more events which will then be deleted as well. + await PublishAsync(new DeleteAssetFolder { AssetFolderId = assetFolderId }); } var childAssets = await assetRepository.QueryChildIdsAsync(appId.Id, folderDeleted.AssetFolderId, default); foreach (var assetId in childAssets) { - await PublishAsync(new DeleteAsset { AppId = appId, AssetId = assetId }); + // Basically the leaves of the tree. + await PublishAsync(new DeleteAsset { AssetId = assetId }); } } } diff --git a/backend/src/Squidex.Domain.Apps.Entities/Backup/RestoreProcessor.cs b/backend/src/Squidex.Domain.Apps.Entities/Backup/RestoreProcessor.cs index 9353f6604..5d2077bcb 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Backup/RestoreProcessor.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Backup/RestoreProcessor.cs @@ -276,6 +276,7 @@ namespace Squidex.Domain.Apps.Entities.Backup try { + // Add the current user to the app, so that the admin can see it and verify integrity. var command = new AssignContributor { Actor = run.Job.Actor, diff --git a/backend/src/Squidex.Web/Resources.cs b/backend/src/Squidex.Web/Resources.cs index 2b1567a33..3a757c7b3 100644 --- a/backend/src/Squidex.Web/Resources.cs +++ b/backend/src/Squidex.Web/Resources.cs @@ -5,7 +5,6 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using Lazy; using Squidex.Domain.Apps.Entities; using Squidex.Infrastructure; using Squidex.Infrastructure.Security; @@ -15,178 +14,137 @@ namespace Squidex.Web { public sealed class Resources { - private readonly Dictionary<(string, string), bool> schemaPermissions = new Dictionary<(string, string), bool>(); + private readonly Dictionary<(string Id, string Schema), bool> permissions = new Dictionary<(string, string), bool>(); // Contents - public bool CanReadContent(string schema) => IsAllowedForSchema(Permissions.AppContentsReadOwn, schema); + public bool CanReadContent(string schema) => Can(Permissions.AppContentsReadOwn, schema); - public bool CanCreateContent(string schema) => IsAllowedForSchema(Permissions.AppContentsCreate, schema); + public bool CanCreateContent(string schema) => Can(Permissions.AppContentsCreate, schema); - public bool CanCreateContentVersion(string schema) => IsAllowedForSchema(Permissions.AppContentsVersionCreateOwn, schema); + public bool CanCreateContentVersion(string schema) => Can(Permissions.AppContentsVersionCreateOwn, schema); - public bool CanDeleteContent(string schema) => IsAllowedForSchema(Permissions.AppContentsDeleteOwn, schema); + public bool CanDeleteContent(string schema) => Can(Permissions.AppContentsDeleteOwn, schema); - public bool CanDeleteContentVersion(string schema) => IsAllowedForSchema(Permissions.AppContentsVersionDeleteOwn, schema); + public bool CanDeleteContentVersion(string schema) => Can(Permissions.AppContentsVersionDeleteOwn, schema); - public bool CanChangeStatus(string schema) => IsAllowedForSchema(Permissions.AppContentsChangeStatus, schema); + public bool CanChangeStatus(string schema) => Can(Permissions.AppContentsChangeStatus, schema); - public bool CanCancelContentStatus(string schema) => IsAllowedForSchema(Permissions.AppContentsChangeStatusCancelOwn, schema); + public bool CanCancelContentStatus(string schema) => Can(Permissions.AppContentsChangeStatusCancelOwn, schema); - public bool CanUpdateContent(string schema) => IsAllowedForSchema(Permissions.AppContentsUpdateOwn, schema); + public bool CanUpdateContent(string schema) => Can(Permissions.AppContentsUpdateOwn, schema); // Schemas - public bool CanUpdateSchema(string schema) => IsAllowedForSchema(Permissions.AppSchemasDelete, schema); + public bool CanUpdateSchema(string schema) => Can(Permissions.AppSchemasDelete, schema); - public bool CanUpdateSchemaScripts(string schema) => IsAllowedForSchema(Permissions.AppSchemasScripts, schema); + public bool CanUpdateSchemaScripts(string schema) => Can(Permissions.AppSchemasScripts, schema); - public bool CanPublishSchema(string schema) => IsAllowedForSchema(Permissions.AppSchemasPublish, schema); + public bool CanPublishSchema(string schema) => Can(Permissions.AppSchemasPublish, schema); - public bool CanDeleteSchema(string schema) => IsAllowedForSchema(Permissions.AppSchemasDelete, schema); + public bool CanDeleteSchema(string schema) => Can(Permissions.AppSchemasDelete, schema); - [Lazy] - public bool CanCreateSchema => IsAllowed(Permissions.AppSchemasCreate); + public bool CanCreateSchema => Can(Permissions.AppSchemasCreate); - [Lazy] - public bool CanUpdateSettings => IsAllowed(Permissions.AppUpdateSettings); + public bool CanUpdateSettings => Can(Permissions.AppUpdateSettings); // Asset Scripts - [Lazy] - public bool CanUpdateAssetsScripts => IsAllowed(Permissions.AppAssetsScriptsUpdate); + public bool CanUpdateAssetsScripts => Can(Permissions.AppAssetsScriptsUpdate); // Contributors - [Lazy] - public bool CanAssignContributor => IsAllowed(Permissions.AppContributorsAssign); + public bool CanAssignContributor => Can(Permissions.AppContributorsAssign); - [Lazy] - public bool CanRevokeContributor => IsAllowed(Permissions.AppContributorsRevoke); + public bool CanRevokeContributor => Can(Permissions.AppContributorsRevoke); // Workflows - [Lazy] - public bool CanCreateWorkflow => IsAllowed(Permissions.AppWorkflowsCreate); + public bool CanCreateWorkflow => Can(Permissions.AppWorkflowsCreate); - [Lazy] - public bool CanUpdateWorkflow => IsAllowed(Permissions.AppWorkflowsUpdate); + public bool CanUpdateWorkflow => Can(Permissions.AppWorkflowsUpdate); - [Lazy] - public bool CanDeleteWorkflow => IsAllowed(Permissions.AppWorkflowsDelete); + public bool CanDeleteWorkflow => Can(Permissions.AppWorkflowsDelete); // Roles - [Lazy] - public bool CanCreateRole => IsAllowed(Permissions.AppRolesCreate); + public bool CanCreateRole => Can(Permissions.AppRolesCreate); - [Lazy] - public bool CanUpdateRole => IsAllowed(Permissions.AppRolesUpdate); + public bool CanUpdateRole => Can(Permissions.AppRolesUpdate); - [Lazy] - public bool CanDeleteRole => IsAllowed(Permissions.AppRolesDelete); + public bool CanDeleteRole => Can(Permissions.AppRolesDelete); // Languages - [Lazy] - public bool CanCreateLanguage => IsAllowed(Permissions.AppLanguagesCreate); + public bool CanCreateLanguage => Can(Permissions.AppLanguagesCreate); - [Lazy] - public bool CanUpdateLanguage => IsAllowed(Permissions.AppLanguagesUpdate); + public bool CanUpdateLanguage => Can(Permissions.AppLanguagesUpdate); - [Lazy] - public bool CanDeleteLanguage => IsAllowed(Permissions.AppLanguagesDelete); + public bool CanDeleteLanguage => Can(Permissions.AppLanguagesDelete); // Clients - [Lazy] - public bool CanCreateClient => IsAllowed(Permissions.AppClientsCreate); + public bool CanCreateClient => Can(Permissions.AppClientsCreate); - [Lazy] - public bool CanUpdateClient => IsAllowed(Permissions.AppClientsUpdate); + public bool CanUpdateClient => Can(Permissions.AppClientsUpdate); - [Lazy] - public bool CanDeleteClient => IsAllowed(Permissions.AppClientsDelete); + public bool CanDeleteClient => Can(Permissions.AppClientsDelete); // Rules - [Lazy] - public bool CanDisableRule => IsAllowed(Permissions.AppRulesDisable); + public bool CanDisableRule => Can(Permissions.AppRulesDisable); - [Lazy] - public bool CanCreateRule => IsAllowed(Permissions.AppRulesCreate); + public bool CanCreateRule => Can(Permissions.AppRulesCreate); - [Lazy] - public bool CanUpdateRule => IsAllowed(Permissions.AppRulesUpdate); + public bool CanUpdateRule => Can(Permissions.AppRulesUpdate); - [Lazy] - public bool CanDeleteRule => IsAllowed(Permissions.AppRulesDelete); + public bool CanDeleteRule => Can(Permissions.AppRulesDelete); - [Lazy] - public bool CanReadRuleEvents => IsAllowed(Permissions.AppRulesEventsRead); + public bool CanReadRuleEvents => Can(Permissions.AppRulesEventsRead); - [Lazy] - public bool CanUpdateRuleEvents => IsAllowed(Permissions.AppRulesEventsUpdate); + public bool CanUpdateRuleEvents => Can(Permissions.AppRulesEventsUpdate); - [Lazy] - public bool CanRunRuleEvents => IsAllowed(Permissions.AppRulesEventsRun); + public bool CanRunRuleEvents => Can(Permissions.AppRulesEventsRun); - [Lazy] - public bool CanDeleteRuleEvents => IsAllowed(Permissions.AppRulesEventsDelete); + public bool CanDeleteRuleEvents => Can(Permissions.AppRulesEventsDelete); // Users - [Lazy] - public bool CanReadUsers => IsAllowed(Permissions.AdminUsersRead); + public bool CanReadUsers => Can(Permissions.AdminUsersRead); - [Lazy] - public bool CanCreateUser => IsAllowed(Permissions.AdminUsersCreate); + public bool CanCreateUser => Can(Permissions.AdminUsersCreate); - [Lazy] - public bool CanLockUser => IsAllowed(Permissions.AdminUsersLock); + public bool CanLockUser => Can(Permissions.AdminUsersLock); - [Lazy] - public bool CanUnlockUser => IsAllowed(Permissions.AdminUsersUnlock); + public bool CanUnlockUser => Can(Permissions.AdminUsersUnlock); - [Lazy] - public bool CanUpdateUser => IsAllowed(Permissions.AdminUsersUpdate); + public bool CanUpdateUser => Can(Permissions.AdminUsersUpdate); // Assets - [Lazy] - public bool CanUploadAsset => IsAllowed(Permissions.AppAssetsUpload); + public bool CanUploadAsset => Can(Permissions.AppAssetsUpload); - [Lazy] - public bool CanCreateAsset => IsAllowed(Permissions.AppAssetsCreate); + public bool CanCreateAsset => Can(Permissions.AppAssetsCreate); - [Lazy] - public bool CanDeleteAsset => IsAllowed(Permissions.AppAssetsDelete); + public bool CanDeleteAsset => Can(Permissions.AppAssetsDelete); - [Lazy] - public bool CanUpdateAsset => IsAllowed(Permissions.AppAssetsUpdate); + public bool CanUpdateAsset => Can(Permissions.AppAssetsUpdate); - [Lazy] - public bool CanReadAssets => IsAllowed(Permissions.AppAssetsRead); + public bool CanReadAssets => Can(Permissions.AppAssetsRead); // Events - [Lazy] - public bool CanReadEvents => IsAllowed(Permissions.AdminEventsRead); + public bool CanReadEvents => Can(Permissions.AdminEventsRead); - [Lazy] - public bool CanManageEvents => IsAllowed(Permissions.AdminEventsManage); + public bool CanManageEvents => Can(Permissions.AdminEventsManage); // Backups - [Lazy] - public bool CanRestoreBackup => IsAllowed(Permissions.AdminRestore); + public bool CanRestoreBackup => Can(Permissions.AdminRestore); - [Lazy] - public bool CanCreateBackup => IsAllowed(Permissions.AppBackupsCreate); + public bool CanCreateBackup => Can(Permissions.AppBackupsCreate); - [Lazy] - public bool CanDeleteBackup => IsAllowed(Permissions.AppBackupsDelete); + public bool CanDeleteBackup => Can(Permissions.AppBackupsDelete); - [Lazy] - public bool CanDownloadBackup => IsAllowed(Permissions.AppBackupsDownload); + public bool CanDownloadBackup => Can(Permissions.AppBackupsDownload); + + public Context Context { get; set; } - [Lazy] public string? App => GetAppName(); - [Lazy] + public string? Schema => GetAppName(); + public DomainId AppId => GetAppId(); public ApiController Controller { get; } - public Context Context { get; set; } - public Resources(ApiController controller) { Controller = controller; @@ -219,16 +177,21 @@ namespace Squidex.Web return Context.UserPermissions.Includes(permission) || additional?.Includes(permission) == true; } - public bool IsAllowedForSchema(string id, string schema) + public bool Can(string id) { - return schemaPermissions.GetOrAdd((id, schema), k => IsAllowed(k.Item1, "*", k.Item2)); + return permissions.GetOrAdd((Id: id, string.Empty), k => IsAllowed(k.Id, Permission.Any, Permission.Any)); + } + + public bool Can(string id, string schema) + { + return permissions.GetOrAdd((Id: id, Schema: schema), k => IsAllowed(k.Id, Permission.Any, k.Schema)); } public bool IsAllowed(string id, string app = Permission.Any, string schema = Permission.Any, PermissionSet? additional = null) { if (app == Permission.Any) { - var fallback = App; + var fallback = GetAppName(); if (!string.IsNullOrWhiteSpace(fallback)) { @@ -238,7 +201,7 @@ namespace Squidex.Web if (schema == Permission.Any) { - var fallback = Controller.HttpContext.Features.Get()?.Schema.SchemaDef.Name; + var fallback = GetSchemaName(); if (!string.IsNullOrWhiteSpace(fallback)) { @@ -256,6 +219,11 @@ namespace Squidex.Web return Controller.HttpContext.Context().App?.Name; } + private string? GetSchemaName() + { + return Controller.HttpContext.Features.Get()?.Schema.SchemaDef.Name; + } + private DomainId GetAppId() { return Controller.HttpContext.Context().App?.Id ?? default; diff --git a/backend/src/Squidex.Web/Squidex.Web.csproj b/backend/src/Squidex.Web/Squidex.Web.csproj index b7186fbfd..0263a513c 100644 --- a/backend/src/Squidex.Web/Squidex.Web.csproj +++ b/backend/src/Squidex.Web/Squidex.Web.csproj @@ -13,14 +13,9 @@ - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/AppDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/AppDto.cs index 48d6b7e3c..c3f9ed4f6 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/AppDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/AppDto.cs @@ -133,104 +133,125 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models { var values = new { app = Name }; - AddGetLink("ping", resources.Url(x => nameof(x.GetAppPing), values)); + AddGetLink("ping", + resources.Url(x => nameof(x.GetAppPing), values)); if (app.Image != null) { - AddGetLink("image", resources.Url(x => nameof(x.GetImage), values)); + AddGetLink("image", + resources.Url(x => nameof(x.GetImage), values)); } if (isContributor) { - AddDeleteLink("leave", resources.Url(x => nameof(x.DeleteMyself), values)); + AddDeleteLink("leave", + resources.Url(x => nameof(x.DeleteMyself), values)); } if (resources.IsAllowed(Shared.Permissions.AppDelete, Name, additional: permissions)) { - AddDeleteLink("delete", resources.Url(x => nameof(x.DeleteApp), values)); + AddDeleteLink("delete", + resources.Url(x => nameof(x.DeleteApp), values)); } if (resources.IsAllowed(Shared.Permissions.AppUpdate, Name, additional: permissions)) { - AddPutLink("update", resources.Url(x => nameof(x.PutApp), values)); + AddPutLink("update", + resources.Url(x => nameof(x.PutApp), values)); } if (resources.IsAllowed(Shared.Permissions.AppAssetsRead, Name, additional: permissions)) { - AddGetLink("assets", resources.Url(x => nameof(x.GetAssets), values)); + AddGetLink("assets", + resources.Url(x => nameof(x.GetAssets), values)); } if (resources.IsAllowed(Shared.Permissions.AppBackupsRead, Name, additional: permissions)) { - AddGetLink("backups", resources.Url(x => nameof(x.GetBackups), values)); + AddGetLink("backups", + resources.Url(x => nameof(x.GetBackups), values)); } if (resources.IsAllowed(Shared.Permissions.AppClientsRead, Name, additional: permissions)) { - AddGetLink("clients", resources.Url(x => nameof(x.GetClients), values)); + AddGetLink("clients", + resources.Url(x => nameof(x.GetClients), values)); } if (resources.IsAllowed(Shared.Permissions.AppContributorsRead, Name, additional: permissions)) { - AddGetLink("contributors", resources.Url(x => nameof(x.GetContributors), values)); + AddGetLink("contributors", + resources.Url(x => nameof(x.GetContributors), values)); } if (resources.IsAllowed(Shared.Permissions.AppLanguagesRead, Name, additional: permissions)) { - AddGetLink("languages", resources.Url(x => nameof(x.GetLanguages), values)); + AddGetLink("languages", + resources.Url(x => nameof(x.GetLanguages), values)); } if (resources.IsAllowed(Shared.Permissions.AppPlansRead, Name, additional: permissions)) { - AddGetLink("plans", resources.Url(x => nameof(x.GetPlans), values)); + AddGetLink("plans", + resources.Url(x => nameof(x.GetPlans), values)); } if (resources.IsAllowed(Shared.Permissions.AppRolesRead, Name, additional: permissions)) { - AddGetLink("roles", resources.Url(x => nameof(x.GetRoles), values)); + AddGetLink("roles", + resources.Url(x => nameof(x.GetRoles), values)); } if (resources.IsAllowed(Shared.Permissions.AppRulesRead, Name, additional: permissions)) { - AddGetLink("rules", resources.Url(x => nameof(x.GetRules), values)); + AddGetLink("rules", + resources.Url(x => nameof(x.GetRules), values)); } if (resources.IsAllowed(Shared.Permissions.AppSchemasRead, Name, additional: permissions)) { - AddGetLink("schemas", resources.Url(x => nameof(x.GetSchemas), values)); + AddGetLink("schemas", + resources.Url(x => nameof(x.GetSchemas), values)); } if (resources.IsAllowed(Shared.Permissions.AppWorkflowsRead, Name, additional: permissions)) { - AddGetLink("workflows", resources.Url(x => nameof(x.GetWorkflows), values)); + AddGetLink("workflows", + resources.Url(x => nameof(x.GetWorkflows), values)); } if (resources.IsAllowed(Shared.Permissions.AppSchemasCreate, Name, additional: permissions)) { - AddPostLink("schemas/create", resources.Url(x => nameof(x.PostSchema), values)); + AddPostLink("schemas/create", + resources.Url(x => nameof(x.PostSchema), values)); } if (resources.IsAllowed(Shared.Permissions.AppAssetsCreate, Name, additional: permissions)) { - AddPostLink("assets/create", resources.Url(x => nameof(x.PostSchema), values)); + AddPostLink("assets/create", + resources.Url(x => nameof(x.PostSchema), values)); } if (resources.IsAllowed(Shared.Permissions.AppImageUpload, Name, additional: permissions)) { - AddPostLink("image/upload", resources.Url(x => nameof(x.UploadImage), values)); + AddPostLink("image/upload", + resources.Url(x => nameof(x.UploadImage), values)); } if (resources.IsAllowed(Shared.Permissions.AppImageDelete, Name, additional: permissions)) { - AddDeleteLink("image/delete", resources.Url(x => nameof(x.DeleteImage), values)); + AddDeleteLink("image/delete", + resources.Url(x => nameof(x.DeleteImage), values)); } if (resources.IsAllowed(Shared.Permissions.AppAssetsScriptsUpdate, Name, additional: permissions)) { - AddDeleteLink("assets/scripts", resources.Url(x => nameof(x.GetAssetScripts), values)); + AddDeleteLink("assets/scripts", + resources.Url(x => nameof(x.GetAssetScripts), values)); } - AddGetLink("settings", resources.Url(x => nameof(x.GetSettings), values)); + AddGetLink("settings", + resources.Url(x => nameof(x.GetSettings), values)); return this; } diff --git a/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/AppLanguageDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/AppLanguageDto.cs index dfe0a5629..12377c141 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/AppLanguageDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/AppLanguageDto.cs @@ -65,12 +65,14 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models { if (resources.CanUpdateLanguage) { - AddPutLink("update", resources.Url(x => nameof(x.PutLanguage), values)); + AddPutLink("update", + resources.Url(x => nameof(x.PutLanguage), values)); } if (resources.CanDeleteLanguage && app.Languages.Languages.Count > 1) { - AddDeleteLink("delete", resources.Url(x => nameof(x.DeleteLanguage), values)); + AddDeleteLink("delete", + resources.Url(x => nameof(x.DeleteLanguage), values)); } } diff --git a/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/AppLanguagesDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/AppLanguagesDto.cs index 3449a7c1c..d0902d318 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/AppLanguagesDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/AppLanguagesDto.cs @@ -43,7 +43,8 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models if (resources.CanCreateLanguage) { - AddPostLink("create", resources.Url(x => nameof(x.PostLanguage), values)); + AddPostLink("create", + resources.Url(x => nameof(x.PostLanguage), values)); } return this; diff --git a/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/AppSettingsDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/AppSettingsDto.cs index 07f624a38..8ae2cef85 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/AppSettingsDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/AppSettingsDto.cs @@ -64,7 +64,8 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models if (resources.CanUpdateSettings) { - AddPutLink("update", resources.Url(x => nameof(x.PutSettings), values)); + AddPutLink("update", + resources.Url(x => nameof(x.PutSettings), values)); } return this; diff --git a/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/AssetScriptsDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/AssetScriptsDto.cs index 50e56a667..d4adadd97 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/AssetScriptsDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/AssetScriptsDto.cs @@ -58,7 +58,8 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models if (resources.CanUpdateAssetsScripts) { - AddPutLink("update", resources.Url(x => nameof(x.PutAssetScripts), values)); + AddPutLink("update", + resources.Url(x => nameof(x.PutAssetScripts), values)); } return this; diff --git a/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/ClientDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/ClientDto.cs index 197a8fbd6..e1ffbd008 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/ClientDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/ClientDto.cs @@ -65,12 +65,14 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models if (resources.CanUpdateClient) { - AddPutLink("update", resources.Url(x => nameof(x.PutClient), values)); + AddPutLink("update", + resources.Url(x => nameof(x.PutClient), values)); } if (resources.CanDeleteClient) { - AddDeleteLink("delete", resources.Url(x => nameof(x.DeleteClient), values)); + AddDeleteLink("delete", + resources.Url(x => nameof(x.DeleteClient), values)); } return this; diff --git a/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/ClientsDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/ClientsDto.cs index 6cffaee03..b59220075 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/ClientsDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/ClientsDto.cs @@ -40,7 +40,8 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models if (resources.CanCreateClient) { - AddPostLink("create", resources.Url(x => nameof(x.PostClient), values)); + AddPostLink("create", + resources.Url(x => nameof(x.PostClient), values)); } return this; diff --git a/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/ContributorDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/ContributorDto.cs index bbeec1d62..fbf7259ed 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/ContributorDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/ContributorDto.cs @@ -70,14 +70,16 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models { var values = new { app }; - AddPostLink("update", resources.Url(x => nameof(x.PostContributor), values)); + AddPostLink("update", + resources.Url(x => nameof(x.PostContributor), values)); } if (resources.CanRevokeContributor) { var values = new { app, id = ContributorId }; - AddDeleteLink("delete", resources.Url(x => nameof(x.DeleteContributor), values)); + AddDeleteLink("delete", + resources.Url(x => nameof(x.DeleteContributor), values)); } } diff --git a/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/ContributorsDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/ContributorsDto.cs index 0152b36e4..f320aaed5 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/ContributorsDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/ContributorsDto.cs @@ -77,7 +77,8 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models if (resources.CanAssignContributor && (MaxContributors < 0 || Items.Length < MaxContributors)) { - AddPostLink("create", resources.Url(x => nameof(x.PostContributor), values)); + AddPostLink("create", + resources.Url(x => nameof(x.PostContributor), values)); } return this; diff --git a/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/RoleDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/RoleDto.cs index f8a37c3d7..bfb510ebc 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/RoleDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/RoleDto.cs @@ -81,12 +81,14 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models { if (resources.CanUpdateRole) { - AddPutLink("update", resources.Url(x => nameof(x.PutRole), values)); + AddPutLink("update", + resources.Url(x => nameof(x.PutRole), values)); } if (resources.CanDeleteRole && NumClients == 0 && NumContributors == 0) { - AddDeleteLink("delete", resources.Url(x => nameof(x.DeleteRole), values)); + AddDeleteLink("delete", + resources.Url(x => nameof(x.DeleteRole), values)); } } diff --git a/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/RolesDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/RolesDto.cs index d5ddc766e..319f7b592 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/RolesDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/RolesDto.cs @@ -42,7 +42,8 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models if (resources.CanCreateRole) { - AddPostLink("create", resources.Url(x => nameof(x.PostRole), values)); + AddPostLink("create", + resources.Url(x => nameof(x.PostRole), values)); } return this; diff --git a/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/WorkflowDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/WorkflowDto.cs index 45a17dc7c..287282133 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/WorkflowDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/WorkflowDto.cs @@ -61,12 +61,14 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models if (resources.CanUpdateWorkflow) { - AddPutLink("update", resources.Url(x => nameof(x.PutWorkflow), values)); + AddPutLink("update", + resources.Url(x => nameof(x.PutWorkflow), values)); } if (resources.CanDeleteWorkflow) { - AddDeleteLink("delete", resources.Url(x => nameof(x.DeleteWorkflow), values)); + AddDeleteLink("delete", + resources.Url(x => nameof(x.DeleteWorkflow), values)); } return this; diff --git a/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/WorkflowsDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/WorkflowsDto.cs index cc7c1f5f3..f34fc8fc3 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/WorkflowsDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/WorkflowsDto.cs @@ -52,7 +52,8 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models if (resources.CanCreateWorkflow) { - AddPostLink("create", resources.Url(x => nameof(x.PostWorkflow), values)); + AddPostLink("create", + resources.Url(x => nameof(x.PostWorkflow), values)); } return this; diff --git a/backend/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetDto.cs index 9cfee697e..ff42c271f 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetDto.cs @@ -189,39 +189,46 @@ namespace Squidex.Areas.Api.Controllers.Assets.Models if (resources.CanUpdateAsset) { - AddPutLink("update", resources.Url(x => nameof(x.PutAsset), values)); + AddPutLink("update", + resources.Url(x => nameof(x.PutAsset), values)); } if (resources.CanUpdateAsset) { - AddPutLink("move", resources.Url(x => nameof(x.PutAssetParent), values)); + AddPutLink("move", + resources.Url(x => nameof(x.PutAssetParent), values)); } if (resources.CanUploadAsset) { - AddPutLink("upload", resources.Url(x => nameof(x.PutAssetContent), values)); + AddPutLink("upload", + resources.Url(x => nameof(x.PutAssetContent), values)); } if (resources.CanDeleteAsset) { - AddDeleteLink("delete", resources.Url(x => nameof(x.DeleteAsset), values)); + AddDeleteLink("delete", + resources.Url(x => nameof(x.DeleteAsset), values)); } if (!string.IsNullOrWhiteSpace(Slug)) { var idValues = new { app, idOrSlug = Id, more = Slug }; - AddGetLink("content", resources.Url(x => nameof(x.GetAssetContentBySlug), idValues)); + AddGetLink("content", + resources.Url(x => nameof(x.GetAssetContentBySlug), idValues)); var slugValues = new { app, idOrSlug = Slug }; - AddGetLink("content/slug", resources.Url(x => nameof(x.GetAssetContentBySlug), slugValues)); + AddGetLink("content/slug", + resources.Url(x => nameof(x.GetAssetContentBySlug), slugValues)); } else { var idValues = new { app, idOrSlug = Id }; - AddGetLink("content", resources.Url(x => nameof(x.GetAssetContentBySlug), idValues)); + AddGetLink("content", + resources.Url(x => nameof(x.GetAssetContentBySlug), idValues)); } return this; diff --git a/backend/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetFolderDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetFolderDto.cs index 62dba07da..3664a4262 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetFolderDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetFolderDto.cs @@ -49,14 +49,17 @@ namespace Squidex.Areas.Api.Controllers.Assets.Models if (resources.CanUpdateAsset) { - AddPutLink("update", resources.Url(x => nameof(x.PutAssetFolder), values)); + AddPutLink("update", + resources.Url(x => nameof(x.PutAssetFolder), values)); - AddPutLink("move", resources.Url(x => nameof(x.PutAssetFolderParent), values)); + AddPutLink("move", + resources.Url(x => nameof(x.PutAssetFolderParent), values)); } if (resources.CanUpdateAsset) { - AddDeleteLink("delete", resources.Url(x => nameof(x.DeleteAssetFolder), values)); + AddDeleteLink("delete", + resources.Url(x => nameof(x.DeleteAssetFolder), values)); } return this; diff --git a/backend/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetFoldersDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetFoldersDto.cs index 85544b5af..9539a2639 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetFoldersDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetFoldersDto.cs @@ -52,7 +52,8 @@ namespace Squidex.Areas.Api.Controllers.Assets.Models if (resources.CanUpdateAsset) { - AddPostLink("create", resources.Url(x => nameof(x.PostAssetFolder), values)); + AddPostLink("create", + resources.Url(x => nameof(x.PostAssetFolder), values)); } return this; diff --git a/backend/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetsDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetsDto.cs index 3f5e9d96c..2a605fa1b 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetsDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetsDto.cs @@ -44,17 +44,20 @@ namespace Squidex.Areas.Api.Controllers.Assets.Models if (resources.CanCreateAsset) { - AddPostLink("create", resources.Url(x => nameof(x.PostAsset), values)); + AddPostLink("create", + resources.Url(x => nameof(x.PostAsset), values)); } if (resources.CanUpdateAsset) { var tagValue = new { values.app, name = "tag" }; - AddPutLink("tags/rename", resources.Url(x => nameof(x.PutTag), tagValue)); + AddPutLink("tags/rename", + resources.Url(x => nameof(x.PutTag), tagValue)); } - AddGetLink("tags", resources.Url(x => nameof(x.GetTags), values)); + AddGetLink("tags", + resources.Url(x => nameof(x.GetTags), values)); return this; } diff --git a/backend/src/Squidex/Areas/Api/Controllers/Backups/Models/BackupJobDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Backups/Models/BackupJobDto.cs index 2cf73ffb3..17aedbf9a 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Backups/Models/BackupJobDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Backups/Models/BackupJobDto.cs @@ -58,14 +58,16 @@ namespace Squidex.Areas.Api.Controllers.Backups.Models { var values = new { app = resources.App, id = Id }; - AddDeleteLink("delete", resources.Url(x => nameof(x.DeleteBackup), values)); + AddDeleteLink("delete", + resources.Url(x => nameof(x.DeleteBackup), values)); } if (resources.CanDownloadBackup) { var values = new { app = resources.App, appId = resources.AppId, id = Id }; - AddGetLink("download", resources.Url(x => nameof(x.GetBackupContentV2), values)); + AddGetLink("download", + resources.Url(x => nameof(x.GetBackupContentV2), values)); } return this; diff --git a/backend/src/Squidex/Areas/Api/Controllers/Backups/Models/BackupJobsDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Backups/Models/BackupJobsDto.cs index 5019b45ff..917155cce 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Backups/Models/BackupJobsDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Backups/Models/BackupJobsDto.cs @@ -37,7 +37,8 @@ namespace Squidex.Areas.Api.Controllers.Backups.Models if (resources.CanCreateBackup) { - AddPostLink("create", resources.Url(x => nameof(x.PostBackup), values)); + AddPostLink("create", + resources.Url(x => nameof(x.PostBackup), values)); } return this; diff --git a/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/ContentDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/ContentDto.cs index ddc270c91..0aee184e8 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/ContentDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/ContentDto.cs @@ -169,21 +169,24 @@ namespace Squidex.Areas.Api.Controllers.Contents.Models { var versioned = new { app, schema, values.id, version = Version - 1 }; - AddGetLink("previous", resources.Url(x => nameof(x.GetContentVersion), versioned)); + AddGetLink("previous", + resources.Url(x => nameof(x.GetContentVersion), versioned)); } if (NewStatus != null) { if (resources.CanDeleteContentVersion(schema)) { - AddDeleteLink("draft/delete", resources.Url(x => nameof(x.DeleteVersion), values)); + AddDeleteLink("draft/delete", + resources.Url(x => nameof(x.DeleteVersion), values)); } } else if (Status == Status.Published) { if (resources.CanCreateContentVersion(schema)) { - AddPostLink("draft/create", resources.Url(x => nameof(x.CreateDraft), values)); + AddPostLink("draft/create", + resources.Url(x => nameof(x.CreateDraft), values)); } } @@ -202,17 +205,20 @@ namespace Squidex.Areas.Api.Controllers.Contents.Models if (!content.IsSingleton && resources.CanDeleteContent(schema)) { - AddDeleteLink("delete", resources.Url(x => nameof(x.DeleteContent), values)); + AddDeleteLink("delete", + resources.Url(x => nameof(x.DeleteContent), values)); } if (content.CanUpdate && resources.CanUpdateContent(schema)) { - AddPatchLink("patch", resources.Url(x => nameof(x.PatchContent), values)); + AddPatchLink("patch", + resources.Url(x => nameof(x.PatchContent), values)); } if (content.CanUpdate && resources.CanUpdateContent(schema)) { - AddPutLink("update", resources.Url(x => nameof(x.PutContent), values)); + AddPutLink("update", + resources.Url(x => nameof(x.PutContent), values)); } return this; diff --git a/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/ContentsDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/ContentsDto.cs index 9658e965a..cbd9e4a0c 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/ContentsDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Contents/Models/ContentsDto.cs @@ -66,13 +66,15 @@ namespace Squidex.Areas.Api.Controllers.Contents.Models if (resources.CanCreateContent(values.schema)) { - AddPostLink("create", resources.Url(x => nameof(x.PostContent), values)); + AddPostLink("create", + resources.Url(x => nameof(x.PostContent), values)); if (resources.CanChangeStatus(values.schema) && await workflow.CanPublishInitialAsync(schema, resources.Context.User)) { var publishValues = new { values.app, values.schema, publish = true }; - AddPostLink("create/publish", resources.Url(x => nameof(x.PostContent), publishValues)); + AddPostLink("create/publish", + resources.Url(x => nameof(x.PostContent), publishValues)); } } } diff --git a/backend/src/Squidex/Areas/Api/Controllers/EventConsumers/Models/EventConsumerDto.cs b/backend/src/Squidex/Areas/Api/Controllers/EventConsumers/Models/EventConsumerDto.cs index 882d09832..da253b0f5 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/EventConsumers/Models/EventConsumerDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/EventConsumers/Models/EventConsumerDto.cs @@ -40,16 +40,19 @@ namespace Squidex.Areas.Api.Controllers.EventConsumers.Models if (!IsResetting) { - AddPutLink("reset", resources.Url(x => nameof(x.ResetEventConsumer), values)); + AddPutLink("reset", + resources.Url(x => nameof(x.ResetEventConsumer), values)); } if (IsStopped) { - AddPutLink("start", resources.Url(x => nameof(x.StartEventConsumer), values)); + AddPutLink("start", + resources.Url(x => nameof(x.StartEventConsumer), values)); } else { - AddPutLink("stop", resources.Url(x => nameof(x.StopEventConsumer), values)); + AddPutLink("stop", + resources.Url(x => nameof(x.StopEventConsumer), values)); } } diff --git a/backend/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleDto.cs index 6799d4906..c56d7f642 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleDto.cs @@ -113,44 +113,52 @@ namespace Squidex.Areas.Api.Controllers.Rules.Models { if (IsEnabled) { - AddPutLink("disable", resources.Url(x => nameof(x.DisableRule), values)); + AddPutLink("disable", + resources.Url(x => nameof(x.DisableRule), values)); } else { - AddPutLink("enable", resources.Url(x => nameof(x.EnableRule), values)); + AddPutLink("enable", + resources.Url(x => nameof(x.EnableRule), values)); } } if (resources.CanUpdateRule) { - AddPutLink("update", resources.Url(x => nameof(x.PutRule), values)); + AddPutLink("update", + resources.Url(x => nameof(x.PutRule), values)); } if (resources.CanRunRuleEvents) { - AddPutLink("trigger", resources.Url(x => nameof(x.TriggerRule), values)); + AddPutLink("trigger", + resources.Url(x => nameof(x.TriggerRule), values)); if (canRun && ruleRunnerService.CanRunRule(rule)) { - AddPutLink("run", resources.Url(x => nameof(x.PutRuleRun), values)); + AddPutLink("run", + resources.Url(x => nameof(x.PutRuleRun), values)); } if (canRun && ruleRunnerService.CanRunFromSnapshots(rule)) { var snaphshotValues = new { values.app, values.id, fromSnapshots = true }; - AddPutLink("run/snapshots", resources.Url(x => nameof(x.PutRuleRun), snaphshotValues)); + AddPutLink("run/snapshots", + resources.Url(x => nameof(x.PutRuleRun), snaphshotValues)); } } if (resources.CanReadRuleEvents) { - AddGetLink("logs", resources.Url(x => nameof(x.GetEvents), values)); + AddGetLink("logs", + resources.Url(x => nameof(x.GetEvents), values)); } if (resources.CanDeleteRule) { - AddDeleteLink("delete", resources.Url(x => nameof(x.DeleteRule), values)); + AddDeleteLink("delete", + resources.Url(x => nameof(x.DeleteRule), values)); } return this; diff --git a/backend/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleEventDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleEventDto.cs index 5847ad345..d0bab6bf3 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleEventDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleEventDto.cs @@ -80,12 +80,14 @@ namespace Squidex.Areas.Api.Controllers.Rules.Models if (resources.CanUpdateRuleEvents) { - AddPutLink("update", resources.Url(x => nameof(x.PutEvent), values)); + AddPutLink("update", + resources.Url(x => nameof(x.PutEvent), values)); } if (resources.CanDeleteRuleEvents && NextAttempt != null) { - AddDeleteLink("cancel", resources.Url(x => nameof(x.DeleteEvent), values)); + AddDeleteLink("cancel", + resources.Url(x => nameof(x.DeleteEvent), values)); } return this; diff --git a/backend/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleEventsDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleEventsDto.cs index 7c5a393ae..0531765da 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleEventsDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleEventsDto.cs @@ -48,11 +48,13 @@ namespace Squidex.Areas.Api.Controllers.Rules.Models { var routeValues = new { values.app, id = ruleId }; - AddDeleteLink("cancel", resources.Url(x => nameof(x.DeleteRuleEvents), routeValues)); + AddDeleteLink("cancel", + resources.Url(x => nameof(x.DeleteRuleEvents), routeValues)); } else { - AddDeleteLink("cancel", resources.Url(x => nameof(x.DeleteEvents), values)); + AddDeleteLink("cancel", + resources.Url(x => nameof(x.DeleteEvents), values)); } } diff --git a/backend/src/Squidex/Areas/Api/Controllers/Rules/Models/RulesDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Rules/Models/RulesDto.cs index 0dbfd7f6f..37137d605 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Rules/Models/RulesDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Rules/Models/RulesDto.cs @@ -49,17 +49,20 @@ namespace Squidex.Areas.Api.Controllers.Rules.Models if (resources.CanCreateRule) { - AddPostLink("create", resources.Url(x => nameof(x.PostRule), values)); + AddPostLink("create", + resources.Url(x => nameof(x.PostRule), values)); } if (resources.CanReadRuleEvents) { - AddGetLink("events", resources.Url(x => nameof(x.GetEvents), values)); + AddGetLink("events", + resources.Url(x => nameof(x.GetEvents), values)); } if (resources.CanDeleteRuleEvents && runningRuleId != null) { - AddDeleteLink("run/cancel", resources.Url(x => nameof(x.DeleteRuleRun), values)); + AddDeleteLink("run/cancel", + resources.Url(x => nameof(x.DeleteRuleRun), values)); } return this; diff --git a/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/FieldDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/FieldDto.cs index 67aa6c1c8..891d06fe0 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/FieldDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/FieldDto.cs @@ -108,44 +108,53 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models { var values = new { app = resources.App, schema, id = FieldId }; - AddPutLink("update", resources.Url(x => nameof(x.PutField), values)); + AddPutLink("update", + resources.Url(x => nameof(x.PutField), values)); if (IsHidden) { - AddPutLink("show", resources.Url(x => nameof(x.ShowField), values)); + AddPutLink("show", + resources.Url(x => nameof(x.ShowField), values)); } else { - AddPutLink("hide", resources.Url(x => nameof(x.HideField), values)); + AddPutLink("hide", + resources.Url(x => nameof(x.HideField), values)); } if (IsDisabled) { - AddPutLink("enable", resources.Url(x => nameof(x.EnableField), values)); + AddPutLink("enable", + resources.Url(x => nameof(x.EnableField), values)); } else { - AddPutLink("disable", resources.Url(x => nameof(x.DisableField), values)); + AddPutLink("disable", + resources.Url(x => nameof(x.DisableField), values)); } if (Nested != null) { var parentValues = new { values.app, values.schema, parentId = FieldId }; - AddPostLink("fields/add", resources.Url(x => nameof(x.PostNestedField), parentValues)); + AddPostLink("fields/add", + resources.Url(x => nameof(x.PostNestedField), parentValues)); if (Nested.Count > 0) { - AddPutLink("fields/order", resources.Url(x => nameof(x.PutNestedFieldOrdering), parentValues)); + AddPutLink("fields/order", + resources.Url(x => nameof(x.PutNestedFieldOrdering), parentValues)); } } if (!IsLocked) { - AddPutLink("lock", resources.Url(x => nameof(x.LockField), values)); + AddPutLink("lock", + resources.Url(x => nameof(x.LockField), values)); } - AddDeleteLink("delete", resources.Url(x => nameof(x.DeleteField), values)); + AddDeleteLink("delete", + resources.Url(x => nameof(x.DeleteField), values)); } if (Nested != null) diff --git a/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/NestedFieldDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/NestedFieldDto.cs index 1d1ccd5eb..bf9550db6 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/NestedFieldDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/NestedFieldDto.cs @@ -53,32 +53,39 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models { var values = new { app = resources.App, schema, parentId, id = FieldId }; - AddPutLink("update", resources.Url(x => nameof(x.PutNestedField), values)); + AddPutLink("update", + resources.Url(x => nameof(x.PutNestedField), values)); if (IsHidden) { - AddPutLink("show", resources.Url(x => nameof(x.ShowNestedField), values)); + AddPutLink("show", + resources.Url(x => nameof(x.ShowNestedField), values)); } else { - AddPutLink("hide", resources.Url(x => nameof(x.HideNestedField), values)); + AddPutLink("hide", + resources.Url(x => nameof(x.HideNestedField), values)); } if (IsDisabled) { - AddPutLink("enable", resources.Url(x => nameof(x.EnableNestedField), values)); + AddPutLink("enable", + resources.Url(x => nameof(x.EnableNestedField), values)); } else { - AddPutLink("disable", resources.Url(x => nameof(x.DisableNestedField), values)); + AddPutLink("disable", + resources.Url(x => nameof(x.DisableNestedField), values)); } if (!IsLocked) { - AddPutLink("lock", resources.Url(x => nameof(x.LockNestedField), values)); + AddPutLink("lock", + resources.Url(x => nameof(x.LockNestedField), values)); } - AddDeleteLink("delete", resources.Url(x => nameof(x.DeleteNestedField), values)); + AddDeleteLink("delete", + resources.Url(x => nameof(x.DeleteNestedField), values)); } } } diff --git a/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/SchemaDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/SchemaDto.cs index 8d16d78b0..670b8527e 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/SchemaDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/SchemaDto.cs @@ -115,13 +115,13 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models /// /// The field rules. /// - public List FieldRules { get; set; } + public List FieldRules { get; set; } = new List(); /// /// The list of fields. /// [LocalizedRequired] - public List Fields { get; set; } + public List Fields { get; set; } = new List(); public static SchemaDto FromDomain(ISchemaEntity schema, Resources resources) { @@ -132,9 +132,10 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models SimpleMapper.Map(schema.SchemaDef.Scripts, result.Scripts); SimpleMapper.Map(schema.SchemaDef.Properties, result.Properties); - result.FieldRules = schema.SchemaDef.FieldRules.Select(FieldRuleDto.FromDomain).ToList(); - - result.Fields = new List(); + foreach (var rule in schema.SchemaDef.FieldRules) + { + result.FieldRules.Add(FieldRuleDto.FromDomain(rule)); + } foreach (var field in schema.SchemaDef.Fields) { @@ -154,51 +155,72 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models AddSelfLink(resources.Url(x => nameof(x.GetSchema), values)); - if (resources.CanReadContent(Name) && Type == SchemaType.Default) + if (resources.CanReadContent(Name) && Type != SchemaType.Component) { - AddGetLink("contents", resources.Url(x => nameof(x.GetContents), values)); + AddGetLink("contents", + resources.Url(x => nameof(x.GetContents), values)); } if (resources.CanCreateContent(Name) && Type == SchemaType.Default) { - AddPostLink("contents/create", resources.Url(x => nameof(x.PostContent), values)); - AddPostLink("contents/create/publish", resources.Url(x => nameof(x.PostContent), values) + "?publish=true"); + AddPostLink("contents/create", + resources.Url(x => nameof(x.PostContent), values)); + + AddPostLink("contents/create/publish", + resources.Url(x => nameof(x.PostContent), values) + "?publish=true"); } if (resources.CanPublishSchema(Name)) { if (IsPublished) { - AddPutLink("unpublish", resources.Url(x => nameof(x.UnpublishSchema), values)); + AddPutLink("unpublish", + resources.Url(x => nameof(x.UnpublishSchema), values)); } else { - AddPutLink("publish", resources.Url(x => nameof(x.PublishSchema), values)); + AddPutLink("publish", + resources.Url(x => nameof(x.PublishSchema), values)); } } if (allowUpdate) { - AddPostLink("fields/add", resources.Url(x => nameof(x.PostField), values)); + AddPostLink("fields/add", + resources.Url(x => nameof(x.PostField), values)); + + AddPutLink("fields/order", + resources.Url(x => nameof(x.PutSchemaFieldOrdering), values)); + + AddPutLink("fields/ui", + resources.Url(x => nameof(x.PutSchemaUIFields), values)); + + AddPutLink("update", + resources.Url(x => nameof(x.PutSchema), values)); + + AddPutLink("update/category", + resources.Url(x => nameof(x.PutCategory), values)); + + AddPutLink("update/rules", + resources.Url(x => nameof(x.PutRules), values)); - AddPutLink("fields/ui", resources.Url(x => nameof(x.PutSchemaUIFields), values)); - AddPutLink("fields/order", resources.Url(x => nameof(x.PutSchemaFieldOrdering), values)); + AddPutLink("update/sync", + resources.Url(x => nameof(x.PutSchemaSync), values)); - AddPutLink("update", resources.Url(x => nameof(x.PutSchema), values)); - AddPutLink("update/category", resources.Url(x => nameof(x.PutCategory), values)); - AddPutLink("update/rules", resources.Url(x => nameof(x.PutRules), values)); - AddPutLink("update/sync", resources.Url(x => nameof(x.PutSchemaSync), values)); - AddPutLink("update/urls", resources.Url(x => nameof(x.PutPreviewUrls), values)); + AddPutLink("update/urls", + resources.Url(x => nameof(x.PutPreviewUrls), values)); } if (resources.CanUpdateSchemaScripts(Name)) { - AddPutLink("update/scripts", resources.Url(x => nameof(x.PutScripts), values)); + AddPutLink("update/scripts", + resources.Url(x => nameof(x.PutScripts), values)); } if (resources.CanDeleteSchema(Name)) { - AddDeleteLink("delete", resources.Url(x => nameof(x.DeleteSchema), values)); + AddDeleteLink("delete", + resources.Url(x => nameof(x.DeleteSchema), values)); } if (Fields != null) diff --git a/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/SchemasDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/SchemasDto.cs index 90ef4942f..0735cc723 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/SchemasDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/SchemasDto.cs @@ -35,7 +35,8 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models if (resources.CanCreateSchema) { - AddPostLink("create", resources.Url(x => nameof(x.PostSchema), values)); + AddPostLink("create", + resources.Url(x => nameof(x.PostSchema), values)); } return this; diff --git a/backend/src/Squidex/Areas/Api/Controllers/Search/Models/SearchResultDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Search/Models/SearchResultDto.cs index f4db011fa..50cd961f0 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Search/Models/SearchResultDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Search/Models/SearchResultDto.cs @@ -40,7 +40,8 @@ namespace Squidex.Areas.Api.Controllers.Search.Models protected SearchResultDto CreateLinks(SearchResult searchResult) { - AddGetLink("url", searchResult.Url); + AddGetLink("url", + searchResult.Url); return this; } diff --git a/backend/src/Squidex/Areas/Api/Controllers/Users/Models/ResourcesDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Users/Models/ResourcesDto.cs index 59603a82f..03a0db791 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Users/Models/ResourcesDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Users/Models/ResourcesDto.cs @@ -19,24 +19,29 @@ namespace Squidex.Areas.Api.Controllers.Users.Models { var result = new ResourcesDto(); - result.AddGetLink("ping", resources.Url(x => nameof(x.GetPing))); + result.AddGetLink("ping", + resources.Url(x => nameof(x.GetPing))); if (resources.CanReadEvents) { - result.AddGetLink("admin/events", resources.Url(x => nameof(x.GetEventConsumers))); + result.AddGetLink("admin/events", + resources.Url(x => nameof(x.GetEventConsumers))); } if (resources.CanRestoreBackup) { - result.AddGetLink("admin/restore", resources.Url(x => nameof(x.GetRestoreJob))); + result.AddGetLink("admin/restore", + resources.Url(x => nameof(x.GetRestoreJob))); } if (resources.CanReadUsers) { - result.AddGetLink("admin/users", resources.Url(x => nameof(x.GetUsers))); + result.AddGetLink("admin/users", + resources.Url(x => nameof(x.GetUsers))); } - result.AddGetLink("languages", resources.Url(x => nameof(x.GetLanguages))); + result.AddGetLink("languages", + resources.Url(x => nameof(x.GetLanguages))); return result; } diff --git a/backend/src/Squidex/Areas/Api/Controllers/Users/Models/UserDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Users/Models/UserDto.cs index 23ee2d790..4d285bd70 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Users/Models/UserDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Users/Models/UserDto.cs @@ -72,23 +72,28 @@ namespace Squidex.Areas.Api.Controllers.Users.Models { if (resources.CanLockUser && !IsLocked) { - AddPutLink("lock", resources.Url(c => nameof(c.LockUser), values)); + AddPutLink("lock", + resources.Url(c => nameof(c.LockUser), values)); } if (resources.CanUnlockUser && IsLocked) { - AddPutLink("unlock", resources.Url(c => nameof(c.UnlockUser), values)); + AddPutLink("unlock", + resources.Url(c => nameof(c.UnlockUser), values)); } - AddDeleteLink("delete", resources.Url(x => nameof(x.DeleteUser), values)); + AddDeleteLink("delete", + resources.Url(x => nameof(x.DeleteUser), values)); } if (resources.CanUpdateUser) { - AddPutLink("update", resources.Url(c => nameof(c.PutUser), values)); + AddPutLink("update", + resources.Url(c => nameof(c.PutUser), values)); } - AddGetLink("picture", resources.Url(c => nameof(c.GetUserPicture), values)); + AddGetLink("picture", + resources.Url(c => nameof(c.GetUserPicture), values)); return this; } diff --git a/backend/src/Squidex/Areas/Api/Controllers/Users/Models/UsersDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Users/Models/UsersDto.cs index 6833018d2..1c345287d 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Users/Models/UsersDto.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Users/Models/UsersDto.cs @@ -41,7 +41,8 @@ namespace Squidex.Areas.Api.Controllers.Users.Models if (context.CanCreateUser) { - AddPostLink("create", context.Url(c => nameof(c.PostUser))); + AddPostLink("create", + context.Url(c => nameof(c.PostUser))); } return this; diff --git a/backend/tools/TestSuite/TestSuite.ApiTests/AppClientsTests.cs b/backend/tools/TestSuite/TestSuite.ApiTests/AppClientsTests.cs index bd5784636..12d49d92f 100644 --- a/backend/tools/TestSuite/TestSuite.ApiTests/AppClientsTests.cs +++ b/backend/tools/TestSuite/TestSuite.ApiTests/AppClientsTests.cs @@ -95,10 +95,7 @@ namespace TestSuite.ApiTests private async Task CreateAsync() { - var createRequest = new CreateClientDto - { - Id = id - }; + var createRequest = new CreateClientDto { Id = id }; var clients = await _.Apps.PostClientAsync(appName, createRequest); var client = clients.Items.Find(x => x.Id == id); @@ -108,10 +105,7 @@ namespace TestSuite.ApiTests private async Task CreateAppAsync() { - var createRequest = new CreateAppDto - { - Name = appName - }; + var createRequest = new CreateAppDto { Name = appName }; await _.Apps.PostAppAsync(createRequest); } diff --git a/backend/tools/TestSuite/TestSuite.ApiTests/AppContributorsTests.cs b/backend/tools/TestSuite/TestSuite.ApiTests/AppContributorsTests.cs index cda5d7c8a..3321f04ce 100644 --- a/backend/tools/TestSuite/TestSuite.ApiTests/AppContributorsTests.cs +++ b/backend/tools/TestSuite/TestSuite.ApiTests/AppContributorsTests.cs @@ -69,10 +69,7 @@ namespace TestSuite.ApiTests // STEP 1: Update contributor role. - var updateRequest = new AssignContributorDto - { - ContributorId = email, Role = "Owner" - }; + var updateRequest = new AssignContributorDto { ContributorId = email, Role = "Owner" }; var contributors_2 = await _.Apps.PostContributorAsync(appName, updateRequest); var contributor_2 = contributors_2.Items.Find(x => x.ContributorId == contributor.ContributorId); @@ -99,11 +96,7 @@ namespace TestSuite.ApiTests private async Task InviteAsync() { - var createInviteRequest = new AssignContributorDto - { - ContributorId = email, - Invite = true - }; + var createInviteRequest = new AssignContributorDto { ContributorId = email, Invite = true }; var contributors = await _.Apps.PostContributorAsync(appName, createInviteRequest); var contributor = contributors.Items.Find(x => x.ContributorName == email); diff --git a/backend/tools/TestSuite/TestSuite.ApiTests/AppRolesTests.cs b/backend/tools/TestSuite/TestSuite.ApiTests/AppRolesTests.cs index 7ffa57c6d..209b1c6fb 100644 --- a/backend/tools/TestSuite/TestSuite.ApiTests/AppRolesTests.cs +++ b/backend/tools/TestSuite/TestSuite.ApiTests/AppRolesTests.cs @@ -141,30 +141,21 @@ namespace TestSuite.ApiTests private async Task AssignContributor(string role = null) { - var assignRequest = new AssignContributorDto - { - ContributorId = contributor, Role = role, Invite = true - }; + var assignRequest = new AssignContributorDto { ContributorId = contributor, Role = role, Invite = true }; await _.Apps.PostContributorAsync(_.AppName, assignRequest); } private async Task AssignClient(string role = null) { - var updateRequest = new UpdateClientDto - { - Role = role - }; + var updateRequest = new UpdateClientDto { Role = role }; await _.Apps.PutClientAsync(_.AppName, client, updateRequest); } private async Task CreateRoleAsync(string name) { - var createRequest = new AddRoleDto - { - Name = name - }; + var createRequest = new AddRoleDto { Name = name }; var roles = await _.Apps.PostRoleAsync(_.AppName, createRequest); var role = roles.Items.Find(x => x.Name == name); diff --git a/backend/tools/TestSuite/TestSuite.ApiTests/AssetTests.cs b/backend/tools/TestSuite/TestSuite.ApiTests/AssetTests.cs index 9bfaf80e1..0778e6140 100644 --- a/backend/tools/TestSuite/TestSuite.ApiTests/AssetTests.cs +++ b/backend/tools/TestSuite/TestSuite.ApiTests/AssetTests.cs @@ -12,7 +12,6 @@ using Xunit; #pragma warning disable SA1300 // Element should begin with upper-case letter #pragma warning disable SA1507 // Code should not contain multiple blank lines in a row -#pragma warning disable SA1133 // Do not combine attributes namespace TestSuite.ApiTests { @@ -455,7 +454,7 @@ namespace TestSuite.ApiTests Assert.Single(assets_1.Items, x => x.Id == asset_1.Id); } - [Fact, Trait("Category", "NotAutomated")] + [Fact] public async Task Should_delete_recursively() { // STEP 1: Create asset folder @@ -477,16 +476,7 @@ namespace TestSuite.ApiTests // STEP 4: Delete folder. await _.Assets.DeleteAssetFolderAsync(_.AppName, folder_1.Id); - - // STEP 5: Wait for recursive deleter to delete the asset. - await Task.Delay(5000); - - var ex = await Assert.ThrowsAnyAsync(() => - { - return _.Assets.GetAssetAsync(_.AppName, asset_1.Id); - }); - - Assert.Equal(404, ex.StatusCode); + Assert.True(await _.Assets.WaitForDeletionAsync(_.AppName, asset_1.Id, TimeSpan.FromSeconds(30))); } [Theory] diff --git a/backend/tools/TestSuite/TestSuite.ApiTests/BackupTests.cs b/backend/tools/TestSuite/TestSuite.ApiTests/BackupTests.cs index 98a577480..ae4b663d8 100644 --- a/backend/tools/TestSuite/TestSuite.ApiTests/BackupTests.cs +++ b/backend/tools/TestSuite/TestSuite.ApiTests/BackupTests.cs @@ -8,6 +8,7 @@ using Squidex.ClientLibrary.Management; using TestSuite.Fixtures; using TestSuite.Model; +using TestSuite.Utils; using Xunit; #pragma warning disable SA1300 // Element should begin with upper-case letter @@ -15,7 +16,6 @@ using Xunit; namespace TestSuite.ApiTests { - [Trait("Category", "NotAutomated")] public class BackupTests : IClassFixture { private readonly string appName = Guid.NewGuid().ToString(); @@ -31,6 +31,9 @@ namespace TestSuite.ApiTests [Fact] public async Task Should_backup_and_restore_app() { + // Load the backup from another URL, because the public URL is might not be accessible for the server. + var backupUrl = TestHelpers.GetAndPrintValue("config:backupUrl", _.ServerUrl); + var appNameRestore = $"{appName}-restore"; // STEP 1: Create app @@ -44,16 +47,22 @@ namespace TestSuite.ApiTests // STEP 3: Create backup - await _.Backups.PostBackupAsync(appNameRestore); + await _.Backups.PostBackupAsync(appName); var backup = await _.Backups.WaitForBackupAsync(appName, TimeSpan.FromMinutes(2)); Assert.Equal(JobStatus.Completed, backup?.Status); - // STEP 3: Restore backup - var uri = new Uri(new Uri(_.ServerUrl, UriKind.Absolute), backup._links["download"].Href); + // STEP 4: Restore backup + var uri = new Uri(new Uri(backupUrl), backup._links["download"].Href); + + var restoreRequest = new RestoreRequestDto { Url = uri, Name = appNameRestore }; + + await _.Backups.PostRestoreJobAsync(restoreRequest); + + // STEP 5: Wait for the backup. var restore = await _.Backups.WaitForRestoreAsync(uri, TimeSpan.FromMinutes(2)); Assert.Equal(JobStatus.Completed, restore?.Status); diff --git a/backend/tools/TestSuite/TestSuite.ApiTests/CDNTests.cs b/backend/tools/TestSuite/TestSuite.ApiTests/CDNTests.cs index ff54f0697..fcfca6d41 100644 --- a/backend/tools/TestSuite/TestSuite.ApiTests/CDNTests.cs +++ b/backend/tools/TestSuite/TestSuite.ApiTests/CDNTests.cs @@ -13,7 +13,6 @@ using Xunit; namespace TestSuite.ApiTests { - [Trait("Category", "NotAutomated")] public class CDNTests : IClassFixture { public CloudFixture _ { get; } diff --git a/backend/tools/TestSuite/TestSuite.ApiTests/ContentUpdateTests.cs b/backend/tools/TestSuite/TestSuite.ApiTests/ContentUpdateTests.cs index 6f2d25e44..501155105 100644 --- a/backend/tools/TestSuite/TestSuite.ApiTests/ContentUpdateTests.cs +++ b/backend/tools/TestSuite/TestSuite.ApiTests/ContentUpdateTests.cs @@ -442,7 +442,7 @@ namespace TestSuite.ApiTests Interlocked.Increment(ref numSuccess); } - catch (SquidexException ex) when (ex.StatusCode is 409 or 412) + catch (SquidexException ex) when (ex.StatusCode is 409 or 412) { Interlocked.Increment(ref numErrors); return; diff --git a/backend/tools/TestSuite/TestSuite.LoadTests/ReadingContentBenchmarks.cs b/backend/tools/TestSuite/TestSuite.LoadTests/ReadingContentBenchmarks.cs index d785c5a12..11934c0b5 100644 --- a/backend/tools/TestSuite/TestSuite.LoadTests/ReadingContentBenchmarks.cs +++ b/backend/tools/TestSuite/TestSuite.LoadTests/ReadingContentBenchmarks.cs @@ -13,7 +13,7 @@ using Xunit; namespace TestSuite.LoadTests { public class ReadingContentBenchmarks : IClassFixture -{ + { public ReadingFixture _ { get; } public ReadingContentBenchmarks(ReadingFixture fixture) diff --git a/backend/tools/TestSuite/TestSuite.Shared/ClientExtensions.cs b/backend/tools/TestSuite/TestSuite.Shared/ClientExtensions.cs index a937e7bc2..6ddf075fb 100644 --- a/backend/tools/TestSuite/TestSuite.Shared/ClientExtensions.cs +++ b/backend/tools/TestSuite/TestSuite.Shared/ClientExtensions.cs @@ -11,6 +11,33 @@ namespace TestSuite { public static class ClientExtensions { + public static async Task WaitForDeletionAsync(this IAssetsClient assetsClient, string app, string id, TimeSpan timeout) + { + try + { + using var cts = new CancellationTokenSource(timeout); + + while (!cts.IsCancellationRequested) + { + try + { + await assetsClient.GetAssetAsync(app, id, cts.Token); + } + catch (SquidexManagementException ex) when (ex.StatusCode == 404) + { + return true; + } + + await Task.Delay(200, cts.Token); + } + } + catch (OperationCanceledException) + { + } + + return false; + } + public static async Task WaitForBackupAsync(this IBackupsClient backupsClient, string app, TimeSpan timeout) { try diff --git a/backend/tools/TestSuite/TestSuite.Shared/TestSuite.Shared.csproj b/backend/tools/TestSuite/TestSuite.Shared/TestSuite.Shared.csproj index 9b88cb9fb..515f8bbe0 100644 --- a/backend/tools/TestSuite/TestSuite.Shared/TestSuite.Shared.csproj +++ b/backend/tools/TestSuite/TestSuite.Shared/TestSuite.Shared.csproj @@ -16,7 +16,7 @@ - +