feat: pivot to social media workflow app
This commit is contained in:
56
backend/Infrastructure/Security/AccessScopeService.cs
Normal file
56
backend/Infrastructure/Security/AccessScopeService.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using System.Security.Claims;
|
||||
using Socialize.Modules.Identity.Contracts;
|
||||
|
||||
namespace Socialize.Infrastructure.Security;
|
||||
|
||||
public sealed class AccessScopeService
|
||||
{
|
||||
public bool IsManager(ClaimsPrincipal user)
|
||||
{
|
||||
return user.IsInRole(KnownRoles.Administrator) || user.IsInRole(KnownRoles.Manager);
|
||||
}
|
||||
|
||||
public bool IsProvider(ClaimsPrincipal user)
|
||||
{
|
||||
return user.IsInRole(KnownRoles.Provider);
|
||||
}
|
||||
|
||||
public bool IsClient(ClaimsPrincipal user)
|
||||
{
|
||||
return user.IsInRole(KnownRoles.Client);
|
||||
}
|
||||
|
||||
public bool CanAccessWorkspace(ClaimsPrincipal user, Guid workspaceId)
|
||||
{
|
||||
return IsManager(user) || user.GetWorkspaceScopeIds().Contains(workspaceId);
|
||||
}
|
||||
|
||||
public bool CanManageWorkspace(ClaimsPrincipal user, Guid workspaceId)
|
||||
{
|
||||
return IsManager(user) && CanAccessWorkspace(user, workspaceId);
|
||||
}
|
||||
|
||||
public bool CanAccessClient(ClaimsPrincipal user, Guid workspaceId, Guid clientId)
|
||||
{
|
||||
return IsManager(user)
|
||||
|| (CanAccessWorkspace(user, workspaceId) && user.GetClientScopeIds().Contains(clientId));
|
||||
}
|
||||
|
||||
public bool CanAccessProject(ClaimsPrincipal user, Guid workspaceId, Guid clientId, Guid projectId)
|
||||
{
|
||||
return IsManager(user)
|
||||
|| (CanAccessClient(user, workspaceId, clientId) && user.GetProjectScopeIds().Contains(projectId));
|
||||
}
|
||||
|
||||
public bool CanContributeToProject(ClaimsPrincipal user, Guid workspaceId, Guid clientId, Guid projectId)
|
||||
{
|
||||
return IsManager(user) || (IsProvider(user) && CanAccessProject(user, workspaceId, clientId, projectId));
|
||||
}
|
||||
|
||||
public bool CanReviewContent(ClaimsPrincipal user, Guid workspaceId, Guid clientId, Guid projectId)
|
||||
{
|
||||
return IsManager(user)
|
||||
|| IsProvider(user) && CanAccessProject(user, workspaceId, clientId, projectId)
|
||||
|| IsClient(user) && CanAccessClient(user, workspaceId, clientId);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,38 @@
|
||||
using System.Security.Claims;
|
||||
|
||||
namespace Hutopy.Infrastructure.Security;
|
||||
namespace Socialize.Infrastructure.Security;
|
||||
|
||||
public static class ClaimsPrincipalExtensions
|
||||
{
|
||||
public static IReadOnlyCollection<Guid> GetScopeIds(this ClaimsPrincipal claims, string key)
|
||||
{
|
||||
return claims.FindAll(key)
|
||||
.Select(claim => Guid.TryParse(claim.Value, out Guid value) ? value : Guid.Empty)
|
||||
.Where(value => value != Guid.Empty)
|
||||
.Distinct()
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
public static IReadOnlyCollection<Guid> GetWorkspaceScopeIds(this ClaimsPrincipal claims)
|
||||
{
|
||||
return claims.GetScopeIds(KnownClaims.WorkspaceScope);
|
||||
}
|
||||
|
||||
public static IReadOnlyCollection<Guid> GetClientScopeIds(this ClaimsPrincipal claims)
|
||||
{
|
||||
return claims.GetScopeIds(KnownClaims.ClientScope);
|
||||
}
|
||||
|
||||
public static IReadOnlyCollection<Guid> GetProjectScopeIds(this ClaimsPrincipal claims)
|
||||
{
|
||||
return claims.GetScopeIds(KnownClaims.ProjectScope);
|
||||
}
|
||||
|
||||
public static string? GetPersona(this ClaimsPrincipal claims)
|
||||
{
|
||||
return (string?)claims.GetClaim<string?>(KnownClaims.Persona);
|
||||
}
|
||||
|
||||
public static Guid GetUserId(this ClaimsPrincipal claims)
|
||||
{
|
||||
return (Guid)claims.GetRequiredClaim<Guid>(ClaimTypes.NameIdentifier);
|
||||
|
||||
@@ -3,7 +3,7 @@ using System.Security.Claims;
|
||||
using System.Text;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
|
||||
namespace Hutopy.Infrastructure.Security;
|
||||
namespace Socialize.Infrastructure.Security;
|
||||
|
||||
public static class JwtTokenHelper
|
||||
{
|
||||
@@ -17,7 +17,9 @@ public static class JwtTokenHelper
|
||||
string? alias,
|
||||
string firstname,
|
||||
string lastname,
|
||||
string? portraitUrl)
|
||||
string? portraitUrl,
|
||||
IEnumerable<string> roles,
|
||||
IEnumerable<Claim> additionalClaims)
|
||||
{
|
||||
SymmetricSecurityKey securityKey = new(Encoding.UTF8.GetBytes(key));
|
||||
SigningCredentials credentials = new(securityKey, SecurityAlgorithms.HmacSha256);
|
||||
@@ -40,6 +42,18 @@ public static class JwtTokenHelper
|
||||
claims.Add(new Claim(KnownClaims.PortraitUrl, portraitUrl));
|
||||
}
|
||||
|
||||
foreach (string role in roles.Distinct(StringComparer.Ordinal))
|
||||
{
|
||||
claims.Add(new Claim(ClaimTypes.Role, role));
|
||||
}
|
||||
|
||||
foreach (Claim claim in additionalClaims
|
||||
.Where(claim => !string.IsNullOrWhiteSpace(claim.Type) && !string.IsNullOrWhiteSpace(claim.Value))
|
||||
.DistinctBy(claim => $"{claim.Type}:{claim.Value}"))
|
||||
{
|
||||
claims.Add(claim);
|
||||
}
|
||||
|
||||
JwtSecurityToken token = new(
|
||||
issuer,
|
||||
audience,
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
namespace Hutopy.Infrastructure.Security;
|
||||
namespace Socialize.Infrastructure.Security;
|
||||
|
||||
public static class KnownClaims
|
||||
{
|
||||
public const string Alias = "alias";
|
||||
public const string PortraitUrl = "portraitUrl";
|
||||
public const string WorkspaceScope = "workspace";
|
||||
public const string ClientScope = "client";
|
||||
public const string ProjectScope = "project";
|
||||
public const string Persona = "persona";
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Hutopy.Infrastructure.Security;
|
||||
namespace Socialize.Infrastructure.Security;
|
||||
|
||||
public class MissingClaimException(
|
||||
string claimName)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace Hutopy.Infrastructure.Security;
|
||||
namespace Socialize.Infrastructure.Security;
|
||||
|
||||
// If we need to add special characters we can alternate between 2 pools.
|
||||
public static class PasswordGenerator
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Hutopy.Infrastructure.Security;
|
||||
namespace Socialize.Infrastructure.Security;
|
||||
|
||||
public static class RefreshTokenGenerator
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user