feat: pivot to social media workflow app
Some checks failed
Backend CI/CD / build_and_deploy (push) Has been cancelled
Frontend CI/CD / build_and_deploy (push) Has been cancelled

This commit is contained in:
2026-04-24 12:58:35 -04:00
parent 0f4acc1b6d
commit df3e602015
349 changed files with 18685 additions and 16010 deletions

View File

@@ -1,8 +1,8 @@
using Hutopy.Infrastructure.Security;
using Hutopy.Modules.Identity.Data;
using Socialize.Infrastructure.Security;
using Socialize.Modules.Identity.Data;
using Microsoft.AspNetCore.Identity;
namespace Hutopy.Modules.Identity.Handlers;
namespace Socialize.Modules.Identity.Handlers;
[PublicAPI]
public record ChangeAddressRequest(

View File

@@ -1,8 +1,8 @@
using Hutopy.Infrastructure.Security;
using Hutopy.Modules.Identity.Data;
using Socialize.Infrastructure.Security;
using Socialize.Modules.Identity.Data;
using Microsoft.AspNetCore.Identity;
namespace Hutopy.Modules.Identity.Handlers;
namespace Socialize.Modules.Identity.Handlers;
[PublicAPI]
public record ChangeAliasRequest(

View File

@@ -1,8 +1,8 @@
using Hutopy.Infrastructure.Security;
using Hutopy.Modules.Identity.Data;
using Socialize.Infrastructure.Security;
using Socialize.Modules.Identity.Data;
using Microsoft.AspNetCore.Identity;
namespace Hutopy.Modules.Identity.Handlers;
namespace Socialize.Modules.Identity.Handlers;
[PublicAPI]
public record ChangeBirthDateRequest(

View File

@@ -1,8 +1,8 @@
using Hutopy.Infrastructure.Security;
using Hutopy.Modules.Identity.Data;
using Socialize.Infrastructure.Security;
using Socialize.Modules.Identity.Data;
using Microsoft.AspNetCore.Identity;
namespace Hutopy.Modules.Identity.Handlers;
namespace Socialize.Modules.Identity.Handlers;
[PublicAPI]
public record ChangeEmailRequest(

View File

@@ -1,8 +1,8 @@
using Hutopy.Infrastructure.Security;
using Hutopy.Modules.Identity.Data;
using Socialize.Infrastructure.Security;
using Socialize.Modules.Identity.Data;
using Microsoft.AspNetCore.Identity;
namespace Hutopy.Modules.Identity.Handlers;
namespace Socialize.Modules.Identity.Handlers;
[PublicAPI]
public record ChangeFullnameRequest(

View File

@@ -1,8 +1,8 @@
using Hutopy.Infrastructure.Security;
using Hutopy.Modules.Identity.Data;
using Socialize.Infrastructure.Security;
using Socialize.Modules.Identity.Data;
using Microsoft.AspNetCore.Identity;
namespace Hutopy.Modules.Identity.Handlers;
namespace Socialize.Modules.Identity.Handlers;
[PublicAPI]
public record ChangePhoneRequest(

View File

@@ -1,9 +1,9 @@
using Hutopy.Infrastructure.BlobStorage.Contracts;
using Hutopy.Infrastructure.Security;
using Hutopy.Modules.Identity.Data;
using Socialize.Infrastructure.BlobStorage.Contracts;
using Socialize.Infrastructure.Security;
using Socialize.Modules.Identity.Data;
using Microsoft.AspNetCore.Identity;
namespace Hutopy.Modules.Identity.Handlers;
namespace Socialize.Modules.Identity.Handlers;
[PublicAPI]
public record ChangePortraitRequest(

View File

@@ -1,10 +1,10 @@
using System.Web;
using Hutopy.Infrastructure.Configuration;
using Hutopy.Infrastructure.Emailer.Contracts;
using Hutopy.Modules.Identity.Data;
using Socialize.Infrastructure.Configuration;
using Socialize.Infrastructure.Emailer.Contracts;
using Socialize.Modules.Identity.Data;
using Microsoft.Extensions.Options;
namespace Hutopy.Modules.Identity.Handlers;
namespace Socialize.Modules.Identity.Handlers;
[PublicAPI]
public record ForgotPasswordRequest(
@@ -49,10 +49,10 @@ public class ForgotPasswordHandler(
$"{options.Value.FrontendBaseUrl}/reset-password?email={HttpUtility.UrlEncode(request.Email)}&token={encodedToken}";
// Create a styled email message
string subject = "Reset your Hutopy password";
string subject = "Reset your Socialize password";
string message = $"""
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; color: #333;">
<h1 style="color: #2c3e50; margin-bottom: 20px;">Reset Your Hutopy Password</h1>
<h1 style="color: #2c3e50; margin-bottom: 20px;">Reset Your Socialize Password</h1>
<p style="font-size: 16px; line-height: 1.5; margin-bottom: 25px;">
Please click the button below to reset your password:

View File

@@ -1,7 +1,9 @@
using Hutopy.Modules.Identity.Data;
using Hutopy.Modules.Identity.Models;
using System.Security.Claims;
using Socialize.Modules.Identity.Data;
using Socialize.Modules.Identity.Models;
using Socialize.Infrastructure.Security;
namespace Hutopy.Modules.Identity.Handlers;
namespace Socialize.Modules.Identity.Handlers;
[PublicAPI]
public class GetCurrentUserQueryHandler(
@@ -26,11 +28,42 @@ public class GetCurrentUserQueryHandler(
}
IList<string> roles = await identityService.GetCurrentUserRolesAsync();
IList<Claim> claims = await identityService.GetCurrentUserClaimsAsync();
string? persona = claims
.Where(claim => claim.Type == KnownClaims.Persona)
.Select(claim => claim.Value)
.LastOrDefault();
List<Guid> workspaceIds = claims
.Where(claim => claim.Type == KnownClaims.WorkspaceScope)
.Select(claim => Guid.TryParse(claim.Value, out Guid id) ? id : Guid.Empty)
.Where(id => id != Guid.Empty)
.Distinct()
.ToList();
List<Guid> clientIds = claims
.Where(claim => claim.Type == KnownClaims.ClientScope)
.Select(claim => Guid.TryParse(claim.Value, out Guid id) ? id : Guid.Empty)
.Where(id => id != Guid.Empty)
.Distinct()
.ToList();
List<Guid> projectIds = claims
.Where(claim => claim.Type == KnownClaims.ProjectScope)
.Select(claim => Guid.TryParse(claim.Value, out Guid id) ? id : Guid.Empty)
.Where(id => id != Guid.Empty)
.Distinct()
.ToList();
await SendOkAsync(
new UserDto
{
Id = userModel.Id,
Persona = persona,
AuthorizedWorkspaceIds = workspaceIds,
AuthorizedClientIds = clientIds,
AuthorizedProjectIds = projectIds,
Alias = userModel.Alias,
PortraitUrl = userModel.PortraitUrl,
Firstname = userModel.Firstname,

View File

@@ -1,8 +1,8 @@
using Hutopy.Infrastructure.BlobStorage.Contracts;
using Hutopy.Modules.Identity.Data;
using Hutopy.Modules.Identity.Models;
using Socialize.Infrastructure.BlobStorage.Contracts;
using Socialize.Modules.Identity.Data;
using Socialize.Modules.Identity.Models;
namespace Hutopy.Modules.Identity.Handlers;
namespace Socialize.Modules.Identity.Handlers;
[PublicAPI]
public class GetCurrentUserPortraitHandler(

View File

@@ -1,9 +1,10 @@
using Hutopy.Infrastructure.Security;
using Hutopy.Modules.Identity.Configuration;
using Hutopy.Modules.Identity.Data;
using Socialize.Infrastructure.Security;
using Socialize.Modules.Identity.Data;
using Socialize.Modules.Identity.Configuration;
using Socialize.Modules.Identity.Services;
using Microsoft.Extensions.Options;
namespace Hutopy.Modules.Identity.Handlers;
namespace Socialize.Modules.Identity.Handlers;
[PublicAPI]
public record LoginRequest(
@@ -18,7 +19,8 @@ public record LoginResponse(
[PublicAPI]
public class LoginHandler(
UserManager userManager,
IOptionsSnapshot<JwtOptions> jwtOptions)
IOptionsSnapshot<JwtOptions> jwtOptions,
AccessTokenFactory accessTokenFactory)
: Endpoint<LoginRequest, LoginResponse>
{
public override void Configure()
@@ -34,6 +36,7 @@ public class LoginHandler(
{
// Find the user by email
User? user = await userManager.FindByEmailAsync(request.Email);
user ??= await userManager.FindByNameAsync(request.Email);
if (user is null)
{
await SendStringAsync(
@@ -70,17 +73,7 @@ public class LoginHandler(
await userManager.UpdateAsync(user);
// Generate JWT token
string accessToken = JwtTokenHelper.GenerateJwtToken(
jwtOptions.Value.Lifetime,
jwtOptions.Value.Issuer,
jwtOptions.Value.Audience,
jwtOptions.Value.Key,
user.Id.ToString(),
user.Email ?? string.Empty,
user.Alias,
user.Firstname ?? string.Empty,
user.Lastname ?? string.Empty,
user.PortraitUrl);
string accessToken = await accessTokenFactory.CreateAsync(user);
await SendOkAsync(
new LoginResponse(accessToken, user.RefreshToken),

View File

@@ -1,12 +1,13 @@
using System.Text.Json;
using System.Text.Json.Serialization;
using Hutopy.Infrastructure.Security;
using Hutopy.Modules.Identity.Configuration;
using Hutopy.Modules.Identity.Data;
using Socialize.Infrastructure.Security;
using Socialize.Modules.Identity.Configuration;
using Socialize.Modules.Identity.Data;
using Socialize.Modules.Identity.Services;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
namespace Hutopy.Modules.Identity.Handlers;
namespace Socialize.Modules.Identity.Handlers;
[PublicAPI]
public class FacebookUserInfo
@@ -42,7 +43,8 @@ public record LoginWithFacebookResponse(
public class LoginWithFacebookHandler(
IHttpClientFactory httpClientFactory,
UserManager userManager,
IOptionsSnapshot<JwtOptions> jwtOptions)
IOptionsSnapshot<JwtOptions> jwtOptions,
AccessTokenFactory accessTokenFactory)
: Endpoint<LoginWithFacebookRequest, LoginWithFacebookResponse>
{
public override void Configure()
@@ -124,17 +126,7 @@ public class LoginWithFacebookHandler(
user.RefreshTokenExpiryTime = DateTime.UtcNow.Add(jwtOptions.Value.RefreshTokenLifetime);
await userManager.UpdateAsync(user);
string accessToken = JwtTokenHelper.GenerateJwtToken(
jwtOptions.Value.Lifetime,
jwtOptions.Value.Issuer,
jwtOptions.Value.Audience,
jwtOptions.Value.Key,
user.Id.ToString(),
user.Email ?? string.Empty,
user.Alias,
user.Firstname ?? string.Empty,
user.Lastname ?? string.Empty,
user.PortraitUrl);
string accessToken = await accessTokenFactory.CreateAsync(user);
await SendOkAsync(
new LoginWithFacebookResponse(accessToken, refreshToken),

View File

@@ -1,12 +1,13 @@
using System.Text.Json;
using System.Text.Json.Serialization;
using Hutopy.Infrastructure.Security;
using Hutopy.Modules.Identity.Configuration;
using Hutopy.Modules.Identity.Data;
using Socialize.Infrastructure.Security;
using Socialize.Modules.Identity.Configuration;
using Socialize.Modules.Identity.Data;
using Socialize.Modules.Identity.Services;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
namespace Hutopy.Modules.Identity.Handlers;
namespace Socialize.Modules.Identity.Handlers;
internal class GoogleToken
{
@@ -42,7 +43,8 @@ public record LoginWithGoogleResponse(
public class LoginWithGoogleHandler(
IHttpClientFactory httpClientFactory,
UserManager userManager,
IOptionsSnapshot<JwtOptions> jwtOptions)
IOptionsSnapshot<JwtOptions> jwtOptions,
AccessTokenFactory accessTokenFactory)
: Endpoint<LoginWithGoogleRequest, LoginWithGoogleResponse>
{
public override void Configure()
@@ -128,17 +130,7 @@ public class LoginWithGoogleHandler(
user.RefreshTokenExpiryTime = DateTime.UtcNow.Add(jwtOptions.Value.RefreshTokenLifetime);
await userManager.UpdateAsync(user);
string accessToken = JwtTokenHelper.GenerateJwtToken(
jwtOptions.Value.Lifetime,
jwtOptions.Value.Issuer,
jwtOptions.Value.Audience,
jwtOptions.Value.Key,
user.Id.ToString(),
user.Email ?? string.Empty,
user.Alias,
user.Firstname ?? string.Empty,
user.Lastname ?? string.Empty,
user.PortraitUrl);
string accessToken = await accessTokenFactory.CreateAsync(user);
await SendOkAsync(
new LoginWithGoogleResponse(accessToken, user.RefreshToken),

View File

@@ -1,9 +1,10 @@
using Hutopy.Infrastructure.Security;
using Hutopy.Modules.Identity.Configuration;
using Hutopy.Modules.Identity.Data;
using Socialize.Infrastructure.Security;
using Socialize.Modules.Identity.Configuration;
using Socialize.Modules.Identity.Data;
using Socialize.Modules.Identity.Services;
using Microsoft.Extensions.Options;
namespace Hutopy.Modules.Identity.Handlers;
namespace Socialize.Modules.Identity.Handlers;
[PublicAPI]
public record RefreshTokenRequest(
@@ -17,7 +18,8 @@ public record RefreshTokenResponse(
[PublicAPI]
public class RefreshTokenHandler(
UserManager userManager,
IOptionsSnapshot<JwtOptions> jwtOptions)
IOptionsSnapshot<JwtOptions> jwtOptions,
AccessTokenFactory accessTokenFactory)
: Endpoint<RefreshTokenRequest, RefreshTokenResponse>
{
public override void Configure()
@@ -52,17 +54,7 @@ public class RefreshTokenHandler(
await userManager.UpdateAsync(user);
// Generate a new access token
string accessToken = JwtTokenHelper.GenerateJwtToken(
jwtOptions.Value.Lifetime,
jwtOptions.Value.Issuer,
jwtOptions.Value.Audience,
jwtOptions.Value.Key,
user.Id.ToString(),
user.Email ?? string.Empty,
user.Alias,
user.Firstname ?? string.Empty,
user.Lastname ?? string.Empty,
user.PortraitUrl);
string accessToken = await accessTokenFactory.CreateAsync(user);
await SendOkAsync(
new RefreshTokenResponse(accessToken, user.RefreshToken),

View File

@@ -1,8 +1,8 @@
using Hutopy.Modules.Identity.Data;
using Hutopy.Modules.Identity.Services;
using Socialize.Modules.Identity.Data;
using Socialize.Modules.Identity.Services;
using Microsoft.AspNetCore.Identity;
namespace Hutopy.Modules.Identity.Handlers;
namespace Socialize.Modules.Identity.Handlers;
[PublicAPI]
public record RegisterRequest(

View File

@@ -1,7 +1,7 @@
using Hutopy.Modules.Identity.Data;
using Hutopy.Modules.Identity.Services;
using Socialize.Modules.Identity.Data;
using Socialize.Modules.Identity.Services;
namespace Hutopy.Modules.Identity.Handlers;
namespace Socialize.Modules.Identity.Handlers;
[PublicAPI]
public record ResendVerificationRequest(

View File

@@ -1,7 +1,7 @@
using Hutopy.Modules.Identity.Data;
using Socialize.Modules.Identity.Data;
using Microsoft.AspNetCore.Identity;
namespace Hutopy.Modules.Identity.Handlers;
namespace Socialize.Modules.Identity.Handlers;
[PublicAPI]
public record ResetPasswordRequest(

View File

@@ -1,8 +1,8 @@
using Hutopy.Infrastructure.Security;
using Hutopy.Modules.Identity.Data;
using Socialize.Infrastructure.Security;
using Socialize.Modules.Identity.Data;
using Microsoft.AspNetCore.Identity;
namespace Hutopy.Modules.Identity.Handlers;
namespace Socialize.Modules.Identity.Handlers;
[PublicAPI]
public record SetPasswordRequest(

View File

@@ -1,8 +1,8 @@
using System.Web;
using Hutopy.Modules.Identity.Data;
using Socialize.Modules.Identity.Data;
using Microsoft.AspNetCore.Identity;
namespace Hutopy.Modules.Identity.Handlers;
namespace Socialize.Modules.Identity.Handlers;
[PublicAPI]
public record VerifyEmailRequest(