Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AWS SES implementation #201

Merged
Merged
Show file tree
Hide file tree
Changes from 40 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
9aa5d21
Added AWS-related settings to appsettings
belmirp Feb 16, 2023
ecd3ce4
Added basic implementation of Amazon SES
belmirp Feb 16, 2023
6593288
Exposed sending email in AdminPanelController for testing purposes
belmirp Feb 16, 2023
d7edf22
Refactored ApplicationStartupService
belmirp Feb 16, 2023
2dd3d81
Exposed endpoint for sending email as HTML in AdminPanelController
belmirp Feb 16, 2023
7712703
Added status and activation GUID to Account model
belmirp Feb 16, 2023
4c0e67f
Added NoReplyEmail to appsettings
belmirp Feb 16, 2023
9f1c404
Formatted appsettings
belmirp Feb 16, 2023
41891d9
Sending activation link on account creation
belmirp Feb 16, 2023
061f8dd
Added WebsiteDomain to development appsettings
belmirp Feb 16, 2023
3101779
Saving account status always
belmirp Feb 16, 2023
cc61671
Added endpoint and method for activating account
belmirp Feb 16, 2023
7b983c9
Added getRouteParamBooleanValue to utilities
belmirp Feb 16, 2023
74bb5dc
Showing alert for activation link after registration
belmirp Feb 16, 2023
a3ad9fe
Changed path for activation link
belmirp Feb 16, 2023
aa33596
Added activation route and component on the frontent
belmirp Feb 16, 2023
8fd986d
Added fields needed for reset password to account
belmirp Feb 18, 2023
494d76c
Added RateLimitService
belmirp Feb 18, 2023
b42b55f
Added initiate reset password methods to backend
belmirp Feb 18, 2023
88d43eb
Added NotFoundException and RateLimitExceededException to ErrorsContr…
belmirp Feb 18, 2023
703c08d
Added Forgot Password page on frontend
belmirp Feb 18, 2023
a8656c7
Added ResetPassword methods and UI components
belmirp Feb 18, 2023
4cbc651
Reverted WebsitePort settings
belmirp Feb 18, 2023
2c8ba5a
Hiding components when reset password completes
belmirp Feb 18, 2023
111fdfa
Merged master
belmirp Feb 19, 2023
58f385f
Reverted deleted endpoints after merge
belmirp Feb 19, 2023
772073b
Added ability to resend activation link
belmirp Feb 19, 2023
58e80e2
Merge branch 'master' into aws-ses-implementation
belmirp Feb 19, 2023
4ab43f5
Changed code to string for HttpError
belmirp Feb 20, 2023
e588e2d
Changed logic for parsing query string
belmirp Feb 20, 2023
c816003
Removed unnecessary utility function
belmirp Feb 20, 2023
08ef845
Fixed casting for query variables
belmirp Feb 21, 2023
db5599b
Merge branch 'master' into aws-ses-implementation
belmirp Feb 21, 2023
43cad17
Added AccountActivationException specific for activate account flow
belmirp Feb 21, 2023
dd939aa
Refactored activate account to be POST request instead of GET
belmirp Feb 21, 2023
e81b8e2
Refactored resend activation link flow to use POST instead of GET req…
belmirp Feb 21, 2023
218706c
Changed initiate reset password flow to use POST instead of GET request
belmirp Feb 21, 2023
241483e
Renamed IResendActivationLink to IResendActivationLinkRequest
belmirp Feb 21, 2023
8113873
Renamed reset-password.ts to reset-password-request.ts
belmirp Feb 21, 2023
a8b3b8e
Standardized naming for master server error responses
belmirp Feb 21, 2023
394ea9a
Fixed how query strings are validated
belmirp Feb 21, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions UT4MasterServer.Common/Enums/AccountStatus.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace UT4MasterServer.Common.Enums;

public enum AccountStatus
{
PendingActivation = 0,
Active = 1,
}
14 changes: 14 additions & 0 deletions UT4MasterServer.Common/Exceptions/AccountActivationException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace UT4MasterServer.Common.Exceptions;

[Serializable]
public sealed class AccountActivationException : Exception
{
public AccountActivationException(string message) : base(message)
{
}

public AccountActivationException(string message, Exception innerException) : base(message, innerException)
{
}
}

13 changes: 13 additions & 0 deletions UT4MasterServer.Common/Exceptions/AccountNotActiveException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace UT4MasterServer.Common.Exceptions;

[Serializable]
public sealed class AccountNotActiveException : Exception
{
public AccountNotActiveException(string message) : base(message)
{
}

public AccountNotActiveException(string message, Exception innerException) : base(message, innerException)
{
}
}
13 changes: 13 additions & 0 deletions UT4MasterServer.Common/Exceptions/AwsSesClientException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace UT4MasterServer.Common.Exceptions;

[Serializable]
public sealed class AwsSesClientException : Exception
{
public AwsSesClientException(string message) : base(message)
{
}

public AwsSesClientException(string message, Exception innerException) : base(message, innerException)
{
}
}
13 changes: 13 additions & 0 deletions UT4MasterServer.Common/Exceptions/NotFoundException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace UT4MasterServer.Common.Exceptions;

[Serializable]
public sealed class NotFoundException : Exception
{
public NotFoundException(string message) : base(message)
{
}

public NotFoundException(string message, Exception innerException) : base(message, innerException)
{
}
}
13 changes: 13 additions & 0 deletions UT4MasterServer.Common/Exceptions/RateLimitExceededException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace UT4MasterServer.Common.Exceptions;

[Serializable]
public sealed class RateLimitExceededException : Exception
{
public RateLimitExceededException(string message) : base(message)
{
}

public RateLimitExceededException(string message, Exception innerException) : base(message, innerException)
{
}
}
9 changes: 9 additions & 0 deletions UT4MasterServer.Models/DTO/Request/SendEmailRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace UT4MasterServer.Models.DTO.Request;

public sealed class SendEmailRequest
{
public string From { get; set; } = string.Empty;
public List<string> To { get; set; } = new();
public string Subject { get; set; } = string.Empty;
public string Body { get; set; } = string.Empty;
}
14 changes: 14 additions & 0 deletions UT4MasterServer.Models/Database/Account.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,20 @@ public class Account
[BsonElement("Flags")]
public AccountFlags Flags { get; set; } = 0;

[BsonIgnoreIfNull]
public string? ActivationLinkGUID { get; set; }

[BsonIgnoreIfNull]
public DateTime? ActivationLinkExpiration { get; set; }

[BsonIgnoreIfNull]
public string? ResetLinkGUID { get; set; }

[BsonIgnoreIfNull]
public DateTime? ResetLinkExpiration { get; set; }

public AccountStatus Status { get; set; } = AccountStatus.PendingActivation;

[BsonIgnore]
public float Level
{
Expand Down
8 changes: 8 additions & 0 deletions UT4MasterServer.Models/Settings/AWSSettings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace UT4MasterServer.Models.Settings;

public sealed class AWSSettings
{
public string AccessKey { get; set; } = string.Empty;
public string SecretKey { get; set; } = string.Empty;
public string RegionName { get; set; } = string.Empty;
}
15 changes: 15 additions & 0 deletions UT4MasterServer.Models/Settings/ApplicationSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,21 @@ public sealed class ApplicationSettings
/// </remarks>
public bool AllowPasswordGrantType { get; set; } = false;

/// <summary>
/// Used for URL generation when sending activation link, reset links, etc.
/// </summary>
public string WebsiteScheme { get; set; } = string.Empty;

/// <summary>
/// Used just to redirect users to correct domain when UT4UU is being used.
/// </summary>
public string WebsiteDomain { get; set; } = string.Empty;

/// <summary>
/// Used for URL generation when sending activation link, reset links, etc.
/// </summary>
public int WebsitePort { get; set; } = -1;

/// <summary>
/// File containing a list of trusted proxy servers (one per line).
/// This file is loaded only once when program starts and it add values to <see cref="ProxyServers"/>.
Expand All @@ -30,4 +40,9 @@ public sealed class ApplicationSettings
/// IP addresses of trusted proxy servers.
/// </summary>
public List<string> ProxyServers { get; set; } = new List<string>();

/// <summary>
/// No-reply email that will be used for activation links, reset password links, etc
/// </summary>
public string NoReplyEmail { get; set; } = string.Empty;
}
78 changes: 35 additions & 43 deletions UT4MasterServer.Services/Hosted/ApplicationStartupService.cs
Original file line number Diff line number Diff line change
@@ -1,50 +1,42 @@
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using UT4MasterServer.Models.Settings;
using UT4MasterServer.Services.Scoped;

namespace UT4MasterServer.Services.Hosted
namespace UT4MasterServer.Services.Hosted;

public sealed class ApplicationStartupService : IHostedService
{
public sealed class ApplicationStartupService : IHostedService
private readonly ILogger<ApplicationStartupService> logger;
private readonly IServiceProvider serviceProvider;

public ApplicationStartupService(ILogger<ApplicationStartupService> logger, IServiceProvider serviceProvider)
{
this.logger = logger;
this.serviceProvider = serviceProvider;
}

public async Task StartAsync(CancellationToken cancellationToken)
{
private readonly ILogger<ApplicationStartupService> logger;
private readonly AccountService accountService;
private readonly StatisticsService statisticsService;
private readonly CloudStorageService cloudStorageService;
private readonly ClientService clientService;
private readonly RatingsService ratingsService;

public ApplicationStartupService(
ILogger<ApplicationStartupService> logger,
ILogger<StatisticsService> statsLogger,
IOptions<ApplicationSettings> settings,
ILogger<CloudStorageService> cloudStorageLogger,
ILogger<RatingsService> ratingsLogger)
{
this.logger = logger;
var db = new DatabaseContext(settings);
accountService = new AccountService(db, settings);
statisticsService = new StatisticsService(statsLogger, db);
cloudStorageService = new CloudStorageService(db, cloudStorageLogger);
clientService = new ClientService(db);
ratingsService = new RatingsService(ratingsLogger, db);
}

public async Task StartAsync(CancellationToken cancellationToken)
{
logger.LogInformation("Configuring MongoDB indexes.");
await accountService.CreateIndexesAsync();
await statisticsService.CreateIndexesAsync();
await ratingsService.CreateIndexesAsync();

logger.LogInformation("Initializing MongoDB CloudStorage.");
await cloudStorageService.EnsureSystemFilesExistAsync();

logger.LogInformation("Initializing MongoDB Clients.");
await clientService.UpdateDefaultClientsAsync();
}

public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
using var scope = serviceProvider.CreateScope();

var accountService = scope.ServiceProvider.GetRequiredService<AccountService>();
var statisticsService = scope.ServiceProvider.GetRequiredService<StatisticsService>();
var ratingsService = scope.ServiceProvider.GetRequiredService<RatingsService>();
var cloudStorageService = scope.ServiceProvider.GetRequiredService<CloudStorageService>();
var clientService = scope.ServiceProvider.GetRequiredService<ClientService>();

logger.LogInformation("Configuring MongoDB indexes.");
await accountService.CreateIndexesAsync();
await statisticsService.CreateIndexesAsync();
await ratingsService.CreateIndexesAsync();

logger.LogInformation("Initializing MongoDB CloudStorage.");
await cloudStorageService.EnsureSystemFilesExistAsync();

logger.LogInformation("Initializing MongoDB Clients.");
await clientService.UpdateDefaultClientsAsync();
}

public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}
Loading