Skip to content

Commit 11aef1d

Browse files
committed
Changed routers for all instances
1 parent 2a9fee5 commit 11aef1d

11 files changed

Lines changed: 1187 additions & 1210 deletions

File tree

server/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
"scripts": {
4343
"build": "tsc --project tsconfig.build.json",
4444
"start": "node build/app.js",
45-
"dev": "nodemon --exec \"ts-node\" src/app.ts",
45+
"dev": "nodemon --exec 'tsx' src/app.ts",
4646
"type-check": "tsc --project tsconfig.json --pretty --noEmit",
4747
"test": "cross-env NODE_ENV=test mocha -r ts-node/register \"tests/**/*.ts\" --exit --timeout 30000",
4848
"test:watch": "cross-env NODE_ENV=test nodemon --watch . --exec 'mocha -r ts-node/register \"tests/**/*.ts\" --timeout 10000' --ext ts"

server/src/db/prisma.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import "dotenv/config";
22
import { PrismaPg } from "@prisma/adapter-pg";
3-
import { PrismaClient } from "@prisma/client";
3+
import { PrismaClient } from "../../generated/prisma/client";
44

55
const connectionString = `${process.env.DATABASE_URL}`;
66

server/src/router/admin.ts

Lines changed: 72 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,38 @@
11
import express from 'express';
22
import { v4 as uuid } from 'uuid';
3-
import * as db from './common';
4-
import { Admin } from '../models/admin';
3+
import { prisma } from '../db/prisma';
4+
import { AdminRole } from '../../generated/prisma/client';
55
import { validateUser, checkNetIDExists, checkNetIDExistsForOtherEmployee } from '../util';
6-
import { UserType } from '../models/subscription';
76

87
const router = express.Router();
9-
const tableName = 'Admins';
108

119
// Get an admin
12-
router.get('/:id', validateUser('Admin'), (req, res) => {
13-
const {
14-
params: { id },
15-
} = req;
16-
db.getById(res, Admin, id, tableName);
10+
router.get('/:id', validateUser('Admin'), async (req, res) => {
11+
try {
12+
const { id } = req.params;
13+
const admin = await prisma.admin.findUnique({ where: { id } });
14+
if (!admin) {
15+
return res.status(400).send({ err: 'id not found in Admins' });
16+
}
17+
res.status(200).json({ data: admin });
18+
} catch (error) {
19+
console.error('Error fetching admin:', error);
20+
res.status(500).send({ err: 'Failed to fetch admin' });
21+
}
1722
});
1823

1924
// Get all admins
20-
router.get('/', validateUser('Admin'), (req, res) => {
21-
db.getAll(res, Admin, tableName);
25+
router.get('/', validateUser('Admin'), async (req, res) => {
26+
try {
27+
const admins = await prisma.admin.findMany();
28+
res.status(200).send({ data: admins });
29+
} catch (error) {
30+
console.error('Error fetching admins:', error);
31+
res.status(500).send({ err: 'Failed to fetch admins' });
32+
}
2233
});
2334

35+
2436
// Put a driver in Admins table
2537
router.post('/', validateUser('Admin'), async (req, res) => {
2638
try {
@@ -33,17 +45,27 @@ router.post('/', validateUser('Admin'), async (req, res) => {
3345
});
3446
}
3547

36-
const admin = new Admin({
37-
id: !body.eid || body.eid === '' ? uuid() : body.eid,
38-
firstName: body.firstName,
39-
lastName: body.lastName,
40-
type: body.type,
41-
isDriver: body.isDriver,
42-
phoneNumber: body.phoneNumber,
43-
email: body.email,
48+
const rolesInput = body.type || body.roles || [];
49+
const roles = Array.isArray(rolesInput)
50+
? rolesInput
51+
.map((r: string) => r.toUpperCase().replace(/\s+/g, '_'))
52+
.filter((r: string) => r === 'SDS_ADMIN' || r === 'REDRUNNER_ADMIN')
53+
: [];
54+
55+
const admin = await prisma.admin.create({
56+
data: {
57+
id: !body.eid || body.eid === '' ? uuid() : body.eid,
58+
firstName: body.firstName,
59+
lastName: body.lastName,
60+
roles: roles as AdminRole[],
61+
isDriver: body.isDriver || false,
62+
phoneNumber: body.phoneNumber,
63+
email: body.email,
64+
photoLink: body.photoLink || null,
65+
},
4466
});
4567

46-
db.create(res, admin);
68+
res.status(200).send({ data: admin });
4769
} catch (error) {
4870
console.error('Error creating admin:', error);
4971
res.status(500).send({ err: 'Failed to create admin' });
@@ -53,12 +75,9 @@ router.post('/', validateUser('Admin'), async (req, res) => {
5375
// Update an existing admin
5476
router.put('/:id', validateUser('Admin'), async (req, res) => {
5577
try {
56-
const {
57-
params: { id },
58-
body,
59-
} = req;
78+
const { id } = req.params;
79+
const { body } = req;
6080

61-
// Check if email is being changed and if it conflicts with another employee
6281
if (body.email) {
6382
const emailExists = await checkNetIDExistsForOtherEmployee(body.email, id);
6483
if (emailExists) {
@@ -68,19 +87,40 @@ router.put('/:id', validateUser('Admin'), async (req, res) => {
6887
}
6988
}
7089

71-
db.update(res, Admin, { id }, body, tableName);
72-
} catch (error) {
90+
if (body.type || body.roles) {
91+
const roles = body.type || body.roles;
92+
body.roles = Array.isArray(roles) ? roles.map((r: string) => r.toUpperCase() as AdminRole) : roles;
93+
delete body.type;
94+
}
95+
96+
const admin = await prisma.admin.update({
97+
where: { id },
98+
data: body,
99+
});
100+
101+
res.status(200).send({ data: admin });
102+
} catch (error: any) {
103+
if (error.code === 'P2025') {
104+
return res.status(400).send({ err: 'id not found in Admins' });
105+
}
73106
console.error('Error updating admin:', error);
74107
res.status(500).send({ err: 'Failed to update admin' });
75108
}
76109
});
77110

78111
// Remove an admin
79-
router.delete('/:id', validateUser('Admin'), (req, res) => {
80-
const {
81-
params: { id },
82-
} = req;
83-
db.deleteById(res, Admin, id, tableName);
112+
router.delete('/:id', validateUser('Admin'), async (req, res) => {
113+
try {
114+
const { id } = req.params;
115+
await prisma.admin.delete({ where: { id } });
116+
res.status(200).send({ id });
117+
} catch (error: any) {
118+
if (error.code === 'P2025') {
119+
return res.status(400).send({ err: 'id not found in Admins' });
120+
}
121+
console.error('Error deleting admin:', error);
122+
res.status(500).send({ err: 'Failed to delete admin' });
123+
}
84124
});
85125

86126
export default router;

server/src/router/auth.ts

Lines changed: 47 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
import express from 'express';
22
import * as jwt from 'jsonwebtoken';
3-
import { Rider } from '../models/rider';
4-
import { Admin } from '../models/admin';
5-
import { Driver } from '../models/driver';
3+
import { prisma } from '../db/prisma';
64
import { OAuth2Client } from 'google-auth-library';
75
import { oauthValues } from '../config';
8-
import { ModelType } from 'dynamoose/dist/General';
9-
import { Item } from 'dynamoose/dist/Item';
106
import { UnregisteredUserType } from '@carriage-web/shared/types';
117

128
const router = express.Router();
@@ -22,19 +18,6 @@ const audience = [
2218
'241748771473-7rfda2grc8f7p099bmf98en0q9bcvp18.apps.googleusercontent.com',
2319
];
2420

25-
/**
26-
* Returns the appropriate model (Rider, Driver, Admin) for a given table name.
27-
* @param table - The string name of the table (e.g., 'Riders', 'Drivers', 'Admins').
28-
*/
29-
function getModel(table: string) {
30-
const tableToModel: { [table: string]: ModelType<Item> } = {
31-
Riders: Rider,
32-
Drivers: Driver,
33-
Admins: Admin,
34-
};
35-
return tableToModel[table];
36-
}
37-
3821
/**
3922
* Derives the singular user type from the table name.
4023
* For example, 'Riders' becomes 'Rider'.
@@ -45,79 +28,48 @@ function getUserType(table: string) {
4528
}
4629

4730
/**
48-
* Finds a user in the specified model by email and sends back a JWT token if found.
31+
* Finds a user in Prisma by email and sends back a JWT token if found.
4932
* If logging in as an Admin and no match is found, the Driver table is checked as a fallback for admin-flagged users.
5033
* @param res - Express response object.
51-
* @param model - The model to query (Rider, Admin, or Driver).
5234
* @param table - Name of the user table (used to derive userType).
5335
* @param email - The email address to look up.
5436
* @param userInfo - Optional user info from Google OAuth (name, etc.).
5537
*/
56-
function findUserAndSendToken(
38+
async function findUserAndSendToken(
5739
res: express.Response,
58-
model: ModelType<Item>,
5940
table: string,
6041
email: string,
6142
userInfo?: Partial<UnregisteredUserType>
6243
) {
63-
model.scan({ email: { eq: email } }).exec((err, data) => {
64-
if (err) {
65-
res.status(err.statusCode || 500).send({ err: err.message });
66-
return;
67-
}
44+
try {
45+
let user: any = null;
6846

69-
if (data?.length) {
70-
const { id, active } = data[0].toJSON();
71-
if (table === 'Riders' && !active) {
47+
if (table === 'Riders') {
48+
user = await prisma.rider.findUnique({ where: { email } });
49+
if (user && !user.active) {
7250
res.status(400).send({ err: 'User not active' });
7351
return;
7452
}
53+
} else if (table === 'Drivers') {
54+
user = await prisma.driver.findUnique({ where: { email } });
55+
} else if (table === 'Admins') {
56+
user = await prisma.admin.findUnique({ where: { email } });
57+
58+
// Fallback: Check drivers table for admins
59+
if (!user) {
60+
const driver = await prisma.driver.findUnique({ where: { email } });
61+
if (driver) {
62+
user = driver;
63+
}
64+
}
65+
}
66+
67+
if (user) {
7568
const userPayload = {
76-
id,
69+
id: user.id,
7770
userType: getUserType(table),
7871
};
79-
res
80-
.status(200)
81-
.send({ jwt: jwt.sign(userPayload, process.env.JWT_SECRET!) });
82-
} else if (table === 'Admins') {
83-
// Check drivers table for admins
84-
// when the frontend page is made, this removed and we only use the first scan and change the error handling to check
85-
// per table this is because we would have decoupled admins and drivers, so drivers wouldnt sign on admin page and vice versa
86-
// but maybe we would allow admins to log onto the driver page?
87-
Driver.scan({ email: { eq: email } }).exec((dErr, dData) => {
88-
if (dErr) {
89-
res.status(dErr.statusCode || 500).send({ err: dErr });
90-
} else if (dData?.length) {
91-
const { id, admin } = dData[0].toJSON();
92-
if (admin) {
93-
const userPayload = {
94-
id,
95-
userType: getUserType(table),
96-
};
97-
res
98-
.status(200)
99-
.send({ jwt: jwt.sign(userPayload, process.env.JWT_SECRET!) });
100-
} else {
101-
const unregisteredUser: UnregisteredUserType = {
102-
email: email,
103-
name: userInfo?.name || 'User',
104-
};
105-
res.status(400).send({
106-
err: 'User not found',
107-
user: unregisteredUser,
108-
});
109-
}
110-
} else {
111-
const unregisteredUser: UnregisteredUserType = {
112-
email: email,
113-
name: userInfo?.name || 'User',
114-
};
115-
res.status(400).send({
116-
err: 'User not found',
117-
user: unregisteredUser,
118-
});
119-
}
120-
});
72+
res.status(200).send({ jwt: jwt.sign(userPayload, process.env.JWT_SECRET!) });
12173
} else {
12274
const unregisteredUser: UnregisteredUserType = {
12375
email: email,
@@ -128,7 +80,10 @@ function findUserAndSendToken(
12880
user: unregisteredUser,
12981
});
13082
}
131-
});
83+
} catch (error) {
84+
console.error('Error finding user:', error);
85+
res.status(500).send({ err: 'Internal server error' });
86+
}
13287
}
13388

13489
/**
@@ -148,6 +103,12 @@ async function getIdToken(client: OAuth2Client, code: string) {
148103
router.post('/', async (req, res) => {
149104
const { code, table } = req.body;
150105
try {
106+
const validTables = ['Riders', 'Drivers', 'Admins'];
107+
if (!validTables.includes(table)) {
108+
res.status(400).send({ err: 'Table not found' });
109+
return;
110+
}
111+
151112
const client = new OAuth2Client({
152113
clientId: oauthValues.client_id,
153114
clientSecret: oauthValues.client_secret,
@@ -158,15 +119,11 @@ router.post('/', async (req, res) => {
158119
const payload = result.getPayload();
159120
const email = payload?.email;
160121
const name = payload?.name;
161-
const model = getModel(table);
162-
if (model && email) {
163-
findUserAndSendToken(res, model, table, email, { name });
164-
} else if (!model) {
165-
res.status(400).send({ err: 'Table not found' });
166-
} else if (!email) {
167-
res.status(400).send({ err: 'Email not found' });
122+
123+
if (email) {
124+
await findUserAndSendToken(res, table, email, { name });
168125
} else {
169-
res.status(400).send({ err: 'Payload not found' });
126+
res.status(400).send({ err: 'Email not found' });
170127
}
171128
} catch (err) {
172129
console.log(err);
@@ -178,15 +135,16 @@ if (process.env.NODE_ENV === 'test') {
178135
router.post('/dummy', async (req, res) => {
179136
const { email, table } = req.body;
180137
try {
181-
const model = getModel(table);
182-
if (model && email) {
183-
findUserAndSendToken(res, model, table, email, { name: email });
184-
} else if (!model) {
138+
const validTables = ['Riders', 'Drivers', 'Admins'];
139+
if (!validTables.includes(table)) {
185140
res.status(400).send({ err: 'Table not found' });
186-
} else if (!email) {
187-
res.status(400).send({ err: 'Email not found' });
141+
return;
142+
}
143+
144+
if (email) {
145+
await findUserAndSendToken(res, table, email, { name: email });
188146
} else {
189-
res.status(400).send({ err: 'Payload not found' });
147+
res.status(400).send({ err: 'Email not found' });
190148
}
191149
} catch (err) {
192150
console.log(err);

0 commit comments

Comments
 (0)