Browse Source

Client permissions

pull/131/head
Sebastian Stehle 8 years ago
parent
commit
8518e13454
  1. 7
      src/Squidex.Domain.Apps.Events/Apps/AppClientUpdated.cs
  2. 2
      src/Squidex.Domain.Apps.Events/Apps/AppContributorAssigned.cs
  3. 29
      src/Squidex.Domain.Apps.Events/Apps/Old/AppClientChanged.cs
  4. 3
      src/Squidex.Domain.Apps.Read.MongoDb/Apps/MongoAppEntityClient.cs
  5. 2
      src/Squidex.Domain.Apps.Read.MongoDb/Apps/MongoAppEntityContributor.cs
  6. 4
      src/Squidex.Domain.Apps.Read.MongoDb/Apps/MongoAppRepository_EventHandling.cs
  7. 4
      src/Squidex.Domain.Apps.Read/Apps/IAppClientEntity.cs
  8. 2
      src/Squidex.Domain.Apps.Read/Apps/IAppContributorEntity.cs
  9. 2
      src/Squidex.Domain.Apps.Read/Apps/Services/Implementations/CachingAppProvider.cs
  10. 18
      src/Squidex.Domain.Apps.Write/Apps/AppClient.cs
  11. 7
      src/Squidex.Domain.Apps.Write/Apps/AppClients.cs
  12. 12
      src/Squidex.Domain.Apps.Write/Apps/AppContributors.cs
  13. 10
      src/Squidex.Domain.Apps.Write/Apps/AppDomainObject.cs
  14. 10
      src/Squidex.Domain.Apps.Write/Apps/Commands/AssignContributor.cs
  15. 12
      src/Squidex.Domain.Apps.Write/Apps/Commands/UpdateClient.cs
  16. 5
      src/Squidex.Infrastructure/ValidationException.cs
  17. 2
      src/Squidex/Controllers/Api/Apps/Models/AppDto.cs
  18. 8
      src/Squidex/Controllers/Api/Apps/Models/ClientDto.cs
  19. 2
      src/Squidex/Controllers/Api/Apps/Models/ContributorDto.cs
  20. 4
      src/Squidex/Pipeline/AppApiFilter.cs
  21. 11
      src/Squidex/app/features/settings/pages/clients/client.component.html
  22. 4
      src/Squidex/app/features/settings/pages/clients/client.component.ts
  23. 2
      src/Squidex/app/features/settings/pages/clients/clients-page.component.html
  24. 6
      src/Squidex/app/features/settings/pages/clients/clients-page.component.ts
  25. 7
      src/Squidex/app/features/settings/pages/contributors/contributors-page.component.ts
  26. 28
      src/Squidex/app/shared/services/app-clients.service.spec.ts
  27. 14
      src/Squidex/app/shared/services/app-clients.service.ts
  28. 2
      tests/Squidex.Domain.Apps.Core.Tests/Schemas/SchemaTests.cs
  29. 25
      tests/Squidex.Domain.Apps.Write.Tests/Apps/AppDomainObjectTests.cs

7
src/Squidex.Domain.Apps.Events/Apps/AppClientChanged.cs → src/Squidex.Domain.Apps.Events/Apps/AppClientUpdated.cs

@ -6,15 +6,16 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using Squidex.Domain.Apps.Core.Apps;
using Squidex.Infrastructure.CQRS.Events; using Squidex.Infrastructure.CQRS.Events;
namespace Squidex.Domain.Apps.Events.Apps namespace Squidex.Domain.Apps.Events.Apps
{ {
[EventType(nameof(AppClientChanged))] [EventType(nameof(AppClientUpdated))]
public sealed class AppClientChanged : AppEvent public sealed class AppClientUpdated : AppEvent
{ {
public string Id { get; set; } public string Id { get; set; }
public bool IsReader { get; set; } public AppClientPermission Permission { get; set; }
} }
} }

2
src/Squidex.Domain.Apps.Events/Apps/AppContributorAssigned.cs

@ -16,6 +16,6 @@ namespace Squidex.Domain.Apps.Events.Apps
{ {
public string ContributorId { get; set; } public string ContributorId { get; set; }
public AppPermission Permission { get; set; } public AppContributorPermission Permission { get; set; }
} }
} }

29
src/Squidex.Domain.Apps.Events/Apps/Old/AppClientChanged.cs

@ -0,0 +1,29 @@
// ==========================================================================
// AppClientChanged.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using Squidex.Domain.Apps.Core.Apps;
using Squidex.Infrastructure.CQRS.Events;
using Squidex.Infrastructure.Reflection;
namespace Squidex.Domain.Apps.Events.Apps.Old
{
[EventType(nameof(AppClientUpdated))]
public sealed class AppClientChanged : AppEvent, IMigratedEvent
{
public string Id { get; set; }
public bool IsReader { get; set; }
public IEvent Migrate()
{
var permission = IsReader ? AppClientPermission.Reader : AppClientPermission.Editor;
return SimpleMapper.Map(this, new AppClientUpdated { Permission = permission });
}
}
}

3
src/Squidex.Domain.Apps.Read.MongoDb/Apps/MongoAppEntityClient.cs

@ -7,6 +7,7 @@
// ========================================================================== // ==========================================================================
using MongoDB.Bson.Serialization.Attributes; using MongoDB.Bson.Serialization.Attributes;
using Squidex.Domain.Apps.Core.Apps;
using Squidex.Domain.Apps.Read.Apps; using Squidex.Domain.Apps.Read.Apps;
namespace Squidex.Domain.Apps.Read.MongoDb.Apps namespace Squidex.Domain.Apps.Read.MongoDb.Apps
@ -27,7 +28,7 @@ namespace Squidex.Domain.Apps.Read.MongoDb.Apps
[BsonIgnoreIfDefault] [BsonIgnoreIfDefault]
[BsonElement] [BsonElement]
public bool IsReader { get; set; } public AppClientPermission Permission { get; set; }
string IAppClientEntity.Name string IAppClientEntity.Name
{ {

2
src/Squidex.Domain.Apps.Read.MongoDb/Apps/MongoAppEntityContributor.cs

@ -20,6 +20,6 @@ namespace Squidex.Domain.Apps.Read.MongoDb.Apps
[BsonRequired] [BsonRequired]
[BsonElement] [BsonElement]
public AppPermission Permission { get; set; } public AppContributorPermission Permission { get; set; }
} }
} }

4
src/Squidex.Domain.Apps.Read.MongoDb/Apps/MongoAppRepository_EventHandling.cs

@ -66,11 +66,11 @@ namespace Squidex.Domain.Apps.Read.MongoDb.Apps
}); });
} }
protected Task On(AppClientChanged @event, EnvelopeHeaders headers) protected Task On(AppClientUpdated @event, EnvelopeHeaders headers)
{ {
return Collection.UpdateAsync(@event, headers, a => return Collection.UpdateAsync(@event, headers, a =>
{ {
a.Clients[@event.Id].IsReader = @event.IsReader; a.Clients[@event.Id].Permission = @event.Permission;
}); });
} }

4
src/Squidex.Domain.Apps.Read/Apps/IAppClientEntity.cs

@ -6,6 +6,8 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using Squidex.Domain.Apps.Core.Apps;
namespace Squidex.Domain.Apps.Read.Apps namespace Squidex.Domain.Apps.Read.Apps
{ {
public interface IAppClientEntity public interface IAppClientEntity
@ -16,6 +18,6 @@ namespace Squidex.Domain.Apps.Read.Apps
string Secret { get; } string Secret { get; }
bool IsReader { get; } AppClientPermission Permission { get; }
} }
} }

2
src/Squidex.Domain.Apps.Read/Apps/IAppContributorEntity.cs

@ -14,6 +14,6 @@ namespace Squidex.Domain.Apps.Read.Apps
{ {
string ContributorId { get; } string ContributorId { get; }
AppPermission Permission { get; } AppContributorPermission Permission { get; }
} }
} }

2
src/Squidex.Domain.Apps.Read/Apps/Services/Implementations/CachingAppProvider.cs

@ -98,7 +98,7 @@ namespace Squidex.Domain.Apps.Read.Apps.Services.Implementations
} }
if (@event.Payload is AppClientAttached || if (@event.Payload is AppClientAttached ||
@event.Payload is AppClientChanged || @event.Payload is AppClientUpdated ||
@event.Payload is AppClientRenamed || @event.Payload is AppClientRenamed ||
@event.Payload is AppClientRevoked || @event.Payload is AppClientRevoked ||
@event.Payload is AppPlanChanged || @event.Payload is AppPlanChanged ||

18
src/Squidex.Domain.Apps.Write/Apps/AppClient.cs

@ -7,6 +7,7 @@
// ========================================================================== // ==========================================================================
using System; using System;
using Squidex.Domain.Apps.Core.Apps;
using Squidex.Infrastructure; using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Write.Apps namespace Squidex.Domain.Apps.Write.Apps
@ -15,28 +16,29 @@ namespace Squidex.Domain.Apps.Write.Apps
{ {
private readonly string name; private readonly string name;
private readonly string secret; private readonly string secret;
private readonly bool isReader; private readonly AppClientPermission permission;
public AppClient(string secret, string name, bool isReader) public AppClient(string secret, string name, AppClientPermission permission)
{ {
Guard.NotNullOrEmpty(name, nameof(name)); Guard.NotNullOrEmpty(name, nameof(name));
Guard.NotNullOrEmpty(secret, nameof(secret)); Guard.NotNullOrEmpty(secret, nameof(secret));
Guard.Enum(permission, nameof(permission));
this.name = name; this.name = name;
this.secret = secret; this.secret = secret;
this.isReader = isReader; this.permission = permission;
} }
public AppClient Change(bool newIsReader, Func<string> message) public AppClient Update(AppClientPermission newPermission, Func<string> message)
{ {
if (isReader == newIsReader) if (permission == newPermission)
{ {
var error = new ValidationError("Client has already the reader state.", "IsReader"); var error = new ValidationError("Client has already the permission.", "IsReader");
throw new ValidationException(message(), error); throw new ValidationException(message(), error);
} }
return new AppClient(secret, name, newIsReader); return new AppClient(secret, name, newPermission);
} }
public AppClient Rename(string newName, Func<string> message) public AppClient Rename(string newName, Func<string> message)
@ -48,7 +50,7 @@ namespace Squidex.Domain.Apps.Write.Apps
throw new ValidationException(message(), error); throw new ValidationException(message(), error);
} }
return new AppClient(secret, newName, isReader); return new AppClient(secret, newName, permission);
} }
} }
} }

7
src/Squidex.Domain.Apps.Write/Apps/AppClients.cs

@ -8,6 +8,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Squidex.Domain.Apps.Core.Apps;
using Squidex.Infrastructure; using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Write.Apps namespace Squidex.Domain.Apps.Write.Apps
@ -25,7 +26,7 @@ namespace Squidex.Domain.Apps.Write.Apps
{ {
ThrowIfFound(id, () => "Cannot add client"); ThrowIfFound(id, () => "Cannot add client");
clients[id] = new AppClient(secret, id, false); clients[id] = new AppClient(secret, id, AppClientPermission.Editor);
} }
public void Rename(string clientId, string name) public void Rename(string clientId, string name)
@ -35,11 +36,11 @@ namespace Squidex.Domain.Apps.Write.Apps
clients[clientId] = clients[clientId].Rename(name, () => "Cannot rename client"); clients[clientId] = clients[clientId].Rename(name, () => "Cannot rename client");
} }
public void Change(string clientId, bool isReader) public void Update(string clientId, AppClientPermission permission)
{ {
ThrowIfNotFound(clientId); ThrowIfNotFound(clientId);
clients[clientId] = clients[clientId].Change(isReader, () => "Cannot change client"); clients[clientId] = clients[clientId].Update(permission, () => "Cannot update client");
} }
public void Revoke(string clientId) public void Revoke(string clientId)

12
src/Squidex.Domain.Apps.Write/Apps/AppContributors.cs

@ -16,14 +16,14 @@ namespace Squidex.Domain.Apps.Write.Apps
{ {
public class AppContributors public class AppContributors
{ {
private readonly Dictionary<string, AppPermission> contributors = new Dictionary<string, AppPermission>(); private readonly Dictionary<string, AppContributorPermission> contributors = new Dictionary<string, AppContributorPermission>();
public int Count public int Count
{ {
get { return contributors.Count; } get { return contributors.Count; }
} }
public void Assign(string contributorId, AppPermission permission) public void Assign(string contributorId, AppContributorPermission permission)
{ {
string Message() => "Cannot assign contributor"; string Message() => "Cannot assign contributor";
@ -51,7 +51,7 @@ namespace Squidex.Domain.Apps.Write.Apps
} }
} }
private void ThrowIfFound(string contributorId, AppPermission permission, Func<string> message) private void ThrowIfFound(string contributorId, AppContributorPermission permission, Func<string> message)
{ {
if (contributors.TryGetValue(contributorId, out var currentPermission) && currentPermission == permission) if (contributors.TryGetValue(contributorId, out var currentPermission) && currentPermission == permission)
{ {
@ -61,13 +61,13 @@ namespace Squidex.Domain.Apps.Write.Apps
} }
} }
private void ThrowIfNoOwner(Action<Dictionary<string, AppPermission>> change, Func<string> message) private void ThrowIfNoOwner(Action<Dictionary<string, AppContributorPermission>> change, Func<string> message)
{ {
var contributorsCopy = new Dictionary<string, AppPermission>(contributors); var contributorsCopy = new Dictionary<string, AppContributorPermission>(contributors);
change(contributorsCopy); change(contributorsCopy);
if (contributorsCopy.All(x => x.Value != AppPermission.Owner)) if (contributorsCopy.All(x => x.Value != AppContributorPermission.Owner))
{ {
var error = new ValidationError("Contributor is the last owner", "ContributorId"); var error = new ValidationError("Contributor is the last owner", "ContributorId");

10
src/Squidex.Domain.Apps.Write/Apps/AppDomainObject.cs

@ -70,9 +70,9 @@ namespace Squidex.Domain.Apps.Write.Apps
clients.Add(@event.Id, @event.Secret); clients.Add(@event.Id, @event.Secret);
} }
protected void On(AppClientChanged @event) protected void On(AppClientUpdated @event)
{ {
clients.Change(@event.Id, @event.IsReader); clients.Update(@event.Id, @event.Permission);
} }
protected void On(AppClientRenamed @event) protected void On(AppClientRenamed @event)
@ -139,9 +139,9 @@ namespace Squidex.Domain.Apps.Write.Apps
RaiseEvent(SimpleMapper.Map(command, new AppClientRenamed())); RaiseEvent(SimpleMapper.Map(command, new AppClientRenamed()));
} }
if (command.IsReader.HasValue) if (command.Permission.HasValue)
{ {
RaiseEvent(SimpleMapper.Map(command, new AppClientChanged { IsReader = command.IsReader.Value })); RaiseEvent(SimpleMapper.Map(command, new AppClientUpdated { Permission = command.Permission.Value }));
} }
return this; return this;
@ -253,7 +253,7 @@ namespace Squidex.Domain.Apps.Write.Apps
private static AppContributorAssigned CreateInitialOwner(NamedId<Guid> id, SquidexCommand command) private static AppContributorAssigned CreateInitialOwner(NamedId<Guid> id, SquidexCommand command)
{ {
return new AppContributorAssigned { AppId = id, ContributorId = command.Actor.Identifier, Permission = AppPermission.Owner }; return new AppContributorAssigned { AppId = id, ContributorId = command.Actor.Identifier, Permission = AppContributorPermission.Owner };
} }
private void ThrowIfOtherUser(ChangePlan command) private void ThrowIfOtherUser(ChangePlan command)

10
src/Squidex.Domain.Apps.Write/Apps/Commands/AssignContributor.cs

@ -16,18 +16,18 @@ namespace Squidex.Domain.Apps.Write.Apps.Commands
{ {
public string ContributorId { get; set; } public string ContributorId { get; set; }
public AppPermission Permission { get; set; } public AppContributorPermission Permission { get; set; }
public void Validate(IList<ValidationError> errors) public void Validate(IList<ValidationError> errors)
{ {
if (Permission.IsEnumValue()) if (string.IsNullOrWhiteSpace(ContributorId))
{ {
errors.Add(new ValidationError("Permission is not valid", nameof(Permission))); errors.Add(new ValidationError("Contributor id not assigned", nameof(ContributorId)));
} }
if (string.IsNullOrWhiteSpace(ContributorId)) if (!Permission.IsEnumValue())
{ {
errors.Add(new ValidationError("Contributor id not assigned", nameof(ContributorId))); errors.Add(new ValidationError("Permission is not valid", nameof(Permission)));
} }
} }
} }

12
src/Squidex.Domain.Apps.Write/Apps/Commands/UpdateClient.cs

@ -7,6 +7,7 @@
// ========================================================================== // ==========================================================================
using System.Collections.Generic; using System.Collections.Generic;
using Squidex.Domain.Apps.Core.Apps;
using Squidex.Infrastructure; using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Write.Apps.Commands namespace Squidex.Domain.Apps.Write.Apps.Commands
@ -17,7 +18,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Commands
public string Name { get; set; } public string Name { get; set; }
public bool? IsReader { get; set; } public AppClientPermission? Permission { get; set; }
public void Validate(IList<ValidationError> errors) public void Validate(IList<ValidationError> errors)
{ {
@ -26,9 +27,14 @@ namespace Squidex.Domain.Apps.Write.Apps.Commands
errors.Add(new ValidationError("Client id must be a valid slug", nameof(Id))); errors.Add(new ValidationError("Client id must be a valid slug", nameof(Id)));
} }
if (string.IsNullOrWhiteSpace(Name) && IsReader == null) if (string.IsNullOrWhiteSpace(Name) && Permission == null)
{ {
errors.Add(new ValidationError("Either name or reader state must be defined.", nameof(Name), nameof(IsReader))); errors.Add(new ValidationError("Either name or permission must be defined.", nameof(Name), nameof(Permission)));
}
if (Permission.HasValue && !Permission.Value.IsEnumValue())
{
errors.Add(new ValidationError("Permission is not valid.", nameof(Permission)));
} }
} }
} }

5
src/Squidex.Infrastructure/ValidationException.cs

@ -45,5 +45,10 @@ namespace Squidex.Infrastructure
{ {
this.errors = errors ?? FallbackErrors; this.errors = errors ?? FallbackErrors;
} }
public override string ToString()
{
return string.Join(" ", Enumerable.Repeat(Message, 1).Union(Errors.Select(x => x.Message)));
}
} }
} }

2
src/Squidex/Controllers/Api/Apps/Models/AppDto.cs

@ -48,6 +48,6 @@ namespace Squidex.Controllers.Api.Apps.Models
/// The permission level of the user. /// The permission level of the user.
/// </summary> /// </summary>
[JsonConverter(typeof(StringEnumConverter))] [JsonConverter(typeof(StringEnumConverter))]
public AppPermission Permission { get; set; } public AppContributorPermission Permission { get; set; }
} }
} }

8
src/Squidex/Controllers/Api/Apps/Models/ClientDto.cs

@ -7,6 +7,9 @@
// ========================================================================== // ==========================================================================
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Squidex.Domain.Apps.Core.Apps;
namespace Squidex.Controllers.Api.Apps.Models namespace Squidex.Controllers.Api.Apps.Models
{ {
@ -31,9 +34,10 @@ namespace Squidex.Controllers.Api.Apps.Models
public string Name { get; set; } public string Name { get; set; }
/// <summary> /// <summary>
/// Determines if the client is a reader. /// The permissions of the client.
/// </summary> /// </summary>
[Required] [Required]
public bool IsReader { get; set; } [JsonConverter(typeof(StringEnumConverter))]
public AppClientPermission Permission { get; set; }
} }
} }

2
src/Squidex/Controllers/Api/Apps/Models/ContributorDto.cs

@ -25,6 +25,6 @@ namespace Squidex.Controllers.Api.Apps.Models
/// The permission level as a contributor. /// The permission level as a contributor.
/// </summary> /// </summary>
[JsonConverter(typeof(StringEnumConverter))] [JsonConverter(typeof(StringEnumConverter))]
public AppPermission Permission { get; set; } public AppContributorPermission Permission { get; set; }
} }
} }

4
src/Squidex/Pipeline/AppApiFilter.cs

@ -124,7 +124,7 @@ namespace Squidex.Pipeline
return null; return null;
} }
return client.IsReader ? AppPermission.Reader : AppPermission.Editor; return client.Permission.ToAppPermission();
} }
private static AppPermission? FindByOpenIdSubject(IAppEntity app, ClaimsPrincipal user) private static AppPermission? FindByOpenIdSubject(IAppEntity app, ClaimsPrincipal user)
@ -138,7 +138,7 @@ namespace Squidex.Pipeline
var contributor = app.Contributors.FirstOrDefault(x => string.Equals(x.ContributorId, subject, StringComparison.OrdinalIgnoreCase)); var contributor = app.Contributors.FirstOrDefault(x => string.Equals(x.ContributorId, subject, StringComparison.OrdinalIgnoreCase));
return contributor?.Permission; return contributor?.Permission.ToAppPermission();
} }
} }
} }

11
src/Squidex/app/features/settings/pages/clients/client.component.html

@ -70,13 +70,12 @@
</td> </td>
</tr> </tr>
<tr> <tr>
<td></td> <td>Permission</td>
<td> <td>
<div class="form-check"> <select class="form-control" [ngModel]="client.permission" (ngModelChange)="updating.emit($event)">
<label class="form-check-label"> <option></option>
<input type="checkbox" [ngModel]="client.isReader" (ngModelChange)="changing.emit($event)" /> Reading only <option *ngFor="let permission of clientPermissions" [ngValue]="permission">{{permission}}</option>
</label> </select>
</div>
</td> </td>
</tr> </tr>
</table> </table>

4
src/Squidex/app/features/settings/pages/clients/client.component.ts

@ -36,7 +36,7 @@ export class ClientComponent extends ComponentBase {
public revoking = new EventEmitter(); public revoking = new EventEmitter();
@Output() @Output()
public changing = new EventEmitter<boolean>(); public updating = new EventEmitter<boolean>();
@Input() @Input()
public appName: string; public appName: string;
@ -44,6 +44,8 @@ export class ClientComponent extends ComponentBase {
@Input() @Input()
public client: AppClientDto; public client: AppClientDto;
public clientPermissions = [ 'Developer', 'Editor', 'Reader' ];
public isRenaming = false; public isRenaming = false;
public token: AccessTokenDto; public token: AccessTokenDto;

2
src/Squidex/app/features/settings/pages/clients/clients-page.component.html

@ -19,7 +19,7 @@
<div *ngFor="let client of appClients?.clients"> <div *ngFor="let client of appClients?.clients">
<sqx-client [client]="client" [appName]="appName() | async" <sqx-client [client]="client" [appName]="appName() | async"
(changing)="changeClient(client, $event)" (updating)="updateClient(client, $event)"
(renaming)="renameClient(client, $event)" (renaming)="renameClient(client, $event)"
(revoking)="revokeClient(client)"></sqx-client> (revoking)="revokeClient(client)"></sqx-client>
</div> </div>

6
src/Squidex/app/features/settings/pages/clients/clients-page.component.ts

@ -89,13 +89,13 @@ export class ClientsPageComponent extends AppComponentBase implements OnInit {
}); });
} }
public changeClient(client: AppClientDto, isReader: boolean) { public updateClient(client: AppClientDto, permission: string) {
const requestDto = new UpdateAppClientDto(undefined, isReader); const requestDto = new UpdateAppClientDto(undefined, permission);
this.appNameOnce() this.appNameOnce()
.switchMap(app => this.appClientsService.updateClient(app, client.id, requestDto, this.appClients.version)) .switchMap(app => this.appClientsService.updateClient(app, client.id, requestDto, this.appClients.version))
.subscribe(dto => { .subscribe(dto => {
this.updateClients(this.appClients.updateClient(client.change(isReader), dto.version)); this.updateClients(this.appClients.updateClient(client.update(permission), dto.version));
}, error => { }, error => {
this.notifyError(error); this.notifyError(error);
}); });

7
src/Squidex/app/features/settings/pages/contributors/contributors-page.component.ts

@ -58,12 +58,7 @@ export class ContributorsPageComponent extends AppComponentBase implements OnIni
public maxContributors = -1; public maxContributors = -1;
public usersDataSource: UsersDataSource; public usersDataSource: UsersDataSource;
public usersPermissions = [ public usersPermissions = [ 'Owner', 'Developer', 'Editor' ];
'Owner',
'Developer',
'Editor',
'Reader'
];
public get canAddContributor() { public get canAddContributor() {
return this.addContributorForm.valid && (this.maxContributors <= -1 || this.appContributors.contributors.length < this.maxContributors); return this.addContributorForm.valid && (this.maxContributors <= -1 || this.appContributors.contributors.length < this.maxContributors);

28
src/Squidex/app/shared/services/app-clients.service.spec.ts

@ -21,9 +21,9 @@ import {
} from './../'; } from './../';
describe('AppClientsDto', () => { describe('AppClientsDto', () => {
const client1 = new AppClientDto('1', '1', '1', false); const client1 = new AppClientDto('1', '1', '1', 'Editor');
const client2 = new AppClientDto('2', '2', '1', false); const client2 = new AppClientDto('2', '2', '1', 'Editor');
const client2_new = new AppClientDto('2', '2 New', '1 New', false); const client2_new = new AppClientDto('2', '2 New', '1 New', 'Editor');
const version = new Version('1'); const version = new Version('1');
const newVersion = new Version('2'); const newVersion = new Version('2');
@ -54,17 +54,17 @@ describe('AppClientsDto', () => {
describe('AppClientDto', () => { describe('AppClientDto', () => {
it('should update name property when renaming', () => { it('should update name property when renaming', () => {
const client_1 = new AppClientDto('1', 'old-name', 'secret', false); const client_1 = new AppClientDto('1', 'old-name', 'secret', 'Editor');
const client_2 = client_1.rename('new-name'); const client_2 = client_1.rename('new-name');
expect(client_2.name).toBe('new-name'); expect(client_2.name).toBe('new-name');
}); });
it('should update isReader property when changing', () => { it('should update isReader property when changing', () => {
const client_1 = new AppClientDto('1', 'old-name', 'secret', false); const client_1 = new AppClientDto('1', 'old-name', 'secret', 'Editor');
const client_2 = client_1.change(true); const client_2 = client_1.update('Developer');
expect(client_2.isReader).toBeTruthy(); expect(client_2.permission).toEqual('Developer');
}); });
}); });
@ -107,13 +107,13 @@ describe('AppClientsService', () => {
id: 'client1', id: 'client1',
name: 'Client 1', name: 'Client 1',
secret: 'secret1', secret: 'secret1',
isReader: true permission: 'Editor'
}, },
{ {
id: 'client2', id: 'client2',
name: 'Client 2', name: 'Client 2',
secret: 'secret2', secret: 'secret2',
isReader: true permission: 'Developer'
} }
], { ], {
headers: { headers: {
@ -123,8 +123,8 @@ describe('AppClientsService', () => {
expect(clients).toEqual( expect(clients).toEqual(
new AppClientsDto([ new AppClientsDto([
new AppClientDto('client1', 'Client 1', 'secret1', true), new AppClientDto('client1', 'Client 1', 'secret1', 'Editor'),
new AppClientDto('client2', 'Client 2', 'secret2', true) new AppClientDto('client2', 'Client 2', 'secret2', 'Developer')
], new Version('2'))); ], new Version('2')));
})); }));
@ -144,10 +144,10 @@ describe('AppClientsService', () => {
expect(req.request.method).toEqual('POST'); expect(req.request.method).toEqual('POST');
expect(req.request.headers.get('If-Match')).toEqual(version.value); expect(req.request.headers.get('If-Match')).toEqual(version.value);
req.flush({ id: 'client1', name: 'Client 1', secret: 'secret1', isReader: true }); req.flush({ id: 'client1', name: 'Client 1', secret: 'secret1', permission: 'Developer' });
expect(client).toEqual( expect(client).toEqual(
new AppClientDto('client1', 'Client 1', 'secret1', true)); new AppClientDto('client1', 'Client 1', 'secret1', 'Developer'));
})); }));
it('should make put request to rename client', it('should make put request to rename client',
@ -183,7 +183,7 @@ describe('AppClientsService', () => {
let accessTokenDto: AccessTokenDto | null = null; let accessTokenDto: AccessTokenDto | null = null;
appClientsService.createToken('my-app', new AppClientDto('myClientId', 'myClient', 'mySecret', false)).subscribe(result => { appClientsService.createToken('my-app', new AppClientDto('myClientId', 'myClient', 'mySecret', 'Editor')).subscribe(result => {
accessTokenDto = result; accessTokenDto = result;
}); });

14
src/Squidex/app/shared/services/app-clients.service.ts

@ -44,16 +44,16 @@ export class AppClientDto {
public readonly id: string, public readonly id: string,
public readonly name: string, public readonly name: string,
public readonly secret: string, public readonly secret: string,
public readonly isReader: boolean public readonly permission: string
) { ) {
} }
public rename(name: string): AppClientDto { public rename(name: string): AppClientDto {
return new AppClientDto(this.id, name, this.secret, this.isReader); return new AppClientDto(this.id, name, this.secret, this.permission);
} }
public change(isReader: boolean): AppClientDto { public update(permission: string): AppClientDto {
return new AppClientDto(this.id, this.name, this.secret, isReader); return new AppClientDto(this.id, this.name, this.secret, permission);
} }
} }
@ -67,7 +67,7 @@ export class CreateAppClientDto {
export class UpdateAppClientDto { export class UpdateAppClientDto {
constructor( constructor(
public readonly name?: string, public readonly name?: string,
public readonly isReader?: boolean public readonly permission?: string
) { ) {
} }
} }
@ -103,7 +103,7 @@ export class AppClientsService {
item.id, item.id,
item.name || body.id, item.name || body.id,
item.secret, item.secret,
item.isReader); item.permission);
}); });
return new AppClientsDto(clients, response.version); return new AppClientsDto(clients, response.version);
@ -122,7 +122,7 @@ export class AppClientsService {
body.id, body.id,
body.name || body.id, body.name || body.id,
body.secret, body.secret,
body.isReader); body.permission);
return new Versioned(response.version, client); return new Versioned(response.version, client);
}) })

2
tests/Squidex.Domain.Apps.Core.Tests/Schemas/SchemaTests.cs

@ -342,7 +342,7 @@ namespace Squidex.Domain.Apps.Core.Schemas
{ {
var languagesConfig = LanguagesConfig.Create(Language.DE, Language.EN); var languagesConfig = LanguagesConfig.Create(Language.DE, Language.EN);
var jsonSchema = BuildMixedSchema().BuildJsonSchema(languagesConfig.ToResolver(), (n, s) => new JsonSchema4 { SchemaReference = s }); var jsonSchema = BuildMixedSchema().BuildJsonSchema(languagesConfig.ToResolver(), (n, s) => new JsonSchema4 { Reference = s });
Assert.NotNull(jsonSchema); Assert.NotNull(jsonSchema);
} }

25
tests/Squidex.Domain.Apps.Write.Tests/Apps/AppDomainObjectTests.cs

@ -62,7 +62,7 @@ namespace Squidex.Domain.Apps.Write.Apps
sut.GetUncomittedEvents() sut.GetUncomittedEvents()
.ShouldHaveSameEvents( .ShouldHaveSameEvents(
CreateEvent(new AppCreated { Name = AppName }), CreateEvent(new AppCreated { Name = AppName }),
CreateEvent(new AppContributorAssigned { ContributorId = User.Identifier, Permission = AppPermission.Owner }), CreateEvent(new AppContributorAssigned { ContributorId = User.Identifier, Permission = AppContributorPermission.Owner }),
CreateEvent(new AppLanguageAdded { Language = Language.EN }) CreateEvent(new AppLanguageAdded { Language = Language.EN })
); );
} }
@ -148,7 +148,7 @@ namespace Squidex.Domain.Apps.Write.Apps
Assert.Throws<ValidationException>(() => Assert.Throws<ValidationException>(() =>
{ {
sut.AssignContributor(CreateCommand(new AssignContributor { ContributorId = User.Identifier, Permission = AppPermission.Editor })); sut.AssignContributor(CreateCommand(new AssignContributor { ContributorId = User.Identifier, Permission = AppContributorPermission.Editor }));
}); });
} }
@ -157,11 +157,11 @@ namespace Squidex.Domain.Apps.Write.Apps
{ {
CreateApp(); CreateApp();
sut.AssignContributor(CreateCommand(new AssignContributor { ContributorId = contributorId, Permission = AppPermission.Editor })); sut.AssignContributor(CreateCommand(new AssignContributor { ContributorId = contributorId, Permission = AppContributorPermission.Editor }));
Assert.Throws<ValidationException>(() => Assert.Throws<ValidationException>(() =>
{ {
sut.AssignContributor(CreateCommand(new AssignContributor { ContributorId = contributorId, Permission = AppPermission.Editor })); sut.AssignContributor(CreateCommand(new AssignContributor { ContributorId = contributorId, Permission = AppContributorPermission.Editor }));
}); });
} }
@ -170,11 +170,11 @@ namespace Squidex.Domain.Apps.Write.Apps
{ {
CreateApp(); CreateApp();
sut.AssignContributor(CreateCommand(new AssignContributor { ContributorId = contributorId, Permission = AppPermission.Editor })); sut.AssignContributor(CreateCommand(new AssignContributor { ContributorId = contributorId, Permission = AppContributorPermission.Editor }));
sut.GetUncomittedEvents() sut.GetUncomittedEvents()
.ShouldHaveSameEvents( .ShouldHaveSameEvents(
CreateEvent(new AppContributorAssigned { ContributorId = contributorId, Permission = AppPermission.Editor }) CreateEvent(new AppContributorAssigned { ContributorId = contributorId, Permission = AppContributorPermission.Editor })
); );
} }
@ -223,7 +223,7 @@ namespace Squidex.Domain.Apps.Write.Apps
{ {
CreateApp(); CreateApp();
sut.AssignContributor(CreateCommand(new AssignContributor { ContributorId = contributorId, Permission = AppPermission.Editor })); sut.AssignContributor(CreateCommand(new AssignContributor { ContributorId = contributorId, Permission = AppContributorPermission.Editor }));
sut.RemoveContributor(CreateCommand(new RemoveContributor { ContributorId = contributorId })); sut.RemoveContributor(CreateCommand(new RemoveContributor { ContributorId = contributorId }));
sut.GetUncomittedEvents().Skip(1) sut.GetUncomittedEvents().Skip(1)
@ -358,6 +358,11 @@ namespace Squidex.Domain.Apps.Write.Apps
{ {
sut.UpdateClient(CreateCommand(new UpdateClient { Id = string.Empty })); sut.UpdateClient(CreateCommand(new UpdateClient { Id = string.Empty }));
}); });
Assert.Throws<ValidationException>(() =>
{
sut.UpdateClient(CreateCommand(new UpdateClient { Permission = (AppClientPermission)int.MaxValue }));
});
} }
[Fact] [Fact]
@ -379,7 +384,7 @@ namespace Squidex.Domain.Apps.Write.Apps
Assert.Throws<ValidationException>(() => Assert.Throws<ValidationException>(() =>
{ {
sut.UpdateClient(CreateCommand(new UpdateClient { Id = clientId, IsReader = false })); sut.UpdateClient(CreateCommand(new UpdateClient { Id = clientId, Permission = AppClientPermission.Editor }));
}); });
} }
@ -403,12 +408,12 @@ namespace Squidex.Domain.Apps.Write.Apps
CreateApp(); CreateApp();
CreateClient(); CreateClient();
sut.UpdateClient(CreateCommand(new UpdateClient { Id = clientId, Name = clientNewName, IsReader = true })); sut.UpdateClient(CreateCommand(new UpdateClient { Id = clientId, Name = clientNewName, Permission = AppClientPermission.Developer }));
sut.GetUncomittedEvents() sut.GetUncomittedEvents()
.ShouldHaveSameEvents( .ShouldHaveSameEvents(
CreateEvent(new AppClientRenamed { Id = clientId, Name = clientNewName }), CreateEvent(new AppClientRenamed { Id = clientId, Name = clientNewName }),
CreateEvent(new AppClientChanged { Id = clientId, IsReader = true }) CreateEvent(new AppClientUpdated { Id = clientId, Permission = AppClientPermission.Developer })
); );
} }

Loading…
Cancel
Save