Browse Source

Small improvements

pull/1/head
Sebastian 9 years ago
parent
commit
24f2d8c807
  1. 3
      src/Squidex.Events/Apps/AppClientAttached.cs
  2. 2
      src/Squidex.Infrastructure/CQRS/IAggregate.cs
  3. 12
      src/Squidex.Write/Apps/AppClient.cs
  4. 4
      src/Squidex.Write/Apps/AppClients.cs
  5. 2
      src/Squidex.Write/Apps/AppCommandHandler.cs
  6. 6
      src/Squidex.Write/Apps/AppDomainObject.cs
  7. 5
      src/Squidex/Config/Domain/WriteModule.cs
  8. 6
      src/Squidex/Controllers/Api/Apps/Models/ClientDto.cs
  9. 16
      src/Squidex/Controllers/UI/Account/AccountController.cs
  10. 4
      src/Squidex/Views/Account/LockedOut.cshtml
  11. 20
      src/Squidex/Views/Account/LogoutCompleted.cshtml
  12. 1
      src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.ts
  13. 2
      src/Squidex/app/features/settings/pages/clients/client.component.html
  14. 2
      src/Squidex/app/features/settings/pages/clients/clients-page.component.ts
  15. 2
      src/Squidex/app/framework/angular/money.pipe.ts
  16. 1
      src/Squidex/app/shared/declarations.ts
  17. 18
      src/Squidex/app/shared/services/app-clients.service.spec.ts
  18. 11
      src/Squidex/app/shared/services/app-clients.service.ts
  19. 2
      src/Squidex/app/shared/services/auth.service.ts
  20. 1
      src/Squidex/app/shared/services/schemas.service.spec.ts
  21. 2
      src/Squidex/app/shell/pages/internal/profile-menu.component.html
  22. 4
      src/Squidex/app/shell/pages/internal/profile-menu.component.scss
  23. 12
      src/Squidex/wwwroot/styles/static.css
  24. 8
      tests/Squidex.Write.Tests/Apps/AppCommandHandlerTests.cs
  25. 17
      tests/Squidex.Write.Tests/Apps/AppDomainObjectTests.cs

3
src/Squidex.Events/Apps/AppClientAttached.cs

@ -6,7 +6,6 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using System;
using Squidex.Infrastructure; using Squidex.Infrastructure;
namespace Squidex.Events.Apps namespace Squidex.Events.Apps
@ -17,7 +16,5 @@ namespace Squidex.Events.Apps
public string Id { get; set; } public string Id { get; set; }
public string Secret { get; set; } public string Secret { get; set; }
public DateTime ExpiresUtc { get; set; }
} }
} }

2
src/Squidex.Infrastructure/CQRS/IAggregate.cs

@ -25,5 +25,3 @@ namespace Squidex.Infrastructure.CQRS
ICollection<Envelope<IEvent>> GetUncomittedEvents(); ICollection<Envelope<IEvent>> GetUncomittedEvents();
} }
} }

12
src/Squidex.Write/Apps/AppClient.cs

@ -6,7 +6,6 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using System;
using Squidex.Infrastructure; using Squidex.Infrastructure;
namespace Squidex.Write.Apps namespace Squidex.Write.Apps
@ -16,7 +15,6 @@ namespace Squidex.Write.Apps
private readonly string name; private readonly string name;
private readonly string id; private readonly string id;
private readonly string secret; private readonly string secret;
private readonly DateTime expiresUtc;
public string Id public string Id
{ {
@ -33,12 +31,7 @@ namespace Squidex.Write.Apps
get { return secret; } get { return secret; }
} }
public DateTime ExpiresUtc public AppClient(string id, string secret, string name = null)
{
get { return expiresUtc; }
}
public AppClient(string id, string secret, DateTime expiresUtc, string name = null)
{ {
Guard.NotNullOrEmpty(id, nameof(id)); Guard.NotNullOrEmpty(id, nameof(id));
Guard.NotNullOrEmpty(secret, nameof(secret)); Guard.NotNullOrEmpty(secret, nameof(secret));
@ -46,12 +39,11 @@ namespace Squidex.Write.Apps
this.id = id; this.id = id;
this.name = name; this.name = name;
this.secret = secret; this.secret = secret;
this.expiresUtc = expiresUtc;
} }
public AppClient Rename(string newName) public AppClient Rename(string newName)
{ {
return new AppClient(Id, Secret, ExpiresUtc, newName); return new AppClient(Id, Secret, newName);
} }
} }
} }

4
src/Squidex.Write/Apps/AppClients.cs

@ -23,11 +23,11 @@ namespace Squidex.Write.Apps
get { return clients; } get { return clients; }
} }
public void Add(string id, string secret, DateTime expires) public void Add(string id, string secret)
{ {
ThrowIfFound(id, () => "Cannot rename client"); ThrowIfFound(id, () => "Cannot rename client");
clients[id] = new AppClient(id, secret, expires); clients[id] = new AppClient(id, secret);
} }
public void Rename(string clientId, string name) public void Rename(string clientId, string name)

2
src/Squidex.Write/Apps/AppCommandHandler.cs

@ -80,7 +80,7 @@ namespace Squidex.Write.Apps
{ {
return handler.UpdateAsync<AppDomainObject>(command, x => return handler.UpdateAsync<AppDomainObject>(command, x =>
{ {
x.AttachClient(command, keyGenerator.GenerateKey(), command.Timestamp.AddYears(1)); x.AttachClient(command, keyGenerator.GenerateKey());
context.Succeed(x.Clients[command.Id]); context.Succeed(x.Clients[command.Id]);
}); });

6
src/Squidex.Write/Apps/AppDomainObject.cs

@ -62,7 +62,7 @@ namespace Squidex.Write.Apps
protected void On(AppClientAttached @event) protected void On(AppClientAttached @event)
{ {
clients.Add(@event.Id, @event.Secret, @event.ExpiresUtc); clients.Add(@event.Id, @event.Secret);
} }
protected void On(AppClientRenamed @event) protected void On(AppClientRenamed @event)
@ -134,13 +134,13 @@ namespace Squidex.Write.Apps
return this; return this;
} }
public AppDomainObject AttachClient(AttachClient command, string secret, DateTime expiresUtc) public AppDomainObject AttachClient(AttachClient command, string secret)
{ {
Guard.Valid(command, nameof(command), () => "Cannot attach client"); Guard.Valid(command, nameof(command), () => "Cannot attach client");
ThrowIfNotCreated(); ThrowIfNotCreated();
RaiseEvent(SimpleMapper.Map(command, new AppClientAttached { Secret = secret, ExpiresUtc = expiresUtc })); RaiseEvent(SimpleMapper.Map(command, new AppClientAttached { Secret = secret }));
return this; return this;
} }

5
src/Squidex/Config/Domain/WriteModule.cs

@ -45,22 +45,18 @@ namespace Squidex.Config.Domain
.As<ICommandHandler>() .As<ICommandHandler>()
.SingleInstance(); .SingleInstance();
builder.RegisterType<EnrichWithAggregateIdProcessor>() builder.RegisterType<EnrichWithAggregateIdProcessor>()
.As<IEventProcessor>() .As<IEventProcessor>()
.SingleInstance(); .SingleInstance();
builder.RegisterType<ClientKeyGenerator>() builder.RegisterType<ClientKeyGenerator>()
.AsSelf() .AsSelf()
.SingleInstance(); .SingleInstance();
builder.RegisterType<FieldRegistry>() builder.RegisterType<FieldRegistry>()
.AsSelf() .AsSelf()
.SingleInstance(); .SingleInstance();
builder.RegisterType<AppCommandHandler>() builder.RegisterType<AppCommandHandler>()
.As<ICommandHandler>() .As<ICommandHandler>()
.SingleInstance(); .SingleInstance();
@ -73,7 +69,6 @@ namespace Squidex.Config.Domain
.As<ICommandHandler>() .As<ICommandHandler>()
.SingleInstance(); .SingleInstance();
builder.Register<DomainObjectFactoryFunction<AppDomainObject>>(c => (id => new AppDomainObject(id, 0))) builder.Register<DomainObjectFactoryFunction<AppDomainObject>>(c => (id => new AppDomainObject(id, 0)))
.AsSelf() .AsSelf()
.SingleInstance(); .SingleInstance();

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

@ -30,11 +30,5 @@ namespace Squidex.Controllers.Api.Apps.Models
/// </summary> /// </summary>
[Required] [Required]
public string Name { get; set; } public string Name { get; set; }
/// <summary>
/// The date and time when the client key expires.
/// </summary>
[Required]
public DateTime ExpiresUtc { get; set; }
} }
} }

16
src/Squidex/Controllers/UI/Account/AccountController.cs

@ -84,6 +84,13 @@ namespace Squidex.Controllers.UI.Account
return View(); return View();
} }
[HttpGet]
[Route("account/logout-completed/")]
public IActionResult LogoutCompleted()
{
return View();
}
[HttpGet] [HttpGet]
[Route("account/error/")] [Route("account/error/")]
public IActionResult Error() public IActionResult Error()
@ -109,6 +116,15 @@ namespace Squidex.Controllers.UI.Account
return Redirect(logoutUrl); return Redirect(logoutUrl);
} }
[HttpGet]
[Route("account/logout-redirect/")]
public async Task<IActionResult> LogoutRedirect()
{
await signInManager.SignOutAsync();
return RedirectToAction(nameof(LogoutCompleted));
}
[HttpGet] [HttpGet]
[Route("account/login/")] [Route("account/login/")]
public IActionResult Login(string returnUrl = null) public IActionResult Login(string returnUrl = null)

4
src/Squidex/Views/Account/LockedOut.cshtml

@ -16,5 +16,9 @@
<p class="splash-text"> <p class="splash-text">
Your account is locked, please contact the administrator. Your account is locked, please contact the administrator.
</p> </p>
<p class="splash-text">
<a href="/identity-server/account/logout-redirect">Logout</a>
</p>
</body> </body>
</html> </html>

20
src/Squidex/Views/Account/LogoutCompleted.cshtml

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html>
<head>
<base href="/">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Squidex - Logout</title>
<link href="/styles/static.css" rel="stylesheet" />
</head>
<body>
<h1 class="splash-h1">Logged out!</h1>
<p class="splash-text">
Please close this popup.
</p>
</body>
</html>

1
src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.ts

@ -133,4 +133,3 @@ function updateSchema(schema: SchemaDto, authService: AuthService, message: Sche
schema.created, DateTime.now()); schema.created, DateTime.now());
} }

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

@ -36,7 +36,7 @@
</span> </span>
</div> </div>
<div class="client-expires">Expires: {{client.expiresUtc.toISOString()}}</div> <div class="client-expires">Access token expire after one hour</div>
</td> </td>
<td class="client-delete"> <td class="client-delete">
<button type="button" class="btn btn-link btn-danger" (click)="revoked.emit()"> <button type="button" class="btn btn-link btn-danger" (click)="revoked.emit()">

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

@ -122,5 +122,5 @@ export class ClientsPageComponent extends AppComponentBase implements OnInit {
} }
function rename(client: AppClientDto, name: string): AppClientDto { function rename(client: AppClientDto, name: string): AppClientDto {
return new AppClientDto(client.id, name, client.secret, client.expiresUtc); return new AppClientDto(client.id, name, client.secret);
}; };

2
src/Squidex/app/framework/angular/money.pipe.ts

@ -33,5 +33,3 @@ export class MoneyPipe {
return result; return result;
} }
} }

1
src/Squidex/app/shared/declarations.ts

@ -38,5 +38,4 @@ export * from './services/users.service';
export * from './utils/messages'; export * from './utils/messages';
export * from 'framework'; export * from 'framework';

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

@ -16,7 +16,6 @@ import {
AppClientsService, AppClientsService,
AuthService, AuthService,
CreateAppClientDto, CreateAppClientDto,
DateTime,
UpdateAppClientDto UpdateAppClientDto
} from './../'; } from './../';
@ -40,13 +39,11 @@ describe('AppClientsService', () => {
body: [{ body: [{
id: 'client1', id: 'client1',
name: 'Client 1', name: 'Client 1',
secret: 'secret1', secret: 'secret1'
expiresUtc: '2016-12-12T10:10'
}, { }, {
id: 'client2', id: 'client2',
name: 'Client 2', name: 'Client 2',
secret: 'secret2', secret: 'secret2'
expiresUtc: '2016-11-11T10:10'
}] }]
}) })
) )
@ -61,8 +58,8 @@ describe('AppClientsService', () => {
expect(clients).toEqual( expect(clients).toEqual(
[ [
new AppClientDto('client1', 'Client 1', 'secret1', DateTime.parseISO_UTC('2016-12-12T10:10')), new AppClientDto('client1', 'Client 1', 'secret1'),
new AppClientDto('client2', 'Client 2', 'secret2', DateTime.parseISO_UTC('2016-11-11T10:10')) new AppClientDto('client2', 'Client 2', 'secret2')
]); ]);
authService.verifyAll(); authService.verifyAll();
@ -78,8 +75,7 @@ describe('AppClientsService', () => {
body: { body: {
id: 'client1', id: 'client1',
name: 'Client 1', name: 'Client 1',
secret: 'secret1', secret: 'secret1'
expiresUtc: '2016-12-12T10:10'
} }
}) })
) )
@ -93,7 +89,7 @@ describe('AppClientsService', () => {
}); });
expect(client).toEqual( expect(client).toEqual(
new AppClientDto('client1', 'Client 1', 'secret1', DateTime.parseISO_UTC('2016-12-12T10:10'))); new AppClientDto('client1', 'Client 1', 'secret1'));
authService.verifyAll(); authService.verifyAll();
}); });
@ -145,7 +141,7 @@ describe('AppClientsService', () => {
let accessTokenDto: AccessTokenDto | null = null; let accessTokenDto: AccessTokenDto | null = null;
appClientsService.createToken('my-app', new AppClientDto('myClientId', 'myClient', 'mySecret', DateTime.now())).subscribe(result => { appClientsService.createToken('my-app', new AppClientDto('myClientId', 'myClient', 'mySecret')).subscribe(result => {
accessTokenDto = result; accessTokenDto = result;
}); });

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

@ -11,15 +11,14 @@ import { Observable } from 'rxjs';
import 'framework/angular/http-extensions'; import 'framework/angular/http-extensions';
import { ApiUrlConfig, DateTime } from 'framework'; import { ApiUrlConfig } from 'framework';
import { AuthService } from './auth.service'; import { AuthService } from './auth.service';
export class AppClientDto { export class AppClientDto {
constructor( constructor(
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 expiresUtc: DateTime
) { ) {
} }
} }
@ -67,8 +66,7 @@ export class AppClientsService {
return new AppClientDto( return new AppClientDto(
item.id, item.id,
item.name, item.name,
item.secret, item.secret);
DateTime.parseISO_UTC(item.expiresUtc));
}); });
}) })
.catchError('Failed to load clients. Please reload.'); .catchError('Failed to load clients. Please reload.');
@ -83,8 +81,7 @@ export class AppClientsService {
return new AppClientDto( return new AppClientDto(
response.id, response.id,
response.name, response.name,
response.secret, response.secret);
DateTime.parseISO_UTC(response.expiresUtc));
}) })
.catchError('Failed to add client. Please reload.'); .catchError('Failed to add client. Please reload.');
} }

2
src/Squidex/app/shared/services/auth.service.ts

@ -32,7 +32,7 @@ export class Profile {
} }
public get isAdmin(): boolean { public get isAdmin(): boolean {
return this.user.profile['role'].toUpperCase() === 'ADMINISTRATOR'; return this.user.profile['role'] && this.user.profile['role'].toUpperCase() === 'ADMINISTRATOR';
} }
public get token(): string { public get token(): string {

1
src/Squidex/app/shared/services/schemas.service.spec.ts

@ -147,7 +147,6 @@ describe('SchemasService', () => {
authService.verifyAll(); authService.verifyAll();
}); });
it('should make post request to create schema', () => { it('should make post request to create schema', () => {
const dto = new CreateSchemaDto('name'); const dto = new CreateSchemaDto('name');

2
src/Squidex/app/shell/pages/internal/profile-menu.component.html

@ -7,7 +7,7 @@
</span> </span>
<div class="dropdown-menu" *sqxModalView="modalMenu" closeAlways="true" [@fade]> <div class="dropdown-menu" *sqxModalView="modalMenu" closeAlways="true" [@fade]>
<a class="dropdown-item" [routerLink]="['/app/administration']" *ngIf="isAdmin"> <a class="dropdown-item" [routerLink]="['/app/administration']" *ngIf="isAdmin">
Administration Administration
</a> </a>

4
src/Squidex/app/shell/pages/internal/profile-menu.component.scss

@ -5,6 +5,10 @@
padding: 0; padding: 0;
} }
.nav-item {
line-height: 2rem;
}
.dropdown { .dropdown {
&-menu { &-menu {
@include absolute(2.6rem, 0, auto, auto); @include absolute(2.6rem, 0, auto, auto);

12
src/Squidex/wwwroot/styles/static.css

@ -8,12 +8,18 @@
line-height: 1.5; line-height: 1.5;
} }
.splash-h1, .splash-text { img {
vertical-align: middle;
}
.splash-h1,
.splash-text {
text-align: center; text-align: center;
} }
img { .splash-text a,
vertical-align: middle; .splash-text a:visited {
color: #146feb;
} }
.redirect-button { .redirect-button {

8
tests/Squidex.Write.Tests/Apps/AppCommandHandlerTests.cs

@ -31,7 +31,6 @@ namespace Squidex.Write.Apps
private readonly Mock<IUserRepository> userRepository = new Mock<IUserRepository>(); private readonly Mock<IUserRepository> userRepository = new Mock<IUserRepository>();
private readonly AppCommandHandler sut; private readonly AppCommandHandler sut;
private readonly AppDomainObject app; private readonly AppDomainObject app;
private readonly DateTime expiresUtc = DateTime.UtcNow.AddYears(1);
private readonly Language language = Language.DE; private readonly Language language = Language.DE;
private readonly string contributorId = Guid.NewGuid().ToString(); private readonly string contributorId = Guid.NewGuid().ToString();
private readonly string clientSecret = Guid.NewGuid().ToString(); private readonly string clientSecret = Guid.NewGuid().ToString();
@ -151,15 +150,14 @@ namespace Squidex.Write.Apps
keyGenerator.VerifyAll(); keyGenerator.VerifyAll();
context.Result<AppClient>().ShouldBeEquivalentTo( context.Result<AppClient>().ShouldBeEquivalentTo(new AppClient(clientName, clientSecret));
new AppClient(clientName, clientSecret, timestamp.AddYears(1)));
} }
[Fact] [Fact]
public async Task RenameClient_should_update_domain_object() public async Task RenameClient_should_update_domain_object()
{ {
CreateApp() CreateApp()
.AttachClient(CreateCommand(new AttachClient { Id = clientName }), clientSecret, expiresUtc); .AttachClient(CreateCommand(new AttachClient { Id = clientName }), clientSecret);
var context = CreateContextForCommand(new RenameClient { Id = clientName, Name = "New Name" }); var context = CreateContextForCommand(new RenameClient { Id = clientName, Name = "New Name" });
@ -173,7 +171,7 @@ namespace Squidex.Write.Apps
public async Task RevokeClient_should_update_domain_object() public async Task RevokeClient_should_update_domain_object()
{ {
CreateApp() CreateApp()
.AttachClient(CreateCommand(new AttachClient { Id = clientName }), clientSecret, expiresUtc); .AttachClient(CreateCommand(new AttachClient { Id = clientName }), clientSecret);
var context = CreateContextForCommand(new RevokeClient { Id = clientName }); var context = CreateContextForCommand(new RevokeClient { Id = clientName });

17
tests/Squidex.Write.Tests/Apps/AppDomainObjectTests.cs

@ -23,7 +23,6 @@ namespace Squidex.Write.Apps
public class AppDomainObjectTests : HandlerTestBase<AppDomainObject> public class AppDomainObjectTests : HandlerTestBase<AppDomainObject>
{ {
private readonly AppDomainObject sut; private readonly AppDomainObject sut;
private readonly DateTime expiresUtc = DateTime.UtcNow.AddYears(1);
private readonly string contributorId = Guid.NewGuid().ToString(); private readonly string contributorId = Guid.NewGuid().ToString();
private readonly string clientSecret = Guid.NewGuid().ToString(); private readonly string clientSecret = Guid.NewGuid().ToString();
private readonly string clientId = "client"; private readonly string clientId = "client";
@ -183,7 +182,7 @@ namespace Squidex.Write.Apps
{ {
Assert.Throws<DomainException>(() => Assert.Throws<DomainException>(() =>
{ {
sut.AttachClient(CreateCommand(new AttachClient { Id = clientId }), clientSecret, expiresUtc); sut.AttachClient(CreateCommand(new AttachClient { Id = clientId }), clientSecret);
}); });
} }
@ -194,12 +193,12 @@ namespace Squidex.Write.Apps
Assert.Throws<ValidationException>(() => Assert.Throws<ValidationException>(() =>
{ {
sut.AttachClient(CreateCommand(new AttachClient()), clientSecret, expiresUtc); sut.AttachClient(CreateCommand(new AttachClient()), clientSecret);
}); });
Assert.Throws<ValidationException>(() => Assert.Throws<ValidationException>(() =>
{ {
sut.AttachClient(CreateCommand(new AttachClient { Id = string.Empty }), clientSecret, expiresUtc); sut.AttachClient(CreateCommand(new AttachClient { Id = string.Empty }), clientSecret);
}); });
} }
@ -208,11 +207,11 @@ namespace Squidex.Write.Apps
{ {
CreateApp(); CreateApp();
sut.AttachClient(CreateCommand(new AttachClient { Id = clientId }), clientSecret, expiresUtc); sut.AttachClient(CreateCommand(new AttachClient { Id = clientId }), clientSecret);
Assert.Throws<ValidationException>(() => Assert.Throws<ValidationException>(() =>
{ {
sut.AttachClient(CreateCommand(new AttachClient { Id = clientId }), clientSecret, expiresUtc); sut.AttachClient(CreateCommand(new AttachClient { Id = clientId }), clientSecret);
}); });
} }
@ -223,11 +222,11 @@ namespace Squidex.Write.Apps
CreateApp(); CreateApp();
sut.AttachClient(CreateCommand(new AttachClient { Id = clientId, Timestamp = now }), clientSecret, expiresUtc); sut.AttachClient(CreateCommand(new AttachClient { Id = clientId, Timestamp = now }), clientSecret);
sut.GetUncomittedEvents() sut.GetUncomittedEvents()
.ShouldHaveSameEvents( .ShouldHaveSameEvents(
CreateEvent(new AppClientAttached { Id = clientId, Secret = clientSecret, ExpiresUtc = expiresUtc }) CreateEvent(new AppClientAttached { Id = clientId, Secret = clientSecret })
); );
} }
@ -510,7 +509,7 @@ namespace Squidex.Write.Apps
private void CreateClient() private void CreateClient()
{ {
sut.AttachClient(CreateCommand(new AttachClient { Id = clientId }), clientSecret, expiresUtc); sut.AttachClient(CreateCommand(new AttachClient { Id = clientId }), clientSecret);
((IAggregate)sut).ClearUncommittedEvents(); ((IAggregate)sut).ClearUncommittedEvents();
} }

Loading…
Cancel
Save