Skip to content

Commit

Permalink
Use env variable as prefix to signalR groups
Browse files Browse the repository at this point in the history
  • Loading branch information
andchiind committed Dec 21, 2023
1 parent b845db3 commit df5cf11
Show file tree
Hide file tree
Showing 7 changed files with 42 additions and 33 deletions.
2 changes: 2 additions & 0 deletions backend/api/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

Console.WriteLine($"\nENVIRONMENT IS SET TO '{builder.Environment.EnvironmentName}'\n");

builder.Configuration.AddEnvironmentVariables();

builder.AddAzureEnvironmentVariables();

if (builder.Configuration.GetSection("KeyVault").GetValue<bool>("UseKeyVault"))
Expand Down
6 changes: 0 additions & 6 deletions backend/api/Services/AccessRoleService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ public interface IAccessRoleService
public Task<List<string>> GetAllowedInstallationCodes(List<string> roles);
public bool IsUserAdmin();
public bool IsAuthenticationAvailable();
public string? GetRequestNameId();
}

public class AccessRoleService(FlotillaDbContext context, IHttpContextAccessor httpContextAccessor) : IAccessRoleService
Expand Down Expand Up @@ -54,10 +53,5 @@ public bool IsAuthenticationAvailable()
{
return httpContextAccessor.HttpContext != null;
}

public string? GetRequestNameId()
{
return httpContextAccessor.HttpContext?.GetUserNameId();
}
}
}
17 changes: 8 additions & 9 deletions backend/api/Services/SignalRService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public interface ISignalRService
public Task SendMessageAsync(string label, Installation? installation, string message);
}

public class SignalRService(IHubContext<SignalRHub> signalRHub, IAccessRoleService accessRoleService) : ISignalRService
public class SignalRService(IHubContext<SignalRHub> signalRHub, IConfiguration configuration) : ISignalRService
{
private readonly JsonSerializerOptions _serializerOptions = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };

Expand All @@ -23,25 +23,24 @@ public async Task SendMessageAsync<T>(string label, Installation? installation,

public async Task SendMessageAsync(string label, Installation? installation, string message)
{
if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development")
if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Local")
{
string? nameId = accessRoleService.GetRequestNameId();
if (nameId is null) return;
string? localDevUser = configuration.GetSection("Local")["DevUserId"];
if (localDevUser is null || localDevUser.Equals("", StringComparison.Ordinal)) return;

if (installation != null)
await signalRHub.Clients.Group(nameId + installation.InstallationCode.ToUpper(CultureInfo.CurrentCulture)).SendAsync(label, "all", message);
await signalRHub.Clients.Group(localDevUser + installation.InstallationCode.ToUpper(CultureInfo.CurrentCulture)).SendAsync(label, "all", message);
else
// TODO: can't do this if we use DEV. Then we instead need a generic group for connection id
await signalRHub.Clients.User(nameId).SendAsync(label, "all", message);
await signalRHub.Clients.Group(localDevUser).SendAsync(label, "all", message);
}
else
{
if (installation != null)
await signalRHub.Clients.Group(installation.InstallationCode.ToUpper(CultureInfo.CurrentCulture)).SendAsync(label, "all", message);
else
// TODO: can't do this if we use DEV. Then we instead need a generic group for connection id
await signalRHub.Clients.All.SendAsync(label, "all", message);
}


await Task.CompletedTask;
}
Expand Down
14 changes: 9 additions & 5 deletions backend/api/SignalR/SignalRHub.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ public interface ISignalRClient
{
}

public class SignalRHub(IAccessRoleService accessRoleService) : Hub<ISignalRClient>
public class SignalRHub(IAccessRoleService accessRoleService, IConfiguration configuration) : Hub<ISignalRClient>
{
/// <summary>
/// Called when a new connection is made.
Expand All @@ -18,14 +18,18 @@ public override async Task OnConnectedAsync()
{
var roles = Context.User.Claims
.Where((c) => c.Type.EndsWith("/role", StringComparison.CurrentCulture)).Select((c) => c.Value).ToList();

var installationCodes = await accessRoleService.GetAllowedInstallationCodes(roles);

if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development")
if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Local")
{
string? objectId = Context.User.Claims.Where((c) => c.Type.EndsWith("/objectidentifier", StringComparison.CurrentCulture)).Select((c) => c.Value).FirstOrDefault();
string? localDevUser = configuration.GetSection("Local")["DevUserId"];
if (localDevUser is null || localDevUser.Equals("", StringComparison.Ordinal))
throw new HubException("Running in development mode, but missing Local__DevUserId value in environment");

await Groups.AddToGroupAsync(Context.ConnectionId, localDevUser); // This is used instead of Users.All
foreach (string installationCode in installationCodes)
await Groups.AddToGroupAsync(Context.ConnectionId, objectId + installationCode.ToUpperInvariant());
await Groups.AddToGroupAsync(Context.ConnectionId, localDevUser + installationCode.ToUpperInvariant());
}
else
{
Expand Down
13 changes: 0 additions & 13 deletions backend/api/Utilities/HttpContextExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,6 @@ public static string GetRequestToken(this HttpContext client)
return value.ToString().Replace("Bearer ", "", StringComparison.CurrentCulture);
}

public static string? GetUserNameId(this HttpContext client)
{
string accessTokenBase64 = client.GetRequestToken();

var handler = new JwtSecurityTokenHandler();
var jwtSecurityToken = handler.ReadJwtToken(accessTokenBase64);

var claims = jwtSecurityToken.Claims;
string? objectId = claims.Where((c) => c.Type == "oid" || c.Type.EndsWith("oid", StringComparison.CurrentCulture)).Select((n) => n.Value).FirstOrDefault();
string? nameId = claims.Where((c) => c.Type == "name" || c.Type.EndsWith("name", StringComparison.CurrentCulture)).Select((n) => n.Value).FirstOrDefault();
return nameId;
}

public static List<System.Security.Claims.Claim> GetRequestedRoles(this HttpContext client)
{
string accessTokenBase64 = client.GetRequestToken();
Expand Down
3 changes: 3 additions & 0 deletions backend/api/appsettings.Local.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,8 @@
},
"Database": {
"UseInMemoryDatabase": true
},
"Local": {
"DevUserId": ""
}
}
20 changes: 20 additions & 0 deletions setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,26 @@ if [ "$backend_abort" != "true" ]; then
dotnet user-secrets set "AzureAd:ClientSecret" $az_client_secret --project backend/api > /dev/null
echo -e "Added client secret to ASP.NET secret manager"

echo -e "A username is needed for local development with SignalR"
echo -en "Input a username for yourself (this only needs to be unique within your development environment):\n"

while [ true ]
do
read -s local_dev_username

if [ -z "$local_dev_username" ]; then
echo "The local dev username cannot be empty"
echo "Try again:"
else
break
fi
done


echo "Local__DevUserId='$local_dev_username'" >> $flotilla_dir/.env
dotnet user-secrets set "Local:DevUserId" $az_client_secret --project backend/api > /dev/null
echo -e "Added local development username to .env file"

echo -e "Backup setup - Done!"
echo -e "-----------------------------\n"
fi
Expand Down

0 comments on commit df5cf11

Please sign in to comment.