11import { defineEventHandler } from "h3"
2- import { eq , desc } from "drizzle-orm"
2+ import { eq , desc , max } from "drizzle-orm"
33import { db } from "../../db"
44import { oauthConsent , oauthClient , oauthAccessToken } from "../../db/schema/auth-schema"
55import { requireSession } from "../../lib/permissions"
@@ -25,20 +25,20 @@ export default defineEventHandler(async (event) => {
2525 . orderBy ( desc ( oauthConsent . createdAt ) )
2626
2727 // Last-used per client = latest access token's createdAt for that (user, client) pair.
28+ // One query: max(createdAt) per (userId, clientId). Scopes by userId so a
29+ // shared client_id between users doesn't leak each other's last-used.
30+ const lastUsedRows = await db
31+ . select ( {
32+ clientId : oauthAccessToken . clientId ,
33+ lastUsedAt : max ( oauthAccessToken . createdAt ) ,
34+ } )
35+ . from ( oauthAccessToken )
36+ . where ( eq ( oauthAccessToken . userId , session . userId ) )
37+ . groupBy ( oauthAccessToken . clientId )
38+
2839 const lastUsedByClient = new Map < string , Date > ( )
29- const lastUsedResults = await Promise . all (
30- consents . map ( ( c ) =>
31- db
32- . select ( { createdAt : oauthAccessToken . createdAt } )
33- . from ( oauthAccessToken )
34- . where ( eq ( oauthAccessToken . clientId , c . clientId ) )
35- . orderBy ( desc ( oauthAccessToken . createdAt ) )
36- . limit ( 1 )
37- . then ( ( rows ) => ( { clientId : c . clientId , createdAt : rows [ 0 ] ?. createdAt ?? null } ) ) ,
38- ) ,
39- )
40- for ( const r of lastUsedResults ) {
41- if ( r . createdAt ) lastUsedByClient . set ( r . clientId , r . createdAt )
40+ for ( const row of lastUsedRows ) {
41+ if ( row . lastUsedAt ) lastUsedByClient . set ( row . clientId , row . lastUsedAt )
4242 }
4343
4444 return {
0 commit comments