-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #44 from galliumplus/feature/users
Changement de mot de passe et envoi de mail
- Loading branch information
Showing
23 changed files
with
741 additions
and
89 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
using Stubble.Core.Interfaces; | ||
using System.Collections.Concurrent; | ||
using System.Text; | ||
|
||
namespace GalliumPlus.WebApi.Core.Email | ||
{ | ||
/// <summary> | ||
/// Un chargeur de modèles qui va récupère les données depuis le système de | ||
/// fichiers local et les mets en cache. Les modèles sont identifiés par leur | ||
/// nom de fichier. | ||
/// </summary> | ||
public class CachedLocalEmailTemplateLoader : IEmailTemplateLoader, IStubbleLoader | ||
{ | ||
private string baseDirectory; | ||
private Dictionary<string, string> cache; | ||
|
||
/// <summary> | ||
/// Crée un nouveau chargeur local. | ||
/// </summary> | ||
/// <param name="baseDirectory">Le chemin absolu du dossier contenant les modèles.</param> | ||
public CachedLocalEmailTemplateLoader(string baseDirectory) | ||
{ | ||
this.baseDirectory = baseDirectory; | ||
this.cache = new(); | ||
} | ||
|
||
public IStubbleLoader Clone() | ||
{ | ||
var loader = new CachedLocalEmailTemplateLoader(this.baseDirectory) | ||
{ | ||
cache = new(this.cache) | ||
}; | ||
return loader; | ||
} | ||
|
||
public string Load(string name) | ||
{ | ||
string? template; | ||
bool cached; | ||
|
||
lock (this.cache) | ||
{ | ||
cached = this.cache.TryGetValue(name, out template); | ||
} | ||
|
||
if (!cached) | ||
{ | ||
try | ||
{ | ||
using (StreamReader f = new(Path.Join(this.baseDirectory, name))) | ||
{ | ||
template = f.ReadToEnd(); | ||
} | ||
lock (this.cache) | ||
{ | ||
cache.TryAdd(name, template); | ||
} | ||
} | ||
catch (FileNotFoundException err) | ||
{ | ||
Console.WriteLine(err.Message); | ||
template = null; | ||
} | ||
} | ||
|
||
return template!; | ||
} | ||
|
||
public async ValueTask<string> LoadAsync(string name) | ||
{ | ||
string? template; | ||
|
||
if (!cache.TryGetValue(name, out template)) | ||
{ | ||
try | ||
{ | ||
using (StreamReader f = new(Path.Join(this.baseDirectory, name), Encoding.UTF8)) | ||
{ | ||
template = await f.ReadToEndAsync(); | ||
} | ||
cache.Add(name, template); | ||
} | ||
catch (FileNotFoundException err) | ||
{ | ||
Console.WriteLine(err.Message); | ||
template = null; | ||
} | ||
} | ||
|
||
return template!; | ||
} | ||
|
||
public EmailTemplate GetTemplate(string identifier) | ||
{ | ||
return new EmailTemplate(identifier, this); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
using Stubble.Core; | ||
using Stubble.Core.Builders; | ||
using Stubble.Core.Interfaces; | ||
|
||
namespace GalliumPlus.WebApi.Core.Email | ||
{ | ||
/// <summary> | ||
/// Un modèle de mail. | ||
/// </summary> | ||
public class EmailTemplate | ||
{ | ||
private string name; | ||
private StubbleVisitorRenderer renderer; | ||
|
||
/// <summary> | ||
/// Crée un nouveau modèle de mail. | ||
/// </summary> | ||
/// <param name="name">Le nom du modèle.</param> | ||
/// <param name="partialTemplateLoader">(optionnel) Le chargeur de modèles partiels.</param> | ||
public EmailTemplate(string name, IStubbleLoader? partialTemplateLoader) | ||
{ | ||
this.name = name; | ||
|
||
this.renderer = new StubbleBuilder() | ||
.Configure(settings => | ||
{ | ||
if (partialTemplateLoader is not null) | ||
{ | ||
settings.AddToTemplateLoader(partialTemplateLoader); | ||
} | ||
}) | ||
.Build(); | ||
} | ||
|
||
/// <summary> | ||
/// Imprime un corps de mail à partir des données fournies. | ||
/// </summary> | ||
/// <param name="view">Les données à utiliser pour remplir le modèle.</param> | ||
/// <returns>Le corps du mail.</returns> | ||
public string Render(object view) | ||
{ | ||
return this.renderer.Render(this.name, view); | ||
} | ||
|
||
/// <inheritdoc cref="Render(object)"/> | ||
public ValueTask<string> RenderAsync(object view) | ||
{ | ||
return this.renderer.RenderAsync(this.name, view); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
namespace GalliumPlus.WebApi.Core.Email | ||
{ | ||
/// <summary> | ||
/// Un système d'envoi de mail. | ||
/// </summary> | ||
public interface IEmailSender | ||
{ | ||
/// <summary> | ||
/// Envoie un mail. | ||
/// </summary> | ||
/// <param name="recipient">L'adresse mail du destinataire.</param> | ||
/// <param name="subject">Le sujet du mail.</param> | ||
/// <param name="content">Le contenu du mail (typiquement le résultat de <see cref="EmailTemplate.Render"/>).</param> | ||
void Send(string recipient, string subject, string content); | ||
|
||
/// <inheritdoc cref="Send"/> | ||
Task SendAsync(string recipient, string subject, string content, CancellationToken ct = default); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
namespace GalliumPlus.WebApi.Core.Email | ||
{ | ||
/// <summary> | ||
/// Un chargeur de modèles. Son rôle est de préparer des <see cref="EmailTemplate"/>. | ||
/// </summary> | ||
public interface IEmailTemplateLoader | ||
{ | ||
/// <summary> | ||
/// Charge un modèle de mail. | ||
/// </summary> | ||
/// <param name="identifier">Une chaîne de caractère permettant d'identifier le modèle.</param> | ||
EmailTemplate GetTemplate(string identifier); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
using Humanizer; | ||
using System.Globalization; | ||
|
||
namespace GalliumPlus.WebApi.Core.Email.TemplateViews | ||
{ | ||
/// <summary> | ||
/// Le contenu dynamique d'un mail d'initialisation de compte ou de réinitialisation de mot de passe. | ||
/// <br/> | ||
/// (Ces mails sont envoyé à l'utilisateur lorsqu'un nouveau compte est créé ou qu'il a oublié son mot de passe) | ||
/// </summary> | ||
public class InitOrResetPassword | ||
{ | ||
/// <summary> | ||
/// Le lien permettant d'activer le compte/changer le mot de passe. | ||
/// </summary> | ||
public string Link { get; private init; } | ||
|
||
/// <summary> | ||
/// L'heure d'expiration du lien (<see cref="Link"/>). | ||
/// </summary> | ||
public DateTime Expiration { get; private init; } | ||
|
||
/// <summary> | ||
/// Une version humaine de l'heure d'expiration du lien (par ex. <em>« dans 2 heures »</em>). | ||
/// </summary> | ||
public string HumanExpiration => this.Expiration.Humanize(utcDate: true, culture: new CultureInfo("fr-FR")); | ||
|
||
/// <summary> | ||
/// Rassemble les données pour un nouveau mail de (ré)initialisation. | ||
/// </summary> | ||
/// <param name="link">L'URL complète de la page de saisie de mot de passe.</param> | ||
/// <param name="expiration">L'heure d'expiration du lien, en temps UTC.</param> | ||
public InitOrResetPassword(string link, DateTime expiration) | ||
{ | ||
this.Link = link; | ||
if (expiration.Kind != DateTimeKind.Utc) throw new ArgumentException("The link expiration must be expressed in UTC."); | ||
this.Expiration = expiration; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.