diff --git a/src/Squidex.Infrastructure.Redis/RedisPubSub.cs b/src/Squidex.Infrastructure.Redis/RedisPubSub.cs index 310bc65b2..2488e6eba 100644 --- a/src/Squidex.Infrastructure.Redis/RedisPubSub.cs +++ b/src/Squidex.Infrastructure.Redis/RedisPubSub.cs @@ -16,11 +16,11 @@ namespace Squidex.Infrastructure.Redis public class RedisPubSub : IPubSub, IExternalSystem { private readonly ConcurrentDictionary subscriptions = new ConcurrentDictionary(); - private readonly IConnectionMultiplexer redisClient; + private readonly Lazy redisClient; + private readonly Lazy redisSubscriber; private readonly ISemanticLog log; - private readonly ISubscriber redisSubscriber; - public RedisPubSub(IConnectionMultiplexer redis, ISemanticLog log) + public RedisPubSub(Lazy redis, ISemanticLog log) { Guard.NotNull(redis, nameof(redis)); Guard.NotNull(log, nameof(log)); @@ -28,18 +28,18 @@ namespace Squidex.Infrastructure.Redis this.log = log; redisClient = redis; - redisSubscriber = redis.GetSubscriber(); + redisSubscriber = new Lazy(() => redis.Value.GetSubscriber()); } public void Connect() { try { - redisClient.GetStatus(); + redisClient.Value.GetStatus(); } catch (Exception ex) { - throw new ConfigurationException($"Redis connection failed to connect to database {redisClient.Configuration}", ex); + throw new ConfigurationException($"Redis connection failed to connect to database {redisClient.Value.Configuration}", ex); } } @@ -47,14 +47,14 @@ namespace Squidex.Infrastructure.Redis { Guard.NotNullOrEmpty(channelName, nameof(channelName)); - subscriptions.GetOrAdd(channelName, c => new RedisSubscription(redisSubscriber, c, log)).Publish(token, notifySelf); + subscriptions.GetOrAdd(channelName, c => new RedisSubscription(redisSubscriber.Value, c, log)).Publish(token, notifySelf); } public IDisposable Subscribe(string channelName, Action handler) { Guard.NotNullOrEmpty(channelName, nameof(channelName)); - return subscriptions.GetOrAdd(channelName, c => new RedisSubscription(redisSubscriber, c, log)).Subscribe(handler); + return subscriptions.GetOrAdd(channelName, c => new RedisSubscription(redisSubscriber.Value, c, log)).Subscribe(handler); } } } diff --git a/src/Squidex.Infrastructure/Singletons.cs b/src/Squidex.Infrastructure/Singletons.cs index b9b6fe9f0..ccbb781d9 100644 --- a/src/Squidex.Infrastructure/Singletons.cs +++ b/src/Squidex.Infrastructure/Singletons.cs @@ -19,5 +19,10 @@ namespace Squidex.Infrastructure { return instances.GetOrAdd(key, factory); } + + public static Lazy GetOrAddLazy(string key, Func factory) + { + return new Lazy(() => instances.GetOrAdd(key, factory)); + } } } diff --git a/src/Squidex/Config/Domain/PubSubModule.cs b/src/Squidex/Config/Domain/PubSubModule.cs index ca6195448..6e3615b09 100644 --- a/src/Squidex/Config/Domain/PubSubModule.cs +++ b/src/Squidex/Config/Domain/PubSubModule.cs @@ -45,12 +45,12 @@ namespace Squidex.Config.Domain throw new ConfigurationException("Configure PubSub Redis configuration with 'pubSub:redis:configuration'."); } - builder.Register(c => Singletons.GetOrAdd(configuration, s => ConnectionMultiplexer.Connect(s))) - .Named(RedisRegistration) + builder.Register(c => Singletons.GetOrAddLazy(configuration, s => ConnectionMultiplexer.Connect(s))) + .Named>(RedisRegistration) .SingleInstance(); builder.RegisterType() - .WithParameter(ResolvedParameter.ForNamed(RedisRegistration)) + .WithParameter(ResolvedParameter.ForNamed>(RedisRegistration)) .As() .As() .SingleInstance(); diff --git a/src/Squidex/Config/Web/WebModule.cs b/src/Squidex/Config/Web/WebModule.cs index 25ed74696..5e51cd6b9 100644 --- a/src/Squidex/Config/Web/WebModule.cs +++ b/src/Squidex/Config/Web/WebModule.cs @@ -25,7 +25,7 @@ namespace Squidex.Config.Web protected override void Load(ContainerBuilder builder) { - builder.RegisterType() + builder.RegisterType() .AsSelf() .SingleInstance(); diff --git a/src/Squidex/Controllers/Api/Apps/AppClientsController.cs b/src/Squidex/Controllers/Api/Apps/AppClientsController.cs index b9f04e324..c74ec0792 100644 --- a/src/Squidex/Controllers/Api/Apps/AppClientsController.cs +++ b/src/Squidex/Controllers/Api/Apps/AppClientsController.cs @@ -8,12 +8,10 @@ using System.Linq; using System.Threading.Tasks; -using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Primitives; using NSwag.Annotations; using Squidex.Controllers.Api.Apps.Models; -using Squidex.Core.Identity; using Squidex.Infrastructure.CQRS.Commands; using Squidex.Infrastructure.Reflection; using Squidex.Pipeline; @@ -26,9 +24,9 @@ namespace Squidex.Controllers.Api.Apps /// /// Manages and configures apps. /// - [Authorize(Roles = SquidexRoles.AppOwner)] + [MustBeAppOwner] [ApiExceptionFilter] - [ServiceFilter(typeof(AppFilterAttribute))] + [AppApi] [SwaggerTag("Apps")] public class AppClientsController : ControllerBase { diff --git a/src/Squidex/Controllers/Api/Apps/AppContributorsController.cs b/src/Squidex/Controllers/Api/Apps/AppContributorsController.cs index 7b4b2fa1e..5af3da83f 100644 --- a/src/Squidex/Controllers/Api/Apps/AppContributorsController.cs +++ b/src/Squidex/Controllers/Api/Apps/AppContributorsController.cs @@ -8,14 +8,12 @@ using System.Linq; using System.Threading.Tasks; -using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Primitives; using NSwag.Annotations; using Squidex.Infrastructure.CQRS.Commands; using Squidex.Infrastructure.Reflection; using Squidex.Controllers.Api.Apps.Models; -using Squidex.Core.Identity; using Squidex.Pipeline; using Squidex.Read.Apps.Services; using Squidex.Write.Apps.Commands; @@ -25,9 +23,9 @@ namespace Squidex.Controllers.Api.Apps /// /// Manages and configures apps. /// - [Authorize(Roles = SquidexRoles.AppOwner)] + [MustBeAppOwner] [ApiExceptionFilter] - [ServiceFilter(typeof(AppFilterAttribute))] + [AppApi] [SwaggerTag("Apps")] public class AppContributorsController : ControllerBase { diff --git a/src/Squidex/Controllers/Api/Apps/AppLanguagesController.cs b/src/Squidex/Controllers/Api/Apps/AppLanguagesController.cs index fe3d92d56..f235623c9 100644 --- a/src/Squidex/Controllers/Api/Apps/AppLanguagesController.cs +++ b/src/Squidex/Controllers/Api/Apps/AppLanguagesController.cs @@ -10,7 +10,6 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Primitives; using NSwag.Annotations; @@ -18,7 +17,6 @@ using Squidex.Infrastructure.CQRS.Commands; using Squidex.Infrastructure.Reflection; using Squidex.Controllers.Api.Apps.Models; using Squidex.Core; -using Squidex.Core.Identity; using Squidex.Infrastructure; using Squidex.Pipeline; using Squidex.Read.Apps.Services; @@ -30,7 +28,7 @@ namespace Squidex.Controllers.Api.Apps /// Manages and configures apps. /// [ApiExceptionFilter] - [ServiceFilter(typeof(AppFilterAttribute))] + [AppApi] [SwaggerTag("Apps")] public class AppLanguagesController : ControllerBase { @@ -50,7 +48,7 @@ namespace Squidex.Controllers.Api.Apps /// 200 => Language configuration returned. /// 404 => App not found. /// - [Authorize(Roles = SquidexRoles.AppEditor)] + [MustBeAppEditor] [HttpGet] [Route("apps/{app}/languages/")] [ProducesResponseType(typeof(LanguageDto[]), 200)] @@ -87,7 +85,7 @@ namespace Squidex.Controllers.Api.Apps /// 400 => Language is an invalid language. /// 404 => App not found. /// - [Authorize(Roles = SquidexRoles.AppOwner)] + [MustBeAppOwner] [HttpPost] [Route("apps/{app}/languages/")] [ProducesResponseType(typeof(AppLanguageDto), 201)] @@ -113,7 +111,7 @@ namespace Squidex.Controllers.Api.Apps /// 400 => Language is an invalid language. /// 404 => App not found. /// - [Authorize(Roles = SquidexRoles.AppOwner)] + [MustBeAppOwner] [HttpPut] [Route("apps/{app}/languages/{language}")] [ApiCosts(1)] @@ -134,7 +132,7 @@ namespace Squidex.Controllers.Api.Apps /// 400 => Language is an invalid language. /// 404 => App not found. /// - [Authorize(Roles = SquidexRoles.AppOwner)] + [MustBeAppOwner] [HttpDelete] [Route("apps/{app}/languages/{language}")] [ApiCosts(1)] diff --git a/src/Squidex/Controllers/Api/Assets/AssetContentController.cs b/src/Squidex/Controllers/Api/Assets/AssetContentController.cs index d8ac35e3e..97fd43757 100644 --- a/src/Squidex/Controllers/Api/Assets/AssetContentController.cs +++ b/src/Squidex/Controllers/Api/Assets/AssetContentController.cs @@ -21,7 +21,7 @@ using Squidex.Read.Assets.Repositories; namespace Squidex.Controllers.Api.Assets { [ApiExceptionFilter] - [ServiceFilter(typeof(AppFilterAttribute))] + [AppApi] [SwaggerIgnore] public class AssetContentController : ControllerBase { diff --git a/src/Squidex/Controllers/Api/Assets/AssetsController.cs b/src/Squidex/Controllers/Api/Assets/AssetsController.cs index 6353a4134..46eeeb035 100644 --- a/src/Squidex/Controllers/Api/Assets/AssetsController.cs +++ b/src/Squidex/Controllers/Api/Assets/AssetsController.cs @@ -10,14 +10,12 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; using Microsoft.Extensions.Primitives; using NSwag.Annotations; using Squidex.Controllers.Api.Assets.Models; -using Squidex.Core.Identity; using Squidex.Infrastructure; using Squidex.Infrastructure.Assets; using Squidex.Infrastructure.CQRS.Commands; @@ -31,9 +29,9 @@ namespace Squidex.Controllers.Api.Assets /// /// Uploads and retrieves assets. /// - [Authorize(Roles = SquidexRoles.AppEditor)] + [MustBeAppEditor] [ApiExceptionFilter] - [ServiceFilter(typeof(AppFilterAttribute))] + [AppApi] [SwaggerTag("Assets")] public class AssetsController : ControllerBase { diff --git a/src/Squidex/Controllers/Api/EventConsumers/EventConsumersController.cs b/src/Squidex/Controllers/Api/EventConsumers/EventConsumersController.cs index 7dca968e0..6364b2d16 100644 --- a/src/Squidex/Controllers/Api/EventConsumers/EventConsumersController.cs +++ b/src/Squidex/Controllers/Api/EventConsumers/EventConsumersController.cs @@ -8,19 +8,17 @@ using System.Linq; using System.Threading.Tasks; -using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using NSwag.Annotations; using Squidex.Controllers.Api.EventConsumers.Models; -using Squidex.Core.Identity; using Squidex.Infrastructure.CQRS.Events; using Squidex.Infrastructure.Reflection; using Squidex.Pipeline; namespace Squidex.Controllers.Api.EventConsumers { + [MustBeAdministrator] [ApiExceptionFilter] - [Authorize(Roles = SquidexRoles.Administrator)] [SwaggerIgnore] public sealed class EventConsumersController : Controller { diff --git a/src/Squidex/Controllers/Api/History/HistoryController.cs b/src/Squidex/Controllers/Api/History/HistoryController.cs index e3c527ef3..05de112a4 100644 --- a/src/Squidex/Controllers/Api/History/HistoryController.cs +++ b/src/Squidex/Controllers/Api/History/HistoryController.cs @@ -25,7 +25,7 @@ namespace Squidex.Controllers.Api.History /// [Authorize] [ApiExceptionFilter] - [ServiceFilter(typeof(AppFilterAttribute))] + [AppApi] [SwaggerTag("History")] public class HistoryController : ControllerBase { diff --git a/src/Squidex/Controllers/Api/Ping/PingController.cs b/src/Squidex/Controllers/Api/Ping/PingController.cs index cf1417be3..eb82e6781 100644 --- a/src/Squidex/Controllers/Api/Ping/PingController.cs +++ b/src/Squidex/Controllers/Api/Ping/PingController.cs @@ -6,10 +6,8 @@ // All rights reserved. // ========================================================================== -using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using NSwag.Annotations; -using Squidex.Core.Identity; using Squidex.Pipeline; namespace Squidex.Controllers.Api.Ping @@ -17,9 +15,9 @@ namespace Squidex.Controllers.Api.Ping /// /// Makes a ping request. /// - [Authorize(Roles = SquidexRoles.AppEditor)] + [MustBeAppEditor] [ApiExceptionFilter] - [ServiceFilter(typeof(AppFilterAttribute))] + [AppApi] [SwaggerTag("Ping")] public class PingController : Controller { diff --git a/src/Squidex/Controllers/Api/Schemas/SchemaFieldsController.cs b/src/Squidex/Controllers/Api/Schemas/SchemaFieldsController.cs index 8a4d3426b..48fcea1c4 100644 --- a/src/Squidex/Controllers/Api/Schemas/SchemaFieldsController.cs +++ b/src/Squidex/Controllers/Api/Schemas/SchemaFieldsController.cs @@ -7,12 +7,10 @@ // ========================================================================== using System.Threading.Tasks; -using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using NSwag.Annotations; using Squidex.Infrastructure.CQRS.Commands; using Squidex.Controllers.Api.Schemas.Models; -using Squidex.Core.Identity; using Squidex.Pipeline; using Squidex.Write.Schemas.Commands; @@ -21,9 +19,9 @@ namespace Squidex.Controllers.Api.Schemas /// /// Manages and retrieves information about schemas. /// - [Authorize(Roles = SquidexRoles.AppDeveloper)] + [MustBeAppDeveloper] [ApiExceptionFilter] - [ServiceFilter(typeof(AppFilterAttribute))] + [AppApi] [SwaggerTag("Schemas")] public class SchemaFieldsController : ControllerBase { diff --git a/src/Squidex/Controllers/Api/Schemas/SchemasController.cs b/src/Squidex/Controllers/Api/Schemas/SchemasController.cs index 38b462865..381b74062 100644 --- a/src/Squidex/Controllers/Api/Schemas/SchemasController.cs +++ b/src/Squidex/Controllers/Api/Schemas/SchemasController.cs @@ -8,7 +8,6 @@ using System.Linq; using System.Threading.Tasks; -using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Primitives; using NSwag.Annotations; @@ -16,7 +15,6 @@ using Squidex.Infrastructure.CQRS.Commands; using Squidex.Infrastructure.Reflection; using Squidex.Controllers.Api.Schemas.Models; using Squidex.Controllers.Api.Schemas.Models.Converters; -using Squidex.Core.Identity; using Squidex.Core.Schemas; using Squidex.Pipeline; using Squidex.Read.Schemas.Repositories; @@ -27,9 +25,9 @@ namespace Squidex.Controllers.Api.Schemas /// /// Manages and retrieves information about schemas. /// - [Authorize(Roles = SquidexRoles.AppDeveloper)] + [MustBeAppDeveloper] [ApiExceptionFilter] - [ServiceFilter(typeof(AppFilterAttribute))] + [AppApi] [SwaggerTag("Schemas")] public class SchemasController : ControllerBase { diff --git a/src/Squidex/Controllers/Api/Statistics/UsagesController.cs b/src/Squidex/Controllers/Api/Statistics/UsagesController.cs index bf988abf0..fa69f5743 100644 --- a/src/Squidex/Controllers/Api/Statistics/UsagesController.cs +++ b/src/Squidex/Controllers/Api/Statistics/UsagesController.cs @@ -9,11 +9,9 @@ using System; using System.Linq; using System.Threading.Tasks; -using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using NSwag.Annotations; using Squidex.Controllers.Api.Statistics.Models; -using Squidex.Core.Identity; using Squidex.Infrastructure.CQRS.Commands; using Squidex.Infrastructure.UsageTracking; using Squidex.Pipeline; @@ -25,7 +23,7 @@ namespace Squidex.Controllers.Api.Statistics /// Retrieves usage information for apps. /// [ApiExceptionFilter] - [ServiceFilter(typeof(AppFilterAttribute))] + [AppApi] [SwaggerTag("Statistics")] public class UsagesController : ControllerBase { @@ -48,7 +46,7 @@ namespace Squidex.Controllers.Api.Statistics /// 200 => Usage tracking results returned. /// 404 => App not found. /// - [Authorize(Roles = SquidexRoles.AppEditor)] + [MustBeAppEditor] [HttpGet] [Route("apps/{app}/usages/calls/month")] [ProducesResponseType(typeof(CurrentCallsDto), 200)] @@ -71,7 +69,7 @@ namespace Squidex.Controllers.Api.Statistics /// 404 => App not found. /// 400 => Range between from date and to date is not valid or has more than 100 days. /// - [Authorize(Roles = SquidexRoles.AppEditor)] + [MustBeAppEditor] [HttpGet] [Route("apps/{app}/usages/calls/{fromDate}/{toDate}")] [ProducesResponseType(typeof(CallsUsageDto[]), 200)] @@ -103,7 +101,7 @@ namespace Squidex.Controllers.Api.Statistics /// 200 => Storage usage returned. /// 404 => App not found. /// - [Authorize(Roles = SquidexRoles.AppEditor)] + [MustBeAppEditor] [HttpGet] [Route("apps/{app}/usages/storage/today")] [ProducesResponseType(typeof(CurrentStorageDto), 200)] @@ -126,7 +124,7 @@ namespace Squidex.Controllers.Api.Statistics /// 404 => App not found. /// 400 => Range between from date and to date is not valid or has more than 100 days. /// - [Authorize(Roles = SquidexRoles.AppEditor)] + [MustBeAppEditor] [HttpGet] [Route("apps/{app}/usages/storage/{fromDate}/{toDate}")] [ProducesResponseType(typeof(StorageUsageDto[]), 200)] diff --git a/src/Squidex/Controllers/Api/Users/UserManagementController.cs b/src/Squidex/Controllers/Api/Users/UserManagementController.cs index f7e1a6399..abfb2ec0a 100644 --- a/src/Squidex/Controllers/Api/Users/UserManagementController.cs +++ b/src/Squidex/Controllers/Api/Users/UserManagementController.cs @@ -9,11 +9,9 @@ using System; using System.Linq; using System.Threading.Tasks; -using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using NSwag.Annotations; using Squidex.Controllers.Api.Users.Models; -using Squidex.Core.Identity; using Squidex.Infrastructure; using Squidex.Infrastructure.Reflection; using Squidex.Infrastructure.Security; @@ -22,8 +20,8 @@ using Squidex.Read.Users.Repositories; namespace Squidex.Controllers.Api.Users { + [MustBeAdministrator] [ApiExceptionFilter] - [Authorize(Roles = SquidexRoles.Administrator)] [SwaggerIgnore] public class UserManagementController : Controller { diff --git a/src/Squidex/Controllers/ContentApi/ContentsController.cs b/src/Squidex/Controllers/ContentApi/ContentsController.cs index 1733da6ee..b960ae10c 100644 --- a/src/Squidex/Controllers/ContentApi/ContentsController.cs +++ b/src/Squidex/Controllers/ContentApi/ContentsController.cs @@ -9,13 +9,11 @@ using System; using System.Linq; using System.Threading.Tasks; -using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Primitives; using NSwag.Annotations; using Squidex.Controllers.ContentApi.Models; using Squidex.Core.Contents; -using Squidex.Core.Identity; using Squidex.Infrastructure.CQRS.Commands; using Squidex.Infrastructure.Reflection; using Squidex.Pipeline; @@ -25,9 +23,9 @@ using Squidex.Write.Contents.Commands; namespace Squidex.Controllers.ContentApi { - [Authorize(Roles = SquidexRoles.AppEditor)] + [MustBeAppEditor] [ApiExceptionFilter] - [ServiceFilter(typeof(AppFilterAttribute))] + [AppApi] [SwaggerIgnore] public class ContentsController : ControllerBase { diff --git a/src/Squidex/Pipeline/AppApiAttribute.cs b/src/Squidex/Pipeline/AppApiAttribute.cs new file mode 100644 index 000000000..d0e6fff8a --- /dev/null +++ b/src/Squidex/Pipeline/AppApiAttribute.cs @@ -0,0 +1,20 @@ +// ========================================================================== +// AppApiAttribute.cs +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex Group +// All rights reserved. +// ========================================================================== + +using Microsoft.AspNetCore.Mvc; + +namespace Squidex.Pipeline +{ + public sealed class AppApiAttribute : ServiceFilterAttribute + { + public AppApiAttribute() + : base(typeof(AppApiFilter)) + { + } + } +} diff --git a/src/Squidex/Pipeline/AppFilterAttribute.cs b/src/Squidex/Pipeline/AppApiFilter.cs similarity index 86% rename from src/Squidex/Pipeline/AppFilterAttribute.cs rename to src/Squidex/Pipeline/AppApiFilter.cs index 9c41678cd..4ea63a1dc 100644 --- a/src/Squidex/Pipeline/AppFilterAttribute.cs +++ b/src/Squidex/Pipeline/AppApiFilter.cs @@ -22,12 +22,11 @@ using Squidex.Read.Apps.Services; namespace Squidex.Pipeline { - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] - public sealed class AppFilterAttribute : Attribute, IAsyncAuthorizationFilter + public sealed class AppApiFilter : IAsyncAuthorizationFilter { private readonly IAppProvider appProvider; - public AppFilterAttribute(IAppProvider appProvider) + public AppApiFilter(IAppProvider appProvider) { this.appProvider = appProvider; } @@ -64,15 +63,12 @@ namespace Squidex.Pipeline { case PermissionLevel.Owner: defaultIdentity.AddClaim(new Claim(defaultIdentity.RoleClaimType, SquidexRoles.AppOwner)); - defaultIdentity.AddClaim(new Claim(defaultIdentity.RoleClaimType, SquidexRoles.AppDeveloper)); - defaultIdentity.AddClaim(new Claim(defaultIdentity.RoleClaimType, SquidexRoles.AppEditor)); break; case PermissionLevel.Editor: - defaultIdentity.AddClaim(new Claim(defaultIdentity.RoleClaimType, SquidexRoles.AppDeveloper)); defaultIdentity.AddClaim(new Claim(defaultIdentity.RoleClaimType, SquidexRoles.AppEditor)); break; case PermissionLevel.Developer: - defaultIdentity.AddClaim(new Claim(defaultIdentity.RoleClaimType, SquidexRoles.AppEditor)); + defaultIdentity.AddClaim(new Claim(defaultIdentity.RoleClaimType, SquidexRoles.AppDeveloper)); break; } diff --git a/src/Squidex/Pipeline/MustBeAdministratorAttribute.cs b/src/Squidex/Pipeline/MustBeAdministratorAttribute.cs new file mode 100644 index 000000000..a57a57956 --- /dev/null +++ b/src/Squidex/Pipeline/MustBeAdministratorAttribute.cs @@ -0,0 +1,21 @@ +// ========================================================================== +// MustBeAdministratorAttribute.cs +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex Group +// All rights reserved. +// ========================================================================== + +using Microsoft.AspNetCore.Authorization; +using Squidex.Core.Identity; + +namespace Squidex.Pipeline +{ + public sealed class MustBeAdministratorAttribute : AuthorizeAttribute + { + public MustBeAdministratorAttribute() + { + Roles = SquidexRoles.Administrator; + } + } +} diff --git a/src/Squidex/Pipeline/MustBeAppDeveloperAttribute.cs b/src/Squidex/Pipeline/MustBeAppDeveloperAttribute.cs new file mode 100644 index 000000000..b61a5a379 --- /dev/null +++ b/src/Squidex/Pipeline/MustBeAppDeveloperAttribute.cs @@ -0,0 +1,21 @@ +// ========================================================================== +// MustBeAppDeveloperAttribute.cs +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex Group +// All rights reserved. +// ========================================================================== + +using Microsoft.AspNetCore.Authorization; +using Squidex.Core.Identity; + +namespace Squidex.Pipeline +{ + public sealed class MustBeAppDeveloperAttribute : AuthorizeAttribute + { + public MustBeAppDeveloperAttribute() + { + Roles = $"{SquidexRoles.AppOwner},{SquidexRoles.AppDeveloper}"; + } + } +} diff --git a/src/Squidex/Pipeline/MustBeAppEditorAttribute.cs b/src/Squidex/Pipeline/MustBeAppEditorAttribute.cs new file mode 100644 index 000000000..3496825e1 --- /dev/null +++ b/src/Squidex/Pipeline/MustBeAppEditorAttribute.cs @@ -0,0 +1,21 @@ +// ========================================================================== +// MustBeAppEditorAttribute.cs +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex Group +// All rights reserved. +// ========================================================================== + +using Microsoft.AspNetCore.Authorization; +using Squidex.Core.Identity; + +namespace Squidex.Pipeline +{ + public sealed class MustBeAppEditorAttribute : AuthorizeAttribute + { + public MustBeAppEditorAttribute() + { + Roles = $"{SquidexRoles.AppOwner},{SquidexRoles.AppDeveloper},{SquidexRoles.AppEditor}"; + } + } +} diff --git a/src/Squidex/Pipeline/MustBeAppOwnerAttribute.cs b/src/Squidex/Pipeline/MustBeAppOwnerAttribute.cs new file mode 100644 index 000000000..881862816 --- /dev/null +++ b/src/Squidex/Pipeline/MustBeAppOwnerAttribute.cs @@ -0,0 +1,21 @@ +// ========================================================================== +// MustBeAppOwnerAttribute.cs +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex Group +// All rights reserved. +// ========================================================================== + +using Microsoft.AspNetCore.Authorization; +using Squidex.Core.Identity; + +namespace Squidex.Pipeline +{ + public sealed class MustBeAppOwnerAttribute : AuthorizeAttribute + { + public MustBeAppOwnerAttribute() + { + Roles = $"{SquidexRoles.AppOwner}"; + } + } +}