aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornanalelfe <nargiza.nosirova@mail.utoronto.ca>2016-07-25 23:36:16 +0000
committernanalelfe <nargiza.nosirova@mail.utoronto.ca>2016-07-25 23:36:16 +0000
commit0d8073039faa903ee0f12e68064c89b5f27cdf14 (patch)
tree221688160f73edd753a35d3d240022154078ee88
parent9f1b0d9f1c807e02a415b5b8a2509dc6445f08b3 (diff)
parent10f1c442e27d82d1fc2c94d1bc0a2ad27917b287 (diff)
Merge branch 'master' of https://github.com/HumairAK/solutions_repo
-rw-r--r--.idea/misc.xml13
-rw-r--r--node_simple.js13
-rw-r--r--routes/admin.js320
-rw-r--r--routes/index.js15
-rw-r--r--views/admin.hbs24
-rw-r--r--views/public_profile.hbs77
-rw-r--r--views/user_search.hbs11
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' >