diff options
| author | nanalelfe <nargiza.nosirova@mail.utoronto.ca> | 2016-07-25 23:36:16 +0000 |
|---|---|---|
| committer | nanalelfe <nargiza.nosirova@mail.utoronto.ca> | 2016-07-25 23:36:16 +0000 |
| commit | 0d8073039faa903ee0f12e68064c89b5f27cdf14 (patch) | |
| tree | 221688160f73edd753a35d3d240022154078ee88 | |
| parent | 9f1b0d9f1c807e02a415b5b8a2509dc6445f08b3 (diff) | |
| parent | 10f1c442e27d82d1fc2c94d1bc0a2ad27917b287 (diff) | |
Merge branch 'master' of https://github.com/HumairAK/solutions_repo
| -rw-r--r-- | .idea/misc.xml | 13 | ||||
| -rw-r--r-- | node_simple.js | 13 | ||||
| -rw-r--r-- | routes/admin.js | 320 | ||||
| -rw-r--r-- | routes/index.js | 15 | ||||
| -rw-r--r-- | views/admin.hbs | 24 | ||||
| -rw-r--r-- | views/public_profile.hbs | 77 | ||||
| -rw-r--r-- | views/user_search.hbs | 11 |
7 files changed, 379 insertions, 94 deletions
diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..72abef0 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="ProjectLevelVcsManager" settingsEditedManually="false"> + <OptionsSetting value="true" id="Add" /> + <OptionsSetting value="true" id="Remove" /> + <OptionsSetting value="true" id="Checkout" /> + <OptionsSetting value="true" id="Update" /> + <OptionsSetting value="true" id="Status" /> + <OptionsSetting value="true" id="Edit" /> + <ConfirmationsSetting value="0" id="Add" /> + <ConfirmationsSetting value="0" id="Remove" /> + </component> +</project>
\ No newline at end of file diff --git a/node_simple.js b/node_simple.js index 165eb22..596cef6 100644 --- a/node_simple.js +++ b/node_simple.js @@ -320,7 +320,7 @@ exports.retrieveFollows = function (user_name, callback) { * course_code, year, term}. * Note: a comment should only exist IF a solution exists. * - * @param {string} user_name: the unique user name for the user + * @param {string} username: the unique user name for the user * @param {function} callback: with 2 args: (boolean, <string>), * where boolean : err ? false : true * where <string> can be error message @@ -380,7 +380,7 @@ exports.retrieve_userComments_history = function (username, callback) { * IF we dont wanna go that route, need to update these fields whenever they are altered * by the user manually. * - * @param {string} user_name: the unique user name for the user + * @param {string} username: the unique user name for the user * @param {function} callback: with 2 args: (boolean, <string>), * where boolean : err ? false : true * where <string> can be error message @@ -402,7 +402,7 @@ exports.retrieve_userComments_count = function (username, callback) { * This function will retrieve ALL the solutions a user has ever provided. * It returns an array containing objects of the solution form. * - * @param {string} user_name: the unique user name for the user + * @param {string} username: the unique user name for the user * @param {function} callback: with 2 args: (boolean, <string>), * where boolean : err ? false : true * where <string> can be error message @@ -432,7 +432,7 @@ exports.retrieve_userSolutions_history = function (username, callback) { * IF we dont wanna go that route, need to update these fields whenever they are altered * by the user manually. * - * @param {string} user_name: the unique user name for the user + * @param {string} username: the unique user name for the user * @param {function} callback: with 2 args: (boolean, <string>), * where boolean is false if err OR true if no error * where <string> can be error message @@ -715,7 +715,7 @@ exports.get_exam_info_by_ID = function (exam_id, callback) { * * @param {string} sol_id: id of the solution to which to add the comment * @param {string[]} fields: <[text, by_username]> - * @param {function} callback: with args (<bool>,<string>) + * @param {function} serverCallback: with args (<bool>,<string>) * where <bool> : err ? false : true * where <string> : err ? err_mssg : success_mssg * */ @@ -760,6 +760,7 @@ exports.add_comment = function (sol_id, fields, serverCallback) { /** * This function will get all the solution for a given exam_id and q_num + * sorted by highest to lowest votes. * * @param {string} exam_id: exam_id for which the info is required. * @param {int} q_num: the question number for which solutions are required. @@ -776,7 +777,7 @@ exports.get_all_solutions = function (exam_id, q_num, callback) { exam_id: exam_id, q_id: q_num } - ).toArray( function (err, docs) { + ).sort({ votes: -1}).toArray( function (err, docs) { if (err) throw err; else { callback(docs); diff --git a/routes/admin.js b/routes/admin.js index 24c5910..565d2dd 100644 --- a/routes/admin.js +++ b/routes/admin.js @@ -4,115 +4,250 @@ var router = express.Router(); var csrf = require('csurf'); // Cross-Site Request Forgery prevention var passport = require('passport'); var passport_file = require('../config/passport.js'); - +var express_validator = require ("express-validator"); +app = express(); var csrfProtection = csrf(); router.use(csrfProtection); // router is protected +app.use(express_validator({ + customValidators:{ + validRadio: function (value) { + if (value==undefined){ + return false; + }else{ + return true; + } + },isCommaSeparated: function(value){ + if (value.match(/[^,\s][^\,]*[^,\s]*/g)){ + return true; + }else{ + return false; + } + },isValidDate:function (value) { + if (value.match(/^(?:(?:31(\/|-|\.)(?:0?[13578]|1[02]))\1|(?:(?:29|30)(\/|-|\.)(?:0?[1,3-9]|1[0-2])\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.)0?2\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\d|2[0-8])(\/|-|\.)(?:(?:0?[1-9])|(?:1[0-2]))\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$/)){ + return true; + }else{ + return false; + } + } + } +})); + router.get('/', isAdmin, function(req,res){ console.log(req.session.messages); - res.render('admin', {csrfToken: req.csrfToken()}); + res.render('admin', {csrfToken: req.csrfToken(), success: req.session.success, errors: req.session.errors}); + req.session.errors = null; req.session.messages = null; }); /* Adds exam from front-end */ router.post('/add/exam', function(req,res){ - var course_code = req.body.course_code, - year = req.body.year, - type = req.body.type, - term = req.body.term, - instructors = parseStringArray(req.body.instructors), - page_count = req.body.page_count, - questions_count = req.body.questions_count, - questions_list = parseStringArray(req.body.questions_list), - upload_date = req.body.upload_date, - uploaded_by = req.body.uploaded_by; - - var fields = [ - course_code, // String - year, // Int - term, // String - type, // String - instructors, // Array of strings - page_count, // Int - questions_count, // Int - upload_date, // String - uploaded_by]; // String - - dbFile.add_exam(fields, questions_list, function(examAdded, statusMsg){ - if(examAdded){ - req.session.messages = {success : statusMsg}; - }else{ - req.session.messages = {error : statusMsg}; - } - console.log(statusMsg); + req.sanitize('course_code').escape(); + req.sanitize('course_code').trim(); + req.check('course_code','Course code cannot be empty').notEmpty(); + + req.sanitize('year').escape(); + req.sanitize('year').trim(); + req.check('year','Invalid year').isInt(); + + req.checkBody('type','Please select a type of exam').validRadio(); + req.checkBody('term','Please select a term for the exam').validRadio(); + + req.sanitize('instructors').trim(); + req.check('instructors','Invalid instructors format').isCommaSeparated(); + + req.sanitize('page_count').trim(); + req.check('page_count','Invalid page count').isInt(); + + req.sanitize('questions_count').trim(); + req.check('questions_count','Invalid questions count').isInt(); + + req.sanitize('questions_list').trim(); + req.check('questions_list','Invalid questions format').isCommaSeparated(); + + req.sanitize('upload_date').trim(); + req.check('upload_date','Invalid date format').isValidDate(); + + req.sanitize('uploaded_by').trim(); + req.sanitize('uploaded_by').escape(); + req.check('uploaded_by','Invalid user name format').notEmpty(); + + var errors = req.validationErrors(); + + if (errors){ + console.log(errors); + req.session.errors = errors; + req.session.success = false; res.redirect('/admin'); - }); + }else{ + + var course_code = req.body.course_code, + year = req.body.year, + type = req.body.type, + term = req.body.term, + instructors = parseStringArray(req.body.instructors), + page_count = req.body.page_count, + questions_count = req.body.questions_count, + questions_list = parseStringArray(req.body.questions_list), + upload_date = req.body.upload_date, + uploaded_by = req.body.uploaded_by; + + var fields = [ + course_code, // String + year, // Int + term, // String + type, // String + instructors, // Array of strings + page_count, // Int + questions_count, // Int + upload_date, // String + uploaded_by]; // String + dbFile.add_exam(fields, questions_list, function(examAdded, statusMsg){ + if(examAdded){ + req.session.messages = {success : statusMsg}; + }else{ + req.session.messages = {error : statusMsg}; + } + console.log(statusMsg); + res.redirect('/admin'); + }); + } }); /* Adds course from front-end */ router.post('/add/course', function(req,res){ - var course_code = req.body.course_code, - title = req.body.title; - - dbFile.add_course(course_code, title, function(courseAdded, statusMsg){ - if(courseAdded){ - req.session.messages = {success : statusMsg}; - }else{ - req.session.messages = {error : statusMsg}; - } - console.log(statusMsg); + + req.sanitize('course_code').escape(); + req.sanitize('course_code').trim(); + req.check('course_code','Course code cannot be empty').notEmpty(); + + req.sanitize('title').escape(); + req.sanitize('title').trim(); + req.check('title','Invalid title').isAlpha(); + + var errors = req.validationErrors(); + + if (errors){ + console.log(errors); + req.session.errors = errors; + req.session.success = false; res.redirect('/admin'); - }); + }else{ + var course_code = req.body.course_code, + title = req.body.title; + dbFile.add_course(course_code, title, function(courseAdded, statusMsg){ + if(courseAdded){ + req.session.messages = {success : statusMsg}; + }else{ + req.session.messages = {error : statusMsg}; + } + console.log(statusMsg); + res.redirect('/admin'); + }); + } }); /* Add a new admin, redirect to admin panel */ router.post('/add/admin', function(req,res){ - var admin_data = { - fname: req.body.fname, - lname: req.body.lname, - username: req.body.username, - password: passport_file.encryptPassword(req.body.password) - }; - - dbFile.addAdmin(admin_data, function(success, error, statusMsg){ - if(success){ - req.session.messages = {success : statusMsg}; - }else{ - req.session.messages = {error : statusMsg}; - } - console.log(statusMsg); + req.assert('fname', 'Please enter a valid first name.').notEmpty().withMessage('First name required.').isAlpha(); + req.check('lname', 'Please enter a valid first name.').notEmpty().withMessage('Last name required.').isAlpha(); + req.check('usrname', 'Enter a valid username').notEmpty().withMessage('Username required.'); + req.check('password', "Password should be between 6 and 12 characters.") + .notEmpty().withMessage('Password required').isLength({min: 6, max: 12}); + + var errors = req.validationErrors(); + if (errors) { + console.log(errors); + req.session.errors = errors; + req.session.success = false; res.redirect('/admin'); - }); + }else{ + var admin_data = { + fname: req.body.fname, + lname: req.body.lname, + username: req.body.username, + password: passport_file.encryptPassword(req.body.password) + }; + + dbFile.addAdmin(admin_data, function(success, error, statusMsg){ + if(success){ + req.session.messages = {success : statusMsg}; + }else{ + req.session.messages = {error : statusMsg}; + } + console.log(statusMsg); + res.redirect('/admin'); + }); + + } }); /* Remove an exam route, redirect to admin panel */ router.post('/remove/exam', function(req,res){ - var course_code = req.body.course_code, - year = req.body.year, - term = req.body.term, - type = req.body.type, - campus = req.body.campus; - - var fields = [course_code, year, term, type]; - - dbFile.remove_exam(fields, function(examRemoved, statusMsg){ - if(examRemoved){ - req.session.messages = {success : statusMsg}; - } else { - req.session.messages = {error : statusMsg}; - } - console.log(statusMsg); + req.sanitize('course_code').escape(); + req.sanitize('course_code').trim(); + req.check('course_code','Course code cannot be empty').notEmpty(); + + req.sanitize('year').escape(); + req.sanitize('year').trim(); + req.check('year','Invalid year').isInt(); + + req.checkBody('type','Please select a type of exam').validRadio(); + req.checkBody('term','Please select a term for the exam').validRadio(); + req.checkBody('campus','Please select a campus for the exam').validRadio(); + + + var errors = req.validationErrors(); + if (errors){ + console.log(errors); + req.session.errors = errors; + req.session.success = false; res.redirect('/admin'); - }); + + }else{ + + var course_code = req.body.course_code, + year = req.body.year, + term = req.body.term, + type = req.body.type, + campus = req.body.campus; + + course_code = course_code.toUpperCase(); + + var fields = [course_code, year, term, type]; + + dbFile.remove_exam(fields, function(examRemoved, statusMsg){ + if(examRemoved){ + req.session.messages = {success : statusMsg}; + } else { + req.session.messages = {error : statusMsg}; + } + console.log(statusMsg); + res.redirect('/admin'); + }); + } }); /* Remove a course route, redirect to admin panel */ router.post('/remove/course', function(req,res){ - var course_code = req.body.course_code; - dbFile.remove_course(course_code, function(courseRemoved, statusMsg){ + + req.sanitize('course_code').escape(); + req.sanitize('course_code').trim(); + req.check('course_code','Course code cannot be empty').notEmpty(); + + var errors = req.validationErrors(); + + if (errors){ + req.session.errors = errors; + req.session.success = false; + res.redirect('/admin'); + }else{ + var course_code = req.body.course_code; + course_code = course_code.toUpperCase(); + dbFile.remove_course(course_code, function(courseRemoved, statusMsg){ if(courseRemoved){ req.session.messages = {success : statusMsg}; } else { @@ -121,21 +256,34 @@ router.post('/remove/course', function(req,res){ console.log(statusMsg); res.redirect('/admin'); }); + } + }); /* Remove a user route, redirect to admin panel */ router.post('/remove/user', function(req,res){ - var username = req.body.username; - dbFile.remove_user(username, function(userRemoved, statusMsg){ - if(userRemoved){ - req.session.messages = {success : statusMsg}; - } else { - req.session.messages = {error : statusMsg}; - } - console.log(statusMsg); - res.redirect('/admin'); - }); + req.sanitize('username').trim(); + req.sanitize('username').escape(); + req.check('username','Invalid user name format').notEmpty(); + + var errors = validationErrors(); + if (errors){ + req.session.errors = errors; + req.session.success = false; + res.redirect('/admin'); + }else{ + var username = req.body.username; + dbFile.remove_user(username, function(userRemoved, statusMsg){ + if(userRemoved){ + req.session.messages = {success : statusMsg}; + } else { + req.session.messages = {error : statusMsg}; + } + console.log(statusMsg); + res.redirect('/admin'); + }); + } }); diff --git a/routes/index.js b/routes/index.js index 6218dd1..347c91a 100644 --- a/routes/index.js +++ b/routes/index.js @@ -24,6 +24,20 @@ router.get('/about', function(req, res, next) { res.render('about'); }); +/* Router for rendering public user profile of a given user */ +router.get('/public_profile/:username', function(req,res,next){ + var username = req.params.username; + dbFile.retrieveUser(username, function(success, error, user, statusMsg){ + if(success){ + res.render('public_profile.hbs', {user: user}); + }else{ + req.session.messages = {error : statusMsg}; + res.redirect('/user/' + username); + } + }); + +}); + /* Render/GET user_solutions page */ router.get('/user_solutions', function(req, res, next) { res.render('user_solutions'); @@ -84,6 +98,7 @@ router.get('/user/:query', function(req,res,next){ if(success){ console.log(result); res.render('user_search', {users : result, query : query}); + req.session.messages = null; }else{ console.log(result); res.redirect('/'); diff --git a/views/admin.hbs b/views/admin.hbs index 12c2ba9..6b1f6af 100644 --- a/views/admin.hbs +++ b/views/admin.hbs @@ -2,7 +2,7 @@ <div class="container"> <div class="row"> <!-- Admin control Panel ---> -<div class="col-xs-12 col-sm-12 col-md-8 col-md-offset-2 col-xs-offset-0 col-sm-offset-0 toppad cpnl-details"> +<div class="col-xs-12 col-sm-12 col-md-8 col-md-offset-2 col-xs-offset-0 col-sm-offset-0 toppad cpnl-sidetails"> {{# if messages.success }} <section class="alert alert-success custom-Alert"> <!-- Change those to banners later --> @@ -16,6 +16,28 @@ {{/if}} {{/if}} + {{# if success }} + <section class="alert alert-success"> + <!-- Change those to banners later --> + <h2>Signup Successful!</h2> + </section> + {{ else }} + {{# if errors }} + <section class="alert alert-danger"> + <ul> + {{# each errors }} + <li>{{ this.msg }}</li> + {{/each}} + </ul> + </section> + {{/if}} + {{/if}} + {{#if flashMsg}} + <section class="alert alert-danger"> + {{flashMsg}} + </section> + {{/if}} + <!-- Admin Control Panel Menu --> <nav class="navbar navbar-custom"> <div class="container-fluid"> diff --git a/views/public_profile.hbs b/views/public_profile.hbs new file mode 100644 index 0000000..d43cc66 --- /dev/null +++ b/views/public_profile.hbs @@ -0,0 +1,77 @@ +<main id="solutions-main"> + <div class="container user-info-content"> + <div class="row"> + + <!-- User Profile details --> + <div class="col-xs-12 col-sm-12 col-md-8 + col-md-offset-2 col-xs-offset-0 col-sm-offset-0 toppad prf-details"> + + + <div class="rounded"> + <div class="panel panel-info rounded"> + <div class="panel-heading"> + <h3 class="panel-title">{{ user.f_name }} {{ user.l_name }}</h3> + </div> + <div class="panel-body"> + <!--- User-Profile Pages --> + <div class="row" id="profile-general"> + <!-- User Image --> + <div class="col-md-3 col-lg-3 " align="center"> + <img alt="User Pic" src="../assets/images/avatar.png" + class="img-circle img-responsive"> + </div> + <!-- User Details --> + <div class=" col-md-9 col-lg-9 "> + <table class="table table-user-information"> + <tbody> + <tr> + <td>Username:</td> + <td>{{ user.user_name }}</td> + </tr> + <tr> + <td>Email:</td> + <td><a href="{{ user.email }}">{{ user.email }}</a></td> + </tr> + {{# if user.university }} + <tr> + <td>University:</td> + <td>{{ user.university }}</td> + </tr> + {{/if}} + {{# if user.department }} + <tr> + <td>Department:</td> + <td>{{ user.department }}</td> + </tr> + {{/if}} + <tr> + <td>Answered:</td> + <td>{{ user.answered }}</td> + </tr> + <tr> + <tr> + <td>Messages:</td> + <td>{{ user.messages }}</td> + </tr> + <tr> + <td>Comments:</td> + <td>{{ user.comments }}</td> + </tr> + </tbody> + </table> + </div> + </div> + <!-- Date, Edit, Logout (new row) --> + <div class="col-md-12 prf-sign-off"> + <p class=" text-info"> July 4 2016 </p> + <br> + </div> + </div> + </div> + </div> + + </div> + + </div> + </div> +</main>
\ No newline at end of file diff --git a/views/user_search.hbs b/views/user_search.hbs index fd08e84..59c9435 100644 --- a/views/user_search.hbs +++ b/views/user_search.hbs @@ -1,9 +1,18 @@ <main id = 'solutions-main'> <div class = 'search container' id = 'solutions-div'> + + <!--- Check to see if something went wrong db end ---> + {{# if messages.error }} + <section class="alert alert-danger custom-Alert"> + <h4>{{ messages.error }}</h4> + </section> + {{/if}} + + <h4 class='search-head'>Search results for "{{query}}"</h4> {{# if users }} {{# each users}} - <a href="/public_profile/{{this._id}}"> + <a href="/public_profile/{{this.user_name}}"> <section class = 'solutions-card'> <h3 class = 'solutions-title'>{{this.user_name}}</h3> <p class = 'solutions-time' > |
