@@ -10,36 +10,51 @@ import { toApi as toApiProjectObject } from '../../domain-objects/Project';
1010const createCoreHandler = ( mapProjectsToResponse ) => async ( req , res ) => {
1111 try {
1212 const { username } = req . params ;
13- const { page, limit } = req . query ;
13+ const { page, limit, sortField , sortDir , q } = req . query ;
1414
1515 if ( ! username ) {
16- res . status ( 422 ) . json ( { message : 'Username not provided' } ) ;
17- return ;
16+ return res . status ( 422 ) . json ( { message : 'Username not provided' } ) ;
1817 }
1918
2019 const user = await User . findByUsername ( username ) ;
2120
2221 if ( ! user ) {
23- res
22+ return res
2423 . status ( 404 )
2524 . json ( { message : 'User with that username does not exist.' } ) ;
26- return ;
2725 }
2826
2927 const canViewPrivate = req . user && req . user . _id . equals ( user . _id ) ;
30-
3128 const filter = { user : user . _id } ;
29+
3230 if ( ! canViewPrivate ) {
3331 filter . visibility = { $ne : 'Private' } ;
3432 }
3533
34+ if ( q && q . trim ( ) ) {
35+ const term = q . trim ( ) ;
36+ const escaped = term . replace ( / [ . * + ? ^ $ { } ( ) | [ \] \\ ] / g, '\\$&' ) ;
37+
38+ filter . name = { $regex : escaped , $options : 'i' } ;
39+ }
40+
3641 const usePagination = page !== undefined && limit !== undefined ;
3742
3843 const parsedPage = Math . max ( parseInt ( page , 10 ) || 1 , 1 ) ;
3944 const parsedLimit = Math . min ( Math . max ( parseInt ( limit , 10 ) || 10 , 1 ) , 100 ) ;
45+ const dir = sortDir === 'desc' ? - 1 : 1 ;
46+ const allowedSortFields = new Set ( [
47+ 'name' ,
48+ 'createdAt' ,
49+ 'updatedAt' ,
50+ 'visibility'
51+ ] ) ;
52+ const safeSortField = allowedSortFields . has ( sortField )
53+ ? sortField
54+ : 'updatedAt' ;
4055
4156 const query = Project . find ( filter )
42- . sort ( '-createdAt' )
57+ . sort ( { [ safeSortField ] : dir , _id : dir } )
4358 . select ( 'name files id createdAt updatedAt visibility' ) ;
4459
4560 if ( usePagination ) {
@@ -56,18 +71,18 @@ const createCoreHandler = (mapProjectsToResponse) => async (req, res) => {
5671 projects : mapProjectsToResponse ( projects ) ,
5772 ...( usePagination && {
5873 metadata : {
59- currentPage : parsedPage || 1 ,
60- totalPages : Math . ceil ( totalProjects / parsedLimit ) || 1 ,
74+ page : parsedPage ,
75+ totalPages : Math . max ( Math . ceil ( totalProjects / parsedLimit ) , 1 ) ,
6176 totalProjects,
6277 limit : parsedLimit ,
6378 hasPagination : true
6479 }
6580 } )
6681 } ;
6782
68- res . json ( response ) ;
83+ return res . json ( response ) ;
6984 } catch ( error ) {
70- res . status ( 500 ) . json ( { message : 'Error fetching projects' } ) ;
85+ return res . status ( 500 ) . json ( { message : 'Error fetching projects' } ) ;
7186 }
7287} ;
7388
0 commit comments