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:
Jeffrey 2026-02-18 16:04:48 +01:00
parent ccdc739c22
commit ed4062aef0
12 changed files with 22947 additions and 7 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

BIN
media/Queen_band.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

5
src/access/adminOnly.ts Normal file
View File

@ -0,0 +1,5 @@
import type { Access } from 'payload'
export const adminOnly: Access = ({ req: { user } }) => {
return user?.role === 'admin'
}

View File

@ -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,

View File

@ -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',

View File

@ -1,4 +1,5 @@
import type { GlobalConfig } from 'payload'
import { adminOnly } from '../access/adminOnly'
export const PopupAnnouncement: GlobalConfig = {
slug: 'popup-announcement',

View File

@ -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: [

File diff suppressed because it is too large Load Diff

View 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";`)
}

View File

@ -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'
},
];

View File

@ -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;