diff --git a/ng1/config.json b/ng1/config.json new file mode 100644 index 0000000..233b803 --- /dev/null +++ b/ng1/config.json @@ -0,0 +1,3 @@ +{ + "mongoUrl": "mongodb://i399:salakala@i399-shard-00-00-otrzj.mongodb.net:27017,i399-shard-00-01-otrzj.mongodb.net:27017,i399-shard-00-02-otrzj.mongodb.net:27017/contacts?ssl=true&replicaSet=i399-shard-0&authSource=admin" +} diff --git a/ng1/dao.js b/ng1/dao.js new file mode 100644 index 0000000..4ce42ff --- /dev/null +++ b/ng1/dao.js @@ -0,0 +1,58 @@ +'use strict'; + +const mongodb = require('mongodb'); +const ObjectID = require('mongodb').ObjectID; +const COLLECTION = 'contacts'; + +class Dao { + + connect(url) { + return mongodb.MongoClient.connect(url) + .then(db => this.db = db); + } + + findAll() { + return this.db.collection(COLLECTION).find().toArray(); + } + + findById(id) { + id = new ObjectID(id); + return this.db.collection(COLLECTION).findOne({_id:id}); + } + + update(id, data) { + id = new ObjectID(id); + data._id = id + return this.db.collection(COLLECTION) + .updateOne({_id:id}, data); + } + + insert(data) { + return this.db.collection(COLLECTION) + .insertOne(data); + } + + remove(id) { + id = new ObjectID(id); + return this.db.collection(COLLECTION) + .remove({_id:id}) + } + + removeMany(idList) { + var objectIds = []; + for (let id of idList) { + objectIds.push(new ObjectID(id)) + } + + return this.db.collection(COLLECTION) + .remove({_id: {$in: objectIds}}) + } + + close() { + if (this.db) { + this.db.close(); + } + } +} + +module.exports = Dao; diff --git a/ng1/http-cat.js b/ng1/http-cat.js new file mode 100644 index 0000000..08fa810 --- /dev/null +++ b/ng1/http-cat.js @@ -0,0 +1,18 @@ +// Express middelware for adding X-Http-Cat header using http.cat api from +// https://http.cat/ + +function middelware (req, res, next) { + var _writeHead = res.writeHead + res.writeHead = function(status) { + res.setHeader('X-Http-Cat', 'https://http.cat/' + status) + _writeHead.apply(res, arguments) + } + + next() +} + + +module.exports = function(){ + return middelware; +} + diff --git a/ng1/package.json b/ng1/package.json index 9791f79..14e42db 100644 --- a/ng1/package.json +++ b/ng1/package.json @@ -8,6 +8,7 @@ "body-parser": "^1.17.1", "express": "^4.15.2", "morgan": "^1.8.2", + "mongodb": "^2.2.28", "nodemon": "^1.11.0" } } diff --git a/ng1/server.js b/ng1/server.js index bd0b1ac..e700e33 100644 --- a/ng1/server.js +++ b/ng1/server.js @@ -3,9 +3,16 @@ const express = require('express'); const bodyParser = require('body-parser'); const morgan = require('morgan'); +const ObjectID = require('mongodb').ObjectID; +const HttpCat = require('./http-cat.js') +const Dao = require('./dao.js'); +const config = require('./config.json'); + +const dao = new Dao(); const app = express(); +app.use(HttpCat()); app.use(morgan('dev')); app.set('etag', false); app.use(bodyParser.json()); // before request handlers @@ -16,122 +23,128 @@ app.get('/api/contacts', getContacts); app.get('/api/contacts/:id', getContact); app.post('/api/contacts', addContact); app.put('/api/contacts/:id', changeContact); -app.post('/api/contacts/delete', deleteMultibleContact); +app.post('/api/contacts/delete', deleteMultibleContacts); app.delete('/api/contacts/:id', deleteContact); -var contacts = [ - { - "_id": 1, - "name": "Jack", - "phone": "123" - }, - { - "_id": 2, - "name": "Jill", - "phone": "456" - }, - { - "_id": 3, - "name": "Mary", - "phone": "789" - } -] -var lastContactId = 3; - app.use(errorHandler); // after request handlers -app.listen(3000, () => console.log('Server is running on port 3000')); +dao.connect(config.mongoUrl) +.then(() => { + app.listen(3000, () => console.log('Server is running on port 3000')); +}).catch(err => { + console.log("MongoDB connection failed: "); + console.log(err) + process.exit(1); +}) + function errorHandler(error, request, response, next) { // there must be 4 arguments + console.log(error) response.status(500).send('error: ' + error.toString()); } function getContacts(req, resp) { - resp.set('Content-Type', 'application/json'); - resp.json(contacts); + dao.findAll().then(data => resp.json(data)); } function getContact(req, resp) { var id = req.params.id; - resp.set('Content-Type', 'application/json'); - for (let contact of contacts) { - if (contact._id == id) { - resp.json(contact); - return; - } + + if (!ObjectID.isValid(id)) { + resp.status(400).json("Invalid id"); + return; } - resp.status(404).end("Contact Not Found"); + + dao.findById(id).then(data => { + resp.json(data); + }).catch(err => { + console.log(err); + resp.status(404).json(err.toString()); + }); } -function addContact(req, resp) { +function addContact(req, resp, next) { var contact = req.body; + if (contact.name == null ) { + resp.status(400).json("Can't add a contact without a name"); + return; + } + var sanitizedContact = { - "_id": ++lastContactId, "name": contact.name, "phone": contact.phone } - contacts.push(sanitizedContact) - - resp.status(200).json(sanitizedContact); + dao.insert(sanitizedContact).then((data) => { + resp.status(201); + resp.location("/api/contacts/"+data.insertedId); + dao.findById(data.insertedId).then(insertedContact => { + resp.json(insertedContact); + }); + }).catch(err => { + console.log(err); + next(err); + }) } function changeContact(req, resp) { var id = req.params.id; - var changedContact = req.body; + var contact = req.body; - for (let contact of contacts) { - if (contact._id == id) { - contact.name = changedContact.name; - contact.phone = changedContact.phone - resp.status(200).end("Changed"); - return; - } + if (!ObjectID.isValid(id)) { + resp.status(400).json("Invalid id"); + return; } - resp.status(404).end("Contact Not Found"); + + if (contact.name == null) { + resp.status(400).json("Contact must have a name"); + return; + } + + var sanitizedContact = { + "name": contact.name, + "phone": contact.phone + } + + dao.update(id, sanitizedContact).then(data => { + resp.status(200).end("Changed"); + }).catch(err => { + console.log(err); + resp.status(404).end("Contact Not Found"); + }); + } function deleteContact(req, resp) { var id = req.params.id; - for (let i=0; i < contacts.length; i++){ - var contact = contacts[i]; - if (contact._id == id){ - contacts.splice(i, 1); - resp.status(200).end("Deleted"); + if (!ObjectID.isValid(id)) { + resp.status(400).json("Invalid id"); + return; + } + + dao.remove(id).then(data => { + resp.status(200).json("Deleted"); + }).catch(err => { + console.log(err); + resp.status(404).end("Contact Not Found"); + }) +} + +function deleteMultibleContacts(req, resp) { + var contactIds = req.body; + + for (let id of contactIds) { + if (!ObjectID.isValid(id)) { + resp.status(400).json("Invalid ID in the list"); return; } } - resp.status(404).end("Contact Not Found"); -} - -function deleteMultibleContact(req, resp) { - var contactIds = req.body; - var invalidIds = []; - - while (true){ - let id = contactIds.pop() - if (!id){ - break; - } - for (let i=0; i < contacts.length; i++){ - var contact = contacts[i]; - if (contact._id == id){ - contacts.splice(i, 1); - id = null; - } - } - - if (id){ - invalidIds.push(id); - } - } - - if(invalidIds.length == 0){ - resp.status(200).end("Deleted"); - } else { - resp.status(404); - resp.json(invalidIds); - } + dao.removeMany(contactIds).then(data => { + resp.status(200).json("Deleted"); + }).catch(err => { + console.log(err); + resp.status(400).json("Failed to delete some or all of the contacts" + err.toString()); + }) }