@@ -4,11 +4,14 @@ const Project = require("../models/Project");
44const { getConnection } = require ( "../utils/connectionManager" ) ;
55const { getCompiledModel } = require ( "../utils/injectModel" ) ;
66
7+ // Helper: CodeQL ko satisfy karne ke liye ID validate karna zaroori hai
8+ const isValidId = ( id ) => mongoose . Types . ObjectId . isValid ( id ) ;
9+
710// 1. INSERT DATA
811module . exports . insertData = async ( req , res ) => {
912 try {
1013 const { collectionName } = req . params ;
11- const project = req . project ; // Middleware se mila project metadata
14+ const project = req . project ;
1215
1316 const collectionConfig = project . collections . find ( c => c . name === collectionName ) ;
1417 if ( ! collectionConfig ) return res . status ( 404 ) . json ( { error : "Collection not found" } ) ;
@@ -17,46 +20,47 @@ module.exports.insertData = async (req, res) => {
1720 const incomingData = req . body ;
1821 const cleanData = { } ;
1922
20- // Validation & Sanitization
2123 for ( const field of schemaRules ) {
22- if ( field . required && incomingData [ field . key ] === undefined ) {
24+ const value = incomingData [ field . key ] ;
25+
26+ if ( field . required && ( value === undefined || value === null ) ) {
2327 return res . status ( 400 ) . json ( { error : `Field '${ field . key } ' is required.` } ) ;
2428 }
25- if ( incomingData [ field . key ] !== undefined ) {
26- // Type Checks
27- if ( field . type === 'Number' && typeof incomingData [ field . key ] !== 'number' ) return res . status ( 400 ) . send ( `Field '${ field . key } ' must be a Number.` ) ;
28- if ( field . type === 'Boolean' && typeof incomingData [ field . key ] !== 'boolean' ) return res . status ( 400 ) . send ( `Field '${ field . key } ' must be a Boolean.` ) ;
29- cleanData [ field . key ] = incomingData [ field . key ] ;
29+
30+ if ( value !== undefined ) {
31+ // Strong Type Checks (Added String and Date)
32+ if ( field . type === 'Number' && typeof value !== 'number' ) return res . status ( 400 ) . json ( { error : `Field '${ field . key } ' must be a Number.` } ) ;
33+ if ( field . type === 'Boolean' && typeof value !== 'boolean' ) return res . status ( 400 ) . json ( { error : `Field '${ field . key } ' must be a Boolean.` } ) ;
34+ if ( field . type === 'String' && typeof value !== 'string' ) return res . status ( 400 ) . json ( { error : `Field '${ field . key } ' must be a String.` } ) ;
35+ if ( field . type === 'Date' && isNaN ( Date . parse ( value ) ) ) return res . status ( 400 ) . json ( { error : `Field '${ field . key } ' must be a valid Date.` } ) ;
36+
37+ cleanData [ field . key ] = value ;
3038 }
3139 }
3240
41+ // Sanitize removes MongoDB operators like $ne, $gt etc.
3342 const safeData = sanitize ( cleanData ) ;
34- Object . assign ( cleanData , safeData ) ;
3543
36- // Usage Limit Check (Internal Only)
3744 let docSize = 0 ;
3845 if ( ! project . isExternal ) {
39- docSize = Buffer . byteLength ( JSON . stringify ( cleanData ) ) ;
46+ docSize = Buffer . byteLength ( JSON . stringify ( safeData ) ) ;
4047 if ( ( project . databaseUsed || 0 ) + docSize > project . databaseLimit ) {
41- return res . status ( 403 ) . send ( "Database limit exceeded." ) ;
48+ return res . status ( 403 ) . json ( { error : "Database limit exceeded." } ) ;
4249 }
4350 }
4451
45- // Get Connection & Model
4652 const connection = await getConnection ( project . _id ) ;
4753 const Model = getCompiledModel ( connection , collectionConfig , project . _id , project . isExternal ) ;
4854
49- const result = await Model . create ( cleanData ) ;
55+ const result = await Model . create ( safeData ) ;
5056
51- // Update Project Metadata (Internal Only)
5257 if ( ! project . isExternal ) {
5358 project . databaseUsed = ( project . databaseUsed || 0 ) + docSize ;
5459 await project . save ( ) ;
5560 }
5661
5762 res . status ( 201 ) . json ( result ) ;
5863 } catch ( err ) {
59- console . error ( "Insert Error:" , err ) ;
6064 res . status ( 500 ) . json ( { error : err . message } ) ;
6165 }
6266} ;
@@ -73,10 +77,9 @@ module.exports.getAllData = async (req, res) => {
7377 const connection = await getConnection ( project . _id ) ;
7478 const Model = getCompiledModel ( connection , collectionConfig , project . _id , project . isExternal ) ;
7579
76- const data = await Model . find ( { } ) . limit ( 100 ) ;
80+ const data = await Model . find ( { } ) . limit ( 100 ) . lean ( ) ;
7781 res . json ( data ) ;
7882 } catch ( err ) {
79- console . log ( "error----------------" )
8083 res . status ( 500 ) . json ( { error : err . message } ) ;
8184 }
8285} ;
@@ -87,14 +90,17 @@ module.exports.getSingleDoc = async (req, res) => {
8790 const { collectionName, id } = req . params ;
8891 const project = req . project ;
8992
93+ // CodeQL Fix: User input ID ko pehle validate karo
94+ if ( ! isValidId ( id ) ) return res . status ( 400 ) . json ( { error : "Invalid ID format." } ) ;
95+
9096 const collectionConfig = project . collections . find ( c => c . name === collectionName ) ;
9197 if ( ! collectionConfig ) return res . status ( 404 ) . json ( { error : "Collection not found" } ) ;
9298
9399 const connection = await getConnection ( project . _id ) ;
94100 const Model = getCompiledModel ( connection , collectionConfig , project . _id , project . isExternal ) ;
95101
96- const doc = await Model . findById ( id ) ;
97- if ( ! doc ) return res . status ( 404 ) . send ( "Document not found." ) ;
102+ const doc = await Model . findById ( id ) . lean ( ) ;
103+ if ( ! doc ) return res . status ( 404 ) . json ( { error : "Document not found." } ) ;
98104
99105 res . json ( doc ) ;
100106 } catch ( err ) {
@@ -109,22 +115,33 @@ module.exports.updateSingleData = async (req, res) => {
109115 const project = req . project ;
110116 const incomingData = req . body ;
111117
118+ if ( ! isValidId ( id ) ) return res . status ( 400 ) . json ( { error : "Invalid ID format." } ) ;
119+
112120 const collectionConfig = project . collections . find ( c => c . name === collectionName ) ;
113121 if ( ! collectionConfig ) return res . status ( 404 ) . json ( { error : "Collection not found" } ) ;
114122
115123 const connection = await getConnection ( project . _id ) ;
116124 const Model = getCompiledModel ( connection , collectionConfig , project . _id , project . isExternal ) ;
117125
118- // Basic Schema Validation
126+ // Strict Schema Validation
119127 const schemaRules = collectionConfig . model ;
128+ const updateData = { } ;
120129 for ( const key in incomingData ) {
121130 const fieldRule = schemaRules . find ( f => f . key === key ) ;
122- if ( ! fieldRule ) return res . status ( 400 ) . send ( `Field '${ key } ' not in schema.` ) ;
123- // Type checks... (Number, Boolean etc.)
131+ if ( ! fieldRule ) continue ; // Unknown fields ko ignore karo
132+
133+ const value = incomingData [ key ] ;
134+ if ( fieldRule . type === 'Number' && typeof value !== 'number' ) return res . status ( 400 ) . json ( { error : `Field '${ key } ' must be a Number.` } ) ;
135+ if ( fieldRule . type === 'Boolean' && typeof value !== 'boolean' ) return res . status ( 400 ) . json ( { error : `Field '${ key } ' must be a Boolean.` } ) ;
136+ if ( fieldRule . type === 'String' && typeof value !== 'string' ) return res . status ( 400 ) . json ( { error : `Field '${ key } ' must be a String.` } ) ;
137+
138+ updateData [ key ] = value ;
124139 }
125140
126- const result = await Model . findByIdAndUpdate ( id , { $set : incomingData } , { new : true } ) ;
127- if ( ! result ) return res . status ( 404 ) . send ( "Document not found." ) ;
141+ const sanitizedData = sanitize ( updateData ) ;
142+
143+ const result = await Model . findByIdAndUpdate ( id , { $set : sanitizedData } , { new : true } ) . lean ( ) ;
144+ if ( ! result ) return res . status ( 404 ) . json ( { error : "Document not found." } ) ;
128145
129146 res . json ( { message : "Updated" , data : result } ) ;
130147 } catch ( err ) {
@@ -138,14 +155,16 @@ module.exports.deleteSingleDoc = async (req, res) => {
138155 const { collectionName, id } = req . params ;
139156 const project = req . project ;
140157
158+ if ( ! isValidId ( id ) ) return res . status ( 400 ) . json ( { error : "Invalid ID format." } ) ;
159+
141160 const collectionConfig = project . collections . find ( c => c . name === collectionName ) ;
142161 if ( ! collectionConfig ) return res . status ( 404 ) . json ( { error : "Collection not found" } ) ;
143162
144163 const connection = await getConnection ( project . _id ) ;
145164 const Model = getCompiledModel ( connection , collectionConfig , project . _id , project . isExternal ) ;
146165
147166 const docToDelete = await Model . findById ( id ) ;
148- if ( ! docToDelete ) return res . status ( 404 ) . send ( "Document not found." ) ;
167+ if ( ! docToDelete ) return res . status ( 404 ) . json ( { error : "Document not found." } ) ;
149168
150169 let docSize = 0 ;
151170 if ( ! project . isExternal ) {
0 commit comments