diff --git a/client/src/actions/show.js b/client/src/actions/show.js index b4ed7719..b5d6d5c0 100644 --- a/client/src/actions/show.js +++ b/client/src/actions/show.js @@ -12,6 +12,16 @@ export function onHandleShowPageUri (params, url) { }; } +export function onHandleShowHomepage (params, url) { + return { + type: actions.HANDLE_SHOW_HOMEPAGE, + data: { + ...params, + url, + } + }; +} + export function onRequestError (error) { return { type: actions.REQUEST_ERROR, diff --git a/client/src/api/homepageApi.js b/client/src/api/homepageApi.js new file mode 100644 index 00000000..58d37870 --- /dev/null +++ b/client/src/api/homepageApi.js @@ -0,0 +1,6 @@ +import Request from '../utils/request'; + +export function getHomepageChannelsData (host, name, id) { + const url = `${host}/api/homepage/data/channels`; + return Request(url); +} diff --git a/client/src/constants/show_action_types.js b/client/src/constants/show_action_types.js index 944b60a6..8bb2eca4 100644 --- a/client/src/constants/show_action_types.js +++ b/client/src/constants/show_action_types.js @@ -1,5 +1,6 @@ // request actions export const HANDLE_SHOW_URI = 'HANDLE_SHOW_URI'; +export const HANDLE_SHOW_HOMEPAGE = 'HANDLE_SHOW_HOMEPAGE'; export const REQUEST_ERROR = 'REQUEST_ERROR'; export const REQUEST_UPDATE = 'REQUEST_UPDATE'; export const ASSET_REQUEST_NEW = 'ASSET_REQUEST_NEW'; diff --git a/client/src/pages/HomePage/index.jsx b/client/src/pages/HomePage/index.jsx index f8357964..eed28610 100644 --- a/client/src/pages/HomePage/index.jsx +++ b/client/src/pages/HomePage/index.jsx @@ -1,5 +1,5 @@ import { connect } from 'react-redux'; -import { onHandleShowPageUri } from '../../actions/show'; +import { onHandleShowHomepage } from '../../actions/show'; import View from './view'; const mapStateToProps = ({ show }) => { @@ -10,7 +10,7 @@ const mapStateToProps = ({ show }) => { }; const mapDispatchToProps = { - onHandleShowPageUri, + onHandleShowHomepage, }; export default connect(mapStateToProps, mapDispatchToProps)(View); diff --git a/client/src/pages/HomePage/view.jsx b/client/src/pages/HomePage/view.jsx index 8ca1e065..91490fae 100644 --- a/client/src/pages/HomePage/view.jsx +++ b/client/src/pages/HomePage/view.jsx @@ -4,6 +4,16 @@ import PageLayout from '@components/PageLayout'; import PublishTool from '@containers/PublishTool'; class HomePage extends React.Component { + componentDidMount () { + this.props.onHandleShowHomepage(this.props.match.params); + } + + componentWillReceiveProps (nextProps) { + if (nextProps.match.params !== this.props.match.params) { + this.props.onHandleShowHomepage(nextProps.match.params); + } + } + render () { return ( sequelize.define( 'abnormal_claim', { @@ -19,7 +24,7 @@ var AbnormalClaimModel = (sequelize, { set() { }, }, is_update: { - type: INTEGER, + type: BOOLEAN, set() { }, }, block_hash: { @@ -47,11 +52,11 @@ var AbnormalClaimModel = (sequelize, { set() { }, }, created_at: { - type: INTEGER, + type: DATE(6), set() { }, }, modified_at: { - type: INTEGER, + type: DATE(6), set() { }, }, }, @@ -73,7 +78,12 @@ var abnormalClaimTable = { }; var AddressModel = (sequelize, { - STRING, BOOLEAN, INTEGER, TEXT, DECIMAL + BOOLEAN, + DATE, + DECIMAL, + INTEGER, + STRING, + TEXT, }) => sequelize.define( 'address', { @@ -87,15 +97,15 @@ var AddressModel = (sequelize, { set() { }, }, first_seen: { - type: INTEGER, + type: DATE(6), set() { }, }, created_at: { - type: INTEGER, + type: DATE(6), set() { }, }, modified_at: { - type: INTEGER, + type: DATE(6), set() { }, }, }, @@ -117,7 +127,12 @@ var addressTable = { }; var BlockModel = (sequelize, { - STRING, BOOLEAN, INTEGER, TEXT, DECIMAL + BOOLEAN, + DATE, + DECIMAL, + INTEGER, + STRING, + TEXT, }) => sequelize.define( 'block', { @@ -195,11 +210,11 @@ var BlockModel = (sequelize, { set() { }, }, created_at: { - type: INTEGER, + type: DATE(6), set() { }, }, modified_at: { - type: INTEGER, + type: DATE(6), set() { }, }, }, @@ -257,7 +272,12 @@ const getterMethods$3 = { }; var ClaimModel = (sequelize, { - STRING, BOOLEAN, INTEGER, TEXT, DECIMAL + BOOLEAN, + DATE, + DECIMAL, + INTEGER, + STRING, + TEXT, }) => sequelize.define( 'claim', { @@ -310,14 +330,6 @@ var ClaimModel = (sequelize, { type: STRING, set() { }, }, - value_as_hex: { - type: STRING, - set() { }, - }, - value_as_json: { - type: STRING, - set() { }, - }, valid_at_height: { type: INTEGER, set() { }, @@ -343,7 +355,7 @@ var ClaimModel = (sequelize, { set() { }, }, is_nsfw: { - type: INTEGER, + type: BOOLEAN, set() { }, }, language: { @@ -367,7 +379,7 @@ var ClaimModel = (sequelize, { set() { }, }, is_filtered: { - type: INTEGER, + type: BOOLEAN, set() { }, }, bid_state: { @@ -375,11 +387,11 @@ var ClaimModel = (sequelize, { set() { }, }, created_at: { - type: INTEGER, + type: DATE(6), set() { }, }, modified_at: { - type: INTEGER, + type: DATE(6), set() { }, }, fee_address: { @@ -409,7 +421,12 @@ var claimTable = { }; var InputModel = (sequelize, { - STRING, BOOLEAN, INTEGER, TEXT, DECIMAL + BOOLEAN, + DATE, + DECIMAL, + INTEGER, + STRING, + TEXT, }) => sequelize.define( 'input', { @@ -431,7 +448,7 @@ var InputModel = (sequelize, { set() { }, }, is_coinbase: { - type: INTEGER, + type: BOOLEAN, set() { }, }, coinbase: { @@ -443,7 +460,7 @@ var InputModel = (sequelize, { set() { }, }, prevout_n: { - type: INTEGER, + type: INTEGER.UNSIGNED, set() { }, }, prevout_spend_updated: { @@ -467,11 +484,11 @@ var InputModel = (sequelize, { set() { }, }, created: { - type: INTEGER, + type: DATE(6), set() { }, }, modified: { - type: INTEGER, + type: DATE(6), set() { }, }, }, @@ -493,7 +510,12 @@ var inputTable = { }; var OutputModel = (sequelize, { - STRING, BOOLEAN, INTEGER, TEXT, DECIMAL + BOOLEAN, + DATE, + DECIMAL, + INTEGER, + STRING, + TEXT, }) => sequelize.define( 'output', { @@ -539,7 +561,7 @@ var OutputModel = (sequelize, { set() { }, }, is_spent: { - type: INTEGER, + type: BOOLEAN, set() { }, }, spent_by_input_id: { @@ -547,11 +569,11 @@ var OutputModel = (sequelize, { set() { }, }, created_at: { - type: INTEGER, + type: DATE(6), set() { }, }, modified_at: { - type: INTEGER, + type: DATE(6), set() { }, }, claim_id: { @@ -577,7 +599,12 @@ var outputTable = { }; var SupportModel = (sequelize, { - STRING, BOOLEAN, INTEGER, TEXT, DECIMAL + BOOLEAN, + DATE, + DECIMAL, + INTEGER, + STRING, + TEXT, }) => sequelize.define( 'support', { @@ -607,11 +634,11 @@ var SupportModel = (sequelize, { set() { }, }, created_at: { - type: INTEGER, + type: DATE(6), set() { }, }, modified_at: { - type: INTEGER, + type: DATE(6), set() { }, }, }, @@ -633,7 +660,12 @@ var supportTable = { }; var TransactionAddressModel = (sequelize, { - STRING, BOOLEAN, INTEGER, TEXT, DECIMAL + BOOLEAN, + DATE, + DECIMAL, + INTEGER, + STRING, + TEXT, }) => sequelize.define( 'transaction_address', { @@ -674,7 +706,12 @@ var transactionAddressTable = { }; var TransactionModel = (sequelize, { - STRING, BOOLEAN, INTEGER, TEXT, DECIMAL + BOOLEAN, + DATE, + DECIMAL, + INTEGER, + STRING, + TEXT, }) => sequelize.define( 'transaction', { @@ -716,7 +753,7 @@ var TransactionModel = (sequelize, { set() { }, }, lock_time: { - type: INTEGER, + type: DATE(6), set() { }, }, raw: { @@ -724,15 +761,15 @@ var TransactionModel = (sequelize, { set() { }, }, created_at: { - type: INTEGER, + type: DATE(6), set() { }, }, modified_at: { - type: INTEGER, + type: DATE(6), set() { }, }, created_time: { - type: INTEGER, + type: DATE(6), set() {}, }, }, @@ -820,7 +857,7 @@ var claimQueries = (db, table) => ({ return await table.findAll({ where: { publisher_id: channelClaimId }, order: [['height', 'DESC']], - raw : true, // returns an array of only data, not an array of instances + raw : false, // returns an array of only data, not an array of instances }) .then(channelClaimsArray => { if(channelClaimsArray.length === 0) { diff --git a/server/chainquery/bundle.js b/server/chainquery/bundle.js index b8fc6b07..52802d7f 100644 --- a/server/chainquery/bundle.js +++ b/server/chainquery/bundle.js @@ -1,7 +1,12 @@ 'use strict'; var AbnormalClaimModel = (sequelize, { - STRING, BOOLEAN, INTEGER, TEXT, DECIMAL + BOOLEAN, + DATE, + DECIMAL, + INTEGER, + STRING, + TEXT, }) => sequelize.define( 'abnormal_claim', { @@ -19,7 +24,7 @@ var AbnormalClaimModel = (sequelize, { set() { }, }, is_update: { - type: INTEGER, + type: BOOLEAN, set() { }, }, block_hash: { @@ -47,11 +52,11 @@ var AbnormalClaimModel = (sequelize, { set() { }, }, created_at: { - type: INTEGER, + type: DATE(6), set() { }, }, modified_at: { - type: INTEGER, + type: DATE(6), set() { }, }, }, @@ -73,7 +78,12 @@ var abnormalClaimTable = { }; var AddressModel = (sequelize, { - STRING, BOOLEAN, INTEGER, TEXT, DECIMAL + BOOLEAN, + DATE, + DECIMAL, + INTEGER, + STRING, + TEXT, }) => sequelize.define( 'address', { @@ -87,15 +97,15 @@ var AddressModel = (sequelize, { set() { }, }, first_seen: { - type: INTEGER, + type: DATE(6), set() { }, }, created_at: { - type: INTEGER, + type: DATE(6), set() { }, }, modified_at: { - type: INTEGER, + type: DATE(6), set() { }, }, }, @@ -117,7 +127,12 @@ var addressTable = { }; var BlockModel = (sequelize, { - STRING, BOOLEAN, INTEGER, TEXT, DECIMAL + BOOLEAN, + DATE, + DECIMAL, + INTEGER, + STRING, + TEXT, }) => sequelize.define( 'block', { @@ -195,11 +210,11 @@ var BlockModel = (sequelize, { set() { }, }, created_at: { - type: INTEGER, + type: DATE(6), set() { }, }, modified_at: { - type: INTEGER, + type: DATE(6), set() { }, }, }, @@ -257,7 +272,12 @@ const getterMethods$3 = { }; var ClaimModel = (sequelize, { - STRING, BOOLEAN, INTEGER, TEXT, DECIMAL + BOOLEAN, + DATE, + DECIMAL, + INTEGER, + STRING, + TEXT, }) => sequelize.define( 'claim', { @@ -310,14 +330,6 @@ var ClaimModel = (sequelize, { type: STRING, set() { }, }, - value_as_hex: { - type: STRING, - set() { }, - }, - value_as_json: { - type: STRING, - set() { }, - }, valid_at_height: { type: INTEGER, set() { }, @@ -343,7 +355,7 @@ var ClaimModel = (sequelize, { set() { }, }, is_nsfw: { - type: INTEGER, + type: BOOLEAN, set() { }, }, language: { @@ -367,7 +379,7 @@ var ClaimModel = (sequelize, { set() { }, }, is_filtered: { - type: INTEGER, + type: BOOLEAN, set() { }, }, bid_state: { @@ -375,11 +387,11 @@ var ClaimModel = (sequelize, { set() { }, }, created_at: { - type: INTEGER, + type: DATE(6), set() { }, }, modified_at: { - type: INTEGER, + type: DATE(6), set() { }, }, fee_address: { @@ -409,7 +421,12 @@ var claimTable = { }; var InputModel = (sequelize, { - STRING, BOOLEAN, INTEGER, TEXT, DECIMAL + BOOLEAN, + DATE, + DECIMAL, + INTEGER, + STRING, + TEXT, }) => sequelize.define( 'input', { @@ -431,7 +448,7 @@ var InputModel = (sequelize, { set() { }, }, is_coinbase: { - type: INTEGER, + type: BOOLEAN, set() { }, }, coinbase: { @@ -443,7 +460,7 @@ var InputModel = (sequelize, { set() { }, }, prevout_n: { - type: INTEGER, + type: INTEGER.UNSIGNED, set() { }, }, prevout_spend_updated: { @@ -467,11 +484,11 @@ var InputModel = (sequelize, { set() { }, }, created: { - type: INTEGER, + type: DATE(6), set() { }, }, modified: { - type: INTEGER, + type: DATE(6), set() { }, }, }, @@ -493,7 +510,12 @@ var inputTable = { }; var OutputModel = (sequelize, { - STRING, BOOLEAN, INTEGER, TEXT, DECIMAL + BOOLEAN, + DATE, + DECIMAL, + INTEGER, + STRING, + TEXT, }) => sequelize.define( 'output', { @@ -539,7 +561,7 @@ var OutputModel = (sequelize, { set() { }, }, is_spent: { - type: INTEGER, + type: BOOLEAN, set() { }, }, spent_by_input_id: { @@ -547,11 +569,11 @@ var OutputModel = (sequelize, { set() { }, }, created_at: { - type: INTEGER, + type: DATE(6), set() { }, }, modified_at: { - type: INTEGER, + type: DATE(6), set() { }, }, claim_id: { @@ -577,7 +599,12 @@ var outputTable = { }; var SupportModel = (sequelize, { - STRING, BOOLEAN, INTEGER, TEXT, DECIMAL + BOOLEAN, + DATE, + DECIMAL, + INTEGER, + STRING, + TEXT, }) => sequelize.define( 'support', { @@ -607,11 +634,11 @@ var SupportModel = (sequelize, { set() { }, }, created_at: { - type: INTEGER, + type: DATE(6), set() { }, }, modified_at: { - type: INTEGER, + type: DATE(6), set() { }, }, }, @@ -633,7 +660,12 @@ var supportTable = { }; var TransactionAddressModel = (sequelize, { - STRING, BOOLEAN, INTEGER, TEXT, DECIMAL + BOOLEAN, + DATE, + DECIMAL, + INTEGER, + STRING, + TEXT, }) => sequelize.define( 'transaction_address', { @@ -674,7 +706,12 @@ var transactionAddressTable = { }; var TransactionModel = (sequelize, { - STRING, BOOLEAN, INTEGER, TEXT, DECIMAL + BOOLEAN, + DATE, + DECIMAL, + INTEGER, + STRING, + TEXT, }) => sequelize.define( 'transaction', { @@ -716,7 +753,7 @@ var TransactionModel = (sequelize, { set() { }, }, lock_time: { - type: INTEGER, + type: DATE(6), set() { }, }, raw: { @@ -724,15 +761,15 @@ var TransactionModel = (sequelize, { set() { }, }, created_at: { - type: INTEGER, + type: DATE(6), set() { }, }, modified_at: { - type: INTEGER, + type: DATE(6), set() { }, }, created_time: { - type: INTEGER, + type: DATE(6), set() {}, }, }, @@ -799,7 +836,7 @@ const isShortClaimId = (claimId) => { return (claimId && (claimId.length < 40)); }; -var claimQueries = (db, table) => ({ +var claimQueries = (db, table, sequelize) => ({ getShortClaimIdFromLongClaimId: async (claimId, claimName) => { logger$1.debug(`claim.getShortClaimIdFromLongClaimId for ${claimName}#${claimId}`); @@ -820,7 +857,6 @@ var claimQueries = (db, table) => ({ return await table.findAll({ where: { publisher_id: channelClaimId }, order: [['height', 'DESC']], - raw : true, // returns an array of only data, not an array of instances }) .then(channelClaimsArray => { if(channelClaimsArray.length === 0) { @@ -1025,7 +1061,7 @@ if (!database || !username || !password) { } // set sequelize options -const sequelize$1 = new Sequelize(database, username, password, { +const sequelize = new Sequelize(database, username, password, { host : host$1, import : port, dialect : 'mysql', @@ -1049,8 +1085,8 @@ for(let i = 0; i < DATABASE_STRUCTURE_KEYS.length; i++) { let dbKey = DATABASE_STRUCTURE_KEYS[i]; let currentData = DATABASE_STRUCTURE[dbKey]; - db[dbKey] = currentData.table.createModel(sequelize$1, Sequelize); - db[dbKey].queries = currentData.queries(db, db[dbKey]); + db[dbKey] = currentData.table.createModel(sequelize, Sequelize); + db[dbKey].queries = currentData.queries(db, db[dbKey], sequelize); } // run model.association for each model in the db object that has an association @@ -1063,7 +1099,7 @@ DATABASE_STRUCTURE_KEYS.forEach(modelName => { }); // establish mysql connection -sequelize$1 +sequelize .authenticate() .then(() => { logger$2.info('Sequelize has established mysql connection for chainquery successfully.'); diff --git a/server/chainquery/index.js b/server/chainquery/index.js index e0c56e5c..fd1c2a81 100644 --- a/server/chainquery/index.js +++ b/server/chainquery/index.js @@ -98,7 +98,7 @@ for(let i = 0; i < DATABASE_STRUCTURE_KEYS.length; i++) { let currentData = DATABASE_STRUCTURE[dbKey]; db[dbKey] = currentData.table.createModel(sequelize, Sequelize); - db[dbKey].queries = currentData.queries(db, db[dbKey]); + db[dbKey].queries = currentData.queries(db, db[dbKey], sequelize); } // run model.association for each model in the db object that has an association diff --git a/server/chainquery/models/ClaimModel.js b/server/chainquery/models/ClaimModel.js index 8f1fbedf..f6a31a22 100644 --- a/server/chainquery/models/ClaimModel.js +++ b/server/chainquery/models/ClaimModel.js @@ -93,14 +93,6 @@ export default (sequelize, { type: STRING, set() { }, }, - value_as_hex: { - type: STRING, - set() { }, - }, - value_as_json: { - type: STRING, - set() { }, - }, valid_at_height: { type: INTEGER, set() { }, diff --git a/server/chainquery/queries/claimQueries.js b/server/chainquery/queries/claimQueries.js index 8f56f922..8972aaa3 100644 --- a/server/chainquery/queries/claimQueries.js +++ b/server/chainquery/queries/claimQueries.js @@ -32,7 +32,7 @@ const isShortClaimId = (claimId) => { return (claimId && (claimId.length < 40)); } -export default (db, table) => ({ +export default (db, table, sequelize) => ({ getShortClaimIdFromLongClaimId: async (claimId, claimName) => { logger.debug(`claim.getShortClaimIdFromLongClaimId for ${claimName}#${claimId}`); @@ -53,7 +53,6 @@ export default (db, table) => ({ return await table.findAll({ where: { publisher_id: channelClaimId }, order: [['height', 'DESC']], - raw : true, // returns an array of only data, not an array of instances }) .then(channelClaimsArray => { if(channelClaimsArray.length === 0) { diff --git a/server/controllers/api/claim/data/index.js b/server/controllers/api/claim/data/index.js index 0eeedd3d..5909abcb 100644 --- a/server/controllers/api/claim/data/index.js +++ b/server/controllers/api/claim/data/index.js @@ -13,7 +13,7 @@ const claimData = ({ ip, originalUrl, body, params }, res) => { const claimName = params.claimName; let claimId = params.claimId; if (claimId === 'none') claimId = null; - chainquery.claim.queries.resolveClaim(claimName, claimId) + chainquery.claim.queries.resolveClaim(claimName, claimId).catch(() => {}) .then(claimInfo => { if (!claimInfo) { // Not found remote, try local @@ -28,6 +28,7 @@ const claimData = ({ ip, originalUrl, body, params }, res) => { message: 'No claim could be found', }); } + res.status(200).json({ success: true, data : getClaimData(claimInfo), diff --git a/server/controllers/api/claim/get/index.js b/server/controllers/api/claim/get/index.js index fc2df8fb..4223c473 100644 --- a/server/controllers/api/claim/get/index.js +++ b/server/controllers/api/claim/get/index.js @@ -4,6 +4,7 @@ const { handleErrorResponse } = require('../../../utils/errorHandlers.js'); const getClaimData = require('server/utils/getClaimData'); const chainquery = require('chainquery'); const db = require('../../../../models'); +const waitOn = require('wait-on'); /* @@ -11,60 +12,46 @@ const db = require('../../../../models'); */ -const claimGet = ({ ip, originalUrl, params }, res) => { +const claimGet = async ({ ip, originalUrl, params }, res) => { const name = params.name; const claimId = params.claimId; - let resolveResult; - let getResult; + try { + let claimData = await chainquery.claim.queries.resolveClaim(name, claimId).catch(() => {}); + if(!claimData) { + claimData = await db.Claim.resolveClaim(name, claimId); + } + if(!claimData) { + throw new Error('No matching uri found in Claim table'); + } - chainquery.claim.queries.resolveClaim(name, claimId) - .then(result => { - if (!result) { - // could not find remote, return false to try local - return false; - } - return resolveResult = result; - }) - .then(result => { - if (result === false) { - // Could not find remote, try local - return db.Claim.resolveClaim(name, claimId); - } - return result; - }) - .then(result => { - if (!result) { - throw new Error('No matching uri found in Claim table'); - } - return resolveResult = result; - }) - .then(result => getClaim(`${name}#${claimId}`)) - .then(result => { - if (!result) { - throw new Error(`Unable to Get ${name}#${claimId}`); - } - getResult = result; - if (result.completed) { - return createFileRecordDataAfterGet(getClaimData(resolveResult), getResult) - .then(fileData => { - const upsertCriteria = {name, claimId}; - return db.upsert(db.File, fileData, upsertCriteria, 'File'); - }); - } - }) - .then(() => { - const { message, completed } = getResult; - res.status(200).json({ - success: true, - message, - completed, + let lbrynetResult = await getClaim(`${name}#${claimId}`); + if(!lbrynetResult) { + throw new Error(`Unable to Get ${name}#${claimId}`); + } + + let fileData = await createFileRecordDataAfterGet(getClaimData(claimData), lbrynetResult); + const upsertCriteria = { name, claimId }; + await db.upsert(db.File, fileData, upsertCriteria, 'File'); + + try { + await waitOn({ + resources: [ lbrynetResult.file_name ], + delay: 100, + timeout: 10000, // 10 seconds }); - }) - .catch(error => { - handleErrorResponse(originalUrl, ip, error, res); + } catch (e) {} + + const { message, completed } = lbrynetResult; + res.status(200).json({ + success: true, + message, + completed, }); + } catch(error) { + handleErrorResponse(originalUrl, ip, error, res); + } }; module.exports = claimGet; diff --git a/server/controllers/api/claim/longId/index.js b/server/controllers/api/claim/longId/index.js index 93f616af..cc197bc8 100644 --- a/server/controllers/api/claim/longId/index.js +++ b/server/controllers/api/claim/longId/index.js @@ -20,14 +20,15 @@ const claimLongId = ({ ip, originalUrl, body, params }, res) => { const channelClaimId = body.channelClaimId; const claimName = body.claimName; let claimId = body.claimId; + getClaimId(channelName, channelClaimId, claimName, claimId) .then(fullClaimId => { claimId = fullClaimId; - return chainquery.claim.queries.getOutpoint(claimName, fullClaimId); + return chainquery.claim.queries.getOutpoint(claimName, fullClaimId).catch(() => {}); }) .then(outpointResult => { if (!outpointResult) { - return db.Claim.getOutpoint(claimName, fullClaimId); + return db.Claim.getOutpoint(claimName, claimId); } return outpointResult; }) diff --git a/server/controllers/api/claim/shortId/index.js b/server/controllers/api/claim/shortId/index.js index c10e41ee..34bf6d8e 100644 --- a/server/controllers/api/claim/shortId/index.js +++ b/server/controllers/api/claim/shortId/index.js @@ -1,5 +1,6 @@ const { handleErrorResponse } = require('../../../utils/errorHandlers.js'); const db = require('../../../../models'); +const chainquery = require('chainquery'); /* @@ -7,14 +8,18 @@ const db = require('../../../../models'); */ -const claimShortId = ({ ip, originalUrl, body, params }, res) => { - db.Claim.getShortClaimIdFromLongClaimId(params.longId, params.name) - .then(shortId => { - res.status(200).json({success: true, data: shortId}); - }) - .catch(error => { - handleErrorResponse(originalUrl, ip, error, res); - }); +const claimShortId = async ({ ip, originalUrl, body, params }, res) => { + try { + let shortId = await chainquery.claim.queries.getShortClaimIdFromLongClaimId(params.longId, params.name); + + if(shortId === null) { + shortId = await db.Claim.getShortClaimIdFromLongClaimId(params.longId, params.name); + } + + res.status(200).json({success: true, data: shortId}); + } catch(error) { + handleErrorResponse(originalUrl, ip, error, res); + } }; module.exports = claimShortId; diff --git a/server/controllers/api/homepage/data/getChannelData.js b/server/controllers/api/homepage/data/getChannelData.js new file mode 100644 index 00000000..a0db2374 --- /dev/null +++ b/server/controllers/api/homepage/data/getChannelData.js @@ -0,0 +1,28 @@ +const db = require('../../../../models'); + +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(fullClaimId => { + longChannelClaimId = fullClaimId; + return db + .Certificate + .getShortChannelIdFromLongChannelId(fullClaimId, channelName); + }) + .then(shortChannelClaimId => { + resolve({ + channelName, + longChannelClaimId, + shortChannelClaimId, + }); + }) + .catch(error => { + reject(error); + }); + }); +}; + +module.exports = getChannelData; diff --git a/server/controllers/api/homepage/data/index.js b/server/controllers/api/homepage/data/index.js new file mode 100644 index 00000000..610f1cb5 --- /dev/null +++ b/server/controllers/api/homepage/data/index.js @@ -0,0 +1,35 @@ +const { handleErrorResponse } = require('../../../utils/errorHandlers.js'); + +const getChannelData = require('./getChannelData.js'); + +const NO_CHANNEL = 'NO_CHANNEL'; + +/* + + route to get data for a channel + +*/ + +const channelData = ({ ip, originalUrl, body, params }, res) => { + const channelName = params.channelName; + let channelClaimId = params.channelClaimId; + if (channelClaimId === 'none') channelClaimId = null; + getChannelData(channelName, channelClaimId) + .then(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); + }); +}; + +module.exports = channelData; diff --git a/server/controllers/assets/utils/getClaimIdAndServeAsset.js b/server/controllers/assets/utils/getClaimIdAndServeAsset.js index 00bf9532..636ed6b3 100644 --- a/server/controllers/assets/utils/getClaimIdAndServeAsset.js +++ b/server/controllers/assets/utils/getClaimIdAndServeAsset.js @@ -1,6 +1,7 @@ const logger = require('winston'); const db = require('../../../models'); +const chainquery = require('chainquery'); const getClaimId = require('../../utils/getClaimId.js'); const { handleErrorResponse } = require('../../utils/errorHandlers.js'); @@ -16,8 +17,13 @@ const getClaimIdAndServeAsset = (channelName, channelClaimId, claimName, claimId getClaimId(channelName, channelClaimId, claimName, claimId) .then(fullClaimId => { claimId = fullClaimId; - logger.debug('Full claim id:', fullClaimId); - return db.Claim.getOutpoint(claimName, fullClaimId); + return chainquery.claim.queries.getOutpoint(claimName, fullClaimId).catch(() => {}); + }) + .then(outpointResult => { + if (!outpointResult) { + return db.Claim.getOutpoint(claimName, claimId); + } + return outpointResult; }) .then(outpoint => { logger.debug('Outpoint:', outpoint); diff --git a/server/controllers/utils/getClaimId.js b/server/controllers/utils/getClaimId.js index 7feaa8c4..da771bd1 100644 --- a/server/controllers/utils/getClaimId.js +++ b/server/controllers/utils/getClaimId.js @@ -1,22 +1,38 @@ const logger = require('winston'); const db = require('../../models'); +const chainquery = require('chainquery'); -const getClaimIdByChannel = (channelName, channelClaimId, claimName) => { +const getClaimIdByChannel = async (channelName, channelClaimId, claimName) => { logger.debug(`getClaimIdByChannel(${channelName}, ${channelClaimId}, ${claimName})`); - return db.Certificate - .getLongChannelId(channelName, channelClaimId) - .then(longChannelId => { - return db.Claim.getClaimIdByLongChannelId(longChannelId, claimName); - }); + + let channelId = await chainquery.claim.queries.getLongClaimIdFromShortClaimId(channelName, channelClaimId); + + if(channelId === null) { + channelId = await db.Certificate.getLongChannelId(channelName, channelClaimId); + } + + let claimId = await chainquery.claim.queries.getClaimIdByLongChannelId(longChannelId, claimName); + + if(claimId === null) { + claimId = db.Claim.getClaimIdByLongChannelId(longChannelId, claimName); + } + + return claimId; }; -const getClaimId = (channelName, channelClaimId, name, claimId) => { +const getClaimId = async (channelName, channelClaimId, name, claimId) => { logger.debug(`getClaimId: ${channelName}, ${channelClaimId}, ${name}, ${claimId})`); if (channelName) { - return getClaimIdByChannel(channelName, channelClaimId, name); + return await getClaimIdByChannel(channelName, channelClaimId, name); } else { - return db.Claim.getLongClaimId(name, claimId); + let claimIdResult = await chainquery.claim.queries.getLongClaimId(name, claimId); + + if(claimIdResult === null) { + claimIdResult = await db.Claim.getLongClaimId(name, claimId); + } + + return claimIdResult; } }; diff --git a/server/index.js b/server/index.js index 097fd9ce..6b140d28 100644 --- a/server/index.js +++ b/server/index.js @@ -27,6 +27,25 @@ const { }, } = require('@config/siteConfig'); +function logMetricsMiddleware(req, res, next) { + res.on('finish', () => { + const userAgent = req.get('user-agent'); + + db.RequestMetrics.create({ + isInternal: /node\-fetch/.test(userAgent), + routePath: httpContext.get('routePath'), + params: JSON.stringify(req.params), + ip: req.headers['x-forwarded-for'] || req.connection.remoteAddress, + request: req.url, + routeData: JSON.stringify(httpContext.get('routeData')), + referrer: req.get('referrer'), + userAgent, + }); + }); + + next(); +} + function setRouteDataInContextMiddleware(routePath, routeData) { return function (req, res, next) { httpContext.set('routePath', routePath); @@ -97,7 +116,12 @@ function Server () { let routeMethod = routeData.hasOwnProperty('method') ? routeData.method : 'get'; let controllers = Array.isArray(routeData.controller) ? routeData.controller : [routeData.controller]; - app[routeMethod](routePath, setRouteDataInContextMiddleware(routePath, routeData), ...controllers); + app[routeMethod]( + routePath, + logMetricsMiddleware, + setRouteDataInContextMiddleware(routePath, routeData), + ...controllers, + ); }); this.app = app; diff --git a/server/models/index.js b/server/models/index.js index 44da2e83..54461da6 100644 --- a/server/models/index.js +++ b/server/models/index.js @@ -1,13 +1,14 @@ const Sequelize = require('sequelize'); const logger = require('winston'); -const Certificate = require('./certificate.js'); -const Channel = require('./channel.js'); -const Claim = require('./claim.js'); -const File = require('./file.js'); -const User = require('./user.js'); -const Blocked = require('./blocked.js'); -const Tor = require('./tor.js'); +const Blocked = require('./blocked'); +const Certificate = require('./certificate'); +const Channel = require('./channel'); +const Claim = require('./claim'); +const File = require('./file'); +const Metrics = require('./metrics'); +const Tor = require('./tor'); +const User = require('./user'); const { database, @@ -48,13 +49,14 @@ sequelize // manually add each model to the db object (note: make this dynamic) const db = {}; +db['Blocked'] = sequelize.import('Blocked', Blocked); db['Certificate'] = sequelize.import('Certificate', Certificate); db['Channel'] = sequelize.import('Channel', Channel); db['Claim'] = sequelize.import('Claim', Claim); db['File'] = sequelize.import('File', File); -db['User'] = sequelize.import('User', User); -db['Blocked'] = sequelize.import('Blocked', Blocked); +db['Metrics'] = sequelize.import('Metrics', Metrics); db['Tor'] = sequelize.import('Tor', Tor); +db['User'] = sequelize.import('User', User); // run model.association for each model in the db object that has an association logger.info('associating db models...'); diff --git a/server/models/metrics.js b/server/models/metrics.js new file mode 100644 index 00000000..766f2525 --- /dev/null +++ b/server/models/metrics.js @@ -0,0 +1,53 @@ +module.exports = (sequelize, { BOOLEAN, DATE, STRING }) => { + const RequestMetrics = sequelize.define( + 'RequestMetrics', + { + time: { + type: DATE(6), + defaultValue: sequelize.NOW, + }, + isInternal: { + type: BOOLEAN, + }, + claimId: { + type: STRING, + defaultValue: null, + }, + ip: { + type: STRING, + defaultValue: null, + }, + request: { + type: STRING, + defaultValue: null, + }, + userAgent: { + type: STRING, + defaultValue: null, + }, + referrer: { + type: STRING, + defaultValue: null, + }, + routePath: { + type: STRING, + defaultValue: null, + }, + params: { + type: STRING, + defaultValue: null, + } + }, + { + freezeTableName: true, + timestamps: false, // don't use default timestamps columns + indexes: [ + { + fields: ['isInternal', 'isChannel', 'time', 'claimId', 'routePath'], + }, + ], + } + ); + + return RequestMetrics; +}; diff --git a/server/routes/api/index.js b/server/routes/api/index.js index f4220179..3866f5d6 100644 --- a/server/routes/api/index.js +++ b/server/routes/api/index.js @@ -22,10 +22,14 @@ const getBlockedList = require('../../controllers/api/blocked'); const getOEmbedData = require('../../controllers/api/oEmbed'); module.exports = { + // homepage routes + '/api/homepage/data/channels': { controller: [ torCheckMiddleware, channelData ] }, + // channel routes '/api/channel/availability/:name': { controller: [ torCheckMiddleware, channelAvailability ] }, '/api/channel/short-id/:longId/:name': { controller: [ torCheckMiddleware, channelShortId ] }, '/api/channel/data/:channelName/:channelClaimId': { controller: [ torCheckMiddleware, channelData ] }, + '/api/channel/data/:channelName/:channelClaimId': { controller: [ torCheckMiddleware, channelData ] }, '/api/channel/claims/:channelName/:channelClaimId/:page': { controller: [ torCheckMiddleware, channelClaims ] }, // claim routes '/api/claim/availability/:name': { controller: [ torCheckMiddleware, claimAvailability ] }, diff --git a/server/routes/index.js b/server/routes/index.js index 73756955..71223948 100644 --- a/server/routes/index.js +++ b/server/routes/index.js @@ -1,7 +1,7 @@ module.exports = { ...require('./pages'), ...require('./api'), - ...require('./assets'), ...require('./auth'), + ...require('./assets'), ...require('./fallback'), }; diff --git a/server/routes/pages/index.js b/server/routes/pages/index.js index 0d097ddf..da05cc64 100644 --- a/server/routes/pages/index.js +++ b/server/routes/pages/index.js @@ -2,8 +2,12 @@ const handlePageRequest = require('../../controllers/pages/sendReactApp'); const handleVideoEmbedRequest = require('../../controllers/pages/sendVideoEmbedPage'); const redirect = require('../../controllers/utils/redirect'); +// TODO: Adjust build & sources to use import/export everywhere +const Actions = require('@actions').default; +const Sagas = require('@sagas').default; + module.exports = { - '/': { controller: handlePageRequest }, + '/': { controller: handlePageRequest, action: Actions.onHandleShowHomepage, saga: Sagas.handleShowHomepage }, '/login': { controller: handlePageRequest }, '/about': { controller: handlePageRequest }, '/trending': { controller: redirect('/popular') },