Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kyle Baker #485

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
.DS_Store
.idea/
node_modules/
.env
private.key
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
Trello Link: https://trello.com/b/OX4kMOli/project-week-backend

# Back End Project Week

This week you will build a backend for a note taking app called "Lambda Notes".
Expand Down
70 changes: 70 additions & 0 deletions api/auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
const express = require('express'),
router = express.Router(),
db = require('../data/helpers/userModel.js'),
bcrypt = require('bcrypt'),
{ generateJwt } = require('../middleware/auth');

router
.post('/register', generateJwt, async function (req, res) {
const { user_name, email, password, name } = req.body;
const saltRounds = 10;

if (!user_name || !email || !password || !name) {
console.log('Missing information');

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make sure to remove the console.log statements when commiting

Suggested change
console.log('Missing information');

return res.status(400).json({ error: "Missing information" });
}

console.log('Registering');

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
console.log('Registering');


req.body.password = await bcrypt.hash(password, saltRounds).then(hash => hash);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this .then(hash => hash); if you are just returning what you are getting, do you even need it?

db.insert(req.body).then(users => {
res.cookie('token', req.token, { httpOnly: true });
res.status(201).json({ users });
}).catch(err => {
console.log(err);
res.status(500).json({
error: "There was an error while saving the user to the database",
info: { err }
});
});
})
.post('/login', generateJwt, function (req, res) {
console.log("Attempting login", req.body);

db.login(req.body.user_name)
.then(user => {
if (!user) {
console.log('User not found');
return res.status(403).json({ error: "User not found" });
}

console.log(user);

return bcrypt.compare(req.body.password, user.password).then(eq => {
if (eq) {
console.log('Passwords match');
res.cookie('token', req.token, { httpOnly: true });
res.json({ user });
} else {
console.log('Passwords do not match');
throw 'Passwords do not match';
}
});

})
.catch(err => res.status(500).json({ error: "There was an issue logging in.", info: err }));
})
.get('/logout', (req, res) => {
console.log('Attempting logout');

if (req.cookies.token) {
res.clearCookie('token');
console.log('Log out success');
res.json({ error: false });
} else {
console.log('Not logged in');
res.send('Not logged in')
}
});

module.exports = router;
67 changes: 67 additions & 0 deletions api/notes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
const express = require('express'),
router = express.Router(),
db = require('../data/helpers/noteModel.js'),
{ validateJwt } = require('../middleware/auth')

router
.post('/', validateJwt, function (req, res) {
const note = req.body
const tags = req.body.tags

delete note.tags

db.insertNoteTag(note, tags)
.then(note => res.status(201).json(note))
.catch(err => {
console.log(err)
res.status(500).json({ error: 'There was an error while saving the note to the database' })
})
})

.get('/', function (req, res) {
db.get(null, { page: req.body.page || 0, pageSize: req.body.pageSize || 10 })
.then(notes => res.json(notes))
.catch(err => {
console.log(err)
res.status(500).json({ error: 'The notes could not be retrieved' })
})
})

.get('/:id', function (req, res) {
db.get(req.params.id, { page: req.body.page || 0, pageSize: req.body.pageSize || 10 })
.then(note => {
if (!note) return res.status(404).json({ message: 'The note with the specified ID does not exist' })
res.json(note)
}).catch(err => {
console.log(err)
res.status(500).json({ error: 'The note could not be retrieved' })
})
})

.delete('/:id', validateJwt, function (req, res) {
db.remove(req.params.id)
.then(note => {
if (!note) return res.status(404).json({ message: 'The note with the specified ID does not exist' })
res.json(note)
}).catch(err => {
console.log(err)
res.status(500).json({ error: 'The note could not be removed' })
})
})

.put('/:id', validateJwt, function (req, res) {
const { title, textBody } = req.body

if (!title || !textBody) return res.status(400).json({ errorMessage: 'Please provide title and text body for the project' })

db.update(req.params.id, req.body)
.then(note => {
if (!note) return res.status(404).json({ message: 'The note with the specified ID does not exist' })
res.json(note)
}).catch(err => {
console.log(err)
res.status(500).json({ error: 'The note could not be modified' })
})
})

module.exports = router
24 changes: 24 additions & 0 deletions api/users.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const express = require('express'),
router = express.Router(),
db = require('../data/helpers/userModel.js'),
bcrypt = require('bcrypt');


router
.get('/', function (req, res) {
db.get().then(users => {
res.json(users);

}).catch(err => res.status(500).json({ error: "There was an issue fetching the user.", info: err }));
})

.get('/:id', function (req, res) {
db.get(req.params.id).then(user => {
if (!user) return res.status(404).json({ error: "That user does not exist" });

res.json(user);

}).catch(err => res.status(500).json({ error: "There was an issue fetching the user." }));
});

module.exports = router;
4 changes: 4 additions & 0 deletions data/dbConfig.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
const knex = require('knex');
const knexConfig = require('../knexfile.js');

module.exports = knex(knexConfig.development);
100 changes: 100 additions & 0 deletions data/helpers/noteModel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
const db = require('../dbConfig.js')
// const mappers = require('./mappers');

module.exports = {
get: function (id, opts) {
console.log(opts);
let query = db('notes as n')
.select('n.id', 'n.textBody', 'n.title', db.raw('GROUP_CONCAT(t.title) as tags'))
.innerJoin('noteTags as nt', 'n.id', 'nt.note_id')
.innerJoin('tags as t', 't.id', 'nt.tag_id')
.groupBy('n.id')

if (id) {
return query
.where('n.id', id)
.first()
.then(note => {
if (note) {
return {...note, tags: note.tags.split(',')}
} else {
return []
}
})
}

return query
.offset(opts.page * opts.pageSize)
.limit(opts.pageSize)
.then(notes => {
return notes.map(n => ({ ...n, tags: n.tags.split(',') }))
})
},
getTags: function (noteId) {
return db('tags')
.where('note_id', noteId)
.then(tags => tags.map(t => t.title))
},
insertNote: async function (note) {
return db('notes').insert(note).then(note => note[0])
},
insertTag: async function (tags) {
let tagIds = []

for (let tag of tags) {
const tagId = await db('tags as t')
.select()
.where('t.title', tag)
.first()
.then(existingTag => {
if (!existingTag) {
return db('tags').insert({ title: tag })
} else {
return [existingTag.id]
}
})

tagIds.push(tagId[0])
}

return tagIds
},
insertNoteTag: function (note, tags) {
const promises = [this.insertNote(note), this.insertTag(tags)]

return Promise.all(promises).then(async (results) => {
let [note_id, tagIds] = results

for (let tag_id of tagIds) {
await db('noteTags').insert({ tag_id, note_id })
}

return this.get(note_id)
})
},
update: async function (id, changes) {
if (changes.tags) {
for (let tag in tags) {
await this.removeTags(id)
await this.insertTag({ title: tag, note_id: id })
}
}

return db('notes')
.where('id', id)
.update(changes)
.then(count => (count > 0 ? this.get(id) : null))
},
removeTags: function (id) {
return db('tags')
.where('note_id', id)
.del()
},
remove: async function (id) {
await this.removeTags(id)

return db('notes')
.where('id', id)
.del()
}
}
28 changes: 28 additions & 0 deletions data/helpers/userModel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const db = require('../dbConfig.js');

module.exports = {
get: function (id) {
let query = db('users as u');

if (id) {
return query
.where('id', id)
.first();
}

return query.select('email', 'user_name');
},
insert: function (user) {
// TODO check if user with email and user_name exists first
return db('users')
.insert(user)
.then(([id]) => this.get(id));
},
login: function (user_name) {
let query = db('users as u');

return query
.where('user_name', user_name)
.first();
}
};
Binary file added data/lambda.sqlite3
Binary file not shown.
12 changes: 12 additions & 0 deletions data/migrations/20190212185648_notesInit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

exports.up = function(knex, Promise) {
return knex.schema.createTable('notes', function (table) {
table.increments();
table.string('title').notNullable();
table.string('textBody').notNullable();
});
};

exports.down = function(knex, Promise) {
return knex.schema.dropTableIfExists('notes');
};
11 changes: 11 additions & 0 deletions data/migrations/20190213185306_tagsInit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

exports.up = function(knex, Promise) {
return knex.schema.createTable('tags', function (table) {
table.increments();
table.string('title').notNullable().unique();
});
};

exports.down = function(knex, Promise) {
return knex.schema.dropTableIfExists('tags');
};
14 changes: 14 additions & 0 deletions data/migrations/20190218124559_noteTagsInit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

exports.up = function(knex, Promise) {
return knex.schema.createTable('noteTags', function (table) {
table.increments();
table.integer('note_id').unsigned().notNullable();
table.foreign('note_id').references('id').on('notes');
table.integer('tag_id').unsigned().notNullable();
table.foreign('tag_id').references('id').on('tags');
});
};

exports.down = function(knex, Promise) {
return knex.schema.dropTableIfExists('noteTags');
};
14 changes: 14 additions & 0 deletions data/migrations/20190218214030_usersInit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
exports.up = function (knex, Promise) {
return knex.schema.createTable('users', function (table) {
table.increments();
table.string('user_name').notNullable();
table.string('email').notNullable();
table.string('name').notNullable();
table.string('password').notNullable();
table.string('role');
});
};

exports.down = function (knex, Promise) {
return knex.schema.dropTableIfExists('users');
};
20 changes: 20 additions & 0 deletions data/seeds/notes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
var loremIpsum = require('lorem-ipsum')

exports.seed = function (knex, Promise) {
return knex('notes').truncate()
.then(() => knex('tags').truncate())
.then(() => knex('noteTags').truncate())
.then(async () => {
console.log('Seeding, please wait...');

for (let i = 0; i < 499; i++) {
const
[noteId] = await knex('notes').insert({ title: `Test Note ${i + 1}`, textBody: loremIpsum() }),
[tagId] = await knex('tags').insert({ title: `tag${i + 1}` })

await knex('noteTags').insert({ note_id: noteId, tag_id: tagId })

if (i >= 498) console.log('Seeding complete')
}
})
}
Loading