colouring-montreal/app/src/api/services/user.ts

188 lines
4.2 KiB
TypeScript
Raw Normal View History

2018-09-30 14:49:07 -04:00
/**
* User data access
*
*/
import { errors } from 'pg-promise';
2019-08-14 05:54:13 -04:00
import db from '../../db';
2019-09-11 11:28:05 -04:00
import { validateUsername, ValidationError, validatePassword } from '../validation';
function createUser(user) {
2019-09-11 11:28:05 -04:00
try {
validateUsername(user.username);
validatePassword(user.password);
} catch(err) {
if (err instanceof ValidationError) {
return Promise.reject({ error: err.message });
} else throw err;
2018-09-13 11:58:05 -04:00
}
2019-09-11 11:28:05 -04:00
2018-09-30 14:49:07 -04:00
return db.one(
`INSERT
INTO users (
user_id,
username,
email,
pass
) VALUES (
gen_random_uuid(),
$1,
$2,
crypt($3, gen_salt('bf'))
) RETURNING user_id
`, [
2019-02-24 14:28:11 -05:00
user.username,
user.email,
user.password
]
2019-02-24 14:28:11 -05:00
).catch(function (error) {
console.error('Error:', error)
2019-02-24 14:28:11 -05:00
if (error.detail.indexOf('already exists') !== -1) {
if (error.detail.indexOf('username') !== -1) {
return { error: 'Username already registered' };
} else if (error.detail.indexOf('email') !== -1) {
2019-02-24 14:28:11 -05:00
return { error: 'Email already registered' };
}
}
2019-02-24 14:28:11 -05:00
return { error: 'Database error' }
});
}
function authUser(username, password) {
2018-09-30 14:49:07 -04:00
return db.one(
`SELECT
user_id,
(
pass = crypt($2, pass)
) AS auth_ok
FROM users
WHERE
username = $1
`, [
2019-02-24 14:28:11 -05:00
username,
password
]
2019-02-24 14:28:11 -05:00
).then(function (user) {
2018-09-13 11:58:05 -04:00
if (user && user.auth_ok) {
2019-02-24 14:28:11 -05:00
return { user_id: user.user_id }
} else {
2019-02-24 14:28:11 -05:00
return { error: 'Username or password not recognised' }
}
2019-02-24 14:28:11 -05:00
}).catch(function (err) {
if (err instanceof errors.QueryResultError) {
console.error(`Authentication failed for user ${username}`);
return { error: 'Username or password not recognised' };
}
console.error('Error:', err);
return { error: 'Database error' };
})
}
2019-05-27 13:26:29 -04:00
function getUserById(id) {
2018-09-30 14:49:07 -04:00
return db.one(
`SELECT
2018-10-20 07:20:10 -04:00
username, email, registered, api_key
FROM
users
WHERE
user_id = $1
`, [
2019-05-27 13:26:29 -04:00
id
]
2019-02-24 14:28:11 -05:00
).catch(function (error) {
console.error('Error:', error)
return undefined;
});
}
function getUserByEmail(email: string) {
return db.one(
`SELECT
user_id, username, email
FROM
users
WHERE
email = $1
`, [email]
).catch(function(error) {
console.error('Error:', error);
return undefined;
});
}
2019-05-27 13:26:29 -04:00
function getNewUserAPIKey(id) {
2018-10-20 07:20:10 -04:00
return db.one(
`UPDATE
users
SET
api_key = gen_random_uuid()
WHERE
user_id = $1
RETURNING
api_key
`, [
2019-05-27 13:26:29 -04:00
id
2018-10-20 07:20:10 -04:00
]
2019-02-24 14:28:11 -05:00
).catch(function (error) {
2018-10-20 07:20:10 -04:00
console.error('Error:', error)
2019-02-24 14:28:11 -05:00
return { error: 'Failed to generate new API key.' };
2018-10-20 07:20:10 -04:00
});
}
2019-05-27 13:26:29 -04:00
function authAPIUser(key) {
return db.one(
`SELECT
user_id
FROM
users
WHERE
api_key = $1
`, [
2019-05-27 13:26:29 -04:00
key
]
2019-02-24 14:28:11 -05:00
).catch(function (error) {
console.error('Error:', error)
return undefined;
});
}
function deleteUser(id) {
return db.none(
`UPDATE users
SET
email = null,
pass = null,
api_key = null,
username = concat('deleted_', cast(user_id as char(13))),
is_deleted = true,
deleted_on = now() at time zone 'utc'
WHERE user_id = $1
`, [id]
).catch((error) => {
console.error('Error:', error);
return {error: 'Database error'};
});
}
function logout(session: Express.Session) {
return new Promise((resolve, reject) => {
session.user_id = undefined;
session.destroy(err => {
if (err) return reject(err);
return resolve();
});
});
}
export {
getUserById,
getUserByEmail,
createUser,
authUser,
getNewUserAPIKey,
authAPIUser,
deleteUser,
logout
};