Skip to content

Commit 07c31e6

Browse files
committed
Add users analytics events
1 parent 7e6ac66 commit 07c31e6

File tree

13 files changed

+83
-25
lines changed

13 files changed

+83
-25
lines changed

src/Api/Endpoints/Auth/RegisterEndpoint.cs

+9-5
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace Api.Endpoints.Auth;
99
public class RegisterEndpoint(
1010
IAuthService authService,
1111
ILogger<RegisterEndpoint> logger)
12-
: Endpoint<RegisterRequest, ApiResponse<UserTokenResponse>>
12+
: Endpoint<RegisterRequest, ApiResponse<UserInfoResponse>>
1313
{
1414
private readonly IAuthService _authService = authService;
1515
private readonly ILogger<RegisterEndpoint> _logger = logger;
@@ -26,17 +26,21 @@ public override async Task HandleAsync(
2626
{
2727
try
2828
{
29-
var tokenInfo = await _authService.RegisterUser(
29+
var registrationResponse = await _authService.RegisterUser(
3030
new RegisterRequestDto(req.Login, req.FullName, req.Password, req.Email), ct);
3131

32-
if (tokenInfo is null)
32+
if (registrationResponse is null)
3333
{
3434
await SendUnauthorizedAsync(ct);
3535
}
3636
else
3737
{
38-
var payload = new UserTokenResponse(tokenInfo.Token, tokenInfo.ExpiresIn);
39-
await SendAsync(ApiResponse<UserTokenResponse>.Success(payload), cancellation: ct);
38+
var tokenInfo = new UserTokenResponse(
39+
registrationResponse.TokenInfo.Token,
40+
registrationResponse.TokenInfo.ExpiresIn);
41+
42+
var payload = new UserInfoResponse(registrationResponse.UserId, tokenInfo);
43+
await SendAsync(ApiResponse<UserInfoResponse>.Success(payload), cancellation: ct);
4044
}
4145
}
4246
catch (Exception ex)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
namespace Api.Models.Responses;
2+
3+
public record UserInfoResponse(string UserId, UserTokenResponse TokenInfo);
+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
namespace Api.Models.Responses;
22

3-
public record UserTokenResponse(string Token, int ExpiresIn);
3+
public record UserTokenResponse(string Token, int ExpiresIn);

src/Core/Core.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<ItemGroup>
1010
<PackageReference Include="ErrorOr" Version="1.3.0" />
1111
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="8.0.0" />
12-
<PackageReference Include="trumpee.masstransit.messages" Version="1.0.0.8" />
12+
<PackageReference Include="trumpee.masstransit.messages" Version="1.0.0.15" />
1313
</ItemGroup>
1414

1515
<ItemGroup>

src/Core/Mappers/External/DeliveryRequestMapper.cs

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ internal static Notification ToRequest(NotificationDto notification, RecipientDt
1212

1313
return new Notification
1414
{
15+
NotificationId = notification.Id!,
1516
Content = ContentNapper.ToContent(notification.Content),
1617
Priority = (Priority?)notification.Priority,
1718
Status = notification.Status,

src/Infrastructure/Auth0/Abstractions/IAuthService.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ namespace Infrastructure.Auth0.Abstractions;
55
public interface IAuthService
66
{
77
Task<TokenInfoDto?> GetUserToken(LoginRequestDto req, CancellationToken ct);
8-
Task<TokenInfoDto?> RegisterUser(RegisterRequestDto req, CancellationToken ct);
8+
Task<UserInfoDto?> RegisterUser(RegisterRequestDto req, CancellationToken ct);
99
}

src/Infrastructure/Auth0/Auth0Service.cs src/Infrastructure/Auth0/AuthService.cs

+20-6
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using Infrastructure.Auth0.Abstractions;
44
using Infrastructure.Auth0.Configuration;
55
using Infrastructure.Auth0.Models;
6+
using Infrastructure.Persistence.MassTransit.Analytics;
67
using Microsoft.Extensions.Logging;
78
using Microsoft.Extensions.Options;
89

@@ -11,11 +12,13 @@ namespace Infrastructure.Auth0;
1112
public class AuthService(
1213
IOptions<Auth0Options> auth0Options,
1314
IAuthenticationApiClient authenticationClient,
15+
IUserAnalyticsClient userAnalyticsClient,
1416
ILogger<AuthService> logger) : IAuthService
1517
{
1618
private readonly Auth0Options _auth0Options = auth0Options.Value ??
1719
throw new ArgumentNullException(nameof(auth0Options));
1820
private readonly IAuthenticationApiClient _auth0Client = authenticationClient;
21+
private readonly IUserAnalyticsClient _userAnalyticsClient = userAnalyticsClient;
1922
private readonly ILogger<AuthService> _logger = logger;
2023

2124
public async Task<TokenInfoDto?> GetUserToken(LoginRequestDto req, CancellationToken ct)
@@ -33,14 +36,15 @@ public class AuthService(
3336
ClientSecret = _auth0Options.ClientSecret,
3437
Scope = "openid"
3538
}, ct);
36-
39+
3740
var authToken = auth0Response?.AccessToken;
3841
if (string.IsNullOrEmpty(authToken))
3942
{
4043
_logger.LogWarning("Failed to get token for user {Login}", req.Login);
4144
return null;
4245
}
43-
46+
47+
await _userAnalyticsClient.SendUserSignIn(req.Login, ct);
4448
return new TokenInfoDto(authToken, auth0Response?.ExpiresIn ?? 0);
4549
}
4650
catch (Exception ex)
@@ -50,11 +54,11 @@ public class AuthService(
5054
}
5155
}
5256

53-
public async Task<TokenInfoDto?> RegisterUser(RegisterRequestDto req, CancellationToken ct)
57+
public async Task<UserInfoDto?> RegisterUser(RegisterRequestDto req, CancellationToken ct)
5458
{
5559
try
5660
{
57-
var username = $"{req.FullName[0]}-{Guid.NewGuid().ToString()[..6]}";
61+
var username = $"{req.FullName[0]}-{Guid.NewGuid().ToString()[..6]}".ToLower();
5862
await _auth0Client.SignupUserAsync(new SignupUserRequest
5963
{
6064
Username = username,
@@ -71,8 +75,18 @@ await _auth0Client.SignupUserAsync(new SignupUserRequest
7175
Connection =_auth0Options.Realm,
7276
ClientId = _auth0Options.ClientId
7377
}, ct);
74-
75-
return await GetUserToken(new LoginRequestDto(req.Email, req.Password), ct);
78+
79+
// By now, all users registered are recipients.
80+
// Administrators are created manually via Auth0 management console.
81+
await _userAnalyticsClient.SendUserSignUp(username, req.Email, req.FullName, "recipient", ct);
82+
var tokenInfo = await GetUserToken(new LoginRequestDto(req.Email, req.Password), ct);
83+
if (tokenInfo is null)
84+
{
85+
_logger.LogWarning("Failed to register user {Login}", req.Login);
86+
return null;
87+
}
88+
89+
return new UserInfoDto(username, tokenInfo);
7690
}
7791
catch (Exception ex)
7892
{
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
namespace Infrastructure.Auth0.Models;
22

3-
public record TokenInfoDto(string Token, int ExpiresIn);
3+
public record TokenInfoDto(string Token, int ExpiresIn);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
namespace Infrastructure.Auth0.Models;
2+
3+
public record UserInfoDto(string UserId, TokenInfoDto TokenInfo);

src/Infrastructure/Infrastructure.csproj

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
<PackageReference Include="MongoAsyncEnumerableAdapter" Version="0.2.0" />
1616
<PackageReference Include="MongoDB.Driver" Version="2.22.0" />
1717
<PackageReference Include="MongoDB.Driver.Core" Version="2.22.0" />
18-
<PackageReference Include="Trumpee.MassTransit" Version="1.0.0.10" />
19-
<PackageReference Include="trumpee.masstransit.messages" Version="1.0.0.8" />
18+
<PackageReference Include="Trumpee.MassTransit" Version="1.0.0.13" />
19+
<PackageReference Include="trumpee.masstransit.messages" Version="1.0.0.15" />
2020
</ItemGroup>
2121

2222
</Project>

src/Infrastructure/Persistence/DependencyInjection.cs

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using Infrastructure.Auth0.Abstractions;
44
using Infrastructure.Auth0.Configuration;
55
using Infrastructure.Persistence.MassTransit;
6+
using Infrastructure.Persistence.MassTransit.Analytics;
67
using Infrastructure.Persistence.Mongo.Abstractions;
78
using Infrastructure.Persistence.Mongo.Configurations;
89
using Infrastructure.Persistence.Mongo.Repositories;
@@ -34,6 +35,7 @@ private static void AddMassTransit(this IServiceCollection services, IConfigurat
3435
services.AddConfiguredMassTransit(config);
3536

3637
services.AddScoped<ITemplateFillerClient, TemplateFillerClient>();
38+
services.AddScoped<IUserAnalyticsClient, UserAnalyticsClient>();
3739
}
3840

3941
private static void AddAuth0(this IServiceCollection services, IConfiguration config)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using MassTransit;
2+
using Trumpee.MassTransit;
3+
using Trumpee.MassTransit.Messages.Analytics.Users;
4+
5+
namespace Infrastructure.Persistence.MassTransit.Analytics;
6+
7+
public class UserAnalyticsClient(ISendEndpointProvider sendEndpointProvider) : IUserAnalyticsClient
8+
{
9+
private readonly ISendEndpointProvider _endpointProvider = sendEndpointProvider;
10+
11+
public async Task SendUserSignIn(string email, CancellationToken ct)
12+
{
13+
var analyticsEvent = User.SignIn("Trumpee Gateway", email);
14+
await SendEvent(analyticsEvent, ct);
15+
}
16+
17+
public async Task SendUserSignUp(string userId,
18+
string email, string name, string roles, CancellationToken ct)
19+
{
20+
var analyticsEvent = User.SignUp("Trumpee Gateway", userId, email, name, roles);
21+
await SendEvent(analyticsEvent, ct);
22+
}
23+
24+
public async Task SendUserAction(string email,
25+
string userAction, string usedRole, string affectedData, CancellationToken ct)
26+
{
27+
var analyticsEvent = User.Action("Trumpee Gateway", email, userAction, usedRole, affectedData);
28+
await SendEvent(analyticsEvent, ct);
29+
}
30+
31+
private async Task SendEvent<T>(T analyticsEvent, CancellationToken ct) where T : class
32+
{
33+
var endpoint = await _endpointProvider.GetSendEndpoint(new Uri(QueueNames.Analytics.Users));
34+
await endpoint.Send(analyticsEvent, ct);
35+
}
36+
}

src/Infrastructure/Persistence/MassTransit/TempalateFillerClient.cs

+3-8
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,13 @@
55

66
namespace Infrastructure.Persistence.MassTransit;
77

8-
public class TemplateFillerClient :
9-
MassTransitClient<Notification>, ITemplateFillerClient
8+
public class TemplateFillerClient(ISendEndpointProvider endpointProvider) :
9+
MassTransitClient<Notification>(endpointProvider), ITemplateFillerClient
1010
{
11-
public TemplateFillerClient(ISendEndpointProvider endpointProvider) :
12-
base(endpointProvider)
13-
{
14-
}
15-
1611
public new Task SendMessages(
1712
IEnumerable<Notification> messages,
1813
string _)
1914
{
20-
return base.SendMessages(messages, QueueNames.TemplateFillerQueueName);
15+
return base.SendMessages(messages, QueueNames.Services.TemplateFillerQueueName);
2116
}
2217
}

0 commit comments

Comments
 (0)