Phase 3.4: customers.display_name nullable + identity-only social scope
Drop NOT NULL on customers.display_name so phone-OTP and social signups can land before the user picks a name; frontend then routes them to /auth/set-name. Google sign-in no longer requests the name claim and Apple SDK scope is trimmed to email only. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -352,6 +352,10 @@ const migrate = async () => {
|
|||||||
await sql`CREATE UNIQUE INDEX IF NOT EXISTS idx_customers_google_sub ON customers (google_sub) WHERE google_sub IS NOT NULL`
|
await sql`CREATE UNIQUE INDEX IF NOT EXISTS idx_customers_google_sub ON customers (google_sub) WHERE google_sub IS NOT NULL`
|
||||||
await sql`CREATE UNIQUE INDEX IF NOT EXISTS idx_customers_apple_sub ON customers (apple_sub) WHERE apple_sub IS NOT NULL`
|
await sql`CREATE UNIQUE INDEX IF NOT EXISTS idx_customers_apple_sub ON customers (apple_sub) WHERE apple_sub IS NOT NULL`
|
||||||
|
|
||||||
|
// display_name is set after sign-in via the set-display-name screen for
|
||||||
|
// direct phone/Google/Apple sign-ups (no anonymous bootstrap). Allow null.
|
||||||
|
await sql`ALTER TABLE customers ALTER COLUMN display_name DROP NOT NULL`
|
||||||
|
|
||||||
// Control center users: password-based auth columns
|
// Control center users: password-based auth columns
|
||||||
// firebase_uid stays for backward compat during migration; will be dropped in a later cleanup migration
|
// firebase_uid stays for backward compat during migration; will be dropped in a later cleanup migration
|
||||||
await sql`ALTER TABLE control_center_users ALTER COLUMN firebase_uid DROP NOT NULL`
|
await sql`ALTER TABLE control_center_users ALTER COLUMN firebase_uid DROP NOT NULL`
|
||||||
|
|||||||
@@ -112,16 +112,18 @@ export const signInWithGoogle = async ({ idToken, anonymousCustomerId, deviceInf
|
|||||||
if (existing) {
|
if (existing) {
|
||||||
customer = existing
|
customer = existing
|
||||||
} else if (anonymousCustomerId) {
|
} else if (anonymousCustomerId) {
|
||||||
|
// Preserve the anonymous display_name; we don't pull name from Google.
|
||||||
customer = await upgradeCustomerIdentity(anonymousCustomerId, {
|
customer = await upgradeCustomerIdentity(anonymousCustomerId, {
|
||||||
google_sub: google.sub,
|
google_sub: google.sub,
|
||||||
email: google.email,
|
email: google.email,
|
||||||
display_name: google.name,
|
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
// No anonymous bootstrap → display_name is null; frontend routes to
|
||||||
|
// the set-display-name screen.
|
||||||
customer = await createCustomerWithIdentity({
|
customer = await createCustomerWithIdentity({
|
||||||
google_sub: google.sub,
|
google_sub: google.sub,
|
||||||
email: google.email,
|
email: google.email,
|
||||||
display_name: google.name,
|
display_name: null,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ const googleClient = new OAuth2Client()
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Verify a Google ID token against Google's JWKS.
|
* Verify a Google ID token against Google's JWKS.
|
||||||
* Throws on invalid; returns { sub, email, email_verified, name } on success.
|
* Throws on invalid; returns { sub, email, email_verified } on success.
|
||||||
|
* Intentionally omits the user's name — call sign is set in-app.
|
||||||
*/
|
*/
|
||||||
export const verifyGoogleIdToken = async (idToken) => {
|
export const verifyGoogleIdToken = async (idToken) => {
|
||||||
const audience = getGoogleClientIds()
|
const audience = getGoogleClientIds()
|
||||||
@@ -30,7 +31,6 @@ export const verifyGoogleIdToken = async (idToken) => {
|
|||||||
sub: payload.sub,
|
sub: payload.sub,
|
||||||
email: payload.email,
|
email: payload.email,
|
||||||
email_verified: payload.email_verified === true,
|
email_verified: payload.email_verified === true,
|
||||||
name: payload.name,
|
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw Object.assign(new Error(err.message || 'Invalid Google token'), {
|
throw Object.assign(new Error(err.message || 'Invalid Google token'), {
|
||||||
|
|||||||
Reference in New Issue
Block a user