Correctly use username from req.loggedInUser

This commit is contained in:
2022-01-03 19:17:27 +01:00
parent be889b8100
commit d8985aaff7
12 changed files with 335 additions and 272 deletions

View File

@@ -1,99 +1,130 @@
const PlexRepository = require('src/plex/plexRepository');
const configuration = require('src/config/configuration').getInstance();
const TMDB = require('src/tmdb/tmdb');
const establishedDatabase = require('src/database/database');
const PlexRepository = require("src/plex/plexRepository");
const configuration = require("src/config/configuration").getInstance();
const TMDB = require("src/tmdb/tmdb");
const establishedDatabase = require("src/database/database");
const plexRepository = new PlexRepository(configuration.get('plex', 'ip'));
const tmdb = new TMDB(configuration.get('tmdb', 'apiKey'));
const plexRepository = new PlexRepository(configuration.get("plex", "ip"));
const tmdb = new TMDB(configuration.get("tmdb", "apiKey"));
class RequestRepository {
constructor(database) {
this.database = database || establishedDatabase;
this.queries = {
insertRequest: `INSERT INTO requests(id,title,year,poster_path,background_path,requested_by,ip,user_agent,type)
constructor(database) {
this.database = database || establishedDatabase;
this.queries = {
insertRequest: `INSERT INTO requests(id,title,year,poster_path,background_path,requested_by,ip,user_agent,type)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
fetchRequestedItems: 'SELECT * FROM requests ORDER BY date DESC LIMIT 25 OFFSET ?*25-25',
fetchRequestedItemsByStatus: 'SELECT * FROM requests WHERE status IS ? AND type LIKE ? ORDER BY date DESC LIMIT 25 OFFSET ?*25-25',
updateRequestedById: 'UPDATE requests SET status = ? WHERE id is ? AND type is ?',
checkIfIdRequested: 'SELECT * FROM requests WHERE id IS ? AND type IS ?',
userRequests: 'SELECT * FROM requests WHERE requested_by IS ? ORDER BY date DESC',
};
this.cacheTags = {
search: 'se',
lookup: 'i',
};
}
fetchRequestedItems:
"SELECT * FROM requests ORDER BY date DESC LIMIT 25 OFFSET ?*25-25",
fetchRequestedItemsByStatus:
"SELECT * FROM requests WHERE status IS ? AND type LIKE ? ORDER BY date DESC LIMIT 25 OFFSET ?*25-25",
updateRequestedById:
"UPDATE requests SET status = ? WHERE id is ? AND type is ?",
checkIfIdRequested: "SELECT * FROM requests WHERE id IS ? AND type IS ?",
userRequests:
"SELECT * FROM requests WHERE requested_by IS ? ORDER BY date DESC"
};
this.cacheTags = {
search: "se",
lookup: "i"
};
}
search(query, type, page) {
return Promise.resolve()
.then(() => tmdb.search(query, type, page))
.catch(error => Error(`error in the house${error}`));
}
search(query, type, page) {
return Promise.resolve()
.then(() => tmdb.search(query, type, page))
.catch(error => Error(`error in the house${error}`));
}
lookup(identifier, type = 'movie') {
return Promise.resolve()
.then(() => tmdb.lookup(identifier, type))
.then(tmdbMovie => this.checkID(tmdbMovie))
.then(tmdbMovie => plexRepository.inPlex(tmdbMovie))
.catch((error) => {
throw new Error(error);
});
}
lookup(identifier, type = "movie") {
return Promise.resolve()
.then(() => tmdb.lookup(identifier, type))
.then(tmdbMovie => this.checkID(tmdbMovie))
.then(tmdbMovie => plexRepository.inPlex(tmdbMovie))
.catch(error => {
throw new Error(error);
});
}
checkID(tmdbMovie) {
return Promise.resolve()
.then(() => this.database.get(this.queries.checkIfIdRequested, [tmdbMovie.id, tmdbMovie.type]))
.then((result, error) => {
if (error) { throw new Error(error); }
tmdbMovie.requested = result ? true : false;
return tmdbMovie;
});
}
checkID(tmdbMovie) {
return Promise.resolve()
.then(() =>
this.database.get(this.queries.checkIfIdRequested, [
tmdbMovie.id,
tmdbMovie.type
])
)
.then((result, error) => {
if (error) {
throw new Error(error);
}
tmdbMovie.requested = result ? true : false;
return tmdbMovie;
});
}
/**
/**
* Send request for given media id.
* @param {identifier, type} the id of the media object and type of media must be defined
* @returns {Promise} If nothing has gone wrong.
*/
sendRequest(identifier, type, ip, user_agent, user) {
return Promise.resolve()
.then(() => tmdb.lookup(identifier, type))
.then((movie) => {
const username = user === undefined ? undefined : user.username;
// Add request to database
return this.database.run(this.queries.insertRequest, [movie.id, movie.title, movie.year, movie.poster_path, movie.background_path, username, ip, user_agent, movie.type]);
sendRequest(identifier, type, ip, user_agent, user) {
return Promise.resolve()
.then(() => tmdb.lookup(identifier, type))
.then(movie => {
const username = user === undefined ? undefined : user.username;
// Add request to database
return this.database.run(this.queries.insertRequest, [
movie.id,
movie.title,
movie.year,
movie.poster_path,
movie.background_path,
username,
ip,
user_agent,
movie.type
]);
});
}
}
fetchRequested(status, page = '1', type = '%') {
return Promise.resolve()
.then(() => {
if (status === 'requested' || status === 'downloading' || status === 'downloaded')
return this.database.all(this.queries.fetchRequestedItemsByStatus, [status, type, page]);
else
return this.database.all(this.queries.fetchRequestedItems, page);
})
}
fetchRequested(status, page = "1", type = "%") {
return Promise.resolve().then(() => {
if (
status === "requested" ||
status === "downloading" ||
status === "downloaded"
)
return this.database.all(this.queries.fetchRequestedItemsByStatus, [
status,
type,
page
]);
else return this.database.all(this.queries.fetchRequestedItems, page);
});
}
userRequests(user) {
return Promise.resolve()
.then(() => this.database.all(this.queries.userRequests, user.username))
.catch((error) => {
if (String(error).includes('no such column')) {
throw new Error('Username not found');
}
throw new Error('Unable to fetch your requests');
})
.then((result) => {
// TODO do a correct mapping before sending, not just a dump of the database
result.map(item => item.poster = item.poster_path)
return result
});
}
userRequests(username) {
return Promise.resolve()
.then(() => this.database.all(this.queries.userRequests, username))
.catch(error => {
if (String(error).includes("no such column")) {
throw new Error("Username not found");
}
throw new Error("Unable to fetch your requests");
})
.then(result => {
// TODO do a correct mapping before sending, not just a dump of the database
result.map(item => (item.poster = item.poster_path));
return result;
});
}
updateRequestedById(id, type, status) {
return this.database.run(this.queries.updateRequestedById, [status, id, type]);
}
updateRequestedById(id, type, status) {
return this.database.run(this.queries.updateRequestedById, [
status,
id,
type
]);
}
}
module.exports = RequestRepository;

View File

@@ -1,26 +1,24 @@
const SearchHistory = require('src/searchHistory/searchHistory');
const Cache = require('src/tmdb/cache');
const RequestRepository = require('src/plex/requestRepository.js');
const SearchHistory = require("src/searchHistory/searchHistory");
const Cache = require("src/tmdb/cache");
const RequestRepository = require("src/plex/requestRepository.js");
const cache = new Cache();
const requestRepository = new RequestRepository(cache);
const searchHistory = new SearchHistory();
function searchRequestController(req, res) {
const user = req.loggedInUser;
const { query, page, type } = req.query;
const username = user === undefined ? undefined : user.username;
const { query, page, type } = req.query;
const username = req.loggedInUser ? req.loggedInUser.username : null;
Promise.resolve()
.then(() => searchHistory.create(username, query))
.then(() => requestRepository.search(query, page, type))
.then((searchResult) => {
res.send(searchResult);
})
.catch(error => {
res.status(500).send({ success: false, message: error.message });
});
Promise.resolve()
.then(() => searchHistory.create(username, query))
.then(() => requestRepository.search(query, page, type))
.then(searchResult => {
res.send(searchResult);
})
.catch(error => {
res.status(500).send({ success: false, message: error.message });
});
}
module.exports = searchRequestController;

View File

@@ -1,16 +1,16 @@
const configuration = require('src/config/configuration').getInstance()
const RequestRepository = require('src/request/request');
const TMDB = require('src/tmdb/tmdb')
const tmdb = new TMDB(configuration.get('tmdb', 'apiKey'))
const request = new RequestRepository()
const configuration = require("src/config/configuration").getInstance();
const RequestRepository = require("src/request/request");
const TMDB = require("src/tmdb/tmdb");
const tmdb = new TMDB(configuration.get("tmdb", "apiKey"));
const request = new RequestRepository();
const tmdbMovieInfo = (id) => {
return tmdb.movieInfo(id)
}
const tmdbMovieInfo = id => {
return tmdb.movieInfo(id);
};
const tmdbShowInfo = (id) => {
return tmdb.showInfo(id)
}
const tmdbShowInfo = id => {
return tmdb.showInfo(id);
};
/**
* Controller: POST a media id to be donwloaded
@@ -21,28 +21,43 @@ const tmdbShowInfo = (id) => {
function submitRequestController(req, res) {
// This is the id that is the param of the url
const id = req.params.mediaId;
const type = req.query.type ? req.query.type.toLowerCase() : undefined
const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
const user_agent = req.headers['user-agent'];
const user = req.loggedInUser;
let mediaFunction = undefined
const type = req.query.type ? req.query.type.toLowerCase() : undefined;
const ip = req.headers["x-forwarded-for"] || req.connection.remoteAddress;
const user_agent = req.headers["user-agent"];
const username = req.loggedInUser ? req.loggedInUser.username : null;
if (type === 'movie') {
console.log('movie')
mediaFunction = tmdbMovieInfo
} else if (type === 'show') {
console.log('show')
mediaFunction = tmdbShowInfo
let mediaFunction = undefined;
if (type === "movie") {
console.log("movie");
mediaFunction = tmdbMovieInfo;
} else if (type === "show") {
console.log("show");
mediaFunction = tmdbShowInfo;
} else {
res.status(422).send({ success: false, message: 'Incorrect type. Allowed types: "movie" or "show"'})
res
.status(422)
.send({
success: false,
message: 'Incorrect type. Allowed types: "movie" or "show"'
});
}
if (mediaFunction === undefined) { res.status(200); return }
if (mediaFunction === undefined) {
res.status(200);
return;
}
mediaFunction(id)
.then(tmdbMedia => request.requestFromTmdb(tmdbMedia, ip, user_agent, user))
.then(() => res.send({ success: true, message: 'Media item successfully requested' }))
.catch(err => res.status(500).send({ success: false, message: err.message }))
.then(tmdbMedia =>
request.requestFromTmdb(tmdbMedia, ip, user_agent, username)
)
.then(() =>
res.send({ success: true, message: "Media item successfully requested" })
)
.catch(err =>
res.status(500).send({ success: false, message: err.message })
);
}
module.exports = submitRequestController;

View File

@@ -23,7 +23,7 @@ function requestTmdbIdController(req, res) {
const ip = req.headers["x-forwarded-for"] || req.connection.remoteAddress;
const user_agent = req.headers["user-agent"];
const user = req.loggedInUser;
const username = req.loggedInUser ? req.loggedInUser.username : null;
let mediaFunction = undefined;
@@ -47,7 +47,9 @@ function requestTmdbIdController(req, res) {
mediaFunction(id)
// .catch((error) => { console.error(error); res.status(404).send({ success: false, error: 'Id not found' }) })
.then(tmdbMedia => request.requestFromTmdb(tmdbMedia, ip, user_agent, user))
.then(tmdbMedia =>
request.requestFromTmdb(tmdbMedia, ip, user_agent, username)
)
.then(() =>
res.send({ success: true, message: "Request has been submitted." })
)

View File

@@ -1,7 +1,7 @@
const configuration = require('src/config/configuration').getInstance();
const TMDB = require('src/tmdb/tmdb');
const SearchHistory = require('src/searchHistory/searchHistory');
const tmdb = new TMDB(configuration.get('tmdb', 'apiKey'));
const configuration = require("src/config/configuration").getInstance();
const TMDB = require("src/tmdb/tmdb");
const SearchHistory = require("src/searchHistory/searchHistory");
const tmdb = new TMDB(configuration.get("tmdb", "apiKey"));
const searchHistory = new SearchHistory();
/**
@@ -11,28 +11,29 @@ const searchHistory = new SearchHistory();
* @returns {Callback}
*/
function movieSearchController(req, res) {
const user = req.loggedInUser;
const { query, page } = req.query;
const username = req.loggedInUser ? req.loggedInUser.username : null;
if (user) {
return searchHistory.create(user, query);
if (username) {
return searchHistory.create(username, query);
}
tmdb.movieSearch(query, page)
tmdb
.movieSearch(query, page)
.then(movieSearchResults => res.send(movieSearchResults))
.catch(error => {
const { status, message } = error;
if (status && message) {
res.status(status).send({ success: false, message })
res.status(status).send({ success: false, message });
} else {
// TODO log unhandled errors
console.log('caugth movie search controller error', error)
console.log("caugth movie search controller error", error);
res.status(500).send({
message: `An unexpected error occured while searching movies with query: ${query}`
})
});
}
})
});
}
module.exports = movieSearchController;

View File

@@ -1,14 +1,14 @@
const configuration = require('src/config/configuration').getInstance();
const TMDB = require('src/tmdb/tmdb');
const SearchHistory = require('src/searchHistory/searchHistory');
const tmdb = new TMDB(configuration.get('tmdb', 'apiKey'));
const configuration = require("src/config/configuration").getInstance();
const TMDB = require("src/tmdb/tmdb");
const SearchHistory = require("src/searchHistory/searchHistory");
const tmdb = new TMDB(configuration.get("tmdb", "apiKey"));
const searchHistory = new SearchHistory();
function checkAndCreateJsonResponse(result) {
if (typeof result['createJsonResponse'] === 'function') {
return result.createJsonResponse()
if (typeof result["createJsonResponse"] === "function") {
return result.createJsonResponse();
}
return result
return result;
}
/**
@@ -18,26 +18,31 @@ function checkAndCreateJsonResponse(result) {
* @returns {Callback}
*/
function multiSearchController(req, res) {
const user = req.loggedInUser;
const { query, page, adult } = req.query;
const username = req.loggedInUser ? req.loggedInUser.username : null;
if (user) {
searchHistory.create(user.username, query)
if (username) {
searchHistory.create(username, query);
}
return tmdb.multiSearch(query, page, adult)
.then(multiSearchResults => res.send(multiSearchResults))
.catch(error => {
const { status, message } = error;
return tmdb
.multiSearch(query, page, adult)
.then(multiSearchResults => res.send(multiSearchResults))
.catch(error => {
const { status, message } = error;
if (status && message) {
res.status(status).send({ success: false, message })
} else {
// TODO log unhandled errors
console.log('caugth multi search controller error', error)
res.status(500).send({ message: `An unexpected error occured while searching with query: ${query}` })
}
})
if (status && message) {
res.status(status).send({ success: false, message });
} else {
// TODO log unhandled errors
console.log("caugth multi search controller error", error);
res
.status(500)
.send({
message: `An unexpected error occured while searching with query: ${query}`
});
}
});
}
module.exports = multiSearchController;

View File

@@ -1,7 +1,7 @@
const configuration = require('src/config/configuration').getInstance();
const TMDB = require('src/tmdb/tmdb');
const SearchHistory = require('src/searchHistory/searchHistory');
const tmdb = new TMDB(configuration.get('tmdb', 'apiKey'));
const configuration = require("src/config/configuration").getInstance();
const TMDB = require("src/tmdb/tmdb");
const SearchHistory = require("src/searchHistory/searchHistory");
const tmdb = new TMDB(configuration.get("tmdb", "apiKey"));
const searchHistory = new SearchHistory();
/**
@@ -11,30 +11,31 @@ const searchHistory = new SearchHistory();
* @returns {Callback}
*/
function personSearchController(req, res) {
const user = req.loggedInUser;
const { query, page } = req.query;
const username = req.loggedInUser ? req.loggedInUser.username : null;
if (user) {
return searchHistory.create(user, query);
if (username) {
return searchHistory.create(username, query);
}
tmdb.personSearch(query, page)
.then((person) => {
tmdb
.personSearch(query, page)
.then(person => {
res.send(person);
})
.catch(error => {
const { status, message } = error;
if (status && message) {
res.status(status).send({ success: false, message })
res.status(status).send({ success: false, message });
} else {
// TODO log unhandled errors
console.log('caugth person search controller error', error)
console.log("caugth person search controller error", error);
res.status(500).send({
message: `An unexpected error occured while searching people with query: ${query}`
})
});
}
})
});
}
module.exports = personSearchController;

View File

@@ -1,7 +1,7 @@
const SearchHistory = require('src/searchHistory/searchHistory');
const configuration = require('src/config/configuration').getInstance();
const TMDB = require('src/tmdb/tmdb');
const tmdb = new TMDB(configuration.get('tmdb', 'apiKey'));
const SearchHistory = require("src/searchHistory/searchHistory");
const configuration = require("src/config/configuration").getInstance();
const TMDB = require("src/tmdb/tmdb");
const tmdb = new TMDB(configuration.get("tmdb", "apiKey"));
const searchHistory = new SearchHistory();
/**
@@ -11,23 +11,23 @@ const searchHistory = new SearchHistory();
* @returns {Callback}
*/
function showSearchController(req, res) {
const user = req.loggedInUser;
const { query, page } = req.query;
const username = req.loggedInUser ? req.loggedInUser.username : null;
Promise.resolve()
.then(() => {
if (user) {
return searchHistory.create(user, query);
}
return null
})
.then(() => tmdb.showSearch(query, page))
.then((shows) => {
res.send(shows);
})
.catch(error => {
res.status(500).send({ success: false, message: error.message });
});
.then(() => {
if (username) {
return searchHistory.create(username, query);
}
return null;
})
.then(() => tmdb.showSearch(query, page))
.then(shows => {
res.send(shows);
})
.catch(error => {
res.status(500).send({ success: false, message: error.message });
});
}
module.exports = showSearchController;

View File

@@ -1,24 +1,25 @@
const UserRepository = require('src/user/userRepository');
const UserRepository = require("src/user/userRepository");
const userRepository = new UserRepository();
const fetch = require('node-fetch');
const FormData = require('form-data');
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'
(message = "Unauthorized. Please check plex credentials."),
(source = "plex");
}
res.status(status).send({ success: false, message, source })
res.status(status).send({ success: false, message, source });
} else {
console.log('caught authenticate plex account controller error', error)
console.log("caught authenticate plex account controller error", error);
res.status(500).send({
message: 'An unexpected error occured while authenticating your account with plex',
message:
"An unexpected error occured while authenticating your account with plex",
source
})
});
}
}
@@ -28,33 +29,32 @@ function handleResponse(response) {
success: false,
status: response.status,
message: response.statusText
}
};
}
return response.json()
return response.json();
}
function plexAuthenticate(username, password) {
const url = 'https://plex.tv/api/v2/users/signin'
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 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'
}
Accept: "application/json, text/plain, */*",
"Content-Type": form.getHeaders()["content-type"],
"X-Plex-Client-Identifier": "seasonedRequest"
};
const options = {
method: 'POST',
method: "POST",
headers,
body: form
}
};
return fetch(url, options)
.then(resp => handleResponse(resp))
return fetch(url, options).then(resp => handleResponse(resp));
}
function link(req, res) {
@@ -63,22 +63,28 @@ function link(req, res) {
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))
.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 user = req.loggedInUser;
const username = req.loggedInUser ? req.loggedInUser.username : null;
return userRepository.unlinkPlexUserId(user.username)
.then(response => res.send({
success: true,
message: "Successfully unlinked plex account from seasoned request."
}))
.catch(error => handleError(error, res))
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 = {

View File

@@ -1,4 +1,4 @@
const RequestRepository = require('src/plex/requestRepository.js');
const RequestRepository = require("src/plex/requestRepository.js");
const requestRepository = new RequestRepository();
@@ -9,15 +9,20 @@ const requestRepository = new RequestRepository();
* @returns {Callback}
*/
function requestsController(req, res) {
const user = req.loggedInUser;
const username = req.loggedInUser ? req.loggedInUser.username : null;
requestRepository.userRequests(user)
.then(requests => {
res.send({ success: true, results: requests, total_results: requests.length });
})
.catch(error => {
res.status(500).send({ success: false, message: error.message });
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;

View File

@@ -1,4 +1,4 @@
const SearchHistory = require('src/searchHistory/searchHistory');
const SearchHistory = require("src/searchHistory/searchHistory");
const searchHistory = new SearchHistory();
@@ -9,16 +9,16 @@ const searchHistory = new SearchHistory();
* @returns {Callback}
*/
function historyController(req, res) {
const user = req.loggedInUser;
const username = user === undefined ? undefined : user.username;
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 });
});
searchHistory
.read(username)
.then(searchQueries => {
res.send({ success: true, searchQueries });
})
.catch(error => {
res.status(404).send({ success: false, message: error.message });
});
}
module.exports = historyController;

View File

@@ -1,4 +1,4 @@
const UserRepository = require('src/user/userRepository');
const UserRepository = require("src/user/userRepository");
const userRepository = new UserRepository();
/**
* Controller: Retrieves settings of a logged in user
@@ -7,36 +7,35 @@ const userRepository = new UserRepository();
* @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 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 user = req.loggedInUser;
const username = user === undefined ? undefined : user.username;
const username = req.loggedInUser ? req.loggedInUser.username : null;
const idempotencyKey = req.headers('Idempotency-Key'); // TODO implement better transactions
const { dark_mode, emoji } = req.body;
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 });
});
}
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
}
getSettingsController,
updateSettingsController
};