mirror of
https://github.com/bitwarden/server.git
synced 2025-07-02 16:42:50 -05:00
SM-365: Add Export & Import Functionality for SM (#2591)
* SM-365: Add Export endpoint * SM-365: Add SM Import/Export support * SM-365: Fix DI and add temp NoAccessCheck * SM-365: Add access checks to import / export * SM-365: dotnet format * SM-365: Fix import bugs * SM-365: Fix import bug with EF & refactor based on PR comments * SM-365: Update access permissions in export * SM-365: Address PR comments * SM-365: Refactor for readability and PR comments
This commit is contained in:
@ -0,0 +1,101 @@
|
||||
using Bit.Core.SecretsManager.Commands.Porting;
|
||||
using Bit.Core.SecretsManager.Commands.Porting.Interfaces;
|
||||
using Bit.Core.SecretsManager.Entities;
|
||||
using Bit.Core.SecretsManager.Repositories;
|
||||
|
||||
namespace Bit.Commercial.Core.SecretsManager.Commands.Porting;
|
||||
|
||||
public class ImportCommand : IImportCommand
|
||||
{
|
||||
private readonly IProjectRepository _projectRepository;
|
||||
private readonly ISecretRepository _secretRepository;
|
||||
|
||||
public ImportCommand(IProjectRepository projectRepository, ISecretRepository secretRepository)
|
||||
{
|
||||
_projectRepository = projectRepository;
|
||||
_secretRepository = secretRepository;
|
||||
}
|
||||
|
||||
public async Task ImportAsync(Guid organizationId, SMImport import)
|
||||
{
|
||||
var importedProjects = new List<Guid>();
|
||||
var importedSecrets = new List<Guid>();
|
||||
|
||||
try
|
||||
{
|
||||
import = AssignNewIds(import);
|
||||
|
||||
if (import.Projects.Any())
|
||||
{
|
||||
importedProjects = (await _projectRepository.ImportAsync(import.Projects.Select(p => new Project
|
||||
{
|
||||
Id = p.Id,
|
||||
OrganizationId = organizationId,
|
||||
Name = p.Name,
|
||||
}))).Select(p => p.Id).ToList();
|
||||
}
|
||||
|
||||
if (import.Secrets != null && import.Secrets.Any())
|
||||
{
|
||||
importedSecrets = (await _secretRepository.ImportAsync(import.Secrets.Select(s => new Secret
|
||||
{
|
||||
Id = s.Id,
|
||||
OrganizationId = organizationId,
|
||||
Key = s.Key,
|
||||
Value = s.Value,
|
||||
Note = s.Note,
|
||||
Projects = s.ProjectIds?.Select(id => new Project { Id = id }).ToList(),
|
||||
}))).Select(s => s.Id).ToList();
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
if (importedProjects.Any())
|
||||
{
|
||||
await _projectRepository.DeleteManyByIdAsync(importedProjects);
|
||||
}
|
||||
|
||||
if (importedSecrets.Any())
|
||||
{
|
||||
await _secretRepository.HardDeleteManyByIdAsync(importedSecrets);
|
||||
}
|
||||
|
||||
throw new Exception("Error attempting import");
|
||||
}
|
||||
}
|
||||
|
||||
public SMImport AssignNewIds(SMImport import)
|
||||
{
|
||||
var projects = new Dictionary<Guid, SMImport.InnerProject>();
|
||||
var secrets = new List<SMImport.InnerSecret>();
|
||||
|
||||
if (import.Projects != null && import.Projects.Any())
|
||||
{
|
||||
projects = import.Projects.ToDictionary(
|
||||
p => p.Id,
|
||||
p => new SMImport.InnerProject { Id = Guid.NewGuid(), Name = p.Name }
|
||||
);
|
||||
}
|
||||
|
||||
if (import.Secrets != null && import.Secrets.Any())
|
||||
{
|
||||
foreach (var secret in import.Secrets)
|
||||
{
|
||||
secrets.Add(new SMImport.InnerSecret
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Key = secret.Key,
|
||||
Value = secret.Value,
|
||||
Note = secret.Note,
|
||||
ProjectIds = secret.ProjectIds?.Select(id => projects[id].Id),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return new SMImport
|
||||
{
|
||||
Projects = projects.Values,
|
||||
Secrets = secrets,
|
||||
};
|
||||
}
|
||||
}
|
@ -1,10 +1,12 @@
|
||||
using Bit.Commercial.Core.SecretsManager.Commands.AccessPolicies;
|
||||
using Bit.Commercial.Core.SecretsManager.Commands.AccessTokens;
|
||||
using Bit.Commercial.Core.SecretsManager.Commands.Porting;
|
||||
using Bit.Commercial.Core.SecretsManager.Commands.Projects;
|
||||
using Bit.Commercial.Core.SecretsManager.Commands.Secrets;
|
||||
using Bit.Commercial.Core.SecretsManager.Commands.ServiceAccounts;
|
||||
using Bit.Core.SecretsManager.Commands.AccessPolicies.Interfaces;
|
||||
using Bit.Core.SecretsManager.Commands.AccessTokens.Interfaces;
|
||||
using Bit.Core.SecretsManager.Commands.Porting.Interfaces;
|
||||
using Bit.Core.SecretsManager.Commands.Projects.Interfaces;
|
||||
using Bit.Core.SecretsManager.Commands.Secrets.Interfaces;
|
||||
using Bit.Core.SecretsManager.Commands.ServiceAccounts.Interfaces;
|
||||
@ -28,5 +30,6 @@ public static class SecretsManagerCollectionExtensions
|
||||
services.AddScoped<ICreateAccessPoliciesCommand, CreateAccessPoliciesCommand>();
|
||||
services.AddScoped<IUpdateAccessPolicyCommand, UpdateAccessPolicyCommand>();
|
||||
services.AddScoped<IDeleteAccessPolicyCommand, DeleteAccessPolicyCommand>();
|
||||
services.AddScoped<IImportCommand, ImportCommand>();
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user