diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..e3ef87d --- /dev/null +++ b/.eslintrc @@ -0,0 +1,20 @@ +{ + "extends": ["eslint:recommended"], + + "parserOptions": { + "ecmaVersion": 8 + }, + + "env": { + "es6": true, + "node": true + }, + + "rules": { + "quotes": ["warn", "single"], + "semi": ["warn", "never"], + "indent": ["warn", 2], + "no-unused-vars": ["warn"], + "no-console": 0 + } +} diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..ef58ff9 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,6 @@ +{ + "trailingComma": "es5", + "tabWidth": 4, + "semi": false, + "singleQuote": true +} diff --git a/db/db.js b/db/db.js index 0513989..0d4671c 100755 --- a/db/db.js +++ b/db/db.js @@ -1,8 +1,7 @@ -const Sequelize = require('sequelize'); -const pkg = require('../package.json'); +const Sequelize = require('sequelize') +const pkg = require('../package.json') -const databaseName = - pkg.name + (process.env.NODE_ENV === 'test' ? '-test' : ''); +const databaseName = pkg.name + (process.env.NODE_ENV === 'test' ? '-test' : '') const createDB = () => { const db = new Sequelize( @@ -11,16 +10,16 @@ const createDB = () => { logging: false, operatorsAliases: false } - ); - return db; -}; + ) + return db +} -const db = createDB(); +const db = createDB() -module.exports = db; +module.exports = db // This is a global Mocha hook used for resource cleanup. // Otherwise, Mocha v4+ does not exit after tests. if (process.env.NODE_ENV === 'test') { - after('close database connection', () => db.close()); + after('close database connection', () => db.close()) } diff --git a/db/index.js b/db/index.js index eabce22..36b5ca0 100755 --- a/db/index.js +++ b/db/index.js @@ -1,6 +1,6 @@ -const db = require('./db'); +const db = require('./db') // register models -require('./models'); +require('./models') -module.exports = db; +module.exports = db diff --git a/db/models/article.js b/db/models/article.js index bcffdbf..613c3e7 100644 --- a/db/models/article.js +++ b/db/models/article.js @@ -1,5 +1,5 @@ -const Sequelize = require('sequelize'); -const db = require('../db'); +const Sequelize = require('sequelize') +const db = require('../db') const Article = db.define('articles', { title: { @@ -9,6 +9,6 @@ const Article = db.define('articles', { link: { type: Sequelize.STRING } -}); +}) -module.exports = Article; +module.exports = Article diff --git a/db/models/comment.js b/db/models/comment.js new file mode 100644 index 0000000..6c93e91 --- /dev/null +++ b/db/models/comment.js @@ -0,0 +1,15 @@ +const Sequelize = require('sequelize') +const db = require('../db') + +const Comment = db.define('comment', { + title: { + type: Sequelize.STRING + }, + + content: { + type: Sequelize.TEXT, + allowNull: false + } +}) + +module.exports = Comment diff --git a/db/models/index.js b/db/models/index.js index a39f030..08e6eeb 100755 --- a/db/models/index.js +++ b/db/models/index.js @@ -1,4 +1,19 @@ -const Item = require('./item'); -const Article = require('./article'); +const Item = require('./item') +const Article = require('./article') +const Comment = require('./comment') +//const User = require('./user') -module.exports = { Item, Article }; +Article.hasMany(Comment) //puts postId on Comment +Comment.belongsTo(Article) + +//User.hasMany(Article) //puts userId on Post, creates instance method 'user.getPosts()' +//Article.belongsTo(User) // creates instance method 'post.getUser()'' + +//User.hasMany(Comment) //puts userId on Comment +//Comment.belongsTo(User) //puts userId on Comment + +// TODO +//Comment.belongsTo(Comment, { as: 'parent' }) +//Comment.hasMany(Comment, { as: { singular: 'reply', plural: 'replies' } }) + +module.exports = { Item, Article, Comment } diff --git a/db/models/item.js b/db/models/item.js index 694f380..7003eb8 100755 --- a/db/models/item.js +++ b/db/models/item.js @@ -1,11 +1,11 @@ -const Sequelize = require('sequelize'); -const db = require('../db'); +const Sequelize = require('sequelize') +const db = require('../db') const Item = db.define('items', { name: { type: Sequelize.STRING, allowNull: false } -}); +}) -module.exports = Item; +module.exports = Item diff --git a/db/models/user.js b/db/models/user.js new file mode 100644 index 0000000..5ce8164 --- /dev/null +++ b/db/models/user.js @@ -0,0 +1,88 @@ +/* +note: this currently isn't exported because I will +have to investigate the salting etc. +*/ + +const crypto = require('crypto') +const Sequelize = require('sequelize') +const db = require('../db') + +const User = db.define('user', { + email: { + type: Sequelize.STRING, + unique: true, + allowNull: false + }, + firstName: { + type: Sequelize.STRING + }, + lastName: { + type: Sequelize.STRING + }, + username: { + type: Sequelize.STRING, + unique: true, + allowNull: false + }, + imageUrl: { + type: Sequelize.STRING, + defaultValue: 'novatore.jpg' + }, + + password: { + type: Sequelize.STRING, + // Making `.password` act like a func hides it when serializing to JSON. + // This is a hack to get around Sequelize's lack of a "private" option. + get() { + return () => this.getDataValue('password') + } + }, + salt: { + type: Sequelize.STRING, + // Making `.salt` act like a function hides it when serializing to JSON. + // This is a hack to get around Sequelize's lack of a "private" option. + get() { + return () => this.getDataValue('salt') + } + }, + googleId: { + type: Sequelize.STRING + } +}) + +module.exports = User + +/** + * instanceMethods + */ +User.prototype.correctPassword = function(candidatePwd) { + return User.encryptPassword(candidatePwd, this.salt()) === this.password() +} + +/** + * classMethods + */ +User.generateSalt = function() { + return crypto.randomBytes(16).toString('base64') +} + +User.encryptPassword = function(plainText, salt) { + return crypto + .createHash('RSA-SHA256') + .update(plainText) + .update(salt) + .digest('hex') +} + +/** + * hooks + */ +const setSaltAndPassword = user => { + if (user.changed('password')) { + user.salt = User.generateSalt() + user.password = User.encryptPassword(user.password(), user.salt()) + } +} + +User.beforeCreate(setSaltAndPassword) +User.beforeUpdate(setSaltAndPassword) diff --git a/db/seed.js b/db/seed.js index 452e0ce..f8f367a 100755 --- a/db/seed.js +++ b/db/seed.js @@ -1,27 +1,27 @@ -const db = require('../db'); -const { Article } = require('./models'); +const db = require('../db') +const { Article } = require('./models') const testArticle = { title: 'read desert', link: 'https://readdesert.org' -}; +} -console.log(Article); +console.log(Article) async function runSeed() { - await db.sync({ force: true }); - console.log('db synced!'); - console.log('seeding...'); + await db.sync({ force: true }) + console.log('db synced!') + console.log('seeding...') try { - await Article.create(testArticle); - console.log('seeded successfully'); + await Article.create(testArticle) + console.log('seeded successfully') } catch (err) { - console.error(err); - process.exitCode = 1; + console.error(err) + process.exitCode = 1 } finally { - console.log('closing db connection'); - await db.close(); - console.log('db connection closed'); + console.log('closing db connection') + await db.close() + console.log('db connection closed') } } -runSeed(); +runSeed()