Browse Source

Events, Commands and Guards for roles.

pull/332/head
Sebastian Stehle 7 years ago
parent
commit
f333355bb3
  1. 1
      src/Squidex.Domain.Apps.Core.Model/Apps/LanguageConfig.cs
  2. 7
      src/Squidex.Domain.Apps.Core.Model/Apps/Role.cs
  3. 30
      src/Squidex.Domain.Apps.Core.Model/Apps/Roles.cs
  4. 45
      src/Squidex.Domain.Apps.Entities/Apps/AppGrain.cs
  5. 14
      src/Squidex.Domain.Apps.Entities/Apps/Commands/AddRole.cs
  6. 14
      src/Squidex.Domain.Apps.Entities/Apps/Commands/DeleteRole.cs
  7. 16
      src/Squidex.Domain.Apps.Entities/Apps/Commands/UpdateRole.cs
  8. 2
      src/Squidex.Domain.Apps.Entities/Apps/Guards/GuardAppPatterns.cs
  9. 103
      src/Squidex.Domain.Apps.Entities/Apps/Guards/GuardAppRoles.cs
  10. 15
      src/Squidex.Domain.Apps.Entities/Apps/State/AppState.cs
  11. 17
      src/Squidex.Domain.Apps.Events/Apps/AppRoleAdded.cs
  12. 17
      src/Squidex.Domain.Apps.Events/Apps/AppRoleDeleted.cs
  13. 19
      src/Squidex.Domain.Apps.Events/Apps/AppRoleUpdated.cs
  14. 28
      tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppPatternsTests.cs
  15. 66
      tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/RolesTests.cs
  16. 30
      tests/Squidex.Domain.Apps.Entities.Tests/Apps/Guards/GuardAppPatternsTests.cs
  17. 164
      tests/Squidex.Domain.Apps.Entities.Tests/Apps/Guards/GuardAppRolesTests.cs

1
src/Squidex.Domain.Apps.Core.Model/Apps/LanguageConfig.cs

@ -16,7 +16,6 @@ namespace Squidex.Domain.Apps.Core.Apps
private static readonly Language[] DefaultFallback = new Language[0]; private static readonly Language[] DefaultFallback = new Language[0];
private readonly Language language; private readonly Language language;
private readonly Language[] languageFallbacks; private readonly Language[] languageFallbacks;
private readonly bool isOptional;
public bool IsOptional { get; } public bool IsOptional { get; }

7
src/Squidex.Domain.Apps.Core.Model/Apps/Role.cs

@ -8,6 +8,7 @@
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.Security; using Squidex.Infrastructure.Security;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.Contracts;
using P = Squidex.Shared.Permissions; using P = Squidex.Shared.Permissions;
namespace Squidex.Domain.Apps.Core.Apps namespace Squidex.Domain.Apps.Core.Apps
@ -42,6 +43,12 @@ namespace Squidex.Domain.Apps.Core.Apps
{ {
} }
[Pure]
public Role Update(string[] permissions)
{
return new Role(Name, new PermissionSet(permissions));
}
public static bool IsDefaultRole(string role) public static bool IsDefaultRole(string role)
{ {
return role != null && DefaultRolesSet.Contains(role); return role != null && DefaultRolesSet.Contains(role);

30
src/Squidex.Domain.Apps.Core.Model/Apps/Roles.cs

@ -5,8 +5,10 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using Squidex.Infrastructure;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Diagnostics.Contracts;
namespace Squidex.Domain.Apps.Core.Apps namespace Squidex.Domain.Apps.Core.Apps
{ {
@ -24,6 +26,34 @@ namespace Squidex.Domain.Apps.Core.Apps
{ {
} }
[Pure]
public Roles Add(string name)
{
var newRole = new Role(name);
return new Roles(Inner.Add(name, newRole));
}
[Pure]
public Roles Remove(string name)
{
return new Roles(Inner.Remove(name));
}
[Pure]
public Roles Update(string name, params string[] permissions)
{
Guard.NotNullOrEmpty(name, nameof(name));
Guard.NotNull(permissions, nameof(permissions));
if (!TryGetValue(name, out var role))
{
return this;
}
return new Roles(Inner.SetItem(name, role.Update(permissions)));
}
public static Roles CreateDefaults(string app) public static Roles CreateDefaults(string app)
{ {
return new Roles( return new Roles(

45
src/Squidex.Domain.Apps.Entities/Apps/AppGrain.cs

@ -133,10 +133,34 @@ namespace Squidex.Domain.Apps.Entities.Apps
UpdateLanguage(c); UpdateLanguage(c);
}); });
case AddRole addRole:
return UpdateAsync(addRole, c =>
{
GuardAppRoles.CanAdd(Snapshot.Roles, c);
AddRole(c);
});
case DeleteRole deleteRole:
return UpdateAsync(deleteRole, c =>
{
GuardAppRoles.CanDelete(Snapshot.Roles, c, Snapshot.Contributors, Snapshot.Clients);
DeleteRole(c);
});
case UpdateRole updateRole:
return UpdateAsync(updateRole, c =>
{
GuardAppRoles.CanUpdate(Snapshot.Roles, c);
UpdateRole(c);
});
case AddPattern addPattern: case AddPattern addPattern:
return UpdateAsync(addPattern, c => return UpdateAsync(addPattern, c =>
{ {
GuardAppPattern.CanAdd(Snapshot.Patterns, c); GuardAppPatterns.CanAdd(Snapshot.Patterns, c);
AddPattern(c); AddPattern(c);
}); });
@ -144,7 +168,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
case DeletePattern deletePattern: case DeletePattern deletePattern:
return UpdateAsync(deletePattern, c => return UpdateAsync(deletePattern, c =>
{ {
GuardAppPattern.CanDelete(Snapshot.Patterns, c); GuardAppPatterns.CanDelete(Snapshot.Patterns, c);
DeletePattern(c); DeletePattern(c);
}); });
@ -152,7 +176,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
case UpdatePattern updatePattern: case UpdatePattern updatePattern:
return UpdateAsync(updatePattern, c => return UpdateAsync(updatePattern, c =>
{ {
GuardAppPattern.CanUpdate(Snapshot.Patterns, c); GuardAppPatterns.CanUpdate(Snapshot.Patterns, c);
UpdatePattern(c); UpdatePattern(c);
}); });
@ -287,6 +311,21 @@ namespace Squidex.Domain.Apps.Entities.Apps
RaiseEvent(SimpleMapper.Map(command, new AppPatternUpdated())); RaiseEvent(SimpleMapper.Map(command, new AppPatternUpdated()));
} }
public void AddRole(AddRole command)
{
RaiseEvent(SimpleMapper.Map(command, new AppRoleAdded()));
}
public void DeleteRole(DeleteRole command)
{
RaiseEvent(SimpleMapper.Map(command, new AppRoleDeleted()));
}
public void UpdateRole(UpdateRole command)
{
RaiseEvent(SimpleMapper.Map(command, new AppRoleUpdated()));
}
public void ArchiveApp(ArchiveApp command) public void ArchiveApp(ArchiveApp command)
{ {
RaiseEvent(SimpleMapper.Map(command, new AppArchived())); RaiseEvent(SimpleMapper.Map(command, new AppArchived()));

14
src/Squidex.Domain.Apps.Entities/Apps/Commands/AddRole.cs

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

14
src/Squidex.Domain.Apps.Entities/Apps/Commands/DeleteRole.cs

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

16
src/Squidex.Domain.Apps.Entities/Apps/Commands/UpdateRole.cs

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

2
src/Squidex.Domain.Apps.Entities/Apps/Guards/GuardAppPattern.cs → src/Squidex.Domain.Apps.Entities/Apps/Guards/GuardAppPatterns.cs

@ -12,7 +12,7 @@ using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Entities.Apps.Guards namespace Squidex.Domain.Apps.Entities.Apps.Guards
{ {
public static class GuardAppPattern public static class GuardAppPatterns
{ {
public static void CanAdd(AppPatterns patterns, AddPattern command) public static void CanAdd(AppPatterns patterns, AddPattern command)
{ {

103
src/Squidex.Domain.Apps.Entities/Apps/Guards/GuardAppRoles.cs

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

15
src/Squidex.Domain.Apps.Entities/Apps/State/AppState.cs

@ -100,6 +100,21 @@ namespace Squidex.Domain.Apps.Entities.Apps.State
Patterns = Patterns.Update(@event.PatternId, @event.Name, @event.Pattern, @event.Message); Patterns = Patterns.Update(@event.PatternId, @event.Name, @event.Pattern, @event.Message);
} }
protected void On(AppRoleAdded @event)
{
Roles = Roles.Add(@event.Name);
}
protected void On(AppRoleDeleted @event)
{
Roles = Roles.Remove(@event.Name);
}
protected void On(AppRoleUpdated @event)
{
Roles = Roles.Update(@event.Name, @event.Permissions);
}
protected void On(AppLanguageAdded @event) protected void On(AppLanguageAdded @event)
{ {
LanguagesConfig = LanguagesConfig.Set(new LanguageConfig(@event.Language)); LanguagesConfig = LanguagesConfig.Set(new LanguageConfig(@event.Language));

17
src/Squidex.Domain.Apps.Events/Apps/AppRoleAdded.cs

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

17
src/Squidex.Domain.Apps.Events/Apps/AppRoleDeleted.cs

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

19
src/Squidex.Domain.Apps.Events/Apps/AppRoleUpdated.cs

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

28
tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppPatternsTests.cs

@ -16,61 +16,61 @@ namespace Squidex.Domain.Apps.Core.Model.Apps
{ {
public class AppPatternsTests public class AppPatternsTests
{ {
private readonly AppPatterns patterns_1; private readonly AppPatterns patterns_0;
private readonly Guid firstId = Guid.NewGuid(); private readonly Guid firstId = Guid.NewGuid();
private readonly Guid id = Guid.NewGuid(); private readonly Guid id = Guid.NewGuid();
public AppPatternsTests() public AppPatternsTests()
{ {
patterns_1 = AppPatterns.Empty.Add(firstId, "Default", "Default Pattern", "Message"); patterns_0 = AppPatterns.Empty.Add(firstId, "Default", "Default Pattern", "Message");
} }
[Fact] [Fact]
public void Should_add_pattern() public void Should_add_pattern()
{ {
var patterns_2 = patterns_1.Add(id, "NewPattern", "New Pattern", "Message"); var patterns_1 = patterns_0.Add(id, "NewPattern", "New Pattern", "Message");
patterns_2[id].Should().BeEquivalentTo(new AppPattern("NewPattern", "New Pattern", "Message")); patterns_1[id].Should().BeEquivalentTo(new AppPattern("NewPattern", "New Pattern", "Message"));
} }
[Fact] [Fact]
public void Should_throw_exception_if_add_pattern_with_same_id() public void Should_throw_exception_if_add_pattern_with_same_id()
{ {
var patterns_2 = patterns_1.Add(id, "NewPattern", "New Pattern", "Message"); var patterns_1 = patterns_0.Add(id, "NewPattern", "New Pattern", "Message");
Assert.Throws<ArgumentException>(() => patterns_2.Add(id, "NewPattern", "New Pattern", "Message")); Assert.Throws<ArgumentException>(() => patterns_1.Add(id, "NewPattern", "New Pattern", "Message"));
} }
[Fact] [Fact]
public void Should_update_pattern() public void Should_update_pattern()
{ {
var patterns_2 = patterns_1.Update(firstId, "UpdatePattern", "Update Pattern", "Message"); var patterns_1 = patterns_0.Update(firstId, "UpdatePattern", "Update Pattern", "Message");
patterns_2[firstId].Should().BeEquivalentTo(new AppPattern("UpdatePattern", "Update Pattern", "Message")); patterns_1[firstId].Should().BeEquivalentTo(new AppPattern("UpdatePattern", "Update Pattern", "Message"));
} }
[Fact] [Fact]
public void Should_return_same_patterns_if_pattern_not_found() public void Should_return_same_patterns_if_pattern_not_found()
{ {
var patterns_2 = patterns_1.Update(id, "NewPattern", "NewPattern", "Message"); var patterns_1 = patterns_0.Update(id, "NewPattern", "NewPattern", "Message");
Assert.Same(patterns_1, patterns_2); Assert.Same(patterns_0, patterns_1);
} }
[Fact] [Fact]
public void Should_remove_pattern() public void Should_remove_pattern()
{ {
var patterns_2 = patterns_1.Remove(firstId); var patterns_1 = patterns_0.Remove(firstId);
Assert.Empty(patterns_2); Assert.Empty(patterns_1);
} }
[Fact] [Fact]
public void Should_do_nothing_if_remove_pattern_not_found() public void Should_do_nothing_if_remove_pattern_not_found()
{ {
var patterns_2 = patterns_1.Remove(id); var patterns_1 = patterns_0.Remove(id);
Assert.NotSame(patterns_1, patterns_2); Assert.NotSame(patterns_0, patterns_1);
} }
} }
} }

66
tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/RolesTests.cs

@ -5,13 +5,75 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using System;
using FluentAssertions;
using Squidex.Domain.Apps.Core.Apps; using Squidex.Domain.Apps.Core.Apps;
using Squidex.Infrastructure.Security;
using Xunit; using Xunit;
#pragma warning disable SA1310 // Field names must not contain underscore
namespace Squidex.Domain.Apps.Core.Model.Apps namespace Squidex.Domain.Apps.Core.Model.Apps
{ {
public class RolesTests public class RolesTests
{ {
private readonly Roles roles_0;
private readonly string firstRole = "Role1";
private readonly string role = "Role2";
public RolesTests()
{
roles_0 = Roles.Empty.Add(firstRole);
}
[Fact]
public void Should_add_role()
{
var roles_1 = roles_0.Add(role);
roles_1[role].Should().BeEquivalentTo(new Role(role, PermissionSet.Empty));
}
[Fact]
public void Should_throw_exception_if_add_role_with_same_name()
{
var roles_1 = roles_0.Add(role);
Assert.Throws<ArgumentException>(() => roles_1.Add(role));
}
[Fact]
public void Should_update_role()
{
var roles_1 = roles_0.Update(firstRole, "P1", "P2");
roles_1[firstRole].Should().BeEquivalentTo(new Role(firstRole, new PermissionSet("P1", "P2")));
}
[Fact]
public void Should_return_same_roles_if_role_not_found()
{
var roles_1 = roles_0.Update(role, "P1", "P2");
Assert.Same(roles_0, roles_1);
}
[Fact]
public void Should_remove_role()
{
var roles_1 = roles_0.Remove(firstRole);
Assert.Empty(roles_1);
}
[Fact]
public void Should_do_nothing_if_remove_role_not_found()
{
var roles_1 = roles_0.Remove(role);
Assert.NotSame(roles_0, roles_1);
}
[Fact] [Fact]
public void Should_create_defaults() public void Should_create_defaults()
{ {
@ -19,9 +81,9 @@ namespace Squidex.Domain.Apps.Core.Model.Apps
Assert.Equal(4, sut.Count); Assert.Equal(4, sut.Count);
foreach (var role in sut) foreach (var sutRole in sut)
{ {
foreach (var permission in role.Value.Permissions) foreach (var permission in sutRole.Value.Permissions)
{ {
Assert.StartsWith("squidex.apps.my-app", permission.Id); Assert.StartsWith("squidex.apps.my-app", permission.Id);
} }

30
tests/Squidex.Domain.Apps.Entities.Tests/Apps/Guards/GuardAppPatternsTests.cs

@ -26,7 +26,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
{ {
var command = new AddPattern { PatternId = patternId, Name = string.Empty, Pattern = ".*" }; var command = new AddPattern { PatternId = patternId, Name = string.Empty, Pattern = ".*" };
ValidationAssert.Throws(() => GuardAppPattern.CanAdd(patterns_0, command), ValidationAssert.Throws(() => GuardAppPatterns.CanAdd(patterns_0, command),
new ValidationError("Name is required.", "Name")); new ValidationError("Name is required.", "Name"));
} }
@ -35,7 +35,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
{ {
var command = new AddPattern { PatternId = patternId, Name = "any", Pattern = string.Empty }; var command = new AddPattern { PatternId = patternId, Name = "any", Pattern = string.Empty };
ValidationAssert.Throws(() => GuardAppPattern.CanAdd(patterns_0, command), ValidationAssert.Throws(() => GuardAppPatterns.CanAdd(patterns_0, command),
new ValidationError("Pattern is required.", "Pattern")); new ValidationError("Pattern is required.", "Pattern"));
} }
@ -44,7 +44,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
{ {
var command = new AddPattern { PatternId = patternId, Name = "any", Pattern = "[0-9{1}" }; var command = new AddPattern { PatternId = patternId, Name = "any", Pattern = "[0-9{1}" };
ValidationAssert.Throws(() => GuardAppPattern.CanAdd(patterns_0, command), ValidationAssert.Throws(() => GuardAppPatterns.CanAdd(patterns_0, command),
new ValidationError("Pattern is not a valid regular expression.", "Pattern")); new ValidationError("Pattern is not a valid regular expression.", "Pattern"));
} }
@ -55,7 +55,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
var command = new AddPattern { PatternId = patternId, Name = "any", Pattern = ".*" }; var command = new AddPattern { PatternId = patternId, Name = "any", Pattern = ".*" };
ValidationAssert.Throws(() => GuardAppPattern.CanAdd(patterns_1, command), ValidationAssert.Throws(() => GuardAppPatterns.CanAdd(patterns_1, command),
new ValidationError("A pattern with the same name already exists.")); new ValidationError("A pattern with the same name already exists."));
} }
@ -66,7 +66,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
var command = new AddPattern { PatternId = patternId, Name = "other", Pattern = "[a-z]" }; var command = new AddPattern { PatternId = patternId, Name = "other", Pattern = "[a-z]" };
ValidationAssert.Throws(() => GuardAppPattern.CanAdd(patterns_1, command), ValidationAssert.Throws(() => GuardAppPatterns.CanAdd(patterns_1, command),
new ValidationError("This pattern already exists but with another name.")); new ValidationError("This pattern already exists but with another name."));
} }
@ -75,7 +75,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
{ {
var command = new AddPattern { PatternId = patternId, Name = "any", Pattern = ".*" }; var command = new AddPattern { PatternId = patternId, Name = "any", Pattern = ".*" };
GuardAppPattern.CanAdd(patterns_0, command); GuardAppPatterns.CanAdd(patterns_0, command);
} }
[Fact] [Fact]
@ -83,7 +83,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
{ {
var command = new DeletePattern { PatternId = patternId }; var command = new DeletePattern { PatternId = patternId };
Assert.Throws<DomainObjectNotFoundException>(() => GuardAppPattern.CanDelete(patterns_0, command)); Assert.Throws<DomainObjectNotFoundException>(() => GuardAppPatterns.CanDelete(patterns_0, command));
} }
[Fact] [Fact]
@ -93,7 +93,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
var command = new DeletePattern { PatternId = patternId }; var command = new DeletePattern { PatternId = patternId };
GuardAppPattern.CanDelete(patterns_1, command); GuardAppPatterns.CanDelete(patterns_1, command);
} }
[Fact] [Fact]
@ -103,7 +103,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
var command = new UpdatePattern { PatternId = patternId, Name = string.Empty, Pattern = ".*" }; var command = new UpdatePattern { PatternId = patternId, Name = string.Empty, Pattern = ".*" };
ValidationAssert.Throws(() => GuardAppPattern.CanUpdate(patterns_1, command), ValidationAssert.Throws(() => GuardAppPatterns.CanUpdate(patterns_1, command),
new ValidationError("Name is required.", "Name")); new ValidationError("Name is required.", "Name"));
} }
@ -114,7 +114,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
var command = new UpdatePattern { PatternId = patternId, Name = "any", Pattern = string.Empty }; var command = new UpdatePattern { PatternId = patternId, Name = "any", Pattern = string.Empty };
ValidationAssert.Throws(() => GuardAppPattern.CanUpdate(patterns_1, command), ValidationAssert.Throws(() => GuardAppPatterns.CanUpdate(patterns_1, command),
new ValidationError("Pattern is required.", "Pattern")); new ValidationError("Pattern is required.", "Pattern"));
} }
@ -125,7 +125,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
var command = new UpdatePattern { PatternId = patternId, Name = "any", Pattern = "[0-9{1}" }; var command = new UpdatePattern { PatternId = patternId, Name = "any", Pattern = "[0-9{1}" };
ValidationAssert.Throws(() => GuardAppPattern.CanUpdate(patterns_1, command), ValidationAssert.Throws(() => GuardAppPatterns.CanUpdate(patterns_1, command),
new ValidationError("Pattern is not a valid regular expression.", "Pattern")); new ValidationError("Pattern is not a valid regular expression.", "Pattern"));
} }
@ -140,7 +140,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
var command = new UpdatePattern { PatternId = id2, Name = "Pattern1", Pattern = "[0-4]" }; var command = new UpdatePattern { PatternId = id2, Name = "Pattern1", Pattern = "[0-4]" };
ValidationAssert.Throws(() => GuardAppPattern.CanUpdate(patterns_2, command), ValidationAssert.Throws(() => GuardAppPatterns.CanUpdate(patterns_2, command),
new ValidationError("A pattern with the same name already exists.")); new ValidationError("A pattern with the same name already exists."));
} }
@ -155,7 +155,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
var command = new UpdatePattern { PatternId = id2, Name = "Pattern2", Pattern = "[0-5]" }; var command = new UpdatePattern { PatternId = id2, Name = "Pattern2", Pattern = "[0-5]" };
ValidationAssert.Throws(() => GuardAppPattern.CanUpdate(patterns_2, command), ValidationAssert.Throws(() => GuardAppPatterns.CanUpdate(patterns_2, command),
new ValidationError("This pattern already exists but with another name.")); new ValidationError("This pattern already exists but with another name."));
} }
@ -164,7 +164,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
{ {
var command = new UpdatePattern { PatternId = patternId, Name = "Pattern1", Pattern = ".*" }; var command = new UpdatePattern { PatternId = patternId, Name = "Pattern1", Pattern = ".*" };
Assert.Throws<DomainObjectNotFoundException>(() => GuardAppPattern.CanUpdate(patterns_0, command)); Assert.Throws<DomainObjectNotFoundException>(() => GuardAppPatterns.CanUpdate(patterns_0, command));
} }
[Fact] [Fact]
@ -174,7 +174,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
var command = new UpdatePattern { PatternId = patternId, Name = "Pattern1", Pattern = ".*" }; var command = new UpdatePattern { PatternId = patternId, Name = "Pattern1", Pattern = ".*" };
GuardAppPattern.CanUpdate(patterns_1, command); GuardAppPatterns.CanUpdate(patterns_1, command);
} }
} }
} }

164
tests/Squidex.Domain.Apps.Entities.Tests/Apps/Guards/GuardAppRolesTests.cs

@ -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…
Cancel
Save