1+ import db from '@codebuff/common/db'
2+ import * as schema from '@codebuff/common/db/schema'
13import { utils } from '@codebuff/internal'
4+ import { eq } from 'drizzle-orm'
25
36import { extractAuthTokenFromHeader } from './auth-helpers'
4- import { getUserInfoFromApiKey } from '../websockets/auth'
57
68import type { ServerAction } from '@codebuff/common/actions'
7- import type { GetUserInfoFromApiKeyFn } from '@codebuff/common/types/contracts/database'
89import type { Logger } from '@codebuff/common/types/contracts/logger'
910import type { Request , Response , NextFunction } from 'express'
1011
1112export const checkAuth = async ( params : {
13+ fingerprintId ?: string
1214 authToken ?: string
1315 clientSessionId : string
14- getUserInfoFromApiKey : GetUserInfoFromApiKeyFn
1516 logger : Logger
1617} ) : Promise < void | ServerAction > => {
17- const { authToken, clientSessionId, getUserInfoFromApiKey, logger } = params
18-
18+ const { fingerprintId, authToken, clientSessionId, logger } = params
1919 // Use shared auth check functionality
20- const authResult = authToken
21- ? await getUserInfoFromApiKey ( {
22- apiKey : authToken ,
23- fields : [ 'id' ] ,
24- } )
25- : null
20+ const authResult = await utils . checkAuthToken ( {
21+ fingerprintId,
22+ authToken,
23+ } )
2624
27- if ( ! authResult ) {
28- const errorMessage = 'Authentication failed'
25+ if ( ! authResult . success ) {
26+ const errorMessage = authResult . error ?. message || 'Authentication failed'
2927 logger . error ( { clientSessionId, error : errorMessage } , errorMessage )
3028 return {
3129 type : 'action-error' ,
@@ -45,44 +43,65 @@ export const checkAuth = async (params: {
4543}
4644
4745// Express middleware for checking admin access
48- export const checkAdmin =
49- ( logger : Logger ) =>
50- async ( req : Request , res : Response , next : NextFunction ) => {
51- // Extract auth token from x-codebuff-api-key header
52- const authToken = extractAuthTokenFromHeader ( req )
53- if ( ! authToken ) {
54- return res
55- . status ( 401 )
56- . json ( { error : 'Missing x-codebuff-api-key header' } )
57- }
46+ export const checkAdmin = ( logger : Logger ) => async (
47+ req : Request ,
48+ res : Response ,
49+ next : NextFunction ,
50+ ) => {
51+ // Extract auth token from x-codebuff-api-key header
52+ const authToken = extractAuthTokenFromHeader ( req )
53+ if ( ! authToken ) {
54+ return res . status ( 401 ) . json ( { error : 'Missing x-codebuff-api-key header' } )
55+ }
5856
59- // Generate a client session ID for this request
60- const clientSessionId = `admin-relabel-${ Date . now ( ) } `
57+ // Generate a client session ID for this request
58+ const clientSessionId = `admin-relabel-${ Date . now ( ) } `
6159
62- // Check authentication
63- const user = await getUserInfoFromApiKey ( {
64- apiKey : authToken ,
65- fields : [ 'id' , 'email' ] ,
66- } )
60+ // Check authentication
61+ const authResult = await checkAuth ( {
62+ authToken,
63+ clientSessionId,
64+ logger,
65+ } )
6766
68- if ( ! user ) {
69- return res . status ( 401 ) . json ( { error : 'Invalid session' } )
70- }
67+ if ( authResult ) {
68+ // checkAuth returns an error action if auth fails
69+ const errorMessage =
70+ authResult . type === 'action-error'
71+ ? authResult . message
72+ : 'Authentication failed'
73+ return res . status ( 401 ) . json ( { error : errorMessage } )
74+ }
7175
72- // Check if user has admin access using shared utility
73- const adminUser = await utils . checkUserIsCodebuffAdmin ( user . id )
74- if ( ! adminUser ) {
75- logger . warn (
76- { userId : user . id , email : user . email , clientSessionId } ,
77- 'Unauthorized access attempt to admin endpoint' ,
78- )
79- return res . status ( 403 ) . json ( { error : 'Forbidden' } )
80- }
76+ // Get the user ID associated with this session token
77+ const user = await db
78+ . select ( {
79+ id : schema . user . id ,
80+ email : schema . user . email ,
81+ } )
82+ . from ( schema . user )
83+ . innerJoin ( schema . session , eq ( schema . user . id , schema . session . userId ) )
84+ . where ( eq ( schema . session . sessionToken , authToken ) )
85+ . then ( ( users ) => users [ 0 ] )
8186
82- // Store user info in request for handlers to use if needed
83- // req.user = adminUser // TODO: ensure type check passes
87+ if ( ! user ) {
88+ return res . status ( 401 ) . json ( { error : 'Invalid session' } )
89+ }
8490
85- // Auth passed and user is admin, proceed to next middleware
86- next ( )
87- return
91+ // Check if user has admin access using shared utility
92+ const adminUser = await utils . checkUserIsCodebuffAdmin ( user . id )
93+ if ( ! adminUser ) {
94+ logger . warn (
95+ { userId : user . id , email : user . email , clientSessionId } ,
96+ 'Unauthorized access attempt to admin endpoint' ,
97+ )
98+ return res . status ( 403 ) . json ( { error : 'Forbidden' } )
8899 }
100+
101+ // Store user info in request for handlers to use if needed
102+ // req.user = adminUser // TODO: ensure type check passes
103+
104+ // Auth passed and user is admin, proceed to next middleware
105+ next ( )
106+ return
107+ }
0 commit comments