Browse Source

Force the email lowercase to make sure they get it right before hashing.

master
Zed A. Shaw 3 days ago
parent
commit
dd78e54950
3 changed files with 19 additions and 7 deletions
  1. +1
    -1
      .eslintrc.js
  2. +17
    -4
      lib/models.js
  3. +1
    -2
      src/routes/api/admin/[table]/index.json.js

+ 1
- 1
.eslintrc.js View File

@@ -194,7 +194,7 @@ module.exports = {
"no-unmodified-loop-condition": "error",
"no-unneeded-ternary": "error",
"no-unused-expressions": "error",
"no-use-before-define": "error",
"no-use-before-define": ["error", {"functions": true, "classes": false}],
"no-useless-call": "error",
"no-useless-computed-key": "error",
"no-useless-concat": "error",


+ 17
- 4
lib/models.js View File

@@ -180,6 +180,15 @@ class User extends Model.from_table('users') {
return res;
}

/*
* Exactly the same as hash_password except it forces the email to
* all lowercase so that it's consistent between users (and because
* email is case insensitive).
*/
static async hash_email(email) {
return bcrypt.hash(email.toLowerCase(), SALT_ROUNDS);
}

static async hash_password(password) {
return bcrypt.hash(password, SALT_ROUNDS);
}
@@ -188,8 +197,13 @@ class User extends Model.from_table('users') {
return bcrypt.compare(password, this.password);
}

/*
* Exactly like valid_password except it forces the email address to
* lowercase for the comparison. This is because email is case insensitive
* but people type them like they type their name, which messes up searches.
*/
async valid_email(email) {
return bcrypt.compare(email, this.email);
return bcrypt.compare(email.toLowerCase(), this.email);
}

async episode_states() {
@@ -229,11 +243,10 @@ class User extends Model.from_table('users') {
}

async update(attr) {
// SECURITY: Need a way to automatically restrict fields to only what's in the DB
// SECURITY: we have to do this here so that they can't unset email and password
const clean = attr;

if(attr.email) clean.email = await User.hash_password(attr.email);
if(attr.email) clean.email = await User.hash_email(attr.email); // forces lowercase
if(attr.password) clean.password = await User.hash_password(attr.password);

let count = await User.update({id: this.id}, clean);
@@ -245,7 +258,7 @@ class User extends Model.from_table('users') {
assert(email && full_name && username && password, "All parameters required.");

// registration is the first time we also log the user in
const email_hash = await User.hash_password(email);
const email_hash = await User.hash_email(email); // forces lowercase
const password_hash = await User.hash_password(password);

const user = await User.insert({


+ 1
- 2
src/routes/api/admin/[table]/index.json.js View File

@@ -1,7 +1,6 @@
import { log } from 'logging';
import { User, knex } from '../../../../../lib/models';
import * as auth from 'auth';
import assert from 'assert';

const default_limit = 20;

@@ -49,7 +48,7 @@ export const post = auth.admin(async ($app, $session, $msg, req) => {

if(table === User.table_name) {
// HACK: only place we need to do this is with users
$msg.email = await User.hash_password($msg.email);
$msg.email = await User.hash_email($msg.email);
$msg.password = await User.hash_password($msg.password);
}



Loading…
Cancel
Save