Files
Krow-workspace/backend/unified-api/scripts/ensure-v2-demo-users.mjs

124 lines
3.5 KiB
JavaScript

import { signInWithPassword, signUpWithPassword } from '../src/services/identity-toolkit.js';
import { applicationDefault, getApps, initializeApp } from 'firebase-admin/app';
import { getAuth } from 'firebase-admin/auth';
const ownerEmail = process.env.V2_DEMO_OWNER_EMAIL || 'legendary.owner+v2@krowd.com';
const staffEmail = process.env.V2_DEMO_STAFF_EMAIL || 'ana.barista+v2@krowd.com';
const staffPhone = process.env.V2_DEMO_STAFF_PHONE || '+15557654321';
const ownerPassword = process.env.V2_DEMO_OWNER_PASSWORD || 'Demo2026!';
const staffPassword = process.env.V2_DEMO_STAFF_PASSWORD || 'Demo2026!';
function ensureAdminApp() {
if (getApps().length === 0) {
initializeApp({ credential: applicationDefault() });
}
}
function getAdminAuth() {
ensureAdminApp();
return getAuth();
}
async function ensureUser({ email, password, displayName }) {
try {
const signedIn = await signInWithPassword({ email, password });
return {
uid: signedIn.localId,
email,
password,
created: false,
displayName,
};
} catch (error) {
const message = error?.message || '';
if (!message.includes('INVALID_LOGIN_CREDENTIALS') && !message.includes('EMAIL_NOT_FOUND')) {
throw error;
}
}
try {
const signedUp = await signUpWithPassword({ email, password });
return {
uid: signedUp.localId,
email,
password,
created: true,
displayName,
};
} catch (error) {
const message = error?.message || '';
if (message.includes('EMAIL_EXISTS')) {
throw new Error(`Firebase user ${email} exists but password does not match expected demo password.`);
}
throw error;
}
}
async function getUserByPhoneNumber(phoneNumber) {
try {
return await getAdminAuth().getUserByPhoneNumber(phoneNumber);
} catch (error) {
if (error?.code === 'auth/user-not-found') return null;
throw error;
}
}
async function reconcileStaffPhoneIdentity({ uid, email, displayName, phoneNumber }) {
const auth = getAdminAuth();
const current = await auth.getUser(uid);
const existingPhoneUser = await getUserByPhoneNumber(phoneNumber);
let deletedConflictingUid = null;
if (existingPhoneUser && existingPhoneUser.uid !== uid) {
deletedConflictingUid = existingPhoneUser.uid;
await auth.deleteUser(existingPhoneUser.uid);
}
const updatePayload = {};
if (current.displayName !== displayName) updatePayload.displayName = displayName;
if (current.email !== email) updatePayload.email = email;
if (current.phoneNumber !== phoneNumber) updatePayload.phoneNumber = phoneNumber;
if (Object.keys(updatePayload).length > 0) {
await auth.updateUser(uid, updatePayload);
}
const reconciled = await auth.getUser(uid);
return {
uid: reconciled.uid,
email: reconciled.email,
phoneNumber: reconciled.phoneNumber,
deletedConflictingUid,
};
}
async function main() {
const owner = await ensureUser({
email: ownerEmail,
password: ownerPassword,
displayName: 'Legendary Demo Owner V2',
});
const staff = await ensureUser({
email: staffEmail,
password: staffPassword,
displayName: 'Ana Barista V2',
});
const reconciledStaff = await reconcileStaffPhoneIdentity({
uid: staff.uid,
email: staff.email,
displayName: staff.displayName,
phoneNumber: staffPhone,
});
// eslint-disable-next-line no-console
console.log(JSON.stringify({ owner, staff: { ...staff, ...reconciledStaff } }, null, 2));
}
main().catch((error) => {
// eslint-disable-next-line no-console
console.error(error);
process.exit(1);
});