fix(store): preserve user profile on upsert and set default role - #18
fix(store): preserve user profile on upsert and set default role#18GormYa wants to merge 4 commits into
Conversation
Ensure UpsertUser does not overwrite existing name and avatar_url with empty values on conflict (such as during OTP login or Stripe sync). Also default missing user role to 'user' on insert.
Add full Turkish (tr) localization across all frontend pages and wire up i18n support in the releases management interface. - Create web/src/i18n/locales/tr.ts with 623 translation keys. - Update web/src/i18n/index.tsx to register the Turkish locale and support browser language detection for Turkish. - Add Turkish language selection to admin settings and persist it in backend configuration. - Extract all hardcoded strings in the releases page into i18n keys across English, Turkish, and Chinese translation files. - Update README.md to list Turkish under built-in i18n languages.
|
Add Turkish (tr) localization support and i18n for releases page What does this PR do?
Why?
How to test
Checklist
|
alanisme
left a comment
There was a problem hiding this comment.
Thanks, this is a solid PR. The upsert fix is right, and the Turkish translation is complete — key parity is exact and all placeholders line up. Nice catch on wiring language into the settings form too, that was dead until now.
Two things before merge:
-
The
TIMEZONESlist lost 7 entries (Europe/Paris, Asia/Karachi, Asia/Dhaka, America/Caracas, Pacific/Midway, Atlantic/Azores, Atlantic/South_Georgia). Anyone already saved on one of those will see an empty select. Can you add Istanbul without dropping the others? -
bunx biome check --write— tr.ts, zh.ts and releases.tsx fail lint.bun run builddoesn't run it.
Why?
How to test
Checklist
|
I'm on it; I'll push the corrected version shortly. |
- Restore dropped timezone entries and add new regions including Europe/Istanbul - Fix code formatting and linting issues in tr.ts, zh.ts, and releases.tsx
|
Restored all dropped timezone entries in TIMEZONES and added Europe/Istanbul & others. |
alanisme
left a comment
There was a problem hiding this comment.
Timezones and lint look good now, thanks.
Could you move the SMTP commit into its own PR? It's unrelated to #17 and people are waiting on that fix, and the config merge has something I'd rather not rush.
smtp_password is deliberately write-only — admins can save it but never read it back. getConfig overrides the host whenever the DB has one, but only overrides the password when the DB value is non-empty. So an admin who points smtp_host at another server and leaves the password field blank gets the env SMTP_PASSWORD sent to that server. I checked it against a local SMTP server and it authenticates with the env password. The username branch already goes for "DB host means DB owns auth" — the password just needs the same rule.
Smaller things for that PR: getConfig queries the settings table on every IsConfigured() and every Send(), so one queue tick can be 20 extra reads, and it uses context.Background() so there's no timeout. TestEmailService_DynamicConfig passes a nil store, so the DB path isn't actually covered. The 465 support itself looks right.
Two things on this PR:
The language Select now drives both the admin's own UI language and the site-wide default from one control — switching my dashboard to Turkish also changes what new visitors get. And it reads value={locale}, so two admins see different values for the same setting. Could you bind the saved field to form.language and leave setLocale as the personal switcher?
Some of the Turkish uses the "Türkçe (English)" form, 22 keys. Reasonable for jargon, but a few land where there's no room: status.revoked renders inside a Badge, licenses.seats is a tab label, analytics.churned is a table header and a chart legend. zh only does this for releases.unyank. Could you drop the gloss on those?
Ensure UpsertUser does not overwrite existing name and avatar_url with empty values on conflict (such as during OTP login or Stripe sync). Also default missing user role to 'user' on insert.
What does this PR do?
UpsertUserininternal/store/store.goto conditionally updatenameandavatar_urlon conflict (ON CONFLICT (email) DO UPDATE).name,avatar_url) from being wiped out by empty strings ("") when a user signs in via OTP or is upserted via Stripe webhook.model.RoleUserduring insertion.Why?
UpsertUserwith only an email unconditionally replacednameandavatar_urlwith empty values, destroying previously saved profile data (e.g. populated via OAuth or profile updates).How to test
nameandavatar_urlpopulated (e.g., through OAuth login or direct store insert).UpsertUser(ctx, &model.User{Email: email})).nameandavatar_urlremain intact.rolecolumn defaults touser.go test ./...andgo vet ./....Checklist
go vet ./...passesgo test ./...passescd web && bun run build)