diff --git a/packages/core-firebase/src/data/demo-events.ts b/packages/core-firebase/src/data/demo-events.ts index 0f09ee20..35ce7b71 100644 --- a/packages/core-firebase/src/data/demo-events.ts +++ b/packages/core-firebase/src/data/demo-events.ts @@ -23,16 +23,19 @@ export const project: Pick = export const projectUsers: Omit[] = [ { email: "alice.thompson@example.com", + createdAt: Date.now(), fullName: "Alice Thompson", externalId: getRandomExternalId(), }, { email: "bob.anderson@example.com", + createdAt: Date.now(), fullName: "Bob Anderson", externalId: getRandomExternalId(), }, { email: "charlie.simpson@example.com", + createdAt: Date.now(), fullName: "Charlie Simpson", externalId: getRandomExternalId(), }, diff --git a/packages/core-firebase/src/data/demo-gaming.ts b/packages/core-firebase/src/data/demo-gaming.ts index 594cf6a3..d7327f04 100644 --- a/packages/core-firebase/src/data/demo-gaming.ts +++ b/packages/core-firebase/src/data/demo-gaming.ts @@ -24,16 +24,19 @@ export const project: Pick = export const projectUsers: Omit[] = [ { email: "gamer.john.777@example.com", + createdAt: Date.now(), fullName: "John Smith", externalId: getRandomExternalId(), }, { email: "mary.jane@example.com", + createdAt: Date.now(), fullName: "Mary Jane", externalId: getRandomExternalId(), }, { email: "j.potter@example.com", + createdAt: Date.now(), fullName: "Joseph Potter", externalId: getRandomExternalId(), }, diff --git a/packages/core-firebase/src/data/demo-phygital.ts b/packages/core-firebase/src/data/demo-phygital.ts index 1b071700..a842a16e 100644 --- a/packages/core-firebase/src/data/demo-phygital.ts +++ b/packages/core-firebase/src/data/demo-phygital.ts @@ -27,16 +27,19 @@ export const projectUsers: Omit[] = [ { email: "gamer.john.777@example.com", fullName: "John Smith", + createdAt: Date.now(), externalId: getRandomExternalId(), }, { email: "mary.jane@example.com", fullName: "Mary Jane", + createdAt: Date.now(), externalId: getRandomExternalId(), }, { email: "j.potter@example.com", fullName: "Joseph Potter", + createdAt: Date.now(), externalId: getRandomExternalId(), }, ]; diff --git a/packages/core-firebase/src/data/dev-local.ts b/packages/core-firebase/src/data/dev-local.ts index 0a5d5aec..4b513c47 100644 --- a/packages/core-firebase/src/data/dev-local.ts +++ b/packages/core-firebase/src/data/dev-local.ts @@ -317,6 +317,7 @@ export const users: User[] = [ { userId: getUUID(100_000), email: "user100_000@example.com", + createdAt: Date.now(), }, ]; export const teams: Team[] = [ @@ -387,12 +388,14 @@ export const projectUsers: ProjectUser[] = [ { userId: getUUID(100_250), email: "johnsmith@example.com", + createdAt: Date.now(), fullName: "John Smith", externalId: "", }, { userId: getUUID(100_251), email: "maryjane@test.com", + createdAt: Date.now(), fullName: "Mary Jane", externalId: "maryJane123", }, diff --git a/packages/core-firebase/src/models/User.ts b/packages/core-firebase/src/models/User.ts index fd1a812a..58f097b5 100644 --- a/packages/core-firebase/src/models/User.ts +++ b/packages/core-firebase/src/models/User.ts @@ -15,11 +15,13 @@ export const decodeUserId: (id: string) => Required = (id) => { export interface UserData { readonly email: string; + readonly createdAt: number; unverified?: boolean; } export const userDataZod = z .object({ email: z.string().email().describe("email"), + createdAt: z.number().int().describe("created at"), unverified: z.boolean().optional(), }) .describe("user"); diff --git a/packages/core-firebase/src/models/projects/ProjectUser.ts b/packages/core-firebase/src/models/projects/ProjectUser.ts index 42104ca6..5de89605 100644 --- a/packages/core-firebase/src/models/projects/ProjectUser.ts +++ b/packages/core-firebase/src/models/projects/ProjectUser.ts @@ -19,6 +19,7 @@ export const decodeProjectUserId: (id: string) => ProjectUserId = (id) => { export interface ProjectUserData { readonly userId: string; readonly email: string; + readonly createdAt: number; fullName?: string; externalId?: string; } @@ -27,6 +28,7 @@ export const projectUserDataZod = z .object({ userId: z.string(), email: z.string().email(), + createdAt: z.number().int().describe("created at"), fullName: z.string().optional(), externalId: z.string().describe("externalId").optional(), }) diff --git a/packages/core-firebase/src/scripts/authUserUID.ts b/packages/core-firebase/src/scripts/authUserUID.ts index f5201ed8..233dc865 100644 --- a/packages/core-firebase/src/scripts/authUserUID.ts +++ b/packages/core-firebase/src/scripts/authUserUID.ts @@ -17,7 +17,7 @@ export async function migrateAuthUserUID(email: string) { console.log({ authUserId: userId, oldUserId: oldUserDocument.userId }); - const newUserDocument: User = { email, userId }; + const newUserDocument: User = { email, userId, createdAt: Date.now() }; const userUpdates = [userResource.set(newUserDocument), userResource.delete(oldUserDocument)]; diff --git a/packages/core-firebase/src/scripts/updateUsersCreatedAt.ts b/packages/core-firebase/src/scripts/updateUsersCreatedAt.ts new file mode 100644 index 00000000..aa137986 --- /dev/null +++ b/packages/core-firebase/src/scripts/updateUsersCreatedAt.ts @@ -0,0 +1,55 @@ +import { projectUserGroupQuery } from "../admin/groupQueries.js"; +import { projectUserResource, userResource } from "../admin/resources.js"; + +export async function updateUsersCreatedAt() { + try { + // Bypass zod verification + const usersSnapshot = await userResource.getAllSnapshot(); + const users = usersSnapshot.docs.map((d) => ({ + data: d.data(), + createdAt: d.createTime.toMillis(), + userId: d.id, + })); + + const usersNoCreatedAt = users.filter((u) => u.data.createdAt === undefined); + + if (usersNoCreatedAt.length > 0) { + const usersUpdated = usersNoCreatedAt.map((u) => { + return { ...u.data, createdAt: u.createdAt, userId: u.userId }; + }); + + await userResource.setBatch(usersUpdated); + + console.log(`Updated ${usersUpdated.length} users.`); + } + + // Bypass zod verification + const projectUsersSnapshot = await projectUserGroupQuery.getAllSnapshot(); + + const projectUsers = projectUsersSnapshot.docs.map((d) => ({ + data: d.data(), + projectId: d.ref.parent.parent!.id, + createdAt: d.createTime.toMillis(), + })); + + const projectUsersNoCreatedAt = projectUsers.filter((u) => u.data.createdAt === undefined); + + if (projectUsersNoCreatedAt.length > 0) { + const projectUsersUpdated = projectUsersNoCreatedAt.map((u) => { + return { + ...u.data, + createdAt: u.createdAt, + projectId: u.projectId, + }; + }); + + await projectUserResource.setBatch(projectUsersUpdated); + + console.log(`Updated ${projectUsersUpdated.length} project users.`); + } + } catch (error) { + console.error("Update failed:", error); + } +} + +// await updateUsersCreatedAt();