Skip to content

Commit

Permalink
handle tenant on workspace import
Browse files Browse the repository at this point in the history
  • Loading branch information
sei-jmattson committed Oct 9, 2024
1 parent 91b076a commit 190e786
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 18 deletions.
68 changes: 58 additions & 10 deletions src/TopoMojo.Api/Features/Admin/TransferService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,28 @@ CoreOptions options
WriteIndented = true
};

private readonly string DisksReadme = """
# README
# This is a list disks where the folder matches the *workspace-id*.
# Any leading, non-hex character sequence of the workspace-id is its *tenant-prefix*.
# When importing data, workspace-id is changed to match the destination tenant-prefix,
# so care must be taken to ensure the destination folders match the new workspace-id.
#
# Folder with all zeros is "stock" folder; don't alter it.
#
# If neither source nor destination use a tenant-prefix, no action necessary.
#
# First, if the source has tenant-prefix, replace those characters with zeros.
#
# Then, if destination has tenant-prefix replace the leading characters with the
# destination tenant-prefix.
#
# The resulting folder names should be 32 characters; only *replace*
# characters, don't add or remove any.
# ----------
""";

public async Task<IEnumerable<string>> Import(string repoPath, string docPath)
{
List<string> results = [];
Expand Down Expand Up @@ -212,6 +234,27 @@ await reader.ReadToEndAsync(),
return [.. (await ImportWorkspaces(data))];
}

private void UpdateTenant(Workspace ws)
{
string src = ws.Id.ExtractTenant();
string dst = _options.Tenant;
string tenant = src.Length > dst.Length
? string.Concat(dst, new string('0', src.Length - dst.Length))
: dst
;

if (tenant.NotEmpty() && !ws.Id.StartsWith(tenant))
{
string target = ws.Id;
ws.Id = string.Concat(tenant, ws.Id.AsSpan(tenant.Length));
foreach (Template t in ws.Templates)
{
t.WorkspaceId = ws.Id;
t.Detail = t.Detail?.Replace(target, ws.Id);
}
}
}

private async Task<string[]> ImportWorkspaces(IEnumerable<Workspace> data)
{
List<string> results = [];
Expand All @@ -220,20 +263,25 @@ private async Task<string[]> ImportWorkspaces(IEnumerable<Workspace> data)

foreach(var topo in data)
{
// prevent overwriting
if (wids.Contains(topo.Id)) {
results.Add($"Duplicate: {topo.Name} {topo.Id}");
continue;
}

// add new stock templates
if (Guid.Parse(topo.Id) == Guid.Empty) {
if (Guid.TryParse(topo.Id, out Guid guid) && guid == Guid.Empty)
{
var stock = topo.Templates.Where(t => !tids.Contains(t.Id)).ToArray();
workspaceStore.DbContext.Templates.AddRange(stock);
results.Add($"Stock templates: {stock.Length}");
continue;
}

// add or remove tenant prefix
UpdateTenant(topo);

// prevent overwriting
if (wids.Contains(topo.Id))
{
results.Add($"Duplicate: {topo.Name} {topo.Id}");
continue;
}

// add workspace to datacontext
workspaceStore.DbContext.Workspaces.Add(topo);
results.Add($"Success: {topo.Name} {topo.Id}");
Expand All @@ -258,7 +306,7 @@ private async Task<Stream> CreateZipfile(IEnumerable<Workspace> data, IEnumerabl
WriteFileToArchive(
zipArchive,
"_disks.txt",
Encoding.UTF8.GetBytes(string.Join("\n", disks))
Encoding.UTF8.GetBytes(string.Concat(DisksReadme, string.Join("\n", disks)))
);

// export markdown doc artifacts
Expand Down Expand Up @@ -303,11 +351,11 @@ private async Task<string[]> ProcessZipfile(Stream stream, string docPath)
foreach (var entry in zipArchive.Entries)
{
// skip disks
if (entry.FullName == "_disks.txt")
if (entry.FullName.Equals("_disks.txt"))
continue;

// deserialize workspace data
if (entry.FullName == "_data.json")
if (entry.FullName.Equals("_data.json"))
{
results = await ImportSerializedWorkspaces(entry.Open());
continue;
Expand Down
8 changes: 4 additions & 4 deletions src/TopoMojo.Api/Features/Gamespace/GamespaceService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,10 @@ private async Task Create(RegistrationContext ctx, User actor)

ctx.Gamespace = new Data.Gamespace
{
Id = Guid.NewGuid().ToString("n"),
Id = string.Concat(
_options.Tenant,
Guid.NewGuid().ToString("n").AsSpan(_options.Tenant.Length)
),
Name = ctx.Workspace.Name,
Workspace = ctx.Workspace,
ManagerId = actor.Id,
Expand All @@ -244,9 +247,6 @@ private async Task Create(RegistrationContext ctx, User actor)
GraderKey = ctx.Request.GraderKey.ToSha256()
};

if (string.IsNullOrEmpty(_options.Tenant).Equals(false))
ctx.Gamespace.Id = _options.Tenant + ctx.Gamespace.Id.Substring(0, ctx.Gamespace.Id.Length - _options.Tenant.Length);

var gamespace = ctx.Gamespace;

foreach (var player in ctx.Request.Players)
Expand Down
8 changes: 4 additions & 4 deletions src/TopoMojo.Api/Features/Workspace/WorkspaceService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,10 @@ public async Task<Workspace> Create(NewWorkspace model, string subjectId, string
workspace.TemplateScope = "";
}

workspace.Id = Guid.NewGuid().ToString("n");
workspace.Id = string.Concat(
_options.Tenant,
Guid.NewGuid().ToString("n").AsSpan(_options.Tenant.Length)
);
workspace.WhenCreated = DateTimeOffset.UtcNow;
workspace.LastActivity = DateTimeOffset.UtcNow;

Expand All @@ -184,9 +187,6 @@ public async Task<Workspace> Create(NewWorkspace model, string subjectId, string
Permission = Permission.Manager
});

if (string.IsNullOrEmpty(_options.Tenant).Equals(false))
workspace.Id = _options.Tenant + workspace.Id.Substring(0, workspace.Id.Length - _options.Tenant.Length);

workspace = await _store.Create(workspace);

// TODO: consider handling document here
Expand Down
16 changes: 16 additions & 0 deletions src/TopoMojo.Api/Structure/StringExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -310,5 +310,21 @@ public static string ToRandomIPv4(this string s)

return result;
}

private static readonly char[] hex = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];

public static string ExtractTenant(this string s)
{
string r = "";
char[] c = s.ToLower().ToCharArray();
for (int i = 0; i < c.Length; i++)
{
if (hex.Contains(c[i]))
break;
else
r += c[i];
}
return r;
}
}
}

0 comments on commit 190e786

Please sign in to comment.