Files
aura-crm/production/backend/internal/authz/authz.go
T

76 lines
2.9 KiB
Go

// Package authz holds the one authorization rule shared by orders and
// cartridge_batches: both tables carry an assigned_master_id column, and
// both need the identical policy applied to it — not just from order/
// cartridge's own handlers but from every other package that acts on a
// specific order or batch (inventory, cash, document, diagnosis). Kept as a
// single package rather than duplicated per-domain logic so the rule and
// its query can't drift between call sites.
package authz
import (
"context"
"github.com/gofiber/fiber/v2"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgxpool"
)
// CanAccessAssigned reports whether a staff member may read or act on a
// record that has an assigned_master_id column. Gated on the "unscoped"
// permission (see core's migrations/007_unscoped_permission.sql) rather than
// the literal "master" role name — a custom role without "unscoped" is just
// as restricted as a built-in master, and owner/manager only keep full
// oversight because that migration seeded "unscoped" onto them. A staff
// member with "unscoped" always can; without it, only an unassigned record
// (nil, not yet claimed by anyone) or one already assigned to them is
// accessible.
func CanAccessAssigned(permissions []string, assignedMasterID *string, staffID string) bool {
if hasUnscoped(permissions) {
return true
}
return assignedMasterID == nil || *assignedMasterID == staffID
}
func hasUnscoped(permissions []string) bool {
for _, p := range permissions {
if p == "unscoped" {
return true
}
}
return false
}
// CheckOrderAccess loads an order's current assigned_master_id and applies
// CanAccessAssigned, returning a ready-to-send fiber error (404 if the order
// doesn't exist, 403 if it's assigned to a different master) or nil.
func CheckOrderAccess(ctx context.Context, db *pgxpool.Pool, orderID string, permissions []string, staffID string) error {
var assignedMasterID *string
err := db.QueryRow(ctx, `SELECT assigned_master_id FROM orders WHERE id = $1::uuid`, orderID).Scan(&assignedMasterID)
if err != nil {
if err == pgx.ErrNoRows {
return fiber.NewError(404, "order not found")
}
return fiber.NewError(500, "internal error")
}
if !CanAccessAssigned(permissions, assignedMasterID, staffID) {
return fiber.NewError(403, "not assigned to you")
}
return nil
}
// CheckBatchAccess is CheckOrderAccess for cartridge_batches.
func CheckBatchAccess(ctx context.Context, db *pgxpool.Pool, batchID string, permissions []string, staffID string) error {
var assignedMasterID *string
err := db.QueryRow(ctx, `SELECT assigned_master_id FROM cartridge_batches WHERE id = $1::uuid`, batchID).Scan(&assignedMasterID)
if err != nil {
if err == pgx.ErrNoRows {
return fiber.NewError(404, "batch not found")
}
return fiber.NewError(500, "internal error")
}
if !CanAccessAssigned(permissions, assignedMasterID, staffID) {
return fiber.NewError(403, "not assigned to you")
}
return nil
}