fixed authlog previous paging

This commit is contained in:
Andris Reinman 2017-07-29 22:08:43 +03:00
parent 1b10664e56
commit ea4b038f73
6 changed files with 52 additions and 12 deletions

View file

@ -432,6 +432,7 @@ This call prepares the user to support 2FA tokens. If 2FA is already enabled the
- **user** (required) is the ID of the user
- **issuer** is the name to be shown in the Authenticator App
- **fresh** is a boolean. If true then generates a new seed even if an old one already exists
- **ip** is the IP address the request was made from
**Response fields**

View file

@ -10,6 +10,7 @@ module.exports = (db, server, userHandler) => {
const schema = Joi.object().keys({
user: Joi.string().hex().lowercase().length(24).required(),
issuer: Joi.string().trim().max(255).required(),
fresh: Joi.boolean().truthy(['Y', 'true', 'yes', 1]).default(false),
ip: Joi.string().ip({
version: ['ipv4', 'ipv6'],
cidr: 'forbidden'

View file

@ -116,6 +116,10 @@ module.exports = (db, server, userHandler) => {
let generateMobileconfig = result.value.generateMobileconfig;
let scopes = result.value.scopes || ['*'];
if (scopes.includes('*')) {
scopes = ['*'];
}
if (generateMobileconfig && !scopes.includes('*') && (!scopes.includes('imap') || !scopes.includes('smtp'))) {
res.json({
error: 'Profile file requires imap and smtp scopes'

View file

@ -72,9 +72,9 @@ module.exports = (db, server, userHandler) => {
user: Joi.string().hex().lowercase().length(24).required(),
action: Joi.string().trim().lowercase().empty('').max(100),
limit: Joi.number().default(20).min(1).max(250),
next: Joi.string().alphanum().max(100),
prev: Joi.string().alphanum().max(100),
page: Joi.number().default(1)
next: Joi.string().empty('').alphanum().max(100),
previous: Joi.string().empty('').alphanum().max(100),
page: Joi.number().empty('').default(1)
});
req.query.user = req.params.user;
@ -82,7 +82,7 @@ module.exports = (db, server, userHandler) => {
const result = Joi.validate(req.query, schema, {
abortEarly: false,
convert: true,
allowUnknown: true
allowUnknown: false
});
if (result.error) {
@ -97,7 +97,7 @@ module.exports = (db, server, userHandler) => {
let action = result.value.action;
let page = result.value.page;
let pageNext = result.value.next;
let pagePrev = result.value.prev;
let pagePrevious = result.value.previous;
db.users.collection('users').findOne({
_id: user
@ -144,8 +144,8 @@ module.exports = (db, server, userHandler) => {
if (pageNext) {
opts.next = pageNext;
} else if (pagePrev) {
opts.prev = pagePrev;
} else if (pagePrevious) {
opts.previous = pagePrevious;
}
MongoPaging.find(db.users.collection('authlog'), opts, (err, result) => {
@ -177,7 +177,9 @@ module.exports = (db, server, userHandler) => {
total,
page,
prev: prevUrl,
previousCursor: result.hasPrevious ? result.previous : false,
next: nextUrl,
nextCursor: result.hasNext ? result.next : false,
results: (result.results || []).map(resultData => {
let response = {
id: resultData._id

View file

@ -256,6 +256,9 @@ module.exports = (db, server, userHandler) => {
enabled2fa: userData.enabled2fa,
forward: userData.forward,
targetUrl: userData.targetUrl,
limits: {
quota: {
allowed: Number(userData.quota) || config.maxStorage * 1024 * 1024,
@ -288,14 +291,14 @@ module.exports = (db, server, userHandler) => {
const schema = Joi.object().keys({
user: Joi.string().hex().lowercase().length(24).required(),
existingPassword: Joi.string().min(1).max(256),
existingPassword: Joi.string().empty('').min(1).max(256),
password: Joi.string().min(8).max(256),
language: Joi.string().min(2).max(20).lowercase(),
name: Joi.string().max(256),
forward: Joi.string().email(),
targetUrl: Joi.string().max(256),
name: Joi.string().empty('').max(256),
forward: Joi.string().empty('').email(),
targetUrl: Joi.string().empty('').max(256),
retention: Joi.number().min(0),
quota: Joi.number().min(0),
@ -330,6 +333,16 @@ module.exports = (db, server, userHandler) => {
let user = new ObjectID(result.value.user);
if (forward) {
result.value.forward = forward;
} else if (!result.value.forward && 'forward' in req.params) {
result.value.forward = '';
}
if (!result.value.targetUrl && 'targetUrl' in req.params) {
result.value.targetUrl = '';
}
if (!result.value.name && 'name' in req.params) {
result.value.name = '';
}
userHandler.update(user, result.value, (err, success) => {

View file

@ -12,6 +12,7 @@ const generatePassword = require('generate-password');
const os = require('os');
const crypto = require('crypto');
const mailboxTranslations = require('./translations');
const base32 = require('base32.js');
class UserHandler {
constructor(options) {
@ -499,7 +500,8 @@ class UserHandler {
}, {
fields: {
username: true,
enabled2fa: true
enabled2fa: true,
seed: true
}
}, (err, userData) => {
if (err) {
@ -515,6 +517,23 @@ class UserHandler {
return callback(new Error('2FA is already enabled for this user'));
}
if (!data.fresh && userData.seed) {
if (userData.seed) {
let otpauth_url = speakeasy.otpauthURL({
secret: base32.decode(userData.seed),
label: userData.username,
issuer: data.issuer || 'Wild Duck'
});
return QRCode.toDataURL(otpauth_url, (err, data_url) => {
if (err) {
log.error('DB', 'QRFAIL username=%s error=%s', userData.username, err.message);
return callback(new Error('Failed to generate QR code'));
}
return callback(null, data_url);
});
}
}
let secret = speakeasy.generateSecret({
length: 20,
name: userData.username