- Add trusted role and isTrusted access helper - Add notification muting and display preferences to the user schema - Auto-create a profile and personal bank account when a user signs up - Add idempotent backfillProfiles seed script for existing members
106 lines
No EOL
2.9 KiB
TypeScript
106 lines
No EOL
2.9 KiB
TypeScript
import { getPayload } from "payload";
|
|
import config from "@payload-config";
|
|
|
|
// Usage: `bun run src/tools/seed/backfillProfiles.ts`.
|
|
// Creates a profile for every user that doesn't have one yet. Idempotent.
|
|
export const backfillProfiles = async () => {
|
|
const payload = await getPayload({ config });
|
|
|
|
payload.logger.info("Backfilling missing profiles...");
|
|
|
|
// Resolve the Recruit rank the same way the Users.ts afterChange hook does.
|
|
const ranks = await payload.find({
|
|
collection: "ranks",
|
|
where: {
|
|
name: {
|
|
like: "Recruit",
|
|
},
|
|
},
|
|
limit: 1,
|
|
depth: 0,
|
|
overrideAccess: true,
|
|
});
|
|
const recruitRankId = (ranks as { docs: Array<{ id: number }> }).docs[0]?.id ?? null;
|
|
payload.logger.info(
|
|
`Resolved Recruit rank: ${recruitRankId === null ? "none found (will use null)" : `id=${recruitRankId}`}`,
|
|
);
|
|
|
|
// Enumerate all users.
|
|
const usersResult = await payload.find({
|
|
collection: "users",
|
|
limit: 500,
|
|
depth: 0,
|
|
overrideAccess: true,
|
|
});
|
|
const users = usersResult.docs as Array<{ id: number; username: string }>;
|
|
payload.logger.info(`Found ${users.length} users.`);
|
|
|
|
// Count existing profiles before we start.
|
|
const profilesBefore = await payload.find({
|
|
collection: "profiles",
|
|
limit: 1,
|
|
depth: 0,
|
|
overrideAccess: true,
|
|
});
|
|
const profilesBeforeCount = profilesBefore.totalDocs;
|
|
payload.logger.info(`Profiles before: ${profilesBeforeCount}`);
|
|
|
|
let created = 0;
|
|
for (const user of users) {
|
|
// Check if this user already has a profile.
|
|
const existing = await payload.find({
|
|
collection: "profiles",
|
|
where: {
|
|
user: {
|
|
equals: user.id,
|
|
},
|
|
},
|
|
limit: 1,
|
|
depth: 0,
|
|
overrideAccess: true,
|
|
});
|
|
|
|
if (existing.totalDocs > 0) {
|
|
continue;
|
|
}
|
|
|
|
try {
|
|
await payload.create({
|
|
collection: "profiles",
|
|
data: {
|
|
user: user.id,
|
|
rank: recruitRankId,
|
|
progression: {
|
|
qualifications: [],
|
|
experience: 0,
|
|
awards: [],
|
|
} as any,
|
|
},
|
|
overrideAccess: true,
|
|
});
|
|
created++;
|
|
payload.logger.info(`Created profile for user id=${user.id} username="${user.username}"`);
|
|
} catch (e) {
|
|
payload.logger.error(
|
|
`Failed to create profile for user id=${user.id} username="${user.username}": ${e}`,
|
|
);
|
|
}
|
|
}
|
|
|
|
// Count profiles after.
|
|
const profilesAfter = await payload.find({
|
|
collection: "profiles",
|
|
limit: 1,
|
|
depth: 0,
|
|
overrideAccess: true,
|
|
});
|
|
const profilesAfterCount = profilesAfter.totalDocs;
|
|
|
|
payload.logger.info("--- backfill summary ---");
|
|
payload.logger.info(`Users: ${users.length}`);
|
|
payload.logger.info(`Profiles before: ${profilesBeforeCount}`);
|
|
payload.logger.info(`Profiles created: ${created}`);
|
|
payload.logger.info(`Profiles after: ${profilesAfterCount}`);
|
|
};
|
|
|
|
await backfillProfiles(); |