feat(server): email notifications (#8447)

* feat(server): add `react-mail` as mail template engine and `nodemailer`

* feat(server): add `smtp` related configs to `SystemConfig`

* feat(web): add page for SMTP settings

* feat(server): add `react-email.adapter`

This adapter render the React-Email into HTML and plain/text email.
The output is set as the body of the email.

* feat(server): add `MailRepository` and `MailService`

Allow to use the NestJS-modules-mailer module to send SMTP emails.
This is the base transport for the `NotificationRepository`

* feat(server): register the job dispatcher and Job for async email

This allows to queue email sending jobs for the `EmailService`.

* feat(server): add `NotificationRepository` and `NotificationService`

This act as a middleware to properly route the notification to the right transport.
As POC I've only implemented a simple SMTP transport.

* feat(server): add `welcome` email template

* feat(server): add the first notification on `createUser` in `UserService`

This trigger an event for the `NotificationRepository` that once processes
by using the global config and per-user config will carry the payload to the right notification transport.

* chore: clean up

* chore: clean up web

* fix: type errors"

* fix package lock

* fix mail sending, option to ignore certs

* chore: open api

* chore: clean up

* remove unused import

* feat: email feature flag

* chore: remove unused interface

* small styling

---------

Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
Co-authored-by: Daniel Dietzler <mail@ddietzler.dev>
Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
This commit is contained in:
Nicolò
2024-05-02 16:43:18 +02:00
committed by GitHub
parent 4b86c7a298
commit 9bce3417e9
60 changed files with 6499 additions and 371 deletions

View File

@@ -21,6 +21,7 @@ class SystemConfigDto {
required this.machineLearning,
required this.map,
required this.newVersionCheck,
required this.notifications,
required this.oauth,
required this.passwordLogin,
required this.reverseGeocoding,
@@ -47,6 +48,8 @@ class SystemConfigDto {
SystemConfigNewVersionCheckDto newVersionCheck;
SystemConfigNotificationsDto notifications;
SystemConfigOAuthDto oauth;
SystemConfigPasswordLoginDto passwordLogin;
@@ -73,6 +76,7 @@ class SystemConfigDto {
other.machineLearning == machineLearning &&
other.map == map &&
other.newVersionCheck == newVersionCheck &&
other.notifications == notifications &&
other.oauth == oauth &&
other.passwordLogin == passwordLogin &&
other.reverseGeocoding == reverseGeocoding &&
@@ -93,6 +97,7 @@ class SystemConfigDto {
(machineLearning.hashCode) +
(map.hashCode) +
(newVersionCheck.hashCode) +
(notifications.hashCode) +
(oauth.hashCode) +
(passwordLogin.hashCode) +
(reverseGeocoding.hashCode) +
@@ -103,7 +108,7 @@ class SystemConfigDto {
(user.hashCode);
@override
String toString() => 'SystemConfigDto[ffmpeg=$ffmpeg, image=$image, job=$job, library_=$library_, logging=$logging, machineLearning=$machineLearning, map=$map, newVersionCheck=$newVersionCheck, oauth=$oauth, passwordLogin=$passwordLogin, reverseGeocoding=$reverseGeocoding, server=$server, storageTemplate=$storageTemplate, theme=$theme, trash=$trash, user=$user]';
String toString() => 'SystemConfigDto[ffmpeg=$ffmpeg, image=$image, job=$job, library_=$library_, logging=$logging, machineLearning=$machineLearning, map=$map, newVersionCheck=$newVersionCheck, notifications=$notifications, oauth=$oauth, passwordLogin=$passwordLogin, reverseGeocoding=$reverseGeocoding, server=$server, storageTemplate=$storageTemplate, theme=$theme, trash=$trash, user=$user]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
@@ -115,6 +120,7 @@ class SystemConfigDto {
json[r'machineLearning'] = this.machineLearning;
json[r'map'] = this.map;
json[r'newVersionCheck'] = this.newVersionCheck;
json[r'notifications'] = this.notifications;
json[r'oauth'] = this.oauth;
json[r'passwordLogin'] = this.passwordLogin;
json[r'reverseGeocoding'] = this.reverseGeocoding;
@@ -142,6 +148,7 @@ class SystemConfigDto {
machineLearning: SystemConfigMachineLearningDto.fromJson(json[r'machineLearning'])!,
map: SystemConfigMapDto.fromJson(json[r'map'])!,
newVersionCheck: SystemConfigNewVersionCheckDto.fromJson(json[r'newVersionCheck'])!,
notifications: SystemConfigNotificationsDto.fromJson(json[r'notifications'])!,
oauth: SystemConfigOAuthDto.fromJson(json[r'oauth'])!,
passwordLogin: SystemConfigPasswordLoginDto.fromJson(json[r'passwordLogin'])!,
reverseGeocoding: SystemConfigReverseGeocodingDto.fromJson(json[r'reverseGeocoding'])!,
@@ -205,6 +212,7 @@ class SystemConfigDto {
'machineLearning',
'map',
'newVersionCheck',
'notifications',
'oauth',
'passwordLogin',
'reverseGeocoding',