// ========================================================================== // Squidex Headless CMS // ========================================================================== // Copyright (c) Squidex UG (haftungsbeschraenkt) // All rights reserved. Licensed under the MIT license. // ========================================================================== using Lazy; using Squidex.Domain.Apps.Entities; using Squidex.Infrastructure; using Squidex.Infrastructure.Security; using Squidex.Shared; namespace Squidex.Web { public sealed class Resources { private readonly Dictionary<(string, string), bool> schemaPermissions = new Dictionary<(string, string), bool>(); // Contents public bool CanReadContent(string schema) => IsAllowedForSchema(Permissions.AppContentsReadOwn, schema); public bool CanCreateContent(string schema) => IsAllowedForSchema(Permissions.AppContentsCreate, schema); public bool CanCreateContentVersion(string schema) => IsAllowedForSchema(Permissions.AppContentsVersionCreateOwn, schema); public bool CanDeleteContent(string schema) => IsAllowedForSchema(Permissions.AppContentsDeleteOwn, schema); public bool CanDeleteContentVersion(string schema) => IsAllowedForSchema(Permissions.AppContentsVersionDeleteOwn, schema); public bool CanChangeStatus(string schema) => IsAllowedForSchema(Permissions.AppContentsChangeStatus, schema); public bool CanCancelContentStatus(string schema) => IsAllowedForSchema(Permissions.AppContentsChangeStatusCancelOwn, schema); public bool CanUpdateContent(string schema) => IsAllowedForSchema(Permissions.AppContentsUpdateOwn, schema); // Schemas public bool CanUpdateSchema(string schema) => IsAllowedForSchema(Permissions.AppSchemasDelete, schema); public bool CanUpdateSchemaScripts(string schema) => IsAllowedForSchema(Permissions.AppSchemasScripts, schema); public bool CanPublishSchema(string schema) => IsAllowedForSchema(Permissions.AppSchemasPublish, schema); public bool CanDeleteSchema(string schema) => IsAllowedForSchema(Permissions.AppSchemasDelete, schema); [Lazy] public bool CanCreateSchema => IsAllowed(Permissions.AppSchemasCreate); [Lazy] public bool CanUpdateSettings => IsAllowed(Permissions.AppUpdateSettings); // Asset Scripts [Lazy] public bool CanUpdateAssetsScripts => IsAllowed(Permissions.AppAssetsScriptsUpdate); // Contributors [Lazy] public bool CanAssignContributor => IsAllowed(Permissions.AppContributorsAssign); [Lazy] public bool CanRevokeContributor => IsAllowed(Permissions.AppContributorsRevoke); // Workflows [Lazy] public bool CanCreateWorkflow => IsAllowed(Permissions.AppWorkflowsCreate); [Lazy] public bool CanUpdateWorkflow => IsAllowed(Permissions.AppWorkflowsUpdate); [Lazy] public bool CanDeleteWorkflow => IsAllowed(Permissions.AppWorkflowsDelete); // Roles [Lazy] public bool CanCreateRole => IsAllowed(Permissions.AppRolesCreate); [Lazy] public bool CanUpdateRole => IsAllowed(Permissions.AppRolesUpdate); [Lazy] public bool CanDeleteRole => IsAllowed(Permissions.AppRolesDelete); // Languages [Lazy] public bool CanCreateLanguage => IsAllowed(Permissions.AppLanguagesCreate); [Lazy] public bool CanUpdateLanguage => IsAllowed(Permissions.AppLanguagesUpdate); [Lazy] public bool CanDeleteLanguage => IsAllowed(Permissions.AppLanguagesDelete); // Clients [Lazy] public bool CanCreateClient => IsAllowed(Permissions.AppClientsCreate); [Lazy] public bool CanUpdateClient => IsAllowed(Permissions.AppClientsUpdate); [Lazy] public bool CanDeleteClient => IsAllowed(Permissions.AppClientsDelete); // Rules [Lazy] public bool CanDisableRule => IsAllowed(Permissions.AppRulesDisable); [Lazy] public bool CanCreateRule => IsAllowed(Permissions.AppRulesCreate); [Lazy] public bool CanUpdateRule => IsAllowed(Permissions.AppRulesUpdate); [Lazy] public bool CanDeleteRule => IsAllowed(Permissions.AppRulesDelete); [Lazy] public bool CanReadRuleEvents => IsAllowed(Permissions.AppRulesEvents); // Users [Lazy] public bool CanReadUsers => IsAllowed(Permissions.AdminUsersRead); [Lazy] public bool CanCreateUser => IsAllowed(Permissions.AdminUsersCreate); [Lazy] public bool CanLockUser => IsAllowed(Permissions.AdminUsersLock); [Lazy] public bool CanUnlockUser => IsAllowed(Permissions.AdminUsersUnlock); [Lazy] public bool CanUpdateUser => IsAllowed(Permissions.AdminUsersUpdate); // Assets [Lazy] public bool CanUploadAsset => IsAllowed(Permissions.AppAssetsUpload); [Lazy] public bool CanCreateAsset => IsAllowed(Permissions.AppAssetsCreate); [Lazy] public bool CanDeleteAsset => IsAllowed(Permissions.AppAssetsDelete); [Lazy] public bool CanUpdateAsset => IsAllowed(Permissions.AppAssetsUpdate); [Lazy] public bool CanReadAssets => IsAllowed(Permissions.AppAssetsRead); // Events [Lazy] public bool CanReadEvents => IsAllowed(Permissions.AdminEventsRead); [Lazy] public bool CanManageEvents => IsAllowed(Permissions.AdminEventsManage); // Orleans [Lazy] public bool CanReadOrleans => IsAllowed(Permissions.AdminOrleans); // Backups [Lazy] public bool CanRestoreBackup => IsAllowed(Permissions.AdminRestore); [Lazy] public bool CanCreateBackup => IsAllowed(Permissions.AppBackupsCreate); [Lazy] public bool CanDeleteBackup => IsAllowed(Permissions.AppBackupsDelete); [Lazy] public bool CanDownloadBackup => IsAllowed(Permissions.AppBackupsDownload); [Lazy] public string? App => GetAppName(); [Lazy] public DomainId AppId => GetAppId(); public ApiController Controller { get; } public Context Context { get; set; } public Resources(ApiController controller) { Controller = controller; Context = controller.HttpContext.Context(); } public string Url(Func action, object? values = null) where T : ApiController { var url = Controller.Url(action, values); var basePath = Controller.HttpContext.Request.PathBase; if (url.StartsWith(Controller.HttpContext.Request.PathBase, StringComparison.OrdinalIgnoreCase)) { url = url[basePath.Value!.Length..]; } return url; } public bool IsUser(string userId) { var subject = Controller.User.OpenIdSubject(); return string.Equals(subject, userId, StringComparison.OrdinalIgnoreCase); } public bool Includes(Permission permission, PermissionSet? additional = null) { return Context.UserPermissions.Includes(permission) || additional?.Includes(permission) == true; } public bool IsAllowedForSchema(string id, string schema) { return schemaPermissions.GetOrAdd((id, schema), k => IsAllowed(k.Item1, "*", k.Item2)); } public bool IsAllowed(string id, string app = Permission.Any, string schema = Permission.Any, PermissionSet? additional = null) { if (app == Permission.Any) { var fallback = App; if (!string.IsNullOrWhiteSpace(fallback)) { app = fallback; } } if (schema == Permission.Any) { var fallback = Controller.HttpContext.Features.Get()?.Schema.SchemaDef.Name; if (!string.IsNullOrWhiteSpace(fallback)) { schema = fallback; } } var permission = Permissions.ForApp(id, app, schema); return Context.UserPermissions.Allows(permission) || additional?.Allows(permission) == true; } private string? GetAppName() { return Controller.HttpContext.Context().App?.Name; } private DomainId GetAppId() { return Controller.HttpContext.Context().App?.Id ?? default; } } }