diff --git a/seasoned_api/.gitignore b/seasoned_api/.gitignore index 436d607..b275448 100644 --- a/seasoned_api/.gitignore +++ b/seasoned_api/.gitignore @@ -61,4 +61,6 @@ typings/ # - - - - - # My own gitignore files and folders shows.db -conf/ +conf/development.json + +# conf/development-prod.json diff --git a/seasoned_api/package.json b/seasoned_api/package.json index 7ef0308..a7a3720 100644 --- a/seasoned_api/package.json +++ b/seasoned_api/package.json @@ -4,7 +4,7 @@ "scripts": { "start": "cross-env SEASONED_CONFIG=conf/development.json NODE_PATH=. node src/webserver/server.js", "test": "cross-env SEASONED_CONFIG=conf/development.json NODE_PATH=. mocha --recursive test/system", - "coverage": "cross-env PLANFLIX_CONFIG=conf/test.json NODE_PATH=. istanbul cover -x script/autogenerate-documentation.js --include-all-sources --dir test/.coverage node_modules/mocha/bin/_mocha --recursive test/**/* -- --report lcovonly && cat test/.coverage/lcov.info | coveralls && rm -rf test/.coverage", + "coverage": "cross-env SEASONED_CONFIG=conf/test.json NODE_PATH=. istanbul cover -x script/autogenerate-documentation.js --include-all-sources --dir test/.coverage node_modules/mocha/bin/_mocha --recursive test/**/* -- --report lcovonly && cat test/.coverage/lcov.info | coveralls && rm -rf test/.coverage", "lint": "./node_modules/.bin/eslint src/" }, "dependencies": { @@ -12,7 +12,7 @@ "body-parser": "~1.0.1", "cross-env": "^3.1.3", "express": "~4.11.0", - "jsonwebtoken": "^8.0.1", + "jsonwebtoken": "^8.0.1", "mongoose": "^3.6.13", "moviedb": "^0.2.10", "node-cache": "^4.1.1", @@ -21,17 +21,15 @@ "raven": "^2.2.1", "request": "^2.81.0", "request-promise": "^4.2", - "sqlite": "^2.9.0" + "sqlite3": "3.1.13" }, "devDependencies": { - "eslint": "^4.9.0", + "eslint": "^4.9.0", "eslint-config-airbnb-base": "^12.1.0", "eslint-plugin-import": "^2.8.0", - "eslint": "^4.9.0", "istanbul": "^0.4.5", "mocha": "^3.1.0", "supertest": "^2.0.1", "supertest-as-promised": "^4.0.1" - } } diff --git a/seasoned_api/src/database/schemas/setup.sql b/seasoned_api/src/database/schemas/setup.sql index 9b54acd..0616964 100644 --- a/seasoned_api/src/database/schemas/setup.sql +++ b/seasoned_api/src/database/schemas/setup.sql @@ -2,6 +2,7 @@ CREATE TABLE IF NOT EXISTS user ( user_name varchar(127) UNIQUE, password varchar(127), email varchar(127) UNIQUE, + admin boolean DEFAULT 0, primary key (user_name) ); @@ -29,7 +30,7 @@ CREATE TABLE IF NOT EXISTS requests( background_path TEXT DEFAULT NULL, requested_by TEXT, ip TEXT, - requested_date DATE DEFAULT CURRENT_DATE NOT NULL, + date DATE DEFAULT CURRENT_TIMESTAMP, status CHAR(25) DEFAULT 'requested' NOT NULL, user_agent CHAR(255) DEFAULT NULL, type CHAR(50) DEFAULT 'movie' diff --git a/seasoned_api/src/database/sqliteDatabase.js b/seasoned_api/src/database/sqliteDatabase.js index 76b92f6..10c2262 100644 --- a/seasoned_api/src/database/sqliteDatabase.js +++ b/seasoned_api/src/database/sqliteDatabase.js @@ -1,12 +1,12 @@ const fs = require('fs'); const path = require('path'); -const sqlite = require('sqlite'); +const sqlite3 = require('sqlite3').verbose(); class SqliteDatabase { constructor(host) { this.host = host; - this.connection = sqlite; + this.connection = this.connect() this.schemaDirectory = path.join(__dirname, 'schemas'); } @@ -15,9 +15,9 @@ class SqliteDatabase { * @returns {Promise} succeeds if connection was established */ connect() { - return Promise.resolve() - .then(() => sqlite.open(this.host)) - .then(() => sqlite.exec('pragma foreign_keys = on;')); + let database = new sqlite3.Database(this.host); + this.connection = database; + return database; } /** @@ -27,7 +27,13 @@ class SqliteDatabase { * @returns {Promise} */ run(sql, parameters) { - return this.connection.run(sql, parameters); + return new Promise((resolve, reject) => { + this.connection.run(sql, parameters, (error, result) => { + if (error) + reject(error); + resolve(result) + }); + }); } /** @@ -36,8 +42,15 @@ class SqliteDatabase { * @param {Array} parameters in the SQL query * @returns {Promise} */ - all(sql, parameters) { - return this.connection.all(sql, parameters); + async all(sql, parameters) { + return new Promise((resolve, reject) => { + this.connection.all(sql, parameters, (err, rows) => { + if (err) { + reject(err); + } + resolve(rows); + }) + }) } /** @@ -46,8 +59,15 @@ class SqliteDatabase { * @param {Array} parameters in the SQL query * @returns {Promise} */ - get(sql, parameters) { - return this.connection.get(sql, parameters); + async get(sql, parameters) { + return new Promise((resolve, reject) => { + this.connection.get(sql, parameters, (err, rows) => { + if (err) { + reject(err); + } + resolve(rows); + }) + }) } /** @@ -56,8 +76,10 @@ class SqliteDatabase { * @param {Array} parameters in the SQL query * @returns {Promise} */ - execute(sql) { - return this.connection.exec(sql); + async execute(sql) { + return new Promise(resolve => { + resolve(this.connection.exec(sql)); + }) } /** diff --git a/seasoned_api/src/pirate/pirateRepository.js b/seasoned_api/src/pirate/pirateRepository.js index c46fcfc..e0c2e95 100644 --- a/seasoned_api/src/pirate/pirateRepository.js +++ b/seasoned_api/src/pirate/pirateRepository.js @@ -1,6 +1,22 @@ const assert = require('assert'); +const http = require('http'); +const { URL } = require('url'); const PythonShell = require('python-shell'); +function getMagnetFromURL(url) { + return new Promise((resolve, reject) => { + const options = new URL(url); + if (options.protocol.includes('magnet')) + resolve(url) + + http.get(options, (res) => { + if (res.statusCode == 301) { + resolve(res.headers.location) + } + }); + }); +} + async function find(searchterm, callback) { const options = { pythonPath: '/usr/bin/python3', @@ -13,14 +29,21 @@ async function find(searchterm, callback) { } -async function callPythonAddMagnet(magnet, callback) { - const options = { - pythonPath: '/usr/bin/python', - // pythonPath: '/Library/Frameworks/Python.framework/Versions/3.6/bin/python3', - args: [magnet], - }; +async function callPythonAddMagnet(url, callback) { + getMagnetFromURL(url) + .then((magnet) => { + const options = { + pythonPath: '/usr/bin/python', + // pythonPath: '/Library/Frameworks/Python.framework/Versions/3.6/bin/python3', + args: [magnet], + }; - PythonShell.run('../app/magnet.py', options, callback); + PythonShell.run('../app/magnet.py', options, callback); + }) + .catch((err) => { + console.log(err); + throw new Error(err); + }) } async function SearchPiratebay(query) { @@ -39,13 +62,14 @@ async function SearchPiratebay(query) { } async function AddMagnet(magnet) { - return await new Promise(resolve => callPythonAddMagnet(magnet, (err, results) => { + return await new Promise((resolve, reject) => callPythonAddMagnet(magnet, (err, results) => { if (err) { /* eslint-disable no-console */ console.log(err); + reject(Error('Enable to add torrent', err)) } /* eslint-disable no-console */ - console.log(results); + console.log('result/error:', err, results); resolve({ success: true }); })); } diff --git a/seasoned_api/src/plex/plexRepository.js b/seasoned_api/src/plex/plexRepository.js index a51f331..0a506c6 100644 --- a/seasoned_api/src/plex/plexRepository.js +++ b/seasoned_api/src/plex/plexRepository.js @@ -6,7 +6,12 @@ class PlexRepository { inPlex(tmdbResult) { return Promise.resolve() .then(() => this.search(tmdbResult.title)) - .then(plexResult => this.compareTmdbToPlex(tmdbResult, plexResult)); + .then(plexResult => this.compareTmdbToPlex(tmdbResult, plexResult)) + .catch((error) => { + console.log(error) + tmdbResult.matchedInPlex = false; + return tmdbResult; + }); } search(query) { @@ -19,6 +24,9 @@ class PlexRepository { }; return rp(options) + .catch((error) => { + throw new Error('Unable to search plex.') + }) .then(result => this.mapResults(result)) .then(([mappedResults, resultCount]) => ({ results: mappedResults, total_results: resultCount })); } @@ -26,10 +34,15 @@ class PlexRepository { compareTmdbToPlex(tmdb, plexResult) { return Promise.resolve() .then(() => { - plexResult.results.map((plexItem) => { - if (tmdb.title === plexItem.title && tmdb.year === plexItem.year) { tmdb.matchedInPlex = true; } - return tmdb; - }); + if (plexResult.results.length === 0) { + tmdb.matchedInPlex = false + } + else { + plexResult.results.map((plexItem) => { + if (tmdb.title === plexItem.title && tmdb.year === plexItem.year) { tmdb.matchedInPlex = true; } + return tmdb; + }); + } return tmdb; }); } diff --git a/seasoned_api/src/plex/requestRepository.js b/seasoned_api/src/plex/requestRepository.js index 3cfb60b..fefa027 100644 --- a/seasoned_api/src/plex/requestRepository.js +++ b/seasoned_api/src/plex/requestRepository.js @@ -16,19 +16,24 @@ class RequestRepository { constructor(cache, database) { this.database = database || establishedDatabase; this.queries = { - insertRequest: "INSERT INTO requests VALUES (?, ?, ?, ?, ?, ?, ?, CURRENT_DATE, 'requested', ?, ?)", - fetchRequstedItems: 'SELECT * FROM requests', + 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', + fetchRequestedItemsByStatus: 'SELECT * FROM requests WHERE status IS ? AND type LIKE ?', 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 ?' + }; + this.cacheTags = { + search: 'se', + lookup: 'i', }; } search(query, type, page) { return Promise.resolve() .then(() => tmdb.search(query, type, page)) - // .then((tmdbResult) => plexRepository.multipleInPlex(tmdbResult)) - .then(result => result) - .catch(error => `error in the house${error}`); + .catch(error => Error(`error in the house${error}`)); } lookup(identifier, type = 'movie') { @@ -60,53 +65,33 @@ class RequestRepository { * @returns {Promise} If nothing has gone wrong. */ sendRequest(identifier, type, ip, user_agent, user) { - tmdb.lookup(identifier, type).then((movie) => { - if (user === 'false') { user = 'NULL'; } + return Promise.resolve() + .then(() => tmdb.lookup(identifier, type)) + .then((movie) => { + const username = user == undefined ? undefined : user.username; // Add request to database - this.database.run(this.queries.insertRequest, [movie.id, movie.title, movie.year, movie.poster_path, movie.background_path, user, ip, user_agent, movie.type]); - - - // create reusable transporter object using the default SMTP transport - const transporter = nodemailer.createTransport({ - service: 'gmail', - auth: { - user: configuration.get('mail', 'user_pi'), - pass: configuration.get('mail', 'password_pi'), - }, - // host: configuration.get('mail', 'host'), - // port: 26, - // ignoreTLS: true, - // tls :{rejectUnauthorized: false}, - // secure: false, // secure:true for port 465, secure:false for port 587 - }); - - const mailTemplate = new MailTemplate(movie); - - // setup email data with unicode symbols - const mailOptions = { - // TODO get the mail adr from global location (easy to add) - from: 'MovieRequester ', // sender address - to: 'kevin.midboe@gmail.com', // list of receivers - subject: 'Download request', // Subject line - text: mailTemplate.toText(), - html: mailTemplate.toHTML(), - }; - - // send mail with defined transport object - transporter.sendMail(mailOptions, (error, info) => { - if (error) { - return console.log(error); - } - console.log('Message %s sent: %s', info.messageId, info.response); - }); + 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]); }); - - // TODO add better response when done. - return Promise.resolve(); } - fetchRequested() { - return this.database.all(this.queries.fetchRequstedItems); + fetchRequested(status, type = '%') { + return Promise.resolve() + .then(() => { + if (status === 'requested' || status === 'downloading' || status === 'downloaded') + return this.database.all(this.queries.fetchRequestedItemsByStatus, [status, type]); + else + return this.database.all(this.queries.fetchRequestedItems); + }) + } + + 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'); } + else { throw new Error('Unable to fetch your requests')} + }) + .then((result) => { return result }) } updateRequestedById(id, type, status) { diff --git a/seasoned_api/src/searchHistory/searchHistory.js b/seasoned_api/src/searchHistory/searchHistory.js index c51590e..4ebb899 100644 --- a/seasoned_api/src/searchHistory/searchHistory.js +++ b/seasoned_api/src/searchHistory/searchHistory.js @@ -15,8 +15,15 @@ class SearchHistory { * @returns {Promise} */ read(user) { - return this.database.all(this.queries.read, user) - .then(rows => rows.map(row => row.search_query)); + return new Promise((resolve, reject) => this.database.all(this.queries.read, user) + .then((result, error) => { + if (error) throw new Error(error); + resolve(result.map(row => row.search_query)); + }) + .catch((error) => { + console.log('Error when fetching history from database:', error) + reject('Unable to get history.'); + })); } /** @@ -26,7 +33,8 @@ class SearchHistory { * @returns {Promise} */ create(user, searchQuery) { - return this.database.run(this.queries.create, [searchQuery, user]) + return Promise.resolve() + .then(() => this.database.run(this.queries.create, [searchQuery, user])) .catch((error) => { if (error.message.includes('FOREIGN')) { throw new Error('Could not create search history.'); diff --git a/seasoned_api/src/tmdb/cache.js b/seasoned_api/src/tmdb/cache.js index 584df15..f55179e 100644 --- a/seasoned_api/src/tmdb/cache.js +++ b/seasoned_api/src/tmdb/cache.js @@ -33,7 +33,7 @@ class Cache { * @param {Number} timeToLive the number of seconds before entry expires * @returns {Object} */ - set(key, value, timeToLive = 172800) { + set(key, value, timeToLive = 10800) { const json = JSON.stringify(value); return Promise.resolve() .then(() => this.database.run(this.queries.create, [key, json, timeToLive])) diff --git a/seasoned_api/src/user/user.js b/seasoned_api/src/user/user.js index d922fbb..bdf326a 100644 --- a/seasoned_api/src/user/user.js +++ b/seasoned_api/src/user/user.js @@ -1,5 +1,5 @@ class User { - constructor(username, email) { + constructor(username, email=undefined) { this.username = username; this.email = email; } diff --git a/seasoned_api/src/user/userRepository.js b/seasoned_api/src/user/userRepository.js index b672a4d..4a6a148 100644 --- a/seasoned_api/src/user/userRepository.js +++ b/seasoned_api/src/user/userRepository.js @@ -6,9 +6,10 @@ class UserRepository { this.database = database || establishedDatabase; this.queries = { read: 'select * from user where lower(user_name) = lower(?)', - create: 'insert into user (user_name, email) values(?, ?)', + create: 'insert into user (user_name) values (?)', change: 'update user set password = ? where user_name = ?', retrieveHash: 'select * from user where user_name = ?', + getAdminStateByUser: 'select admin from user where user_name = ?' }; } @@ -20,13 +21,10 @@ class UserRepository { create(user) { return Promise.resolve() .then(() => this.database.get(this.queries.read, user.username)) - .then(row => assert.equal(row, undefined)) - .then(() => this.database.run(this.queries.create, [user.username, user.email])) + .then(() => this.database.run(this.queries.create, user.username)) .catch((error) => { - if (error.message.endsWith('email')) { - throw new Error('That email is already taken'); - } else if (error.name === 'AssertionError' || error.message.endsWith('user_name')) { - throw new Error('That username is already taken'); + if (error.name === 'AssertionError' || error.message.endsWith('user_name')) { + throw new Error('That username is already registered'); } }); } @@ -52,6 +50,12 @@ class UserRepository { changePassword(user, password) { return this.database.run(this.queries.change, [password, user.username]); } + + checkAdmin(user) { + return this.database.get(this.queries.getAdminStateByUser, user.username).then((row) => { + return row.admin; + }) + } } module.exports = UserRepository; diff --git a/seasoned_api/src/user/userSecurity.js b/seasoned_api/src/user/userSecurity.js index 71583db..9cf4ba4 100644 --- a/seasoned_api/src/user/userSecurity.js +++ b/seasoned_api/src/user/userSecurity.js @@ -15,8 +15,6 @@ class UserSecurity { createNewUser(user, clearPassword) { if (user.username.trim() === '') { throw new Error('The username is empty.'); - } else if (user.email.trim() === '') { - throw new Error('The email is empty.'); } else if (clearPassword.trim() === '') { throw new Error('The password is empty.'); } else { diff --git a/seasoned_api/src/webserver/app.js b/seasoned_api/src/webserver/app.js index cf5aabc..e038e1e 100644 --- a/seasoned_api/src/webserver/app.js +++ b/seasoned_api/src/webserver/app.js @@ -3,6 +3,7 @@ const Raven = require('raven'); const bodyParser = require('body-parser'); const tokenToUser = require('./middleware/tokenToUser'); const mustBeAuthenticated = require('./middleware/mustBeAuthenticated'); +const mustBeAdmin = require('./middleware/mustBeAdmin'); const configuration = require('src/config/configuration').getInstance(); // TODO: Have our raven router check if there is a value, if not don't enable raven. @@ -61,7 +62,8 @@ app.use(function onError(err, req, res, next) { */ router.post('/v1/user', require('./controllers/user/register.js')); router.post('/v1/user/login', require('./controllers/user/login.js')); -router.get('/v1/user/history', require('./controllers/user/history.js')); +router.get('/v1/user/history', mustBeAuthenticated, require('./controllers/user/history.js')); +router.get('/v1/user/requests', mustBeAuthenticated, require('./controllers/user/requests.js')); /** * Seasoned @@ -104,6 +106,10 @@ router.get('/v1/tmdb/:mediaId', require('./controllers/tmdb/readMedia.js')); */ router.post('/v1/git/dump', require('./controllers/git/dumpHook.js')); +/** + * misc + */ + router.get('/v1/emoji', require('./controllers/misc/emoji.js')); // REGISTER OUR ROUTES ------------------------------- // all of our routes will be prefixed with /api diff --git a/seasoned_api/src/webserver/controllers/misc/emoji.js b/seasoned_api/src/webserver/controllers/misc/emoji.js new file mode 100644 index 0000000..546d93b --- /dev/null +++ b/seasoned_api/src/webserver/controllers/misc/emoji.js @@ -0,0 +1,23 @@ +const RequestRepository = require('src/plex/requestRepository.js'); + +const requestRepository = new RequestRepository(); + +/** + * Controller: Returns a random emoji โœจ + * @param {Request} req http request variable + * @param {Response} res + * @returns {Callback} + */ +function emojiController(req, res) { + var emojis = [ + '๐Ÿ˜„','๐Ÿ˜ƒ','๐Ÿ˜€','๐Ÿ˜Š','โ˜บ','๐Ÿ˜‰','๐Ÿ˜','๐Ÿ˜˜','๐Ÿ˜š','๐Ÿ˜—','๐Ÿ˜™','๐Ÿ˜œ','๐Ÿ˜','๐Ÿ˜›','๐Ÿ˜ณ','๐Ÿ˜','๐Ÿ˜”','๐Ÿ˜Œ','๐Ÿ˜’','๐Ÿ˜ž','๐Ÿ˜ฃ','๐Ÿ˜ข','๐Ÿ˜‚','๐Ÿ˜ญ','๐Ÿ˜ช','๐Ÿ˜ฅ','๐Ÿ˜ฐ','๐Ÿ˜…','๐Ÿ˜“','๐Ÿ˜ฉ','๐Ÿ˜ซ','๐Ÿ˜จ','๐Ÿ˜ฑ','๐Ÿ˜ ','๐Ÿ˜ก','๐Ÿ˜ค','๐Ÿ˜–','๐Ÿ˜†','๐Ÿ˜‹','๐Ÿ˜ท','๐Ÿ˜Ž','๐Ÿ˜ด','๐Ÿ˜ต','๐Ÿ˜ฒ','๐Ÿ˜Ÿ','๐Ÿ˜ฆ','๐Ÿ˜ง','๐Ÿ˜ˆ','๐Ÿ‘ฟ','๐Ÿ˜ฎ','๐Ÿ˜ฌ','๐Ÿ˜','๐Ÿ˜•','๐Ÿ˜ฏ','๐Ÿ˜ถ','๐Ÿ˜‡','๐Ÿ˜','๐Ÿ˜‘','๐Ÿ‘ฒ','๐Ÿ‘ณ','๐Ÿ‘ฎ','๐Ÿ‘ท','๐Ÿ’‚','๐Ÿ‘ถ','๐Ÿ‘ฆ','๐Ÿ‘ง','๐Ÿ‘จ','๐Ÿ‘ฉ','๐Ÿ‘ด','๐Ÿ‘ต','๐Ÿ‘ฑ','๐Ÿ‘ผ','๐Ÿ‘ธ','๐Ÿ˜บ','๐Ÿ˜ธ','๐Ÿ˜ป','๐Ÿ˜ฝ','๐Ÿ˜ผ','๐Ÿ™€','๐Ÿ˜ฟ','๐Ÿ˜น','๐Ÿ˜พ','๐Ÿ‘น','๐Ÿ‘บ','๐Ÿ™ˆ','๐Ÿ™‰','๐Ÿ™Š','๐Ÿ’€','๐Ÿ‘ฝ','๐Ÿ’ฉ','๐Ÿ”ฅ','โœจ','๐ŸŒŸ','๐Ÿ’ซ','๐Ÿ’ฅ','๐Ÿ’ข','๐Ÿ’ฆ','๐Ÿ’ง','๐Ÿ’ค','๐Ÿ’จ','๐Ÿ‘‚','๐Ÿ‘€','๐Ÿ‘ƒ','๐Ÿ‘…','๐Ÿ‘„','๐Ÿ‘','๐Ÿ‘Ž','๐Ÿ‘Œ','๐Ÿ‘Š','โœŠ','โœŒ','๐Ÿ‘‹','โœ‹','๐Ÿ‘','๐Ÿ‘†','๐Ÿ‘‡','๐Ÿ‘‰','๐Ÿ‘ˆ','๐Ÿ™Œ','๐Ÿ™','โ˜','๐Ÿ‘','๐Ÿ’ช','๐Ÿšถ','๐Ÿƒ','๐Ÿ’ƒ','๐Ÿ‘ซ','๐Ÿ‘ช','๐Ÿ‘ฌ','๐Ÿ‘ญ','๐Ÿ’','๐Ÿ’‘','๐Ÿ‘ฏ','๐Ÿ™†','๐Ÿ™…','๐Ÿ’','๐Ÿ™‹','๐Ÿ’†','๐Ÿ’‡','๐Ÿ’…','๐Ÿ‘ฐ','๐Ÿ™Ž','๐Ÿ™','๐Ÿ™‡','๐ŸŽฉ','๐Ÿ‘‘','๐Ÿ‘’','๐Ÿ‘Ÿ','๐Ÿ‘ž','๐Ÿ‘ก','๐Ÿ‘ ','๐Ÿ‘ข','๐Ÿ‘•','๐Ÿ‘”','๐Ÿ‘š','๐Ÿ‘—','๐ŸŽฝ','๐Ÿ‘–','๐Ÿ‘˜','๐Ÿ‘™','๐Ÿ’ผ','๐Ÿ‘œ','๐Ÿ‘','๐Ÿ‘›','๐Ÿ‘“','๐ŸŽ€','๐ŸŒ‚','๐Ÿ’„','๐Ÿ’›','๐Ÿ’™','๐Ÿ’œ','๐Ÿ’š','โค','๐Ÿ’”','๐Ÿ’—','๐Ÿ’“','๐Ÿ’•','๐Ÿ’–','๐Ÿ’ž','๐Ÿ’˜','๐Ÿ’Œ','๐Ÿ’‹','๐Ÿ’','๐Ÿ’Ž','๐Ÿ‘ค','๐Ÿ‘ฅ','๐Ÿ’ฌ','๐Ÿ‘ฃ','๐Ÿ’ญ','๐Ÿถ','๐Ÿบ','๐Ÿฑ','๐Ÿญ','๐Ÿน','๐Ÿฐ','๐Ÿธ','๐Ÿฏ','๐Ÿจ','๐Ÿป','๐Ÿท','๐Ÿฝ','๐Ÿฎ','๐Ÿ—','๐Ÿต','๐Ÿ’','๐Ÿด','๐Ÿ‘','๐Ÿ˜','๐Ÿผ','๐Ÿง','๐Ÿฆ','๐Ÿค','๐Ÿฅ','๐Ÿฃ','๐Ÿ”','๐Ÿ','๐Ÿข','๐Ÿ›','๐Ÿ','๐Ÿœ','๐Ÿž','๐ŸŒ','๐Ÿ™','๐Ÿš','๐Ÿ ','๐ŸŸ','๐Ÿฌ','๐Ÿณ','๐Ÿ‹','๐Ÿ„','๐Ÿ','๐Ÿ€','๐Ÿƒ','๐Ÿ…','๐Ÿ‡','๐Ÿ‰','๐ŸŽ','๐Ÿ','๐Ÿ“','๐Ÿ•','๐Ÿ–','๐Ÿ','๐Ÿ‚','๐Ÿฒ','๐Ÿก','๐ŸŠ','๐Ÿซ','๐Ÿช','๐Ÿ†','๐Ÿˆ','๐Ÿฉ','๐Ÿพ','๐Ÿ’','๐ŸŒธ','๐ŸŒท','๐Ÿ€','๐ŸŒน','๐ŸŒป','๐ŸŒบ','๐Ÿ','๐Ÿƒ','๐Ÿ‚','๐ŸŒฟ','๐ŸŒพ','๐Ÿ„','๐ŸŒต','๐ŸŒด','๐ŸŒฒ','๐ŸŒณ','๐ŸŒฐ','๐ŸŒฑ','๐ŸŒผ','๐ŸŒ','๐ŸŒž','๐ŸŒ','๐ŸŒš','๐ŸŒ‘','๐ŸŒ’','๐ŸŒ“','๐ŸŒ”','๐ŸŒ•','๐ŸŒ–','๐ŸŒ—','๐ŸŒ˜','๐ŸŒœ','๐ŸŒ›','๐ŸŒ™','๐ŸŒ','๐ŸŒŽ','๐ŸŒ','๐ŸŒ‹','๐ŸŒŒ','๐ŸŒ ','โญ','โ˜€','โ›…','โ˜','โšก','โ˜”','โ„','โ›„','๐ŸŒ€','๐ŸŒ','๐ŸŒˆ','๐ŸŒŠ','๐ŸŽ','๐Ÿ’','๐ŸŽŽ','๐ŸŽ’','๐ŸŽ“','๐ŸŽ','๐ŸŽ†','๐ŸŽ‡','๐ŸŽ','๐ŸŽ‘','๐ŸŽƒ','๐Ÿ‘ป','๐ŸŽ…','๐ŸŽ„','๐ŸŽ','๐ŸŽ‹','๐ŸŽ‰','๐ŸŽŠ','๐ŸŽˆ','๐ŸŽŒ','๐Ÿ”ฎ','๐ŸŽฅ','๐Ÿ“ท','๐Ÿ“น','๐Ÿ“ผ','๐Ÿ’ฟ','๐Ÿ“€','๐Ÿ’ฝ','๐Ÿ’พ','๐Ÿ’ป','๐Ÿ“ฑ','โ˜Ž','๐Ÿ“ž','๐Ÿ“Ÿ','๐Ÿ“ ','๐Ÿ“ก','๐Ÿ“บ','๐Ÿ“ป','๐Ÿ”Š','๐Ÿ”‰','๐Ÿ”ˆ','๐Ÿ”‡','๐Ÿ””','๐Ÿ”•','๐Ÿ“ข','๐Ÿ“ฃ','โณ','โŒ›','โฐ','โŒš','๐Ÿ”“','๐Ÿ”’','๐Ÿ”','๐Ÿ”','๐Ÿ”‘','๐Ÿ”Ž','๐Ÿ’ก','๐Ÿ”ฆ','๐Ÿ”†','๐Ÿ”…','๐Ÿ”Œ','๐Ÿ”‹','๐Ÿ”','๐Ÿ›','๐Ÿ›€','๐Ÿšฟ','๐Ÿšฝ','๐Ÿ”ง','๐Ÿ”ฉ','๐Ÿ”จ','๐Ÿšช','๐Ÿšฌ','๐Ÿ’ฃ','๐Ÿ”ซ','๐Ÿ”ช','๐Ÿ’Š','๐Ÿ’‰','๐Ÿ’ฐ','๐Ÿ’ด','๐Ÿ’ต','๐Ÿ’ท','๐Ÿ’ถ','๐Ÿ’ณ','๐Ÿ’ธ','๐Ÿ“ฒ','๐Ÿ“ง','๐Ÿ“ฅ','๐Ÿ“ค','โœ‰','๐Ÿ“ฉ','๐Ÿ“จ','๐Ÿ“ฏ','๐Ÿ“ซ','๐Ÿ“ช','๐Ÿ“ฌ','๐Ÿ“ญ','๐Ÿ“ฎ','๐Ÿ“ฆ','๐Ÿ“','๐Ÿ“„','๐Ÿ“ƒ','๐Ÿ“‘','๐Ÿ“Š','๐Ÿ“ˆ','๐Ÿ“‰','๐Ÿ“œ','๐Ÿ“‹','๐Ÿ“…','๐Ÿ“†','๐Ÿ“‡','๐Ÿ“','๐Ÿ“‚','โœ‚','๐Ÿ“Œ','๐Ÿ“Ž','โœ’','โœ','๐Ÿ“','๐Ÿ“','๐Ÿ“•','๐Ÿ“—','๐Ÿ“˜','๐Ÿ“™','๐Ÿ““','๐Ÿ“”','๐Ÿ“’','๐Ÿ“š','๐Ÿ“–','๐Ÿ”–','๐Ÿ“›','๐Ÿ”ฌ','๐Ÿ”ญ','๐Ÿ“ฐ','๐ŸŽจ','๐ŸŽฌ','๐ŸŽค','๐ŸŽง','๐ŸŽผ','๐ŸŽต','๐ŸŽถ','๐ŸŽน','๐ŸŽป','๐ŸŽบ','๐ŸŽท','๐ŸŽธ','๐Ÿ‘พ','๐ŸŽฎ','๐Ÿƒ','๐ŸŽด','๐Ÿ€„','๐ŸŽฒ','๐ŸŽฏ','๐Ÿˆ','๐Ÿ€','โšฝ','โšพ','๐ŸŽพ','๐ŸŽฑ','๐Ÿ‰','๐ŸŽณ','โ›ณ','๐Ÿšต','๐Ÿšด','๐Ÿ','๐Ÿ‡','๐Ÿ†','๐ŸŽฟ','๐Ÿ‚','๐ŸŠ','๐Ÿ„','๐ŸŽฃ','โ˜•','๐Ÿต','๐Ÿถ','๐Ÿผ','๐Ÿบ','๐Ÿป','๐Ÿธ','๐Ÿน','๐Ÿท','๐Ÿด','๐Ÿ•','๐Ÿ”','๐ŸŸ','๐Ÿ—','๐Ÿ–','๐Ÿ','๐Ÿ›','๐Ÿค','๐Ÿฑ','๐Ÿฃ','๐Ÿฅ','๐Ÿ™','๐Ÿ˜','๐Ÿš','๐Ÿœ','๐Ÿฒ','๐Ÿข','๐Ÿก','๐Ÿณ','๐Ÿž','๐Ÿฉ','๐Ÿฎ','๐Ÿฆ','๐Ÿจ','๐Ÿง','๐ŸŽ‚','๐Ÿฐ','๐Ÿช','๐Ÿซ','๐Ÿฌ','๐Ÿญ','๐Ÿฏ','๐ŸŽ','๐Ÿ','๐ŸŠ','๐Ÿ‹','๐Ÿ’','๐Ÿ‡','๐Ÿ‰','๐Ÿ“','๐Ÿ‘','๐Ÿˆ','๐ŸŒ','๐Ÿ','๐Ÿ','๐Ÿ ','๐Ÿ†','๐Ÿ…','๐ŸŒฝ','๐Ÿ ','๐Ÿก','๐Ÿซ','๐Ÿข','๐Ÿฃ','๐Ÿฅ','๐Ÿฆ','๐Ÿช','๐Ÿฉ','๐Ÿจ','๐Ÿ’’','โ›ช','๐Ÿฌ','๐Ÿค','๐ŸŒ‡','๐ŸŒ†','๐Ÿฏ','๐Ÿฐ','โ›บ','๐Ÿญ','๐Ÿ—ผ','๐Ÿ—พ','๐Ÿ—ป','๐ŸŒ„','๐ŸŒ…','๐ŸŒƒ','๐Ÿ—ฝ','๐ŸŒ‰','๐ŸŽ ','๐ŸŽก','โ›ฒ','๐ŸŽข','๐Ÿšข','โ›ต','๐Ÿšค','๐Ÿšฃ','โš“','๐Ÿš€','โœˆ','๐Ÿ’บ','๐Ÿš','๐Ÿš‚','๐ŸšŠ','๐Ÿš‰','๐Ÿšž','๐Ÿš†','๐Ÿš„','๐Ÿš…','๐Ÿšˆ','๐Ÿš‡','๐Ÿš','๐Ÿš‹','๐Ÿšƒ','๐ŸšŽ','๐ŸšŒ','๐Ÿš','๐Ÿš™','๐Ÿš˜','๐Ÿš—','๐Ÿš•','๐Ÿš–','๐Ÿš›','๐Ÿšš','๐Ÿšจ','๐Ÿš“','๐Ÿš”','๐Ÿš’','๐Ÿš‘','๐Ÿš','๐Ÿšฒ','๐Ÿšก','๐ŸšŸ','๐Ÿš ','๐Ÿšœ','๐Ÿ’ˆ','๐Ÿš','๐ŸŽซ','๐Ÿšฆ','๐Ÿšฅ','โš ','๐Ÿšง','๐Ÿ”ฐ','โ›ฝ','๐Ÿฎ','๐ŸŽฐ','โ™จ','๐Ÿ—ฟ','๐ŸŽช','๐ŸŽญ','๐Ÿ“','๐Ÿšฉ','โฌ†','โฌ‡','โฌ…','โžก','๐Ÿ” ','๐Ÿ”ก','๐Ÿ”ค','โ†—','โ†–','โ†˜','โ†™','โ†”','โ†•','๐Ÿ”„','โ—€','โ–ถ','๐Ÿ”ผ','๐Ÿ”ฝ','โ†ฉ','โ†ช','โ„น','โช','โฉ','โซ','โฌ','โคต','โคด','๐Ÿ†—','๐Ÿ”€','๐Ÿ”','๐Ÿ”‚','๐Ÿ†•','๐Ÿ†™','๐Ÿ†’','๐Ÿ†“','๐Ÿ†–','๐Ÿ“ถ','๐ŸŽฆ','๐Ÿˆ','๐Ÿˆฏ','๐Ÿˆณ','๐Ÿˆต','๐Ÿˆด','๐Ÿˆฒ','๐Ÿ‰','๐Ÿˆน','๐Ÿˆบ','๐Ÿˆถ','๐Ÿˆš','๐Ÿšป','๐Ÿšน','๐Ÿšบ','๐Ÿšผ','๐Ÿšพ','๐Ÿšฐ','๐Ÿšฎ','๐Ÿ…ฟ','โ™ฟ','๐Ÿšญ','๐Ÿˆท','๐Ÿˆธ','๐Ÿˆ‚','โ“‚','๐Ÿ›‚','๐Ÿ›„','๐Ÿ›…','๐Ÿ›ƒ','๐Ÿ‰‘','ใŠ™','ใŠ—','๐Ÿ†‘','๐Ÿ†˜','๐Ÿ†”','๐Ÿšซ','๐Ÿ”ž','๐Ÿ“ต','๐Ÿšฏ','๐Ÿšฑ','๐Ÿšณ','๐Ÿšท','๐Ÿšธ','โ›”','โœณ','โ‡','โŽ','โœ…','โœด','๐Ÿ’Ÿ','๐Ÿ†š','๐Ÿ“ณ','๐Ÿ“ด','๐Ÿ…ฐ','๐Ÿ…ฑ','๐Ÿ†Ž','๐Ÿ…พ','๐Ÿ’ ','โžฟ','โ™ป','โ™ˆ','โ™‰','โ™Š','โ™‹','โ™Œ','โ™','โ™Ž','โ™','โ™','โ™‘','โ™’','โ™“','โ›Ž','๐Ÿ”ฏ','๐Ÿง','๐Ÿ’น','๐Ÿ’ฒ','๐Ÿ’ฑ','ยฉ','ยฎ','โ„ข','ใ€ฝ','ใ€ฐ','๐Ÿ”','๐Ÿ”š','๐Ÿ”™','๐Ÿ”›','๐Ÿ”œ','โŒ','โญ•','โ—','โ“','โ•','โ”','๐Ÿ”ƒ','๐Ÿ•›','๐Ÿ•ง','๐Ÿ•','๐Ÿ•œ','๐Ÿ•‘','๐Ÿ•','๐Ÿ•’','๐Ÿ•ž','๐Ÿ•“','๐Ÿ•Ÿ','๐Ÿ•”','๐Ÿ• ','๐Ÿ••','๐Ÿ•–','๐Ÿ•—','๐Ÿ•˜','๐Ÿ•™','๐Ÿ•š','๐Ÿ•ก','๐Ÿ•ข','๐Ÿ•ฃ','๐Ÿ•ค','๐Ÿ•ฅ','๐Ÿ•ฆ','โœ–','โž•','โž–','โž—','โ™ ','โ™ฅ','โ™ฃ','โ™ฆ','๐Ÿ’ฎ','๐Ÿ’ฏ','โœ”','โ˜‘','๐Ÿ”˜','๐Ÿ”—','โžฐ','๐Ÿ”ฑ','๐Ÿ”ฒ','๐Ÿ”ณ','โ—ผ','โ—ป','โ—พ','โ—ฝ','โ–ช','โ–ซ','๐Ÿ”บ','โฌœ','โฌ›','โšซ','โšช','๐Ÿ”ด','๐Ÿ”ต','๐Ÿ”ป','๐Ÿ”ถ','๐Ÿ”ท','๐Ÿ”ธ','๐Ÿ”น' + ]; + + res.send({ + success: true, + emoji: emojis[Math.floor(Math.random() * emojis.length)], + message: 'Happy emoji-ing! ๐ŸŒ' + }) +} + +module.exports = emojiController; diff --git a/seasoned_api/src/webserver/controllers/pirate/addMagnet.js b/seasoned_api/src/webserver/controllers/pirate/addMagnet.js index 9899831..ed6f7a3 100644 --- a/seasoned_api/src/webserver/controllers/pirate/addMagnet.js +++ b/seasoned_api/src/webserver/controllers/pirate/addMagnet.js @@ -8,7 +8,7 @@ const PirateRepository = require('src/pirate/pirateRepository'); -function updateRequested(req, res) { +function addMagnet(req, res) { const magnet = req.body.magnet; PirateRepository.AddMagnet(magnet) @@ -16,8 +16,8 @@ function updateRequested(req, res) { res.send(result); }) .catch((error) => { - res.status(401).send({ success: false, error: error.message }); + res.status(500).send({ success: false, error: error.message }); }); } -module.exports = updateRequested; +module.exports = addMagnet; diff --git a/seasoned_api/src/webserver/controllers/pirate/searchTheBay.js b/seasoned_api/src/webserver/controllers/pirate/searchTheBay.js index 4f85f69..fcba93a 100644 --- a/seasoned_api/src/webserver/controllers/pirate/searchTheBay.js +++ b/seasoned_api/src/webserver/controllers/pirate/searchTheBay.js @@ -2,7 +2,7 @@ * @Author: KevinMidboe * @Date: 2017-10-21 09:54:31 * @Last Modified by: KevinMidboe -* @Last Modified time: 2017-10-21 12:12:26 +* @Last Modified time: 2018-02-26 19:56:32 */ const PirateRepository = require('src/pirate/pirateRepository'); @@ -19,7 +19,7 @@ function updateRequested(req, res) { PirateRepository.SearchPiratebay(query, page, type) .then((result) => { - res.send({ success: true, torrents: result }); + res.send({ success: true, results: result }); }) .catch((error) => { res.status(401).send({ success: false, error: error.message }); diff --git a/seasoned_api/src/webserver/controllers/plex/fetchRequested.js b/seasoned_api/src/webserver/controllers/plex/fetchRequested.js index 1602aba..f216396 100644 --- a/seasoned_api/src/webserver/controllers/plex/fetchRequested.js +++ b/seasoned_api/src/webserver/controllers/plex/fetchRequested.js @@ -8,10 +8,11 @@ const requestRepository = new RequestRepository(); * @param {Response} res * @returns {Callback} */ -function historyController(req, res) { +function fetchRequestedController(req, res) { // const user = req.loggedInUser; + const { status } = req.query; - requestRepository.fetchRequested() + requestRepository.fetchRequested(status) .then((requestedItems) => { res.send({ success: true, results: requestedItems, total_results: requestedItems.length }); }) @@ -20,4 +21,4 @@ function historyController(req, res) { }); } -module.exports = historyController; +module.exports = fetchRequestedController; diff --git a/seasoned_api/src/webserver/controllers/plex/searchRequest.js b/seasoned_api/src/webserver/controllers/plex/searchRequest.js index e5b038c..a568c04 100644 --- a/seasoned_api/src/webserver/controllers/plex/searchRequest.js +++ b/seasoned_api/src/webserver/controllers/plex/searchRequest.js @@ -8,17 +8,18 @@ const searchHistory = new SearchHistory(); function searchRequestController(req, res) { - const user = req.headers.loggedinuser; + const user = req.loggedInUser; const { query, page, type } = req.query; + const username = user == undefined ? undefined : user.username; Promise.resolve() - .then(() => searchHistory.create(user, query)) + .then(() => searchHistory.create(username, query)) .then(() => requestRepository.search(query, page, type)) .then((searchResult) => { res.send(searchResult); }) .catch((error) => { - res.status(500).send({ success: false, error: error.message }); + res.status(500).send({ success: false, error: error }); }); } diff --git a/seasoned_api/src/webserver/controllers/plex/submitRequest.js b/seasoned_api/src/webserver/controllers/plex/submitRequest.js index 6afb085..293d80c 100644 --- a/seasoned_api/src/webserver/controllers/plex/submitRequest.js +++ b/seasoned_api/src/webserver/controllers/plex/submitRequest.js @@ -15,7 +15,7 @@ function submitRequestController(req, res) { const type = req.query.type; const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress; const user_agent = req.headers['user-agent']; - const user = req.headers.loggedinuser; + const user = req.loggedInUser; requestRepository.sendRequest(id, type, ip, user_agent, user) .then(() => { diff --git a/seasoned_api/src/webserver/controllers/user/history.js b/seasoned_api/src/webserver/controllers/user/history.js index a396c1d..2371c33 100644 --- a/seasoned_api/src/webserver/controllers/user/history.js +++ b/seasoned_api/src/webserver/controllers/user/history.js @@ -10,13 +10,14 @@ const searchHistory = new SearchHistory(); */ function historyController(req, res) { const user = req.loggedInUser; + const username = user == undefined ? undefined : user.username; - searchHistory.read(user) + searchHistory.read(username) .then((searchQueries) => { res.send({ success: true, searchQueries }); }) .catch((error) => { - res.status(401).send({ success: false, error: error.message }); + res.status(404).send({ success: false, error: error }); }); } diff --git a/seasoned_api/src/webserver/controllers/user/login.js b/seasoned_api/src/webserver/controllers/user/login.js index e839276..888c2b1 100644 --- a/seasoned_api/src/webserver/controllers/user/login.js +++ b/seasoned_api/src/webserver/controllers/user/login.js @@ -1,10 +1,12 @@ const User = require('src/user/user'); const Token = require('src/user/token'); const UserSecurity = require('src/user/userSecurity'); +const UserRepository = require('src/user/userRepository'); const configuration = require('src/config/configuration').getInstance(); const secret = configuration.get('authentication', 'secret'); const userSecurity = new UserSecurity(); +const userRepository = new UserRepository(); /** * Controller: Log in a user provided correct credentials. @@ -17,9 +19,11 @@ function loginController(req, res) { const password = req.body.password; userSecurity.login(user, password) - .then(() => { + .then(() => userRepository.checkAdmin(user)) + .then((checkAdmin) => { const token = new Token(user).toString(secret); - res.send({ success: true, token }); + const admin_state = checkAdmin == 1 ? true : false; + res.send({ success: true, token, admin: admin_state }); }) .catch((error) => { res.status(401).send({ success: false, error: error.message }); diff --git a/seasoned_api/src/webserver/controllers/user/register.js b/seasoned_api/src/webserver/controllers/user/register.js index 6ca3663..63040c3 100644 --- a/seasoned_api/src/webserver/controllers/user/register.js +++ b/seasoned_api/src/webserver/controllers/user/register.js @@ -1,7 +1,12 @@ const User = require('src/user/user'); +const Token = require('src/user/token'); const UserSecurity = require('src/user/userSecurity'); +const UserRepository = require('src/user/userRepository'); +const configuration = require('src/config/configuration').getInstance(); +const secret = configuration.get('authentication', 'secret'); const userSecurity = new UserSecurity(); +const userRepository = new UserRepository(); /** * Controller: Register a new user @@ -14,8 +19,11 @@ function registerController(req, res) { const password = req.body.password; userSecurity.createNewUser(user, password) - .then(() => { - res.send({ success: true, message: 'Welcome to Seasoned!' }); + .then(() => userRepository.checkAdmin(user)) + .then((checkAdmin) => { + const token = new Token(user).toString(secret); + const admin_state = checkAdmin == 1 ? true : false; + res.send({ success: true, message: 'Welcome to Seasoned!', token, admin: admin_state }); }) .catch((error) => { res.status(401).send({ success: false, error: error.message }); diff --git a/seasoned_api/src/webserver/controllers/user/requests.js b/seasoned_api/src/webserver/controllers/user/requests.js new file mode 100644 index 0000000..98bb219 --- /dev/null +++ b/seasoned_api/src/webserver/controllers/user/requests.js @@ -0,0 +1,24 @@ +const RequestRepository = require('src/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 user = req.loggedInUser; + + requestRepository.userRequests(user) + .then((requests) => { + res.send({ success: true, results: requests, total_results: requests.length }); + }) + .catch((error) => { + console.log(error) + res.status(500).send({ success: false, error: error }); + }); +} + +module.exports = requestsController; diff --git a/seasoned_api/src/webserver/middleware/mustBeAdmin.js b/seasoned_api/src/webserver/middleware/mustBeAdmin.js new file mode 100644 index 0000000..042bd40 --- /dev/null +++ b/seasoned_api/src/webserver/middleware/mustBeAdmin.js @@ -0,0 +1,27 @@ +const establishedDatabase = require('src/database/database'); + +const mustBeAdmin = (req, res, next) => { + let database = establishedDatabase; + + if (req.loggedInUser === undefined) { + return res.status(401).send({ + success: false, + error: 'You must be logged in.', + }); + } else { + database.get(`SELECT admin FROM user WHERE user_name IS ?`, req.loggedInUser.username) + .then((isAdmin) => { + console.log(isAdmin, req.loggedInUser) + if (isAdmin.admin == 0) { + return res.status(401).send({ + success: false, + error: 'You must be logged in as a admin.' + }) + } + }) + } + + return next(); +}; + +module.exports = mustBeAdmin;