Merge branch 'api/v2' of github.com:KevinMidboe/seasonedShows into api/v2

This commit is contained in:
2019-07-25 00:53:16 +02:00
9 changed files with 129 additions and 82 deletions

View File

@@ -11,11 +11,11 @@
"test": "cross-env SEASONED_CONFIG=conf/test.json NODE_PATH=. mocha --recursive test/unit test/system", "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", "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/", "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": { "dependencies": {
"axios": "^0.18.0", "axios": "^0.18.0",
"bcrypt-nodejs": "^0.0.3", "bcrypt": "^3.0.6",
"body-parser": "~1.18.2", "body-parser": "~1.18.2",
"cross-env": "~5.1.4", "cross-env": "~5.1.4",
"express": "~4.16.0", "express": "~4.16.0",

View File

@@ -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

View File

@@ -124,6 +124,7 @@ class RequestRepository {
*/ */
fetchAll(page=1, sort_by=undefined, sort_direction='asc', filter=undefined, query=undefined) { fetchAll(page=1, sort_by=undefined, sort_direction='asc', filter=undefined, query=undefined) {
// TODO implemented sort and filter // TODO implemented sort and filter
page = parseInt(page)
let fetchQuery = this.queries.fetchAll let fetchQuery = this.queries.fetchAll
let fetchTotalResults = this.queries.totalRequests let fetchTotalResults = this.queries.totalRequests
let fetchParams = [page] let fetchParams = [page]

View File

@@ -2,8 +2,9 @@ const User = require('src/user/user');
const jwt = require('jsonwebtoken'); const jwt = require('jsonwebtoken');
class Token { class Token {
constructor(user) { constructor(user, admin=false) {
this.user = user; this.user = user;
this.admin = admin;
} }
/** /**
@@ -12,7 +13,14 @@ class Token {
* @returns {String} * @returns {String}
*/ */
toString(secret) { toString(secret) {
return jwt.sign({ username: this.user.username }, 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' });
} }
/** /**
@@ -24,13 +32,13 @@ class Token {
static fromString(jwtToken, secret) { static fromString(jwtToken, secret) {
let username = null; let username = null;
try { const token = jwt.verify(jwtToken, secret, { clockTolerance: 10000 })
username = jwt.verify(jwtToken, secret).username; if (token.username === undefined)
} catch (error) { throw new Error('Malformed token')
throw new Error('The token is invalid.');
} username = token.username
const user = new User(username); const user = new User(username)
return new Token(user); return new Token(user)
} }
} }

View File

@@ -1,4 +1,4 @@
const bcrypt = require('bcrypt-nodejs'); const bcrypt = require('bcrypt');
const UserRepository = require('src/user/userRepository'); const UserRepository = require('src/user/userRepository');
class UserSecurity { class UserSecurity {
@@ -35,7 +35,7 @@ class UserSecurity {
return Promise.resolve() return Promise.resolve()
.then(() => this.userRepository.retrieveHash(user)) .then(() => this.userRepository.retrieveHash(user))
.then(hash => UserSecurity.compareHashes(hash, clearPassword)) .then(hash => UserSecurity.compareHashes(hash, clearPassword))
.catch(() => { throw new Error('Wrong username or password.'); }); .catch(() => { throw new Error('Incorrect username or password.'); });
} }
/** /**
@@ -46,12 +46,10 @@ class UserSecurity {
*/ */
static compareHashes(hash, clearPassword) { static compareHashes(hash, clearPassword) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
bcrypt.compare(clearPassword, hash, (error, matches) => { bcrypt.compare(clearPassword, hash, (error, match) => {
if (matches === true) { if (match)
resolve(); resolve()
} else { reject()
reject();
}
}); });
}); });
} }
@@ -63,7 +61,8 @@ class UserSecurity {
*/ */
static hashPassword(clearPassword) { static hashPassword(clearPassword) {
return new Promise((resolve) => { return new Promise((resolve) => {
bcrypt.hash(clearPassword, null, null, (error, hash) => { const salatRounds = 10;
bcrypt.hash(clearPassword, saltRounds, (error, hash) => {
resolve(hash); resolve(hash);
}); });
}); });

View File

@@ -21,9 +21,9 @@ function loginController(req, res) {
userSecurity.login(user, password) userSecurity.login(user, password)
.then(() => userRepository.checkAdmin(user)) .then(() => userRepository.checkAdmin(user))
.then((checkAdmin) => { .then((checkAdmin) => {
const token = new Token(user).toString(secret); const isAdmin = checkAdmin === 1 ? true : false;
const admin_state = checkAdmin === 1 ? true : false; const token = new Token(user, isAdmin).toString(secret);
res.send({ success: true, token, admin: admin_state }); res.send({ success: true, token });
}) })
.catch((error) => { .catch((error) => {
res.status(401).send({ success: false, error: error.message }); res.status(401).send({ success: false, error: error.message });

View File

@@ -21,10 +21,10 @@ function registerController(req, res) {
userSecurity.createNewUser(user, password) userSecurity.createNewUser(user, password)
.then(() => userRepository.checkAdmin(user)) .then(() => userRepository.checkAdmin(user))
.then((checkAdmin) => { .then((checkAdmin) => {
const token = new Token(user).toString(secret); const isAdmin = checkAdmin === 1 ? true : false;
const admin_state = checkAdmin === 1 ? true : false; const token = new Token(user, isAdmin).toString(secret);
res.send({ res.send({
success: true, message: 'Welcome to Seasoned!', token, admin: admin_state, success: true, message: 'Welcome to Seasoned!', token
}); });
}) })
.catch((error) => { .catch((error) => {