diff --git a/cli/defaults/siteConfig.json b/cli/defaults/siteConfig.json index 67e4a79f..15243fce 100644 --- a/cli/defaults/siteConfig.json +++ b/cli/defaults/siteConfig.json @@ -23,7 +23,7 @@ "publishing": { "primaryClaimAddress": null, "uploadDirectory": "/home/lbry/Uploads", - "lbrynetHome": "/CURRENTLYUNUSED", + "lbrynetHome": "/home/lbry", "thumbnailChannel": null, "thumbnailChannelId": null, "additionalClaimAddresses": [], @@ -36,17 +36,6 @@ "publishingChannelWhitelist": [], "channelClaimBidAmount": "0.1", "fileClaimBidAmount": "0.01", - "fileSizeLimits": { - "image": 50000000, - "video": 50000000, - "audio": 50000000, - "text": 50000000, - "model": 50000000, - "application": 50000000, - "customByContentType": { - "application/octet-stream": 50000000 - } - }, "maxSizeImage": 10000000, "maxSizeGif": 50000000, "maxSizeVideo": 50000000 @@ -60,19 +49,7 @@ "publicDisallowedTypesMain": [] }, "customFileExtensions": { - "application/x-troff-man": ".man", - "application/x-troff-me": ".me", - "application/x-mif": ".mif", - "application/x-troff-ms": ".ms", - "application/x-troff": ".roff", - "application/x-python-code": ".pyc", - "text/x-python": ".py", - "application/x-pn-realaudio": ".ram", - "application/x-sgml": ".sgm", - "model/stl": ".stl", - "image/pict": ".pct", - "text/xul": ".xul", - "text/x-go": "go" + "application/example-type": "example" } }, "startup": { diff --git a/client/src/components/DropzonePreviewImage/index.jsx b/client/src/components/DropzonePreviewImage/index.jsx index 5aa6f730..d62abaeb 100644 --- a/client/src/components/DropzonePreviewImage/index.jsx +++ b/client/src/components/DropzonePreviewImage/index.jsx @@ -5,9 +5,8 @@ class PublishPreview extends React.Component { constructor (props) { super(props); this.state = { - imgSource : '', - defaultVideoThumbnail: '/assets/img/video_thumb_default.png', - defaultThumbnail : '/assets/img/Speech_Logo_Main@OG-02.jpg', + imgSource : '', + defaultThumbnail: '/assets/img/video_thumb_default.png', }; } componentDidMount () { @@ -38,13 +37,12 @@ class PublishPreview extends React.Component { }; } setPreviewImageSource (file) { - if (this.props.thumbnail) { - this.setPreviewImageSourceFromFile(this.props.thumbnail); - } else if (file.type.substr(0, file.type.indexOf('/')) === 'image'){ + if (file.type !== 'video/mp4') { this.setPreviewImageSourceFromFile(file); - } else if (file.type === 'video'){ - this.setState({imgSource: this.state.defaultVideoThumbnail}); } else { + if (this.props.thumbnail) { + this.setPreviewImageSourceFromFile(this.props.thumbnail); + } this.setState({imgSource: this.state.defaultThumbnail}); } } diff --git a/client/src/containers/Dropzone/view.jsx b/client/src/containers/Dropzone/view.jsx index cba685f9..a4a6d00e 100644 --- a/client/src/containers/Dropzone/view.jsx +++ b/client/src/containers/Dropzone/view.jsx @@ -1,13 +1,13 @@ import React from 'react'; +import { validateFile } from '../../utils/file'; import Memeify from '@components/Memeify'; import DropzonePreviewImage from '@components/DropzonePreviewImage'; import DropzoneDropItDisplay from '@components/DropzoneDropItDisplay'; import DropzoneInstructionsDisplay from '@components/DropzoneInstructionsDisplay'; -import validateFileForPublish from '@globalutils/validateFileForPublish'; -import { library } from '@fortawesome/fontawesome-svg-core'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { library } from '@fortawesome/fontawesome-svg-core' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { faEdit } from '@fortawesome/free-solid-svg-icons'; const isFacebook = (() => { @@ -29,7 +29,7 @@ class Dropzone extends React.Component { memeify : false, }; - if (props.file) { + if(props.file) { // No side effects allowed with `getDerivedStateFromProps`, so // we must use `componentDidUpdate` and `constructor` routines. // Note: `FileReader` has an `onloadend` side-effect @@ -133,7 +133,7 @@ class Dropzone extends React.Component { chooseFile (file) { if (file) { try { - validateFileForPublish(file); // validate the file's name, type, and size + validateFile(file); // validate the file's name, type, and size } catch (error) { return this.props.setFileError(error.message); } diff --git a/client/src/utils/createAssetMetaTags.js b/client/src/utils/createAssetMetaTags.js index e2a0b5ef..70bead44 100644 --- a/client/src/utils/createAssetMetaTags.js +++ b/client/src/utils/createAssetMetaTags.js @@ -47,6 +47,8 @@ const createAssetMetaTags = asset => { const ogThumbnailContentType = determineContentTypeFromExtension(claimData.thumbnail); const ogThumbnail = claimData.thumbnail || defaultThumbnail; + console.log('asset.claimData', asset.claimData); + // {property: 'og:title'] = ogTitle}, const metaTags = { 'og:title': ogTitle, diff --git a/server/chainquery/models/ClaimModel.js b/server/chainquery/models/ClaimModel.js index 4fcc1af0..022656f9 100644 --- a/server/chainquery/models/ClaimModel.js +++ b/server/chainquery/models/ClaimModel.js @@ -1,17 +1,9 @@ const logger = require('winston'); const mime = require('mime-types'); -const { - serving: { customFileExtensions }, -} = require('@config/siteConfig'); const getterMethods = { generated_extension() { - logger.info('trying to generate extension', this.content_type); - if (customFileExtensions.hasOwnProperty(this.content_type)) { - return customFileExtensions[this.content_type]; - } else { - return mime.extension(this.content_type) ? mime.extension(this.content_type) : 'jpg'; - } + return mime.extension(this.content_type) ? mime.extension(this.content_type) : 'jpg'; }, }; diff --git a/server/controllers/api/claim/publish/parsePublishApiRequestFiles.js b/server/controllers/api/claim/publish/parsePublishApiRequestFiles.js index 6979740e..3fdcdfc3 100644 --- a/server/controllers/api/claim/publish/parsePublishApiRequestFiles.js +++ b/server/controllers/api/claim/publish/parsePublishApiRequestFiles.js @@ -1,6 +1,5 @@ const path = require('path'); const validateFileTypeAndSize = require('./validateFileTypeAndSize.js'); -const validateFileForPublish = require('./validateFileForPublish.js'); const parsePublishApiRequestFiles = ({ file, thumbnail }, isUpdate) => { // make sure a file was provided @@ -41,7 +40,7 @@ const parsePublishApiRequestFiles = ({ file, thumbnail }, isUpdate) => { } // validate the file - if (file) validateFileForPublish(file); + if (file) validateFileTypeAndSize(file); // return results const obj = { fileName: file.name, diff --git a/server/controllers/api/claim/publish/validateFileForPublish.js b/server/controllers/api/claim/publish/validateFileForPublish.js deleted file mode 100644 index 1047c048..00000000 --- a/server/controllers/api/claim/publish/validateFileForPublish.js +++ /dev/null @@ -1,38 +0,0 @@ -const logger = require('winston'); - -const { publishing } = require('@config/siteConfig.json'); - -const { fileSizeLimits } = publishing; - -const SIZE_MB = 1000000; - -const validateFileForPublish = file => { - let contentType = file.type; - let mediaType = contentType ? contentType.substr(0, contentType.indexOf('/')) : ''; - let mediaTypeLimit = fileSizeLimits[mediaType] || false; - let customLimits = fileSizeLimits['customByContentType']; - - if (!file) { - throw new Error('no file provided'); - } - - if (/'/.test(file.name)) { - throw new Error('apostrophes are not allowed in the file name'); - } - - if (Object.keys(customLimits).includes(contentType)) { - if (file.size > customLimits[contentType]) { - throw new Error( - `Sorry, type ${contentType} is limited to ${customLimits[contentType] / SIZE_MB} MB.` - ); - } - } - if (mediaTypeLimit) { - if (file.size > mediaTypeLimit) { - throw new Error(`Sorry, type ${mediaType} is limited to ${mediaTypeLimit / SIZE_MB} MB.`); - } - } - return file; -}; - -module.exports = validateFileForPublish; diff --git a/server/index.js b/server/index.js index be209d33..d423ffac 100644 --- a/server/index.js +++ b/server/index.js @@ -13,7 +13,7 @@ const httpContext = require('express-http-context'); const db = require('./models'); const requestLogger = require('./middleware/requestLogger'); const createDatabaseIfNotExists = require('./models/utils/createDatabaseIfNotExists'); -const { getWalletBalance } = require('./lbrynet/index'); +const { getAccountBalance } = require('./lbrynet/index'); const configureLogging = require('./utils/configureLogging'); const configureSlack = require('./utils/configureSlack'); const { setupBlockList } = require('./utils/blockList'); @@ -27,10 +27,7 @@ const { const { details: { port: PORT, blockListEndpoint }, - startup: { - performChecks, - performUpdates, - }, + startup: { performChecks, performUpdates }, } = require('@config/siteConfig'); const { sessionKey } = require('@private/authConfig.json'); @@ -38,7 +35,7 @@ const { sessionKey } = require('@private/authConfig.json'); // configure.js doesn't handle new keys in config.json files yet. Make sure it doens't break. let finalBlockListEndpoint; -function Server () { +function Server() { this.initialize = () => { // configure logging configureLogging(); @@ -53,12 +50,16 @@ function Server () { const webpack = require('webpack'); const webpackDevMiddleware = require('webpack-dev-middleware'); - const webpackClientConfig = require('../webpack/webpack.client.config')(null, { mode: 'development' }); + const webpackClientConfig = require('../webpack/webpack.client.config')(null, { + mode: 'development', + }); const clientCompiler = webpack(webpackClientConfig); - app.use(webpackDevMiddleware(clientCompiler, { - publicPath: webpackClientConfig.output.publicPath, - })); + app.use( + webpackDevMiddleware(clientCompiler, { + publicPath: webpackClientConfig.output.publicPath, + }) + ); app.use(require('webpack-hot-middleware')(clientCompiler)); } @@ -67,8 +68,15 @@ function Server () { app.enable('trust proxy'); app.use((req, res, next) => { - if (req.get('User-Agent') === 'Mozilla/5.0 (Windows NT 5.1; rv:14.0) Gecko/20120405 Firefox/14.0a1') { - res.status(403).send('

Forbidden

If you are seeing this by mistake, please contact us using https://chat.lbry.io/'); + if ( + req.get('User-Agent') === + 'Mozilla/5.0 (Windows NT 5.1; rv:14.0) Gecko/20120405 Firefox/14.0a1' + ) { + res + .status(403) + .send( + '

Forbidden

If you are seeing this by mistake, please contact us using https://chat.lbry.io/' + ); res.end(); } else { next(); @@ -101,38 +109,45 @@ function Server () { app.use(requestLogger); // initialize passport - app.use(cookieSession({ - name: 'session', - keys: [sessionKey], - })); + app.use( + cookieSession({ + name: 'session', + keys: [sessionKey], + }) + ); app.use(speechPassport.initialize()); app.use(speechPassport.session()); // configure handlebars & register it with express app const viewsPath = Path.resolve(process.cwd(), 'server/views'); - app.engine('handlebars', expressHandlebars({ - async : false, - dataType : 'text', - defaultLayout: 'embed', - partialsDir : Path.join(viewsPath, '/partials'), - layoutsDir : Path.join(viewsPath, '/layouts'), - })); + app.engine( + 'handlebars', + expressHandlebars({ + async: false, + dataType: 'text', + defaultLayout: 'embed', + partialsDir: Path.join(viewsPath, '/partials'), + layoutsDir: Path.join(viewsPath, '/layouts'), + }) + ); app.set('views', viewsPath); app.set('view engine', 'handlebars'); // set the routes on the app const routes = require('./routes'); - Object.keys(routes).map((routePath) => { + Object.keys(routes).map(routePath => { let routeData = routes[routePath]; let routeMethod = routeData.hasOwnProperty('method') ? routeData.method : 'get'; - let controllers = Array.isArray(routeData.controller) ? routeData.controller : [routeData.controller]; + let controllers = Array.isArray(routeData.controller) + ? routeData.controller + : [routeData.controller]; app[routeMethod]( routePath, logMetricsMiddleware, setRouteDataInContextMiddleware(routePath, routeData), - ...controllers, + ...controllers ); }); @@ -153,22 +168,18 @@ function Server () { }; this.syncDatabase = () => { logger.info(`Syncing database...`); - return createDatabaseIfNotExists() - .then(() => { - db.sequelize.sync(); - }); + return createDatabaseIfNotExists().then(() => { + db.sequelize.sync(); + }); }; this.performChecks = () => { if (!performChecks) { return; } logger.info(`Performing checks...`); - return Promise.all([ - getWalletBalance(), - ]) - .then(([walletBalance]) => { - logger.info('Starting LBC balance:', walletBalance); - }); + return Promise.all([getAccountBalance()]).then(([accountBalance]) => { + logger.info('Starting LBC balance:', accountBalance); + }); }; this.performUpdates = () => { @@ -178,27 +189,29 @@ function Server () { if (blockListEndpoint) { finalBlockListEndpoint = blockListEndpoint; } else if (!blockListEndpoint) { - if (typeof (blockListEndpoint) !== 'string') { - logger.warn('blockListEndpoint is null due to outdated siteConfig file. \n' + - 'Continuing with default LBRY blocklist api endpoint. \n ' + - '(Specify /"blockListEndpoint" : ""/ to disable.'); + if (typeof blockListEndpoint !== 'string') { + logger.warn( + 'blockListEndpoint is null due to outdated siteConfig file. \n' + + 'Continuing with default LBRY blocklist api endpoint. \n ' + + '(Specify /"blockListEndpoint" : ""/ to disable.' + ); finalBlockListEndpoint = 'https://api.lbry.io/file/list_blocked'; } } logger.info(`Peforming updates...`); if (!finalBlockListEndpoint) { logger.info('Configured for no Block List'); - db.Tor.refreshTable().then((updatedTorList) => { + db.Tor.refreshTable().then(updatedTorList => { logger.info('Tor list updated, length:', updatedTorList.length); }); } else { return Promise.all([ db.Blocked.refreshTable(finalBlockListEndpoint), - db.Tor.refreshTable()]) - .then(([updatedBlockedList, updatedTorList]) => { - logger.info('Blocked list updated, length:', updatedBlockedList.length); - logger.info('Tor list updated, length:', updatedTorList.length); - }); + db.Tor.refreshTable(), + ]).then(([updatedBlockedList, updatedTorList]) => { + logger.info('Blocked list updated, length:', updatedBlockedList.length); + logger.info('Tor list updated, length:', updatedTorList.length); + }); } }; this.start = () => { @@ -210,10 +223,7 @@ function Server () { return this.startServerListening(); }) .then(() => { - return Promise.all([ - this.performChecks(), - this.performUpdates(), - ]); + return Promise.all([this.performChecks(), this.performUpdates()]); }) .then(() => { return setupBlockList(); diff --git a/server/lbrynet/index.js b/server/lbrynet/index.js index 3b4eafcd..5d8c24c2 100644 --- a/server/lbrynet/index.js +++ b/server/lbrynet/index.js @@ -8,7 +8,7 @@ const handleLbrynetResponse = require('./utils/handleLbrynetResponse.js'); const { publishing } = require('@config/siteConfig'); module.exports = { - publishClaim (publishParams) { + publishClaim(publishParams) { logger.debug(`lbryApi >> Publishing claim to "${publishParams.name}"`); const gaStartTime = Date.now(); return new Promise((resolve, reject) => { @@ -18,7 +18,13 @@ module.exports = { params: publishParams, }) .then(response => { - sendGATimingEvent('lbrynet', 'publish', chooseGaLbrynetPublishLabel(publishParams), gaStartTime, Date.now()); + sendGATimingEvent( + 'lbrynet', + 'publish', + chooseGaLbrynetPublishLabel(publishParams), + gaStartTime, + Date.now() + ); handleLbrynetResponse(response, resolve, reject); }) .catch(error => { @@ -26,7 +32,7 @@ module.exports = { }); }); }, - getClaim (uri) { + getClaim(uri) { logger.debug(`lbryApi >> Getting Claim for "${uri}"`); const gaStartTime = Date.now(); return new Promise((resolve, reject) => { @@ -47,7 +53,7 @@ module.exports = { }); }); }, - async abandonClaim ({claimId}) { + async abandonClaim({ claimId }) { logger.debug(`lbryApi >> Abandon claim "${claimId}"`); const gaStartTime = Date.now(); try { @@ -62,7 +68,7 @@ module.exports = { return error; } }, - getClaimList (claimName) { + getClaimList(claimName) { logger.debug(`lbryApi >> Getting claim_list for "${claimName}"`); const gaStartTime = Date.now(); return new Promise((resolve, reject) => { @@ -80,7 +86,7 @@ module.exports = { }); }); }, - resolveUri (uri) { + resolveUri(uri) { logger.debug(`lbryApi >> Resolving URI for "${uri}"`); const gaStartTime = Date.now(); return new Promise((resolve, reject) => { @@ -97,9 +103,11 @@ module.exports = { db.Claim.findOne({ where: { claimId: uri.split('#')[1] } }) .then(() => reject('This claim has not yet been confirmed on the LBRY blockchain')) .catch(() => reject(`Claim ${uri} does not exist`)); - } else if (data.result[uri].error) { // check for errors + } else if (data.result[uri].error) { + // check for errors reject(data.result[uri].error); - } else { // if no errors, resolve + } else { + // if no errors, resolve resolve(data.result[uri]); } }) @@ -108,7 +116,7 @@ module.exports = { }); }); }, - getDownloadDirectory () { + getDownloadDirectory() { logger.debug('lbryApi >> Retrieving the download directory path from lbry daemon...'); const gaStartTime = Date.now(); return new Promise((resolve, reject) => { @@ -117,11 +125,19 @@ module.exports = { method: 'settings_get', }) .then(({ data }) => { - sendGATimingEvent('lbrynet', 'getDownloadDirectory', 'SETTINGS_GET', gaStartTime, Date.now()); + sendGATimingEvent( + 'lbrynet', + 'getDownloadDirectory', + 'SETTINGS_GET', + gaStartTime, + Date.now() + ); if (data.result) { resolve(data.result.download_directory); } else { - return new Error('Successfully connected to lbry daemon, but unable to retrieve the download directory.'); + return new Error( + 'Successfully connected to lbry daemon, but unable to retrieve the download directory.' + ); } }) .catch(error => { @@ -130,7 +146,7 @@ module.exports = { }); }); }, - createChannel (name) { + createChannel(name) { logger.debug(`lbryApi >> Creating channel for ${name}...`); const gaStartTime = Date.now(); return new Promise((resolve, reject) => { @@ -139,7 +155,7 @@ module.exports = { method: 'channel_new', params: { channel_name: name, - amount : publishing.channelClaimBidAmount, + amount: publishing.channelClaimBidAmount, }, }) .then(response => { @@ -151,15 +167,21 @@ module.exports = { }); }); }, - getWalletBalance () { + getAccountBalance() { const gaStartTime = Date.now(); return new Promise((resolve, reject) => { axios .post(lbrynetUri, { - method: 'wallet_balance', + method: 'account_balance', }) .then(response => { - sendGATimingEvent('lbrynet', 'getWalletBalance', 'SETTINGS_GET', gaStartTime, Date.now()); + sendGATimingEvent( + 'lbrynet', + 'getAccountBalance', + 'SETTINGS_GET', + gaStartTime, + Date.now() + ); handleLbrynetResponse(response, resolve, reject); }) .catch(error => { diff --git a/utils/validateFileForPublish.js b/utils/validateFileForPublish.js deleted file mode 100644 index ef129305..00000000 --- a/utils/validateFileForPublish.js +++ /dev/null @@ -1,34 +0,0 @@ -import { publishing } from '@config/siteConfig.json'; - -const { fileSizeLimits } = publishing; - -const SIZE_MB = 1000000; - -export default function validateFileForPublish(file) { - let contentType = file.type; - let mediaType = contentType ? contentType.substr(0, contentType.indexOf('/')) : ''; - let mediaTypeLimit = fileSizeLimits[mediaType] || false; - let customLimits = fileSizeLimits['customByContentType']; - - if (!file) { - throw new Error('no file provided'); - } - - if (/'/.test(file.name)) { - throw new Error('apostrophes are not allowed in the file name'); - } - - if (Object.keys(customLimits).includes(contentType)) { - if (file.size > customLimits[contentType]) { - throw new Error( - `Sorry, type ${contentType} is limited to ${customLimits[contentType] / SIZE_MB} MB.` - ); - } - } - if (mediaTypeLimit) { - if (file.size > mediaTypeLimit) { - throw new Error(`Sorry, type ${mediaType} is limited to ${mediaTypeLimit / SIZE_MB} MB.`); - } - } - return file; -}