Skip to content

Commit

Permalink
feat(server): use tenant name as key (normalized)
Browse files Browse the repository at this point in the history
  • Loading branch information
thomashilzendegen authored and gingters committed Nov 9, 2023
1 parent 3c1b3ac commit 5d953a1
Show file tree
Hide file tree
Showing 88 changed files with 892 additions and 4,788 deletions.
2 changes: 1 addition & 1 deletion .config/dotnet-tools.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"isRoot": true,
"tools": {
"dotnet-ef": {
"version": "3.1.3",
"version": "7.0.13",
"commands": [
"dotnet-ef"
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public class ClientRequest : IClientRequest
public string Target { get; set; } = default!;

/// <inheritdoc />
public Guid TenantId { get; set; }
public string TenantName { get; set; } = default!;

/// <inheritdoc />
public string HttpMethod { get; set; } = default!;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ public interface IClientRequest
string Target { get; set; }

/// <summary>
/// The unique id of the tenant.
/// The unique name of the tenant.
/// </summary>
Guid TenantId { get; set; }
string TenantName { get; set; }

/// <summary>
/// The HTTP method used by the requesting client.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public RelayServerTenantStore(ITenantService tenantService)
/// <inheritdoc />
async Task<Client?> IClientStore.FindClientByIdAsync(string clientId)
{
var tenant = await _tenantService.LoadTenantCompleteByNameAsync(clientId);
var tenant = await _tenantService.LoadTenantCompleteAsync(clientId);
return tenant == null ? null : ConvertToClient(tenant);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public interface IConnectionService
/// <summary>
/// Returns true when a connection for the tenant is available; otherwise, false.
/// </summary>
/// <param name="tenantId">The unique id of the tenant.</param>
/// <param name="tenantName">The unique name of the tenant.</param>
/// <returns>A <see cref="Task"/> representing the asynchronous operation, which wraps the result.</returns>
Task<bool> IsConnectionAvailableAsync(Guid tenantId);
Task<bool> IsConnectionAvailableAsync(string tenantName);
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ public interface IConnectionStatisticsWriter
/// Sets the connection time of a connection.
/// </summary>
/// <param name="connectionId">The connection id from the corresponding transport.</param>
/// <param name="tenantId">The unique id of the tenant.</param>
/// <param name="tenantName">The unique name of the tenant.</param>
/// <param name="originId">The unique id of the origin.</param>
/// <param name="remoteIpAddress">The optional remote ip address of the connection.</param>
/// <param name="cancellationToken">
/// The token to monitor for cancellation requests. The default value is
/// <see cref="CancellationToken.None"/>.
/// </param>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
Task SetConnectionTimeAsync(string connectionId, Guid tenantId, Guid originId, IPAddress? remoteIpAddress,
Task SetConnectionTimeAsync(string connectionId, string tenantName, Guid originId, IPAddress? remoteIpAddress,
CancellationToken cancellationToken = default);

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,15 @@ public interface IStatisticsService
/// Sets the connection time of a connection.
/// </summary>
/// <param name="connectionId">The connection id from the corresponding transport.</param>
/// <param name="tenantId">The unique id of the tenant.</param>
/// <param name="tenantName">The unique name of the tenant.</param>
/// <param name="originId">The unique id of the origin.</param>
/// <param name="remoteIpAddress">The optional remote ip address of the connection.</param>
/// <param name="cancellationToken">
/// The token to monitor for cancellation requests. The default value is
/// <see cref="CancellationToken.None"/>.
/// </param>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
Task SetConnectionTimeAsync(string connectionId, Guid tenantId, Guid originId, IPAddress? remoteIpAddress,
Task SetConnectionTimeAsync(string connectionId, string tenantName, Guid originId, IPAddress? remoteIpAddress,
CancellationToken cancellationToken = default);

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,56 +12,56 @@ namespace Thinktecture.Relay.Server.Persistence;
public interface ITenantService
{
/// <summary>
/// Loads a <see cref="Tenant"/> by its name with all depending entities (connections, secrets, config).
/// Loads a <see cref="Tenant"/> with all depending entities (connections, secrets, config).
/// </summary>
/// <param name="name">The name of the <see cref="Tenant"/> to load.</param>
/// <param name="tenantName">The name of the <see cref="Tenant"/> to load.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is
/// <see cref="P:System.Threading.CancellationToken.None"/>.
/// </param>
/// <returns>
/// A <see cref="Task"/> representing the asynchronous operation, which wraps the <see cref="Tenant"/> or null if
/// not found.
/// </returns>
Task<Tenant?> LoadTenantCompleteByNameAsync(string name, CancellationToken cancellationToken = default);
Task<Tenant?> LoadTenantCompleteAsync(string tenantName, CancellationToken cancellationToken = default);

/// <summary>
/// Loads a <see cref="Tenant"/> by its name together with its connections.
/// Loads a <see cref="Tenant"/> with some depending entities (secrets, config).
/// </summary>
/// <param name="name">The name of the <see cref="Tenant"/> to load.</param>
/// <param name="tenantName">The name of the <see cref="Tenant"/> to load.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is
/// <see cref="P:System.Threading.CancellationToken.None"/>.
/// </param>
/// <returns>
/// A <see cref="Task"/> representing the asynchronous operation, which wraps the <see cref="Tenant"/> or null if
/// not found.
/// </returns>
Task<Tenant?> LoadTenantWithConnectionsByNameAsync(string name, CancellationToken cancellationToken = default);
Task<Tenant?> LoadTenantAsync(string tenantName, CancellationToken cancellationToken = default);

/// <summary>
/// Loads a <see cref="Tenant"/> by its name together with its config.
/// Loads a <see cref="Tenant"/> together with its connections.
/// </summary>
/// <param name="name">The name of the <see cref="Tenant"/> to load.</param>
/// <param name="tenantName">The name of the <see cref="Tenant"/> to load.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is
/// <see cref="P:System.Threading.CancellationToken.None"/>.
/// </param>
/// <returns>
/// A <see cref="Task"/> representing the asynchronous operation, which wraps the <see cref="Tenant"/> or null if
/// not found.
/// </returns>
Task<Tenant?> LoadTenantWithConfigByNameAsync(string name, CancellationToken cancellationToken = default);
Task<Tenant?> LoadTenantWithConnectionsAsync(string tenantName, CancellationToken cancellationToken = default);

/// <summary>
/// Loads a <see cref="Tenant"/> by its id.
/// Loads a <see cref="Tenant"/> together with its config.
/// </summary>
/// <param name="id">The id of the <see cref="Tenant"/> to load.</param>
/// <param name="tenantName">The name of the <see cref="Tenant"/> to load.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is
/// <see cref="P:System.Threading.CancellationToken.None"/>.
/// </param>
/// <returns>
/// A <see cref="Task"/> representing the asynchronous operation, which wraps the <see cref="Tenant"/> or null if
/// not found.
/// </returns>
Task<Tenant?> LoadTenantCompleteByIdAsync(Guid id, CancellationToken cancellationToken = default);
Task<Tenant?> LoadTenantWithConfigAsync(string tenantName, CancellationToken cancellationToken = default);

/// <summary>
/// Loads all <see cref="Tenant"/> with paging.
Expand All @@ -81,19 +81,19 @@ public interface ITenantService
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is
/// <see cref="P:System.Threading.CancellationToken.None"/>.
/// </param>
/// <returns>A <see cref="Task"/> representing the asynchronous operation, which wraps the id of the created tenant.</returns>
Task<Guid> CreateTenantAsync(Tenant tenant, CancellationToken cancellationToken = default);
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
Task CreateTenantAsync(Tenant tenant, CancellationToken cancellationToken = default);

/// <summary>
/// Updates an existing <see cref="Tenant"/>.
/// </summary>
/// <param name="tenantId">The id of the <see cref="Tenant"/> to update.</param>
/// <param name="tenantName">The name of the <see cref="Tenant"/> to update.</param>
/// <param name="tenant">The <see cref="Tenant"/> with the data to update.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is
/// <see cref="P:System.Threading.CancellationToken.None"/>.
/// </param>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
Task<bool> UpdateTenantAsync(Guid tenantId, Tenant tenant, CancellationToken cancellationToken = default);
Task<bool> UpdateTenantAsync(string tenantName, Tenant tenant, CancellationToken cancellationToken = default);

// TODO fix these methods, these are preliminary

Expand All @@ -110,25 +110,25 @@ public interface ITenantService
/// <summary>
/// Deletes a <see cref="Tenant"/>.
/// </summary>
/// <param name="id">The unique id of the tenant.</param>
/// <param name="tenantName">The name of the <see cref="Tenant"/> to delete.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is
/// <see cref="P:System.Threading.CancellationToken.None"/>.
/// </param>
/// <returns>A <see cref="Task"/> representing the asynchronous operation, which wraps the success of the deletion.</returns>
Task<bool> DeleteTenantByIdAsync(Guid id, CancellationToken cancellationToken = default);
Task<bool> DeleteTenantAsync(string tenantName, CancellationToken cancellationToken = default);

/// <summary>
/// Loads an optional <see cref="Config"/> for a tenant
/// </summary>
/// <param name="id">The unique id of the tenant.</param>
/// <param name="tenantName">The name of the <see cref="Tenant"/> to load the config for.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is
/// <see cref="P:System.Threading.CancellationToken.None"/>.
/// </param>
/// <returns>
/// A <see cref="Task"/> representing the asynchronous operation, which wraps the <see cref="Config"/> or null if
/// not found.
/// </returns>
Task<Config?> LoadTenantConfigAsync(Guid id, CancellationToken cancellationToken = default);
Task<Config?> LoadTenantConfigAsync(string tenantName, CancellationToken cancellationToken = default);

/// <summary>
/// Normalizes the name of the tenant.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ public class ClientSecret
public Guid Id { get; set; }

/// <summary>
/// The unique id of the <see cref="Tenant"/> this secret is for.
/// The unique name of the tenant.
/// </summary>
public Guid TenantId { get; set; }
public string TenantName { get; set; } = default!;

/// <summary>
/// A SHA256 or SHA512 of the actual secret string.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ namespace Thinktecture.Relay.Server.Persistence.Models;
public class Config : ITenantConfig
{
/// <summary>
/// The unique id of the tenant.
/// The unique name of the tenant.
/// </summary>
public Guid TenantId { get; set; }
public string TenantName { get; set; } = default!;

/// <inheritdoc />
public TimeSpan? KeepAliveInterval { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ public class Connection
public string Id { get; set; } = default!;

/// <summary>
/// The unique id of the tenant.
/// The unique name of the tenant.
/// </summary>
public Guid TenantId { get; set; }
public string TenantName { get; set; } = default!;

/// <summary>
/// The unique id of the relay server instance this connection is held to.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,8 @@ public static class PersistenceModelsExtensions
public static void UpdateFrom(this ClientSecret instance, ClientSecret other)
{
if (instance.Id != other.Id)
{
throw new InvalidOperationException(
$"Id of other secret: {other.Id} is not the same as this: {instance.Id}. Cannot update from other instance.");
}
$"Id of other secret ({other.Id}) is not the same as this ({instance.Id}). Cannot update from other instance.");

instance.Created = other.Created;
instance.Value = other.Value;
Expand All @@ -47,26 +45,21 @@ public static void UpdateFrom(this Config instance, Config other)
/// <param name="other">The source to copy the data over from to this instance.</param>
public static void UpdateFrom(this Tenant instance, Tenant other)
{
if (instance.Id != other.Id)
{
if (instance.NormalizedName != other.NormalizedName)
throw new InvalidOperationException(
$"Id of other tenant: {other.Id} is not the same as this: {instance.Id}. Cannot update from other instance.");
}

instance.Name = other.Name;
instance.NormalizedName = other.NormalizedName;
$"Name of other tenant ({other.Name}) is not the same as this ({instance.Name}). Cannot update from other instance.");

instance.DisplayName = other.DisplayName;
instance.Description = other.Description;

// Copy over config if available
// copy over config if available
if (other.Config != null)
{
instance.Config ??= new Config();
instance.Config.UpdateFrom(other.Config);
}

// Copy over secrets when they are complete with values
// copy over secrets when they are complete with values
if (other.ClientSecrets != null)
{
instance.ClientSecrets ??= new List<ClientSecret>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ namespace Thinktecture.Relay.Server.Persistence.Models;
public class Request
{
/// <summary>
/// The unique id of the tenant.
/// The unique name of the tenant.
/// </summary>
public Guid TenantId { get; set; }
public string TenantName { get; set; } = default!;

/// <summary>
/// The unique id of the request.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,7 @@ namespace Thinktecture.Relay.Server.Persistence.Models;
public class Tenant
{
/// <summary>
/// The unique id of the tenant.
/// </summary>
public Guid Id { get; set; }

/// <summary>
/// The name of the tenant. Also used as ClientId for connector authentication.
/// The unique name of the tenant.
/// </summary>
/// <remarks>The maximum length is 100 unicode characters.</remarks>
public string Name { get; set; } = default!;
Expand Down
Loading

0 comments on commit 5d953a1

Please sign in to comment.