From cfb7e47fbd46fabd6afbe89b7a2b93796221534d Mon Sep 17 00:00:00 2001 From: bill bittner Date: Thu, 26 Apr 2018 18:50:47 -0700 Subject: [PATCH 01/13] reorganized half of the helper functions --- server/controllers/serveController.js | 2 +- .../utils}/channelPagination.js | 0 server/helpers/authHelpers.js | 10 ---------- server/routes/api/channelAvailability.js | 2 +- server/routes/api/channelClaims.js | 2 +- server/routes/api/channelData.js | 2 +- server/routes/api/channelShortId.js | 2 +- server/routes/api/claimAvailability.js | 2 +- server/routes/api/claimData.js | 2 +- server/routes/api/claimGet.js | 2 +- server/routes/api/claimList.js | 2 +- server/routes/api/claimLongId.js | 2 +- server/routes/api/claimPublish.js | 2 +- server/routes/api/claimResolve.js | 2 +- server/routes/api/claimShortId.js | 2 +- server/routes/api/fileAvailability.js | 2 +- server/routes/assets/serveAssetByClaim.js | 8 ++++++-- .../routes/assets/serveAssetByIdentifierAndClaim.js | 4 ++-- server/{helpers => routes/utils}/errorHandlers.js | 0 server/{helpers => routes/utils}/lbryUri.js | 0 .../serveHelpers.js => routes/utils/serve.js} | 2 +- server/speechPassport/index.js | 11 ++++++----- server/speechPassport/utils/deserializeUser.js | 7 +++++++ server/speechPassport/{ => utils}/local-login.js | 2 +- server/speechPassport/{ => utils}/local-signup.js | 4 ++-- server/speechPassport/utils/serializeUser.js | 7 +++++++ 26 files changed, 46 insertions(+), 37 deletions(-) rename server/{helpers => controllers/utils}/channelPagination.js (100%) delete mode 100644 server/helpers/authHelpers.js rename server/{helpers => routes/utils}/errorHandlers.js (100%) rename server/{helpers => routes/utils}/lbryUri.js (100%) rename server/{helpers/serveHelpers.js => routes/utils/serve.js} (97%) create mode 100644 server/speechPassport/utils/deserializeUser.js rename server/speechPassport/{ => utils}/local-login.js (97%) rename server/speechPassport/{ => utils}/local-signup.js (96%) create mode 100644 server/speechPassport/utils/serializeUser.js diff --git a/server/controllers/serveController.js b/server/controllers/serveController.js index a1a8fbc8..0513073a 100644 --- a/server/controllers/serveController.js +++ b/server/controllers/serveController.js @@ -1,6 +1,6 @@ const db = require('../models'); const logger = require('winston'); -const { returnPaginatedChannelClaims } = require('../helpers/channelPagination.js'); +const { returnPaginatedChannelClaims } = require('./utils/channelPagination.js'); const NO_CHANNEL = 'NO_CHANNEL'; const NO_CLAIM = 'NO_CLAIM'; diff --git a/server/helpers/channelPagination.js b/server/controllers/utils/channelPagination.js similarity index 100% rename from server/helpers/channelPagination.js rename to server/controllers/utils/channelPagination.js diff --git a/server/helpers/authHelpers.js b/server/helpers/authHelpers.js deleted file mode 100644 index 029be2e0..00000000 --- a/server/helpers/authHelpers.js +++ /dev/null @@ -1,10 +0,0 @@ -module.exports = { - serializeSpeechUser (user, done) { // returns user data to be serialized into session - console.log('serializing user'); - done(null, user); - }, - deserializeSpeechUser (user, done) { // deserializes session and populates additional info to req.user - console.log('deserializing user'); - done(null, user); - }, -}; diff --git a/server/routes/api/channelAvailability.js b/server/routes/api/channelAvailability.js index b9f6230c..672bdcd0 100644 --- a/server/routes/api/channelAvailability.js +++ b/server/routes/api/channelAvailability.js @@ -1,6 +1,6 @@ const { checkChannelAvailability } = require('../../controllers/publishController.js'); const { sendGATimingEvent } = require('../../helpers/googleAnalytics.js'); -const { handleErrorResponse } = require('../../helpers/errorHandlers.js'); +const { handleErrorResponse } = require('../utils/errorHandlers.js'); /* diff --git a/server/routes/api/channelClaims.js b/server/routes/api/channelClaims.js index 55986dbf..980d3e8e 100644 --- a/server/routes/api/channelClaims.js +++ b/server/routes/api/channelClaims.js @@ -1,5 +1,5 @@ const { getChannelClaims } = require('../../controllers/serveController.js'); -const { handleErrorResponse } = require('../../helpers/errorHandlers.js'); +const { handleErrorResponse } = require('../utils/errorHandlers.js'); const NO_CHANNEL = 'NO_CHANNEL'; diff --git a/server/routes/api/channelData.js b/server/routes/api/channelData.js index de12b340..8f14cd47 100644 --- a/server/routes/api/channelData.js +++ b/server/routes/api/channelData.js @@ -1,5 +1,5 @@ const { getChannelData } = require('../../controllers/serveController.js'); -const { handleErrorResponse } = require('../../helpers/errorHandlers.js'); +const { handleErrorResponse } = require('../utils/errorHandlers.js'); const NO_CHANNEL = 'NO_CHANNEL'; diff --git a/server/routes/api/channelShortId.js b/server/routes/api/channelShortId.js index 9fc33a8f..c5575ab6 100644 --- a/server/routes/api/channelShortId.js +++ b/server/routes/api/channelShortId.js @@ -1,4 +1,4 @@ -const { handleErrorResponse } = require('../../helpers/errorHandlers.js'); +const { handleErrorResponse } = require('../utils/errorHandlers.js'); const db = require('../../models'); /* diff --git a/server/routes/api/claimAvailability.js b/server/routes/api/claimAvailability.js index bd8726bf..c4d05cdd 100644 --- a/server/routes/api/claimAvailability.js +++ b/server/routes/api/claimAvailability.js @@ -1,6 +1,6 @@ const { claimNameIsAvailable } = require('../../controllers/publishController.js'); const { sendGATimingEvent } = require('../../helpers/googleAnalytics.js'); -const { handleErrorResponse } = require('../../helpers/errorHandlers.js'); +const { handleErrorResponse } = require('../utils/errorHandlers.js'); /* diff --git a/server/routes/api/claimData.js b/server/routes/api/claimData.js index 9a3a5495..965336df 100644 --- a/server/routes/api/claimData.js +++ b/server/routes/api/claimData.js @@ -1,4 +1,4 @@ -const { handleErrorResponse } = require('../../helpers/errorHandlers.js'); +const { handleErrorResponse } = require('../utils/errorHandlers.js'); const db = require('../../models'); /* diff --git a/server/routes/api/claimGet.js b/server/routes/api/claimGet.js index 9317b717..1551b7f2 100644 --- a/server/routes/api/claimGet.js +++ b/server/routes/api/claimGet.js @@ -1,6 +1,6 @@ const { getClaim } = require('../../helpers/lbryApi.js'); const { addGetResultsToFileData, createFileData } = require('../../helpers/publishHelpers.js'); -const { handleErrorResponse } = require('../../helpers/errorHandlers.js'); +const { handleErrorResponse } = require('../utils/errorHandlers.js'); const db = require('../../models'); /* diff --git a/server/routes/api/claimList.js b/server/routes/api/claimList.js index 005fb591..e5a54215 100644 --- a/server/routes/api/claimList.js +++ b/server/routes/api/claimList.js @@ -1,5 +1,5 @@ const { getClaimList } = require('../../helpers/lbryApi.js'); -const { handleErrorResponse } = require('../../helpers/errorHandlers.js'); +const { handleErrorResponse } = require('../utils/errorHandlers.js'); /* diff --git a/server/routes/api/claimLongId.js b/server/routes/api/claimLongId.js index a5dd5fa5..3286afae 100644 --- a/server/routes/api/claimLongId.js +++ b/server/routes/api/claimLongId.js @@ -1,5 +1,5 @@ const { getClaimId } = require('../../controllers/serveController.js'); -const { handleErrorResponse } = require('../../helpers/errorHandlers.js'); +const { handleErrorResponse } = require('../utils/errorHandlers.js'); const NO_CHANNEL = 'NO_CHANNEL'; const NO_CLAIM = 'NO_CLAIM'; diff --git a/server/routes/api/claimPublish.js b/server/routes/api/claimPublish.js index 5f8135d7..c3074421 100644 --- a/server/routes/api/claimPublish.js +++ b/server/routes/api/claimPublish.js @@ -2,7 +2,7 @@ const { createBasicPublishParams, createThumbnailPublishParams, parsePublishApiR const { claimNameIsAvailable, publish } = require('../../controllers/publishController.js'); const { authenticateUser } = require('../../auth/authentication.js'); const { sendGATimingEvent } = require('../../helpers/googleAnalytics.js'); -const { handleErrorResponse } = require('../../helpers/errorHandlers.js'); +const { handleErrorResponse } = require('../utils/errorHandlers.js'); const { details: { host } } = require('../../../config/siteConfig.js'); /* diff --git a/server/routes/api/claimResolve.js b/server/routes/api/claimResolve.js index 3876bde7..8f8aeaf9 100644 --- a/server/routes/api/claimResolve.js +++ b/server/routes/api/claimResolve.js @@ -1,5 +1,5 @@ const { resolveUri } = require('../../helpers/lbryApi.js'); -const { handleErrorResponse } = require('../../helpers/errorHandlers.js'); +const { handleErrorResponse } = require('../utils/errorHandlers.js'); /* diff --git a/server/routes/api/claimShortId.js b/server/routes/api/claimShortId.js index 1b28f519..db4833ba 100644 --- a/server/routes/api/claimShortId.js +++ b/server/routes/api/claimShortId.js @@ -1,4 +1,4 @@ -const { handleErrorResponse } = require('../../helpers/errorHandlers.js'); +const { handleErrorResponse } = require('../utils/errorHandlers.js'); const db = require('../../models'); /* diff --git a/server/routes/api/fileAvailability.js b/server/routes/api/fileAvailability.js index 153a60b9..f5cdb5bc 100644 --- a/server/routes/api/fileAvailability.js +++ b/server/routes/api/fileAvailability.js @@ -1,4 +1,4 @@ -const { handleErrorResponse } = require('../../helpers/errorHandlers.js'); +const { handleErrorResponse } = require('../utils/errorHandlers.js'); const db = require('../../models'); /* diff --git a/server/routes/assets/serveAssetByClaim.js b/server/routes/assets/serveAssetByClaim.js index 26c1a995..fa73c031 100644 --- a/server/routes/assets/serveAssetByClaim.js +++ b/server/routes/assets/serveAssetByClaim.js @@ -1,6 +1,10 @@ const { sendGAServeEvent } = require('../../helpers/googleAnalytics'); -const { determineResponseType, logRequestData, getClaimIdAndServeAsset } = require('../../helpers/serveHelpers.js'); -const lbryUri = require('../../helpers/lbryUri.js'); +const { + determineResponseType, + logRequestData, + getClaimIdAndServeAsset, +} = require('../utils/serve.js'); +const lbryUri = require('../utils/lbryUri.js'); const handleShowRender = require('../../render/build/handleShowRender.js'); const SERVE = 'SERVE'; diff --git a/server/routes/assets/serveAssetByIdentifierAndClaim.js b/server/routes/assets/serveAssetByIdentifierAndClaim.js index 470a0be7..71c2d413 100644 --- a/server/routes/assets/serveAssetByIdentifierAndClaim.js +++ b/server/routes/assets/serveAssetByIdentifierAndClaim.js @@ -4,8 +4,8 @@ const { flipClaimNameAndIdForBackwardsCompatibility, logRequestData, getClaimIdAndServeAsset, -} = require('../../helpers/serveHelpers.js'); -const lbryUri = require('../../helpers/lbryUri.js'); +} = require('../utils/serve.js'); +const lbryUri = require('../utils/lbryUri.js'); const handleShowRender = require('../../render/build/handleShowRender.js'); const SERVE = 'SERVE'; diff --git a/server/helpers/errorHandlers.js b/server/routes/utils/errorHandlers.js similarity index 100% rename from server/helpers/errorHandlers.js rename to server/routes/utils/errorHandlers.js diff --git a/server/helpers/lbryUri.js b/server/routes/utils/lbryUri.js similarity index 100% rename from server/helpers/lbryUri.js rename to server/routes/utils/lbryUri.js diff --git a/server/helpers/serveHelpers.js b/server/routes/utils/serve.js similarity index 97% rename from server/helpers/serveHelpers.js rename to server/routes/utils/serve.js index 4a425327..a5c9acd0 100644 --- a/server/helpers/serveHelpers.js +++ b/server/routes/utils/serve.js @@ -1,5 +1,5 @@ const logger = require('winston'); -const { getClaimId, getLocalFileRecord } = require('../controllers/serveController.js'); +const { getClaimId, getLocalFileRecord } = require('../../controllers/serveController.js'); const { handleErrorResponse } = require('./errorHandlers.js'); const SERVE = 'SERVE'; diff --git a/server/speechPassport/index.js b/server/speechPassport/index.js index 3c60d3bc..60ec1808 100644 --- a/server/speechPassport/index.js +++ b/server/speechPassport/index.js @@ -1,10 +1,11 @@ const passport = require('passport'); -const localLoginStrategy = require('./local-login.js'); -const localSignupStrategy = require('./local-signup.js'); -const { serializeSpeechUser, deserializeSpeechUser } = require('../helpers/authHelpers.js'); +const localLoginStrategy = require('./utils/local-login.js'); +const localSignupStrategy = require('./utils/local-signup.js'); +const serializeUser = require('./utils/serializeUser.js'); +const deserializeUser = require('./utils/deserializeUser.js'); -passport.deserializeUser(deserializeSpeechUser); -passport.serializeUser(serializeSpeechUser); +passport.deserializeUser(deserializeUser); +passport.serializeUser(serializeUser); passport.use('local-login', localLoginStrategy); passport.use('local-signup', localSignupStrategy); diff --git a/server/speechPassport/utils/deserializeUser.js b/server/speechPassport/utils/deserializeUser.js new file mode 100644 index 00000000..34cecfa1 --- /dev/null +++ b/server/speechPassport/utils/deserializeUser.js @@ -0,0 +1,7 @@ +const deserializeUser = (user, done) => { + // deserializes session and populates additional info to req.user + console.log('deserializing user'); + done(null, user); +}; + +module.exports = deserializeUser; diff --git a/server/speechPassport/local-login.js b/server/speechPassport/utils/local-login.js similarity index 97% rename from server/speechPassport/local-login.js rename to server/speechPassport/utils/local-login.js index 42be4b47..a8a11b8f 100644 --- a/server/speechPassport/local-login.js +++ b/server/speechPassport/utils/local-login.js @@ -1,6 +1,6 @@ const PassportLocalStrategy = require('passport-local').Strategy; const logger = require('winston'); -const db = require('../models'); +const db = require('../../models/index'); const returnUserAndChannelInfo = (userInstance) => { return new Promise((resolve, reject) => { diff --git a/server/speechPassport/local-signup.js b/server/speechPassport/utils/local-signup.js similarity index 96% rename from server/speechPassport/local-signup.js rename to server/speechPassport/utils/local-signup.js index 07971a9e..cabb0b0f 100644 --- a/server/speechPassport/local-signup.js +++ b/server/speechPassport/utils/local-signup.js @@ -1,7 +1,7 @@ const PassportLocalStrategy = require('passport-local').Strategy; -const lbryApi = require('../helpers/lbryApi.js'); +const lbryApi = require('../../helpers/lbryApi.js'); const logger = require('winston'); -const db = require('../models'); +const db = require('../../models/index'); module.exports = new PassportLocalStrategy( { diff --git a/server/speechPassport/utils/serializeUser.js b/server/speechPassport/utils/serializeUser.js new file mode 100644 index 00000000..ce3cc719 --- /dev/null +++ b/server/speechPassport/utils/serializeUser.js @@ -0,0 +1,7 @@ +const serializeUser = (user, done) => { + // returns user data to be serialized into session + console.log('serializing user'); + done(null, user); +}; + +module.exports = serializeUser; From b785edf100ec126555a19be3334d17aaef4a1fb0 Mon Sep 17 00:00:00 2001 From: bill bittner Date: Thu, 26 Apr 2018 19:19:11 -0700 Subject: [PATCH 02/13] moved remaining helpers except for publishHelpers --- index.js | 2 +- server/controllers/publishController.js | 2 +- server/helpers/configVarCheck.js | 17 --------- server/helpers/sequelizeHelpers.js | 25 ------------ server/helpers/statsHelpers.js | 38 ------------------- server/models/certificate.js | 2 +- server/models/claim.js | 2 +- server/models/utils/returnShortId.js | 25 ++++++++++++ server/routes/api/channelAvailability.js | 2 +- server/routes/api/claimAvailability.js | 2 +- server/routes/api/claimGet.js | 2 +- server/routes/api/claimList.js | 2 +- server/routes/api/claimPublish.js | 2 +- server/routes/api/claimResolve.js | 2 +- server/routes/api/index.js | 2 +- server/routes/assets/serveAssetByClaim.js | 2 +- .../assets/serveAssetByIdentifierAndClaim.js | 2 +- .../utils}/multipartMiddleware.js | 2 +- server/speechPassport/utils/local-signup.js | 2 +- server/{helpers => utils}/googleAnalytics.js | 0 server/{helpers => utils}/lbryApi.js | 0 21 files changed, 40 insertions(+), 95 deletions(-) delete mode 100644 server/helpers/configVarCheck.js delete mode 100644 server/helpers/sequelizeHelpers.js delete mode 100644 server/helpers/statsHelpers.js create mode 100644 server/models/utils/returnShortId.js rename server/{helpers => routes/utils}/multipartMiddleware.js (64%) rename server/{helpers => utils}/googleAnalytics.js (100%) rename server/{helpers => utils}/lbryApi.js (100%) diff --git a/index.js b/index.js index bcb6bb08..0e2a6efc 100644 --- a/index.js +++ b/index.js @@ -55,7 +55,7 @@ function Server () { app.use(requestLogger); // configure passport - const speechPassport = require('./server/speechPassport/index'); + const speechPassport = require('./server/speechPassport'); // initialize passport const sessionKey = siteConfig.auth.sessionKey; app.use(cookieSession({ diff --git a/server/controllers/publishController.js b/server/controllers/publishController.js index cee6dbbe..9037fccc 100644 --- a/server/controllers/publishController.js +++ b/server/controllers/publishController.js @@ -1,6 +1,6 @@ const logger = require('winston'); const db = require('../models'); -const lbryApi = require('../helpers/lbryApi.js'); +const lbryApi = require('../utils/lbryApi.js'); const publishHelpers = require('../helpers/publishHelpers.js'); const { publishing: { primaryClaimAddress, additionalClaimAddresses } } = require('../../config/siteConfig.js'); const Sequelize = require('sequelize'); diff --git a/server/helpers/configVarCheck.js b/server/helpers/configVarCheck.js deleted file mode 100644 index 642125ba..00000000 --- a/server/helpers/configVarCheck.js +++ /dev/null @@ -1,17 +0,0 @@ -const logger = require('winston'); - -module.exports = (config) => { - // get the config file - for (let configCategoryKey in config) { - if (config.hasOwnProperty(configCategoryKey)) { - // get the final variables for each config category - const configVariables = config[configCategoryKey]; - for (let configVarKey in configVariables) { - if (configVariables.hasOwnProperty(configVarKey)) { - // print each variable - logger.debug(`CONFIG CHECK: ${configCategoryKey}.${configVarKey} === ${configVariables[configVarKey]}`); - } - } - } - } -}; diff --git a/server/helpers/sequelizeHelpers.js b/server/helpers/sequelizeHelpers.js deleted file mode 100644 index 0297f676..00000000 --- a/server/helpers/sequelizeHelpers.js +++ /dev/null @@ -1,25 +0,0 @@ -module.exports = { - returnShortId: function (claimsArray, longId) { - let claimIndex; - let shortId = longId.substring(0, 1); // default short id is the first letter - let shortIdLength = 0; - // find the index of this claim id - claimIndex = claimsArray.findIndex(element => { - return element.claimId === longId; - }); - if (claimIndex < 0) { - throw new Error('claim id not found in claims list'); - } - // get an array of all claims with lower height - let possibleMatches = claimsArray.slice(0, claimIndex); - // remove certificates with the same prefixes until none are left. - while (possibleMatches.length > 0) { - shortIdLength += 1; - shortId = longId.substring(0, shortIdLength); - possibleMatches = possibleMatches.filter(element => { - return (element.claimId && (element.claimId.substring(0, shortIdLength) === shortId)); - }); - } - return shortId; - }, -}; diff --git a/server/helpers/statsHelpers.js b/server/helpers/statsHelpers.js deleted file mode 100644 index 9e471172..00000000 --- a/server/helpers/statsHelpers.js +++ /dev/null @@ -1,38 +0,0 @@ -const logger = require('winston'); -const db = require('../models'); - -module.exports = { - postToStats (action, url, ipAddress, name, claimId, result) { - logger.debug('action:', action); - // make sure the result is a string - if (result && (typeof result !== 'string')) { - result = result.toString(); - } - // make sure the ip address(es) are a string - if (ipAddress && (typeof ipAddress !== 'string')) { - ipAddress = ipAddress.toString(); - } - db.File - .findOne({where: { name, claimId }}) - .then(file => { - // create record in the db - let FileId; - if (file) { - FileId = file.dataValues.id; - } else { - FileId = null; - } - return db.Request - .create({ - action, - url, - ipAddress, - result, - FileId, - }); - }) - .catch(error => { - logger.error('Sequelize error >>', error); - }); - }, -}; diff --git a/server/models/certificate.js b/server/models/certificate.js index 7a83f66d..679f6312 100644 --- a/server/models/certificate.js +++ b/server/models/certificate.js @@ -1,5 +1,5 @@ const logger = require('winston'); -const { returnShortId } = require('../helpers/sequelizeHelpers.js'); +const returnShortId = require('./utils/returnShortId.js'); module.exports = (sequelize, { STRING, BOOLEAN, INTEGER, TEXT, DECIMAL }) => { const Certificate = sequelize.define( diff --git a/server/models/claim.js b/server/models/claim.js index b7803cb6..1ab5f355 100644 --- a/server/models/claim.js +++ b/server/models/claim.js @@ -1,5 +1,5 @@ const logger = require('winston'); -const { returnShortId } = require('../helpers/sequelizeHelpers.js'); +const returnShortId = require('./utils/returnShortId.js'); const { assetDefaults: { thumbnail: defaultThumbnail }, details: { host } } = require('../../config/siteConfig.js'); function determineFileExtensionFromContentType (contentType) { diff --git a/server/models/utils/returnShortId.js b/server/models/utils/returnShortId.js new file mode 100644 index 00000000..9c362c61 --- /dev/null +++ b/server/models/utils/returnShortId.js @@ -0,0 +1,25 @@ +const returnShortId = (claimsArray, longId) => { + let claimIndex; + let shortId = longId.substring(0, 1); // default short id is the first letter + let shortIdLength = 0; + // find the index of this claim id + claimIndex = claimsArray.findIndex(element => { + return element.claimId === longId; + }); + if (claimIndex < 0) { + throw new Error('claim id not found in claims list'); + } + // get an array of all claims with lower height + let possibleMatches = claimsArray.slice(0, claimIndex); + // remove certificates with the same prefixes until none are left. + while (possibleMatches.length > 0) { + shortIdLength += 1; + shortId = longId.substring(0, shortIdLength); + possibleMatches = possibleMatches.filter(element => { + return (element.claimId && (element.claimId.substring(0, shortIdLength) === shortId)); + }); + } + return shortId; +}; + +module.exports = returnShortId; diff --git a/server/routes/api/channelAvailability.js b/server/routes/api/channelAvailability.js index 672bdcd0..6ea7a76b 100644 --- a/server/routes/api/channelAvailability.js +++ b/server/routes/api/channelAvailability.js @@ -1,5 +1,5 @@ const { checkChannelAvailability } = require('../../controllers/publishController.js'); -const { sendGATimingEvent } = require('../../helpers/googleAnalytics.js'); +const { sendGATimingEvent } = require('../../utils/googleAnalytics.js'); const { handleErrorResponse } = require('../utils/errorHandlers.js'); /* diff --git a/server/routes/api/claimAvailability.js b/server/routes/api/claimAvailability.js index c4d05cdd..575bd4d4 100644 --- a/server/routes/api/claimAvailability.js +++ b/server/routes/api/claimAvailability.js @@ -1,5 +1,5 @@ const { claimNameIsAvailable } = require('../../controllers/publishController.js'); -const { sendGATimingEvent } = require('../../helpers/googleAnalytics.js'); +const { sendGATimingEvent } = require('../../utils/googleAnalytics.js'); const { handleErrorResponse } = require('../utils/errorHandlers.js'); /* diff --git a/server/routes/api/claimGet.js b/server/routes/api/claimGet.js index 1551b7f2..77553397 100644 --- a/server/routes/api/claimGet.js +++ b/server/routes/api/claimGet.js @@ -1,4 +1,4 @@ -const { getClaim } = require('../../helpers/lbryApi.js'); +const { getClaim } = require('../../utils/lbryApi.js'); const { addGetResultsToFileData, createFileData } = require('../../helpers/publishHelpers.js'); const { handleErrorResponse } = require('../utils/errorHandlers.js'); const db = require('../../models'); diff --git a/server/routes/api/claimList.js b/server/routes/api/claimList.js index e5a54215..2502007a 100644 --- a/server/routes/api/claimList.js +++ b/server/routes/api/claimList.js @@ -1,4 +1,4 @@ -const { getClaimList } = require('../../helpers/lbryApi.js'); +const { getClaimList } = require('../../utils/lbryApi.js'); const { handleErrorResponse } = require('../utils/errorHandlers.js'); /* diff --git a/server/routes/api/claimPublish.js b/server/routes/api/claimPublish.js index c3074421..d1312fdc 100644 --- a/server/routes/api/claimPublish.js +++ b/server/routes/api/claimPublish.js @@ -1,7 +1,7 @@ const { createBasicPublishParams, createThumbnailPublishParams, parsePublishApiRequestBody, parsePublishApiRequestFiles } = require('../../helpers/publishHelpers.js'); const { claimNameIsAvailable, publish } = require('../../controllers/publishController.js'); const { authenticateUser } = require('../../auth/authentication.js'); -const { sendGATimingEvent } = require('../../helpers/googleAnalytics.js'); +const { sendGATimingEvent } = require('../../utils/googleAnalytics.js'); const { handleErrorResponse } = require('../utils/errorHandlers.js'); const { details: { host } } = require('../../../config/siteConfig.js'); diff --git a/server/routes/api/claimResolve.js b/server/routes/api/claimResolve.js index 8f8aeaf9..459efa51 100644 --- a/server/routes/api/claimResolve.js +++ b/server/routes/api/claimResolve.js @@ -1,4 +1,4 @@ -const { resolveUri } = require('../../helpers/lbryApi.js'); +const { resolveUri } = require('../../utils/lbryApi.js'); const { handleErrorResponse } = require('../utils/errorHandlers.js'); /* diff --git a/server/routes/api/index.js b/server/routes/api/index.js index b6ce0964..59e9e169 100644 --- a/server/routes/api/index.js +++ b/server/routes/api/index.js @@ -12,7 +12,7 @@ const claimShortId = require('./claimShortId'); const claimList = require('./claimList'); const fileAvailability = require('./fileAvailability'); -const multipartMiddleware = require('../../helpers/multipartMiddleware'); +const multipartMiddleware = require('../utils/multipartMiddleware'); module.exports = (app) => { // channel routes diff --git a/server/routes/assets/serveAssetByClaim.js b/server/routes/assets/serveAssetByClaim.js index fa73c031..63592043 100644 --- a/server/routes/assets/serveAssetByClaim.js +++ b/server/routes/assets/serveAssetByClaim.js @@ -1,4 +1,4 @@ -const { sendGAServeEvent } = require('../../helpers/googleAnalytics'); +const { sendGAServeEvent } = require('../../utils/googleAnalytics'); const { determineResponseType, logRequestData, diff --git a/server/routes/assets/serveAssetByIdentifierAndClaim.js b/server/routes/assets/serveAssetByIdentifierAndClaim.js index 71c2d413..f7bd8d18 100644 --- a/server/routes/assets/serveAssetByIdentifierAndClaim.js +++ b/server/routes/assets/serveAssetByIdentifierAndClaim.js @@ -1,4 +1,4 @@ -const { sendGAServeEvent } = require('../../helpers/googleAnalytics'); +const { sendGAServeEvent } = require('../../utils/googleAnalytics'); const { determineResponseType, flipClaimNameAndIdForBackwardsCompatibility, diff --git a/server/helpers/multipartMiddleware.js b/server/routes/utils/multipartMiddleware.js similarity index 64% rename from server/helpers/multipartMiddleware.js rename to server/routes/utils/multipartMiddleware.js index e85fc5c6..bd2e98f6 100644 --- a/server/helpers/multipartMiddleware.js +++ b/server/routes/utils/multipartMiddleware.js @@ -1,5 +1,5 @@ const multipart = require('connect-multiparty'); -const { publishing: { uploadDirectory } } = require('../../config/siteConfig.js'); +const { publishing: { uploadDirectory } } = require('../../../config/siteConfig.js'); const multipartMiddleware = multipart({uploadDir: uploadDirectory}); module.exports = multipartMiddleware; diff --git a/server/speechPassport/utils/local-signup.js b/server/speechPassport/utils/local-signup.js index cabb0b0f..0f4326e6 100644 --- a/server/speechPassport/utils/local-signup.js +++ b/server/speechPassport/utils/local-signup.js @@ -1,5 +1,5 @@ const PassportLocalStrategy = require('passport-local').Strategy; -const lbryApi = require('../../helpers/lbryApi.js'); +const lbryApi = require('../../utils/lbryApi.js'); const logger = require('winston'); const db = require('../../models/index'); diff --git a/server/helpers/googleAnalytics.js b/server/utils/googleAnalytics.js similarity index 100% rename from server/helpers/googleAnalytics.js rename to server/utils/googleAnalytics.js diff --git a/server/helpers/lbryApi.js b/server/utils/lbryApi.js similarity index 100% rename from server/helpers/lbryApi.js rename to server/utils/lbryApi.js From dd012282d3b6f7d02a39f3803e9ab15b141128ee Mon Sep 17 00:00:00 2001 From: bill bittner Date: Thu, 26 Apr 2018 23:42:22 -0700 Subject: [PATCH 03/13] reorganized controllers into folders by route --- .../api/channelAvailability.js | 2 +- .../api/channelClaims.js | 2 +- .../api/channelData.js | 2 +- .../api/channelShortId.js | 2 +- .../api/claimAvailability.js | 4 +- .../{routes => controllers}/api/claimData.js | 2 +- .../{routes => controllers}/api/claimGet.js | 4 +- .../{routes => controllers}/api/claimList.js | 2 +- .../api/claimLongId.js | 2 +- .../api/claimPublish.js | 16 ++- .../api/claimResolve.js | 2 +- .../api/claimShortId.js | 2 +- .../api/fileAvailability.js | 2 +- .../assets/serveAssetByClaim.js | 0 .../assets/serveAssetByIdentifierAndClaim.js | 0 server/{routes => controllers}/auth/login.js | 2 +- server/{routes => controllers}/auth/logout.js | 0 server/{routes => controllers}/auth/signup.js | 0 server/{routes => controllers}/auth/user.js | 0 .../fallback/sendReactApp.js | 0 .../{routes => controllers}/pages/redirect.js | 0 .../pages/sendEmbedPage.js | 0 .../pages/sendReactApp.js | 0 server/controllers/publishController.js | 134 ------------------ server/controllers/statsController.js | 19 --- server/controllers/utils/channelPagination.js | 6 +- .../utils/checkChannelAvailability.js | 19 +++ .../utils/checkClaimAvailability.js | 31 ++++ server/controllers/utils/deleteFile.js | 13 ++ .../utils/errorHandlers.js | 4 +- server/controllers/utils/file.js | 20 +++ .../{routes => controllers}/utils/lbryUri.js | 0 server/controllers/utils/publish.js | 92 ++++++++++++ .../utils}/publishHelpers.js | 13 +- server/{routes => controllers}/utils/serve.js | 2 +- .../serveHelpers.js} | 4 +- server/{utils/lbryApi.js => lbrynet/index.js} | 33 ++--- server/lbrynet/utils/handleLbrynetResponse.js | 19 +++ server/routes/api/index.js | 26 ++-- server/routes/assets/index.js | 4 +- server/routes/auth/index.js | 8 +- server/routes/fallback/index.js | 2 +- server/routes/pages/index.js | 6 +- server/speechPassport/utils/local-signup.js | 6 +- test/unit/publishHelpers.test.js | 2 +- 45 files changed, 264 insertions(+), 245 deletions(-) rename server/{routes => controllers}/api/channelAvailability.js (88%) rename server/{routes => controllers}/api/channelClaims.js (90%) rename server/{routes => controllers}/api/channelData.js (90%) rename server/{routes => controllers}/api/channelShortId.js (91%) rename server/{routes => controllers}/api/claimAvailability.js (84%) rename server/{routes => controllers}/api/claimData.js (94%) rename server/{routes => controllers}/api/claimGet.js (93%) rename server/{routes => controllers}/api/claimList.js (86%) rename server/{routes => controllers}/api/claimLongId.js (92%) rename server/{routes => controllers}/api/claimPublish.js (87%) rename server/{routes => controllers}/api/claimResolve.js (88%) rename server/{routes => controllers}/api/claimShortId.js (91%) rename server/{routes => controllers}/api/fileAvailability.js (93%) rename server/{routes => controllers}/assets/serveAssetByClaim.js (100%) rename server/{routes => controllers}/assets/serveAssetByIdentifierAndClaim.js (100%) rename server/{routes => controllers}/auth/login.js (91%) rename server/{routes => controllers}/auth/logout.js (100%) rename server/{routes => controllers}/auth/signup.js (100%) rename server/{routes => controllers}/auth/user.js (100%) rename server/{routes => controllers}/fallback/sendReactApp.js (100%) rename server/{routes => controllers}/pages/redirect.js (100%) rename server/{routes => controllers}/pages/sendEmbedPage.js (100%) rename server/{routes => controllers}/pages/sendReactApp.js (100%) delete mode 100644 server/controllers/publishController.js delete mode 100644 server/controllers/statsController.js create mode 100644 server/controllers/utils/checkChannelAvailability.js create mode 100644 server/controllers/utils/checkClaimAvailability.js create mode 100644 server/controllers/utils/deleteFile.js rename server/{routes => controllers}/utils/errorHandlers.js (98%) create mode 100644 server/controllers/utils/file.js rename server/{routes => controllers}/utils/lbryUri.js (100%) create mode 100644 server/controllers/utils/publish.js rename server/{helpers => controllers/utils}/publishHelpers.js (93%) rename server/{routes => controllers}/utils/serve.js (97%) rename server/controllers/{serveController.js => utils/serveHelpers.js} (97%) rename server/{utils/lbryApi.js => lbrynet/index.js} (85%) create mode 100644 server/lbrynet/utils/handleLbrynetResponse.js diff --git a/server/routes/api/channelAvailability.js b/server/controllers/api/channelAvailability.js similarity index 88% rename from server/routes/api/channelAvailability.js rename to server/controllers/api/channelAvailability.js index 6ea7a76b..33f5f5f3 100644 --- a/server/routes/api/channelAvailability.js +++ b/server/controllers/api/channelAvailability.js @@ -1,4 +1,4 @@ -const { checkChannelAvailability } = require('../../controllers/publishController.js'); +const checkChannelAvailability = require('../utils/checkChannelAvailability.js'); const { sendGATimingEvent } = require('../../utils/googleAnalytics.js'); const { handleErrorResponse } = require('../utils/errorHandlers.js'); diff --git a/server/routes/api/channelClaims.js b/server/controllers/api/channelClaims.js similarity index 90% rename from server/routes/api/channelClaims.js rename to server/controllers/api/channelClaims.js index 980d3e8e..d9a3683e 100644 --- a/server/routes/api/channelClaims.js +++ b/server/controllers/api/channelClaims.js @@ -1,4 +1,4 @@ -const { getChannelClaims } = require('../../controllers/serveController.js'); +const { getChannelClaims } = require('../utils/serveHelpers.js'); const { handleErrorResponse } = require('../utils/errorHandlers.js'); const NO_CHANNEL = 'NO_CHANNEL'; diff --git a/server/routes/api/channelData.js b/server/controllers/api/channelData.js similarity index 90% rename from server/routes/api/channelData.js rename to server/controllers/api/channelData.js index 8f14cd47..92609412 100644 --- a/server/routes/api/channelData.js +++ b/server/controllers/api/channelData.js @@ -1,4 +1,4 @@ -const { getChannelData } = require('../../controllers/serveController.js'); +const { getChannelData } = require('../utils/serveHelpers.js'); const { handleErrorResponse } = require('../utils/errorHandlers.js'); const NO_CHANNEL = 'NO_CHANNEL'; diff --git a/server/routes/api/channelShortId.js b/server/controllers/api/channelShortId.js similarity index 91% rename from server/routes/api/channelShortId.js rename to server/controllers/api/channelShortId.js index c5575ab6..898456a1 100644 --- a/server/routes/api/channelShortId.js +++ b/server/controllers/api/channelShortId.js @@ -1,5 +1,5 @@ const { handleErrorResponse } = require('../utils/errorHandlers.js'); -const db = require('../../models'); +const db = require('../../models/index'); /* diff --git a/server/routes/api/claimAvailability.js b/server/controllers/api/claimAvailability.js similarity index 84% rename from server/routes/api/claimAvailability.js rename to server/controllers/api/claimAvailability.js index 575bd4d4..23a3a21f 100644 --- a/server/routes/api/claimAvailability.js +++ b/server/controllers/api/claimAvailability.js @@ -1,4 +1,4 @@ -const { claimNameIsAvailable } = require('../../controllers/publishController.js'); +const checkClaimAvailability = require('../utils/checkClaimAvailability.js'); const { sendGATimingEvent } = require('../../utils/googleAnalytics.js'); const { handleErrorResponse } = require('../utils/errorHandlers.js'); @@ -10,7 +10,7 @@ const { handleErrorResponse } = require('../utils/errorHandlers.js'); const claimAvailability = ({ ip, originalUrl, params: { name } }, res) => { const gaStartTime = Date.now(); - claimNameIsAvailable(name) + checkClaimAvailability(name) .then(result => { res.status(200).json(result); sendGATimingEvent('end-to-end', 'claim name availability', name, gaStartTime, Date.now()); diff --git a/server/routes/api/claimData.js b/server/controllers/api/claimData.js similarity index 94% rename from server/routes/api/claimData.js rename to server/controllers/api/claimData.js index 965336df..4549671d 100644 --- a/server/routes/api/claimData.js +++ b/server/controllers/api/claimData.js @@ -1,5 +1,5 @@ const { handleErrorResponse } = require('../utils/errorHandlers.js'); -const db = require('../../models'); +const db = require('../../models/index'); /* diff --git a/server/routes/api/claimGet.js b/server/controllers/api/claimGet.js similarity index 93% rename from server/routes/api/claimGet.js rename to server/controllers/api/claimGet.js index 77553397..a5a04926 100644 --- a/server/routes/api/claimGet.js +++ b/server/controllers/api/claimGet.js @@ -1,5 +1,5 @@ -const { getClaim } = require('../../utils/lbryApi.js'); -const { addGetResultsToFileData, createFileData } = require('../../helpers/publishHelpers.js'); +const { getClaim } = require('../../lbrynet'); +const { addGetResultsToFileData, createFileData } = require('../utils/file.js'); const { handleErrorResponse } = require('../utils/errorHandlers.js'); const db = require('../../models'); diff --git a/server/routes/api/claimList.js b/server/controllers/api/claimList.js similarity index 86% rename from server/routes/api/claimList.js rename to server/controllers/api/claimList.js index 2502007a..300b1864 100644 --- a/server/routes/api/claimList.js +++ b/server/controllers/api/claimList.js @@ -1,4 +1,4 @@ -const { getClaimList } = require('../../utils/lbryApi.js'); +const { getClaimList } = require('../../lbrynet/index'); const { handleErrorResponse } = require('../utils/errorHandlers.js'); /* diff --git a/server/routes/api/claimLongId.js b/server/controllers/api/claimLongId.js similarity index 92% rename from server/routes/api/claimLongId.js rename to server/controllers/api/claimLongId.js index 3286afae..aaa9b171 100644 --- a/server/routes/api/claimLongId.js +++ b/server/controllers/api/claimLongId.js @@ -1,4 +1,4 @@ -const { getClaimId } = require('../../controllers/serveController.js'); +const { getClaimId } = require('../utils/serveHelpers.js'); const { handleErrorResponse } = require('../utils/errorHandlers.js'); const NO_CHANNEL = 'NO_CHANNEL'; diff --git a/server/routes/api/claimPublish.js b/server/controllers/api/claimPublish.js similarity index 87% rename from server/routes/api/claimPublish.js rename to server/controllers/api/claimPublish.js index d1312fdc..f776a46e 100644 --- a/server/routes/api/claimPublish.js +++ b/server/controllers/api/claimPublish.js @@ -1,9 +1,15 @@ -const { createBasicPublishParams, createThumbnailPublishParams, parsePublishApiRequestBody, parsePublishApiRequestFiles } = require('../../helpers/publishHelpers.js'); -const { claimNameIsAvailable, publish } = require('../../controllers/publishController.js'); +const { details: { host } } = require('../../../config/siteConfig.js'); const { authenticateUser } = require('../../auth/authentication.js'); const { sendGATimingEvent } = require('../../utils/googleAnalytics.js'); const { handleErrorResponse } = require('../utils/errorHandlers.js'); -const { details: { host } } = require('../../../config/siteConfig.js'); +const checkClaimAvailability = require('../utils/checkClaimAvailability'); +const publish = require('../utils/publish.js'); +const { + createBasicPublishParams, + createThumbnailPublishParams, + parsePublishApiRequestBody, + parsePublishApiRequestFiles, +} = require('../utils/publishHelpers.js'); /* @@ -29,7 +35,7 @@ const claimPublish = ({ body, files, headers, ip, originalUrl, user }, res) => { Promise .all([ authenticateUser(channelName, channelId, channelPassword, user), - claimNameIsAvailable(name), + checkClaimAvailability(name), createBasicPublishParams(filePath, name, title, description, license, nsfw, thumbnail), createThumbnailPublishParams(thumbnailFilePath, name, license, nsfw), ]) @@ -39,7 +45,7 @@ const claimPublish = ({ body, files, headers, ip, originalUrl, user }, res) => { publishParams['channel_name'] = channelName; publishParams['channel_id'] = channelClaimId; } - // publish the thumbnail + // publish the thumbnail, if one exists if (thumbnailPublishParams) { publish(thumbnailPublishParams, thumbnailFileName, thumbnailFileType); } diff --git a/server/routes/api/claimResolve.js b/server/controllers/api/claimResolve.js similarity index 88% rename from server/routes/api/claimResolve.js rename to server/controllers/api/claimResolve.js index 459efa51..2d347ddd 100644 --- a/server/routes/api/claimResolve.js +++ b/server/controllers/api/claimResolve.js @@ -1,4 +1,4 @@ -const { resolveUri } = require('../../utils/lbryApi.js'); +const { resolveUri } = require('../../lbrynet/index'); const { handleErrorResponse } = require('../utils/errorHandlers.js'); /* diff --git a/server/routes/api/claimShortId.js b/server/controllers/api/claimShortId.js similarity index 91% rename from server/routes/api/claimShortId.js rename to server/controllers/api/claimShortId.js index db4833ba..4357c46c 100644 --- a/server/routes/api/claimShortId.js +++ b/server/controllers/api/claimShortId.js @@ -1,5 +1,5 @@ const { handleErrorResponse } = require('../utils/errorHandlers.js'); -const db = require('../../models'); +const db = require('../../models/index'); /* diff --git a/server/routes/api/fileAvailability.js b/server/controllers/api/fileAvailability.js similarity index 93% rename from server/routes/api/fileAvailability.js rename to server/controllers/api/fileAvailability.js index f5cdb5bc..116fcaaf 100644 --- a/server/routes/api/fileAvailability.js +++ b/server/controllers/api/fileAvailability.js @@ -1,5 +1,5 @@ const { handleErrorResponse } = require('../utils/errorHandlers.js'); -const db = require('../../models'); +const db = require('../../models/index'); /* diff --git a/server/routes/assets/serveAssetByClaim.js b/server/controllers/assets/serveAssetByClaim.js similarity index 100% rename from server/routes/assets/serveAssetByClaim.js rename to server/controllers/assets/serveAssetByClaim.js diff --git a/server/routes/assets/serveAssetByIdentifierAndClaim.js b/server/controllers/assets/serveAssetByIdentifierAndClaim.js similarity index 100% rename from server/routes/assets/serveAssetByIdentifierAndClaim.js rename to server/controllers/assets/serveAssetByIdentifierAndClaim.js diff --git a/server/routes/auth/login.js b/server/controllers/auth/login.js similarity index 91% rename from server/routes/auth/login.js rename to server/controllers/auth/login.js index 63f13814..229b4e98 100644 --- a/server/routes/auth/login.js +++ b/server/controllers/auth/login.js @@ -1,4 +1,4 @@ -const speechPassport = require('../../speechPassport'); +const speechPassport = require('../../speechPassport/index'); const login = (req, res, next) => { speechPassport.authenticate('local-login', (err, user, info) => { diff --git a/server/routes/auth/logout.js b/server/controllers/auth/logout.js similarity index 100% rename from server/routes/auth/logout.js rename to server/controllers/auth/logout.js diff --git a/server/routes/auth/signup.js b/server/controllers/auth/signup.js similarity index 100% rename from server/routes/auth/signup.js rename to server/controllers/auth/signup.js diff --git a/server/routes/auth/user.js b/server/controllers/auth/user.js similarity index 100% rename from server/routes/auth/user.js rename to server/controllers/auth/user.js diff --git a/server/routes/fallback/sendReactApp.js b/server/controllers/fallback/sendReactApp.js similarity index 100% rename from server/routes/fallback/sendReactApp.js rename to server/controllers/fallback/sendReactApp.js diff --git a/server/routes/pages/redirect.js b/server/controllers/pages/redirect.js similarity index 100% rename from server/routes/pages/redirect.js rename to server/controllers/pages/redirect.js diff --git a/server/routes/pages/sendEmbedPage.js b/server/controllers/pages/sendEmbedPage.js similarity index 100% rename from server/routes/pages/sendEmbedPage.js rename to server/controllers/pages/sendEmbedPage.js diff --git a/server/routes/pages/sendReactApp.js b/server/controllers/pages/sendReactApp.js similarity index 100% rename from server/routes/pages/sendReactApp.js rename to server/controllers/pages/sendReactApp.js diff --git a/server/controllers/publishController.js b/server/controllers/publishController.js deleted file mode 100644 index 9037fccc..00000000 --- a/server/controllers/publishController.js +++ /dev/null @@ -1,134 +0,0 @@ -const logger = require('winston'); -const db = require('../models'); -const lbryApi = require('../utils/lbryApi.js'); -const publishHelpers = require('../helpers/publishHelpers.js'); -const { publishing: { primaryClaimAddress, additionalClaimAddresses } } = require('../../config/siteConfig.js'); -const Sequelize = require('sequelize'); -const Op = Sequelize.Op; - -module.exports = { - publish (publishParams, fileName, fileType) { - return new Promise((resolve, reject) => { - let publishResults, certificateId, channelName; - // publish the file - return lbryApi.publishClaim(publishParams) - .then(tx => { - logger.info(`Successfully published ${publishParams.name} ${fileName}`, tx); - publishResults = tx; - // get the channel information - if (publishParams.channel_name) { - logger.debug(`this claim was published in channel: ${publishParams.channel_name}`); - return db.Channel.findOne({ - where: { - channelName: publishParams.channel_name, - }, - }); - } else { - logger.debug('this claim was not published in a channel'); - return null; - } - }) - .then(channel => { - // set channel information - certificateId = null; - channelName = null; - if (channel) { - certificateId = channel.channelClaimId; - channelName = channel.channelName; - } - logger.debug(`certificateId: ${certificateId}`); - }) - .then(() => { - // create the File record - const fileRecord = { - name : publishParams.name, - claimId : publishResults.claim_id, - title : publishParams.metadata.title, - description: publishParams.metadata.description, - address : publishParams.claim_address, - outpoint : `${publishResults.txid}:${publishResults.nout}`, - height : 0, - fileName, - filePath : publishParams.file_path, - fileType, - nsfw : publishParams.metadata.nsfw, - }; - // create the Claim record - const claimRecord = { - name : publishParams.name, - claimId : publishResults.claim_id, - title : publishParams.metadata.title, - description: publishParams.metadata.description, - address : publishParams.claim_address, - thumbnail : publishParams.metadata.thumbnail, - outpoint : `${publishResults.txid}:${publishResults.nout}`, - height : 0, - contentType: fileType, - nsfw : publishParams.metadata.nsfw, - amount : publishParams.bid, - certificateId, - channelName, - }; - // upsert criteria - const upsertCriteria = { - name : publishParams.name, - claimId: publishResults.claim_id, - }; - // upsert the records - return Promise.all([db.upsert(db.File, fileRecord, upsertCriteria, 'File'), db.upsert(db.Claim, claimRecord, upsertCriteria, 'Claim')]); - }) - .then(([file, claim]) => { - logger.debug('File and Claim records successfully created'); - return Promise.all([file.setClaim(claim), claim.setFile(file)]); - }) - .then(() => { - logger.debug('File and Claim records successfully associated'); - resolve(publishResults); // resolve the promise with the result from lbryApi.publishClaim; - }) - .catch(error => { - logger.error('PUBLISH ERROR', error); - publishHelpers.deleteTemporaryFile(publishParams.file_path); // delete the local file - reject(error); - }); - }); - }, - claimNameIsAvailable (name) { - const claimAddresses = additionalClaimAddresses || []; - claimAddresses.push(primaryClaimAddress); - // find any records where the name is used - return db.Claim - .findAll({ - attributes: ['address'], - where : { - name, - address: { - [Op.or]: claimAddresses, - }, - }, - }) - .then(result => { - if (result.length >= 1) { - throw new Error('That claim is already in use'); - }; - return name; - }) - .catch(error => { - throw error; - }); - }, - checkChannelAvailability (name) { - return db.Channel - .findAll({ - where: { channelName: name }, - }) - .then(result => { - if (result.length >= 1) { - throw new Error('That channel has already been claimed'); - } - return name; - }) - .catch(error => { - throw error; - }); - }, -}; diff --git a/server/controllers/statsController.js b/server/controllers/statsController.js deleted file mode 100644 index 8292ddc9..00000000 --- a/server/controllers/statsController.js +++ /dev/null @@ -1,19 +0,0 @@ -const logger = require('winston'); -const db = require('../models'); - -module.exports = { - getRecentClaims () { - logger.debug('retrieving most recent claims'); - return new Promise((resolve, reject) => { - // get the raw requests data - db.File.getRecentClaims() - .then(results => { - resolve(results); - }) - .catch(error => { - logger.error('sequelize error', error); - reject(error); - }); - }); - }, -}; diff --git a/server/controllers/utils/channelPagination.js b/server/controllers/utils/channelPagination.js index e76a1158..01c35e2d 100644 --- a/server/controllers/utils/channelPagination.js +++ b/server/controllers/utils/channelPagination.js @@ -4,7 +4,7 @@ module.exports = { returnPaginatedChannelClaims (channelName, longChannelClaimId, claims, page) { const totalPages = module.exports.determineTotalPages(claims); const paginationPage = module.exports.getPageFromQuery(page); - const viewData = { + return { channelName : channelName, longChannelClaimId: longChannelClaimId, claims : module.exports.extractPageFromClaims(claims, paginationPage), @@ -14,7 +14,6 @@ module.exports = { totalPages : totalPages, totalResults : module.exports.determineTotalClaims(claims), }; - return viewData; }, getPageFromQuery (page) { if (page) { @@ -30,8 +29,7 @@ module.exports = { // logger.debug(`pageNumber ${pageNumber} is number?`, Number.isInteger(pageNumber)); const claimStartIndex = (pageNumber - 1) * CLAIMS_PER_PAGE; const claimEndIndex = claimStartIndex + CLAIMS_PER_PAGE; - const pageOfClaims = claims.slice(claimStartIndex, claimEndIndex); - return pageOfClaims; + return claims.slice(claimStartIndex, claimEndIndex); }, determineTotalPages (claims) { if (!claims) { diff --git a/server/controllers/utils/checkChannelAvailability.js b/server/controllers/utils/checkChannelAvailability.js new file mode 100644 index 00000000..8dfce07a --- /dev/null +++ b/server/controllers/utils/checkChannelAvailability.js @@ -0,0 +1,19 @@ +const db = require('../../models'); + +const checkChannelAvailability = (name) => { + return db.Channel + .findAll({ + where: { channelName: name }, + }) + .then(result => { + if (result.length >= 1) { + throw new Error('That channel has already been claimed'); + } + return name; + }) + .catch(error => { + throw error; + }); +}; + +module.exports = checkChannelAvailability; diff --git a/server/controllers/utils/checkClaimAvailability.js b/server/controllers/utils/checkClaimAvailability.js new file mode 100644 index 00000000..9cd3d09b --- /dev/null +++ b/server/controllers/utils/checkClaimAvailability.js @@ -0,0 +1,31 @@ +const db = require('../../models/index'); +const { publishing: { primaryClaimAddress, additionalClaimAddresses } } = require('../../../config/siteConfig.js'); +const Sequelize = require('sequelize'); +const Op = Sequelize.Op; + +const claimAvailability = (name) => { + const claimAddresses = additionalClaimAddresses || []; + claimAddresses.push(primaryClaimAddress); + // find any records where the name is used + return db.Claim + .findAll({ + attributes: ['address'], + where : { + name, + address: { + [Op.or]: claimAddresses, + }, + }, + }) + .then(result => { + if (result.length >= 1) { + throw new Error('That claim is already in use'); + } + return name; + }) + .catch(error => { + throw error; + }); +}; + +module.exports = claimAvailability; diff --git a/server/controllers/utils/deleteFile.js b/server/controllers/utils/deleteFile.js new file mode 100644 index 00000000..2381f001 --- /dev/null +++ b/server/controllers/utils/deleteFile.js @@ -0,0 +1,13 @@ +const logger = require('winston'); +const fs = require('fs'); + +const deleteFile = (filePath) => { + fs.unlink(filePath, err => { + if (err) { + return logger.error(`error deleting temporary file ${filePath}`); + } + logger.debug(`successfully deleted ${filePath}`); + }); +}; + +module.exports = deleteFile; diff --git a/server/routes/utils/errorHandlers.js b/server/controllers/utils/errorHandlers.js similarity index 98% rename from server/routes/utils/errorHandlers.js rename to server/controllers/utils/errorHandlers.js index 1c7336dd..c2d6cac5 100644 --- a/server/routes/utils/errorHandlers.js +++ b/server/controllers/utils/errorHandlers.js @@ -21,8 +21,8 @@ module.exports = { message = error.message; } else { message = error; - }; - }; + } + } return [status, message]; }, useObjectPropertiesIfNoKeys: function (err) { diff --git a/server/controllers/utils/file.js b/server/controllers/utils/file.js new file mode 100644 index 00000000..b786f8e8 --- /dev/null +++ b/server/controllers/utils/file.js @@ -0,0 +1,20 @@ +module.exports = { + addGetResultsToFileData (fileInfo, getResult) { + fileInfo.fileName = getResult.file_name; + fileInfo.filePath = getResult.download_path; + return fileInfo; + }, + createFileData ({ name, claimId, outpoint, height, address, nsfw, contentType }) { + return { + name, + claimId, + outpoint, + height, + address, + fileName: '', + filePath: '', + fileType: contentType, + nsfw, + }; + }, +}; diff --git a/server/routes/utils/lbryUri.js b/server/controllers/utils/lbryUri.js similarity index 100% rename from server/routes/utils/lbryUri.js rename to server/controllers/utils/lbryUri.js diff --git a/server/controllers/utils/publish.js b/server/controllers/utils/publish.js new file mode 100644 index 00000000..5d2daea2 --- /dev/null +++ b/server/controllers/utils/publish.js @@ -0,0 +1,92 @@ +const logger = require('winston'); +const db = require('../../models'); +const { publishClaim } = require('../../lbrynet'); +const deleteFile = require('./deleteFile.js'); + +const publish = (publishParams, fileName, fileType) => { + return new Promise((resolve, reject) => { + let publishResults, certificateId, channelName; + // publish the file + return publishClaim(publishParams) + .then(tx => { + logger.info(`Successfully published ${publishParams.name} ${fileName}`, tx); + publishResults = tx; + // get the channel information + if (publishParams.channel_name) { + logger.debug(`this claim was published in channel: ${publishParams.channel_name}`); + return db.Channel.findOne({ + where: { + channelName: publishParams.channel_name, + }, + }); + } else { + logger.debug('this claim was not published in a channel'); + return null; + } + }) + .then(channel => { + // set channel information + certificateId = null; + channelName = null; + if (channel) { + certificateId = channel.channelClaimId; + channelName = channel.channelName; + } + logger.debug(`certificateId: ${certificateId}`); + }) + .then(() => { + // create the File record + const fileRecord = { + name : publishParams.name, + claimId : publishResults.claim_id, + title : publishParams.metadata.title, + description: publishParams.metadata.description, + address : publishParams.claim_address, + outpoint : `${publishResults.txid}:${publishResults.nout}`, + height : 0, + fileName, + filePath : publishParams.file_path, + fileType, + nsfw : publishParams.metadata.nsfw, + }; + // create the Claim record + const claimRecord = { + name : publishParams.name, + claimId : publishResults.claim_id, + title : publishParams.metadata.title, + description: publishParams.metadata.description, + address : publishParams.claim_address, + thumbnail : publishParams.metadata.thumbnail, + outpoint : `${publishResults.txid}:${publishResults.nout}`, + height : 0, + contentType: fileType, + nsfw : publishParams.metadata.nsfw, + amount : publishParams.bid, + certificateId, + channelName, + }; + // upsert criteria + const upsertCriteria = { + name : publishParams.name, + claimId: publishResults.claim_id, + }; + // upsert the records + return Promise.all([db.upsert(db.File, fileRecord, upsertCriteria, 'File'), db.upsert(db.Claim, claimRecord, upsertCriteria, 'Claim')]); + }) + .then(([file, claim]) => { + logger.debug('File and Claim records successfully created'); + return Promise.all([file.setClaim(claim), claim.setFile(file)]); + }) + .then(() => { + logger.debug('File and Claim records successfully associated'); + resolve(publishResults); // resolve the promise with the result from lbryApi publishClaim; + }) + .catch(error => { + logger.error('PUBLISH ERROR', error); + deleteFile(publishParams.file_path); // delete the local file + reject(error); + }); + }); +}; + +module.exports = publish; diff --git a/server/helpers/publishHelpers.js b/server/controllers/utils/publishHelpers.js similarity index 93% rename from server/helpers/publishHelpers.js rename to server/controllers/utils/publishHelpers.js index 03625d9e..8338f08e 100644 --- a/server/helpers/publishHelpers.js +++ b/server/controllers/utils/publishHelpers.js @@ -1,7 +1,5 @@ const logger = require('winston'); -const fs = require('fs'); - -const { details, publishing } = require('../../config/siteConfig.js'); +const { details, publishing } = require('../../../config/siteConfig.js'); module.exports = { parsePublishApiRequestBody ({name, nsfw, license, title, description, thumbnail}) { @@ -146,15 +144,6 @@ module.exports = { channel_id : publishing.thumbnailChannelId, }; }, - deleteTemporaryFile (filePath) { - fs.unlink(filePath, err => { - if (err) { - logger.error(`error deleting temporary file ${filePath}`); - throw err; - } - logger.debug(`successfully deleted ${filePath}`); - }); - }, addGetResultsToFileData (fileInfo, getResult) { fileInfo.fileName = getResult.file_name; fileInfo.filePath = getResult.download_path; diff --git a/server/routes/utils/serve.js b/server/controllers/utils/serve.js similarity index 97% rename from server/routes/utils/serve.js rename to server/controllers/utils/serve.js index a5c9acd0..f9fb7f8b 100644 --- a/server/routes/utils/serve.js +++ b/server/controllers/utils/serve.js @@ -1,5 +1,5 @@ const logger = require('winston'); -const { getClaimId, getLocalFileRecord } = require('../../controllers/serveController.js'); +const { getClaimId, getLocalFileRecord } = require('./serveHelpers.js'); const { handleErrorResponse } = require('./errorHandlers.js'); const SERVE = 'SERVE'; diff --git a/server/controllers/serveController.js b/server/controllers/utils/serveHelpers.js similarity index 97% rename from server/controllers/serveController.js rename to server/controllers/utils/serveHelpers.js index 0513073a..cbed71de 100644 --- a/server/controllers/serveController.js +++ b/server/controllers/utils/serveHelpers.js @@ -1,6 +1,6 @@ -const db = require('../models'); +const db = require('../../models/index'); const logger = require('winston'); -const { returnPaginatedChannelClaims } = require('./utils/channelPagination.js'); +const { returnPaginatedChannelClaims } = require('./channelPagination.js'); const NO_CHANNEL = 'NO_CHANNEL'; const NO_CLAIM = 'NO_CLAIM'; diff --git a/server/utils/lbryApi.js b/server/lbrynet/index.js similarity index 85% rename from server/utils/lbryApi.js rename to server/lbrynet/index.js index 4d54ad2b..c8ea72a1 100644 --- a/server/utils/lbryApi.js +++ b/server/lbrynet/index.js @@ -1,24 +1,9 @@ const axios = require('axios'); const logger = require('winston'); const { api: { apiHost, apiPort } } = require('../../config/lbryConfig.js'); -const lbryApiUri = 'http://' + apiHost + ':' + apiPort; -const { chooseGaLbrynetPublishLabel, sendGATimingEvent } = require('./googleAnalytics.js'); - -const handleLbrynetResponse = ({ data }, resolve, reject) => { - logger.debug('lbry api data:', data); - if (data.result) { - // check for an error - if (data.result.error) { - logger.debug('Lbrynet api error:', data.result.error); - reject(new Error(data.result.error)); - return; - }; - resolve(data.result); - return; - } - // fallback in case it just timed out - reject(JSON.stringify(data)); -}; +const lbrynetUri = 'http://' + apiHost + ':' + apiPort; +const { chooseGaLbrynetPublishLabel, sendGATimingEvent } = require('../utils/googleAnalytics.js'); +const handleLbrynetResponse = require('./utils/handleLbrynetResponse.js'); module.exports = { publishClaim (publishParams) { @@ -26,7 +11,7 @@ module.exports = { const gaStartTime = Date.now(); return new Promise((resolve, reject) => { axios - .post(lbryApiUri, { + .post(lbrynetUri, { method: 'publish', params: publishParams, }) @@ -44,7 +29,7 @@ module.exports = { const gaStartTime = Date.now(); return new Promise((resolve, reject) => { axios - .post(lbryApiUri, { + .post(lbrynetUri, { method: 'get', params: { uri, timeout: 20 }, }) @@ -62,7 +47,7 @@ module.exports = { const gaStartTime = Date.now(); return new Promise((resolve, reject) => { axios - .post(lbryApiUri, { + .post(lbrynetUri, { method: 'claim_list', params: { name: claimName }, }) @@ -80,7 +65,7 @@ module.exports = { const gaStartTime = Date.now(); return new Promise((resolve, reject) => { axios - .post(lbryApiUri, { + .post(lbrynetUri, { method: 'resolve', params: { uri }, }) @@ -102,7 +87,7 @@ module.exports = { const gaStartTime = Date.now(); return new Promise((resolve, reject) => { axios - .post(lbryApiUri, { + .post(lbrynetUri, { method: 'settings_get', }) .then(({ data }) => { @@ -124,7 +109,7 @@ module.exports = { const gaStartTime = Date.now(); return new Promise((resolve, reject) => { axios - .post(lbryApiUri, { + .post(lbrynetUri, { method: 'channel_new', params: { channel_name: name, diff --git a/server/lbrynet/utils/handleLbrynetResponse.js b/server/lbrynet/utils/handleLbrynetResponse.js new file mode 100644 index 00000000..8c430047 --- /dev/null +++ b/server/lbrynet/utils/handleLbrynetResponse.js @@ -0,0 +1,19 @@ +const logger = require('winston'); + +const handleLbrynetResponse = ({ data }, resolve, reject) => { + logger.debug('lbry api data:', data); + if (data.result) { + // check for an error + if (data.result.error) { + logger.debug('Lbrynet api error:', data.result.error); + reject(new Error(data.result.error)); + return; + }; + resolve(data.result); + return; + } + // fallback in case it just timed out + reject(JSON.stringify(data)); +}; + +module.exports = handleLbrynetResponse; diff --git a/server/routes/api/index.js b/server/routes/api/index.js index 59e9e169..15b272f5 100644 --- a/server/routes/api/index.js +++ b/server/routes/api/index.js @@ -1,16 +1,16 @@ -const channelAvailability = require('./channelAvailability'); -const channelClaims = require('./channelClaims'); -const channelData = require('./channelData'); -const channelShortId = require('./channelShortId'); -const claimAvailability = require('./claimAvailability'); -const claimData = require('./claimData'); -const claimGet = require('./claimGet'); -const claimLongId = require('./claimLongId'); -const claimPublish = require('./claimPublish'); -const claimResolve = require('./claimResolve'); -const claimShortId = require('./claimShortId'); -const claimList = require('./claimList'); -const fileAvailability = require('./fileAvailability'); +const channelAvailability = require('../../controllers/api/channelAvailability'); +const channelClaims = require('../../controllers/api/channelClaims'); +const channelData = require('../../controllers/api/channelData'); +const channelShortId = require('../../controllers/api/channelShortId'); +const claimAvailability = require('../../controllers/api/claimAvailability'); +const claimData = require('../../controllers/api/claimData'); +const claimGet = require('../../controllers/api/claimGet'); +const claimLongId = require('../../controllers/api/claimLongId'); +const claimPublish = require('../../controllers/api/claimPublish'); +const claimResolve = require('../../controllers/api/claimResolve'); +const claimShortId = require('../../controllers/api/claimShortId'); +const claimList = require('../../controllers/api/claimList'); +const fileAvailability = require('../../controllers/api/fileAvailability'); const multipartMiddleware = require('../utils/multipartMiddleware'); diff --git a/server/routes/assets/index.js b/server/routes/assets/index.js index 4f358a74..d1d82a2a 100644 --- a/server/routes/assets/index.js +++ b/server/routes/assets/index.js @@ -1,5 +1,5 @@ -const serveAssetByClaim = require('./serveAssetByClaim'); -const serveAssetByIdentifierAndClaim = require('./serveAssetByIdentifierAndClaim'); +const serveAssetByClaim = require('../../controllers/assets/serveAssetByClaim'); +const serveAssetByIdentifierAndClaim = require('../../controllers/assets/serveAssetByIdentifierAndClaim'); module.exports = (app, db) => { app.get('/:identifier/:claim', serveAssetByIdentifierAndClaim); diff --git a/server/routes/auth/index.js b/server/routes/auth/index.js index a0a4e64b..9754f5b2 100644 --- a/server/routes/auth/index.js +++ b/server/routes/auth/index.js @@ -1,8 +1,8 @@ const speechPassport = require('../../speechPassport'); -const handleSignupRequest = require('./signup'); -const handleLoginRequest = require('./login'); -const handleLogoutRequest = require('./logout'); -const handleUserRequest = require('./user'); +const handleSignupRequest = require('../../controllers/auth/signup'); +const handleLoginRequest = require('../../controllers/auth/login'); +const handleLogoutRequest = require('../../controllers/auth/logout'); +const handleUserRequest = require('../../controllers/auth/user'); module.exports = (app) => { app.post('/signup', speechPassport.authenticate('local-signup'), handleSignupRequest); diff --git a/server/routes/fallback/index.js b/server/routes/fallback/index.js index 35073607..0fc57d0c 100644 --- a/server/routes/fallback/index.js +++ b/server/routes/fallback/index.js @@ -1,4 +1,4 @@ -const handlePageRequest = require('./sendReactApp'); +const handlePageRequest = require('../../controllers/fallback/sendReactApp'); module.exports = (app) => { app.get('*', handlePageRequest); diff --git a/server/routes/pages/index.js b/server/routes/pages/index.js index 5d4c27ae..a7c3a936 100644 --- a/server/routes/pages/index.js +++ b/server/routes/pages/index.js @@ -1,6 +1,6 @@ -const handlePageRequest = require('./sendReactApp'); -const handleEmbedRequest = require('./sendEmbedPage'); -const redirect = require('./redirect'); +const handlePageRequest = require('../../controllers/pages/sendReactApp'); +const handleEmbedRequest = require('../../controllers/pages/sendEmbedPage'); +const redirect = require('../../controllers/pages/redirect'); module.exports = (app) => { app.get('/', handlePageRequest); diff --git a/server/speechPassport/utils/local-signup.js b/server/speechPassport/utils/local-signup.js index 0f4326e6..1a2067e8 100644 --- a/server/speechPassport/utils/local-signup.js +++ b/server/speechPassport/utils/local-signup.js @@ -1,7 +1,7 @@ const PassportLocalStrategy = require('passport-local').Strategy; -const lbryApi = require('../../utils/lbryApi.js'); +const { createChannel } = require('../../lbrynet'); const logger = require('winston'); -const db = require('../../models/index'); +const db = require('../../models'); module.exports = new PassportLocalStrategy( { @@ -14,7 +14,7 @@ module.exports = new PassportLocalStrategy( // server-side validaton of inputs (username, password) // create the channel and retrieve the metadata - return lbryApi.createChannel(`@${username}`) + return createChannel(`@${username}`) .then(tx => { // create user record const userData = { diff --git a/test/unit/publishHelpers.test.js b/test/unit/publishHelpers.test.js index c522b487..471d1f56 100644 --- a/test/unit/publishHelpers.test.js +++ b/test/unit/publishHelpers.test.js @@ -2,7 +2,7 @@ const chai = require('chai'); const expect = chai.expect; describe('publishHelpers.js', function () { - const publishHelpers = require('../../server/helpers/publishHelpers.js'); + const publishHelpers = require('../../server/controllers/utils/publishHelpers.js'); describe('#parsePublishApiRequestBody()', function () { it('should throw an error if no body', function () { From aa1834e1c6138549ce906d3e7dcc2e14d2c1b567 Mon Sep 17 00:00:00 2001 From: bill bittner Date: Fri, 27 Apr 2018 09:54:36 -0700 Subject: [PATCH 04/13] organized api controllers and helpers --- .../availability}/checkChannelAvailability.js | 2 +- .../availability/index.js} | 6 +- .../channel/claims}/channelPagination.js | 0 .../api/channel/claims/getChannelClaims.js | 31 ++++ .../claims/index.js} | 4 +- .../api/channel/data/getChannelData.js | 32 ++++ .../{channelData.js => channel/data/index.js} | 4 +- .../shortId/index.js} | 4 +- .../availability/index.js} | 4 +- .../api/{claimData.js => claim/data/index.js} | 4 +- .../api/{claimGet.js => claim/get/index.js} | 8 +- .../api/{claimList.js => claim/list/index.js} | 4 +- .../{claimLongId.js => claim/longId/index.js} | 4 +- .../claim/publish/createBasicPublishParams.js | 40 +++++ .../publish/createThumbnailPublishParams.js | 28 +++ .../claim/publish}/deleteFile.js | 0 .../publish/index.js} | 22 ++- .../publish/parsePublishApiRequestBody.js | 27 +++ .../publish/parsePublishApiRequestFiles.js | 34 ++++ .../{utils => api/claim/publish}/publish.js | 4 +- .../claim/publish/validateFileTypeAndSize.js | 33 ++++ .../resolve/index.js} | 4 +- .../shortId/index.js} | 4 +- .../claim}/utils/checkClaimAvailability.js | 4 +- .../availability/index.js} | 4 +- .../index.js} | 8 +- .../index.js} | 8 +- server/controllers/utils/publishHelpers.js | 165 ------------------ server/controllers/utils/serveHelpers.js | 55 +----- server/routes/api/index.js | 26 +-- server/routes/assets/index.js | 4 +- server/speechPassport/utils/local-login.js | 2 +- .../utils.test.js} | 27 ++- 33 files changed, 310 insertions(+), 296 deletions(-) rename server/controllers/{utils => api/channel/availability}/checkChannelAvailability.js (89%) rename server/controllers/api/{channelAvailability.js => channel/availability/index.js} (69%) rename server/controllers/{utils => api/channel/claims}/channelPagination.js (100%) create mode 100644 server/controllers/api/channel/claims/getChannelClaims.js rename server/controllers/api/{channelClaims.js => channel/claims/index.js} (84%) create mode 100644 server/controllers/api/channel/data/getChannelData.js rename server/controllers/api/{channelData.js => channel/data/index.js} (82%) rename server/controllers/api/{channelShortId.js => channel/shortId/index.js} (77%) rename server/controllers/api/{claimAvailability.js => claim/availability/index.js} (78%) rename server/controllers/api/{claimData.js => claim/data/index.js} (83%) rename server/controllers/api/{claimGet.js => claim/get/index.js} (84%) rename server/controllers/api/{claimList.js => claim/list/index.js} (70%) rename server/controllers/api/{claimLongId.js => claim/longId/index.js} (86%) create mode 100644 server/controllers/api/claim/publish/createBasicPublishParams.js create mode 100644 server/controllers/api/claim/publish/createThumbnailPublishParams.js rename server/controllers/{utils => api/claim/publish}/deleteFile.js (100%) rename server/controllers/api/{claimPublish.js => claim/publish/index.js} (78%) create mode 100644 server/controllers/api/claim/publish/parsePublishApiRequestBody.js create mode 100644 server/controllers/api/claim/publish/parsePublishApiRequestFiles.js rename server/controllers/{utils => api/claim/publish}/publish.js (97%) create mode 100644 server/controllers/api/claim/publish/validateFileTypeAndSize.js rename server/controllers/api/{claimResolve.js => claim/resolve/index.js} (73%) rename server/controllers/api/{claimShortId.js => claim/shortId/index.js} (77%) rename server/controllers/{ => api/claim}/utils/checkClaimAvailability.js (87%) rename server/controllers/api/{fileAvailability.js => file/availability/index.js} (82%) rename server/controllers/assets/{serveAssetByClaim.js => serveByClaim/index.js} (83%) rename server/controllers/assets/{serveAssetByIdentifierAndClaim.js => serveByIdentifierAndClaim/index.js} (87%) delete mode 100644 server/controllers/utils/publishHelpers.js rename test/unit/{publishHelpers.test.js => publish/utils.test.js} (62%) diff --git a/server/controllers/utils/checkChannelAvailability.js b/server/controllers/api/channel/availability/checkChannelAvailability.js similarity index 89% rename from server/controllers/utils/checkChannelAvailability.js rename to server/controllers/api/channel/availability/checkChannelAvailability.js index 8dfce07a..3c5d78b5 100644 --- a/server/controllers/utils/checkChannelAvailability.js +++ b/server/controllers/api/channel/availability/checkChannelAvailability.js @@ -1,4 +1,4 @@ -const db = require('../../models'); +const db = require('../../../../models'); const checkChannelAvailability = (name) => { return db.Channel diff --git a/server/controllers/api/channelAvailability.js b/server/controllers/api/channel/availability/index.js similarity index 69% rename from server/controllers/api/channelAvailability.js rename to server/controllers/api/channel/availability/index.js index 33f5f5f3..ae2a3807 100644 --- a/server/controllers/api/channelAvailability.js +++ b/server/controllers/api/channel/availability/index.js @@ -1,6 +1,6 @@ -const checkChannelAvailability = require('../utils/checkChannelAvailability.js'); -const { sendGATimingEvent } = require('../../utils/googleAnalytics.js'); -const { handleErrorResponse } = require('../utils/errorHandlers.js'); +const checkChannelAvailability = require('./checkChannelAvailability.js'); +const { sendGATimingEvent } = require('../../../../utils/googleAnalytics.js'); +const { handleErrorResponse } = require('../../../utils/errorHandlers.js'); /* diff --git a/server/controllers/utils/channelPagination.js b/server/controllers/api/channel/claims/channelPagination.js similarity index 100% rename from server/controllers/utils/channelPagination.js rename to server/controllers/api/channel/claims/channelPagination.js diff --git a/server/controllers/api/channel/claims/getChannelClaims.js b/server/controllers/api/channel/claims/getChannelClaims.js new file mode 100644 index 00000000..aec6f03e --- /dev/null +++ b/server/controllers/api/channel/claims/getChannelClaims.js @@ -0,0 +1,31 @@ +const db = require('../../../../models'); +const { returnPaginatedChannelClaims } = require('./channelPagination.js'); +const NO_CHANNEL = 'NO_CHANNEL'; + +const getChannelClaims = (channelName, channelClaimId, page) => { + return new Promise((resolve, reject) => { + // 1. get the long channel Id (make sure channel exists) + db.Certificate.getLongChannelId(channelName, channelClaimId) + .then(longChannelClaimId => { + if (!longChannelClaimId) { + return [null, null, null]; + } + // 2. get the short ID and all claims for that channel + return Promise.all([longChannelClaimId, db.Claim.getAllChannelClaims(longChannelClaimId)]); + }) + .then(([longChannelClaimId, channelClaimsArray]) => { + if (!longChannelClaimId) { + return resolve(NO_CHANNEL); + } + // 3. format the data for the view, including pagination + let paginatedChannelViewData = returnPaginatedChannelClaims(channelName, longChannelClaimId, channelClaimsArray, page); + // 4. return all the channel information and contents + resolve(paginatedChannelViewData); + }) + .catch(error => { + reject(error); + }); + }); +}; + +module.exports = getChannelClaims; diff --git a/server/controllers/api/channelClaims.js b/server/controllers/api/channel/claims/index.js similarity index 84% rename from server/controllers/api/channelClaims.js rename to server/controllers/api/channel/claims/index.js index d9a3683e..4c7b6777 100644 --- a/server/controllers/api/channelClaims.js +++ b/server/controllers/api/channel/claims/index.js @@ -1,5 +1,5 @@ -const { getChannelClaims } = require('../utils/serveHelpers.js'); -const { handleErrorResponse } = require('../utils/errorHandlers.js'); +const { handleErrorResponse } = require('../../../utils/errorHandlers.js'); +const getChannelClaims = require('./getChannelClaims.js'); const NO_CHANNEL = 'NO_CHANNEL'; diff --git a/server/controllers/api/channel/data/getChannelData.js b/server/controllers/api/channel/data/getChannelData.js new file mode 100644 index 00000000..98c3a8d5 --- /dev/null +++ b/server/controllers/api/channel/data/getChannelData.js @@ -0,0 +1,32 @@ +const db = require('../../../../models'); +const NO_CHANNEL = 'NO_CHANNEL'; + +const getChannelData = (channelName, channelClaimId, page) => { + return new Promise((resolve, reject) => { + // 1. get the long channel Id (make sure channel exists) + db.Certificate.getLongChannelId(channelName, channelClaimId) + .then(longChannelClaimId => { + if (!longChannelClaimId) { + return [null, null, null]; + } + // 2. get the short ID and all claims for that channel + return Promise.all([longChannelClaimId, db.Certificate.getShortChannelIdFromLongChannelId(longChannelClaimId, channelName)]); + }) + .then(([longChannelClaimId, shortChannelClaimId]) => { + if (!longChannelClaimId) { + return resolve(NO_CHANNEL); + } + // 3. return all the channel information + resolve({ + channelName, + longChannelClaimId, + shortChannelClaimId, + }); + }) + .catch(error => { + reject(error); + }); + }); +}; + +module.exports = getChannelData; diff --git a/server/controllers/api/channelData.js b/server/controllers/api/channel/data/index.js similarity index 82% rename from server/controllers/api/channelData.js rename to server/controllers/api/channel/data/index.js index 92609412..ad678d78 100644 --- a/server/controllers/api/channelData.js +++ b/server/controllers/api/channel/data/index.js @@ -1,5 +1,5 @@ -const { getChannelData } = require('../utils/serveHelpers.js'); -const { handleErrorResponse } = require('../utils/errorHandlers.js'); +const { getChannelData } = require('../../../utils/serveHelpers.js'); +const { handleErrorResponse } = require('../../../utils/errorHandlers.js'); const NO_CHANNEL = 'NO_CHANNEL'; diff --git a/server/controllers/api/channelShortId.js b/server/controllers/api/channel/shortId/index.js similarity index 77% rename from server/controllers/api/channelShortId.js rename to server/controllers/api/channel/shortId/index.js index 898456a1..937d92b8 100644 --- a/server/controllers/api/channelShortId.js +++ b/server/controllers/api/channel/shortId/index.js @@ -1,5 +1,5 @@ -const { handleErrorResponse } = require('../utils/errorHandlers.js'); -const db = require('../../models/index'); +const { handleErrorResponse } = require('../../../utils/errorHandlers.js'); +const db = require('../../../../models'); /* diff --git a/server/controllers/api/claimAvailability.js b/server/controllers/api/claim/availability/index.js similarity index 78% rename from server/controllers/api/claimAvailability.js rename to server/controllers/api/claim/availability/index.js index 23a3a21f..9f9d330d 100644 --- a/server/controllers/api/claimAvailability.js +++ b/server/controllers/api/claim/availability/index.js @@ -1,6 +1,6 @@ const checkClaimAvailability = require('../utils/checkClaimAvailability.js'); -const { sendGATimingEvent } = require('../../utils/googleAnalytics.js'); -const { handleErrorResponse } = require('../utils/errorHandlers.js'); +const { sendGATimingEvent } = require('../../../../utils/googleAnalytics.js'); +const { handleErrorResponse } = require('../../../utils/errorHandlers.js'); /* diff --git a/server/controllers/api/claimData.js b/server/controllers/api/claim/data/index.js similarity index 83% rename from server/controllers/api/claimData.js rename to server/controllers/api/claim/data/index.js index 4549671d..49361d71 100644 --- a/server/controllers/api/claimData.js +++ b/server/controllers/api/claim/data/index.js @@ -1,5 +1,5 @@ -const { handleErrorResponse } = require('../utils/errorHandlers.js'); -const db = require('../../models/index'); +const { handleErrorResponse } = require('../../../utils/errorHandlers.js'); +const db = require('../../../../models'); /* diff --git a/server/controllers/api/claimGet.js b/server/controllers/api/claim/get/index.js similarity index 84% rename from server/controllers/api/claimGet.js rename to server/controllers/api/claim/get/index.js index a5a04926..d54fcc87 100644 --- a/server/controllers/api/claimGet.js +++ b/server/controllers/api/claim/get/index.js @@ -1,7 +1,7 @@ -const { getClaim } = require('../../lbrynet'); -const { addGetResultsToFileData, createFileData } = require('../utils/file.js'); -const { handleErrorResponse } = require('../utils/errorHandlers.js'); -const db = require('../../models'); +const { getClaim } = require('../../../../lbrynet'); +const { addGetResultsToFileData, createFileData } = require('../../../utils/file.js'); +const { handleErrorResponse } = require('../../../utils/errorHandlers.js'); +const db = require('../../../../models'); /* diff --git a/server/controllers/api/claimList.js b/server/controllers/api/claim/list/index.js similarity index 70% rename from server/controllers/api/claimList.js rename to server/controllers/api/claim/list/index.js index 300b1864..bb7eb1d0 100644 --- a/server/controllers/api/claimList.js +++ b/server/controllers/api/claim/list/index.js @@ -1,5 +1,5 @@ -const { getClaimList } = require('../../lbrynet/index'); -const { handleErrorResponse } = require('../utils/errorHandlers.js'); +const { getClaimList } = require('../../../../lbrynet'); +const { handleErrorResponse } = require('../../../utils/errorHandlers.js'); /* diff --git a/server/controllers/api/claimLongId.js b/server/controllers/api/claim/longId/index.js similarity index 86% rename from server/controllers/api/claimLongId.js rename to server/controllers/api/claim/longId/index.js index aaa9b171..b84ded1e 100644 --- a/server/controllers/api/claimLongId.js +++ b/server/controllers/api/claim/longId/index.js @@ -1,5 +1,5 @@ -const { getClaimId } = require('../utils/serveHelpers.js'); -const { handleErrorResponse } = require('../utils/errorHandlers.js'); +const { getClaimId } = require('../../../utils/serveHelpers.js'); +const { handleErrorResponse } = require('../../../utils/errorHandlers.js'); const NO_CHANNEL = 'NO_CHANNEL'; const NO_CLAIM = 'NO_CLAIM'; diff --git a/server/controllers/api/claim/publish/createBasicPublishParams.js b/server/controllers/api/claim/publish/createBasicPublishParams.js new file mode 100644 index 00000000..a8d84404 --- /dev/null +++ b/server/controllers/api/claim/publish/createBasicPublishParams.js @@ -0,0 +1,40 @@ +const logger = require('winston'); +const { details, publishing } = require('../../../../../config/siteConfig.js'); + +const createBasicPublishParams = (filePath, name, title, description, license, nsfw, thumbnail) => { + logger.debug(`Creating Publish Parameters`); + // provide defaults for title + if (title === null || title.trim() === '') { + title = name; + } + // provide default for description + if (description === null || description.trim() === '') { + description = ''; + } + // provide default for license + if (license === null || license.trim() === '') { + license = ' '; // default to empty string + } + // create the publish params + const publishParams = { + name, + file_path: filePath, + bid : 0.01, + metadata : { + description, + title, + author : details.title, + language: 'en', + license, + nsfw, + }, + claim_address: publishing.primaryClaimAddress, + }; + // add thumbnail to channel if video + if (thumbnail) { + publishParams['metadata']['thumbnail'] = thumbnail; + } + return publishParams; +}; + +module.exports = createBasicPublishParams; diff --git a/server/controllers/api/claim/publish/createThumbnailPublishParams.js b/server/controllers/api/claim/publish/createThumbnailPublishParams.js new file mode 100644 index 00000000..c10d9cd9 --- /dev/null +++ b/server/controllers/api/claim/publish/createThumbnailPublishParams.js @@ -0,0 +1,28 @@ +const logger = require('winston'); +const { details, publishing } = require('../../../../../config/siteConfig.js'); + +const createThumbnailPublishParams = (thumbnailFilePath, claimName, license, nsfw) => { + if (!thumbnailFilePath) { + return; + } + logger.debug(`Creating Thumbnail Publish Parameters`); + // create the publish params + return { + name : `${claimName}-thumb`, + file_path: thumbnailFilePath, + bid : 0.01, + metadata : { + title : `${claimName} thumbnail`, + description: `a thumbnail for ${claimName}`, + author : details.title, + language : 'en', + license, + nsfw, + }, + claim_address: publishing.primaryClaimAddress, + channel_name : publishing.thumbnailChannel, + channel_id : publishing.thumbnailChannelId, + }; +}; + +module.exports = createThumbnailPublishParams; diff --git a/server/controllers/utils/deleteFile.js b/server/controllers/api/claim/publish/deleteFile.js similarity index 100% rename from server/controllers/utils/deleteFile.js rename to server/controllers/api/claim/publish/deleteFile.js diff --git a/server/controllers/api/claimPublish.js b/server/controllers/api/claim/publish/index.js similarity index 78% rename from server/controllers/api/claimPublish.js rename to server/controllers/api/claim/publish/index.js index f776a46e..2d4ee10d 100644 --- a/server/controllers/api/claimPublish.js +++ b/server/controllers/api/claim/publish/index.js @@ -1,15 +1,13 @@ -const { details: { host } } = require('../../../config/siteConfig.js'); -const { authenticateUser } = require('../../auth/authentication.js'); -const { sendGATimingEvent } = require('../../utils/googleAnalytics.js'); -const { handleErrorResponse } = require('../utils/errorHandlers.js'); -const checkClaimAvailability = require('../utils/checkClaimAvailability'); -const publish = require('../utils/publish.js'); -const { - createBasicPublishParams, - createThumbnailPublishParams, - parsePublishApiRequestBody, - parsePublishApiRequestFiles, -} = require('../utils/publishHelpers.js'); +const { details: { host } } = require('../../../../../config/siteConfig.js'); +const { authenticateUser } = require('../../../../auth/authentication.js'); +const { sendGATimingEvent } = require('../../../../utils/googleAnalytics.js'); +const { handleErrorResponse } = require('../../../utils/errorHandlers.js'); +const publish = require('./publish.js'); +const createBasicPublishParams = require('./createBasicPublishParams.js'); +const createThumbnailPublishParams = require('./createThumbnailPublishParams.js'); +const parsePublishApiRequestBody = require('./parsePublishApiRequestBody.js'); +const parsePublishApiRequestFiles = require('./parsePublishApiRequestFiles.js'); +const checkClaimAvailability = require('../utils/checkClaimAvailability.js'); /* diff --git a/server/controllers/api/claim/publish/parsePublishApiRequestBody.js b/server/controllers/api/claim/publish/parsePublishApiRequestBody.js new file mode 100644 index 00000000..e417e0a9 --- /dev/null +++ b/server/controllers/api/claim/publish/parsePublishApiRequestBody.js @@ -0,0 +1,27 @@ +const parsePublishApiRequestBody = ({name, nsfw, license, title, description, thumbnail}) => { + // validate name + if (!name) { + throw new Error('no name field found in request'); + } + const invalidNameCharacters = /[^A-Za-z0-9,-]/.exec(name); + if (invalidNameCharacters) { + throw new Error('The claim name you provided is not allowed. Only the following characters are allowed: A-Z, a-z, 0-9, and "-"'); + } + // optional parameters + nsfw = (nsfw === 'true'); + license = license || null; + title = title || null; + description = description || null; + thumbnail = thumbnail || null; + // return results + return { + name, + nsfw, + license, + title, + description, + thumbnail, + }; +}; + +module.exports = parsePublishApiRequestBody; diff --git a/server/controllers/api/claim/publish/parsePublishApiRequestFiles.js b/server/controllers/api/claim/publish/parsePublishApiRequestFiles.js new file mode 100644 index 00000000..d7b509e9 --- /dev/null +++ b/server/controllers/api/claim/publish/parsePublishApiRequestFiles.js @@ -0,0 +1,34 @@ +const validateFileTypeAndSize = require('./validateFileTypeAndSize.js'); + +const parsePublishApiRequestFiles = ({file, thumbnail}) => { + // make sure a file was provided + if (!file) { + throw new Error('no file with key of [file] found in request'); + } + if (!file.path) { + throw new Error('no file path found'); + } + if (!file.type) { + throw new Error('no file type found'); + } + if (!file.size) { + throw new Error('no file type found'); + } + // validate the file name + if (/'/.test(file.name)) { + throw new Error('apostrophes are not allowed in the file name'); + } + // validate the file + validateFileTypeAndSize(file); + // return results + return { + fileName : file.name, + filePath : file.path, + fileType : file.type, + thumbnailFileName: (thumbnail ? thumbnail.name : null), + thumbnailFilePath: (thumbnail ? thumbnail.path : null), + thumbnailFileType: (thumbnail ? thumbnail.type : null), + }; +}; + +module.exports = parsePublishApiRequestFiles; diff --git a/server/controllers/utils/publish.js b/server/controllers/api/claim/publish/publish.js similarity index 97% rename from server/controllers/utils/publish.js rename to server/controllers/api/claim/publish/publish.js index 5d2daea2..b80dc0b7 100644 --- a/server/controllers/utils/publish.js +++ b/server/controllers/api/claim/publish/publish.js @@ -1,6 +1,6 @@ const logger = require('winston'); -const db = require('../../models'); -const { publishClaim } = require('../../lbrynet'); +const db = require('../../../../models'); +const { publishClaim } = require('../../../../lbrynet'); const deleteFile = require('./deleteFile.js'); const publish = (publishParams, fileName, fileType) => { diff --git a/server/controllers/api/claim/publish/validateFileTypeAndSize.js b/server/controllers/api/claim/publish/validateFileTypeAndSize.js new file mode 100644 index 00000000..ca3d4f17 --- /dev/null +++ b/server/controllers/api/claim/publish/validateFileTypeAndSize.js @@ -0,0 +1,33 @@ +const logger = require('winston'); + +const validateFileTypeAndSize = (file) => { + // check file type and size + switch (file.type) { + case 'image/jpeg': + case 'image/jpg': + case 'image/png': + if (file.size > 10000000) { + logger.debug('publish > file validation > .jpeg/.jpg/.png was too big'); + throw new Error('Sorry, images are limited to 10 megabytes.'); + } + break; + case 'image/gif': + if (file.size > 50000000) { + logger.debug('publish > file validation > .gif was too big'); + throw new Error('Sorry, .gifs are limited to 50 megabytes.'); + } + break; + case 'video/mp4': + if (file.size > 50000000) { + logger.debug('publish > file validation > .mp4 was too big'); + throw new Error('Sorry, videos are limited to 50 megabytes.'); + } + break; + default: + logger.debug('publish > file validation > unrecognized file type'); + throw new Error('The ' + file.type + ' content type is not supported. Only, .jpeg, .png, .gif, and .mp4 files are currently supported.'); + } + return file; +}; + +module.exports = validateFileTypeAndSize; diff --git a/server/controllers/api/claimResolve.js b/server/controllers/api/claim/resolve/index.js similarity index 73% rename from server/controllers/api/claimResolve.js rename to server/controllers/api/claim/resolve/index.js index 2d347ddd..9b057bda 100644 --- a/server/controllers/api/claimResolve.js +++ b/server/controllers/api/claim/resolve/index.js @@ -1,5 +1,5 @@ -const { resolveUri } = require('../../lbrynet/index'); -const { handleErrorResponse } = require('../utils/errorHandlers.js'); +const { resolveUri } = require('../../../../lbrynet/index'); +const { handleErrorResponse } = require('../../../utils/errorHandlers.js'); /* diff --git a/server/controllers/api/claimShortId.js b/server/controllers/api/claim/shortId/index.js similarity index 77% rename from server/controllers/api/claimShortId.js rename to server/controllers/api/claim/shortId/index.js index 4357c46c..c10e41ee 100644 --- a/server/controllers/api/claimShortId.js +++ b/server/controllers/api/claim/shortId/index.js @@ -1,5 +1,5 @@ -const { handleErrorResponse } = require('../utils/errorHandlers.js'); -const db = require('../../models/index'); +const { handleErrorResponse } = require('../../../utils/errorHandlers.js'); +const db = require('../../../../models'); /* diff --git a/server/controllers/utils/checkClaimAvailability.js b/server/controllers/api/claim/utils/checkClaimAvailability.js similarity index 87% rename from server/controllers/utils/checkClaimAvailability.js rename to server/controllers/api/claim/utils/checkClaimAvailability.js index 9cd3d09b..f10f2590 100644 --- a/server/controllers/utils/checkClaimAvailability.js +++ b/server/controllers/api/claim/utils/checkClaimAvailability.js @@ -1,5 +1,5 @@ -const db = require('../../models/index'); -const { publishing: { primaryClaimAddress, additionalClaimAddresses } } = require('../../../config/siteConfig.js'); +const db = require('../../../../models'); +const { publishing: { primaryClaimAddress, additionalClaimAddresses } } = require('../../../../../config/siteConfig.js'); const Sequelize = require('sequelize'); const Op = Sequelize.Op; diff --git a/server/controllers/api/fileAvailability.js b/server/controllers/api/file/availability/index.js similarity index 82% rename from server/controllers/api/fileAvailability.js rename to server/controllers/api/file/availability/index.js index 116fcaaf..d55ed230 100644 --- a/server/controllers/api/fileAvailability.js +++ b/server/controllers/api/file/availability/index.js @@ -1,5 +1,5 @@ -const { handleErrorResponse } = require('../utils/errorHandlers.js'); -const db = require('../../models/index'); +const { handleErrorResponse } = require('../../../utils/errorHandlers.js'); +const db = require('../../../../models'); /* diff --git a/server/controllers/assets/serveAssetByClaim.js b/server/controllers/assets/serveByClaim/index.js similarity index 83% rename from server/controllers/assets/serveAssetByClaim.js rename to server/controllers/assets/serveByClaim/index.js index 63592043..51d9a500 100644 --- a/server/controllers/assets/serveAssetByClaim.js +++ b/server/controllers/assets/serveByClaim/index.js @@ -1,11 +1,11 @@ -const { sendGAServeEvent } = require('../../utils/googleAnalytics'); +const { sendGAServeEvent } = require('../../../utils/googleAnalytics'); const { determineResponseType, logRequestData, getClaimIdAndServeAsset, -} = require('../utils/serve.js'); -const lbryUri = require('../utils/lbryUri.js'); -const handleShowRender = require('../../render/build/handleShowRender.js'); +} = require('../../utils/serve.js'); +const lbryUri = require('../../utils/lbryUri.js'); +const handleShowRender = require('../../../render/build/handleShowRender.js'); const SERVE = 'SERVE'; /* diff --git a/server/controllers/assets/serveAssetByIdentifierAndClaim.js b/server/controllers/assets/serveByIdentifierAndClaim/index.js similarity index 87% rename from server/controllers/assets/serveAssetByIdentifierAndClaim.js rename to server/controllers/assets/serveByIdentifierAndClaim/index.js index f7bd8d18..954421d9 100644 --- a/server/controllers/assets/serveAssetByIdentifierAndClaim.js +++ b/server/controllers/assets/serveByIdentifierAndClaim/index.js @@ -1,12 +1,12 @@ -const { sendGAServeEvent } = require('../../utils/googleAnalytics'); +const { sendGAServeEvent } = require('../../../utils/googleAnalytics'); const { determineResponseType, flipClaimNameAndIdForBackwardsCompatibility, logRequestData, getClaimIdAndServeAsset, -} = require('../utils/serve.js'); -const lbryUri = require('../utils/lbryUri.js'); -const handleShowRender = require('../../render/build/handleShowRender.js'); +} = require('../../utils/serve.js'); +const lbryUri = require('../../utils/lbryUri.js'); +const handleShowRender = require('../../../render/build/handleShowRender.js'); const SERVE = 'SERVE'; diff --git a/server/controllers/utils/publishHelpers.js b/server/controllers/utils/publishHelpers.js deleted file mode 100644 index 8338f08e..00000000 --- a/server/controllers/utils/publishHelpers.js +++ /dev/null @@ -1,165 +0,0 @@ -const logger = require('winston'); -const { details, publishing } = require('../../../config/siteConfig.js'); - -module.exports = { - parsePublishApiRequestBody ({name, nsfw, license, title, description, thumbnail}) { - // validate name - if (!name) { - throw new Error('no name field found in request'); - } - const invalidNameCharacters = /[^A-Za-z0-9,-]/.exec(name); - if (invalidNameCharacters) { - throw new Error('The claim name you provided is not allowed. Only the following characters are allowed: A-Z, a-z, 0-9, and "-"'); - } - // optional parameters - nsfw = (nsfw === 'true'); - license = license || null; - title = title || null; - description = description || null; - thumbnail = thumbnail || null; - // return results - return { - name, - nsfw, - license, - title, - description, - thumbnail, - }; - }, - parsePublishApiRequestFiles ({file, thumbnail}) { - // make sure a file was provided - if (!file) { - throw new Error('no file with key of [file] found in request'); - } - if (!file.path) { - throw new Error('no file path found'); - } - if (!file.type) { - throw new Error('no file type found'); - } - if (!file.size) { - throw new Error('no file type found'); - } - // validate the file name - if (/'/.test(file.name)) { - throw new Error('apostrophes are not allowed in the file name'); - } - // validate the file - module.exports.validateFileTypeAndSize(file); - // return results - return { - fileName : file.name, - filePath : file.path, - fileType : file.type, - thumbnailFileName: (thumbnail ? thumbnail.name : null), - thumbnailFilePath: (thumbnail ? thumbnail.path : null), - thumbnailFileType: (thumbnail ? thumbnail.type : null), - }; - }, - validateFileTypeAndSize (file) { - // check file type and size - switch (file.type) { - case 'image/jpeg': - case 'image/jpg': - case 'image/png': - if (file.size > 10000000) { - logger.debug('publish > file validation > .jpeg/.jpg/.png was too big'); - throw new Error('Sorry, images are limited to 10 megabytes.'); - } - break; - case 'image/gif': - if (file.size > 50000000) { - logger.debug('publish > file validation > .gif was too big'); - throw new Error('Sorry, .gifs are limited to 50 megabytes.'); - } - break; - case 'video/mp4': - if (file.size > 50000000) { - logger.debug('publish > file validation > .mp4 was too big'); - throw new Error('Sorry, videos are limited to 50 megabytes.'); - } - break; - default: - logger.debug('publish > file validation > unrecognized file type'); - throw new Error('The ' + file.type + ' content type is not supported. Only, .jpeg, .png, .gif, and .mp4 files are currently supported.'); - } - return file; - }, - createBasicPublishParams (filePath, name, title, description, license, nsfw, thumbnail) { - logger.debug(`Creating Publish Parameters`); - // provide defaults for title - if (title === null || title.trim() === '') { - title = name; - } - // provide default for description - if (description === null || description.trim() === '') { - description = ''; - } - // provide default for license - if (license === null || license.trim() === '') { - license = ' '; // default to empty string - } - // create the publish params - const publishParams = { - name, - file_path: filePath, - bid : 0.01, - metadata : { - description, - title, - author : details.title, - language: 'en', - license, - nsfw, - }, - claim_address: publishing.primaryClaimAddress, - }; - // add thumbnail to channel if video - if (thumbnail) { - publishParams['metadata']['thumbnail'] = thumbnail; - } - return publishParams; - }, - createThumbnailPublishParams (thumbnailFilePath, claimName, license, nsfw) { - if (!thumbnailFilePath) { - return; - } - logger.debug(`Creating Thumbnail Publish Parameters`); - // create the publish params - return { - name : `${claimName}-thumb`, - file_path: thumbnailFilePath, - bid : 0.01, - metadata : { - title : `${claimName} thumbnail`, - description: `a thumbnail for ${claimName}`, - author : details.title, - language : 'en', - license, - nsfw, - }, - claim_address: publishing.primaryClaimAddress, - channel_name : publishing.thumbnailChannel, - channel_id : publishing.thumbnailChannelId, - }; - }, - addGetResultsToFileData (fileInfo, getResult) { - fileInfo.fileName = getResult.file_name; - fileInfo.filePath = getResult.download_path; - return fileInfo; - }, - createFileData ({ name, claimId, outpoint, height, address, nsfw, contentType }) { - return { - name, - claimId, - outpoint, - height, - address, - fileName: '', - filePath: '', - fileType: contentType, - nsfw, - }; - }, -}; diff --git a/server/controllers/utils/serveHelpers.js b/server/controllers/utils/serveHelpers.js index cbed71de..68b46335 100644 --- a/server/controllers/utils/serveHelpers.js +++ b/server/controllers/utils/serveHelpers.js @@ -1,6 +1,5 @@ -const db = require('../../models/index'); +const db = require('../../models'); const logger = require('winston'); -const { returnPaginatedChannelClaims } = require('./channelPagination.js'); const NO_CHANNEL = 'NO_CHANNEL'; const NO_CLAIM = 'NO_CLAIM'; @@ -53,58 +52,6 @@ module.exports = { }); }); }, - getChannelData (channelName, channelClaimId, page) { - return new Promise((resolve, reject) => { - // 1. get the long channel Id (make sure channel exists) - db.Certificate.getLongChannelId(channelName, channelClaimId) - .then(longChannelClaimId => { - if (!longChannelClaimId) { - return [null, null, null]; - } - // 2. get the short ID and all claims for that channel - return Promise.all([longChannelClaimId, db.Certificate.getShortChannelIdFromLongChannelId(longChannelClaimId, channelName)]); - }) - .then(([longChannelClaimId, shortChannelClaimId]) => { - if (!longChannelClaimId) { - return resolve(NO_CHANNEL); - } - // 3. return all the channel information - resolve({ - channelName, - longChannelClaimId, - shortChannelClaimId, - }); - }) - .catch(error => { - reject(error); - }); - }); - }, - getChannelClaims (channelName, channelClaimId, page) { - return new Promise((resolve, reject) => { - // 1. get the long channel Id (make sure channel exists) - db.Certificate.getLongChannelId(channelName, channelClaimId) - .then(longChannelClaimId => { - if (!longChannelClaimId) { - return [null, null, null]; - } - // 2. get the short ID and all claims for that channel - return Promise.all([longChannelClaimId, db.Claim.getAllChannelClaims(longChannelClaimId)]); - }) - .then(([longChannelClaimId, channelClaimsArray]) => { - if (!longChannelClaimId) { - return resolve(NO_CHANNEL); - } - // 3. format the data for the view, including pagination - let paginatedChannelViewData = returnPaginatedChannelClaims(channelName, longChannelClaimId, channelClaimsArray, page); - // 4. return all the channel information and contents - resolve(paginatedChannelViewData); - }) - .catch(error => { - reject(error); - }); - }); - }, getLocalFileRecord (claimId, name) { return db.File.findOne({where: {claimId, name}}) .then(file => { diff --git a/server/routes/api/index.js b/server/routes/api/index.js index 15b272f5..a1a46974 100644 --- a/server/routes/api/index.js +++ b/server/routes/api/index.js @@ -1,16 +1,16 @@ -const channelAvailability = require('../../controllers/api/channelAvailability'); -const channelClaims = require('../../controllers/api/channelClaims'); -const channelData = require('../../controllers/api/channelData'); -const channelShortId = require('../../controllers/api/channelShortId'); -const claimAvailability = require('../../controllers/api/claimAvailability'); -const claimData = require('../../controllers/api/claimData'); -const claimGet = require('../../controllers/api/claimGet'); -const claimLongId = require('../../controllers/api/claimLongId'); -const claimPublish = require('../../controllers/api/claimPublish'); -const claimResolve = require('../../controllers/api/claimResolve'); -const claimShortId = require('../../controllers/api/claimShortId'); -const claimList = require('../../controllers/api/claimList'); -const fileAvailability = require('../../controllers/api/fileAvailability'); +const channelAvailability = require('../../controllers/api/channel/availability'); +const channelClaims = require('../../controllers/api/channel/claims'); +const channelData = require('../../controllers/api/channel/data'); +const channelShortId = require('../../controllers/api/channel/shortId'); +const claimAvailability = require('../../controllers/api/claim/availability'); +const claimData = require('../../controllers/api/claim/data/'); +const claimGet = require('../../controllers/api/claim/get'); +const claimLongId = require('../../controllers/api/claim/longId'); +const claimPublish = require('../../controllers/api/claim/publish'); +const claimResolve = require('../../controllers/api/claim/resolve'); +const claimShortId = require('../../controllers/api/claim/shortId'); +const claimList = require('../../controllers/api/claim/list'); +const fileAvailability = require('../../controllers/api/file/availability'); const multipartMiddleware = require('../utils/multipartMiddleware'); diff --git a/server/routes/assets/index.js b/server/routes/assets/index.js index d1d82a2a..4e87d2dd 100644 --- a/server/routes/assets/index.js +++ b/server/routes/assets/index.js @@ -1,5 +1,5 @@ -const serveAssetByClaim = require('../../controllers/assets/serveAssetByClaim'); -const serveAssetByIdentifierAndClaim = require('../../controllers/assets/serveAssetByIdentifierAndClaim'); +const serveAssetByClaim = require('../../controllers/assets/serveByClaim'); +const serveAssetByIdentifierAndClaim = require('../../controllers/assets/serveByIdentifierAndClaim'); module.exports = (app, db) => { app.get('/:identifier/:claim', serveAssetByIdentifierAndClaim); diff --git a/server/speechPassport/utils/local-login.js b/server/speechPassport/utils/local-login.js index a8a11b8f..d9f889c8 100644 --- a/server/speechPassport/utils/local-login.js +++ b/server/speechPassport/utils/local-login.js @@ -1,6 +1,6 @@ const PassportLocalStrategy = require('passport-local').Strategy; const logger = require('winston'); -const db = require('../../models/index'); +const db = require('../../models'); const returnUserAndChannelInfo = (userInstance) => { return new Promise((resolve, reject) => { diff --git a/test/unit/publishHelpers.test.js b/test/unit/publish/utils.test.js similarity index 62% rename from test/unit/publishHelpers.test.js rename to test/unit/publish/utils.test.js index 471d1f56..4d8aac20 100644 --- a/test/unit/publishHelpers.test.js +++ b/test/unit/publish/utils.test.js @@ -1,27 +1,34 @@ const chai = require('chai'); const expect = chai.expect; -describe('publishHelpers.js', function () { - const publishHelpers = require('../../server/controllers/utils/publishHelpers.js'); +describe('publish utils', function () { describe('#parsePublishApiRequestBody()', function () { + const parsePublishApiRequestBody = require('../../../server/controllers/api/claim/publish/parsePublishApiRequestBody.js'); + it('should throw an error if no body', function () { - expect(publishHelpers.parsePublishApiRequestBody.bind(this, null)).to.throw(); + expect(parsePublishApiRequestBody.bind(this, null)).to.throw(); }); + it('should throw an error if no body.name', function () { const bodyNoName = {}; - expect(publishHelpers.parsePublishApiRequestBody.bind(this, bodyNoName)).to.throw(); + expect(parsePublishApiRequestBody.bind(this, bodyNoName)).to.throw(); }); + }); describe('#parsePublishApiRequestFiles()', function () { + const parsePublishApiRequestFiles = require('../../../server/controllers/api/claim/publish/parsePublishApiRequestFiles.js'); + it('should throw an error if no files', function () { - expect(publishHelpers.parsePublishApiRequestFiles.bind(this, null)).to.throw(); + expect(parsePublishApiRequestFiles.bind(this, null)).to.throw(); }); + it('should throw an error if no files.file', function () { const filesNoFile = {}; - expect(publishHelpers.parsePublishApiRequestFiles.bind(this, filesNoFile)).to.throw(); + expect(parsePublishApiRequestFiles.bind(this, filesNoFile)).to.throw(); }); + it('should throw an error if file.size is too large', function () { const filesTooBig = { file: { @@ -31,8 +38,9 @@ describe('publishHelpers.js', function () { size: 10000001, }, }; - expect(publishHelpers.parsePublishApiRequestFiles.bind(this, filesTooBig)).to.throw(); + expect(parsePublishApiRequestFiles.bind(this, filesTooBig)).to.throw(); }); + it('should throw error if not an accepted file type', function () { const filesWrongType = { file: { @@ -42,8 +50,9 @@ describe('publishHelpers.js', function () { size: 10000000, }, }; - expect(publishHelpers.parsePublishApiRequestFiles.bind(this, filesWrongType)).to.throw(); + expect(parsePublishApiRequestFiles.bind(this, filesWrongType)).to.throw(); }); + it('should throw NO error if no problems', function () { const filesNoProblems = { file: { @@ -53,7 +62,7 @@ describe('publishHelpers.js', function () { size: 10000000, }, }; - expect(publishHelpers.parsePublishApiRequestFiles.bind(this, filesNoProblems)).to.not.throw(); + expect(parsePublishApiRequestFiles.bind(this, filesNoProblems)).to.not.throw(); }); }); From c30b2158b3d580a9477965b8ea9c8e77468103e9 Mon Sep 17 00:00:00 2001 From: bill bittner Date: Fri, 27 Apr 2018 10:24:40 -0700 Subject: [PATCH 05/13] organized assets controllers --- server/controllers/api/channel/data/index.js | 3 +- .../api/claim/get/addGetResultsToFileData.js | 5 + .../api/claim/get/createFileData.js | 13 +++ server/controllers/api/claim/get/index.js | 3 +- server/controllers/api/claim/longId/index.js | 2 +- .../controllers/assets/serveByClaim/index.js | 13 ++- .../assets/serveByIdentifierAndClaim/index.js | 14 +-- .../assets/utils/determineResponseType.js | 37 ++++++ ...ClaimNameAndIdForBackwardsCompatibility.js | 23 ++++ .../assets/utils/getClaimIdAndServeAsset.js | 51 ++++++++ .../controllers/{ => assets}/utils/lbryUri.js | 0 .../assets/utils/logRequestData.js | 10 ++ server/controllers/utils/file.js | 20 ---- server/controllers/utils/getClaimId.js | 57 +++++++++ .../controllers/utils/getLocalFileRecord.js | 15 +++ server/controllers/utils/serve.js | 109 ------------------ server/controllers/utils/serveHelpers.js | 64 ---------- 17 files changed, 230 insertions(+), 209 deletions(-) create mode 100644 server/controllers/api/claim/get/addGetResultsToFileData.js create mode 100644 server/controllers/api/claim/get/createFileData.js create mode 100644 server/controllers/assets/utils/determineResponseType.js create mode 100644 server/controllers/assets/utils/flipClaimNameAndIdForBackwardsCompatibility.js create mode 100644 server/controllers/assets/utils/getClaimIdAndServeAsset.js rename server/controllers/{ => assets}/utils/lbryUri.js (100%) create mode 100644 server/controllers/assets/utils/logRequestData.js delete mode 100644 server/controllers/utils/file.js create mode 100644 server/controllers/utils/getClaimId.js create mode 100644 server/controllers/utils/getLocalFileRecord.js delete mode 100644 server/controllers/utils/serve.js delete mode 100644 server/controllers/utils/serveHelpers.js diff --git a/server/controllers/api/channel/data/index.js b/server/controllers/api/channel/data/index.js index ad678d78..b52022f8 100644 --- a/server/controllers/api/channel/data/index.js +++ b/server/controllers/api/channel/data/index.js @@ -1,6 +1,7 @@ -const { getChannelData } = require('../../../utils/serveHelpers.js'); const { handleErrorResponse } = require('../../../utils/errorHandlers.js'); +const getChannelData = require('./getChannelData.js'); + const NO_CHANNEL = 'NO_CHANNEL'; /* diff --git a/server/controllers/api/claim/get/addGetResultsToFileData.js b/server/controllers/api/claim/get/addGetResultsToFileData.js new file mode 100644 index 00000000..3fe3cc43 --- /dev/null +++ b/server/controllers/api/claim/get/addGetResultsToFileData.js @@ -0,0 +1,5 @@ +module.exports = (fileInfo, getResult) => { + fileInfo.fileName = getResult.file_name; + fileInfo.filePath = getResult.download_path; + return fileInfo; +}; diff --git a/server/controllers/api/claim/get/createFileData.js b/server/controllers/api/claim/get/createFileData.js new file mode 100644 index 00000000..71d295ab --- /dev/null +++ b/server/controllers/api/claim/get/createFileData.js @@ -0,0 +1,13 @@ +module.exports = ({ name, claimId, outpoint, height, address, nsfw, contentType }) => { + return { + name, + claimId, + outpoint, + height, + address, + fileName: '', + filePath: '', + fileType: contentType, + nsfw, + }; +}; diff --git a/server/controllers/api/claim/get/index.js b/server/controllers/api/claim/get/index.js index d54fcc87..1a8757e8 100644 --- a/server/controllers/api/claim/get/index.js +++ b/server/controllers/api/claim/get/index.js @@ -1,5 +1,6 @@ const { getClaim } = require('../../../../lbrynet'); -const { addGetResultsToFileData, createFileData } = require('../../../utils/file.js'); +const addGetResultsToFileData = require('./addGetResultsToFileData.js'); +const createFileData = require('./createFileData.js'); const { handleErrorResponse } = require('../../../utils/errorHandlers.js'); const db = require('../../../../models'); diff --git a/server/controllers/api/claim/longId/index.js b/server/controllers/api/claim/longId/index.js index b84ded1e..f246fd0c 100644 --- a/server/controllers/api/claim/longId/index.js +++ b/server/controllers/api/claim/longId/index.js @@ -1,4 +1,4 @@ -const { getClaimId } = require('../../../utils/serveHelpers.js'); +const getClaimId = require('../../../utils/getClaimId.js'); const { handleErrorResponse } = require('../../../utils/errorHandlers.js'); const NO_CHANNEL = 'NO_CHANNEL'; diff --git a/server/controllers/assets/serveByClaim/index.js b/server/controllers/assets/serveByClaim/index.js index 51d9a500..a561754e 100644 --- a/server/controllers/assets/serveByClaim/index.js +++ b/server/controllers/assets/serveByClaim/index.js @@ -1,11 +1,12 @@ const { sendGAServeEvent } = require('../../../utils/googleAnalytics'); -const { - determineResponseType, - logRequestData, - getClaimIdAndServeAsset, -} = require('../../utils/serve.js'); -const lbryUri = require('../../utils/lbryUri.js'); const handleShowRender = require('../../../render/build/handleShowRender.js'); + +const lbryUri = require('../utils/lbryUri.js'); + +const determineResponseType = require('../utils/determineResponseType.js'); +const getClaimIdAndServeAsset = require('../utils/getClaimIdAndServeAsset.js'); +const logRequestData = require('../utils/logRequestData.js'); + const SERVE = 'SERVE'; /* diff --git a/server/controllers/assets/serveByIdentifierAndClaim/index.js b/server/controllers/assets/serveByIdentifierAndClaim/index.js index 954421d9..2fbdb7bb 100644 --- a/server/controllers/assets/serveByIdentifierAndClaim/index.js +++ b/server/controllers/assets/serveByIdentifierAndClaim/index.js @@ -1,13 +1,13 @@ const { sendGAServeEvent } = require('../../../utils/googleAnalytics'); -const { - determineResponseType, - flipClaimNameAndIdForBackwardsCompatibility, - logRequestData, - getClaimIdAndServeAsset, -} = require('../../utils/serve.js'); -const lbryUri = require('../../utils/lbryUri.js'); const handleShowRender = require('../../../render/build/handleShowRender.js'); +const lbryUri = require('../utils/lbryUri.js'); + +const determineResponseType = require('../utils/determineResponseType.js'); +const getClaimIdAndServeAsset = require('../utils/getClaimIdAndServeAsset.js'); +const flipClaimNameAndIdForBackwardsCompatibility = require('../utils/flipClaimNameAndIdForBackwardsCompatibility.js'); +const logRequestData = require('../utils/logRequestData.js'); + const SERVE = 'SERVE'; /* diff --git a/server/controllers/assets/utils/determineResponseType.js b/server/controllers/assets/utils/determineResponseType.js new file mode 100644 index 00000000..f32a0c5c --- /dev/null +++ b/server/controllers/assets/utils/determineResponseType.js @@ -0,0 +1,37 @@ +const logger = require('winston'); + +const SERVE = 'SERVE'; +const SHOW = 'SHOW'; + +function clientAcceptsHtml ({accept}) { + return accept && accept.match(/text\/html/); +}; + +function requestIsFromBrowser (headers) { + return headers['user-agent'] && headers['user-agent'].match(/Mozilla/); +}; + +function clientWantsAsset ({accept, range}) { + const imageIsWanted = accept && accept.match(/image\/.*/) && !accept.match(/text\/html/) && !accept.match(/text\/\*/); + const videoIsWanted = accept && range; + return imageIsWanted || videoIsWanted; +}; + +const determineResponseType = (hasFileExtension, headers) => { + let responseType; + if (hasFileExtension) { + responseType = SERVE; // assume a serve request if file extension is present + if (clientAcceptsHtml(headers)) { // if the request comes from a browser, change it to a show request + responseType = SHOW; + } + } else { + responseType = SHOW; + if (clientWantsAsset(headers) && requestIsFromBrowser(headers)) { // this is in case someone embeds a show url + logger.debug('Show request came from browser but wants an image/video. Changing response to serve...'); + responseType = SERVE; + } + } + return responseType; +}; + +module.exports = determineResponseType; diff --git a/server/controllers/assets/utils/flipClaimNameAndIdForBackwardsCompatibility.js b/server/controllers/assets/utils/flipClaimNameAndIdForBackwardsCompatibility.js new file mode 100644 index 00000000..47ebab32 --- /dev/null +++ b/server/controllers/assets/utils/flipClaimNameAndIdForBackwardsCompatibility.js @@ -0,0 +1,23 @@ +function isValidClaimId (claimId) { + return ((claimId.length === 40) && !/[^A-Za-z0-9]/g.test(claimId)); +}; + +function isValidShortId (claimId) { + return claimId.length === 1; // it should really evaluate the short url itself +}; + +function isValidShortIdOrClaimId (input) { + return (isValidClaimId(input) || isValidShortId(input)); +}; + +const flipClaimNameAndIdForBackwardsCompatibility = (identifier, name) => { + // this is a patch for backwards compatability with '/name/claim_id' url format + if (isValidShortIdOrClaimId(name) && !isValidShortIdOrClaimId(identifier)) { + const tempName = name; + name = identifier; + identifier = tempName; + } + return [identifier, name]; +}; + +module.exports = flipClaimNameAndIdForBackwardsCompatibility; diff --git a/server/controllers/assets/utils/getClaimIdAndServeAsset.js b/server/controllers/assets/utils/getClaimIdAndServeAsset.js new file mode 100644 index 00000000..ab0e3ce3 --- /dev/null +++ b/server/controllers/assets/utils/getClaimIdAndServeAsset.js @@ -0,0 +1,51 @@ +const logger = require('winston'); +const getClaimId = require('../../utils/getClaimId.js'); +const getLocalFileRecord = require('../../utils/getLocalFileRecord.js'); +const { handleErrorResponse } = require('../../utils/errorHandlers.js'); + +const NO_FILE = 'NO_FILE'; +const NO_CHANNEL = 'NO_CHANNEL'; +const NO_CLAIM = 'NO_CLAIM'; + +function serveAssetToClient (claimId, name, res) { + return getLocalFileRecord(claimId, name) + .then(fileRecord => { + // check that a local record was found + if (fileRecord === NO_FILE) { + return res.status(307).redirect(`/api/claim/get/${name}/${claimId}`); + } + // serve the file + const {filePath, fileType} = fileRecord; + logger.verbose(`serving file: ${filePath}`); + const sendFileOptions = { + headers: { + 'X-Content-Type-Options': 'nosniff', + 'Content-Type' : fileType || 'image/jpeg', + }, + }; + res.status(200).sendFile(filePath, sendFileOptions); + }) + .catch(error => { + throw error; + }); +}; + +const getClaimIdAndServeAsset = (channelName, channelClaimId, claimName, claimId, originalUrl, ip, res) => { + // get the claim Id and then serve the asset + getClaimId(channelName, channelClaimId, claimName, claimId) + .then(fullClaimId => { + if (fullClaimId === NO_CLAIM) { + return res.status(404).json({success: false, message: 'no claim id could be found'}); + } else if (fullClaimId === NO_CHANNEL) { + return res.status(404).json({success: false, message: 'no channel id could be found'}); + } + serveAssetToClient(fullClaimId, claimName, res); + // postToStats(responseType, originalUrl, ip, claimName, fullClaimId, 'success'); + }) + .catch(error => { + handleErrorResponse(originalUrl, ip, error, res); + // postToStats(responseType, originalUrl, ip, claimName, fullClaimId, 'fail'); + }); +}; + +module.exports = getClaimIdAndServeAsset; diff --git a/server/controllers/utils/lbryUri.js b/server/controllers/assets/utils/lbryUri.js similarity index 100% rename from server/controllers/utils/lbryUri.js rename to server/controllers/assets/utils/lbryUri.js diff --git a/server/controllers/assets/utils/logRequestData.js b/server/controllers/assets/utils/logRequestData.js new file mode 100644 index 00000000..dde074c2 --- /dev/null +++ b/server/controllers/assets/utils/logRequestData.js @@ -0,0 +1,10 @@ +const logger = require('winston'); + +const logRequestData = (responseType, claimName, channelName, claimId) => { + logger.debug('responseType ===', responseType); + logger.debug('claim name === ', claimName); + logger.debug('channel name ===', channelName); + logger.debug('claim id ===', claimId); +}; + +module.exports = logRequestData; diff --git a/server/controllers/utils/file.js b/server/controllers/utils/file.js deleted file mode 100644 index b786f8e8..00000000 --- a/server/controllers/utils/file.js +++ /dev/null @@ -1,20 +0,0 @@ -module.exports = { - addGetResultsToFileData (fileInfo, getResult) { - fileInfo.fileName = getResult.file_name; - fileInfo.filePath = getResult.download_path; - return fileInfo; - }, - createFileData ({ name, claimId, outpoint, height, address, nsfw, contentType }) { - return { - name, - claimId, - outpoint, - height, - address, - fileName: '', - filePath: '', - fileType: contentType, - nsfw, - }; - }, -}; diff --git a/server/controllers/utils/getClaimId.js b/server/controllers/utils/getClaimId.js new file mode 100644 index 00000000..4e6c5a29 --- /dev/null +++ b/server/controllers/utils/getClaimId.js @@ -0,0 +1,57 @@ +const logger = require('winston'); + +const db = require('../../models'); + +const NO_CHANNEL = 'NO_CHANNEL'; +const NO_CLAIM = 'NO_CLAIM'; + +const getClaimIdByClaim = (claimName, claimId) => { + logger.debug(`getClaimIdByClaim(${claimName}, ${claimId})`); + return new Promise((resolve, reject) => { + db.Claim.getLongClaimId(claimName, claimId) + .then(longClaimId => { + if (!longClaimId) { + resolve(NO_CLAIM); + } + resolve(longClaimId); + }) + .catch(error => { + reject(error); + }); + }); +}; + +const getClaimIdByChannel = (channelName, channelClaimId, claimName) => { + logger.debug(`getClaimIdByChannel(${channelName}, ${channelClaimId}, ${claimName})`); + return new Promise((resolve, reject) => { + db.Certificate.getLongChannelId(channelName, channelClaimId) // 1. get the long channel id + .then(longChannelId => { + if (!longChannelId) { + return [null, null]; + } + return Promise.all([longChannelId, db.Claim.getClaimIdByLongChannelId(longChannelId, claimName)]); // 2. get the long claim id + }) + .then(([longChannelId, longClaimId]) => { + if (!longChannelId) { + return resolve(NO_CHANNEL); + } + if (!longClaimId) { + return resolve(NO_CLAIM); + } + resolve(longClaimId); + }) + .catch(error => { + reject(error); + }); + }); +}; + +const getClaimId = (channelName, channelClaimId, name, claimId) => { + if (channelName) { + return getClaimIdByChannel(channelName, channelClaimId, name); + } else { + return getClaimIdByClaim(name, claimId); + } +}; + +module.exports = getClaimId; diff --git a/server/controllers/utils/getLocalFileRecord.js b/server/controllers/utils/getLocalFileRecord.js new file mode 100644 index 00000000..3d2016d1 --- /dev/null +++ b/server/controllers/utils/getLocalFileRecord.js @@ -0,0 +1,15 @@ +const db = require('../../models'); + +const NO_FILE = 'NO_FILE'; + +const getLocalFileRecord = (claimId, name) => { + return db.File.findOne({where: {claimId, name}}) + .then(file => { + if (!file) { + return NO_FILE; + } + return file.dataValues; + }); +}; + +module.exports = getLocalFileRecord; diff --git a/server/controllers/utils/serve.js b/server/controllers/utils/serve.js deleted file mode 100644 index f9fb7f8b..00000000 --- a/server/controllers/utils/serve.js +++ /dev/null @@ -1,109 +0,0 @@ -const logger = require('winston'); -const { getClaimId, getLocalFileRecord } = require('./serveHelpers.js'); -const { handleErrorResponse } = require('./errorHandlers.js'); - -const SERVE = 'SERVE'; -const SHOW = 'SHOW'; -const NO_FILE = 'NO_FILE'; -const NO_CHANNEL = 'NO_CHANNEL'; -const NO_CLAIM = 'NO_CLAIM'; - -function clientAcceptsHtml ({accept}) { - return accept && accept.match(/text\/html/); -}; - -function requestIsFromBrowser (headers) { - return headers['user-agent'] && headers['user-agent'].match(/Mozilla/); -}; - -function clientWantsAsset ({accept, range}) { - const imageIsWanted = accept && accept.match(/image\/.*/) && !accept.match(/text\/html/) && !accept.match(/text\/\*/); - const videoIsWanted = accept && range; - return imageIsWanted || videoIsWanted; -}; - -function isValidClaimId (claimId) { - return ((claimId.length === 40) && !/[^A-Za-z0-9]/g.test(claimId)); -}; - -function isValidShortId (claimId) { - return claimId.length === 1; // it should really evaluate the short url itself -}; - -function isValidShortIdOrClaimId (input) { - return (isValidClaimId(input) || isValidShortId(input)); -}; - -function serveAssetToClient (claimId, name, res) { - return getLocalFileRecord(claimId, name) - .then(fileRecord => { - // check that a local record was found - if (fileRecord === NO_FILE) { - return res.status(307).redirect(`/api/claim/get/${name}/${claimId}`); - } - // serve the file - const {filePath, fileType} = fileRecord; - logger.verbose(`serving file: ${filePath}`); - const sendFileOptions = { - headers: { - 'X-Content-Type-Options': 'nosniff', - 'Content-Type' : fileType || 'image/jpeg', - }, - }; - res.status(200).sendFile(filePath, sendFileOptions); - }) - .catch(error => { - throw error; - }); -}; - -module.exports = { - getClaimIdAndServeAsset (channelName, channelClaimId, claimName, claimId, originalUrl, ip, res) { - // get the claim Id and then serve the asset - getClaimId(channelName, channelClaimId, claimName, claimId) - .then(fullClaimId => { - if (fullClaimId === NO_CLAIM) { - return res.status(404).json({success: false, message: 'no claim id could be found'}); - } else if (fullClaimId === NO_CHANNEL) { - return res.status(404).json({success: false, message: 'no channel id could be found'}); - } - serveAssetToClient(fullClaimId, claimName, res); - // postToStats(responseType, originalUrl, ip, claimName, fullClaimId, 'success'); - }) - .catch(error => { - handleErrorResponse(originalUrl, ip, error, res); - // postToStats(responseType, originalUrl, ip, claimName, fullClaimId, 'fail'); - }); - }, - determineResponseType (hasFileExtension, headers) { - let responseType; - if (hasFileExtension) { - responseType = SERVE; // assume a serve request if file extension is present - if (clientAcceptsHtml(headers)) { // if the request comes from a browser, change it to a show request - responseType = SHOW; - } - } else { - responseType = SHOW; - if (clientWantsAsset(headers) && requestIsFromBrowser(headers)) { // this is in case someone embeds a show url - logger.debug('Show request came from browser but wants an image/video. Changing response to serve...'); - responseType = SERVE; - } - } - return responseType; - }, - flipClaimNameAndIdForBackwardsCompatibility (identifier, name) { - // this is a patch for backwards compatability with '/name/claim_id' url format - if (isValidShortIdOrClaimId(name) && !isValidShortIdOrClaimId(identifier)) { - const tempName = name; - name = identifier; - identifier = tempName; - } - return [identifier, name]; - }, - logRequestData (responseType, claimName, channelName, claimId) { - logger.debug('responseType ===', responseType); - logger.debug('claim name === ', claimName); - logger.debug('channel name ===', channelName); - logger.debug('claim id ===', claimId); - }, -}; diff --git a/server/controllers/utils/serveHelpers.js b/server/controllers/utils/serveHelpers.js deleted file mode 100644 index 68b46335..00000000 --- a/server/controllers/utils/serveHelpers.js +++ /dev/null @@ -1,64 +0,0 @@ -const db = require('../../models'); -const logger = require('winston'); - -const NO_CHANNEL = 'NO_CHANNEL'; -const NO_CLAIM = 'NO_CLAIM'; -const NO_FILE = 'NO_FILE'; - -module.exports = { - getClaimId (channelName, channelClaimId, name, claimId) { - if (channelName) { - return module.exports.getClaimIdByChannel(channelName, channelClaimId, name); - } else { - return module.exports.getClaimIdByClaim(name, claimId); - } - }, - getClaimIdByClaim (claimName, claimId) { - logger.debug(`getClaimIdByClaim(${claimName}, ${claimId})`); - return new Promise((resolve, reject) => { - db.Claim.getLongClaimId(claimName, claimId) - .then(longClaimId => { - if (!longClaimId) { - resolve(NO_CLAIM); - } - resolve(longClaimId); - }) - .catch(error => { - reject(error); - }); - }); - }, - getClaimIdByChannel (channelName, channelClaimId, claimName) { - logger.debug(`getClaimIdByChannel(${channelName}, ${channelClaimId}, ${claimName})`); - return new Promise((resolve, reject) => { - db.Certificate.getLongChannelId(channelName, channelClaimId) // 1. get the long channel id - .then(longChannelId => { - if (!longChannelId) { - return [null, null]; - } - return Promise.all([longChannelId, db.Claim.getClaimIdByLongChannelId(longChannelId, claimName)]); // 2. get the long claim id - }) - .then(([longChannelId, longClaimId]) => { - if (!longChannelId) { - return resolve(NO_CHANNEL); - } - if (!longClaimId) { - return resolve(NO_CLAIM); - } - resolve(longClaimId); - }) - .catch(error => { - reject(error); - }); - }); - }, - getLocalFileRecord (claimId, name) { - return db.File.findOne({where: {claimId, name}}) - .then(file => { - if (!file) { - return NO_FILE; - } - return file.dataValues; - }); - }, -}; From 060af3a95717a6fa6e2d4ebc76b86b5afc839e20 Mon Sep 17 00:00:00 2001 From: bill bittner Date: Fri, 27 Apr 2018 14:29:00 -0700 Subject: [PATCH 06/13] organized auth, fallback, and page controllers; --- server/auth/authentication.js | 74 ------------------ .../api/claim/publish/authentication.js | 75 +++++++++++++++++++ server/controllers/api/claim/publish/index.js | 8 +- .../assets/serveByIdentifierAndClaim/index.js | 5 +- ...Compatibility.js => flipClaimNameAndId.js} | 6 +- .../auth/{login.js => login/index.js} | 2 +- .../auth/{logout.js => logout/index.js} | 0 .../auth/{signup.js => signup/index.js} | 0 .../auth/{user.js => user/index.js} | 0 server/controllers/fallback/sendReactApp.js | 7 -- .../controllers/{pages => utils}/redirect.js | 0 server/routes/fallback/index.js | 2 +- server/routes/pages/index.js | 2 +- 13 files changed, 90 insertions(+), 91 deletions(-) delete mode 100644 server/auth/authentication.js create mode 100644 server/controllers/api/claim/publish/authentication.js rename server/controllers/assets/utils/{flipClaimNameAndIdForBackwardsCompatibility.js => flipClaimNameAndId.js} (79%) rename server/controllers/auth/{login.js => login/index.js} (90%) rename server/controllers/auth/{logout.js => logout/index.js} (100%) rename server/controllers/auth/{signup.js => signup/index.js} (100%) rename server/controllers/auth/{user.js => user/index.js} (100%) delete mode 100644 server/controllers/fallback/sendReactApp.js rename server/controllers/{pages => utils}/redirect.js (100%) diff --git a/server/auth/authentication.js b/server/auth/authentication.js deleted file mode 100644 index accff721..00000000 --- a/server/auth/authentication.js +++ /dev/null @@ -1,74 +0,0 @@ -const logger = require('winston'); -const db = require('../models'); - -module.exports = { - authenticateUser (channelName, channelId, channelPassword, user) { - // case: no channelName or channel Id are provided (anonymous), regardless of whether user token is provided - if (!channelName && !channelId) { - return { - channelName : null, - channelClaimId: null, - }; - } - // case: channelName or channel Id are provided with user token - if (user) { - if (channelName && channelName !== user.channelName) { - throw new Error('the provided channel name does not match user credentials'); - } - if (channelId && channelId !== user.channelClaimId) { - throw new Error('the provided channel id does not match user credentials'); - } - return { - channelName : user.channelName, - channelClaimId: user.channelClaimId, - }; - } - // case: channelName or channel Id are provided with password instead of user token - if (!channelPassword) throw new Error('no channel password provided'); - return module.exports.authenticateChannelCredentials(channelName, channelId, channelPassword); - }, - authenticateChannelCredentials (channelName, channelId, userPassword) { - return new Promise((resolve, reject) => { - // hoisted variables - let channelData; - // build the params for finding the channel - let channelFindParams = {}; - if (channelName) channelFindParams['channelName'] = channelName; - if (channelId) channelFindParams['channelClaimId'] = channelId; - // find the channel - db.Channel - .findOne({ - where: channelFindParams, - }) - .then(channel => { - if (!channel) { - logger.debug('no channel found'); - throw new Error('Authentication failed, you do not have access to that channel'); - } - channelData = channel.get(); - logger.debug('channel data:', channelData); - return db.User.findOne({ - where: { userName: channelData.channelName.substring(1) }, - }); - }) - .then(user => { - if (!user) { - logger.debug('no user found'); - throw new Error('Authentication failed, you do not have access to that channel'); - } - return user.comparePassword(userPassword); - }) - .then(isMatch => { - if (!isMatch) { - logger.debug('incorrect password'); - throw new Error('Authentication failed, you do not have access to that channel'); - } - logger.debug('...password was a match...'); - resolve(channelData); - }) - .catch(error => { - reject(error); - }); - }); - }, -}; diff --git a/server/controllers/api/claim/publish/authentication.js b/server/controllers/api/claim/publish/authentication.js new file mode 100644 index 00000000..d41902ef --- /dev/null +++ b/server/controllers/api/claim/publish/authentication.js @@ -0,0 +1,75 @@ +const logger = require('winston'); +const db = require('../../../../models/index'); + +const authenticateChannelCredentials = (channelName, channelId, userPassword) => { + return new Promise((resolve, reject) => { + // hoisted variables + let channelData; + // build the params for finding the channel + let channelFindParams = {}; + if (channelName) channelFindParams['channelName'] = channelName; + if (channelId) channelFindParams['channelClaimId'] = channelId; + // find the channel + db.Channel + .findOne({ + where: channelFindParams, + }) + .then(channel => { + if (!channel) { + logger.debug('no channel found'); + throw new Error('Authentication failed, you do not have access to that channel'); + } + channelData = channel.get(); + logger.debug('channel data:', channelData); + return db.User.findOne({ + where: { userName: channelData.channelName.substring(1) }, + }); + }) + .then(user => { + if (!user) { + logger.debug('no user found'); + throw new Error('Authentication failed, you do not have access to that channel'); + } + return user.comparePassword(userPassword); + }) + .then(isMatch => { + if (!isMatch) { + logger.debug('incorrect password'); + throw new Error('Authentication failed, you do not have access to that channel'); + } + logger.debug('...password was a match...'); + resolve(channelData); + }) + .catch(error => { + reject(error); + }); + }); +}; + +const authenticateUser = (channelName, channelId, channelPassword, user) => { + // case: no channelName or channel Id are provided (anonymous), regardless of whether user token is provided + if (!channelName && !channelId) { + return { + channelName : null, + channelClaimId: null, + }; + } + // case: channelName or channel Id are provided with user token + if (user) { + if (channelName && channelName !== user.channelName) { + throw new Error('the provided channel name does not match user credentials'); + } + if (channelId && channelId !== user.channelClaimId) { + throw new Error('the provided channel id does not match user credentials'); + } + return { + channelName : user.channelName, + channelClaimId: user.channelClaimId, + }; + } + // case: channelName or channel Id are provided with password instead of user token + if (!channelPassword) throw new Error('no channel password provided'); + return authenticateChannelCredentials(channelName, channelId, channelPassword); +}; + +module.exports = authenticateUser; diff --git a/server/controllers/api/claim/publish/index.js b/server/controllers/api/claim/publish/index.js index 2d4ee10d..1e95d317 100644 --- a/server/controllers/api/claim/publish/index.js +++ b/server/controllers/api/claim/publish/index.js @@ -1,13 +1,17 @@ const { details: { host } } = require('../../../../../config/siteConfig.js'); -const { authenticateUser } = require('../../../../auth/authentication.js'); + const { sendGATimingEvent } = require('../../../../utils/googleAnalytics.js'); + const { handleErrorResponse } = require('../../../utils/errorHandlers.js'); + +const checkClaimAvailability = require('../utils/checkClaimAvailability.js'); + const publish = require('./publish.js'); const createBasicPublishParams = require('./createBasicPublishParams.js'); const createThumbnailPublishParams = require('./createThumbnailPublishParams.js'); const parsePublishApiRequestBody = require('./parsePublishApiRequestBody.js'); const parsePublishApiRequestFiles = require('./parsePublishApiRequestFiles.js'); -const checkClaimAvailability = require('../utils/checkClaimAvailability.js'); +const authenticateUser = require('./authentication.js'); /* diff --git a/server/controllers/assets/serveByIdentifierAndClaim/index.js b/server/controllers/assets/serveByIdentifierAndClaim/index.js index 2fbdb7bb..e493e01e 100644 --- a/server/controllers/assets/serveByIdentifierAndClaim/index.js +++ b/server/controllers/assets/serveByIdentifierAndClaim/index.js @@ -5,7 +5,7 @@ const lbryUri = require('../utils/lbryUri.js'); const determineResponseType = require('../utils/determineResponseType.js'); const getClaimIdAndServeAsset = require('../utils/getClaimIdAndServeAsset.js'); -const flipClaimNameAndIdForBackwardsCompatibility = require('../utils/flipClaimNameAndIdForBackwardsCompatibility.js'); +const flipClaimNameAndId = require('../utils/flipClaimNameAndId.js'); const logRequestData = require('../utils/logRequestData.js'); const SERVE = 'SERVE'; @@ -46,8 +46,9 @@ const serverAssetByIdentifierAndClaim = (req, res) => { } catch (error) { return res.status(400).json({success: false, message: error.message}); } + // for backwards compatability, flip claim name and claim id if necessary if (!isChannel) { - [claimId, claimName] = flipClaimNameAndIdForBackwardsCompatibility(claimId, claimName); + [claimId, claimName] = flipClaimNameAndId(claimId, claimName); } // log the request data for debugging logRequestData(responseType, claimName, channelName, claimId); diff --git a/server/controllers/assets/utils/flipClaimNameAndIdForBackwardsCompatibility.js b/server/controllers/assets/utils/flipClaimNameAndId.js similarity index 79% rename from server/controllers/assets/utils/flipClaimNameAndIdForBackwardsCompatibility.js rename to server/controllers/assets/utils/flipClaimNameAndId.js index 47ebab32..c41ebd02 100644 --- a/server/controllers/assets/utils/flipClaimNameAndIdForBackwardsCompatibility.js +++ b/server/controllers/assets/utils/flipClaimNameAndId.js @@ -10,8 +10,8 @@ function isValidShortIdOrClaimId (input) { return (isValidClaimId(input) || isValidShortId(input)); }; -const flipClaimNameAndIdForBackwardsCompatibility = (identifier, name) => { - // this is a patch for backwards compatability with '/name/claim_id' url format +const flipClaimNameAndId = (identifier, name) => { + // this is a patch for backwards compatability with '/name/claimId' url format if (isValidShortIdOrClaimId(name) && !isValidShortIdOrClaimId(identifier)) { const tempName = name; name = identifier; @@ -20,4 +20,4 @@ const flipClaimNameAndIdForBackwardsCompatibility = (identifier, name) => { return [identifier, name]; }; -module.exports = flipClaimNameAndIdForBackwardsCompatibility; +module.exports = flipClaimNameAndId; diff --git a/server/controllers/auth/login.js b/server/controllers/auth/login/index.js similarity index 90% rename from server/controllers/auth/login.js rename to server/controllers/auth/login/index.js index 229b4e98..e88de217 100644 --- a/server/controllers/auth/login.js +++ b/server/controllers/auth/login/index.js @@ -1,4 +1,4 @@ -const speechPassport = require('../../speechPassport/index'); +const speechPassport = require('../../../speechPassport/index'); const login = (req, res, next) => { speechPassport.authenticate('local-login', (err, user, info) => { diff --git a/server/controllers/auth/logout.js b/server/controllers/auth/logout/index.js similarity index 100% rename from server/controllers/auth/logout.js rename to server/controllers/auth/logout/index.js diff --git a/server/controllers/auth/signup.js b/server/controllers/auth/signup/index.js similarity index 100% rename from server/controllers/auth/signup.js rename to server/controllers/auth/signup/index.js diff --git a/server/controllers/auth/user.js b/server/controllers/auth/user/index.js similarity index 100% rename from server/controllers/auth/user.js rename to server/controllers/auth/user/index.js diff --git a/server/controllers/fallback/sendReactApp.js b/server/controllers/fallback/sendReactApp.js deleted file mode 100644 index e291fd0a..00000000 --- a/server/controllers/fallback/sendReactApp.js +++ /dev/null @@ -1,7 +0,0 @@ -const handlePageRender = require('../../render/build/handlePageRender.js'); - -const sendReactApp = (req, res) => { - handlePageRender(req, res); -}; - -module.exports = sendReactApp; diff --git a/server/controllers/pages/redirect.js b/server/controllers/utils/redirect.js similarity index 100% rename from server/controllers/pages/redirect.js rename to server/controllers/utils/redirect.js diff --git a/server/routes/fallback/index.js b/server/routes/fallback/index.js index 0fc57d0c..cc453b81 100644 --- a/server/routes/fallback/index.js +++ b/server/routes/fallback/index.js @@ -1,4 +1,4 @@ -const handlePageRequest = require('../../controllers/fallback/sendReactApp'); +const handlePageRequest = require('../../controllers/pages/sendReactApp'); module.exports = (app) => { app.get('*', handlePageRequest); diff --git a/server/routes/pages/index.js b/server/routes/pages/index.js index a7c3a936..fc825225 100644 --- a/server/routes/pages/index.js +++ b/server/routes/pages/index.js @@ -1,6 +1,6 @@ const handlePageRequest = require('../../controllers/pages/sendReactApp'); const handleEmbedRequest = require('../../controllers/pages/sendEmbedPage'); -const redirect = require('../../controllers/pages/redirect'); +const redirect = require('../../controllers/utils/redirect'); module.exports = (app) => { app.get('/', handlePageRequest); From b5c486c4ac3daa0c3725c07c0889dc9f156c9907 Mon Sep 17 00:00:00 2001 From: bill bittner Date: Fri, 27 Apr 2018 15:17:09 -0700 Subject: [PATCH 07/13] added blocked model --- server/models/blocked.js | 14 ++++++++++++++ server/models/index.js | 2 ++ 2 files changed, 16 insertions(+) create mode 100644 server/models/blocked.js diff --git a/server/models/blocked.js b/server/models/blocked.js new file mode 100644 index 00000000..04adbb79 --- /dev/null +++ b/server/models/blocked.js @@ -0,0 +1,14 @@ +module.exports = (sequelize, { STRING }) => { + return sequelize.define( + 'Blocked', + { + outpoint: { + type : STRING, + allowNull: false, + }, + }, + { + freezeTableName: true, + } + ); +}; diff --git a/server/models/index.js b/server/models/index.js index cda6419f..6c030cd6 100644 --- a/server/models/index.js +++ b/server/models/index.js @@ -4,6 +4,7 @@ const Claim = require('./claim.js'); const File = require('./file.js'); const Request = require('./request.js'); const User = require('./user.js'); +const Blocked = require('./blocked.js'); const Sequelize = require('sequelize'); const logger = require('winston'); @@ -42,6 +43,7 @@ db['Claim'] = sequelize.import('Claim', Claim); db['File'] = sequelize.import('File', File); db['Request'] = sequelize.import('Request', Request); db['User'] = sequelize.import('User', User); +db['Blocked'] = sequelize.import('Blocked', Blocked); // run model.association for each model in the db object that has an association logger.info('associating db models...'); From c89fdd390e035c8198258f076377ec1e28d1d772 Mon Sep 17 00:00:00 2001 From: bill bittner Date: Sun, 29 Apr 2018 10:31:26 -0700 Subject: [PATCH 08/13] added blocked model --- .../assets/utils/getClaimIdAndServeAsset.js | 2 +- server/models/blocked.js | 26 ++++++++++++++++++- server/models/claim.js | 5 +++- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/server/controllers/assets/utils/getClaimIdAndServeAsset.js b/server/controllers/assets/utils/getClaimIdAndServeAsset.js index ab0e3ce3..f5c50a1f 100644 --- a/server/controllers/assets/utils/getClaimIdAndServeAsset.js +++ b/server/controllers/assets/utils/getClaimIdAndServeAsset.js @@ -7,7 +7,7 @@ const NO_FILE = 'NO_FILE'; const NO_CHANNEL = 'NO_CHANNEL'; const NO_CLAIM = 'NO_CLAIM'; -function serveAssetToClient (claimId, name, res) { +const serveAssetToClient = (claimId, name, res) => { return getLocalFileRecord(claimId, name) .then(fileRecord => { // check that a local record was found diff --git a/server/models/blocked.js b/server/models/blocked.js index 04adbb79..a3955c47 100644 --- a/server/models/blocked.js +++ b/server/models/blocked.js @@ -1,5 +1,7 @@ +const logger = require('winston'); + module.exports = (sequelize, { STRING }) => { - return sequelize.define( + const Blocked = sequelize.define( 'Blocked', { outpoint: { @@ -11,4 +13,26 @@ module.exports = (sequelize, { STRING }) => { freezeTableName: true, } ); + + Blocked.isBlocked = function (outpoint) { + logger.debug(`checking to see if ${outpoint} is blocked`); + return new Promise((resolve, reject) => { + this.findOne({ + where: { + outpoint, + }, + }) + .then(result => { + if (!result) { + return resolve(false); + } + resolve(true); + }) + .catch(error => { + reject(error); + }); + }); + }; + + return Blocked; }; diff --git a/server/models/claim.js b/server/models/claim.js index 1ab5f355..a5232e6d 100644 --- a/server/models/claim.js +++ b/server/models/claim.js @@ -315,7 +315,10 @@ module.exports = (sequelize, { STRING, BOOLEAN, INTEGER, TEXT, DECIMAL }) => { Claim.validateLongClaimId = function (name, claimId) { return new Promise((resolve, reject) => { this.findOne({ - where: {name, claimId}, + where: { + name, + claimId, + }, }) .then(result => { if (!result) { From d57a6b3340f19590a0541f52bddbe0bba533dd69 Mon Sep 17 00:00:00 2001 From: bill bittner Date: Sun, 29 Apr 2018 12:17:23 -0700 Subject: [PATCH 09/13] added check for blocked content and updated claimid flow to use rejected promises --- .../checkClaimAvailability.js | 2 +- .../api/claim/availability/index.js | 2 +- .../api/claim/longId/getClaimId.js | 31 +++++++ server/controllers/api/claim/longId/index.js | 24 ++++-- server/controllers/api/claim/publish/index.js | 2 +- .../assets/utils/getClaimIdAndServeAsset.js | 65 +++++++-------- .../{ => assets}/utils/getLocalFileRecord.js | 2 +- .../assets/utils/serveAssetToClient.js | 28 +++++++ server/controllers/utils/getClaimId.js | 57 ------------- server/models/blocked.js | 24 ++++-- server/models/certificate.js | 65 +++++++++------ server/models/claim.js | 82 +++++++++++-------- 12 files changed, 211 insertions(+), 173 deletions(-) rename server/controllers/api/claim/{utils => availability}/checkClaimAvailability.js (94%) create mode 100644 server/controllers/api/claim/longId/getClaimId.js rename server/controllers/{ => assets}/utils/getLocalFileRecord.js (87%) create mode 100644 server/controllers/assets/utils/serveAssetToClient.js delete mode 100644 server/controllers/utils/getClaimId.js diff --git a/server/controllers/api/claim/utils/checkClaimAvailability.js b/server/controllers/api/claim/availability/checkClaimAvailability.js similarity index 94% rename from server/controllers/api/claim/utils/checkClaimAvailability.js rename to server/controllers/api/claim/availability/checkClaimAvailability.js index f10f2590..c4f4501a 100644 --- a/server/controllers/api/claim/utils/checkClaimAvailability.js +++ b/server/controllers/api/claim/availability/checkClaimAvailability.js @@ -1,4 +1,4 @@ -const db = require('../../../../models'); +const db = require('../../../../models/index'); const { publishing: { primaryClaimAddress, additionalClaimAddresses } } = require('../../../../../config/siteConfig.js'); const Sequelize = require('sequelize'); const Op = Sequelize.Op; diff --git a/server/controllers/api/claim/availability/index.js b/server/controllers/api/claim/availability/index.js index 9f9d330d..1583cb26 100644 --- a/server/controllers/api/claim/availability/index.js +++ b/server/controllers/api/claim/availability/index.js @@ -1,4 +1,4 @@ -const checkClaimAvailability = require('../utils/checkClaimAvailability.js'); +const checkClaimAvailability = require('./checkClaimAvailability.js'); const { sendGATimingEvent } = require('../../../../utils/googleAnalytics.js'); const { handleErrorResponse } = require('../../../utils/errorHandlers.js'); diff --git a/server/controllers/api/claim/longId/getClaimId.js b/server/controllers/api/claim/longId/getClaimId.js new file mode 100644 index 00000000..d1a3a212 --- /dev/null +++ b/server/controllers/api/claim/longId/getClaimId.js @@ -0,0 +1,31 @@ +const logger = require('winston'); + +const db = require('../../../../models'); + +const getClaimIdByChannel = (channelName, channelClaimId, claimName) => { + return new Promise((resolve, reject) => { + db.Certificate + .getLongChannelId(channelName, channelClaimId) + .then(longChannelId => { + return db.Claim.getClaimIdByLongChannelId(longChannelId, claimName); + }) + .then(longClaimId => { + resolve(longClaimId); + }) + .catch(error => { + reject(error); + }); + }); +}; + +const getClaimId = (channelName, channelClaimId, name, claimId) => { + if (channelName) { + logger.debug(`getClaimIdByChannel(${channelName}, ${channelClaimId}, ${name})`); + return getClaimIdByChannel(channelName, channelClaimId, name); + } else { + logger.debug(`db.Claim.getLongClaimId(${name}, ${claimId})`); + return db.Claim.getLongClaimId(name, claimId); + } +}; + +module.exports = getClaimId; diff --git a/server/controllers/api/claim/longId/index.js b/server/controllers/api/claim/longId/index.js index f246fd0c..c9dd78be 100644 --- a/server/controllers/api/claim/longId/index.js +++ b/server/controllers/api/claim/longId/index.js @@ -1,4 +1,4 @@ -const getClaimId = require('../../../utils/getClaimId.js'); +const getClaimId = require('./getClaimId.js'); const { handleErrorResponse } = require('../../../utils/errorHandlers.js'); const NO_CHANNEL = 'NO_CHANNEL'; @@ -16,16 +16,22 @@ const claimLongId = ({ ip, originalUrl, body, params }, res) => { const claimName = body.claimName; const claimId = body.claimId; getClaimId(channelName, channelClaimId, claimName, claimId) - .then(result => { - if (result === NO_CHANNEL) { - return res.status(404).json({success: false, message: 'No matching channel could be found'}); - } - if (result === NO_CLAIM) { - return res.status(404).json({success: false, message: 'No matching claim id could be found'}); - } - res.status(200).json({success: true, data: result}); + .then(fullClaimId => { + res.status(200).json({success: true, data: fullClaimId}); }) .catch(error => { + if (error === NO_CLAIM) { + return res.status(404).json({ + success: false, + message: 'No claim id could be found', + }); + } + if (error === NO_CHANNEL) { + return res.status(404).json({ + success: false, + message: 'No channel id could be found', + }); + } handleErrorResponse(originalUrl, ip, error, res); }); }; diff --git a/server/controllers/api/claim/publish/index.js b/server/controllers/api/claim/publish/index.js index 1e95d317..0a748753 100644 --- a/server/controllers/api/claim/publish/index.js +++ b/server/controllers/api/claim/publish/index.js @@ -4,7 +4,7 @@ const { sendGATimingEvent } = require('../../../../utils/googleAnalytics.js'); const { handleErrorResponse } = require('../../../utils/errorHandlers.js'); -const checkClaimAvailability = require('../utils/checkClaimAvailability.js'); +const checkClaimAvailability = require('../availability/checkClaimAvailability.js'); const publish = require('./publish.js'); const createBasicPublishParams = require('./createBasicPublishParams.js'); diff --git a/server/controllers/assets/utils/getClaimIdAndServeAsset.js b/server/controllers/assets/utils/getClaimIdAndServeAsset.js index f5c50a1f..6bd868b2 100644 --- a/server/controllers/assets/utils/getClaimIdAndServeAsset.js +++ b/server/controllers/assets/utils/getClaimIdAndServeAsset.js @@ -1,50 +1,43 @@ -const logger = require('winston'); -const getClaimId = require('../../utils/getClaimId.js'); -const getLocalFileRecord = require('../../utils/getLocalFileRecord.js'); +const db = require('../../../models'); + +const getClaimId = require('../../api/claim/longId/getClaimId.js'); const { handleErrorResponse } = require('../../utils/errorHandlers.js'); -const NO_FILE = 'NO_FILE'; +const serveAssetToClient = require('./serveAssetToClient.js'); + const NO_CHANNEL = 'NO_CHANNEL'; const NO_CLAIM = 'NO_CLAIM'; - -const serveAssetToClient = (claimId, name, res) => { - return getLocalFileRecord(claimId, name) - .then(fileRecord => { - // check that a local record was found - if (fileRecord === NO_FILE) { - return res.status(307).redirect(`/api/claim/get/${name}/${claimId}`); - } - // serve the file - const {filePath, fileType} = fileRecord; - logger.verbose(`serving file: ${filePath}`); - const sendFileOptions = { - headers: { - 'X-Content-Type-Options': 'nosniff', - 'Content-Type' : fileType || 'image/jpeg', - }, - }; - res.status(200).sendFile(filePath, sendFileOptions); - }) - .catch(error => { - throw error; - }); -}; +const BLOCKED_CLAIM = 'BLOCKED_CLAIM'; const getClaimIdAndServeAsset = (channelName, channelClaimId, claimName, claimId, originalUrl, ip, res) => { - // get the claim Id and then serve the asset getClaimId(channelName, channelClaimId, claimName, claimId) .then(fullClaimId => { - if (fullClaimId === NO_CLAIM) { - return res.status(404).json({success: false, message: 'no claim id could be found'}); - } else if (fullClaimId === NO_CHANNEL) { - return res.status(404).json({success: false, message: 'no channel id could be found'}); - } - serveAssetToClient(fullClaimId, claimName, res); - // postToStats(responseType, originalUrl, ip, claimName, fullClaimId, 'success'); + claimId = fullClaimId; + return db.Blocked.isNotBlocked(fullClaimId, claimName); + }) + .then(() => { + serveAssetToClient(claimId, claimName, res); }) .catch(error => { + if (error === NO_CLAIM) { + return res.status(404).json({ + success: false, + message: 'No claim id could be found', + }); + } + if (error === NO_CHANNEL) { + return res.status(404).json({ + success: false, + message: 'No channel id could be found', + }); + } + if (error === BLOCKED_CLAIM) { + return res.status(410).json({ + success: false, + message: 'In response to a complaint we received under the US Digital Millennium Copyright Act, we have blocked access to this content from our applications. For more details, see https://lbry.io/faq/dmca', + }); + } handleErrorResponse(originalUrl, ip, error, res); - // postToStats(responseType, originalUrl, ip, claimName, fullClaimId, 'fail'); }); }; diff --git a/server/controllers/utils/getLocalFileRecord.js b/server/controllers/assets/utils/getLocalFileRecord.js similarity index 87% rename from server/controllers/utils/getLocalFileRecord.js rename to server/controllers/assets/utils/getLocalFileRecord.js index 3d2016d1..53f8a469 100644 --- a/server/controllers/utils/getLocalFileRecord.js +++ b/server/controllers/assets/utils/getLocalFileRecord.js @@ -1,4 +1,4 @@ -const db = require('../../models'); +const db = require('../../../models'); const NO_FILE = 'NO_FILE'; diff --git a/server/controllers/assets/utils/serveAssetToClient.js b/server/controllers/assets/utils/serveAssetToClient.js new file mode 100644 index 00000000..28991d24 --- /dev/null +++ b/server/controllers/assets/utils/serveAssetToClient.js @@ -0,0 +1,28 @@ +const logger = require('winston'); +const getLocalFileRecord = require('./getLocalFileRecord.js'); +const NO_FILE = 'NO_FILE'; + +const serveAssetToClient = (claimId, name, res) => { + return getLocalFileRecord(claimId, name) + .then(fileRecord => { + // check that a local record was found + if (fileRecord === NO_FILE) { + return res.status(307).redirect(`/api/claim/get/${name}/${claimId}`); + } + // serve the file + const {filePath, fileType} = fileRecord; + logger.verbose(`serving file: ${filePath}`); + const sendFileOptions = { + headers: { + 'X-Content-Type-Options': 'nosniff', + 'Content-Type' : fileType || 'image/jpeg', + }, + }; + res.status(200).sendFile(filePath, sendFileOptions); + }) + .catch(error => { + throw error; + }); +}; + +module.exports = serveAssetToClient; diff --git a/server/controllers/utils/getClaimId.js b/server/controllers/utils/getClaimId.js deleted file mode 100644 index 4e6c5a29..00000000 --- a/server/controllers/utils/getClaimId.js +++ /dev/null @@ -1,57 +0,0 @@ -const logger = require('winston'); - -const db = require('../../models'); - -const NO_CHANNEL = 'NO_CHANNEL'; -const NO_CLAIM = 'NO_CLAIM'; - -const getClaimIdByClaim = (claimName, claimId) => { - logger.debug(`getClaimIdByClaim(${claimName}, ${claimId})`); - return new Promise((resolve, reject) => { - db.Claim.getLongClaimId(claimName, claimId) - .then(longClaimId => { - if (!longClaimId) { - resolve(NO_CLAIM); - } - resolve(longClaimId); - }) - .catch(error => { - reject(error); - }); - }); -}; - -const getClaimIdByChannel = (channelName, channelClaimId, claimName) => { - logger.debug(`getClaimIdByChannel(${channelName}, ${channelClaimId}, ${claimName})`); - return new Promise((resolve, reject) => { - db.Certificate.getLongChannelId(channelName, channelClaimId) // 1. get the long channel id - .then(longChannelId => { - if (!longChannelId) { - return [null, null]; - } - return Promise.all([longChannelId, db.Claim.getClaimIdByLongChannelId(longChannelId, claimName)]); // 2. get the long claim id - }) - .then(([longChannelId, longClaimId]) => { - if (!longChannelId) { - return resolve(NO_CHANNEL); - } - if (!longClaimId) { - return resolve(NO_CLAIM); - } - resolve(longClaimId); - }) - .catch(error => { - reject(error); - }); - }); -}; - -const getClaimId = (channelName, channelClaimId, name, claimId) => { - if (channelName) { - return getClaimIdByChannel(channelName, channelClaimId, name); - } else { - return getClaimIdByClaim(name, claimId); - } -}; - -module.exports = getClaimId; diff --git a/server/models/blocked.js b/server/models/blocked.js index a3955c47..12a04ca9 100644 --- a/server/models/blocked.js +++ b/server/models/blocked.js @@ -1,9 +1,19 @@ const logger = require('winston'); +const BLOCKED_CLAIM = 'BLOCKED_CLAIM'; + module.exports = (sequelize, { STRING }) => { const Blocked = sequelize.define( 'Blocked', { + claimId: { + type : STRING, + allowNull: false, + }, + name: { + type : STRING, + allowNull: false, + }, outpoint: { type : STRING, allowNull: false, @@ -14,22 +24,24 @@ module.exports = (sequelize, { STRING }) => { } ); - Blocked.isBlocked = function (outpoint) { - logger.debug(`checking to see if ${outpoint} is blocked`); + Blocked.isNotBlocked = function (claimId, name) { + logger.debug(`checking to see if ${name}#${claimId} is not blocked`); return new Promise((resolve, reject) => { this.findOne({ where: { - outpoint, + claimId, + name, }, }) .then(result => { - if (!result) { - return resolve(false); + if (result) { + return reject(BLOCKED_CLAIM); } resolve(true); }) .catch(error => { - reject(error); + logger.error(error); + reject(BLOCKED_CLAIM); }); }); }; diff --git a/server/models/certificate.js b/server/models/certificate.js index 679f6312..85a5bc50 100644 --- a/server/models/certificate.js +++ b/server/models/certificate.js @@ -1,6 +1,16 @@ const logger = require('winston'); const returnShortId = require('./utils/returnShortId.js'); +const NO_CHANNEL = 'NO_CHANNEL'; + +function isLongChannelId (channelId) { + return (channelId && (channelId.length === 40)); +} + +function isShortChannelId (channelId) { + return (channelId && (channelId.length < 40)); +} + module.exports = (sequelize, { STRING, BOOLEAN, INTEGER, TEXT, DECIMAL }) => { const Certificate = sequelize.define( 'Certificate', @@ -121,6 +131,25 @@ module.exports = (sequelize, { STRING, BOOLEAN, INTEGER, TEXT, DECIMAL }) => { }); }; + Certificate.validateLongChannelId = function (name, claimId) { + logger.debug(`validateLongChannelId(${name}, ${claimId})`); + return new Promise((resolve, reject) => { + this.findOne({ + where: {name, claimId}, + }) + .then(result => { + if (!result) { + return reject(NO_CHANNEL); + } + resolve(claimId); + }) + .catch(error => { + logger.error(error); + reject(NO_CHANNEL); + }); + }); + }; + Certificate.getLongChannelIdFromShortChannelId = function (channelName, channelClaimId) { logger.debug(`getLongChannelIdFromShortChannelId(${channelName}, ${channelClaimId})`); return new Promise((resolve, reject) => { @@ -137,13 +166,14 @@ module.exports = (sequelize, { STRING, BOOLEAN, INTEGER, TEXT, DECIMAL }) => { .then(result => { switch (result.length) { case 0: - return resolve(null); - default: // note results must be sorted + return reject(NO_CHANNEL); + default: return resolve(result[0].claimId); } }) .catch(error => { - reject(error); + logger.error(error); + reject(NO_CHANNEL); }); }); }; @@ -159,43 +189,26 @@ module.exports = (sequelize, { STRING, BOOLEAN, INTEGER, TEXT, DECIMAL }) => { .then(result => { switch (result.length) { case 0: - return resolve(null); + return reject(NO_CHANNEL); default: return resolve(result[0].claimId); } }) .catch(error => { - reject(error); - }); - }); - }; - - Certificate.validateLongChannelId = function (name, claimId) { - logger.debug(`validateLongChannelId(${name}, ${claimId})`); - return new Promise((resolve, reject) => { - this.findOne({ - where: {name, claimId}, - }) - .then(result => { - if (!result) { - return resolve(null); - }; - resolve(claimId); - }) - .catch(error => { - reject(error); + logger.error(error); + reject(NO_CHANNEL); }); }); }; Certificate.getLongChannelId = function (channelName, channelClaimId) { logger.debug(`getLongChannelId(${channelName}, ${channelClaimId})`); - if (channelClaimId && (channelClaimId.length === 40)) { // if a full channel id is provided + if (isLongChannelId(channelClaimId)) { return this.validateLongChannelId(channelName, channelClaimId); - } else if (channelClaimId && channelClaimId.length < 40) { // if a short channel id is provided + } else if (isShortChannelId(channelClaimId)) { return this.getLongChannelIdFromShortChannelId(channelName, channelClaimId); } else { - return this.getLongChannelIdFromChannelName(channelName); // if no channel id provided + return this.getLongChannelIdFromChannelName(channelName); } }; diff --git a/server/models/claim.js b/server/models/claim.js index a5232e6d..409ad94c 100644 --- a/server/models/claim.js +++ b/server/models/claim.js @@ -2,6 +2,8 @@ const logger = require('winston'); const returnShortId = require('./utils/returnShortId.js'); const { assetDefaults: { thumbnail: defaultThumbnail }, details: { host } } = require('../../config/siteConfig.js'); +const NO_CLAIM = 'NO_CLAIM'; + function determineFileExtensionFromContentType (contentType) { switch (contentType) { case 'image/jpeg': @@ -17,14 +19,14 @@ function determineFileExtensionFromContentType (contentType) { logger.debug('setting unknown file type as file extension jpeg'); return 'jpeg'; } -}; +} function determineThumbnail (storedThumbnail, defaultThumbnail) { if (storedThumbnail === '') { return defaultThumbnail; } return storedThumbnail; -}; +} function prepareClaimData (claim) { // logger.debug('preparing claim data based on resolved data:', claim); @@ -32,7 +34,15 @@ function prepareClaimData (claim) { claim['fileExt'] = determineFileExtensionFromContentType(claim.contentType); claim['host'] = host; return claim; -}; +} + +function isLongClaimId (claimId) { + return (claimId && (claimId.length === 40)); +} + +function isShortClaimId (claimId) { + return (claimId && (claimId.length < 40)); +} module.exports = (sequelize, { STRING, BOOLEAN, INTEGER, TEXT, DECIMAL }) => { const Claim = sequelize.define( @@ -265,6 +275,27 @@ module.exports = (sequelize, { STRING, BOOLEAN, INTEGER, TEXT, DECIMAL }) => { }); }; + Claim.validateLongClaimId = function (name, claimId) { + return new Promise((resolve, reject) => { + this.findOne({ + where: { + name, + claimId, + }, + }) + .then(result => { + if (!result) { + return reject(NO_CLAIM); + } + resolve(claimId); + }) + .catch(error => { + logger.error(error); + reject(NO_CLAIM); + }); + }); + }; + Claim.getLongClaimIdFromShortClaimId = function (name, shortId) { return new Promise((resolve, reject) => { this @@ -279,13 +310,14 @@ module.exports = (sequelize, { STRING, BOOLEAN, INTEGER, TEXT, DECIMAL }) => { .then(result => { switch (result.length) { case 0: - return resolve(null); - default: // note results must be sorted + return reject(NO_CLAIM); + default: return resolve(result[0].claimId); } }) .catch(error => { - reject(error); + logger.error(error); + reject(NO_CLAIM); }); }); }; @@ -295,51 +327,31 @@ module.exports = (sequelize, { STRING, BOOLEAN, INTEGER, TEXT, DECIMAL }) => { this .findAll({ where: { name }, - order: [['effectiveAmount', 'DESC'], ['height', 'ASC']], // note: maybe height and effective amount need to switch? + order: [['effectiveAmount', 'DESC'], ['height', 'ASC']], }) .then(result => { - logger.debug('length of result', result.length); switch (result.length) { case 0: - return resolve(null); + return reject(NO_CLAIM); default: return resolve(result[0].dataValues.claimId); } }) .catch(error => { - reject(error); - }); - }); - }; - - Claim.validateLongClaimId = function (name, claimId) { - return new Promise((resolve, reject) => { - this.findOne({ - where: { - name, - claimId, - }, - }) - .then(result => { - if (!result) { - return resolve(null); - }; - resolve(claimId); - }) - .catch(error => { - reject(error); + logger.error(error); + reject(NO_CLAIM); }); }); }; Claim.getLongClaimId = function (claimName, claimId) { - logger.debug(`getLongClaimId(${claimName}, ${claimId})`); - if (claimId && (claimId.length === 40)) { // if a full claim id is provided + // logger.debug(`getLongClaimId(${claimName}, ${claimId})`); + if (isLongClaimId(claimId)) { return this.validateLongClaimId(claimName, claimId); - } else if (claimId && claimId.length < 40) { - return this.getLongClaimIdFromShortClaimId(claimName, claimId); // if a short claim id is provided + } else if (isShortClaimId(claimId)) { + return this.getLongClaimIdFromShortClaimId(claimName, claimId); } else { - return this.getTopFreeClaimIdByClaimName(claimName); // if no claim id is provided + return this.getTopFreeClaimIdByClaimName(claimName); } }; From bbd691018be27281d0ebb0d3c14d66cfa394d819 Mon Sep 17 00:00:00 2001 From: bill bittner Date: Sun, 29 Apr 2018 13:00:41 -0700 Subject: [PATCH 10/13] updated api/longId route --- server/controllers/api/claim/longId/index.js | 24 ++++++++++++---- .../assets/utils/getClaimIdAndServeAsset.js | 22 ++++++++++++--- .../assets/utils/serveAssetToClient.js | 28 ------------------- server/controllers/assets/utils/serveFile.js | 14 ++++++++++ 4 files changed, 51 insertions(+), 37 deletions(-) delete mode 100644 server/controllers/assets/utils/serveAssetToClient.js create mode 100644 server/controllers/assets/utils/serveFile.js diff --git a/server/controllers/api/claim/longId/index.js b/server/controllers/api/claim/longId/index.js index c9dd78be..0eb3668c 100644 --- a/server/controllers/api/claim/longId/index.js +++ b/server/controllers/api/claim/longId/index.js @@ -1,8 +1,12 @@ -const getClaimId = require('./getClaimId.js'); +const db = require('../../../../models'); + const { handleErrorResponse } = require('../../../utils/errorHandlers.js'); +const getClaimId = require('./getClaimId.js'); + const NO_CHANNEL = 'NO_CHANNEL'; const NO_CLAIM = 'NO_CLAIM'; +const BLOCKED_CLAIM = 'BLOCKED_CLAIM'; /* @@ -14,22 +18,32 @@ const claimLongId = ({ ip, originalUrl, body, params }, res) => { const channelName = body.channelName; const channelClaimId = body.channelClaimId; const claimName = body.claimName; - const claimId = body.claimId; + let claimId = body.claimId; getClaimId(channelName, channelClaimId, claimName, claimId) .then(fullClaimId => { - res.status(200).json({success: true, data: fullClaimId}); + claimId = fullClaimId; + return db.Blocked.isNotBlocked(fullClaimId, claimName); + }) + .then(() => { + res.status(200).json({success: true, data: claimId}); }) .catch(error => { if (error === NO_CLAIM) { return res.status(404).json({ success: false, - message: 'No claim id could be found', + message: 'No matching claim id could be found for that url', }); } if (error === NO_CHANNEL) { return res.status(404).json({ success: false, - message: 'No channel id could be found', + message: 'No matching channel id could be found for that url', + }); + } + if (error === BLOCKED_CLAIM) { + return res.status(410).json({ + success: false, + message: 'In response to a complaint we received under the US Digital Millennium Copyright Act, we have blocked access to this content from our applications. For more details, see https://lbry.io/faq/dmca', }); } handleErrorResponse(originalUrl, ip, error, res); diff --git a/server/controllers/assets/utils/getClaimIdAndServeAsset.js b/server/controllers/assets/utils/getClaimIdAndServeAsset.js index 6bd868b2..9b48399f 100644 --- a/server/controllers/assets/utils/getClaimIdAndServeAsset.js +++ b/server/controllers/assets/utils/getClaimIdAndServeAsset.js @@ -1,13 +1,17 @@ +const logger = require('winston'); + const db = require('../../../models'); const getClaimId = require('../../api/claim/longId/getClaimId.js'); const { handleErrorResponse } = require('../../utils/errorHandlers.js'); -const serveAssetToClient = require('./serveAssetToClient.js'); +const getLocalFileRecord = require('./getLocalFileRecord.js'); +const serveFile = require('./serveFile.js'); const NO_CHANNEL = 'NO_CHANNEL'; const NO_CLAIM = 'NO_CLAIM'; const BLOCKED_CLAIM = 'BLOCKED_CLAIM'; +const NO_FILE = 'NO_FILE'; const getClaimIdAndServeAsset = (channelName, channelClaimId, claimName, claimId, originalUrl, ip, res) => { getClaimId(channelName, channelClaimId, claimName, claimId) @@ -16,27 +20,37 @@ const getClaimIdAndServeAsset = (channelName, channelClaimId, claimName, claimId return db.Blocked.isNotBlocked(fullClaimId, claimName); }) .then(() => { - serveAssetToClient(claimId, claimName, res); + return getLocalFileRecord(claimId, claimName); + }) + .then(fileRecord => { + serveFile(fileRecord, res); }) .catch(error => { if (error === NO_CLAIM) { + logger.debug('no claim found'); return res.status(404).json({ success: false, - message: 'No claim id could be found', + message: 'No matching claim id could be found for that url', }); } if (error === NO_CHANNEL) { + logger.debug('no channel found'); return res.status(404).json({ success: false, - message: 'No channel id could be found', + message: 'No matching channel id could be found for that url', }); } if (error === BLOCKED_CLAIM) { + logger.debug('claim was blocked'); return res.status(410).json({ success: false, message: 'In response to a complaint we received under the US Digital Millennium Copyright Act, we have blocked access to this content from our applications. For more details, see https://lbry.io/faq/dmca', }); } + if (error === NO_FILE) { + logger.debug('claim was blocked'); + return res.status(307).redirect(`/api/claim/get/${name}/${claimId}`); + } handleErrorResponse(originalUrl, ip, error, res); }); }; diff --git a/server/controllers/assets/utils/serveAssetToClient.js b/server/controllers/assets/utils/serveAssetToClient.js deleted file mode 100644 index 28991d24..00000000 --- a/server/controllers/assets/utils/serveAssetToClient.js +++ /dev/null @@ -1,28 +0,0 @@ -const logger = require('winston'); -const getLocalFileRecord = require('./getLocalFileRecord.js'); -const NO_FILE = 'NO_FILE'; - -const serveAssetToClient = (claimId, name, res) => { - return getLocalFileRecord(claimId, name) - .then(fileRecord => { - // check that a local record was found - if (fileRecord === NO_FILE) { - return res.status(307).redirect(`/api/claim/get/${name}/${claimId}`); - } - // serve the file - const {filePath, fileType} = fileRecord; - logger.verbose(`serving file: ${filePath}`); - const sendFileOptions = { - headers: { - 'X-Content-Type-Options': 'nosniff', - 'Content-Type' : fileType || 'image/jpeg', - }, - }; - res.status(200).sendFile(filePath, sendFileOptions); - }) - .catch(error => { - throw error; - }); -}; - -module.exports = serveAssetToClient; diff --git a/server/controllers/assets/utils/serveFile.js b/server/controllers/assets/utils/serveFile.js new file mode 100644 index 00000000..ab3c167a --- /dev/null +++ b/server/controllers/assets/utils/serveFile.js @@ -0,0 +1,14 @@ +const logger = require('winston'); + +const serveFile = ({ filePath, fileType }, res) => { + logger.verbose(`serving file: ${filePath}`); + const sendFileOptions = { + headers: { + 'X-Content-Type-Options': 'nosniff', + 'Content-Type' : fileType || 'image/jpeg', + }, + }; + res.status(200).sendFile(filePath, sendFileOptions); +}; + +module.exports = serveFile; From 6c97b40c322399705454ecedd9012ecadd1b3211 Mon Sep 17 00:00:00 2001 From: bill bittner Date: Sun, 29 Apr 2018 15:30:11 -0700 Subject: [PATCH 11/13] added api endpoint to trigger blocked-list refresh --- .../api/claim/blockedList/index.js | 56 +++++++++++++++++++ server/routes/api/index.js | 16 +++--- 2 files changed, 65 insertions(+), 7 deletions(-) create mode 100644 server/controllers/api/claim/blockedList/index.js diff --git a/server/controllers/api/claim/blockedList/index.js b/server/controllers/api/claim/blockedList/index.js new file mode 100644 index 00000000..abc80d8e --- /dev/null +++ b/server/controllers/api/claim/blockedList/index.js @@ -0,0 +1,56 @@ +const logger = require('winston'); +const db = require('../../../../models'); + +const updateBlockedList = (req, res) => { + return fetch('https://api.lbry.io/file/list_blocked') + .then(response => { + return response.json(); + }) + .then(jsonResponse => { + if (!jsonResponse.data) { + throw new Error('no data in list_blocked response'); + } + if (!jsonResponse.data.outpoints) { + throw new Error('no outpoints in list_blocked response'); + } + return jsonResponse.data.outpoints; + }) + .then(outpoints => { + logger.info('number of blocked outpoints:', outpoints.length); + let updatePromises = []; + outpoints.forEach(outpoint => { + // logger.debug('outpoint:', outpoint); + updatePromises.push(db.Claim + .findOne({ + where: { + outpoint, + }, + }) + .then(Claim => { + if (Claim) { + const { claimId, name } = Claim; + logger.debug(`creating record in Blocked for ${name}#${claimId}`); + const blocked = { + claimId, + name, + outpoint, + }; + return db.upsert(db.Blocked, blocked, blocked, 'Blocked') + } + }) + .catch(error => { + logger.error(error); + })); + }); + return Promise.all(updatePromises); + }) + .then(() => { + logger.info('finished updating blocked content list'); + res.status(200).json({success: true, message: 'finished updating blocked content list'}); + }) + .catch((error) => { + logger.error(error); + }); +}; + +module.exports = updateBlockedList; diff --git a/server/routes/api/index.js b/server/routes/api/index.js index a1a46974..4eda3f2a 100644 --- a/server/routes/api/index.js +++ b/server/routes/api/index.js @@ -3,13 +3,14 @@ const channelClaims = require('../../controllers/api/channel/claims'); const channelData = require('../../controllers/api/channel/data'); const channelShortId = require('../../controllers/api/channel/shortId'); const claimAvailability = require('../../controllers/api/claim/availability'); +const claimBlockedList = require('../../controllers/api/claim/blockedList'); const claimData = require('../../controllers/api/claim/data/'); const claimGet = require('../../controllers/api/claim/get'); +const claimList = require('../../controllers/api/claim/list'); const claimLongId = require('../../controllers/api/claim/longId'); const claimPublish = require('../../controllers/api/claim/publish'); const claimResolve = require('../../controllers/api/claim/resolve'); const claimShortId = require('../../controllers/api/claim/shortId'); -const claimList = require('../../controllers/api/claim/list'); const fileAvailability = require('../../controllers/api/file/availability'); const multipartMiddleware = require('../utils/multipartMiddleware'); @@ -21,14 +22,15 @@ module.exports = (app) => { app.get('/api/channel/data/:channelName/:channelClaimId', channelData); app.get('/api/channel/claims/:channelName/:channelClaimId/:page', channelClaims); // claim routes - app.get('/api/claim/list/:name', claimList); - app.get('/api/claim/get/:name/:claimId', claimGet); app.get('/api/claim/availability/:name', claimAvailability); - app.get('/api/claim/resolve/:name/:claimId', claimResolve); - app.post('/api/claim/publish', multipartMiddleware, claimPublish); - app.get('/api/claim/short-id/:longId/:name', claimShortId); - app.post('/api/claim/long-id', claimLongId); + app.get('/api/claim/blocked-list/', claimBlockedList); app.get('/api/claim/data/:claimName/:claimId', claimData); + app.get('/api/claim/get/:name/:claimId', claimGet); + app.get('/api/claim/list/:name', claimList); + app.post('/api/claim/long-id', claimLongId); + app.post('/api/claim/publish', multipartMiddleware, claimPublish); + app.get('/api/claim/resolve/:name/:claimId', claimResolve); + app.get('/api/claim/short-id/:longId/:name', claimShortId); // file routes app.get('/api/file/availability/:name/:claimId', fileAvailability); }; From 47a3fb865b90a92351139885f960d10451213ab0 Mon Sep 17 00:00:00 2001 From: bill bittner Date: Mon, 30 Apr 2018 15:36:03 -0700 Subject: [PATCH 12/13] updated http response code to 451 --- server/controllers/assets/utils/getClaimIdAndServeAsset.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/controllers/assets/utils/getClaimIdAndServeAsset.js b/server/controllers/assets/utils/getClaimIdAndServeAsset.js index 9b48399f..e391383d 100644 --- a/server/controllers/assets/utils/getClaimIdAndServeAsset.js +++ b/server/controllers/assets/utils/getClaimIdAndServeAsset.js @@ -42,7 +42,7 @@ const getClaimIdAndServeAsset = (channelName, channelClaimId, claimName, claimId } if (error === BLOCKED_CLAIM) { logger.debug('claim was blocked'); - return res.status(410).json({ + return res.status(451).json({ success: false, message: 'In response to a complaint we received under the US Digital Millennium Copyright Act, we have blocked access to this content from our applications. For more details, see https://lbry.io/faq/dmca', }); From 69ebce3efd1db656a3b7a9a80c765d9f1a10b875 Mon Sep 17 00:00:00 2001 From: bill bittner Date: Mon, 30 Apr 2018 15:58:04 -0700 Subject: [PATCH 13/13] updated channel long id retrieval to match claims pattern --- .../api/channel/claims/getChannelClaims.js | 22 ++++++++--------- .../controllers/api/channel/claims/index.js | 9 ++++--- .../api/channel/data/getChannelData.js | 24 ++++++++----------- server/controllers/api/channel/data/index.js | 16 +++++++++---- server/models/certificate.js | 2 +- 5 files changed, 38 insertions(+), 35 deletions(-) diff --git a/server/controllers/api/channel/claims/getChannelClaims.js b/server/controllers/api/channel/claims/getChannelClaims.js index aec6f03e..a36e559b 100644 --- a/server/controllers/api/channel/claims/getChannelClaims.js +++ b/server/controllers/api/channel/claims/getChannelClaims.js @@ -1,22 +1,20 @@ const db = require('../../../../models'); + const { returnPaginatedChannelClaims } = require('./channelPagination.js'); -const NO_CHANNEL = 'NO_CHANNEL'; const getChannelClaims = (channelName, channelClaimId, page) => { return new Promise((resolve, reject) => { + let longChannelClaimId; // 1. get the long channel Id (make sure channel exists) - db.Certificate.getLongChannelId(channelName, channelClaimId) - .then(longChannelClaimId => { - if (!longChannelClaimId) { - return [null, null, null]; - } - // 2. get the short ID and all claims for that channel - return Promise.all([longChannelClaimId, db.Claim.getAllChannelClaims(longChannelClaimId)]); + db.Certificate + .getLongChannelId(channelName, channelClaimId) + .then(result => { + longChannelClaimId = result; + return db + .Claim + .getAllChannelClaims(longChannelClaimId); }) - .then(([longChannelClaimId, channelClaimsArray]) => { - if (!longChannelClaimId) { - return resolve(NO_CHANNEL); - } + .then(channelClaimsArray => { // 3. format the data for the view, including pagination let paginatedChannelViewData = returnPaginatedChannelClaims(channelName, longChannelClaimId, channelClaimsArray, page); // 4. return all the channel information and contents diff --git a/server/controllers/api/channel/claims/index.js b/server/controllers/api/channel/claims/index.js index 4c7b6777..473394b2 100644 --- a/server/controllers/api/channel/claims/index.js +++ b/server/controllers/api/channel/claims/index.js @@ -16,12 +16,15 @@ const channelClaims = ({ ip, originalUrl, body, params }, res) => { const page = params.page; getChannelClaims(channelName, channelClaimId, page) .then(data => { - if (data === NO_CHANNEL) { - return res.status(404).json({success: false, message: 'No matching channel was found'}); - } res.status(200).json({success: true, data}); }) .catch(error => { + if (error === NO_CHANNEL) { + return res.status(404).json({ + success: false, + message: 'No matching channel was found', + }); + } handleErrorResponse(originalUrl, ip, error, res); }); }; diff --git a/server/controllers/api/channel/data/getChannelData.js b/server/controllers/api/channel/data/getChannelData.js index 98c3a8d5..a0db2374 100644 --- a/server/controllers/api/channel/data/getChannelData.js +++ b/server/controllers/api/channel/data/getChannelData.js @@ -1,22 +1,18 @@ const db = require('../../../../models'); -const NO_CHANNEL = 'NO_CHANNEL'; -const getChannelData = (channelName, channelClaimId, page) => { +const getChannelData = (channelName, channelClaimId) => { return new Promise((resolve, reject) => { + let longChannelClaimId; // 1. get the long channel Id (make sure channel exists) - db.Certificate.getLongChannelId(channelName, channelClaimId) - .then(longChannelClaimId => { - if (!longChannelClaimId) { - return [null, null, null]; - } - // 2. get the short ID and all claims for that channel - return Promise.all([longChannelClaimId, db.Certificate.getShortChannelIdFromLongChannelId(longChannelClaimId, channelName)]); + db.Certificate + .getLongChannelId(channelName, channelClaimId) + .then(fullClaimId => { + longChannelClaimId = fullClaimId; + return db + .Certificate + .getShortChannelIdFromLongChannelId(fullClaimId, channelName); }) - .then(([longChannelClaimId, shortChannelClaimId]) => { - if (!longChannelClaimId) { - return resolve(NO_CHANNEL); - } - // 3. return all the channel information + .then(shortChannelClaimId => { resolve({ channelName, longChannelClaimId, diff --git a/server/controllers/api/channel/data/index.js b/server/controllers/api/channel/data/index.js index b52022f8..730549e5 100644 --- a/server/controllers/api/channel/data/index.js +++ b/server/controllers/api/channel/data/index.js @@ -14,14 +14,20 @@ const channelData = ({ ip, originalUrl, body, params }, res) => { const channelName = params.channelName; let channelClaimId = params.channelClaimId; if (channelClaimId === 'none') channelClaimId = null; - getChannelData(channelName, channelClaimId, 0) + getChannelData(channelName, channelClaimId) .then(data => { - if (data === NO_CHANNEL) { - return res.status(404).json({success: false, message: 'No matching channel was found'}); - } - res.status(200).json({success: true, data}); + res.status(200).json({ + success: true, + data + }); }) .catch(error => { + if (error === NO_CHANNEL) { + return res.status(404).json({ + success: false, + message: 'No matching channel was found', + }); + } handleErrorResponse(originalUrl, ip, error, res); }); }; diff --git a/server/models/certificate.js b/server/models/certificate.js index 85a5bc50..723b5065 100644 --- a/server/models/certificate.js +++ b/server/models/certificate.js @@ -120,7 +120,7 @@ module.exports = (sequelize, { STRING, BOOLEAN, INTEGER, TEXT, DECIMAL }) => { .then(result => { switch (result.length) { case 0: - throw new Error('No channel(s) found with that channel name'); + return reject(NO_CHANNEL); default: return resolve(returnShortId(result, longChannelId)); }