spee.ch/index.js

4202 lines
390 KiB
JavaScript
Raw Normal View History

module.exports =
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "/";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 26);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports) {
module.exports = require("winston");
/***/ }),
/* 1 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
var logger = __webpack_require__(0);
module.exports = {
handleErrorResponse: function handleErrorResponse(originalUrl, ip, error, res) {
logger.error('Error on ' + originalUrl, module.exports.useObjectPropertiesIfNoKeys(error));
var _module$exports$retur = module.exports.returnErrorMessageAndStatus(error),
_module$exports$retur2 = _slicedToArray(_module$exports$retur, 2),
status = _module$exports$retur2[0],
message = _module$exports$retur2[1];
res.status(status).json(module.exports.createErrorResponsePayload(status, message));
},
returnErrorMessageAndStatus: function returnErrorMessageAndStatus(error) {
var status = void 0,
message = void 0;
// check for daemon being turned off
if (error.code === 'ECONNREFUSED') {
status = 503;
message = 'Connection refused. The daemon may not be running.';
// fallback for everything else
} else {
status = 400;
if (error.message) {
message = error.message;
} else {
message = error;
};
};
return [status, message];
},
useObjectPropertiesIfNoKeys: function useObjectPropertiesIfNoKeys(err) {
if (Object.keys(err).length === 0) {
var newErrorObject = {};
Object.getOwnPropertyNames(err).forEach(function (key) {
newErrorObject[key] = err[key];
});
return newErrorObject;
}
return err;
},
createErrorResponsePayload: function createErrorResponsePayload(status, message) {
return {
status: status,
success: false,
message: message
};
}
};
/***/ }),
/* 2 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var Certificate = __webpack_require__(44);
var Channel = __webpack_require__(45);
var Claim = __webpack_require__(46);
var File = __webpack_require__(47);
var Request = __webpack_require__(48);
var User = __webpack_require__(49);
var Sequelize = __webpack_require__(13);
var logger = __webpack_require__(0);
var _require = __webpack_require__(10),
database = _require.database,
username = _require.username,
password = _require.password;
// set sequelize options
var sequelize = new Sequelize(database, username, password, {
host: 'localhost',
dialect: 'mysql',
dialectOptions: { decimalNumbers: true },
logging: false,
pool: {
max: 5,
min: 0,
idle: 10000,
acquire: 10000
}
});
// establish mysql connection
sequelize.authenticate().then(function () {
logger.info('Sequelize has established mysql connection successfully.');
}).catch(function (err) {
logger.error('Sequelize was unable to connect to the database:', err);
});
// manually add each model to the db object (note: make this dynamic)
var db = {};
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['Request'] = sequelize.import('Request', Request);
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...');
Object.keys(db).forEach(function (modelName) {
if (db[modelName].associate) {
logger.info('Associating model:', modelName);
db[modelName].associate(db);
}
});
// add sequelize/Sequelize to db
db.sequelize = sequelize;
db.Sequelize = Sequelize;
// add an 'upsert' method to the db object
db.upsert = function (Model, values, condition, tableName) {
return Model.findOne({
where: condition
}).then(function (obj) {
if (obj) {
// update
logger.debug('updating record in db.' + tableName);
return obj.update(values);
} else {
// insert
logger.debug('creating record in db.' + tableName);
return Model.create(values);
}
}).catch(function (error) {
logger.error(tableName + '.upsert error', error);
throw error;
});
};
module.exports = db;
/***/ }),
/* 3 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
function SiteConfig() {
var _this = this;
this.analytics = {
googleId: 'default'
};
this.assetDefaults = {
description: 'An asset published on Spee.ch',
thumbnail: 'https://spee.ch/assets/img/video_thumb_default.png',
title: 'A Spee.ch Implementation'
};
this.auth = {
sessionKey: 'default'
};
this.customComponents = {};
this.customContainers = {};
this.customPages = {};
this.details = {
description: 'Welcome to my decentralized image and video sharing site.',
host: 'http://localhost:3000',
port: 3000,
title: 'My Spee.ch Site',
twitter: '@exampleTwitterHandle'
};
this.publishing = {
additionalClaimAddresses: [],
disabled: false,
disabledMessage: 'Please check back soon.',
primaryClaimAddress: 'default',
thumbnailChannel: 'default',
thumbnailChannelId: 'default',
uploadDirectory: '/home/lbry/Uploads'
};
this.routes = {};
this.update = function (config) {
if (!config) {
return console.log('No site config received.');
}
var analytics = config.analytics,
assetDefaults = config.assetDefaults,
auth = config.auth,
customComponents = config.customComponents,
customContainers = config.customContainers,
customPages = config.customPages,
details = config.details,
publishing = config.publishing,
routes = config.routes;
console.log('Configuring site details...');
_this.analytics = analytics;
_this.assetDefaults = assetDefaults;
_this.auth = auth;
_this.details = details;
_this.publishing = publishing;
_this.customComponents = customComponents;
_this.customContainers = customContainers;
_this.customPages = customPages;
_this.routes = routes;
};
};
module.exports = new SiteConfig();
/***/ }),
/* 4 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var logger = __webpack_require__(0);
var ua = __webpack_require__(54);
var _require = __webpack_require__(3),
googleId = _require.analytics.googleId,
title = _require.details.title;
function createServeEventParams(headers, ip, originalUrl) {
return {
eventCategory: 'client requests',
eventAction: 'serve request',
eventLabel: originalUrl,
ipOverride: ip,
userAgentOverride: headers['user-agent']
};
};
function createPublishTimingEventParams(category, variable, label, startTime, endTime) {
var duration = endTime - startTime;
return {
userTimingCategory: category,
userTimingVariableName: variable,
userTimingTime: duration,
userTimingLabel: label
};
};
function sendGoogleAnalyticsEvent(ip, params) {
var visitorId = ip.replace(/\./g, '-');
var visitor = ua(googleId, visitorId, { strictCidFormat: false, https: true });
visitor.event(params, function (err) {
if (err) {
logger.error('Google Analytics Event Error >>', err);
}
});
};
function sendGoogleAnalyticsTiming(visitorId, params) {
var visitor = ua(googleId, visitorId, { strictCidFormat: false, https: true });
visitor.timing(params, function (err) {
if (err) {
logger.error('Google Analytics Event Error >>', err);
}
logger.debug('Timing event successfully sent to google analytics');
});
};
module.exports = {
sendGAServeEvent: function sendGAServeEvent(headers, ip, originalUrl) {
var params = createServeEventParams(headers, ip, originalUrl);
sendGoogleAnalyticsEvent(ip, params);
},
sendGATimingEvent: function sendGATimingEvent(category, variable, label, startTime, endTime) {
var params = createPublishTimingEventParams(category, variable, label, startTime, endTime);
sendGoogleAnalyticsTiming(title, params);
},
chooseGaLbrynetPublishLabel: function chooseGaLbrynetPublishLabel(_ref) {
var channelName = _ref.channel_name,
channelId = _ref.channel_id;
return channelName || channelId ? 'PUBLISH_IN_CHANNEL_CLAIM' : 'PUBLISH_ANONYMOUS_CLAIM';
}
};
/***/ }),
/* 5 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var axios = __webpack_require__(52);
var logger = __webpack_require__(0);
var _require = __webpack_require__(53),
_require$api = _require.api,
apiHost = _require$api.apiHost,
apiPort = _require$api.apiPort;
var lbryApiUri = 'http://' + apiHost + ':' + apiPort;
var _require2 = __webpack_require__(4),
chooseGaLbrynetPublishLabel = _require2.chooseGaLbrynetPublishLabel,
sendGATimingEvent = _require2.sendGATimingEvent;
var handleLbrynetResponse = function handleLbrynetResponse(_ref, resolve, reject) {
var data = _ref.data;
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 = {
publishClaim: function publishClaim(publishParams) {
logger.debug('lbryApi >> Publishing claim to "' + publishParams.name + '"');
var gaStartTime = Date.now();
return new Promise(function (resolve, reject) {
axios.post(lbryApiUri, {
method: 'publish',
params: publishParams
}).then(function (response) {
sendGATimingEvent('lbrynet', 'publish', chooseGaLbrynetPublishLabel(publishParams), gaStartTime, Date.now());
handleLbrynetResponse(response, resolve, reject);
}).catch(function (error) {
reject(error);
});
});
},
getClaim: function getClaim(uri) {
logger.debug('lbryApi >> Getting Claim for "' + uri + '"');
var gaStartTime = Date.now();
return new Promise(function (resolve, reject) {
axios.post(lbryApiUri, {
method: 'get',
params: { uri: uri, timeout: 20 }
}).then(function (response) {
sendGATimingEvent('lbrynet', 'getClaim', 'GET', gaStartTime, Date.now());
handleLbrynetResponse(response, resolve, reject);
}).catch(function (error) {
reject(error);
});
});
},
getClaimList: function getClaimList(claimName) {
logger.debug('lbryApi >> Getting claim_list for "' + claimName + '"');
var gaStartTime = Date.now();
return new Promise(function (resolve, reject) {
axios.post(lbryApiUri, {
method: 'claim_list',
params: { name: claimName }
}).then(function (response) {
sendGATimingEvent('lbrynet', 'getClaimList', 'CLAIM_LIST', gaStartTime, Date.now());
handleLbrynetResponse(response, resolve, reject);
}).catch(function (error) {
reject(error);
});
});
},
resolveUri: function resolveUri(uri) {
logger.debug('lbryApi >> Resolving URI for "' + uri + '"');
var gaStartTime = Date.now();
return new Promise(function (resolve, reject) {
axios.post(lbryApiUri, {
method: 'resolve',
params: { uri: uri }
}).then(function (_ref2) {
var data = _ref2.data;
sendGATimingEvent('lbrynet', 'resolveUri', 'RESOLVE', gaStartTime, Date.now());
if (data.result[uri].error) {
// check for errors
reject(data.result[uri].error);
} else {
// if no errors, resolve
resolve(data.result[uri]);
}
}).catch(function (error) {
reject(error);
});
});
},
getDownloadDirectory: function getDownloadDirectory() {
logger.debug('lbryApi >> Retrieving the download directory path from lbry daemon...');
var gaStartTime = Date.now();
return new Promise(function (resolve, reject) {
axios.post(lbryApiUri, {
method: 'settings_get'
}).then(function (_ref3) {
var data = _ref3.data;
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.');
}
}).catch(function (error) {
logger.error('Lbrynet Error:', error);
resolve('/home/lbry/Downloads/');
});
});
},
createChannel: function createChannel(name) {
logger.debug('lbryApi >> Creating channel for ' + name + '...');
var gaStartTime = Date.now();
return new Promise(function (resolve, reject) {
axios.post(lbryApiUri, {
method: 'channel_new',
params: {
channel_name: name,
amount: 0.1
}
}).then(function (response) {
sendGATimingEvent('lbrynet', 'createChannel', 'CHANNEL_NEW', gaStartTime, Date.now());
handleLbrynetResponse(response, resolve, reject);
}).catch(function (error) {
reject(error);
});
});
}
};
/***/ }),
/* 6 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
var db = __webpack_require__(2);
var logger = __webpack_require__(0);
var _require = __webpack_require__(65),
returnPaginatedChannelClaims = _require.returnPaginatedChannelClaims;
var NO_CHANNEL = 'NO_CHANNEL';
var NO_CLAIM = 'NO_CLAIM';
var NO_FILE = 'NO_FILE';
module.exports = {
getClaimId: function getClaimId(channelName, channelClaimId, name, claimId) {
if (channelName) {
return module.exports.getClaimIdByChannel(channelName, channelClaimId, name);
} else {
return module.exports.getClaimIdByClaim(name, claimId);
}
},
getClaimIdByClaim: function getClaimIdByClaim(claimName, claimId) {
logger.debug('getClaimIdByClaim(' + claimName + ', ' + claimId + ')');
return new Promise(function (resolve, reject) {
db.Claim.getLongClaimId(claimName, claimId).then(function (longClaimId) {
if (!longClaimId) {
resolve(NO_CLAIM);
}
resolve(longClaimId);
}).catch(function (error) {
reject(error);
});
});
},
getClaimIdByChannel: function getClaimIdByChannel(channelName, channelClaimId, claimName) {
logger.debug('getClaimIdByChannel(' + channelName + ', ' + channelClaimId + ', ' + claimName + ')');
return new Promise(function (resolve, reject) {
db.Certificate.getLongChannelId(channelName, channelClaimId) // 1. get the long channel id
.then(function (longChannelId) {
if (!longChannelId) {
return [null, null];
}
return Promise.all([longChannelId, db.Claim.getClaimIdByLongChannelId(longChannelId, claimName)]); // 2. get the long claim id
}).then(function (_ref) {
var _ref2 = _slicedToArray(_ref, 2),
longChannelId = _ref2[0],
longClaimId = _ref2[1];
if (!longChannelId) {
return resolve(NO_CHANNEL);
}
if (!longClaimId) {
return resolve(NO_CLAIM);
}
resolve(longClaimId);
}).catch(function (error) {
reject(error);
});
});
},
getChannelData: function getChannelData(channelName, channelClaimId, page) {
return new Promise(function (resolve, reject) {
// 1. get the long channel Id (make sure channel exists)
db.Certificate.getLongChannelId(channelName, channelClaimId).then(function (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(function (_ref3) {
var _ref4 = _slicedToArray(_ref3, 2),
longChannelClaimId = _ref4[0],
shortChannelClaimId = _ref4[1];
if (!longChannelClaimId) {
return resolve(NO_CHANNEL);
}
// 3. return all the channel information
resolve({
channelName: channelName,
longChannelClaimId: longChannelClaimId,
shortChannelClaimId: shortChannelClaimId
});
}).catch(function (error) {
reject(error);
});
});
},
getChannelClaims: function getChannelClaims(channelName, channelClaimId, page) {
return new Promise(function (resolve, reject) {
// 1. get the long channel Id (make sure channel exists)
db.Certificate.getLongChannelId(channelName, channelClaimId).then(function (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(function (_ref5) {
var _ref6 = _slicedToArray(_ref5, 2),
longChannelClaimId = _ref6[0],
channelClaimsArray = _ref6[1];
if (!longChannelClaimId) {
return resolve(NO_CHANNEL);
}
// 3. format the data for the view, including pagination
var paginatedChannelViewData = returnPaginatedChannelClaims(channelName, longChannelClaimId, channelClaimsArray, page);
// 4. return all the channel information and contents
resolve(paginatedChannelViewData);
}).catch(function (error) {
reject(error);
});
});
},
getLocalFileRecord: function getLocalFileRecord(claimId, name) {
return db.File.findOne({ where: { claimId: claimId, name: name } }).then(function (file) {
if (!file) {
return NO_FILE;
}
return file.dataValues;
});
}
};
/***/ }),
/* 7 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var passport = __webpack_require__(42);
var localLoginStrategy = __webpack_require__(43);
var localSignupStrategy = __webpack_require__(51);
var _require = __webpack_require__(55),
serializeSpeechUser = _require.serializeSpeechUser,
deserializeSpeechUser = _require.deserializeSpeechUser;
passport.deserializeUser(deserializeSpeechUser);
passport.serializeUser(serializeSpeechUser);
passport.use('local-login', localLoginStrategy);
passport.use('local-signup', localSignupStrategy);
module.exports = passport;
/***/ }),
/* 8 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
var logger = __webpack_require__(0);
var db = __webpack_require__(2);
var lbryApi = __webpack_require__(5);
var publishHelpers = __webpack_require__(9);
var _require = __webpack_require__(3),
_require$publishing = _require.publishing,
primaryClaimAddress = _require$publishing.primaryClaimAddress,
additionalClaimAddresses = _require$publishing.additionalClaimAddresses;
var Sequelize = __webpack_require__(13);
var Op = Sequelize.Op;
module.exports = {
publish: function publish(publishParams, fileName, fileType) {
return new Promise(function (resolve, reject) {
var publishResults = void 0,
certificateId = void 0,
channelName = void 0;
// publish the file
return lbryApi.publishClaim(publishParams).then(function (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(function (channel) {
// set channel information
certificateId = null;
channelName = null;
if (channel) {
certificateId = channel.channelClaimId;
channelName = channel.channelName;
}
logger.debug('certificateId: ' + certificateId);
}).then(function () {
// create the File record
var 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: fileName,
filePath: publishParams.file_path,
fileType: fileType,
nsfw: publishParams.metadata.nsfw
};
// create the Claim record
var 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: certificateId,
channelName: channelName
};
// upsert criteria
var 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(function (_ref) {
var _ref2 = _slicedToArray(_ref, 2),
file = _ref2[0],
claim = _ref2[1];
logger.debug('File and Claim records successfully created');
return Promise.all([file.setClaim(claim), claim.setFile(file)]);
}).then(function () {
logger.debug('File and Claim records successfully associated');
resolve(publishResults); // resolve the promise with the result from lbryApi.publishClaim;
}).catch(function (error) {
logger.error('PUBLISH ERROR', error);
publishHelpers.deleteTemporaryFile(publishParams.file_path); // delete the local file
reject(error);
});
});
},
claimNameIsAvailable: function claimNameIsAvailable(name) {
var claimAddresses = additionalClaimAddresses || [];
claimAddresses.push(primaryClaimAddress);
// find any records where the name is used
return db.Claim.findAll({
attributes: ['address'],
where: {
name: name,
address: _defineProperty({}, Op.or, claimAddresses)
}
}).then(function (result) {
if (result.length >= 1) {
throw new Error('That claim is already in use');
};
return name;
}).catch(function (error) {
throw error;
});
},
checkChannelAvailability: function checkChannelAvailability(name) {
return db.Channel.findAll({
where: { channelName: name }
}).then(function (result) {
if (result.length >= 1) {
throw new Error('That channel has already been claimed');
}
return name;
}).catch(function (error) {
throw error;
});
}
};
/***/ }),
/* 9 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var logger = __webpack_require__(0);
var fs = __webpack_require__(63);
var _require = __webpack_require__(3),
details = _require.details,
publishing = _require.publishing;
module.exports = {
parsePublishApiRequestBody: function parsePublishApiRequestBody(_ref) {
var name = _ref.name,
nsfw = _ref.nsfw,
license = _ref.license,
title = _ref.title,
description = _ref.description,
thumbnail = _ref.thumbnail;
// validate name
if (!name) {
throw new Error('no name field found in request');
}
var 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: name,
nsfw: nsfw,
license: license,
title: title,
description: description,
thumbnail: thumbnail
};
},
parsePublishApiRequestFiles: function parsePublishApiRequestFiles(_ref2) {
var file = _ref2.file,
thumbnail = _ref2.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: function 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: function 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
var publishParams = {
name: name,
file_path: filePath,
bid: 0.01,
metadata: {
description: description,
title: title,
author: details.title,
language: 'en',
license: license,
nsfw: nsfw
},
claim_address: publishing.primaryClaimAddress
};
// add thumbnail to channel if video
if (thumbnail) {
publishParams['metadata']['thumbnail'] = thumbnail;
}
return publishParams;
},
createThumbnailPublishParams: function 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: license,
nsfw: nsfw
},
claim_address: publishing.primaryClaimAddress,
channel_name: publishing.thumbnailChannel,
channel_id: publishing.thumbnailChannelId
};
},
deleteTemporaryFile: function deleteTemporaryFile(filePath) {
fs.unlink(filePath, function (err) {
if (err) {
logger.error('error deleting temporary file ' + filePath);
throw err;
}
logger.debug('successfully deleted ' + filePath);
});
},
addGetResultsToFileData: function addGetResultsToFileData(fileInfo, getResult) {
fileInfo.fileName = getResult.file_name;
fileInfo.filePath = getResult.download_path;
return fileInfo;
},
createFileData: function createFileData(_ref3) {
var name = _ref3.name,
claimId = _ref3.claimId,
outpoint = _ref3.outpoint,
height = _ref3.height,
address = _ref3.address,
nsfw = _ref3.nsfw,
contentType = _ref3.contentType;
return {
name: name,
claimId: claimId,
outpoint: outpoint,
height: height,
address: address,
fileName: '',
filePath: '',
fileType: contentType,
nsfw: nsfw
};
}
};
/***/ }),
/* 10 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var logger = __webpack_require__(0);
function mysql() {
var _this = this;
this.database = 'default';
this.username = 'default';
this.password = 'default';
this.update = function (config) {
if (!config) {
return logger.warn('No MySQL config received.');
}
// configure credentials
logger.info('configuring mysql...');
var database = config.database,
username = config.username,
password = config.password;
_this.database = database;
_this.username = username;
_this.password = password;
};
};
module.exports = new mysql();
/***/ }),
/* 11 */
/***/ (function(module, exports) {
module.exports = require("passport-local");
/***/ }),
/* 12 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
module.exports = {
returnShortId: function returnShortId(claimsArray, longId) {
var claimIndex = void 0;
var shortId = longId.substring(0, 1); // default short id is the first letter
var shortIdLength = 0;
// find the index of this claim id
claimIndex = claimsArray.findIndex(function (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
var 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(function (element) {
return element.claimId && element.claimId.substring(0, shortIdLength) === shortId;
});
}
return shortId;
}
};
/***/ }),
/* 13 */
/***/ (function(module, exports) {
module.exports = require("sequelize");
/***/ }),
/* 14 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var _react = __webpack_require__(15);
var _react2 = _interopRequireDefault(_react);
var _server = __webpack_require__(16);
var _redux = __webpack_require__(17);
var _reactRedux = __webpack_require__(18);
var _reactRouterDom = __webpack_require__(19);
var _spee = __webpack_require__(20);
var _renderFullPage = __webpack_require__(21);
var _renderFullPage2 = _interopRequireDefault(_renderFullPage);
var _reactHelmet = __webpack_require__(22);
var _reactHelmet2 = _interopRequireDefault(_reactHelmet);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/*
^ note: to do this right, maybe
these should be passed in from the implementation (www.spee.ch) itself,
so that there are no conflicts between the SSR here and
the bundle sent to the server?
there might also be issues if this package uses a different version of spee.ch-components than www.spee.ch does?
*/
var siteConfig = __webpack_require__(3);
module.exports = function (req, res) {
var context = {};
// customize the reducer by passing in intial state configs
var MyReducers = (0, _spee.Reducers)(siteConfig);
var MyApp = (0, _spee.App)(siteConfig);
var MyGAListener = (0, _spee.GAListener)(siteConfig);
// create a new Redux store instance
var store = (0, _redux.createStore)(MyReducers);
// render component to a string
var html = (0, _server.renderToString)(_react2.default.createElement(
_reactRedux.Provider,
{ store: store },
_react2.default.createElement(
_reactRouterDom.StaticRouter,
{ location: req.url, context: context },
_react2.default.createElement(
MyGAListener,
null,
_react2.default.createElement(MyApp, null)
)
)
));
// get head tags from helmet
var helmet = _reactHelmet2.default.renderStatic();
// check for a redirect
if (context.url) {
// Somewhere a `<Redirect>` was rendered
return res.redirect(301, context.url);
} else {}
// we're good, send the response
// get the initial state from our Redux store
var preloadedState = store.getState();
// send the rendered page back to the client
res.send((0, _renderFullPage2.default)(helmet, html, preloadedState));
console.log('hello from spee.ch handlePageRender.jsx');
};
/***/ }),
/* 15 */
/***/ (function(module, exports) {
module.exports = require("react");
/***/ }),
/* 16 */
/***/ (function(module, exports) {
module.exports = require("react-dom/server");
/***/ }),
/* 17 */
/***/ (function(module, exports) {
module.exports = require("redux");
/***/ }),
/* 18 */
/***/ (function(module, exports) {
module.exports = require("react-redux");
/***/ }),
/* 19 */
/***/ (function(module, exports) {
module.exports = require("react-router-dom");
/***/ }),
/* 20 */
/***/ (function(module, exports) {
module.exports = require("spee.ch-components");
/***/ }),
/* 21 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
module.exports = function (helmet, html, preloadedState) {
// take the html and preloadedState and return the full page
return '\n <!DOCTYPE html>\n <html lang="en" prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb#">\n <head>\n <meta charset="UTF-8">\n <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1, user-scalable=no">\n <meta http-equiv="X-UA-Compatible" content="ie=edge">\n <!--helmet-->\n ' + helmet.title.toString() + '\n ' + helmet.meta.toString() + '\n ' + helmet.link.toString() + '\n <!--style sheets-->\n <link rel="stylesheet" href="/assets/css/reset.css" type="text/css">\n <link rel="stylesheet" href="/assets/css/general.css" type="text/css">\n <link rel="stylesheet" href="/assets/css/mediaQueries.css" type="text/css">\n <!--google font-->\n <link href="https://fonts.googleapis.com/css?family=Roboto:300" rel="stylesheet">\n </head>\n <body id="main-body">\n <div class="row row--tall flex-container--column">\n <div id="react-app" class="row row--tall flex-container--column">' + html + '</div>\n </div>\n <script>\n window.__PRELOADED_STATE__ = ' + JSON.stringify(preloadedState).replace(/</g, '\\<') + '\n </script>\n <script src="/bundle/bundle.js"></script>\n </body>\n </html>\n ';
};
/***/ }),
/* 22 */
/***/ (function(module, exports) {
module.exports = require("react-helmet");
/***/ }),
/* 23 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var logger = __webpack_require__(0);
var _require = __webpack_require__(6),
getClaimId = _require.getClaimId,
getLocalFileRecord = _require.getLocalFileRecord;
var _require2 = __webpack_require__(1),
handleErrorResponse = _require2.handleErrorResponse;
var SERVE = 'SERVE';
var SHOW = 'SHOW';
var NO_FILE = 'NO_FILE';
var NO_CHANNEL = 'NO_CHANNEL';
var NO_CLAIM = 'NO_CLAIM';
function clientAcceptsHtml(_ref) {
var accept = _ref.accept;
return accept && accept.match(/text\/html/);
};
function requestIsFromBrowser(headers) {
return headers['user-agent'] && headers['user-agent'].match(/Mozilla/);
};
function clientWantsAsset(_ref2) {
var accept = _ref2.accept,
range = _ref2.range;
var imageIsWanted = accept && accept.match(/image\/.*/) && !accept.match(/text\/html/) && !accept.match(/text\/\*/);
var 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(function (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
var filePath = fileRecord.filePath,
fileType = fileRecord.fileType;
logger.verbose('serving file: ' + filePath);
var sendFileOptions = {
headers: {
'X-Content-Type-Options': 'nosniff',
'Content-Type': fileType || 'image/jpeg'
}
};
res.status(200).sendFile(filePath, sendFileOptions);
}).catch(function (error) {
throw error;
});
};
module.exports = {
getClaimIdAndServeAsset: function getClaimIdAndServeAsset(channelName, channelClaimId, claimName, claimId, originalUrl, ip, res) {
// get the claim Id and then serve the asset
getClaimId(channelName, channelClaimId, claimName, claimId).then(function (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(function (error) {
handleErrorResponse(originalUrl, ip, error, res);
// postToStats(responseType, originalUrl, ip, claimName, fullClaimId, 'fail');
});
},
determineResponseType: function determineResponseType(hasFileExtension, headers) {
var responseType = void 0;
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: function flipClaimNameAndIdForBackwardsCompatibility(identifier, name) {
// this is a patch for backwards compatability with '/name/claim_id' url format
if (isValidShortIdOrClaimId(name) && !isValidShortIdOrClaimId(identifier)) {
var tempName = name;
name = identifier;
identifier = tempName;
}
return [identifier, name];
},
logRequestData: function logRequestData(responseType, claimName, channelName, claimId) {
logger.debug('responseType ===', responseType);
logger.debug('claim name === ', claimName);
logger.debug('channel name ===', channelName);
logger.debug('claim id ===', claimId);
}
};
/***/ }),
/* 24 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
var logger = __webpack_require__(0);
module.exports = {
REGEXP_INVALID_CLAIM: /[^A-Za-z0-9-]/g,
REGEXP_INVALID_CHANNEL: /[^A-Za-z0-9-@]/g,
REGEXP_ADDRESS: /^b(?=[^0OIl]{32,33})[0-9A-Za-z]{32,33}$/,
CHANNEL_CHAR: '@',
parseIdentifier: function parseIdentifier(identifier) {
logger.debug('parsing identifier:', identifier);
var componentsRegex = new RegExp('([^:$#/]*)' + // value (stops at the first separator or end)
'([:$#]?)([^/]*)' // modifier separator, modifier (stops at the first path separator or end)
);
var _componentsRegex$exec = componentsRegex.exec(identifier).map(function (match) {
return match || null;
}),
_componentsRegex$exec2 = _slicedToArray(_componentsRegex$exec, 4),
proto = _componentsRegex$exec2[0],
value = _componentsRegex$exec2[1],
modifierSeperator = _componentsRegex$exec2[2],
modifier = _componentsRegex$exec2[3];
logger.debug(proto + ', ' + value + ', ' + modifierSeperator + ', ' + modifier);
// Validate and process name
if (!value) {
throw new Error('Check your url. No channel name provided before "' + modifierSeperator + '"');
}
var isChannel = value.startsWith(module.exports.CHANNEL_CHAR);
var channelName = isChannel ? value : null;
var claimId = void 0;
if (isChannel) {
if (!channelName) {
throw new Error('No channel name after @.');
}
var nameBadChars = channelName.match(module.exports.REGEXP_INVALID_CHANNEL);
if (nameBadChars) {
throw new Error('Invalid characters in channel name: ' + nameBadChars.join(', ') + '.');
}
} else {
claimId = value;
}
// Validate and process modifier
var channelClaimId = void 0;
if (modifierSeperator) {
if (!modifier) {
throw new Error('No modifier provided after separator "' + modifierSeperator + '"');
}
if (modifierSeperator === ':') {
channelClaimId = modifier;
} else {
throw new Error('The "' + modifierSeperator + '" modifier is not currently supported');
}
}
return {
isChannel: isChannel,
channelName: channelName,
channelClaimId: channelClaimId,
claimId: claimId
};
},
parseClaim: function parseClaim(claim) {
logger.debug('parsing name:', claim);
var componentsRegex = new RegExp('([^:$#/.]*)' + // name (stops at the first modifier)
'([:$#.]?)([^/]*)' // modifier separator, modifier (stops at the first path separator or end)
);
var _componentsRegex$exec3 = componentsRegex.exec(claim).map(function (match) {
return match || null;
}),
_componentsRegex$exec4 = _slicedToArray(_componentsRegex$exec3, 4),
proto = _componentsRegex$exec4[0],
claimName = _componentsRegex$exec4[1],
modifierSeperator = _componentsRegex$exec4[2],
modifier = _componentsRegex$exec4[3];
logger.debug(proto + ', ' + claimName + ', ' + modifierSeperator + ', ' + modifier);
// Validate and process name
if (!claimName) {
throw new Error('No claim name provided before .');
}
var nameBadChars = claimName.match(module.exports.REGEXP_INVALID_CLAIM);
if (nameBadChars) {
throw new Error('Invalid characters in claim name: ' + nameBadChars.join(', ') + '.');
}
// Validate and process modifier
if (modifierSeperator) {
if (!modifier) {
throw new Error('No file extension provided after separator ' + modifierSeperator + '.');
}
if (modifierSeperator !== '.') {
throw new Error('The ' + modifierSeperator + ' modifier is not supported in the claim name');
}
}
// return results
return {
claimName: claimName
};
},
parseModifier: function parseModifier(claim) {
logger.debug('parsing modifier:', claim);
var componentsRegex = new RegExp('([^:$#/.]*)' + // name (stops at the first modifier)
'([:$#.]?)([^/]*)' // modifier separator, modifier (stops at the first path separator or end)
);
var _componentsRegex$exec5 = componentsRegex.exec(claim).map(function (match) {
return match || null;
}),
_componentsRegex$exec6 = _slicedToArray(_componentsRegex$exec5, 4),
proto = _componentsRegex$exec6[0],
claimName = _componentsRegex$exec6[1],
modifierSeperator = _componentsRegex$exec6[2],
modifier = _componentsRegex$exec6[3];
logger.debug(proto + ', ' + claimName + ', ' + modifierSeperator + ', ' + modifier);
// Validate and process modifier
var hasFileExtension = false;
if (modifierSeperator) {
hasFileExtension = true;
}
return {
hasFileExtension: hasFileExtension
};
}
};
/***/ }),
/* 25 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var _react = __webpack_require__(15);
var _react2 = _interopRequireDefault(_react);
var _server = __webpack_require__(16);
var _redux = __webpack_require__(17);
var _reactRedux = __webpack_require__(18);
var _reactRouterDom = __webpack_require__(19);
var _renderFullPage = __webpack_require__(21);
var _renderFullPage2 = _interopRequireDefault(_renderFullPage);
var _reduxSaga = __webpack_require__(86);
var _reduxSaga2 = _interopRequireDefault(_reduxSaga);
var _effects = __webpack_require__(87);
var _spee = __webpack_require__(20);
var _reactHelmet = __webpack_require__(22);
var _reactHelmet2 = _interopRequireDefault(_reactHelmet);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var siteConfig = __webpack_require__(3);
/*
^ note: to do this right, maybe
these should be passed in from the implementation (www.spee.ch) itself,
so that there are no conflicts between the SSR here and
the bundle sent to the server?
there might also be issues if this package uses a different version of spee.ch-components than www.spee.ch does?
*/
var returnSagaWithParams = function returnSagaWithParams(saga, params) {
return (/*#__PURE__*/regeneratorRuntime.mark(function _callee() {
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_context.next = 2;
return (0, _effects.call)(saga, params);
case 2:
case 'end':
return _context.stop();
}
}
}, _callee, this);
})
);
};
module.exports = function (req, res) {
var context = {};
// configure the reducers by passing initial state configs
var MyReducers = (0, _spee.Reducers)(siteConfig);
var MyApp = (0, _spee.App)(siteConfig);
var MyGAListener = (0, _spee.GAListener)(siteConfig);
// create and apply middleware
var sagaMiddleware = (0, _reduxSaga2.default)();
var middleware = (0, _redux.applyMiddleware)(sagaMiddleware);
// create a new Redux store instance
var store = (0, _redux.createStore)(MyReducers, middleware);
// create saga
var action = _spee.Actions.onHandleShowPageUri(req.params);
var saga = returnSagaWithParams(_spee.Sagas.handleShowPageUri, action);
// run the saga middleware
sagaMiddleware.run(saga).done.then(function () {
// render component to a string
var html = (0, _server.renderToString)(_react2.default.createElement(
_reactRedux.Provider,
{ store: store },
_react2.default.createElement(
_reactRouterDom.StaticRouter,
{ location: req.url, context: context },
_react2.default.createElement(
MyGAListener,
null,
_react2.default.createElement(MyApp, null)
)
)
));
// get head tags from helmet
var helmet = _reactHelmet2.default.renderStatic();
// check for a redirect
if (context.url) {
return res.redirect(301, context.url);
}
// get the initial state from our Redux store
var preloadedState = store.getState();
// send the rendered page back to the client
res.send((0, _renderFullPage2.default)(helmet, html, preloadedState));
});
console.log('hello from spee.ch handleShowRender.jsx');
};
/***/ }),
/* 26 */
/***/ (function(module, exports, __webpack_require__) {
__webpack_require__(27);
__webpack_require__(28);
module.exports = __webpack_require__(29);
/***/ }),
/* 27 */
/***/ (function(module, exports) {
module.exports = require("babel-polyfill");
/***/ }),
/* 28 */
/***/ (function(module, exports) {
module.exports = require("whatwg-fetch");
/***/ }),
/* 29 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
// app dependencies
var express = __webpack_require__(30);
var bodyParser = __webpack_require__(31);
var expressHandlebars = __webpack_require__(32);
var Handlebars = __webpack_require__(33);
var helmet = __webpack_require__(34);
var cookieSession = __webpack_require__(35);
var http = __webpack_require__(36);
var logger = __webpack_require__(0);
var requestLogger = __webpack_require__(37);
var Path = __webpack_require__(38);
var loggerConfig = __webpack_require__(39);
var mysqlConfig = __webpack_require__(10);
var siteConfig = __webpack_require__(3);
var slackConfig = __webpack_require__(40);
function Server() {
var _this = this;
this.configureLogger = function (userConfig) {
loggerConfig.update(userConfig);
};
this.configureMysql = function (userConfig) {
mysqlConfig.update(userConfig);
};
this.configureSite = function (userConfig) {
siteConfig.update(userConfig);
};
this.configureSlack = function (userConfig) {
slackConfig.update(userConfig);
};
this.configureModels = function () {
logger.debug('here is where you could add/overwrite the default models');
};
this.configureRoutes = function () {
logger.debug('here is where you could add/overwrite the default routes');
};
this.createApp = function () {
// create an Express application
var app = express();
// trust the proxy to get ip address for us
app.enable('trust proxy');
/* add middleware */
// set HTTP headers to protect against well-known web vulnerabilties
app.use(helmet());
// 'express.static' to serve static files from public directory
if (siteConfig.routes.publicFolder) {
// take in a different public folder, so it can serve it's own bundle if needed
var publicFolder = Path.resolve(process.cwd(), siteConfig.routes.publicFolder);
app.use(express.static(publicFolder));
logger.info('serving static files from custom path:', publicFolder);
} else {
var publicPath = Path.resolve(process.cwd(), 'public');
app.use(express.static(publicPath));
logger.warn('serving static files from default static path at ' + publicPath + '. Please specify a path in your config/siteConfig.js file');
};
// 'body parser' for parsing application/json
app.use(bodyParser.json());
// 'body parser' for parsing application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true }));
// add custom middleware (note: build out to accept dynamically use what is in server/middleware/
app.use(requestLogger);
// configure passport
var speechPassport = __webpack_require__(7);
// initialize passport
var sessionKey = siteConfig.auth.sessionKey;
app.use(cookieSession({
name: 'session',
keys: [sessionKey],
maxAge: 24 * 60 * 60 * 1000 // i.e. 24 hours
}));
app.use(speechPassport.initialize());
app.use(speechPassport.session());
// configure handlebars & register it with express app
var hbs = expressHandlebars.create({
defaultLayout: 'embed',
handlebars: Handlebars
});
app.engine('handlebars', hbs.engine);
app.set('view engine', 'handlebars');
// set the routes on the app
__webpack_require__(56)(app);
__webpack_require__(61)(app);
__webpack_require__(80)(app);
__webpack_require__(84)(app);
__webpack_require__(89)(app);
_this.app = app;
};
this.initialize = function () {
_this.createApp();
_this.server = http.Server(_this.app);
};
this.start = function () {
var db = __webpack_require__(2);
var PORT = siteConfig.details.port;
// sync sequelize
db.sequelize.sync()
// start the server
.then(function () {
_this.server.listen(PORT, function () {
logger.info('Server is listening on PORT ' + PORT);
});
}).catch(function (error) {
logger.error('Startup Error:', error);
});
};
};
module.exports = Server;
/***/ }),
/* 30 */
/***/ (function(module, exports) {
module.exports = require("express");
/***/ }),
/* 31 */
/***/ (function(module, exports) {
module.exports = require("body-parser");
/***/ }),
/* 32 */
/***/ (function(module, exports) {
module.exports = require("express-handlebars");
/***/ }),
/* 33 */
/***/ (function(module, exports) {
module.exports = require("handlebars");
/***/ }),
/* 34 */
/***/ (function(module, exports) {
module.exports = require("helmet");
/***/ }),
/* 35 */
/***/ (function(module, exports) {
module.exports = require("cookie-session");
/***/ }),
/* 36 */
/***/ (function(module, exports) {
module.exports = require("http");
/***/ }),
/* 37 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var logger = __webpack_require__(0);
var requestLogger = function requestLogger(req, res, next) {
// custom logging middleware to log all incoming http requests
logger.verbose('Request on ' + req.originalUrl + ' from ' + req.ip);
next();
};
module.exports = requestLogger;
/***/ }),
/* 38 */
/***/ (function(module, exports) {
module.exports = require("path");
/***/ }),
/* 39 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var logger = __webpack_require__(0);
function LoggerConfig() {
var _this = this;
this.logLevel = 'debug';
this.update = function (config) {
if (!config) {
return logger.warn('No logger config received.');
}
logger.info('configuring winston logger...');
// update values with local config params
var logLevel = config.logLevel;
_this.logLevel = logLevel;
// configure the winston logger
logger.configure({
transports: [new logger.transports.Console({
level: _this.logLevel,
timestamp: false,
colorize: true,
prettyPrint: true,
handleExceptions: true,
humanReadableUnhandledException: true
})]
});
// test all the log levels
logger.info('testing winston log levels...');
logger.error('Level 0');
logger.warn('Level 1');
logger.info('Level 2');
logger.verbose('Level 3');
logger.debug('Level 4');
logger.silly('Level 5');
};
};
module.exports = new LoggerConfig();
/***/ }),
/* 40 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var winstonSlackWebHook = __webpack_require__(41).SlackWebHook;
var winston = __webpack_require__(0);
function SlackConfig() {
var _this = this;
this.slackWebHook = 'default';
this.slackErrorChannel = 'default';
this.slackInfoChannel = 'default';
this.update = function (config) {
if (!config) {
return winston.warn('No slack config received');
}
// update variables
winston.info('configuring slack logger...');
var slackWebHook = config.slackWebHook,
slackErrorChannel = config.slackErrorChannel,
slackInfoChannel = config.slackInfoChannel;
_this.slackWebHook = slackWebHook;
_this.slackErrorChannel = slackErrorChannel;
_this.slackInfoChannel = slackInfoChannel;
// update slack webhook settings
if (_this.slackWebHook) {
// add a transport for errors to slack
if (_this.slackErrorChannel) {
winston.add(winstonSlackWebHook, {
name: 'slack-errors-transport',
level: 'warn',
webhookUrl: _this.slackWebHook,
channel: _this.slackErrorChannel,
username: 'spee.ch',
iconEmoji: ':face_with_head_bandage:'
});
};
if (slackInfoChannel) {
winston.add(winstonSlackWebHook, {
name: 'slack-info-transport',
level: 'info',
webhookUrl: _this.slackWebHook,
channel: _this.slackInfoChannel,
username: 'spee.ch',
iconEmoji: ':nerd_face:'
});
};
// send test messages
winston.info('testing slack logger...');
winston.error('Slack "error" logging is online.');
winston.info('Slack "info" logging is online.');
} else {
winston.warn('Slack logging is not enabled because no slackWebHook config var provided.');
}
};
};
module.exports = new SlackConfig();
/***/ }),
/* 41 */
/***/ (function(module, exports) {
module.exports = require("winston-slack-webhook");
/***/ }),
/* 42 */
/***/ (function(module, exports) {
module.exports = require("passport");
/***/ }),
/* 43 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var PassportLocalStrategy = __webpack_require__(11).Strategy;
var logger = __webpack_require__(0);
var db = __webpack_require__(2);
var returnUserAndChannelInfo = function returnUserAndChannelInfo(userInstance) {
return new Promise(function (resolve, reject) {
var userInfo = {};
userInfo['id'] = userInstance.id;
userInfo['userName'] = userInstance.userName;
userInstance.getChannel().then(function (_ref) {
var channelName = _ref.channelName,
channelClaimId = _ref.channelClaimId;
userInfo['channelName'] = channelName;
userInfo['channelClaimId'] = channelClaimId;
return db.Certificate.getShortChannelIdFromLongChannelId(channelClaimId, channelName);
}).then(function (shortChannelId) {
userInfo['shortChannelId'] = shortChannelId;
resolve(userInfo);
}).catch(function (error) {
reject(error);
});
});
};
module.exports = new PassportLocalStrategy({
usernameField: 'username',
passwordField: 'password'
}, function (username, password, done) {
return db.User.findOne({
where: { userName: username }
}).then(function (user) {
if (!user) {
logger.debug('no user found');
return done(null, false, { message: 'Incorrect username or password' });
}
return user.comparePassword(password).then(function (isMatch) {
if (!isMatch) {
logger.debug('incorrect password');
return done(null, false, { message: 'Incorrect username or password' });
}
logger.debug('Password was a match, returning User');
return returnUserAndChannelInfo(user).then(function (userInfo) {
return done(null, userInfo);
}).catch(function (error) {
return error;
});
}).catch(function (error) {
return error;
});
}).catch(function (error) {
return done(error);
});
});
/***/ }),
/* 44 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var logger = __webpack_require__(0);
var _require = __webpack_require__(12),
returnShortId = _require.returnShortId;
module.exports = function (sequelize, _ref) {
var STRING = _ref.STRING,
BOOLEAN = _ref.BOOLEAN,
INTEGER = _ref.INTEGER,
TEXT = _ref.TEXT,
DECIMAL = _ref.DECIMAL;
var Certificate = sequelize.define('Certificate', {
address: {
type: STRING,
default: null
},
amount: {
type: DECIMAL(19, 8),
default: null
},
claimId: {
type: STRING,
default: null
},
claimSequence: {
type: INTEGER,
default: null
},
decodedClaim: {
type: BOOLEAN,
default: null
},
depth: {
type: INTEGER,
default: null
},
effectiveAmount: {
type: DECIMAL(19, 8),
default: null
},
hasSignature: {
type: BOOLEAN,
default: null
},
height: {
type: INTEGER,
default: null
},
hex: {
type: TEXT('long'),
default: null
},
name: {
type: STRING,
default: null
},
nout: {
type: INTEGER,
default: null
},
txid: {
type: STRING,
default: null
},
validAtHeight: {
type: INTEGER,
default: null
},
outpoint: {
type: STRING,
default: null
},
valueVersion: {
type: STRING,
default: null
},
claimType: {
type: STRING,
default: null
},
certificateVersion: {
type: STRING,
default: null
},
keyType: {
type: STRING,
default: null
},
publicKey: {
type: TEXT('long'),
default: null
}
}, {
freezeTableName: true
});
Certificate.associate = function (db) {
Certificate.belongsTo(db.Channel, {
foreignKey: {
allowNull: true
}
});
};
Certificate.getShortChannelIdFromLongChannelId = function (longChannelId, channelName) {
var _this = this;
logger.debug('getShortChannelIdFromLongChannelId ' + channelName + ':' + longChannelId);
return new Promise(function (resolve, reject) {
_this.findAll({
where: { name: channelName },
order: [['height', 'ASC']]
}).then(function (result) {
switch (result.length) {
case 0:
throw new Error('No channel(s) found with that channel name');
default:
return resolve(returnShortId(result, longChannelId));
}
}).catch(function (error) {
reject(error);
});
});
};
Certificate.getLongChannelIdFromShortChannelId = function (channelName, channelClaimId) {
var _this2 = this;
logger.debug('getLongChannelIdFromShortChannelId(' + channelName + ', ' + channelClaimId + ')');
return new Promise(function (resolve, reject) {
_this2.findAll({
where: {
name: channelName,
claimId: {
$like: channelClaimId + '%'
}
},
order: [['height', 'ASC']]
}).then(function (result) {
switch (result.length) {
case 0:
return resolve(null);
default:
// note results must be sorted
return resolve(result[0].claimId);
}
}).catch(function (error) {
reject(error);
});
});
};
Certificate.getLongChannelIdFromChannelName = function (channelName) {
var _this3 = this;
logger.debug('getLongChannelIdFromChannelName(' + channelName + ')');
return new Promise(function (resolve, reject) {
_this3.findAll({
where: { name: channelName },
order: [['effectiveAmount', 'DESC'], ['height', 'ASC']]
}).then(function (result) {
switch (result.length) {
case 0:
return resolve(null);
default:
return resolve(result[0].claimId);
}
}).catch(function (error) {
reject(error);
});
});
};
Certificate.validateLongChannelId = function (name, claimId) {
var _this4 = this;
logger.debug('validateLongChannelId(' + name + ', ' + claimId + ')');
return new Promise(function (resolve, reject) {
_this4.findOne({
where: { name: name, claimId: claimId }
}).then(function (result) {
if (!result) {
return resolve(null);
};
resolve(claimId);
}).catch(function (error) {
reject(error);
});
});
};
Certificate.getLongChannelId = function (channelName, channelClaimId) {
logger.debug('getLongChannelId(' + channelName + ', ' + channelClaimId + ')');
if (channelClaimId && channelClaimId.length === 40) {
// if a full channel id is provided
return this.validateLongChannelId(channelName, channelClaimId);
} else if (channelClaimId && channelClaimId.length < 40) {
// if a short channel id is provided
return this.getLongChannelIdFromShortChannelId(channelName, channelClaimId);
} else {
return this.getLongChannelIdFromChannelName(channelName); // if no channel id provided
}
};
return Certificate;
};
/***/ }),
/* 45 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
module.exports = function (sequelize, _ref) {
var STRING = _ref.STRING;
var Channel = sequelize.define('Channel', {
channelName: {
type: STRING,
allowNull: false
},
channelClaimId: {
type: STRING,
allowNull: false
}
}, {
freezeTableName: true
});
Channel.associate = function (db) {
Channel.belongsTo(db.User);
Channel.hasOne(db.Certificate);
};
return Channel;
};
/***/ }),
/* 46 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var logger = __webpack_require__(0);
var _require = __webpack_require__(12),
returnShortId = _require.returnShortId;
var _require2 = __webpack_require__(3),
defaultThumbnail = _require2.assetDefaults.thumbnail,
host = _require2.details.host;
function determineFileExtensionFromContentType(contentType) {
switch (contentType) {
case 'image/jpeg':
case 'image/jpg':
return 'jpeg';
case 'image/png':
return 'png';
case 'image/gif':
return 'gif';
case 'video/mp4':
return 'mp4';
default:
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);
claim['thumbnail'] = determineThumbnail(claim.thumbnail, defaultThumbnail);
claim['fileExt'] = determineFileExtensionFromContentType(claim.contentType);
claim['host'] = host;
return claim;
};
module.exports = function (sequelize, _ref) {
var STRING = _ref.STRING,
BOOLEAN = _ref.BOOLEAN,
INTEGER = _ref.INTEGER,
TEXT = _ref.TEXT,
DECIMAL = _ref.DECIMAL;
var Claim = sequelize.define('Claim', {
address: {
type: STRING,
default: null
},
amount: {
type: DECIMAL(19, 8),
default: null
},
claimId: {
type: STRING,
default: null
},
claimSequence: {
type: INTEGER,
default: null
},
decodedClaim: {
type: BOOLEAN,
default: null
},
depth: {
type: INTEGER,
default: null
},
effectiveAmount: {
type: DECIMAL(19, 8),
default: null
},
hasSignature: {
type: BOOLEAN,
default: null
},
height: {
type: INTEGER,
default: null
},
hex: {
type: TEXT('long'),
default: null
},
name: {
type: STRING,
default: null
},
nout: {
type: INTEGER,
default: null
},
txid: {
type: STRING,
default: null
},
validAtHeight: {
type: INTEGER,
default: null
},
outpoint: {
type: STRING,
default: null
},
claimType: {
type: STRING,
default: null
},
certificateId: {
type: STRING,
default: null
},
author: {
type: STRING,
default: null
},
description: {
type: TEXT('long'),
default: null
},
language: {
type: STRING,
default: null
},
license: {
type: STRING,
default: null
},
licenseUrl: {
type: STRING,
default: null
},
nsfw: {
type: BOOLEAN,
default: null
},
preview: {
type: STRING,
default: null
},
thumbnail: {
type: STRING,
default: null
},
title: {
type: STRING,
default: null
},
metadataVersion: {
type: STRING,
default: null
},
contentType: {
type: STRING,
default: null
},
source: {
type: STRING,
default: null
},
sourceType: {
type: STRING,
default: null
},
sourceVersion: {
type: STRING,
default: null
},
streamVersion: {
type: STRING,
default: null
},
valueVersion: {
type: STRING,
default: null
},
channelName: {
type: STRING,
allowNull: true,
default: null
}
}, {
freezeTableName: true
});
Claim.associate = function (db) {
Claim.belongsTo(db.File, {
foreignKey: {
allowNull: true
}
});
};
Claim.getShortClaimIdFromLongClaimId = function (claimId, claimName) {
var _this = this;
logger.debug('Claim.getShortClaimIdFromLongClaimId for ' + claimName + '#' + claimId);
return new Promise(function (resolve, reject) {
_this.findAll({
where: { name: claimName },
order: [['height', 'ASC']]
}).then(function (result) {
switch (result.length) {
case 0:
throw new Error('No claim(s) found with that claim name');
default:
resolve(returnShortId(result, claimId));
}
}).catch(function (error) {
reject(error);
});
});
};
Claim.getAllChannelClaims = function (channelClaimId) {
var _this2 = this;
logger.debug('Claim.getAllChannelClaims for ' + channelClaimId);
return new Promise(function (resolve, reject) {
_this2.findAll({
where: { certificateId: channelClaimId },
order: [['height', 'ASC']],
raw: true // returns an array of only data, not an array of instances
}).then(function (channelClaimsArray) {
// logger.debug('channelclaimsarray length:', channelClaimsArray.length);
switch (channelClaimsArray.length) {
case 0:
return resolve(null);
default:
channelClaimsArray.forEach(function (claim) {
claim['fileExt'] = determineFileExtensionFromContentType(claim.contentType);
claim['thumbnail'] = determineThumbnail(claim.thumbnail, defaultThumbnail);
return claim;
});
return resolve(channelClaimsArray);
}
}).catch(function (error) {
reject(error);
});
});
};
Claim.getClaimIdByLongChannelId = function (channelClaimId, claimName) {
var _this3 = this;
logger.debug('finding claim id for claim ' + claimName + ' from channel ' + channelClaimId);
return new Promise(function (resolve, reject) {
_this3.findAll({
where: { name: claimName, certificateId: channelClaimId },
order: [['id', 'ASC']]
}).then(function (result) {
switch (result.length) {
case 0:
return resolve(null);
case 1:
return resolve(result[0].claimId);
default:
logger.error(result.length + ' records found for "' + claimName + '" in channel "' + channelClaimId + '"');
return resolve(result[0].claimId);
}
}).catch(function (error) {
reject(error);
});
});
};
Claim.getLongClaimIdFromShortClaimId = function (name, shortId) {
var _this4 = this;
return new Promise(function (resolve, reject) {
_this4.findAll({
where: {
name: name,
claimId: {
$like: shortId + '%'
} },
order: [['height', 'ASC']]
}).then(function (result) {
switch (result.length) {
case 0:
return resolve(null);
default:
// note results must be sorted
return resolve(result[0].claimId);
}
}).catch(function (error) {
reject(error);
});
});
};
Claim.getTopFreeClaimIdByClaimName = function (name) {
var _this5 = this;
return new Promise(function (resolve, reject) {
_this5.findAll({
where: { name: name },
order: [['effectiveAmount', 'DESC'], ['height', 'ASC']] // note: maybe height and effective amount need to switch?
}).then(function (result) {
logger.debug('length of result', result.length);
switch (result.length) {
case 0:
return resolve(null);
default:
return resolve(result[0].dataValues.claimId);
}
}).catch(function (error) {
reject(error);
});
});
};
Claim.validateLongClaimId = function (name, claimId) {
var _this6 = this;
return new Promise(function (resolve, reject) {
_this6.findOne({
where: { name: name, claimId: claimId }
}).then(function (result) {
if (!result) {
return resolve(null);
};
resolve(claimId);
}).catch(function (error) {
reject(error);
});
});
};
Claim.getLongClaimId = function (claimName, claimId) {
logger.debug('getLongClaimId(' + claimName + ', ' + claimId + ')');
if (claimId && claimId.length === 40) {
// if a full claim id is provided
return this.validateLongClaimId(claimName, claimId);
} else if (claimId && claimId.length < 40) {
return this.getLongClaimIdFromShortClaimId(claimName, claimId); // if a short claim id is provided
} else {
return this.getTopFreeClaimIdByClaimName(claimName); // if no claim id is provided
}
};
Claim.resolveClaim = function (name, claimId) {
var _this7 = this;
logger.debug('Claim.resolveClaim: ' + name + ' ' + claimId);
return new Promise(function (resolve, reject) {
_this7.findAll({
where: { name: name, claimId: claimId }
}).then(function (claimArray) {
switch (claimArray.length) {
case 0:
return resolve(null);
case 1:
return resolve(prepareClaimData(claimArray[0].dataValues));
default:
logger.error('more than one record matches ' + name + '#' + claimId + ' in db.Claim');
return resolve(prepareClaimData(claimArray[0].dataValues));
}
}).catch(function (error) {
reject(error);
});
});
};
return Claim;
};
/***/ }),
/* 47 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
module.exports = function (sequelize, _ref) {
var STRING = _ref.STRING,
BOOLEAN = _ref.BOOLEAN,
INTEGER = _ref.INTEGER;
var File = sequelize.define('File', {
name: {
type: STRING,
allowNull: false
},
claimId: {
type: STRING,
allowNull: false
},
address: {
type: STRING,
allowNull: false
},
outpoint: {
type: STRING,
allowNull: false
},
height: {
type: INTEGER,
allowNull: false,
default: 0
},
fileName: {
type: STRING,
allowNull: false
},
filePath: {
type: STRING,
allowNull: false
},
fileType: {
type: STRING
},
nsfw: {
type: BOOLEAN,
allowNull: false,
defaultValue: false
},
trendingEligible: {
type: BOOLEAN,
allowNull: false,
defaultValue: true
}
}, {
freezeTableName: true
});
File.associate = function (db) {
File.hasMany(db.Request);
File.hasOne(db.Claim);
};
File.getRecentClaims = function () {
return this.findAll({
where: { nsfw: false, trendingEligible: true },
order: [['createdAt', 'DESC']],
limit: 25
});
};
return File;
};
/***/ }),
/* 48 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
module.exports = function (sequelize, _ref) {
var STRING = _ref.STRING,
BOOLEAN = _ref.BOOLEAN,
TEXT = _ref.TEXT;
var Request = sequelize.define('Request', {
action: {
type: STRING,
allowNull: false
},
url: {
type: STRING,
allowNull: false
},
ipAddress: {
type: STRING,
allowNull: true
},
result: {
type: TEXT('long'),
allowNull: true,
default: null
}
}, {
freezeTableName: true
});
Request.associate = function (db) {
Request.belongsTo(db.File, {
foreignKey: {
allowNull: true
}
});
};
return Request;
};
/***/ }),
/* 49 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var bcrypt = __webpack_require__(50);
var logger = __webpack_require__(0);
module.exports = function (sequelize, _ref) {
var STRING = _ref.STRING;
var User = sequelize.define('User', {
userName: {
type: STRING,
allowNull: false
},
password: {
type: STRING,
allowNull: false
}
}, {
freezeTableName: true
});
User.associate = function (db) {
User.hasOne(db.Channel);
};
User.prototype.comparePassword = function (password) {
return bcrypt.compare(password, this.password);
};
User.prototype.changePassword = function (newPassword) {
var _this = this;
return new Promise(function (resolve, reject) {
// generate a salt string to use for hashing
bcrypt.genSalt(function (saltError, salt) {
if (saltError) {
logger.error('salt error', saltError);
reject(saltError);
return;
}
// generate a hashed version of the user's password
bcrypt.hash(newPassword, salt, function (hashError, hash) {
// if there is an error with the hash generation return the error
if (hashError) {
logger.error('hash error', hashError);
reject(hashError);
return;
}
// replace the current password with the new hash
_this.update({ password: hash }).then(function () {
resolve();
}).catch(function (error) {
reject(error);
});
});
});
});
};
// pre-save hook method to hash the user's password before the user's info is saved to the db.
User.hook('beforeCreate', function (user, options) {
logger.debug('User.beforeCreate hook...');
return new Promise(function (resolve, reject) {
// generate a salt string to use for hashing
bcrypt.genSalt(function (saltError, salt) {
if (saltError) {
logger.error('salt error', saltError);
reject(saltError);
return;
}
// generate a hashed version of the user's password
bcrypt.hash(user.password, salt, function (hashError, hash) {
// if there is an error with the hash generation return the error
if (hashError) {
logger.error('hash error', hashError);
reject(hashError);
return;
}
// replace the password string with the hash password value
user.password = hash;
resolve();
});
});
});
});
return User;
};
/***/ }),
/* 50 */
/***/ (function(module, exports) {
module.exports = require("bcrypt");
/***/ }),
/* 51 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
var PassportLocalStrategy = __webpack_require__(11).Strategy;
var lbryApi = __webpack_require__(5);
var logger = __webpack_require__(0);
var db = __webpack_require__(2);
module.exports = new PassportLocalStrategy({
usernameField: 'username',
passwordField: 'password'
}, function (username, password, done) {
logger.verbose('new channel signup request. user: ' + username + ' pass: ' + password + ' .');
var userInfo = {};
// server-side validaton of inputs (username, password)
// create the channel and retrieve the metadata
return lbryApi.createChannel('@' + username).then(function (tx) {
// create user record
var userData = {
userName: username,
password: password
};
logger.verbose('userData >', userData);
// create user record
var channelData = {
channelName: '@' + username,
channelClaimId: tx.claim_id
};
logger.verbose('channelData >', channelData);
// create certificate record
var certificateData = {
claimId: tx.claim_id,
name: '@' + username
// address,
};
logger.verbose('certificateData >', certificateData);
// save user and certificate to db
return Promise.all([db.User.create(userData), db.Channel.create(channelData), db.Certificate.create(certificateData)]);
}).then(function (_ref) {
var _ref2 = _slicedToArray(_ref, 3),
newUser = _ref2[0],
newChannel = _ref2[1],
newCertificate = _ref2[2];
logger.verbose('user and certificate successfully created');
// store the relevant newUser info to be passed back for req.User
userInfo['id'] = newUser.id;
userInfo['userName'] = newUser.userName;
userInfo['channelName'] = newChannel.channelName;
userInfo['channelClaimId'] = newChannel.channelClaimId;
// associate the instances
return Promise.all([newCertificate.setChannel(newChannel), newChannel.setUser(newUser)]);
}).then(function () {
logger.verbose('user and certificate successfully associated');
return db.Certificate.getShortChannelIdFromLongChannelId(userInfo.channelClaimId, userInfo.channelName);
}).then(function (shortChannelId) {
userInfo['shortChannelId'] = shortChannelId;
return done(null, userInfo);
}).catch(function (error) {
logger.error('signup error', error);
return done(error);
});
});
/***/ }),
/* 52 */
/***/ (function(module, exports) {
module.exports = require("axios");
/***/ }),
/* 53 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var lbryConfig = {
api: {
apiHost: 'localhost',
apiPort: '5279'
}
};
module.exports = lbryConfig;
/***/ }),
/* 54 */
/***/ (function(module, exports) {
module.exports = require("universal-analytics");
/***/ }),
/* 55 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
module.exports = {
serializeSpeechUser: function serializeSpeechUser(user, done) {
// returns user data to be serialized into session
console.log('serializing user');
done(null, user);
},
deserializeSpeechUser: function deserializeSpeechUser(user, done) {
// deserializes session and populates additional info to req.user
console.log('deserializing user');
done(null, user);
}
};
/***/ }),
/* 56 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var speechPassport = __webpack_require__(7);
var handleSignupRequest = __webpack_require__(57);
var handleLoginRequest = __webpack_require__(58);
var handleLogoutRequest = __webpack_require__(59);
var handleUserRequest = __webpack_require__(60);
module.exports = function (app) {
app.post('/signup', speechPassport.authenticate('local-signup'), handleSignupRequest);
app.post('/login', handleLoginRequest);
app.get('/logout', handleLogoutRequest);
app.get('/user', handleUserRequest);
};
/***/ }),
/* 57 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var signup = function signup(req, res) {
res.status(200).json({
success: true,
channelName: req.user.channelName,
channelClaimId: req.user.channelClaimId,
shortChannelId: req.user.shortChannelId
});
};
module.exports = signup;
/***/ }),
/* 58 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var speechPassport = __webpack_require__(7);
var login = function login(req, res, next) {
speechPassport.authenticate('local-login', function (err, user, info) {
if (err) {
return next(err);
}
if (!user) {
return res.status(400).json({
success: false,
message: info.message
});
}
req.logIn(user, function (err) {
if (err) {
return next(err);
}
return res.status(200).json({
success: true,
channelName: req.user.channelName,
channelClaimId: req.user.channelClaimId,
shortChannelId: req.user.shortChannelId
});
});
})(req, res, next);
};
module.exports = login;
/***/ }),
/* 59 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var logout = function logout(req, res) {
req.logout();
res.status(200).json({ success: true, message: 'you successfully logged out' });
};
module.exports = logout;
/***/ }),
/* 60 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var user = function user(req, res) {
if (req.user) {
res.status(200).json({ success: true, data: req.user });
} else {
res.status(401).json({ success: false, message: 'user is not logged in' });
}
};
module.exports = user;
/***/ }),
/* 61 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var channelAvailability = __webpack_require__(62);
var channelClaims = __webpack_require__(64);
var channelData = __webpack_require__(66);
var channelShortId = __webpack_require__(67);
var claimAvailability = __webpack_require__(68);
var claimData = __webpack_require__(69);
var claimGet = __webpack_require__(70);
var claimLongId = __webpack_require__(71);
var claimPublish = __webpack_require__(72);
var claimResolve = __webpack_require__(74);
var claimShortId = __webpack_require__(75);
var claimList = __webpack_require__(76);
var fileAvailability = __webpack_require__(77);
var multipartMiddleware = __webpack_require__(78);
module.exports = function (app) {
// channel routes
app.get('/api/channel/availability/:name', channelAvailability);
app.get('/api/channel/short-id/:longId/:name', channelShortId);
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/data/:claimName/:claimId', claimData);
// file routes
app.get('/api/file/availability/:name/:claimId', fileAvailability);
};
/***/ }),
/* 62 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var _require = __webpack_require__(8),
checkChannelAvailability = _require.checkChannelAvailability;
var _require2 = __webpack_require__(4),
sendGATimingEvent = _require2.sendGATimingEvent;
var _require3 = __webpack_require__(1),
handleErrorResponse = _require3.handleErrorResponse;
/*
route to check whether site has published to a channel
*/
var channelAvailability = function channelAvailability(_ref, res) {
var ip = _ref.ip,
originalUrl = _ref.originalUrl,
name = _ref.params.name;
var gaStartTime = Date.now();
checkChannelAvailability(name).then(function (availableName) {
res.status(200).json(availableName);
sendGATimingEvent('end-to-end', 'claim name availability', name, gaStartTime, Date.now());
}).catch(function (error) {
handleErrorResponse(originalUrl, ip, error, res);
});
};
module.exports = channelAvailability;
/***/ }),
/* 63 */
/***/ (function(module, exports) {
module.exports = require("fs");
/***/ }),
/* 64 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var _require = __webpack_require__(6),
getChannelClaims = _require.getChannelClaims;
var _require2 = __webpack_require__(1),
handleErrorResponse = _require2.handleErrorResponse;
var NO_CHANNEL = 'NO_CHANNEL';
/*
route to get all claims for channel
*/
var channelClaims = function channelClaims(_ref, res) {
var ip = _ref.ip,
originalUrl = _ref.originalUrl,
body = _ref.body,
params = _ref.params;
var channelName = params.channelName;
var channelClaimId = params.channelClaimId;
if (channelClaimId === 'none') channelClaimId = null;
var page = params.page;
getChannelClaims(channelName, channelClaimId, page).then(function (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: data });
}).catch(function (error) {
handleErrorResponse(originalUrl, ip, error, res);
});
};
module.exports = channelClaims;
/***/ }),
/* 65 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var CLAIMS_PER_PAGE = 12;
module.exports = {
returnPaginatedChannelClaims: function returnPaginatedChannelClaims(channelName, longChannelClaimId, claims, page) {
var totalPages = module.exports.determineTotalPages(claims);
var paginationPage = module.exports.getPageFromQuery(page);
var viewData = {
channelName: channelName,
longChannelClaimId: longChannelClaimId,
claims: module.exports.extractPageFromClaims(claims, paginationPage),
previousPage: module.exports.determinePreviousPage(paginationPage),
currentPage: paginationPage,
nextPage: module.exports.determineNextPage(totalPages, paginationPage),
totalPages: totalPages,
totalResults: module.exports.determineTotalClaims(claims)
};
return viewData;
},
getPageFromQuery: function getPageFromQuery(page) {
if (page) {
return parseInt(page);
}
return 1;
},
extractPageFromClaims: function extractPageFromClaims(claims, pageNumber) {
if (!claims) {
return []; // if no claims, return this default
}
// logger.debug('claims is array?', Array.isArray(claims));
// logger.debug(`pageNumber ${pageNumber} is number?`, Number.isInteger(pageNumber));
var claimStartIndex = (pageNumber - 1) * CLAIMS_PER_PAGE;
var claimEndIndex = claimStartIndex + CLAIMS_PER_PAGE;
var pageOfClaims = claims.slice(claimStartIndex, claimEndIndex);
return pageOfClaims;
},
determineTotalPages: function determineTotalPages(claims) {
if (!claims) {
return 0;
} else {
var totalClaims = claims.length;
if (totalClaims < CLAIMS_PER_PAGE) {
return 1;
}
var fullPages = Math.floor(totalClaims / CLAIMS_PER_PAGE);
var remainder = totalClaims % CLAIMS_PER_PAGE;
if (remainder === 0) {
return fullPages;
}
return fullPages + 1;
}
},
determinePreviousPage: function determinePreviousPage(currentPage) {
if (currentPage === 1) {
return null;
}
return currentPage - 1;
},
determineNextPage: function determineNextPage(totalPages, currentPage) {
if (currentPage === totalPages) {
return null;
}
return currentPage + 1;
},
determineTotalClaims: function determineTotalClaims(claims) {
if (!claims) {
return 0;
}
return claims.length;
}
};
/***/ }),
/* 66 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var _require = __webpack_require__(6),
getChannelData = _require.getChannelData;
var _require2 = __webpack_require__(1),
handleErrorResponse = _require2.handleErrorResponse;
var NO_CHANNEL = 'NO_CHANNEL';
/*
route to get data for a channel
*/
var channelData = function channelData(_ref, res) {
var ip = _ref.ip,
originalUrl = _ref.originalUrl,
body = _ref.body,
params = _ref.params;
var channelName = params.channelName;
var channelClaimId = params.channelClaimId;
if (channelClaimId === 'none') channelClaimId = null;
getChannelData(channelName, channelClaimId, 0).then(function (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: data });
}).catch(function (error) {
handleErrorResponse(originalUrl, ip, error, res);
});
};
module.exports = channelData;
/***/ }),
/* 67 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var _require = __webpack_require__(1),
handleErrorResponse = _require.handleErrorResponse;
var db = __webpack_require__(2);
/*
route to get a short channel id from long channel Id
*/
var channelShortIdRoute = function channelShortIdRoute(_ref, res) {
var ip = _ref.ip,
originalUrl = _ref.originalUrl,
params = _ref.params;
db.Certificate.getShortChannelIdFromLongChannelId(params.longId, params.name).then(function (shortId) {
res.status(200).json(shortId);
}).catch(function (error) {
handleErrorResponse(originalUrl, ip, error, res);
});
};
module.exports = channelShortIdRoute;
/***/ }),
/* 68 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var _require = __webpack_require__(8),
claimNameIsAvailable = _require.claimNameIsAvailable;
var _require2 = __webpack_require__(4),
sendGATimingEvent = _require2.sendGATimingEvent;
var _require3 = __webpack_require__(1),
handleErrorResponse = _require3.handleErrorResponse;
/*
route to check whether this site published to a claim
*/
var claimAvailability = function claimAvailability(_ref, res) {
var ip = _ref.ip,
originalUrl = _ref.originalUrl,
name = _ref.params.name;
var gaStartTime = Date.now();
claimNameIsAvailable(name).then(function (result) {
res.status(200).json(result);
sendGATimingEvent('end-to-end', 'claim name availability', name, gaStartTime, Date.now());
}).catch(function (error) {
handleErrorResponse(originalUrl, ip, error, res);
});
};
module.exports = claimAvailability;
/***/ }),
/* 69 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var _require = __webpack_require__(1),
handleErrorResponse = _require.handleErrorResponse;
var db = __webpack_require__(2);
/*
route to return data for a claim
*/
var claimData = function claimData(_ref, res) {
var ip = _ref.ip,
originalUrl = _ref.originalUrl,
body = _ref.body,
params = _ref.params;
var claimName = params.claimName;
var claimId = params.claimId;
if (claimId === 'none') claimId = null;
db.Claim.resolveClaim(claimName, claimId).then(function (claimInfo) {
if (!claimInfo) {
return res.status(404).json({ success: false, message: 'No claim could be found' });
}
res.status(200).json({ success: true, data: claimInfo });
}).catch(function (error) {
handleErrorResponse(originalUrl, ip, error, res);
});
};
module.exports = claimData;
/***/ }),
/* 70 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
var _require = __webpack_require__(5),
getClaim = _require.getClaim;
var _require2 = __webpack_require__(9),
addGetResultsToFileData = _require2.addGetResultsToFileData,
createFileData = _require2.createFileData;
var _require3 = __webpack_require__(1),
handleErrorResponse = _require3.handleErrorResponse;
var db = __webpack_require__(2);
/*
route to get a claim
*/
var claimGet = function claimGet(_ref, res) {
var ip = _ref.ip,
originalUrl = _ref.originalUrl,
params = _ref.params;
var name = params.name;
var claimId = params.claimId;
// resolve the claim
db.Claim.resolveClaim(name, claimId).then(function (resolveResult) {
// make sure a claim actually exists at that uri
if (!resolveResult) {
throw new Error('No matching uri found in Claim table');
}
var fileData = createFileData(resolveResult);
// get the claim
return Promise.all([fileData, getClaim(name + '#' + claimId)]);
}).then(function (_ref2) {
var _ref3 = _slicedToArray(_ref2, 2),
fileData = _ref3[0],
getResult = _ref3[1];
fileData = addGetResultsToFileData(fileData, getResult);
return Promise.all([db.upsert(db.File, fileData, { name: name, claimId: claimId }, 'File'), getResult]);
}).then(function (_ref4) {
var _ref5 = _slicedToArray(_ref4, 2),
fileRecord = _ref5[0],
_ref5$ = _ref5[1],
message = _ref5$.message,
completed = _ref5$.completed;
res.status(200).json({ success: true, message: message, completed: completed });
}).catch(function (error) {
handleErrorResponse(originalUrl, ip, error, res);
});
};
module.exports = claimGet;
/***/ }),
/* 71 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var _require = __webpack_require__(6),
getClaimId = _require.getClaimId;
var _require2 = __webpack_require__(1),
handleErrorResponse = _require2.handleErrorResponse;
var NO_CHANNEL = 'NO_CHANNEL';
var NO_CLAIM = 'NO_CLAIM';
/*
route to get a long claim id
*/
var claimLongId = function claimLongId(_ref, res) {
var ip = _ref.ip,
originalUrl = _ref.originalUrl,
body = _ref.body,
params = _ref.params;
var channelName = body.channelName;
var channelClaimId = body.channelClaimId;
var claimName = body.claimName;
var claimId = body.claimId;
getClaimId(channelName, channelClaimId, claimName, claimId).then(function (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 });
}).catch(function (error) {
handleErrorResponse(originalUrl, ip, error, res);
});
};
module.exports = claimLongId;
/***/ }),
/* 72 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
var _require = __webpack_require__(9),
createBasicPublishParams = _require.createBasicPublishParams,
createThumbnailPublishParams = _require.createThumbnailPublishParams,
parsePublishApiRequestBody = _require.parsePublishApiRequestBody,
parsePublishApiRequestFiles = _require.parsePublishApiRequestFiles;
var _require2 = __webpack_require__(8),
claimNameIsAvailable = _require2.claimNameIsAvailable,
publish = _require2.publish;
var _require3 = __webpack_require__(73),
authenticateUser = _require3.authenticateUser;
var _require4 = __webpack_require__(4),
sendGATimingEvent = _require4.sendGATimingEvent;
var _require5 = __webpack_require__(1),
handleErrorResponse = _require5.handleErrorResponse;
var _require6 = __webpack_require__(3),
host = _require6.details.host;
/*
route to publish a claim through the daemon
*/
var claimPublish = function claimPublish(_ref, res) {
var body = _ref.body,
files = _ref.files,
headers = _ref.headers,
ip = _ref.ip,
originalUrl = _ref.originalUrl,
user = _ref.user;
// define variables
var channelName = void 0,
channelId = void 0,
channelPassword = void 0,
description = void 0,
fileName = void 0,
filePath = void 0,
fileType = void 0,
gaStartTime = void 0,
license = void 0,
name = void 0,
nsfw = void 0,
thumbnail = void 0,
thumbnailFileName = void 0,
thumbnailFilePath = void 0,
thumbnailFileType = void 0,
title = void 0;
// record the start time of the request
gaStartTime = Date.now();
// validate the body and files of the request
try {
var _parsePublishApiReque = parsePublishApiRequestBody(body);
// validateApiPublishRequest(body, files);
name = _parsePublishApiReque.name;
nsfw = _parsePublishApiReque.nsfw;
license = _parsePublishApiReque.license;
title = _parsePublishApiReque.title;
description = _parsePublishApiReque.description;
thumbnail = _parsePublishApiReque.thumbnail;
var _parsePublishApiReque2 = parsePublishApiRequestFiles(files);
fileName = _parsePublishApiReque2.fileName;
filePath = _parsePublishApiReque2.filePath;
fileType = _parsePublishApiReque2.fileType;
thumbnailFileName = _parsePublishApiReque2.thumbnailFileName;
thumbnailFilePath = _parsePublishApiReque2.thumbnailFilePath;
thumbnailFileType = _parsePublishApiReque2.thumbnailFileType;
channelName = body.channelName;
channelId = body.channelId;
channelPassword = body.channelPassword;
} catch (error) {
return res.status(400).json({ success: false, message: error.message });
}
// check channel authorization
Promise.all([authenticateUser(channelName, channelId, channelPassword, user), claimNameIsAvailable(name), createBasicPublishParams(filePath, name, title, description, license, nsfw, thumbnail), createThumbnailPublishParams(thumbnailFilePath, name, license, nsfw)]).then(function (_ref2) {
var _ref3 = _slicedToArray(_ref2, 4),
_ref3$ = _ref3[0],
channelName = _ref3$.channelName,
channelClaimId = _ref3$.channelClaimId,
validatedClaimName = _ref3[1],
publishParams = _ref3[2],
thumbnailPublishParams = _ref3[3];
// add channel details to the publish params
if (channelName && channelClaimId) {
publishParams['channel_name'] = channelName;
publishParams['channel_id'] = channelClaimId;
}
// publish the thumbnail
if (thumbnailPublishParams) {
publish(thumbnailPublishParams, thumbnailFileName, thumbnailFileType);
}
// publish the asset
return publish(publishParams, fileName, fileType);
}).then(function (result) {
res.status(200).json({
success: true,
message: 'publish completed successfully',
data: {
name: name,
claimId: result.claim_id,
url: host + '/' + result.claim_id + '/' + name,
lbryTx: result
}
});
// record the publish end time and send to google analytics
sendGATimingEvent('end-to-end', 'publish', fileType, gaStartTime, Date.now());
}).catch(function (error) {
handleErrorResponse(originalUrl, ip, error, res);
});
};
module.exports = claimPublish;
/***/ }),
/* 73 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var db = __webpack_require__(2);
var logger = __webpack_require__(0);
module.exports = {
authenticateUser: function 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: function authenticateChannelCredentials(channelName, channelId, userPassword) {
return new Promise(function (resolve, reject) {
// hoisted variables
var channelData = void 0;
// build the params for finding the channel
var channelFindParams = {};
if (channelName) channelFindParams['channelName'] = channelName;
if (channelId) channelFindParams['channelClaimId'] = channelId;
// find the channel
db.Channel.findOne({
where: channelFindParams
}).then(function (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(function (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(function (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(function (error) {
reject(error);
});
});
}
};
/***/ }),
/* 74 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var _require = __webpack_require__(5),
resolveUri = _require.resolveUri;
var _require2 = __webpack_require__(1),
handleErrorResponse = _require2.handleErrorResponse;
/*
route to run a resolve request on the daemon
*/
var claimResolve = function claimResolve(_ref, res) {
var headers = _ref.headers,
ip = _ref.ip,
originalUrl = _ref.originalUrl,
params = _ref.params;
resolveUri(params.name + '#' + params.claimId).then(function (resolvedUri) {
res.status(200).json(resolvedUri);
}).catch(function (error) {
handleErrorResponse(originalUrl, ip, error, res);
});
};
module.exports = claimResolve;
/***/ }),
/* 75 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var _require = __webpack_require__(1),
handleErrorResponse = _require.handleErrorResponse;
var db = __webpack_require__(2);
/*
route to get a short claim id from long claim Id
*/
var claimShortId = function claimShortId(_ref, res) {
var ip = _ref.ip,
originalUrl = _ref.originalUrl,
body = _ref.body,
params = _ref.params;
db.Claim.getShortClaimIdFromLongClaimId(params.longId, params.name).then(function (shortId) {
res.status(200).json({ success: true, data: shortId });
}).catch(function (error) {
handleErrorResponse(originalUrl, ip, error, res);
});
};
module.exports = claimShortId;
/***/ }),
/* 76 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var _require = __webpack_require__(5),
getClaimList = _require.getClaimList;
var _require2 = __webpack_require__(1),
handleErrorResponse = _require2.handleErrorResponse;
/*
route to get list of claims
*/
var claimList = function claimList(_ref, res) {
var ip = _ref.ip,
originalUrl = _ref.originalUrl,
params = _ref.params;
getClaimList(params.name).then(function (claimsList) {
res.status(200).json(claimsList);
}).catch(function (error) {
handleErrorResponse(originalUrl, ip, error, res);
});
};
module.exports = claimList;
/***/ }),
/* 77 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var _require = __webpack_require__(1),
handleErrorResponse = _require.handleErrorResponse;
var db = __webpack_require__(2);
/*
route to see if asset is available locally
*/
var fileAvailability = function fileAvailability(_ref, res) {
var ip = _ref.ip,
originalUrl = _ref.originalUrl,
params = _ref.params;
var name = params.name;
var claimId = params.claimId;
db.File.findOne({
where: {
name: name,
claimId: claimId
}
}).then(function (result) {
if (result) {
return res.status(200).json({ success: true, data: true });
}
res.status(200).json({ success: true, data: false });
}).catch(function (error) {
handleErrorResponse(originalUrl, ip, error, res);
});
};
module.exports = fileAvailability;
/***/ }),
/* 78 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var multipart = __webpack_require__(79);
var _require = __webpack_require__(3),
uploadDirectory = _require.publishing.uploadDirectory;
var multipartMiddleware = multipart({ uploadDir: uploadDirectory });
module.exports = multipartMiddleware;
/***/ }),
/* 79 */
/***/ (function(module, exports) {
module.exports = require("connect-multiparty");
/***/ }),
/* 80 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var handlePageRequest = __webpack_require__(81);
var handleEmbedRequest = __webpack_require__(82);
var redirect = __webpack_require__(83);
module.exports = function (app) {
app.get('/', handlePageRequest);
app.get('/login', handlePageRequest);
app.get('/about', handlePageRequest);
app.get('/trending', redirect('/popular'));
app.get('/popular', handlePageRequest);
app.get('/new', handlePageRequest);
app.get('/embed/:claimId/:name', handleEmbedRequest); // route to send embedable video player (for twitter)
};
/***/ }),
/* 81 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var handlePageRender = __webpack_require__(14);
var sendReactApp = function sendReactApp(req, res) {
handlePageRender(req, res);
};
module.exports = sendReactApp;
/***/ }),
/* 82 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var _require = __webpack_require__(3),
host = _require.details.host;
var sendEmbedPage = function sendEmbedPage(_ref, res) {
var params = _ref.params;
var claimId = params.claimId;
var name = params.name;
// get and render the content
res.status(200).render('embed', { layout: 'embed', host: host, claimId: claimId, name: name });
};
module.exports = sendEmbedPage;
/***/ }),
/* 83 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var redirect = function redirect(route) {
return function (req, res) {
res.status(301).redirect(route);
};
};
module.exports = redirect;
/***/ }),
/* 84 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var serveAssetByClaim = __webpack_require__(85);
var serveAssetByIdentifierAndClaim = __webpack_require__(88);
module.exports = function (app, db) {
app.get('/:identifier/:claim', serveAssetByIdentifierAndClaim);
app.get('/:claim', serveAssetByClaim);
};
/***/ }),
/* 85 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var _require = __webpack_require__(4),
sendGAServeEvent = _require.sendGAServeEvent;
var _require2 = __webpack_require__(23),
determineResponseType = _require2.determineResponseType,
logRequestData = _require2.logRequestData,
getClaimIdAndServeAsset = _require2.getClaimIdAndServeAsset;
var lbryUri = __webpack_require__(24);
var handleShowRender = __webpack_require__(25);
var SERVE = 'SERVE';
/*
route to serve an asset or the react app via the claim name only
*/
var serverAssetByClaim = function serverAssetByClaim(req, res) {
var headers = req.headers,
ip = req.ip,
originalUrl = req.originalUrl,
params = req.params;
// decide if this is a show request
var hasFileExtension = void 0;
try {
var _lbryUri$parseModifie = lbryUri.parseModifier(params.claim);
hasFileExtension = _lbryUri$parseModifie.hasFileExtension;
} catch (error) {
return res.status(400).json({ success: false, message: error.message });
}
var responseType = determineResponseType(hasFileExtension, headers);
if (responseType !== SERVE) {
return handleShowRender(req, res);
}
// handle serve request
// send google analytics
sendGAServeEvent(headers, ip, originalUrl);
// parse the claim
var claimName = void 0;
try {
var _lbryUri$parseClaim = lbryUri.parseClaim(params.claim);
claimName = _lbryUri$parseClaim.claimName;
} catch (error) {
return res.status(400).json({ success: false, message: error.message });
}
// log the request data for debugging
logRequestData(responseType, claimName, null, null);
// get the claim Id and then serve the asset
getClaimIdAndServeAsset(null, null, claimName, null, originalUrl, ip, res);
};
module.exports = serverAssetByClaim;
/***/ }),
/* 86 */
/***/ (function(module, exports) {
module.exports = require("redux-saga");
/***/ }),
/* 87 */
/***/ (function(module, exports) {
module.exports = require("redux-saga/effects");
/***/ }),
/* 88 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
var _require = __webpack_require__(4),
sendGAServeEvent = _require.sendGAServeEvent;
var _require2 = __webpack_require__(23),
determineResponseType = _require2.determineResponseType,
flipClaimNameAndIdForBackwardsCompatibility = _require2.flipClaimNameAndIdForBackwardsCompatibility,
logRequestData = _require2.logRequestData,
getClaimIdAndServeAsset = _require2.getClaimIdAndServeAsset;
var lbryUri = __webpack_require__(24);
var handleShowRender = __webpack_require__(25);
var SERVE = 'SERVE';
/*
route to serve an asset or the react app via the claim name and an identifier
*/
var serverAssetByIdentifierAndClaim = function serverAssetByIdentifierAndClaim(req, res) {
var headers = req.headers,
ip = req.ip,
originalUrl = req.originalUrl,
params = req.params;
// decide if this is a show request
var hasFileExtension = void 0;
try {
var _lbryUri$parseModifie = lbryUri.parseModifier(params.claim);
hasFileExtension = _lbryUri$parseModifie.hasFileExtension;
} catch (error) {
return res.status(400).json({ success: false, message: error.message });
}
var responseType = determineResponseType(hasFileExtension, headers);
if (responseType !== SERVE) {
return handleShowRender(req, res);
}
// handle serve request
// send google analytics
sendGAServeEvent(headers, ip, originalUrl);
// parse the claim
var claimName = void 0;
try {
var _lbryUri$parseClaim = lbryUri.parseClaim(params.claim);
claimName = _lbryUri$parseClaim.claimName;
} catch (error) {
return res.status(400).json({ success: false, message: error.message });
}
// parse the identifier
var isChannel = void 0,
channelName = void 0,
channelClaimId = void 0,
claimId = void 0;
try {
var _lbryUri$parseIdentif = lbryUri.parseIdentifier(params.identifier);
isChannel = _lbryUri$parseIdentif.isChannel;
channelName = _lbryUri$parseIdentif.channelName;
channelClaimId = _lbryUri$parseIdentif.channelClaimId;
claimId = _lbryUri$parseIdentif.claimId;
} catch (error) {
return res.status(400).json({ success: false, message: error.message });
}
if (!isChannel) {
var _flipClaimNameAndIdFo = flipClaimNameAndIdForBackwardsCompatibility(claimId, claimName);
var _flipClaimNameAndIdFo2 = _slicedToArray(_flipClaimNameAndIdFo, 2);
claimId = _flipClaimNameAndIdFo2[0];
claimName = _flipClaimNameAndIdFo2[1];
}
// log the request data for debugging
logRequestData(responseType, claimName, channelName, claimId);
// get the claim Id and then serve the asset
getClaimIdAndServeAsset(channelName, channelClaimId, claimName, claimId, originalUrl, ip, res);
};
module.exports = serverAssetByIdentifierAndClaim;
/***/ }),
/* 89 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var handlePageRequest = __webpack_require__(90);
module.exports = function (app) {
app.get('*', handlePageRequest);
};
/***/ }),
/* 90 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var handlePageRender = __webpack_require__(14);
var sendReactApp = function sendReactApp(req, res) {
handlePageRender(req, res);
};
module.exports = sendReactApp;
/***/ })
/******/ ]);
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay9ib290c3RyYXAgZWJlOTIyZDMzNDNkYjE4YmI3N2EiLCJ3ZWJwYWNrOi8vL2V4dGVybmFsIFwid2luc3RvblwiIiwid2VicGFjazovLy8uL3NlcnZlci9oZWxwZXJzL2Vycm9ySGFuZGxlcnMuanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL21vZGVscy9pbmRleC5qcyIsIndlYnBhY2s6Ly8vLi9jb25maWcvc2l0ZUNvbmZpZy5qcyIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvaGVscGVycy9nb29nbGVBbmFseXRpY3MuanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL2hlbHBlcnMvbGJyeUFwaS5qcyIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvY29udHJvbGxlcnMvc2VydmVDb250cm9sbGVyLmpzIiwid2VicGFjazovLy8uL3NlcnZlci9zcGVlY2hQYXNzcG9ydC9pbmRleC5qcyIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvY29udHJvbGxlcnMvcHVibGlzaENvbnRyb2xsZXIuanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL2hlbHBlcnMvcHVibGlzaEhlbHBlcnMuanMiLCJ3ZWJwYWNrOi8vLy4vY29uZmlnL215c3FsQ29uZmlnLmpzIiwid2VicGFjazovLy9leHRlcm5hbCBcInBhc3Nwb3J0LWxvY2FsXCIiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL2hlbHBlcnMvc2VxdWVsaXplSGVscGVycy5qcyIsIndlYnBhY2s6Ly8vZXh0ZXJuYWwgXCJzZXF1ZWxpemVcIiIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvaGVscGVycy9oYW5kbGVQYWdlUmVuZGVyLmpzeCIsIndlYnBhY2s6Ly8vZXh0ZXJuYWwgXCJyZWFjdFwiIiwid2VicGFjazovLy9leHRlcm5hbCBcInJlYWN0LWRvbS9zZXJ2ZXJcIiIsIndlYnBhY2s6Ly8vZXh0ZXJuYWwgXCJyZWR1eFwiIiwid2VicGFjazovLy9leHRlcm5hbCBcInJlYWN0LXJlZHV4XCIiLCJ3ZWJwYWNrOi8vL2V4dGVybmFsIFwicmVhY3Qtcm91dGVyLWRvbVwiIiwid2VicGFjazovLy9leHRlcm5hbCBcInNwZWUuY2gtY29tcG9uZW50c1wiIiwid2VicGFjazovLy8uL3NlcnZlci9oZWxwZXJzL3JlbmRlckZ1bGxQYWdlLmpzIiwid2VicGFjazovLy9leHRlcm5hbCBcInJlYWN0LWhlbG1ldFwiIiwid2VicGFjazovLy8uL3NlcnZlci9oZWxwZXJzL3NlcnZlSGVscGVycy5qcyIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvaGVscGVycy9sYnJ5VXJpLmpzIiwid2VicGFjazovLy8uL3NlcnZlci9oZWxwZXJzL2hhbmRsZVNob3dSZW5kZXIuanN4Iiwid2VicGFjazovLy9leHRlcm5hbCBcImJhYmVsLXBvbHlmaWxsXCIiLCJ3ZWJwYWNrOi8vL2V4dGVybmFsIFwid2hhdHdnLWZldGNoXCIiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL2luZGV4LmpzIiwid2VicGFjazovLy9leHRlcm5hbCBcImV4cHJlc3NcIiIsIndlYnBhY2s6Ly8vZXh0ZXJuYWwgXCJib2R5LXBhcnNlclwiIiwid2VicGFjazovLy9leHRlcm5hbCBcImV4cHJlc3MtaGFuZGxlYmFyc1wiIiwid2VicGFjazovLy9leHRlcm5hbCBcImhhbmRsZWJhcnNcIiIsIndlYnBhY2s6Ly8vZXh0ZXJuYWwgXCJoZWxtZXRcIiIsIndlYnBhY2s6Ly8vZXh0ZXJuYWwgXCJjb29raWUtc2Vzc2lvblwiIiwid2VicGFjazovLy9leHRlcm5hbCBcImh0dHBcIiIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvbWlkZGxld2FyZS9yZXF1ZXN0TG9nZ2VyLmpzIiwid2VicGFjazovLy9leHRlcm5hbCBcInBhdGhcIiIsIndlYnBhY2s6Ly8vLi9jb25maWcvbG9nZ2VyQ29uZmlnLmpzIiwid2VicGFjazovLy8uL2NvbmZpZy9zbGFja0NvbmZpZy5qcyIsIndlYnBhY2s6Ly8vZXh0ZXJuYWwgXCJ3aW5zdG9uLXNsYWNrLXdlYmhvb2tcIiIsIndlYnBhY2s6Ly8vZXh0ZXJuYWwgXCJwYXNzcG9ydFwiIiwid2VicGFjazovLy8uL3NlcnZlci9zcGVlY2hQYXNzcG9ydC9sb2NhbC1sb2dpbi5qcyIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvbW9kZWxzL2NlcnRpZmljYXRlLmpzIiwid2VicGFjazovLy8uL3NlcnZlci9tb2RlbHMvY2hhbm5lbC5qcyIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvbW9kZWxzL2NsYWltLmpzIiwid2VicGFjazovLy8uL3NlcnZlci9tb2RlbHMvZmlsZS5qcyIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvbW9kZWxzL3JlcXVlc3QuanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL21vZGVscy91c2VyLmpzIiwid2VicGFjazovLy9leHRlcm5hbCBcImJjcnlwdFwiIiwid2VicGFjazovLy8uL3NlcnZlci9zcGVlY2hQYXNzcG9ydC9sb2NhbC1zaWdudXAuanMiLCJ3ZWJwYWNrOi8vL2V4dGVybmFsIFwiYXhpb3NcIiIsIndlYnBhY2s6Ly8vLi9jb25maWcvbGJyeUNvbmZpZy5qcyIsIndlYnBhY2s6Ly8vZXh0ZXJuYWwgXCJ1bml2ZXJzYWwtYW5hbHl0aWNzXCIiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL2hlbHBlcnMvYXV0aEhlbHBlcnMuanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL3JvdXRlcy9hdXRoL2luZGV4LmpzIiwid2VicGFjazovLy8uL3NlcnZlci9yb3V0ZXMvYXV0aC9zaWdudXAuanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL3JvdXRlcy9hdXRoL2xvZ2luLmpzIiwid2VicGFjazovLy8uL3NlcnZlci9yb3V0ZXMvYXV0aC9sb2dvdXQuanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL3JvdXRlcy9hdXRoL3VzZXIuanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL3JvdXRlcy9hcGkvaW5kZXguanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL3JvdXRlcy9hcGkvY2hhbm5lbEF2YWlsYWJpbGl0eS5qcyIsIndlYnBhY2s6Ly8vZXh0ZXJuYWwgXCJmc1wiIiwid2VicGFjazovLy8uL3NlcnZlci9yb3V0ZXMvYXBpL2NoYW5uZWxDbGFpbXMuanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL2hlbHBlcnMvY2hhbm5lbFBhZ2luYXRpb24uanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL3JvdXRlcy9hcGkvY2hhbm5lbERhdGEuanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL3JvdXRlcy9hcGkvY2hhbm5lbFNob3J0SWQuanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL3JvdXRlcy9hcGkvY2xhaW1BdmFpbGFiaWxpdHkuanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL3JvdXRlcy9hcGkvY2xhaW1EYXRhLmpzIiwid2VicGFjazovLy8uL3NlcnZlci9yb3V0ZXMvYXBpL2NsYWltR2V0Lmp