add accounts
This commit is contained in:
parent
99e5bdcff5
commit
5e82f06032
|
@ -34,6 +34,11 @@ const structure = {
|
||||||
gpgkey: {
|
gpgkey: {
|
||||||
type: DataTypes.TEXT,
|
type: DataTypes.TEXT,
|
||||||
allowNull: false
|
allowNull: false
|
||||||
|
},
|
||||||
|
accessLevel: {
|
||||||
|
type: DataTypes.SMALLINT,
|
||||||
|
allowNull: false,
|
||||||
|
defaultValue: 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
User.structure = structure
|
User.structure = structure
|
||||||
|
|
|
@ -0,0 +1,117 @@
|
||||||
|
process.env.DEBUG = undefined;
|
||||||
|
|
||||||
|
const db = require('../models');
|
||||||
|
const args = require('args-parser')(process.argv);
|
||||||
|
const { authenticator } = require('otplib');
|
||||||
|
const path = require('path');
|
||||||
|
const crypto = require('crypto');
|
||||||
|
const qrcode = require('qrcode-terminal');
|
||||||
|
const prompt = require('prompt-sync')({ sigint: true, eot: true });
|
||||||
|
const bcrypt = require('bcrypt')
|
||||||
|
|
||||||
|
if (args['help']) {
|
||||||
|
console.log(path.basename(__filename) + ' [--pass] [--login] [--email] [--gpgkey] [--dry-run] [--no-interactive|-n] [--totp] [--set-totp] [--set-totp-recovery]');
|
||||||
|
console.log(
|
||||||
|
' --pass: Set password.\n' +
|
||||||
|
' --login: Set login.\n' +
|
||||||
|
' --email: Set email.\n' +
|
||||||
|
' --gpgkey: Set path to your GPG key.\n' +
|
||||||
|
' --dry-run: Don\'t do anything, but simulate like something is done.\n' +
|
||||||
|
' --no-interactive -n: Disable prompts. Designed for script usage.\n' +
|
||||||
|
' --totp: Add TOTP to the account. QR code and recovery codes would be printed to terminal.\n' +
|
||||||
|
' --set-totp: Set TOTP key. Designed for script usage.\n' +
|
||||||
|
' --set-totp-recovery: Set TOTP recovery keys (comma separated).'
|
||||||
|
)
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function exit_error(error, exitCode) {
|
||||||
|
if (!exitCode) exitCode = -1;
|
||||||
|
console.error(error);
|
||||||
|
process.exit(exitCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
let interactive = true;
|
||||||
|
if (args['no-interactive']) interactive = false;
|
||||||
|
|
||||||
|
// get data
|
||||||
|
let password, login, email, gpgkey;
|
||||||
|
let totpkey, totprecover, totpurl;
|
||||||
|
if (args['pass']) {
|
||||||
|
password = args['pass'];
|
||||||
|
} else if (interactive) {
|
||||||
|
// node does not provide a way to
|
||||||
|
// get a password with hidden stdin
|
||||||
|
password = prompt('Password: ');
|
||||||
|
console.clear();
|
||||||
|
} else exit_error('No password supplied.');
|
||||||
|
|
||||||
|
if (args['login']) {
|
||||||
|
login = args['login'];
|
||||||
|
} else if (interactive) {
|
||||||
|
login = prompt('Login: ');
|
||||||
|
} else exit_error('No login supplied.');
|
||||||
|
|
||||||
|
if (args['email']) {
|
||||||
|
email = args['email'];
|
||||||
|
} else if (interactive) {
|
||||||
|
email = prompt('Email: ');
|
||||||
|
} else exit_error('No email supplied.');
|
||||||
|
|
||||||
|
if (args['gpgkey']) {
|
||||||
|
gpgkey = require('fs').readFileSync(args['gpgkey'], {encoding: 'utf-8'}).toString();
|
||||||
|
} else if (interactive) {
|
||||||
|
gpgkey = prompt('Paste your GPG key:\n');
|
||||||
|
} else exit_error('No GPG key supplied.')
|
||||||
|
|
||||||
|
if (args['totp']) {
|
||||||
|
totpkey = authenticator.generateSecret(32);
|
||||||
|
totprecover = [];
|
||||||
|
for (let i = 0; i != 6; i++) {
|
||||||
|
totprecover[i] = crypto.randomInt(11111111, 99999999);
|
||||||
|
}
|
||||||
|
|
||||||
|
totpkey = args['set-totp'] ? args['set-totp'] : totpkey;
|
||||||
|
totprecover = args['set-totp-recovery'] ? args['set-totp-recovery'].split(',') : totprecover;
|
||||||
|
|
||||||
|
totpurl = `otpauth://totp/blek/${login}@blek.codes?secret=${totpkey}&issuer=blek`;
|
||||||
|
qrcode.generate(totpurl);
|
||||||
|
console.log('Totp URL: ' + totpurl);
|
||||||
|
console.log('Recovery keys:');
|
||||||
|
for (let i = 0; i <= totprecover.length - 2; i+= 2) {
|
||||||
|
console.log(' ' + totprecover[i] + ', ' + totprecover[i+1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
password = '' + password;
|
||||||
|
|
||||||
|
// insert data
|
||||||
|
if (args['dry-run']) {
|
||||||
|
console.log('All done');
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const salt = bcrypt.genSaltSync(12);
|
||||||
|
const pass = bcrypt.hashSync(password, salt);
|
||||||
|
|
||||||
|
|
||||||
|
async function create() {
|
||||||
|
const data = await db.User.findAndCountAll({where: {login}});
|
||||||
|
if (data.count !== 0) {
|
||||||
|
console.error('User with this login already exists.');
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = await db.User.create({
|
||||||
|
login,
|
||||||
|
email,
|
||||||
|
pass,
|
||||||
|
accessLevel: 4,
|
||||||
|
gpgkey,
|
||||||
|
totp: totpkey,
|
||||||
|
totpRec: totprecover ? totprecover.join(',') : undefined
|
||||||
|
});
|
||||||
|
console.log('All done');
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
create();
|
|
@ -9,6 +9,8 @@
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"args-parser": "^1.3.0"
|
"args-parser": "^1.3.0",
|
||||||
|
"prompt-sync": "^4.2.0",
|
||||||
|
"qrcode-terminal": "^0.12.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue