Moved contents of seasoned_api up to root folder
This commit is contained in:
93
src/webserver/controllers/user/authenticatePlexAccount.js
Normal file
93
src/webserver/controllers/user/authenticatePlexAccount.js
Normal file
@@ -0,0 +1,93 @@
|
||||
const UserRepository = require("../../../user/userRepository");
|
||||
const userRepository = new UserRepository();
|
||||
const fetch = require("node-fetch");
|
||||
const FormData = require("form-data");
|
||||
|
||||
function handleError(error, res) {
|
||||
let { status, message, source } = error;
|
||||
|
||||
if (status && message) {
|
||||
if (status === 401) {
|
||||
(message = "Unauthorized. Please check plex credentials."),
|
||||
(source = "plex");
|
||||
}
|
||||
|
||||
res.status(status).send({ success: false, message, source });
|
||||
} else {
|
||||
console.log("caught authenticate plex account controller error", error);
|
||||
res.status(500).send({
|
||||
message:
|
||||
"An unexpected error occured while authenticating your account with plex",
|
||||
source
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function handleResponse(response) {
|
||||
if (!response.ok) {
|
||||
throw {
|
||||
success: false,
|
||||
status: response.status,
|
||||
message: response.statusText
|
||||
};
|
||||
}
|
||||
|
||||
return response.json();
|
||||
}
|
||||
|
||||
function plexAuthenticate(username, password) {
|
||||
const url = "https://plex.tv/api/v2/users/signin";
|
||||
|
||||
const form = new FormData();
|
||||
form.append("login", username);
|
||||
form.append("password", password);
|
||||
form.append("rememberMe", "false");
|
||||
|
||||
const headers = {
|
||||
Accept: "application/json, text/plain, */*",
|
||||
"Content-Type": form.getHeaders()["content-type"],
|
||||
"X-Plex-Client-Identifier": "seasonedRequest"
|
||||
};
|
||||
const options = {
|
||||
method: "POST",
|
||||
headers,
|
||||
body: form
|
||||
};
|
||||
|
||||
return fetch(url, options).then(resp => handleResponse(resp));
|
||||
}
|
||||
|
||||
function link(req, res) {
|
||||
const user = req.loggedInUser;
|
||||
const { username, password } = req.body;
|
||||
|
||||
return plexAuthenticate(username, password)
|
||||
.then(plexUser => userRepository.linkPlexUserId(user.username, plexUser.id))
|
||||
.then(response =>
|
||||
res.send({
|
||||
success: true,
|
||||
message:
|
||||
"Successfully authenticated and linked plex account with seasoned request."
|
||||
})
|
||||
)
|
||||
.catch(error => handleError(error, res));
|
||||
}
|
||||
|
||||
function unlink(req, res) {
|
||||
const username = req.loggedInUser ? req.loggedInUser.username : null;
|
||||
|
||||
return userRepository
|
||||
.unlinkPlexUserId(username)
|
||||
.then(response =>
|
||||
res.send({
|
||||
success: true,
|
||||
message: "Successfully unlinked plex account from seasoned request."
|
||||
})
|
||||
)
|
||||
.catch(error => handleError(error, res));
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
link,
|
||||
unlink
|
||||
};
|
||||
61
src/webserver/controllers/user/login.js
Normal file
61
src/webserver/controllers/user/login.js
Normal file
@@ -0,0 +1,61 @@
|
||||
const User = require("../../../user/user");
|
||||
const Token = require("../../../user/token");
|
||||
const UserSecurity = require("../../../user/userSecurity");
|
||||
const UserRepository = require("../../../user/userRepository");
|
||||
const configuration = require("../../../config/configuration").getInstance();
|
||||
|
||||
const secret = configuration.get("authentication", "secret");
|
||||
const userSecurity = new UserSecurity();
|
||||
const userRepository = new UserRepository();
|
||||
|
||||
// TODO look to move some of the token generation out of the reach of the final "catch-all"
|
||||
// catch including the, maybe sensitive, error message.
|
||||
|
||||
const isProduction = process.env.NODE_ENV === "production";
|
||||
const cookieOptions = {
|
||||
httpOnly: false,
|
||||
secure: isProduction,
|
||||
maxAge: 90 * 24 * 3600000, // 90 days
|
||||
sameSite: isProduction ? "Strict" : "Lax"
|
||||
};
|
||||
|
||||
/**
|
||||
* Controller: Log in a user provided correct credentials.
|
||||
* @param {Request} req http request variable
|
||||
* @param {Response} res
|
||||
* @returns {Callback}
|
||||
*/
|
||||
async function loginController(req, res) {
|
||||
const user = new User(req.body.username);
|
||||
const password = req.body.password;
|
||||
|
||||
try {
|
||||
const [loggedIn, isAdmin, settings] = await Promise.all([
|
||||
userSecurity.login(user, password),
|
||||
userRepository.checkAdmin(user),
|
||||
userRepository.getSettings(user.username)
|
||||
]);
|
||||
|
||||
if (!loggedIn) {
|
||||
return res.status(503).send({
|
||||
success: false,
|
||||
message: "Unexpected error! Unable to create user."
|
||||
});
|
||||
}
|
||||
|
||||
const token = new Token(
|
||||
user,
|
||||
isAdmin === 1 ? true : false,
|
||||
settings
|
||||
).toString(secret);
|
||||
|
||||
return res.cookie("authorization", token, cookieOptions).status(200).send({
|
||||
success: true,
|
||||
message: "Welcome to request.movie!"
|
||||
});
|
||||
} catch (error) {
|
||||
return res.status(401).send({ success: false, message: error.message });
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = loginController;
|
||||
16
src/webserver/controllers/user/logout.js
Normal file
16
src/webserver/controllers/user/logout.js
Normal file
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Controller: Log out a user (destroy authorization token)
|
||||
* @param {Request} req http request variable
|
||||
* @param {Response} res
|
||||
* @returns {Callback}
|
||||
*/
|
||||
async function logoutController(req, res) {
|
||||
res.clearCookie("authorization");
|
||||
|
||||
return res.status(200).send({
|
||||
success: true,
|
||||
message: "Logged out, see you later!"
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = logoutController;
|
||||
47
src/webserver/controllers/user/register.js
Normal file
47
src/webserver/controllers/user/register.js
Normal file
@@ -0,0 +1,47 @@
|
||||
const User = require("../../../user/user");
|
||||
const Token = require("../../../user/token");
|
||||
const UserSecurity = require("../../../user/userSecurity");
|
||||
const UserRepository = require("../../../user/userRepository");
|
||||
const configuration = require("../../../config/configuration").getInstance();
|
||||
|
||||
const secret = configuration.get("authentication", "secret");
|
||||
const userSecurity = new UserSecurity();
|
||||
const userRepository = new UserRepository();
|
||||
|
||||
const isProduction = process.env.NODE_ENV === "production";
|
||||
const cookieOptions = {
|
||||
httpOnly: false,
|
||||
secure: isProduction,
|
||||
maxAge: 90 * 24 * 3600000, // 90 days
|
||||
sameSite: isProduction ? "Strict" : "Lax"
|
||||
};
|
||||
|
||||
/**
|
||||
* Controller: Register a new user
|
||||
* @param {Request} req http request variable
|
||||
* @param {Response} res
|
||||
* @returns {Callback}
|
||||
*/
|
||||
function registerController(req, res) {
|
||||
const user = new User(req.body.username, req.body.email);
|
||||
const password = req.body.password;
|
||||
|
||||
userSecurity
|
||||
.createNewUser(user, password)
|
||||
.then(() => {
|
||||
const token = new Token(user, false).toString(secret);
|
||||
|
||||
return res
|
||||
.cookie("authorization", token, cookieOptions)
|
||||
.status(200)
|
||||
.send({
|
||||
success: true,
|
||||
message: "Welcome to Seasoned!"
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
res.status(401).send({ success: false, message: error.message });
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = registerController;
|
||||
28
src/webserver/controllers/user/requests.js
Normal file
28
src/webserver/controllers/user/requests.js
Normal file
@@ -0,0 +1,28 @@
|
||||
const RequestRepository = require("../../../plex/requestRepository.js");
|
||||
|
||||
const requestRepository = new RequestRepository();
|
||||
|
||||
/**
|
||||
* Controller: Retrieves requested items of a logged in user
|
||||
* @param {Request} req http request variable
|
||||
* @param {Response} res
|
||||
* @returns {Callback}
|
||||
*/
|
||||
function requestsController(req, res) {
|
||||
const username = req.loggedInUser ? req.loggedInUser.username : null;
|
||||
|
||||
requestRepository
|
||||
.userRequests(username)
|
||||
.then(requests => {
|
||||
res.send({
|
||||
success: true,
|
||||
results: requests,
|
||||
total_results: requests.length
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
res.status(500).send({ success: false, message: error.message });
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = requestsController;
|
||||
24
src/webserver/controllers/user/searchHistory.js
Normal file
24
src/webserver/controllers/user/searchHistory.js
Normal file
@@ -0,0 +1,24 @@
|
||||
const SearchHistory = require("../../../searchHistory/searchHistory");
|
||||
|
||||
const searchHistory = new SearchHistory();
|
||||
|
||||
/**
|
||||
* Controller: Retrieves search history of a logged in user
|
||||
* @param {Request} req http request variable
|
||||
* @param {Response} res
|
||||
* @returns {Callback}
|
||||
*/
|
||||
function historyController(req, res) {
|
||||
const username = req.loggedInUser ? req.loggedInUser.username : null;
|
||||
|
||||
searchHistory
|
||||
.read(username)
|
||||
.then(searchQueries => {
|
||||
res.send({ success: true, searchQueries });
|
||||
})
|
||||
.catch(error => {
|
||||
res.status(404).send({ success: false, message: error.message });
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = historyController;
|
||||
41
src/webserver/controllers/user/settings.js
Normal file
41
src/webserver/controllers/user/settings.js
Normal file
@@ -0,0 +1,41 @@
|
||||
const UserRepository = require("../../../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 username = req.loggedInUser ? req.loggedInUser.username : null;
|
||||
|
||||
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 username = req.loggedInUser ? req.loggedInUser.username : null;
|
||||
|
||||
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
|
||||
};
|
||||
107
src/webserver/controllers/user/viewHistory.js
Normal file
107
src/webserver/controllers/user/viewHistory.js
Normal file
@@ -0,0 +1,107 @@
|
||||
const configuration = require("../../../config/configuration").getInstance();
|
||||
const Tautulli = require("../../../tautulli/tautulli");
|
||||
const apiKey = configuration.get("tautulli", "apiKey");
|
||||
const ip = configuration.get("tautulli", "ip");
|
||||
const port = configuration.get("tautulli", "port");
|
||||
const tautulli = new Tautulli(apiKey, ip, port);
|
||||
|
||||
function handleError(error, res) {
|
||||
const { status, message } = error;
|
||||
|
||||
if (status && message) {
|
||||
return res.status(status).send({ success: false, message });
|
||||
} else {
|
||||
console.log("caught view history controller error", error);
|
||||
return res.status(500).send({
|
||||
message: "An unexpected error occured while fetching view history"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function watchTimeStatsController(req, res) {
|
||||
const user = req.loggedInUser;
|
||||
|
||||
return tautulli
|
||||
.watchTimeStats(user.plex_userid)
|
||||
.then(data => {
|
||||
return res.send({
|
||||
success: true,
|
||||
data: data.response.data,
|
||||
message: "watch time successfully fetched from tautulli"
|
||||
});
|
||||
})
|
||||
.catch(error => handleError(error, res));
|
||||
}
|
||||
|
||||
function getPlaysByDayOfWeekController(req, res) {
|
||||
const user = req.loggedInUser;
|
||||
const { days, y_axis } = req.query;
|
||||
|
||||
return tautulli
|
||||
.getPlaysByDayOfWeek(user.plex_userid, days, y_axis)
|
||||
.then(data =>
|
||||
res.send({
|
||||
success: true,
|
||||
data: data.response.data,
|
||||
message: "play by day of week successfully fetched from tautulli"
|
||||
})
|
||||
)
|
||||
.catch(error => handleError(error, res));
|
||||
}
|
||||
|
||||
function getPlaysByDaysController(req, res) {
|
||||
const user = req.loggedInUser;
|
||||
const { days, y_axis } = req.query;
|
||||
|
||||
if (days === undefined) {
|
||||
return res.status(422).send({
|
||||
success: false,
|
||||
message: "Missing parameter: days (number)"
|
||||
});
|
||||
}
|
||||
|
||||
const allowedYAxisDataType = ["plays", "duration"];
|
||||
if (!allowedYAxisDataType.includes(y_axis)) {
|
||||
return res.status(422).send({
|
||||
success: false,
|
||||
message: `Y axis parameter must be one of values: [${allowedYAxisDataType}]`
|
||||
});
|
||||
}
|
||||
|
||||
return tautulli
|
||||
.getPlaysByDays(user.plex_userid, days, y_axis)
|
||||
.then(data =>
|
||||
res.send({
|
||||
success: true,
|
||||
data: data.response.data
|
||||
})
|
||||
)
|
||||
.catch(error => handleError(error, res));
|
||||
}
|
||||
|
||||
function userViewHistoryController(req, res) {
|
||||
const user = req.loggedInUser;
|
||||
|
||||
// TODO here we should check if we can init tau
|
||||
// and then return 501 Not implemented
|
||||
|
||||
return tautulli
|
||||
.viewHistory(user.plex_userid)
|
||||
.then(data => {
|
||||
return res.send({
|
||||
success: true,
|
||||
data: data.response.data.data,
|
||||
message: "view history successfully fetched from tautulli"
|
||||
});
|
||||
})
|
||||
.catch(error => handleError(error, res));
|
||||
|
||||
// const username = user.username;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
watchTimeStatsController,
|
||||
getPlaysByDaysController,
|
||||
getPlaysByDayOfWeekController,
|
||||
userViewHistoryController
|
||||
};
|
||||
Reference in New Issue
Block a user