Skip to content

Commit

Permalink
Add implementation for new IEmailSender<T>.
Browse files Browse the repository at this point in the history
  • Loading branch information
bitbound committed Feb 24, 2024
1 parent edb4bc5 commit 7478d63
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 38 deletions.
4 changes: 3 additions & 1 deletion Server/Components/Account/Pages/ForgotPassword.razor
Expand Up @@ -40,7 +40,9 @@
private async Task OnValidSubmitAsync()
{
var user = await UserManager.FindByEmailAsync(Input.Email);
if (user is null || !(await UserManager.IsEmailConfirmedAsync(user)))
// if (user is null || !(await UserManager.IsEmailConfirmedAsync(user)))
// Confirmation is currently disabled by default.
if (user is null)
{
// Don't reveal that the user does not exist or is not confirmed
RedirectManager.RedirectTo("Account/ForgotPasswordConfirmation");
Expand Down
3 changes: 1 addition & 2 deletions Server/Components/_Imports.razor
Expand Up @@ -25,5 +25,4 @@
@using Remotely.Server.Components.TreeView
@using Remotely.Server.Auth
@using Remotely.Shared.Entities
@using Remotely.Server.Models
@using Remotely.Server.Enums;
@using Remotely.Server.Models
39 changes: 20 additions & 19 deletions Server/Program.cs
@@ -1,31 +1,31 @@
using Immense.RemoteControl.Server.Extensions;
using Immense.SimpleMessenger;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.Server.Circuits;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.RateLimiting;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.FileProviders;
using Remotely.Server.Auth;
using Remotely.Server.Components;
using Remotely.Server.Components.Account;
using Remotely.Server.Data;
using Remotely.Server.Extensions;
using Remotely.Server.Hubs;
using Remotely.Server.Models;
using Remotely.Server.Options;
using Remotely.Server.Services;
using System.Net;
using Immense.RemoteControl.Server.Extensions;
using Remotely.Server.Services.RcImplementations;
using Remotely.Server.Services.Stores;
using Remotely.Shared.Entities;
using Remotely.Shared.Services;
using Serilog;
using Microsoft.AspNetCore.RateLimiting;
using System.Net;
using RatePolicyNames = Remotely.Server.RateLimiting.PolicyNames;
using Remotely.Shared.Entities;
using Immense.SimpleMessenger;
using Remotely.Server.Services.Stores;
using Remotely.Server.Components.Account;
using Remotely.Server.Components;
using Remotely.Server.Options;
using Remotely.Server.Extensions;
using Remotely.Server.Models;

var builder = WebApplication.CreateBuilder(args);
var configuration = builder.Configuration;
Expand Down Expand Up @@ -57,19 +57,22 @@
{
case "sqlite":
services.AddDbContext<AppDb, SqliteDbContext>(
contextLifetime: ServiceLifetime.Transient,
contextLifetime: ServiceLifetime.Transient,
optionsLifetime: ServiceLifetime.Transient);
break;

case "sqlserver":
services.AddDbContext<AppDb, SqlServerDbContext>(
contextLifetime: ServiceLifetime.Transient,
optionsLifetime: ServiceLifetime.Transient);
break;

case "postgresql":
services.AddDbContext<AppDb, PostgreSqlDbContext>(
contextLifetime: ServiceLifetime.Transient,
optionsLifetime: ServiceLifetime.Transient);
break;

default:
throw new InvalidOperationException(
$"Invalid DBProvider: {dbProvider}. Ensure a valid value " +
Expand Down Expand Up @@ -112,7 +115,6 @@
.AddSignInManager()
.AddDefaultTokenProviders();


services.AddScoped<IAuthorizationHandler, TwoFactorRequiredHandler>();
services.AddScoped<IAuthorizationHandler, OrganizationAdminRequirementHandler>();
services.AddScoped<IAuthorizationHandler, ServerAdminRequirementHandler>();
Expand Down Expand Up @@ -154,7 +156,7 @@

services.AddCors(options =>
{
if (settings.TrustedCorsOrigins is { Count: > 0} trustedOrigins)
if (settings.TrustedCorsOrigins is { Count: > 0 } trustedOrigins)
{
options.AddPolicy("TrustedOriginPolicy", builder => builder
.WithOrigins(trustedOrigins.ToArray())
Expand All @@ -165,7 +167,6 @@
}
});


services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders = ForwardedHeaders.All;
Expand All @@ -177,7 +178,7 @@
options.KnownProxies.Add(dockerGatewayIp);
}
if (settings.KnownProxies is { Count: >0 } knownProxies)
if (settings.KnownProxies is { Count: > 0 } knownProxies)
{
foreach (var proxy in knownProxies)
{
Expand Down Expand Up @@ -207,7 +208,7 @@
{
clOptions.QueueLimit = int.MaxValue;
clOptions.PermitLimit =
clOptions.PermitLimit =
settings.MaxConcurrentUpdates <= 0 ?
10 :
settings.MaxConcurrentUpdates;
Expand All @@ -222,6 +223,7 @@
}
else
{
services.AddScoped<IEmailSender<RemotelyUser>, EmailSenderEx>();
services.AddScoped<IEmailSenderEx, EmailSenderEx>();
}
services.AddSingleton<IAppDbFactory, AppDbFactory>();
Expand Down Expand Up @@ -367,13 +369,12 @@ void ConfigureSerilog(WebApplicationBuilder webAppBuilder, SettingsModel setting
{
try
{

var dataRetentionDays = settings.DataRetentionInDays;
if (dataRetentionDays <= 0)
{
dataRetentionDays = 7;
}

var logPath = LogsManager.DefaultLogsDirectory;

void ApplySharedLoggerConfig(LoggerConfiguration loggerConfiguration)
Expand Down
59 changes: 43 additions & 16 deletions Server/Services/EmailSender.cs
@@ -1,21 +1,16 @@
using MailKit.Net.Smtp;
using MailKit.Security;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.Build.Framework;
using Microsoft.Extensions.Logging;
using Microsoft.Identity.Client;
using MimeKit;
using MimeKit.Text;
using NuGet.Configuration;
using System;
using System.Net;
using System.Threading.Tasks;
using Remotely.Shared.Entities;

namespace Remotely.Server.Services;

public interface IEmailSenderEx
{
Task<bool> SendEmailAsync(string email, string replyTo, string subject, string htmlMessage, string? organizationID = null);

Task<bool> SendEmailAsync(string email, string subject, string htmlMessage, string? organizationID = null);
}

Expand All @@ -34,7 +29,7 @@ public Task SendEmailAsync(string email, string subject, string htmlMessage)
}
}

public class EmailSenderEx : IEmailSenderEx
public class EmailSenderEx : IEmailSenderEx, IEmailSender<RemotelyUser>
{
private readonly IDataService _dataService;
private readonly ILogger<EmailSenderEx> _logger;
Expand All @@ -46,11 +41,22 @@ public class EmailSenderEx : IEmailSenderEx
_dataService = dataService;
_logger = logger;
}

public async Task SendConfirmationLinkAsync(RemotelyUser user, string email, string confirmationLink)
{
await SendEmailAsync(
email,
"Remotely Account Confirmation",
"Please confirm your Remotely account by clicking the following link: " +
$"<a href=\"{confirmationLink}\">{confirmationLink}</a>",
user.OrganizationID);
}

public async Task<bool> SendEmailAsync(
string toEmail,
string replyTo,
string subject,
string htmlMessage,
string toEmail,
string replyTo,
string subject,
string htmlMessage,
string? organizationID = null)
{
try
Expand All @@ -68,7 +74,7 @@ public class EmailSenderEx : IEmailSenderEx
};

using var client = new SmtpClient();

if (!string.IsNullOrWhiteSpace(settings.SmtpLocalDomain))
{
client.LocalDomain = settings.SmtpLocalDomain;
Expand Down Expand Up @@ -103,7 +109,28 @@ public async Task<bool> SendEmailAsync(string email, string subject, string html
var settings = await _dataService.GetSettings();
return await SendEmailAsync(email, settings.SmtpEmail, subject, htmlMessage, organizationID);
}

public async Task SendPasswordResetCodeAsync(RemotelyUser user, string email, string resetCode)
{
await SendEmailAsync(
email,
"Remotely Password Reset",
$"A password reset code has been requested for your account. Reset Code: {resetCode}",
user.OrganizationID);
}

public async Task SendPasswordResetLinkAsync(RemotelyUser user, string email, string resetLink)
{
await SendEmailAsync(
email,
"Remotely Password Reset",
"A password reset has been requested for your account. If this was not requested by you, you can ignore this email.<br/><br/>" +
"Otherwise, please follow this link to reset your password: " +
$"<a href=\"{resetLink}\">{resetLink}</a>",
user.OrganizationID);
}
}

public class EmailSenderFake(ILogger<EmailSenderFake> _logger) : IEmailSenderEx
{
public Task<bool> SendEmailAsync(string email, string replyTo, string subject, string htmlMessage, string? organizationID = null)
Expand All @@ -112,8 +139,8 @@ public Task<bool> SendEmailAsync(string email, string replyTo, string subject, s
"Fake EmailSender registered in dev mode. " +
"Email would have been sent to {email}." +
"\n\nSubject: {EmailSubject}. " +
"\n\nMessage: {EmailMessage}",
email,
"\n\nMessage: {EmailMessage}",
email,
subject,
htmlMessage);
return Task.FromResult(true);
Expand Down

0 comments on commit 7478d63

Please sign in to comment.