- Sign-up emails a confirmation link (24h); unconfirmed accounts see a banner on the web with "send it again", and status in Settings. - Change email (needs the password): the new address gets a confirmation link and only replaces the old one once clicked; the old address gets a heads-up with a reset-password link. Pending changes can be cancelled. - Change password (needs the current one): signs out other sessions. - Password fields have Show/Hide on web and mobile. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MzFywujuH9TiuXbr9vjoX8
This commit is contained in:
@@ -22,6 +22,10 @@ export const users = pgTable('users', {
|
||||
username: varchar('username', { length: 32 }).notNull().unique(),
|
||||
email: varchar('email', { length: 320 }).notNull().unique(),
|
||||
passwordHash: text('password_hash').notNull(),
|
||||
/** Set once they click the link we email them; null until then. */
|
||||
emailVerifiedAt: timestamp('email_verified_at', { withTimezone: true }),
|
||||
/** A new address waiting for its confirmation link; `email` changes only once it's clicked. */
|
||||
pendingEmail: varchar('pending_email', { length: 320 }),
|
||||
displayName: varchar('display_name', { length: 64 }),
|
||||
bio: varchar('bio', { length: 280 }),
|
||||
/** Path of the uploaded picture (`/avatars/<id>?v=<version>`), resolved against API_PUBLIC_URL when sent. */
|
||||
@@ -238,6 +242,21 @@ export const featuredSongs = pgTable('featured_songs', {
|
||||
.default(sql`now()`),
|
||||
});
|
||||
|
||||
/** Email confirmation links (sign-up and email changes). Only a hash of the token is stored. */
|
||||
export const emailVerifications = pgTable(
|
||||
'email_verifications',
|
||||
{
|
||||
id: text('id').primaryKey(),
|
||||
userId: uuid('user_id')
|
||||
.notNull()
|
||||
.references(() => users.id, { onDelete: 'cascade' }),
|
||||
email: varchar('email', { length: 320 }).notNull(),
|
||||
expiresAt: timestamp('expires_at', { withTimezone: true }).notNull(),
|
||||
createdAt: createdAt(),
|
||||
},
|
||||
(t) => [index('email_verifications_user_idx').on(t.userId)],
|
||||
);
|
||||
|
||||
/** One-time password reset links. Only a hash of the token is stored. */
|
||||
export const passwordResets = pgTable(
|
||||
'password_resets',
|
||||
|
||||
Reference in New Issue
Block a user