@@ -570,6 +570,44 @@ module.exports.createCollection = async (req, res) => {
570570 }
571571} ;
572572
573+ // GET DOC BY ID
574+ module . exports . getData = async ( req , res ) => {
575+ try {
576+ const { projectId, collectionName } = req . params ;
577+ const project = await Project . findOne ( { _id : projectId , owner : req . user . _id } ) ;
578+ if ( ! project ) return res . status ( 404 ) . json ( { error : "Project not found." } ) ;
579+
580+ const collectionConfig = project . collections . find ( c => c . name === collectionName ) ;
581+ if ( ! collectionConfig ) {
582+ return res . status ( 404 ) . json ( {
583+ error : "Collection not found" ,
584+ collection : collectionName
585+ } ) ;
586+ }
587+
588+ const connection = await getConnection ( projectId ) ;
589+ const model = getCompiledModel ( connection , collectionConfig , projectId , project . resources . db . isExternal ) ;
590+
591+ // const collectionsList = await mongoose.connection.db.listCollections({ name: finalCollectionName }).toArray();
592+
593+ const query = model . find ( ) ;
594+ if ( collectionName === 'users' ) {
595+ query . select ( '-password' ) ;
596+ }
597+
598+ const features = new QueryEngine ( query , req . query )
599+ . filter ( )
600+ . sort ( )
601+ . paginate ( ) ;
602+
603+ const data = await features . query . lean ( ) ;
604+
605+ res . json ( data ) ;
606+ } catch ( err ) {
607+ res . status ( 500 ) . json ( { error : err . message } ) ;
608+ }
609+ }
610+
573611module . exports . deleteCollection = async ( req , res ) => {
574612 try {
575613 const { projectId, collectionName } = req . params ;
@@ -1253,3 +1291,76 @@ module.exports.toggleAuth = async (req, res) => {
12531291 res . status ( 500 ) . json ( { error : err . message } ) ;
12541292 }
12551293} ;
1294+
1295+
1296+ // PATCH FOR UPDATING COLLECTION RLS
1297+ module . exports . updateCollectionRls = async ( req , res ) => {
1298+ try {
1299+ const { projectId, collectionName } = req . params ;
1300+ const { enabled, mode, ownerField, requireAuthForWrite } = req . body || { } ;
1301+
1302+ const project = await Project . findOne ( { _id : projectId , owner : req . user . _id } ) ;
1303+ if ( ! project ) return res . status ( 404 ) . json ( { error : "Project not found" } ) ;
1304+
1305+ const collection = project . collections . find ( c => c . name === collectionName ) ;
1306+ if ( ! collection ) return res . status ( 404 ) . json ( { error : "Collection not found" } ) ;
1307+
1308+ const validMode = mode || collection ?. rls ?. mode || 'owner-write-only' ;
1309+ if ( validMode !== 'owner-write-only' ) {
1310+ return res . status ( 400 ) . json ( { error : "Unsupported RLS mode. Only 'owner-write-only' is allowed in V1." } ) ;
1311+ }
1312+
1313+ const modelKeys = ( collection . model || [ ] )
1314+ . map ( f => String ( f ?. key || '' ) . trim ( ) )
1315+ . filter ( Boolean ) ;
1316+ const modelKeySet = new Set ( modelKeys ) ;
1317+ const modelKeyLowerMap = new Map ( modelKeys . map ( k => [ k . toLowerCase ( ) , k ] ) ) ;
1318+
1319+ const requestedOwnerRaw = String ( ownerField ?? collection ?. rls ?. ownerField ?? 'userId' ) . trim ( ) ;
1320+ const requestedOwnerLower = requestedOwnerRaw . toLowerCase ( ) ;
1321+ const canonicalOwnerField = modelKeySet . has ( requestedOwnerRaw )
1322+ ? requestedOwnerRaw
1323+ : modelKeyLowerMap . get ( requestedOwnerLower ) ;
1324+ const nextOwnerField = requestedOwnerRaw === '_id' ? '_id' : ( canonicalOwnerField || requestedOwnerRaw ) ;
1325+
1326+ if ( nextOwnerField !== '_id' && ! modelKeySet . has ( nextOwnerField ) ) {
1327+ return res . status ( 400 ) . json ( {
1328+ error : "Invalid owner field" ,
1329+ message : `ownerField '${ nextOwnerField } ' not found in collection schema`
1330+ } ) ;
1331+ }
1332+
1333+ // Restrict use of '_id' as ownerField to the 'users' collection only.
1334+ if ( nextOwnerField === '_id' && collection . name !== 'users' ) {
1335+ return res . status ( 400 ) . json ( {
1336+ error : "Invalid owner field" ,
1337+ message : "ownerField '_id' is only allowed for the 'users' collection"
1338+ } ) ;
1339+ }
1340+
1341+ collection . rls = {
1342+ enabled : typeof enabled === 'boolean' ? enabled : ! ! collection ?. rls ?. enabled ,
1343+ mode : validMode ,
1344+ ownerField : nextOwnerField ,
1345+ requireAuthForWrite : typeof requireAuthForWrite === 'boolean'
1346+ ? requireAuthForWrite
1347+ : ( collection ?. rls ?. requireAuthForWrite ?? true )
1348+ } ;
1349+
1350+ await project . save ( ) ;
1351+
1352+ await deleteProjectById ( projectId ) ;
1353+ await deleteProjectByApiKeyCache ( project . publishableKey ) ;
1354+ await deleteProjectByApiKeyCache ( project . secretKey ) ;
1355+
1356+ res . json ( {
1357+ message : "Collection RLS updated" ,
1358+ collection : {
1359+ name : collection . name ,
1360+ rls : collection . rls
1361+ }
1362+ } ) ;
1363+ } catch ( err ) {
1364+ res . status ( 500 ) . json ( { error : err . message } ) ;
1365+ }
1366+ }
0 commit comments