Skip to content
This repository was archived by the owner on Dec 14, 2023. It is now read-only.

Commit f49f155

Browse files
authored
Merge pull request #315 from CoderDojo/rpi-login
Rpi login
2 parents be6d287 + 6544606 commit f49f155

File tree

3 files changed

+118
-86
lines changed

3 files changed

+118
-86
lines changed

profiles.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ module.exports = function (options) {
2424

2525
var immutableFields = ['userType', 'avatar'];
2626

27-
var requiredProfileFields = ['name', 'alias', 'dob', 'country'];
27+
var requiredProfileFields = ['name', 'alias', 'country'];
2828

2929
// var userTypes = ['champion', 'mentor', 'parent-guardian', 'attendee-o13', 'attendee-u13'];
3030
// var userTypes = ['attendee-u13', 'attendee-o13', 'parent-guardian', 'mentor', 'champion'];
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
DO $$
2+
BEGIN
3+
BEGIN
4+
ALTER TABLE sys_user ADD COLUMN profile_id character varying;
5+
EXCEPTION
6+
WHEN duplicate_column THEN RAISE NOTICE 'column profile_id already exists in sys_user.';
7+
END;
8+
END;
9+
$$

users.js

Lines changed: 108 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ module.exports = function (options) {
2424
seneca.add({role: plugin, cmd: 'register'}, cmd_register);
2525
seneca.add({role: plugin, cmd: 'promote'}, cmd_promote);
2626
seneca.add({role: plugin, cmd: 'get_users_by_emails'}, cmd_get_users_by_emails);
27+
seneca.add({role: plugin, cmd: 'get_user_by_profile_id'}, cmd_get_user_by_profile_id);
2728
seneca.add({role: plugin, cmd: 'update'}, cmd_update);
2829
seneca.add({role: plugin, cmd: 'get_init_user_types'}, cmd_get_init_user_types);
2930
seneca.add({role: plugin, cmd: 'is_champion'}, cmd_is_champion);
@@ -92,25 +93,26 @@ module.exports = function (options) {
9293
seneca.make(ENTITY_NS).list$(query, done);
9394
}
9495

95-
function checkPassword (args, done) {
96-
var containsNumber = /[0-9]/.test(args.password);
97-
var containsCharacter = /[!|@|#|$|%|^|&|*|(|)|-|_]/.test(args.password);
98-
var containsCapital = /[A-Z]/.test(args.password);
99-
var containsLowerCase = /[a-z]/.test(args.password);
96+
function checkPassword (user) {
97+
var containsNumber = /[0-9]/.test(user.password);
98+
var containsCharacter = /[!|@|#|$|%|^|&|*|(|)|-|_]/.test(user.password);
99+
var containsCapital = /[A-Z]/.test(user.password);
100+
var containsLowerCase = /[a-z]/.test(user.password);
100101
var minPasswordLength = 8;
101102

102-
if (args.password === args.email) {
103-
return done(null, {ok: false, token: args.token, why: 'Password must not be the same as your email address'});
104-
} if ((args.password.length < minPasswordLength) || !(containsNumber || containsCharacter)) {
105-
return done(null, {ok: false, token: args.token, why: 'Password must be a minimum of 8 characters in length and contain at least one number or punctuation character'});
106-
} if (_.includes(args.roles, 'cdf-admin') && (!containsNumber || !containsCharacter || !containsCapital || !containsLowerCase)) {
107-
return done(null, {ok: false, token: args.token, why: 'An admin account must contain at least one number, one special character and one capital.'});
103+
if (user.password === user.email) {
104+
return {ok: false, token: user.token, why: 'Password must not be the same as your email address'};
105+
} if ((user.password.length < minPasswordLength) || !(containsNumber || containsCharacter)) {
106+
return {ok: false, token: user.token, why: 'Password must be a minimum of 8 characters in length and contain at least one number or punctuation character'};
107+
} if (_.includes(user.roles, 'cdf-admin') && (!containsNumber || !containsCharacter || !containsCapital || !containsLowerCase)) {
108+
return {ok: false, token: user.token, why: 'An admin account must contain at least one number, one special character and one capital.'};
108109
}
109-
return done(null, args);
110+
return {ok: true};
110111
}
111112

112113
function cmd_register (args, done) {
113114
var profile = args.profile;
115+
var isTrusted = args.isTrusted;
114116
var user = args.user;
115117
var locality = user.locality || 'en_US';
116118
var emailCode = 'auth-register-';
@@ -125,29 +127,28 @@ module.exports = function (options) {
125127
// Roles Available: basic-user, cdf-admin
126128
var seneca = this;
127129

128-
if (!user['g-recaptcha-response']) {
129-
return done(new Error('Error with captcha'));
130-
}
131-
132-
var secret = so['recaptcha_secret_key'];
133-
var captchaResponse = user['g-recaptcha-response'];
134-
135-
var postData = {
136-
url: 'https://www.google.com/recaptcha/api/siteverify',
137-
form: {
138-
response: captchaResponse,
139-
secret: secret
140-
}
141-
};
142-
143-
function addProfilePassword (data, done) {
130+
function addProfilePassword (done) {
144131
profileUtils.encodePassword(user.password).then((profileHash) => {
145132
user.profilePassword = profileHash;
146-
done(null, data);
133+
done(null);
147134
});
148135
}
149136

150137
function verifyCaptcha (done) {
138+
if (!user['g-recaptcha-response']) {
139+
return done(new Error('Error with captcha'));
140+
}
141+
142+
var secret = so['recaptcha_secret_key'];
143+
var captchaResponse = user['g-recaptcha-response'];
144+
145+
var postData = {
146+
url: 'https://www.google.com/recaptcha/api/siteverify',
147+
form: {
148+
response: captchaResponse,
149+
secret: secret
150+
}
151+
};
151152
request.post(postData, function (err, response, body) {
152153
if (err) {
153154
return done(err);
@@ -159,69 +160,69 @@ module.exports = function (options) {
159160
return done('captcha-failed');
160161
}
161162

162-
return done(null, body.success);
163+
return done(null);
163164
});
164165
}
165166

166-
function checkPermissions (success, done) {
167+
function checkPermissions (done) {
167168
// if forumMods array contains the users email, make them an admin
168169
if (options.users.cdfAdmins.indexOf(user.email) > -1) {
169170
user.roles = ['cdf-admin'];
170171
} else {
171172
user.roles = ['basic-user'];
172173
}
173174

174-
return done(null, success);
175+
return done(null);
175176
}
176177

177-
function registerUser (success, done) {
178+
function registerUser (done) {
178179
user = _.omit(user, ['g-recaptcha-response', 'zenHostname', 'locality', 'user', 'emailSubject']);
179180

180181
user.mailingList = (user.mailingList) ? 1 : 0;
182+
const passwordCheckResult = checkPassword(user);
181183

182-
checkPassword(user, function (err, user) {
184+
if (!passwordCheckResult.ok) {
185+
return done(null, passwordCheckResult);
186+
}
187+
if (!user.name) {
188+
user.name = user.firstName + ' ' + user.lastName;
189+
}
190+
seneca.act({role: 'user', cmd: 'register'}, user, function (err, registerResponse) {
183191
if (err) return done(err);
184-
if (typeof user.ok !== 'undefined' && !user.ok) {
185-
return done(null, user);
192+
if (!registerResponse.ok) {
193+
return done(null, registerResponse);
186194
}
187-
user.name = user.firstName + ' ' + user.lastName;
188-
seneca.act({role: 'user', cmd: 'register'}, user, function (err, registerResponse) {
189-
if (err) return done(err);
190-
if (!registerResponse.ok) {
191-
return done(null, registerResponse);
192-
}
193-
194-
var user = registerResponse.user;
195-
// Create user profile based on initial user type.
196-
var userType = 'attendee-o13';
197-
if (user.initUserType) userType = user.initUserType.name;
198-
199-
_.defaults(profile, {
200-
private: true,
201-
userId: user.id,
202-
name: user.name,
203-
firstName: user.firstName,
204-
lastName: user.lastName,
205-
email: user.email,
206-
userType: userType
207-
});
208195

209-
var profileKeys = _.keys(profile);
210-
var missingKeys = _.difference(requiredProfileFields, profileKeys);
211-
if (_.isEmpty(missingKeys)) profile.requiredFieldsComplete = true;
196+
var user = registerResponse.user;
197+
// Create user profile based on initial user type.
198+
var userType = 'attendee-o13';
199+
if (user.initUserType) userType = user.initUserType.name;
200+
201+
_.defaults(profile, {
202+
private: true,
203+
userId: user.id,
204+
name: user.name,
205+
firstName: user.firstName,
206+
lastName: user.lastName,
207+
email: user.email,
208+
userType: userType
209+
});
212210

213-
seneca.act({role: 'cd-profiles', cmd: 'save', profile: profile}, function (err, profile) {
214-
if (err) return done(err);
215-
done(null, registerResponse);
216-
});
211+
var profileKeys = _.keys(profile);
212+
var missingKeys = _.difference(requiredProfileFields, profileKeys);
213+
if (_.isEmpty(missingKeys)) profile.requiredFieldsComplete = true;
214+
215+
seneca.act({role: 'cd-profiles', cmd: 'save', profile: profile}, function (err, profile) {
216+
if (err) return done(err);
217+
done(null, registerResponse);
217218
});
218219
});
219220
}
220221

221222
function sendWelcomeEmail (registerResponse, done) {
222223
if (registerResponse.ok) {
223-
seneca.act({role: 'email-notifications', cmd: 'send'},
224-
{code: emailCode,
224+
seneca.act({role: 'email-notifications', cmd: 'send'}, {
225+
code: emailCode,
225226
locality: locality,
226227
to: args.email,
227228
subject: emailSubject,
@@ -235,13 +236,15 @@ module.exports = function (options) {
235236
}
236237
}
237238

238-
async.waterfall([
239-
verifyCaptcha,
239+
var tasks = [
240+
!isTrusted && verifyCaptcha,
240241
checkPermissions,
241-
addProfilePassword,
242+
!isTrusted && addProfilePassword,
242243
registerUser,
243244
sendWelcomeEmail
244-
], function (err, results) {
245+
].filter(Boolean);
246+
247+
async.waterfall(tasks, function (err, results) {
245248
if (err) {
246249
return done(null, {error: err});
247250
}
@@ -306,6 +309,28 @@ module.exports = function (options) {
306309
}
307310
}
308311

312+
function cmd_get_user_by_profile_id (args, done) {
313+
var seneca = this;
314+
var query = {};
315+
316+
query.profileId = args.profileId;
317+
query.limit$ = query.limit$ ? query.limit$ : 1;
318+
319+
seneca.make(ENTITY_NS).list$(query, function (err, users) {
320+
if (err) {
321+
return done(err);
322+
}
323+
324+
users = _.map(users, function (user) {
325+
return {email: user.email, id: user.id, name: user.name};
326+
});
327+
328+
users = _.uniq(users, 'email');
329+
330+
done(null, users[0] || {});
331+
});
332+
}
333+
309334
function cmd_update (args, done) {
310335
var seneca = this;
311336
var user = args.user;
@@ -435,25 +460,23 @@ module.exports = function (options) {
435460
userEntity.load$({ id: reset.user }, function (err, user) {
436461
if (err) { return done(err); }
437462
user.password = args.password;
438-
checkPassword(user, function (err, user) {
463+
var checkPasswordResult = checkPassword(user);
464+
if (!checkPasswordResult.ok) {
465+
return done(null, checkPasswordResult);
466+
}
467+
delete user.password;
468+
seneca.act({ role: 'user', cmd: 'change_password', user: user, password: args.password, repeat: args.repeat }, function (err, out) {
439469
if (err) { return done(err); }
440-
if (typeof user.ok !== 'undefined' && !user.ok) {
441-
return done(null, user);
442-
}
443-
delete user.password;
444-
seneca.act({ role: 'user', cmd: 'change_password', user: user, password: args.password, repeat: args.repeat }, function (err, out) {
445-
if (err) { return done(err); }
446470

447-
out.reset = reset;
448-
if (!out.ok) { return done(null, out); }
471+
out.reset = reset;
472+
if (!out.ok) { return done(null, out); }
449473

450-
seneca.act({role: plugin, cmd: 'update_profile_password'}, {password: args.password, user: user});
474+
seneca.act({role: plugin, cmd: 'update_profile_password'}, {password: args.password, user: user});
451475

452-
reset.active = false;
453-
reset.save$(function (err, reset) {
454-
if (err) { return done(err); }
455-
return done(null, { user: user, reset: reset, ok: true });
456-
});
476+
reset.active = false;
477+
reset.save$(function (err, reset) {
478+
if (err) { return done(err); }
479+
return done(null, { user: user, reset: reset, ok: true });
457480
});
458481
});
459482
});

0 commit comments

Comments
 (0)