123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470 |
- /* vim: set ts=2: */
- // DEPENDENCIES
- var crypto = require( 'crypto' );
- var mongoose = require( 'mongoose' );
- var Schema = mongoose.Schema;
- var ObjectId = mongoose.SchemaTypes.ObjectId;
- // SUPPORT FUNCTIONS
- function salt() {
- return Math.round( ( new Date().valueOf() * Math.random() ) ).toString();
- }
- // MODELS
- // user
- var UserSchema = new Schema( {
- email : { type : String, require: true, index : { unique : true } },
- school : String,
- name : String,
- affil : String,
- created : { type : Date, default : Date.now },
- hashed : String,
- activated : Boolean,
- activateCode : String,
- resetPassCode : String,
- resetPassDate : Date,
- salt : String,
- session : String,
- showName : { 'type' : Boolean, 'default' : true },
- admin : { 'type' : Boolean, 'default' : false }
- });
- UserSchema.virtual( 'sanitized' ).get(function() {
- var user = {
- email: this.email,
- name: this.name,
- affil: this.affil,
- showName: this.showName,
- admin: this.admin
- }
- return user;
- });
- UserSchema.virtual( 'displayName' )
- .get( function() {
- if( this.showName ) {
- return this.name;
- } else {
- return this.email;
- }
- });
- UserSchema.virtual( 'password' )
- .set( function( password ) {
- this.salt = salt();
- this.hashed = this.encrypt( password );
- });
- UserSchema.virtual( 'isComplete' )
- .get( function() {
- // build on this as the schema develops
- return ( this.name && this.affil && this.hashed );
- });
- UserSchema.method( 'encrypt', function( password ) {
- var hmac = crypto.createHmac( 'sha1', this.salt );
- return hmac.update( password ).digest( 'hex' );
- });
- UserSchema.method( 'authenticate', function( plaintext ) {
- return ( this.encrypt( plaintext ) === this.hashed );
- });
- UserSchema.method('genRandomPassword', function () {
- // this function generates the random password, it does not keep or save it.
- var plaintext = '';
- var len = 8;
- var charSet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
- for (var i = 0; i < len; i++) {
- var randomPoz = Math.floor(Math.random() * charSet.length);
- plaintext += charSet.substring(randomPoz, randomPoz + 1);
- }
- return plaintext;
- });
- UserSchema.method( 'setResetPassCode', function ( code ) {
- this.resetPassCode = code;
- this.resetPassDate = new Date();
- return this.resetPassCode;
- });
- UserSchema.method( 'canResetPassword', function ( code ) {
- // ensure the passCode is valid, matches and the date has not yet expired, lets say 2 weeks for good measure.
- var value = false;
- var expDate = new Date();
- expDate.setDate(expDate.getDate() - 14);
- // we have a valid code and date
- if (this.resetPassCode != null && this.resetPassDate != null && this.resetPassDate >= expDate && this.resetPassCode == code) {
- value = true;
- }
- return value;
- });
- UserSchema.method( 'resetPassword', function ( code, newPass1, newPass2) {
- // ensure the date has not expired, lets say 2 weeks for good measure.
- var success = false;
- if (this.canResetPassword(code) && newPass1 != null && newPass1.length > 0 && newPass1 == newPass2) {
- this.password = newPass1;
- this.resetPassCode = null;
- this.resetPassDate = null;
- success = true;
- }
- return success;
- });
- var User = mongoose.model( 'User', UserSchema );
- // schools
- var SchoolSchema = new Schema( {
- name : { type : String, required : true },
- description : String,
- url : String,
- created : { type : Date, default : Date.now },
- hostnames : Array,
- users : Array,
- courseNum : Number
- });
- SchoolSchema.virtual( 'sanitized' ).get(function() {
- var school = {
- _id: this._id,
- name: this.name,
- description: this.description,
- url: this.url,
- coursesNum: this.courseNum
- }
- return school;
- })
- SchoolSchema.method( 'authorize', function( user, cb ) {
- return cb(user.admin || ( this.users.indexOf( user._id ) !== -1 ));
- });
- var School = mongoose.model( 'School', SchoolSchema );
- // harvardcourses
- var HarvardCourses = new Schema( {
- cat_num : Number, // Catalog numb, unique_togther w/ term
- term : String, // FALL or SPRING
- bracketed : Boolean,
- field : String, // TODO: Add docs
- number : Number, // string, int, float, intStringFloat
- title : String,
- faculty : String, // hash fk to faculty table
- description : String,
- prerequisites : String,
- notes : String,
- meetings : String, // TODO: try to auto parse this
- building : String, // FIXME: Most == '', this is why we have to update
- room : String
- });
- HarvardCourses.virtual( 'sanitized' ).get(function() {
- var hcourse = {
- _id : this._id,
- title : this.name,
- field : this.field,
- number : this.number,
- desc : this.description,
- meetings: this.meetings,
- building: this.building,
- room : this.room,
- faculty : this.faculty
- }
- return hcourse
- })
- // courses
- var CourseSchema = new Schema( {
- name : { type : String, required : true },
- number : String,
- description : String,
- instructor : ObjectId,
- subject : String,
- department : String,
- // courses are tied to one school
- school : ObjectId,
- // XXX: room for additional resources
- created : { type : Date, default : Date.now },
- creator : ObjectId,
- deleted : Boolean,
- // many users may subscribe to a course
- users : Array,
- lectureNum : Number
- });
- CourseSchema.virtual( 'sanitized' ).get(function() {
- var course = {
- _id: this._id,
- name: this.name,
- number: this.number || 'None',
- description: this.description || 'None',
- subject: this.subject || 'None',
- department: this.department || 'None',
- lectureNum: this.lecturenum
- }
- return course;
- });
- CourseSchema.virtual( 'displayName' )
- .get( function() {
- if( this.number ) {
- return this.number + ': ' + this.name;
- } else {
- return this.name;
- }
- });
- CourseSchema.method( 'authorize', function( user, cb ) {
- School.findById( this.school, function( err, school ) {
- if ( school ) {
- school.authorize( user, function( result ) {
- return cb( result );
- })
- }
- });
- });
- CourseSchema.method( 'subscribed', function( user ) {
- return ( this.users.indexOf( user ) > -1 ) ;
- });
- CourseSchema.method( 'subscribe', function( user, callback ) {
- var id = this._id;
- // mongoose issue #404
- Course.collection.update( { '_id' : id }, { '$addToSet' : { 'users' : user } }, function( err ) {
- callback( err );
- });
- });
- CourseSchema.method( 'unsubscribe', function( user, callback ) {
- var id = this._id;
- // mongoose issue #404
- Course.collection.update( { '_id' : id }, { '$pull' : { 'users' : user } }, function( err ) {
- callback( err );
- });
- });
- CourseSchema.method( 'delete', function( callback ) {
- var id = this._id;
- Course.collection.update( { '_id' : id }, { '$set' : { 'deleted' : true } }, function( err ) {
- if (callback) callback( err );
- Lecture.find( { course: id }, function( err, lectures) {
- if (lectures.length > 0) {
- lectures.forEach(function(lecture) {
- lecture.delete();
- })
- }
- })
- })
- });
- var Course = mongoose.model( 'Course', CourseSchema );
- // lectures
- var LectureSchema = new Schema( {
- name : { type : String, required : true },
- date : { type : Date, default: Date.now },
- live : Boolean,
- creator : ObjectId,
- deleted : Boolean,
- course : ObjectId
- });
- LectureSchema.virtual( 'sanitized' ).get(function() {
- var lecture = {
- _id: this._id,
- name: this.name,
- date: this.date,
- live: this.live
- }
- return lecture;
- })
- LectureSchema.method( 'authorize', function( user, cb ) {
- Course.findById( this.course, function( err, course ) {
- if (course) {
- course.authorize( user, function( res ) {
- return cb( res );
- })
- } else {
- return cb( false );
- }
- });
- });
- LectureSchema.method( 'delete', function( callback ) {
- var id = this._id;
- Lecture.collection.update( { '_id' : id }, { '$set' : { 'deleted' : true } }, function( err ) {
- if (callback) callback( err );
- Note.find( { lecture : id }, function(err, notes) {
- notes.forEach(function(note) {
- note.delete();
- })
- })
- Post.find( { lecture : id }, function(err, posts) {
- posts.forEach(function(post) {
- post.delete();
- })
- })
- })
- });
- var Lecture = mongoose.model( 'Lecture', LectureSchema );
- // notes
- var NoteSchema = new Schema( {
- name : { type : String, required : true },
- path : String,
- public : Boolean,
- roID : String,
- visits : Number,
- created : { type : Date, default : Date.now },
- creator : ObjectId,
- deleted : Boolean,
- lecture : ObjectId,
- collaborators : [String]
- });
- NoteSchema.virtual( 'sanitized').get(function() {
- var note = {
- _id: this._id,
- name: this.name,
- path: this.path,
- public: this.public,
- roID: this.roID,
- visits: this.visits
- }
- return note;
- });
- NoteSchema.method( 'authorize', function( user, cb ) {
- Lecture.findById( this.lecture, function( err, lecture ) {
- if (lecture) {
- lecture.authorize( user, function( res ) {
- return cb( res );
- })
- } else {
- return cb( false );
- }
- });
- });
- NoteSchema.method( 'addVisit', function() {
- var id = this._id;
- Note.collection.update( { '_id' : id }, { '$inc' : { 'visits' : 1 } } );
- });
- NoteSchema.method( 'delete', function( callback ) {
- var id = this._id;
- Note.collection.update( { '_id' : id }, { '$set' : { 'deleted' : true } }, function( err ) {
- if (callback) callback( err );
- })
- });
- var Note = mongoose.model( 'Note', NoteSchema );
- // comments
- var PostSchema = new Schema({
- date : { type : Date, default : Date.now },
- body : String,
- votes : [String],
- reports : [String],
- public : Boolean,
- userid : String, // ObjectId,
- userName : String,
- userAffil : String,
- comments : Array,
- lecture : String, // ObjectId
- deleted : Boolean
- })
- PostSchema.method( 'delete', function( callback ) {
- var id = this._id;
- Post.collection.update( { '_id' : id }, { '$set' : { 'deleted' : true } }, function( err ) {
- if (callback) callback( err );
- })
- });
- mongoose.model( 'Post', PostSchema );
- var ArchivedCourse = new Schema({
- id: Number,
- instructor: String,
- section: String,
- name: String,
- description: String,
- subject_id: Number
- })
- mongoose.model( 'ArchivedCourse', ArchivedCourse )
- var ArchivedNote = new Schema({
- course_id: Number,
- topic: String,
- text: String
- })
- ArchivedNote.virtual( 'sanitized' ).get(function() {
- var note = {
- _id: this._id,
- topic: this.topic === '' ? (this.text.replace(/(<(.|\n)*?>)|[\r\n\t]*/g, '')).substr(0, 15) + '...' : this.topic
- }
- return note;
- })
- mongoose.model( 'ArchivedNote', ArchivedNote )
- var ArchivedSubject = new Schema({
- id: Number,
- name: String
- })
- mongoose.model( 'ArchivedSubject', ArchivedSubject )
- module.exports.mongoose = mongoose;
|