Skip to content

Commit 6d668fb

Browse files
0xi4oyau-wd
andauthored
feat: email change confirmation flow (#5992)
* fix: update stripe email when changing email in account settings * fix: review feedback * fix: circular dependency, destroy all sessions on email change * add: email change confirmation flow + smtp available check + enable email flows for oss and enterprise * add: confirm email change page. update: change email behavior in account settings --------- Co-authored-by: yau-wd <yau.ong@workday.com>
1 parent dc07f40 commit 6d668fb

18 files changed

Lines changed: 2712 additions & 31 deletions

packages/server/src/IdentityManager.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,11 @@ export class IdentityManager {
312312
return await this.stripeManager.getCustomerWithDefaultSource(customerId)
313313
}
314314

315+
public async updateStripeCustomerEmail(customerId: string, email: string) {
316+
if (!this.stripeManager) throw new Error('Stripe manager is not initialized')
317+
await this.stripeManager.updateCustomerEmail(customerId, email)
318+
}
319+
315320
public async getAdditionalSeatsProration(subscriptionId: string, newQuantity: number) {
316321
if (!subscriptionId) return {}
317322
if (!this.stripeManager) {

packages/server/src/StripeManager.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,11 @@ export class StripeManager {
270270
}
271271
}
272272

273+
public async updateCustomerEmail(customerId: string, email: string) {
274+
if (!this.stripe) throw new Error('Stripe is not initialized')
275+
await this.stripe.customers.update(customerId, { email })
276+
}
277+
273278
public async getAdditionalSeatsProration(subscriptionId: string, quantity: number) {
274279
if (!this.stripe) {
275280
throw new Error('Stripe is not initialized')

packages/server/src/enterprise/controllers/account.controller.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,16 @@ export class AccountController {
5757
}
5858
}
5959

60+
public async confirmEmailChange(req: Request, res: Response, next: NextFunction) {
61+
try {
62+
const accountService = new AccountService()
63+
const data = await accountService.confirmEmailChange(req.body)
64+
return res.status(StatusCodes.OK).json(data)
65+
} catch (error) {
66+
next(error)
67+
}
68+
}
69+
6070
public async forgotPassword(req: Request, res: Response, next: NextFunction) {
6171
try {
6272
const accountService = new AccountService()

packages/server/src/enterprise/controllers/user.controller.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { InternalFlowiseError } from '../../errors/internalFlowiseError'
44
import { GeneralErrorMessage } from '../../utils/constants'
55
import { getRunningExpressApp } from '../../utils/getRunningExpressApp'
66
import { User } from '../database/entities/user.entity'
7+
import { AccountService } from '../services/account.service'
78
import { UserErrorMessage, UserService } from '../services/user.service'
89

910
export class UserController {
@@ -51,7 +52,6 @@ export class UserController {
5152

5253
public async update(req: Request, res: Response, next: NextFunction) {
5354
try {
54-
const userService = new UserService()
5555
const currentUser = req.user
5656
if (!currentUser) {
5757
throw new InternalFlowiseError(StatusCodes.UNAUTHORIZED, UserErrorMessage.USER_NOT_FOUND)
@@ -60,8 +60,11 @@ export class UserController {
6060
if (currentUser.id !== id) {
6161
throw new InternalFlowiseError(StatusCodes.FORBIDDEN, UserErrorMessage.USER_NOT_FOUND)
6262
}
63-
const user = await userService.updateUser({ id, name, updatedBy: currentUser.id, oldPassword, newPassword, confirmPassword })
64-
return res.status(StatusCodes.OK).json(user)
63+
const accountService = new AccountService()
64+
const result = await accountService.updateAuthenticatedUserProfile(currentUser.id, req.body, (userId, newEmail) =>
65+
accountService.syncStripeCustomerEmailAfterUserEmailChange(userId, newEmail)
66+
)
67+
return res.status(StatusCodes.OK).json(result)
6568
} catch (error) {
6669
next(error)
6770
}

packages/server/src/enterprise/emails/confirm_email_change.hbs

Lines changed: 877 additions & 0 deletions
Large diffs are not rendered by default.

packages/server/src/enterprise/emails/confirm_email_change.html

Lines changed: 1282 additions & 0 deletions
Large diffs are not rendered by default.

packages/server/src/enterprise/routes/account.route.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ router.post('/logout', accountController.logout)
2222

2323
router.post('/verify', accountController.verify)
2424

25+
router.post('/confirm-email-change', accountController.confirmEmailChange)
26+
2527
router.post('/resend-verification', accountController.resendVerificationEmail)
2628

2729
router.post('/forgot-password', accountController.forgotPassword)

0 commit comments

Comments
 (0)