require authentication on every login
gitea/salix/pipeline/head There was a failure building this commit
Details
gitea/salix/pipeline/head There was a failure building this commit
Details
This commit is contained in:
parent
9aaea7e8ed
commit
ef87dcc0f5
|
@ -1,9 +1,8 @@
|
||||||
const md5 = require('md5');
|
const md5 = require('md5');
|
||||||
const UserError = require('vn-loopback/util/user-error');
|
const UserError = require('vn-loopback/util/user-error');
|
||||||
const ForbiddenError = require('vn-loopback/util/forbiddenError');
|
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('login', {
|
Self.remoteMethod('login', {
|
||||||
description: 'Login a user with username/email and password',
|
description: 'Login a user with username/email and password',
|
||||||
accepts: [
|
accepts: [
|
||||||
{
|
{
|
||||||
|
@ -27,11 +26,13 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.login = async function(ctx, user, password) {
|
Self.login = async function(user, password) {
|
||||||
let $ = Self.app.models;
|
let $ = Self.app.models;
|
||||||
let token;
|
let token;
|
||||||
let usesEmail = user.indexOf('@') !== -1;
|
let usesEmail = user.indexOf('@') !== -1;
|
||||||
|
|
||||||
|
console.log(user, password);
|
||||||
|
|
||||||
let userInfo = usesEmail
|
let userInfo = usesEmail
|
||||||
? {email: user}
|
? {email: user}
|
||||||
: {username: user};
|
: {username: user};
|
||||||
|
@ -44,7 +45,7 @@ module.exports = Self => {
|
||||||
? {email: user}
|
? {email: user}
|
||||||
: {name: user};
|
: {name: user};
|
||||||
let account = await Self.findOne({
|
let account = await Self.findOne({
|
||||||
fields: ['id', 'active', 'email', 'password', 'twoFactor'],
|
fields: ['id', 'active', 'password'],
|
||||||
where
|
where
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -64,34 +65,6 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (account && account.twoFactor === 'email') {
|
|
||||||
const authAccess = await $.UserAccess.findOne({
|
|
||||||
where: {
|
|
||||||
userFk: account.id,
|
|
||||||
ip: ctx.req.connection.remoteAddress
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (!authAccess) {
|
|
||||||
const code = String(Math.floor(Math.random() * 999999));
|
|
||||||
const maxTTL = ((60 * 1000) * 5); // 5 min
|
|
||||||
await $.AuthCode.upsertWithWhere({userFk: account.id}, {
|
|
||||||
userFk: account.id,
|
|
||||||
code: code,
|
|
||||||
expires: Date.now() + maxTTL
|
|
||||||
});
|
|
||||||
|
|
||||||
const params = {
|
|
||||||
recipientId: account.id,
|
|
||||||
recipient: account.email,
|
|
||||||
code: code
|
|
||||||
};
|
|
||||||
ctx.args = {...ctx.args, ...params};
|
|
||||||
await Self.sendTemplate(ctx, 'auth-code');
|
|
||||||
|
|
||||||
throw new ForbiddenError('REQUIRES_2FA');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let loginInfo = Object.assign({password}, userInfo);
|
let loginInfo = Object.assign({password}, userInfo);
|
||||||
token = await $.User.login(loginInfo, 'user');
|
token = await $.User.login(loginInfo, 'user');
|
||||||
return {token: token.id};
|
return {token: token.id};
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
const ForbiddenError = require('vn-loopback/util/forbiddenError');
|
||||||
|
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethodCtx('signin', {
|
||||||
|
description: 'Login a user with username/email and password',
|
||||||
|
accepts: [
|
||||||
|
{
|
||||||
|
arg: 'user',
|
||||||
|
type: 'String',
|
||||||
|
description: 'The user name or email',
|
||||||
|
required: true
|
||||||
|
}, {
|
||||||
|
arg: 'password',
|
||||||
|
type: 'String',
|
||||||
|
description: 'The password'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
returns: {
|
||||||
|
type: 'object',
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/signin`,
|
||||||
|
verb: 'POST'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.signin = async function(ctx, user, password) {
|
||||||
|
const $ = Self.app.models;
|
||||||
|
const usesEmail = user.indexOf('@') !== -1;
|
||||||
|
|
||||||
|
const where = usesEmail
|
||||||
|
? {email: user}
|
||||||
|
: {name: user};
|
||||||
|
|
||||||
|
const account = await Self.findOne({
|
||||||
|
fields: ['id', 'active', 'email', 'password', 'twoFactor'],
|
||||||
|
where
|
||||||
|
});
|
||||||
|
|
||||||
|
if (account && account.twoFactor === 'email') {
|
||||||
|
const code = String(Math.floor(Math.random() * 999999));
|
||||||
|
const maxTTL = ((60 * 1000) * 5); // 5 min
|
||||||
|
await $.AuthCode.upsertWithWhere({userFk: account.id}, {
|
||||||
|
userFk: account.id,
|
||||||
|
code: code,
|
||||||
|
expires: Date.now() + maxTTL
|
||||||
|
});
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
recipientId: account.id,
|
||||||
|
recipient: account.email,
|
||||||
|
code: code
|
||||||
|
};
|
||||||
|
ctx.args = {...ctx.args, ...params};
|
||||||
|
await Self.sendTemplate(ctx, 'auth-code');
|
||||||
|
|
||||||
|
throw new ForbiddenError('REQUIRES_2FA');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $.models.login(user, password);
|
||||||
|
};
|
||||||
|
};
|
|
@ -68,6 +68,6 @@ module.exports = Self => {
|
||||||
|
|
||||||
await authCode.destroy();
|
await authCode.destroy();
|
||||||
|
|
||||||
return Self.login(ctx, username, password);
|
return Self.login(username, password);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,6 +4,7 @@ const LoopBackContext = require('loopback-context');
|
||||||
const {Email} = require('vn-print');
|
const {Email} = require('vn-print');
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
|
require('../methods/account/sign-in')(Self);
|
||||||
require('../methods/account/login')(Self);
|
require('../methods/account/login')(Self);
|
||||||
require('../methods/account/logout')(Self);
|
require('../methods/account/logout')(Self);
|
||||||
require('../methods/account/acl')(Self);
|
require('../methods/account/acl')(Self);
|
||||||
|
|
|
@ -89,7 +89,7 @@
|
||||||
},
|
},
|
||||||
"acls": [
|
"acls": [
|
||||||
{
|
{
|
||||||
"property": "login",
|
"property": "signin",
|
||||||
"accessType": "EXECUTE",
|
"accessType": "EXECUTE",
|
||||||
"principalType": "ROLE",
|
"principalType": "ROLE",
|
||||||
"principalId": "$everyone",
|
"principalId": "$everyone",
|
||||||
|
|
|
@ -59,7 +59,7 @@ export default class Auth {
|
||||||
password: password || undefined
|
password: password || undefined
|
||||||
};
|
};
|
||||||
|
|
||||||
return this.$http.post('Accounts/login', params).then(
|
return this.$http.post('Accounts/signin', params).then(
|
||||||
json => this.onLoginOk(json, remember));
|
json => this.onLoginOk(json, remember));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue