238 lines
5.8 KiB
TypeScript
238 lines
5.8 KiB
TypeScript
import type { CollectionConfig } from "payload";
|
|
import { isAdmin, isDeveloper } from "@/utils/access-control/isRole";
|
|
import { ensurePersonalAccount } from "@/lib/banking/index";
|
|
import { MUTEABLE_NOTIFICATION_TYPES } from "@/lib/notifications/notificationTypes";
|
|
|
|
export const Users: CollectionConfig = {
|
|
hooks: {
|
|
afterChange: [
|
|
async ({ req, doc, operation }) => {
|
|
if (operation !== "create") return doc;
|
|
|
|
const payload = req.payload;
|
|
const userId = doc.id as number;
|
|
|
|
try {
|
|
await ensurePersonalAccount(payload, userId);
|
|
} catch (e) {
|
|
payload.logger.error(
|
|
`[Users] Failed to create personal bank account for user ${userId}: ${e}`,
|
|
);
|
|
}
|
|
|
|
const ranks = await payload.find({
|
|
collection: "ranks",
|
|
where: {
|
|
name: {
|
|
like: "Recruit",
|
|
},
|
|
},
|
|
limit: 1,
|
|
depth: 0,
|
|
overrideAccess: true,
|
|
});
|
|
const recruit = (ranks as { docs: Array<{ id: number }> }).docs[0];
|
|
|
|
try {
|
|
await payload.create({
|
|
collection: "profiles",
|
|
data: {
|
|
user: userId,
|
|
rank: recruit?.id ?? null,
|
|
progression: {
|
|
qualifications: [],
|
|
experience: 0,
|
|
awards: [],
|
|
} as any,
|
|
},
|
|
overrideAccess: true,
|
|
});
|
|
} catch (e) {
|
|
payload.logger.error(`[Users] Failed to create profile for user ${userId}: ${e}`);
|
|
}
|
|
|
|
return doc;
|
|
},
|
|
],
|
|
},
|
|
slug: "users",
|
|
access: {
|
|
admin: isAdmin,
|
|
unlock: isDeveloper,
|
|
create: isDeveloper,
|
|
update: ({ req, data }) => {
|
|
const isEditingDeveloper = data?.roles?.includes("developer");
|
|
if (isEditingDeveloper) {
|
|
return isDeveloper({ req });
|
|
}
|
|
return isAdmin({ req });
|
|
},
|
|
delete: ({ req, data }) => {
|
|
const isEditingDeveloper = data?.roles?.includes("developer");
|
|
if (isEditingDeveloper) {
|
|
return isDeveloper({ req });
|
|
}
|
|
return isAdmin({ req });
|
|
},
|
|
},
|
|
admin: {
|
|
useAsTitle: "payloadDisplayName",
|
|
group: "Users",
|
|
},
|
|
auth: {
|
|
loginWithUsername: {
|
|
requireUsername: true,
|
|
allowEmailLogin: false,
|
|
requireEmail: false,
|
|
},
|
|
},
|
|
fields: [
|
|
// Email added by default by Payload, but essentially ignored in this application
|
|
{
|
|
name: "username",
|
|
type: "text",
|
|
required: true,
|
|
unique: true,
|
|
},
|
|
{
|
|
name: "discordUsername",
|
|
type: "text",
|
|
required: true,
|
|
unique: true,
|
|
},
|
|
{
|
|
name: "discordId",
|
|
type: "text",
|
|
label: "Discord User ID",
|
|
unique: true,
|
|
index: true,
|
|
},
|
|
{
|
|
name: "displayName",
|
|
type: "text",
|
|
label: "In-Game Name",
|
|
required: true,
|
|
},
|
|
{
|
|
name: "payloadDisplayName",
|
|
type: "text",
|
|
label: "Display Name",
|
|
admin: {
|
|
hidden: true,
|
|
readOnly: true,
|
|
},
|
|
hooks: {
|
|
beforeChange: [
|
|
({ data }) => {
|
|
// console.log(data);
|
|
return `${data!.displayName ? data!.displayName + " " : ""}(${data!.username})`;
|
|
},
|
|
],
|
|
},
|
|
},
|
|
{
|
|
name: "steamId",
|
|
type: "text",
|
|
label: "Steam ID 64",
|
|
required: true,
|
|
},
|
|
{
|
|
name: "roles",
|
|
type: "select",
|
|
access: {
|
|
create: isDeveloper,
|
|
update: isDeveloper,
|
|
},
|
|
hasMany: true,
|
|
options: [
|
|
{
|
|
label: "Guest",
|
|
value: "guest",
|
|
},
|
|
{
|
|
label: "User",
|
|
value: "user",
|
|
},
|
|
{
|
|
label: "Trusted",
|
|
value: "trusted",
|
|
},
|
|
{
|
|
label: "Admin",
|
|
value: "admin",
|
|
},
|
|
{
|
|
label: "Developer",
|
|
value: "developer",
|
|
},
|
|
],
|
|
/*filterOptions: ({ options, data, req }) => {
|
|
return !isDeveloper({ req })
|
|
? options.filter(
|
|
(option) => (typeof option === "string" ? options : !["developer", "admin"].includes(option.value)),
|
|
)
|
|
: options;
|
|
},*/
|
|
},
|
|
{
|
|
name: "preferences",
|
|
label: "Preferences",
|
|
type: "group",
|
|
fields: [
|
|
{
|
|
name: "notifications",
|
|
label: "Notifications",
|
|
type: "group",
|
|
fields: [
|
|
{
|
|
name: "mutedAll",
|
|
label: "Mute all in-app notifications",
|
|
type: "checkbox",
|
|
defaultValue: false,
|
|
},
|
|
{
|
|
name: "mutedTypes",
|
|
label: "Muted notification types",
|
|
type: "select",
|
|
hasMany: true,
|
|
options: MUTEABLE_NOTIFICATION_TYPES.map((t) => ({ label: t.label, value: t.value })),
|
|
},
|
|
],
|
|
},
|
|
{
|
|
name: "display",
|
|
label: "Display",
|
|
type: "group",
|
|
fields: [
|
|
{
|
|
name: "showCallsign",
|
|
label: "Show callsign (username) instead of display name in the sidebar",
|
|
type: "checkbox",
|
|
defaultValue: false,
|
|
},
|
|
],
|
|
},
|
|
{
|
|
name: "discord",
|
|
label: "Discord",
|
|
type: "group",
|
|
fields: [
|
|
{
|
|
name: "enabled",
|
|
label: "Discord notifications",
|
|
type: "checkbox",
|
|
defaultValue: false,
|
|
},
|
|
{
|
|
name: "mutedTypes",
|
|
label: "Muted notification types",
|
|
type: "select",
|
|
hasMany: true,
|
|
options: MUTEABLE_NOTIFICATION_TYPES.map((t) => ({ label: t.label, value: t.value })),
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
],
|
|
};
|