hostr/api/lib/auth.js

102 lines
2.7 KiB
JavaScript
Raw Normal View History

2015-07-09 23:01:43 +01:00
import passwords from 'passwords';
import auth from 'basic-auth';
import debugname from 'debug';
2018-06-02 18:07:00 +00:00
import models from '../../models';
2015-07-09 23:01:43 +01:00
const debug = debugname('hostr-api:auth');
const badLoginMsg = '{"error": {"message": "Incorrect login details.", "code": 607}}';
2018-06-02 15:50:39 +00:00
export default async (ctx, next) => {
2015-07-09 23:01:43 +01:00
let user = false;
2018-06-02 15:50:39 +00:00
const remoteIp = ctx.req.headers['x-forwarded-for'] || ctx.req.connection.remoteAddress;
const login = await models.login.create({
2020-06-14 22:29:04 +01:00
ip: remoteIp.split(',')[0],
2016-06-19 10:14:47 -07:00
successful: false,
});
2018-06-02 15:50:39 +00:00
if (ctx.req.headers.authorization && ctx.req.headers.authorization[0] === ':') {
2015-07-09 23:01:43 +01:00
debug('Logging in with token');
2018-06-02 15:50:39 +00:00
const userToken = await ctx.redis.get(ctx.req.headers.authorization.substr(1));
ctx.assert(userToken, 401, '{"error": {"message": "Invalid token.", "code": 606}}');
2015-07-09 23:01:43 +01:00
debug('Token found');
2019-06-08 07:52:57 -07:00
user = await models.user.findByPk(userToken);
2016-06-19 10:14:47 -07:00
if (!user) {
login.save();
return;
}
2015-07-09 23:01:43 +01:00
} else {
2018-06-02 15:50:39 +00:00
const authUser = auth(ctx);
ctx.assert(authUser, 401, badLoginMsg);
const count = await models.login.count({
2016-06-19 10:14:47 -07:00
where: {
2020-06-14 22:29:04 +01:00
ip: remoteIp.split(',')[0],
2016-06-19 10:14:47 -07:00
successful: false,
createdAt: {
2016-08-07 14:38:05 +01:00
$gt: new Date(Date.now() - 600000),
2016-06-19 10:14:47 -07:00
},
},
2016-06-06 15:37:00 +01:00
});
2016-06-19 10:14:47 -07:00
2018-06-02 18:07:00 +00:00
ctx.assert(
count < 25, 401,
'{"error": {"message": "Too many incorrect logins.", "code": 608}}',
);
2015-07-09 23:01:43 +01:00
2018-06-02 15:50:39 +00:00
user = await models.user.findOne({
2016-06-19 10:14:47 -07:00
where: {
email: authUser.name,
activated: true,
},
2016-06-06 15:37:00 +01:00
});
2016-06-19 10:14:47 -07:00
2018-06-02 15:50:39 +00:00
if (!user || !(await passwords.match(authUser.pass, user.password))) {
2016-06-19 10:14:47 -07:00
login.save();
2018-06-02 15:50:39 +00:00
ctx.throw(401, badLoginMsg);
2016-06-19 10:14:47 -07:00
return;
}
2015-07-09 23:01:43 +01:00
}
debug('Checking user');
2018-06-02 15:50:39 +00:00
ctx.assert(user, 401, badLoginMsg);
2015-07-09 23:01:43 +01:00
debug('Checking user is activated');
2016-06-19 10:14:47 -07:00
debug(user.activated);
2018-06-02 18:07:00 +00:00
ctx.assert(
user.activated === true, 401,
'{"error": {"message": "Account has not been activated.", "code": 603}}',
);
2015-07-09 23:01:43 +01:00
2016-06-19 10:14:47 -07:00
login.successful = true;
2018-06-02 15:50:39 +00:00
await login.save();
2016-06-19 10:14:47 -07:00
2018-06-02 15:50:39 +00:00
const uploadedTotal = await models.file.count({
2016-06-19 10:14:47 -07:00
where: {
userId: user.id,
},
});
2018-06-02 15:50:39 +00:00
const uploadedToday = await models.file.count({
2016-06-19 10:14:47 -07:00
where: {
userId: user.id,
createdAt: {
2016-08-07 14:38:05 +01:00
$gt: Date.now() - 86400000,
2016-06-19 10:14:47 -07:00
},
},
2016-06-06 15:37:00 +01:00
});
2015-07-09 23:01:43 +01:00
const normalisedUser = {
2016-06-19 10:14:47 -07:00
id: user.id,
2016-06-06 15:37:00 +01:00
email: user.email,
2016-06-19 10:14:47 -07:00
daily_upload_allowance: user.plan === 'Pro' ? 'unlimited' : 15,
2016-06-06 15:37:00 +01:00
file_count: uploadedTotal,
2016-06-19 10:14:47 -07:00
max_filesize: user.plan === 'Pro' ? 524288000 : 20971520,
plan: user.plan,
2016-06-06 15:37:00 +01:00
uploads_today: uploadedToday,
2015-07-09 23:01:43 +01:00
};
2018-06-02 18:07:00 +00:00
ctx.response.set(
'Daily-Uploads-Remaining',
user.type === 'Pro' ? 'unlimited' : 15 - uploadedToday,
);
2018-06-02 15:50:39 +00:00
ctx.user = normalisedUser;
debug('Authenticated user: ', ctx.user.email);
await next();
2018-06-02 18:07:00 +00:00
};