Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
9cb84e7
Update database schema
wongcolin45 Mar 28, 2026
0fc3e64
Updated backend to user new RoleType fields
wongcolin45 Mar 28, 2026
f1fe2d3
Updated the frontend to use the new role fields
wongcolin45 Mar 28, 2026
5d08e91
Update tests
wongcolin45 Mar 29, 2026
831a516
Update schema.prisma
wongcolin45 Mar 29, 2026
6b0bf6e
Moved permission logic to single file
wongcolin45 Mar 29, 2026
e92b47f
Update migrations
wongcolin45 Mar 29, 2026
f6794ed
Merge branch 'dev' into colin/update/roles
wongcolin45 Mar 29, 2026
b0d429d
Fix
wongcolin45 Mar 29, 2026
c821b07
Merge branch 'colin/update/roles' of https://github.com/SGAOperations…
wongcolin45 Mar 29, 2026
5255533
Update MeetingHistoryPanel.tsx
wongcolin45 Mar 29, 2026
07bd0d5
Change CI to do migration first
wongcolin45 Mar 29, 2026
bdbd06e
Update ci.yml
wongcolin45 Mar 29, 2026
97c4463
Merge branch 'dev' into colin/update/roles
wongcolin45 Mar 30, 2026
33fcfb8
Remove None Role Type
wongcolin45 Mar 30, 2026
2993bc9
Merge branch 'colin/update/roles' of https://github.com/SGAOperations…
wongcolin45 Mar 30, 2026
ff9c87f
Fix
wongcolin45 Mar 30, 2026
d929d68
Prettier
wongcolin45 Mar 30, 2026
d3ba4ca
Update ci.yml
wongcolin45 Mar 30, 2026
ec1c8c1
Lock down backend
wongcolin45 Apr 1, 2026
fe32bc4
Fix db
wongcolin45 Apr 1, 2026
4b17c54
fix test
wongcolin45 Apr 1, 2026
9839383
prettier
wongcolin45 Apr 1, 2026
94d7736
Removed checks for voting
wongcolin45 Apr 1, 2026
3ad6cbc
Merge branch 'dev' into colin/update/roles
wongcolin45 Apr 2, 2026
ffbfa8f
Merge branch 'dev' into colin/update/roles
wongcolin45 Apr 2, 2026
24d3482
Update permissions
wongcolin45 Apr 2, 2026
16799eb
Merge branch 'dev' into colin/update/roles
wongcolin45 Apr 7, 2026
7588d53
Prettier
wongcolin45 Apr 7, 2026
d0456bd
Lint + Update
wongcolin45 Apr 7, 2026
aac2692
Migrations on test db
wongcolin45 Apr 7, 2026
05165d9
Remove none
wongcolin45 Apr 7, 2026
79c4036
Merge branch 'dev' into colin/update/roles
wongcolin45 Apr 8, 2026
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
7 changes: 6 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ jobs:
runs-on: ubuntu-latest
env:
DATABASE_URL: ${{ secrets.DATABASE_URL_TEST }}
DIRECT_URL: ${{ secrets.DATABASE_URL_TEST }}
NODE_ENV: test
steps:
- name: Checkout repository
Expand All @@ -30,7 +31,11 @@ jobs:
- name: Generate Prisma Client
working-directory: attendance-manager
run: npx prisma generate


- name: Run Migrations
working-directory: attendance-manager
run: npx prisma migrate deploy

- name: Lint
working-directory: attendance-manager
run: npm run lint
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-- Add new RoleType enum values only
ALTER TYPE "RoleType" ADD VALUE IF NOT EXISTS 'SUPER_ADMIN';
ALTER TYPE "RoleType" ADD VALUE IF NOT EXISTS 'ADMIN';
ALTER TYPE "RoleType" ADD VALUE IF NOT EXISTS 'SENATOR';
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
-- Add roleType column with default MEMBER
ALTER TABLE "User" ADD COLUMN "roleType" "RoleType" NOT NULL DEFAULT 'MEMBER';

-- Add isVotingMember column with default false
ALTER TABLE "User" ADD COLUMN "isVotingMember" BOOLEAN NOT NULL DEFAULT false;

-- Backfill roleType from existing Role table
UPDATE "User" u
SET "roleType" = r."roleType"
FROM "Role" r
WHERE u."roleId" = r."roleId";

-- Backfill isVotingMember: true for MEMBER role users
UPDATE "User"
SET "isVotingMember" = true
WHERE "roleType" = 'MEMBER';
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
-- Convert any NONE role types to MEMBER
UPDATE "User" SET "roleType" = 'MEMBER' WHERE "roleType"::text = 'NONE';
UPDATE "Role" SET "roleType" = 'MEMBER' WHERE "roleType"::text = 'NONE';
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
-- Convert any remaining NONE role types to MEMBER
UPDATE "User" SET "roleType" = 'MEMBER' WHERE "roleType"::text = 'NONE';
UPDATE "Role" SET "roleType" = 'MEMBER' WHERE "roleType"::text = 'NONE';

-- Recreate the RoleType enum without NONE
-- Drop column defaults that reference the enum first
ALTER TABLE "User" ALTER COLUMN "roleType" DROP DEFAULT;

-- Create new enum without NONE
CREATE TYPE "RoleType_new" AS ENUM ('SUPER_ADMIN', 'ADMIN', 'SENATOR', 'EBOARD', 'MEMBER');

-- Migrate columns to new enum type
ALTER TABLE "User" ALTER COLUMN "roleType" TYPE "RoleType_new" USING "roleType"::text::"RoleType_new";
ALTER TABLE "Role" ALTER COLUMN "roleType" TYPE "RoleType_new" USING "roleType"::text::"RoleType_new";

-- Drop old type and rename
DROP TYPE "RoleType";
ALTER TYPE "RoleType_new" RENAME TO "RoleType";

-- Restore default
ALTER TABLE "User" ALTER COLUMN "roleType" SET DEFAULT 'MEMBER';
5 changes: 5 additions & 0 deletions attendance-manager/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ model User {
firstName String
lastName String
roleId String
roleType RoleType @default(MEMBER)
isVotingMember Boolean @default(false)
password String? // Optional - Supabase handles authentication
attendance Attendance[]
role Role @relation(fields: [roleId], references: [roleId])
Expand Down Expand Up @@ -96,6 +98,9 @@ model VotingRecord {
}

enum RoleType {
SUPER_ADMIN
ADMIN
SENATOR
EBOARD
MEMBER
}
Expand Down
12 changes: 12 additions & 0 deletions attendance-manager/src/app/api/attendance/[attendanceId]/route.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { NextRequest, NextResponse } from 'next/server';
import { AttendanceController } from '../../../../attendance/attendance.controller';
import { requireAuth } from '@/utils/api-auth';
import { checkCanManageAttendance } from '@/utils/permissions';

/**
* Updates an Attendance
Expand All @@ -12,6 +14,11 @@ export async function PATCH(
req: NextRequest,
{ params }: { params: Promise<{ attendanceId: string }> },
) {
const { user, error } = await requireAuth();
if (error) return error;
if (!checkCanManageAttendance(user.roleType)) {
return NextResponse.json({ error: 'Forbidden' }, { status: 403 });
}
try {
const { attendanceId } = await params;
const data = await req.json();
Expand All @@ -38,6 +45,11 @@ export async function DELETE(
req: NextRequest,
{ params }: { params: Promise<{ attendanceId: string }> },
) {
const { user, error } = await requireAuth();
if (error) return error;
if (!checkCanManageAttendance(user.roleType)) {
return NextResponse.json({ error: 'Forbidden' }, { status: 403 });
}
try {
const { attendanceId } = await params; // Await params
await AttendanceController.deleteAttendance(attendanceId);
Expand Down
1 change: 1 addition & 0 deletions attendance-manager/src/app/api/auth/signup/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export async function POST(request: Request) {
lastName,
nuid,
roleId: finalRoleId,
roleType: RoleType.MEMBER,
password: undefined, // Optional - Supabase handles authentication
},
include: {
Expand Down
16 changes: 16 additions & 0 deletions attendance-manager/src/app/api/meeting/[id]/route.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { NextResponse } from 'next/server';
import { MeetingController } from '@/meeting/meeting.controller';
import { requireAuth } from '@/utils/api-auth';
import {
checkCanEditMeetings,
checkCanManageMeetings,
} from '@/utils/permissions';

export async function GET(
request: Request,
Expand All @@ -12,6 +18,11 @@ export async function PUT(
request: Request,
{ params }: { params: Promise<{ id: string }> },
) {
const { user, error } = await requireAuth();
if (error) return error;
if (!checkCanEditMeetings(user.roleType)) {
return NextResponse.json({ error: 'Forbidden' }, { status: 403 });
}
const { id } = await params;
return MeetingController.updateMeeting(request, { meetingId: id });
}
Expand All @@ -20,6 +31,11 @@ export async function DELETE(
request: Request,
{ params }: { params: Promise<{ id: string }> },
) {
const { user, error } = await requireAuth();
if (error) return error;
if (!checkCanManageMeetings(user.roleType)) {
return NextResponse.json({ error: 'Forbidden' }, { status: 403 });
}
const { id } = await params;
return MeetingController.deleteMeeting({ meetingId: id });
}
8 changes: 8 additions & 0 deletions attendance-manager/src/app/api/meeting/route.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { NextResponse } from 'next/server';
import { MeetingController } from '@/meeting/meeting.controller';
import { requireAuth } from '@/utils/api-auth';
import { checkCanManageMeetings } from '@/utils/permissions';
/**
* @swagger
* /api/users:
Expand All @@ -25,5 +28,10 @@ export async function GET() {
* description: Missing required fields.
*/
export async function POST(request: Request) {
const { user, error } = await requireAuth();
if (error) return error;
if (!checkCanManageMeetings(user.roleType)) {
return NextResponse.json({ error: 'Forbidden' }, { status: 403 });
}
return MeetingController.createMeeting(request);
}
Loading
Loading