5 var crypto = require( 'crypto' );
7 var mongoose = require( 'mongoose' );
9 var Schema = mongoose.Schema;
10 var ObjectId = mongoose.SchemaTypes.ObjectId;
15 return Math.round( ( new Date().valueOf() * Math.random() ) ).toString();
22 var UserSchema = new Schema( {
23 email : { type : String, require: true, index : { unique : true } },
27 created : { type : Date, default : Date.now },
30 activateCode : String,
31 resetPassCode : String,
35 showName : { 'type' : Boolean, 'default' : true },
36 admin : { 'type' : Boolean, 'default' : false }
39 UserSchema.virtual( 'displayName' )
48 UserSchema.virtual( 'password' )
49 .set( function( password ) {
51 this.hashed = this.encrypt( password );
54 UserSchema.virtual( 'isComplete' )
56 // build on this as the schema develops
58 return ( this.name && this.affil && this.hashed );
61 UserSchema.method( 'encrypt', function( password ) {
62 var hmac = crypto.createHmac( 'sha1', this.salt );
64 return hmac.update( password ).digest( 'hex' );
67 UserSchema.method( 'authenticate', function( plaintext ) {
68 return ( this.encrypt( plaintext ) === this.hashed );
71 UserSchema.method('genRandomPassword', function () {
72 // this function generates the random password, it does not keep or save it.
76 var charSet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
77 for (var i = 0; i < len; i++) {
78 var randomPoz = Math.floor(Math.random() * charSet.length);
79 plaintext += charSet.substring(randomPoz, randomPoz + 1);
85 UserSchema.method( 'setResetPassCode', function ( code ) {
86 this.resetPassCode = code;
87 this.resetPassDate = new Date();
88 return this.resetPassCode;
91 UserSchema.method( 'canResetPassword', function ( code ) {
92 // ensure the passCode is valid, matches and the date has not yet expired, lets say 2 weeks for good measure.
95 var expDate = new Date();
96 expDate.setDate(expDate.getDate() - 14);
98 // we have a valid code and date
99 if (this.resetPassCode != null && this.resetPassDate != null && this.resetPassDate >= expDate && this.resetPassCode == code) {
106 UserSchema.method( 'resetPassword', function ( code, newPass1, newPass2) {
107 // ensure the date has not expired, lets say 2 weeks for good measure.
110 if (this.canResetPassword(code) && newPass1 != null && newPass1.length > 0 && newPass1 == newPass2) {
111 this.password = newPass1;
112 this.resetPassCode = null;
113 this.resetPassDate = null;
120 var User = mongoose.model( 'User', UserSchema );
124 var SchoolSchema = new Schema( {
125 name : { type : String, required : true },
126 description : String,
129 created : { type : Date, default : Date.now },
135 SchoolSchema.virtual( 'sanitized' ).get(function() {
139 description: this.description,
146 SchoolSchema.method( 'authorize', function( user, cb ) {
147 return cb(user.admin || ( this.users.indexOf( user._id ) !== -1 ));
150 var School = mongoose.model( 'School', SchoolSchema );
154 var CourseSchema = new Schema( {
155 name : { type : String, required : true },
157 description : String,
158 instructor : ObjectId,
161 // courses are tied to one school
164 // XXX: room for additional resources
165 created : { type : Date, default : Date.now },
169 // many users may subscribe to a course
173 CourseSchema.virtual( 'sanitized' ).get(function() {
178 description: this.description,
179 subject: this.subject,
180 department: this.department
186 CourseSchema.virtual( 'displayName' )
189 return this.number + ': ' + this.name;
195 CourseSchema.method( 'authorize', function( user, cb ) {
196 School.findById( this.school, function( err, school ) {
198 school.authorize( user, function( result ) {
205 CourseSchema.method( 'subscribed', function( user ) {
206 return ( this.users.indexOf( user ) > -1 ) ;
209 CourseSchema.method( 'subscribe', function( user, callback ) {
212 // mongoose issue #404
213 Course.collection.update( { '_id' : id }, { '$addToSet' : { 'users' : user } }, function( err ) {
218 CourseSchema.method( 'unsubscribe', function( user, callback ) {
221 // mongoose issue #404
222 Course.collection.update( { '_id' : id }, { '$pull' : { 'users' : user } }, function( err ) {
227 CourseSchema.method( 'delete', function( callback ) {
230 Course.collection.update( { '_id' : id }, { '$set' : { 'deleted' : true } }, function( err ) {
231 if (callback) callback( err );
232 Lecture.find( { course: id }, function( err, lectures) {
233 if (lectures.length > 0) {
234 lectures.forEach(function(lecture) {
242 var Course = mongoose.model( 'Course', CourseSchema );
246 var LectureSchema = new Schema( {
247 name : { type : String, required : true },
248 date : { type : Date, default: Date.now },
256 LectureSchema.method( 'authorize', function( user, cb ) {
257 Course.findById( this.course, function( err, course ) {
259 course.authorize( user, function( res ) {
268 LectureSchema.method( 'delete', function( callback ) {
271 Lecture.collection.update( { '_id' : id }, { '$set' : { 'deleted' : true } }, function( err ) {
272 if (callback) callback( err );
273 Note.find( { lecture : id }, function(err, notes) {
274 notes.forEach(function(note) {
278 Post.find( { lecture : id }, function(err, posts) {
279 posts.forEach(function(post) {
286 var Lecture = mongoose.model( 'Lecture', LectureSchema );
290 var NoteSchema = new Schema( {
291 name : { type : String, required : true },
296 created : { type : Date, default : Date.now },
302 collaborators : [String]
305 NoteSchema.method( 'authorize', function( user, cb ) {
306 Lecture.findById( this.lecture, function( err, lecture ) {
308 lecture.authorize( user, function( res ) {
317 NoteSchema.method( 'addVisit', function() {
320 Note.collection.update( { '_id' : id }, { '$inc' : { 'visits' : 1 } } );
323 NoteSchema.method( 'delete', function( callback ) {
326 Note.collection.update( { '_id' : id }, { '$set' : { 'deleted' : true } }, function( err ) {
327 if (callback) callback( err );
331 var Note = mongoose.model( 'Note', NoteSchema );
335 var PostSchema = new Schema({
336 date : { type : Date, default : Date.now },
342 userid : String, // ObjectId,
348 lecture : String, // ObjectId
352 PostSchema.method( 'delete', function( callback ) {
355 Post.collection.update( { '_id' : id }, { '$set' : { 'deleted' : true } }, function( err ) {
356 if (callback) callback( err );
360 mongoose.model( 'Post', PostSchema );
362 var ArchivedCourse = new Schema({
371 mongoose.model( 'ArchivedCourse', ArchivedCourse )
373 var ArchivedNote = new Schema({
379 mongoose.model( 'ArchivedNote', ArchivedNote )
381 var ArchivedSubject = new Schema({
386 mongoose.model( 'ArchivedSubject', ArchivedSubject )
388 module.exports.mongoose = mongoose;