Browse Source

Attributes improved

pull/65/head
Sebastian Stehle 9 years ago
parent
commit
c5f2dace51
  1. 16
      src/Squidex.Infrastructure.Redis/RedisPubSub.cs
  2. 5
      src/Squidex.Infrastructure/Singletons.cs
  3. 6
      src/Squidex/Config/Domain/PubSubModule.cs
  4. 2
      src/Squidex/Config/Web/WebModule.cs
  5. 6
      src/Squidex/Controllers/Api/Apps/AppClientsController.cs
  6. 6
      src/Squidex/Controllers/Api/Apps/AppContributorsController.cs
  7. 12
      src/Squidex/Controllers/Api/Apps/AppLanguagesController.cs
  8. 2
      src/Squidex/Controllers/Api/Assets/AssetContentController.cs
  9. 6
      src/Squidex/Controllers/Api/Assets/AssetsController.cs
  10. 4
      src/Squidex/Controllers/Api/EventConsumers/EventConsumersController.cs
  11. 2
      src/Squidex/Controllers/Api/History/HistoryController.cs
  12. 6
      src/Squidex/Controllers/Api/Ping/PingController.cs
  13. 6
      src/Squidex/Controllers/Api/Schemas/SchemaFieldsController.cs
  14. 6
      src/Squidex/Controllers/Api/Schemas/SchemasController.cs
  15. 12
      src/Squidex/Controllers/Api/Statistics/UsagesController.cs
  16. 4
      src/Squidex/Controllers/Api/Users/UserManagementController.cs
  17. 6
      src/Squidex/Controllers/ContentApi/ContentsController.cs
  18. 20
      src/Squidex/Pipeline/AppApiAttribute.cs
  19. 10
      src/Squidex/Pipeline/AppApiFilter.cs
  20. 21
      src/Squidex/Pipeline/MustBeAdministratorAttribute.cs
  21. 21
      src/Squidex/Pipeline/MustBeAppDeveloperAttribute.cs
  22. 21
      src/Squidex/Pipeline/MustBeAppEditorAttribute.cs
  23. 21
      src/Squidex/Pipeline/MustBeAppOwnerAttribute.cs

16
src/Squidex.Infrastructure.Redis/RedisPubSub.cs

@ -16,11 +16,11 @@ namespace Squidex.Infrastructure.Redis
public class RedisPubSub : IPubSub, IExternalSystem
{
private readonly ConcurrentDictionary<string, RedisSubscription> subscriptions = new ConcurrentDictionary<string, RedisSubscription>();
private readonly IConnectionMultiplexer redisClient;
private readonly Lazy<IConnectionMultiplexer> redisClient;
private readonly Lazy<ISubscriber> redisSubscriber;
private readonly ISemanticLog log;
private readonly ISubscriber redisSubscriber;
public RedisPubSub(IConnectionMultiplexer redis, ISemanticLog log)
public RedisPubSub(Lazy<IConnectionMultiplexer> 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<ISubscriber>(() => 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<string> 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);
}
}
}

5
src/Squidex.Infrastructure/Singletons.cs

@ -19,5 +19,10 @@ namespace Squidex.Infrastructure
{
return instances.GetOrAdd(key, factory);
}
public static Lazy<T> GetOrAddLazy(string key, Func<string, T> factory)
{
return new Lazy<T>(() => instances.GetOrAdd(key, factory));
}
}
}

6
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<IConnectionMultiplexer>.GetOrAdd(configuration, s => ConnectionMultiplexer.Connect(s)))
.Named<IConnectionMultiplexer>(RedisRegistration)
builder.Register(c => Singletons<IConnectionMultiplexer>.GetOrAddLazy(configuration, s => ConnectionMultiplexer.Connect(s)))
.Named<Lazy<IConnectionMultiplexer>>(RedisRegistration)
.SingleInstance();
builder.RegisterType<RedisPubSub>()
.WithParameter(ResolvedParameter.ForNamed<IConnectionMultiplexer>(RedisRegistration))
.WithParameter(ResolvedParameter.ForNamed<Lazy<IConnectionMultiplexer>>(RedisRegistration))
.As<IPubSub>()
.As<IExternalSystem>()
.SingleInstance();

2
src/Squidex/Config/Web/WebModule.cs

@ -25,7 +25,7 @@ namespace Squidex.Config.Web
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<AppFilterAttribute>()
builder.RegisterType<AppApiFilter>()
.AsSelf()
.SingleInstance();

6
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
/// <summary>
/// Manages and configures apps.
/// </summary>
[Authorize(Roles = SquidexRoles.AppOwner)]
[MustBeAppOwner]
[ApiExceptionFilter]
[ServiceFilter(typeof(AppFilterAttribute))]
[AppApi]
[SwaggerTag("Apps")]
public class AppClientsController : ControllerBase
{

6
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
/// <summary>
/// Manages and configures apps.
/// </summary>
[Authorize(Roles = SquidexRoles.AppOwner)]
[MustBeAppOwner]
[ApiExceptionFilter]
[ServiceFilter(typeof(AppFilterAttribute))]
[AppApi]
[SwaggerTag("Apps")]
public class AppContributorsController : ControllerBase
{

12
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.
/// </summary>
[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.
/// </returns>
[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.
/// </returns>
[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.
/// </returns>
[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.
/// </returns>
[Authorize(Roles = SquidexRoles.AppOwner)]
[MustBeAppOwner]
[HttpDelete]
[Route("apps/{app}/languages/{language}")]
[ApiCosts(1)]

2
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
{

6
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
/// <summary>
/// Uploads and retrieves assets.
/// </summary>
[Authorize(Roles = SquidexRoles.AppEditor)]
[MustBeAppEditor]
[ApiExceptionFilter]
[ServiceFilter(typeof(AppFilterAttribute))]
[AppApi]
[SwaggerTag("Assets")]
public class AssetsController : ControllerBase
{

4
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
{

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

@ -25,7 +25,7 @@ namespace Squidex.Controllers.Api.History
/// </summary>
[Authorize]
[ApiExceptionFilter]
[ServiceFilter(typeof(AppFilterAttribute))]
[AppApi]
[SwaggerTag("History")]
public class HistoryController : ControllerBase
{

6
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
/// <summary>
/// Makes a ping request.
/// </summary>
[Authorize(Roles = SquidexRoles.AppEditor)]
[MustBeAppEditor]
[ApiExceptionFilter]
[ServiceFilter(typeof(AppFilterAttribute))]
[AppApi]
[SwaggerTag("Ping")]
public class PingController : Controller
{

6
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
/// <summary>
/// Manages and retrieves information about schemas.
/// </summary>
[Authorize(Roles = SquidexRoles.AppDeveloper)]
[MustBeAppDeveloper]
[ApiExceptionFilter]
[ServiceFilter(typeof(AppFilterAttribute))]
[AppApi]
[SwaggerTag("Schemas")]
public class SchemaFieldsController : ControllerBase
{

6
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
/// <summary>
/// Manages and retrieves information about schemas.
/// </summary>
[Authorize(Roles = SquidexRoles.AppDeveloper)]
[MustBeAppDeveloper]
[ApiExceptionFilter]
[ServiceFilter(typeof(AppFilterAttribute))]
[AppApi]
[SwaggerTag("Schemas")]
public class SchemasController : ControllerBase
{

12
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.
/// </summary>
[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.
/// </returns>
[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.
/// </returns>
[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.
/// </returns>
[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.
/// </returns>
[Authorize(Roles = SquidexRoles.AppEditor)]
[MustBeAppEditor]
[HttpGet]
[Route("apps/{app}/usages/storage/{fromDate}/{toDate}")]
[ProducesResponseType(typeof(StorageUsageDto[]), 200)]

4
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
{

6
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
{

20
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))
{
}
}
}

10
src/Squidex/Pipeline/AppFilterAttribute.cs → 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;
}

21
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;
}
}
}

21
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}";
}
}
}

21
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}";
}
}
}

21
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}";
}
}
}
Loading…
Cancel
Save