Added ability to set a pin for settings menu

This commit is contained in:
Tzahi12345
2023-04-27 21:37:32 -04:00
parent f973426bd2
commit 010f0fbb1c
150 changed files with 482 additions and 152 deletions

View File

@@ -742,6 +742,18 @@ const optionalJwt = async function (req, res, next) {
return next();
};
const optionalPin = async function (req, res, next) {
const use_pin = config_api.getConfigItem('ytdl_use_pin');
if (use_pin && req.path.includes('/api/setConfig')) {
if (!req.query.pin_token) {
res.sendStatus(418); // I'm a teapot (RFC 2324)
return;
}
return next();
}
return next();
};
app.get('/api/config', function(req, res) {
let config_file = config_api.getConfigFile();
res.send({
@@ -750,7 +762,7 @@ app.get('/api/config', function(req, res) {
});
});
app.post('/api/setConfig', optionalJwt, function(req, res) {
app.post('/api/setConfig', optionalJwt, optionalPin, function(req, res) {
let new_config_file = req.body.new_config_file;
if (new_config_file && new_config_file['YoutubeDLMaterial']) {
let success = config_api.setConfigFile(new_config_file);
@@ -1934,12 +1946,23 @@ app.post('/api/auth/login'
, auth_api.generateJWT
, auth_api.returnAuthResponse
);
app.post('/api/auth/pinLogin'
, auth_api.passport.authenticate(['local_pin'], {})
, auth_api.generatePinJWT
, auth_api.returnPinAuthResponse
);
app.post('/api/auth/jwtAuth'
, auth_api.passport.authenticate('jwt', { session: false })
, auth_api.passport.authorize('jwt')
, auth_api.generateJWT
, auth_api.returnAuthResponse
);
app.post('/api/auth/pinAuth'
, auth_api.passport.authenticate('pin', { session: false })
, auth_api.passport.authorize('pin')
, auth_api.generatePinJWT
, auth_api.returnPinAuthResponse
);
app.post('/api/auth/changePassword', optionalJwt, async (req, res) => {
let user_uid = req.body.user_uid;
let password = req.body.new_password;
@@ -2029,6 +2052,13 @@ app.post('/api/changeRolePermissions', optionalJwt, async (req, res) => {
res.send({success: success});
});
app.post('/api/setPin', function(req, res) {
const success = auth_api.setPin(req.body.new_pin);
res.send({
success: success
});
});
// notifications
app.post('/api/getNotifications', optionalJwt, async (req, res) => {

View File

@@ -15,7 +15,6 @@ var JwtStrategy = require('passport-jwt').Strategy,
// other required vars
let SERVER_SECRET = null;
let JWT_EXPIRATION = null;
let opts = null;
let saltRounds = null;
exports.initialize = function () {
@@ -50,11 +49,11 @@ exports.initialize = function () {
db_api.users_db.set('jwt_secret', SERVER_SECRET).write();
}
opts = {}
const opts = {}
opts.jwtFromRequest = ExtractJwt.fromUrlQueryParameter('jwt');
opts.secretOrKey = SERVER_SECRET;
exports.passport.use(new JwtStrategy(opts, async function(jwt_payload, done) {
exports.passport.use('jwt', new JwtStrategy(opts, async function(jwt_payload, done) {
const user = await db_api.getRecord('users', {uid: jwt_payload.user});
if (user) {
return done(null, user);
@@ -63,6 +62,21 @@ exports.initialize = function () {
// or you could create a new account
}
}));
const pin_opts = {}
pin_opts.jwtFromRequest = ExtractJwt.fromUrlQueryParameter('pin_token');
pin_opts.secretOrKey = SERVER_SECRET;
exports.passport.use('pin', new JwtStrategy(pin_opts, {
passwordField: 'pin'},
async function(username, password, done) {
if (await bcrypt.compare(password, config_api.getConfigItem('ytdl_pin_hash'))) {
return done(null, { success: true });
} else {
return done(null, false, { message: 'Incorrect pin' });
}
}
));
}
const setupRoles = async () => {
@@ -188,6 +202,10 @@ exports.login = async (username, password) => {
return await bcrypt.compare(password, user.passhash) ? user : false;
}
exports.pinLogin = async (pin) => {
return await bcrypt.compare(pin, config_api.getConfigItem('ytdl_pin_hash'));
}
exports.passport.use(new LocalStrategy({
usernameField: 'username',
passwordField: 'password'},
@@ -196,6 +214,14 @@ exports.passport.use(new LocalStrategy({
}
));
exports.passport.use('local_pin', new LocalStrategy({
usernameField: 'username',
passwordField: 'password'},
async function(username, password, done) {
return done(null, await exports.pinLogin(password));
}
));
var getLDAPConfiguration = function(req, callback) {
const ldap_config = config_api.getConfigItem('ytdl_ldap_config');
const opts = {server: ldap_config};
@@ -237,6 +263,14 @@ exports.generateJWT = function(req, res, next) {
next();
}
exports.generatePinJWT = function(req, res, next) {
var payload = {
exp: Math.floor(Date.now() / 1000) + JWT_EXPIRATION
};
req.token = jwt.sign(payload, SERVER_SECRET);
next();
}
exports.returnAuthResponse = async function(req, res) {
res.status(200).json({
user: req.user,
@@ -246,6 +280,12 @@ exports.returnAuthResponse = async function(req, res) {
});
}
exports.returnPinAuthResponse = async function(req, res) {
res.status(200).json({
pin_token: req.token
});
}
/***************************************
* Authorization: middleware that checks the
* JWT token for validity before allowing
@@ -439,6 +479,13 @@ exports.userPermissions = async function(user_uid) {
return user_permissions;
}
// pin
exports.setPin = async (new_pin) => {
const pin_hash = await bcrypt.hash(new_pin, saltRounds);
return config_api.setConfigItem('ytdl_pin_hash', pin_hash);
}
function getToken(queryParams) {
if (queryParams && queryParams.jwt) {
var parted = queryParams.jwt.split(' ');
@@ -450,7 +497,7 @@ function getToken(queryParams) {
} else {
return null;
}
};
}
function generateUserObject(userid, username, hash, auth_method = 'internal') {
let new_user = {

View File

@@ -202,6 +202,8 @@ const DEFAULT_CONFIG = {
"enable_all_notifications": true,
"allowed_notification_types": [],
"enable_rss_feed": false,
"use_pin": false,
"pin_hash": "",
},
"API": {
"use_API_key": false,

View File

@@ -92,6 +92,14 @@ exports.CONFIG_ITEMS = {
'key': 'ytdl_enable_rss_feed',
'path': 'YoutubeDLMaterial.Extra.enable_rss_feed'
},
'ytdl_use_pin': {
'key': 'ytdl_use_pin',
'path': 'YoutubeDLMaterial.Extra.use_pin'
},
'ytdl_pin_hash': {
'key': 'ytdl_pin_hash',
'path': 'YoutubeDLMaterial.Extra.pin_hash'
},
// API
'ytdl_use_api_key': {