@@ -17,11 +17,8 @@ packageJson('parse-dashboard', 'latest').then(latestPackage => {
17
17
}
18
18
} ) ;
19
19
20
- function getMount ( req ) {
21
- let url = req . url ;
22
- let originalUrl = req . originalUrl ;
23
- var mountPathLength = req . originalUrl . length - req . url . length ;
24
- var mountPath = req . originalUrl . slice ( 0 , mountPathLength ) ;
20
+ function getMount ( mountPath ) {
21
+ mountPath = mountPath || '' ;
25
22
if ( ! mountPath . endsWith ( '/' ) ) {
26
23
mountPath += '/' ;
27
24
}
@@ -59,149 +56,152 @@ module.exports = function(config, allowInsecureHTTP) {
59
56
app . enable ( 'trust proxy' ) ;
60
57
}
61
58
62
- const users = config . users ;
63
- const useEncryptedPasswords = config . useEncryptedPasswords ? true : false ;
64
- const authInstance = new Authentication ( users , useEncryptedPasswords ) ;
65
- authInstance . initialize ( app ) ;
66
-
67
- // CSRF error handler
68
- app . use ( function ( err , req , res , next ) {
69
- if ( err . code !== 'EBADCSRFTOKEN' ) return next ( err )
70
-
71
- // handle CSRF token errors here
72
- res . status ( 403 )
73
- res . send ( 'form tampered with' )
74
- } ) ;
75
-
76
- // Serve the configuration.
77
- app . get ( '/parse-dashboard-config.json' , function ( req , res ) {
78
- let response = {
79
- apps : config . apps ,
80
- newFeaturesInLatestVersion : newFeaturesInLatestVersion ,
81
- } ;
82
-
83
- //Based on advice from Doug Wilson here:
84
- //https://github.com/expressjs/express/issues/2518
85
- const requestIsLocal =
86
- req . connection . remoteAddress === '127.0.0.1' ||
87
- req . connection . remoteAddress === '::ffff:127.0.0.1' ||
88
- req . connection . remoteAddress === '::1' ;
89
- if ( ! requestIsLocal && ! req . secure && ! allowInsecureHTTP ) {
90
- //Disallow HTTP requests except on localhost, to prevent the master key from being transmitted in cleartext
91
- return res . send ( { success : false , error : 'Parse Dashboard can only be remotely accessed via HTTPS' } ) ;
92
- }
59
+ // wait for app to mount in order to get mountpath
60
+ app . on ( 'mount' , function ( ) {
61
+ const mountPath = getMount ( app . mountpath ) ;
62
+ const users = config . users ;
63
+ const useEncryptedPasswords = config . useEncryptedPasswords ? true : false ;
64
+ const authInstance = new Authentication ( users , useEncryptedPasswords , mountPath ) ;
65
+ authInstance . initialize ( app ) ;
66
+
67
+ // CSRF error handler
68
+ app . use ( function ( err , req , res , next ) {
69
+ if ( err . code !== 'EBADCSRFTOKEN' ) return next ( err )
70
+
71
+ // handle CSRF token errors here
72
+ res . status ( 403 )
73
+ res . send ( 'form tampered with' )
74
+ } ) ;
93
75
94
- if ( ! requestIsLocal && ! users ) {
95
- //Accessing the dashboard over the internet can only be done with username and password
96
- return res . send ( { success : false , error : 'Configure a user to access Parse Dashboard remotely' } ) ;
97
- }
76
+ // Serve the configuration.
77
+ app . get ( '/parse-dashboard-config.json' , function ( req , res ) {
78
+ let response = {
79
+ apps : config . apps ,
80
+ newFeaturesInLatestVersion : newFeaturesInLatestVersion ,
81
+ } ;
82
+
83
+ //Based on advice from Doug Wilson here:
84
+ //https://github.com/expressjs/express/issues/2518
85
+ const requestIsLocal =
86
+ req . connection . remoteAddress === '127.0.0.1' ||
87
+ req . connection . remoteAddress === '::ffff:127.0.0.1' ||
88
+ req . connection . remoteAddress === '::1' ;
89
+ if ( ! requestIsLocal && ! req . secure && ! allowInsecureHTTP ) {
90
+ //Disallow HTTP requests except on localhost, to prevent the master key from being transmitted in cleartext
91
+ return res . send ( { success : false , error : 'Parse Dashboard can only be remotely accessed via HTTPS' } ) ;
92
+ }
98
93
99
- const authentication = req . user ;
94
+ if ( ! requestIsLocal && ! users ) {
95
+ //Accessing the dashboard over the internet can only be done with username and password
96
+ return res . send ( { success : false , error : 'Configure a user to access Parse Dashboard remotely' } ) ;
97
+ }
100
98
101
- const successfulAuth = authentication && authentication . isAuthenticated ;
102
- const appsUserHasAccess = authentication && authentication . appsUserHasAccessTo ;
99
+ const authentication = req . user ;
100
+
101
+ const successfulAuth = authentication && authentication . isAuthenticated ;
102
+ const appsUserHasAccess = authentication && authentication . appsUserHasAccessTo ;
103
+
104
+ if ( successfulAuth ) {
105
+ if ( appsUserHasAccess ) {
106
+ // Restric access to apps defined in user dictionary
107
+ // If they didn't supply any app id, user will access all apps
108
+ response . apps = response . apps . filter ( function ( app ) {
109
+ return appsUserHasAccess . find ( appUserHasAccess => {
110
+ return app . appId == appUserHasAccess . appId
111
+ } )
112
+ } ) ;
113
+ }
114
+ // They provided correct auth
115
+ return res . json ( response ) ;
116
+ }
103
117
104
- if ( successfulAuth ) {
105
- if ( appsUserHasAccess ) {
106
- // Restric access to apps defined in user dictionary
107
- // If they didn't supply any app id, user will access all apps
108
- response . apps = response . apps . filter ( function ( app ) {
109
- return appsUserHasAccess . find ( appUserHasAccess => {
110
- return app . appId == appUserHasAccess . appId
111
- } )
112
- } ) ;
118
+ if ( users ) {
119
+ //They provided incorrect auth
120
+ return res . sendStatus ( 401 ) ;
113
121
}
114
- // They provided correct auth
115
- return res . json ( response ) ;
116
- }
117
122
118
- if ( users ) {
119
- //They provided incorrect auth
120
- return res . sendStatus ( 401 ) ;
121
- }
123
+ //They didn't provide auth, and have configured the dashboard to not need auth
124
+ //(ie. didn't supply usernames and passwords)
125
+ if ( requestIsLocal ) {
126
+ //Allow no-auth access on localhost only, if they have configured the dashboard to not need auth
127
+ return res . json ( response ) ;
128
+ }
129
+ //We shouldn't get here. Fail closed.
130
+ res . send ( { success : false , error : 'Something went wrong.' } ) ;
131
+ } ) ;
122
132
123
- //They didn't provide auth, and have configured the dashboard to not need auth
124
- //(ie. didn't supply usernames and passwords)
125
- if ( requestIsLocal ) {
126
- //Allow no-auth access on localhost only, if they have configured the dashboard to not need auth
127
- return res . json ( response ) ;
133
+ // Serve the app icons. Uses the optional `iconsFolder` parameter as
134
+ // directory name, that was setup in the config file.
135
+ // We are explicitly not using `__dirpath` here because one may be
136
+ // running parse-dashboard from globally installed npm.
137
+ if ( config . iconsFolder ) {
138
+ try {
139
+ var stat = fs . statSync ( config . iconsFolder ) ;
140
+ if ( stat . isDirectory ( ) ) {
141
+ app . use ( '/appicons' , express . static ( config . iconsFolder ) ) ;
142
+ //Check also if the icons really exist
143
+ checkIfIconsExistForApps ( config . apps , config . iconsFolder ) ;
144
+ }
145
+ } catch ( e ) {
146
+ // Directory doesn't exist or something.
147
+ console . warn ( "Iconsfolder at path: " + config . iconsFolder +
148
+ " not found!" ) ;
149
+ }
128
150
}
129
- //We shouldn't get here. Fail closed.
130
- res . send ( { success : false , error : 'Something went wrong.' } ) ;
131
- } ) ;
132
151
133
- // Serve the app icons. Uses the optional `iconsFolder` parameter as
134
- // directory name, that was setup in the config file.
135
- // We are explicitly not using `__dirpath` here because one may be
136
- // running parse-dashboard from globally installed npm.
137
- if ( config . iconsFolder ) {
138
- try {
139
- var stat = fs . statSync ( config . iconsFolder ) ;
140
- if ( stat . isDirectory ( ) ) {
141
- app . use ( '/appicons' , express . static ( config . iconsFolder ) ) ;
142
- //Check also if the icons really exist
143
- checkIfIconsExistForApps ( config . apps , config . iconsFolder ) ;
152
+ app . get ( '/login' , csrf ( ) , function ( req , res ) {
153
+ if ( ! users || ( req . user && req . user . isAuthenticated ) ) {
154
+ return res . redirect ( `${ mountPath } apps` ) ;
144
155
}
145
- } catch ( e ) {
146
- // Directory doesn't exist or something.
147
- console . warn ( "Iconsfolder at path: " + config . iconsFolder +
148
- " not found!" ) ;
149
- }
150
- }
151
156
152
- app . get ( '/login' , csrf ( ) , function ( req , res ) {
153
- if ( ! users || ( req . user && req . user . isAuthenticated ) ) {
154
- return res . redirect ( '/apps' ) ;
155
- }
156
- let mountPath = getMount ( req ) ;
157
- let errors = req . flash ( 'error' ) ;
158
- if ( errors && errors . length ) {
159
- errors = `<div id="login_errors" style="display: none;">
160
- ${ errors . join ( ' ' ) }
161
- </div>`
162
- }
163
- res . send ( `<!DOCTYPE html>
164
- <head>
165
- <link rel="shortcut icon" type="image/x-icon" href="${ mountPath } favicon.ico" />
166
- <base href="${ mountPath } "/>
167
- <script>
168
- PARSE_DASHBOARD_PATH = "${ mountPath } ";
169
- </script>
170
- </head>
171
- <html>
172
- <title>Parse Dashboard</title>
173
- <body>
174
- <div id="login_mount"></div>
175
- ${ errors }
176
- <script id="csrf" type="application/json">"${ req . csrfToken ( ) } "</script>
177
- <script src="${ mountPath } bundles/login.bundle.js"></script>
178
- </body>
179
- </html>
180
- ` ) ;
181
- } ) ;
157
+ let errors = req . flash ( 'error' ) ;
158
+ if ( errors && errors . length ) {
159
+ errors = `<div id="login_errors" style="display: none;">
160
+ ${ errors . join ( ' ' ) }
161
+ </div>`
162
+ }
163
+ res . send ( `<!DOCTYPE html>
164
+ <head>
165
+ <link rel="shortcut icon" type="image/x-icon" href="${ mountPath } favicon.ico" />
166
+ <base href="${ mountPath } "/>
167
+ <script>
168
+ PARSE_DASHBOARD_PATH = "${ mountPath } ";
169
+ </script>
170
+ </head>
171
+ <html>
172
+ <title>Parse Dashboard</title>
173
+ <body>
174
+ <div id="login_mount"></div>
175
+ ${ errors }
176
+ <script id="csrf" type="application/json">"${ req . csrfToken ( ) } "</script>
177
+ <script src="${ mountPath } bundles/login.bundle.js"></script>
178
+ </body>
179
+ </html>
180
+ ` ) ;
181
+ } ) ;
182
182
183
- // For every other request, go to index.html. Let client-side handle the rest.
184
- app . get ( '/*' , function ( req , res ) {
185
- if ( users && ( ! req . user || ! req . user . isAuthenticated ) ) {
186
- return res . redirect ( '/ login' ) ;
187
- }
188
- let mountPath = getMount ( req ) ;
189
- res . send ( `<!DOCTYPE html >
190
- <head >
191
- <link rel="shortcut icon" type="image/x-icon" href="${ mountPath } favicon.ico" />
192
- <base href=" ${ mountPath } "/ >
193
- <script>
194
- PARSE_DASHBOARD_PATH = " ${ mountPath } ";
195
- </script >
196
- </head >
197
- <html >
198
- <title>Parse Dashboard</title >
199
- <body >
200
- <div id="browser_mount "></div >
201
- <script src=" ${ mountPath } bundles/dashboard.bundle.js"></script >
202
- </body >
203
- </html>
204
- ` ) ;
183
+ // For every other request, go to index.html. Let client-side handle the rest.
184
+ app . get ( '/*' , function ( req , res ) {
185
+ if ( users && ( ! req . user || ! req . user . isAuthenticated ) ) {
186
+ return res . redirect ( ` ${ mountPath } login` ) ;
187
+ }
188
+ res . send ( `<!DOCTYPE html>
189
+ <head >
190
+ <link rel="shortcut icon" type="image/x-icon" href=" ${ mountPath } favicon.ico" / >
191
+ <base href="${ mountPath } " />
192
+ <script >
193
+ PARSE_DASHBOARD_PATH = " ${ mountPath } ";
194
+ </script>
195
+ </head >
196
+ <html >
197
+ <title>Parse Dashboard</title >
198
+ <body >
199
+ <div id="browser_mount"></div >
200
+ <script src=" ${ mountPath } bundles/dashboard.bundle.js "></script >
201
+ </body >
202
+ </html >
203
+ ` ) ;
204
+ } ) ;
205
205
} ) ;
206
206
207
207
return app ;
0 commit comments