diff --git a/src/Squidex.Domain.Apps.Entities/Backup/IRestoreGrain.cs b/src/Squidex.Domain.Apps.Entities/Backup/IRestoreGrain.cs index f38df5629..6ee281401 100644 --- a/src/Squidex.Domain.Apps.Entities/Backup/IRestoreGrain.cs +++ b/src/Squidex.Domain.Apps.Entities/Backup/IRestoreGrain.cs @@ -14,7 +14,7 @@ namespace Squidex.Domain.Apps.Entities.Backup { public interface IRestoreGrain : IGrainWithStringKey { - Task RestoreAsync(Uri url); + Task RestoreAsync(Uri url, string newAppName = null); Task> GetJobAsync(); } diff --git a/src/Squidex.Domain.Apps.Entities/Backup/RestoreGrain.cs b/src/Squidex.Domain.Apps.Entities/Backup/RestoreGrain.cs index 6200c7bf5..70a7d5a50 100644 --- a/src/Squidex.Domain.Apps.Entities/Backup/RestoreGrain.cs +++ b/src/Squidex.Domain.Apps.Entities/Backup/RestoreGrain.cs @@ -105,10 +105,15 @@ namespace Squidex.Domain.Apps.Entities.Backup } } - public Task RestoreAsync(Uri url) + public Task RestoreAsync(Uri url, string newAppName) { Guard.NotNull(url, nameof(url)); + if (newAppName != null) + { + Guard.ValidSlug(newAppName, nameof(newAppName)); + } + if (CurrentJob?.Status == JobStatus.Started) { throw new DomainException("A restore operation is already running."); @@ -117,6 +122,7 @@ namespace Squidex.Domain.Apps.Entities.Backup state.Job = new RestoreStateJob { Id = Guid.NewGuid(), + NewAppName = newAppName, Started = clock.GetCurrentInstant(), Status = JobStatus.Started, Url = url @@ -267,6 +273,16 @@ namespace Squidex.Domain.Apps.Entities.Backup if (@event.Payload is AppCreated appCreated) { CurrentJob.AppId = appCreated.AppId.Id; + + if (!string.IsNullOrWhiteSpace(CurrentJob.NewAppName)) + { + appCreated.Name = CurrentJob.NewAppName; + } + } + + if (@event.Payload is AppEvent appEvent && !string.IsNullOrWhiteSpace(CurrentJob.NewAppName)) + { + appEvent.AppId = new NamedId(appEvent.AppId.Id, CurrentJob.NewAppName); } foreach (var handler in handlers) diff --git a/src/Squidex.Domain.Apps.Entities/Backup/State/RestoreStateJob.cs b/src/Squidex.Domain.Apps.Entities/Backup/State/RestoreStateJob.cs index 4140fcae2..e601232a8 100644 --- a/src/Squidex.Domain.Apps.Entities/Backup/State/RestoreStateJob.cs +++ b/src/Squidex.Domain.Apps.Entities/Backup/State/RestoreStateJob.cs @@ -23,6 +23,9 @@ namespace Squidex.Domain.Apps.Entities.Backup.State [JsonProperty] public Uri Url { get; set; } + [JsonProperty] + public string NewAppName { get; set; } + [JsonProperty] public Instant Started { get; set; } diff --git a/src/Squidex/Areas/Api/Controllers/Backups/Models/RestoreRequest.cs b/src/Squidex/Areas/Api/Controllers/Backups/Models/RestoreRequest.cs index 50dd8ec55..3b4154f0c 100644 --- a/src/Squidex/Areas/Api/Controllers/Backups/Models/RestoreRequest.cs +++ b/src/Squidex/Areas/Api/Controllers/Backups/Models/RestoreRequest.cs @@ -17,5 +17,8 @@ namespace Squidex.Areas.Api.Controllers.Backups.Models /// [Required] public Uri Url { get; set; } + + [RegularExpression("^[a-z0-9]+(\\-[a-z0-9]+)*$")] + public string Name { get; set; } } } diff --git a/src/Squidex/Areas/Api/Controllers/Backups/RestoreController.cs b/src/Squidex/Areas/Api/Controllers/Backups/RestoreController.cs index 4965bfd9e..2162860a5 100644 --- a/src/Squidex/Areas/Api/Controllers/Backups/RestoreController.cs +++ b/src/Squidex/Areas/Api/Controllers/Backups/RestoreController.cs @@ -63,7 +63,7 @@ namespace Squidex.Areas.Api.Controllers.Backups { var restoreGrain = grainFactory.GetGrain(User.OpenIdSubject()); - await restoreGrain.RestoreAsync(request.Url); + await restoreGrain.RestoreAsync(request.Url, request.Name); return NoContent(); }