From 4becb09a480ad2592abc0d5846f7d6621622759c Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Fri, 1 Sep 2017 12:40:41 +0200 Subject: [PATCH 1/3] UI controller. --- src/Squidex/Config/MyUIOptions.cs | 17 ++++++ .../Api/Apps/AppClientsController.cs | 2 +- .../Api/Apps/AppContributorsController.cs | 2 +- .../Api/Apps/AppLanguagesController.cs | 2 +- .../Controllers/Api/Apps/AppsController.cs | 2 +- .../Api/Apps/Models/AddAppLanguageDto.cs | 2 +- .../Api/Apps/Models/AppLanguageDto.cs | 2 +- .../Controllers/Api/Apps/Models/ClientDto.cs | 2 +- .../Api/Apps/Models/ContributorsDto.cs | 2 +- .../Api/Apps/Models/UpdateAppClientDto.cs | 2 +- .../Api/Apps/Models/UpdateAppLanguageDto.cs | 2 +- .../Api/Assets/AssetContentController.cs | 2 +- .../Api/Assets/AssetsController.cs | 2 +- .../Api/Assets/Models/AssetUpdateDto.cs | 2 +- .../Controllers/Api/EntityCreatedDto.cs | 2 +- .../Api/History/HistoryController.cs | 2 +- .../Api/History/Models/HistoryEventDto.cs | 2 +- src/Squidex/Controllers/Api/LanguageDto.cs | 2 +- .../Api/Languages/LanguagesController.cs | 2 +- .../Controllers/Api/Ping/PingController.cs | 2 +- .../Api/Plans/AppPlansController.cs | 2 +- .../Api/Plans/Models/AppPlansDto.cs | 2 +- .../Api/Plans/Models/ChangePlanDto.cs | 2 +- .../Api/Plans/Models/PlanChangedDto.cs | 2 +- .../Controllers/Api/Plans/Models/PlanDto.cs | 2 +- .../Api/Schemas/Models/ReorderFieldsDto.cs | 2 +- .../Api/Schemas/Models/SchemaDto.cs | 2 +- .../Api/Schemas/Models/SchemaPropertiesDto.cs | 2 +- .../Api/Schemas/Models/UpdateFieldDto.cs | 2 +- .../Api/Schemas/Models/UpdateSchemaDto.cs | 2 +- .../Api/Schemas/SchemaFieldsController.cs | 2 +- .../Api/Schemas/SchemasController.cs | 2 +- .../Api/Statistics/Models/CallsUsageDto.cs | 2 +- .../Api/Statistics/Models/CurrentCallsDto.cs | 2 +- .../Statistics/Models/CurrentStorageDto.cs | 2 +- .../Api/Statistics/Models/StorageUsageDto.cs | 2 +- .../Api/Statistics/UsagesController.cs | 2 +- .../Api/UI/Models/UIRegexSuggestionDto.cs | 27 +++++++++ .../Api/UI/Models/UISettingsDto.cs | 22 +++++++ .../Controllers/Api/UI/UIController.cs | 57 +++++++++++++++++++ .../Api/Users/Models/UserCreatedDto.cs | 2 +- .../Controllers/Api/Users/Models/UsersDto.cs | 2 +- .../Api/Users/UserManagementController.cs | 2 +- .../Controllers/Api/Users/UsersController.cs | 2 +- .../Api/Webhooks/Models/CreateWebhookDto.cs | 2 +- .../Api/Webhooks/Models/UpdateWebhookDto.cs | 2 +- .../Api/Webhooks/Models/WebhookCreatedDto.cs | 2 +- .../Api/Webhooks/Models/WebhookDto.cs | 2 +- .../Api/Webhooks/Models/WebhookEventDto.cs | 2 +- .../Api/Webhooks/Models/WebhookEventsDto.cs | 2 +- .../Api/Webhooks/Models/WebhookSchemaDto.cs | 2 +- .../Api/Webhooks/WebhooksController.cs | 2 +- .../ContentApi/ContentSwaggerController.cs | 2 +- .../ContentApi/ContentsController.cs | 2 +- .../ContentApi/Models/ContentsDto.cs | 2 +- .../Controllers/UI/Error/ErrorController.cs | 2 +- .../UI/Profile/PortalController.cs | 2 +- .../UI/Profile/ProfileController.cs | 2 +- src/Squidex/Startup.cs | 2 + src/Squidex/appsettings.json | 9 +++ 60 files changed, 188 insertions(+), 54 deletions(-) create mode 100644 src/Squidex/Config/MyUIOptions.cs create mode 100644 src/Squidex/Controllers/Api/UI/Models/UIRegexSuggestionDto.cs create mode 100644 src/Squidex/Controllers/Api/UI/Models/UISettingsDto.cs create mode 100644 src/Squidex/Controllers/Api/UI/UIController.cs diff --git a/src/Squidex/Config/MyUIOptions.cs b/src/Squidex/Config/MyUIOptions.cs new file mode 100644 index 000000000..f95e5c24b --- /dev/null +++ b/src/Squidex/Config/MyUIOptions.cs @@ -0,0 +1,17 @@ +// ========================================================================== +// MyUIOptions.cs +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex Group +// All rights reserved. +// ========================================================================== + +using System.Collections.Generic; + +namespace Squidex.Config +{ + public sealed class MyUIOptions + { + public Dictionary RegexSuggestions { get; set; } + } +} diff --git a/src/Squidex/Controllers/Api/Apps/AppClientsController.cs b/src/Squidex/Controllers/Api/Apps/AppClientsController.cs index d80d78453..98364fc35 100644 --- a/src/Squidex/Controllers/Api/Apps/AppClientsController.cs +++ b/src/Squidex/Controllers/Api/Apps/AppClientsController.cs @@ -26,7 +26,7 @@ namespace Squidex.Controllers.Api.Apps [ApiExceptionFilter] [AppApi] [SwaggerTag("Apps")] - public class AppClientsController : ControllerBase + public sealed class AppClientsController : ControllerBase { public AppClientsController(ICommandBus commandBus) : base(commandBus) diff --git a/src/Squidex/Controllers/Api/Apps/AppContributorsController.cs b/src/Squidex/Controllers/Api/Apps/AppContributorsController.cs index 7dd87c4ba..e7c1251b8 100644 --- a/src/Squidex/Controllers/Api/Apps/AppContributorsController.cs +++ b/src/Squidex/Controllers/Api/Apps/AppContributorsController.cs @@ -27,7 +27,7 @@ namespace Squidex.Controllers.Api.Apps [ApiExceptionFilter] [AppApi] [SwaggerTag("Apps")] - public class AppContributorsController : ControllerBase + public sealed class AppContributorsController : ControllerBase { private readonly IAppPlansProvider appPlansProvider; diff --git a/src/Squidex/Controllers/Api/Apps/AppLanguagesController.cs b/src/Squidex/Controllers/Api/Apps/AppLanguagesController.cs index 379c3af78..86c5b7d01 100644 --- a/src/Squidex/Controllers/Api/Apps/AppLanguagesController.cs +++ b/src/Squidex/Controllers/Api/Apps/AppLanguagesController.cs @@ -29,7 +29,7 @@ namespace Squidex.Controllers.Api.Apps [ApiExceptionFilter] [AppApi] [SwaggerTag("Apps")] - public class AppLanguagesController : ControllerBase + public sealed class AppLanguagesController : ControllerBase { public AppLanguagesController(ICommandBus commandBus) : base(commandBus) diff --git a/src/Squidex/Controllers/Api/Apps/AppsController.cs b/src/Squidex/Controllers/Api/Apps/AppsController.cs index 517a40700..5fdf1c88c 100644 --- a/src/Squidex/Controllers/Api/Apps/AppsController.cs +++ b/src/Squidex/Controllers/Api/Apps/AppsController.cs @@ -28,7 +28,7 @@ namespace Squidex.Controllers.Api.Apps [Authorize] [ApiExceptionFilter] [SwaggerTag("Apps")] - public class AppsController : ControllerBase + public sealed class AppsController : ControllerBase { private readonly IAppRepository appRepository; diff --git a/src/Squidex/Controllers/Api/Apps/Models/AddAppLanguageDto.cs b/src/Squidex/Controllers/Api/Apps/Models/AddAppLanguageDto.cs index 60f59a825..d604c8aac 100644 --- a/src/Squidex/Controllers/Api/Apps/Models/AddAppLanguageDto.cs +++ b/src/Squidex/Controllers/Api/Apps/Models/AddAppLanguageDto.cs @@ -11,7 +11,7 @@ using Squidex.Infrastructure; namespace Squidex.Controllers.Api.Apps.Models { - public class AddAppLanguageDto + public sealed class AddAppLanguageDto { /// /// The language to add. diff --git a/src/Squidex/Controllers/Api/Apps/Models/AppLanguageDto.cs b/src/Squidex/Controllers/Api/Apps/Models/AppLanguageDto.cs index b194cd01b..40ff4771c 100644 --- a/src/Squidex/Controllers/Api/Apps/Models/AppLanguageDto.cs +++ b/src/Squidex/Controllers/Api/Apps/Models/AppLanguageDto.cs @@ -12,7 +12,7 @@ using Squidex.Infrastructure; namespace Squidex.Controllers.Api.Apps.Models { - public class AppLanguageDto + public sealed class AppLanguageDto { /// /// The iso code of the language. diff --git a/src/Squidex/Controllers/Api/Apps/Models/ClientDto.cs b/src/Squidex/Controllers/Api/Apps/Models/ClientDto.cs index 6fe81cf72..efe437699 100644 --- a/src/Squidex/Controllers/Api/Apps/Models/ClientDto.cs +++ b/src/Squidex/Controllers/Api/Apps/Models/ClientDto.cs @@ -10,7 +10,7 @@ using System.ComponentModel.DataAnnotations; namespace Squidex.Controllers.Api.Apps.Models { - public class ClientDto + public sealed class ClientDto { /// /// The client id. diff --git a/src/Squidex/Controllers/Api/Apps/Models/ContributorsDto.cs b/src/Squidex/Controllers/Api/Apps/Models/ContributorsDto.cs index 96769079b..cd542674b 100644 --- a/src/Squidex/Controllers/Api/Apps/Models/ContributorsDto.cs +++ b/src/Squidex/Controllers/Api/Apps/Models/ContributorsDto.cs @@ -10,7 +10,7 @@ using System.ComponentModel.DataAnnotations; namespace Squidex.Controllers.Api.Apps.Models { - public class ContributorsDto + public sealed class ContributorsDto { /// /// The contributors. diff --git a/src/Squidex/Controllers/Api/Apps/Models/UpdateAppClientDto.cs b/src/Squidex/Controllers/Api/Apps/Models/UpdateAppClientDto.cs index 3eb7cee0e..13d20bf25 100644 --- a/src/Squidex/Controllers/Api/Apps/Models/UpdateAppClientDto.cs +++ b/src/Squidex/Controllers/Api/Apps/Models/UpdateAppClientDto.cs @@ -10,7 +10,7 @@ using System.ComponentModel.DataAnnotations; namespace Squidex.Controllers.Api.Apps.Models { - public class UpdateAppClientDto + public sealed class UpdateAppClientDto { /// /// The new display name of the client. diff --git a/src/Squidex/Controllers/Api/Apps/Models/UpdateAppLanguageDto.cs b/src/Squidex/Controllers/Api/Apps/Models/UpdateAppLanguageDto.cs index 94368f040..d2d21cc52 100644 --- a/src/Squidex/Controllers/Api/Apps/Models/UpdateAppLanguageDto.cs +++ b/src/Squidex/Controllers/Api/Apps/Models/UpdateAppLanguageDto.cs @@ -11,7 +11,7 @@ using Squidex.Infrastructure; namespace Squidex.Controllers.Api.Apps.Models { - public class UpdateAppLanguageDto + public sealed class UpdateAppLanguageDto { /// /// Set the value to true to make the language the master. diff --git a/src/Squidex/Controllers/Api/Assets/AssetContentController.cs b/src/Squidex/Controllers/Api/Assets/AssetContentController.cs index 0415ab079..088ec9b6f 100644 --- a/src/Squidex/Controllers/Api/Assets/AssetContentController.cs +++ b/src/Squidex/Controllers/Api/Assets/AssetContentController.cs @@ -26,7 +26,7 @@ namespace Squidex.Controllers.Api.Assets [ApiExceptionFilter] [AppApi] [SwaggerTag("Assets")] - public class AssetContentController : ControllerBase + public sealed class AssetContentController : ControllerBase { private readonly IAssetStore assetStorage; private readonly IAssetRepository assetRepository; diff --git a/src/Squidex/Controllers/Api/Assets/AssetsController.cs b/src/Squidex/Controllers/Api/Assets/AssetsController.cs index 2ffec457d..245ab471b 100644 --- a/src/Squidex/Controllers/Api/Assets/AssetsController.cs +++ b/src/Squidex/Controllers/Api/Assets/AssetsController.cs @@ -36,7 +36,7 @@ namespace Squidex.Controllers.Api.Assets [ApiExceptionFilter] [AppApi] [SwaggerTag("Assets")] - public class AssetsController : ControllerBase + public sealed class AssetsController : ControllerBase { private readonly IAssetRepository assetRepository; private readonly IAssetStatsRepository assetStatsRepository; diff --git a/src/Squidex/Controllers/Api/Assets/Models/AssetUpdateDto.cs b/src/Squidex/Controllers/Api/Assets/Models/AssetUpdateDto.cs index f93891d28..53b84ce34 100644 --- a/src/Squidex/Controllers/Api/Assets/Models/AssetUpdateDto.cs +++ b/src/Squidex/Controllers/Api/Assets/Models/AssetUpdateDto.cs @@ -10,7 +10,7 @@ using System.ComponentModel.DataAnnotations; namespace Squidex.Controllers.Api.Assets.Models { - public class AssetUpdateDto + public sealed class AssetUpdateDto { /// /// The new name of the asset. diff --git a/src/Squidex/Controllers/Api/EntityCreatedDto.cs b/src/Squidex/Controllers/Api/EntityCreatedDto.cs index 65297c183..b60d8dbb4 100644 --- a/src/Squidex/Controllers/Api/EntityCreatedDto.cs +++ b/src/Squidex/Controllers/Api/EntityCreatedDto.cs @@ -10,7 +10,7 @@ using System.ComponentModel.DataAnnotations; namespace Squidex.Controllers.Api { - public class EntityCreatedDto + public sealed class EntityCreatedDto { /// /// Id of the created entity. diff --git a/src/Squidex/Controllers/Api/History/HistoryController.cs b/src/Squidex/Controllers/Api/History/HistoryController.cs index a9ae4c65f..f7f2a2781 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 [ApiExceptionFilter] [AppApi] [SwaggerTag("History")] - public class HistoryController : ControllerBase + public sealed class HistoryController : ControllerBase { private readonly IHistoryEventRepository historyEventRepository; diff --git a/src/Squidex/Controllers/Api/History/Models/HistoryEventDto.cs b/src/Squidex/Controllers/Api/History/Models/HistoryEventDto.cs index 7fb20900e..4eff213d3 100644 --- a/src/Squidex/Controllers/Api/History/Models/HistoryEventDto.cs +++ b/src/Squidex/Controllers/Api/History/Models/HistoryEventDto.cs @@ -12,7 +12,7 @@ using NodaTime; namespace Squidex.Controllers.Api.History.Models { - public class HistoryEventDto + public sealed class HistoryEventDto { /// /// The message of the event. diff --git a/src/Squidex/Controllers/Api/LanguageDto.cs b/src/Squidex/Controllers/Api/LanguageDto.cs index 11304fad3..30f9b56a4 100644 --- a/src/Squidex/Controllers/Api/LanguageDto.cs +++ b/src/Squidex/Controllers/Api/LanguageDto.cs @@ -10,7 +10,7 @@ using System.ComponentModel.DataAnnotations; namespace Squidex.Controllers.Api { - public class LanguageDto + public sealed class LanguageDto { /// /// The iso code of the language. diff --git a/src/Squidex/Controllers/Api/Languages/LanguagesController.cs b/src/Squidex/Controllers/Api/Languages/LanguagesController.cs index 83d68afdb..610c22a1b 100644 --- a/src/Squidex/Controllers/Api/Languages/LanguagesController.cs +++ b/src/Squidex/Controllers/Api/Languages/LanguagesController.cs @@ -22,7 +22,7 @@ namespace Squidex.Controllers.Api.Languages [Authorize] [ApiExceptionFilter] [SwaggerTag("Languages")] - public class LanguagesController : Controller + public sealed class LanguagesController : Controller { /// /// Get supported languages. diff --git a/src/Squidex/Controllers/Api/Ping/PingController.cs b/src/Squidex/Controllers/Api/Ping/PingController.cs index 4529669c3..01fb8f789 100644 --- a/src/Squidex/Controllers/Api/Ping/PingController.cs +++ b/src/Squidex/Controllers/Api/Ping/PingController.cs @@ -19,7 +19,7 @@ namespace Squidex.Controllers.Api.Ping [ApiExceptionFilter] [AppApi] [SwaggerTag("Ping")] - public class PingController : Controller + public sealed class PingController : Controller { /// /// Get ping status. diff --git a/src/Squidex/Controllers/Api/Plans/AppPlansController.cs b/src/Squidex/Controllers/Api/Plans/AppPlansController.cs index 9e3ae931d..6df93786c 100644 --- a/src/Squidex/Controllers/Api/Plans/AppPlansController.cs +++ b/src/Squidex/Controllers/Api/Plans/AppPlansController.cs @@ -28,7 +28,7 @@ namespace Squidex.Controllers.Api.Plans [ApiExceptionFilter] [AppApi] [SwaggerTag("Plans")] - public class AppPlansController : ControllerBase + public sealed class AppPlansController : ControllerBase { private readonly IAppPlansProvider appPlansProvider; private readonly IAppPlanBillingManager appPlansBillingManager; diff --git a/src/Squidex/Controllers/Api/Plans/Models/AppPlansDto.cs b/src/Squidex/Controllers/Api/Plans/Models/AppPlansDto.cs index 92031bd9b..a44c341fe 100644 --- a/src/Squidex/Controllers/Api/Plans/Models/AppPlansDto.cs +++ b/src/Squidex/Controllers/Api/Plans/Models/AppPlansDto.cs @@ -10,7 +10,7 @@ using System.Collections.Generic; namespace Squidex.Controllers.Api.Plans.Models { - public class AppPlansDto + public sealed class AppPlansDto { /// /// The available plans. diff --git a/src/Squidex/Controllers/Api/Plans/Models/ChangePlanDto.cs b/src/Squidex/Controllers/Api/Plans/Models/ChangePlanDto.cs index 9b2d6cb79..5daadd6d8 100644 --- a/src/Squidex/Controllers/Api/Plans/Models/ChangePlanDto.cs +++ b/src/Squidex/Controllers/Api/Plans/Models/ChangePlanDto.cs @@ -10,7 +10,7 @@ using System.ComponentModel.DataAnnotations; namespace Squidex.Controllers.Api.Plans.Models { - public class ChangePlanDto + public sealed class ChangePlanDto { /// /// The new plan id. diff --git a/src/Squidex/Controllers/Api/Plans/Models/PlanChangedDto.cs b/src/Squidex/Controllers/Api/Plans/Models/PlanChangedDto.cs index 3674351dc..afb56d754 100644 --- a/src/Squidex/Controllers/Api/Plans/Models/PlanChangedDto.cs +++ b/src/Squidex/Controllers/Api/Plans/Models/PlanChangedDto.cs @@ -8,7 +8,7 @@ namespace Squidex.Controllers.Api.Plans.Models { - public class PlanChangedDto + public sealed class PlanChangedDto { /// /// Optional redirect uri. diff --git a/src/Squidex/Controllers/Api/Plans/Models/PlanDto.cs b/src/Squidex/Controllers/Api/Plans/Models/PlanDto.cs index 30c1191f9..0c45639ea 100644 --- a/src/Squidex/Controllers/Api/Plans/Models/PlanDto.cs +++ b/src/Squidex/Controllers/Api/Plans/Models/PlanDto.cs @@ -8,7 +8,7 @@ namespace Squidex.Controllers.Api.Plans.Models { - public class PlanDto + public sealed class PlanDto { /// /// The id of the plan. diff --git a/src/Squidex/Controllers/Api/Schemas/Models/ReorderFieldsDto.cs b/src/Squidex/Controllers/Api/Schemas/Models/ReorderFieldsDto.cs index b4e2ab89e..ae7cd21be 100644 --- a/src/Squidex/Controllers/Api/Schemas/Models/ReorderFieldsDto.cs +++ b/src/Squidex/Controllers/Api/Schemas/Models/ReorderFieldsDto.cs @@ -11,7 +11,7 @@ using System.ComponentModel.DataAnnotations; namespace Squidex.Controllers.Api.Schemas.Models { - public class ReorderFieldsDto + public sealed class ReorderFieldsDto { /// /// The field ids in the target order. diff --git a/src/Squidex/Controllers/Api/Schemas/Models/SchemaDto.cs b/src/Squidex/Controllers/Api/Schemas/Models/SchemaDto.cs index 0a92da355..1d6cf78e2 100644 --- a/src/Squidex/Controllers/Api/Schemas/Models/SchemaDto.cs +++ b/src/Squidex/Controllers/Api/Schemas/Models/SchemaDto.cs @@ -13,7 +13,7 @@ using Squidex.Infrastructure; namespace Squidex.Controllers.Api.Schemas.Models { - public class SchemaDto + public sealed class SchemaDto { /// /// The id of the schema. diff --git a/src/Squidex/Controllers/Api/Schemas/Models/SchemaPropertiesDto.cs b/src/Squidex/Controllers/Api/Schemas/Models/SchemaPropertiesDto.cs index e36928c49..822c6f12b 100644 --- a/src/Squidex/Controllers/Api/Schemas/Models/SchemaPropertiesDto.cs +++ b/src/Squidex/Controllers/Api/Schemas/Models/SchemaPropertiesDto.cs @@ -10,7 +10,7 @@ using System.ComponentModel.DataAnnotations; namespace Squidex.Controllers.Api.Schemas.Models { - public class SchemaPropertiesDto + public sealed class SchemaPropertiesDto { /// /// Optional label for the editor. diff --git a/src/Squidex/Controllers/Api/Schemas/Models/UpdateFieldDto.cs b/src/Squidex/Controllers/Api/Schemas/Models/UpdateFieldDto.cs index d2df340c6..6ec10e43c 100644 --- a/src/Squidex/Controllers/Api/Schemas/Models/UpdateFieldDto.cs +++ b/src/Squidex/Controllers/Api/Schemas/Models/UpdateFieldDto.cs @@ -10,7 +10,7 @@ using System.ComponentModel.DataAnnotations; namespace Squidex.Controllers.Api.Schemas.Models { - public class UpdateFieldDto + public sealed class UpdateFieldDto { /// /// The field properties. diff --git a/src/Squidex/Controllers/Api/Schemas/Models/UpdateSchemaDto.cs b/src/Squidex/Controllers/Api/Schemas/Models/UpdateSchemaDto.cs index 07919d47b..6c3ea84ed 100644 --- a/src/Squidex/Controllers/Api/Schemas/Models/UpdateSchemaDto.cs +++ b/src/Squidex/Controllers/Api/Schemas/Models/UpdateSchemaDto.cs @@ -10,7 +10,7 @@ using System.ComponentModel.DataAnnotations; namespace Squidex.Controllers.Api.Schemas.Models { - public class UpdateSchemaDto + public sealed class UpdateSchemaDto { /// /// Optional label for the editor. diff --git a/src/Squidex/Controllers/Api/Schemas/SchemaFieldsController.cs b/src/Squidex/Controllers/Api/Schemas/SchemaFieldsController.cs index 4449d0627..386f1005e 100644 --- a/src/Squidex/Controllers/Api/Schemas/SchemaFieldsController.cs +++ b/src/Squidex/Controllers/Api/Schemas/SchemaFieldsController.cs @@ -23,7 +23,7 @@ namespace Squidex.Controllers.Api.Schemas [ApiExceptionFilter] [AppApi] [SwaggerTag("Schemas")] - public class SchemaFieldsController : ControllerBase + public sealed class SchemaFieldsController : ControllerBase { public SchemaFieldsController(ICommandBus commandBus) : base(commandBus) diff --git a/src/Squidex/Controllers/Api/Schemas/SchemasController.cs b/src/Squidex/Controllers/Api/Schemas/SchemasController.cs index 3f9a8c822..8174fd9ec 100644 --- a/src/Squidex/Controllers/Api/Schemas/SchemasController.cs +++ b/src/Squidex/Controllers/Api/Schemas/SchemasController.cs @@ -30,7 +30,7 @@ namespace Squidex.Controllers.Api.Schemas [ApiExceptionFilter] [AppApi] [SwaggerTag("Schemas")] - public class SchemasController : ControllerBase + public sealed class SchemasController : ControllerBase { private readonly ISchemaRepository schemaRepository; diff --git a/src/Squidex/Controllers/Api/Statistics/Models/CallsUsageDto.cs b/src/Squidex/Controllers/Api/Statistics/Models/CallsUsageDto.cs index 17b0c632c..99ff2038d 100644 --- a/src/Squidex/Controllers/Api/Statistics/Models/CallsUsageDto.cs +++ b/src/Squidex/Controllers/Api/Statistics/Models/CallsUsageDto.cs @@ -10,7 +10,7 @@ using System; namespace Squidex.Controllers.Api.Statistics.Models { - public class CallsUsageDto + public sealed class CallsUsageDto { /// /// The date when the usage was tracked. diff --git a/src/Squidex/Controllers/Api/Statistics/Models/CurrentCallsDto.cs b/src/Squidex/Controllers/Api/Statistics/Models/CurrentCallsDto.cs index 7082bf5d8..19d797079 100644 --- a/src/Squidex/Controllers/Api/Statistics/Models/CurrentCallsDto.cs +++ b/src/Squidex/Controllers/Api/Statistics/Models/CurrentCallsDto.cs @@ -8,7 +8,7 @@ namespace Squidex.Controllers.Api.Statistics.Models { - public class CurrentCallsDto + public sealed class CurrentCallsDto { /// /// The number of calls. diff --git a/src/Squidex/Controllers/Api/Statistics/Models/CurrentStorageDto.cs b/src/Squidex/Controllers/Api/Statistics/Models/CurrentStorageDto.cs index 85f5e91d9..30d59396f 100644 --- a/src/Squidex/Controllers/Api/Statistics/Models/CurrentStorageDto.cs +++ b/src/Squidex/Controllers/Api/Statistics/Models/CurrentStorageDto.cs @@ -8,7 +8,7 @@ namespace Squidex.Controllers.Api.Statistics.Models { - public class CurrentStorageDto + public sealed class CurrentStorageDto { /// /// The size in bytes. diff --git a/src/Squidex/Controllers/Api/Statistics/Models/StorageUsageDto.cs b/src/Squidex/Controllers/Api/Statistics/Models/StorageUsageDto.cs index 5da3a4f05..a03eef402 100644 --- a/src/Squidex/Controllers/Api/Statistics/Models/StorageUsageDto.cs +++ b/src/Squidex/Controllers/Api/Statistics/Models/StorageUsageDto.cs @@ -10,7 +10,7 @@ using System; namespace Squidex.Controllers.Api.Statistics.Models { - public class StorageUsageDto + public sealed class StorageUsageDto { /// /// The date when the usage was tracked. diff --git a/src/Squidex/Controllers/Api/Statistics/UsagesController.cs b/src/Squidex/Controllers/Api/Statistics/UsagesController.cs index 9fcbd3411..b36837b2a 100644 --- a/src/Squidex/Controllers/Api/Statistics/UsagesController.cs +++ b/src/Squidex/Controllers/Api/Statistics/UsagesController.cs @@ -27,7 +27,7 @@ namespace Squidex.Controllers.Api.Statistics [ApiExceptionFilter] [AppApi] [SwaggerTag("Statistics")] - public class UsagesController : ControllerBase + public sealed class UsagesController : ControllerBase { private readonly IUsageTracker usageTracker; private readonly IAppPlansProvider appPlanProvider; diff --git a/src/Squidex/Controllers/Api/UI/Models/UIRegexSuggestionDto.cs b/src/Squidex/Controllers/Api/UI/Models/UIRegexSuggestionDto.cs new file mode 100644 index 000000000..cd47f6fd1 --- /dev/null +++ b/src/Squidex/Controllers/Api/UI/Models/UIRegexSuggestionDto.cs @@ -0,0 +1,27 @@ +// ========================================================================== +// UIRegexSuggestionDto.cs +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex Group +// All rights reserved. +// ========================================================================== + +using System.ComponentModel.DataAnnotations; + +namespace Squidex.Controllers.Api.UI.Models +{ + public sealed class UIRegexSuggestionDto + { + /// + /// The name of the suggestion. + /// + [Required] + public string Name { get; set; } + + /// + /// The regex pattern. + /// + [Required] + public string Pattern { get; set; } + } +} diff --git a/src/Squidex/Controllers/Api/UI/Models/UISettingsDto.cs b/src/Squidex/Controllers/Api/UI/Models/UISettingsDto.cs new file mode 100644 index 000000000..73df39d84 --- /dev/null +++ b/src/Squidex/Controllers/Api/UI/Models/UISettingsDto.cs @@ -0,0 +1,22 @@ +// ========================================================================== +// UISettingsDto.cs +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex Group +// All rights reserved. +// ========================================================================== + +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; + +namespace Squidex.Controllers.Api.UI.Models +{ + public sealed class UISettingsDto + { + /// + /// The regex suggestions. + /// + [Required] + public List RegexSuggestions { get; set; } + } +} diff --git a/src/Squidex/Controllers/Api/UI/UIController.cs b/src/Squidex/Controllers/Api/UI/UIController.cs new file mode 100644 index 000000000..6fd8a28f3 --- /dev/null +++ b/src/Squidex/Controllers/Api/UI/UIController.cs @@ -0,0 +1,57 @@ +// ========================================================================== +// UIController.cs +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex Group +// All rights reserved. +// ========================================================================== + +using System.Collections.Generic; +using System.Linq; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Options; +using NSwag.Annotations; +using Squidex.Config; +using Squidex.Controllers.Api.UI.Models; +using Squidex.Pipeline; + +namespace Squidex.Controllers.Api.UI +{ + /// + /// Manages ui settings and configs. + /// + [ApiExceptionFilter] + [SwaggerTag("UI")] + public sealed class UIController : Controller + { + private readonly MyUIOptions uiOptions; + + public UIController(IOptions uiOptions) + { + this.uiOptions = uiOptions.Value; + } + + /// + /// Get ui settings. + /// + [HttpGet] + [Route("ui/settings/")] + [ProducesResponseType(typeof(UISettingsDto), 200)] + [ApiCosts(0)] + public IActionResult GetSettings() + { + var dto = new UISettingsDto + { + RegexSuggestions = + uiOptions?.RegexSuggestions.Where(x => + !string.IsNullOrWhiteSpace(x.Key) && + !string.IsNullOrWhiteSpace(x.Value)) + .Select(x => new UIRegexSuggestionDto { Name = x.Key, Pattern = x.Value }) + .ToList() + ?? new List() + }; + + return Ok(dto); + } + } +} diff --git a/src/Squidex/Controllers/Api/Users/Models/UserCreatedDto.cs b/src/Squidex/Controllers/Api/Users/Models/UserCreatedDto.cs index 324e202f1..3e84a714c 100644 --- a/src/Squidex/Controllers/Api/Users/Models/UserCreatedDto.cs +++ b/src/Squidex/Controllers/Api/Users/Models/UserCreatedDto.cs @@ -10,7 +10,7 @@ using System.ComponentModel.DataAnnotations; namespace Squidex.Controllers.Api.Users.Models { - public class UserCreatedDto + public sealed class UserCreatedDto { [Required] public string Id { get; set; } diff --git a/src/Squidex/Controllers/Api/Users/Models/UsersDto.cs b/src/Squidex/Controllers/Api/Users/Models/UsersDto.cs index fc0ca93fd..919150480 100644 --- a/src/Squidex/Controllers/Api/Users/Models/UsersDto.cs +++ b/src/Squidex/Controllers/Api/Users/Models/UsersDto.cs @@ -8,7 +8,7 @@ namespace Squidex.Controllers.Api.Users.Models { - public class UsersDto + public sealed class UsersDto { /// /// The total number of users. diff --git a/src/Squidex/Controllers/Api/Users/UserManagementController.cs b/src/Squidex/Controllers/Api/Users/UserManagementController.cs index 4774350c0..1b5c2d11c 100644 --- a/src/Squidex/Controllers/Api/Users/UserManagementController.cs +++ b/src/Squidex/Controllers/Api/Users/UserManagementController.cs @@ -25,7 +25,7 @@ namespace Squidex.Controllers.Api.Users [MustBeAdministrator] [ApiExceptionFilter] [SwaggerIgnore] - public class UserManagementController : Controller + public sealed class UserManagementController : Controller { private readonly UserManager userManager; private readonly IUserFactory userFactory; diff --git a/src/Squidex/Controllers/Api/Users/UsersController.cs b/src/Squidex/Controllers/Api/Users/UsersController.cs index fbc5ddba2..4f6bc080d 100644 --- a/src/Squidex/Controllers/Api/Users/UsersController.cs +++ b/src/Squidex/Controllers/Api/Users/UsersController.cs @@ -30,7 +30,7 @@ namespace Squidex.Controllers.Api.Users /// [ApiExceptionFilter] [SwaggerTag("Users")] - public class UsersController : Controller + public sealed class UsersController : Controller { private static readonly byte[] AvatarBytes; private readonly UserManager userManager; diff --git a/src/Squidex/Controllers/Api/Webhooks/Models/CreateWebhookDto.cs b/src/Squidex/Controllers/Api/Webhooks/Models/CreateWebhookDto.cs index fca6289f7..56ef402f4 100644 --- a/src/Squidex/Controllers/Api/Webhooks/Models/CreateWebhookDto.cs +++ b/src/Squidex/Controllers/Api/Webhooks/Models/CreateWebhookDto.cs @@ -14,7 +14,7 @@ using System.ComponentModel.DataAnnotations; namespace Squidex.Controllers.Api.Webhooks.Models { - public class CreateWebhookDto + public sealed class CreateWebhookDto { /// /// The url of the webhook. diff --git a/src/Squidex/Controllers/Api/Webhooks/Models/UpdateWebhookDto.cs b/src/Squidex/Controllers/Api/Webhooks/Models/UpdateWebhookDto.cs index 684600a18..d5b7da231 100644 --- a/src/Squidex/Controllers/Api/Webhooks/Models/UpdateWebhookDto.cs +++ b/src/Squidex/Controllers/Api/Webhooks/Models/UpdateWebhookDto.cs @@ -12,7 +12,7 @@ using System.ComponentModel.DataAnnotations; namespace Squidex.Controllers.Api.Webhooks.Models { - public class UpdateWebhookDto + public sealed class UpdateWebhookDto { /// /// The url of the webhook. diff --git a/src/Squidex/Controllers/Api/Webhooks/Models/WebhookCreatedDto.cs b/src/Squidex/Controllers/Api/Webhooks/Models/WebhookCreatedDto.cs index 7b04c9f0e..f00234562 100644 --- a/src/Squidex/Controllers/Api/Webhooks/Models/WebhookCreatedDto.cs +++ b/src/Squidex/Controllers/Api/Webhooks/Models/WebhookCreatedDto.cs @@ -11,7 +11,7 @@ using System.ComponentModel.DataAnnotations; namespace Squidex.Controllers.Api.Webhooks.Models { - public class WebhookCreatedDto + public sealed class WebhookCreatedDto { /// /// The id of the webhook. diff --git a/src/Squidex/Controllers/Api/Webhooks/Models/WebhookDto.cs b/src/Squidex/Controllers/Api/Webhooks/Models/WebhookDto.cs index f2801d9b1..f6a90e7a7 100644 --- a/src/Squidex/Controllers/Api/Webhooks/Models/WebhookDto.cs +++ b/src/Squidex/Controllers/Api/Webhooks/Models/WebhookDto.cs @@ -14,7 +14,7 @@ using System.Collections.Generic; namespace Squidex.Controllers.Api.Webhooks.Models { - public class WebhookDto + public sealed class WebhookDto { /// /// The id of the webhook. diff --git a/src/Squidex/Controllers/Api/Webhooks/Models/WebhookEventDto.cs b/src/Squidex/Controllers/Api/Webhooks/Models/WebhookEventDto.cs index 21a721c71..4473fe749 100644 --- a/src/Squidex/Controllers/Api/Webhooks/Models/WebhookEventDto.cs +++ b/src/Squidex/Controllers/Api/Webhooks/Models/WebhookEventDto.cs @@ -13,7 +13,7 @@ using Squidex.Domain.Apps.Read.Webhooks; namespace Squidex.Controllers.Api.Webhooks.Models { - public class WebhookEventDto + public sealed class WebhookEventDto { /// /// The id of the event. diff --git a/src/Squidex/Controllers/Api/Webhooks/Models/WebhookEventsDto.cs b/src/Squidex/Controllers/Api/Webhooks/Models/WebhookEventsDto.cs index 06b4d0620..977f44c04 100644 --- a/src/Squidex/Controllers/Api/Webhooks/Models/WebhookEventsDto.cs +++ b/src/Squidex/Controllers/Api/Webhooks/Models/WebhookEventsDto.cs @@ -8,7 +8,7 @@ namespace Squidex.Controllers.Api.Webhooks.Models { - public class WebhookEventsDto + public sealed class WebhookEventsDto { /// /// The total number of webhook events. diff --git a/src/Squidex/Controllers/Api/Webhooks/Models/WebhookSchemaDto.cs b/src/Squidex/Controllers/Api/Webhooks/Models/WebhookSchemaDto.cs index 32c89468d..d0dd44e65 100644 --- a/src/Squidex/Controllers/Api/Webhooks/Models/WebhookSchemaDto.cs +++ b/src/Squidex/Controllers/Api/Webhooks/Models/WebhookSchemaDto.cs @@ -10,7 +10,7 @@ using System; namespace Squidex.Controllers.Api.Webhooks.Models { - public class WebhookSchemaDto + public sealed class WebhookSchemaDto { /// /// The id of the schema. diff --git a/src/Squidex/Controllers/Api/Webhooks/WebhooksController.cs b/src/Squidex/Controllers/Api/Webhooks/WebhooksController.cs index 775f2f76e..19f152f11 100644 --- a/src/Squidex/Controllers/Api/Webhooks/WebhooksController.cs +++ b/src/Squidex/Controllers/Api/Webhooks/WebhooksController.cs @@ -29,7 +29,7 @@ namespace Squidex.Controllers.Api.Webhooks [AppApi] [SwaggerTag("Webhooks")] [MustBeAppDeveloper] - public class WebhooksController : ControllerBase + public sealed class WebhooksController : ControllerBase { private readonly IWebhookRepository webhooksRepository; private readonly IWebhookEventRepository webhookEventsRepository; diff --git a/src/Squidex/Controllers/ContentApi/ContentSwaggerController.cs b/src/Squidex/Controllers/ContentApi/ContentSwaggerController.cs index 014de14fc..12ff9ef87 100644 --- a/src/Squidex/Controllers/ContentApi/ContentSwaggerController.cs +++ b/src/Squidex/Controllers/ContentApi/ContentSwaggerController.cs @@ -20,7 +20,7 @@ namespace Squidex.Controllers.ContentApi { [ApiExceptionFilter] [SwaggerIgnore] - public class ContentSwaggerController : Controller + public sealed class ContentSwaggerController : Controller { private readonly ISchemaRepository schemaRepository; private readonly IAppProvider appProvider; diff --git a/src/Squidex/Controllers/ContentApi/ContentsController.cs b/src/Squidex/Controllers/ContentApi/ContentsController.cs index 37d02ee7a..df74c4df8 100644 --- a/src/Squidex/Controllers/ContentApi/ContentsController.cs +++ b/src/Squidex/Controllers/ContentApi/ContentsController.cs @@ -32,7 +32,7 @@ namespace Squidex.Controllers.ContentApi [ApiExceptionFilter] [AppApi] [SwaggerIgnore] - public class ContentsController : ControllerBase + public sealed class ContentsController : ControllerBase { private readonly ISchemaProvider schemas; private readonly IContentRepository contentRepository; diff --git a/src/Squidex/Controllers/ContentApi/Models/ContentsDto.cs b/src/Squidex/Controllers/ContentApi/Models/ContentsDto.cs index d1d594ca3..62c345510 100644 --- a/src/Squidex/Controllers/ContentApi/Models/ContentsDto.cs +++ b/src/Squidex/Controllers/ContentApi/Models/ContentsDto.cs @@ -8,7 +8,7 @@ namespace Squidex.Controllers.ContentApi.Models { - public class AssetsDto + public sealed class AssetsDto { /// /// The total number of content items. diff --git a/src/Squidex/Controllers/UI/Error/ErrorController.cs b/src/Squidex/Controllers/UI/Error/ErrorController.cs index aa471c875..c37a91c7f 100644 --- a/src/Squidex/Controllers/UI/Error/ErrorController.cs +++ b/src/Squidex/Controllers/UI/Error/ErrorController.cs @@ -12,7 +12,7 @@ using NSwag.Annotations; namespace Squidex.Controllers.UI.Error { [SwaggerIgnore] - public class ErrorController : Controller + public sealed class ErrorController : Controller { [Route("error")] public IActionResult Error() diff --git a/src/Squidex/Controllers/UI/Profile/PortalController.cs b/src/Squidex/Controllers/UI/Profile/PortalController.cs index 9dc89038f..deb8f6c05 100644 --- a/src/Squidex/Controllers/UI/Profile/PortalController.cs +++ b/src/Squidex/Controllers/UI/Profile/PortalController.cs @@ -17,7 +17,7 @@ namespace Squidex.Controllers.UI.Profile { [Authorize] [SwaggerIgnore] - public class PortalController : Controller + public sealed class PortalController : Controller { private readonly IAppPlanBillingManager appPlansBillingManager; diff --git a/src/Squidex/Controllers/UI/Profile/ProfileController.cs b/src/Squidex/Controllers/UI/Profile/ProfileController.cs index 15eec326b..c065d6bf4 100644 --- a/src/Squidex/Controllers/UI/Profile/ProfileController.cs +++ b/src/Squidex/Controllers/UI/Profile/ProfileController.cs @@ -27,7 +27,7 @@ namespace Squidex.Controllers.UI.Profile { [Authorize] [SwaggerIgnore] - public class ProfileController : Controller + public sealed class ProfileController : Controller { private readonly SignInManager signInManager; private readonly UserManager userManager; diff --git a/src/Squidex/Startup.cs b/src/Squidex/Startup.cs index c7559180d..8c6ca15fb 100644 --- a/src/Squidex/Startup.cs +++ b/src/Squidex/Startup.cs @@ -76,6 +76,8 @@ namespace Squidex Configuration.GetSection("urls")); services.Configure( Configuration.GetSection("identity")); + services.Configure( + Configuration.GetSection("ui")); services.Configure( Configuration.GetSection("usage")); diff --git a/src/Squidex/appsettings.json b/src/Squidex/appsettings.json index b603429ea..585bfb045 100644 --- a/src/Squidex/appsettings.json +++ b/src/Squidex/appsettings.json @@ -6,6 +6,15 @@ "baseUrl": "http://localhost:5000" }, + "ui": { + "regexSuggestions": { + "Email": "^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\\\.[a-zA-Z0-9-]+)*$", + "Phone": "^\\(*\\+*[1-9]{0,3}\\)*-*[1-9]{0,3}[-. /]*\\(*[2-9]\\d{2}\\)*[-. /]*\\d{3}[-. /]*\\d{4} *e*x*t*\\.* *\\d{0,4}$", + "Slug": "^[a-z0-9]+(\\\\-[a-z0-9]+)*$", + "Url": "^(?:http(s)?:\\/\\/)?[\\w.-]+(?:\\.[\\w\\.-]+)+[\\w\\-\\._~:/?#[\\]@!\\$&'\\(\\)\\*\\+,;=.]+$" + } + }, + "logging": { /* * Setting the flag to true, enables well formatteds json logs. From 4b0693cac49b0bd54c391e56f513cc16d9382e2b Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Fri, 1 Sep 2017 15:51:46 +0200 Subject: [PATCH 2/3] Scopes improved and UI for pattern suggestions. --- src/Squidex.Shared/Identity/SquidexRoles.cs | 10 +-- src/Squidex/Config/Constants.cs | 2 +- src/Squidex/Config/MyUIOptions.cs | 2 + src/Squidex/Config/Swagger/ScopesProcessor.cs | 49 ++++++++++++ src/Squidex/Config/Swagger/SwaggerServices.cs | 5 +- .../Controllers/Api/UI/UIController.cs | 6 +- .../Generator/SchemaSwaggerGenerator.cs | 56 +++++++++++-- .../Generator/SchemasSwaggerGenerator.cs | 26 ------ src/Squidex/Pipeline/Swagger/SwaggerHelper.cs | 7 +- src/Squidex/Startup.cs | 2 +- .../types/string-validation.component.html | 15 +++- .../types/string-validation.component.scss | 27 +++++++ .../types/string-validation.component.ts | 45 +++++++++-- src/Squidex/app/shared/declarations-base.ts | 1 + src/Squidex/app/shared/module.ts | 2 + .../app/shared/services/ui.service.spec.ts | 79 +++++++++++++++++++ src/Squidex/app/shared/services/ui.service.ts | 49 ++++++++++++ src/Squidex/appsettings.json | 7 ++ .../Contents/GraphQLTests.cs | 4 +- 19 files changed, 335 insertions(+), 59 deletions(-) create mode 100644 src/Squidex/Config/Swagger/ScopesProcessor.cs create mode 100644 src/Squidex/app/shared/services/ui.service.spec.ts create mode 100644 src/Squidex/app/shared/services/ui.service.ts diff --git a/src/Squidex.Shared/Identity/SquidexRoles.cs b/src/Squidex.Shared/Identity/SquidexRoles.cs index 666f86fe9..eb88be6e1 100644 --- a/src/Squidex.Shared/Identity/SquidexRoles.cs +++ b/src/Squidex.Shared/Identity/SquidexRoles.cs @@ -10,14 +10,14 @@ namespace Squidex.Shared.Identity { public static class SquidexRoles { - public static readonly string Administrator = "ADMINISTRATOR"; + public static readonly string Administrator = "administrator"; - public static readonly string AppOwner = "APP-OWNER"; + public static readonly string AppOwner = "app:owner"; - public static readonly string AppEditor = "APP-EDITOR"; + public static readonly string AppEditor = "app:editor"; - public static readonly string AppReader = "APP-READER"; + public static readonly string AppReader = "app:reader"; - public static readonly string AppDeveloper = "APP-DEVELOPER"; + public static readonly string AppDeveloper = "app:dev"; } } diff --git a/src/Squidex/Config/Constants.cs b/src/Squidex/Config/Constants.cs index f1a9f9385..3db252580 100644 --- a/src/Squidex/Config/Constants.cs +++ b/src/Squidex/Config/Constants.cs @@ -10,7 +10,7 @@ namespace Squidex.Config { public static class Constants { - public static readonly string SecurityDefinition = "oauth-client-auth"; + public static readonly string SecurityDefinition = "squidex-oauth-auth"; public static readonly string ApiPrefix = "/api"; diff --git a/src/Squidex/Config/MyUIOptions.cs b/src/Squidex/Config/MyUIOptions.cs index f95e5c24b..ea3f363f5 100644 --- a/src/Squidex/Config/MyUIOptions.cs +++ b/src/Squidex/Config/MyUIOptions.cs @@ -8,6 +8,8 @@ using System.Collections.Generic; +// ReSharper disable CollectionNeverUpdated.Global + namespace Squidex.Config { public sealed class MyUIOptions diff --git a/src/Squidex/Config/Swagger/ScopesProcessor.cs b/src/Squidex/Config/Swagger/ScopesProcessor.cs new file mode 100644 index 000000000..7e16bbec5 --- /dev/null +++ b/src/Squidex/Config/Swagger/ScopesProcessor.cs @@ -0,0 +1,49 @@ +// ========================================================================== +// ScopesProcessor.cs +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex Group +// All rights reserved. +// ========================================================================== + +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using NSwag; +using NSwag.SwaggerGeneration.Processors; +using NSwag.SwaggerGeneration.Processors.Contexts; +using Squidex.Infrastructure.Tasks; + +// ReSharper disable InvertIf + +namespace Squidex.Config.Swagger +{ + public class ScopesProcessor : IOperationProcessor + { + public Task ProcessAsync(OperationProcessorContext context) + { + if (context.OperationDescription.Operation.Security == null) + { + context.OperationDescription.Operation.Security = new List(); + } + + var authorizeAttributes = + context.MethodInfo.GetCustomAttributes(true).OfType().Union( + context.MethodInfo.DeclaringType.GetTypeInfo().GetCustomAttributes(true).OfType()).ToArray(); + + if (authorizeAttributes.Any()) + { + var scopes = authorizeAttributes.Where(a => a.Roles != null).SelectMany(a => a.Roles.Split(',')).Distinct().ToList(); + + context.OperationDescription.Operation.Security.Add(new SwaggerSecurityRequirement + { + { Constants.SecurityDefinition, scopes } + }); + } + + return TaskHelper.True; + } + } +} diff --git a/src/Squidex/Config/Swagger/SwaggerServices.cs b/src/Squidex/Config/Swagger/SwaggerServices.cs index e2b02792b..c3d4346ad 100644 --- a/src/Squidex/Config/Swagger/SwaggerServices.cs +++ b/src/Squidex/Config/Swagger/SwaggerServices.cs @@ -42,10 +42,9 @@ namespace Squidex.Config.Swagger private static SwaggerSettings ConfigureIdentity(this SwaggerSettings settings, MyUrlsOptions urlOptions) { - settings.DocumentProcessors.Add( - new SecurityDefinitionAppender(Constants.SecurityDefinition, SwaggerHelper.CreateOAuthSchema(urlOptions))); + settings.DocumentProcessors.Add(new SecurityDefinitionAppender(Constants.SecurityDefinition, SwaggerHelper.CreateOAuthSchema(urlOptions))); - settings.OperationProcessors.Add(new OperationSecurityScopeProcessor(Constants.SecurityDefinition)); + settings.OperationProcessors.Add(new ScopesProcessor()); return settings; } diff --git a/src/Squidex/Controllers/Api/UI/UIController.cs b/src/Squidex/Controllers/Api/UI/UIController.cs index 6fd8a28f3..71b1a3c85 100644 --- a/src/Squidex/Controllers/Api/UI/UIController.cs +++ b/src/Squidex/Controllers/Api/UI/UIController.cs @@ -43,11 +43,11 @@ namespace Squidex.Controllers.Api.UI var dto = new UISettingsDto { RegexSuggestions = - uiOptions?.RegexSuggestions.Where(x => + uiOptions.RegexSuggestions? + .Where(x => !string.IsNullOrWhiteSpace(x.Key) && !string.IsNullOrWhiteSpace(x.Value)) - .Select(x => new UIRegexSuggestionDto { Name = x.Key, Pattern = x.Value }) - .ToList() + .Select(x => new UIRegexSuggestionDto { Name = x.Key, Pattern = x.Value }).ToList() ?? new List() }; diff --git a/src/Squidex/Controllers/ContentApi/Generator/SchemaSwaggerGenerator.cs b/src/Squidex/Controllers/ContentApi/Generator/SchemaSwaggerGenerator.cs index 25ae90123..5af7a3e8f 100644 --- a/src/Squidex/Controllers/ContentApi/Generator/SchemaSwaggerGenerator.cs +++ b/src/Squidex/Controllers/ContentApi/Generator/SchemaSwaggerGenerator.cs @@ -11,11 +11,13 @@ using System.Collections.Generic; using System.Linq; using NJsonSchema; using NSwag; +using Squidex.Config; using Squidex.Domain.Apps.Core; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Read.Contents.JsonSchema; using Squidex.Infrastructure; using Squidex.Pipeline.Swagger; +using Squidex.Shared.Identity; // ReSharper disable InvertIf @@ -23,8 +25,10 @@ namespace Squidex.Controllers.ContentApi.Generator { public sealed class SchemaSwaggerGenerator { - private static readonly string schemaQueryDescription; - private static readonly string schemaBodyDescription; + private static readonly string SchemaQueryDescription; + private static readonly string SchemaBodyDescription; + private static readonly List EditorSecurity; + private static readonly List ReaderSecurity; private readonly ContentSchemaBuilder schemaBuilder = new ContentSchemaBuilder(); private readonly SwaggerDocument document; private readonly JsonSchema4 contentSchema; @@ -36,8 +40,28 @@ namespace Squidex.Controllers.ContentApi.Generator static SchemaSwaggerGenerator() { - schemaBodyDescription = SwaggerHelper.LoadDocs("schemabody"); - schemaQueryDescription = SwaggerHelper.LoadDocs("schemaquery"); + SchemaBodyDescription = SwaggerHelper.LoadDocs("schemabody"); + SchemaQueryDescription = SwaggerHelper.LoadDocs("schemaquery"); + + ReaderSecurity = new List + { + new SwaggerSecurityRequirement + { + { + Constants.SecurityDefinition, new[] { SquidexRoles.AppReader } + } + } + }; + + EditorSecurity = new List + { + new SwaggerSecurityRequirement + { + { + Constants.SecurityDefinition, new[] { SquidexRoles.AppEditor } + } + } + }; } public SchemaSwaggerGenerator(SwaggerDocument document, string path, Schema schema, @@ -89,7 +113,7 @@ namespace Squidex.Controllers.ContentApi.Generator operation.OperationId = $"Query{schemaKey}Contents"; operation.Summary = $"Queries {schemaName} contents."; - operation.Description = schemaQueryDescription; + operation.Description = SchemaQueryDescription; operation.AddQueryParameter("$top", JsonObjectType.Number, "Optional number of contents to take."); operation.AddQueryParameter("$skip", JsonObjectType.Number, "Optional number of contents to skip."); @@ -98,6 +122,8 @@ namespace Squidex.Controllers.ContentApi.Generator operation.AddQueryParameter("orderby", JsonObjectType.String, "Optional OData order definition."); operation.AddResponse("200", $"{schemaName} content retrieved.", CreateContentsSchema(schemaName, contentSchema)); + + operation.Security = ReaderSecurity; }); } @@ -109,6 +135,8 @@ namespace Squidex.Controllers.ContentApi.Generator operation.Summary = $"Get a {schemaName} content."; operation.AddResponse("200", $"{schemaName} content found.", contentSchema); + + operation.Security = ReaderSecurity; }); } @@ -119,10 +147,12 @@ namespace Squidex.Controllers.ContentApi.Generator operation.OperationId = $"Create{schemaKey}Content"; operation.Summary = $"Create a {schemaName} content."; - operation.AddBodyParameter("data", dataSchema, schemaBodyDescription); + operation.AddBodyParameter("data", dataSchema, SchemaBodyDescription); operation.AddQueryParameter("publish", JsonObjectType.Boolean, "Set to true to autopublish content."); operation.AddResponse("201", $"{schemaName} created.", contentSchema); + + operation.Security = EditorSecurity; }); } @@ -133,9 +163,11 @@ namespace Squidex.Controllers.ContentApi.Generator operation.OperationId = $"Update{schemaKey}Content"; operation.Summary = $"Update a {schemaName} content."; - operation.AddBodyParameter("data", dataSchema, schemaBodyDescription); + operation.AddBodyParameter("data", dataSchema, SchemaBodyDescription); operation.AddResponse("204", $"{schemaName} element updated."); + + operation.Security = EditorSecurity; }); } @@ -146,9 +178,11 @@ namespace Squidex.Controllers.ContentApi.Generator operation.OperationId = $"Path{schemaKey}Content"; operation.Summary = $"Patchs a {schemaName} content."; - operation.AddBodyParameter("data", contentSchema, schemaBodyDescription); + operation.AddBodyParameter("data", contentSchema, SchemaBodyDescription); operation.AddResponse("204", $"{schemaName} element updated."); + + operation.Security = EditorSecurity; }); } @@ -160,6 +194,8 @@ namespace Squidex.Controllers.ContentApi.Generator operation.Summary = $"Publish a {schemaName} content."; operation.AddResponse("204", $"{schemaName} element published."); + + operation.Security = EditorSecurity; }); } @@ -171,6 +207,8 @@ namespace Squidex.Controllers.ContentApi.Generator operation.Summary = $"Unpublish a {schemaName} content."; operation.AddResponse("204", $"{schemaName} element unpublished."); + + operation.Security = EditorSecurity; }); } @@ -182,6 +220,8 @@ namespace Squidex.Controllers.ContentApi.Generator operation.Summary = $"Delete a {schemaName} content."; operation.AddResponse("204", $"{schemaName} content deleted."); + + operation.Security = EditorSecurity; }); } diff --git a/src/Squidex/Controllers/ContentApi/Generator/SchemasSwaggerGenerator.cs b/src/Squidex/Controllers/ContentApi/Generator/SchemasSwaggerGenerator.cs index c9f35e3dc..a8b32c62d 100644 --- a/src/Squidex/Controllers/ContentApi/Generator/SchemasSwaggerGenerator.cs +++ b/src/Squidex/Controllers/ContentApi/Generator/SchemasSwaggerGenerator.cs @@ -20,7 +20,6 @@ using Squidex.Domain.Apps.Read.Apps; using Squidex.Domain.Apps.Read.Schemas; using Squidex.Infrastructure; using Squidex.Pipeline.Swagger; -using Squidex.Shared.Identity; // ReSharper disable InvertIf // ReSharper disable SuggestBaseTypeForParameter @@ -55,37 +54,12 @@ namespace Squidex.Controllers.ContentApi.Generator swaggerGenerator = new SwaggerGenerator(schemaGenerator, settings, schemaResolver); GenerateSchemasOperations(schemas, app); - GenerateSecurityRequirements(); await GenerateDefaultErrorsAsync(); return document; } - private void GenerateSecurityRequirements() - { - var securityRequirements = new List - { - new SwaggerSecurityRequirement - { - { - Constants.SecurityDefinition, - new List - { - SquidexRoles.AppOwner, - SquidexRoles.AppDeveloper, - SquidexRoles.AppEditor - } - } - } - }; - - foreach (var operation in document.Paths.Values.SelectMany(x => x.Values)) - { - operation.Security = securityRequirements; - } - } - private void GenerateSchemasOperations(IEnumerable schemas, IAppEntity app) { var appBasePath = $"/content/{app.Name}"; diff --git a/src/Squidex/Pipeline/Swagger/SwaggerHelper.cs b/src/Squidex/Pipeline/Swagger/SwaggerHelper.cs index cf0a7fadf..c6816edf8 100644 --- a/src/Squidex/Pipeline/Swagger/SwaggerHelper.cs +++ b/src/Squidex/Pipeline/Swagger/SwaggerHelper.cs @@ -94,9 +94,10 @@ namespace Squidex.Pipeline.Swagger Scopes = new Dictionary { { Constants.ApiScope, "Read and write access to the API" }, - { SquidexRoles.AppOwner, "You get this scope / role when you are owner of the app you are accessing." }, - { SquidexRoles.AppEditor, "You get this scope / role when you are owner of the app you are accessing or when the subject is a client." }, - { SquidexRoles.AppDeveloper, "You get this scope / role when you are owner of the app you are accessing." } + { SquidexRoles.AppOwner, "App contributor with Owner permission." }, + { SquidexRoles.AppEditor, "Client (writer) or App contributor with Editor permission." }, + { SquidexRoles.AppReader, "Client (readonly) or App contributor with Editor permission." }, + { SquidexRoles.AppDeveloper, "App contributor with Developer permission." }, }, Description = securityDescription }; diff --git a/src/Squidex/Startup.cs b/src/Squidex/Startup.cs index 8c6ca15fb..fedb373ab 100644 --- a/src/Squidex/Startup.cs +++ b/src/Squidex/Startup.cs @@ -76,7 +76,7 @@ namespace Squidex Configuration.GetSection("urls")); services.Configure( Configuration.GetSection("identity")); - services.Configure( + services.Configure( Configuration.GetSection("ui")); services.Configure( Configuration.GetSection("usage")); diff --git a/src/Squidex/app/features/schemas/pages/schema/types/string-validation.component.html b/src/Squidex/app/features/schemas/pages/schema/types/string-validation.component.html index fef4a9e6d..09f659250 100644 --- a/src/Squidex/app/features/schemas/pages/schema/types/string-validation.component.html +++ b/src/Squidex/app/features/schemas/pages/schema/types/string-validation.component.html @@ -24,7 +24,20 @@
- + + +
+

Suggestions

+ +
+
{{suggestion.name}}
+
{{suggestion.pattern}}
+
+
diff --git a/src/Squidex/app/features/schemas/pages/schema/types/string-validation.component.scss b/src/Squidex/app/features/schemas/pages/schema/types/string-validation.component.scss index 644d162d7..a1a14fec0 100644 --- a/src/Squidex/app/features/schemas/pages/schema/types/string-validation.component.scss +++ b/src/Squidex/app/features/schemas/pages/schema/types/string-validation.component.scss @@ -11,6 +11,33 @@ } } +.control-dropdown { + & { + max-width: 285px; + min-height: 220px; + } + + h4 { + padding: .5rem 0 0 .5rem; + } + + &-item { + & { + font-size: .85rem; + } + + &:hover { + .text-muted { + color: $color-dark-foreground !important; + } + } + } +} + .form-check-input { margin: 0; +} + +.truncate { + @include truncate; } \ No newline at end of file diff --git a/src/Squidex/app/features/schemas/pages/schema/types/string-validation.component.ts b/src/Squidex/app/features/schemas/pages/schema/types/string-validation.component.ts index d864b003b..772da9f1e 100644 --- a/src/Squidex/app/features/schemas/pages/schema/types/string-validation.component.ts +++ b/src/Squidex/app/features/schemas/pages/schema/types/string-validation.component.ts @@ -9,7 +9,12 @@ import { Component, Input, OnDestroy, OnInit } from '@angular/core'; import { FormControl, FormGroup } from '@angular/forms'; import { Observable, Subscription } from 'rxjs'; -import { StringFieldPropertiesDto } from 'shared'; +import { + ModalView, + StringFieldPropertiesDto, + UIRegexSuggestionDto, + UIService +} from 'shared'; @Component({ selector: 'sqx-string-validation', @@ -18,6 +23,7 @@ import { StringFieldPropertiesDto } from 'shared'; }) export class StringValidationComponent implements OnDestroy, OnInit { private patternSubscription: Subscription; + private uiSettingsSubscription: Subscription; @Input() public editForm: FormGroup; @@ -27,9 +33,20 @@ export class StringValidationComponent implements OnDestroy, OnInit { public showDefaultValue: Observable; public showPatternMessage: Observable; + public showPatternSuggestions: Observable; + + public regexSuggestions: UIRegexSuggestionDto[] = []; + + public regexSuggestionsModal = new ModalView(false, false); + + constructor( + private readonly uiService: UIService + ) { + } public ngOnDestroy() { this.patternSubscription.unsubscribe(); + this.uiSettingsSubscription.unsubscribe(); } public ngOnInit() { @@ -58,11 +75,27 @@ export class StringValidationComponent implements OnDestroy, OnInit { .startWith('') .map(x => x && x.trim().length > 0); + this.showPatternSuggestions = + this.editForm.controls['pattern'].valueChanges + .startWith('') + .map(x => !x || x.trim().length === 0); + + this.uiSettingsSubscription = + this.uiService.getSettings() + .subscribe(settings => { + this.regexSuggestions = settings.regexSuggestions; + }); + this.patternSubscription = - this.editForm.controls['pattern'].valueChanges.subscribe((value: string) => { - if (!value || value.length === 0) { - this.editForm.controls['patternMessage'].setValue(undefined); - } - }); + this.editForm.controls['pattern'].valueChanges + .subscribe((value: string) => { + if (!value || value.length === 0) { + this.editForm.controls['patternMessage'].setValue(undefined); + } + }); + } + + public setPattern(pattern: string) { + this.editForm.controls['pattern'].setValue(pattern); } } \ No newline at end of file diff --git a/src/Squidex/app/shared/declarations-base.ts b/src/Squidex/app/shared/declarations-base.ts index e32ab59f0..01d4a0bdc 100644 --- a/src/Squidex/app/shared/declarations-base.ts +++ b/src/Squidex/app/shared/declarations-base.ts @@ -31,6 +31,7 @@ export * from './services/history.service'; export * from './services/languages.service'; export * from './services/plans.service'; export * from './services/schemas.service'; +export * from './services/ui.service'; export * from './services/usages.service'; export * from './services/users-provider.service'; export * from './services/users.service'; diff --git a/src/Squidex/app/shared/module.ts b/src/Squidex/app/shared/module.ts index 71b81bf22..f67368770 100644 --- a/src/Squidex/app/shared/module.ts +++ b/src/Squidex/app/shared/module.ts @@ -44,6 +44,7 @@ import { ResolveSchemaGuard, SchemasService, ResolveUserGuard, + UIService, UsagesService, UserDtoPicture, UserEmailPipe, @@ -129,6 +130,7 @@ export class SqxSharedModule { ResolveSchemaGuard, ResolveUserGuard, SchemasService, + UIService, UsagesService, UserManagementService, UsersProviderService, diff --git a/src/Squidex/app/shared/services/ui.service.spec.ts b/src/Squidex/app/shared/services/ui.service.spec.ts new file mode 100644 index 000000000..a1cb05b2c --- /dev/null +++ b/src/Squidex/app/shared/services/ui.service.spec.ts @@ -0,0 +1,79 @@ +/* + * Squidex Headless CMS + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; +import { inject, TestBed } from '@angular/core/testing'; + +import { + ApiUrlConfig, + UIService, + UISettingsDto +} from './../'; + +describe('UIService', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ + HttpClientTestingModule + ], + providers: [ + UIService, + { provide: ApiUrlConfig, useValue: new ApiUrlConfig('http://service/p/') } + ] + }); + }); + + afterEach(inject([HttpTestingController], (httpMock: HttpTestingController) => { + httpMock.verify(); + })); + + it('should make get request to get settings', + inject([UIService, HttpTestingController], (uiService: UIService, httpMock: HttpTestingController) => { + + let settings1: UISettingsDto | null = null; + let settings2: UISettingsDto | null = null; + + uiService.getSettings().subscribe(result => { + settings1 = result; + }); + + const response: UISettingsDto = { regexSuggestions: [] }; + + const req = httpMock.expectOne('http://service/p/api/ui/settings'); + + expect(req.request.method).toEqual('GET'); + expect(req.request.headers.get('If-Match')).toBeNull(); + + req.flush(response); + + uiService.getSettings().subscribe(result => { + settings2 = result; + }); + + expect(settings1).toEqual(response); + expect(settings2).toEqual(response); + })); + + it('should return default settings when error occurs', + inject([UIService, HttpTestingController], (uiService: UIService, httpMock: HttpTestingController) => { + + let settings: UISettingsDto | null = null; + + uiService.getSettings().subscribe(result => { + settings = result; + }); + + const req = httpMock.expectOne('http://service/p/api/ui/settings'); + + expect(req.request.method).toEqual('GET'); + expect(req.request.headers.get('If-Match')).toBeNull(); + + req.error(new ErrorEvent('500')); + + expect(settings.regexSuggestions).toEqual([]); + })); +}); \ No newline at end of file diff --git a/src/Squidex/app/shared/services/ui.service.ts b/src/Squidex/app/shared/services/ui.service.ts new file mode 100644 index 000000000..fe9d999fc --- /dev/null +++ b/src/Squidex/app/shared/services/ui.service.ts @@ -0,0 +1,49 @@ +/* + * Squidex Headless CMS + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; + +import 'framework/angular/http-extensions'; + +import { ApiUrlConfig } from 'framework'; + +export interface UISettingsDto { + regexSuggestions: UIRegexSuggestionDto[]; +} + +export interface UIRegexSuggestionDto { + name: string; pattern: string; +} + +@Injectable() +export class UIService { + private settings: UISettingsDto; + + constructor( + private readonly http: HttpClient, + private readonly apiUrl: ApiUrlConfig + ) { + } + + public getSettings(): Observable { + if (this.settings) { + return Observable.of(this.settings); + } else { + const url = this.apiUrl.buildUrl(`api/ui/settings`); + + return this.http.get(url) + .catch(error => { + return Observable.of({ regexSuggestions: [] }); + }) + .do(settings => { + this.settings = settings; + }); + } + } +} \ No newline at end of file diff --git a/src/Squidex/appsettings.json b/src/Squidex/appsettings.json index 585bfb045..eec0956f2 100644 --- a/src/Squidex/appsettings.json +++ b/src/Squidex/appsettings.json @@ -7,10 +7,17 @@ }, "ui": { + /* + * Regex suggestions for the UI + */ "regexSuggestions": { + // Regex for emails. "Email": "^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\\\.[a-zA-Z0-9-]+)*$", + // Regex for phone numbers. "Phone": "^\\(*\\+*[1-9]{0,3}\\)*-*[1-9]{0,3}[-. /]*\\(*[2-9]\\d{2}\\)*[-. /]*\\d{3}[-. /]*\\d{4} *e*x*t*\\.* *\\d{0,4}$", + // Regex for slugs (e.g. hello-world). "Slug": "^[a-z0-9]+(\\\\-[a-z0-9]+)*$", + // Regex for urls. "Url": "^(?:http(s)?:\\/\\/)?[\\w.-]+(?:\\.[\\w\\.-]+)+[\\w\\-\\._~:/?#[\\]@!\\$&'\\(\\)\\*\\+,;=.]+$" } }, diff --git a/tests/Squidex.Domain.Apps.Read.Tests/Contents/GraphQLTests.cs b/tests/Squidex.Domain.Apps.Read.Tests/Contents/GraphQLTests.cs index 56dd1acf4..3497331f2 100644 --- a/tests/Squidex.Domain.Apps.Read.Tests/Contents/GraphQLTests.cs +++ b/tests/Squidex.Domain.Apps.Read.Tests/Contents/GraphQLTests.cs @@ -35,8 +35,8 @@ namespace Squidex.Domain.Apps.Read.Contents { public class GraphQLTests { - private static readonly Guid schemaId = Guid.NewGuid(); - private static readonly Guid appId = Guid.NewGuid(); + private readonly Guid schemaId = Guid.NewGuid(); + private readonly Guid appId = Guid.NewGuid(); private readonly Schema schema = Schema.Create("my-schema", new SchemaProperties()) From 52eacd0b31df0a81abf23871a8ead5a78680b1d9 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Fri, 1 Sep 2017 16:44:55 +0200 Subject: [PATCH 3/3] Build fixed --- tests/Squidex.Domain.Apps.Read.Tests/Contents/GraphQLTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Squidex.Domain.Apps.Read.Tests/Contents/GraphQLTests.cs b/tests/Squidex.Domain.Apps.Read.Tests/Contents/GraphQLTests.cs index 3497331f2..56dd1acf4 100644 --- a/tests/Squidex.Domain.Apps.Read.Tests/Contents/GraphQLTests.cs +++ b/tests/Squidex.Domain.Apps.Read.Tests/Contents/GraphQLTests.cs @@ -35,8 +35,8 @@ namespace Squidex.Domain.Apps.Read.Contents { public class GraphQLTests { - private readonly Guid schemaId = Guid.NewGuid(); - private readonly Guid appId = Guid.NewGuid(); + private static readonly Guid schemaId = Guid.NewGuid(); + private static readonly Guid appId = Guid.NewGuid(); private readonly Schema schema = Schema.Create("my-schema", new SchemaProperties())