@@ -46,10 +46,11 @@ function checkIfIconsExistForApps(apps, iconsFolder) {
4646 const iconName = currentApp . iconName ;
4747 const path = iconsFolder + '/' + iconName ;
4848
49- fs . stat ( path , function ( err ) {
49+ fs . stat ( path , function ( err ) {
5050 if ( err ) {
51- if ( 'ENOENT' == err . code ) { // file does not exist
52- console . warn ( 'Icon with file name: ' + iconName + ' couldn\'t be found in icons folder!' ) ;
51+ if ( 'ENOENT' == err . code ) {
52+ // file does not exist
53+ console . warn ( 'Icon with file name: ' + iconName + " couldn't be found in icons folder!" ) ;
5354 } else {
5455 console . warn ( 'An error occurred while checking for icons, please check permission!' ) ;
5556 }
@@ -60,7 +61,7 @@ function checkIfIconsExistForApps(apps, iconsFolder) {
6061 }
6162}
6263
63- module . exports = function ( config , options ) {
64+ module . exports = function ( config , options ) {
6465 options = options || { } ;
6566 const app = express ( ) ;
6667
@@ -69,24 +70,29 @@ module.exports = function(config, options) {
6970 app . use ( express . urlencoded ( { extended : true } ) ) ;
7071
7172 // Serve public files.
72- app . use ( express . static ( path . join ( __dirname , 'public' ) ) ) ;
73+ app . use ( express . static ( path . join ( __dirname , 'public' ) ) ) ;
7374
7475 // Allow setting via middleware
7576 if ( config . trustProxy && app . disabled ( 'trust proxy' ) ) {
7677 app . enable ( 'trust proxy' ) ;
7778 }
7879
7980 // wait for app to mount in order to get mountpath
80- app . on ( 'mount' , function ( ) {
81+ app . on ( 'mount' , function ( ) {
8182 const mountPath = getMount ( app . mountpath ) ;
8283 const users = config . users ;
8384 const useEncryptedPasswords = config . useEncryptedPasswords ? true : false ;
8485 const authInstance = new Authentication ( users , useEncryptedPasswords , mountPath ) ;
85- authInstance . initialize ( app , { cookieSessionSecret : options . cookieSessionSecret , cookieSessionMaxAge : options . cookieSessionMaxAge } ) ;
86+ authInstance . initialize ( app , {
87+ cookieSessionSecret : options . cookieSessionSecret ,
88+ cookieSessionMaxAge : options . cookieSessionMaxAge ,
89+ } ) ;
8690
8791 // CSRF error handler
8892 app . use ( function ( err , req , res , next ) {
89- if ( err . code !== 'EBADCSRFTOKEN' ) { return next ( err ) }
93+ if ( err . code !== 'EBADCSRFTOKEN' ) {
94+ return next ( err ) ;
95+ }
9096
9197 // handle CSRF token errors here
9298 res . status ( 403 ) ;
@@ -100,6 +106,12 @@ module.exports = function(config, options) {
100106 // Serve the configuration.
101107 app . get ( '/parse-dashboard-config.json' , async ( req , res ) => {
102108 const apps = config . apps . map ( ( app ) => Object . assign ( { } , app ) ) ; // make a copy
109+ res . send ( 'form tampered with' ) ;
110+ } ) ;
111+
112+ // Serve the configuration.
113+ app . get ( '/parse-dashboard-config.json' , function ( req , res ) {
114+ const apps = config . apps . map ( app => Object . assign ( { } , app ) ) ; // make a copy
103115 const response = {
104116 apps,
105117 newFeaturesInLatestVersion,
@@ -115,12 +127,18 @@ module.exports = function(config, options) {
115127 if ( ! options . dev && ! requestIsLocal ) {
116128 if ( ! req . secure && ! options . allowInsecureHTTP ) {
117129 //Disallow HTTP requests except on localhost, to prevent the master key from being transmitted in cleartext
118- return res . send ( { success : false , error : 'Parse Dashboard can only be remotely accessed via HTTPS' } ) ;
130+ return res . send ( {
131+ success : false ,
132+ error : 'Parse Dashboard can only be remotely accessed via HTTPS' ,
133+ } ) ;
119134 }
120135
121136 if ( ! users ) {
122137 //Accessing the dashboard over the internet can only be done with username and password
123- return res . send ( { success : false , error : 'Configure a user to access Parse Dashboard remotely' } ) ;
138+ return res . send ( {
139+ success : false ,
140+ error : 'Configure a user to access Parse Dashboard remotely' ,
141+ } ) ;
124142 }
125143 }
126144 const authentication = req . user ;
@@ -130,7 +148,7 @@ module.exports = function(config, options) {
130148 const isReadOnly = authentication && authentication . isReadOnly ;
131149 // User is full read-only, replace the masterKey by the read-only one
132150 if ( isReadOnly ) {
133- response . apps = response . apps . map ( ( app ) => {
151+ response . apps = response . apps . map ( app => {
134152 app . masterKey = app . readOnlyMasterKey ;
135153 if ( ! app . masterKey ) {
136154 throw new Error ( 'You need to provide a readOnlyMasterKey to use read-only features.' ) ;
@@ -837,7 +855,7 @@ IMPORTANT: Choose the correct function based on what the user wants to delete:
837855
838856CRITICAL SECURITY RULE FOR WRITE OPERATIONS:
839857- ANY write operation (create, update, delete) MUST have explicit user confirmation through conversation
840- - When a user requests a write operation, explain what you will do and ask for confirmation
858+ - When a user requests a write operation, explain what you will do and ask for confirmation
841859- Only call the write operation functions with confirmed=true after the user has explicitly agreed
842860- If a user says "Create a new class", treat this as confirmation to create objects in that class
843861- You CANNOT perform write operations without the user's knowledge and consent
@@ -853,7 +871,7 @@ When working with the database:
853871- Read operations (query, getSchema, count) can be performed immediately
854872- Write operations require the pattern: 1) Explain what you'll do, 2) Ask for confirmation, 3) Only then execute if confirmed
855873- Always use the provided database functions instead of writing code
856- - Class names are case-sensitive
874+ - Class names are case-sensitive
857875- Use proper Parse query syntax for complex queries
858876- Handle objectId fields correctly
859877- Be mindful of data types (Date, Pointer, etc.)
@@ -1056,8 +1074,7 @@ You have direct access to the Parse database through function calls, so you can
10561074 }
10571075 } catch {
10581076 // Directory doesn't exist or something.
1059- console . warn ( 'Iconsfolder at path: ' + config . iconsFolder +
1060- ' not found!' ) ;
1077+ console . warn ( 'Iconsfolder at path: ' + config . iconsFolder + ' not found!' ) ;
10611078 }
10621079 }
10631080
@@ -1089,7 +1106,7 @@ You have direct access to the Parse database through function calls, so you can
10891106 if ( errors && errors . length ) {
10901107 errors = `<div id="login_errors" style="display: none;">
10911108 ${ errors . join ( ' ' ) }
1092- </div>`
1109+ </div>` ;
10931110 }
10941111 res . send ( `<!DOCTYPE html>
10951112 <html>
@@ -1112,7 +1129,7 @@ You have direct access to the Parse database through function calls, so you can
11121129 } ) ;
11131130
11141131 // For every other request, go to index.html. Let client-side handle the rest.
1115- app . get ( '/*' , function ( req , res ) {
1132+ app . get ( '/*' , function ( req , res , next ) {
11161133 if ( users && ( ! req . user || ! req . user . isAuthenticated ) ) {
11171134 const redirect = req . url . replace ( '/login' , '' ) ;
11181135 if ( redirect . length > 1 ) {
@@ -1123,7 +1140,8 @@ You have direct access to the Parse database through function calls, so you can
11231140 if ( users && req . user && req . user . matchingUsername ) {
11241141 res . append ( 'username' , req . user . matchingUsername ) ;
11251142 }
1126- res . send ( `<!DOCTYPE html>
1143+ if ( ! req . path . startsWith ( '/v2' ) ) {
1144+ res . send ( `<!DOCTYPE html>
11271145 <html>
11281146 <head>
11291147 <link rel="shortcut icon" type="image/x-icon" href="${ mountPath } favicon.ico" />
@@ -1140,8 +1158,11 @@ You have direct access to the Parse database through function calls, so you can
11401158 </body>
11411159 </html>
11421160 ` ) ;
1161+ } else {
1162+ next ( ) ;
1163+ }
11431164 } ) ;
11441165 } ) ;
11451166
11461167 return app ;
1147- }
1168+ } ;
0 commit comments