Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,10 @@ hooks: {

## Access Control

### Resource Access Checking

ALWAYS utilize `src/access/checkResourceAccess.ts` for resource access checking. The only exception is for specific resources (like `users` or service accounts) where it is strictly for admins to create. For all other resources, you must use `checkResourceAccess.ts`.

### Collection-Level Access

```typescript
Expand Down Expand Up @@ -1019,6 +1023,7 @@ export const myPlugin =
3. Extract hooks to `hooks/` directory
4. Use reusable field factories for common patterns
5. Document complex access control with comments
6. Always write seed functions after creating a new resource

## Common Gotchas

Expand Down Expand Up @@ -1123,7 +1128,6 @@ For deeper exploration of specific topics, refer to the context files located in
- Best practices

13. **`components.md`** - Custom Components

- Component types (Root, Collection, Global, Field)
- Server vs Client Components
- Component paths and definition
Expand Down
35 changes: 18 additions & 17 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,25 @@
<!-- Release notes generated using configuration in .github/release.yml at release/production -->

## What's Changed

### 🏑 Other Changes
* feat: dockerize CMS config by @ASPactores in https://github.com/DurianPy-Davao-Python-User-Group/durianpy-cms/pull/1
* chore: add volume mapping for public directory in development configuration by @ASPactores in https://github.com/DurianPy-Davao-Python-User-Group/durianpy-cms/pull/2
* feat: update user model and implement access management checks by @seangaaab in https://github.com/DurianPy-Davao-Python-User-Group/durianpy-cms/pull/3
* feat: implement github action for checks and image push by @seangaaab in https://github.com/DurianPy-Davao-Python-User-Group/durianpy-cms/pull/4
* chore: harden docker image, add sast checking to ci, and optimize gh actions by @ASPactores in https://github.com/DurianPy-Davao-Python-User-Group/durianpy-cms/pull/5
* chore: s3 and api gateway fixes for file upload by @ASPactores in https://github.com/DurianPy-Davao-Python-User-Group/durianpy-cms/pull/6
* docs: repository documentations by @seangaaab in https://github.com/DurianPy-Davao-Python-User-Group/durianpy-cms/pull/8
* feat: documentations pt2 by @seangaaab in https://github.com/DurianPy-Davao-Python-User-Group/durianpy-cms/pull/9
* chore: prepare pr templates and pre-commit hooks by @ASPactores in https://github.com/DurianPy-Davao-Python-User-Group/durianpy-cms/pull/10
* feat: remove unused files and update collection access logic by @seangaaab in https://github.com/DurianPy-Davao-Python-User-Group/durianpy-cms/pull/11
* chore: remove unnecessary dockerfiles by @ASPactores in https://github.com/DurianPy-Davao-Python-User-Group/durianpy-cms/pull/12
* docs: include mandatory visual evidence section in PR template by @ASPactores in https://github.com/DurianPy-Davao-Python-User-Group/durianpy-cms/pull/13
* feat: update workflow to include test cases and initialize unit tests by @seangaaab in https://github.com/DurianPy-Davao-Python-User-Group/durianpy-cms/pull/14
* ci: enforce cicd approval workflow by @ASPactores in https://github.com/DurianPy-Davao-Python-User-Group/durianpy-cms/pull/26
* chore(build-push-ecr.yml): delete unnecessary file by @ASPactores in https://github.com/DurianPy-Davao-Python-User-Group/durianpy-cms/pull/27
* feat: update ci cd by @seangaaab in https://github.com/DurianPy-Davao-Python-User-Group/durianpy-cms/pull/28
* chore: test git autotagging by @ASPactores in https://github.com/DurianPy-Davao-Python-User-Group/durianpy-cms/pull/30

- feat: dockerize CMS config by @ASPactores in https://github.com/DurianPy-Davao-Python-User-Group/durianpy-cms/pull/1
- chore: add volume mapping for public directory in development configuration by @ASPactores in https://github.com/DurianPy-Davao-Python-User-Group/durianpy-cms/pull/2
- feat: update user model and implement access management checks by @seangaaab in https://github.com/DurianPy-Davao-Python-User-Group/durianpy-cms/pull/3
- feat: implement github action for checks and image push by @seangaaab in https://github.com/DurianPy-Davao-Python-User-Group/durianpy-cms/pull/4
- chore: harden docker image, add sast checking to ci, and optimize gh actions by @ASPactores in https://github.com/DurianPy-Davao-Python-User-Group/durianpy-cms/pull/5
- chore: s3 and api gateway fixes for file upload by @ASPactores in https://github.com/DurianPy-Davao-Python-User-Group/durianpy-cms/pull/6
- docs: repository documentations by @seangaaab in https://github.com/DurianPy-Davao-Python-User-Group/durianpy-cms/pull/8
- feat: documentations pt2 by @seangaaab in https://github.com/DurianPy-Davao-Python-User-Group/durianpy-cms/pull/9
- chore: prepare pr templates and pre-commit hooks by @ASPactores in https://github.com/DurianPy-Davao-Python-User-Group/durianpy-cms/pull/10
- feat: remove unused files and update collection access logic by @seangaaab in https://github.com/DurianPy-Davao-Python-User-Group/durianpy-cms/pull/11
- chore: remove unnecessary dockerfiles by @ASPactores in https://github.com/DurianPy-Davao-Python-User-Group/durianpy-cms/pull/12
- docs: include mandatory visual evidence section in PR template by @ASPactores in https://github.com/DurianPy-Davao-Python-User-Group/durianpy-cms/pull/13
- feat: update workflow to include test cases and initialize unit tests by @seangaaab in https://github.com/DurianPy-Davao-Python-User-Group/durianpy-cms/pull/14
- ci: enforce cicd approval workflow by @ASPactores in https://github.com/DurianPy-Davao-Python-User-Group/durianpy-cms/pull/26
- chore(build-push-ecr.yml): delete unnecessary file by @ASPactores in https://github.com/DurianPy-Davao-Python-User-Group/durianpy-cms/pull/27
- feat: update ci cd by @seangaaab in https://github.com/DurianPy-Davao-Python-User-Group/durianpy-cms/pull/28
- chore: test git autotagging by @ASPactores in https://github.com/DurianPy-Davao-Python-User-Group/durianpy-cms/pull/30

**Full Changelog**: https://github.com/DurianPy-Davao-Python-User-Group/durianpy-cms/commits/v0.0.1
3 changes: 2 additions & 1 deletion next.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ const NEXT_PUBLIC_SERVER_URL =
? `https://${process.env.VERCEL_PROJECT_PRODUCTION_URL}`
: process.env.__NEXT_PRIVATE_ORIGIN || 'http://localhost:3000')

const isProduction = process.env.NODE_ENV === 'production' || process.env.ENVIRONMENT === 'production'
const isProduction =
process.env.NODE_ENV === 'production' || process.env.ENVIRONMENT === 'production'

const nextConfig: NextConfig = {
output: 'standalone',
Expand Down
33 changes: 0 additions & 33 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
"build": "cross-env NODE_OPTIONS=--no-deprecation next build",
"dev": "cross-env NODE_OPTIONS=--no-deprecation next dev",
"dev:prod": "cross-env NODE_OPTIONS=--no-deprecation rm -rf .next && npm run build && npm run start",
"format": "prettier --write .",
"format:check": "prettier --check .",
"generate:importmap": "cross-env NODE_OPTIONS=--no-deprecation payload generate:importmap",
"generate:types": "cross-env NODE_OPTIONS=--no-deprecation payload generate:types",
"ii": "cross-env NODE_OPTIONS=--no-deprecation npm install",
Expand Down
54 changes: 0 additions & 54 deletions src/access/checkCollectionAccess.ts

This file was deleted.

96 changes: 96 additions & 0 deletions src/access/checkResourceAccess.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import type { AccessArgs, Where, CollectionConfig, GlobalConfig } from 'payload'
import type { User } from '@/payload-types'
import { anyAdmin } from './anyAdmin'
import { AccessType, getSlugType } from '@/constants/accessTypes'
import { PERMISSION_TO_ACCESS_TYPES } from '@/constants/permissions'
import { GlobalSlug } from '@/constants/globals'
import { CollectionSlug } from '@/constants/collections'
import { getSidebarGroupItems, SidebarGroupSlug } from '@/constants/sidebarGroup'

export function checkResourceAccess(
{ req }: AccessArgs<User>,
resourceSlug: CollectionSlug | SidebarGroupSlug | GlobalSlug,
accessType?: AccessType,
) {
const user = req.user

if (!user) {
return false
}

if (anyAdmin({ req })) {
return true
}

const permissions = user.permissions || []

if (permissions.length === 0 || !accessType) {
return false
}

return permissions.some((assignment) => {
const assignedSlug = assignment.resource
const slugType = getSlugType(assignedSlug)
let isApplicable = false

if (slugType === 'group') {
const groupItems = getSidebarGroupItems(assignedSlug as SidebarGroupSlug)
isApplicable = groupItems.includes(resourceSlug as CollectionSlug)
} else if (slugType === 'collection') {
isApplicable = assignedSlug === resourceSlug
}

if (isApplicable) {
const grantedAccessTypes = PERMISSION_TO_ACCESS_TYPES[assignment.accessLevel]
return grantedAccessTypes.includes(accessType)
}

return false
})
}

/**
* Verifies read access for a resource and enforces draft visibility rules.
* Service accounts can only access drafts if they are also granted write (update) access.
*/
export function checkReadAccess(
accessArgs: AccessArgs<User>,
resourceSlug: CollectionSlug | GlobalSlug,
hasDrafts: boolean = false,
): boolean | Where {
const hasRead = checkResourceAccess(accessArgs, resourceSlug, 'read')
if (!hasRead) return false

if (hasDrafts) {
const hasUpdate = checkResourceAccess(accessArgs, resourceSlug, 'update')
if (hasUpdate) return true
return { _status: { equals: 'published' } }
}

return true
}

/**
* Factory function to create standard access control methods for a Collection.
*/
export const createCollectionAccess = (
resourceSlug: CollectionSlug,
hasDrafts = false,
): CollectionConfig['access'] => ({
admin: (access) => checkResourceAccess(access, resourceSlug, 'admin') as boolean,
create: (access) => checkResourceAccess(access, resourceSlug, 'create') as boolean,
delete: (access) => checkResourceAccess(access, resourceSlug, 'delete') as boolean,
read: (access) => checkReadAccess(access, resourceSlug, hasDrafts),
update: (access) => checkResourceAccess(access, resourceSlug, 'update') as boolean,
})

/**
* Factory function to create standard access control methods for a Global.
*/
export const createGlobalAccess = (
resourceSlug: GlobalSlug,
hasDrafts = false,
): GlobalConfig['access'] => ({
read: (access) => checkReadAccess(access, resourceSlug, hasDrafts),
update: (access) => checkResourceAccess(access, resourceSlug, 'update') as boolean,
})
Loading
Loading