bsw/jbe@0: Member = mondelefant.new_class() bsw/jbe@0: Member.table = 'member' bsw/jbe@0: bsw/jbe@0: Member:add_reference{ bsw@9: mode = "1m", bsw@9: to = "MemberHistory", bsw@9: this_key = 'id', bsw@9: that_key = 'member_id', bsw@9: ref = 'history_entries', bsw@9: back_ref = 'member' bsw@9: } bsw@9: bsw@9: Member:add_reference{ bsw/jbe@4: mode = '1m', bsw@2: to = "MemberImage", bsw@2: this_key = 'id', bsw@2: that_key = 'member_id', bsw/jbe@4: ref = 'images', bsw@2: back_ref = 'member' bsw@2: } bsw@2: bsw@2: Member:add_reference{ bsw/jbe@0: mode = '1m', bsw/jbe@0: to = "Contact", bsw/jbe@0: this_key = 'id', bsw/jbe@0: that_key = 'member_id', bsw/jbe@0: ref = 'contacts', bsw/jbe@0: back_ref = 'member', bsw/jbe@0: default_order = '"other_member_id"' bsw/jbe@0: } bsw/jbe@0: bsw/jbe@0: Member:add_reference{ bsw/jbe@0: mode = '1m', bsw/jbe@0: to = "Contact", bsw/jbe@0: this_key = 'id', bsw/jbe@0: that_key = 'member_id', bsw/jbe@0: ref = 'foreign_contacts', bsw/jbe@0: back_ref = 'other_member', bsw/jbe@0: default_order = '"member_id"' bsw/jbe@0: } bsw/jbe@0: bsw/jbe@0: Member:add_reference{ bsw/jbe@0: mode = '1m', bsw/jbe@0: to = "Session", bsw/jbe@0: this_key = 'id', bsw/jbe@0: that_key = 'member_id', bsw/jbe@0: ref = 'sessions', bsw/jbe@0: back_ref = 'member', bsw/jbe@0: default_order = '"ident"' bsw/jbe@0: } bsw/jbe@0: bsw/jbe@0: Member:add_reference{ bsw/jbe@0: mode = '1m', bsw/jbe@0: to = "Draft", bsw/jbe@0: this_key = 'id', bsw/jbe@0: that_key = 'author_id', bsw/jbe@0: ref = 'drafts', bsw/jbe@0: back_ref = 'author', bsw/jbe@0: default_order = '"id"' bsw/jbe@0: } bsw/jbe@0: bsw/jbe@0: Member:add_reference{ bsw/jbe@0: mode = '1m', bsw/jbe@0: to = "Suggestion", bsw/jbe@0: this_key = 'id', bsw/jbe@0: that_key = 'author_id', bsw/jbe@0: ref = 'suggestions', bsw/jbe@0: back_ref = 'author', bsw/jbe@0: default_order = '"id"' bsw/jbe@0: } bsw/jbe@0: bsw/jbe@0: Member:add_reference{ bsw/jbe@0: mode = '1m', bsw/jbe@0: to = "Membership", bsw/jbe@0: this_key = 'id', bsw/jbe@0: that_key = 'member_id', bsw/jbe@0: ref = 'memberships', bsw/jbe@0: back_ref = 'member', bsw/jbe@0: default_order = '"area_id"' bsw/jbe@0: } bsw/jbe@0: bsw/jbe@0: Member:add_reference{ bsw/jbe@0: mode = '1m', bsw/jbe@0: to = "Interest", bsw/jbe@0: this_key = 'id', bsw/jbe@0: that_key = 'member_id', bsw/jbe@0: ref = 'interests', bsw/jbe@0: back_ref = 'member', bsw/jbe@0: default_order = '"id"' bsw/jbe@0: } bsw/jbe@0: bsw/jbe@0: Member:add_reference{ bsw/jbe@0: mode = '1m', bsw/jbe@0: to = "Initiator", bsw/jbe@0: this_key = 'id', bsw/jbe@0: that_key = 'member_id', bsw/jbe@0: ref = 'initiators', bsw@10: back_ref = 'member' bsw/jbe@0: } bsw/jbe@0: bsw/jbe@0: Member:add_reference{ bsw/jbe@0: mode = '1m', bsw/jbe@0: to = "Supporter", bsw/jbe@0: this_key = 'id', bsw/jbe@0: that_key = 'member_id', bsw/jbe@0: ref = 'supporters', bsw@2: back_ref = 'member' bsw/jbe@0: } bsw/jbe@0: bsw/jbe@0: Member:add_reference{ bsw/jbe@0: mode = '1m', bsw/jbe@0: to = "Opinion", bsw/jbe@0: this_key = 'id', bsw/jbe@0: that_key = 'member_id', bsw/jbe@0: ref = 'opinions', bsw/jbe@0: back_ref = 'member', bsw/jbe@0: default_order = '"id"' bsw/jbe@0: } bsw/jbe@0: bsw/jbe@0: Member:add_reference{ bsw/jbe@0: mode = '1m', bsw/jbe@0: to = "Delegation", bsw/jbe@0: this_key = 'id', bsw/jbe@0: that_key = 'truster_id', bsw/jbe@0: ref = 'outgoing_delegations', bsw/jbe@0: back_ref = 'truster', bsw/jbe@0: default_order = '"id"' bsw/jbe@0: } bsw/jbe@0: bsw/jbe@0: Member:add_reference{ bsw/jbe@0: mode = '1m', bsw/jbe@0: to = "Delegation", bsw/jbe@0: this_key = 'id', bsw/jbe@0: that_key = 'trustee_id', bsw/jbe@0: ref = 'incoming_delegations', bsw/jbe@0: back_ref = 'trustee', bsw/jbe@0: default_order = '"id"' bsw/jbe@0: } bsw/jbe@0: bsw/jbe@0: Member:add_reference{ bsw/jbe@0: mode = '1m', bsw/jbe@0: to = "DirectVoter", bsw/jbe@0: this_key = 'id', bsw/jbe@0: that_key = 'member_id', bsw/jbe@0: ref = 'direct_voter', bsw/jbe@0: back_ref = 'member', bsw/jbe@0: default_order = '"issue_id"' bsw/jbe@0: } bsw/jbe@0: bsw/jbe@0: Member:add_reference{ bsw/jbe@0: mode = '1m', bsw/jbe@0: to = "Vote", bsw/jbe@0: this_key = 'id', bsw/jbe@0: that_key = 'member_id', bsw/jbe@0: ref = 'vote', bsw/jbe@0: back_ref = 'member', bsw/jbe@0: default_order = '"issue_id", "initiative_id"' bsw/jbe@0: } bsw/jbe@0: bsw/jbe@0: Member:add_reference{ bsw/jbe@0: mode = 'mm', bsw/jbe@0: to = "Member", bsw/jbe@0: this_key = 'id', bsw/jbe@0: that_key = 'id', bsw/jbe@0: connected_by_table = 'contact', bsw/jbe@0: connected_by_this_key = 'member_id', bsw/jbe@0: connected_by_that_key = 'other_member_id', bsw/jbe@0: ref = 'saved_members', bsw/jbe@0: } bsw/jbe@0: bsw/jbe@0: Member:add_reference{ bsw/jbe@0: mode = 'mm', bsw/jbe@0: to = "Member", bsw/jbe@0: this_key = 'id', bsw/jbe@0: that_key = 'id', bsw/jbe@0: connected_by_table = 'contact', bsw/jbe@0: connected_by_this_key = 'other_member_id', bsw/jbe@0: connected_by_that_key = 'member_id', bsw/jbe@0: ref = 'saved_by_members', bsw/jbe@0: } bsw/jbe@0: bsw/jbe@0: Member:add_reference{ bsw/jbe@0: mode = 'mm', bsw/jbe@0: to = "Area", bsw/jbe@0: this_key = 'id', bsw/jbe@0: that_key = 'id', bsw/jbe@0: connected_by_table = 'membership', bsw/jbe@0: connected_by_this_key = 'member_id', bsw/jbe@0: connected_by_that_key = 'area_id', bsw/jbe@0: ref = 'areas' bsw/jbe@0: } bsw/jbe@0: bsw/jbe@0: Member:add_reference{ bsw/jbe@0: mode = 'mm', bsw/jbe@0: to = "Issue", bsw/jbe@0: this_key = 'id', bsw/jbe@0: that_key = 'id', bsw/jbe@0: connected_by_table = 'interest', bsw/jbe@0: connected_by_this_key = 'member_id', bsw/jbe@0: connected_by_that_key = 'issue_id', bsw/jbe@0: ref = 'issues' bsw/jbe@0: } bsw/jbe@0: bsw/jbe@0: Member:add_reference{ bsw/jbe@0: mode = 'mm', bsw/jbe@0: to = "Initiative", bsw/jbe@0: this_key = 'id', bsw/jbe@0: that_key = 'id', bsw/jbe@0: connected_by_table = 'initiator', bsw/jbe@0: connected_by_this_key = 'member_id', bsw/jbe@0: connected_by_that_key = 'initiative_id', bsw/jbe@0: ref = 'initiated_initiatives' bsw/jbe@0: } bsw/jbe@0: bsw/jbe@0: Member:add_reference{ bsw/jbe@0: mode = 'mm', bsw/jbe@0: to = "Initiative", bsw/jbe@0: this_key = 'id', bsw/jbe@0: that_key = 'id', bsw/jbe@0: connected_by_table = 'supporter', bsw/jbe@0: connected_by_this_key = 'member_id', bsw/jbe@0: connected_by_that_key = 'initiative_id', bsw/jbe@0: ref = 'supported_initiatives' bsw/jbe@0: } bsw/jbe@0: bsw@193: function Member:build_selector(args) bsw@193: local selector = self:new_selector() bsw@193: if args.active ~= nil then bsw@193: selector:add_where{ "member.active = ?", args.active } bsw@193: end bsw@199: if args.is_contact_of_member_id then bsw@199: selector:join("contact", "__model_member__contact", "member.id = __model_member__contact.other_member_id") bsw@199: selector:add_where{ "__model_member__contact.member_id = ?", args.is_contact_of_member_id } bsw@199: end bsw@193: if args.order then bsw@193: if args.order == "id" then bsw@193: selector:add_order_by("id") bsw@193: elseif args.order == "login" then bsw@193: selector:add_order_by("login") bsw@193: elseif args.order == "name" then bsw@193: selector:add_order_by("name") bsw@193: else bsw@193: error("invalid order") bsw@193: end bsw@193: end bsw@193: return selector bsw@193: end bsw@193: bsw/jbe@0: function Member.object:set_password(password) bsw/jbe@0: local hash = os.crypt( bsw/jbe@0: password, bsw/jbe@0: "$1$" .. multirand.string( bsw/jbe@0: 8, bsw/jbe@0: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./" bsw/jbe@0: ) bsw/jbe@0: ) bsw/jbe@0: assert(hash, "os.crypt failed") bsw/jbe@0: self.password = hash bsw/jbe@0: end bsw/jbe@0: bsw/jbe@0: function Member.object:check_password(password) bsw/jbe@0: if type(password) == "string" and type(self.password) == "string" then bsw/jbe@0: return os.crypt(password, self.password) == self.password bsw/jbe@0: else bsw/jbe@0: return false bsw/jbe@0: end bsw/jbe@0: end bsw/jbe@0: bsw/jbe@0: function Member.object_get:published_contacts() bsw/jbe@0: return Member:new_selector() bsw/jbe@0: :join('"contact"', nil, '"contact"."other_member_id" = "member"."id"') bsw/jbe@0: :add_where{ '"contact"."member_id" = ?', self.id } bsw/jbe@0: :add_where("public") bsw/jbe@0: :exec() bsw/jbe@0: end bsw/jbe@0: bsw/jbe@0: function Member:by_login_and_password(login, password) bsw/jbe@0: local selector = self:new_selector() bsw/jbe@5: selector:add_where{'"login" = ?', login } bsw@203: selector:add_where('NOT "locked"') bsw/jbe@0: selector:optional_object_mode() bsw/jbe@0: local member = selector:exec() bsw/jbe@0: if member and member:check_password(password) then bsw/jbe@0: return member bsw/jbe@0: else bsw/jbe@0: return nil bsw/jbe@0: end bsw/jbe@0: end bsw/jbe@0: bsw/jbe@5: function Member:by_login(login) bsw/jbe@5: local selector = self:new_selector() bsw/jbe@5: selector:add_where{'"login" = ?', login } bsw/jbe@5: selector:optional_object_mode() bsw/jbe@5: return selector:exec() bsw/jbe@5: end bsw/jbe@5: bsw/jbe@5: function Member:by_name(name) bsw/jbe@5: local selector = self:new_selector() bsw/jbe@5: selector:add_where{'"name" = ?', name } bsw/jbe@5: selector:optional_object_mode() bsw/jbe@5: return selector:exec() bsw/jbe@5: end bsw/jbe@5: bsw@2: function Member:get_search_selector(search_string) bsw/jbe@0: return self:new_selector() bsw@2: :add_field( {'"highlight"("member"."name", ?)', search_string }, "name_highlighted") bsw@2: :add_where{ '"member"."text_search_data" @@ "text_search_query"(?)', search_string } bsw/jbe@0: :add_where("active") bsw/jbe@0: end bsw@2: bsw/jbe@6: function Member.object:set_notify_email(notify_email) bsw@224: trace.disable() bsw/jbe@6: local expiry = db:query("SELECT now() + '7 days'::interval as expiry", "object").expiry bsw/jbe@6: self.notify_email_unconfirmed = notify_email bsw/jbe@6: self.notify_email_secret = multirand.string( 24, "23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" ) bsw/jbe@6: self.notify_email_secret_expiry = expiry bsw/jbe@6: local content = slot.use_temporary(function() bsw/jbe@6: slot.put(_"Hello " .. self.name .. ",\n\n") bsw/jbe@6: slot.put(_"Please confirm your email address by clicking the following link:\n\n") bsw/jbe@6: slot.put(config.absolute_base_url .. "index/confirm_notify_email.html?secret=" .. self.notify_email_secret .. "\n\n") bsw/jbe@6: slot.put(_"If this link is not working, please open following url in your web browser:\n\n") bsw/jbe@6: slot.put(config.absolute_base_url .. "index/confirm_notify_email.html\n\n") bsw/jbe@6: slot.put(_"On that page please enter the confirmation code:\n\n") bsw/jbe@6: slot.put(self.notify_email_secret .. "\n\n") bsw/jbe@6: end) bsw/jbe@6: local success = net.send_mail{ bsw/jbe@6: envelope_from = config.mail_envelope_from, bsw/jbe@6: from = config.mail_from, bsw/jbe@6: reply_to = config.mail_reply_to, bsw/jbe@6: to = self.notify_email_unconfirmed, bsw/jbe@6: subject = config.mail_subject_prefix .. _"Email confirmation request", bsw/jbe@6: content_type = "text/plain; charset=UTF-8", bsw/jbe@6: content = content bsw/jbe@6: } bsw@75: if success then bsw@75: local lock_expiry = db:query("SELECT now() + '1 hour'::interval AS lock_expiry", "object").lock_expiry bsw@75: self.notify_email_lock_expiry = lock_expiry bsw@75: end bsw@75: self:save() bsw/jbe@6: return success bsw/jbe@6: end bsw@11: bsw/jbe@19: function Member.object:get_setting(key) bsw@79: return Setting:by_pk(self.id, key) bsw/jbe@19: end bsw/jbe@19: bsw/jbe@19: function Member.object:get_setting_value(key) bsw@79: local setting = Setting:by_pk(self.id, key) bsw/jbe@19: if setting then bsw/jbe@19: return setting.value bsw/jbe@19: end bsw@11: end bsw@11: bsw@11: function Member.object:set_setting(key, value) bsw/jbe@19: local setting = self:get_setting(key) bsw/jbe@19: if not setting then bsw/jbe@19: setting = Setting:new() bsw@79: setting.member_id = self.id bsw/jbe@19: setting.key = key bsw/jbe@19: end bsw/jbe@19: setting.value = value bsw/jbe@19: setting:save() bsw@11: end bsw@11: bsw@11: function Member.object:get_setting_maps_by_key(key) bsw@11: return SettingMap:new_selector() bsw@11: :add_where{ "member_id = ?", self.id } bsw@11: :add_where{ "key = ?", key } bsw@11: :add_order_by("subkey") bsw@11: :exec() bsw@11: end bsw@11: bsw@11: function Member.object:get_setting_map_by_key_and_subkey(key, subkey) bsw@11: return SettingMap:new_selector() bsw@11: :add_where{ "member_id = ?", self.id } bsw@11: :add_where{ "key = ?", key } bsw@11: :add_where{ "subkey = ?", subkey } bsw@11: :add_order_by("subkey") bsw@11: :optional_object_mode() bsw@11: :exec() bsw@11: end bsw@11: bsw@11: function Member.object:set_setting_map(key, subkey, value) poelzi@144: setting_map = self:get_setting_map_by_key_and_subkey(key, subkey) poelzi@144: if not setting_map then poelzi@144: setting_map = SettingMap:new() poelzi@144: setting_map.member_id = self.id poelzi@144: setting_map.key = key poelzi@144: setting_map.subkey = subkey poelzi@144: end poelzi@144: setting_map.value = value poelzi@144: setting_map:save() bsw@11: end bsw@75: bsw@75: function Member.object_get:notify_email_locked() bsw@75: return( bsw@75: Member:new_selector() bsw@75: :add_where{ "id = ?", app.session.member.id } bsw@75: :add_where("notify_email_lock_expiry > now()") bsw@75: :count() == 1 bsw@75: ) poelzi@134: end poelzi@134: poelzi@134: function Member.object:ui_field_text(args) poelzi@134: args = args or {} poelzi@134: if app.session.member_id or config.public_access == "pseudonym" then poelzi@134: -- ugly workaround for getting html into a replaced string and to the user poelzi@134: ui.container{label = args.label, label_attr={class="ui_field_label"}, content = function() poelzi@134: slot.put(string.format('%s', poelzi@134: encode.url{ poelzi@134: module = "member", poelzi@134: view = "show", poelzi@134: id = self.id, poelzi@134: }, poelzi@134: encode.html(self.name))) poelzi@134: end poelzi@134: } poelzi@134: else poelzi@134: ui.field.text{ label = args.label, value = _"[not displayed public]" } poelzi@134: end poelzi@134: end