Browse Source

Fix role validation for clients and contributors.

pull/332/head
Sebastian Stehle 7 years ago
parent
commit
73312a7686
  1. 4
      src/Squidex.Domain.Apps.Entities/Apps/AppGrain.cs
  2. 36
      src/Squidex.Domain.Apps.Entities/Apps/AppHistoryEventsCreator.cs
  3. 4
      src/Squidex.Domain.Apps.Entities/Apps/Guards/GuardAppClients.cs
  4. 4
      src/Squidex.Domain.Apps.Entities/Apps/Guards/GuardAppContributors.cs
  5. 23
      src/Squidex/Areas/Api/Controllers/Apps/Models/RoleDto.cs
  6. 5
      src/Squidex/Areas/Api/Controllers/Apps/Models/RolesDto.cs
  7. 2
      src/Squidex/app/features/settings/pages/languages/language.component.html
  8. 14
      src/Squidex/app/features/settings/pages/roles/role.component.html
  9. 12
      src/Squidex/app/features/settings/pages/roles/role.component.scss
  10. 10
      src/Squidex/app/shared/services/app-roles.service.spec.ts
  11. 6
      src/Squidex/app/shared/services/app-roles.service.ts
  12. 6
      src/Squidex/app/shared/state/roles.state.spec.ts
  13. 15
      tests/Squidex.Domain.Apps.Entities.Tests/Apps/Guards/GuardAppClientsTests.cs
  14. 21
      tests/Squidex.Domain.Apps.Entities.Tests/Apps/Guards/GuardAppContributorsTests.cs

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

@ -70,7 +70,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
case AssignContributor assigneContributor: case AssignContributor assigneContributor:
return UpdateReturnAsync(assigneContributor, async c => return UpdateReturnAsync(assigneContributor, async c =>
{ {
await GuardAppContributors.CanAssign(Snapshot.Contributors, c, userResolver, appPlansProvider.GetPlan(Snapshot.Plan?.PlanId)); await GuardAppContributors.CanAssign(Snapshot.Contributors, c, userResolver, appPlansProvider.GetPlan(Snapshot.Plan?.PlanId), Snapshot.Roles);
AssignContributor(c); AssignContributor(c);
@ -96,7 +96,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
case UpdateClient updateClient: case UpdateClient updateClient:
return UpdateAsync(updateClient, c => return UpdateAsync(updateClient, c =>
{ {
GuardAppClients.CanUpdate(Snapshot.Clients, c); GuardAppClients.CanUpdate(Snapshot.Clients, c, Snapshot.Roles);
UpdateClient(c); UpdateClient(c);
}); });

36
src/Squidex.Domain.Apps.Entities/Apps/AppHistoryEventsCreator.cs

@ -63,6 +63,15 @@ namespace Squidex.Domain.Apps.Entities.Apps
AddEventMessage<AppPatternUpdated>( AddEventMessage<AppPatternUpdated>(
"updated pattern {[Name]}"); "updated pattern {[Name]}");
AddEventMessage<AppRoleAdded>(
"added role {[Name]}");
AddEventMessage<AppRoleDeleted>(
"deleted role {[Name]}");
AddEventMessage<AppRoleUpdated>(
"updated role {[Name]}");
} }
protected Task<HistoryEventToStore> On(AppContributorRemoved @event) protected Task<HistoryEventToStore> On(AppContributorRemoved @event)
@ -173,6 +182,33 @@ namespace Squidex.Domain.Apps.Entities.Apps
.AddParameter("PatternId", @event.PatternId)); .AddParameter("PatternId", @event.PatternId));
} }
protected Task<HistoryEventToStore> On(AppRoleAdded @event)
{
const string channel = "settings.roles";
return Task.FromResult(
ForEvent(@event, channel)
.AddParameter("Name", @event.Name));
}
protected Task<HistoryEventToStore> On(AppRoleUpdated @event)
{
const string channel = "settings.roles";
return Task.FromResult(
ForEvent(@event, channel)
.AddParameter("Name", @event.Name));
}
protected Task<HistoryEventToStore> On(AppRoleDeleted @event)
{
const string channel = "settings.roles";
return Task.FromResult(
ForEvent(@event, channel)
.AddParameter("Name", @event.Name));
}
protected override Task<HistoryEventToStore> CreateEventCoreAsync(Envelope<IEvent> @event) protected override Task<HistoryEventToStore> CreateEventCoreAsync(Envelope<IEvent> @event)
{ {
return this.DispatchFuncAsync(@event.Payload, (HistoryEventToStore)null); return this.DispatchFuncAsync(@event.Payload, (HistoryEventToStore)null);

4
src/Squidex.Domain.Apps.Entities/Apps/Guards/GuardAppClients.cs

@ -45,7 +45,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
}); });
} }
public static void CanUpdate(AppClients clients, UpdateClient command) public static void CanUpdate(AppClients clients, UpdateClient command, Roles roles)
{ {
Guard.NotNull(command, nameof(command)); Guard.NotNull(command, nameof(command));
@ -63,7 +63,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
e("Either name or role must be defined.", nameof(command.Name), nameof(command.Role)); e("Either name or role must be defined.", nameof(command.Name), nameof(command.Role));
} }
if (command.Role != null && !Role.IsDefaultRole(command.Role)) if (command.Role != null && !roles.ContainsKey(command.Role))
{ {
e("Role is not valid.", nameof(command.Role)); e("Role is not valid.", nameof(command.Role));
} }

4
src/Squidex.Domain.Apps.Entities/Apps/Guards/GuardAppContributors.cs

@ -18,13 +18,13 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
{ {
public static class GuardAppContributors public static class GuardAppContributors
{ {
public static Task CanAssign(AppContributors contributors, AssignContributor command, IUserResolver users, IAppLimitsPlan plan) public static Task CanAssign(AppContributors contributors, AssignContributor command, IUserResolver users, IAppLimitsPlan plan, Roles roles)
{ {
Guard.NotNull(command, nameof(command)); Guard.NotNull(command, nameof(command));
return Validate.It(() => "Cannot assign contributor.", async e => return Validate.It(() => "Cannot assign contributor.", async e =>
{ {
if (!Role.IsDefaultRole(command.Role)) if (!roles.ContainsKey(command.Role))
{ {
e("Role is not valid.", nameof(command.Role)); e("Role is not valid.", nameof(command.Role));
} }

23
src/Squidex/Areas/Api/Controllers/Apps/Models/RoleDto.cs

@ -5,6 +5,7 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using System;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Linq; using System.Linq;
using Squidex.Domain.Apps.Core.Apps; using Squidex.Domain.Apps.Core.Apps;
@ -20,17 +21,33 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models
[Required] [Required]
public string Name { get; set; } public string Name { get; set; }
/// <summary>
/// The number of clients with this role.
/// </summary>
public int NumClients { get; set; }
/// <summary>
/// The number of contributors with this role.
/// </summary>
public int NumContributors { get; set; }
/// <summary> /// <summary>
/// Associated list of permissions. /// Associated list of permissions.
/// </summary> /// </summary>
[Required] [Required]
public string[] Permissions { get; set; } public string[] Permissions { get; set; }
public static RoleDto FromRole(Role role, string appName) public static RoleDto FromRole(Role role, IAppEntity app)
{ {
var permissions = role.Permissions.WithoutApp(appName); var permissions = role.Permissions.WithoutApp(app.Name);
return new RoleDto { Name = role.Name, Permissions = permissions.ToIds().ToArray() }; return new RoleDto
{
Name = role.Name,
NumClients = app.Clients.Count(x => string.Equals(x.Value.Role, role.Name, StringComparison.OrdinalIgnoreCase)),
NumContributors = app.Contributors.Count(x => string.Equals(x.Value, role.Name, StringComparison.OrdinalIgnoreCase)),
Permissions = permissions.ToIds().ToArray()
};
} }
} }
} }

5
src/Squidex/Areas/Api/Controllers/Apps/Models/RolesDto.cs

@ -5,7 +5,6 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Linq; using System.Linq;
using Squidex.Domain.Apps.Entities.Apps; using Squidex.Domain.Apps.Entities.Apps;
@ -15,14 +14,14 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models
public sealed class RolesDto public sealed class RolesDto
{ {
/// <summary> /// <summary>
/// The roles. /// The app roles.
/// </summary> /// </summary>
[Required] [Required]
public RoleDto[] Roles { get; set; } public RoleDto[] Roles { get; set; }
public static RolesDto FromApp(IAppEntity app) public static RolesDto FromApp(IAppEntity app)
{ {
var roles = app.Roles.Values.Select(x => RoleDto.FromRole(x, app.Name)).ToArray(); var roles = app.Roles.Values.Select(x => RoleDto.FromRole(x, app)).ToArray();
return new RolesDto { Roles = roles }; return new RolesDto { Roles = roles };
} }

2
src/Squidex/app/features/settings/pages/languages/language.component.html

@ -7,7 +7,7 @@
<div class="col col-6" [class.language-optional]="language.isOptional" [class.language-master]="language.isMaster"> <div class="col col-6" [class.language-optional]="language.isOptional" [class.language-master]="language.isMaster">
{{language.englishName}} {{language.englishName}}
</div> </div>
<div class="col col-options"> <div class="col col-auto">
<div class="float-right"> <div class="float-right">
<button type="button" class="btn btn-secondary table-items-edit-button" [class.active]="isEditing" (click)="toggleEditing()" *ngIf="!language.isMaster"> <button type="button" class="btn btn-secondary table-items-edit-button" [class.active]="isEditing" (click)="toggleEditing()" *ngIf="!language.isMaster">
<i class="icon-settings"></i> <i class="icon-settings"></i>

14
src/Squidex/app/features/settings/pages/roles/role.component.html

@ -1,16 +1,22 @@
<div class="table-items-row table-items-row-expandable"> <div class="table-items-row table-items-row-expandable">
<div class="table-items-row-summary"> <div class="table-items-row-summary">
<div class="row"> <div class="row">
<div class="col" [class.built]="isDefaultRole"> <div class="col col-5" [class.built]="isDefaultRole">
{{role.name}} <span class="role-name">{{role.name}}</span>
</div> </div>
<div class="col col-options"> <div class="col text-decent">
Clients: <span [class.text-force]="role.numClients > 0">{{role.numClients}}</span>
</div>
<div class="col text-decent">
Users: <span [class.text-force]="role.numContributors > 0">{{role.numContributors}}</span>
</div>
<div class="col col-auto">
<div class="float-right"> <div class="float-right">
<button type="button" class="btn btn-secondary table-items-edit-button" [class.active]="isEditing" (click)="toggleEditing()"> <button type="button" class="btn btn-secondary table-items-edit-button" [class.active]="isEditing" (click)="toggleEditing()">
<i class="icon-settings"></i> <i class="icon-settings"></i>
</button> </button>
<button type="button" class="btn btn-link btn-danger" [class.invisible]="isDefaultRole" <button type="button" class="btn btn-link btn-danger" [class.invisible]="isDefaultRole || role.numClients > 0 || role.numContributors > 0"
(sqxConfirmClick)="remove()" (sqxConfirmClick)="remove()"
confirmTitle="Delete role" confirmTitle="Delete role"
confirmText="Do you really want to delete the language?"> confirmText="Do you really want to delete the language?">

12
src/Squidex/app/features/settings/pages/roles/role.component.scss

@ -11,6 +11,18 @@
} }
} }
.rule-name {
@include truncate;
}
.text-decent {
color: $color-text-decent;
}
.text-force {
color: $color-text;
}
.built { .built {
font-weight: bold; font-weight: bold;
} }

10
src/Squidex/app/shared/services/app-roles.service.spec.ts

@ -75,9 +75,13 @@ describe('AppRolesService', () => {
req.flush({ req.flush({
roles: [{ roles: [{
name: 'Role1', name: 'Role1',
numClients: 3,
numContributors: 5,
permissions: ['P1'] permissions: ['P1']
}, { }, {
name: 'Role2', name: 'Role2',
numClients: 7,
numContributors: 9,
permissions: ['P2'] permissions: ['P2']
}] }]
}, { }, {
@ -88,8 +92,8 @@ describe('AppRolesService', () => {
expect(roles!).toEqual( expect(roles!).toEqual(
new AppRolesDto([ new AppRolesDto([
new AppRoleDto('Role1', ['P1']), new AppRoleDto('Role1', 3, 5, ['P1']),
new AppRoleDto('Role2', ['P2']) new AppRoleDto('Role2', 7, 9, ['P2'])
], ],
new Version('2'))); new Version('2')));
})); }));
@ -112,7 +116,7 @@ describe('AppRolesService', () => {
req.flush({}); req.flush({});
expect(role!).toEqual(new AppRoleDto('Role3', [])); expect(role!).toEqual(new AppRoleDto('Role3', 0, 0, []));
})); }));
it('should make put request to update role', it('should make put request to update role',

6
src/Squidex/app/shared/services/app-roles.service.ts

@ -32,6 +32,8 @@ export class AppRolesDto extends Model {
export class AppRoleDto extends Model { export class AppRoleDto extends Model {
constructor( constructor(
public readonly name: string, public readonly name: string,
public readonly numClients: number,
public readonly numContributors: number,
public readonly permissions: string[] public readonly permissions: string[]
) { ) {
super(); super();
@ -77,6 +79,8 @@ export class AppRolesService {
const roles = items.map(item => { const roles = items.map(item => {
return new AppRoleDto( return new AppRoleDto(
item.name, item.name,
item.numClients,
item.numContributors,
item.permissions); item.permissions);
}); });
@ -90,7 +94,7 @@ export class AppRolesService {
return HTTP.postVersioned<any>(this.http, url, dto, version).pipe( return HTTP.postVersioned<any>(this.http, url, dto, version).pipe(
map(response => { map(response => {
const role = new AppRoleDto(dto.name, []); const role = new AppRoleDto(dto.name, 0, 0, []);
return new Versioned(response.version, role); return new Versioned(response.version, role);
}), }),

6
src/Squidex/app/shared/state/roles.state.spec.ts

@ -26,8 +26,8 @@ describe('RolesState', () => {
const newVersion = new Version('2'); const newVersion = new Version('2');
const oldRoles = [ const oldRoles = [
new AppRoleDto('Role1', ['P1']), new AppRoleDto('Role1', 3, 5, ['P1']),
new AppRoleDto('Role2', ['P2']) new AppRoleDto('Role2', 7, 9, ['P2'])
]; ];
let dialogs: IMock<DialogService>; let dialogs: IMock<DialogService>;
@ -69,7 +69,7 @@ describe('RolesState', () => {
}); });
it('should add role to snapshot when added', () => { it('should add role to snapshot when added', () => {
const newRole = new AppRoleDto('Role3', ['P3']); const newRole = new AppRoleDto('Role3', 0, 0, ['P3']);
const request = new CreateAppRoleDto('Role3'); const request = new CreateAppRoleDto('Role3');

15
tests/Squidex.Domain.Apps.Entities.Tests/Apps/Guards/GuardAppClientsTests.cs

@ -18,6 +18,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
public class GuardAppClientsTests public class GuardAppClientsTests
{ {
private readonly AppClients clients_0 = AppClients.Empty; private readonly AppClients clients_0 = AppClients.Empty;
private readonly Roles roles = Roles.CreateDefaults("my-app");
[Fact] [Fact]
public void CanAttach_should_throw_execption_if_client_id_is_null() public void CanAttach_should_throw_execption_if_client_id_is_null()
@ -81,7 +82,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
{ {
var command = new UpdateClient { Name = "iOS" }; var command = new UpdateClient { Name = "iOS" };
ValidationAssert.Throws(() => GuardAppClients.CanUpdate(clients_0, command), ValidationAssert.Throws(() => GuardAppClients.CanUpdate(clients_0, command, Roles.Empty),
new ValidationError("Client id is required.", "Id")); new ValidationError("Client id is required.", "Id"));
} }
@ -90,7 +91,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
{ {
var command = new UpdateClient { Id = "ios", Name = "iOS" }; var command = new UpdateClient { Id = "ios", Name = "iOS" };
Assert.Throws<DomainObjectNotFoundException>(() => GuardAppClients.CanUpdate(clients_0, command)); Assert.Throws<DomainObjectNotFoundException>(() => GuardAppClients.CanUpdate(clients_0, command, Roles.Empty));
} }
[Fact] [Fact]
@ -100,7 +101,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
var clients_1 = clients_0.Add("ios", "secret"); var clients_1 = clients_0.Add("ios", "secret");
ValidationAssert.Throws(() => GuardAppClients.CanUpdate(clients_1, command), ValidationAssert.Throws(() => GuardAppClients.CanUpdate(clients_1, command, roles),
new ValidationError("Either name or role must be defined.", "Name", "Role")); new ValidationError("Either name or role must be defined.", "Name", "Role"));
} }
@ -111,7 +112,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
var clients_1 = clients_0.Add("ios", "secret"); var clients_1 = clients_0.Add("ios", "secret");
ValidationAssert.Throws(() => GuardAppClients.CanUpdate(clients_1, command), ValidationAssert.Throws(() => GuardAppClients.CanUpdate(clients_1, command, roles),
new ValidationError("Role is not valid.", "Role")); new ValidationError("Role is not valid.", "Role"));
} }
@ -122,7 +123,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
var clients_1 = clients_0.Add("ios", "secret"); var clients_1 = clients_0.Add("ios", "secret");
ValidationAssert.Throws(() => GuardAppClients.CanUpdate(clients_1, command), ValidationAssert.Throws(() => GuardAppClients.CanUpdate(clients_1, command, roles),
new ValidationError("Client has already this name.", "Name")); new ValidationError("Client has already this name.", "Name"));
} }
@ -133,7 +134,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
var clients_1 = clients_0.Add("ios", "secret"); var clients_1 = clients_0.Add("ios", "secret");
ValidationAssert.Throws(() => GuardAppClients.CanUpdate(clients_1, command), ValidationAssert.Throws(() => GuardAppClients.CanUpdate(clients_1, command, roles),
new ValidationError("Client has already this role.", "Role")); new ValidationError("Client has already this role.", "Role"));
} }
@ -144,7 +145,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
var clients_1 = clients_0.Add("ios", "secret"); var clients_1 = clients_0.Add("ios", "secret");
GuardAppClients.CanUpdate(clients_1, command); GuardAppClients.CanUpdate(clients_1, command, roles);
} }
} }
} }

21
tests/Squidex.Domain.Apps.Entities.Tests/Apps/Guards/GuardAppContributorsTests.cs

@ -27,6 +27,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
private readonly IUserResolver users = A.Fake<IUserResolver>(); private readonly IUserResolver users = A.Fake<IUserResolver>();
private readonly IAppLimitsPlan appPlan = A.Fake<IAppLimitsPlan>(); private readonly IAppLimitsPlan appPlan = A.Fake<IAppLimitsPlan>();
private readonly AppContributors contributors_0 = AppContributors.Empty; private readonly AppContributors contributors_0 = AppContributors.Empty;
private readonly Roles roles = Roles.CreateDefaults("my-app");
public GuardAppContributorsTests() public GuardAppContributorsTests()
{ {
@ -54,7 +55,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
{ {
var command = new AssignContributor(); var command = new AssignContributor();
return ValidationAssert.ThrowsAsync(() => GuardAppContributors.CanAssign(contributors_0, command, users, appPlan), return ValidationAssert.ThrowsAsync(() => GuardAppContributors.CanAssign(contributors_0, command, users, appPlan, roles),
new ValidationError("Contributor id is required.", "ContributorId")); new ValidationError("Contributor id is required.", "ContributorId"));
} }
@ -63,7 +64,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
{ {
var command = new AssignContributor { ContributorId = "1", Role = "Invalid" }; var command = new AssignContributor { ContributorId = "1", Role = "Invalid" };
return ValidationAssert.ThrowsAsync(() => GuardAppContributors.CanAssign(contributors_0, command, users, appPlan), return ValidationAssert.ThrowsAsync(() => GuardAppContributors.CanAssign(contributors_0, command, users, appPlan, roles),
new ValidationError("Role is not valid.", "Role")); new ValidationError("Role is not valid.", "Role"));
} }
@ -74,7 +75,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
var contributors_1 = contributors_0.Assign("1", Role.Owner); var contributors_1 = contributors_0.Assign("1", Role.Owner);
return ValidationAssert.ThrowsAsync(() => GuardAppContributors.CanAssign(contributors_1, command, users, appPlan), return ValidationAssert.ThrowsAsync(() => GuardAppContributors.CanAssign(contributors_1, command, users, appPlan, roles),
new ValidationError("Contributor has already this role.", "Role")); new ValidationError("Contributor has already this role.", "Role"));
} }
@ -83,7 +84,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
{ {
var command = new AssignContributor { ContributorId = "notfound", Role = Role.Owner }; var command = new AssignContributor { ContributorId = "notfound", Role = Role.Owner };
return Assert.ThrowsAsync<DomainObjectNotFoundException>(() => GuardAppContributors.CanAssign(contributors_0, command, users, appPlan)); return Assert.ThrowsAsync<DomainObjectNotFoundException>(() => GuardAppContributors.CanAssign(contributors_0, command, users, appPlan, roles));
} }
[Fact] [Fact]
@ -91,7 +92,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
{ {
var command = new AssignContributor { ContributorId = "3", Role = Role.Editor, Actor = new RefToken("user", "3") }; var command = new AssignContributor { ContributorId = "3", Role = Role.Editor, Actor = new RefToken("user", "3") };
return Assert.ThrowsAsync<DomainForbiddenException>(() => GuardAppContributors.CanAssign(contributors_0, command, users, appPlan)); return Assert.ThrowsAsync<DomainForbiddenException>(() => GuardAppContributors.CanAssign(contributors_0, command, users, appPlan, roles));
} }
[Fact] [Fact]
@ -105,7 +106,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
var contributors_1 = contributors_0.Assign("1", Role.Owner); var contributors_1 = contributors_0.Assign("1", Role.Owner);
var contributors_2 = contributors_1.Assign("2", Role.Editor); var contributors_2 = contributors_1.Assign("2", Role.Editor);
return ValidationAssert.ThrowsAsync(() => GuardAppContributors.CanAssign(contributors_2, command, users, appPlan), return ValidationAssert.ThrowsAsync(() => GuardAppContributors.CanAssign(contributors_2, command, users, appPlan, roles),
new ValidationError("You have reached the maximum number of contributors for your plan.")); new ValidationError("You have reached the maximum number of contributors for your plan."));
} }
@ -114,7 +115,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
{ {
var command = new AssignContributor { ContributorId = "1@email.com" }; var command = new AssignContributor { ContributorId = "1@email.com" };
await GuardAppContributors.CanAssign(contributors_0, command, users, appPlan); await GuardAppContributors.CanAssign(contributors_0, command, users, appPlan, roles);
Assert.Equal("1", command.ContributorId); Assert.Equal("1", command.ContributorId);
} }
@ -124,7 +125,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
{ {
var command = new AssignContributor { ContributorId = "1" }; var command = new AssignContributor { ContributorId = "1" };
return GuardAppContributors.CanAssign(contributors_0, command, users, appPlan); return GuardAppContributors.CanAssign(contributors_0, command, users, appPlan, roles);
} }
[Fact] [Fact]
@ -134,7 +135,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
var contributors_1 = contributors_0.Assign("1", Role.Editor); var contributors_1 = contributors_0.Assign("1", Role.Editor);
return GuardAppContributors.CanAssign(contributors_1, command, users, appPlan); return GuardAppContributors.CanAssign(contributors_1, command, users, appPlan, roles);
} }
[Fact] [Fact]
@ -148,7 +149,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
var contributors_1 = contributors_0.Assign("1", Role.Editor); var contributors_1 = contributors_0.Assign("1", Role.Editor);
var contributors_2 = contributors_1.Assign("2", Role.Editor); var contributors_2 = contributors_1.Assign("2", Role.Editor);
return GuardAppContributors.CanAssign(contributors_2, command, users, appPlan); return GuardAppContributors.CanAssign(contributors_2, command, users, appPlan, roles);
} }
[Fact] [Fact]

Loading…
Cancel
Save