-
Notifications
You must be signed in to change notification settings - Fork 6
/
models.coffee
221 lines (188 loc) · 5.01 KB
/
models.coffee
1
2
3
4
5
6
7
8
9
10
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
crypto = require('crypto')
CoffeeScript = require 'coffee-script'
dateFormat = require 'dateformat'
async = require('async')
toLower = (v) ->
v.toLowerCase()
validatePresenceOf = (value) ->
value && value.length
defineModels = (mongoose, next) ->
Schema = mongoose.Schema
ObjectId = Schema.ObjectId
###
Model: User
###
User = new Schema
username:
type: String
validate: [validatePresenceOf, 'username is required']
index:
unique: true
email:
type: String
validate: [validatePresenceOf, 'email is required']
index: true
name:
first:
type: String
default: ""
last:
type: String
default: ""
hashed_password: String
salt: String
roles: [String]
User.virtual('id').get () ->
this._id.toHexString()
User.virtual('name.full').get () ->
return this.name.first + " " + this.name.last
User.virtual('name.initials').get () ->
initials = String(this.name.first).substr(0,1) + String(this.name.last).substr(0,1)
initials = initials.toUpperCase()
return initials
User.virtual('password').set (password) ->
this._password = password
this.salt = this.makeSalt()
this.hashed_password = this.encryptPassword password
.get () -> this._password
User.method 'authenticate', (plainText) ->
this.encryptPassword(plainText) is this.hashed_password
User.method 'makeSalt', () ->
Math.round(new Date().valueOf() * Math.random()) + ''
User.method 'encryptPassword', (password) ->
crypto.createHmac('sha1', this.salt).update(password).digest('hex')
User.pre 'save', (next) ->
if !validatePresenceOf this.hashed_password
next new Error('Invalid password')
else
next()
User.method 'hasRoles', (roles, next) ->
Role = mongoose.model 'Role'
Group = mongoose.model 'Group'
tasks = []
user_id = this._id
for rk in roles
do (rk) ->
tasks.push (cb) ->
Role.findOne {name: rk}, (err, role) ->
if err || !role
return cb(null, 0)
if role.hasUser user_id
cb(null, 1)
else if role.groups.length > 0
async.forEach role.groups, (grp, cbb) ->
Group.findOne {_id: grp.group_id}, (e, group) ->
if group && group.hasUser user_id
return cbb()
else
return cbb(0)
, (e, r) ->
if e
cb(null, 0)
else
cb(null, 1)
else
cb(null, 0)
async.series tasks, (err, results) ->
tot = 0
for r in results
tot += r
next(tot)
###
Model: GroupUser
###
GroupUser = new Schema
user_id: ObjectId
username: String
name:
first: String
last: String
full: String
###
Model: Groups
###
Group = new Schema
name:
type: String
validate: [validatePresenceOf, 'name is required']
index:
unique: true
users: [GroupUser]
Group.method 'hasUser', (user_id) ->
for user in this.users
if user.user_id.toString() == user_id.toString()
return true
return false
###
Model: RoleGroup
###
RoleGroup = new Schema
group_id: ObjectId
name: String
###
Model: RoleUser
###
RoleUser = new Schema
user_id: ObjectId
username: String
name:
first: String
last: String
full: String
###
Model: Role
###
Role = new Schema
name:
type: String
validate: [validatePresenceOf, 'key is required']
index:
unique: true
set: toLower
groups: [RoleGroup]
users: [RoleUser]
Role.method 'hasGroup', (group_id) ->
for grp in this.groups
if grp.group_id.toString() == group_id.toString()
return true
return false
Role.method 'hasUser', (user_id) ->
for user in this.users
if user.user_id.toString() == user_id.toString()
return true
return false
###
Model: LoginToken
Used for session persistence.
###
LoginToken = new Schema
username:
type: String
index: true
series:
type: String
index: true
token:
type: String
index: true
LoginToken.method 'randomToken', () ->
Math.round (new Date().valueOf() * Math.random()) + ''
LoginToken.pre 'save', (next) ->
#Automatically create the tokens
this.token = this.randomToken()
if this.isNew
this.series = this.randomToken()
next()
LoginToken.virtual('id').get () ->
this._id.toHexString()
LoginToken.virtual('cookieValue').get () ->
JSON.stringify username: this.username, token: this.token, series: this.series
mongoose.model 'User', User
mongoose.model 'Group', Group
mongoose.model 'Role', Role
mongoose.model 'GroupUser', GroupUser
mongoose.model 'RoleGroup', RoleGroup
mongoose.model 'RoleUser', RoleUser
mongoose.model 'LoginToken', LoginToken
next()
exports.defineModels = defineModels