Skip to content

Administration & Permissions ​

Beyond core submission and search, Papex ships an operator-facing admin area and a fine-grained permission system. This guide covers four capabilities:

  1. Roles & permissions (RBAC) — control paper publishing, viewing, downloading and commenting by role or per-user.
  2. User permission management — assign extra roles and set per-user allow / deny overrides for any permission.
  3. Co-review (peer review) — admins send co-review requests; reviewers accept, submit opinions and receive receipts, forming a closed loop.
  4. Categorized messages & broadcast — a unified notification center spanning system notices, review results, ticket receipts, co-review requests, admin DMs and community replies, plus targeted broadcasts.

1. Roles & Permissions (RBAC) ​

Papex uses a three-layer model — base role + assigned roles + per-user overrides — supporting both bulk role-based authorization and personalized per-user restrictions.

1.1 Permission model ​

LayerDescriptionMaintained at
Base roleThe role inherent to every user in users.role: author / moderator / adminDefault author at registration
Assigned rolesExtra roles layered on a user via the user_roles join tableUser management page
Per-user overridesExplicit allow or deny for a single permission on a user; highest priorityUser management page

ℹ️ reader is an assigned RBAC role (in the roles table), not a database base role (users.role only allows author / moderator / admin). The base role defines the login and default permission boundary; assigned roles stack on top.

1.2 Permission catalog ​

The system ships 15 permissions across 6 groups:

GroupPermission keyNameDescription
paperpaper:publishPublish paperSubmit a new paper or version
paper:viewView paperBrowse published papers
paper:downloadDownload paperDownload PDF / source package
paper:moderateModerate paperApprove / reject / withdraw
commentcomment:createPost commentComment & reply under papers
comment:viewView commentsBrowse the comment section
ticketticket:createCreate ticketOpen feedback / ticket
ticket:manageManage ticketsReply to / handle tickets
co_reviewco_review:assignAssign co-reviewSend a co-review request
co_review:respondTake co-reviewAccept / decline a request
co_review:manageManage co-reviewView all co-review progress
messagemessage:broadcastBroadcastSend messages to users
adminuser:manageManage usersView / edit users
role:manageManage rolesConfigure roles & permissions
permission:manageManage overridesPer-user allow / deny

1.3 Default role permissions ​

The seed (db:seed) writes a default permission mapping for each system role:

RoleCountPermissions
admin15All permissions
moderator12paper view/download/moderate, comment create/view, ticket create/manage, co-review assign/respond/manage, broadcast, user manage
author6paper publish/view/download, comment create/view, ticket create
reader3paper view/download, comment view

1.4 Resolution order ​

When a protected operation runs, effective permissions resolve as:

base role permissions
  ∪ assigned role permissions      (role union)
  ∪ per-user overrides marked allow
  − per-user overrides marked deny  (overrides win)

So even if neither the base nor assigned roles grant paper:publish, an explicit allow override still permits it; conversely, an explicit deny blocks it even when roles grant it.

Fallback: if the roles / permissions tables are not yet seeded (e.g. a fresh DB without db:seed), the engine falls back to the constant default mapping above to avoid locking the whole site. Running db:seed after deploy is still recommended.

1.5 Protected operations (gateways) ​

Key operations are gated; missing permission returns 403:

  • POST /api/papers — requires paper:publish
  • POST /api/papers/:id/comments — requires comment:create
  • Moderation, ticket handling, co-review assignment / management, user & role edits, broadcast, etc. require their respective permissions, and the routes are protected by middleware (only moderator / admin may enter /admin).

2. User permission management ​

Open /admin/users (requires user:manage):

  • Search users by username / email / display name, with pagination.
  • Assign extra roles: tick system roles (admin / moderator / author / reader) in the user editor to stack onto the base role.
  • Three-state permission override: for each of the 15 permissions set:
    • inherit (default) — follow the role-union result;
    • allow — force-grant even if roles omit it;
    • deny — force-block even if roles include it.

All changes save instantly via PATCH /api/admin/users/:id and apply to that user's subsequent authorization checks.


3. Co-review (peer review) ​

Co-review is a complete peer-review loop connecting admin → reviewer → author.

3.1 Closed loop ​

Admin assigns ──► Reviewer gets a "co-review request" message
     │
     ▼
Reviewer responds (accept / decline)
     │ accept
     ▼
Reviewer submits opinion (approve / reject / revise + comment)
     │
     ▼
System receipt ──► notifies assigner "opinion submitted"
                ──► notifies author "co-review completed" (if author ≠ assigner)

3.2 State machine ​

A co-review record (co_reviews) transitions as follows:

StateMeaningEntered by
pendingAwaiting reviewer responseAdmin assignment (POST /api/co-reviews)
acceptedAcceptedReviewer accepts (POST /api/co-reviews/:id/respond {accepted:true})
declinedDeclinedReviewer declines (respond {accepted:false})
completedCompletedReviewer submits opinion (submit)
expiredExpired(reserved state for timeout closure)

A reviewer may only respond while pending, and may only submit an opinion while accepted. A mismatched state returns INVALID_STATE.

3.3 Entry points & notifications ​

  • Admin: /admin/co-reviews to assign and monitor all co-reviews; /admin/co-reviews/:id for detail. Assignment picks from papers in submitted status.
  • Reviewer: /co-reviews (my reviews) and /co-reviews/:id (accept / decline + submit opinion).
  • Unified notifications: every state change fires a co_review_request / co_review_result message to the relevant parties (see Section 4).

4. Categorized messages & broadcast ​

4.1 Message categories ​

Messages are classified by kind into 8 categories, colored and grouped in the inbox:

kindLabelToneTypical source
systemSystem noticedefaultSystem events
ticket_replyTicket receiptinfo blueTicket replied
announcementAnnouncementwarning yellowAdmin broadcast
review_resultReview resultsuccess greenPaper approved / rejected
co_review_requestCo-review requestpurpleCo-review assigned
co_review_resultCo-review receiptpurpleResponse / opinion submitted
admin_messageAdmin DMdanger redTargeted direct message
community_replyCommunity replyinfo blueComment replied to

The inbox (/messages) supports filtering by category (GET /api/messages?kind=...); clicking a message navigates to its associated link (paper, ticket, co-review, …).

4.2 Unified notification funnel ​

All cross-module alerts are emitted through a single notifications service so review, ticket, co-review and community modules share one notification contract:

  • Review: paper decision → notify author (review_result).
  • Tickets: staff reply → notify reporter (ticket_reply).
  • Co-review: assign / respond / submit → notify reviewer, assigner, author (co_review_request / co_review_result).
  • Community: comment replied → notify parent-comment author (community_reply).

4.3 Broadcast ​

Open /admin/messages (requires message:broadcast):

  • Scope:
    • all — every user;
    • role — a base role (author / moderator / admin);
    • userIds — a list of specific user IDs.
  • Kind: announcement / system / admin_message.
  • Fill in title, body (with optional link), submit, and the message is written in bulk to the target audience; the success count is returned.

5. Admin navigation ​

Admin entry points live in the logged-in user menu and the /admin overview, including:

ModuleRouteDescription
Overview/adminStats cards + module shortcuts
Review queue/admin/reviewApprove / reject papers (+ reason)
Stats/admin/statsPlatform metrics
Tickets/admin/ticketsTicket handling
Co-review/admin/co-reviewsAssign & monitor co-reviews
Users/admin/usersRoles & permission overrides
Roles/admin/rolesRole permission matrix
Messages/admin/messagesBroadcast

These routes are protected by middleware; only users with a moderator or admin base role may access them, and write actions additionally require the matching fine-grained permission.


6. Ops: migrate & seed ​

The four systems depend on migration 0003_add_rbac_co_review_messages (adds roles / permissions / role_permissions / user_roles / user_permissions / co_reviews / moderation_logs, and extends messages.kind to 8 categories). On deploy or local init run:

bash
npm run db:migrate   # apply migrations (RBAC / co-review / message categories)
npm run db:seed      # write 4 system roles + 15 permissions + defaults (idempotent)

The RBAC seed uses onConflictDoNothing and is safe to re-run. After migrate + seed, the permission engine uses the roles / permissions tables; before seeding it falls back to the constant defaults (see 1.4).


7. API quick reference ​

MethodPathDescription
GET/api/messages?kind=Inbox, filter by category
POST/api/papers/:id/moderateModerate {action:"approve"|"reject"|"withdraw", reason?}
GET/api/co-reviews?scope=mine|allCo-review list (mine / all)
POST/api/co-reviewsAssign {paperId, reviewerId, note?}
GET/api/co-reviews/:idCo-review detail
POST/api/co-reviews/:id/respondRespond {accepted:boolean}
POST/api/co-reviews/:id/submitSubmit {decision:"approve"|"reject"|"revise", comment}
GET/api/admin/usersUser list (pagination / search)
PATCH/api/admin/users/:idSet roles {roleKeys} or override {permission:{key,grant}}
GET/api/admin/rolesRole list
PUT/api/admin/roles/:idSet role permissions {permissionKeys}
POST/api/admin/messagesBroadcast {scope, role?, userIds?, kind, title, body, link?}
GET/api/admin/statsPlatform stats

See the API reference for the full list.

Papex is open source under the Apache-2.0 license.