fix(05-06): add Collection and Remittance CASL subjects, update routes
- Add Collection and Remittance to AppSubjects union type - Grant OFFICE_STAFF manage:Collection and manage:Remittance - Grant COLLECTOR create/read:Collection and create/read:Remittance - Update all 8 collection/remittance route handlers from Subscriber to their dedicated CASL subjects (Collection or Remittance) - Update JSDoc comments in route files to reflect new subject names Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
/**
|
||||
* GET /api/collections/[id] — Get a single collection with allocations
|
||||
* GET /api/collections/[id] — Get a single collection with allocations (requires read:Collection)
|
||||
*/
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { withPermission } from "@/lib/middleware/authorize";
|
||||
import { withTenantContext } from "@/lib/prisma-tenant";
|
||||
|
||||
export function GET(req: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
||||
return withPermission("read", "Subscriber")(
|
||||
return withPermission("read", "Collection")(
|
||||
async (_req: NextRequest, { user }) => {
|
||||
if (!user.tenantId) {
|
||||
return NextResponse.json(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* POST /api/collections/[id]/void — Void a collection (reversing JE)
|
||||
* POST /api/collections/[id]/void — Void a collection (requires update:Collection)
|
||||
*/
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { withPermission } from "@/lib/middleware/authorize";
|
||||
@@ -7,7 +7,7 @@ import { withTenantContext } from "@/lib/prisma-tenant";
|
||||
import { voidCollection } from "@/lib/services/collector-service";
|
||||
|
||||
export function POST(req: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
||||
return withPermission("update", "Subscriber")(
|
||||
return withPermission("update", "Collection")(
|
||||
async (_req: NextRequest, { user }) => {
|
||||
if (!user.tenantId) {
|
||||
return NextResponse.json(
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/**
|
||||
* POST /api/collections — Record a new cash collection
|
||||
* GET /api/collections — Get collection history (filtered by subscriberId or collectorId)
|
||||
* POST /api/collections — Record a new cash collection (requires create:Collection)
|
||||
* GET /api/collections — Get collection history (requires read:Collection)
|
||||
*/
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { withPermission } from "@/lib/middleware/authorize";
|
||||
import { withTenantContext } from "@/lib/prisma-tenant";
|
||||
import { recordCollection, getCollectionHistory } from "@/lib/services/collector-service";
|
||||
|
||||
export const POST = withPermission("create", "Subscriber")(
|
||||
export const POST = withPermission("create", "Collection")(
|
||||
async (req: NextRequest, { user }) => {
|
||||
if (!user.tenantId) {
|
||||
return NextResponse.json(
|
||||
@@ -53,7 +53,7 @@ export const POST = withPermission("create", "Subscriber")(
|
||||
}
|
||||
);
|
||||
|
||||
export const GET = withPermission("read", "Subscriber")(
|
||||
export const GET = withPermission("read", "Collection")(
|
||||
async (req: NextRequest, { user }) => {
|
||||
if (!user.tenantId) {
|
||||
return NextResponse.json(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* POST /api/remittances/[id]/verify — Verify a remittance (office staff counts total)
|
||||
* POST /api/remittances/[id]/verify — Verify a remittance (requires update:Remittance)
|
||||
*/
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { withPermission } from "@/lib/middleware/authorize";
|
||||
@@ -7,7 +7,7 @@ import { withTenantContext } from "@/lib/prisma-tenant";
|
||||
import { verifyRemittance } from "@/lib/services/remittance-service";
|
||||
|
||||
export function POST(req: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
||||
return withPermission("update", "Subscriber")(
|
||||
return withPermission("update", "Remittance")(
|
||||
async (innerReq: NextRequest, { user }) => {
|
||||
if (!user.tenantId) {
|
||||
return NextResponse.json(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* POST /api/remittances — Create a new remittance (collector declares total)
|
||||
* GET /api/remittances — List remittances with optional filtering
|
||||
* POST /api/remittances — Create a new remittance (requires create:Remittance)
|
||||
* GET /api/remittances — List remittances with optional filtering (requires read:Remittance)
|
||||
*/
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { withPermission } from "@/lib/middleware/authorize";
|
||||
@@ -8,7 +8,7 @@ import { withTenantContext } from "@/lib/prisma-tenant";
|
||||
import { createRemittance, listRemittances } from "@/lib/services/remittance-service";
|
||||
import { RemittanceStatus } from "@prisma/client";
|
||||
|
||||
export const POST = withPermission("create", "Subscriber")(
|
||||
export const POST = withPermission("create", "Remittance")(
|
||||
async (req: NextRequest, { user }) => {
|
||||
if (!user.tenantId) {
|
||||
return NextResponse.json(
|
||||
@@ -50,7 +50,7 @@ export const POST = withPermission("create", "Subscriber")(
|
||||
}
|
||||
);
|
||||
|
||||
export const GET = withPermission("read", "Subscriber")(
|
||||
export const GET = withPermission("read", "Remittance")(
|
||||
async (req: NextRequest, { user }) => {
|
||||
if (!user.tenantId) {
|
||||
return NextResponse.json(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* GET /api/reports/collections — Daily collection summary report
|
||||
* GET /api/reports/collections — Daily collection summary report (requires read:Collection)
|
||||
*
|
||||
* Query params:
|
||||
* date — ISO date string (defaults to today)
|
||||
@@ -10,7 +10,7 @@ import { withPermission } from "@/lib/middleware/authorize";
|
||||
import { withTenantContext } from "@/lib/prisma-tenant";
|
||||
import { getDailyCollectionSummary, getCollectorCollectionDetail } from "@/lib/services/collection-report-service";
|
||||
|
||||
export const GET = withPermission("read", "Subscriber")(
|
||||
export const GET = withPermission("read", "Collection")(
|
||||
async (req: NextRequest, { user }) => {
|
||||
if (!user.tenantId) {
|
||||
return NextResponse.json(
|
||||
|
||||
@@ -66,6 +66,9 @@ export function definePermissionsFor(
|
||||
can("manage", "Expense");
|
||||
// Vendor management (CRUD)
|
||||
can("manage", "Vendor");
|
||||
// Collection and remittance management
|
||||
can("manage", "Collection");
|
||||
can("manage", "Remittance");
|
||||
// Job type rates (read-only for office staff — admin configures rates)
|
||||
can("read", "JobTypeRate");
|
||||
// View financial reports (read-only)
|
||||
@@ -88,6 +91,12 @@ export function definePermissionsFor(
|
||||
can("create", "Payment");
|
||||
// View payment history
|
||||
can("read", "Payment");
|
||||
// Can create and view collections
|
||||
can("create", "Collection");
|
||||
can("read", "Collection");
|
||||
// Can create and view remittances
|
||||
can("create", "Remittance");
|
||||
can("read", "Remittance");
|
||||
// NOTE: No explicit cannot() needed — Collector simply has no rules for
|
||||
// Invoice, User management, or Reports. Absence of a rule = no access.
|
||||
break;
|
||||
|
||||
@@ -13,6 +13,8 @@ export type AppSubjects =
|
||||
| "Subscriber"
|
||||
| "Invoice"
|
||||
| "Payment"
|
||||
| "Collection"
|
||||
| "Remittance"
|
||||
| "Zone"
|
||||
| "Ticket"
|
||||
| "JobOrder"
|
||||
|
||||
Reference in New Issue
Block a user