mirror of https://github.com/Squidex/squidex.git
17 changed files with 552 additions and 36 deletions
@ -0,0 +1,14 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
namespace Squidex.Domain.Apps.Entities.Apps.Commands |
||||
|
{ |
||||
|
public sealed class AddRole : AppCommand |
||||
|
{ |
||||
|
public string Name { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
namespace Squidex.Domain.Apps.Entities.Apps.Commands |
||||
|
{ |
||||
|
public sealed class DeleteRole : AppCommand |
||||
|
{ |
||||
|
public string Name { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
namespace Squidex.Domain.Apps.Entities.Apps.Commands |
||||
|
{ |
||||
|
public sealed class UpdateRole : AppCommand |
||||
|
{ |
||||
|
public string Name { get; set; } |
||||
|
|
||||
|
public string[] Permissions { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,103 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System; |
||||
|
using System.Linq; |
||||
|
using Squidex.Domain.Apps.Core.Apps; |
||||
|
using Squidex.Domain.Apps.Entities.Apps.Commands; |
||||
|
using Squidex.Infrastructure; |
||||
|
|
||||
|
namespace Squidex.Domain.Apps.Entities.Apps.Guards |
||||
|
{ |
||||
|
public static class GuardAppRoles |
||||
|
{ |
||||
|
public static void CanAdd(Roles roles, AddRole command) |
||||
|
{ |
||||
|
Guard.NotNull(command, nameof(command)); |
||||
|
|
||||
|
Validate.It(() => "Cannot add role.", e => |
||||
|
{ |
||||
|
if (string.IsNullOrWhiteSpace(command.Name)) |
||||
|
{ |
||||
|
e("Name is required.", nameof(command.Name)); |
||||
|
} |
||||
|
else if (roles.ContainsKey(command.Name)) |
||||
|
{ |
||||
|
e("A role with the same name already exists."); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
public static void CanDelete(Roles roles, DeleteRole command, AppContributors contributors, AppClients clients) |
||||
|
{ |
||||
|
Guard.NotNull(command, nameof(command)); |
||||
|
|
||||
|
GetRoleOrThrow(roles, command.Name); |
||||
|
|
||||
|
Validate.It(() => "Cannot delete role.", e => |
||||
|
{ |
||||
|
if (string.IsNullOrWhiteSpace(command.Name)) |
||||
|
{ |
||||
|
e("Name is required.", nameof(command.Name)); |
||||
|
} |
||||
|
else if (Role.IsDefaultRole(command.Name)) |
||||
|
{ |
||||
|
e("Cannot delete a default role."); |
||||
|
} |
||||
|
|
||||
|
if (clients.Values.Any(x => string.Equals(x.Role, command.Name, StringComparison.OrdinalIgnoreCase))) |
||||
|
{ |
||||
|
e("Cannot remove a role when a client is assigned."); |
||||
|
} |
||||
|
|
||||
|
if (contributors.Values.Any(x => string.Equals(x, command.Name, StringComparison.OrdinalIgnoreCase))) |
||||
|
{ |
||||
|
e("Cannot remove a role when a contributor is assigned."); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
public static void CanUpdate(Roles roles, UpdateRole command) |
||||
|
{ |
||||
|
Guard.NotNull(command, nameof(command)); |
||||
|
|
||||
|
GetRoleOrThrow(roles, command.Name); |
||||
|
|
||||
|
Validate.It(() => "Cannot delete role.", e => |
||||
|
{ |
||||
|
if (string.IsNullOrWhiteSpace(command.Name)) |
||||
|
{ |
||||
|
e("Name is required.", nameof(command.Name)); |
||||
|
} |
||||
|
else if (Role.IsDefaultRole(command.Name)) |
||||
|
{ |
||||
|
e("Cannot update a default role."); |
||||
|
} |
||||
|
|
||||
|
if (command.Permissions == null) |
||||
|
{ |
||||
|
e("Permissions is required.", nameof(command.Permissions)); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private static Role GetRoleOrThrow(Roles roles, string name) |
||||
|
{ |
||||
|
if (string.IsNullOrWhiteSpace(name)) |
||||
|
{ |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
if (!roles.TryGetValue(name, out var role)) |
||||
|
{ |
||||
|
throw new DomainObjectNotFoundException(name, "Roles", typeof(IAppEntity)); |
||||
|
} |
||||
|
|
||||
|
return role; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using Squidex.Infrastructure.EventSourcing; |
||||
|
|
||||
|
namespace Squidex.Domain.Apps.Events.Apps |
||||
|
{ |
||||
|
[EventType(nameof(AppRoleAdded))] |
||||
|
public sealed class AppRoleAdded : AppEvent |
||||
|
{ |
||||
|
public string Name { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using Squidex.Infrastructure.EventSourcing; |
||||
|
|
||||
|
namespace Squidex.Domain.Apps.Events.Apps |
||||
|
{ |
||||
|
[EventType(nameof(AppRoleDeleted))] |
||||
|
public sealed class AppRoleDeleted : AppEvent |
||||
|
{ |
||||
|
public string Name { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,19 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using Squidex.Infrastructure.EventSourcing; |
||||
|
|
||||
|
namespace Squidex.Domain.Apps.Events.Apps |
||||
|
{ |
||||
|
[EventType(nameof(AppRoleUpdated))] |
||||
|
public sealed class AppRoleUpdated : AppEvent |
||||
|
{ |
||||
|
public string Name { get; set; } |
||||
|
|
||||
|
public string[] Permissions { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,164 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using Squidex.Domain.Apps.Core.Apps; |
||||
|
using Squidex.Domain.Apps.Entities.Apps.Commands; |
||||
|
using Squidex.Domain.Apps.Entities.TestHelpers; |
||||
|
using Squidex.Infrastructure; |
||||
|
using Xunit; |
||||
|
|
||||
|
#pragma warning disable SA1310 // Field names must not contain underscore
|
||||
|
|
||||
|
namespace Squidex.Domain.Apps.Entities.Apps.Guards |
||||
|
{ |
||||
|
public class GuardAppRolesTests |
||||
|
{ |
||||
|
private readonly string roleName = "Role1"; |
||||
|
private readonly Roles roles_0 = Roles.Empty; |
||||
|
private readonly AppContributors contributors = AppContributors.Empty; |
||||
|
private readonly AppClients clients = AppClients.Empty; |
||||
|
|
||||
|
[Fact] |
||||
|
public void CanAdd_should_throw_exception_if_name_empty() |
||||
|
{ |
||||
|
var command = new AddRole { Name = null }; |
||||
|
|
||||
|
ValidationAssert.Throws(() => GuardAppRoles.CanAdd(roles_0, command), |
||||
|
new ValidationError("Name is required.", "Name")); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void CanAdd_should_throw_exception_if_name_exists() |
||||
|
{ |
||||
|
var roles_1 = roles_0.Add(roleName); |
||||
|
|
||||
|
var command = new AddRole { Name = roleName }; |
||||
|
|
||||
|
ValidationAssert.Throws(() => GuardAppRoles.CanAdd(roles_1, command), |
||||
|
new ValidationError("A role with the same name already exists.")); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void CanAdd_should_not_throw_exception_if_success() |
||||
|
{ |
||||
|
var command = new AddRole { Name = roleName }; |
||||
|
|
||||
|
GuardAppRoles.CanAdd(roles_0, command); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void CanDelete_should_throw_exception_if_name_empty() |
||||
|
{ |
||||
|
var command = new DeleteRole { Name = null }; |
||||
|
|
||||
|
ValidationAssert.Throws(() => GuardAppRoles.CanDelete(roles_0, command, contributors, clients), |
||||
|
new ValidationError("Name is required.", "Name")); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void CanDelete_should_throw_exception_if_role_not_found() |
||||
|
{ |
||||
|
var command = new DeleteRole { Name = roleName }; |
||||
|
|
||||
|
Assert.Throws<DomainObjectNotFoundException>(() => GuardAppRoles.CanDelete(roles_0, command, contributors, clients)); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void CanDelete_should_throw_exception_if_contributor_found() |
||||
|
{ |
||||
|
var roles_1 = roles_0.Add(roleName); |
||||
|
|
||||
|
var command = new DeleteRole { Name = roleName }; |
||||
|
|
||||
|
ValidationAssert.Throws(() => GuardAppRoles.CanDelete(roles_1, command, contributors.Assign("1", roleName), clients), |
||||
|
new ValidationError("Cannot remove a role when a contributor is assigned.")); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void CanDelete_should_throw_exception_if_client_found() |
||||
|
{ |
||||
|
var roles_1 = roles_0.Add(roleName); |
||||
|
|
||||
|
var command = new DeleteRole { Name = roleName }; |
||||
|
|
||||
|
ValidationAssert.Throws(() => GuardAppRoles.CanDelete(roles_1, command, contributors, clients.Add("1", new AppClient("client", "1", roleName))), |
||||
|
new ValidationError("Cannot remove a role when a client is assigned.")); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void CanDelete_should_throw_exception_if_default_role() |
||||
|
{ |
||||
|
var roles_1 = roles_0.Add(Role.Developer); |
||||
|
|
||||
|
var command = new DeleteRole { Name = Role.Developer }; |
||||
|
|
||||
|
ValidationAssert.Throws(() => GuardAppRoles.CanDelete(roles_1, command, contributors, clients), |
||||
|
new ValidationError("Cannot delete a default role.")); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void CanDelete_should_not_throw_exception_if_success() |
||||
|
{ |
||||
|
var roles_1 = roles_0.Add(roleName); |
||||
|
|
||||
|
var command = new DeleteRole { Name = roleName }; |
||||
|
|
||||
|
GuardAppRoles.CanDelete(roles_1, command, contributors, clients); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void CanUpdate_should_throw_exception_if_name_empty() |
||||
|
{ |
||||
|
var roles_1 = roles_0.Add(roleName); |
||||
|
|
||||
|
var command = new UpdateRole { Name = null, Permissions = new[] { "P1" } }; |
||||
|
|
||||
|
ValidationAssert.Throws(() => GuardAppRoles.CanUpdate(roles_1, command), |
||||
|
new ValidationError("Name is required.", "Name")); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void CanUpdate_should_throw_exception_if_permission_is_null() |
||||
|
{ |
||||
|
var roles_1 = roles_0.Add(roleName); |
||||
|
|
||||
|
var command = new UpdateRole { Name = roleName, Permissions = null }; |
||||
|
|
||||
|
ValidationAssert.Throws(() => GuardAppRoles.CanUpdate(roles_1, command), |
||||
|
new ValidationError("Permissions is required.", "Permissions")); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void CanUpdate_should_throw_exception_if_default_role() |
||||
|
{ |
||||
|
var roles_1 = roles_0.Add(Role.Developer); |
||||
|
|
||||
|
var command = new UpdateRole { Name = Role.Developer, Permissions = new[] { "P1" } }; |
||||
|
|
||||
|
ValidationAssert.Throws(() => GuardAppRoles.CanUpdate(roles_1, command), |
||||
|
new ValidationError("Cannot update a default role.")); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void CanUpdate_should_throw_exception_if_role_does_not_exists() |
||||
|
{ |
||||
|
var command = new UpdateRole { Name = roleName, Permissions = new[] { "P1" } }; |
||||
|
|
||||
|
Assert.Throws<DomainObjectNotFoundException>(() => GuardAppRoles.CanUpdate(roles_0, command)); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void CanUpdate_should_not_throw_exception_if_role_exist_with_valid_command() |
||||
|
{ |
||||
|
var roles_1 = roles_0.Add(roleName); |
||||
|
|
||||
|
var command = new UpdateRole { Name = roleName, Permissions = new[] { "P1" } }; |
||||
|
|
||||
|
GuardAppRoles.CanUpdate(roles_1, command); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue