[PB-1960]: feat/implement mail account provisioning and recovery email functionality#1019
[PB-1960]: feat/implement mail account provisioning and recovery email functionality#1019
Conversation
5886722 to
a07353d
Compare
a07353d to
c0b82e5
Compare
c0b82e5 to
6452a6b
Compare
| dto: CreateMailAccountDto, | ||
| ): Promise<{ token: string; newToken: string; address: string }> { | ||
| await this.assertMailAccessEnabled(user); | ||
| this.verifyPassword(user, dto.password); |
There was a problem hiding this comment.
Do we expect users to send their password when creating an email address? What's the flow for this?
There was a problem hiding this comment.
If not, you could try to use the gateway for any check you need and create the mail directly from mail-server instead.
I guess it depends on the other comment.
There was a problem hiding this comment.
If the user uses a @inxt.com (example) to login, Drive (because it contains the auth) should ask mail to locate the uuid here by that username, and with that uuid and the password, match against drive.users. Am I wrong @jzunigax2 @apsantiso ?
There was a problem hiding this comment.
In consequence, we should not ask for the password here
There was a problem hiding this comment.
@sg-gs this is intended as a flow that runs the first time a user acceses mail. they choose their new internxt email address and must re enter their password right before submitting.
if succesful they would now use their new internxt email address to login and their original email becomes their recovery email.
however I do agree with @apsantiso there are many edge cases, I guess all email comunications would have to defaut to recovery email if available
There was a problem hiding this comment.
Okay then, anyway, use the gateway to check the password against the auth source of truth (right now, Drive)
There was a problem hiding this comment.
hmm, the reason this logic lives here in drive rather than mail is that at this point in the flow mail-server has zero user context, it doesn't know if the user exists, is authenticated, or has mail access. All of that lives here in drive.
The flow is:
- User exists and is already authed (drive validates the token)
- Drive checks the feature limit (mail access on their plan)
- Drive verifies the password re confirmation
- Drive calls mail-server via mail's gateway to provision the account
- Drive handles the auth side-effects like updating the email, issuing new tokens
There was a problem hiding this comment.
We can also share the token at some extend like we did with VPN @jzunigax2. Just throwing ideas tho. Not sure if that aligns with what @sg-gs thought
| await this.userRepository.updateByUuid(user.uuid, { | ||
| email: fullAddress, | ||
| recoveryEmail: previousEmail, | ||
| }); | ||
| } catch (error) { | ||
| await this.userRepository.updateByUuid(user.uuid, { | ||
| email: previousEmail, | ||
| recoveryEmail: null, | ||
| }); | ||
| throw error; | ||
| } | ||
|
|
||
| const updatedUser = await this.userRepository.findByUuid(user.uuid); | ||
|
|
||
| const { token, newToken } = | ||
| await this.userUseCases.getAuthTokens(updatedUser); | ||
|
|
||
| return { token, newToken, address: fullAddress }; |
There was a problem hiding this comment.
Do we really want to change how drive-server works and identifies users because of mail?
If the user downgrades then we would need to change the email again. I know it seems to be a product decision, but it could create strange edge cases here.
It might be worth to re-check this with product @jzunigax2 @sg-gs
There was a problem hiding this comment.
At product level they want to make possible to login with your @inxt.com mail, which means we should match that, but just in case the user has mail enabled.
There was a problem hiding this comment.
Ok, what about preserving the email field as it is and store the internxt email in another field or even table (I would go for the second option to support multiple emails in the future)?
If the user wish to change their primary email they can always change the email manually. @jzunigax2 @sg-gs
The only downside I see is related to any sharing/workspace operation that requires searching by mail. We would need to change the mail search in those usecases
There was a problem hiding this comment.
Anyway, we need to think about the downgrade process. We would need to prevent new users from signing up with the recovery_email too.
There was a problem hiding this comment.
Anyway, we need to think about the downgrade process. We would need to prevent new users from signing up with the recovery_email too.
Isn't this already handled by the signup itself? Or am I missing something?
Ok, what about preserving the email field as it is and store the internxt email in another field or even table (I would go for the second option to support multiple emails in the future)?
If the user wish to change their primary email they can always change the email manually.
At our level (before Stalwart) I assume we should have the local-part (this naming comes from https://datatracker.ietf.org/doc/html/rfc5322) multiplexing per user on another table.
The only downside I see is related to any sharing/workspace operation that requires searching by mail. We would need to change the mail search in those usecases
Why? I mean, we will search by the local-part and from there, get the user (in case you need the search to find the user) or are you referring to something else?
There was a problem hiding this comment.
Why? I mean, we will search by the local-part and from there, get the user (in case you need the search to find the user) or are you referring to something else?
@sg-gs I mean we should change how we search for the user in the "invite user" usecase, which uses the email address to find the user. Not a big deal as we use mainly uuids tho. If I can login with john@internxt.com too, I would expect other users to find me as john@internxt.com too.
Isn't this already handled by the signup itself? Or am I missing something?
No, the current status of the code switches the user's original email to recovery_email and the internxt's email becomes the new 'email'. That's why I jumped in, as changing the main email would lead to weird things. IMO we should store the data like this:
- Primary email: XXX@original-external-mail.com
Mails associated
So when the users want to log in, we just need to search for the primary email + associated mails (local-parts, whatever we do).
Instead of switching them:
- Primary email: xxx@internxt.eu
Recovery email
I may be missing things so correct me if I'm just pushing things blindly haha
There was a problem hiding this comment.
@sg-gs I mean we should change how we search for the user in the "invite user" usecase, which uses the email address to find the user. Not a big deal as we use mainly uuids tho. If I can login with john@internxt.com too, I would expect other users to find me as john@internxt.com too.
Let's assume this happens, in both ways:
- An Internxt user that has multiple mail extensions is invited to an item. Receives the email, joins with a token, Drive's session is the same, it works.
a. The internal invitation notifications will still appear as it is invited using its uuid. (which mail would have also) - An Internxt User that does not have Mail --> not affected.
So I do not see any issue here
That's why I jumped in, as changing the main email would lead to weird things
This could be visual. I won't change it internally. Just do the following:
- User without mail -> works as always.
- User using a internxt mail domain -> ask Mail for the uuid, get the password on Drive with that uuid -> match password.
And Drive would still have the same thing: email, password, uuid
And Mail would store: uuid, mail.localParts.userId -> mail.users.uuid (FK), mail.localParts.value (here, there would be as many rows per user as different domains it can have)
…ality - Added migration to include recovery_email field in users table. - Introduced Mail module with MailService and MailController for handling mail account creation. - Implemented MailUseCases to manage mail account provisioning and validation. - Updated user model to support recovery email and added necessary DTOs for mail account creation. - Enhanced audit logging to track mail setup actions.
6452a6b to
dd84afb
Compare
- Deleted migration for recovery_email field in users table. - Refactored MailService and AuthController to remove recovery email handling. - Updated MailUseCases and user model to eliminate recovery email references. - Introduced managed mail domains logic for email resolution in login process.
|
|
@sg-gs @apsantiso addressed concerns, removed recovery mail stuff and the email replacement logic. I'll improve test coverage, but in the meantime does it look good overall? |
There was a problem hiding this comment.
I think this should not be part of Drive, rather than from payments.
| const userId = await this.mailService.findUserIdByAddress(email); | ||
| if (!userId) return email; | ||
|
|
||
| const user = await this.userUseCases.findByUuid(userId).catch(() => null); |
There was a problem hiding this comment.
Don't hide errors, log or let them propagate
| private readonly mailService: MailService, | ||
| ) {} | ||
|
|
||
| private async resolveLoginEmail(email: string): Promise<string> { |
There was a problem hiding this comment.
This is part of the login logic, I will add it to the auth.service, not in the controller, as this applies to the login itself, with independence of the web login or the CLI one
| import { AuditLog } from '../../common/audit-logs/decorators/audit-log.decorator'; | ||
| import { AuditAction } from '../../common/audit-logs/audit-logs.attributes'; | ||
|
|
||
| @Controller('mail') |
There was a problem hiding this comment.
Why is this here? Shouldn't this be on mail-server?
|
closing in favor of internxt/mail-server#25 |


Uh oh!
There was an error while loading. Please reload this page.