feat: client, instructor, tenant join relationship
This commit is contained in:
parent
5d03b2c414
commit
553ca30d12
31
src/collections/InstructorClientTenantRelations/index.ts
Normal file
31
src/collections/InstructorClientTenantRelations/index.ts
Normal 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
|
||||||
@ -17,6 +17,8 @@ export const readAccess: Access<User> = ({ req, id }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const superAdmin = isSuperAdmin(req.user)
|
const superAdmin = isSuperAdmin(req.user)
|
||||||
|
if (superAdmin) return true;
|
||||||
|
|
||||||
const selectedTenant = getTenantFromCookie(
|
const selectedTenant = getTenantFromCookie(
|
||||||
req.headers,
|
req.headers,
|
||||||
getCollectionIDType({ payload: req.payload, collectionSlug: 'tenants' }),
|
getCollectionIDType({ payload: req.payload, collectionSlug: 'tenants' }),
|
||||||
@ -35,10 +37,6 @@ export const readAccess: Access<User> = ({ req, id }) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (superAdmin) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
or: [
|
or: [
|
||||||
{
|
{
|
||||||
|
|||||||
@ -28,7 +28,7 @@ const defaultTenantArrayField = tenantsArrayField({
|
|||||||
{
|
{
|
||||||
name: 'roles',
|
name: 'roles',
|
||||||
type: 'select',
|
type: 'select',
|
||||||
defaultValue: ['tenant-viewer'],
|
defaultValue: ['tenant-client'],
|
||||||
hasMany: true,
|
hasMany: true,
|
||||||
options: ['tenant-admin', 'tenant-client', 'tenant-instructor'],
|
options: ['tenant-admin', 'tenant-client', 'tenant-instructor'],
|
||||||
required: true,
|
required: true,
|
||||||
@ -76,12 +76,6 @@ export const Users: CollectionConfig = {
|
|||||||
},
|
},
|
||||||
index: true,
|
index: true,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: 'accessLevel',
|
|
||||||
type: 'number',
|
|
||||||
max: UserAccessLevel.FULL_ACCESS,
|
|
||||||
defaultValue: UserAccessLevel.GUEST,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
...defaultTenantArrayField,
|
...defaultTenantArrayField,
|
||||||
admin: {
|
admin: {
|
||||||
@ -89,6 +83,18 @@ export const Users: CollectionConfig = {
|
|||||||
position: 'sidebar',
|
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,
|
timestamps: true,
|
||||||
hooks: {
|
hooks: {
|
||||||
|
|||||||
@ -86,6 +86,7 @@ export interface Config {
|
|||||||
habbits: Habbit;
|
habbits: Habbit;
|
||||||
habbitEntries: HabbitEntry;
|
habbitEntries: HabbitEntry;
|
||||||
schedules: Schedule;
|
schedules: Schedule;
|
||||||
|
instructorClientTenantRelations: InstructorClientTenantRelation;
|
||||||
redirects: Redirect;
|
redirects: Redirect;
|
||||||
forms: Form;
|
forms: Form;
|
||||||
'form-submissions': FormSubmission;
|
'form-submissions': FormSubmission;
|
||||||
@ -95,7 +96,11 @@ export interface Config {
|
|||||||
'payload-preferences': PayloadPreference;
|
'payload-preferences': PayloadPreference;
|
||||||
'payload-migrations': PayloadMigration;
|
'payload-migrations': PayloadMigration;
|
||||||
};
|
};
|
||||||
collectionsJoins: {};
|
collectionsJoins: {
|
||||||
|
users: {
|
||||||
|
clients: 'instructorClientTenantRelations';
|
||||||
|
};
|
||||||
|
};
|
||||||
collectionsSelect: {
|
collectionsSelect: {
|
||||||
pages: PagesSelect<false> | PagesSelect<true>;
|
pages: PagesSelect<false> | PagesSelect<true>;
|
||||||
posts: PostsSelect<false> | PostsSelect<true>;
|
posts: PostsSelect<false> | PostsSelect<true>;
|
||||||
@ -116,6 +121,7 @@ export interface Config {
|
|||||||
habbits: HabbitsSelect<false> | HabbitsSelect<true>;
|
habbits: HabbitsSelect<false> | HabbitsSelect<true>;
|
||||||
habbitEntries: HabbitEntriesSelect<false> | HabbitEntriesSelect<true>;
|
habbitEntries: HabbitEntriesSelect<false> | HabbitEntriesSelect<true>;
|
||||||
schedules: SchedulesSelect<false> | SchedulesSelect<true>;
|
schedules: SchedulesSelect<false> | SchedulesSelect<true>;
|
||||||
|
instructorClientTenantRelations: InstructorClientTenantRelationsSelect<false> | InstructorClientTenantRelationsSelect<true>;
|
||||||
redirects: RedirectsSelect<false> | RedirectsSelect<true>;
|
redirects: RedirectsSelect<false> | RedirectsSelect<true>;
|
||||||
forms: FormsSelect<false> | FormsSelect<true>;
|
forms: FormsSelect<false> | FormsSelect<true>;
|
||||||
'form-submissions': FormSubmissionsSelect<false> | FormSubmissionsSelect<true>;
|
'form-submissions': FormSubmissionsSelect<false> | FormSubmissionsSelect<true>;
|
||||||
@ -426,7 +432,6 @@ export interface User {
|
|||||||
id: number;
|
id: number;
|
||||||
roles?: ('full-access' | 'super-admin' | 'user' | 'guest')[] | null;
|
roles?: ('full-access' | 'super-admin' | 'user' | 'guest')[] | null;
|
||||||
username?: string | null;
|
username?: string | null;
|
||||||
accessLevel?: number | null;
|
|
||||||
tenants?:
|
tenants?:
|
||||||
| {
|
| {
|
||||||
tenant: number | Tenant;
|
tenant: number | Tenant;
|
||||||
@ -434,6 +439,11 @@ export interface User {
|
|||||||
id?: string | null;
|
id?: string | null;
|
||||||
}[]
|
}[]
|
||||||
| null;
|
| null;
|
||||||
|
clients?: {
|
||||||
|
docs?: (number | InstructorClientTenantRelation)[];
|
||||||
|
hasNextPage?: boolean;
|
||||||
|
totalDocs?: number;
|
||||||
|
};
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
email: string;
|
email: string;
|
||||||
@ -445,6 +455,19 @@ export interface User {
|
|||||||
lockUntil?: string | null;
|
lockUntil?: string | null;
|
||||||
password?: 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
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "CallToActionBlock".
|
* via the `definition` "CallToActionBlock".
|
||||||
@ -1434,6 +1457,10 @@ export interface PayloadLockedDocument {
|
|||||||
relationTo: 'schedules';
|
relationTo: 'schedules';
|
||||||
value: number | Schedule;
|
value: number | Schedule;
|
||||||
} | null)
|
} | null)
|
||||||
|
| ({
|
||||||
|
relationTo: 'instructorClientTenantRelations';
|
||||||
|
value: number | InstructorClientTenantRelation;
|
||||||
|
} | null)
|
||||||
| ({
|
| ({
|
||||||
relationTo: 'redirects';
|
relationTo: 'redirects';
|
||||||
value: number | Redirect;
|
value: number | Redirect;
|
||||||
@ -1783,7 +1810,6 @@ export interface CategoriesSelect<T extends boolean = true> {
|
|||||||
export interface UsersSelect<T extends boolean = true> {
|
export interface UsersSelect<T extends boolean = true> {
|
||||||
roles?: T;
|
roles?: T;
|
||||||
username?: T;
|
username?: T;
|
||||||
accessLevel?: T;
|
|
||||||
tenants?:
|
tenants?:
|
||||||
| T
|
| T
|
||||||
| {
|
| {
|
||||||
@ -1791,6 +1817,7 @@ export interface UsersSelect<T extends boolean = true> {
|
|||||||
roles?: T;
|
roles?: T;
|
||||||
id?: T;
|
id?: T;
|
||||||
};
|
};
|
||||||
|
clients?: T;
|
||||||
updatedAt?: T;
|
updatedAt?: T;
|
||||||
createdAt?: T;
|
createdAt?: T;
|
||||||
email?: T;
|
email?: T;
|
||||||
@ -2030,6 +2057,18 @@ export interface SchedulesSelect<T extends boolean = true> {
|
|||||||
updatedAt?: T;
|
updatedAt?: T;
|
||||||
createdAt?: 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
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "redirects_select".
|
* via the `definition` "redirects_select".
|
||||||
|
|||||||
@ -24,6 +24,7 @@ import { HabbitCategories } from './collections/Habbits/HabbitCategories'
|
|||||||
import { Habbits } from './collections/Habbits/Habbits'
|
import { Habbits } from './collections/Habbits/Habbits'
|
||||||
import { HabbitEntries } from './collections/Habbits/HabbitEntry'
|
import { HabbitEntries } from './collections/Habbits/HabbitEntry'
|
||||||
import { Schedules } from './collections/Schedules'
|
import { Schedules } from './collections/Schedules'
|
||||||
|
import InstructorClientTenantRelations from './collections/InstructorClientTenantRelations'
|
||||||
|
|
||||||
const filename = fileURLToPath(import.meta.url)
|
const filename = fileURLToPath(import.meta.url)
|
||||||
const dirname = path.dirname(filename)
|
const dirname = path.dirname(filename)
|
||||||
@ -72,7 +73,7 @@ export default buildConfig({
|
|||||||
connectionString: process.env.DATABASE_URI || '',
|
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),
|
cors: [getServerSideURL()].filter(Boolean),
|
||||||
globals: [Header, Footer],
|
globals: [Header, Footer],
|
||||||
plugins: [
|
plugins: [
|
||||||
|
|||||||
@ -14,7 +14,6 @@ import { beforeSyncWithSearch } from '@/search/beforeSync'
|
|||||||
|
|
||||||
import { Config, Page, Post, User } from '@/payload-types'
|
import { Config, Page, Post, User } from '@/payload-types'
|
||||||
import { getServerSideURL } from '@/utilities/getURL'
|
import { getServerSideURL } from '@/utilities/getURL'
|
||||||
import { UserAccessLevel } from '@/collections/Users'
|
|
||||||
import { isSuperAdmin } from '@/access/isSuperAdmin'
|
import { isSuperAdmin } from '@/access/isSuperAdmin'
|
||||||
import { getUserTenantIDs } from '@/utilities/getUserTenantIds'
|
import { getUserTenantIDs } from '@/utilities/getUserTenantIds'
|
||||||
|
|
||||||
@ -117,7 +116,7 @@ export const plugins: Plugin[] = [
|
|||||||
tenantsArrayField: {
|
tenantsArrayField: {
|
||||||
includeDefaultField: false,
|
includeDefaultField: false,
|
||||||
},
|
},
|
||||||
userHasAccessToAllTenants: (user: User) => (user.accessLevel || 0) >= UserAccessLevel.SUPER_ADMIN,
|
userHasAccessToAllTenants: (user: User) => isSuperAdmin(user),
|
||||||
tenantField: {
|
tenantField: {
|
||||||
access: {
|
access: {
|
||||||
read: () => true,
|
read: () => true,
|
||||||
@ -127,7 +126,6 @@ export const plugins: Plugin[] = [
|
|||||||
}
|
}
|
||||||
return getUserTenantIDs(req.user).length > 0
|
return getUserTenantIDs(req.user).length > 0
|
||||||
},
|
},
|
||||||
create: () => true,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user