Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

homebridge-config-ui-x

Package Overview
Dependencies
Maintainers
1
Versions
2139
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

homebridge-config-ui-x - npm Package Compare versions

Comparing version 2.3.1 to 2.3.2

4

dist/app.js

@@ -55,3 +55,5 @@ "use strict";

console.error(err);
res.status(err.status || 500);
if (res.statusCode === 200) {
res.status(500);
}
res.json({

@@ -58,0 +60,0 @@ error: err,

@@ -11,14 +11,10 @@ "use strict";

this.passport.use(new passport_http_1.BasicStrategy((username, password, callback) => {
users_1.users.findByUsername(username, (err, user) => {
if (err) {
return callback(err);
}
return users_1.users.login(username, password)
.then((user) => {
if (!user) {
return callback(null, false);
}
if (user.hashedPassword !== users_1.users.hashPassword(password, username)) {
return callback(null, false);
}
return callback(null, user);
});
})
.catch((err) => callback(err, false));
}));

@@ -29,8 +25,10 @@ this.passport.serializeUser((user, callback) => {

this.passport.deserializeUser((id, callback) => {
users_1.users.findById(id, (err, user) => {
if (err) {
return callback(err);
return users_1.users.findById(id)
.then((user) => {
if (!user) {
return callback(null, false);
}
callback(null, user);
});
return callback(null, user);
})
.catch((err) => callback(err, false));
});

@@ -58,14 +56,22 @@ this.init = [

noAuthHandler(req, res, next) {
req.user = users_1.users.getUsers()[0];
next();
return users_1.users.getUsers()
.then((authfile) => {
req.user = authfile[0];
return next();
})
.catch(next);
}
formAuthHandler(req, res, next) {
if (req.headers['x-jwt']) {
users_1.users.verifyJwt(req.headers['x-jwt'], (err, user) => {
if (err) {
return users_1.users.verifyJwt(req.headers['x-jwt'])
.then((user) => {
if (user) {
req.user = user;
return next();
}
else {
return res.sendStatus(401);
}
req.user = user;
next();
});
})
.catch(() => res.sendStatus(401));
}

@@ -72,0 +78,0 @@ else {

@@ -23,4 +23,2 @@ "use strict";

hb_1.hb.init(log, config);
// ensure auth.json is setup correctly
users_1.users.setupAuthFile();
// bootstrap the server

@@ -31,2 +29,4 @@ this.bootstrap();

return __awaiter(this, void 0, void 0, function* () {
// ensure auth.json is setup correctly
yield users_1.users.setupAuthFile();
// dynamically load modules so app is only loaded if plugin is enabled

@@ -33,0 +33,0 @@ const { ExpressServer } = yield Promise.resolve().then(() => require('./app'));

@@ -11,16 +11,15 @@ "use strict";

login(req, res, next) {
users_1.users.findByUsername(req.body.username, (err, user) => {
if (err) {
return res.sendStatus(403);
}
return users_1.users.login(req.body.username, req.body.password)
.then((user) => {
if (!user) {
return res.sendStatus(403);
}
if (user.hashedPassword !== users_1.users.hashPassword(req.body.password, req.body.username)) {
return res.sendStatus(403);
}
return res.json({
token: users_1.users.getJwt(user)
return users_1.users.getJwt(user)
.then((token) => {
return res.json({
token: token
});
});
});
})
.catch(next);
}

@@ -27,0 +26,0 @@ }

@@ -61,5 +61,9 @@ "use strict";

getToken(req, res, next) {
return res.json({
token: users_1.users.getJwt(req.user)
});
return users_1.users.getJwt(req.user)
.then((token) => {
return res.json({
token: token
});
})
.catch(next);
}

@@ -66,0 +70,0 @@ }

@@ -14,26 +14,40 @@ "use strict";

getUser(req, res, next) {
let authfile = users_1.users.getUsers();
// remove user passwords before sending to client
authfile = authfile.map((user) => {
delete user.password;
return user;
});
res.json(authfile);
return users_1.users.getUsers()
.then((authfile) => {
// remove sensitive data before sending user list to client
authfile = authfile.map((user) => {
delete user.hashedPassword;
return user;
});
return res.json(authfile);
})
.catch(next);
}
createUser(req, res, next) {
const authfile = users_1.users.getUsers();
// check to see if user already exists
if (authfile.find(x => x.username === req.body.username)) {
return res.sendStatus(409);
}
users_1.users.addUser(req.body);
res.json({ ok: true });
return users_1.users.findByUsername(req.body.username)
.then((user) => {
if (user) {
return res.sendStatus(409);
}
return users_1.users.addUser(req.body)
.then(() => {
return res.json({ ok: true });
});
})
.catch(next);
}
deleteUser(req, res, next) {
users_1.users.deleteUser(req.params.id);
res.json({ ok: true });
return users_1.users.deleteUser(req.params.id)
.then(() => {
return res.json({ ok: true });
})
.catch(next);
}
updateUser(req, res, next) {
users_1.users.updateUser(parseInt(req.params.id, 10), req.body);
res.json({ ok: true });
return users_1.users.updateUser(parseInt(req.params.id, 10), req.body)
.then(() => {
return res.json({ ok: true });
})
.catch(next);
}

@@ -40,0 +54,0 @@ }

"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs = require("fs-extra");
const crypto = require("crypto");
const jwt = require("jsonwebtoken");
const cryptoNode = require("crypto");
const Bluebird = require("bluebird");
const jsonwebtoken = require("jsonwebtoken");
const crypto = Bluebird.promisifyAll(cryptoNode);
const jwt = Bluebird.promisifyAll(jsonwebtoken);
const hb_1 = require("./hb");
class Users {
findById(id, callback) {
const authfile = this.getUsers();
const user = authfile.find(x => x.id === id);
if (user) {
callback(null, user);
}
else {
callback(new Error('User ' + id + ' does not exist'));
}
getUsers() {
return __awaiter(this, void 0, void 0, function* () {
const allUsers = yield fs.readJson(hb_1.hb.authPath);
return allUsers;
});
}
findByUsername(username, callback) {
const authfile = this.getUsers();
const user = authfile.find(x => x.username === username);
if (user) {
callback(null, user);
}
else {
callback(null, null);
}
findById(id) {
return __awaiter(this, void 0, void 0, function* () {
const authfile = yield this.getUsers();
const user = authfile.find(x => x.id === id);
return user;
});
}
getUsers() {
return fs.readJsonSync(hb_1.hb.authPath);
findByUsername(username) {
return __awaiter(this, void 0, void 0, function* () {
const authfile = yield this.getUsers();
const user = authfile.find(x => x.username === username);
return user;
});
}
hashPassword(password, salt) {
// pbkdf2 iterations have been kept low so we don't lock up homebridge when a user logs in on low powered devices
// we're using the username as the salt for the sake of keeping the module portable
const derivedKey = crypto.pbkdf2Sync(password, salt, 1000, 64, 'sha512');
return derivedKey.toString('hex');
return __awaiter(this, void 0, void 0, function* () {
const derivedKey = yield crypto.pbkdf2Async(password, salt, 1000, 64, 'sha512');
return derivedKey.toString('hex');
});
}
genSalt() {
return __awaiter(this, void 0, void 0, function* () {
const salt = yield crypto.randomBytesAsync(32);
return salt.toString('hex');
});
}
login(username, password) {
return __awaiter(this, void 0, void 0, function* () {
const user = yield this.findByUsername(username);
if (!user) {
return null;
}
// using username as salt if user.salt not set to maintain backwards compatibility with older versions.
const hashedPassword = yield this.hashPassword(password, user.salt || user.username);
if (hashedPassword === user.hashedPassword) {
return user;
}
else {
return null;
}
});
}
addUser(user) {
const authfile = this.getUsers();
// user object
const newuser = {
id: authfile.length ? Math.max.apply(Math, authfile.map(x => x.id)) + 1 : 1,
username: user.username,
name: user.name,
hashedPassword: this.hashPassword(user.password, user.username),
admin: user.admin
};
// add the user to the authfile
authfile.push(newuser);
// update the auth.json
fs.writeFileSync(hb_1.hb.authPath, JSON.stringify(authfile, null, 4));
hb_1.hb.log(`Added new user: ${user.username}`);
return __awaiter(this, void 0, void 0, function* () {
const authfile = yield this.getUsers();
const salt = yield this.genSalt();
// user object
const newUser = {
id: authfile.length ? Math.max.apply(Math, authfile.map(x => x.id)) + 1 : 1,
username: user.username,
name: user.name,
hashedPassword: yield this.hashPassword(user.password, salt),
salt: salt,
admin: user.admin
};
// add the user to the authfile
authfile.push(newUser);
// update the auth.json
yield fs.writeJson(hb_1.hb.authPath, authfile, { spaces: 4 });
hb_1.hb.log(`Added new user: ${user.username}`);
});
}
updateUser(userId, update) {
const authfile = this.getUsers();
const user = authfile.find(x => x.id === userId);
if (!user) {
throw new Error('User not gound');
}
user.name = update.name || user.name;
user.admin = update.admin || user.admin;
if (update.password) {
user.hashedPassword = this.hashPassword(update.password, user.username);
}
// update the auth.json
fs.writeFileSync(hb_1.hb.authPath, JSON.stringify(authfile, null, 4));
hb_1.hb.log(`Updated user: ${user.username}`);
return __awaiter(this, void 0, void 0, function* () {
const authfile = yield this.getUsers();
const user = authfile.find(x => x.id === userId);
if (!user) {
throw new Error('User Not Found');
}
user.name = update.name || user.name;
user.admin = update.admin || user.admin;
if (update.password) {
const salt = yield this.genSalt();
user.hashedPassword = yield this.hashPassword(update.password, salt);
user.salt = salt;
}
// update the auth.json
yield fs.writeJson(hb_1.hb.authPath, authfile, { spaces: 4 });
hb_1.hb.log(`Updated user: ${user.username}`);
});
}
deleteUser(id) {
const authfile = this.getUsers();
const index = authfile.findIndex(x => x.id === parseInt(id, 10));
if (index < 0) {
throw new Error('User not found');
}
authfile.splice(index, 1);
// update the auth.json
fs.writeFileSync(hb_1.hb.authPath, JSON.stringify(authfile, null, 4));
hb_1.hb.log(`Deleted user with ID ${id}`);
return __awaiter(this, void 0, void 0, function* () {
const authfile = yield this.getUsers();
const index = authfile.findIndex(x => x.id === parseInt(id, 10));
if (index < 0) {
throw new Error('User not found');
}
authfile.splice(index, 1);
// update the auth.json
yield fs.writeJson(hb_1.hb.authPath, authfile, { spaces: 4 });
hb_1.hb.log(`Deleted user with ID ${id}`);
});
}
getJwt(user) {
return jwt.sign({
username: user.username,
name: user.name,
admin: user.admin
}, user.hashedPassword, { expiresIn: '8h' });
return __awaiter(this, void 0, void 0, function* () {
return jwt.signAsync({
username: user.username,
name: user.name,
admin: user.admin
}, user.hashedPassword, { expiresIn: '8h' });
});
}
verifyJwt(token, callback) {
const authfile = this.getUsers();
const decoded = jwt.decode(token);
if (!decoded) {
return callback(new Error('User Not Found'));
}
const user = authfile.find(x => x.username === decoded.username);
if (user) {
jwt.verify(token, user.hashedPassword, (err, res) => {
return callback(err, user);
});
}
else {
return callback(new Error('User Not Found'));
}
}
updateOldPasswords() {
let authfile = this.getUsers();
authfile = authfile.map((user) => {
if (user.password && !user.hashedPassword) {
user.hashedPassword = this.hashPassword(user.password, user.username);
delete user.password;
return user;
verifyJwt(token) {
return __awaiter(this, void 0, void 0, function* () {
const decoded = jwt.decode(token);
if (!decoded) {
return null;
}
const user = yield this.findByUsername(decoded.username);
if (user) {
try {
yield jwt.verifyAsync(token, user.hashedPassword);
return user;
}
catch (e) {
hb_1.hb.log(`Invalid token sent by ${user.username}: ${e.message}`);
return null;
}
}
else {
return user;
return null;
}
});
fs.writeFileSync(hb_1.hb.authPath, JSON.stringify(authfile, null, 4));
}
updateOldPasswords() {
return __awaiter(this, void 0, void 0, function* () {
let authfile = yield this.getUsers();
authfile = yield Bluebird.map(authfile, (user) => __awaiter(this, void 0, void 0, function* () {
if (user.password && !user.hashedPassword) {
const salt = yield this.genSalt();
user.hashedPassword = yield this.hashPassword(user.password, salt);
user.salt = salt;
delete user.password;
hb_1.hb.log(`Hashed password for "${user.username}" in auth.json`);
return user;
}
else {
return user;
}
}));
// update the auth.json
yield fs.writeJson(hb_1.hb.authPath, authfile, { spaces: 4 });
});
}
setupDefaultUser() {
return this.addUser({
'username': 'admin',
'password': 'admin',
'name': 'Administrator',
'admin': true
return __awaiter(this, void 0, void 0, function* () {
return this.addUser({
'username': 'admin',
'password': 'admin',
'name': 'Administrator',
'admin': true
});
});
}
setupAuthFile() {
if (!fs.existsSync(hb_1.hb.authPath)) {
fs.writeFileSync(hb_1.hb.authPath, '[]');
}
const authfile = this.getUsers();
// if there are no admin users, add the default user
if (!authfile.find(x => x.admin === true || x.username === 'admin')) {
this.setupDefaultUser();
}
// update older auth.json files from plain text to hashed passwords
if (authfile.find(x => x.password && !x.hashedPassword)) {
this.updateOldPasswords();
}
return __awaiter(this, void 0, void 0, function* () {
if (!(yield fs.pathExists(hb_1.hb.authPath))) {
yield fs.writeJson(hb_1.hb.authPath, []);
}
const authfile = yield this.getUsers();
// if there are no admin users, add the default user
if (!authfile.find(x => x.admin === true || x.username === 'admin')) {
yield this.setupDefaultUser();
}
// update older auth.json files from plain text to hashed passwords
if (authfile.find(x => x.password && !x.hashedPassword)) {
yield this.updateOldPasswords();
}
});
}

@@ -138,0 +196,0 @@ }

@@ -46,15 +46,20 @@ "use strict";

if (params.token) {
users_1.users.verifyJwt(params.token, (err) => {
if (err) {
return users_1.users.verifyJwt(params.token)
.then((user) => {
if (user) {
return callback(true);
}
else {
// invalid token - reject the websocket connection
hb_1.hb.log('Unauthorised WebSocket Connection Closed');
callback(false);
return callback(false);
}
});
})
.catch(() => callback(false));
}
else {
// no token provided - reject the websocket connection
callback(false);
hb_1.hb.log('Unauthorised WebSocket Connection Closed');
return callback(false);
}
callback(true);
}

@@ -61,0 +66,0 @@ subscribeHandler(ws, req, msg) {

{
"name": "homebridge-config-ui-x",
"version": "2.3.1",
"version": "2.3.2",
"description": "Configuration UI plugin for Homebridge",

@@ -5,0 +5,0 @@ "license": "MIT",

@@ -75,3 +75,7 @@ import * as path from 'path';

console.error(err);
res.status(err.status || 500);
if (res.statusCode === 200) {
res.status(500);
}
res.json({

@@ -78,0 +82,0 @@ error: err,

@@ -18,17 +18,11 @@ import { Passport } from 'passport';

this.passport.use(new BasicStrategy((username, password, callback) => {
users.findByUsername(username, (err, user) => {
if (err) {
return callback(err);
}
return users.login(username, password)
.then((user) => {
if (!user) {
return callback(null, false);
}
if (!user) {
return callback(null, false);
}
if (user.hashedPassword !== users.hashPassword(password, username)) {
return callback(null, false);
}
return callback(null, user);
});
return callback(null, user);
})
.catch((err) => callback(err, false));
}));

@@ -41,9 +35,11 @@

this.passport.deserializeUser((id, callback) => {
users.findById(id, (err, user) => {
if (err) {
return callback(err);
}
return users.findById(id)
.then((user) => {
if (!user) {
return callback(null, false);
}
callback(null, user);
});
return callback(null, user);
})
.catch((err) => callback(err, false));
});

@@ -72,4 +68,8 @@

noAuthHandler (req: Request, res: Response, next: NextFunction) {
req.user = users.getUsers()[0];
next();
return users.getUsers()
.then((authfile) => {
req.user = authfile[0];
return next();
})
.catch(next);
}

@@ -79,9 +79,12 @@

if (req.headers['x-jwt']) {
users.verifyJwt(req.headers['x-jwt'], (err, user) => {
if (err) {
return res.sendStatus(401);
}
req.user = user;
next();
});
return users.verifyJwt(req.headers['x-jwt'])
.then((user) => {
if (user) {
req.user = user;
return next();
} else {
return res.sendStatus(401);
}
})
.catch(() => res.sendStatus(401));
} else {

@@ -88,0 +91,0 @@ return res.sendStatus(401);

@@ -20,5 +20,2 @@ import 'source-map-support/register';

// ensure auth.json is setup correctly
users.setupAuthFile();
// bootstrap the server

@@ -29,2 +26,5 @@ this.bootstrap();

async bootstrap () {
// ensure auth.json is setup correctly
await users.setupAuthFile();
// dynamically load modules so app is only loaded if plugin is enabled

@@ -31,0 +31,0 @@ const { ExpressServer } = await import('./app');

@@ -15,20 +15,17 @@ import { Router, Request, Response, NextFunction } from 'express';

login (req: Request, res: Response, next: NextFunction) {
users.findByUsername(req.body.username, (err, user) => {
if (err) {
return res.sendStatus(403);
}
return users.login(req.body.username, req.body.password)
.then((user) => {
if (!user) {
return res.sendStatus(403);
}
if (!user) {
return res.sendStatus(403);
}
if (user.hashedPassword !== users.hashPassword(req.body.password, req.body.username)) {
return res.sendStatus(403);
}
return res.json({
token: users.getJwt(user)
});
});
return users.getJwt(user)
.then((token) => {
return res.json({
token: token
});
});
})
.catch(next);
}
}

@@ -72,6 +72,10 @@ import * as qr from 'qr-image';

getToken (req: Request, res: Response, next: NextFunction) {
return res.json({
token: users.getJwt(req.user)
});
return users.getJwt(req.user)
.then((token) => {
return res.json({
token: token
});
})
.catch(next);
}
}

@@ -18,35 +18,46 @@ import { Router, Request, Response, NextFunction } from 'express';

getUser (req: Request, res: Response, next: NextFunction) {
let authfile = users.getUsers();
return users.getUsers()
.then((authfile) => {
// remove sensitive data before sending user list to client
authfile = authfile.map((user) => {
delete user.hashedPassword;
return user;
});
// remove user passwords before sending to client
authfile = authfile.map((user) => {
delete user.password;
return user;
});
res.json(authfile);
return res.json(authfile);
})
.catch(next);
}
createUser (req: Request, res: Response, next: NextFunction) {
const authfile = users.getUsers();
// check to see if user already exists
if (authfile.find(x => x.username === req.body.username)) {
return res.sendStatus(409);
}
return users.findByUsername(req.body.username)
.then((user) => {
if (user) {
return res.sendStatus(409);
}
users.addUser(req.body);
res.json({ ok: true });
return users.addUser(req.body)
.then(() => {
return res.json({ ok: true });
});
})
.catch(next);
}
deleteUser (req: Request, res: Response, next: NextFunction) {
users.deleteUser(req.params.id);
res.json({ ok: true });
return users.deleteUser(req.params.id)
.then(() => {
return res.json({ ok: true });
})
.catch(next);
}
updateUser (req: Request, res: Response, next: NextFunction) {
users.updateUser(parseInt(req.params.id, 10), req.body);
res.json({ ok: true });
return users.updateUser(parseInt(req.params.id, 10), req.body)
.then(() => {
return res.json({ ok: true });
})
.catch(next);
}
}
import * as fs from 'fs-extra';
import * as crypto from 'crypto';
import * as jwt from 'jsonwebtoken';
import * as cryptoNode from 'crypto';
import * as Bluebird from 'bluebird';
import * as jsonwebtoken from 'jsonwebtoken';
const crypto = Bluebird.promisifyAll(cryptoNode);
const jwt = Bluebird.promisifyAll(jsonwebtoken);
import { hb } from './hb';
interface User {
id: number;
name: string;
username: string;
admin: boolean;
hashedPassword: string;
salt: string;
password?: string;
}
class Users {
findById (id, callback) {
const authfile = this.getUsers();
async getUsers () {
const allUsers: User[] = await fs.readJson(hb.authPath);
return allUsers;
}
async findById (id: number) {
const authfile = await this.getUsers();
const user = authfile.find(x => x.id === id);
return user;
}
if (user) {
callback(null, user);
} else {
callback(new Error('User ' + id + ' does not exist'));
}
async findByUsername (username: string) {
const authfile = await this.getUsers();
const user = authfile.find(x => x.username === username);
return user;
}
findByUsername (username, callback) {
const authfile = this.getUsers();
async hashPassword (password: string, salt: string) {
const derivedKey = await crypto.pbkdf2Async(password, salt, 1000, 64, 'sha512');
return derivedKey.toString('hex');
}
const user = authfile.find(x => x.username === username);
async genSalt () {
const salt = await crypto.randomBytesAsync(32);
return salt.toString('hex');
}
if (user) {
callback(null, user);
async login (username: string, password: string) {
const user = await this.findByUsername(username);
if (!user) {
return null;
}
// using username as salt if user.salt not set to maintain backwards compatibility with older versions.
const hashedPassword = await this.hashPassword(password, user.salt || user.username);
if (hashedPassword === user.hashedPassword) {
return user;
} else {
callback(null, null);
return null;
}
}
getUsers () {
return fs.readJsonSync(hb.authPath);
}
async addUser (user) {
const authfile = await this.getUsers();
hashPassword (password, salt) {
// pbkdf2 iterations have been kept low so we don't lock up homebridge when a user logs in on low powered devices
// we're using the username as the salt for the sake of keeping the module portable
const derivedKey = crypto.pbkdf2Sync(password, salt, 1000, 64, 'sha512');
return derivedKey.toString('hex');
}
const salt = await this.genSalt();
addUser (user) {
const authfile = this.getUsers();
// user object
const newuser = {
const newUser: User = {
id: authfile.length ? Math.max.apply(Math, authfile.map(x => x.id)) + 1 : 1,
username: user.username,
name: user.name,
hashedPassword: this.hashPassword(user.password, user.username),
hashedPassword: await this.hashPassword(user.password, salt),
salt: salt,
admin: user.admin

@@ -56,6 +82,6 @@ };

// add the user to the authfile
authfile.push(newuser);
authfile.push(newUser);
// update the auth.json
fs.writeFileSync(hb.authPath, JSON.stringify(authfile, null, 4));
await fs.writeJson(hb.authPath, authfile, {spaces: 4});

@@ -65,4 +91,4 @@ hb.log(`Added new user: ${user.username}`);

updateUser (userId, update) {
const authfile = this.getUsers();
async updateUser (userId, update) {
const authfile = await this.getUsers();

@@ -72,3 +98,3 @@ const user = authfile.find(x => x.id === userId);

if (!user) {
throw new Error('User not gound');
throw new Error('User Not Found');
}

@@ -80,7 +106,10 @@

if (update.password) {
user.hashedPassword = this.hashPassword(update.password, user.username);
const salt = await this.genSalt();
user.hashedPassword = await this.hashPassword(update.password, salt);
user.salt = salt;
}
// update the auth.json
fs.writeFileSync(hb.authPath, JSON.stringify(authfile, null, 4));
await fs.writeJson(hb.authPath, authfile, { spaces: 4 });

@@ -90,6 +119,7 @@ hb.log(`Updated user: ${user.username}`);

deleteUser (id) {
const authfile = this.getUsers();
async deleteUser (id) {
const authfile = await this.getUsers();
const index = authfile.findIndex(x => x.id === parseInt(id, 10));
if (index < 0) {

@@ -102,3 +132,3 @@ throw new Error('User not found');

// update the auth.json
fs.writeFileSync(hb.authPath, JSON.stringify(authfile, null, 4));
await fs.writeJson(hb.authPath, authfile, { spaces: 4 });

@@ -108,4 +138,4 @@ hb.log(`Deleted user with ID ${id}`);

getJwt (user) {
return jwt.sign({
async getJwt (user) {
return jwt.signAsync({
username: user.username,

@@ -117,28 +147,37 @@ name: user.name,

verifyJwt (token, callback) {
const authfile = this.getUsers();
async verifyJwt (token) {
const decoded = jwt.decode(token);
if (!decoded) {
return callback(new Error('User Not Found'));
return null;
}
const user = authfile.find(x => x.username === decoded.username);
const user = await this.findByUsername(decoded.username);
if (user) {
jwt.verify(token, user.hashedPassword, (err, res) => {
return callback(err, user);
});
try {
await jwt.verifyAsync(token, user.hashedPassword);
return user;
} catch (e) {
hb.log(`Invalid token sent by ${user.username}: ${e.message}`);
return null;
}
} else {
return callback(new Error('User Not Found'));
return null;
}
}
updateOldPasswords () {
let authfile = this.getUsers();
async updateOldPasswords () {
let authfile = await this.getUsers();
authfile = authfile.map((user) => {
authfile = await Bluebird.map(authfile, async (user) => {
if (user.password && !user.hashedPassword) {
user.hashedPassword = this.hashPassword(user.password, user.username);
const salt = await this.genSalt();
user.hashedPassword = await this.hashPassword(user.password, salt);
user.salt = salt;
delete user.password;
hb.log(`Hashed password for "${user.username}" in auth.json`);
return user;

@@ -150,6 +189,7 @@ } else {

fs.writeFileSync(hb.authPath, JSON.stringify(authfile, null, 4));
// update the auth.json
await fs.writeJson(hb.authPath, authfile, { spaces: 4 });
}
setupDefaultUser () {
async setupDefaultUser () {
return this.addUser({

@@ -163,12 +203,12 @@ 'username': 'admin',

setupAuthFile () {
if (!fs.existsSync(hb.authPath)) {
fs.writeFileSync(hb.authPath, '[]');
async setupAuthFile () {
if (!await fs.pathExists(hb.authPath)) {
await fs.writeJson(hb.authPath, []);
}
const authfile = this.getUsers();
const authfile = await this.getUsers();
// if there are no admin users, add the default user
if (!authfile.find(x => x.admin === true || x.username === 'admin')) {
this.setupDefaultUser();
await this.setupDefaultUser();
}

@@ -178,3 +218,3 @@

if (authfile.find(x => x.password && !x.hashedPassword)) {
this.updateOldPasswords();
await this.updateOldPasswords();
}

@@ -181,0 +221,0 @@ }

@@ -53,14 +53,18 @@ import * as url from 'url';

if (params.token) {
users.verifyJwt(params.token, (err) => {
if (err) {
// invalid token - reject the websocket connection
hb.log('Unauthorised WebSocket Connection Closed');
callback(false);
}
});
return users.verifyJwt(params.token)
.then((user) => {
if (user) {
return callback(true);
} else {
// invalid token - reject the websocket connection
hb.log('Unauthorised WebSocket Connection Closed');
return callback(false);
}
})
.catch(() => callback(false));
} else {
// no token provided - reject the websocket connection
callback(false);
hb.log('Unauthorised WebSocket Connection Closed');
return callback(false);
}
callback(true);
}

@@ -67,0 +71,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc