├── .gitignore ├── .idea ├── Library-Management-System.iml ├── modules.xml └── vcs.xml ├── README.md ├── config └── default.js ├── index.js ├── lib └── mongo.js ├── middlewares └── check.js ├── models ├── borrowBooks.js ├── library.js └── users.js ├── package-lock.json ├── package.json ├── public ├── css │ ├── common.css │ ├── semantic.min.css │ └── themes │ │ ├── basic │ │ └── assets │ │ │ └── fonts │ │ │ ├── icons.eot │ │ │ ├── icons.svg │ │ │ ├── icons.ttf │ │ │ └── icons.woff │ │ └── default │ │ └── assets │ │ ├── fonts │ │ ├── icons.eot │ │ ├── icons.otf │ │ ├── icons.svg │ │ ├── icons.ttf │ │ ├── icons.woff │ │ └── icons.woff2 │ │ └── images │ │ └── flags.png ├── img │ ├── upload_3424d6994a994d4340ab043b0717d6a4.jpg │ ├── upload_4c1fdd5646bd120237aaa5ffe7ddd40d.jpg │ ├── upload_60d2f41215d11b1d20d57bb3dc65c131.jpeg │ ├── upload_637c32ec1ab0534d2fb4f090a504c556.jpg │ └── upload_71930cd725a347a06009b3061468f7aa.jpeg └── js │ ├── jquery-3.2.1.min.js │ └── semantic.min.js ├── routes ├── borrow.js ├── home.js ├── index.js ├── library.js ├── post.js ├── profile.js ├── quick_borrow.js ├── search.js ├── signin.js ├── signout.js ├── signup.js └── users.js └── views ├── 404.ejs ├── book.ejs ├── borrow.ejs ├── error.ejs ├── home.ejs ├── layout ├── footer.ejs ├── header.ejs ├── nav-setting.ejs ├── nav.ejs └── notification.ejs ├── library.ejs ├── profile.ejs ├── quick_borrow.ejs ├── signin.ejs ├── signup.ejs └── users.ejs /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | -------------------------------------------------------------------------------- /.idea/Library-Management-System.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Online Library System 2 | 3 | ### Implemented following major functionalities: 4 | - User signup: Register a new user to the system. 5 | - Check the new username or email address if it’s already registered to the system. 6 | - Form validation: Check if all mandatory fields are filled out. 7 |  - Check if password is strong enough. Define the rules of having a strong password. User passwords will be hashed and hashed version of passwords will be stored in the database. 8 | - User login 9 | - List available books in the system. User can filter the results based on at least one criterion (i.e. Book's name). Also, can “Search” for a specific item. 10 | - Implemented Favorites function. 11 | - For Admin user(s): 12 | - List all items 13 | - Add new item 14 | - Delete item 15 | - Update item 16 | - For delete, soft-delete should be implemented. 17 | 18 | ### Frond-end Design 19 | HTML5, CSS, Bootstrap. 20 | 21 | ### Back-end Design 22 | Node.JS, MongoDB. 23 | 24 | ### How to run the project 25 | - Install mongo, node js, npm. 26 | - Use npm to install all node_modules showed in json file. 27 | - In terminal, run `mongod` to start mongo. 28 | - In GUI, create a new db connnection, default port is 27017 or access mongodb in terminal, open another window, run `mongo`. 29 | - Run `node index` under project folder, go to your browser, http://localhost:port/. 30 | -------------------------------------------------------------------------------- /config/default.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | port: 3000, 3 | session: { 4 | secret: 'libraryManagemengtSys', 5 | key: 'librarySys', 6 | maxAge: 2592000000 7 | }, 8 | mongodb: 'mongodb://localhost:27017/library_system' 9 | } -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var express = require('express'); 3 | var session = require('express-session'); 4 | var MongoStore = require('connect-mongo')(session); 5 | var flash = require('connect-flash'); 6 | var config = require('config-lite')(__dirname); 7 | var routes = require('./routes'); 8 | var pkg = require('./package'); 9 | var winston = require('winston'); 10 | var expressWinston = require('express-winston'); 11 | 12 | var app = express(); 13 | 14 | 15 | app.set('views', path.join(__dirname, 'views')); 16 | app.set('view engine', 'ejs'); 17 | 18 | app.use(express.static(path.join(__dirname, 'public'))); 19 | 20 | app.use(session({ 21 | name: config.session.key, 22 | secret: config.session.secret, 23 | resave: true, 24 | saveUninitialized: false, 25 | cookie: { 26 | maxAge: config.session.maxAge 27 | }, 28 | store: new MongoStore({ 29 | url: config.mongodb 30 | }) 31 | })); 32 | app.use(flash()); 33 | app.use(require('express-formidable')({ 34 | uploadDir: path.join(__dirname, 'public/img'), 35 | keepExtensions: true 36 | })); 37 | 38 | app.locals.blog = { 39 | title: 'Welcome to Sierra!' 40 | }; 41 | 42 | app.use(function (req, res, next) { 43 | res.locals.user = req.session.user; 44 | res.locals.success = req.flash('success').toString(); 45 | res.locals.error = req.flash('error').toString(); 46 | next(); 47 | }); 48 | 49 | app.use(expressWinston.logger({ 50 | transports: [ 51 | new (winston.transports.Console)({ 52 | json: true, 53 | colorize: true 54 | }), 55 | new winston.transports.File({ 56 | filename: 'logs/success.log' 57 | }) 58 | ] 59 | })); 60 | 61 | routes(app); 62 | 63 | app.use(expressWinston.errorLogger({ 64 | transports: [ 65 | new winston.transports.Console({ 66 | json: true, 67 | colorize: true 68 | }), 69 | new winston.transports.File({ 70 | filename: 'logs/error.log' 71 | }) 72 | ] 73 | })); 74 | 75 | 76 | app.use(function (err, req, res, next) { 77 | res.render('error', { 78 | error: err 79 | }); 80 | }); 81 | app.listen(config.port, function () { 82 | console.log(`${pkg.name} listening on port ${config.port}`); 83 | }); -------------------------------------------------------------------------------- /lib/mongo.js: -------------------------------------------------------------------------------- 1 | var config = require('config-lite')(__dirname); 2 | var Mongolass = require('mongolass'); 3 | var moment = require('moment'); 4 | var objectIdToTimestamp = require('objectid-to-timestamp'); 5 | 6 | var mongolass = new Mongolass(); 7 | 8 | mongolass.connect(config.mongodb); 9 | 10 | mongolass.plugin('addCreatedAt', { 11 | afterFind: function (results) { 12 | results.forEach(function (item) { 13 | item.created_at = moment(objectIdToTimestamp(item._id)).format('YYYY-MM-DD HH:mm'); 14 | }); 15 | return results; 16 | }, 17 | afterFindOne: function (result) { 18 | if (result) { 19 | result.created_at = moment(objectIdToTimestamp(result._id)).format('YYYY-MM-DD HH:mm'); 20 | } 21 | return result; 22 | } 23 | }); 24 | 25 | exports.User = mongolass.model('User', { 26 | id: { type: 'string'}, 27 | name: { type: 'string' }, 28 | password: { type: 'string' }, 29 | avatar: { type: 'string' }, 30 | gender: { type: 'string', enum: ['m', 'f', 'x'] }, 31 | bio: { type: 'string' }, 32 | isAdmin: { type: 'boolean'} 33 | }); 34 | exports.User.index({ id: 1 }, { unique: true }).exec(); 35 | 36 | exports.Library = mongolass.model('Library', { 37 | admin: { 38 | type: Mongolass.Types.ObjectId 39 | }, 40 | name: { 41 | type: 'string' 42 | }, 43 | location: { 44 | type: 'string' 45 | }, 46 | author: { 47 | type: 'string' 48 | }, 49 | press: { 50 | type: 'string' 51 | }, 52 | inventory: { 53 | type: 'number' 54 | }, 55 | date: { 56 | type: 'string' 57 | }, 58 | score: { 59 | type: 'number' 60 | }, 61 | cover: { 62 | type: 'string' 63 | }, 64 | introduction: { 65 | type: 'string' 66 | }, 67 | pv: { 68 | type: 'number' 69 | }, 70 | show: { 71 | type: 'boolean' 72 | } 73 | }); 74 | exports.Library.index({ 75 | admin: 1, 76 | _id: -1 77 | }).exec(); 78 | 79 | exports.BorrowBook = mongolass.model('BorrowBook', { 80 | userId: { 81 | type: Mongolass.Types.ObjectId, 82 | }, 83 | bookId: { 84 | type: Mongolass.Types.ObjectId 85 | }, 86 | bool: { 87 | type: 'boolean' 88 | }, 89 | return_time: { 90 | type: 'string' 91 | } 92 | }); 93 | 94 | exports.Favorite = mongolass.model('Favorite', { 95 | userId: { 96 | type: Mongolass.Types.ObjectId, 97 | }, 98 | bookId: { 99 | type: Mongolass.Types.ObjectId 100 | }, 101 | favorite: { 102 | type: 'boolean' 103 | } 104 | }) 105 | 106 | exports.BorrowBook.index({ 107 | userId: 1, 108 | _id: 1 109 | }).exec(); 110 | -------------------------------------------------------------------------------- /middlewares/check.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | checkLogin: function checkLogin(req, res, next) { 3 | if (!req.session.user) { 4 | req.flash('error', 'Not logged in'); 5 | return res.redirect('/signin'); 6 | } 7 | next(); 8 | }, 9 | 10 | checkNotLogin: function checkNotLogin(req, res, next) { 11 | if (req.session.user) { 12 | req.flash('error', 'Has logged'); 13 | return res.redirect('back'); 14 | } 15 | next(); 16 | }, 17 | 18 | checkIsAdmin: function checkIsAdmin(req, res, next) { 19 | if (!req.session.user) { 20 | req.flash('error', 'Not logged in'); 21 | return res.redirect('/signin'); 22 | } else { 23 | if (!req.session.user.isAdmin) { 24 | req.flash('error', 'No Access'); 25 | return res.redirect('back'); 26 | } 27 | } 28 | next(); 29 | } 30 | }; -------------------------------------------------------------------------------- /models/borrowBooks.js: -------------------------------------------------------------------------------- 1 | var BorrowBooks = require('../lib/mongo').BorrowBook; 2 | var moment = require('moment'); 3 | var objectIdToTimestamp = require('objectid-to-timestamp'); 4 | module.exports = { 5 | create: function(borrowbook) { 6 | return BorrowBooks.create(borrowbook).exec(); 7 | }, 8 | getBorrowBooks: function(userId) { 9 | return BorrowBooks 10 | .find({ userId: userId }) 11 | .populate({ path: 'admin', model: 'User' }) 12 | .sort({ _id: -1 }) 13 | .addCreatedAt() 14 | .exec(); 15 | }, 16 | getBorrowBooksCount: function(bookId) { 17 | return BorrowBooks 18 | .count({ bookId: bookId, bool: false}) 19 | .exec(); 20 | }, 21 | returnBookById: function (id) { 22 | return BorrowBooks.remove({ _id: id }).exec(); 23 | }, 24 | getBorrowUsers: function(bookId) { 25 | return BorrowBooks 26 | .find({ bookId: bookId}) 27 | .sort({ _id: 1 }) 28 | .addCreatedAt() 29 | .exec(); 30 | }, 31 | returnBookByBookId: function(bookId, userId) { 32 | return BorrowBooks.update({ bookId: bookId, userId: userId, bool: false, return_time: null}, { $set: { bool: true, return_time: moment().format('YYYY-MM-DD HH:mm')}}).exec(); 33 | } 34 | } -------------------------------------------------------------------------------- /models/library.js: -------------------------------------------------------------------------------- 1 | var Library = require('../lib/mongo').Library; 2 | var async = require('asyncawait/async'); 3 | var await = require('asyncawait/await'); 4 | 5 | module.exports = { 6 | create: function create(book) { 7 | return Library.create(book).exec(); 8 | }, 9 | getBookById: function (bookId) { 10 | return Library 11 | .findOne({ _id: bookId }) 12 | .populate({ path: 'admin', model: 'User' }) 13 | .addCreatedAt() 14 | .exec(); 15 | }, 16 | getBooks: function(admin) { 17 | var query = {}; 18 | if (admin) { 19 | query.admin = "5a246f7a4015d2070b89df75"; 20 | } 21 | return Library 22 | .find(query) 23 | .populate({ path: 'admin', model: 'User' }) 24 | .sort({"inventory" : -1}) 25 | .addCreatedAt() 26 | .exec(); 27 | }, 28 | searchBook: function(data) { 29 | var queryData = new RegExp(data.trim()); 30 | return Library 31 | .find({ 32 | '$or': [{ 33 | name: queryData 34 | }, { 35 | author: queryData 36 | }, { 37 | press: queryData 38 | }] 39 | }) 40 | .sort({ _id: -1 }) 41 | .exec(); 42 | }, 43 | checkBook: function(bookName) { 44 | return Library 45 | .find({ name: bookName }) 46 | .exec(); 47 | }, 48 | getRawBookById: function (bookId) { 49 | return Library 50 | .findOne({ _id: bookId }) 51 | .populate({ path: 'admin', model: 'User' }) 52 | .exec(); 53 | }, 54 | updateBookById: function (bookId, admin, data) { 55 | return Library.update({ admin: admin, _id: bookId }, { $set: data }).exec(); 56 | }, 57 | delBookById: function (bookId, admin) { 58 | return Library.update({ admin: admin, _id: bookId }, { $set: {show : false}}).exec(); 59 | }, 60 | incPv: function incPv(bookId) { 61 | return Library 62 | .update({ _id: bookId }, { $inc: { pv: 1 } }) 63 | .exec(); 64 | } 65 | }; -------------------------------------------------------------------------------- /models/users.js: -------------------------------------------------------------------------------- 1 | var User = require('../lib/mongo').User; 2 | 3 | module.exports = { 4 | create: function (user) { 5 | return User.create(user).exec(); 6 | }, 7 | getUserById: function (id) { 8 | return User 9 | .findOne({ id: id }) 10 | .addCreatedAt() 11 | .exec(); 12 | }, 13 | getUserByDefaultId: function(id) { 14 | return User 15 | .findOne({ _id: id}) 16 | .addCreatedAt() 17 | .exec(); 18 | } 19 | }; -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "library_system", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "accepts": { 8 | "version": "1.3.7", 9 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", 10 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", 11 | "requires": { 12 | "mime-types": "~2.1.24", 13 | "negotiator": "0.6.2" 14 | } 15 | }, 16 | "another-json-schema": { 17 | "version": "2.1.1", 18 | "resolved": "https://registry.npmjs.org/another-json-schema/-/another-json-schema-2.1.1.tgz", 19 | "integrity": "sha512-9yaRsy+XUnBC+KzfpwPVeQgCXJjrTzwffZSvMzabRCbV91gqM8I4+JTL68ig5tkgi26eo6s8Fg+k2tMkdTcBGQ==", 20 | "requires": { 21 | "is-buffer": "^1.1.2" 22 | } 23 | }, 24 | "ansi-styles": { 25 | "version": "3.2.1", 26 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 27 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 28 | "requires": { 29 | "color-convert": "^1.9.0" 30 | } 31 | }, 32 | "argparse": { 33 | "version": "1.0.10", 34 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 35 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 36 | "requires": { 37 | "sprintf-js": "~1.0.2" 38 | } 39 | }, 40 | "array-flatten": { 41 | "version": "1.1.1", 42 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 43 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 44 | }, 45 | "async": { 46 | "version": "1.0.0", 47 | "resolved": "https://registry.npmjs.org/async/-/async-1.0.0.tgz", 48 | "integrity": "sha1-+PwEyjoTeErenhZBr5hXjPvWR6k=" 49 | }, 50 | "asyncawait": { 51 | "version": "1.0.8", 52 | "resolved": "https://registry.npmjs.org/asyncawait/-/asyncawait-1.0.8.tgz", 53 | "integrity": "sha512-yssMQjNRaFYJbJPXnZQ/G4o5uqBj6Ol7HqjEzjyO7306RHnqLGoenKaVbqUgqhk1QBXZSJ3yf2xhQCWcZjWt6w==", 54 | "requires": { 55 | "bluebird": "^3.1.1", 56 | "fibers": "^2.0.2", 57 | "lodash": "^4.17.11" 58 | } 59 | }, 60 | "bluebird": { 61 | "version": "3.7.1", 62 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.1.tgz", 63 | "integrity": "sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg==" 64 | }, 65 | "bson": { 66 | "version": "1.0.9", 67 | "resolved": "https://registry.npmjs.org/bson/-/bson-1.0.9.tgz", 68 | "integrity": "sha512-IQX9/h7WdMBIW/q/++tGd+emQr0XMdeZ6icnT/74Xk9fnabWn+gZgpE+9V+gujL3hhJOoNrnDVY7tWdzc7NUTg==" 69 | }, 70 | "buffer-shims": { 71 | "version": "1.0.0", 72 | "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", 73 | "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=" 74 | }, 75 | "chalk": { 76 | "version": "2.1.0", 77 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz", 78 | "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==", 79 | "requires": { 80 | "ansi-styles": "^3.1.0", 81 | "escape-string-regexp": "^1.0.5", 82 | "supports-color": "^4.0.0" 83 | } 84 | }, 85 | "charenc": { 86 | "version": "0.0.2", 87 | "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", 88 | "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=" 89 | }, 90 | "co": { 91 | "version": "4.6.0", 92 | "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", 93 | "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" 94 | }, 95 | "color-convert": { 96 | "version": "1.9.3", 97 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 98 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 99 | "requires": { 100 | "color-name": "1.1.3" 101 | } 102 | }, 103 | "color-name": { 104 | "version": "1.1.3", 105 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 106 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" 107 | }, 108 | "colors": { 109 | "version": "1.0.3", 110 | "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", 111 | "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" 112 | }, 113 | "config-lite": { 114 | "version": "2.1.0", 115 | "resolved": "https://registry.npmjs.org/config-lite/-/config-lite-2.1.0.tgz", 116 | "integrity": "sha512-eYPW4i7lDKYTo3CSutjL/v08pFZqyyhR6Ql4/X5auZqWQ+tZlWE3INSv+InzxTl6csasyQHQGudqq86kWS/JKA==", 117 | "requires": { 118 | "chalk": "2.1.0", 119 | "js-yaml": "3.9.1", 120 | "lodash": "4.17.4", 121 | "optimist": "0.6.1", 122 | "resolve": "1.4.0", 123 | "toml": "2.3.2" 124 | }, 125 | "dependencies": { 126 | "lodash": { 127 | "version": "4.17.4", 128 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", 129 | "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" 130 | } 131 | } 132 | }, 133 | "connect-flash": { 134 | "version": "0.1.1", 135 | "resolved": "https://registry.npmjs.org/connect-flash/-/connect-flash-0.1.1.tgz", 136 | "integrity": "sha1-2GMPJtlaf4UfmVax6MxnMvO2qjA=" 137 | }, 138 | "connect-mongo": { 139 | "version": "2.0.0", 140 | "resolved": "https://registry.npmjs.org/connect-mongo/-/connect-mongo-2.0.0.tgz", 141 | "integrity": "sha512-2Nj5d4XO55AXSy1GOXDZteSEEUObGm/kvJaXyEQCa8cCHsCiZH+V/+sjk3b+khc4V8oyVi34rCtUxor4TfETLA==", 142 | "requires": { 143 | "mongodb": "^2.0.36" 144 | } 145 | }, 146 | "content-disposition": { 147 | "version": "0.5.1", 148 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.1.tgz", 149 | "integrity": "sha1-h0dsamfI2qh+Muh2Ft+IO6f7Bxs=" 150 | }, 151 | "content-type": { 152 | "version": "1.0.4", 153 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 154 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 155 | }, 156 | "cookie": { 157 | "version": "0.3.1", 158 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", 159 | "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" 160 | }, 161 | "cookie-signature": { 162 | "version": "1.0.6", 163 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 164 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 165 | }, 166 | "core-util-is": { 167 | "version": "1.0.2", 168 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 169 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 170 | }, 171 | "crc": { 172 | "version": "3.4.4", 173 | "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.4.tgz", 174 | "integrity": "sha1-naHpgOO9RPxck79as9ozeNheRms=" 175 | }, 176 | "crypt": { 177 | "version": "0.0.2", 178 | "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", 179 | "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=" 180 | }, 181 | "cycle": { 182 | "version": "1.0.3", 183 | "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", 184 | "integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI=" 185 | }, 186 | "debug": { 187 | "version": "2.2.0", 188 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", 189 | "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", 190 | "requires": { 191 | "ms": "0.7.1" 192 | } 193 | }, 194 | "depd": { 195 | "version": "1.1.2", 196 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 197 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 198 | }, 199 | "destroy": { 200 | "version": "1.0.4", 201 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 202 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 203 | }, 204 | "ee-first": { 205 | "version": "1.1.1", 206 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 207 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 208 | }, 209 | "ejs": { 210 | "version": "2.5.7", 211 | "resolved": "http://r.cnpmjs.org/ejs/download/ejs-2.5.7.tgz", 212 | "integrity": "sha1-zIcsFoiArjxxiXYv1f/ACJbJUYo=" 213 | }, 214 | "encodeurl": { 215 | "version": "1.0.2", 216 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 217 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" 218 | }, 219 | "es6-promise": { 220 | "version": "3.2.1", 221 | "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz", 222 | "integrity": "sha1-7FYjOGgDKQkgcXDDlEjiREndH8Q=" 223 | }, 224 | "escape-html": { 225 | "version": "1.0.3", 226 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 227 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 228 | }, 229 | "escape-string-regexp": { 230 | "version": "1.0.5", 231 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 232 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" 233 | }, 234 | "esprima": { 235 | "version": "4.0.1", 236 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 237 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" 238 | }, 239 | "etag": { 240 | "version": "1.7.0", 241 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz", 242 | "integrity": "sha1-A9MLX2fdbmMtKUXTDWZScxo01dg=" 243 | }, 244 | "express": { 245 | "version": "4.14.0", 246 | "resolved": "https://registry.npmjs.org/express/-/express-4.14.0.tgz", 247 | "integrity": "sha1-we4/Qs3Ikfs9xlCoki1R7IR9DWY=", 248 | "requires": { 249 | "accepts": "~1.3.3", 250 | "array-flatten": "1.1.1", 251 | "content-disposition": "0.5.1", 252 | "content-type": "~1.0.2", 253 | "cookie": "0.3.1", 254 | "cookie-signature": "1.0.6", 255 | "debug": "~2.2.0", 256 | "depd": "~1.1.0", 257 | "encodeurl": "~1.0.1", 258 | "escape-html": "~1.0.3", 259 | "etag": "~1.7.0", 260 | "finalhandler": "0.5.0", 261 | "fresh": "0.3.0", 262 | "merge-descriptors": "1.0.1", 263 | "methods": "~1.1.2", 264 | "on-finished": "~2.3.0", 265 | "parseurl": "~1.3.1", 266 | "path-to-regexp": "0.1.7", 267 | "proxy-addr": "~1.1.2", 268 | "qs": "6.2.0", 269 | "range-parser": "~1.2.0", 270 | "send": "0.14.1", 271 | "serve-static": "~1.11.1", 272 | "type-is": "~1.6.13", 273 | "utils-merge": "1.0.0", 274 | "vary": "~1.1.0" 275 | } 276 | }, 277 | "express-formidable": { 278 | "version": "1.0.0", 279 | "resolved": "https://registry.npmjs.org/express-formidable/-/express-formidable-1.0.0.tgz", 280 | "integrity": "sha1-3JIvBFUTIyJFip7BowHYkbP/yo0=", 281 | "requires": { 282 | "formidable": "^1.0.17" 283 | } 284 | }, 285 | "express-session": { 286 | "version": "1.15.6", 287 | "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.15.6.tgz", 288 | "integrity": "sha512-r0nrHTCYtAMrFwZ0kBzZEXa1vtPVrw0dKvGSrKP4dahwBQ1BJpF2/y1Pp4sCD/0kvxV4zZeclyvfmw0B4RMJQA==", 289 | "requires": { 290 | "cookie": "0.3.1", 291 | "cookie-signature": "1.0.6", 292 | "crc": "3.4.4", 293 | "debug": "2.6.9", 294 | "depd": "~1.1.1", 295 | "on-headers": "~1.0.1", 296 | "parseurl": "~1.3.2", 297 | "uid-safe": "~2.1.5", 298 | "utils-merge": "1.0.1" 299 | }, 300 | "dependencies": { 301 | "debug": { 302 | "version": "2.6.9", 303 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 304 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 305 | "requires": { 306 | "ms": "2.0.0" 307 | } 308 | }, 309 | "ms": { 310 | "version": "2.0.0", 311 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 312 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 313 | }, 314 | "utils-merge": { 315 | "version": "1.0.1", 316 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 317 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 318 | } 319 | } 320 | }, 321 | "express-winston": { 322 | "version": "2.4.0", 323 | "resolved": "https://registry.npmjs.org/express-winston/-/express-winston-2.4.0.tgz", 324 | "integrity": "sha1-J6ts2TBT4t/cNbzuoUoHfcfVLkk=", 325 | "requires": { 326 | "chalk": "~0.4.0", 327 | "lodash": "~4.11.1" 328 | }, 329 | "dependencies": { 330 | "ansi-styles": { 331 | "version": "1.0.0", 332 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", 333 | "integrity": "sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=" 334 | }, 335 | "chalk": { 336 | "version": "0.4.0", 337 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", 338 | "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=", 339 | "requires": { 340 | "ansi-styles": "~1.0.0", 341 | "has-color": "~0.1.0", 342 | "strip-ansi": "~0.1.0" 343 | } 344 | }, 345 | "lodash": { 346 | "version": "4.11.2", 347 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.11.2.tgz", 348 | "integrity": "sha1-1rQzixEKWOIdrlzrz9u/0rxM2zs=" 349 | } 350 | } 351 | }, 352 | "eyes": { 353 | "version": "0.1.8", 354 | "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", 355 | "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=" 356 | }, 357 | "fibers": { 358 | "version": "2.0.2", 359 | "resolved": "https://registry.npmjs.org/fibers/-/fibers-2.0.2.tgz", 360 | "integrity": "sha512-HfVRxhYG7C8Jl9FqtrlElMR2z/8YiLQVDKf67MLY25Ic+ILx3ecmklfT1v3u+7P5/4vEFjuxaAFXhr2/Afwk5g==" 361 | }, 362 | "finalhandler": { 363 | "version": "0.5.0", 364 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.5.0.tgz", 365 | "integrity": "sha1-6VCKvs6bbbqHGmlCodeRG5GRGsc=", 366 | "requires": { 367 | "debug": "~2.2.0", 368 | "escape-html": "~1.0.3", 369 | "on-finished": "~2.3.0", 370 | "statuses": "~1.3.0", 371 | "unpipe": "~1.0.0" 372 | } 373 | }, 374 | "formidable": { 375 | "version": "1.2.1", 376 | "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz", 377 | "integrity": "sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg==" 378 | }, 379 | "forwarded": { 380 | "version": "0.1.2", 381 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", 382 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" 383 | }, 384 | "fresh": { 385 | "version": "0.3.0", 386 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz", 387 | "integrity": "sha1-ZR+DjiJCTnVm3hYdg1jKoZn4PU8=" 388 | }, 389 | "has-color": { 390 | "version": "0.1.7", 391 | "resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz", 392 | "integrity": "sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=" 393 | }, 394 | "has-flag": { 395 | "version": "2.0.0", 396 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", 397 | "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" 398 | }, 399 | "hash-set": { 400 | "version": "1.0.1", 401 | "resolved": "https://registry.npmjs.org/hash-set/-/hash-set-1.0.1.tgz", 402 | "integrity": "sha1-wLbTLTP95zEgQyCQiRKETELonMU=" 403 | }, 404 | "http-errors": { 405 | "version": "1.5.1", 406 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.5.1.tgz", 407 | "integrity": "sha1-eIwNLB3iyBuebowBhDtrl+uSB1A=", 408 | "requires": { 409 | "inherits": "2.0.3", 410 | "setprototypeof": "1.0.2", 411 | "statuses": ">= 1.3.1 < 2" 412 | }, 413 | "dependencies": { 414 | "inherits": { 415 | "version": "2.0.3", 416 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 417 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 418 | } 419 | } 420 | }, 421 | "inflected": { 422 | "version": "2.0.2", 423 | "resolved": "https://registry.npmjs.org/inflected/-/inflected-2.0.2.tgz", 424 | "integrity": "sha1-G8MaxCfKUyGyoWzFbW/yn80v+Aw=" 425 | }, 426 | "inherits": { 427 | "version": "2.0.4", 428 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 429 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 430 | }, 431 | "ipaddr.js": { 432 | "version": "1.4.0", 433 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.4.0.tgz", 434 | "integrity": "sha1-KWrKh4qCGBbluF0KKFqZvP9FgvA=" 435 | }, 436 | "is-buffer": { 437 | "version": "1.1.6", 438 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", 439 | "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" 440 | }, 441 | "isarray": { 442 | "version": "1.0.0", 443 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 444 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 445 | }, 446 | "isstream": { 447 | "version": "0.1.2", 448 | "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", 449 | "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" 450 | }, 451 | "js-yaml": { 452 | "version": "3.9.1", 453 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.9.1.tgz", 454 | "integrity": "sha512-CbcG379L1e+mWBnLvHWWeLs8GyV/EMw862uLI3c+GxVyDHWZcjZinwuBd3iW2pgxgIlksW/1vNJa4to+RvDOww==", 455 | "requires": { 456 | "argparse": "^1.0.7", 457 | "esprima": "^4.0.0" 458 | } 459 | }, 460 | "lodash": { 461 | "version": "4.17.15", 462 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", 463 | "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" 464 | }, 465 | "marked": { 466 | "version": "0.7.0", 467 | "resolved": "https://registry.npmjs.org/marked/-/marked-0.7.0.tgz", 468 | "integrity": "sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg==" 469 | }, 470 | "media-typer": { 471 | "version": "0.3.0", 472 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 473 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 474 | }, 475 | "merge-descriptors": { 476 | "version": "1.0.1", 477 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 478 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 479 | }, 480 | "methods": { 481 | "version": "1.1.2", 482 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 483 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 484 | }, 485 | "mime": { 486 | "version": "1.3.4", 487 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", 488 | "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=" 489 | }, 490 | "mime-db": { 491 | "version": "1.40.0", 492 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", 493 | "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" 494 | }, 495 | "mime-types": { 496 | "version": "2.1.24", 497 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", 498 | "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", 499 | "requires": { 500 | "mime-db": "1.40.0" 501 | } 502 | }, 503 | "minimist": { 504 | "version": "0.0.10", 505 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", 506 | "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=" 507 | }, 508 | "moment": { 509 | "version": "2.18.1", 510 | "resolved": "https://registry.npmjs.org/moment/-/moment-2.18.1.tgz", 511 | "integrity": "sha1-w2GT3Tzhwu7SrbfIAtu8d6gbHA8=" 512 | }, 513 | "mongodb": { 514 | "version": "2.2.36", 515 | "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.36.tgz", 516 | "integrity": "sha512-P2SBLQ8Z0PVx71ngoXwo12+FiSfbNfGOClAao03/bant5DgLNkOPAck5IaJcEk4gKlQhDEURzfR3xuBG1/B+IA==", 517 | "requires": { 518 | "es6-promise": "3.2.1", 519 | "mongodb-core": "2.1.20", 520 | "readable-stream": "2.2.7" 521 | } 522 | }, 523 | "mongodb-core": { 524 | "version": "2.1.20", 525 | "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.20.tgz", 526 | "integrity": "sha512-IN57CX5/Q1bhDq6ShAR6gIv4koFsZP7L8WOK1S0lR0pVDQaScffSMV5jxubLsmZ7J+UdqmykKw4r9hG3XQEGgQ==", 527 | "requires": { 528 | "bson": "~1.0.4", 529 | "require_optional": "~1.0.0" 530 | } 531 | }, 532 | "mongolass": { 533 | "version": "3.1.5", 534 | "resolved": "https://registry.npmjs.org/mongolass/-/mongolass-3.1.5.tgz", 535 | "integrity": "sha512-BV08Q/xWPjupWw9XCYfvUVRsM8cY6mnTRz8sHdyl1vgrxRixDNuLcoDzB65p1Uf6fAhHAge5vYtTPDuoFkRPmg==", 536 | "requires": { 537 | "another-json-schema": "2.1.1", 538 | "co": "4.6.0", 539 | "debug": "3.0.0", 540 | "inflected": "2.0.2", 541 | "lodash": "4.17.4", 542 | "mongodb": "2.2.31", 543 | "mongolass-plugin-populate": "*", 544 | "validator": "8.0.0" 545 | }, 546 | "dependencies": { 547 | "debug": { 548 | "version": "3.0.0", 549 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.0.0.tgz", 550 | "integrity": "sha512-XQkHxxqbsCb+zFurCHbotmJZl5jXsxvkRt952pT6Hpo7LmjWAJF12d9/kqBg5owjbLADbBDli1olravjSiSg8g==", 551 | "requires": { 552 | "ms": "2.0.0" 553 | } 554 | }, 555 | "lodash": { 556 | "version": "4.17.4", 557 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", 558 | "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" 559 | }, 560 | "mongodb": { 561 | "version": "2.2.31", 562 | "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.31.tgz", 563 | "integrity": "sha1-GUBEXGYeGSF7s7+CRdmFSq71SNs=", 564 | "requires": { 565 | "es6-promise": "3.2.1", 566 | "mongodb-core": "2.1.15", 567 | "readable-stream": "2.2.7" 568 | } 569 | }, 570 | "mongodb-core": { 571 | "version": "2.1.15", 572 | "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.15.tgz", 573 | "integrity": "sha1-hB9TuH//9MdFgYnDXIroJ+EWl2Q=", 574 | "requires": { 575 | "bson": "~1.0.4", 576 | "require_optional": "~1.0.0" 577 | } 578 | }, 579 | "ms": { 580 | "version": "2.0.0", 581 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 582 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 583 | } 584 | } 585 | }, 586 | "mongolass-plugin-populate": { 587 | "version": "0.4.0", 588 | "resolved": "https://registry.npmjs.org/mongolass-plugin-populate/-/mongolass-plugin-populate-0.4.0.tgz", 589 | "integrity": "sha512-umM40jqPi/wf5YitZ3ILRKDbwEPeWAMhDR7scFMTXJo0m4doi9C4pGneXqFBHtlSVCrlhpwJV9AhZyiZdd3vRg==", 590 | "requires": { 591 | "lodash": "4.17.10" 592 | }, 593 | "dependencies": { 594 | "lodash": { 595 | "version": "4.17.10", 596 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", 597 | "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" 598 | } 599 | } 600 | }, 601 | "ms": { 602 | "version": "0.7.1", 603 | "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", 604 | "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" 605 | }, 606 | "negotiator": { 607 | "version": "0.6.2", 608 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", 609 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" 610 | }, 611 | "objectid-to-timestamp": { 612 | "version": "1.3.0", 613 | "resolved": "https://registry.npmjs.org/objectid-to-timestamp/-/objectid-to-timestamp-1.3.0.tgz", 614 | "integrity": "sha1-Yeys9lgHUdIGOzVEZwndjM7C5fE=" 615 | }, 616 | "on-finished": { 617 | "version": "2.3.0", 618 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 619 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 620 | "requires": { 621 | "ee-first": "1.1.1" 622 | } 623 | }, 624 | "on-headers": { 625 | "version": "1.0.2", 626 | "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", 627 | "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" 628 | }, 629 | "optimist": { 630 | "version": "0.6.1", 631 | "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", 632 | "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", 633 | "requires": { 634 | "minimist": "~0.0.1", 635 | "wordwrap": "~0.0.2" 636 | } 637 | }, 638 | "parseurl": { 639 | "version": "1.3.3", 640 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 641 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 642 | }, 643 | "path-parse": { 644 | "version": "1.0.6", 645 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", 646 | "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" 647 | }, 648 | "path-to-regexp": { 649 | "version": "0.1.7", 650 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 651 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 652 | }, 653 | "process-nextick-args": { 654 | "version": "1.0.7", 655 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", 656 | "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" 657 | }, 658 | "proxy-addr": { 659 | "version": "1.1.5", 660 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.5.tgz", 661 | "integrity": "sha1-ccDuOxAt4/IC87ZPYI0XP8uhqRg=", 662 | "requires": { 663 | "forwarded": "~0.1.0", 664 | "ipaddr.js": "1.4.0" 665 | } 666 | }, 667 | "qs": { 668 | "version": "6.2.0", 669 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.0.tgz", 670 | "integrity": "sha1-O3hIwDwt7OaalSKw+ujEEm10Xzs=" 671 | }, 672 | "random-bytes": { 673 | "version": "1.0.0", 674 | "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", 675 | "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" 676 | }, 677 | "range-parser": { 678 | "version": "1.2.1", 679 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 680 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 681 | }, 682 | "readable-stream": { 683 | "version": "2.2.7", 684 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz", 685 | "integrity": "sha1-BwV6y+JGeyIELTb5jFrVBwVOlbE=", 686 | "requires": { 687 | "buffer-shims": "~1.0.0", 688 | "core-util-is": "~1.0.0", 689 | "inherits": "~2.0.1", 690 | "isarray": "~1.0.0", 691 | "process-nextick-args": "~1.0.6", 692 | "string_decoder": "~1.0.0", 693 | "util-deprecate": "~1.0.1" 694 | } 695 | }, 696 | "require_optional": { 697 | "version": "1.0.1", 698 | "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", 699 | "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", 700 | "requires": { 701 | "resolve-from": "^2.0.0", 702 | "semver": "^5.1.0" 703 | } 704 | }, 705 | "resolve": { 706 | "version": "1.4.0", 707 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.4.0.tgz", 708 | "integrity": "sha512-aW7sVKPufyHqOmyyLzg/J+8606v5nevBgaliIlV7nUpVMsDnoBGV/cbSLNjZAg9q0Cfd/+easKVKQ8vOu8fn1Q==", 709 | "requires": { 710 | "path-parse": "^1.0.5" 711 | } 712 | }, 713 | "resolve-from": { 714 | "version": "2.0.0", 715 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", 716 | "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" 717 | }, 718 | "safe-buffer": { 719 | "version": "5.1.2", 720 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 721 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 722 | }, 723 | "semver": { 724 | "version": "5.7.1", 725 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 726 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" 727 | }, 728 | "send": { 729 | "version": "0.14.1", 730 | "resolved": "https://registry.npmjs.org/send/-/send-0.14.1.tgz", 731 | "integrity": "sha1-qVSYQyU5L1FTKndgdg5FlZjIn3o=", 732 | "requires": { 733 | "debug": "~2.2.0", 734 | "depd": "~1.1.0", 735 | "destroy": "~1.0.4", 736 | "encodeurl": "~1.0.1", 737 | "escape-html": "~1.0.3", 738 | "etag": "~1.7.0", 739 | "fresh": "0.3.0", 740 | "http-errors": "~1.5.0", 741 | "mime": "1.3.4", 742 | "ms": "0.7.1", 743 | "on-finished": "~2.3.0", 744 | "range-parser": "~1.2.0", 745 | "statuses": "~1.3.0" 746 | } 747 | }, 748 | "serve-static": { 749 | "version": "1.11.2", 750 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.11.2.tgz", 751 | "integrity": "sha1-LPmIm9RDWjIMw2iVyapXvWYuasc=", 752 | "requires": { 753 | "encodeurl": "~1.0.1", 754 | "escape-html": "~1.0.3", 755 | "parseurl": "~1.3.1", 756 | "send": "0.14.2" 757 | }, 758 | "dependencies": { 759 | "ms": { 760 | "version": "0.7.2", 761 | "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", 762 | "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=" 763 | }, 764 | "send": { 765 | "version": "0.14.2", 766 | "resolved": "https://registry.npmjs.org/send/-/send-0.14.2.tgz", 767 | "integrity": "sha1-ObBDiz9RC+Xcb2Z6EfcWiTaM3u8=", 768 | "requires": { 769 | "debug": "~2.2.0", 770 | "depd": "~1.1.0", 771 | "destroy": "~1.0.4", 772 | "encodeurl": "~1.0.1", 773 | "escape-html": "~1.0.3", 774 | "etag": "~1.7.0", 775 | "fresh": "0.3.0", 776 | "http-errors": "~1.5.1", 777 | "mime": "1.3.4", 778 | "ms": "0.7.2", 779 | "on-finished": "~2.3.0", 780 | "range-parser": "~1.2.0", 781 | "statuses": "~1.3.1" 782 | } 783 | } 784 | } 785 | }, 786 | "setprototypeof": { 787 | "version": "1.0.2", 788 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.2.tgz", 789 | "integrity": "sha1-gaVSFB7BBLiOic44MQOtXGZWTQg=" 790 | }, 791 | "sha1": { 792 | "version": "1.1.1", 793 | "resolved": "https://registry.npmjs.org/sha1/-/sha1-1.1.1.tgz", 794 | "integrity": "sha1-rdqnqTFo85PxnrKxUJFhjicA+Eg=", 795 | "requires": { 796 | "charenc": ">= 0.0.1", 797 | "crypt": ">= 0.0.1" 798 | } 799 | }, 800 | "sprintf-js": { 801 | "version": "1.0.3", 802 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 803 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" 804 | }, 805 | "stack-trace": { 806 | "version": "0.0.10", 807 | "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", 808 | "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" 809 | }, 810 | "statuses": { 811 | "version": "1.3.1", 812 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", 813 | "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" 814 | }, 815 | "string_decoder": { 816 | "version": "1.0.3", 817 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", 818 | "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", 819 | "requires": { 820 | "safe-buffer": "~5.1.0" 821 | } 822 | }, 823 | "strip-ansi": { 824 | "version": "0.1.1", 825 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", 826 | "integrity": "sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=" 827 | }, 828 | "supports-color": { 829 | "version": "4.5.0", 830 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", 831 | "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", 832 | "requires": { 833 | "has-flag": "^2.0.0" 834 | } 835 | }, 836 | "toml": { 837 | "version": "2.3.2", 838 | "resolved": "https://registry.npmjs.org/toml/-/toml-2.3.2.tgz", 839 | "integrity": "sha1-Xt7VykKIeSSUn9BusOlVZWAB6DQ=" 840 | }, 841 | "type-is": { 842 | "version": "1.6.18", 843 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 844 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 845 | "requires": { 846 | "media-typer": "0.3.0", 847 | "mime-types": "~2.1.24" 848 | } 849 | }, 850 | "uid-safe": { 851 | "version": "2.1.5", 852 | "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", 853 | "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", 854 | "requires": { 855 | "random-bytes": "~1.0.0" 856 | } 857 | }, 858 | "unpipe": { 859 | "version": "1.0.0", 860 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 861 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 862 | }, 863 | "util-deprecate": { 864 | "version": "1.0.2", 865 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 866 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 867 | }, 868 | "utils-merge": { 869 | "version": "1.0.0", 870 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", 871 | "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=" 872 | }, 873 | "validator": { 874 | "version": "8.0.0", 875 | "resolved": "https://registry.npmjs.org/validator/-/validator-8.0.0.tgz", 876 | "integrity": "sha512-ni6X82obaR98FomBC8M/IF01u7d8WBjNhadxDDo+xGHGSfbTug1IS0j1zaoViYWQaMMFVfz40UhYxgs3dzvnZg==" 877 | }, 878 | "vary": { 879 | "version": "1.1.2", 880 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 881 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 882 | }, 883 | "winston": { 884 | "version": "2.4.0", 885 | "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.0.tgz", 886 | "integrity": "sha1-gIBQuT1SZh7Z+2wms/DIJnCLCu4=", 887 | "requires": { 888 | "async": "~1.0.0", 889 | "colors": "1.0.x", 890 | "cycle": "1.0.x", 891 | "eyes": "0.1.x", 892 | "isstream": "0.1.x", 893 | "stack-trace": "0.0.x" 894 | } 895 | }, 896 | "wordwrap": { 897 | "version": "0.0.3", 898 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", 899 | "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" 900 | } 901 | } 902 | } 903 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "library_system", 3 | "version": "1.0.0", 4 | "description": "a library system", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [ 10 | "node", 11 | "express", 12 | "mongodb" 13 | ], 14 | "author": "nickj", 15 | "license": "ISC", 16 | "dependencies": { 17 | "asyncawait": "^1.0.6", 18 | "config-lite": "2.1.0", 19 | "connect-flash": "0.1.1", 20 | "connect-mongo": "2.0.0", 21 | "ejs": "2.5.7", 22 | "express": "4.14.0", 23 | "express-formidable": "1.0.0", 24 | "express-session": "1.15.6", 25 | "express-winston": "2.4.0", 26 | "hash-set": "^1.0.1", 27 | "marked": "0.7.0", 28 | "moment": "2.18.1", 29 | "mongolass": "3.1.5", 30 | "objectid-to-timestamp": "1.3.0", 31 | "sha1": "1.1.1", 32 | "winston": "2.4.0" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /public/css/common.css: -------------------------------------------------------------------------------- 1 | body { 2 | /* width: 1100px; */ 3 | height: 100%; 4 | margin: 0 auto; 5 | } 6 | 7 | .button { 8 | background-color: #4fc08d; 9 | color: #fff; 10 | } 11 | 12 | .avatar { 13 | border-radius: 3px; 14 | width: 48px; 15 | height: 48px; 16 | float: right; 17 | } 18 | 19 | 20 | /* ---------- nav ---------- */ 21 | 22 | .nav { 23 | margin-bottom: 20px; 24 | color: #999; 25 | text-align: center; 26 | } 27 | 28 | .nav h1 { 29 | color: #4fc08d; 30 | display: inline-block; 31 | margin: 10px 0; 32 | } 33 | 34 | 35 | /* ---------- nav-setting ---------- */ 36 | 37 | .nav-setting { 38 | position: fixed; 39 | right: 30px; 40 | top: 35px; 41 | z-index: 999; 42 | } 43 | 44 | .nav-setting .ui.dropdown.button { 45 | padding: 10px 10px 0 10px; 46 | background-color: #fff !important; 47 | } 48 | 49 | .nav-setting .icon.bars { 50 | color: #000; 51 | font-size: 18px; 52 | } 53 | 54 | 55 | /* ---------- post-content ---------- */ 56 | 57 | .post-content h3 a { 58 | color: #4fc08d !important; 59 | } 60 | 61 | .post-content .tag { 62 | font-size: 13px; 63 | margin-right: 5px; 64 | color: #999; 65 | } 66 | 67 | .post-content .tag.right { 68 | float: right; 69 | margin-right: 0; 70 | } 71 | 72 | .post-content .tag.right a { 73 | color: #999; 74 | } -------------------------------------------------------------------------------- /public/css/themes/basic/assets/fonts/icons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhongzhang/Online-Library-System/e41682073273fb1b7ffc09ef0f633df9979f519b/public/css/themes/basic/assets/fonts/icons.eot -------------------------------------------------------------------------------- /public/css/themes/basic/assets/fonts/icons.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Created by FontForge 20100429 at Thu Sep 20 22:09:47 2012 6 | By root 7 | Copyright (C) 2012 by original authors @ fontello.com 8 | 9 | 10 | 11 | 24 | 26 | 28 | 30 | 32 | 35 | 37 | 41 | 44 | 47 | 49 | 51 | 53 | 55 | 57 | 59 | 61 | 63 | 65 | 68 | 71 | 74 | 76 | 80 | 86 | 89 | 91 | 101 | 103 | 105 | 108 | 110 | 112 | 115 | 118 | 121 | 123 | 125 | 127 | 129 | 131 | 133 | 135 | 137 | 140 | 142 | 146 | 149 | 153 | 158 | 161 | 163 | 165 | 169 | 172 | 174 | 178 | 181 | 184 | 191 | 193 | 196 | 199 | 203 | 206 | 209 | 213 | 217 | 219 | 221 | 223 | 225 | 228 | 231 | 234 | 237 | 240 | 243 | 245 | 247 | 250 | 253 | 255 | 258 | 262 | 264 | 266 | 268 | 270 | 273 | 275 | 278 | 283 | 289 | 292 | 295 | 299 | 301 | 304 | 307 | 311 | 315 | 317 | 322 | 325 | 329 | 334 | 341 | 344 | 347 | 351 | 354 | 358 | 362 | 367 | 372 | 377 | 380 | 385 | 388 | 392 | 398 | 401 | 403 | 409 | 411 | 413 | 418 | 422 | 425 | 428 | 431 | 434 | 436 | 440 | 443 | 446 | 449 | 450 | 451 | -------------------------------------------------------------------------------- /public/css/themes/basic/assets/fonts/icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhongzhang/Online-Library-System/e41682073273fb1b7ffc09ef0f633df9979f519b/public/css/themes/basic/assets/fonts/icons.ttf -------------------------------------------------------------------------------- /public/css/themes/basic/assets/fonts/icons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhongzhang/Online-Library-System/e41682073273fb1b7ffc09ef0f633df9979f519b/public/css/themes/basic/assets/fonts/icons.woff -------------------------------------------------------------------------------- /public/css/themes/default/assets/fonts/icons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhongzhang/Online-Library-System/e41682073273fb1b7ffc09ef0f633df9979f519b/public/css/themes/default/assets/fonts/icons.eot -------------------------------------------------------------------------------- /public/css/themes/default/assets/fonts/icons.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhongzhang/Online-Library-System/e41682073273fb1b7ffc09ef0f633df9979f519b/public/css/themes/default/assets/fonts/icons.otf -------------------------------------------------------------------------------- /public/css/themes/default/assets/fonts/icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhongzhang/Online-Library-System/e41682073273fb1b7ffc09ef0f633df9979f519b/public/css/themes/default/assets/fonts/icons.ttf -------------------------------------------------------------------------------- /public/css/themes/default/assets/fonts/icons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhongzhang/Online-Library-System/e41682073273fb1b7ffc09ef0f633df9979f519b/public/css/themes/default/assets/fonts/icons.woff -------------------------------------------------------------------------------- /public/css/themes/default/assets/fonts/icons.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhongzhang/Online-Library-System/e41682073273fb1b7ffc09ef0f633df9979f519b/public/css/themes/default/assets/fonts/icons.woff2 -------------------------------------------------------------------------------- /public/css/themes/default/assets/images/flags.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhongzhang/Online-Library-System/e41682073273fb1b7ffc09ef0f633df9979f519b/public/css/themes/default/assets/images/flags.png -------------------------------------------------------------------------------- /public/img/upload_3424d6994a994d4340ab043b0717d6a4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhongzhang/Online-Library-System/e41682073273fb1b7ffc09ef0f633df9979f519b/public/img/upload_3424d6994a994d4340ab043b0717d6a4.jpg -------------------------------------------------------------------------------- /public/img/upload_4c1fdd5646bd120237aaa5ffe7ddd40d.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhongzhang/Online-Library-System/e41682073273fb1b7ffc09ef0f633df9979f519b/public/img/upload_4c1fdd5646bd120237aaa5ffe7ddd40d.jpg -------------------------------------------------------------------------------- /public/img/upload_60d2f41215d11b1d20d57bb3dc65c131.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhongzhang/Online-Library-System/e41682073273fb1b7ffc09ef0f633df9979f519b/public/img/upload_60d2f41215d11b1d20d57bb3dc65c131.jpeg -------------------------------------------------------------------------------- /public/img/upload_637c32ec1ab0534d2fb4f090a504c556.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhongzhang/Online-Library-System/e41682073273fb1b7ffc09ef0f633df9979f519b/public/img/upload_637c32ec1ab0534d2fb4f090a504c556.jpg -------------------------------------------------------------------------------- /public/img/upload_71930cd725a347a06009b3061468f7aa.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzhongzhang/Online-Library-System/e41682073273fb1b7ffc09ef0f633df9979f519b/public/img/upload_71930cd725a347a06009b3061468f7aa.jpeg -------------------------------------------------------------------------------- /routes/borrow.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | var async = require('asyncawait/async'); 4 | var await = require('asyncawait/await'); 5 | var UserModel = require('../models/users'); 6 | var BorrowBookModel = require('../models/borrowBooks'); 7 | var BorrowBooks = require('../lib/mongo').BorrowBook; 8 | var checkIsAdmin = require('../middlewares/check').checkIsAdmin; 9 | 10 | router.get('/:bookId', checkIsAdmin, async (function (req, res, next) { 11 | var bookId = req.params.bookId; 12 | var result = []; 13 | try { 14 | var users = await (BorrowBookModel.getBorrowUsers(bookId)); 15 | users.forEach(async (function(user){ 16 | var userInfo = await (UserModel.getUserByDefaultId(user.userId)) 17 | result.push({ 18 | userId: user.userId, 19 | name: userInfo.name, 20 | id: userInfo.id, 21 | avatar: userInfo.avatar, 22 | borrowTime: user.created_at, 23 | borrowId: user._id, 24 | bookId: bookId, 25 | returnTime: user.return_time, 26 | bool: user.bool 27 | }) 28 | })); 29 | 30 | setTimeout(function() { 31 | res.render('borrow', { 32 | borrowUser: result 33 | }); 34 | }, 1000); 35 | 36 | } catch (error) { 37 | next(); 38 | } 39 | 40 | })); 41 | 42 | module.exports = router; -------------------------------------------------------------------------------- /routes/home.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | var Library = require('../lib/mongo').Library; 4 | var async = require('asyncawait/async'); 5 | var await = require('asyncawait/await'); 6 | var mongo = require('mongodb'); 7 | var LibraryModel = require('../models/library'); 8 | var checkLogin = require('../middlewares/check').checkLogin; 9 | 10 | var FavoriteModel = require('../lib/mongo').Favorite; 11 | 12 | 13 | router.get('/', async (function (req, res, next) { 14 | var query = {}; 15 | query.admin = '5a246f7a4015d2070b89df75'; 16 | // var perPage = 4; 17 | // var page = req.query.page || 1; 18 | 19 | var curcount; 20 | var books = await (Library 21 | .find(query) 22 | .populate({ path: 'admin', model: 'User' }) 23 | .sort({"inventory" : -1}) 24 | .addCreatedAt() 25 | .exec()); 26 | var result = []; 27 | if(req.session.user) { 28 | books.forEach(async (function(book) { 29 | var userId = new mongo.ObjectId(req.session.user._id); 30 | var bookId = new mongo.ObjectId(book._id); 31 | 32 | var record = await (FavoriteModel.findOne({userId: userId, bookId: bookId}).exec()); 33 | var like = false; 34 | if(record !== null) { 35 | like = record.favorite; 36 | } 37 | 38 | result.push({ 39 | _id: book._id, 40 | name: book.name, 41 | cover: book.cover, 42 | score: book.score, 43 | author: book.author, 44 | like: like, 45 | show: book.show 46 | }) 47 | })); 48 | } 49 | else { 50 | result = books; 51 | } 52 | setTimeout(function() { 53 | 54 | res.render('home', { 55 | books: result 56 | }); 57 | }, 1000); 58 | })); 59 | 60 | 61 | router.get('/:bookId/favorite', async (function(req,res){ 62 | var userId = new mongo.ObjectId(req.session.user._id); 63 | var book_Id = new mongo.ObjectId(req.params.bookId); 64 | var record = await (FavoriteModel.findOne({userId: userId, bookId: book_Id}).exec()); 65 | if(record === null) { 66 | await(FavoriteModel.insertOne({ 67 | userId: userId, 68 | bookId: book_Id, 69 | favorite: true 70 | }).exec()); 71 | } 72 | else { 73 | await(FavoriteModel.update({userId: userId, bookId: book_Id, favorite: false}, {$set:{favorite : true}}).exec()); 74 | } 75 | setTimeout(function() { 76 | res.redirect('/'); 77 | }, 10); 78 | })); 79 | 80 | router.get('/:bookId/unfavorite', async (function(req,res){ 81 | var userId = new mongo.ObjectId(req.session.user._id); 82 | var book_Id = new mongo.ObjectId(req.params.bookId); 83 | 84 | await(FavoriteModel.update({userId: userId, bookId: book_Id, favorite: true}, {$set:{favorite : false}}).exec()); 85 | 86 | setTimeout(function() { 87 | res.redirect('/'); 88 | }, 10); 89 | })); 90 | module.exports = router; -------------------------------------------------------------------------------- /routes/index.js: -------------------------------------------------------------------------------- 1 | module.exports = function (app) { 2 | app.get('/', function (req, res) { 3 | res.redirect('./home'); 4 | }); 5 | app.use('/home', require('./home')); 6 | app.use('/signup', require('./signup')); 7 | app.use('/signin', require('./signin')); 8 | app.use('/signout', require('./signout')); 9 | app.use('/library', require('./library')); 10 | app.use('/search', require('./search')); 11 | app.use('/profile', require('./profile')); 12 | app.use('/borrow', require('./borrow')); 13 | app.use('/quick_borrow', require('./quick_borrow')); 14 | // 404 page 15 | app.use(function (req, res) { 16 | if (!res.headersSent) { 17 | res.status(404).render('404'); 18 | } 19 | }); 20 | }; -------------------------------------------------------------------------------- /routes/library.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var path = require('path'); 3 | var express = require('express'); 4 | var router = express.Router(); 5 | var async = require('asyncawait/async'); 6 | var await = require('asyncawait/await'); 7 | var LibraryModel = require('../models/library'); 8 | var BorrowBookModel = require('../models/borrowBooks'); 9 | var UserModel = require('../models/users'); 10 | var checkLogin = require('../middlewares/check').checkLogin; 11 | var checkIsAdmin = require('../middlewares/check').checkIsAdmin; 12 | 13 | router.get('/', checkIsAdmin, async(function (req, res, next) { 14 | var admin = req.query.admin; 15 | 16 | try { 17 | var books = await (LibraryModel.getBooks(admin)); 18 | books.forEach(async (function(book) { 19 | try { 20 | var borrowCount = await (BorrowBookModel.getBorrowBooksCount(book._id)); 21 | book.borrowCount = borrowCount; 22 | } catch (error) { 23 | req.flash('error', 'Something go wrong, please try again!'); 24 | } 25 | }), this); 26 | 27 | setTimeout(() => { 28 | res.render('library', { 29 | books: books 30 | }); 31 | }, 1000) 32 | } catch (error) { 33 | req.flash('error', 'Something go wrong, please try again!'); 34 | next(); 35 | } 36 | 37 | })); 38 | 39 | router.post('/', checkIsAdmin, async (function (req, res, next) { 40 | var admin = req.session.user._id; 41 | 42 | var bookData = { 43 | admin: req.session.user._id, 44 | name: req.fields.name, 45 | location: req.fields.location, 46 | author: req.fields.author, 47 | press: req.fields.press, 48 | inventory: parseInt(req.fields.inventory), 49 | date: req.fields.date, 50 | score: parseInt(req.fields.score), 51 | cover: req.fields.cover_url || req.files.cover.path.split(path.sep).pop() , 52 | introduction: req.fields.introduction 53 | } 54 | try { 55 | if (!bookData.name.length) { 56 | throw new Error('Please fill in the name!'); 57 | } 58 | if (!bookData.introduction.length) { 59 | throw new Error('Please fill in the introduction!'); 60 | } 61 | } catch (e) { 62 | req.flash('error', e.message); 63 | return res.redirect('back'); 64 | } 65 | 66 | var book = { 67 | admin: bookData.admin, 68 | name: bookData.name, 69 | location: bookData.location, 70 | author: bookData.author, 71 | press: bookData.press, 72 | inventory: bookData.inventory, 73 | date: bookData.date, 74 | score: bookData.score, 75 | cover: bookData.cover, 76 | introduction: bookData.introduction, 77 | pv: 0, 78 | show: true 79 | }; 80 | 81 | var checkBook = await (LibraryModel.checkBook(book.name)); 82 | 83 | if (!checkBook.length) { 84 | LibraryModel.create(book) 85 | .then(function (result) { 86 | book = result.ops[0]; 87 | req.flash('success', 'Add successfully!'); 88 | res.redirect(`/library`); 89 | }) 90 | .catch(next); 91 | } else { 92 | req.flash('error', 'This book has already exist!'); 93 | res.redirect(`/library`); 94 | } 95 | 96 | })); 97 | 98 | router.get('/:bookId', function (req, res, next) { 99 | var bookId = req.params.bookId; 100 | 101 | Promise.all([ 102 | LibraryModel.getBookById(bookId), 103 | LibraryModel.incPv(bookId) 104 | ]) 105 | .then(function (result) { 106 | var book = result[0]; 107 | if (!book) { 108 | throw new Error('The book does not exist!'); 109 | } 110 | book.location = book.location; 111 | res.render('book', { 112 | book: book 113 | }); 114 | }) 115 | .catch(next); 116 | }); 117 | 118 | router.get('/:bookId/remove', checkIsAdmin, function (req, res, next) { 119 | var bookId = req.params.bookId; 120 | var admin = req.session.user._id; 121 | 122 | LibraryModel.delBookById(bookId, admin) 123 | .then(function () { 124 | req.flash('success', 'Delete the book successfully!'); 125 | res.redirect('/library'); 126 | }) 127 | .catch(next); 128 | }); 129 | 130 | router.post('/:bookId/edit', checkIsAdmin, function (req, res, next) { 131 | var bookId = req.params.bookId; 132 | var admin = req.session.user._id; 133 | 134 | var bookData = { 135 | name: req.fields.name, 136 | author: req.fields.author, 137 | press: req.fields.press, 138 | inventory: parseInt(req.fields.inventory), 139 | date: req.fields.date, 140 | score: parseInt(req.fields.score), 141 | introduction: req.fields.introduction 142 | }; 143 | 144 | LibraryModel.updateBookById(bookId, admin, bookData) 145 | .then(function () { 146 | req.flash('success', 'Edit book success!'); 147 | res.redirect('/library'); 148 | }) 149 | .catch(next); 150 | }); 151 | 152 | router.get('/:bookId/borrow', checkIsAdmin, async (function (req, res, next) { 153 | var userId = req.session.user._id; 154 | var bookId = req.params.bookId; 155 | 156 | var borrow = { 157 | userId: userId, 158 | bookId: bookId, 159 | bool: false 160 | }; 161 | try { 162 | var book = await (LibraryModel.getRawBookById(borrow.bookId)); 163 | if (book.inventory >= 1) { 164 | try { 165 | await (LibraryModel.updateBookById(borrow.bookId, '5a246f7a4015d2070b89df75', { 166 | inventory: book.inventory - 1 167 | })) 168 | try { 169 | await (BorrowBookModel.create(borrow)) 170 | req.flash('success', 'Borrow Successfully!'); 171 | res.redirect('back'); 172 | } catch (error) { 173 | req.flash('error', 'Something go wrong, please try again!'); 174 | res.redirect('back'); 175 | } 176 | } catch (error) { 177 | req.flash('error', 'Something go wrong, please try again!'); 178 | res.redirect('back'); 179 | } 180 | 181 | } else { 182 | req.flash('error', 'Zero inventory!'); 183 | res.redirect('back'); 184 | } 185 | } catch (error) { 186 | req.flash('error', 'Something go wrong, please try again!'); 187 | res.redirect('back'); 188 | } 189 | 190 | })); 191 | router.get('/:bookId/borrow/:userId', checkIsAdmin, async (function (req, res, next) { 192 | var userId = req.params.userId; 193 | var bookId = req.params.bookId; 194 | var user = await (UserModel.getUserById(userId)); 195 | if (!user) { 196 | req.flash('error', 'There is no Student Id exist, please try another one!'); 197 | res.redirect('back'); 198 | return false; 199 | } 200 | 201 | var borrow = { 202 | userId: user._id, 203 | bookId: bookId, 204 | bool: false, 205 | }; 206 | 207 | try { 208 | var book = await (LibraryModel.getRawBookById(borrow.bookId)); 209 | if (book.inventory >= 1) { 210 | try { 211 | await (LibraryModel.updateBookById(borrow.bookId, '5a246f7a4015d2070b89df75', { 212 | inventory: book.inventory - 1 213 | })) 214 | try { 215 | await (BorrowBookModel.create(borrow)) 216 | req.flash('success', 'Borrow Successfully by ' + userId +'!'); 217 | res.redirect('back'); 218 | } catch (error) { 219 | req.flash('error', 'Something go wrong, please try again!'); 220 | res.redirect('back'); 221 | } 222 | } catch (error) { 223 | req.flash('error', 'Something go wrong, please try again!'); 224 | res.redirect('back'); 225 | } 226 | 227 | } else { 228 | req.flash('error', 'Zero inventory!'); 229 | res.redirect('back'); 230 | } 231 | } catch (error) { 232 | req.flash('error', 'Your book Id maybe wrong, please try again!'); 233 | res.redirect('back'); 234 | } 235 | 236 | })); 237 | 238 | 239 | 240 | module.exports = router; -------------------------------------------------------------------------------- /routes/post.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | 4 | var BorrowBookModel = require('../models/borrowBooks'); 5 | 6 | var checkLogin = require('../middlewares/check').checkLogin; 7 | 8 | router.get('/:userId', function(req, res) { 9 | 10 | }) -------------------------------------------------------------------------------- /routes/profile.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | var async = require('asyncawait/async'); 4 | var await = require('asyncawait/await'); 5 | var UserModel = require('../models/users'); 6 | var LibraryModel = require('../models/library'); 7 | var BorrowBookModel = require('../models/borrowBooks'); 8 | var checkLogin = require('../middlewares/check').checkLogin; 9 | var checkIsAdmin = require('../middlewares/check').checkIsAdmin; 10 | 11 | router.get('/:userId', checkLogin, async (function (req, res, next) { 12 | var currentUser = req.session.user; 13 | var userId = req.params.userId; 14 | var user = await (UserModel.getUserByDefaultId(userId)); 15 | 16 | try { 17 | var bBook = await (BorrowBookModel.getBorrowBooks(user._id)) 18 | 19 | var result = []; 20 | bBook.forEach(async (function(item) { 21 | var book = await (LibraryModel.getRawBookById(item.bookId)); 22 | 23 | var temp = item.created_at.split(" "); 24 | var returnTime = temp[0].split("-"); 25 | var rtMonth = parseInt(returnTime[1]) + 1; 26 | var rtYear = parseInt(returnTime[0]); 27 | if (rtMonth > 12) { 28 | rtYear += 1; 29 | rtMonth -= 12; 30 | } 31 | var rTime = rtYear + "-" + rtMonth + "-" + returnTime[2]; 32 | 33 | var returnDate = item.return_time; 34 | 35 | 36 | result.push({ 37 | id: item._id, 38 | userId: userId, 39 | bookId: item.bookId, 40 | created_at: item.created_at, 41 | returnTime: rTime, 42 | name: book.name, 43 | author: book.author, 44 | cover: book.cover, 45 | introduction: book.introduction, 46 | bool: item.bool, 47 | returnDate: returnDate 48 | }) 49 | })); 50 | setTimeout(() => { 51 | res.render('profile', { 52 | profile: user, 53 | borrow: result 54 | }) 55 | }, 1000) 56 | } catch(e) { 57 | req.flash('error', 'Something go wrong, please try again!'); 58 | } 59 | })); 60 | 61 | router.get('/:bookId/return2/:userId', checkIsAdmin, async (function (req, res, next) { 62 | var bookId = req.params.bookId, 63 | userId = req.params.userId; 64 | 65 | var user = await (UserModel.getUserById(userId)); 66 | 67 | try { 68 | await (BorrowBookModel.returnBookByBookId(bookId, user._id)); // bookid, user._id 69 | var book = await (LibraryModel.getRawBookById(bookId)); 70 | try { 71 | await (LibraryModel.updateBookById(bookId, '5a246f7a4015d2070b89df75', { 72 | inventory: book.inventory + 1 73 | })) 74 | req.flash('success', 'Return Successfully!'); 75 | res.redirect('back'); 76 | } catch (e) { 77 | req.flash('error', 'Something go wrong, please try again!'); 78 | res.redirect('back'); 79 | } 80 | } catch (error) { 81 | req.flash('error', 'Can\'t find the borrowed record, please try again!'); 82 | res.redirect('back'); 83 | } 84 | })); 85 | 86 | module.exports = router; -------------------------------------------------------------------------------- /routes/quick_borrow.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | var async = require('asyncawait/async'); 4 | var await = require('asyncawait/await'); 5 | var UserModel = require('../models/users'); 6 | var LibraryModel = require('../models/library'); 7 | var BorrowBookModel = require('../models/borrowBooks'); 8 | 9 | var checkIsAdmin = require('../middlewares/check').checkIsAdmin; 10 | 11 | router.get('/', checkIsAdmin, async (function (req, res, next) { 12 | var admin = req.query.admin; 13 | 14 | res.render('quick_borrow'); 15 | 16 | })); 17 | 18 | module.exports = router; -------------------------------------------------------------------------------- /routes/search.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | 4 | var LibraryModel = require('../models/library'); 5 | var checkLogin = require('../middlewares/check').checkLogin; 6 | 7 | router.get('/:payload', function (req, res, next) { 8 | var payload = req.params.payload, 9 | type = req.query.type; 10 | 11 | LibraryModel.searchBook(payload) 12 | .then(function (books) { 13 | switch (type) { 14 | case 'library': 15 | res.render('library', { 16 | books: books 17 | }); 18 | break; 19 | default: 20 | res.render('home', { 21 | books: books 22 | }); 23 | } 24 | }) 25 | .catch(next); 26 | }); 27 | 28 | 29 | 30 | module.exports = router; -------------------------------------------------------------------------------- /routes/signin.js: -------------------------------------------------------------------------------- 1 | var sha1 = require('sha1'); 2 | var express = require('express'); 3 | var router = express.Router(); 4 | 5 | var UserModel = require('../models/users'); 6 | var checkNotLogin = require('../middlewares/check').checkNotLogin; 7 | 8 | router.get('/', checkNotLogin, function (req, res, next) { 9 | res.render('signin') 10 | }); 11 | 12 | router.post('/', checkNotLogin, function (req, res, next) { 13 | var id = req.fields.id; 14 | var password = req.fields.password; 15 | 16 | UserModel.getUserById(id) 17 | .then(function (user) { 18 | if (!id) { 19 | req.flash('error', 'User does not exist!'); 20 | return res.redirect('back'); 21 | } 22 | if (sha1(password) !== user.password) { 23 | req.flash('error', 'Wrong user name or password!'); 24 | return res.redirect('back'); 25 | } 26 | req.flash('success', 'Signin successful!'); 27 | delete user.password; 28 | req.session.user = user; 29 | res.redirect('/home'); 30 | }) 31 | .catch(function(e) { 32 | req.flash('error', 'This user has not registered yet!'); 33 | res.redirect('/signin'); 34 | next(e) 35 | }); 36 | }); 37 | 38 | 39 | module.exports = router; -------------------------------------------------------------------------------- /routes/signout.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | 4 | var checkLogin = require('../middlewares/check').checkLogin; 5 | 6 | router.get('/', checkLogin, function (req, res, next) { 7 | req.session.user = null; 8 | req.flash('success', 'Sign out successfully!'); 9 | res.redirect('/home'); 10 | }); 11 | 12 | module.exports = router; -------------------------------------------------------------------------------- /routes/signup.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var path = require('path'); 3 | var sha1 = require('sha1'); 4 | var express = require('express'); 5 | var router = express.Router(); 6 | 7 | var UserModel = require('../models/users'); 8 | var checkNotLogin = require('../middlewares/check').checkNotLogin; 9 | var checkIsAdmin = require('../middlewares/check').checkIsAdmin; 10 | 11 | router.get('/', function (req, res, next) { 12 | res.render('signup'); 13 | }); 14 | 15 | router.post('/', function (req, res, next) { 16 | var userData = { 17 | id: req.fields.id, 18 | name: req.fields.name, 19 | gender: req.fields.gender, 20 | bio: req.fields.bio, 21 | avatar: req.files.avatar.path.split(path.sep).pop(), 22 | password: req.fields.password, 23 | repassword: req.fields.repassword 24 | } 25 | try { 26 | if (userData.password !== userData.repassword) { 27 | throw new Error('not match'); 28 | } 29 | } catch (e) { 30 | fs.unlink(req.files.avatar.path); 31 | req.flash('error', e.message); 32 | return res.redirect('/signup'); 33 | } 34 | 35 | userData.password = sha1(userData.password); 36 | 37 | var user = { 38 | id: userData.id, 39 | name: userData.name, 40 | password: userData.password, 41 | gender: userData.gender, 42 | bio: userData.bio, 43 | avatar: userData.avatar, 44 | isAdmin: false 45 | }; 46 | UserModel.create(user) 47 | .then(function (result) { 48 | user = result.ops[0]; 49 | delete user.password; 50 | req.flash('success', 'Registration success'); 51 | res.redirect('/home'); 52 | }) 53 | .catch(function (e) { 54 | fs.unlink(req.files.avatar.path); 55 | if (e.message.match('E11000 duplicate key')) { 56 | req.flash('error', 'This Student\'s ID has been used, please try another one!'); 57 | return res.redirect('/signup'); 58 | } 59 | next(e); 60 | }); 61 | }); 62 | 63 | module.exports = router; -------------------------------------------------------------------------------- /routes/users.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | 4 | router.get('/:name', function(req, res) { 5 | res.render('users', { 6 | name: req.params.name 7 | }) 8 | }); 9 | 10 | module.exports = router; -------------------------------------------------------------------------------- /views/404.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | <%= blog.title %> 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /views/book.ejs: -------------------------------------------------------------------------------- 1 | <%- include('./layout/header') %> 2 | 7 |
8 |

9 | <%= book.name %> 10 |

11 |
12 |
13 |
14 | "> 15 |
16 |
17 |

18 | Book ID: <%= book._id%> 19 |

20 |

21 | Location: <%= book.location%> 22 |

23 |

24 | Author: <%= book.author%> 25 |

26 |

27 | Press: <%= book.press%> 28 |

29 |

30 | Published Date: <%= book.date%> 31 |

32 |

33 | Score: 34 | 35 |

36 |

37 | Inventory: <%= book.inventory%> 38 |

39 |

40 | Pv: <%= book.pv%> 41 |

42 | 43 |
44 |
45 |
46 | <% if (user) { %> 47 | <% if(user.isAdmin){%> 48 |
49 |
50 | 51 | Borrow One 52 |
53 |
54 | <% } %> 55 | <% } %> 56 | 57 |
58 |
59 |
60 |
61 |

Brief Introduction

62 |

<%- book.introduction %>

63 |
64 | 65 |
66 | 67 | <% if (user) { %> 68 | <% if(user.isAdmin){%> 69 | 90 | <%}%> 91 | <% } %> 92 | 93 |
94 | 118 | <%- include('./layout/footer') %> -------------------------------------------------------------------------------- /views/borrow.ejs: -------------------------------------------------------------------------------- 1 | <%- include('./layout/header') %> 2 |
3 | <% borrowUser.forEach(function(user){ %> 4 |
5 | 6 | 7 | 8 |
9 | <%= user.name%> 10 |
11 |

Id : <%= user.id%>

12 |

Borrow Time: <%= user.borrowTime%>

13 |

Return Time: <%= user.bool == false ? "Not returned" : user.returnTime%>

14 | 15 |
16 |
17 |
18 | <% }) %> 19 |
20 | <%- include('./layout/footer') %> -------------------------------------------------------------------------------- /views/error.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | <%= blog.title %> 8 | 9 | 10 | 11 | 12 | 13 |

14 | <%= error.message %> 15 |

16 |

17 | <%= error.stack %> 18 |

19 | 20 | 21 | -------------------------------------------------------------------------------- /views/home.ejs: -------------------------------------------------------------------------------- 1 | <%- include('./layout/header') %> 2 | 7 | 8 |
9 | <% books.forEach(function (book) { %> 10 | <%if (book.show) {%> 11 |
12 |
13 | 14 | 15 | "> 16 | 17 |
18 |
19 | <%= book.name %> 20 |
21 |
22 | 23 |
24 | <%= book.author %> 25 |
26 | 27 |
28 | Like 29 | <% if(book.like){ %> 30 | 31 | <%} else {%> 32 | 33 | <% } %> 34 |
35 |
36 |
37 |
38 | <%}%> 39 | <% }) %> 40 |
41 | 42 | 76 | 77 | <%- include('./layout/footer') %> -------------------------------------------------------------------------------- /views/layout/footer.ejs: -------------------------------------------------------------------------------- 1 | 2 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /views/layout/header.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | <%- include('./nav-setting') %> 20 | <%- include('./nav') %> 21 | <%- include('./notification') %> -------------------------------------------------------------------------------- /views/layout/nav-setting.ejs: -------------------------------------------------------------------------------- 1 | 41 | -------------------------------------------------------------------------------- /views/layout/nav.ejs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /views/layout/notification.ejs: -------------------------------------------------------------------------------- 1 |
2 | 3 | <% if (success) { %> 4 |
5 |

6 | <%= success %> 7 |

8 |
9 | <% } %> 10 | 11 | <% if (error) { %> 12 |
13 |

14 | <%= error %> 15 |

16 |
17 | <% } %> 18 | 19 | 20 |
-------------------------------------------------------------------------------- /views/library.ejs: -------------------------------------------------------------------------------- 1 | <%- include('./layout/header') %> 2 | 12 |
13 |
14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | <% books.forEach(function (book) { %> 34 | 43 | 46 | 49 | 50 | 51 | 52 | 55 | 61 | 67 | 75 | 81 | 82 | <% }) %> 83 | 84 | 85 | 86 | 87 | 88 | 89 | 152 | 198 | 210 | 211 | 212 |
CoverNameAuthorPressPublished DateScoreBorrowedInventoryIntroductionOperating
44 | cover" > 45 | 47 | <%= book.name %> 48 | <%= book.author %><%= book.press %><%= book.date %> 53 |
54 |
56 | Has lent <%= book.borrowCount %> books
57 | <% if (book.borrowCount > 0) { %> 58 | Examine 59 | <% } %> 60 |
62 | <%= book.inventory %>
63 | 66 |
68 |
69 |
View
70 |
71 | 74 |
76 | 78 | 80 |
213 |
214 | 215 | 475 | 476 | <%- include('./layout/footer') %> -------------------------------------------------------------------------------- /views/profile.ejs: -------------------------------------------------------------------------------- 1 | <%- include('./layout/header') %> 2 |
3 |

4 | <%= profile.name %> 5 |

6 |
7 |
8 |
9 |
10 | "> 11 |
12 |
13 |
14 |

15 | Id: 16 | <%= profile.id%> 17 |

18 |

19 | Gender: 20 | 21 |

22 |

23 | Introduction: 24 | <%= profile.bio%> 25 |

26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |

Borrowed books

34 |
35 | <% borrow.forEach(function(item) {%> 36 |
37 |
38 | 39 |
40 |
41 |
42 | <%= item.name %> 43 |
44 |
45 |
46 | <%= item.author %> 47 | <%= item.id %> 48 |
49 |
50 | Borrow date: <%= item.created_at %> 51 | <% if(item.bool) {%> 52 | Return date: <%= item.returnDate %> 53 | <% } else {%> 54 | Expire date: <%= item.returnTime %> 55 | <% }%> 56 | 57 |
58 |
59 |
60 |

61 | <%= item.introduction %> 62 |

63 |
64 |
65 | <% if(item.bool) {%> 66 |

67 | Returned 68 |

69 | <% } else {%> 70 |

71 | Not returned 72 |

73 | <% }%> 74 | 75 | 76 |
77 | <% if(user._id == '5a1e5e12e3028a132aee2bab' && !item.bool){%> 78 |
79 |
Return the book
80 |
81 | <% } %> 82 |
83 |
84 | <% }) %> 85 |
86 |
87 |
88 | 89 | 101 |
102 | 126 | <%- include('./layout/footer') %> -------------------------------------------------------------------------------- /views/quick_borrow.ejs: -------------------------------------------------------------------------------- 1 | <%- include('./layout/header') %> 2 |
3 |
4 |
5 |
6 |
7 |

8 |
9 | Quick Borrow & Return 10 |
11 |

12 |
13 |
14 |
15 |
16 | 17 | 18 |
19 |
20 |
21 |
22 | 23 | 24 |
25 |
26 |
27 |
Return
28 |
Borrow
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | 37 |
38 | 39 | 68 | <%- include('./layout/footer') %> -------------------------------------------------------------------------------- /views/signin.ejs: -------------------------------------------------------------------------------- 1 | <%- include('./layout/header') %> 2 | 3 |
4 |
5 |
6 |
7 |
8 |

9 |
10 | Sign in to your account 11 |
12 |

13 |
14 |
15 |
16 |
17 | 18 | 19 |
20 |
21 |
22 |
23 | 24 | 25 |
26 |
27 | 28 |
29 | 30 |
31 | 32 |
33 | 34 |
35 | Sign Up 36 |
37 |
38 |
39 |
40 | 41 |
42 | 78 | <%- include('./layout/footer') %> -------------------------------------------------------------------------------- /views/signup.ejs: -------------------------------------------------------------------------------- 1 | <%- include('./layout/header') %> 2 | 3 |
4 |
5 |
6 |
7 |
8 | 9 | 10 |
11 |
12 | 13 | 14 |
15 |
16 | 17 | 18 |
19 |
20 | 21 | 22 |
23 |
24 | 25 | 30 |
31 |
32 | 33 | 34 |
35 |
36 | 37 | 38 |
39 | 40 |
41 |
42 |
43 | 44 | 117 | <%- include('./layout/footer') %> -------------------------------------------------------------------------------- /views/users.ejs: -------------------------------------------------------------------------------- 1 | <%- include('./layout/header') %> 2 |

3 | <%= name.toUpperCase() %> 4 |

5 |

Hello, 6 | <%= name %> 7 |

8 | <%- include('./layout/footer') %> --------------------------------------------------------------------------------