feat: add admin/editor roles to users, restrict globals to adminOnly
- Users: added role field (admin/editor), role field locked to adminOnly update - SiteSettings, AnnouncementBar, PopupAnnouncement: update restricted to adminOnly - Added src/access/adminOnly.ts helper
This commit is contained in:
parent
ccdc739c22
commit
ed4062aef0
BIN
media/Queen_band-400x281.webp
Normal file
BIN
media/Queen_band-400x281.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
BIN
media/Queen_band-800x561.webp
Normal file
BIN
media/Queen_band-800x561.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 36 KiB |
BIN
media/Queen_band.webp
Normal file
BIN
media/Queen_band.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 36 KiB |
5
src/access/adminOnly.ts
Normal file
5
src/access/adminOnly.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import type { Access } from 'payload'
|
||||
|
||||
export const adminOnly: Access = ({ req: { user } }) => {
|
||||
return user?.role === 'admin'
|
||||
}
|
||||
@ -1,18 +1,20 @@
|
||||
import type { CollectionConfig } from 'payload'
|
||||
|
||||
import { authenticated } from '../../access/authenticated'
|
||||
|
||||
// Only admins can manage users
|
||||
const adminOnly = ({ req: { user } }: any) => user?.role === 'admin'
|
||||
|
||||
export const Users: CollectionConfig = {
|
||||
slug: 'users',
|
||||
access: {
|
||||
admin: authenticated,
|
||||
create: authenticated,
|
||||
delete: authenticated,
|
||||
create: adminOnly,
|
||||
delete: adminOnly,
|
||||
read: authenticated,
|
||||
update: authenticated,
|
||||
update: authenticated, // users can update themselves; field-level locks the role field
|
||||
},
|
||||
admin: {
|
||||
defaultColumns: ['name', 'email'],
|
||||
defaultColumns: ['name', 'email', 'role'],
|
||||
useAsTitle: 'name',
|
||||
},
|
||||
auth: true,
|
||||
@ -20,6 +22,25 @@ export const Users: CollectionConfig = {
|
||||
{
|
||||
name: 'name',
|
||||
type: 'text',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'role',
|
||||
type: 'select',
|
||||
label: 'Roll',
|
||||
required: true,
|
||||
defaultValue: 'editor',
|
||||
options: [
|
||||
{ label: 'Admin', value: 'admin' },
|
||||
{ label: 'Redaktör', value: 'editor' },
|
||||
],
|
||||
// Only admins can change roles
|
||||
access: {
|
||||
update: adminOnly,
|
||||
},
|
||||
admin: {
|
||||
description: 'Admin har full åtkomst. Redaktör kan hantera sidor, inlägg och media.',
|
||||
},
|
||||
},
|
||||
],
|
||||
timestamps: true,
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import type { GlobalConfig } from 'payload'
|
||||
import { adminOnly } from '../access/adminOnly'
|
||||
|
||||
export const AnnouncementBar: GlobalConfig = {
|
||||
slug: 'announcement-bar',
|
||||
@ -6,6 +7,10 @@ export const AnnouncementBar: GlobalConfig = {
|
||||
admin: {
|
||||
group: 'Globala inställningar',
|
||||
},
|
||||
access: {
|
||||
read: () => true,
|
||||
update: adminOnly,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'enabled',
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import type { GlobalConfig } from 'payload'
|
||||
import { adminOnly } from '../access/adminOnly'
|
||||
|
||||
export const PopupAnnouncement: GlobalConfig = {
|
||||
slug: 'popup-announcement',
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
import type { GlobalConfig } from 'payload'
|
||||
import { adminOnly } from '../access/adminOnly'
|
||||
|
||||
export const SiteSettings: GlobalConfig = {
|
||||
slug: 'site-settings',
|
||||
label: 'Webbplatsinställningar',
|
||||
access: {
|
||||
update: adminOnly,
|
||||
read: () => true,
|
||||
},
|
||||
fields: [
|
||||
|
||||
22880
src/migrations/20260218_145924.json
Normal file
22880
src/migrations/20260218_145924.json
Normal file
File diff suppressed because it is too large
Load Diff
15
src/migrations/20260218_145924.ts
Normal file
15
src/migrations/20260218_145924.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { MigrateUpArgs, MigrateDownArgs, sql } from '@payloadcms/db-postgres'
|
||||
|
||||
export async function up({ db, payload, req }: MigrateUpArgs): Promise<void> {
|
||||
await db.execute(sql`
|
||||
CREATE TYPE "public"."enum_users_role" AS ENUM('admin', 'editor');
|
||||
ALTER TABLE "users" ALTER COLUMN "name" SET NOT NULL;
|
||||
ALTER TABLE "users" ADD COLUMN "role" "enum_users_role" DEFAULT 'editor' NOT NULL;`)
|
||||
}
|
||||
|
||||
export async function down({ db, payload, req }: MigrateDownArgs): Promise<void> {
|
||||
await db.execute(sql`
|
||||
ALTER TABLE "users" ALTER COLUMN "name" DROP NOT NULL;
|
||||
ALTER TABLE "users" DROP COLUMN "role";
|
||||
DROP TYPE "public"."enum_users_role";`)
|
||||
}
|
||||
@ -5,6 +5,7 @@ import * as migration_20260216_183152 from './20260216_183152';
|
||||
import * as migration_20260216_184110 from './20260216_184110';
|
||||
import * as migration_20260216_184342 from './20260216_184342';
|
||||
import * as migration_20260218_130902 from './20260218_130902';
|
||||
import * as migration_20260218_145924 from './20260218_145924';
|
||||
|
||||
export const migrations = [
|
||||
{
|
||||
@ -40,6 +41,11 @@ export const migrations = [
|
||||
{
|
||||
up: migration_20260218_130902.up,
|
||||
down: migration_20260218_130902.down,
|
||||
name: '20260218_130902'
|
||||
name: '20260218_130902',
|
||||
},
|
||||
{
|
||||
up: migration_20260218_145924.up,
|
||||
down: migration_20260218_145924.down,
|
||||
name: '20260218_145924'
|
||||
},
|
||||
];
|
||||
|
||||
@ -1397,7 +1397,11 @@ export interface Category {
|
||||
*/
|
||||
export interface User {
|
||||
id: number;
|
||||
name?: string | null;
|
||||
name: string;
|
||||
/**
|
||||
* Admin har full åtkomst. Redaktör kan hantera sidor, inlägg och media.
|
||||
*/
|
||||
role: 'admin' | 'editor';
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
email: string;
|
||||
@ -2448,6 +2452,7 @@ export interface CategoriesSelect<T extends boolean = true> {
|
||||
*/
|
||||
export interface UsersSelect<T extends boolean = true> {
|
||||
name?: T;
|
||||
role?: T;
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
email?: T;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user