Skip to content
This repository was archived by the owner on Oct 5, 2020. It is now read-only.

Commit 69e8b60

Browse files
committed
#288: refined logic a bit
1 parent 0ab17c8 commit 69e8b60

File tree

6 files changed

+103
-76
lines changed

6 files changed

+103
-76
lines changed

app/templates/node-server/node-app.js

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,25 +17,11 @@ app.use(expressSession({
1717
resave: true
1818
}));
1919

20-
//
21-
// Uncomment the following to by-pass authentication entirely by enforcing defaultUser on the session.
22-
//
23-
// Note: consider blocking update calls in the proxy when enabling this.
24-
//
25-
// app.use(function (req, res, next) {
26-
// var options = require('./utils/options')();
27-
// req.session.user = { name: options.defaultUser, password: options.defaultPass, profile: { fullname: 'Guest' } };
28-
// next();
29-
// });
30-
3120
app.use(logger('dev'));
3221

3322
app.use('/v1', require('./proxy'));
3423
app.use('/api', require('./routes'));
3524

36-
app.use('/create', express.static('./build/index.html'));
37-
app.use('/profile', express.static('./build/index.html'));
38-
3925
console.log('About to crank up node');
4026
console.log('PORT=' + port);
4127
console.log('NODE_ENV=' + environment);

app/templates/node-server/proxy.js

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ var options = require('./utils/options')();
2222
// For any other GET request, proxy it on to MarkLogic.
2323
router.get('*', function(req, res) {
2424
noCache(res);
25-
if (req.session.user === undefined) {
25+
if (!options.guestAccess && req.session.user === undefined) {
2626
res.status(401).send('Unauthorized');
2727
} else {
2828
proxy(req, res);
@@ -35,9 +35,9 @@ router.put('*', function(req, res) {
3535
// For PUT requests, require authentication
3636
if (req.session.user === undefined) {
3737
res.status(401).send('Unauthorized');
38-
} else if (req.path === '/v1/documents' &&
38+
} else if (options.readOnlyAccess || (req.path === '/v1/documents' &&
3939
req.query.uri.match('/api/users/') &&
40-
req.query.uri.match(new RegExp('/api/users/[^(' + req.session.user.name + ')]+.json'))) {
40+
req.query.uri.match(new RegExp('/api/users/[^(' + req.session.user.name + ')]+.json')))) {
4141
// The user is trying to PUT to a profile document other than his/her own. Not allowed.
4242
res.status(403).send('Forbidden');
4343
} else {
@@ -50,10 +50,20 @@ router.put('*', function(req, res) {
5050
});
5151

5252
// Require authentication for POST requests
53+
router.post(/^\/(alert\/match|search|suggest|values\/.*)$/, function(req, res) {
54+
noCache(res);
55+
if (!options.guestAccess && req.session.user === undefined) {
56+
res.status(401).send('Unauthorized');
57+
} else {
58+
proxy(req, res);
59+
}
60+
});
5361
router.post('*', function(req, res) {
5462
noCache(res);
5563
if (req.session.user === undefined) {
5664
res.status(401).send('Unauthorized');
65+
} else if (options.readOnlyAccess) {
66+
res.status(403).send('Forbidden');
5767
} else {
5868
proxy(req, res);
5969
}
@@ -64,6 +74,8 @@ router.delete('*', function(req, res) {
6474
noCache(res);
6575
if (req.session.user === undefined) {
6676
res.status(401).send('Unauthorized');
77+
} else if (options.readOnlyAccess) {
78+
res.status(403).send('Forbidden');
6779
} else {
6880
proxy(req, res);
6981
}

app/templates/node-server/routes.js

Lines changed: 70 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,15 @@ router.get('/user/status', function(req, res) {
1616
var headers = req.headers;
1717
noCache(res);
1818
if (req.session.user === undefined) {
19-
res.send({authenticated: false});
19+
if (options.guestAccess) {
20+
res.send({
21+
authenticated: true,
22+
username: options.defaultUser,
23+
profile: { fullname: 'Guest' }
24+
});
25+
} else {
26+
res.send({authenticated: false});
27+
}
2028
} else {
2129
delete headers['content-length'];
2230
var status = http.get({
@@ -29,15 +37,15 @@ router.get('/user/status', function(req, res) {
2937
if (response.statusCode === 200) {
3038
response.on('data', function(chunk) {
3139
var json = JSON.parse(chunk);
32-
if (json.user !== undefined) {
33-
res.status(200).send({
34-
authenticated: true,
35-
username: req.session.user.name,
36-
profile: json.user
37-
});
38-
} else {
40+
if (json.user === undefined) {
3941
console.log('did not find chunk.user');
4042
}
43+
res.status(200).send({
44+
authenticated: true,
45+
username: req.session.user.name,
46+
profile: json.user || {}
47+
});
48+
req.session.user.profile = json.user || {};
4149
});
4250
} else if (response.statusCode === 404) {
4351
//no profile yet for user
@@ -62,68 +70,74 @@ router.post('/user/login', function(req, res) {
6270
// Attempt to read the user's profile, then check the response code.
6371
// 404 - valid credentials, but no profile yet
6472
// 401 - bad credentials
65-
var username = req.body.username;
66-
var password = req.body.password;
73+
var username = req.body.username || '';
74+
var password = req.body.password || '';
6775
var headers = req.headers;
76+
6877
//make sure login isn't cached
6978
noCache(res);
7079

71-
// remove content length so ML doesn't wait for request body
72-
// that isn't being passed.
73-
delete headers['content-length'];
74-
var login = http.get({
75-
hostname: options.mlHost,
76-
port: options.mlHttpPort,
77-
path: '/v1/documents?uri=/api/users/' + username + '.json',
78-
headers: headers,
79-
auth: username + ':' + password
80-
}, function(response) {
81-
if (response.statusCode === 401) {
82-
res.statusCode = 401;
83-
res.send('Unauthenticated');
84-
} else if (response.statusCode === 404) {
85-
// authentication successful, but no profile defined
86-
req.session.user = {
87-
name: username,
88-
password: password
89-
};
90-
res.status(200).send({
91-
authenticated: true,
92-
username: username,
93-
profile: {}
94-
});
95-
} else {
96-
console.log('code: ' + response.statusCode);
97-
if (response.statusCode === 200) {
98-
// authentication successful, remember the username
80+
var startsWithMatch = new RegExp('^' + options.appName + '-');
81+
if (options.appUsersOnly && !startsWithMatch.test(username)) {
82+
res.status(403).send('Forbidden');
83+
} else {
84+
// remove content length so ML doesn't wait for request body
85+
// that isn't being passed.
86+
delete headers['content-length'];
87+
88+
var login = http.get({
89+
hostname: options.mlHost,
90+
port: options.mlHttpPort,
91+
path: '/v1/documents?uri=/api/users/' + username + '.json',
92+
headers: headers,
93+
auth: username + ':' + password
94+
}, function(response) {
95+
96+
if (response.statusCode === 401) {
97+
res.status(401).send('Unauthenticated');
98+
} else if (response.statusCode === 404) {
99+
// authentication successful, but no profile defined
99100
req.session.user = {
100101
name: username,
101102
password: password
102103
};
103-
response.on('data', function(chunk) {
104-
var json = JSON.parse(chunk);
105-
if (json.user !== undefined) {
104+
res.status(200).send({
105+
authenticated: true,
106+
username: username,
107+
profile: {}
108+
});
109+
} else {
110+
console.log('code: ' + response.statusCode);
111+
if (response.statusCode === 200) {
112+
// authentication successful, remember the username
113+
req.session.user = {
114+
name: username,
115+
password: password
116+
};
117+
response.on('data', function(chunk) {
118+
var json = JSON.parse(chunk);
119+
if (json.user === undefined) {
120+
console.log('did not find chunk.user');
121+
}
106122
res.status(200).send({
107123
authenticated: true,
108124
username: username,
109-
profile: json.user
125+
profile: json.user || {}
110126
});
111-
req.session.user.profile = json.user;
112-
} else {
113-
console.log('did not find chunk.user');
114-
}
115-
});
116-
} else {
117-
res.statusCode = response.statusCode;
118-
res.send(response.statusMessage);
127+
req.session.user.profile = json.user || {};
128+
});
129+
} else {
130+
res.status(response.statusCode).send(response.statusMessage);
131+
}
119132
}
120-
}
121-
});
122133

123-
login.on('error', function(e) {
124-
console.log(JSON.stringify(e));
125-
console.log('login failed: ' + e.statusCode);
126-
});
134+
});
135+
136+
login.on('error', function(e) {
137+
console.log(JSON.stringify(e));
138+
console.log('login failed: ' + e.statusCode);
139+
});
140+
}
127141
});
128142

129143
router.get('/user/logout', function(req, res) {

app/templates/node-server/utils/options.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,15 @@ module.exports = function(){
1010
var envJson = getEnvOptions(environment === 'build' ? 'prod' : 'local');
1111

1212
var options = {
13+
appName: process.env.APP_NAME || envJson['app-name'] || 'slush-app',
1314
appPort: process.env.APP_PORT || envJson['node-port'] || config.defaultPort,
1415
mlHost: process.env.ML_HOST || envJson['ml-host'] || config.marklogic.host,
1516
mlHttpPort: process.env.ML_PORT || envJson['ml-http-port'] || config.marklogic.httpPort,
1617
defaultUser: process.env.ML_APP_USER || envJson['ml-app-user'] || config.marklogic.user,
17-
defaultPass: process.env.ML_APP_PASS || envJson['ml-app-pass'] || config.marklogic.password
18+
defaultPass: process.env.ML_APP_PASS || envJson['ml-app-pass'] || config.marklogic.password,
19+
guestAccess: bool(process.env.GUEST_ACCESS || envJson['guest-access'] || config.marklogic.guestAccess || false),
20+
readOnlyAccess: bool(process.env.READ_ONLY_ACCESS || envJson['read-only-access'] || config.marklogic.readOnlyAccess || false),
21+
appUsersOnly: bool(process.env.APP_USERS_ONLY || envJson['app-users-only'] || config.marklogic.appUsersOnly || false)
1822
};
1923

2024
return options;
@@ -35,4 +39,8 @@ module.exports = function(){
3539
return envJson;
3640
}
3741

42+
function bool(x) {
43+
return (x === 'true' || x === true);
44+
}
45+
3846
};

app/templates/ui/app/login/login.service.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
}
2626

2727
function failLogin(response) {
28-
if (response.status === 401) {
28+
if (response.status > 200) {
2929
_loginError = true;
3030
}
3131
}
@@ -35,7 +35,7 @@
3535
}
3636

3737
function getAuthenticatedStatus() {
38-
if (_isAuthenticated) {
38+
if (_isAuthenticated !== undefined) {
3939
return _isAuthenticated;
4040
}
4141

slushfile.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,12 @@ function configRoxy() {
187187
var matches = passwordMatch.exec(properties);
188188
settings.appuserPassword = matches[1];
189189

190+
// fix bug in Roxy causing { in pwd to get escaped mistakenly
191+
if (settings.appuserPassword.match(/\{/g)) {
192+
settings.appuserPassword = settings.appuserPassword.replace(/\{/g, '');
193+
properties = properties.replace(passwordMatch, 'appuser-password=' + settings.appuserPassword);
194+
}
195+
190196
fs.writeFileSync('deploy/build.properties', properties);
191197
} catch (e) {
192198
console.log('failed to update properties: ' + e.message);
@@ -311,6 +317,7 @@ gulp.task('configGulp', ['init'], function(done) {
311317

312318
try {
313319
var configJSON = {};
320+
configJSON['app-name'] = settings.appName;
314321
configJSON['ml-version'] = settings.mlVersion;
315322
configJSON['ml-host'] = settings.marklogicHost;
316323
configJSON['ml-admin-user'] = settings.marklogicAdminUser;

0 commit comments

Comments
 (0)