diff --git a/.gitignore b/.gitignore index a45e5a85..356b3db2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ node_modules .idea -config/config.json config/sequelizeCliConfig.js config/speechConfig.js \ No newline at end of file diff --git a/.sequelizerc b/.sequelizerc new file mode 100644 index 00000000..f2daa0b6 --- /dev/null +++ b/.sequelizerc @@ -0,0 +1,5 @@ +const path = require('path'); + +module.exports = { + 'config': path.resolve('config', 'sequelizeCliConfig.js'), +} \ No newline at end of file diff --git a/config/sequelizeCliConfig.js.example b/config/sequelizeCliConfig.js.example new file mode 100644 index 00000000..8b91eccb --- /dev/null +++ b/config/sequelizeCliConfig.js.example @@ -0,0 +1,23 @@ +module.exports = { + development: { + username: '', + password: '', + database: '', + host : '127.0.0.1', + dialect : 'mysql', + }, + test: { + username: '', + password: '', + database: '', + host : '127.0.0.1', + dialect : 'mysql', + }, + production: { + username: '', + password: '', + database: '', + host : '127.0.0.1', + dialect : 'mysql', + }, +}; diff --git a/config/speechConfig.js.example b/config/speechConfig.js.example index d10745a3..f485fb34 100644 --- a/config/speechConfig.js.example +++ b/config/speechConfig.js.example @@ -19,4 +19,7 @@ module.exports = { session: { sessionKey: null, // enter a secret key to be used for session encryption }, + files: { + uploadDirectory: null, // enter file path to where uploads/publishes should be stored + }, }; diff --git a/migrations/AddChannelNameToClaim.js b/migrations/AddChannelNameToClaim.js deleted file mode 100644 index b9ac1da8..00000000 --- a/migrations/AddChannelNameToClaim.js +++ /dev/null @@ -1,22 +0,0 @@ -module.exports = { - up: (queryInterface, Sequelize) => { - // logic for transforming into the new state - const p1 = queryInterface.addColumn( - 'Claim', - 'channelName', - { - type : Sequelize.STRING, - allowNull: true, - } - ); - return Promise.all([p1]); - }, - down: (queryInterface, Sequelize) => { - // logic for reverting the changes - const p1 = queryInterface.removeColumn( - 'Claim', - 'channelName' - ); - return Promise.all([p1]); - }, -}; diff --git a/migrations/ChangeCertificateColumnTypes2.js b/migrations/ChangeCertificateColumnTypes2.js new file mode 100644 index 00000000..8fbcee79 --- /dev/null +++ b/migrations/ChangeCertificateColumnTypes2.js @@ -0,0 +1,42 @@ +module.exports = { + up: (queryInterface, Sequelize) => { + // logic for transforming into the new state + const p1 = queryInterface.changeColumn( + 'Certificate', + 'amount', + { + type : Sequelize.DECIMAL(19, 8), + allowNull: true, + } + ); + const p2 = queryInterface.changeColumn( + 'Certificate', + 'effectiveAmount', + { + type : Sequelize.DECIMAL(19, 8), + allowNull: true, + } + ); + return Promise.all([p1, p2]); + }, + down: (queryInterface, Sequelize) => { + // logic for reverting the changes + const p1 = queryInterface.changeColumn( + 'Certificate', + 'amount', + { + type : Sequelize.DOUBLE, + allowNull: true, + } + ); + const p2 = queryInterface.changeColumn( + 'Certificate', + 'effectiveAmount', + { + type : Sequelize.DOUBLE, + allowNull: true, + } + ); + return Promise.all([p1, p2]); + }, +}; diff --git a/migrations/ChangeClaimColumnTypes.js b/migrations/ChangeClaimColumnTypes.js new file mode 100644 index 00000000..11c2bb52 --- /dev/null +++ b/migrations/ChangeClaimColumnTypes.js @@ -0,0 +1,42 @@ +module.exports = { + up: (queryInterface, Sequelize) => { + // logic for transforming into the new state + const p1 = queryInterface.changeColumn( + 'Claim', + 'amount', + { + type : Sequelize.DECIMAL(19, 8), + allowNull: true, + } + ); + const p2 = queryInterface.changeColumn( + 'Claim', + 'effectiveAmount', + { + type : Sequelize.DECIMAL(19, 8), + allowNull: true, + } + ); + return Promise.all([p1, p2]); + }, + down: (queryInterface, Sequelize) => { + // logic for reverting the changes + const p1 = queryInterface.changeColumn( + 'Claim', + 'amount', + { + type : Sequelize.DOUBLE, + allowNull: true, + } + ); + const p2 = queryInterface.changeColumn( + 'Claim', + 'effectiveAmount', + { + type : Sequelize.DOUBLE, + allowNull: true, + } + ); + return Promise.all([p1, p2]); + }, +}; diff --git a/migrations/UpdateUserPasswords5.js b/migrations/UpdateUserPasswords5.js deleted file mode 100644 index f911c86e..00000000 --- a/migrations/UpdateUserPasswords5.js +++ /dev/null @@ -1,46 +0,0 @@ -const db = require('../models'); -const bcrypt = require('bcrypt'); -const logger = require('winston'); - -module.exports = { - up: (queryInterface, Sequelize) => { - // get all the users - return db.User - .findAll() - .then((users) => { - // create an array of promises, with each promise bcrypting a password and updating the record - const promises = users.map((record) => { - // bcrypt - // generate a salt string to use for hashing - return new Promise((resolve, reject) => { - bcrypt.genSalt((saltError, salt) => { - if (saltError) { - logger.error('salt error', saltError); - reject(saltError); - return; - } - // generate a hashed version of the user's password - bcrypt.hash(record.password, salt, (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 - resolve(queryInterface.sequelize.query(`UPDATE User SET User.password = "${hash}" WHERE User.id = ${record.id}`)); - }); - }); - }); - }); - // return the array of promises - return Promise.all(promises); - }) - .catch(error => { - logger.error('error prepping promises array', error); - }); - }, - down: (queryInterface, Sequelize) => { - // logic for reverting the changes - }, -}; diff --git a/models/certificate.js b/models/certificate.js index 19ad8b39..eb081826 100644 --- a/models/certificate.js +++ b/models/certificate.js @@ -2,7 +2,7 @@ const logger = require('winston'); const { returnShortId } = require('../helpers/sequelizeHelpers.js'); const NO_CHANNEL = 'NO_CHANNEL'; -module.exports = (sequelize, { STRING, BOOLEAN, INTEGER, TEXT }) => { +module.exports = (sequelize, { STRING, BOOLEAN, INTEGER, TEXT, DECIMAL }) => { const Certificate = sequelize.define( 'Certificate', { @@ -11,7 +11,7 @@ module.exports = (sequelize, { STRING, BOOLEAN, INTEGER, TEXT }) => { default: null, }, amount: { - type : STRING, + type : DECIMAL(19, 8), default: null, }, claimId: { @@ -31,7 +31,7 @@ module.exports = (sequelize, { STRING, BOOLEAN, INTEGER, TEXT }) => { default: null, }, effectiveAmount: { - type : STRING, + type : DECIMAL(19, 8), default: null, }, hasSignature: { @@ -39,7 +39,7 @@ module.exports = (sequelize, { STRING, BOOLEAN, INTEGER, TEXT }) => { default: null, }, height: { - type : STRING, + type : INTEGER, default: null, }, hex: { @@ -59,7 +59,7 @@ module.exports = (sequelize, { STRING, BOOLEAN, INTEGER, TEXT }) => { default: null, }, validAtHeight: { - type : STRING, + type : INTEGER, default: null, }, outpoint: { diff --git a/models/claim.js b/models/claim.js index cb6a6d7a..64d565a5 100644 --- a/models/claim.js +++ b/models/claim.js @@ -2,7 +2,7 @@ const logger = require('winston'); const { returnShortId } = require('../helpers/sequelizeHelpers.js'); const NO_CLAIM = 'NO_CLAIM'; -module.exports = (sequelize, { STRING, BOOLEAN, INTEGER, TEXT, ARRAY, DECIMAL, DOUBLE, Op }) => { +module.exports = (sequelize, { STRING, BOOLEAN, INTEGER, TEXT, DECIMAL }) => { const Claim = sequelize.define( 'Claim', { @@ -11,7 +11,7 @@ module.exports = (sequelize, { STRING, BOOLEAN, INTEGER, TEXT, ARRAY, DECIMAL, D default: null, }, amount: { - type : STRING, + type : DECIMAL(19, 8), default: null, }, claimId: { @@ -31,7 +31,7 @@ module.exports = (sequelize, { STRING, BOOLEAN, INTEGER, TEXT, ARRAY, DECIMAL, D default: null, }, effectiveAmount: { - type : STRING, + type : DECIMAL(19, 8), default: null, }, hasSignature: { @@ -39,7 +39,7 @@ module.exports = (sequelize, { STRING, BOOLEAN, INTEGER, TEXT, ARRAY, DECIMAL, D default: null, }, height: { - type : STRING, + type : INTEGER, default: null, }, hex: { @@ -59,7 +59,7 @@ module.exports = (sequelize, { STRING, BOOLEAN, INTEGER, TEXT, ARRAY, DECIMAL, D default: null, }, validAtHeight: { - type : STRING, + type : INTEGER, default: null, }, outpoint: { diff --git a/models/index.js b/models/index.js index 83f277e9..4bc622fd 100644 --- a/models/index.js +++ b/models/index.js @@ -2,19 +2,20 @@ const fs = require('fs'); const path = require('path'); const Sequelize = require('sequelize'); const basename = path.basename(module.filename); -const config = require('../config/speechConfig.js'); -const db = {}; const logger = require('winston'); - +const config = require('../config/speechConfig.js'); const database = config.sql.database; const username = config.sql.username; const password = config.sql.password; +const db = {}; +// set sequelize options const sequelize = new Sequelize(database, username, password, { - host : 'localhost', - dialect: 'mysql', - logging: false, - pool : { + host : 'localhost', + dialect : 'mysql', + dialectOptions: {decimalNumbers: true}, // fix to ensure DECIMAL will not be stored as a string + logging : false, + pool : { max : 5, min : 0, idle : 10000, @@ -53,6 +54,7 @@ Object.keys(db).forEach(modelName => { db.sequelize = sequelize; db.Sequelize = Sequelize; +// add an 'upsert' method to the db object db.upsert = (Model, values, condition, tableName) => { return Model .findOne({ where: condition }) @@ -70,6 +72,7 @@ db.upsert = (Model, values, condition, tableName) => { }); }; +// add a 'getTrendingClaims' method to the db object db.getTrendingClaims = (startDate) => { return db.sequelize.query(`SELECT COUNT(*), File.* FROM Request LEFT JOIN File ON Request.FileId = File.id WHERE FileId IS NOT NULL AND nsfw != 1 AND trendingEligible = 1 AND Request.createdAt > "${startDate}" GROUP BY FileId ORDER BY COUNT(*) DESC LIMIT 25;`, { type: db.sequelize.QueryTypes.SELECT }); }; diff --git a/public/assets/css/general.css b/public/assets/css/general.css index 9b8c8e77..1fcfefe9 100644 --- a/public/assets/css/general.css +++ b/public/assets/css/general.css @@ -74,7 +74,7 @@ body, .flex-container--column { /* TEXT */ -body, button, input, textarea, label, select, option { +body, button, input, textarea, label, select, option, #channel-publish-in-progress > p, #channel-publish-done > p { font-family: 'Lekton', monospace; font-size: large; } diff --git a/public/assets/js/createChannelFunctions.js b/public/assets/js/createChannelFunctions.js index 379c9430..dbcf4e49 100644 --- a/public/assets/js/createChannelFunctions.js +++ b/public/assets/js/createChannelFunctions.js @@ -1,11 +1,14 @@ +// display the content that shows channel creation has started function showChannelCreateInProgressDisplay () { const publishChannelForm = document.getElementById('publish-channel-form'); - publishChannelForm.hidden = true; const inProgress = document.getElementById('channel-publish-in-progress'); + const channelProgressBar = document.getElementById('create-channel-progress-bar'); + publishChannelForm.hidden = true; inProgress.hidden = false; - createProgressBar(document.getElementById('create-channel-progress-bar'), 12); + createProgressBar(channelProgressBar, 12); } +// display the content that shows channle creation is done function showChannelCreateDoneDisplay() { const inProgress = document.getElementById('channel-publish-in-progress'); inProgress.hidden=true; @@ -38,7 +41,6 @@ function publishNewChannel (event) { if (window.location.pathname === '/') { // remove old channel and replace with new one & select it replaceChannelOptionInPublishChannelSelect(); - // remove old channel and replace with new one & select it replaceChannelOptionInNavBarChannelSelect(); } else { window.location = '/'; @@ -47,7 +49,7 @@ function publishNewChannel (event) { .catch(error => { if (error.name === 'ChannelNameError' || error.name === 'ChannelPasswordError'){ const channelNameErrorDisplayElement = document.getElementById('input-error-channel-name'); - showError(channelNameErrorDisplayElement, error.message); + validationFunctions.showError(channelNameErrorDisplayElement, error.message); } else { console.log('signup failure:', error); showChannelCreationError('Unfortunately, Spee.ch encountered an error while creating your channel. Please let us know in slack!'); diff --git a/public/assets/js/generalFunctions.js b/public/assets/js/generalFunctions.js index d591a0ee..ec56009f 100644 --- a/public/assets/js/generalFunctions.js +++ b/public/assets/js/generalFunctions.js @@ -151,7 +151,7 @@ function copyToClipboard(event){ try { document.execCommand('copy'); } catch (err) { - showError(errorElement, 'Oops, unable to copy'); + validationFunctions.showError(errorElement, 'Oops, unable to copy'); } } diff --git a/public/assets/js/validationFunctions.js b/public/assets/js/validationFunctions.js index 3cb2fcaf..f79cc4fa 100644 --- a/public/assets/js/validationFunctions.js +++ b/public/assets/js/validationFunctions.js @@ -38,7 +38,6 @@ const validationFunctions = { }, // validation function that checks to make sure the claim name is valid validateClaimName: function (name) { - console.log('validating the claim name'); // ensure a name was entered if (name.length < 1) { throw new NameError("You must enter a name for your url"); diff --git a/routes/api-routes.js b/routes/api-routes.js index 821caf07..38b5b1e8 100644 --- a/routes/api-routes.js +++ b/routes/api-routes.js @@ -1,6 +1,7 @@ const logger = require('winston'); const multipart = require('connect-multiparty'); -const multipartMiddleware = multipart({uploadDir: '/home/lbry/test/'}); +const config = require('../config/speechConfig.js'); +const multipartMiddleware = multipart({uploadDir: config.files.uploadDirectory}); const db = require('../models'); const { publish } = require('../controllers/publishController.js'); const { getClaimList, resolveUri } = require('../helpers/lbryApi.js'); diff --git a/speech.js b/speech.js index 19253e10..7e7a4e5f 100644 --- a/speech.js +++ b/speech.js @@ -1,7 +1,6 @@ // load dependencies const express = require('express'); const bodyParser = require('body-parser'); -const siofu = require('socketio-file-upload'); const expressHandlebars = require('express-handlebars'); const Handlebars = require('handlebars'); const handlebarsHelpers = require('./helpers/handlebarsHelpers.js'); @@ -32,7 +31,6 @@ app.use(helmet()); // set HTTP headers to protect against well-known web vulnera app.use(express.static(`${__dirname}/public`)); // 'express.static' to serve static files from public directory app.use(bodyParser.json()); // 'body parser' for parsing application/json app.use(bodyParser.urlencoded({ extended: true })); // 'body parser' for parsing application/x-www-form-urlencoded -app.use(siofu.router); // 'socketio-file-upload' router for uploading with socket.io app.use((req, res, next) => { // custom logging middleware to log all incoming http requests logger.verbose(`Request on ${req.originalUrl} from ${req.ip}`); logger.debug('req.body:', req.body); @@ -76,7 +74,7 @@ db.sequelize .then(hostedContentPath => { // add the hosted content folder at a static path app.use('/media', express.static(hostedContentPath)); - // require routes & wrap in socket.io + // require routes require('./routes/auth-routes.js')(app); require('./routes/api-routes.js')(app); require('./routes/page-routes.js')(app); diff --git a/views/index.handlebars b/views/index.handlebars index 09c01c0e..0b09d8a6 100644 --- a/views/index.handlebars +++ b/views/index.handlebars @@ -1,8 +1,8 @@
- +
-
+

Drag & drop image or video here to publish

@@ -22,7 +22,7 @@
-
+