Skip to content

Commit 8c782e5

Browse files
authored
Merge pull request #335 from snap-cloud/debug-wrong-passwords
Finish Bulk Account Creation
2 parents 868bf9e + e84ef90 commit 8c782e5

10 files changed

Lines changed: 121 additions & 66 deletions

File tree

api.lua

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,11 @@ app:match(api_route('my_user'), respond_to({
9090
DELETE = UserController.delete
9191
}))
9292

93+
app:match('logout', respond_to({
94+
GET = UserController.logout_get,
95+
}))
96+
9397
app:match(api_route('logout'), respond_to({
94-
GET = UserController.logout,
9598
POST = UserController.logout
9699
}))
97100

app.lua

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -283,9 +283,13 @@ function app:handle_404()
283283
end
284284

285285
function app:handle_error(err, trace)
286-
local inspect = require('inspect')
287-
print(inspect(err))
288-
print(inspect(trace))
286+
if config._name == 'development' then
287+
debug_print(err, trace)
288+
local msg = '<pre style="text-align: left; width: 80ch">'
289+
.. err .. '<br>' .. trace .. '</pre>'
290+
return errorResponse(msg, 500)
291+
end
292+
289293
local err_msg = exceptions.normalize_error(err)
290294
local user_info = exceptions.get_user_info(self.session)
291295
if config.sentry_dsn then

bin/deploy

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,21 @@ echo "Deploying branch: $branch"
1010
# Deploy a copy of snapCloud
1111
pushd ~/snapCloud/ > /dev/null;
1212

13+
git fetch
1314
git checkout $branch
14-
git pull origin $branch
15+
# git pull origin $branch
1516
# Always init, just incase we add a submodule.
1617
git submodule init
1718
git submodule update --recursive --remote
1819

20+
# TODO: Clean this up...
1921
pushd ~/snapCloud/bin/;
20-
2122
./renew-certs
2223
./deploy-certs
24+
popd;
25+
2326
# ./update-snap
2427

25-
popd;
2628

2729
echo "Updating Dependencies:"
2830
sudo luarocks install --only-deps snapcloud-dev-0.rockspec

controllers/user.lua

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ UserController = {
156156
if self.queried_user.verified then
157157
return okResponse('User ' .. self.queried_user.username
158158
.. ' logged in')
159+
-- TODO: Handle first-time student account logins.
159160
else
160161
return jsonResponse({
161162
title = 'Verify your account',
@@ -171,13 +172,19 @@ UserController = {
171172
return self:build_url('index')
172173
end
173174
end),
175+
logout_get = capture_errors(function (self)
176+
self.session.username = ''
177+
self.session.user_id = nil
178+
self.cookies.persist_session = 'false'
179+
return { redirect_to = self:build_url('/') }
180+
end),
174181
logout = capture_errors(function (self)
175182
self.session.username = ''
176183
self.session.user_id = nil
177184
self.cookies.persist_session = 'false'
178-
return jsonResponse(
179-
{ redirect = self.params.redirect or self:build_url('index') }
180-
)
185+
return jsonResponse({
186+
redirect = (self.params.redirect or self:build_url('/'))
187+
})
181188
end),
182189
change_email = capture_errors(function (self)
183190
assert_logged_in(self)
@@ -187,6 +194,8 @@ UserController = {
187194
if self.queried_user then
188195
-- we're trying to change someone else's email
189196
assert_min_role(self, 'moderator')
197+
elseif user:is_student() then
198+
yield_error(err.student_cannot_change_email)
190199
elseif (user.password ~=
191200
hash_password(self.params.password, user.salt)) then
192201
yield_error(err.wrong_password)
@@ -227,7 +236,7 @@ UserController = {
227236
local minutes = db.select(
228237
'extract(minutes from (now()::timestamp - ?::timestamp))',
229238
token.created)[1].date_part
230-
if minutes < 15 then
239+
if minutes and minutes < 15 then
231240
yield_error(err.too_many_password_resets)
232241
end
233242
end
@@ -490,20 +499,21 @@ UserController = {
490499
end
491500
end
492501
end
502+
local salt, password, result
493503
for _, user in pairs(users) do
494-
user.username = util.trim(tostring(user.username))
495-
user.password = util.trim(tostring(user.password))
496-
user.email = user.email or self.current_user.email
497-
-- TODO: This doesn't reveal which record has an invalid value...
498-
validate.assert_valid(user, Users.validations)
499-
500-
user.created = db.format_date()
501-
user.salt = secure_salt()
502-
user.password = hash_password(user.password, user.salt)
503-
user.verified = true
504-
user.role = 'student'
505-
user.creator_id = self.current_user.id
506-
local result = Users:create(user)
504+
salt = secure_salt()
505+
password = util.trim(tostring(user.password))
506+
result = Users:create({
507+
created = db.format_date(),
508+
username = util.trim(tostring(user.username)),
509+
salt = salt,
510+
password = hash_password(hash_password(password, ''), salt),
511+
email = (user.email or self.current_user.email),
512+
verified = true,
513+
role = 'student',
514+
creator_id = self.current_user.id
515+
})
516+
507517
if not result then
508518
db.query('ROLLBACK;')
509519
return errorResponse(

lib/util.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,5 @@ local function capitalize(str)
2727
end
2828

2929
return {
30-
capitalize
30+
capitalize = capitalize
3131
}

static/style/classes.css

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,3 +167,11 @@ pre.in-place {
167167
img.emoji {
168168
height: 1em;
169169
}
170+
171+
.code-example {
172+
border: 1px solid;
173+
border-radius: 4px;
174+
margin: 1em;
175+
padding: 0.5em;
176+
background: rgb(248, 248, 255);
177+
}

validation.lua

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@ err = {
118118
teacher_account_required = {
119119
msg = 'You must be verified as a teacher to perform this action.',
120120
status = 403
121+
},
122+
student_cannot_change_email = {
123+
msg = 'Student account email addresses cannot be changed. Please contact your instructor for help.',
124+
status = 403
121125
}
122126
}
123127

views/bulk.etlua

Lines changed: 62 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,70 @@
11
<script src="/static/js/papaparse.min.js"></script>
2+
23
<h1><%- locale.get('bulk_tile') %></h1>
34
<div class="bulk">
45
<p><%- locale.get('bulk_text') %></p>
5-
<label for="csv">Upload a CSV file:</label>
6-
<input type="file" class="csv" name="csv">
7-
<p>
8-
<input type="checkbox" class="add-collection" name="add_collection"
9-
onchange="
10-
document.querySelector('div.collection').hidden =
11-
!document.querySelector('div.collection').hidden;
12-
">
13-
<label for="add_collection"
14-
><%- locale.get('bulk_make_collection') %></label>
15-
<div class="collection" hidden>
16-
<strong><%- locale.get('collection_name') %></strong>
17-
<input name="collection_name" class="collection_name"></input>
18-
</div>
19-
</p>
20-
<button class="pure-button" onclick="
21-
var div = document.querySelector('div.bulk'),
22-
collection_name =
23-
div.querySelector('input.add-collection').checked ?
24-
div.querySelector('.collection_name').value :
25-
null,
26-
file = div.querySelector('.csv').files[0];
27-
Papa.parse(
28-
file,
29-
{
30-
skipEmptyLines: true,
31-
header: true,
32-
complete: (results) => {
33-
cloud.post(
34-
'/users/create_learners',
6+
<div>
7+
<p>Example:</p>
8+
<pre class="code-example">
9+
username,password
10+
myclass-student1,correct-horse-battery-staple
11+
myclass-student2,sentences-make-good-passowrds</pre>
12+
</div>
13+
<div class="pure-form">
14+
<br>
15+
<label for="csv"><strong>Upload a CSV file:</strong>
16+
<input id="csv" type="file" class="csv" name="csv">
17+
</label>
18+
<br><br>
19+
<details>
20+
<summary>Alternatively, paste a CSV File</summary>
21+
<br>
22+
<label for="csv_txt">CSV Contents</label>
23+
<br>
24+
<textarea id="csv_text" rows="5" name="csv_text" class="pure-input-1-2"
25+
style="font-family: monospace"></textarea>
26+
</details>
27+
<p>
28+
<label for="add_collection" class="pure-checkbox">
29+
<input id="add_collection" type="checkbox" class="add-collection" name="add_collection"
30+
onchange="document.querySelector('div.collection').hidden =
31+
!document.querySelector('div.collection').hidden;">
32+
<%- locale.get('bulk_make_collection') %>
33+
</label>
34+
<div class="collection" hidden>
35+
<label for="collection_name">
36+
<strong><%- locale.get('collection_name') %></strong>
37+
</label>
38+
<input id="collection_name" name="collection_name" class="collection_name" />
39+
</div>
40+
</p>
41+
<button class="pure-button" onclick="
42+
var div = document.querySelector('div.bulk'),
43+
collection_name =
44+
div.querySelector('input.add-collection').checked ?
45+
div.querySelector('.collection_name').value :
3546
null,
36-
{
37-
collection_name: collection_name,
38-
users: results.data
47+
file = div.querySelector('.csv').files[0],
48+
csv_text = document.querySelector('#csv_text').value,
49+
csv_data = csv_text || file;
50+
Papa.parse(
51+
csv_data,
52+
{
53+
skipEmptyLines: true,
54+
header: true,
55+
complete: (results) => {
56+
let post_body = { users: results.data };
57+
if (collection_name) {
58+
post_body.collection_name = collection_name;
3959
}
40-
);
60+
cloud.post('/users/create_learners', null, post_body);
61+
}
4162
}
42-
}
43-
);
44-
"><%- locale.get('bulk_create') %></button>
45-
<script>
46-
document.querySelector('div.collection').hidden =
47-
!document.querySelector('input.add-collection').checked;
48-
</script>
63+
);
64+
"><%- locale.get('bulk_create') %></button>
65+
<script>
66+
document.querySelector('div.collection').hidden =
67+
!document.querySelector('input.add-collection').checked;
68+
</script>
69+
</div>
4970
</div>

views/profile.etlua

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@
2121
<div class="pure-u-1-2 buttons">
2222
<a class="pure-button"
2323
href="change_password"><%- locale.get('change_my_password') %></a>
24+
<% if not user:is_student() then %>
2425
<a class="pure-button"
2526
href="change_email"><%- locale.get('change_my_email') %></a>
27+
<% end %>
2628
<a class="pure-button pure-button-warning" onclick="
2729
confirmDeleteMyself()"><%- locale.get('delete_my_user') %></a>
2830
</div>

views/user_admin.etlua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ render(
2828
{ label = 'Reviewer', value = 'reviewer' },
2929
{ label = 'Moderator', value = 'moderator' },
3030
{ label = 'Administrator', value = 'admin' },
31+
{ label = 'Student', value = 'student' },
3132
{ label = 'Banned', value = 'banned' },
3233
}
3334
}

0 commit comments

Comments
 (0)