feat: client, instructor, tenant join relationship

This commit is contained in:
Yehoshua Sandler 2025-05-19 15:34:55 -05:00
parent 5d03b2c414
commit 553ca30d12
6 changed files with 91 additions and 18 deletions

View File

@ -0,0 +1,31 @@
import { CollectionConfig } from "payload";
export const InstructorClientTenantRelations: CollectionConfig = {
slug: 'instructorClientTenantRelations',
fields: [
{
name: 'displayName',
type: 'text',
},
{
name: 'instructor',
type: 'relationship',
relationTo: 'users',
hasMany: false,
},
{
name: 'client',
type: 'relationship',
relationTo: 'users',
hasMany: false,
},
{
name: 'tenant',
type: 'relationship',
relationTo: 'tenants',
hasMany: false,
}
]
}
export default InstructorClientTenantRelations

View File

@ -17,6 +17,8 @@ export const readAccess: Access<User> = ({ req, id }) => {
}
const superAdmin = isSuperAdmin(req.user)
if (superAdmin) return true;
const selectedTenant = getTenantFromCookie(
req.headers,
getCollectionIDType({ payload: req.payload, collectionSlug: 'tenants' }),
@ -35,10 +37,6 @@ export const readAccess: Access<User> = ({ req, id }) => {
}
}
if (superAdmin) {
return true
}
return {
or: [
{

View File

@ -28,7 +28,7 @@ const defaultTenantArrayField = tenantsArrayField({
{
name: 'roles',
type: 'select',
defaultValue: ['tenant-viewer'],
defaultValue: ['tenant-client'],
hasMany: true,
options: ['tenant-admin', 'tenant-client', 'tenant-instructor'],
required: true,
@ -76,12 +76,6 @@ export const Users: CollectionConfig = {
},
index: true,
},
{
name: 'accessLevel',
type: 'number',
max: UserAccessLevel.FULL_ACCESS,
defaultValue: UserAccessLevel.GUEST,
},
{
...defaultTenantArrayField,
admin: {
@ -89,6 +83,18 @@ export const Users: CollectionConfig = {
position: 'sidebar',
},
},
{
name: 'clients',
type: 'join',
collection: 'instructorClientTenantRelations',
on: 'instructor',
admin: {
condition: (data) => {
const tenantRoles = data.tenants?.flatMap((t: any) => t.roles)
return tenantRoles.includes('tenant-instructor')
}
},
}
],
timestamps: true,
hooks: {

View File

@ -86,6 +86,7 @@ export interface Config {
habbits: Habbit;
habbitEntries: HabbitEntry;
schedules: Schedule;
instructorClientTenantRelations: InstructorClientTenantRelation;
redirects: Redirect;
forms: Form;
'form-submissions': FormSubmission;
@ -95,7 +96,11 @@ export interface Config {
'payload-preferences': PayloadPreference;
'payload-migrations': PayloadMigration;
};
collectionsJoins: {};
collectionsJoins: {
users: {
clients: 'instructorClientTenantRelations';
};
};
collectionsSelect: {
pages: PagesSelect<false> | PagesSelect<true>;
posts: PostsSelect<false> | PostsSelect<true>;
@ -116,6 +121,7 @@ export interface Config {
habbits: HabbitsSelect<false> | HabbitsSelect<true>;
habbitEntries: HabbitEntriesSelect<false> | HabbitEntriesSelect<true>;
schedules: SchedulesSelect<false> | SchedulesSelect<true>;
instructorClientTenantRelations: InstructorClientTenantRelationsSelect<false> | InstructorClientTenantRelationsSelect<true>;
redirects: RedirectsSelect<false> | RedirectsSelect<true>;
forms: FormsSelect<false> | FormsSelect<true>;
'form-submissions': FormSubmissionsSelect<false> | FormSubmissionsSelect<true>;
@ -426,7 +432,6 @@ export interface User {
id: number;
roles?: ('full-access' | 'super-admin' | 'user' | 'guest')[] | null;
username?: string | null;
accessLevel?: number | null;
tenants?:
| {
tenant: number | Tenant;
@ -434,6 +439,11 @@ export interface User {
id?: string | null;
}[]
| null;
clients?: {
docs?: (number | InstructorClientTenantRelation)[];
hasNextPage?: boolean;
totalDocs?: number;
};
updatedAt: string;
createdAt: string;
email: string;
@ -445,6 +455,19 @@ export interface User {
lockUntil?: string | null;
password?: string | null;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "instructorClientTenantRelations".
*/
export interface InstructorClientTenantRelation {
id: number;
displayName?: string | null;
instructor?: (number | null) | User;
client?: (number | null) | User;
tenant?: (number | null) | Tenant;
updatedAt: string;
createdAt: string;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "CallToActionBlock".
@ -1434,6 +1457,10 @@ export interface PayloadLockedDocument {
relationTo: 'schedules';
value: number | Schedule;
} | null)
| ({
relationTo: 'instructorClientTenantRelations';
value: number | InstructorClientTenantRelation;
} | null)
| ({
relationTo: 'redirects';
value: number | Redirect;
@ -1783,7 +1810,6 @@ export interface CategoriesSelect<T extends boolean = true> {
export interface UsersSelect<T extends boolean = true> {
roles?: T;
username?: T;
accessLevel?: T;
tenants?:
| T
| {
@ -1791,6 +1817,7 @@ export interface UsersSelect<T extends boolean = true> {
roles?: T;
id?: T;
};
clients?: T;
updatedAt?: T;
createdAt?: T;
email?: T;
@ -2030,6 +2057,18 @@ export interface SchedulesSelect<T extends boolean = true> {
updatedAt?: T;
createdAt?: T;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "instructorClientTenantRelations_select".
*/
export interface InstructorClientTenantRelationsSelect<T extends boolean = true> {
displayName?: T;
instructor?: T;
client?: T;
tenant?: T;
updatedAt?: T;
createdAt?: T;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "redirects_select".

View File

@ -24,6 +24,7 @@ import { HabbitCategories } from './collections/Habbits/HabbitCategories'
import { Habbits } from './collections/Habbits/Habbits'
import { HabbitEntries } from './collections/Habbits/HabbitEntry'
import { Schedules } from './collections/Schedules'
import InstructorClientTenantRelations from './collections/InstructorClientTenantRelations'
const filename = fileURLToPath(import.meta.url)
const dirname = path.dirname(filename)
@ -72,7 +73,7 @@ export default buildConfig({
connectionString: process.env.DATABASE_URI || '',
},
}),
collections: [Pages, Posts, Media, Categories, Users, Tenants, Exercises, ExerciseTypes, MuscleGroups, Equipments, Workouts, WorkoutTypes, Ingredients, MealItems, Meals, HabbitCategories, Habbits, HabbitEntries, Schedules],
collections: [Pages, Posts, Media, Categories, Users, Tenants, Exercises, ExerciseTypes, MuscleGroups, Equipments, Workouts, WorkoutTypes, Ingredients, MealItems, Meals, HabbitCategories, Habbits, HabbitEntries, Schedules, InstructorClientTenantRelations],
cors: [getServerSideURL()].filter(Boolean),
globals: [Header, Footer],
plugins: [

View File

@ -14,7 +14,6 @@ import { beforeSyncWithSearch } from '@/search/beforeSync'
import { Config, Page, Post, User } from '@/payload-types'
import { getServerSideURL } from '@/utilities/getURL'
import { UserAccessLevel } from '@/collections/Users'
import { isSuperAdmin } from '@/access/isSuperAdmin'
import { getUserTenantIDs } from '@/utilities/getUserTenantIds'
@ -117,7 +116,7 @@ export const plugins: Plugin[] = [
tenantsArrayField: {
includeDefaultField: false,
},
userHasAccessToAllTenants: (user: User) => (user.accessLevel || 0) >= UserAccessLevel.SUPER_ADMIN,
userHasAccessToAllTenants: (user: User) => isSuperAdmin(user),
tenantField: {
access: {
read: () => true,
@ -127,7 +126,6 @@ export const plugins: Plugin[] = [
}
return getUserTenantIDs(req.user).length > 0
},
create: () => true,
},
},
}),