Browse Source

Fix for restore from client.

pull/346/head
Sebastian Stehle 7 years ago
parent
commit
1e5ba27fb0
  1. 3
      src/Squidex.Domain.Apps.Entities/Backup/IRestoreGrain.cs
  2. 38
      src/Squidex.Domain.Apps.Entities/Backup/RestoreGrain.cs
  3. 4
      src/Squidex.Domain.Apps.Entities/Backup/State/RestoreStateJob.cs
  4. 19
      src/Squidex.Infrastructure/Security/Extensions.cs
  5. 3
      src/Squidex/Areas/Api/Controllers/Backups/RestoreController.cs
  6. 21
      src/Squidex/Pipeline/CommandMiddlewares/EnrichWithActorCommandMiddleware.cs

3
src/Squidex.Domain.Apps.Entities/Backup/IRestoreGrain.cs

@ -8,13 +8,14 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Orleans; using Orleans;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Orleans; using Squidex.Infrastructure.Orleans;
namespace Squidex.Domain.Apps.Entities.Backup namespace Squidex.Domain.Apps.Entities.Backup
{ {
public interface IRestoreGrain : IGrainWithStringKey public interface IRestoreGrain : IGrainWithStringKey
{ {
Task RestoreAsync(Uri url, string newAppName = null); Task RestoreAsync(Uri url, RefToken actor, string newAppName = null);
Task<J<IRestoreJob>> GetJobAsync(); Task<J<IRestoreJob>> GetJobAsync();
} }

38
src/Squidex.Domain.Apps.Entities/Backup/RestoreGrain.cs

@ -37,7 +37,6 @@ namespace Squidex.Domain.Apps.Entities.Backup
private readonly IEventDataFormatter eventDataFormatter; private readonly IEventDataFormatter eventDataFormatter;
private readonly ISemanticLog log; private readonly ISemanticLog log;
private readonly IStreamNameResolver streamNameResolver; private readonly IStreamNameResolver streamNameResolver;
private RefToken actor;
private RestoreStateJob CurrentJob private RestoreStateJob CurrentJob
{ {
@ -80,8 +79,6 @@ namespace Squidex.Domain.Apps.Entities.Backup
protected override Task OnActivateAsync(string key) protected override Task OnActivateAsync(string key)
{ {
actor = new RefToken(RefTokenType.Subject, key);
RecoverAfterRestartAsync().Forget(); RecoverAfterRestartAsync().Forget();
return TaskHelper.Done; return TaskHelper.Done;
@ -100,9 +97,10 @@ namespace Squidex.Domain.Apps.Entities.Backup
} }
} }
public Task RestoreAsync(Uri url, string newAppName) public Task RestoreAsync(Uri url, RefToken actor, string newAppName)
{ {
Guard.NotNull(url, nameof(url)); Guard.NotNull(url, nameof(url));
Guard.NotNull(actor, nameof(actor));
if (!string.IsNullOrWhiteSpace(newAppName)) if (!string.IsNullOrWhiteSpace(newAppName))
{ {
@ -118,6 +116,7 @@ namespace Squidex.Domain.Apps.Entities.Backup
{ {
Id = Guid.NewGuid(), Id = Guid.NewGuid(),
NewAppName = newAppName, NewAppName = newAppName,
Actor = actor,
Started = clock.GetCurrentInstant(), Started = clock.GetCurrentInstant(),
Status = JobStatus.Started, Status = JobStatus.Started,
Url = url Url = url
@ -238,16 +237,25 @@ namespace Squidex.Domain.Apps.Entities.Backup
private async Task AssignContributorAsync() private async Task AssignContributorAsync()
{ {
await commandBus.PublishAsync(new AssignContributor var actor = CurrentJob.Actor;
{
Actor = actor,
AppId = CurrentJob.AppId,
ContributorId = actor.Identifier,
IsRestore = true,
Role = Role.Owner
});
Log("Assigned current user."); if (string.Equals(actor?.Type, RefTokenType.Subject))
{
await commandBus.PublishAsync(new AssignContributor
{
Actor = actor,
AppId = CurrentJob.AppId,
ContributorId = actor.Identifier,
IsRestore = true,
Role = Role.Owner
});
Log("Assigned current user.");
}
else
{
Log("Current user not assigned because restore was triggered by client.");
}
} }
private async Task CleanupAsync() private async Task CleanupAsync()
@ -286,7 +294,7 @@ namespace Squidex.Domain.Apps.Entities.Backup
{ {
if (@event.Payload is SquidexEvent squidexEvent) if (@event.Payload is SquidexEvent squidexEvent)
{ {
squidexEvent.Actor = actor; squidexEvent.Actor = CurrentJob.Actor;
} }
if (@event.Payload is AppCreated appCreated) if (@event.Payload is AppCreated appCreated)
@ -306,7 +314,7 @@ namespace Squidex.Domain.Apps.Entities.Backup
foreach (var handler in handlers) foreach (var handler in handlers)
{ {
if (!await handler.RestoreEventAsync(@event, CurrentJob.AppId, reader, actor)) if (!await handler.RestoreEventAsync(@event, CurrentJob.AppId, reader, CurrentJob.Actor))
{ {
return; return;
} }

4
src/Squidex.Domain.Apps.Entities/Backup/State/RestoreStateJob.cs

@ -9,6 +9,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using NodaTime; using NodaTime;
using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Entities.Backup.State namespace Squidex.Domain.Apps.Entities.Backup.State
{ {
@ -24,6 +25,9 @@ namespace Squidex.Domain.Apps.Entities.Backup.State
[DataMember] [DataMember]
public Guid AppId { get; set; } public Guid AppId { get; set; }
[DataMember]
public RefToken Actor { get; set; }
[DataMember] [DataMember]
public Uri Url { get; set; } public Uri Url { get; set; }

19
src/Squidex.Infrastructure/Security/Extensions.cs

@ -13,6 +13,25 @@ namespace Squidex.Infrastructure.Security
{ {
public static class Extensions public static class Extensions
{ {
public static RefToken Token(this ClaimsPrincipal principal)
{
var subjectId = principal.OpenIdSubject();
if (!string.IsNullOrWhiteSpace(subjectId))
{
return new RefToken(subjectId, RefTokenType.Subject);
}
var clientId = principal.OpenIdClientId();
if (!string.IsNullOrWhiteSpace(clientId))
{
return new RefToken(clientId, RefTokenType.Client);
}
return null;
}
public static string OpenIdSubject(this ClaimsPrincipal principal) public static string OpenIdSubject(this ClaimsPrincipal principal)
{ {
return principal.Claims.FirstOrDefault(x => x.Type == OpenIdClaims.Subject)?.Value; return principal.Claims.FirstOrDefault(x => x.Type == OpenIdClaims.Subject)?.Value;

3
src/Squidex/Areas/Api/Controllers/Backups/RestoreController.cs

@ -12,6 +12,7 @@ using Squidex.Areas.Api.Controllers.Backups.Models;
using Squidex.Domain.Apps.Entities.Backup; using Squidex.Domain.Apps.Entities.Backup;
using Squidex.Infrastructure.Commands; using Squidex.Infrastructure.Commands;
using Squidex.Infrastructure.Orleans; using Squidex.Infrastructure.Orleans;
using Squidex.Infrastructure.Security;
using Squidex.Pipeline; using Squidex.Pipeline;
using Squidex.Shared; using Squidex.Shared;
@ -71,7 +72,7 @@ namespace Squidex.Areas.Api.Controllers.Backups
{ {
var restoreGrain = grainFactory.GetGrain<IRestoreGrain>(SingleGrain.Id); var restoreGrain = grainFactory.GetGrain<IRestoreGrain>(SingleGrain.Id);
await restoreGrain.RestoreAsync(request.Url, request.Name); await restoreGrain.RestoreAsync(request.Url, User.Token(), request.Name);
return NoContent(); return NoContent();
} }

21
src/Squidex/Pipeline/CommandMiddlewares/EnrichWithActorCommandMiddleware.cs

@ -10,7 +10,6 @@ using System.Security;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Squidex.Domain.Apps.Entities; using Squidex.Domain.Apps.Entities;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Commands; using Squidex.Infrastructure.Commands;
using Squidex.Infrastructure.Security; using Squidex.Infrastructure.Security;
@ -34,11 +33,11 @@ namespace Squidex.Pipeline.CommandMiddlewares
if (context.Command is SquidexCommand squidexCommand) if (context.Command is SquidexCommand squidexCommand)
{ {
var user = httpContextAccessor.HttpContext.User;
if (squidexCommand.Actor == null) if (squidexCommand.Actor == null)
{ {
var actorToken = var actorToken = user.Token();
FindActorFromSubject() ??
FindActorFromClient();
squidexCommand.Actor = actorToken ?? throw new SecurityException("No actor with subject or client id available."); squidexCommand.Actor = actorToken ?? throw new SecurityException("No actor with subject or client id available.");
} }
@ -51,19 +50,5 @@ namespace Squidex.Pipeline.CommandMiddlewares
return next(); return next();
} }
private RefToken FindActorFromSubject()
{
var subjectId = httpContextAccessor.HttpContext.User.OpenIdSubject();
return subjectId == null ? null : new RefToken(RefTokenType.Subject, subjectId);
}
private RefToken FindActorFromClient()
{
var clientId = httpContextAccessor.HttpContext.User.OpenIdClientId();
return clientId == null ? null : new RefToken(RefTokenType.Client, clientId);
}
} }
} }

Loading…
Cancel
Save