Repository navigation
feat(deleter): email the user after their account is deleted - #2034
Conversation
parseMailTemplate picks the configured or built-in subject and body and parses them. sendMail fills them in and sends one mail. The org delete email uses both and sends the same message as before.
DeleteUser reads the user first, disabled or not, and refuses an id that is not a UUID. A failed read stops the delete, and a user with no row still runs the cleanup before the row delete returns not found. Once the row is deleted, it sends the email from app.deletion.user_delete_notice, with plain built-in text when it is empty. The delete handler returns INVALID_ARGUMENT for an id that is not a UUID.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Summary
Merge Risk:
|
Coverage Report for CI Build 41415687973Coverage increased (+0.06%) to 56.053%Details
Uncovered Changes
Coverage Regressions1 previously-covered line in 1 file lost coverage.
Coverage Stats
💛 - Coveralls |
There was a problem hiding this comment.
Actionable comments posted: 1

Review info
-
Run configuration-
- Source mode: Auto
- Repository: raystack/frontier
- Branch: feat/user-delete-email
- File: .coderabbit.yaml
- Commit: b6c8898
- Layers: Repository YAML
- Review profile: CHILL
- Plan: Advanced
- Run ID:
d323db92-5413-4a71-b65b-67518f58cfec
Files selected for processing: 11-
config/config_test.goconfig/sample.config.yamlconfig/testdata/deletion.yamlcore/deleter/config.gocore/deleter/delete_notice.gocore/deleter/delete_notice_test.gocore/deleter/service.gocore/deleter/service_test.godocs/content/docs/reference/configurations.mdxinternal/api/v1beta1connect/user.gointernal/api/v1beta1connect/user_test.go
Included review availability: This review used your included allowance. Your plan provides up to 2 included reviews per hour; 1 remain after this review.
-
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to GitHub limitations.

Minor · Pass a disabled mailer to the deleter. · delete_notice.go:238-253
core/deleter/delete_notice.go:238-253
Minor · Functional Correctness · Quick win Pass a disabled mailer to the deleter.
DeleteUseris reachable through the authenticatedDeleteUserendpoint. Withoutapp.mailer.smtp_host, the server passes a non-nil mock dialer to the deleter. The mock returnsnilfromDialAndSendwithout delivery, sosendUserDeleteNoticelogssent the user delete notice. This violates the documented contract that the notice is sent only when SMTP is configured.Suggested fix
var mailDialer mailer.Dialer = mailer.NewMockDialer() +var deletionMailDialer mailer.Dialer if cfg.App.Mailer.SMTPHost != "" && cfg.App.Mailer.SMTPHost != "smtp.example.com" { mailDialer = mailer.NewDialerImpl(cfg.App.Mailer.SMTPHost, cfg.App.Mailer.SMTPPort, cfg.App.Mailer.SMTPUsername, cfg.App.Mailer.SMTPPassword, cfg.App.Mailer.SMTPInsecure, cfg.App.Mailer.Headers, cfg.App.Mailer.TLSPolicy(), ) + deletionMailDialer = mailDialer logger.Info("mailer enabled", "host", cfg.App.Mailer.SMTPHost, "port", cfg.App.Mailer.SMTPPort) } // ... - mailDialer, cfg.Billing.OrgDeleteNotice, cfg.App.Deletion, + deletionMailDialer, cfg.Billing.OrgDeleteNotice, cfg.App.Deletion,

Review info
-
Run configuration-
- Source mode: Auto
- Repository: raystack/frontier
- Branch: feat/user-delete-email
- File: .coderabbit.yaml
- Commit: 0b5270d
- Layers: Repository YAML
- Review profile: CHILL
- Plan: Advanced
- Run ID:
6dc77fbc-3b89-4c28-8e8b-5e5776a8ce74
Files selected for processing: 3-
core/deleter/delete_notice_test.gocore/deleter/service_test.godocs/content/docs/reference/configurations.mdx
Included review availability: This review used your included allowance. Your plan provides up to 2 included reviews per hour; 1 remain after this review.
-
Summary
A user delete, by an admin or by the user, now emails the deleted user once the user row is gone. The subject and body come from the new
app.deletion.user_delete_noticeconfig. When it is empty, a plain built-in text is used. The org delete email now uses the same template code and is otherwise unchanged.Changes
core/deleter/service.go:DeleteUserreads the user first, disabled or not. LikegetProject, it refuses an id that is not a UUID. A failed read stops the delete before anything changes. A user with no row still goes through the cleanup, and the row delete returns not found. After the row delete, it sends the email.core/deleter/delete_notice.go:parseMailTemplateandsendMailhold the template and send code that both emails use.sendUserDeleteNoticelogs a failure and never returns one.core/deleter/config.go:user_delete_noticewith asubjectand abody, both Go templates. It is sent whether or notenabledis set.internal/api/v1beta1connect/user.go: a user id that is not a UUID returnsINVALID_ARGUMENTinstead ofINTERNAL.config/sample.config.yaml,docs/content/docs/reference/configurations.mdx: the new key.Technical Details
DeleteUserandDeleteCurrentUserboth send it, because both run the deleter'sDeleteUser. A disabled user gets it too..UserhasID,Name,Email,Title,AvatarandState.NOT_FOUND. Anything it left behind (policies, PATs, relations) is still cleared on the way, as before.billing.org_delete_notice.Test Plan
core/deleter/service_test.goTestDeleteUser: the email goes to the user's address, after the row delete, with the built-in subject and body; a configured template can use the user's fields; a disabled user gets the email; a failed send does not fail the delete; a broken configured template still deletes the user, without an email; a failed read, or an id that is not a UUID, stops the delete before anything changes; a user with no row still has its leftovers cleared and returns not found; no failure case sends an email.core/deleter/delete_notice_test.go:TestParseMailTemplate(fallbacks, configured values, broken templates) andTestSendMail(headers; nothing sent when the subject or the body fails to render).TestDeleteOrganizationpasses unchanged on the shared code.internal/api/v1beta1connect/user_test.goTestConnectHandler_DeleteUser: an id that is not a UUID returnsINVALID_ARGUMENT.config/config_test.goTestLoadDeletion: the new key loads from YAML.go vet ./..., the unit tests of the changed packages with-race, andmake lintpass.