加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
db.js 12.45 KB
一键复制 编辑 原始数据 按行查看 历史
Albeforia 提交于 2016-01-15 23:42 . @ fix invalid token
var DB = ((mongoose, db_name) => {
var utils = require('./utils');
//==============================
// roles definition
var ROLE = {
admin: '管理员',
oaa: '教务处',
teacher: '教师',
student: '学生'
};
//==============================
//==============================
// schemas definition
var Schema = mongoose.Schema;
//------------------------------
// {counters}
// simulate auto-incrementing field
var schema_counters = new Schema({
name: String,
seq: Number
});
//------------------------------
// {users}
// 'seq' should auto-increment whenever
// create, change infomation or revoke
var schema_users = new Schema({
id: { type: Number, unique: true },
seq: Number,
username: String,
credential: String,
role: String,
name: String,
telephone: Number,
}, { id: false });
//------------------------------
// {projects}
var schema_projects = new Schema({
id: { type: Number, unique: true },
creator: { type: Schema.Types.ObjectId, ref: 'User' },
name: String,
description: String,
date: Date,
budget: Number,
// 0: 待审批 1: 被拒绝 2: 已批准(选择学生)
// 3: 开题 4: 中期 5: 结题 >5: 已完成
state: { type: Number, default: 0 },
// 0: empty 1: 审批 2: 拒绝 3: 通过
report_state: { type: Number, default: 0 },
applicants: [{ type: Schema.Types.ObjectId, ref: 'User' }],
participants: [{ type: Schema.Types.ObjectId, ref: 'User' }]
}, { id: false });
schema_projects.path('date').get(e => e.toLocaleDateString('zh-Hans-CN'));
schema_projects.set('toJSON', { getters: true, virtuals: false });
// do NOT use arrow function for 'this' binding
schema_projects.methods.add_applicants = function(students) {
if (this.state != 2) throw 'invalid';
students.forEach(e => this.applicants.indexOf(e) == -1
&& this.applicants.push(e));
return this;
};
schema_projects.methods.add_participants = function(students) {
if (this.state != 2) throw 'invalid';
students.forEach(e => this.participants.indexOf(e) == -1
&& this.participants.push(e));
return this;
};
//------------------------------
// {activities}
var schema_activities = new Schema({
id: { type: Number, unique: true },
creator: { type: Schema.Types.ObjectId, ref: 'User' },
project: { type: Schema.Types.ObjectId, ref: 'Project' },
content: String,
cost: Number,
date: Date
}, { id: false });
schema_activities.path('date').get(e => e.toLocaleDateString('zh-Hans-CN'));
schema_activities.set('toJSON', { getters: true, virtuals: false });
//------------------------------
// {reports}
var schema_reports = new Schema({
id: { type: Number, unique: true },
//creator: { type: Schema.Types.ObjectId, ref: 'User' },
project: { type: Schema.Types.ObjectId, ref: 'Project' },
content: String,
// 1: 开题 2: 中期 3: 结题
type: Number,
// 1: 审批 2: 拒绝 3: 通过
state: { type: Number, default: 1 },
date: Date
}, { id: false });
schema_reports.path('date').get(e => e.toLocaleDateString('zh-Hans-CN'));
schema_reports.set('toJSON', { getters: true, virtuals: false });
//==============================
//==============================
// compile models
var Counter = mongoose.model('Counter', schema_counters);
// FIXME may be better
Counter.next_seq = name => {
return Counter.findOneAndUpdate(
{ name },
{ $inc: { seq: 1 } },
{ new: true, upsert: true }
).exec().then(x => x.seq);
};
var User = mongoose.model('User', schema_users);
var Project = mongoose.model('Project', schema_projects);
var Activity = mongoose.model('Activity', schema_activities);
var Report = mongoose.model('Report', schema_reports);
//==============================
//==============================
// API definition
var _exclude = { _id: 0, __v: 0 };
var list_query = (model, query, after, sort, limit) => {
query = query || {};
after = after || -1;
sort = sort || -1;
limit = limit || 10;
if (after >= 0) {
query.id = { $lt: after };
}
return model.find(query, _exclude).sort({ id: sort }).limit(limit);
};
var api = {
user_login: (username, password) => {
return User.findOne({
username,
credential: { $exists: true }
}).exec().then(user => {
if (!user) {
throw 'not exist';
}
// FIXME check credential
if (user.credential != password) {
throw 'auth failed';
}
var token = utils.make_token(user.seq, user.role);
return { token, name: user.name };
});
},
user_revoke_self: (_self) => {
'@roles'
return Counter.next_seq('users_seq').then(seq => {
return User.findByIdAndUpdate(_self._id, { $set: { seq } }).exec();
});
},
user_validate: (username, password) => {
//
},
user_password_self: (value, _self) => {
'@roles'
return Counter.next_seq('users_seq').then(seq => {
return User.findByIdAndUpdate(_self._id, {
$set: { seq, credential: value }
}).exec();
});
},
user_password: (user, value) => {
'@roles admin'
return Counter.next_seq('users_seq').then(seq => {
return User.findOneAndUpdate({ id: user }, {
$set: { seq, credential: value }
}).exec();
});
},
user_add: (username, password, role, name, telephone) => {
'@roles admin'
var user = new User({
username,
credential: password, // FIXME encryption
role, name, telephone
});
return Counter.next_seq('users_id').then(id => {
Counter.next_seq('users_seq').then(seq => {
user.id = id;
user.seq = seq;
user.save();
return user;
})
});
},
user_list: (after) => {
'@roles admin'
return list_query(User, {}, after).exec();
},
user_leave: (user) => {
'@roles admin'
// FIXME set credential to NULL?
return User.findOneAndRemove({ id: user }).exec();
},
project_add: (name, description, budget, _self) => {
'@roles teacher'
var prj = new Project({
name, description, budget,
creator: _self._id,
date: new Date()
});
Counter.next_seq('projects_id').then(id => {
prj.id = id;
prj.save();
return prj;
});
},
project_list: (_self, after) => {
'@roles student oaa'
switch (_self.role) {
case ROLE.student:
return list_query(Project, { state: 2 }, after)
.populate('creator applicants participants')
.find({ $nor: [
{ applicants: { _id: _self._id } },
{ participants: { _id: _self._id } }
]})
.exec();
case ROLE.oaa:
return list_query(Project, {}, after)
.populate('creator')
.exec();
default:
break;
}
},
project_list_self: (_self, after) => {
'@roles teacher'
return list_query(Project, { creator: _self._id }, after)
.select('-creator -applicants -participants')
.exec();
},
project_approve: (project) => {
'@roles oaa'
return Project.findOneAndUpdate({ id: project }, {
$set: { state: 2 }
});
},
project_reject: (project, reason) => {
'@roles oaa'
return Project.findOneAndUpdate({ id: project }, {
$set: { state: 1 }
});
},
project_student_list: (project, after) => {
'@roles teacher'
// FIXME use after
return Project.findOne({ id: project })
.populate('applicants participants')
.exec().then(p => {
var field = p.state == 2 ? 'applicants'
: p.state == 3 ? 'participants' : 'invalid';
return p[field];
});
},
project_student_approve: (project, $students) => {
'@roles teacher'
return Project.findOne({ id: project })
.exec().then(prj => {
return User.find({ id: { $in: $students } })
.exec().then(s => {
prj.add_participants(s.map(e => e._id));
prj.state = 3;
prj.save();
return prj;
});
});
},
project_activity_add: (project, content, cost, _self) => {
'@roles student'
return Project.findOne({ id: project })
.exec().then(prj => {
var act = new Activity({
creator: _self._id,
project: prj._id,
content, cost,
date: new Date()
});
Counter.next_seq('activities_id').then(id => {
act.id = id;
act.save();
return act;
});
});
},
project_activity_list: (project, after) => {
'@roles teacher oaa'
return list_query(Activity, {}, after)
.populate('project creator')
.exec().then(ls => ls.filter(e => e.project.id == project));
},
project_activity_list_self: (project, _self, after) => {
'@roles student'
return list_query(Activity, { creator: _self._id }, after)
.populate('project')
.exec().then(ls => ls.filter(e => e.project.id == project));
},
project_report_add: (project, content, _self) => {
'@roles student'
return Project.findOneAndUpdate({ id: project }, {report_state: 1})
.exec().then(prj => {
var rep = new Report({
project: prj._id,
content,
type: prj.state - 2,
date: new Date()
});
Counter.next_seq('reports_id').then(id => {
rep.id = id;
rep.save();
return rep;
});
});
},
project_report_list_open: (project, after) => {
'@roles teacher oaa student'
return list_query(Report, {type : 1}, after)
.populate('project')
.exec().then(ls => ls.filter(e => e.project.id == project));
},
project_report_list_middle: (project, after) => {
'@roles teacher oaa student'
return list_query(Report, {type : 2}, after)
.populate('project')
.exec().then(ls => ls.filter(e => e.project.id == project));
},
project_report_list_final: (project, after) => {
'@roles teacher oaa student'
return list_query(Report, {type : 3}, after)
.populate('project')
.exec().then(ls => ls.filter(e => e.project.id == project));
},
project_report_approve: (report) => {
'@roles teacher'
return Report.findOneAndUpdate({ id: report }, { state: 3 })
.populate('project')
.exec().then(rep => {
return Project.findByIdAndUpdate(rep.project._id, {report_state : 0, $inc: {state: 1} });
});
},
project_report_reject: (report) => {
'@roles teacher'
return Report.findOneAndUpdate({ id: report }, { state: 2 })
.populate('project')
.exec().then(rep => {
return Project.findByIdAndUpdate(rep.project._id, {report_state : 2});
});
},
student_apply: (project, _self) => {
'@roles student'
return Project.findOne({ id: project })
.exec().then(prj => prj.add_applicants([_self._id]).save());
},
student_cancel: (project, _self) => {
'@roles student'
return Project.findOneAndUpdate(
{ id: project },
{ $pull: { applicants: _self._id } }).exec();
},
student_list_project_pending: (_self, after) => {
'@roles student'
return list_query(Project, { state: 2 }, after)
.populate('creator applicants')
.find({ applicants: { _id: _self._id } })
.select('-applicants -participants')
.exec();
},
student_list_project: (_self, after) => {
'@roles student'
return list_query(Project, { state: {$gte : 3} }, after)
.populate('creator participants')
.find({ participants: { _id: _self._id } })
.select('-applicants -participants')
.exec();
},
};
//==============================
// set privileges
var privileges = {};
Object.keys(api).map(e => ({ key: e, value: api[e] })).forEach(e => {
var roles = e.value.toString().match(/'@roles.*?'/);
if (roles) {
privileges[e.key] = [];
roles[0].replace(/'/g, '').split(' ').slice(1)
.forEach(x => privileges[e.key].push(ROLE[x]));
if (privileges[e.key].length == 0) {
privileges[e.key] = Object.keys(ROLE).map(e => ROLE[e]);
}
}
});
var check_privilege = (api, token) => {
// privilege undefined <=> don't need token
if (!privileges[api]) {
return Promise.resolve(1);
}
if (!token) throw 'denied';
var raw_token = utils.unpack_token(token);
if (privileges[api].indexOf(raw_token.role) === -1) throw 'denied';
return User.findOne({ seq: raw_token.seq }).exec().then(user => user);
};
var connect = (err, ok) => {
err = err || (() => { });
ok = ok || (() => { });
mongoose.connect('mongodb://localhost/' + db_name);
var db = mongoose.connection;
db.on('error', err);
db.once('open', ok);
};
return {
connect, api, check_privilege
}
})(require('mongoose'), 'rsms');
module.exports = DB;
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化