Closed ruchitha007 closed 1 year ago
webserver.js const mongoose = require("mongoose"); mongoose.Promise = require("bluebird");
const async = require("async");
const express = require("express"); const app = express();
// Load the Mongoose schema for User, Photo, and SchemaInfo const User = require("./schema/user.js"); const Photo = require("./schema/photo.js"); const SchemaInfo = require("./schema/schemaInfo.js");
// XXX - Your submission should work without this line. Comment out or delete // this line for tests and before submission! //const models = require("./modelData/photoApp.js").models; mongoose.set("strictQuery", false); mongoose.connect("mongodb://127.0.0.1/project6", { useNewUrlParser: true, useUnifiedTopology: true, });
// We have the express static module // (http://expressjs.com/en/starter/static-files.html) do all the work for us. app.use(express.static(__dirname));
app.get("/", function (request, response) { response.send("Simple web server of files from " + __dirname); });
app.get("/test/:p1", function (request, response) { // Express parses the ":p1" from the URL and returns it in the request.params // objects. console.log("/test called with param1 = ", request.params.p1);
const param = request.params.p1 || "info";
if (param === "info") { // Fetch the SchemaInfo. There should only one of them. The query of {} will // match it. SchemaInfo.find({}, function (err, info) { if (err) { // Query returned an error. We pass it back to the browser with an // Internal Service Error (500) error code. console.error("Error in /user/info:", err); response.status(500).send(JSON.stringify(err)); return; } if (info.length === 0) { // Query didn't return an error but didn't find the SchemaInfo object - // This is also an internal error return. response.status(500).send("Missing SchemaInfo"); return; }
// We got the object - return it in JSON format.
console.log("SchemaInfo", info[0]);
response.end(JSON.stringify(info[0]));
});
} else if (param === "counts") { // In order to return the counts of all the collections we need to do an // async call to each collections. That is tricky to do so we use the async // package do the work. We put the collections into array and use async.each // to do each .count() query. const collections = [ { name: "user", collection: User }, { name: "photo", collection: Photo }, { name: "schemaInfo", collection: SchemaInfo }, ]; async.each( collections, function (col, done_callback) { col.collection.countDocuments({}, function (err, count) { col.count = count; done_callback(err); }); }, function (err) { if (err) { response.status(500).send(JSON.stringify(err)); } else { const obj = {}; for (let i = 0; i < collections.length; i++) { obj[collections[i].name] = collections[i].count; } response.end(JSON.stringify(obj)); } } ); } else { response.status(400).send("Bad param " + param); } });
app.get("/user/list", function (request, response) { User.find({}, "_id first_name last_name", function (err, users) { if (err) { console.error("Error in /user/list:", err); response.status(500).send(JSON.stringify(err)); } else { // Convert the users to the required format const userList = users.map(user => ({ _id: user._id, first_name: user.first_name, last_name: user.last_name, })); response.status(200).json(userList); } }); });
app.get("/user/:id", function (request, response) { const id = request.params.id; //if (user === null) { //console.log("User with _id:" + id + " not found."); //response.status(400).send("Not found"); //return; //} User.findById(id, "_id first_name last_name location description occupation", function (err, user) { if (err) { console.error("Error in /user/:id:", err); response.status(500).send(JSON.stringify(err)); } else if (!user) { response.status(400).send("User not found"); } else { response.status(200).json(user); } }); });
app.get("/photosOfUser/:id", function (request, response) { const id = request.params.id; Photo.find({ user_id: id }, function (err, photos) { if (err !== null) { response.status(400).send("error");
} else if (photos.length === 0) {
response.status(400).send("no such user photos");
} else {
var functionStack = [];
var info = JSON.parse(JSON.stringify(photos));
for (var i = 0; i < info.length; i++) {
delete info[i].__v;
var comments = info[i].comments;
comments.forEach(function (comment) {
var uid = comment.user_id;
functionStack.push(function (callback) {
User.findOne({
_id: uid
// eslint-disable-next-line no-shadow
}, function (err, result) {
if (err !== null) {
response.status(400).send("error");
} else {
var userInfo = JSON.parse(JSON.stringify(result));
var user = {
_id: uid,
first_name: userInfo.first_name,
last_name: userInfo.last_name
};
comment.user = user;
}
callback();
});
});
delete comment.user_id;
});
}
// eslint-disable-next-line no-unused-vars
async.parallel(functionStack, function (res) {
response.status(200).send(info);
});
}
}); });
const server = app.listen(3000, function () { const port = server.address().port; console.log( "Listening at http://localhost:" + port + " exporting the directory " + __dirname ); });
photoapp.js "use strict"; / jshint node: true / /*
*/ (function() { // Create fake test Schema var schemaInfo = { load_date_time: "Fri Apr 29 2016 01:45:15 GMT-0700 (PDT)", __v: 0, _id: "57231f1b30e4351f4e9f4bf6" };
// Create init users.
var im = {_id: "57231f1a30e4351f4e9f4bd7", first_name: "Ian", last_name: "Malcolm", location: "Austin, TX", description: "Should've stayed in the car.", occupation: "Mathematician"}; var er = {_id: "57231f1a30e4351f4e9f4bd8", first_name: "Ellen", last_name: "Ripley", location: "Nostromo", description: "Lvl 6 rating. Pilot.", occupation: "Warrant Officer"}; var pt = {_id: "57231f1a30e4351f4e9f4bd9", first_name: "Peregrin", last_name: "Took", location: "Gondor", description: "Home is behind, the world ahead... " + "And there are many paths to tread. Through shadow, to the edge of night, " + "until the stars are all alight... Mist and shadow, cloud and shade, " + "all shall fade... all... shall... fade... ", occupation: "Thain"}; var rk = {_id: "57231f1a30e4351f4e9f4bda", first_name: "Rey", last_name: "Kenobi", location: "D'Qar", description: "Excited to be here!", occupation: "Rebel"}; var al = {_id: "57231f1a30e4351f4e9f4bdb", first_name: "April", last_name: "Ludgate", location: "Pawnee, IN", description: "Witch", occupation: "Animal Control"}; var jo = {_id: "57231f1a30e4351f4e9f4bdc", first_name: "John", last_name: "Ousterhout", location: "Stanford, CA", description: "CS101!", occupation: "Professor"};
var users = [im, er, pt, rk, al, jo];
// Create initial photos. var photo1 = {_id: "57231f1a30e4351f4e9f4bdd", date_time: "2012-08-30 10:44:23", file_name: "ouster.jpg", user_id: jo._id}; var photo2 = {_id: "57231f1a30e4351f4e9f4bde", date_time: "2009-09-13 20:00:00", file_name: "malcolm2.jpg", user_id: im._id}; var photo3 = {_id: "57231f1a30e4351f4e9f4bdf", date_time: "2009-09-13 20:05:03", file_name: "malcolm1.jpg", user_id: im._id}; var photo4 = {_id: "57231f1a30e4351f4e9f4be0", date_time: "2013-11-18 18:02:00", file_name: "ripley1.jpg", user_id: er._id}; var photo5 = {_id: "57231f1a30e4351f4e9f4be1", date_time: "2013-09-20 17:30:00", file_name: "ripley2.jpg", user_id: er._id}; var photo6 = {_id: "57231f1a30e4351f4e9f4be2", date_time: "2009-07-10 16:02:49", file_name: "kenobi1.jpg", user_id: rk._id}; var photo7 = {_id: "57231f1a30e4351f4e9f4be3", date_time: "2010-03-18 23:48:00", file_name: "kenobi2.jpg", user_id: rk._id}; var photo8 = {_id: "57231f1a30e4351f4e9f4be4", date_time: "2010-08-30 14:26:00", file_name: "kenobi3.jpg", user_id: rk._id}; var photo9 = {_id: "57231f1a30e4351f4e9f4be5", date_time: "2013-12-03 09:02:00", file_name: "took1.jpg", user_id: pt._id}; var photo10 = {_id: "57231f1a30e4351f4e9f4be6", date_time: "2013-12-03 09:03:00", file_name: "took2.jpg", user_id: pt._id}; var photo11 = {_id: "57231f1a30e4351f4e9f4be7", date_time: "2013-09-04 09:16:32", file_name: "ludgate1.jpg", user_id: al._id}; var photo12 = {_id: "57231f1a30e4351f4e9f4be8", date_time: "2008-10-16 17:12:28", file_name: "kenobi4.jpg", user_id: rk._id};
var photos = [photo1, photo2, photo3, photo4, photo5, photo6, photo7, photo8, photo9, photo10, photo11, photo12];
// Create initial comments. var comment1 = { _id: "57231f1a30e4351f4e9f4be9", date_time: "2012-09-02 14:01:00", comment: "Learning new programming languages is hard... " + "it's so easy to forget a
var comment2 = { _id: "57231f1a30e4351f4e9f4bea", date_time: "2013-09-06 14:02:00", comment: "This is another comment, with a bit more text; " + "if the text gets long enough, does it wrap properly " + "from line to line?", user: jo, photo_id: photo1._id };
var comment3 = { _id: "57231f1a30e4351f4e9f4beb", date_time: "2013-09-08 14:06:00", comment: "If you see this text in boldface " + "then HTML escaping isn't working properly.", user: jo, photo_id: photo1._id };
var comment4 = { _id: "57231f1a30e4351f4e9f4bec", date_time: "2009-09-14 18:07:00", comment: "If there is one thing the history of evolution has" + " taught us it's that life will not be contained. Life breaks " + "free, it expands to new territories and crashes through " + "barriers, painfully, maybe even dangerously, but, uh... well, " + "there it is. Life finds a way.", user: im, photo_id: photo2._id };
var comment5 = { _id: "57231f1a30e4351f4e9f4bed", date_time: "2013-11-28 17:45:13", comment: "Back from my trip. Did IQs just... drop sharply while I was " + "away?", user: er, photo_id: photo5._id };
var comment6 = { _id: "57231f1a30e4351f4e9f4bee", date_time: "2013-11-02 14:07:00", comment: "Hey Rey, great form. Love what " + "you do with the scavenged tech, got any tips?", user: er, photo_id: photo7._id };
var comment7 = { _id: "57231f1a30e4351f4e9f4bef", date_time: "2013-11-02 14:07:00", comment: "Definitely! I love your work! I'm away on a trip at " + "the moment, but let's meet up when I get back! :)", user: rk, photo_id: photo7._id };
var comment8 = { _id: "57231f1a30e4351f4e9f4bf0", date_time: "2010-09-06 13:59:33", comment: "Made a new friend today! Well, they followed me " + "home, anyway.", user: rk, photo_id: photo8._id };
var comment9 = { _id: "57231f1a30e4351f4e9f4bf1", date_time: "2008-10-16 18:04:55", comment: "Wouldn't get anywhere without this beauty! " + "Completely built from scraps by hand, but she goes at top " + "speeds that'll rival any First Order piece of junk.", user: rk, photo_id: photo12._id };
var comment10 = { _id: "57231f1a30e4351f4e9f4bf2", date_time: "2013-12-04 13:12:00", comment: "What do you mean you haven't heard of second " + "breakfast?", user: pt, photo_id: photo10._id };
var comment11 = { _id: "57231f1a30e4351f4e9f4bf3", date_time: "2013-09-04 10:14:32", comment: "Beautiful yet cold and aloof. Loner. Does not obey, " + "occasionally chooses to cooperate. ", user: al, photo_id: photo11._id };
var comment12 = { _id: "57231f1a30e4351f4e9f4bf4", date_time: "2016-01-04 2:00:01", comment: "Which one are you?", user: al, photo_id: photo9._id };
var comment13 = { _id: "57231f1a30e4351f4e9f4bf5", date_time: "2016-01-04 2:04:01", comment: "The tall one.", user: pt, photo_id: photo9._id };
var comments = [comment1, comment2, comment3, comment4, comment5, comment6, comment7, comment8, comment9, comment10, comment11, comment12, comment13];
comments.forEach(function (comment) { var photo = photos.filter(function (photo) { return (photo._id === comment.photo_id); })[0]; //only one match. return the content of the match inside the array
if (!photo.comments) { photo.comments = []; } photo.comments.push(comment); });
var userListModel = function() { return users; };
var userModel = function(userId) { for (var i = 0; i < users.length; i++) { if (users[i]._id === userId) { return users[i]; } } return null; };
var photoOfUserModel = function(userId) { return photos.filter(function (photo) { return (photo.user_id === userId); }); };
var schemaModel = function() { return schemaInfo; };
var models = { userListModel: userListModel, userModel: userModel, photoOfUserModel: photoOfUserModel, schemaInfo: schemaModel };
if( typeof exports !== 'undefined' ) { // We're being loaded by the Node.js module loader ('require') so we use its // conventions of returning the object in exports. exports.models = models; } else { // We're not in the Note.js module loader so we assume we're being loaded // by the browser into the DOM. window.models = models; } })();
I've completed the development tasks for the database integration. All references to magic models have been removed, and MongoDB schemas/models are in place. The API routes have been implemented as specified, and object cloning through JSON serialization is working. Ready for code review.
As a developer, I want the assignee to convert the web server to use the MongoDB database instead of magic models. This will ensure that the application fetches data from a database, eliminating dependencies on magic models and conforming to the specified API.
Acceptance criteria :
Update webServer.js to remove all references to magic models, including the line: var models = require('./modelData/photoApp.js').models;
Create MongoDB schemas and models for users and photos.
Implement API route '/test' to return schema information and object counts from the MongoDB database.
Develop API route '/user/list' to return a list of user properties suitable for the navigation sidebar, including '_id', 'first_name', and 'last_name'.
Implement API route '/user/:id' to provide detailed user information for a given user ID, including '_id', 'first_name', 'last_name', 'location', 'description', and 'occupation'. Handle invalid user IDs with a 400 HTTP status response and an informative message.
Develop API route '/photosOfUser/:id' to return user photos and comments, including '_id', 'user_id', 'comments', 'file_name', and 'date_time'. Ensure comments include 'comment', 'date_time', '_id', and 'user' with minimal user information. Handle invalid user IDs with a 400 HTTP status response and an informative message.
Ensure that the responses align with the needs of the UI views without altering the database schema.
Implement object cloning using JSON serialization to create copies of MongoDB models without Mongoose-specific modifications.