142 lines
3.5 KiB
TypeScript
142 lines
3.5 KiB
TypeScript
import type { CollectionConfig } from 'payload'
|
|
|
|
import { createAccess } from './access/create'
|
|
import { readAccess } from './access/read'
|
|
import { updateAndDeleteAccess } from './access/updateAndDelete'
|
|
import { externalUsersLogin } from './endpoints/externalUsersLogin'
|
|
import { ensureUniqueUsername } from './hooks/ensureUniqueUsername'
|
|
import { isSuperAdmin } from '@/access/isSuperAdmin'
|
|
import { setCookieBasedOnDomain } from './hooks/setCookieBasedOnDomain'
|
|
import { tenantsArrayField } from '@payloadcms/plugin-multi-tenant/fields'
|
|
|
|
/**
|
|
* Tenant Roles for Care Home Staff:
|
|
* - admin: Full access within their care home(s)
|
|
* - caregiver: Can create/manage meal orders for residents
|
|
* - kitchen: Can view orders and mark as prepared
|
|
*/
|
|
const defaultTenantArrayField = tenantsArrayField({
|
|
tenantsArrayFieldName: 'tenants',
|
|
tenantsArrayTenantFieldName: 'tenant',
|
|
tenantsCollectionSlug: 'tenants',
|
|
arrayFieldAccess: {},
|
|
tenantFieldAccess: {},
|
|
rowFields: [
|
|
{
|
|
name: 'roles',
|
|
type: 'select',
|
|
defaultValue: ['caregiver'],
|
|
hasMany: true,
|
|
options: [
|
|
{ label: 'Admin', value: 'admin' },
|
|
{ label: 'Caregiver', value: 'caregiver' },
|
|
{ label: 'Kitchen', value: 'kitchen' },
|
|
],
|
|
required: true,
|
|
admin: {
|
|
description: 'Role(s) for this user within the care home',
|
|
},
|
|
access: {
|
|
update: ({ req }) => {
|
|
const { user } = req
|
|
if (!user) {
|
|
return false
|
|
}
|
|
// Super admins and tenant admins can update roles
|
|
return isSuperAdmin(user) || true
|
|
},
|
|
},
|
|
},
|
|
],
|
|
})
|
|
|
|
/**
|
|
* Users Collection
|
|
*
|
|
* Two-level role system:
|
|
* - Global roles: super-admin (system-wide access), user (access via tenant roles)
|
|
* - Tenant roles: admin, caregiver, kitchen (per care home)
|
|
*/
|
|
const Users: CollectionConfig = {
|
|
slug: 'users',
|
|
access: {
|
|
create: createAccess,
|
|
delete: updateAndDeleteAccess,
|
|
read: readAccess,
|
|
update: updateAndDeleteAccess,
|
|
},
|
|
admin: {
|
|
useAsTitle: 'email',
|
|
defaultColumns: ['email', 'roles', 'createdAt'],
|
|
},
|
|
auth: true,
|
|
endpoints: [externalUsersLogin],
|
|
fields: [
|
|
{
|
|
name: 'name',
|
|
type: 'text',
|
|
admin: {
|
|
description: 'Full name of the user',
|
|
},
|
|
},
|
|
{
|
|
type: 'text',
|
|
name: 'password',
|
|
hidden: true,
|
|
access: {
|
|
read: () => false,
|
|
update: ({ req, id }) => {
|
|
const { user } = req
|
|
if (!user) {
|
|
return false
|
|
}
|
|
if (id === user.id) {
|
|
return true
|
|
}
|
|
return isSuperAdmin(user)
|
|
},
|
|
},
|
|
},
|
|
{
|
|
admin: {
|
|
position: 'sidebar',
|
|
description: 'Global system role',
|
|
},
|
|
name: 'roles',
|
|
type: 'select',
|
|
defaultValue: ['user'],
|
|
hasMany: true,
|
|
options: [
|
|
{ label: 'Super Admin', value: 'super-admin' },
|
|
{ label: 'User', value: 'user' },
|
|
],
|
|
access: {
|
|
update: ({ req }) => {
|
|
return isSuperAdmin(req.user)
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: 'username',
|
|
type: 'text',
|
|
hooks: {
|
|
beforeValidate: [ensureUniqueUsername],
|
|
},
|
|
index: true,
|
|
},
|
|
{
|
|
...defaultTenantArrayField,
|
|
admin: {
|
|
...(defaultTenantArrayField?.admin || {}),
|
|
position: 'sidebar',
|
|
description: 'Care homes this user has access to',
|
|
},
|
|
},
|
|
],
|
|
hooks: {
|
|
afterLogin: [setCookieBasedOnDomain],
|
|
},
|
|
}
|
|
|
|
export default Users
|