11import express from 'express' ;
22import * 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' ;
64import { OAuth2Client } from 'google-auth-library' ;
75import { oauthValues } from '../config' ;
8- import { ModelType } from 'dynamoose/dist/General' ;
9- import { Item } from 'dynamoose/dist/Item' ;
106import { UnregisteredUserType } from '@carriage-web/shared/types' ;
117
128const 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) {
148103router . 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