liquid_feedback_frontend

view model/member.lua @ 224:bf735d8095aa

Fixed security related bug, security tokens were exposed through trace output.
author bsw
date Tue May 17 03:23:16 2011 +0200 (2011-05-17)
parents 5e35add677ee
children 7196685f9dd7 a34142b39bd8
line source
1 Member = mondelefant.new_class()
2 Member.table = 'member'
4 Member:add_reference{
5 mode = "1m",
6 to = "MemberHistory",
7 this_key = 'id',
8 that_key = 'member_id',
9 ref = 'history_entries',
10 back_ref = 'member'
11 }
13 Member:add_reference{
14 mode = '1m',
15 to = "MemberImage",
16 this_key = 'id',
17 that_key = 'member_id',
18 ref = 'images',
19 back_ref = 'member'
20 }
22 Member:add_reference{
23 mode = '1m',
24 to = "Contact",
25 this_key = 'id',
26 that_key = 'member_id',
27 ref = 'contacts',
28 back_ref = 'member',
29 default_order = '"other_member_id"'
30 }
32 Member:add_reference{
33 mode = '1m',
34 to = "Contact",
35 this_key = 'id',
36 that_key = 'member_id',
37 ref = 'foreign_contacts',
38 back_ref = 'other_member',
39 default_order = '"member_id"'
40 }
42 Member:add_reference{
43 mode = '1m',
44 to = "Session",
45 this_key = 'id',
46 that_key = 'member_id',
47 ref = 'sessions',
48 back_ref = 'member',
49 default_order = '"ident"'
50 }
52 Member:add_reference{
53 mode = '1m',
54 to = "Draft",
55 this_key = 'id',
56 that_key = 'author_id',
57 ref = 'drafts',
58 back_ref = 'author',
59 default_order = '"id"'
60 }
62 Member:add_reference{
63 mode = '1m',
64 to = "Suggestion",
65 this_key = 'id',
66 that_key = 'author_id',
67 ref = 'suggestions',
68 back_ref = 'author',
69 default_order = '"id"'
70 }
72 Member:add_reference{
73 mode = '1m',
74 to = "Membership",
75 this_key = 'id',
76 that_key = 'member_id',
77 ref = 'memberships',
78 back_ref = 'member',
79 default_order = '"area_id"'
80 }
82 Member:add_reference{
83 mode = '1m',
84 to = "Interest",
85 this_key = 'id',
86 that_key = 'member_id',
87 ref = 'interests',
88 back_ref = 'member',
89 default_order = '"id"'
90 }
92 Member:add_reference{
93 mode = '1m',
94 to = "Initiator",
95 this_key = 'id',
96 that_key = 'member_id',
97 ref = 'initiators',
98 back_ref = 'member'
99 }
101 Member:add_reference{
102 mode = '1m',
103 to = "Supporter",
104 this_key = 'id',
105 that_key = 'member_id',
106 ref = 'supporters',
107 back_ref = 'member'
108 }
110 Member:add_reference{
111 mode = '1m',
112 to = "Opinion",
113 this_key = 'id',
114 that_key = 'member_id',
115 ref = 'opinions',
116 back_ref = 'member',
117 default_order = '"id"'
118 }
120 Member:add_reference{
121 mode = '1m',
122 to = "Delegation",
123 this_key = 'id',
124 that_key = 'truster_id',
125 ref = 'outgoing_delegations',
126 back_ref = 'truster',
127 default_order = '"id"'
128 }
130 Member:add_reference{
131 mode = '1m',
132 to = "Delegation",
133 this_key = 'id',
134 that_key = 'trustee_id',
135 ref = 'incoming_delegations',
136 back_ref = 'trustee',
137 default_order = '"id"'
138 }
140 Member:add_reference{
141 mode = '1m',
142 to = "DirectVoter",
143 this_key = 'id',
144 that_key = 'member_id',
145 ref = 'direct_voter',
146 back_ref = 'member',
147 default_order = '"issue_id"'
148 }
150 Member:add_reference{
151 mode = '1m',
152 to = "Vote",
153 this_key = 'id',
154 that_key = 'member_id',
155 ref = 'vote',
156 back_ref = 'member',
157 default_order = '"issue_id", "initiative_id"'
158 }
160 Member:add_reference{
161 mode = 'mm',
162 to = "Member",
163 this_key = 'id',
164 that_key = 'id',
165 connected_by_table = 'contact',
166 connected_by_this_key = 'member_id',
167 connected_by_that_key = 'other_member_id',
168 ref = 'saved_members',
169 }
171 Member:add_reference{
172 mode = 'mm',
173 to = "Member",
174 this_key = 'id',
175 that_key = 'id',
176 connected_by_table = 'contact',
177 connected_by_this_key = 'other_member_id',
178 connected_by_that_key = 'member_id',
179 ref = 'saved_by_members',
180 }
182 Member:add_reference{
183 mode = 'mm',
184 to = "Area",
185 this_key = 'id',
186 that_key = 'id',
187 connected_by_table = 'membership',
188 connected_by_this_key = 'member_id',
189 connected_by_that_key = 'area_id',
190 ref = 'areas'
191 }
193 Member:add_reference{
194 mode = 'mm',
195 to = "Issue",
196 this_key = 'id',
197 that_key = 'id',
198 connected_by_table = 'interest',
199 connected_by_this_key = 'member_id',
200 connected_by_that_key = 'issue_id',
201 ref = 'issues'
202 }
204 Member:add_reference{
205 mode = 'mm',
206 to = "Initiative",
207 this_key = 'id',
208 that_key = 'id',
209 connected_by_table = 'initiator',
210 connected_by_this_key = 'member_id',
211 connected_by_that_key = 'initiative_id',
212 ref = 'initiated_initiatives'
213 }
215 Member:add_reference{
216 mode = 'mm',
217 to = "Initiative",
218 this_key = 'id',
219 that_key = 'id',
220 connected_by_table = 'supporter',
221 connected_by_this_key = 'member_id',
222 connected_by_that_key = 'initiative_id',
223 ref = 'supported_initiatives'
224 }
226 Member:new_selector()
227 :add_order_by("member.name")
228 :exec()
230 function Member:build_selector(args)
231 local selector = self:new_selector()
232 if args.active ~= nil then
233 selector:add_where{ "member.active = ?", args.active }
234 end
235 if args.is_contact_of_member_id then
236 selector:join("contact", "__model_member__contact", "member.id = __model_member__contact.other_member_id")
237 selector:add_where{ "__model_member__contact.member_id = ?", args.is_contact_of_member_id }
238 end
239 if args.order then
240 if args.order == "id" then
241 selector:add_order_by("id")
242 elseif args.order == "login" then
243 selector:add_order_by("login")
244 elseif args.order == "name" then
245 selector:add_order_by("name")
246 else
247 error("invalid order")
248 end
249 end
250 return selector
251 end
253 function Member.object:set_password(password)
254 local hash = os.crypt(
255 password,
256 "$1$" .. multirand.string(
257 8,
258 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./"
259 )
260 )
261 assert(hash, "os.crypt failed")
262 self.password = hash
263 end
265 function Member.object:check_password(password)
266 if type(password) == "string" and type(self.password) == "string" then
267 return os.crypt(password, self.password) == self.password
268 else
269 return false
270 end
271 end
273 function Member.object_get:published_contacts()
274 return Member:new_selector()
275 :join('"contact"', nil, '"contact"."other_member_id" = "member"."id"')
276 :add_where{ '"contact"."member_id" = ?', self.id }
277 :add_where("public")
278 :exec()
279 end
281 function Member:by_login_and_password(login, password)
282 local selector = self:new_selector()
283 selector:add_where{'"login" = ?', login }
284 selector:add_where('NOT "locked"')
285 selector:optional_object_mode()
286 local member = selector:exec()
287 if member and member:check_password(password) then
288 return member
289 else
290 return nil
291 end
292 end
294 function Member:by_login(login)
295 local selector = self:new_selector()
296 selector:add_where{'"login" = ?', login }
297 selector:optional_object_mode()
298 return selector:exec()
299 end
301 function Member:by_name(name)
302 local selector = self:new_selector()
303 selector:add_where{'"name" = ?', name }
304 selector:optional_object_mode()
305 return selector:exec()
306 end
308 function Member:get_search_selector(search_string)
309 return self:new_selector()
310 :add_field( {'"highlight"("member"."name", ?)', search_string }, "name_highlighted")
311 :add_where{ '"member"."text_search_data" @@ "text_search_query"(?)', search_string }
312 :add_where("active")
313 end
315 function Member.object:set_notify_email(notify_email)
316 trace.disable()
317 local expiry = db:query("SELECT now() + '7 days'::interval as expiry", "object").expiry
318 self.notify_email_unconfirmed = notify_email
319 self.notify_email_secret = multirand.string( 24, "23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" )
320 self.notify_email_secret_expiry = expiry
321 local content = slot.use_temporary(function()
322 slot.put(_"Hello " .. self.name .. ",\n\n")
323 slot.put(_"Please confirm your email address by clicking the following link:\n\n")
324 slot.put(config.absolute_base_url .. "index/confirm_notify_email.html?secret=" .. self.notify_email_secret .. "\n\n")
325 slot.put(_"If this link is not working, please open following url in your web browser:\n\n")
326 slot.put(config.absolute_base_url .. "index/confirm_notify_email.html\n\n")
327 slot.put(_"On that page please enter the confirmation code:\n\n")
328 slot.put(self.notify_email_secret .. "\n\n")
329 end)
330 local success = net.send_mail{
331 envelope_from = config.mail_envelope_from,
332 from = config.mail_from,
333 reply_to = config.mail_reply_to,
334 to = self.notify_email_unconfirmed,
335 subject = config.mail_subject_prefix .. _"Email confirmation request",
336 content_type = "text/plain; charset=UTF-8",
337 content = content
338 }
339 if success then
340 local lock_expiry = db:query("SELECT now() + '1 hour'::interval AS lock_expiry", "object").lock_expiry
341 self.notify_email_lock_expiry = lock_expiry
342 end
343 self:save()
344 return success
345 end
347 function Member.object:get_setting(key)
348 return Setting:by_pk(self.id, key)
349 end
351 function Member.object:get_setting_value(key)
352 local setting = Setting:by_pk(self.id, key)
353 if setting then
354 return setting.value
355 end
356 end
358 function Member.object:set_setting(key, value)
359 local setting = self:get_setting(key)
360 if not setting then
361 setting = Setting:new()
362 setting.member_id = self.id
363 setting.key = key
364 end
365 setting.value = value
366 setting:save()
367 end
369 function Member.object:get_setting_maps_by_key(key)
370 return SettingMap:new_selector()
371 :add_where{ "member_id = ?", self.id }
372 :add_where{ "key = ?", key }
373 :add_order_by("subkey")
374 :exec()
375 end
377 function Member.object:get_setting_map_by_key_and_subkey(key, subkey)
378 return SettingMap:new_selector()
379 :add_where{ "member_id = ?", self.id }
380 :add_where{ "key = ?", key }
381 :add_where{ "subkey = ?", subkey }
382 :add_order_by("subkey")
383 :optional_object_mode()
384 :exec()
385 end
387 function Member.object:set_setting_map(key, subkey, value)
388 setting_map = self:get_setting_map_by_key_and_subkey(key, subkey)
389 if not setting_map then
390 setting_map = SettingMap:new()
391 setting_map.member_id = self.id
392 setting_map.key = key
393 setting_map.subkey = subkey
394 end
395 setting_map.value = value
396 setting_map:save()
397 end
399 function Member.object_get:notify_email_locked()
400 return(
401 Member:new_selector()
402 :add_where{ "id = ?", app.session.member.id }
403 :add_where("notify_email_lock_expiry > now()")
404 :count() == 1
405 )
406 end
408 function Member.object:ui_field_text(args)
409 args = args or {}
410 if app.session.member_id or config.public_access == "pseudonym" then
411 -- ugly workaround for getting html into a replaced string and to the user
412 ui.container{label = args.label, label_attr={class="ui_field_label"}, content = function()
413 slot.put(string.format('<span><a href="%s">%s</a></span>',
414 encode.url{
415 module = "member",
416 view = "show",
417 id = self.id,
418 },
419 encode.html(self.name)))
420 end
421 }
422 else
423 ui.field.text{ label = args.label, value = _"[not displayed public]" }
424 end
425 end

Impressum / About Us