diff --git a/seasoned_api/package.json b/seasoned_api/package.json index a0e79a1..dfc9297 100644 --- a/seasoned_api/package.json +++ b/seasoned_api/package.json @@ -11,11 +11,11 @@ "test": "cross-env SEASONED_CONFIG=conf/test.json NODE_PATH=. mocha --recursive test/unit test/system", "coverage": "cross-env SEASONED_CONFIG=conf/test.json NODE_PATH=. nyc mocha --recursive test && nyc report --reporter=text-lcov | coveralls", "lint": "./node_modules/.bin/eslint src/", - "update": "cross-env SEASONED_CONFIG=conf/development.json NODE_PATH=. node src/plex/updateRequestsInPlex.js" + "update": "cross-env SEASONED_CONFIG=conf/development.json NODE_PATH=. node src/plex/updateRequestsInPlex.js", }, "dependencies": { "axios": "^0.18.0", - "bcrypt-nodejs": "^0.0.3", + "bcrypt": "^3.0.6", "body-parser": "~1.18.2", "cross-env": "~5.1.4", "express": "~4.16.0", diff --git a/seasoned_api/src/plex/updateRequestsInPlex.js b/seasoned_api/src/plex/updateRequestsInPlex.js new file mode 100644 index 0000000..c53ff7f --- /dev/null +++ b/seasoned_api/src/plex/updateRequestsInPlex.js @@ -0,0 +1,39 @@ +const Plex = require('src/plex/plex') +const configuration = require('src/config/configuration').getInstance(); +const plex = new Plex(configuration.get('plex', 'ip')) +const establishedDatabase = require('src/database/database'); + +class UpdateRequestsInPlex { + constructor() { + this.database = establishedDatabase; + this.queries = { + getMovies: `SELECT * FROM requests WHERE status = 'requested' OR status = 'downloading'`, +// getMovies: "select * from requests where status is 'reset'", + saveNewStatus: `UPDATE requests SET status = ? WHERE id IS ? and type IS ?`, + } + } + getByStatus() { + return this.database.all(this.queries.getMovies); + } + scrub() { + return this.getByStatus() + .then((requests) => Promise.all(requests.map(movie => plex.existsInPlex(movie)))) + } + + commitNewStatus(status, id, type, title) { + console.log(type, title, 'updated to:', status) + this.database.run(this.queries.saveNewStatus, [status, id, type]) + } + + + updateStatus(status) { + this.getByStatus() + .then(requests => Promise.all(requests.map(request => plex.existsInPlex(request)))) + .then(matchedRequests => matchedRequests.filter(request => request.existsInPlex)) + .then(newMatches => newMatches.map(match => this.commitNewStatus(status, match.id, match.type, match.title))) + } +} +var requestsUpdater = new UpdateRequestsInPlex(); +requestsUpdater.updateStatus('downloaded') + +module.exports = UpdateRequestsInPlex diff --git a/seasoned_api/src/request/request.js b/seasoned_api/src/request/request.js index 6e17e70..b83882e 100644 --- a/seasoned_api/src/request/request.js +++ b/seasoned_api/src/request/request.js @@ -124,6 +124,7 @@ class RequestRepository { */ fetchAll(page=1, sort_by=undefined, sort_direction='asc', filter=undefined, query=undefined) { // TODO implemented sort and filter + page = parseInt(page) let fetchQuery = this.queries.fetchAll let fetchTotalResults = this.queries.totalRequests let fetchParams = [page] diff --git a/seasoned_api/src/user/token.js b/seasoned_api/src/user/token.js index cd8c285..0590dc3 100644 --- a/seasoned_api/src/user/token.js +++ b/seasoned_api/src/user/token.js @@ -2,36 +2,44 @@ const User = require('src/user/user'); const jwt = require('jsonwebtoken'); class Token { - constructor(user) { - this.user = user; - } + constructor(user, admin=false) { + this.user = user; + this.admin = admin; + } - /** + /** * Generate a new token. * @param {String} secret a cipher of the token * @returns {String} */ - toString(secret) { - return jwt.sign({ username: this.user.username }, secret); - } + toString(secret) { + const username = this.user.username; + const admin = this.admin; + let data = { username } - /** + if (admin) + data = { ...data, admin } + + return jwt.sign(data, secret, { expiresIn: '90d' }); + } + + /** * Decode a token. * @param {Token} jwtToken an encrypted token * @param {String} secret a cipher of the token * @returns {Token} */ - static fromString(jwtToken, secret) { - let username = null; + static fromString(jwtToken, secret) { + let username = null; - try { - username = jwt.verify(jwtToken, secret).username; - } catch (error) { - throw new Error('The token is invalid.'); - } - const user = new User(username); - return new Token(user); - } + const token = jwt.verify(jwtToken, secret, { clockTolerance: 10000 }) + if (token.username === undefined) + throw new Error('Malformed token') + + username = token.username + const user = new User(username) + return new Token(user) + } } module.exports = Token; diff --git a/seasoned_api/src/user/userSecurity.js b/seasoned_api/src/user/userSecurity.js index 9cf4ba4..571ec58 100644 --- a/seasoned_api/src/user/userSecurity.js +++ b/seasoned_api/src/user/userSecurity.js @@ -1,73 +1,72 @@ -const bcrypt = require('bcrypt-nodejs'); +const bcrypt = require('bcrypt'); const UserRepository = require('src/user/userRepository'); class UserSecurity { - constructor(database) { - this.userRepository = new UserRepository(database); - } + constructor(database) { + this.userRepository = new UserRepository(database); +} - /** + /** * Create a new user in PlanFlix. * @param {User} user the new user you want to create * @param {String} clearPassword a password of the user * @returns {Promise} */ - createNewUser(user, clearPassword) { - if (user.username.trim() === '') { - throw new Error('The username is empty.'); - } else if (clearPassword.trim() === '') { - throw new Error('The password is empty.'); - } else { - return Promise.resolve() - .then(() => this.userRepository.create(user)) - .then(() => UserSecurity.hashPassword(clearPassword)) - .then(hash => this.userRepository.changePassword(user, hash)); - } - } + createNewUser(user, clearPassword) { + if (user.username.trim() === '') { + throw new Error('The username is empty.'); + } else if (clearPassword.trim() === '') { + throw new Error('The password is empty.'); + } else { + return Promise.resolve() + .then(() => this.userRepository.create(user)) + .then(() => UserSecurity.hashPassword(clearPassword)) + .then(hash => this.userRepository.changePassword(user, hash)); + } + } - /** + /** * Login into PlanFlix. * @param {User} user the user you want to login * @param {String} clearPassword the user's password * @returns {Promise} */ - login(user, clearPassword) { - return Promise.resolve() - .then(() => this.userRepository.retrieveHash(user)) - .then(hash => UserSecurity.compareHashes(hash, clearPassword)) - .catch(() => { throw new Error('Wrong username or password.'); }); - } + login(user, clearPassword) { + return Promise.resolve() + .then(() => this.userRepository.retrieveHash(user)) + .then(hash => UserSecurity.compareHashes(hash, clearPassword)) + .catch(() => { throw new Error('Incorrect username or password.'); }); + } /** - * Compare between a password and a hash password from database. - * @param {String} hash the hash password from database - * @param {String} clearPassword the user's password - * @returns {Promise} - */ - static compareHashes(hash, clearPassword) { - return new Promise((resolve, reject) => { - bcrypt.compare(clearPassword, hash, (error, matches) => { - if (matches === true) { - resolve(); - } else { - reject(); - } - }); + * Compare between a password and a hash password from database. + * @param {String} hash the hash password from database + * @param {String} clearPassword the user's password + * @returns {Promise} + */ + static compareHashes(hash, clearPassword) { + return new Promise((resolve, reject) => { + bcrypt.compare(clearPassword, hash, (error, match) => { + if (match) + resolve() + reject() }); - } + }); + } - /** + /** * Hashes a password. * @param {String} clearPassword the user's password * @returns {Promise} */ - static hashPassword(clearPassword) { - return new Promise((resolve) => { - bcrypt.hash(clearPassword, null, null, (error, hash) => { - resolve(hash); - }); + static hashPassword(clearPassword) { + return new Promise((resolve) => { + const salatRounds = 10; + bcrypt.hash(clearPassword, saltRounds, (error, hash) => { + resolve(hash); }); - } + }); + } } module.exports = UserSecurity; diff --git a/seasoned_api/src/webserver/controllers/user/login.js b/seasoned_api/src/webserver/controllers/user/login.js index 89722c1..25d8bca 100644 --- a/seasoned_api/src/webserver/controllers/user/login.js +++ b/seasoned_api/src/webserver/controllers/user/login.js @@ -21,9 +21,9 @@ function loginController(req, res) { userSecurity.login(user, password) .then(() => userRepository.checkAdmin(user)) .then((checkAdmin) => { - const token = new Token(user).toString(secret); - const admin_state = checkAdmin === 1 ? true : false; - res.send({ success: true, token, admin: admin_state }); + const isAdmin = checkAdmin === 1 ? true : false; + const token = new Token(user, isAdmin).toString(secret); + res.send({ success: true, token }); }) .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 280f4be..36d9ff2 100644 --- a/seasoned_api/src/webserver/controllers/user/register.js +++ b/seasoned_api/src/webserver/controllers/user/register.js @@ -21,10 +21,10 @@ function registerController(req, res) { userSecurity.createNewUser(user, password) .then(() => userRepository.checkAdmin(user)) .then((checkAdmin) => { - const token = new Token(user).toString(secret); - const admin_state = checkAdmin === 1 ? true : false; + const isAdmin = checkAdmin === 1 ? true : false; + const token = new Token(user, isAdmin).toString(secret); res.send({ - success: true, message: 'Welcome to Seasoned!', token, admin: admin_state, + success: true, message: 'Welcome to Seasoned!', token }); }) .catch((error) => { diff --git a/seasoned_api/src/webserver/middleware/.tokenToUser.js.swp b/seasoned_api/src/webserver/middleware/.tokenToUser.js.swp new file mode 100644 index 0000000..7b48de5 Binary files /dev/null and b/seasoned_api/src/webserver/middleware/.tokenToUser.js.swp differ diff --git a/seasoned_api/src/webserver/middleware/tokenToUser.js b/seasoned_api/src/webserver/middleware/tokenToUser.js index 462d077..069c3e5 100644 --- a/seasoned_api/src/webserver/middleware/tokenToUser.js +++ b/seasoned_api/src/webserver/middleware/tokenToUser.js @@ -8,16 +8,16 @@ const Token = require('src/user/token'); // curl -i -H "Authorization:[token]" localhost:31459/api/v1/user/history const tokenToUser = (req, res, next) => { - const rawToken = req.headers.authorization; - if (rawToken) { - try { - const token = Token.fromString(rawToken, secret); - req.loggedInUser = token.user; - } catch (error) { - req.loggedInUser = undefined; - } - } - next(); + const rawToken = req.headers.authorization; + if (rawToken) { + try { + const token = Token.fromString(rawToken, secret); + req.loggedInUser = token.user; + } catch (error) { + req.loggedInUser = undefined; + } + } + next(); }; module.exports = tokenToUser;