Browse Source

UI Claims. (#909)

pull/911/head
Sebastian Stehle 3 years ago
committed by GitHub
parent
commit
cc1db76e23
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 25
      backend/src/Squidex.Domain.Apps.Core.Model/Apps/Role.cs
  2. 30
      backend/src/Squidex.Domain.Apps.Core.Model/Apps/Roles.cs
  3. 2
      backend/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleEventFormatter.cs
  4. 21
      backend/src/Squidex.Domain.Apps.Entities/Apps/AppExtensions.cs
  5. 22
      backend/src/Squidex.Domain.Apps.Entities/Apps/AppSettingsSearchSource.cs
  6. 12
      backend/src/Squidex.Domain.Apps.Entities/Apps/RolePermissionsProvider.cs
  7. 2
      backend/src/Squidex.Domain.Apps.Entities/Assets/AssetsSearchSource.cs
  8. 6
      backend/src/Squidex.Domain.Apps.Entities/Assets/DomainObject/AssetsBulkUpdateCommandMiddleware.cs
  9. 2
      backend/src/Squidex.Domain.Apps.Entities/Contents/ContentsSearchSource.cs
  10. 16
      backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/ContentDomainObject.cs
  11. 14
      backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/ContentsBulkUpdateCommandMiddleware.cs
  12. 2
      backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/Guards/SecurityExtensions.cs
  13. 12
      backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/ContentActions.cs
  14. 6
      backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentQueryService.cs
  15. 2
      backend/src/Squidex.Domain.Apps.Entities/Context.cs
  16. 2
      backend/src/Squidex.Domain.Apps.Entities/Schemas/SchemasSearchSource.cs
  17. 2
      backend/src/Squidex.Domain.Users/DefaultUserService.cs
  18. 2
      backend/src/Squidex.Domain.Users/UserClaimsPrincipalFactoryWithEmail.cs
  19. 2
      backend/src/Squidex.Shared/Identity/SquidexClaimTypes.cs
  20. 23
      backend/src/Squidex.Shared/Identity/SquidexClaimsExtensions.cs
  21. 2
      backend/src/Squidex.Shared/PermissionExtensions.cs
  22. 9
      backend/src/Squidex.Shared/PermissionIds.cs
  23. 2
      backend/src/Squidex.Web/Pipeline/ApiPermissionUnifier.cs
  24. 14
      backend/src/Squidex.Web/Pipeline/AppResolver.cs
  25. 108
      backend/src/Squidex.Web/Resources.cs
  26. 4
      backend/src/Squidex/Areas/Api/Controllers/Apps/AppAssetsController.cs
  27. 8
      backend/src/Squidex/Areas/Api/Controllers/Apps/AppClientsController.cs
  28. 6
      backend/src/Squidex/Areas/Api/Controllers/Apps/AppContributorsController.cs
  29. 8
      backend/src/Squidex/Areas/Api/Controllers/Apps/AppLanguagesController.cs
  30. 10
      backend/src/Squidex/Areas/Api/Controllers/Apps/AppRolesController.cs
  31. 2
      backend/src/Squidex/Areas/Api/Controllers/Apps/AppSettingsController.cs
  32. 8
      backend/src/Squidex/Areas/Api/Controllers/Apps/AppWorkflowsController.cs
  33. 8
      backend/src/Squidex/Areas/Api/Controllers/Apps/AppsController.cs
  34. 53
      backend/src/Squidex/Areas/Api/Controllers/Apps/Models/AppDto.cs
  35. 10
      backend/src/Squidex/Areas/Api/Controllers/Assets/AssetFoldersController.cs
  36. 26
      backend/src/Squidex/Areas/Api/Controllers/Assets/AssetsController.cs
  37. 6
      backend/src/Squidex/Areas/Api/Controllers/Backups/BackupsController.cs
  38. 4
      backend/src/Squidex/Areas/Api/Controllers/Backups/RestoreController.cs
  39. 8
      backend/src/Squidex/Areas/Api/Controllers/Comments/CommentsController.cs
  40. 24
      backend/src/Squidex/Areas/Api/Controllers/Contents/ContentsController.cs
  41. 2
      backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/OperationBuilder.cs
  42. 22
      backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/SchemasOpenApiGenerator.cs
  43. 4
      backend/src/Squidex/Areas/Api/Controllers/Diagnostics/DiagnosticsController.cs
  44. 8
      backend/src/Squidex/Areas/Api/Controllers/EventConsumers/EventConsumersController.cs
  45. 2
      backend/src/Squidex/Areas/Api/Controllers/History/HistoryController.cs
  46. 2
      backend/src/Squidex/Areas/Api/Controllers/Ping/PingController.cs
  47. 4
      backend/src/Squidex/Areas/Api/Controllers/Plans/AppPlansController.cs
  48. 32
      backend/src/Squidex/Areas/Api/Controllers/Rules/RulesController.cs
  49. 38
      backend/src/Squidex/Areas/Api/Controllers/Schemas/SchemaFieldsController.cs
  50. 24
      backend/src/Squidex/Areas/Api/Controllers/Schemas/SchemasController.cs
  51. 2
      backend/src/Squidex/Areas/Api/Controllers/Search/SearchController.cs
  52. 8
      backend/src/Squidex/Areas/Api/Controllers/Statistics/UsagesController.cs
  53. 2
      backend/src/Squidex/Areas/Api/Controllers/Translations/TranslationsController.cs
  54. 2
      backend/src/Squidex/Areas/Api/Controllers/UI/UIController.cs
  55. 14
      backend/src/Squidex/Areas/Api/Controllers/Users/UserManagementController.cs
  56. 2
      backend/src/Squidex/Areas/IdentityServer/Config/ApplicationExtensions.cs
  57. 4
      backend/src/Squidex/Areas/IdentityServer/Config/CreateAdminInitializer.cs
  58. 22
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Apps/AppSettingsSearchSourceTests.cs
  59. 2
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetsSearchSourceTests.cs
  60. 14
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/DomainObject/AssetsBulkUpdateCommandMiddlewareTests.cs
  61. 2
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentsSearchSourceTests.cs
  62. 48
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DomainObject/ContentsBulkUpdateCommandMiddlewareTests.cs
  63. 10
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DomainObject/Guards/GuardContentTests.cs
  64. 38
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLMutationTests.cs
  65. 2
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLTestBase.cs
  66. 8
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/ContentQueryServiceTests.cs
  67. 6
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/SchemasSearchSourceTests.cs
  68. 2
      backend/tests/Squidex.Domain.Users.Tests/DefaultUserServiceTests.cs
  69. 10
      backend/tests/Squidex.Web.Tests/ApiPermissionAttributeTests.cs
  70. 2
      backend/tests/Squidex.Web.Tests/Pipeline/ApiPermissionUnifierTests.cs

25
backend/src/Squidex.Domain.Apps.Core.Model/Apps/Role.cs

@ -9,6 +9,7 @@ using System.Diagnostics.Contracts;
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.Json.Objects; using Squidex.Infrastructure.Json.Objects;
using Squidex.Infrastructure.Security; using Squidex.Infrastructure.Security;
using Squidex.Shared;
#pragma warning disable SA1313 // Parameter names should begin with lower-case letter #pragma warning disable SA1313 // Parameter names should begin with lower-case letter
@ -18,16 +19,16 @@ namespace Squidex.Domain.Apps.Core.Apps
{ {
private static readonly HashSet<string> ExtraPermissions = new HashSet<string> private static readonly HashSet<string> ExtraPermissions = new HashSet<string>
{ {
Shared.Permissions.AppComments, PermissionIds.AppComments,
Shared.Permissions.AppContributorsRead, PermissionIds.AppContributorsRead,
Shared.Permissions.AppHistory, PermissionIds.AppHistory,
Shared.Permissions.AppLanguagesRead, PermissionIds.AppLanguagesRead,
Shared.Permissions.AppPing, PermissionIds.AppPing,
Shared.Permissions.AppRolesRead, PermissionIds.AppRolesRead,
Shared.Permissions.AppSchemasRead, PermissionIds.AppSchemasRead,
Shared.Permissions.AppSearch, PermissionIds.AppSearch,
Shared.Permissions.AppTranslate, PermissionIds.AppTranslate,
Shared.Permissions.AppUsage PermissionIds.AppUsage
}; };
public const string Editor = "Editor"; public const string Editor = "Editor";
@ -75,7 +76,7 @@ namespace Squidex.Domain.Apps.Core.Apps
if (Permissions.Any()) if (Permissions.Any())
{ {
var prefix = Shared.Permissions.ForApp(Shared.Permissions.App, app).Id; var prefix = PermissionIds.ForApp(PermissionIds.App, app).Id;
foreach (var permission in Permissions) foreach (var permission in Permissions)
{ {
@ -87,7 +88,7 @@ namespace Squidex.Domain.Apps.Core.Apps
{ {
foreach (var extraPermissionId in ExtraPermissions) foreach (var extraPermissionId in ExtraPermissions)
{ {
var extraPermission = Shared.Permissions.ForApp(extraPermissionId, app); var extraPermission = PermissionIds.ForApp(extraPermissionId, app);
result.Add(extraPermission); result.Add(extraPermission);
} }

30
backend/src/Squidex.Domain.Apps.Core.Model/Apps/Roles.cs

@ -24,33 +24,33 @@ namespace Squidex.Domain.Apps.Core.Apps
[Role.Owner] = [Role.Owner] =
new Role(Role.Owner, new Role(Role.Owner,
new PermissionSet( new PermissionSet(
WithoutPrefix(Permissions.App)), WithoutPrefix(PermissionIds.App)),
new JsonObject()), new JsonObject()),
[Role.Reader] = [Role.Reader] =
new Role(Role.Reader, new Role(Role.Reader,
new PermissionSet( new PermissionSet(
WithoutPrefix(Permissions.AppAssetsRead), WithoutPrefix(PermissionIds.AppAssetsRead),
WithoutPrefix(Permissions.AppContentsRead)), WithoutPrefix(PermissionIds.AppContentsRead)),
new JsonObject() new JsonObject()
.Add("ui.api.hide", true)), .Add("ui.api.hide", true)),
[Role.Editor] = [Role.Editor] =
new Role(Role.Editor, new Role(Role.Editor,
new PermissionSet( new PermissionSet(
WithoutPrefix(Permissions.AppAssets), WithoutPrefix(PermissionIds.AppAssets),
WithoutPrefix(Permissions.AppContents), WithoutPrefix(PermissionIds.AppContents),
WithoutPrefix(Permissions.AppRolesRead), WithoutPrefix(PermissionIds.AppRolesRead),
WithoutPrefix(Permissions.AppWorkflowsRead)), WithoutPrefix(PermissionIds.AppWorkflowsRead)),
new JsonObject() new JsonObject()
.Add("ui.api.hide", true)), .Add("ui.api.hide", true)),
[Role.Developer] = [Role.Developer] =
new Role(Role.Developer, new Role(Role.Developer,
new PermissionSet( new PermissionSet(
WithoutPrefix(Permissions.AppAssets), WithoutPrefix(PermissionIds.AppAssets),
WithoutPrefix(Permissions.AppContents), WithoutPrefix(PermissionIds.AppContents),
WithoutPrefix(Permissions.AppRolesRead), WithoutPrefix(PermissionIds.AppRolesRead),
WithoutPrefix(Permissions.AppRules), WithoutPrefix(PermissionIds.AppRules),
WithoutPrefix(Permissions.AppSchemas), WithoutPrefix(PermissionIds.AppSchemas),
WithoutPrefix(Permissions.AppWorkflows)), WithoutPrefix(PermissionIds.AppWorkflows)),
new JsonObject()) new JsonObject())
}; };
@ -175,9 +175,9 @@ namespace Squidex.Domain.Apps.Core.Apps
private static string WithoutPrefix(string permission) private static string WithoutPrefix(string permission)
{ {
permission = Permissions.ForApp(permission).Id; permission = PermissionIds.ForApp(permission).Id;
var prefix = Permissions.ForApp(Permissions.App); var prefix = PermissionIds.ForApp(PermissionIds.App);
if (permission.StartsWith(prefix.Id, StringComparison.OrdinalIgnoreCase)) if (permission.StartsWith(prefix.Id, StringComparison.OrdinalIgnoreCase))
{ {

2
backend/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleEventFormatter.cs

@ -149,7 +149,7 @@ namespace Squidex.Domain.Apps.Core.HandleRules
var claimsIdentity = new ClaimsIdentity(); var claimsIdentity = new ClaimsIdentity();
var claimsPrincipal = new ClaimsPrincipal(claimsIdentity); var claimsPrincipal = new ClaimsPrincipal(claimsIdentity);
claimsIdentity.AddClaim(new Claim(SquidexClaimTypes.Permissions, Permissions.All)); claimsIdentity.AddClaim(new Claim(SquidexClaimTypes.Permissions, PermissionIds.All));
return claimsPrincipal; return claimsPrincipal;
} }

21
backend/src/Squidex.Domain.Apps.Entities/Apps/AppExtensions.cs

@ -5,6 +5,8 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using System.Diagnostics.CodeAnalysis;
using Squidex.Domain.Apps.Core.Apps;
using Squidex.Infrastructure; using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Entities.Apps namespace Squidex.Domain.Apps.Entities.Apps
@ -15,5 +17,24 @@ namespace Squidex.Domain.Apps.Entities.Apps
{ {
return new NamedId<DomainId>(app.Id, app.Name); return new NamedId<DomainId>(app.Id, app.Name);
} }
public static bool TryGetContributorRole(this IAppEntity app, string id, bool isFrontend, [MaybeNullWhen(false)] out Role role)
{
role = null;
return app.Contributors.TryGetValue(id, out var roleName) && app.TryGetRole(roleName, isFrontend, out role);
}
public static bool TryGetClientRole(this IAppEntity app, string id, bool isFrontend, [MaybeNullWhen(false)] out Role role)
{
role = null;
return app.Clients.TryGetValue(id, out var client) && app.TryGetRole(client.Role, isFrontend, out role);
}
public static bool TryGetRole(this IAppEntity app, string roleName, bool isFrontend, [MaybeNullWhen(false)] out Role role)
{
return app.Roles.TryGet(app.Name, roleName, isFrontend, out role);
}
} }
} }

22
backend/src/Squidex.Domain.Apps.Entities/Apps/AppSettingsSearchSource.cs

@ -42,37 +42,37 @@ namespace Squidex.Domain.Apps.Entities.Apps
} }
} }
Search("Assets", Permissions.AppAssetsRead, Search("Assets", PermissionIds.AppAssetsRead,
a => urlGenerator.AssetsUI(a), SearchResultType.Asset); a => urlGenerator.AssetsUI(a), SearchResultType.Asset);
Search("Backups", Permissions.AppBackupsRead, Search("Backups", PermissionIds.AppBackupsRead,
urlGenerator.BackupsUI, SearchResultType.Setting); urlGenerator.BackupsUI, SearchResultType.Setting);
Search("Clients", Permissions.AppClientsRead, Search("Clients", PermissionIds.AppClientsRead,
urlGenerator.ClientsUI, SearchResultType.Setting); urlGenerator.ClientsUI, SearchResultType.Setting);
Search("Contributors", Permissions.AppContributorsRead, Search("Contributors", PermissionIds.AppContributorsRead,
urlGenerator.ContributorsUI, SearchResultType.Setting); urlGenerator.ContributorsUI, SearchResultType.Setting);
Search("Dashboard", Permissions.AppUsage, Search("Dashboard", PermissionIds.AppUsage,
urlGenerator.DashboardUI, SearchResultType.Dashboard); urlGenerator.DashboardUI, SearchResultType.Dashboard);
Search("Languages", Permissions.AppLanguagesRead, Search("Languages", PermissionIds.AppLanguagesRead,
urlGenerator.LanguagesUI, SearchResultType.Setting); urlGenerator.LanguagesUI, SearchResultType.Setting);
Search("Roles", Permissions.AppRolesRead, Search("Roles", PermissionIds.AppRolesRead,
urlGenerator.RolesUI, SearchResultType.Setting); urlGenerator.RolesUI, SearchResultType.Setting);
Search("Rules", Permissions.AppRulesRead, Search("Rules", PermissionIds.AppRulesRead,
urlGenerator.RulesUI, SearchResultType.Rule); urlGenerator.RulesUI, SearchResultType.Rule);
Search("Schemas", Permissions.AppSchemasRead, Search("Schemas", PermissionIds.AppSchemasRead,
urlGenerator.SchemasUI, SearchResultType.Schema); urlGenerator.SchemasUI, SearchResultType.Schema);
Search("Subscription", Permissions.AppPlansRead, Search("Subscription", PermissionIds.AppPlansRead,
urlGenerator.PlansUI, SearchResultType.Setting); urlGenerator.PlansUI, SearchResultType.Setting);
Search("Workflows", Permissions.AppWorkflowsRead, Search("Workflows", PermissionIds.AppWorkflowsRead,
urlGenerator.WorkflowsUI, SearchResultType.Setting); urlGenerator.WorkflowsUI, SearchResultType.Setting);
return Task.FromResult(result); return Task.FromResult(result);

12
backend/src/Squidex.Domain.Apps.Entities/Apps/RolePermissionsProvider.cs

@ -21,15 +21,15 @@ namespace Squidex.Domain.Apps.Entities.Apps
{ {
this.appProvider = appProvider; this.appProvider = appProvider;
foreach (var field in typeof(Permissions).GetFields(BindingFlags.Public | BindingFlags.Static)) foreach (var field in typeof(PermissionIds).GetFields(BindingFlags.Public | BindingFlags.Static))
{ {
if (field.IsLiteral && !field.IsInitOnly) if (field.IsLiteral && !field.IsInitOnly)
{ {
var value = field.GetValue(null) as string; var value = field.GetValue(null) as string;
if (value?.StartsWith(Permissions.App, StringComparison.OrdinalIgnoreCase) == true) if (value?.StartsWith(PermissionIds.App, StringComparison.OrdinalIgnoreCase) == true)
{ {
if (value.IndexOf("{schema}", Permissions.App.Length, StringComparison.OrdinalIgnoreCase) >= 0) if (value.IndexOf("{schema}", PermissionIds.App.Length, StringComparison.OrdinalIgnoreCase) >= 0)
{ {
forAppSchemas.Add(value); forAppSchemas.Add(value);
} }
@ -50,9 +50,9 @@ namespace Squidex.Domain.Apps.Entities.Apps
foreach (var permission in forAppWithoutSchemas) foreach (var permission in forAppWithoutSchemas)
{ {
if (permission.Length > Permissions.App.Length + 1) if (permission.Length > PermissionIds.App.Length + 1)
{ {
var trimmed = permission[(Permissions.App.Length + 1)..]; var trimmed = permission[(PermissionIds.App.Length + 1)..];
if (trimmed.Length > 0) if (trimmed.Length > 0)
{ {
@ -63,7 +63,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
foreach (var permission in forAppSchemas) foreach (var permission in forAppSchemas)
{ {
var trimmed = permission[(Permissions.App.Length + 1)..]; var trimmed = permission[(PermissionIds.App.Length + 1)..];
foreach (var schema in schemaNames) foreach (var schema in schemaNames)
{ {

2
backend/src/Squidex.Domain.Apps.Entities/Assets/AssetsSearchSource.cs

@ -30,7 +30,7 @@ namespace Squidex.Domain.Apps.Entities.Assets
{ {
var result = new SearchResults(); var result = new SearchResults();
if (context.UserPermissions.Allows(Permissions.AppAssetsRead, context.App.Name)) if (context.UserPermissions.Allows(PermissionIds.AppAssetsRead, context.App.Name))
{ {
var filter = ClrFilter.Contains("fileName", query); var filter = ClrFilter.Contains("fileName", query);

6
backend/src/Squidex.Domain.Apps.Entities/Assets/DomainObject/AssetsBulkUpdateCommandMiddleware.cs

@ -180,7 +180,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
{ {
var command = new AnnotateAsset(); var command = new AnnotateAsset();
EnrichAndCheckPermission(task, command, Permissions.AppAssetsUpdate); EnrichAndCheckPermission(task, command, PermissionIds.AppAssetsUpdate);
return command; return command;
} }
@ -188,7 +188,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
{ {
var command = new MoveAsset(); var command = new MoveAsset();
EnrichAndCheckPermission(task, command, Permissions.AppAssetsUpdate); EnrichAndCheckPermission(task, command, PermissionIds.AppAssetsUpdate);
return command; return command;
} }
@ -196,7 +196,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
{ {
var command = new DeleteAsset(); var command = new DeleteAsset();
EnrichAndCheckPermission(task, command, Permissions.AppAssetsDelete); EnrichAndCheckPermission(task, command, PermissionIds.AppAssetsDelete);
return command; return command;
} }

2
backend/src/Squidex.Domain.Apps.Entities/Contents/ContentsSearchSource.cs

@ -88,7 +88,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
private static bool HasPermission(Context context, string schemaName) private static bool HasPermission(Context context, string schemaName)
{ {
return context.UserPermissions.Allows(Permissions.AppContentsReadOwn, context.App.Name, schemaName); return context.UserPermissions.Allows(PermissionIds.AppContentsReadOwn, context.App.Name, schemaName);
} }
private static string FormatName(IEnrichedContentEntity content, string masterLanguage) private static string FormatName(IEnrichedContentEntity content, string masterLanguage)

16
backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/ContentDomainObject.cs

@ -257,7 +257,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
private async Task ChangeCore(ChangeContentStatus c, ContentOperation operation) private async Task ChangeCore(ChangeContentStatus c, ContentOperation operation)
{ {
operation.MustHavePermission(Permissions.AppContentsChangeStatus); operation.MustHavePermission(PermissionIds.AppContentsChangeStatus);
operation.MustNotChangeSingleton(c.Status); operation.MustNotChangeSingleton(c.Status);
if (c.Status == Snapshot.EditingStatus()) if (c.Status == Snapshot.EditingStatus())
@ -310,7 +310,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
private async Task UpdateCore(UpdateContent c, ContentOperation operation) private async Task UpdateCore(UpdateContent c, ContentOperation operation)
{ {
operation.MustHavePermission(Permissions.AppContentsUpdate); operation.MustHavePermission(PermissionIds.AppContentsUpdate);
operation.MustHaveData(c.Data); operation.MustHaveData(c.Data);
if (!c.DoNotValidate) if (!c.DoNotValidate)
@ -345,7 +345,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
private async Task PatchCore(UpdateContent c, ContentOperation operation) private async Task PatchCore(UpdateContent c, ContentOperation operation)
{ {
operation.MustHavePermission(Permissions.AppContentsUpdate); operation.MustHavePermission(PermissionIds.AppContentsUpdate);
operation.MustHaveData(c.Data); operation.MustHaveData(c.Data);
if (!c.DoNotValidate) if (!c.DoNotValidate)
@ -380,7 +380,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
private void CancelChangeCore(CancelContentSchedule c, ContentOperation operation) private void CancelChangeCore(CancelContentSchedule c, ContentOperation operation)
{ {
operation.MustHavePermission(Permissions.AppContentsChangeStatusCancel); operation.MustHavePermission(PermissionIds.AppContentsChangeStatusCancel);
if (Snapshot.ScheduleJob != null) if (Snapshot.ScheduleJob != null)
{ {
@ -390,14 +390,14 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
private async Task ValidateCore(ContentOperation operation) private async Task ValidateCore(ContentOperation operation)
{ {
operation.MustHavePermission(Permissions.AppContentsRead); operation.MustHavePermission(PermissionIds.AppContentsRead);
await operation.ValidateContentAndInputAsync(Snapshot.Data, false, Snapshot.IsPublished()); await operation.ValidateContentAndInputAsync(Snapshot.Data, false, Snapshot.IsPublished());
} }
private async Task CreateDraftCore(CreateContentDraft c, ContentOperation operation) private async Task CreateDraftCore(CreateContentDraft c, ContentOperation operation)
{ {
operation.MustHavePermission(Permissions.AppContentsVersionCreate); operation.MustHavePermission(PermissionIds.AppContentsVersionCreate);
operation.MustCreateDraft(); operation.MustCreateDraft();
var status = await operation.GetInitialStatusAsync(); var status = await operation.GetInitialStatusAsync();
@ -407,7 +407,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
private void DeleteDraftCore(DeleteContentDraft c, ContentOperation operation) private void DeleteDraftCore(DeleteContentDraft c, ContentOperation operation)
{ {
operation.MustHavePermission(Permissions.AppContentsVersionDelete); operation.MustHavePermission(PermissionIds.AppContentsVersionDelete);
operation.MustDeleteDraft(); operation.MustDeleteDraft();
DeleteDraft(c); DeleteDraft(c);
@ -415,7 +415,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
private async Task DeleteCore(DeleteContent c, ContentOperation operation) private async Task DeleteCore(DeleteContent c, ContentOperation operation)
{ {
operation.MustHavePermission(Permissions.AppContentsDelete); operation.MustHavePermission(PermissionIds.AppContentsDelete);
operation.MustNotDeleteSingleton(); operation.MustNotDeleteSingleton();
if (!c.DoNotScript) if (!c.DoNotScript)

14
backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/ContentsBulkUpdateCommandMiddleware.cs

@ -207,7 +207,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
{ {
var command = new CreateContent(); var command = new CreateContent();
await EnrichAndCheckPermissionAsync(task, command, Permissions.AppContentsCreate); await EnrichAndCheckPermissionAsync(task, command, PermissionIds.AppContentsCreate);
return command; return command;
} }
@ -215,7 +215,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
{ {
var command = new UpdateContent(); var command = new UpdateContent();
await EnrichAndCheckPermissionAsync(task, command, Permissions.AppContentsUpdateOwn); await EnrichAndCheckPermissionAsync(task, command, PermissionIds.AppContentsUpdateOwn);
return command; return command;
} }
@ -223,7 +223,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
{ {
var command = new UpsertContent(); var command = new UpsertContent();
await EnrichAndCheckPermissionAsync(task, command, Permissions.AppContentsUpsert); await EnrichAndCheckPermissionAsync(task, command, PermissionIds.AppContentsUpsert);
return command; return command;
} }
@ -231,7 +231,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
{ {
var command = new PatchContent(); var command = new PatchContent();
await EnrichAndCheckPermissionAsync(task, command, Permissions.AppContentsUpdateOwn); await EnrichAndCheckPermissionAsync(task, command, PermissionIds.AppContentsUpdateOwn);
return command; return command;
} }
@ -239,7 +239,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
{ {
var command = new ValidateContent(); var command = new ValidateContent();
await EnrichAndCheckPermissionAsync(task, command, Permissions.AppContentsReadOwn); await EnrichAndCheckPermissionAsync(task, command, PermissionIds.AppContentsReadOwn);
return command; return command;
} }
@ -247,7 +247,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
{ {
var command = new ChangeContentStatus { Status = job.Status ?? Status.Draft }; var command = new ChangeContentStatus { Status = job.Status ?? Status.Draft };
await EnrichAndCheckPermissionAsync(task, command, Permissions.AppContentsChangeStatusOwn); await EnrichAndCheckPermissionAsync(task, command, PermissionIds.AppContentsChangeStatusOwn);
return command; return command;
} }
@ -255,7 +255,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
{ {
var command = new DeleteContent(); var command = new DeleteContent();
await EnrichAndCheckPermissionAsync(task, command, Permissions.AppContentsDeleteOwn); await EnrichAndCheckPermissionAsync(task, command, PermissionIds.AppContentsDeleteOwn);
return command; return command;
} }

2
backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/Guards/SecurityExtensions.cs

@ -30,7 +30,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject.Guards
throw new DomainForbiddenException(T.Get("common.errorNoPermission")); throw new DomainForbiddenException(T.Get("common.errorNoPermission"));
} }
var permission = Permissions.ForApp(permissionId, context.App.Name, context.Schema.SchemaDef.Name); var permission = PermissionIds.ForApp(permissionId, context.App.Name, context.Schema.SchemaDef.Name);
if (!permissions.Allows(permission)) if (!permissions.Allows(permission))
{ {

12
backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/ContentActions.cs

@ -226,7 +226,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents
}; };
} }
public static readonly IFieldResolver Resolver = ResolveAsync(Permissions.AppContentsCreate, c => public static readonly IFieldResolver Resolver = ResolveAsync(PermissionIds.AppContentsCreate, c =>
{ {
var contentId = c.GetArgument<string?>("id"); var contentId = c.GetArgument<string?>("id");
var contentData = c.GetArgument<ContentData>("data")!; var contentData = c.GetArgument<ContentData>("data")!;
@ -297,7 +297,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents
}; };
} }
public static readonly IFieldResolver Resolver = ResolveAsync(Permissions.AppContentsUpsert, c => public static readonly IFieldResolver Resolver = ResolveAsync(PermissionIds.AppContentsUpsert, c =>
{ {
var contentId = c.GetArgument<DomainId>("id"); var contentId = c.GetArgument<DomainId>("id");
var contentData = c.GetArgument<ContentData>("data")!; var contentData = c.GetArgument<ContentData>("data")!;
@ -346,7 +346,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents
}; };
} }
public static readonly IFieldResolver Resolver = ResolveAsync(Permissions.AppContentsUpdateOwn, c => public static readonly IFieldResolver Resolver = ResolveAsync(PermissionIds.AppContentsUpdateOwn, c =>
{ {
var contentId = c.GetArgument<DomainId>("id"); var contentId = c.GetArgument<DomainId>("id");
var contentData = c.GetArgument<ContentData>("data")!; var contentData = c.GetArgument<ContentData>("data")!;
@ -382,7 +382,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents
}; };
} }
public static readonly IFieldResolver Resolver = ResolveAsync(Permissions.AppContentsUpdateOwn, c => public static readonly IFieldResolver Resolver = ResolveAsync(PermissionIds.AppContentsUpdateOwn, c =>
{ {
var contentId = c.GetArgument<DomainId>("id"); var contentId = c.GetArgument<DomainId>("id");
var contentData = c.GetArgument<ContentData>("data")!; var contentData = c.GetArgument<ContentData>("data")!;
@ -421,7 +421,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents
} }
}; };
public static readonly IFieldResolver Resolver = ResolveAsync(Permissions.AppContentsChangeStatusOwn, c => public static readonly IFieldResolver Resolver = ResolveAsync(PermissionIds.AppContentsChangeStatusOwn, c =>
{ {
var contentId = c.GetArgument<DomainId>("id"); var contentId = c.GetArgument<DomainId>("id");
var contentStatus = c.GetArgument<Status>("status"); var contentStatus = c.GetArgument<Status>("status");
@ -449,7 +449,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents
} }
}; };
public static readonly IFieldResolver Resolver = ResolveAsync(Permissions.AppContentsDeleteOwn, c => public static readonly IFieldResolver Resolver = ResolveAsync(PermissionIds.AppContentsDeleteOwn, c =>
{ {
var contentId = c.GetArgument<DomainId>("id"); var contentId = c.GetArgument<DomainId>("id");

6
backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentQueryService.cs

@ -89,7 +89,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
var schema = await GetSchemaOrThrowAsync(context, schemaIdOrName, ct); var schema = await GetSchemaOrThrowAsync(context, schemaIdOrName, ct);
if (!HasPermission(context, schema, Permissions.AppContentsRead)) if (!HasPermission(context, schema, PermissionIds.AppContentsRead))
{ {
q = q with { CreatedBy = context.User.Token() }; q = q with { CreatedBy = context.User.Token() };
} }
@ -199,7 +199,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
schema = await appProvider.GetSchemaAsync(context.App.Id, schemaIdOrName, canCache, ct); schema = await appProvider.GetSchemaAsync(context.App.Id, schemaIdOrName, canCache, ct);
} }
if (schema != null && !HasPermission(context, schema, Permissions.AppContentsReadOwn)) if (schema != null && !HasPermission(context, schema, PermissionIds.AppContentsReadOwn))
{ {
throw new DomainForbiddenException(T.Get("schemas.noPermission")); throw new DomainForbiddenException(T.Get("schemas.noPermission"));
} }
@ -212,7 +212,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
{ {
var schemas = await appProvider.GetSchemasAsync(context.App.Id, ct); var schemas = await appProvider.GetSchemasAsync(context.App.Id, ct);
return schemas.Where(x => IsAccessible(x) && HasPermission(context, x, Permissions.AppContentsReadOwn)).ToList(); return schemas.Where(x => IsAccessible(x) && HasPermission(context, x, PermissionIds.AppContentsReadOwn)).ToList();
} }
private async Task<IResultList<IContentEntity>> QueryCoreAsync(Context context, Q q, ISchemaEntity schema, private async Task<IResultList<IContentEntity>> QueryCoreAsync(Context context, Q q, ISchemaEntity schema,

2
backend/src/Squidex.Domain.Apps.Entities/Context.cs

@ -60,7 +60,7 @@ namespace Squidex.Domain.Apps.Entities
var claimsIdentity = new ClaimsIdentity(); var claimsIdentity = new ClaimsIdentity();
var claimsPrincipal = new ClaimsPrincipal(claimsIdentity); var claimsPrincipal = new ClaimsPrincipal(claimsIdentity);
claimsIdentity.AddClaim(new Claim(SquidexClaimTypes.Permissions, Permissions.All)); claimsIdentity.AddClaim(new Claim(SquidexClaimTypes.Permissions, PermissionIds.All));
return new Context(claimsPrincipal, app); return new Context(claimsPrincipal, app);
} }

2
backend/src/Squidex.Domain.Apps.Entities/Schemas/SchemasSearchSource.cs

@ -84,7 +84,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas
private static bool HasPermission(Context context, NamedId<DomainId> schemaId) private static bool HasPermission(Context context, NamedId<DomainId> schemaId)
{ {
return context.Allows(Permissions.AppContentsReadOwn, schemaId.Name); return context.Allows(PermissionIds.AppContentsReadOwn, schemaId.Name);
} }
} }
} }

2
backend/src/Squidex.Domain.Users/DefaultUserService.cs

@ -179,7 +179,7 @@ namespace Squidex.Domain.Users
{ {
var permissions = values.Permissions?.ToIds().ToList() ?? new List<string>(); var permissions = values.Permissions?.ToIds().ToList() ?? new List<string>();
permissions.Add(Permissions.Admin); permissions.Add(PermissionIds.Admin);
values.Permissions = new PermissionSet(permissions); values.Permissions = new PermissionSet(permissions);
} }

2
backend/src/Squidex.Domain.Users/UserClaimsPrincipalFactoryWithEmail.cs

@ -33,7 +33,7 @@ namespace Squidex.Domain.Users
if (await UserManager.IsInRoleAsync(user, AdministratorRole)) if (await UserManager.IsInRoleAsync(user, AdministratorRole))
{ {
identity.AddClaim(new Claim(SquidexClaimTypes.Permissions, Permissions.Admin)); identity.AddClaim(new Claim(SquidexClaimTypes.Permissions, PermissionIds.Admin));
} }
return principal; return principal;

2
backend/src/Squidex.Shared/Identity/SquidexClaimTypes.cs

@ -32,5 +32,7 @@ namespace Squidex.Shared.Identity
public const string PictureUrlStore = "store"; public const string PictureUrlStore = "store";
public const string TotalApps = "urn:squidex:internal:totalApps"; public const string TotalApps = "urn:squidex:internal:totalApps";
public const string UIPrefix = "urn:squidex:custom";
} }
} }

23
backend/src/Squidex.Shared/Identity/SquidexClaimsExtensions.cs

@ -106,13 +106,32 @@ namespace Squidex.Shared.Identity
public static IEnumerable<(string Name, string Value)> GetCustomProperties(this IEnumerable<Claim> user) public static IEnumerable<(string Name, string Value)> GetCustomProperties(this IEnumerable<Claim> user)
{ {
var prefix = SquidexClaimTypes.CustomPrefix;
foreach (var claim in user)
{
var type = GetType(claim);
if (type.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
{
var name = type[(prefix.Length + 1)..].ToString();
yield return (name, claim.Value);
}
}
}
public static IEnumerable<(string Name, string Value)> GetUIProperties(this IEnumerable<Claim> user, string app)
{
var prefix = $"{SquidexClaimTypes.UIPrefix}:{app}";
foreach (var claim in user) foreach (var claim in user)
{ {
var type = GetType(claim); var type = GetType(claim);
if (type.StartsWith(SquidexClaimTypes.CustomPrefix, StringComparison.OrdinalIgnoreCase)) if (type.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
{ {
var name = type[(SquidexClaimTypes.CustomPrefix.Length + 1)..].ToString(); var name = type[(prefix.Length + 1)..].ToString();
yield return (name, claim.Value); yield return (name, claim.Value);
} }

2
backend/src/Squidex.Shared/PermissionExtensions.cs

@ -14,7 +14,7 @@ namespace Squidex.Shared
{ {
public static bool Allows(this PermissionSet permissions, string id, string app = Permission.Any, string schema = Permission.Any) public static bool Allows(this PermissionSet permissions, string id, string app = Permission.Any, string schema = Permission.Any)
{ {
var permission = Permissions.ForApp(id, app, schema); var permission = PermissionIds.ForApp(id, app, schema);
return permissions.Allows(permission); return permissions.Allows(permission);
} }

9
backend/src/Squidex.Shared/Permissions.cs → backend/src/Squidex.Shared/PermissionIds.cs

@ -11,7 +11,7 @@ using Squidex.Infrastructure.Security;
namespace Squidex.Shared namespace Squidex.Shared
{ {
public static class Permissions public static class PermissionIds
{ {
public const string All = "squidex.*"; public const string All = "squidex.*";
@ -173,9 +173,10 @@ namespace Squidex.Shared
{ {
Guard.NotNull(id); Guard.NotNull(id);
return new Permission(id id = id.Replace("{app}", app ?? Permission.Any, StringComparison.Ordinal);
.Replace("{app}", app ?? Permission.Any, StringComparison.Ordinal) id = id.Replace("{schema}", schema ?? Permission.Any, StringComparison.Ordinal);
.Replace("{schema}", schema ?? Permission.Any, StringComparison.Ordinal));
return new Permission(id);
} }
} }
} }

2
backend/src/Squidex.Web/Pipeline/ApiPermissionUnifier.cs

@ -22,7 +22,7 @@ namespace Squidex.Web.Pipeline
if (string.Equals(identity.FindFirst(identity.RoleClaimType)?.Value, AdministratorRole, StringComparison.OrdinalIgnoreCase)) if (string.Equals(identity.FindFirst(identity.RoleClaimType)?.Value, AdministratorRole, StringComparison.OrdinalIgnoreCase))
{ {
identity.AddClaim(new Claim(SquidexClaimTypes.Permissions, Permissions.Admin)); identity.AddClaim(new Claim(SquidexClaimTypes.Permissions, PermissionIds.Admin));
} }
return Task.FromResult(principal); return Task.FromResult(principal);

14
backend/src/Squidex.Web/Pipeline/AppResolver.cs

@ -145,7 +145,7 @@ namespace Squidex.Web.Pipeline
private static bool HasPermission(string appName, Context requestContext) private static bool HasPermission(string appName, Context requestContext)
{ {
return requestContext.UserPermissions.Includes(Permissions.ForApp(Permissions.App, appName)); return requestContext.UserPermissions.Includes(PermissionIds.ForApp(PermissionIds.App, appName));
} }
private static bool AllowAnonymous(ActionExecutingContext context) private static bool AllowAnonymous(ActionExecutingContext context)
@ -162,9 +162,9 @@ namespace Squidex.Web.Pipeline
return default; return default;
} }
if (app.Clients.TryGetValue(clientId, out var client) && app.Roles.TryGet(app.Name, client.Role, isFrontend, out var role)) if (app.TryGetClientRole(clientId, isFrontend, out var role))
{ {
return (clientId, client.Role, role.Permissions); return (clientId, role.Name, role.Permissions);
} }
return default; return default;
@ -179,9 +179,9 @@ namespace Squidex.Web.Pipeline
return default; return default;
} }
if (app.Roles.TryGet(app.Name, client.Value.Role, isFrontend, out var role)) if (app.TryGetRole(client.Value.Role, isFrontend, out var role))
{ {
return (client.Key, client.Value.Role, role.Permissions); return (client.Key, role.Name, role.Permissions);
} }
return default; return default;
@ -196,9 +196,9 @@ namespace Squidex.Web.Pipeline
return default; return default;
} }
if (app.Contributors.TryGetValue(subjectId, out var roleName) && app.Roles.TryGet(app.Name, roleName, isFrontend, out var role)) if (app.TryGetContributorRole(subjectId, isFrontend, out var role))
{ {
return (roleName, role.Permissions); return (role.Name, role.Permissions);
} }
return default; return default;

108
backend/src/Squidex.Web/Resources.cs

@ -17,123 +17,123 @@ namespace Squidex.Web
private readonly Dictionary<(string Id, string Schema), bool> permissions = new Dictionary<(string, string), bool>(); private readonly Dictionary<(string Id, string Schema), bool> permissions = new Dictionary<(string, string), bool>();
// Contents // Contents
public bool CanReadContent(string schema) => Can(Permissions.AppContentsReadOwn, schema); public bool CanReadContent(string schema) => Can(PermissionIds.AppContentsReadOwn, schema);
public bool CanCreateContent(string schema) => Can(Permissions.AppContentsCreate, schema); public bool CanCreateContent(string schema) => Can(PermissionIds.AppContentsCreate, schema);
public bool CanCreateContentVersion(string schema) => Can(Permissions.AppContentsVersionCreateOwn, schema); public bool CanCreateContentVersion(string schema) => Can(PermissionIds.AppContentsVersionCreateOwn, schema);
public bool CanDeleteContent(string schema) => Can(Permissions.AppContentsDeleteOwn, schema); public bool CanDeleteContent(string schema) => Can(PermissionIds.AppContentsDeleteOwn, schema);
public bool CanDeleteContentVersion(string schema) => Can(Permissions.AppContentsVersionDeleteOwn, schema); public bool CanDeleteContentVersion(string schema) => Can(PermissionIds.AppContentsVersionDeleteOwn, schema);
public bool CanChangeStatus(string schema) => Can(Permissions.AppContentsChangeStatus, schema); public bool CanChangeStatus(string schema) => Can(PermissionIds.AppContentsChangeStatus, schema);
public bool CanCancelContentStatus(string schema) => Can(Permissions.AppContentsChangeStatusCancelOwn, schema); public bool CanCancelContentStatus(string schema) => Can(PermissionIds.AppContentsChangeStatusCancelOwn, schema);
public bool CanUpdateContent(string schema) => Can(Permissions.AppContentsUpdateOwn, schema); public bool CanUpdateContent(string schema) => Can(PermissionIds.AppContentsUpdateOwn, schema);
// Schemas // Schemas
public bool CanUpdateSchema(string schema) => Can(Permissions.AppSchemasDelete, schema); public bool CanUpdateSchema(string schema) => Can(PermissionIds.AppSchemasDelete, schema);
public bool CanUpdateSchemaScripts(string schema) => Can(Permissions.AppSchemasScripts, schema); public bool CanUpdateSchemaScripts(string schema) => Can(PermissionIds.AppSchemasScripts, schema);
public bool CanPublishSchema(string schema) => Can(Permissions.AppSchemasPublish, schema); public bool CanPublishSchema(string schema) => Can(PermissionIds.AppSchemasPublish, schema);
public bool CanDeleteSchema(string schema) => Can(Permissions.AppSchemasDelete, schema); public bool CanDeleteSchema(string schema) => Can(PermissionIds.AppSchemasDelete, schema);
public bool CanCreateSchema => Can(Permissions.AppSchemasCreate); public bool CanCreateSchema => Can(PermissionIds.AppSchemasCreate);
public bool CanUpdateSettings => Can(Permissions.AppUpdateSettings); public bool CanUpdateSettings => Can(PermissionIds.AppUpdateSettings);
// Asset Scripts // Asset Scripts
public bool CanUpdateAssetsScripts => Can(Permissions.AppAssetsScriptsUpdate); public bool CanUpdateAssetsScripts => Can(PermissionIds.AppAssetsScriptsUpdate);
// Contributors // Contributors
public bool CanAssignContributor => Can(Permissions.AppContributorsAssign); public bool CanAssignContributor => Can(PermissionIds.AppContributorsAssign);
public bool CanRevokeContributor => Can(Permissions.AppContributorsRevoke); public bool CanRevokeContributor => Can(PermissionIds.AppContributorsRevoke);
// Workflows // Workflows
public bool CanCreateWorkflow => Can(Permissions.AppWorkflowsCreate); public bool CanCreateWorkflow => Can(PermissionIds.AppWorkflowsCreate);
public bool CanUpdateWorkflow => Can(Permissions.AppWorkflowsUpdate); public bool CanUpdateWorkflow => Can(PermissionIds.AppWorkflowsUpdate);
public bool CanDeleteWorkflow => Can(Permissions.AppWorkflowsDelete); public bool CanDeleteWorkflow => Can(PermissionIds.AppWorkflowsDelete);
// Roles // Roles
public bool CanCreateRole => Can(Permissions.AppRolesCreate); public bool CanCreateRole => Can(PermissionIds.AppRolesCreate);
public bool CanUpdateRole => Can(Permissions.AppRolesUpdate); public bool CanUpdateRole => Can(PermissionIds.AppRolesUpdate);
public bool CanDeleteRole => Can(Permissions.AppRolesDelete); public bool CanDeleteRole => Can(PermissionIds.AppRolesDelete);
// Languages // Languages
public bool CanCreateLanguage => Can(Permissions.AppLanguagesCreate); public bool CanCreateLanguage => Can(PermissionIds.AppLanguagesCreate);
public bool CanUpdateLanguage => Can(Permissions.AppLanguagesUpdate); public bool CanUpdateLanguage => Can(PermissionIds.AppLanguagesUpdate);
public bool CanDeleteLanguage => Can(Permissions.AppLanguagesDelete); public bool CanDeleteLanguage => Can(PermissionIds.AppLanguagesDelete);
// Clients // Clients
public bool CanCreateClient => Can(Permissions.AppClientsCreate); public bool CanCreateClient => Can(PermissionIds.AppClientsCreate);
public bool CanUpdateClient => Can(Permissions.AppClientsUpdate); public bool CanUpdateClient => Can(PermissionIds.AppClientsUpdate);
public bool CanDeleteClient => Can(Permissions.AppClientsDelete); public bool CanDeleteClient => Can(PermissionIds.AppClientsDelete);
// Rules // Rules
public bool CanDisableRule => Can(Permissions.AppRulesDisable); public bool CanDisableRule => Can(PermissionIds.AppRulesDisable);
public bool CanCreateRule => Can(Permissions.AppRulesCreate); public bool CanCreateRule => Can(PermissionIds.AppRulesCreate);
public bool CanUpdateRule => Can(Permissions.AppRulesUpdate); public bool CanUpdateRule => Can(PermissionIds.AppRulesUpdate);
public bool CanDeleteRule => Can(Permissions.AppRulesDelete); public bool CanDeleteRule => Can(PermissionIds.AppRulesDelete);
public bool CanReadRuleEvents => Can(Permissions.AppRulesEventsRead); public bool CanReadRuleEvents => Can(PermissionIds.AppRulesEventsRead);
public bool CanUpdateRuleEvents => Can(Permissions.AppRulesEventsUpdate); public bool CanUpdateRuleEvents => Can(PermissionIds.AppRulesEventsUpdate);
public bool CanRunRuleEvents => Can(Permissions.AppRulesEventsRun); public bool CanRunRuleEvents => Can(PermissionIds.AppRulesEventsRun);
public bool CanDeleteRuleEvents => Can(Permissions.AppRulesEventsDelete); public bool CanDeleteRuleEvents => Can(PermissionIds.AppRulesEventsDelete);
// Users // Users
public bool CanReadUsers => Can(Permissions.AdminUsersRead); public bool CanReadUsers => Can(PermissionIds.AdminUsersRead);
public bool CanCreateUser => Can(Permissions.AdminUsersCreate); public bool CanCreateUser => Can(PermissionIds.AdminUsersCreate);
public bool CanLockUser => Can(Permissions.AdminUsersLock); public bool CanLockUser => Can(PermissionIds.AdminUsersLock);
public bool CanUnlockUser => Can(Permissions.AdminUsersUnlock); public bool CanUnlockUser => Can(PermissionIds.AdminUsersUnlock);
public bool CanUpdateUser => Can(Permissions.AdminUsersUpdate); public bool CanUpdateUser => Can(PermissionIds.AdminUsersUpdate);
// Assets // Assets
public bool CanUploadAsset => Can(Permissions.AppAssetsUpload); public bool CanUploadAsset => Can(PermissionIds.AppAssetsUpload);
public bool CanCreateAsset => Can(Permissions.AppAssetsCreate); public bool CanCreateAsset => Can(PermissionIds.AppAssetsCreate);
public bool CanDeleteAsset => Can(Permissions.AppAssetsDelete); public bool CanDeleteAsset => Can(PermissionIds.AppAssetsDelete);
public bool CanUpdateAsset => Can(Permissions.AppAssetsUpdate); public bool CanUpdateAsset => Can(PermissionIds.AppAssetsUpdate);
public bool CanReadAssets => Can(Permissions.AppAssetsRead); public bool CanReadAssets => Can(PermissionIds.AppAssetsRead);
// Events // Events
public bool CanReadEvents => Can(Permissions.AdminEventsRead); public bool CanReadEvents => Can(PermissionIds.AdminEventsRead);
public bool CanManageEvents => Can(Permissions.AdminEventsManage); public bool CanManageEvents => Can(PermissionIds.AdminEventsManage);
// Backups // Backups
public bool CanRestoreBackup => Can(Permissions.AdminRestore); public bool CanRestoreBackup => Can(PermissionIds.AdminRestore);
public bool CanCreateBackup => Can(Permissions.AppBackupsCreate); public bool CanCreateBackup => Can(PermissionIds.AppBackupsCreate);
public bool CanDeleteBackup => Can(Permissions.AppBackupsDelete); public bool CanDeleteBackup => Can(PermissionIds.AppBackupsDelete);
public bool CanDownloadBackup => Can(Permissions.AppBackupsDownload); public bool CanDownloadBackup => Can(PermissionIds.AppBackupsDownload);
public Context Context { get; set; } public Context Context { get; set; }
@ -209,7 +209,7 @@ namespace Squidex.Web
} }
} }
var permission = Permissions.ForApp(id, app, schema); var permission = PermissionIds.ForApp(id, app, schema);
return Context.UserPermissions.Allows(permission) || additional?.Allows(permission) == true; return Context.UserPermissions.Allows(permission) || additional?.Allows(permission) == true;
} }

4
backend/src/Squidex/Areas/Api/Controllers/Apps/AppAssetsController.cs

@ -36,7 +36,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
[HttpGet] [HttpGet]
[Route("apps/{app}/assets/scripts")] [Route("apps/{app}/assets/scripts")]
[ProducesResponseType(typeof(AssetScriptsDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(AssetScriptsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppAssetSScriptsRead)] [ApiPermissionOrAnonymous(PermissionIds.AppAssetSScriptsRead)]
[ApiCosts(0)] [ApiCosts(0)]
public IActionResult GetAssetScripts(string app) public IActionResult GetAssetScripts(string app)
{ {
@ -61,7 +61,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
[HttpPut] [HttpPut]
[Route("apps/{app}/assets/scripts")] [Route("apps/{app}/assets/scripts")]
[ProducesResponseType(typeof(AssetScriptsDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(AssetScriptsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppAssetsScriptsUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppAssetsScriptsUpdate)]
[ApiCosts(0)] [ApiCosts(0)]
public async Task<IActionResult> PutAssetScripts(string app, [FromBody] UpdateAssetScriptsDto request) public async Task<IActionResult> PutAssetScripts(string app, [FromBody] UpdateAssetScriptsDto request)
{ {

8
backend/src/Squidex/Areas/Api/Controllers/Apps/AppClientsController.cs

@ -41,7 +41,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
[HttpGet] [HttpGet]
[Route("apps/{app}/clients/")] [Route("apps/{app}/clients/")]
[ProducesResponseType(typeof(ClientsDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ClientsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppClientsRead)] [ApiPermissionOrAnonymous(PermissionIds.AppClientsRead)]
[ApiCosts(0)] [ApiCosts(0)]
public IActionResult GetClients(string app) public IActionResult GetClients(string app)
{ {
@ -72,7 +72,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
[HttpPost] [HttpPost]
[Route("apps/{app}/clients/")] [Route("apps/{app}/clients/")]
[ProducesResponseType(typeof(ClientsDto), 201)] [ProducesResponseType(typeof(ClientsDto), 201)]
[ApiPermissionOrAnonymous(Permissions.AppClientsCreate)] [ApiPermissionOrAnonymous(PermissionIds.AppClientsCreate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PostClient(string app, [FromBody] CreateClientDto request) public async Task<IActionResult> PostClient(string app, [FromBody] CreateClientDto request)
{ {
@ -100,7 +100,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
[HttpPut] [HttpPut]
[Route("apps/{app}/clients/{id}/")] [Route("apps/{app}/clients/{id}/")]
[ProducesResponseType(typeof(ClientsDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ClientsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppClientsUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppClientsUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PutClient(string app, string id, [FromBody] UpdateClientDto request) public async Task<IActionResult> PutClient(string app, string id, [FromBody] UpdateClientDto request)
{ {
@ -126,7 +126,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
[HttpDelete] [HttpDelete]
[Route("apps/{app}/clients/{id}/")] [Route("apps/{app}/clients/{id}/")]
[ProducesResponseType(typeof(ClientsDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ClientsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppClientsDelete)] [ApiPermissionOrAnonymous(PermissionIds.AppClientsDelete)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> DeleteClient(string app, string id) public async Task<IActionResult> DeleteClient(string app, string id)
{ {

6
backend/src/Squidex/Areas/Api/Controllers/Apps/AppContributorsController.cs

@ -50,7 +50,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
[HttpGet] [HttpGet]
[Route("apps/{app}/contributors/")] [Route("apps/{app}/contributors/")]
[ProducesResponseType(typeof(ContributorsDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ContributorsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppContributorsRead)] [ApiPermissionOrAnonymous(PermissionIds.AppContributorsRead)]
[ApiCosts(0)] [ApiCosts(0)]
public IActionResult GetContributors(string app) public IActionResult GetContributors(string app)
{ {
@ -77,7 +77,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
[HttpPost] [HttpPost]
[Route("apps/{app}/contributors/")] [Route("apps/{app}/contributors/")]
[ProducesResponseType(typeof(ContributorsDto), 201)] [ProducesResponseType(typeof(ContributorsDto), 201)]
[ApiPermissionOrAnonymous(Permissions.AppContributorsAssign)] [ApiPermissionOrAnonymous(PermissionIds.AppContributorsAssign)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PostContributor(string app, [FromBody] AssignContributorDto request) public async Task<IActionResult> PostContributor(string app, [FromBody] AssignContributorDto request)
{ {
@ -122,7 +122,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
[HttpDelete] [HttpDelete]
[Route("apps/{app}/contributors/{id}/")] [Route("apps/{app}/contributors/{id}/")]
[ProducesResponseType(typeof(ContributorsDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ContributorsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppContributorsRevoke)] [ApiPermissionOrAnonymous(PermissionIds.AppContributorsRevoke)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> DeleteContributor(string app, string id) public async Task<IActionResult> DeleteContributor(string app, string id)
{ {

8
backend/src/Squidex/Areas/Api/Controllers/Apps/AppLanguagesController.cs

@ -39,7 +39,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
[HttpGet] [HttpGet]
[Route("apps/{app}/languages/")] [Route("apps/{app}/languages/")]
[ProducesResponseType(typeof(AppLanguagesDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(AppLanguagesDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppLanguagesRead)] [ApiPermissionOrAnonymous(PermissionIds.AppLanguagesRead)]
[ApiCosts(0)] [ApiCosts(0)]
public IActionResult GetLanguages(string app) public IActionResult GetLanguages(string app)
{ {
@ -66,7 +66,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
[HttpPost] [HttpPost]
[Route("apps/{app}/languages/")] [Route("apps/{app}/languages/")]
[ProducesResponseType(typeof(AppLanguagesDto), 201)] [ProducesResponseType(typeof(AppLanguagesDto), 201)]
[ApiPermissionOrAnonymous(Permissions.AppLanguagesCreate)] [ApiPermissionOrAnonymous(PermissionIds.AppLanguagesCreate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PostLanguage(string app, [FromBody] AddLanguageDto request) public async Task<IActionResult> PostLanguage(string app, [FromBody] AddLanguageDto request)
{ {
@ -91,7 +91,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
[HttpPut] [HttpPut]
[Route("apps/{app}/languages/{language}/")] [Route("apps/{app}/languages/{language}/")]
[ProducesResponseType(typeof(AppLanguagesDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(AppLanguagesDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppLanguagesUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppLanguagesUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PutLanguage(string app, string language, [FromBody] UpdateLanguageDto request) public async Task<IActionResult> PutLanguage(string app, string language, [FromBody] UpdateLanguageDto request)
{ {
@ -115,7 +115,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
[HttpDelete] [HttpDelete]
[Route("apps/{app}/languages/{language}/")] [Route("apps/{app}/languages/{language}/")]
[ProducesResponseType(typeof(AppLanguagesDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(AppLanguagesDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppLanguagesDelete)] [ApiPermissionOrAnonymous(PermissionIds.AppLanguagesDelete)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> DeleteLanguage(string app, string language) public async Task<IActionResult> DeleteLanguage(string app, string language)
{ {

10
backend/src/Squidex/Areas/Api/Controllers/Apps/AppRolesController.cs

@ -42,7 +42,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
[HttpGet] [HttpGet]
[Route("apps/{app}/roles/")] [Route("apps/{app}/roles/")]
[ProducesResponseType(typeof(RolesDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(RolesDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppRolesRead)] [ApiPermissionOrAnonymous(PermissionIds.AppRolesRead)]
[ApiCosts(0)] [ApiCosts(0)]
public IActionResult GetRoles(string app) public IActionResult GetRoles(string app)
{ {
@ -67,7 +67,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
[HttpGet] [HttpGet]
[Route("apps/{app}/roles/permissions")] [Route("apps/{app}/roles/permissions")]
[ProducesResponseType(typeof(string[]), StatusCodes.Status200OK)] [ProducesResponseType(typeof(string[]), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppRolesRead)] [ApiPermissionOrAnonymous(PermissionIds.AppRolesRead)]
[ApiCosts(0)] [ApiCosts(0)]
public IActionResult GetPermissions(string app) public IActionResult GetPermissions(string app)
{ {
@ -94,7 +94,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
[HttpPost] [HttpPost]
[Route("apps/{app}/roles/")] [Route("apps/{app}/roles/")]
[ProducesResponseType(typeof(RolesDto), 201)] [ProducesResponseType(typeof(RolesDto), 201)]
[ApiPermissionOrAnonymous(Permissions.AppRolesCreate)] [ApiPermissionOrAnonymous(PermissionIds.AppRolesCreate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PostRole(string app, [FromBody] AddRoleDto request) public async Task<IActionResult> PostRole(string app, [FromBody] AddRoleDto request)
{ {
@ -119,7 +119,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
[HttpPut] [HttpPut]
[Route("apps/{app}/roles/{roleName}/")] [Route("apps/{app}/roles/{roleName}/")]
[ProducesResponseType(typeof(RolesDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(RolesDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppRolesUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppRolesUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
[UrlDecodeRouteParams] [UrlDecodeRouteParams]
public async Task<IActionResult> PutRole(string app, string roleName, [FromBody] UpdateRoleDto request) public async Task<IActionResult> PutRole(string app, string roleName, [FromBody] UpdateRoleDto request)
@ -144,7 +144,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
[HttpDelete] [HttpDelete]
[Route("apps/{app}/roles/{roleName}/")] [Route("apps/{app}/roles/{roleName}/")]
[ProducesResponseType(typeof(RolesDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(RolesDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppRolesDelete)] [ApiPermissionOrAnonymous(PermissionIds.AppRolesDelete)]
[ApiCosts(1)] [ApiCosts(1)]
[UrlDecodeRouteParams] [UrlDecodeRouteParams]
public async Task<IActionResult> DeleteRole(string app, string roleName) public async Task<IActionResult> DeleteRole(string app, string roleName)

2
backend/src/Squidex/Areas/Api/Controllers/Apps/AppSettingsController.cs

@ -61,7 +61,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
[HttpPut] [HttpPut]
[Route("apps/{app}/settings")] [Route("apps/{app}/settings")]
[ProducesResponseType(typeof(AppSettingsDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(AppSettingsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppUpdateSettings)] [ApiPermissionOrAnonymous(PermissionIds.AppUpdateSettings)]
[ApiCosts(0)] [ApiCosts(0)]
public async Task<IActionResult> PutSettings(string app, [FromBody] UpdateAppSettingsDto request) public async Task<IActionResult> PutSettings(string app, [FromBody] UpdateAppSettingsDto request)
{ {

8
backend/src/Squidex/Areas/Api/Controllers/Apps/AppWorkflowsController.cs

@ -43,7 +43,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
[HttpGet] [HttpGet]
[Route("apps/{app}/workflows/")] [Route("apps/{app}/workflows/")]
[ProducesResponseType(typeof(WorkflowsDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(WorkflowsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppWorkflowsRead)] [ApiPermissionOrAnonymous(PermissionIds.AppWorkflowsRead)]
[ApiCosts(0)] [ApiCosts(0)]
public IActionResult GetWorkflows(string app) public IActionResult GetWorkflows(string app)
{ {
@ -70,7 +70,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
[HttpPost] [HttpPost]
[Route("apps/{app}/workflows/")] [Route("apps/{app}/workflows/")]
[ProducesResponseType(typeof(WorkflowsDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(WorkflowsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppWorkflowsUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppWorkflowsUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PostWorkflow(string app, [FromBody] AddWorkflowDto request) public async Task<IActionResult> PostWorkflow(string app, [FromBody] AddWorkflowDto request)
{ {
@ -95,7 +95,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
[HttpPut] [HttpPut]
[Route("apps/{app}/workflows/{id}")] [Route("apps/{app}/workflows/{id}")]
[ProducesResponseType(typeof(WorkflowsDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(WorkflowsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppWorkflowsUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppWorkflowsUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PutWorkflow(string app, DomainId id, [FromBody] UpdateWorkflowDto request) public async Task<IActionResult> PutWorkflow(string app, DomainId id, [FromBody] UpdateWorkflowDto request)
{ {
@ -118,7 +118,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
[HttpDelete] [HttpDelete]
[Route("apps/{app}/workflows/{id}")] [Route("apps/{app}/workflows/{id}")]
[ProducesResponseType(typeof(WorkflowsDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(WorkflowsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppWorkflowsUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppWorkflowsUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> DeleteWorkflow(string app, DomainId id) public async Task<IActionResult> DeleteWorkflow(string app, DomainId id)
{ {

8
backend/src/Squidex/Areas/Api/Controllers/Apps/AppsController.cs

@ -135,7 +135,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
[HttpPut] [HttpPut]
[Route("apps/{app}/")] [Route("apps/{app}/")]
[ProducesResponseType(typeof(AppDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(AppDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppUpdate)]
[ApiCosts(0)] [ApiCosts(0)]
public async Task<IActionResult> PutApp(string app, [FromBody] UpdateAppDto request) public async Task<IActionResult> PutApp(string app, [FromBody] UpdateAppDto request)
{ {
@ -157,7 +157,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
[HttpPost] [HttpPost]
[Route("apps/{app}/image")] [Route("apps/{app}/image")]
[ProducesResponseType(typeof(AppDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(AppDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppImageUpload)] [ApiPermissionOrAnonymous(PermissionIds.AppImageUpload)]
[ApiCosts(0)] [ApiCosts(0)]
public async Task<IActionResult> UploadImage(string app, IFormFile file) public async Task<IActionResult> UploadImage(string app, IFormFile file)
{ {
@ -177,7 +177,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
[HttpDelete] [HttpDelete]
[Route("apps/{app}/image")] [Route("apps/{app}/image")]
[ProducesResponseType(typeof(AppDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(AppDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppImageDelete)] [ApiPermissionOrAnonymous(PermissionIds.AppImageDelete)]
[ApiCosts(0)] [ApiCosts(0)]
public async Task<IActionResult> DeleteImage(string app) public async Task<IActionResult> DeleteImage(string app)
{ {
@ -196,7 +196,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
/// </returns> /// </returns>
[HttpDelete] [HttpDelete]
[Route("apps/{app}/")] [Route("apps/{app}/")]
[ApiPermission(Permissions.AppDelete)] [ApiPermission(PermissionIds.AppDelete)]
[ApiCosts(0)] [ApiCosts(0)]
public async Task<IActionResult> DeleteApp(string app) public async Task<IActionResult> DeleteApp(string app)
{ {

53
backend/src/Squidex/Areas/Api/Controllers/Apps/Models/AppDto.cs

@ -18,6 +18,8 @@ using Squidex.Infrastructure.Json.Objects;
using Squidex.Infrastructure.Reflection; using Squidex.Infrastructure.Reflection;
using Squidex.Infrastructure.Security; using Squidex.Infrastructure.Security;
using Squidex.Infrastructure.Validation; using Squidex.Infrastructure.Validation;
using Squidex.Shared;
using Squidex.Shared.Identity;
using Squidex.Web; using Squidex.Web;
#pragma warning disable RECS0033 // Convert 'if' to '||' expression #pragma warning disable RECS0033 // Convert 'if' to '||' expression
@ -88,7 +90,7 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models
/// The properties from the role. /// The properties from the role.
/// </summary> /// </summary>
[LocalizedRequired] [LocalizedRequired]
public JsonValue RoleProperties { get; set; } public JsonObject RoleProperties { get; set; }
public static AppDto FromDomain(IAppEntity app, string userId, bool isFrontend, Resources resources) public static AppDto FromDomain(IAppEntity app, string userId, bool isFrontend, Resources resources)
{ {
@ -98,19 +100,19 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models
var isContributor = false; var isContributor = false;
if (app.Contributors.TryGetValue(userId, out var roleName) && app.Roles.TryGet(app.Name, roleName, isFrontend, out var role)) if (app.TryGetContributorRole(userId, isFrontend, out var role))
{ {
isContributor = true; isContributor = true;
result.RoleName = roleName; result.RoleName = role.Name;
result.RoleProperties = role.Properties; result.RoleProperties = role.Properties;
result.Permissions = permissions.ToIds(); result.Permissions = permissions.ToIds();
permissions = role.Permissions; permissions = role.Permissions;
} }
else if (app.Clients.TryGetValue(userId, out var client) && app.Roles.TryGet(app.Name, client.Role, isFrontend, out role)) else if (app.TryGetClientRole(userId, isFrontend, out role))
{ {
result.RoleName = roleName; result.RoleName = role.Name;
result.RoleProperties = role.Properties; result.RoleProperties = role.Properties;
result.Permissions = permissions.ToIds(); result.Permissions = permissions.ToIds();
@ -121,7 +123,12 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models
result.RoleProperties = new JsonObject(); result.RoleProperties = new JsonObject();
} }
if (resources.Includes(Shared.Permissions.ForApp(Shared.Permissions.AppContents, app.Name), permissions)) foreach (var (key, value) in resources.Context.User.Claims.GetUIProperties(app.Name))
{
result.RoleProperties[key] = JsonValue.Create(value);
}
if (resources.Includes(PermissionIds.ForApp(PermissionIds.AppContents, app.Name), permissions))
{ {
result.CanAccessContent = true; result.CanAccessContent = true;
} }
@ -148,103 +155,103 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models
resources.Url<AppContributorsController>(x => nameof(x.DeleteMyself), values)); resources.Url<AppContributorsController>(x => nameof(x.DeleteMyself), values));
} }
if (resources.IsAllowed(Shared.Permissions.AppDelete, Name, additional: permissions)) if (resources.IsAllowed(PermissionIds.AppDelete, Name, additional: permissions))
{ {
AddDeleteLink("delete", AddDeleteLink("delete",
resources.Url<AppsController>(x => nameof(x.DeleteApp), values)); resources.Url<AppsController>(x => nameof(x.DeleteApp), values));
} }
if (resources.IsAllowed(Shared.Permissions.AppUpdate, Name, additional: permissions)) if (resources.IsAllowed(PermissionIds.AppUpdate, Name, additional: permissions))
{ {
AddPutLink("update", AddPutLink("update",
resources.Url<AppsController>(x => nameof(x.PutApp), values)); resources.Url<AppsController>(x => nameof(x.PutApp), values));
} }
if (resources.IsAllowed(Shared.Permissions.AppAssetsRead, Name, additional: permissions)) if (resources.IsAllowed(PermissionIds.AppAssetsRead, Name, additional: permissions))
{ {
AddGetLink("assets", AddGetLink("assets",
resources.Url<AssetsController>(x => nameof(x.GetAssets), values)); resources.Url<AssetsController>(x => nameof(x.GetAssets), values));
} }
if (resources.IsAllowed(Shared.Permissions.AppBackupsRead, Name, additional: permissions)) if (resources.IsAllowed(PermissionIds.AppBackupsRead, Name, additional: permissions))
{ {
AddGetLink("backups", AddGetLink("backups",
resources.Url<BackupsController>(x => nameof(x.GetBackups), values)); resources.Url<BackupsController>(x => nameof(x.GetBackups), values));
} }
if (resources.IsAllowed(Shared.Permissions.AppClientsRead, Name, additional: permissions)) if (resources.IsAllowed(PermissionIds.AppClientsRead, Name, additional: permissions))
{ {
AddGetLink("clients", AddGetLink("clients",
resources.Url<AppClientsController>(x => nameof(x.GetClients), values)); resources.Url<AppClientsController>(x => nameof(x.GetClients), values));
} }
if (resources.IsAllowed(Shared.Permissions.AppContributorsRead, Name, additional: permissions)) if (resources.IsAllowed(PermissionIds.AppContributorsRead, Name, additional: permissions))
{ {
AddGetLink("contributors", AddGetLink("contributors",
resources.Url<AppContributorsController>(x => nameof(x.GetContributors), values)); resources.Url<AppContributorsController>(x => nameof(x.GetContributors), values));
} }
if (resources.IsAllowed(Shared.Permissions.AppLanguagesRead, Name, additional: permissions)) if (resources.IsAllowed(PermissionIds.AppLanguagesRead, Name, additional: permissions))
{ {
AddGetLink("languages", AddGetLink("languages",
resources.Url<AppLanguagesController>(x => nameof(x.GetLanguages), values)); resources.Url<AppLanguagesController>(x => nameof(x.GetLanguages), values));
} }
if (resources.IsAllowed(Shared.Permissions.AppPlansRead, Name, additional: permissions)) if (resources.IsAllowed(PermissionIds.AppPlansRead, Name, additional: permissions))
{ {
AddGetLink("plans", AddGetLink("plans",
resources.Url<AppPlansController>(x => nameof(x.GetPlans), values)); resources.Url<AppPlansController>(x => nameof(x.GetPlans), values));
} }
if (resources.IsAllowed(Shared.Permissions.AppRolesRead, Name, additional: permissions)) if (resources.IsAllowed(PermissionIds.AppRolesRead, Name, additional: permissions))
{ {
AddGetLink("roles", AddGetLink("roles",
resources.Url<AppRolesController>(x => nameof(x.GetRoles), values)); resources.Url<AppRolesController>(x => nameof(x.GetRoles), values));
} }
if (resources.IsAllowed(Shared.Permissions.AppRulesRead, Name, additional: permissions)) if (resources.IsAllowed(PermissionIds.AppRulesRead, Name, additional: permissions))
{ {
AddGetLink("rules", AddGetLink("rules",
resources.Url<RulesController>(x => nameof(x.GetRules), values)); resources.Url<RulesController>(x => nameof(x.GetRules), values));
} }
if (resources.IsAllowed(Shared.Permissions.AppSchemasRead, Name, additional: permissions)) if (resources.IsAllowed(PermissionIds.AppSchemasRead, Name, additional: permissions))
{ {
AddGetLink("schemas", AddGetLink("schemas",
resources.Url<SchemasController>(x => nameof(x.GetSchemas), values)); resources.Url<SchemasController>(x => nameof(x.GetSchemas), values));
} }
if (resources.IsAllowed(Shared.Permissions.AppWorkflowsRead, Name, additional: permissions)) if (resources.IsAllowed(PermissionIds.AppWorkflowsRead, Name, additional: permissions))
{ {
AddGetLink("workflows", AddGetLink("workflows",
resources.Url<AppWorkflowsController>(x => nameof(x.GetWorkflows), values)); resources.Url<AppWorkflowsController>(x => nameof(x.GetWorkflows), values));
} }
if (resources.IsAllowed(Shared.Permissions.AppSchemasCreate, Name, additional: permissions)) if (resources.IsAllowed(PermissionIds.AppSchemasCreate, Name, additional: permissions))
{ {
AddPostLink("schemas/create", AddPostLink("schemas/create",
resources.Url<SchemasController>(x => nameof(x.PostSchema), values)); resources.Url<SchemasController>(x => nameof(x.PostSchema), values));
} }
if (resources.IsAllowed(Shared.Permissions.AppAssetsCreate, Name, additional: permissions)) if (resources.IsAllowed(PermissionIds.AppAssetsCreate, Name, additional: permissions))
{ {
AddPostLink("assets/create", AddPostLink("assets/create",
resources.Url<SchemasController>(x => nameof(x.PostSchema), values)); resources.Url<SchemasController>(x => nameof(x.PostSchema), values));
} }
if (resources.IsAllowed(Shared.Permissions.AppImageUpload, Name, additional: permissions)) if (resources.IsAllowed(PermissionIds.AppImageUpload, Name, additional: permissions))
{ {
AddPostLink("image/upload", AddPostLink("image/upload",
resources.Url<AppsController>(x => nameof(x.UploadImage), values)); resources.Url<AppsController>(x => nameof(x.UploadImage), values));
} }
if (resources.IsAllowed(Shared.Permissions.AppImageDelete, Name, additional: permissions)) if (resources.IsAllowed(PermissionIds.AppImageDelete, Name, additional: permissions))
{ {
AddDeleteLink("image/delete", AddDeleteLink("image/delete",
resources.Url<AppsController>(x => nameof(x.DeleteImage), values)); resources.Url<AppsController>(x => nameof(x.DeleteImage), values));
} }
if (resources.IsAllowed(Shared.Permissions.AppAssetsScriptsUpdate, Name, additional: permissions)) if (resources.IsAllowed(PermissionIds.AppAssetsScriptsUpdate, Name, additional: permissions))
{ {
AddDeleteLink("assets/scripts", AddDeleteLink("assets/scripts",
resources.Url<AppAssetsController>(x => nameof(x.GetAssetScripts), values)); resources.Url<AppAssetsController>(x => nameof(x.GetAssetScripts), values));

10
backend/src/Squidex/Areas/Api/Controllers/Assets/AssetFoldersController.cs

@ -49,7 +49,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
[HttpGet] [HttpGet]
[Route("apps/{app}/assets/folders", Order = -1)] [Route("apps/{app}/assets/folders", Order = -1)]
[ProducesResponseType(typeof(AssetFoldersDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(AssetFoldersDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppAssetsRead)] [ApiPermissionOrAnonymous(PermissionIds.AppAssetsRead)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> GetAssetFolders(string app, [FromQuery] DomainId parentId, [FromQuery] AssetFolderScope scope = AssetFolderScope.PathAndItems) public async Task<IActionResult> GetAssetFolders(string app, [FromQuery] DomainId parentId, [FromQuery] AssetFolderScope scope = AssetFolderScope.PathAndItems)
{ {
@ -81,7 +81,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
[Route("apps/{app}/assets/folders", Order = -1)] [Route("apps/{app}/assets/folders", Order = -1)]
[ProducesResponseType(typeof(AssetFolderDto), 201)] [ProducesResponseType(typeof(AssetFolderDto), 201)]
[AssetRequestSizeLimit] [AssetRequestSizeLimit]
[ApiPermissionOrAnonymous(Permissions.AppAssetsUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppAssetsUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PostAssetFolder(string app, [FromBody] CreateAssetFolderDto request) public async Task<IActionResult> PostAssetFolder(string app, [FromBody] CreateAssetFolderDto request)
{ {
@ -107,7 +107,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
[Route("apps/{app}/assets/folders/{id}/", Order = -1)] [Route("apps/{app}/assets/folders/{id}/", Order = -1)]
[ProducesResponseType(typeof(AssetFolderDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(AssetFolderDto), StatusCodes.Status200OK)]
[AssetRequestSizeLimit] [AssetRequestSizeLimit]
[ApiPermissionOrAnonymous(Permissions.AppAssetsUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppAssetsUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PutAssetFolder(string app, DomainId id, [FromBody] RenameAssetFolderDto request) public async Task<IActionResult> PutAssetFolder(string app, DomainId id, [FromBody] RenameAssetFolderDto request)
{ {
@ -133,7 +133,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
[Route("apps/{app}/assets/folders/{id}/parent", Order = -1)] [Route("apps/{app}/assets/folders/{id}/parent", Order = -1)]
[ProducesResponseType(typeof(AssetFolderDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(AssetFolderDto), StatusCodes.Status200OK)]
[AssetRequestSizeLimit] [AssetRequestSizeLimit]
[ApiPermissionOrAnonymous(Permissions.AppAssetsUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppAssetsUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PutAssetFolderParent(string app, DomainId id, [FromBody] MoveAssetFolderDto request) public async Task<IActionResult> PutAssetFolderParent(string app, DomainId id, [FromBody] MoveAssetFolderDto request)
{ {
@ -155,7 +155,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
/// </returns> /// </returns>
[HttpDelete] [HttpDelete]
[Route("apps/{app}/assets/folders/{id}/", Order = -1)] [Route("apps/{app}/assets/folders/{id}/", Order = -1)]
[ApiPermissionOrAnonymous(Permissions.AppAssetsUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppAssetsUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> DeleteAssetFolder(string app, DomainId id) public async Task<IActionResult> DeleteAssetFolder(string app, DomainId id)
{ {

26
backend/src/Squidex/Areas/Api/Controllers/Assets/AssetsController.cs

@ -68,7 +68,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
[HttpGet] [HttpGet]
[Route("apps/{app}/assets/tags")] [Route("apps/{app}/assets/tags")]
[ProducesResponseType(typeof(Dictionary<string, int>), StatusCodes.Status200OK)] [ProducesResponseType(typeof(Dictionary<string, int>), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppAssetsRead)] [ApiPermissionOrAnonymous(PermissionIds.AppAssetsRead)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> GetTags(string app) public async Task<IActionResult> GetTags(string app)
{ {
@ -92,7 +92,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
[HttpPut] [HttpPut]
[Route("apps/{app}/assets/tags/{name}")] [Route("apps/{app}/assets/tags/{name}")]
[ProducesResponseType(typeof(Dictionary<string, int>), StatusCodes.Status200OK)] [ProducesResponseType(typeof(Dictionary<string, int>), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppAssetsUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppAssetsUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PutTag(string app, string name, [FromBody] RenameTagDto request) public async Task<IActionResult> PutTag(string app, string name, [FromBody] RenameTagDto request)
{ {
@ -118,7 +118,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
[HttpGet] [HttpGet]
[Route("apps/{app}/assets/")] [Route("apps/{app}/assets/")]
[ProducesResponseType(typeof(AssetsDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(AssetsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppAssetsRead)] [ApiPermissionOrAnonymous(PermissionIds.AppAssetsRead)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> GetAssets(string app, [FromQuery] DomainId? parentId, [FromQuery] string? ids = null, [FromQuery] string? q = null) public async Task<IActionResult> GetAssets(string app, [FromQuery] DomainId? parentId, [FromQuery] string? ids = null, [FromQuery] string? q = null)
{ {
@ -147,7 +147,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
[HttpPost] [HttpPost]
[Route("apps/{app}/assets/query")] [Route("apps/{app}/assets/query")]
[ProducesResponseType(typeof(AssetsDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(AssetsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppAssetsRead)] [ApiPermissionOrAnonymous(PermissionIds.AppAssetsRead)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> GetAssetsPost(string app, [FromBody] QueryDto query) public async Task<IActionResult> GetAssetsPost(string app, [FromBody] QueryDto query)
{ {
@ -173,7 +173,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
[HttpGet] [HttpGet]
[Route("apps/{app}/assets/{id}/")] [Route("apps/{app}/assets/{id}/")]
[ProducesResponseType(typeof(AssetDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(AssetDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppAssetsRead)] [ApiPermissionOrAnonymous(PermissionIds.AppAssetsRead)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> GetAsset(string app, DomainId id) public async Task<IActionResult> GetAsset(string app, DomainId id)
{ {
@ -210,7 +210,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
[Route("apps/{app}/assets/")] [Route("apps/{app}/assets/")]
[ProducesResponseType(typeof(AssetDto), 201)] [ProducesResponseType(typeof(AssetDto), 201)]
[AssetRequestSizeLimit] [AssetRequestSizeLimit]
[ApiPermissionOrAnonymous(Permissions.AppAssetsCreate)] [ApiPermissionOrAnonymous(PermissionIds.AppAssetsCreate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PostAsset(string app, CreateAssetDto request) public async Task<IActionResult> PostAsset(string app, CreateAssetDto request)
{ {
@ -238,7 +238,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
[Route("apps/{app}/assets/tus/{**fileId}")] [Route("apps/{app}/assets/tus/{**fileId}")]
[ProducesResponseType(typeof(AssetDto), 201)] [ProducesResponseType(typeof(AssetDto), 201)]
[AssetRequestSizeLimit] [AssetRequestSizeLimit]
[ApiPermissionOrAnonymous(Permissions.AppAssetsCreate)] [ApiPermissionOrAnonymous(PermissionIds.AppAssetsCreate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PostAssetTus(string app) public async Task<IActionResult> PostAssetTus(string app)
{ {
@ -271,7 +271,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
[HttpPost] [HttpPost]
[Route("apps/{app}/assets/bulk")] [Route("apps/{app}/assets/bulk")]
[ProducesResponseType(typeof(BulkResultDto[]), StatusCodes.Status200OK)] [ProducesResponseType(typeof(BulkResultDto[]), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppAssetsRead)] [ApiPermissionOrAnonymous(PermissionIds.AppAssetsRead)]
[ApiCosts(5)] [ApiCosts(5)]
public async Task<IActionResult> BulkUpdateAssets(string app, [FromBody] BulkUpdateAssetsDto request) public async Task<IActionResult> BulkUpdateAssets(string app, [FromBody] BulkUpdateAssetsDto request)
{ {
@ -304,7 +304,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
[Route("apps/{app}/assets/{id}")] [Route("apps/{app}/assets/{id}")]
[ProducesResponseType(typeof(AssetDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(AssetDto), StatusCodes.Status200OK)]
[AssetRequestSizeLimit] [AssetRequestSizeLimit]
[ApiPermissionOrAnonymous(Permissions.AppAssetsCreate)] [ApiPermissionOrAnonymous(PermissionIds.AppAssetsCreate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PostUpsertAsset(string app, DomainId id, UpsertAssetDto request) public async Task<IActionResult> PostUpsertAsset(string app, DomainId id, UpsertAssetDto request)
{ {
@ -334,7 +334,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
[Route("apps/{app}/assets/{id}/content/")] [Route("apps/{app}/assets/{id}/content/")]
[ProducesResponseType(typeof(AssetDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(AssetDto), StatusCodes.Status200OK)]
[AssetRequestSizeLimit] [AssetRequestSizeLimit]
[ApiPermissionOrAnonymous(Permissions.AppAssetsUpload)] [ApiPermissionOrAnonymous(PermissionIds.AppAssetsUpload)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PutAssetContent(string app, DomainId id, IFormFile file) public async Task<IActionResult> PutAssetContent(string app, DomainId id, IFormFile file)
{ {
@ -360,7 +360,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
[Route("apps/{app}/assets/{id}/")] [Route("apps/{app}/assets/{id}/")]
[ProducesResponseType(typeof(AssetDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(AssetDto), StatusCodes.Status200OK)]
[AssetRequestSizeLimit] [AssetRequestSizeLimit]
[ApiPermissionOrAnonymous(Permissions.AppAssetsUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppAssetsUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PutAsset(string app, DomainId id, [FromBody] AnnotateAssetDto request) public async Task<IActionResult> PutAsset(string app, DomainId id, [FromBody] AnnotateAssetDto request)
{ {
@ -386,7 +386,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
[Route("apps/{app}/assets/{id}/parent")] [Route("apps/{app}/assets/{id}/parent")]
[ProducesResponseType(typeof(AssetDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(AssetDto), StatusCodes.Status200OK)]
[AssetRequestSizeLimit] [AssetRequestSizeLimit]
[ApiPermissionOrAnonymous(Permissions.AppAssetsUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppAssetsUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PutAssetParent(string app, DomainId id, [FromBody] MoveAssetDto request) public async Task<IActionResult> PutAssetParent(string app, DomainId id, [FromBody] MoveAssetDto request)
{ {
@ -409,7 +409,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
/// </returns> /// </returns>
[HttpDelete] [HttpDelete]
[Route("apps/{app}/assets/{id}/")] [Route("apps/{app}/assets/{id}/")]
[ApiPermissionOrAnonymous(Permissions.AppAssetsDelete)] [ApiPermissionOrAnonymous(PermissionIds.AppAssetsDelete)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> DeleteAsset(string app, DomainId id, DeleteAssetDto request) public async Task<IActionResult> DeleteAsset(string app, DomainId id, DeleteAssetDto request)
{ {

6
backend/src/Squidex/Areas/Api/Controllers/Backups/BackupsController.cs

@ -41,7 +41,7 @@ namespace Squidex.Areas.Api.Controllers.Backups
[HttpGet] [HttpGet]
[Route("apps/{app}/backups/")] [Route("apps/{app}/backups/")]
[ProducesResponseType(typeof(BackupJobsDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(BackupJobsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppBackupsRead)] [ApiPermissionOrAnonymous(PermissionIds.AppBackupsRead)]
[ApiCosts(0)] [ApiCosts(0)]
public async Task<IActionResult> GetBackups(string app) public async Task<IActionResult> GetBackups(string app)
{ {
@ -64,7 +64,7 @@ namespace Squidex.Areas.Api.Controllers.Backups
[HttpPost] [HttpPost]
[Route("apps/{app}/backups/")] [Route("apps/{app}/backups/")]
[ProducesResponseType(typeof(BackupJobDto[]), StatusCodes.Status200OK)] [ProducesResponseType(typeof(BackupJobDto[]), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppBackupsCreate)] [ApiPermissionOrAnonymous(PermissionIds.AppBackupsCreate)]
[ApiCosts(0)] [ApiCosts(0)]
public async Task<IActionResult> PostBackup(string app) public async Task<IActionResult> PostBackup(string app)
{ {
@ -85,7 +85,7 @@ namespace Squidex.Areas.Api.Controllers.Backups
[HttpDelete] [HttpDelete]
[Route("apps/{app}/backups/{id}")] [Route("apps/{app}/backups/{id}")]
[ProducesResponseType(typeof(BackupJobDto[]), StatusCodes.Status200OK)] [ProducesResponseType(typeof(BackupJobDto[]), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppBackupsDelete)] [ApiPermissionOrAnonymous(PermissionIds.AppBackupsDelete)]
[ApiCosts(0)] [ApiCosts(0)]
public async Task<IActionResult> DeleteBackup(string app, DomainId id) public async Task<IActionResult> DeleteBackup(string app, DomainId id)
{ {

4
backend/src/Squidex/Areas/Api/Controllers/Backups/RestoreController.cs

@ -39,7 +39,7 @@ namespace Squidex.Areas.Api.Controllers.Backups
[HttpGet] [HttpGet]
[Route("apps/restore/")] [Route("apps/restore/")]
[ProducesResponseType(typeof(RestoreJobDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(RestoreJobDto), StatusCodes.Status200OK)]
[ApiPermission(Permissions.AdminRestore)] [ApiPermission(PermissionIds.AdminRestore)]
public async Task<IActionResult> GetRestoreJob() public async Task<IActionResult> GetRestoreJob()
{ {
var job = await backupService.GetRestoreAsync(HttpContext.RequestAborted); var job = await backupService.GetRestoreAsync(HttpContext.RequestAborted);
@ -63,7 +63,7 @@ namespace Squidex.Areas.Api.Controllers.Backups
/// </returns> /// </returns>
[HttpPost] [HttpPost]
[Route("apps/restore/")] [Route("apps/restore/")]
[ApiPermission(Permissions.AdminRestore)] [ApiPermission(PermissionIds.AdminRestore)]
public async Task<IActionResult> PostRestoreJob([FromBody] RestoreRequestDto request) public async Task<IActionResult> PostRestoreJob([FromBody] RestoreRequestDto request)
{ {
await backupService.StartRestoreAsync(User.Token()!, request.Url, request.Name); await backupService.StartRestoreAsync(User.Token()!, request.Url, request.Name);

8
backend/src/Squidex/Areas/Api/Controllers/Comments/CommentsController.cs

@ -75,7 +75,7 @@ namespace Squidex.Areas.Api.Controllers.Comments
[HttpGet] [HttpGet]
[Route("apps/{app}/comments/{commentsId}")] [Route("apps/{app}/comments/{commentsId}")]
[ProducesResponseType(typeof(CommentsDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(CommentsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppCommentsRead)] [ApiPermissionOrAnonymous(PermissionIds.AppCommentsRead)]
[ApiCosts(0)] [ApiCosts(0)]
public async Task<IActionResult> GetComments(string app, DomainId commentsId, [FromQuery] long version = EtagVersion.Any) public async Task<IActionResult> GetComments(string app, DomainId commentsId, [FromQuery] long version = EtagVersion.Any)
{ {
@ -105,7 +105,7 @@ namespace Squidex.Areas.Api.Controllers.Comments
[HttpPost] [HttpPost]
[Route("apps/{app}/comments/{commentsId}")] [Route("apps/{app}/comments/{commentsId}")]
[ProducesResponseType(typeof(CommentDto), 201)] [ProducesResponseType(typeof(CommentDto), 201)]
[ApiPermissionOrAnonymous(Permissions.AppCommentsCreate)] [ApiPermissionOrAnonymous(PermissionIds.AppCommentsCreate)]
[ApiCosts(0)] [ApiCosts(0)]
public async Task<IActionResult> PostComment(string app, DomainId commentsId, [FromBody] UpsertCommentDto request) public async Task<IActionResult> PostComment(string app, DomainId commentsId, [FromBody] UpsertCommentDto request)
{ {
@ -132,7 +132,7 @@ namespace Squidex.Areas.Api.Controllers.Comments
/// </returns> /// </returns>
[HttpPut] [HttpPut]
[Route("apps/{app}/comments/{commentsId}/{commentId}")] [Route("apps/{app}/comments/{commentsId}/{commentId}")]
[ApiPermissionOrAnonymous(Permissions.AppCommentsUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppCommentsUpdate)]
[ApiCosts(0)] [ApiCosts(0)]
public async Task<IActionResult> PutComment(string app, DomainId commentsId, DomainId commentId, [FromBody] UpsertCommentDto request) public async Task<IActionResult> PutComment(string app, DomainId commentsId, DomainId commentId, [FromBody] UpsertCommentDto request)
{ {
@ -155,7 +155,7 @@ namespace Squidex.Areas.Api.Controllers.Comments
/// </returns> /// </returns>
[HttpDelete] [HttpDelete]
[Route("apps/{app}/comments/{commentsId}/{commentId}")] [Route("apps/{app}/comments/{commentsId}/{commentId}")]
[ApiPermissionOrAnonymous(Permissions.AppCommentsDelete)] [ApiPermissionOrAnonymous(PermissionIds.AppCommentsDelete)]
[ApiCosts(0)] [ApiCosts(0)]
public async Task<IActionResult> DeleteComment(string app, DomainId commentsId, DomainId commentId) public async Task<IActionResult> DeleteComment(string app, DomainId commentsId, DomainId commentId)
{ {

24
backend/src/Squidex/Areas/Api/Controllers/Contents/ContentsController.cs

@ -319,7 +319,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
/// </remarks> /// </remarks>
[HttpGet] [HttpGet]
[Route("content/{app}/{schema}/{id}/{version}/")] [Route("content/{app}/{schema}/{id}/{version}/")]
[ApiPermissionOrAnonymous(Permissions.AppContentsReadOwn)] [ApiPermissionOrAnonymous(PermissionIds.AppContentsReadOwn)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> GetContentVersion(string app, string schema, DomainId id, int version) public async Task<IActionResult> GetContentVersion(string app, string schema, DomainId id, int version)
{ {
@ -352,7 +352,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
[HttpPost] [HttpPost]
[Route("content/{app}/{schema}/")] [Route("content/{app}/{schema}/")]
[ProducesResponseType(typeof(ContentsDto), 201)] [ProducesResponseType(typeof(ContentsDto), 201)]
[ApiPermissionOrAnonymous(Permissions.AppContentsCreate)] [ApiPermissionOrAnonymous(PermissionIds.AppContentsCreate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PostContent(string app, string schema, CreateContentDto request) public async Task<IActionResult> PostContent(string app, string schema, CreateContentDto request)
{ {
@ -380,7 +380,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
[HttpPost] [HttpPost]
[Route("content/{app}/{schema}/import")] [Route("content/{app}/{schema}/import")]
[ProducesResponseType(typeof(BulkResultDto[]), StatusCodes.Status200OK)] [ProducesResponseType(typeof(BulkResultDto[]), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppContentsCreate)] [ApiPermissionOrAnonymous(PermissionIds.AppContentsCreate)]
[ApiCosts(5)] [ApiCosts(5)]
[Obsolete("Use bulk endpoint now.")] [Obsolete("Use bulk endpoint now.")]
public async Task<IActionResult> PostContents(string app, string schema, [FromBody] ImportContentsDto request) public async Task<IActionResult> PostContents(string app, string schema, [FromBody] ImportContentsDto request)
@ -412,7 +412,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
[HttpPost] [HttpPost]
[Route("content/{app}/{schema}/bulk")] [Route("content/{app}/{schema}/bulk")]
[ProducesResponseType(typeof(BulkResultDto[]), StatusCodes.Status200OK)] [ProducesResponseType(typeof(BulkResultDto[]), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppContentsReadOwn)] [ApiPermissionOrAnonymous(PermissionIds.AppContentsReadOwn)]
[ApiCosts(5)] [ApiCosts(5)]
public async Task<IActionResult> BulkUpdateContents(string app, string schema, [FromBody] BulkUpdateContentsDto request) public async Task<IActionResult> BulkUpdateContents(string app, string schema, [FromBody] BulkUpdateContentsDto request)
{ {
@ -444,7 +444,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
[HttpPost] [HttpPost]
[Route("content/{app}/{schema}/{id}/")] [Route("content/{app}/{schema}/{id}/")]
[ProducesResponseType(typeof(ContentsDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ContentsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppContentsUpsert)] [ApiPermissionOrAnonymous(PermissionIds.AppContentsUpsert)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PostUpsertContent(string app, string schema, DomainId id, UpsertContentDto request) public async Task<IActionResult> PostUpsertContent(string app, string schema, DomainId id, UpsertContentDto request)
{ {
@ -473,7 +473,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
[HttpPut] [HttpPut]
[Route("content/{app}/{schema}/{id}/")] [Route("content/{app}/{schema}/{id}/")]
[ProducesResponseType(typeof(ContentsDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ContentsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppContentsUpdateOwn)] [ApiPermissionOrAnonymous(PermissionIds.AppContentsUpdateOwn)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PutContent(string app, string schema, DomainId id, [FromBody] ContentData request) public async Task<IActionResult> PutContent(string app, string schema, DomainId id, [FromBody] ContentData request)
{ {
@ -502,7 +502,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
[HttpPatch] [HttpPatch]
[Route("content/{app}/{schema}/{id}/")] [Route("content/{app}/{schema}/{id}/")]
[ProducesResponseType(typeof(ContentsDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ContentsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppContentsUpdateOwn)] [ApiPermissionOrAnonymous(PermissionIds.AppContentsUpdateOwn)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PatchContent(string app, string schema, DomainId id, [FromBody] ContentData request) public async Task<IActionResult> PatchContent(string app, string schema, DomainId id, [FromBody] ContentData request)
{ {
@ -531,7 +531,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
[HttpPut] [HttpPut]
[Route("content/{app}/{schema}/{id}/status/")] [Route("content/{app}/{schema}/{id}/status/")]
[ProducesResponseType(typeof(ContentsDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ContentsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppContentsChangeStatusOwn)] [ApiPermissionOrAnonymous(PermissionIds.AppContentsChangeStatusOwn)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PutContentStatus(string app, string schema, DomainId id, [FromBody] ChangeStatusDto request) public async Task<IActionResult> PutContentStatus(string app, string schema, DomainId id, [FromBody] ChangeStatusDto request)
{ {
@ -559,7 +559,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
[HttpDelete] [HttpDelete]
[Route("content/{app}/{schema}/{id}/status/")] [Route("content/{app}/{schema}/{id}/status/")]
[ProducesResponseType(typeof(ContentsDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ContentsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppContentsChangeStatusOwn)] [ApiPermissionOrAnonymous(PermissionIds.AppContentsChangeStatusOwn)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> DeleteContentStatus(string app, string schema, DomainId id) public async Task<IActionResult> DeleteContentStatus(string app, string schema, DomainId id)
{ {
@ -586,7 +586,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
[HttpPost] [HttpPost]
[Route("content/{app}/{schema}/{id}/draft/")] [Route("content/{app}/{schema}/{id}/draft/")]
[ProducesResponseType(typeof(ContentsDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ContentsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppContentsVersionCreateOwn)] [ApiPermissionOrAnonymous(PermissionIds.AppContentsVersionCreateOwn)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> CreateDraft(string app, string schema, DomainId id) public async Task<IActionResult> CreateDraft(string app, string schema, DomainId id)
{ {
@ -613,7 +613,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
[HttpDelete] [HttpDelete]
[Route("content/{app}/{schema}/{id}/draft/")] [Route("content/{app}/{schema}/{id}/draft/")]
[ProducesResponseType(typeof(ContentsDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ContentsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppContentsVersionDeleteOwn)] [ApiPermissionOrAnonymous(PermissionIds.AppContentsVersionDeleteOwn)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> DeleteVersion(string app, string schema, DomainId id) public async Task<IActionResult> DeleteVersion(string app, string schema, DomainId id)
{ {
@ -641,7 +641,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
/// </remarks> /// </remarks>
[HttpDelete] [HttpDelete]
[Route("content/{app}/{schema}/{id}/")] [Route("content/{app}/{schema}/{id}/")]
[ApiPermissionOrAnonymous(Permissions.AppContentsDeleteOwn)] [ApiPermissionOrAnonymous(PermissionIds.AppContentsDeleteOwn)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> DeleteContent(string app, string schema, DomainId id, DeleteContentDto request) public async Task<IActionResult> DeleteContent(string app, string schema, DomainId id, DeleteContentDto request)
{ {

2
backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/OperationBuilder.cs

@ -121,7 +121,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
{ {
[Constants.SecurityDefinition] = new[] [Constants.SecurityDefinition] = new[]
{ {
Permissions.ForApp(permissionId, operations.Parent.AppName, operations.SchemaName).Id PermissionIds.ForApp(permissionId, operations.Parent.AppName, operations.SchemaName).Id
} }
} }
}; };

22
backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/SchemasOpenApiGenerator.cs

@ -94,7 +94,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
private static void GenerateSharedOperations(OperationsBuilder builder) private static void GenerateSharedOperations(OperationsBuilder builder)
{ {
builder.AddOperation(OpenApiOperationMethod.Get, "/") builder.AddOperation(OpenApiOperationMethod.Get, "/")
.RequirePermission(Permissions.AppContentsReadOwn) .RequirePermission(PermissionIds.AppContentsReadOwn)
.Operation("Query") .Operation("Query")
.OperationSummary("Query contents across all schemas.") .OperationSummary("Query contents across all schemas.")
.HasQuery("ids", JsonObjectType.String, "Comma-separated list of content IDs.") .HasQuery("ids", JsonObjectType.String, "Comma-separated list of content IDs.")
@ -105,7 +105,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
private static void GenerateSchemaOperations(OperationsBuilder builder) private static void GenerateSchemaOperations(OperationsBuilder builder)
{ {
builder.AddOperation(OpenApiOperationMethod.Get, "/") builder.AddOperation(OpenApiOperationMethod.Get, "/")
.RequirePermission(Permissions.AppContentsReadOwn) .RequirePermission(PermissionIds.AppContentsReadOwn)
.Operation("Query") .Operation("Query")
.OperationSummary("Query [schema] contents items.") .OperationSummary("Query [schema] contents items.")
.Describe(Resources.OpenApiSchemaQuery) .Describe(Resources.OpenApiSchemaQuery)
@ -114,14 +114,14 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
.Responds(400, "Content query not valid."); .Responds(400, "Content query not valid.");
builder.AddOperation(OpenApiOperationMethod.Get, "/{id}") builder.AddOperation(OpenApiOperationMethod.Get, "/{id}")
.RequirePermission(Permissions.AppContentsReadOwn) .RequirePermission(PermissionIds.AppContentsReadOwn)
.Operation("Get") .Operation("Get")
.OperationSummary("Get a [schema] content item.") .OperationSummary("Get a [schema] content item.")
.HasId() .HasId()
.Responds(200, "Content item returned.", builder.ContentSchema); .Responds(200, "Content item returned.", builder.ContentSchema);
builder.AddOperation(OpenApiOperationMethod.Get, "/{id}/{version}") builder.AddOperation(OpenApiOperationMethod.Get, "/{id}/{version}")
.RequirePermission(Permissions.AppContentsReadOwn) .RequirePermission(PermissionIds.AppContentsReadOwn)
.Operation("GetVersioned") .Operation("GetVersioned")
.OperationSummary("Get a [schema] content item by id and version.") .OperationSummary("Get a [schema] content item by id and version.")
.HasPath("version", JsonObjectType.Number, FieldDescriptions.EntityVersion) .HasPath("version", JsonObjectType.Number, FieldDescriptions.EntityVersion)
@ -129,7 +129,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
.Responds(200, "Content item returned.", builder.ContentSchema); .Responds(200, "Content item returned.", builder.ContentSchema);
builder.AddOperation(OpenApiOperationMethod.Get, "/{id}/validity") builder.AddOperation(OpenApiOperationMethod.Get, "/{id}/validity")
.RequirePermission(Permissions.AppContentsReadOwn) .RequirePermission(PermissionIds.AppContentsReadOwn)
.Operation("Validate") .Operation("Validate")
.OperationSummary("Validates a [schema] content item.") .OperationSummary("Validates a [schema] content item.")
.HasId() .HasId()
@ -137,7 +137,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
.Responds(400, "Content item is not valid."); .Responds(400, "Content item is not valid.");
builder.AddOperation(OpenApiOperationMethod.Post, "/") builder.AddOperation(OpenApiOperationMethod.Post, "/")
.RequirePermission(Permissions.AppContentsCreate) .RequirePermission(PermissionIds.AppContentsCreate)
.Operation("Create") .Operation("Create")
.OperationSummary("Create a [schema] content item.") .OperationSummary("Create a [schema] content item.")
.HasQuery("publish", JsonObjectType.Boolean, FieldDescriptions.ContentRequestPublish) .HasQuery("publish", JsonObjectType.Boolean, FieldDescriptions.ContentRequestPublish)
@ -147,7 +147,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
.Responds(400, "Content data not valid."); .Responds(400, "Content data not valid.");
builder.AddOperation(OpenApiOperationMethod.Post, "/{id}") builder.AddOperation(OpenApiOperationMethod.Post, "/{id}")
.RequirePermission(Permissions.AppContentsUpsert) .RequirePermission(PermissionIds.AppContentsUpsert)
.Operation("Upsert") .Operation("Upsert")
.OperationSummary("Upsert a [schema] content item.") .OperationSummary("Upsert a [schema] content item.")
.HasQuery("patch", JsonObjectType.Boolean, FieldDescriptions.ContentRequestPatch) .HasQuery("patch", JsonObjectType.Boolean, FieldDescriptions.ContentRequestPatch)
@ -158,7 +158,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
.Responds(400, "Content data not valid."); .Responds(400, "Content data not valid.");
builder.AddOperation(OpenApiOperationMethod.Put, "/{id}") builder.AddOperation(OpenApiOperationMethod.Put, "/{id}")
.RequirePermission(Permissions.AppContentsUpdateOwn) .RequirePermission(PermissionIds.AppContentsUpdateOwn)
.Operation("Update") .Operation("Update")
.OperationSummary("Update a [schema] content item.") .OperationSummary("Update a [schema] content item.")
.HasId() .HasId()
@ -167,7 +167,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
.Responds(400, "Content data not valid."); .Responds(400, "Content data not valid.");
builder.AddOperation(OpenApiOperationMethod.Patch, "/{id}") builder.AddOperation(OpenApiOperationMethod.Patch, "/{id}")
.RequirePermission(Permissions.AppContentsUpdateOwn) .RequirePermission(PermissionIds.AppContentsUpdateOwn)
.Operation("Patch") .Operation("Patch")
.OperationSummary("Patch a [schema] content item.") .OperationSummary("Patch a [schema] content item.")
.HasId() .HasId()
@ -176,7 +176,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
.Responds(400, "Content data not valid."); .Responds(400, "Content data not valid.");
builder.AddOperation(OpenApiOperationMethod.Put, "/{id}/status") builder.AddOperation(OpenApiOperationMethod.Put, "/{id}/status")
.RequirePermission(Permissions.AppContentsChangeStatusOwn) .RequirePermission(PermissionIds.AppContentsChangeStatusOwn)
.Operation("Change") .Operation("Change")
.OperationSummary("Change the status of a [schema] content item.") .OperationSummary("Change the status of a [schema] content item.")
.HasId() .HasId()
@ -185,7 +185,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
.Responds(400, "Content status not valid."); .Responds(400, "Content status not valid.");
builder.AddOperation(OpenApiOperationMethod.Delete, "/{id}") builder.AddOperation(OpenApiOperationMethod.Delete, "/{id}")
.RequirePermission(Permissions.AppContentsDeleteOwn) .RequirePermission(PermissionIds.AppContentsDeleteOwn)
.Operation("Delete") .Operation("Delete")
.OperationSummary("Delete a [schema] content item.") .OperationSummary("Delete a [schema] content item.")
.HasId() .HasId()

4
backend/src/Squidex/Areas/Api/Controllers/Diagnostics/DiagnosticsController.cs

@ -36,7 +36,7 @@ namespace Squidex.Areas.Api.Controllers.Diagnostics
/// </returns> /// </returns>
[HttpGet] [HttpGet]
[Route("diagnostics/dump")] [Route("diagnostics/dump")]
[ApiPermissionOrAnonymous(Permissions.Admin)] [ApiPermissionOrAnonymous(PermissionIds.Admin)]
public async Task<IActionResult> GetDump() public async Task<IActionResult> GetDump()
{ {
var success = await dumper.CreateDumpAsync(HttpContext.RequestAborted); var success = await dumper.CreateDumpAsync(HttpContext.RequestAborted);
@ -58,7 +58,7 @@ namespace Squidex.Areas.Api.Controllers.Diagnostics
/// </returns> /// </returns>
[HttpGet] [HttpGet]
[Route("diagnostics/gcdump")] [Route("diagnostics/gcdump")]
[ApiPermissionOrAnonymous(Permissions.Admin)] [ApiPermissionOrAnonymous(PermissionIds.Admin)]
public async Task<IActionResult> GetGCDump() public async Task<IActionResult> GetGCDump()
{ {
var success = await dumper.CreateGCDumpAsync(HttpContext.RequestAborted); var success = await dumper.CreateGCDumpAsync(HttpContext.RequestAborted);

8
backend/src/Squidex/Areas/Api/Controllers/EventConsumers/EventConsumersController.cs

@ -27,7 +27,7 @@ namespace Squidex.Areas.Api.Controllers.EventConsumers
[HttpGet] [HttpGet]
[Route("event-consumers/")] [Route("event-consumers/")]
[ProducesResponseType(typeof(EventConsumersDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(EventConsumersDto), StatusCodes.Status200OK)]
[ApiPermission(Permissions.AdminEventsRead)] [ApiPermission(PermissionIds.AdminEventsRead)]
public async Task<IActionResult> GetEventConsumers() public async Task<IActionResult> GetEventConsumers()
{ {
var eventConsumers = await eventConsumerManager.GetConsumersAsync(HttpContext.RequestAborted); var eventConsumers = await eventConsumerManager.GetConsumersAsync(HttpContext.RequestAborted);
@ -40,7 +40,7 @@ namespace Squidex.Areas.Api.Controllers.EventConsumers
[HttpPut] [HttpPut]
[Route("event-consumers/{consumerName}/start/")] [Route("event-consumers/{consumerName}/start/")]
[ProducesResponseType(typeof(EventConsumerDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(EventConsumerDto), StatusCodes.Status200OK)]
[ApiPermission(Permissions.AdminEventsManage)] [ApiPermission(PermissionIds.AdminEventsManage)]
public async Task<IActionResult> StartEventConsumer(string consumerName) public async Task<IActionResult> StartEventConsumer(string consumerName)
{ {
var eventConsumer = await eventConsumerManager.StartAsync(consumerName, HttpContext.RequestAborted); var eventConsumer = await eventConsumerManager.StartAsync(consumerName, HttpContext.RequestAborted);
@ -53,7 +53,7 @@ namespace Squidex.Areas.Api.Controllers.EventConsumers
[HttpPut] [HttpPut]
[Route("event-consumers/{consumerName}/stop/")] [Route("event-consumers/{consumerName}/stop/")]
[ProducesResponseType(typeof(EventConsumerDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(EventConsumerDto), StatusCodes.Status200OK)]
[ApiPermission(Permissions.AdminEventsManage)] [ApiPermission(PermissionIds.AdminEventsManage)]
public async Task<IActionResult> StopEventConsumer(string consumerName) public async Task<IActionResult> StopEventConsumer(string consumerName)
{ {
var eventConsumer = await eventConsumerManager.StopAsync(consumerName, HttpContext.RequestAborted); var eventConsumer = await eventConsumerManager.StopAsync(consumerName, HttpContext.RequestAborted);
@ -66,7 +66,7 @@ namespace Squidex.Areas.Api.Controllers.EventConsumers
[HttpPut] [HttpPut]
[Route("event-consumers/{consumerName}/reset/")] [Route("event-consumers/{consumerName}/reset/")]
[ProducesResponseType(typeof(EventConsumerDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(EventConsumerDto), StatusCodes.Status200OK)]
[ApiPermission(Permissions.AdminEventsManage)] [ApiPermission(PermissionIds.AdminEventsManage)]
public async Task<IActionResult> ResetEventConsumer(string consumerName) public async Task<IActionResult> ResetEventConsumer(string consumerName)
{ {
var eventConsumer = await eventConsumerManager.ResetAsync(consumerName, HttpContext.RequestAborted); var eventConsumer = await eventConsumerManager.ResetAsync(consumerName, HttpContext.RequestAborted);

2
backend/src/Squidex/Areas/Api/Controllers/History/HistoryController.cs

@ -40,7 +40,7 @@ namespace Squidex.Areas.Api.Controllers.History
[HttpGet] [HttpGet]
[Route("apps/{app}/history/")] [Route("apps/{app}/history/")]
[ProducesResponseType(typeof(HistoryEventDto[]), StatusCodes.Status200OK)] [ProducesResponseType(typeof(HistoryEventDto[]), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppHistory)] [ApiPermissionOrAnonymous(PermissionIds.AppHistory)]
[ApiCosts(0.1)] [ApiCosts(0.1)]
public async Task<IActionResult> GetHistory(string app, string channel) public async Task<IActionResult> GetHistory(string app, string channel)
{ {

2
backend/src/Squidex/Areas/Api/Controllers/Ping/PingController.cs

@ -68,7 +68,7 @@ namespace Squidex.Areas.Api.Controllers.Ping
/// </remarks> /// </remarks>
[HttpGet] [HttpGet]
[Route("ping/{app}/")] [Route("ping/{app}/")]
[ApiPermissionOrAnonymous(Permissions.AppPing)] [ApiPermissionOrAnonymous(PermissionIds.AppPing)]
[ApiCosts(0)] [ApiCosts(0)]
public IActionResult GetAppPing(string app) public IActionResult GetAppPing(string app)
{ {

4
backend/src/Squidex/Areas/Api/Controllers/Plans/AppPlansController.cs

@ -44,7 +44,7 @@ namespace Squidex.Areas.Api.Controllers.Plans
[HttpGet] [HttpGet]
[Route("apps/{app}/plans/")] [Route("apps/{app}/plans/")]
[ProducesResponseType(typeof(AppPlansDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(AppPlansDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppPlansRead)] [ApiPermissionOrAnonymous(PermissionIds.AppPlansRead)]
[ApiCosts(0)] [ApiCosts(0)]
public IActionResult GetPlans(string app) public IActionResult GetPlans(string app)
{ {
@ -73,7 +73,7 @@ namespace Squidex.Areas.Api.Controllers.Plans
[HttpPut] [HttpPut]
[Route("apps/{app}/plan/")] [Route("apps/{app}/plan/")]
[ProducesResponseType(typeof(PlanChangedDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(PlanChangedDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppPlansChange)] [ApiPermissionOrAnonymous(PermissionIds.AppPlansChange)]
[ApiCosts(0)] [ApiCosts(0)]
public async Task<IActionResult> PutPlan(string app, [FromBody] ChangePlanDto request) public async Task<IActionResult> PutPlan(string app, [FromBody] ChangePlanDto request)
{ {

32
backend/src/Squidex/Areas/Api/Controllers/Rules/RulesController.cs

@ -92,7 +92,7 @@ namespace Squidex.Areas.Api.Controllers.Rules
[HttpGet] [HttpGet]
[Route("apps/{app}/rules/")] [Route("apps/{app}/rules/")]
[ProducesResponseType(typeof(RulesDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(RulesDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppRulesRead)] [ApiPermissionOrAnonymous(PermissionIds.AppRulesRead)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> GetRules(string app) public async Task<IActionResult> GetRules(string app)
{ {
@ -119,7 +119,7 @@ namespace Squidex.Areas.Api.Controllers.Rules
[HttpPost] [HttpPost]
[Route("apps/{app}/rules/")] [Route("apps/{app}/rules/")]
[ProducesResponseType(typeof(RuleDto), 201)] [ProducesResponseType(typeof(RuleDto), 201)]
[ApiPermissionOrAnonymous(Permissions.AppRulesCreate)] [ApiPermissionOrAnonymous(PermissionIds.AppRulesCreate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PostRule(string app, [FromBody] CreateRuleDto request) public async Task<IActionResult> PostRule(string app, [FromBody] CreateRuleDto request)
{ {
@ -140,7 +140,7 @@ namespace Squidex.Areas.Api.Controllers.Rules
[HttpDelete] [HttpDelete]
[Route("apps/{app}/rules/run")] [Route("apps/{app}/rules/run")]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[ApiPermissionOrAnonymous(Permissions.AppRulesEventsUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppRulesEventsUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> DeleteRuleRun(string app) public async Task<IActionResult> DeleteRuleRun(string app)
{ {
@ -163,7 +163,7 @@ namespace Squidex.Areas.Api.Controllers.Rules
[HttpPut] [HttpPut]
[Route("apps/{app}/rules/{id}/")] [Route("apps/{app}/rules/{id}/")]
[ProducesResponseType(typeof(RuleDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(RuleDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppRulesUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppRulesUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PutRule(string app, DomainId id, [FromBody] UpdateRuleDto request) public async Task<IActionResult> PutRule(string app, DomainId id, [FromBody] UpdateRuleDto request)
{ {
@ -186,7 +186,7 @@ namespace Squidex.Areas.Api.Controllers.Rules
[HttpPut] [HttpPut]
[Route("apps/{app}/rules/{id}/enable/")] [Route("apps/{app}/rules/{id}/enable/")]
[ProducesResponseType(typeof(RuleDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(RuleDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppRulesDisable)] [ApiPermissionOrAnonymous(PermissionIds.AppRulesDisable)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> EnableRule(string app, DomainId id) public async Task<IActionResult> EnableRule(string app, DomainId id)
{ {
@ -209,7 +209,7 @@ namespace Squidex.Areas.Api.Controllers.Rules
[HttpPut] [HttpPut]
[Route("apps/{app}/rules/{id}/disable/")] [Route("apps/{app}/rules/{id}/disable/")]
[ProducesResponseType(typeof(RuleDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(RuleDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppRulesDisable)] [ApiPermissionOrAnonymous(PermissionIds.AppRulesDisable)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> DisableRule(string app, DomainId id) public async Task<IActionResult> DisableRule(string app, DomainId id)
{ {
@ -231,7 +231,7 @@ namespace Squidex.Areas.Api.Controllers.Rules
/// </returns> /// </returns>
[HttpPut] [HttpPut]
[Route("apps/{app}/rules/{id}/trigger/")] [Route("apps/{app}/rules/{id}/trigger/")]
[ApiPermissionOrAnonymous(Permissions.AppRulesEventsRun)] [ApiPermissionOrAnonymous(PermissionIds.AppRulesEventsRun)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> TriggerRule(string app, DomainId id) public async Task<IActionResult> TriggerRule(string app, DomainId id)
{ {
@ -254,7 +254,7 @@ namespace Squidex.Areas.Api.Controllers.Rules
[HttpPut] [HttpPut]
[Route("apps/{app}/rules/{id}/run")] [Route("apps/{app}/rules/{id}/run")]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[ApiPermissionOrAnonymous(Permissions.AppRulesEventsRun)] [ApiPermissionOrAnonymous(PermissionIds.AppRulesEventsRun)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PutRuleRun(string app, DomainId id, [FromQuery] bool fromSnapshots = false) public async Task<IActionResult> PutRuleRun(string app, DomainId id, [FromQuery] bool fromSnapshots = false)
{ {
@ -274,7 +274,7 @@ namespace Squidex.Areas.Api.Controllers.Rules
[HttpDelete] [HttpDelete]
[Route("apps/{app}/rules/{id}/events/")] [Route("apps/{app}/rules/{id}/events/")]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[ApiPermissionOrAnonymous(Permissions.AppRulesEventsDelete)] [ApiPermissionOrAnonymous(PermissionIds.AppRulesEventsDelete)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> DeleteRuleEvents(string app, DomainId id) public async Task<IActionResult> DeleteRuleEvents(string app, DomainId id)
{ {
@ -295,7 +295,7 @@ namespace Squidex.Areas.Api.Controllers.Rules
[HttpPost] [HttpPost]
[Route("apps/{app}/rules/simulate/")] [Route("apps/{app}/rules/simulate/")]
[ProducesResponseType(typeof(SimulatedRuleEventsDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(SimulatedRuleEventsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppRulesEventsRead)] [ApiPermissionOrAnonymous(PermissionIds.AppRulesEventsRead)]
[ApiCosts(5)] [ApiCosts(5)]
public async Task<IActionResult> Simulate(string app, [FromBody] CreateRuleDto request) public async Task<IActionResult> Simulate(string app, [FromBody] CreateRuleDto request)
{ {
@ -320,7 +320,7 @@ namespace Squidex.Areas.Api.Controllers.Rules
[HttpGet] [HttpGet]
[Route("apps/{app}/rules/{id}/simulate/")] [Route("apps/{app}/rules/{id}/simulate/")]
[ProducesResponseType(typeof(SimulatedRuleEventsDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(SimulatedRuleEventsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppRulesEventsRead)] [ApiPermissionOrAnonymous(PermissionIds.AppRulesEventsRead)]
[ApiCosts(5)] [ApiCosts(5)]
public async Task<IActionResult> Simulate(string app, DomainId id) public async Task<IActionResult> Simulate(string app, DomainId id)
{ {
@ -349,7 +349,7 @@ namespace Squidex.Areas.Api.Controllers.Rules
/// </returns> /// </returns>
[HttpDelete] [HttpDelete]
[Route("apps/{app}/rules/{id}/")] [Route("apps/{app}/rules/{id}/")]
[ApiPermissionOrAnonymous(Permissions.AppRulesDelete)] [ApiPermissionOrAnonymous(PermissionIds.AppRulesDelete)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> DeleteRule(string app, DomainId id) public async Task<IActionResult> DeleteRule(string app, DomainId id)
{ {
@ -374,7 +374,7 @@ namespace Squidex.Areas.Api.Controllers.Rules
[HttpGet] [HttpGet]
[Route("apps/{app}/rules/events/")] [Route("apps/{app}/rules/events/")]
[ProducesResponseType(typeof(RuleEventsDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(RuleEventsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppRulesEventsRead)] [ApiPermissionOrAnonymous(PermissionIds.AppRulesEventsRead)]
[ApiCosts(0)] [ApiCosts(0)]
public async Task<IActionResult> GetEvents(string app, [FromQuery] DomainId? ruleId = null, [FromQuery] int skip = 0, [FromQuery] int take = 20) public async Task<IActionResult> GetEvents(string app, [FromQuery] DomainId? ruleId = null, [FromQuery] int skip = 0, [FromQuery] int take = 20)
{ {
@ -396,7 +396,7 @@ namespace Squidex.Areas.Api.Controllers.Rules
/// </returns> /// </returns>
[HttpPut] [HttpPut]
[Route("apps/{app}/rules/events/{id}/")] [Route("apps/{app}/rules/events/{id}/")]
[ApiPermissionOrAnonymous(Permissions.AppRulesEventsUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppRulesEventsUpdate)]
[ApiCosts(0)] [ApiCosts(0)]
public async Task<IActionResult> PutEvent(string app, DomainId id) public async Task<IActionResult> PutEvent(string app, DomainId id)
{ {
@ -422,7 +422,7 @@ namespace Squidex.Areas.Api.Controllers.Rules
[HttpDelete] [HttpDelete]
[Route("apps/{app}/rules/events/")] [Route("apps/{app}/rules/events/")]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[ApiPermissionOrAnonymous(Permissions.AppRulesEventsDelete)] [ApiPermissionOrAnonymous(PermissionIds.AppRulesEventsDelete)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> DeleteEvents(string app) public async Task<IActionResult> DeleteEvents(string app)
{ {
@ -442,7 +442,7 @@ namespace Squidex.Areas.Api.Controllers.Rules
/// </returns> /// </returns>
[HttpDelete] [HttpDelete]
[Route("apps/{app}/rules/events/{id}/")] [Route("apps/{app}/rules/events/{id}/")]
[ApiPermissionOrAnonymous(Permissions.AppRulesEventsDelete)] [ApiPermissionOrAnonymous(PermissionIds.AppRulesEventsDelete)]
[ApiCosts(0)] [ApiCosts(0)]
public async Task<IActionResult> DeleteEvent(string app, DomainId id) public async Task<IActionResult> DeleteEvent(string app, DomainId id)
{ {

38
backend/src/Squidex/Areas/Api/Controllers/Schemas/SchemaFieldsController.cs

@ -41,7 +41,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
[HttpPost] [HttpPost]
[Route("apps/{app}/schemas/{schema}/fields/")] [Route("apps/{app}/schemas/{schema}/fields/")]
[ProducesResponseType(typeof(SchemaDto), 201)] [ProducesResponseType(typeof(SchemaDto), 201)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppSchemasUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PostField(string app, string schema, [FromBody] AddFieldDto request) public async Task<IActionResult> PostField(string app, string schema, [FromBody] AddFieldDto request)
{ {
@ -68,7 +68,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
[HttpPost] [HttpPost]
[Route("apps/{app}/schemas/{schema}/fields/{parentId:long}/nested/")] [Route("apps/{app}/schemas/{schema}/fields/{parentId:long}/nested/")]
[ProducesResponseType(typeof(SchemaDto), 201)] [ProducesResponseType(typeof(SchemaDto), 201)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppSchemasUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PostNestedField(string app, string schema, long parentId, [FromBody] AddFieldDto request) public async Task<IActionResult> PostNestedField(string app, string schema, long parentId, [FromBody] AddFieldDto request)
{ {
@ -93,7 +93,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
[HttpPut] [HttpPut]
[Route("apps/{app}/schemas/{schema}/fields/ui/")] [Route("apps/{app}/schemas/{schema}/fields/ui/")]
[ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppSchemasUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PutSchemaUIFields(string app, string schema, [FromBody] ConfigureUIFieldsDto request) public async Task<IActionResult> PutSchemaUIFields(string app, string schema, [FromBody] ConfigureUIFieldsDto request)
{ {
@ -118,7 +118,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
[HttpPut] [HttpPut]
[Route("apps/{app}/schemas/{schema}/fields/ordering/")] [Route("apps/{app}/schemas/{schema}/fields/ordering/")]
[ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppSchemasUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PutSchemaFieldOrdering(string app, string schema, [FromBody] ReorderFieldsDto request) public async Task<IActionResult> PutSchemaFieldOrdering(string app, string schema, [FromBody] ReorderFieldsDto request)
{ {
@ -144,7 +144,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
[HttpPut] [HttpPut]
[Route("apps/{app}/schemas/{schema}/fields/{parentId:long}/nested/ordering/")] [Route("apps/{app}/schemas/{schema}/fields/{parentId:long}/nested/ordering/")]
[ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppSchemasUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PutNestedFieldOrdering(string app, string schema, long parentId, [FromBody] ReorderFieldsDto request) public async Task<IActionResult> PutNestedFieldOrdering(string app, string schema, long parentId, [FromBody] ReorderFieldsDto request)
{ {
@ -170,7 +170,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
[HttpPut] [HttpPut]
[Route("apps/{app}/schemas/{schema}/fields/{id:long}/")] [Route("apps/{app}/schemas/{schema}/fields/{id:long}/")]
[ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppSchemasUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PutField(string app, string schema, long id, [FromBody] UpdateFieldDto request) public async Task<IActionResult> PutField(string app, string schema, long id, [FromBody] UpdateFieldDto request)
{ {
@ -197,7 +197,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
[HttpPut] [HttpPut]
[Route("apps/{app}/schemas/{schema}/fields/{parentId:long}/nested/{id:long}/")] [Route("apps/{app}/schemas/{schema}/fields/{parentId:long}/nested/{id:long}/")]
[ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppSchemasUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PutNestedField(string app, string schema, long parentId, long id, [FromBody] UpdateFieldDto request) public async Task<IActionResult> PutNestedField(string app, string schema, long parentId, long id, [FromBody] UpdateFieldDto request)
{ {
@ -225,7 +225,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
[HttpPut] [HttpPut]
[Route("apps/{app}/schemas/{schema}/fields/{id:long}/lock/")] [Route("apps/{app}/schemas/{schema}/fields/{id:long}/lock/")]
[ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppSchemasUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> LockField(string app, string schema, long id) public async Task<IActionResult> LockField(string app, string schema, long id)
{ {
@ -254,7 +254,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
[HttpPut] [HttpPut]
[Route("apps/{app}/schemas/{schema}/fields/{parentId:long}/nested/{id:long}/lock/")] [Route("apps/{app}/schemas/{schema}/fields/{parentId:long}/nested/{id:long}/lock/")]
[ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppSchemasUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> LockNestedField(string app, string schema, long parentId, long id) public async Task<IActionResult> LockNestedField(string app, string schema, long parentId, long id)
{ {
@ -282,7 +282,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
[HttpPut] [HttpPut]
[Route("apps/{app}/schemas/{schema}/fields/{id:long}/hide/")] [Route("apps/{app}/schemas/{schema}/fields/{id:long}/hide/")]
[ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppSchemasUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> HideField(string app, string schema, long id) public async Task<IActionResult> HideField(string app, string schema, long id)
{ {
@ -311,7 +311,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
[HttpPut] [HttpPut]
[Route("apps/{app}/schemas/{schema}/fields/{parentId:long}/nested/{id:long}/hide/")] [Route("apps/{app}/schemas/{schema}/fields/{parentId:long}/nested/{id:long}/hide/")]
[ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppSchemasUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> HideNestedField(string app, string schema, long parentId, long id) public async Task<IActionResult> HideNestedField(string app, string schema, long parentId, long id)
{ {
@ -339,7 +339,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
[HttpPut] [HttpPut]
[Route("apps/{app}/schemas/{schema}/fields/{id:long}/show/")] [Route("apps/{app}/schemas/{schema}/fields/{id:long}/show/")]
[ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppSchemasUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> ShowField(string app, string schema, long id) public async Task<IActionResult> ShowField(string app, string schema, long id)
{ {
@ -368,7 +368,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
[HttpPut] [HttpPut]
[Route("apps/{app}/schemas/{schema}/fields/{parentId:long}/nested/{id:long}/show/")] [Route("apps/{app}/schemas/{schema}/fields/{parentId:long}/nested/{id:long}/show/")]
[ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppSchemasUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> ShowNestedField(string app, string schema, long parentId, long id) public async Task<IActionResult> ShowNestedField(string app, string schema, long parentId, long id)
{ {
@ -396,7 +396,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
[HttpPut] [HttpPut]
[Route("apps/{app}/schemas/{schema}/fields/{id:long}/enable/")] [Route("apps/{app}/schemas/{schema}/fields/{id:long}/enable/")]
[ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppSchemasUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> EnableField(string app, string schema, long id) public async Task<IActionResult> EnableField(string app, string schema, long id)
{ {
@ -425,7 +425,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
[HttpPut] [HttpPut]
[Route("apps/{app}/schemas/{schema}/fields/{parentId:long}/nested/{id:long}/enable/")] [Route("apps/{app}/schemas/{schema}/fields/{parentId:long}/nested/{id:long}/enable/")]
[ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppSchemasUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> EnableNestedField(string app, string schema, long parentId, long id) public async Task<IActionResult> EnableNestedField(string app, string schema, long parentId, long id)
{ {
@ -453,7 +453,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
[HttpPut] [HttpPut]
[Route("apps/{app}/schemas/{schema}/fields/{id:long}/disable/")] [Route("apps/{app}/schemas/{schema}/fields/{id:long}/disable/")]
[ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppSchemasUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> DisableField(string app, string schema, long id) public async Task<IActionResult> DisableField(string app, string schema, long id)
{ {
@ -482,7 +482,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
[HttpPut] [HttpPut]
[Route("apps/{app}/schemas/{schema}/fields/{parentId:long}/nested/{id:long}/disable/")] [Route("apps/{app}/schemas/{schema}/fields/{parentId:long}/nested/{id:long}/disable/")]
[ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppSchemasUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> DisableNestedField(string app, string schema, long parentId, long id) public async Task<IActionResult> DisableNestedField(string app, string schema, long parentId, long id)
{ {
@ -507,7 +507,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
[HttpDelete] [HttpDelete]
[Route("apps/{app}/schemas/{schema}/fields/{id:long}/")] [Route("apps/{app}/schemas/{schema}/fields/{id:long}/")]
[ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppSchemasUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> DeleteField(string app, string schema, long id) public async Task<IActionResult> DeleteField(string app, string schema, long id)
{ {
@ -533,7 +533,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
[HttpDelete] [HttpDelete]
[Route("apps/{app}/schemas/{schema}/fields/{parentId:long}/nested/{id:long}/")] [Route("apps/{app}/schemas/{schema}/fields/{parentId:long}/nested/{id:long}/")]
[ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppSchemasUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> DeleteNestedField(string app, string schema, long parentId, long id) public async Task<IActionResult> DeleteNestedField(string app, string schema, long parentId, long id)
{ {

24
backend/src/Squidex/Areas/Api/Controllers/Schemas/SchemasController.cs

@ -48,7 +48,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
[HttpGet] [HttpGet]
[Route("apps/{app}/schemas/")] [Route("apps/{app}/schemas/")]
[ProducesResponseType(typeof(SchemasDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(SchemasDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasRead)] [ApiPermissionOrAnonymous(PermissionIds.AppSchemasRead)]
[ApiCosts(0)] [ApiCosts(0)]
public async Task<IActionResult> GetSchemas(string app) public async Task<IActionResult> GetSchemas(string app)
{ {
@ -76,7 +76,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
[HttpGet] [HttpGet]
[Route("apps/{app}/schemas/{schema}/")] [Route("apps/{app}/schemas/{schema}/")]
[ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasRead)] [ApiPermissionOrAnonymous(PermissionIds.AppSchemasRead)]
[ApiCosts(0)] [ApiCosts(0)]
public IActionResult GetSchema(string app, string schema) public IActionResult GetSchema(string app, string schema)
{ {
@ -103,7 +103,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
[HttpPost] [HttpPost]
[Route("apps/{app}/schemas/")] [Route("apps/{app}/schemas/")]
[ProducesResponseType(typeof(SchemaDto), 201)] [ProducesResponseType(typeof(SchemaDto), 201)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasCreate)] [ApiPermissionOrAnonymous(PermissionIds.AppSchemasCreate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PostSchema(string app, [FromBody] CreateSchemaDto request) public async Task<IActionResult> PostSchema(string app, [FromBody] CreateSchemaDto request)
{ {
@ -128,7 +128,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
[HttpPut] [HttpPut]
[Route("apps/{app}/schemas/{schema}/")] [Route("apps/{app}/schemas/{schema}/")]
[ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppSchemasUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PutSchema(string app, string schema, [FromBody] UpdateSchemaDto request) public async Task<IActionResult> PutSchema(string app, string schema, [FromBody] UpdateSchemaDto request)
{ {
@ -153,7 +153,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
[HttpPut] [HttpPut]
[Route("apps/{app}/schemas/{schema}/sync")] [Route("apps/{app}/schemas/{schema}/sync")]
[ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppSchemasUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PutSchemaSync(string app, string schema, [FromBody] SynchronizeSchemaDto request) public async Task<IActionResult> PutSchemaSync(string app, string schema, [FromBody] SynchronizeSchemaDto request)
{ {
@ -178,7 +178,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
[HttpPut] [HttpPut]
[Route("apps/{app}/schemas/{schema}/category")] [Route("apps/{app}/schemas/{schema}/category")]
[ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppSchemasUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PutCategory(string app, string schema, [FromBody] ChangeCategoryDto request) public async Task<IActionResult> PutCategory(string app, string schema, [FromBody] ChangeCategoryDto request)
{ {
@ -203,7 +203,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
[HttpPut] [HttpPut]
[Route("apps/{app}/schemas/{schema}/preview-urls")] [Route("apps/{app}/schemas/{schema}/preview-urls")]
[ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppSchemasUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PutPreviewUrls(string app, string schema, [FromBody] ConfigurePreviewUrlsDto request) public async Task<IActionResult> PutPreviewUrls(string app, string schema, [FromBody] ConfigurePreviewUrlsDto request)
{ {
@ -228,7 +228,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
[HttpPut] [HttpPut]
[Route("apps/{app}/schemas/{schema}/scripts/")] [Route("apps/{app}/schemas/{schema}/scripts/")]
[ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasScripts)] [ApiPermissionOrAnonymous(PermissionIds.AppSchemasScripts)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PutScripts(string app, string schema, [FromBody] SchemaScriptsDto request) public async Task<IActionResult> PutScripts(string app, string schema, [FromBody] SchemaScriptsDto request)
{ {
@ -253,7 +253,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
[HttpPut] [HttpPut]
[Route("apps/{app}/schemas/{schema}/rules/")] [Route("apps/{app}/schemas/{schema}/rules/")]
[ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)] [ApiPermissionOrAnonymous(PermissionIds.AppSchemasUpdate)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PutRules(string app, string schema, [FromBody] ConfigureFieldRulesDto request) public async Task<IActionResult> PutRules(string app, string schema, [FromBody] ConfigureFieldRulesDto request)
{ {
@ -276,7 +276,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
[HttpPut] [HttpPut]
[Route("apps/{app}/schemas/{schema}/publish/")] [Route("apps/{app}/schemas/{schema}/publish/")]
[ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasPublish)] [ApiPermissionOrAnonymous(PermissionIds.AppSchemasPublish)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> PublishSchema(string app, string schema) public async Task<IActionResult> PublishSchema(string app, string schema)
{ {
@ -299,7 +299,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
[HttpPut] [HttpPut]
[Route("apps/{app}/schemas/{schema}/unpublish/")] [Route("apps/{app}/schemas/{schema}/unpublish/")]
[ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(SchemaDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasPublish)] [ApiPermissionOrAnonymous(PermissionIds.AppSchemasPublish)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> UnpublishSchema(string app, string schema) public async Task<IActionResult> UnpublishSchema(string app, string schema)
{ {
@ -321,7 +321,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
/// </returns> /// </returns>
[HttpDelete] [HttpDelete]
[Route("apps/{app}/schemas/{schema}/")] [Route("apps/{app}/schemas/{schema}/")]
[ApiPermissionOrAnonymous(Permissions.AppSchemasDelete)] [ApiPermissionOrAnonymous(PermissionIds.AppSchemasDelete)]
[ApiCosts(1)] [ApiCosts(1)]
public async Task<IActionResult> DeleteSchema(string app, string schema) public async Task<IActionResult> DeleteSchema(string app, string schema)
{ {

2
backend/src/Squidex/Areas/Api/Controllers/Search/SearchController.cs

@ -40,7 +40,7 @@ namespace Squidex.Areas.Api.Controllers.Search
[HttpGet] [HttpGet]
[Route("apps/{app}/search/")] [Route("apps/{app}/search/")]
[ProducesResponseType(typeof(SearchResultDto[]), StatusCodes.Status200OK)] [ProducesResponseType(typeof(SearchResultDto[]), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSearch)] [ApiPermissionOrAnonymous(PermissionIds.AppSearch)]
[ApiCosts(0)] [ApiCosts(0)]
public async Task<IActionResult> GetSearchResults(string app, [FromQuery] string? query = null) public async Task<IActionResult> GetSearchResults(string app, [FromQuery] string? query = null)
{ {

8
backend/src/Squidex/Areas/Api/Controllers/Statistics/UsagesController.cs

@ -64,7 +64,7 @@ namespace Squidex.Areas.Api.Controllers.Statistics
[HttpGet] [HttpGet]
[Route("apps/{app}/usages/log/")] [Route("apps/{app}/usages/log/")]
[ProducesResponseType(typeof(LogDownloadDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(LogDownloadDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppUsage)] [ApiPermissionOrAnonymous(PermissionIds.AppUsage)]
[ApiCosts(0)] [ApiCosts(0)]
public IActionResult GetLog(string app) public IActionResult GetLog(string app)
{ {
@ -92,7 +92,7 @@ namespace Squidex.Areas.Api.Controllers.Statistics
[HttpGet] [HttpGet]
[Route("apps/{app}/usages/calls/{fromDate}/{toDate}/")] [Route("apps/{app}/usages/calls/{fromDate}/{toDate}/")]
[ProducesResponseType(typeof(CallsUsageDtoDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(CallsUsageDtoDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppUsage)] [ApiPermissionOrAnonymous(PermissionIds.AppUsage)]
[ApiCosts(0)] [ApiCosts(0)]
public async Task<IActionResult> GetUsages(string app, DateTime fromDate, DateTime toDate) public async Task<IActionResult> GetUsages(string app, DateTime fromDate, DateTime toDate)
{ {
@ -123,7 +123,7 @@ namespace Squidex.Areas.Api.Controllers.Statistics
[HttpGet] [HttpGet]
[Route("apps/{app}/usages/storage/today/")] [Route("apps/{app}/usages/storage/today/")]
[ProducesResponseType(typeof(CurrentStorageDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(CurrentStorageDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppUsage)] [ApiPermissionOrAnonymous(PermissionIds.AppUsage)]
[ApiCosts(0)] [ApiCosts(0)]
public async Task<IActionResult> GetCurrentStorageSize(string app) public async Task<IActionResult> GetCurrentStorageSize(string app)
{ {
@ -151,7 +151,7 @@ namespace Squidex.Areas.Api.Controllers.Statistics
[HttpGet] [HttpGet]
[Route("apps/{app}/usages/storage/{fromDate}/{toDate}/")] [Route("apps/{app}/usages/storage/{fromDate}/{toDate}/")]
[ProducesResponseType(typeof(StorageUsagePerDateDto[]), StatusCodes.Status200OK)] [ProducesResponseType(typeof(StorageUsagePerDateDto[]), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppUsage)] [ApiPermissionOrAnonymous(PermissionIds.AppUsage)]
[ApiCosts(0)] [ApiCosts(0)]
public async Task<IActionResult> GetStorageSizes(string app, DateTime fromDate, DateTime toDate) public async Task<IActionResult> GetStorageSizes(string app, DateTime fromDate, DateTime toDate)
{ {

2
backend/src/Squidex/Areas/Api/Controllers/Translations/TranslationsController.cs

@ -39,7 +39,7 @@ namespace Squidex.Areas.Api.Controllers.Translations
[HttpPost] [HttpPost]
[Route("apps/{app}/translations/")] [Route("apps/{app}/translations/")]
[ProducesResponseType(typeof(TranslationDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(TranslationDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppTranslate)] [ApiPermissionOrAnonymous(PermissionIds.AppTranslate)]
[ApiCosts(0)] [ApiCosts(0)]
public async Task<IActionResult> PostTranslation(string app, [FromBody] TranslateDto request) public async Task<IActionResult> PostTranslation(string app, [FromBody] TranslateDto request)
{ {

2
backend/src/Squidex/Areas/Api/Controllers/UI/UIController.cs

@ -20,7 +20,7 @@ namespace Squidex.Areas.Api.Controllers.UI
{ {
public sealed class UIController : ApiController public sealed class UIController : ApiController
{ {
private static readonly Permission CreateAppPermission = new Permission(Permissions.AdminAppCreate); private static readonly Permission CreateAppPermission = new Permission(PermissionIds.AdminAppCreate);
private readonly MyUIOptions uiOptions; private readonly MyUIOptions uiOptions;
private readonly IAppUISettings appUISettings; private readonly IAppUISettings appUISettings;

14
backend/src/Squidex/Areas/Api/Controllers/Users/UserManagementController.cs

@ -30,7 +30,7 @@ namespace Squidex.Areas.Api.Controllers.Users
[HttpGet] [HttpGet]
[Route("user-management/")] [Route("user-management/")]
[ProducesResponseType(typeof(UsersDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(UsersDto), StatusCodes.Status200OK)]
[ApiPermission(Permissions.AdminUsersRead)] [ApiPermission(PermissionIds.AdminUsersRead)]
public async Task<IActionResult> GetUsers([FromQuery] string? query = null, [FromQuery] int skip = 0, [FromQuery] int take = 10) public async Task<IActionResult> GetUsers([FromQuery] string? query = null, [FromQuery] int skip = 0, [FromQuery] int take = 10)
{ {
var users = await userService.QueryAsync(query, take, skip, HttpContext.RequestAborted); var users = await userService.QueryAsync(query, take, skip, HttpContext.RequestAborted);
@ -43,7 +43,7 @@ namespace Squidex.Areas.Api.Controllers.Users
[HttpGet] [HttpGet]
[Route("user-management/{id}/")] [Route("user-management/{id}/")]
[ProducesResponseType(typeof(UserDto), 201)] [ProducesResponseType(typeof(UserDto), 201)]
[ApiPermission(Permissions.AdminUsersRead)] [ApiPermission(PermissionIds.AdminUsersRead)]
public async Task<IActionResult> GetUser(string id) public async Task<IActionResult> GetUser(string id)
{ {
var user = await userService.FindByIdAsync(id, HttpContext.RequestAborted); var user = await userService.FindByIdAsync(id, HttpContext.RequestAborted);
@ -61,7 +61,7 @@ namespace Squidex.Areas.Api.Controllers.Users
[HttpPost] [HttpPost]
[Route("user-management/")] [Route("user-management/")]
[ProducesResponseType(typeof(UserDto), 201)] [ProducesResponseType(typeof(UserDto), 201)]
[ApiPermission(Permissions.AdminUsersCreate)] [ApiPermission(PermissionIds.AdminUsersCreate)]
public async Task<IActionResult> PostUser([FromBody] CreateUserDto request) public async Task<IActionResult> PostUser([FromBody] CreateUserDto request)
{ {
var user = await userService.CreateAsync(request.Email, request.ToValues(), ct: HttpContext.RequestAborted); var user = await userService.CreateAsync(request.Email, request.ToValues(), ct: HttpContext.RequestAborted);
@ -74,7 +74,7 @@ namespace Squidex.Areas.Api.Controllers.Users
[HttpPut] [HttpPut]
[Route("user-management/{id}/")] [Route("user-management/{id}/")]
[ProducesResponseType(typeof(UserDto), 201)] [ProducesResponseType(typeof(UserDto), 201)]
[ApiPermission(Permissions.AdminUsersUpdate)] [ApiPermission(PermissionIds.AdminUsersUpdate)]
public async Task<IActionResult> PutUser(string id, [FromBody] UpdateUserDto request) public async Task<IActionResult> PutUser(string id, [FromBody] UpdateUserDto request)
{ {
var user = await userService.UpdateAsync(id, request.ToValues(), ct: HttpContext.RequestAborted); var user = await userService.UpdateAsync(id, request.ToValues(), ct: HttpContext.RequestAborted);
@ -87,7 +87,7 @@ namespace Squidex.Areas.Api.Controllers.Users
[HttpPut] [HttpPut]
[Route("user-management/{id}/lock/")] [Route("user-management/{id}/lock/")]
[ProducesResponseType(typeof(UserDto), 201)] [ProducesResponseType(typeof(UserDto), 201)]
[ApiPermission(Permissions.AdminUsersLock)] [ApiPermission(PermissionIds.AdminUsersLock)]
public async Task<IActionResult> LockUser(string id) public async Task<IActionResult> LockUser(string id)
{ {
if (this.IsUser(id)) if (this.IsUser(id))
@ -105,7 +105,7 @@ namespace Squidex.Areas.Api.Controllers.Users
[HttpPut] [HttpPut]
[Route("user-management/{id}/unlock/")] [Route("user-management/{id}/unlock/")]
[ProducesResponseType(typeof(UserDto), 201)] [ProducesResponseType(typeof(UserDto), 201)]
[ApiPermission(Permissions.AdminUsersUnlock)] [ApiPermission(PermissionIds.AdminUsersUnlock)]
public async Task<IActionResult> UnlockUser(string id) public async Task<IActionResult> UnlockUser(string id)
{ {
if (this.IsUser(id)) if (this.IsUser(id))
@ -123,7 +123,7 @@ namespace Squidex.Areas.Api.Controllers.Users
[HttpDelete] [HttpDelete]
[Route("user-management/{id}/")] [Route("user-management/{id}/")]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[ApiPermission(Permissions.AdminUsersUnlock)] [ApiPermission(PermissionIds.AdminUsersUnlock)]
public async Task<IActionResult> DeleteUser(string id) public async Task<IActionResult> DeleteUser(string id)
{ {
if (this.IsUser(id)) if (this.IsUser(id))

2
backend/src/Squidex/Areas/IdentityServer/Config/ApplicationExtensions.cs

@ -19,7 +19,7 @@ namespace Squidex.Areas.IdentityServer.Config
{ {
public static OpenIddictApplicationDescriptor SetAdmin(this OpenIddictApplicationDescriptor application) public static OpenIddictApplicationDescriptor SetAdmin(this OpenIddictApplicationDescriptor application)
{ {
application.Properties[SquidexClaimTypes.Permissions] = CreateParameter(Enumerable.Repeat(Permissions.All, 1)); application.Properties[SquidexClaimTypes.Permissions] = CreateParameter(Enumerable.Repeat(PermissionIds.All, 1));
return application; return application;
} }

4
backend/src/Squidex/Areas/IdentityServer/Config/CreateAdminInitializer.cs

@ -95,11 +95,11 @@ namespace Squidex.Areas.IdentityServer.Config
private PermissionSet CreatePermissions(PermissionSet permissions) private PermissionSet CreatePermissions(PermissionSet permissions)
{ {
permissions = permissions.Add(Permissions.Admin); permissions = permissions.Add(PermissionIds.Admin);
foreach (var app in identityOptions.AdminApps.OrEmpty()) foreach (var app in identityOptions.AdminApps.OrEmpty())
{ {
permissions = permissions.Add(Permissions.ForApp(Permissions.AppAdmin, app)); permissions = permissions.Add(PermissionIds.ForApp(PermissionIds.AppAdmin, app));
} }
return permissions; return permissions;

22
backend/tests/Squidex.Domain.Apps.Entities.Tests/Apps/AppSettingsSearchSourceTests.cs

@ -42,7 +42,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
[Fact] [Fact]
public async Task Should_return_dashboard_result_if_matching_and_permission_given() public async Task Should_return_dashboard_result_if_matching_and_permission_given()
{ {
var permission = Permissions.ForApp(Permissions.AppUsage, appId.Name); var permission = PermissionIds.ForApp(PermissionIds.AppUsage, appId.Name);
var ctx = ContextWithPermission(permission.Id); var ctx = ContextWithPermission(permission.Id);
@ -69,7 +69,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
[Fact] [Fact]
public async Task Should_return_languages_result_if_matching_and_permission_given() public async Task Should_return_languages_result_if_matching_and_permission_given()
{ {
var permission = Permissions.ForApp(Permissions.AppLanguagesRead, appId.Name); var permission = PermissionIds.ForApp(PermissionIds.AppLanguagesRead, appId.Name);
var ctx = ContextWithPermission(permission.Id); var ctx = ContextWithPermission(permission.Id);
@ -106,7 +106,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
[Fact] [Fact]
public async Task Should_return_schemas_result_if_matching_and_permission_given() public async Task Should_return_schemas_result_if_matching_and_permission_given()
{ {
var permission = Permissions.ForApp(Permissions.AppSchemasRead, appId.Name); var permission = PermissionIds.ForApp(PermissionIds.AppSchemasRead, appId.Name);
var ctx = ContextWithPermission(permission.Id); var ctx = ContextWithPermission(permission.Id);
@ -133,7 +133,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
[Fact] [Fact]
public async Task Should_return_assets_result_if_matching_and_permission_given() public async Task Should_return_assets_result_if_matching_and_permission_given()
{ {
var permission = Permissions.ForApp(Permissions.AppAssetsRead, appId.Name); var permission = PermissionIds.ForApp(PermissionIds.AppAssetsRead, appId.Name);
var ctx = ContextWithPermission(permission.Id); var ctx = ContextWithPermission(permission.Id);
@ -160,7 +160,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
[Fact] [Fact]
public async Task Should_return_backups_result_if_matching_and_permission_given() public async Task Should_return_backups_result_if_matching_and_permission_given()
{ {
var permission = Permissions.ForApp(Permissions.AppBackupsRead, appId.Name); var permission = PermissionIds.ForApp(PermissionIds.AppBackupsRead, appId.Name);
var ctx = ContextWithPermission(permission.Id); var ctx = ContextWithPermission(permission.Id);
@ -187,7 +187,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
[Fact] [Fact]
public async Task Should_return_clients_result_if_matching_and_permission_given() public async Task Should_return_clients_result_if_matching_and_permission_given()
{ {
var permission = Permissions.ForApp(Permissions.AppClientsRead, appId.Name); var permission = PermissionIds.ForApp(PermissionIds.AppClientsRead, appId.Name);
var ctx = ContextWithPermission(permission.Id); var ctx = ContextWithPermission(permission.Id);
@ -214,7 +214,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
[Fact] [Fact]
public async Task Should_return_contributors_result_if_matching_and_permission_given() public async Task Should_return_contributors_result_if_matching_and_permission_given()
{ {
var permission = Permissions.ForApp(Permissions.AppContributorsRead, appId.Name); var permission = PermissionIds.ForApp(PermissionIds.AppContributorsRead, appId.Name);
var ctx = ContextWithPermission(permission.Id); var ctx = ContextWithPermission(permission.Id);
@ -241,7 +241,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
[Fact] [Fact]
public async Task Should_return_subscription_result_if_matching_and_permission_given() public async Task Should_return_subscription_result_if_matching_and_permission_given()
{ {
var permission = Permissions.ForApp(Permissions.AppPlansRead, appId.Name); var permission = PermissionIds.ForApp(PermissionIds.AppPlansRead, appId.Name);
var ctx = ContextWithPermission(permission.Id); var ctx = ContextWithPermission(permission.Id);
@ -268,7 +268,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
[Fact] [Fact]
public async Task Should_return_roles_result_if_matching_and_permission_given() public async Task Should_return_roles_result_if_matching_and_permission_given()
{ {
var permission = Permissions.ForApp(Permissions.AppRolesRead, appId.Name); var permission = PermissionIds.ForApp(PermissionIds.AppRolesRead, appId.Name);
var ctx = ContextWithPermission(permission.Id); var ctx = ContextWithPermission(permission.Id);
@ -295,7 +295,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
[Fact] [Fact]
public async Task Should_return_rules_result_if_matching_and_permission_given() public async Task Should_return_rules_result_if_matching_and_permission_given()
{ {
var permission = Permissions.ForApp(Permissions.AppRulesRead, appId.Name); var permission = PermissionIds.ForApp(PermissionIds.AppRulesRead, appId.Name);
var ctx = ContextWithPermission(permission.Id); var ctx = ContextWithPermission(permission.Id);
@ -322,7 +322,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
[Fact] [Fact]
public async Task Should_return_workflows_result_if_matching_and_permission_given() public async Task Should_return_workflows_result_if_matching_and_permission_given()
{ {
var permission = Permissions.ForApp(Permissions.AppWorkflowsRead, appId.Name); var permission = PermissionIds.ForApp(PermissionIds.AppWorkflowsRead, appId.Name);
var ctx = ContextWithPermission(permission.Id); var ctx = ContextWithPermission(permission.Id);

2
backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetsSearchSourceTests.cs

@ -46,7 +46,7 @@ namespace Squidex.Domain.Apps.Entities.Assets
[Fact] [Fact]
public async Task Should_return_assets_results_if_found() public async Task Should_return_assets_results_if_found()
{ {
var permission = Permissions.ForApp(Permissions.AppAssetsRead, appId.Name); var permission = PermissionIds.ForApp(PermissionIds.AppAssetsRead, appId.Name);
var ctx = ContextWithPermission(permission.Id); var ctx = ContextWithPermission(permission.Id);

14
backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/DomainObject/AssetsBulkUpdateCommandMiddlewareTests.cs

@ -59,7 +59,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
[Fact] [Fact]
public async Task Should_annotate_asset() public async Task Should_annotate_asset()
{ {
SetupContext(Permissions.AppAssetsUpdate); SetupContext(PermissionIds.AppAssetsUpdate);
var id = DomainId.NewGuid(); var id = DomainId.NewGuid();
@ -77,7 +77,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
[Fact] [Fact]
public async Task Should_throw_security_exception_if_user_has_no_permission_for_annotating() public async Task Should_throw_security_exception_if_user_has_no_permission_for_annotating()
{ {
SetupContext(Permissions.AppAssetsRead); SetupContext(PermissionIds.AppAssetsRead);
var id = DomainId.NewGuid(); var id = DomainId.NewGuid();
@ -95,7 +95,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
[Fact] [Fact]
public async Task Should_move_asset() public async Task Should_move_asset()
{ {
SetupContext(Permissions.AppAssetsUpdate); SetupContext(PermissionIds.AppAssetsUpdate);
var id = DomainId.NewGuid(); var id = DomainId.NewGuid();
@ -113,7 +113,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
[Fact] [Fact]
public async Task Should_throw_security_exception_if_user_has_no_permission_for_moving() public async Task Should_throw_security_exception_if_user_has_no_permission_for_moving()
{ {
SetupContext(Permissions.AppAssetsRead); SetupContext(PermissionIds.AppAssetsRead);
var id = DomainId.NewGuid(); var id = DomainId.NewGuid();
@ -131,7 +131,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
[Fact] [Fact]
public async Task Should_delete_asset() public async Task Should_delete_asset()
{ {
SetupContext(Permissions.AppAssetsDelete); SetupContext(PermissionIds.AppAssetsDelete);
var id = DomainId.NewGuid(); var id = DomainId.NewGuid();
@ -150,7 +150,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
[Fact] [Fact]
public async Task Should_throw_security_exception_if_user_has_no_permission_for_deletion() public async Task Should_throw_security_exception_if_user_has_no_permission_for_deletion()
{ {
SetupContext(Permissions.AppAssetsRead); SetupContext(PermissionIds.AppAssetsRead);
var id = DomainId.NewGuid(); var id = DomainId.NewGuid();
@ -193,7 +193,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
private Context SetupContext(string id) private Context SetupContext(string id)
{ {
var permission = Permissions.ForApp(id, appId.Name).Id; var permission = PermissionIds.ForApp(id, appId.Name).Id;
var claimsIdentity = new ClaimsIdentity(); var claimsIdentity = new ClaimsIdentity();
var claimsPrincipal = new ClaimsPrincipal(claimsIdentity); var claimsPrincipal = new ClaimsPrincipal(claimsIdentity);

2
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentsSearchSourceTests.cs

@ -212,7 +212,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
foreach (var schemaId in allowedSchemas) foreach (var schemaId in allowedSchemas)
{ {
var permission = Permissions.ForApp(Permissions.AppContentsReadOwn, appId.Name, schemaId.Name).Id; var permission = PermissionIds.ForApp(PermissionIds.AppContentsReadOwn, appId.Name, schemaId.Name).Id;
claimsIdentity.AddClaim(new Claim(SquidexClaimTypes.Permissions, permission)); claimsIdentity.AddClaim(new Claim(SquidexClaimTypes.Permissions, permission));
} }

48
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DomainObject/ContentsBulkUpdateCommandMiddlewareTests.cs

@ -67,7 +67,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
[Fact] [Fact]
public async Task Should_throw_exception_if_content_cannot_be_resolved() public async Task Should_throw_exception_if_content_cannot_be_resolved()
{ {
SetupContext(Permissions.AppContentsUpdateOwn); SetupContext(PermissionIds.AppContentsUpdateOwn);
CreateTestData(true); CreateTestData(true);
@ -85,7 +85,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
[Fact] [Fact]
public async Task Should_throw_exception_if_query_resolves_multiple_contents() public async Task Should_throw_exception_if_query_resolves_multiple_contents()
{ {
var requestContext = SetupContext(Permissions.AppContentsUpdateOwn); var requestContext = SetupContext(PermissionIds.AppContentsUpdateOwn);
var (id, _, query) = CreateTestData(true); var (id, _, query) = CreateTestData(true);
@ -111,7 +111,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
[Fact] [Fact]
public async Task Should_upsert_content_with_resolved_id() public async Task Should_upsert_content_with_resolved_id()
{ {
var requestContext = SetupContext(Permissions.AppContentsUpsert); var requestContext = SetupContext(PermissionIds.AppContentsUpsert);
var (id, data, query) = CreateTestData(true); var (id, data, query) = CreateTestData(true);
@ -138,7 +138,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
[Fact] [Fact]
public async Task Should_upsert_content_with_resolved_ids() public async Task Should_upsert_content_with_resolved_ids()
{ {
var requestContext = SetupContext(Permissions.AppContentsUpsert); var requestContext = SetupContext(PermissionIds.AppContentsUpsert);
var (_, data, query) = CreateTestData(true); var (_, data, query) = CreateTestData(true);
@ -177,7 +177,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
[Fact] [Fact]
public async Task Should_upsert_content_with_random_id_if_no_query_and_id_defined() public async Task Should_upsert_content_with_random_id_if_no_query_and_id_defined()
{ {
SetupContext(Permissions.AppContentsUpsert); SetupContext(PermissionIds.AppContentsUpsert);
var (_, data, _) = CreateTestData(false); var (_, data, _) = CreateTestData(false);
@ -196,7 +196,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
[Fact] [Fact]
public async Task Should_upsert_content_with_random_id_if_query_returns_no_result() public async Task Should_upsert_content_with_random_id_if_query_returns_no_result()
{ {
SetupContext(Permissions.AppContentsUpsert); SetupContext(PermissionIds.AppContentsUpsert);
var (_, data, query) = CreateTestData(true); var (_, data, query) = CreateTestData(true);
@ -215,7 +215,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
[Fact] [Fact]
public async Task Should_upsert_content_if_id_defined() public async Task Should_upsert_content_if_id_defined()
{ {
SetupContext(Permissions.AppContentsUpsert); SetupContext(PermissionIds.AppContentsUpsert);
var (id, data, _) = CreateTestData(false); var (id, data, _) = CreateTestData(false);
@ -234,7 +234,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
[Fact] [Fact]
public async Task Should_upsert_content_with_custom_id() public async Task Should_upsert_content_with_custom_id()
{ {
SetupContext(Permissions.AppContentsUpsert); SetupContext(PermissionIds.AppContentsUpsert);
var (id, data, _) = CreateTestData(true); var (id, data, _) = CreateTestData(true);
@ -253,7 +253,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
[Fact] [Fact]
public async Task Should_create_content() public async Task Should_create_content()
{ {
SetupContext(Permissions.AppContentsCreate); SetupContext(PermissionIds.AppContentsCreate);
var (id, data, _) = CreateTestData(false); var (id, data, _) = CreateTestData(false);
@ -272,7 +272,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
[Fact] [Fact]
public async Task Should_throw_security_exception_if_user_has_no_permission_for_creating() public async Task Should_throw_security_exception_if_user_has_no_permission_for_creating()
{ {
SetupContext(Permissions.AppContentsReadOwn); SetupContext(PermissionIds.AppContentsReadOwn);
var (id, data, _) = CreateTestData(false); var (id, data, _) = CreateTestData(false);
@ -290,7 +290,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
[Fact] [Fact]
public async Task Should_update_content() public async Task Should_update_content()
{ {
SetupContext(Permissions.AppContentsUpdateOwn); SetupContext(PermissionIds.AppContentsUpdateOwn);
var (id, data, _) = CreateTestData(false); var (id, data, _) = CreateTestData(false);
@ -309,7 +309,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
[Fact] [Fact]
public async Task Should_throw_security_exception_if_user_has_no_permission_for_updating() public async Task Should_throw_security_exception_if_user_has_no_permission_for_updating()
{ {
SetupContext(Permissions.AppContentsReadOwn); SetupContext(PermissionIds.AppContentsReadOwn);
var (id, data, _) = CreateTestData(false); var (id, data, _) = CreateTestData(false);
@ -327,7 +327,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
[Fact] [Fact]
public async Task Should_patch_content() public async Task Should_patch_content()
{ {
SetupContext(Permissions.AppContentsUpdateOwn); SetupContext(PermissionIds.AppContentsUpdateOwn);
var (id, data, _) = CreateTestData(false); var (id, data, _) = CreateTestData(false);
@ -346,7 +346,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
[Fact] [Fact]
public async Task Should_throw_security_exception_if_user_has_no_permission_for_patching() public async Task Should_throw_security_exception_if_user_has_no_permission_for_patching()
{ {
SetupContext(Permissions.AppContentsReadOwn); SetupContext(PermissionIds.AppContentsReadOwn);
var (id, data, _) = CreateTestData(false); var (id, data, _) = CreateTestData(false);
@ -364,7 +364,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
[Fact] [Fact]
public async Task Should_change_content_status() public async Task Should_change_content_status()
{ {
SetupContext(Permissions.AppContentsChangeStatusOwn); SetupContext(PermissionIds.AppContentsChangeStatusOwn);
var (id, _, _) = CreateTestData(false); var (id, _, _) = CreateTestData(false);
@ -383,7 +383,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
[Fact] [Fact]
public async Task Should_change_content_status_with_due_time() public async Task Should_change_content_status_with_due_time()
{ {
SetupContext(Permissions.AppContentsChangeStatusOwn); SetupContext(PermissionIds.AppContentsChangeStatusOwn);
var (id, _, _) = CreateTestData(false); var (id, _, _) = CreateTestData(false);
@ -402,7 +402,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
[Fact] [Fact]
public async Task Should_throw_security_exception_if_user_has_no_permission_for_changing_status() public async Task Should_throw_security_exception_if_user_has_no_permission_for_changing_status()
{ {
SetupContext(Permissions.AppContentsReadOwn); SetupContext(PermissionIds.AppContentsReadOwn);
var (id, _, _) = CreateTestData(false); var (id, _, _) = CreateTestData(false);
@ -420,7 +420,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
[Fact] [Fact]
public async Task Should_validate_content() public async Task Should_validate_content()
{ {
SetupContext(Permissions.AppContentsReadOwn); SetupContext(PermissionIds.AppContentsReadOwn);
var (id, _, _) = CreateTestData(false); var (id, _, _) = CreateTestData(false);
@ -439,7 +439,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
[Fact] [Fact]
public async Task Should_throw_security_exception_if_user_has_no_permission_for_validation() public async Task Should_throw_security_exception_if_user_has_no_permission_for_validation()
{ {
SetupContext(Permissions.AppContentsDeleteOwn); SetupContext(PermissionIds.AppContentsDeleteOwn);
var (id, _, _) = CreateTestData(false); var (id, _, _) = CreateTestData(false);
@ -457,7 +457,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
[Fact] [Fact]
public async Task Should_delete_content() public async Task Should_delete_content()
{ {
SetupContext(Permissions.AppContentsDeleteOwn); SetupContext(PermissionIds.AppContentsDeleteOwn);
var (id, _, _) = CreateTestData(false); var (id, _, _) = CreateTestData(false);
@ -476,7 +476,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
[Fact] [Fact]
public async Task Should_throw_security_exception_if_user_has_no_permission_for_deletion() public async Task Should_throw_security_exception_if_user_has_no_permission_for_deletion()
{ {
SetupContext(Permissions.AppContentsReadOwn); SetupContext(PermissionIds.AppContentsReadOwn);
var (id, _, _) = CreateTestData(false); var (id, _, _) = CreateTestData(false);
@ -494,7 +494,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
[Fact] [Fact]
public async Task Should_override_schema_name() public async Task Should_override_schema_name()
{ {
SetupContext(Permissions.AppContentsDeleteOwn); SetupContext(PermissionIds.AppContentsDeleteOwn);
A.CallTo(() => contentQuery.GetSchemaOrThrowAsync(A<Context>._, schemaCustomId.Name, ct)) A.CallTo(() => contentQuery.GetSchemaOrThrowAsync(A<Context>._, schemaCustomId.Name, ct))
.Returns(Mocks.Schema(appId, schemaCustomId)); .Returns(Mocks.Schema(appId, schemaCustomId));
@ -546,11 +546,11 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
claimsIdentity.AddClaim( claimsIdentity.AddClaim(
new Claim(SquidexClaimTypes.Permissions, new Claim(SquidexClaimTypes.Permissions,
Permissions.ForApp(id, appId.Name, schemaId.Name).Id)); PermissionIds.ForApp(id, appId.Name, schemaId.Name).Id));
claimsIdentity.AddClaim( claimsIdentity.AddClaim(
new Claim(SquidexClaimTypes.Permissions, new Claim(SquidexClaimTypes.Permissions,
Permissions.ForApp(id, appId.Name, schemaCustomId.Name).Id)); PermissionIds.ForApp(id, appId.Name, schemaCustomId.Name).Id));
var requestContext = new Context(claimsPrincipal, Mocks.App(appId)); var requestContext = new Context(claimsPrincipal, Mocks.App(appId));

10
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DomainObject/Guards/GuardContentTests.cs

@ -317,14 +317,14 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject.Guards
[Fact] [Fact]
public void Should_not_throw_exception_if_content_is_from_another_user_but_user_has_permission() public void Should_not_throw_exception_if_content_is_from_another_user_but_user_has_permission()
{ {
var userPermission = Permissions.ForApp(Permissions.AppContentsDelete, appId.Name, schemaId.Name).Id; var userPermission = PermissionIds.ForApp(PermissionIds.AppContentsDelete, appId.Name, schemaId.Name).Id;
var userObject = Mocks.FrontendUser(permission: userPermission); var userObject = Mocks.FrontendUser(permission: userPermission);
var operation = Operation(CreateContent(Status.Draft), normalSchema, userObject); var operation = Operation(CreateContent(Status.Draft), normalSchema, userObject);
((ContentEntity)operation.Snapshot).CreatedBy = RefToken.User("456"); ((ContentEntity)operation.Snapshot).CreatedBy = RefToken.User("456");
operation.MustHavePermission(Permissions.AppContentsDelete); operation.MustHavePermission(PermissionIds.AppContentsDelete);
} }
[Fact] [Fact]
@ -334,7 +334,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject.Guards
((ContentEntity)operation.Snapshot).CreatedBy = actor; ((ContentEntity)operation.Snapshot).CreatedBy = actor;
operation.MustHavePermission(Permissions.AppContentsDelete); operation.MustHavePermission(PermissionIds.AppContentsDelete);
} }
[Fact] [Fact]
@ -344,7 +344,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject.Guards
((ContentEntity)operation.Snapshot).CreatedBy = RefToken.User("456"); ((ContentEntity)operation.Snapshot).CreatedBy = RefToken.User("456");
operation.MustHavePermission(Permissions.AppContentsDelete); operation.MustHavePermission(PermissionIds.AppContentsDelete);
} }
[Fact] [Fact]
@ -354,7 +354,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject.Guards
((ContentEntity)operation.Snapshot).CreatedBy = RefToken.User("456"); ((ContentEntity)operation.Snapshot).CreatedBy = RefToken.User("456");
Assert.Throws<DomainForbiddenException>(() => operation.MustHavePermission(Permissions.AppContentsDelete)); Assert.Throws<DomainForbiddenException>(() => operation.MustHavePermission(PermissionIds.AppContentsDelete));
} }
[Fact] [Fact]

38
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLMutationTests.cs

@ -44,7 +44,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
} }
}"; }";
var result = await ExecuteAsync(new ExecutionOptions { Query = query }, Permissions.AppContentsReadOwn); var result = await ExecuteAsync(new ExecutionOptions { Query = query }, PermissionIds.AppContentsReadOwn);
var expected = new var expected = new
{ {
@ -88,7 +88,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
commandContext.Complete(content); commandContext.Complete(content);
var result = await ExecuteAsync(new ExecutionOptions { Query = query }, Permissions.AppContentsCreate); var result = await ExecuteAsync(new ExecutionOptions { Query = query }, PermissionIds.AppContentsCreate);
var expected = new var expected = new
{ {
@ -122,7 +122,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
commandContext.Complete(content); commandContext.Complete(content);
var result = await ExecuteAsync(new ExecutionOptions { Query = query }, Permissions.AppContentsCreate); var result = await ExecuteAsync(new ExecutionOptions { Query = query }, PermissionIds.AppContentsCreate);
var expected = new var expected = new
{ {
@ -157,7 +157,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
commandContext.Complete(content); commandContext.Complete(content);
var result = await ExecuteAsync(new ExecutionOptions { Query = query, Variables = GetInput() }, Permissions.AppContentsCreate); var result = await ExecuteAsync(new ExecutionOptions { Query = query, Variables = GetInput() }, PermissionIds.AppContentsCreate);
var expected = new var expected = new
{ {
@ -189,7 +189,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
} }
}"); }");
var result = await ExecuteAsync(new ExecutionOptions { Query = query }, Permissions.AppContentsReadOwn); var result = await ExecuteAsync(new ExecutionOptions { Query = query }, PermissionIds.AppContentsReadOwn);
var expected = new var expected = new
{ {
@ -233,7 +233,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
commandContext.Complete(content); commandContext.Complete(content);
var result = await ExecuteAsync(new ExecutionOptions { Query = query }, Permissions.AppContentsUpdateOwn); var result = await ExecuteAsync(new ExecutionOptions { Query = query }, PermissionIds.AppContentsUpdateOwn);
var expected = new var expected = new
{ {
@ -267,7 +267,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
commandContext.Complete(content); commandContext.Complete(content);
var result = await ExecuteAsync(new ExecutionOptions { Query = query, Variables = GetInput() }, Permissions.AppContentsUpdateOwn); var result = await ExecuteAsync(new ExecutionOptions { Query = query, Variables = GetInput() }, PermissionIds.AppContentsUpdateOwn);
var expected = new var expected = new
{ {
@ -299,7 +299,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
} }
}"); }");
var result = await ExecuteAsync(new ExecutionOptions { Query = query }, Permissions.AppContentsReadOwn); var result = await ExecuteAsync(new ExecutionOptions { Query = query }, PermissionIds.AppContentsReadOwn);
var expected = new var expected = new
{ {
@ -343,7 +343,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
commandContext.Complete(content); commandContext.Complete(content);
var result = await ExecuteAsync(new ExecutionOptions { Query = query }, Permissions.AppContentsUpsert); var result = await ExecuteAsync(new ExecutionOptions { Query = query }, PermissionIds.AppContentsUpsert);
var expected = new var expected = new
{ {
@ -378,7 +378,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
commandContext.Complete(content); commandContext.Complete(content);
var result = await ExecuteAsync(new ExecutionOptions { Query = query, Variables = GetInput() }, Permissions.AppContentsUpsert); var result = await ExecuteAsync(new ExecutionOptions { Query = query, Variables = GetInput() }, PermissionIds.AppContentsUpsert);
var expected = new var expected = new
{ {
@ -411,7 +411,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
} }
}"); }");
var result = await ExecuteAsync(new ExecutionOptions { Query = query }, Permissions.AppContentsReadOwn); var result = await ExecuteAsync(new ExecutionOptions { Query = query }, PermissionIds.AppContentsReadOwn);
var expected = new var expected = new
{ {
@ -455,7 +455,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
commandContext.Complete(content); commandContext.Complete(content);
var result = await ExecuteAsync(new ExecutionOptions { Query = query }, Permissions.AppContentsUpdateOwn); var result = await ExecuteAsync(new ExecutionOptions { Query = query }, PermissionIds.AppContentsUpdateOwn);
var expected = new var expected = new
{ {
@ -489,7 +489,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
commandContext.Complete(content); commandContext.Complete(content);
var result = await ExecuteAsync(new ExecutionOptions { Query = query, Variables = GetInput() }, Permissions.AppContentsUpdateOwn); var result = await ExecuteAsync(new ExecutionOptions { Query = query, Variables = GetInput() }, PermissionIds.AppContentsUpdateOwn);
var expected = new var expected = new
{ {
@ -521,7 +521,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
} }
}"); }");
var result = await ExecuteAsync(new ExecutionOptions { Query = query }, Permissions.AppContentsReadOwn); var result = await ExecuteAsync(new ExecutionOptions { Query = query }, PermissionIds.AppContentsReadOwn);
var expected = new var expected = new
{ {
@ -567,7 +567,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
commandContext.Complete(content); commandContext.Complete(content);
var result = await ExecuteAsync(new ExecutionOptions { Query = query }, Permissions.AppContentsChangeStatusOwn); var result = await ExecuteAsync(new ExecutionOptions { Query = query }, PermissionIds.AppContentsChangeStatusOwn);
var expected = new var expected = new
{ {
@ -602,7 +602,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
commandContext.Complete(content); commandContext.Complete(content);
var result = await ExecuteAsync(new ExecutionOptions { Query = query }, Permissions.AppContentsChangeStatusOwn); var result = await ExecuteAsync(new ExecutionOptions { Query = query }, PermissionIds.AppContentsChangeStatusOwn);
var expected = new var expected = new
{ {
@ -637,7 +637,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
commandContext.Complete(content); commandContext.Complete(content);
var result = await ExecuteAsync(new ExecutionOptions { Query = query }, Permissions.AppContentsChangeStatusOwn); var result = await ExecuteAsync(new ExecutionOptions { Query = query }, PermissionIds.AppContentsChangeStatusOwn);
var expected = new var expected = new
{ {
@ -670,7 +670,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
} }
}"); }");
var result = await ExecuteAsync(new ExecutionOptions { Query = query }, Permissions.AppContentsReadOwn); var result = await ExecuteAsync(new ExecutionOptions { Query = query }, PermissionIds.AppContentsReadOwn);
var expected = new var expected = new
{ {
@ -714,7 +714,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
commandContext.Complete(CommandResult.Empty(contentId, 13, 12)); commandContext.Complete(CommandResult.Empty(contentId, 13, 12));
var result = await ExecuteAsync(new ExecutionOptions { Query = query }, Permissions.AppContentsDeleteOwn); var result = await ExecuteAsync(new ExecutionOptions { Query = query }, PermissionIds.AppContentsDeleteOwn);
var expected = new var expected = new
{ {

2
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLTestBase.cs

@ -71,7 +71,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
if (permissionId != null) if (permissionId != null)
{ {
var permission = Permissions.ForApp(permissionId, TestApp.Default.Name, TestSchemas.DefaultId.Name).Id; var permission = PermissionIds.ForApp(permissionId, TestApp.Default.Name, TestSchemas.DefaultId.Name).Id;
context = new Context(Mocks.FrontendUser(permission: permission), TestApp.Default); context = new Context(Mocks.FrontendUser(permission: permission), TestApp.Default);
} }

8
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/ContentQueryServiceTests.cs

@ -273,7 +273,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
[Fact] [Fact]
public async Task Should_query_contents_from_user_if_user_has_only_own_permission() public async Task Should_query_contents_from_user_if_user_has_only_own_permission()
{ {
var requestContext = CreateContext(permissionId: Permissions.AppContentsReadOwn); var requestContext = CreateContext(permissionId: PermissionIds.AppContentsReadOwn);
await sut.QueryAsync(requestContext, schemaId.Name, Q.Empty, ct); await sut.QueryAsync(requestContext, schemaId.Name, Q.Empty, ct);
@ -286,7 +286,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
[Fact] [Fact]
public async Task Should_query_all_contents_if_user_has_read_permission() public async Task Should_query_all_contents_if_user_has_read_permission()
{ {
var requestContext = CreateContext(permissionId: Permissions.AppContentsRead); var requestContext = CreateContext(permissionId: PermissionIds.AppContentsRead);
await sut.QueryAsync(requestContext, schemaId.Name, Q.Empty, ct); await sut.QueryAsync(requestContext, schemaId.Name, Q.Empty, ct);
@ -311,7 +311,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
int isFrontend = 0, int isFrontend = 0,
int isUnpublished = 0, int isUnpublished = 0,
bool allowSchema = true, bool allowSchema = true,
string permissionId = Permissions.AppContentsRead) string permissionId = PermissionIds.AppContentsRead)
{ {
var claimsIdentity = new ClaimsIdentity(); var claimsIdentity = new ClaimsIdentity();
var claimsPrincipal = new ClaimsPrincipal(claimsIdentity); var claimsPrincipal = new ClaimsPrincipal(claimsIdentity);
@ -325,7 +325,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
if (allowSchema) if (allowSchema)
{ {
var concretePermission = Permissions.ForApp(permissionId, appId.Name, schemaId.Name).Id; var concretePermission = PermissionIds.ForApp(permissionId, appId.Name, schemaId.Name).Id;
claimsIdentity.AddClaim(new Claim(SquidexClaimTypes.Permissions, concretePermission)); claimsIdentity.AddClaim(new Claim(SquidexClaimTypes.Permissions, concretePermission));
} }

6
backend/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/SchemasSearchSourceTests.cs

@ -55,7 +55,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas
[Fact] [Fact]
public async Task Should_not_add_result_to_contents_if_schema_is_component() public async Task Should_not_add_result_to_contents_if_schema_is_component()
{ {
var permission = Permissions.ForApp(Permissions.AppContentsReadOwn, appId.Name, "schemaA1"); var permission = PermissionIds.ForApp(PermissionIds.AppContentsReadOwn, appId.Name, "schemaA1");
var ctx = ContextWithPermission(); var ctx = ContextWithPermission();
@ -77,7 +77,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas
[Fact] [Fact]
public async Task Should_return_result_to_schema_and_contents_if_matching_and_permission_given() public async Task Should_return_result_to_schema_and_contents_if_matching_and_permission_given()
{ {
var permission = Permissions.ForApp(Permissions.AppContentsReadOwn, appId.Name, "schemaA2"); var permission = PermissionIds.ForApp(PermissionIds.AppContentsReadOwn, appId.Name, "schemaA2");
var ctx = ContextWithPermission(permission.Id); var ctx = ContextWithPermission(permission.Id);
@ -109,7 +109,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas
[Fact] [Fact]
public async Task Should_return_result_to_schema_and_contents_if_schema_is_singleton() public async Task Should_return_result_to_schema_and_contents_if_schema_is_singleton()
{ {
var permission = Permissions.ForApp(Permissions.AppContentsReadOwn, appId.Name, "schemaA1"); var permission = PermissionIds.ForApp(PermissionIds.AppContentsReadOwn, appId.Name, "schemaA1");
var ctx = ContextWithPermission(permission.Id); var ctx = ContextWithPermission(permission.Id);

2
backend/tests/Squidex.Domain.Users.Tests/DefaultUserServiceTests.cs

@ -226,7 +226,7 @@ namespace Squidex.Domain.Users
await sut.CreateAsync(identity.Email, values); await sut.CreateAsync(identity.Email, values);
A.CallTo(() => userManager.AddClaimsAsync(identity, HasClaim(SquidexClaimTypes.Permissions, Permissions.Admin))) A.CallTo(() => userManager.AddClaimsAsync(identity, HasClaim(SquidexClaimTypes.Permissions, PermissionIds.Admin)))
.MustHaveHappened(); .MustHaveHappened();
} }

10
backend/tests/Squidex.Web.Tests/ApiPermissionAttributeTests.cs

@ -69,7 +69,7 @@ namespace Squidex.Web
SetContext(); SetContext();
var sut = new ApiPermissionAttribute(Permissions.AppSchemasCreate); var sut = new ApiPermissionAttribute(PermissionIds.AppSchemasCreate);
await sut.OnActionExecutionAsync(actionExecutingContext, next); await sut.OnActionExecutionAsync(actionExecutingContext, next);
@ -87,7 +87,7 @@ namespace Squidex.Web
SetContext(); SetContext();
var sut = new ApiPermissionAttribute(Permissions.AppSchemasUpdate); var sut = new ApiPermissionAttribute(PermissionIds.AppSchemasUpdate);
await sut.OnActionExecutionAsync(actionExecutingContext, next); await sut.OnActionExecutionAsync(actionExecutingContext, next);
@ -104,7 +104,7 @@ namespace Squidex.Web
SetContext(); SetContext();
var sut = new ApiPermissionAttribute(Permissions.AppSchemasCreate); var sut = new ApiPermissionAttribute(PermissionIds.AppSchemasCreate);
await sut.OnActionExecutionAsync(actionExecutingContext, next); await sut.OnActionExecutionAsync(actionExecutingContext, next);
@ -119,7 +119,7 @@ namespace Squidex.Web
SetContext(); SetContext();
var sut = new ApiPermissionAttribute(Permissions.AppSchemasCreate); var sut = new ApiPermissionAttribute(PermissionIds.AppSchemasCreate);
await sut.OnActionExecutionAsync(actionExecutingContext, next); await sut.OnActionExecutionAsync(actionExecutingContext, next);
@ -132,7 +132,7 @@ namespace Squidex.Web
{ {
SetContext(); SetContext();
var sut = new ApiPermissionAttribute(Permissions.AppSchemasCreate); var sut = new ApiPermissionAttribute(PermissionIds.AppSchemasCreate);
await sut.OnActionExecutionAsync(actionExecutingContext, next); await sut.OnActionExecutionAsync(actionExecutingContext, next);

2
backend/tests/Squidex.Web.Tests/Pipeline/ApiPermissionUnifierTests.cs

@ -28,7 +28,7 @@ namespace Squidex.Web.Pipeline
var result = await sut.TransformAsync(userPrincipal); var result = await sut.TransformAsync(userPrincipal);
Assert.Equal(Permissions.Admin, result.Claims.FirstOrDefault(x => x.Type == SquidexClaimTypes.Permissions)?.Value); Assert.Equal(PermissionIds.Admin, result.Claims.FirstOrDefault(x => x.Type == SquidexClaimTypes.Permissions)?.Value);
Assert.Equal(role, result.Claims.FirstOrDefault(x => x.Type == userIdentity.RoleClaimType)?.Value); Assert.Equal(role, result.Claims.FirstOrDefault(x => x.Type == userIdentity.RoleClaimType)?.Value);
} }

Loading…
Cancel
Save