UNPKG

@vulcan-sql/serve

Version:

VulcanSQL package for serving projects

122 lines 5.49 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PasswordFileAuthenticator = void 0; const tslib_1 = require("tslib"); const fs = require("fs"); const readline = require("readline"); const bcrypt = require("bcryptjs"); const models_1 = require("../../models/index"); const core_1 = require("@vulcan-sql/core"); const lodash_1 = require("lodash"); require("koa-bodyparser"); /** The password-file authenticator. * * Setting the password file with {username}:{bcrypt-password} format, we use the bcrypt round 10. * Then authenticate by passing encode base64 {username}:{password} to authorization. */ let PasswordFileAuthenticator = class PasswordFileAuthenticator extends models_1.BaseAuthenticator { constructor() { super(...arguments); this.usersCredentials = {}; this.options = {}; } /** read password file and users info to initialize user credentials */ onActivate() { var e_1, _a; var _b; return tslib_1.__awaiter(this, void 0, void 0, function* () { this.options = this.getOptions() || this.options; const { path, users } = this.options; if (!path || !fs.existsSync(path) || !fs.statSync(path).isFile()) return; const reader = readline.createInterface({ input: fs.createReadStream(path), }); try { // <username>:<bcrypt-password> for (var reader_1 = tslib_1.__asyncValues(reader), reader_1_1; reader_1_1 = yield reader_1.next(), !reader_1_1.done;) { const line = reader_1_1.value; const name = line.split(':')[0] || ''; const bcryptPassword = line.split(':')[1] || ''; if (!(0, lodash_1.isEmpty)(bcryptPassword) && !bcryptPassword.startsWith('$2y$')) throw new core_1.ConfigurationError(`"${this.getExtensionId()}" type must bcrypt in file.`); // if users exist the same name, add attr to here, or as empty this.usersCredentials[name] = { bcryptPassword, attr: ((_b = users === null || users === void 0 ? void 0 : users.find((user) => user.name === name)) === null || _b === void 0 ? void 0 : _b.attr) || {}, }; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (reader_1_1 && !reader_1_1.done && (_a = reader_1.return)) yield _a.call(reader_1); } finally { if (e_1) throw e_1.error; } } }); } getTokenInfo(ctx) { return tslib_1.__awaiter(this, void 0, void 0, function* () { const username = ctx.request.body['username']; const password = ctx.request.body['password']; if (!username || !password) throw new core_1.UserError('please provide "username" and "password".'); const token = Buffer.from(`${username}:${password}`).toString('base64'); return { token: token, }; }); } authCredential(context) { return tslib_1.__awaiter(this, void 0, void 0, function* () { const incorrect = { status: models_1.AuthStatus.INDETERMINATE, type: this.getExtensionId(), }; // will not auth user if vulcan.yaml didn't configure this authenticator if ((0, lodash_1.isEmpty)(this.options) || !this.getOptions()) return incorrect; // validate request auth token const authorize = context.request.headers['authorization']; const token = authorize.trim().split(' ')[1]; const bareToken = Buffer.from(token, 'base64').toString(); try { return yield this.validate(bareToken); } catch (err) { // if not found matched user credential, return failed return { status: models_1.AuthStatus.FAIL, type: this.getExtensionId(), message: err.message, }; } }); } validate(baredToken) { return tslib_1.__awaiter(this, void 0, void 0, function* () { const username = baredToken.split(':')[0] || ''; // bare password in token const password = baredToken.split(':')[1] || ''; // if authenticated, return user data if (!(username in this.usersCredentials) || !bcrypt.compareSync(password, this.usersCredentials[username].bcryptPassword)) throw new core_1.UserError(`authenticate user by "${this.getExtensionId()}" type failed.`); return { status: models_1.AuthStatus.SUCCESS, type: this.getExtensionId(), user: { name: username, attr: this.usersCredentials[username].attr, }, }; }); } }; PasswordFileAuthenticator = tslib_1.__decorate([ (0, core_1.VulcanInternalExtension)('auth'), (0, core_1.VulcanExtensionId)(models_1.AuthType.PasswordFile) ], PasswordFileAuthenticator); exports.PasswordFileAuthenticator = PasswordFileAuthenticator; //# sourceMappingURL=passwordFileAuthenticator.js.map