feat: implement permissions and actions management
CI / Lint, typecheck, test, build (push) Canceled after 0s
CI / End-to-end tests (push) Canceled after 0s

- Add permissions logic for status options in corrective actions.
- Create tests for permissions functionality.
- Implement queries for user authentication and actions management.
- Develop Actions page to display and manage corrective actions.
- Create authentication pages for login, setup, and password reset.
- Add IncidentDetail page to view incident details and associated actions.
- Implement Settings page for user management and password changes.
This commit is contained in:
jayjennings committed 2026-10-06 11:20:44 -07:00
1 parent 708da6b9f7
commit 3f6dff5f24
94 files changed
+7213 -643

No files matched your search

+18 -3
View File
@@ -2,7 +2,7 @@
import { hashPassword } from '../auth/password.ts'
import { loadConfig } from '../config.ts'
import { openDatabase } from './client.ts'
import { areas, incidentCounters, incidents, organizations, sites, users } from './schema.ts'
import { auditLog, areas, incidentCounters, incidents, organizations, sites, users } from './schema.ts'
const DEMO_PASSWORD = 'safetylog-demo'
@@ -49,8 +49,10 @@ try {
{ title: 'Wet floor near employee entrance', type: 'hazard', severity: 'medium', status: 'actions', building: 'Building A', locationDetail: 'Ground floor lobby', reporter: 'reporter@example.com', days: 6 },
{ title: 'Forklift reversed into pallet stack', type: 'near_miss', severity: 'high', status: 'triage', building: 'Warehouse 04', locationDetail: 'Loading bay C', reporter: 'admin@example.com', days: 5 },
] as const
await tx.insert(incidents).values(
demo.map((item, index) => ({
const created = await tx
.insert(incidents)
.values(
demo.map((item, index) => ({
organizationId: org.id,
number: index + 1,
title: item.title,
@@ -58,10 +60,23 @@ try {
severity: item.severity,
status: item.status,
occurredAt: daysAgo(item.days),
createdAt: new Date(daysAgo(item.days).getTime() + 2 * 3_600_000),
...areaIds[item.building],
locationDetail: item.locationDetail,
reporterId: person(item.reporter),
closedAt: item.status === 'closed' ? daysAgo(item.days - 3) : null,
})),
)
.returning()
await tx.insert(auditLog).values(
created.map((incident) => ({
organizationId: org.id,
actorId: incident.reporterId,
entityType: 'incident',
entityId: incident.id,
action: 'create',
changes: { number: incident.number, title: incident.title },
createdAt: incident.createdAt,
})),
)
await tx.insert(incidentCounters).values({ organizationId: org.id, lastNumber: demo.length })