note date: "$Date$" revision: "$Revision$" class ACCOUNT_HANDLER inherit WSF_URI_HANDLER rename new_mapping as new_uri_mapping end WSF_URI_TEMPLATE_HANDLER select new_mapping end IRON_NODE_HANDLER rename set_iron as make end SHARED_HTML_ENCODER create make feature -- Execution execute (req: WSF_REQUEST; res: WSF_RESPONSE) local curr: like current_user do if req.is_get_request_method then curr := current_user (req) if curr = Void then if attached req.query_parameter ("register") then handle_registration (req, res) elseif attached {WSF_STRING} req.query_parameter ("reset_password") as s_reset_password then handle_reset_password (s_reset_password.value, req, res) elseif attached {WSF_STRING} req.query_parameter ("activate") as l_code and then attached {WSF_STRING} req.path_parameter ("uid") as l_uid then handle_activation (l_uid, l_code.value, req, res) else handle_user (Void, req, res) end elseif attached {WSF_STRING} req.query_parameter ("activate") as l_code and then attached {WSF_STRING} req.path_parameter ("uid") as s_uid and then curr.name.same_string (s_uid.value) then handle_activation (s_uid, l_code.value, req, res) else handle_user (curr, req, res) end else if not is_authenticated (req) then if attached req.query_parameter ("register") then handle_registration_post (req, res) elseif attached {WSF_STRING} req.query_parameter ("reset_password") then handle_reset_password (Void, req, res) end else res.send (create {WSF_METHOD_NOT_ALLOWED_RESPONSE}.make (req)) end end end handle_user (a_user: detachable IRON_NODE_USER; req: WSF_REQUEST; res: WSF_RESPONSE) local m: like new_response_message s: STRING do if req.is_content_type_accepted ("text/html") then m := new_response_message (req) s := "..." if attached {WSF_STRING} req.item ("redirection") as l_redir then m.set_location (l_redir.value) elseif a_user /= Void then m.set_location (iron.user_page (a_user)) end m.set_title ("Information") m.set_body (s) res.send (m) else res.send (create {WSF_NOT_IMPLEMENTED_RESPONSE}.make (req)) end end feature -- Users handle_reset_password (a_reset_pwd: detachable READABLE_STRING_GENERAL; req: WSF_REQUEST; res: WSF_RESPONSE) local f: WSF_FORM i: WSF_FORM_TEXT_INPUT sub: WSF_FORM_SUBMIT_INPUT m: like new_response_message s: STRING l_uuid: STRING do m := new_response_message (req) create s.make_empty if attached {WSF_STRING} req.item ("uid") as s_uid then if attached iron.database.user (s_uid.value) as u then if req.is_post_request_method and then attached {WSF_STRING} req.form_parameter ("code") as s_code and then attached {WSF_STRING} req.form_parameter ("new_password") as s_new_password and then attached {WSF_STRING} req.form_parameter ("new_password_check") as s_new_password_check then if attached {READABLE_STRING_GENERAL} u.data_item ("reset_password.code") as l_code and then l_code.is_case_insensitive_equal (s_code.value) then if s_new_password.same_string (s_new_password_check.value) then u.set_password (s_new_password.value) u.remove_data_item ("reset_password.code") u.remove_data_item ("reset_password.url") u.remove_data_item ("reset_password.datetime") iron.database.update_user (u) s.append ("Password reset completed.") s.append ("Sign in with your new password.") else s.append ("The Password and Re-typed Password do not match!") f := new_reset_password_with_token_form (u, s_code.value) f.process (req, Void, Void) if attached f.last_data as f_data then f_data.set_fields_invalid (True, "new_password_check") f_data.apply_to_associated_form end f.append_to_html (create {WSF_REQUEST_THEME}.make_with_request (req), s) end else s.append ("Reset password code is not associated with user ["+ html_encoder.general_encoded_string (s_uid.value) +"]!") end elseif a_reset_pwd /= Void and then not a_reset_pwd.is_empty then if attached {READABLE_STRING_GENERAL} u.data_item ("reset_password.code") as l_code and then l_code.is_case_insensitive_equal (a_reset_pwd) then f := new_reset_password_with_token_form (u, a_reset_pwd) f.append_to_html (create {WSF_REQUEST_THEME}.make_with_request (req), s) else s.append ("Reset password url is not associated with user ["+ html_encoder.general_encoded_string (s_uid.value) +"]!") end else l_uuid := (create {UUID_GENERATOR}).generate_uuid.out u.set_data_item ("reset_password.code", l_uuid) u.set_data_item ("reset_password.url", req.absolute_script_url (iron.account_page (u) + "?reset_password=" + l_uuid)) u.set_data_item ("reset_password.datetime", (create {HTTP_DATE}.make_now_utc).string) iron.database.update_user (u) s.append ("An email has just been sent to you. This describes how to reset your password. Check you inbox (eventually also your spam folder).") end else s.append ("User ["+ html_encoder.general_encoded_string (s_uid.value) +"] does not exists") end else create f.make (iron.account_page (Void) + "?reset_password", "reset_password") f.set_method_post create i.make ("uid") i.set_label ("Username") -- " or email" i.set_description ("Enter your username.") --, or the email associated with your account.") f.extend (i) create sub.make_with_text ("op", "Submit") f.extend (sub) f.append_to_html (create {WSF_REQUEST_THEME}.make_with_request (req), s) end m.set_body (s) res.send (m) end handle_activation (a_uid: READABLE_STRING_32; a_code: READABLE_STRING_GENERAL; req: WSF_REQUEST; res: WSF_RESPONSE) local m: like new_response_message s: STRING u: detachable like current_user do m := new_response_message (req) create s.make_empty u := iron.database.user (a_uid) if u /= Void and then attached {READABLE_STRING_GENERAL} u.data_item ("activation.code") as u_code and then a_code.is_case_insensitive_equal (a_code) then u.remove_data_item ("activation.code") u.remove_data_item ("activation.url") u.remove_data_item ("activation.datetime") iron.database.update_user (u) s.append ("User activated!") else s.append ("Activation code [" + html_encoder.general_encoded_string (a_code) + "] is not associated with user [" + html_encoder.general_encoded_string (a_uid) + "]!") end m.set_body (s) res.send (m) end handle_registration (req: WSF_REQUEST; res: WSF_RESPONSE) local m: like new_response_message f: WSF_FORM s: STRING do m := new_response_message (req) f := registration_form (req.script_url (req.path_info) + "?register", "new_account") create s.make_empty f.append_to_html (create {WSF_REQUEST_THEME}.make_with_request (req), s) m.set_body (s) res.send (m) end handle_registration_post (req: WSF_REQUEST; res: WSF_RESPONSE) local m: like new_response_message f: WSF_FORM s: STRING do m := new_response_message (req) f := registration_form (req.script_url (req.path_info) + "?register", "new_account") f.validation_actions.extend (agent on_registration_form_validation (req, ?)) f.submit_actions.extend (agent on_registration_form_submitted (req, ?)) f.process (req, Void, Void) create s.make_empty if attached f.last_data as d and then not d.is_valid then s.append ("Error in form registration") if attached d.errors as errs then across errs as c loop if attached c.message as msg then s.append ("