UserRepository handles updating db settings better.
Moved the plex_userid to settings to expanded with functions for updating and fetching settings, each with its own helper function towards the database. Since we had a linkPlexUserId function and we dont want plex_userid to be updated from the updatesettings function we moved unlinking to a separate endpoint and class function. Also a new controller and endpoints for getting and updating settings.
This commit is contained in:
@@ -10,7 +10,11 @@ class UserRepository {
|
|||||||
change: 'update user set password = ? where user_name = ?',
|
change: 'update user set password = ? where user_name = ?',
|
||||||
retrieveHash: 'select * from user where user_name = ?',
|
retrieveHash: 'select * from user where user_name = ?',
|
||||||
getAdminStateByUser: 'select admin from user where user_name = ?',
|
getAdminStateByUser: 'select admin from user where user_name = ?',
|
||||||
link: 'update user set plex_userid = ? where user_name = ?'
|
link: 'update settings set plex_userid = ? where user_name = ?',
|
||||||
|
unlink: 'update settings set plex_userid = null where user_name = ?',
|
||||||
|
createSettings: 'insert into settings (user_name) values (?)',
|
||||||
|
updateSettings: 'update settings set user_name = ?, dark_mode = ?, emoji = ?',
|
||||||
|
getSettings: 'select * from settings where user_name = ?'
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,7 +60,7 @@ changePassword(user, password) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Link plex userid with seasoned user
|
* Link plex userid with seasoned user
|
||||||
* @param {User} user the user you want to lunk plex userid with
|
* @param {String} username the user you want to lunk plex userid with
|
||||||
* @param {Number} plexUserID plex unique id
|
* @param {Number} plexUserID plex unique id
|
||||||
* @returns {Promsie}
|
* @returns {Promsie}
|
||||||
*/
|
*/
|
||||||
@@ -77,11 +81,139 @@ linkPlexUserId(username, plexUserID) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unlink plex userid with seasoned user
|
||||||
|
* @param {User} user the user you want to lunk plex userid with
|
||||||
|
* @returns {Promsie}
|
||||||
|
*/
|
||||||
|
unlinkPlexUserId(username) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.database.run(this.queries.unlink, plexUserID)
|
||||||
|
.then(row => resolve(row))
|
||||||
|
.catch(error => {
|
||||||
|
// TODO log this unknown db error
|
||||||
|
console.log('db error', error)
|
||||||
|
|
||||||
|
reject({
|
||||||
|
status: 500,
|
||||||
|
message: 'An unexpected error occured while unlinking plex and seasoned accounts',
|
||||||
|
source: 'seasoned database'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the user has boolean flag set for admin in database
|
||||||
|
* @param {User} user object
|
||||||
|
* @returns {Promsie}
|
||||||
|
*/
|
||||||
checkAdmin(user) {
|
checkAdmin(user) {
|
||||||
return this.database.get(this.queries.getAdminStateByUser, user.username).then((row) => {
|
return this.database.get(this.queries.getAdminStateByUser, user.username)
|
||||||
return row.admin;
|
.then((row) => row.admin);
|
||||||
});
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get settings for user matching string username
|
||||||
|
* @param {String} username
|
||||||
|
* @returns {Promsie}
|
||||||
|
*/
|
||||||
|
getSettings(username) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.database.get(this.queries.getSettings, username)
|
||||||
|
.then(async (row) => {
|
||||||
|
if (row == null) {
|
||||||
|
console.log(`settings do not exist for user: ${username}. Creating settings entry.`)
|
||||||
|
|
||||||
|
const userExistsWithUsername = await this.database.get('select * from user where user_name is ?', username)
|
||||||
|
if (userExistsWithUsername !== undefined) {
|
||||||
|
try {
|
||||||
|
resolve(this.dbCreateSettings(username))
|
||||||
|
} catch (error) {
|
||||||
|
reject(error)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
reject({
|
||||||
|
status: 404,
|
||||||
|
message: 'User not found, no settings to get'
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resolve(row)
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Unexpected error occured while fetching settings for your account. Error:', error)
|
||||||
|
reject({
|
||||||
|
status: 500,
|
||||||
|
message: 'An unexpected error occured while fetching settings for your account',
|
||||||
|
source: 'seasoned database'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update settings values for user matching string username
|
||||||
|
* @param {String} username
|
||||||
|
* @param {String} dark_mode
|
||||||
|
* @param {String} emoji
|
||||||
|
* @returns {Promsie}
|
||||||
|
*/
|
||||||
|
updateSettings(username, dark_mode=undefined, emoji=undefined) {
|
||||||
|
const settings = this.getSettings(username)
|
||||||
|
dark_mode = dark_mode !== undefined ? dark_mode : settings.dark_mode
|
||||||
|
emoji = emoji !== undefined ? emoji : settings.emoji
|
||||||
|
|
||||||
|
return this.dbUpdateSettings(username, dark_mode, emoji)
|
||||||
|
.catch(error => {
|
||||||
|
if (error.status && error.message) {
|
||||||
|
return error
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
status: 500,
|
||||||
|
message: 'An unexpected error occured while updating settings for your account'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function for creating settings in the database
|
||||||
|
* @param {String} username
|
||||||
|
* @returns {Promsie}
|
||||||
|
*/
|
||||||
|
dbCreateSettings(username) {
|
||||||
|
return this.database.run(this.queries.createSettings, username)
|
||||||
|
.then(() => this.database.get(this.queries.getSettings, username))
|
||||||
|
.catch(error => rejectUnexpectedDatabaseError('Unexpected error occured while creating settings', 503, error))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function for updating settings in the database
|
||||||
|
* @param {String} username
|
||||||
|
* @returns {Promsie}
|
||||||
|
*/
|
||||||
|
dbUpdateSettings(username, dark_mode, emoji) {
|
||||||
|
return new Promise((resolve, reject) =>
|
||||||
|
this.database.run(this.queries.updateSettings, [username, dark_mode, emoji])
|
||||||
|
.then(row => resolve(row)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const rejectUnexpectedDatabaseError = (message, status, error, reject=null) => {
|
||||||
|
console.error(error)
|
||||||
|
const body = {
|
||||||
|
status,
|
||||||
|
message,
|
||||||
|
source: 'seasoned database'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reject == null) {
|
||||||
|
return new Promise((resolve, reject) => reject(body))
|
||||||
|
}
|
||||||
|
reject(body)
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = UserRepository;
|
module.exports = UserRepository;
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ const configuration = require('src/config/configuration').getInstance();
|
|||||||
|
|
||||||
const listController = require('./controllers/list/listController');
|
const listController = require('./controllers/list/listController');
|
||||||
const tautulli = require('./controllers/user/viewHistory.js');
|
const tautulli = require('./controllers/user/viewHistory.js');
|
||||||
|
const SettingsController = require('./controllers/user/settings');
|
||||||
|
const AuthenticatePlexAccountController = require('./controllers/user/AuthenticatePlexAccount');
|
||||||
|
|
||||||
// TODO: Have our raven router check if there is a value, if not don't enable raven.
|
// TODO: Have our raven router check if there is a value, if not don't enable raven.
|
||||||
Raven.config(configuration.get('raven', 'DSN')).install();
|
Raven.config(configuration.get('raven', 'DSN')).install();
|
||||||
@@ -55,9 +57,12 @@ app.use(function onError(err, req, res, next) {
|
|||||||
*/
|
*/
|
||||||
router.post('/v1/user', require('./controllers/user/register.js'));
|
router.post('/v1/user', require('./controllers/user/register.js'));
|
||||||
router.post('/v1/user/login', require('./controllers/user/login.js'));
|
router.post('/v1/user/login', require('./controllers/user/login.js'));
|
||||||
|
router.get('/v1/user/settings', mustBeAuthenticated, SettingsController.getSettingsController);
|
||||||
|
router.put('/v1/user/settings', mustBeAuthenticated, SettingsController.updateSettingsController);
|
||||||
router.get('/v1/user/search_history', mustBeAuthenticated, require('./controllers/user/searchHistory.js'));
|
router.get('/v1/user/search_history', mustBeAuthenticated, require('./controllers/user/searchHistory.js'));
|
||||||
router.get('/v1/user/requests', mustBeAuthenticated, require('./controllers/user/requests.js'));
|
router.get('/v1/user/requests', mustBeAuthenticated, require('./controllers/user/requests.js'));
|
||||||
router.post('/v1/user/authenticate', mustBeAuthenticated, require('./controllers/user/authenticatePlexAccount.js'));
|
router.post('/v1/user/link_plex', mustBeAuthenticated, AuthenticatePlexAccountController.link);
|
||||||
|
router.post('/v1/user/unlink_plex', mustBeAuthenticated, AuthenticatePlexAccountController.unlink);
|
||||||
|
|
||||||
router.get('/v1/user/view_history', mustHaveAccountLinkedToPlex, tautulli.userViewHistoryController);
|
router.get('/v1/user/view_history', mustHaveAccountLinkedToPlex, tautulli.userViewHistoryController);
|
||||||
router.get('/v1/user/watch_time', mustHaveAccountLinkedToPlex, tautulli.watchTimeStatsController);
|
router.get('/v1/user/watch_time', mustHaveAccountLinkedToPlex, tautulli.watchTimeStatsController);
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ function plexAuthenticate(username, password) {
|
|||||||
.then(resp => handleResponse(resp))
|
.then(resp => handleResponse(resp))
|
||||||
}
|
}
|
||||||
|
|
||||||
function authenticatePlexAccountController(req, res) {
|
function link(req, res) {
|
||||||
const user = req.loggedInUser;
|
const user = req.loggedInUser;
|
||||||
const { username, password } = req.body;
|
const { username, password } = req.body;
|
||||||
|
|
||||||
@@ -70,4 +70,18 @@ function authenticatePlexAccountController(req, res) {
|
|||||||
.catch(error => handleError(error, res))
|
.catch(error => handleError(error, res))
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = authenticatePlexAccountController;
|
function link(req, res) {
|
||||||
|
const user = req.loggedInUser;
|
||||||
|
|
||||||
|
return userRepository.unlinkPlexUserId(user.username)
|
||||||
|
.then(response => res.send({
|
||||||
|
success: true,
|
||||||
|
message: "Successfully unlinked plex account from seasoned request."
|
||||||
|
}))
|
||||||
|
.catch(error => handleError(error, res))
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
link,
|
||||||
|
unlink
|
||||||
|
};
|
||||||
|
|||||||
42
seasoned_api/src/webserver/controllers/user/settings.js
Normal file
42
seasoned_api/src/webserver/controllers/user/settings.js
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
const UserRepository = require('src/user/userRepository');
|
||||||
|
const userRepository = new UserRepository();
|
||||||
|
/**
|
||||||
|
* Controller: Retrieves settings of a logged in user
|
||||||
|
* @param {Request} req http request variable
|
||||||
|
* @param {Response} res
|
||||||
|
* @returns {Callback}
|
||||||
|
*/
|
||||||
|
const getSettingsController = (req, res) => {
|
||||||
|
const user = req.loggedInUser;
|
||||||
|
const username = user === undefined ? undefined : user.username;
|
||||||
|
|
||||||
|
userRepository.getSettings(username)
|
||||||
|
.then(settings => {
|
||||||
|
res.send({ success: true, settings });
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
res.status(404).send({ success: false, message: error.message });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const updateSettingsController = (req, res) => {
|
||||||
|
const user = req.loggedInUser;
|
||||||
|
const username = user === undefined ? undefined : user.username;
|
||||||
|
|
||||||
|
const idempotencyKey = req.headers('Idempotency-Key'); // TODO implement better transactions
|
||||||
|
const { dark_mode, emoji } = req.body;
|
||||||
|
|
||||||
|
userRepository.updateSettings(username, dark_mode, emoji)
|
||||||
|
.then(settings => {
|
||||||
|
res.send({ success: true, settings });
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
res.status(404).send({ success: false, message: error.message });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getSettingsController,
|
||||||
|
updateSettingsController
|
||||||
|
}
|
||||||
@@ -7,10 +7,10 @@ const mustHaveAccountLinkedToPlex = (req, res, next) => {
|
|||||||
if (loggedInUser === undefined) {
|
if (loggedInUser === undefined) {
|
||||||
return res.status(401).send({
|
return res.status(401).send({
|
||||||
success: false,
|
success: false,
|
||||||
message: 'You must be logged in.',
|
message: 'You must have your account linked to a plex account.',
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
database.get(`SELECT plex_userid FROM user WHERE user_name IS ?`, loggedInUser.username)
|
database.get(`SELECT plex_userid FROM settings WHERE user_name IS ?`, loggedInUser.username)
|
||||||
.then(row => {
|
.then(row => {
|
||||||
const plex_userid = row.plex_userid;
|
const plex_userid = row.plex_userid;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user