From 784891705f3a350b56d4be5b5e45e8316ebe5d46 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Mon, 6 Feb 2017 18:40:20 +0100 Subject: [PATCH] Added possibility to change its own username. --- .../handler/user/cms_user_form_response.e | 5 +- modules/auth/cms_authentication_module.e | 82 +++++++++++++++++-- src/persistence/user/cms_user_storage_i.e | 12 ++- src/persistence/user/cms_user_storage_null.e | 6 +- src/persistence/user/cms_user_storage_sql_i.e | 56 ++++++++++++- src/service/user/cms_user_api.e | 44 +++++++++- 6 files changed, 184 insertions(+), 21 deletions(-) diff --git a/modules/admin/handler/user/cms_user_form_response.e b/modules/admin/handler/user/cms_user_form_response.e index 6b41e75..fc9d331 100644 --- a/modules/admin/handler/user/cms_user_form_response.e +++ b/modules/admin/handler/user/cms_user_form_response.e @@ -227,7 +227,7 @@ feature -- Form end new_edit_form (a_user: detachable CMS_USER; a_url: READABLE_STRING_8; a_name: STRING): CMS_FORM - -- Create a web form named `a_name' for uSER `a_YSER' (if set), using form action url `a_url'. + -- Create a web form named `a_name' for user `a_user' (if set), using form action url `a_url'. local f: CMS_FORM th: WSF_FORM_HIDDEN_INPUT @@ -309,8 +309,6 @@ feature -- Form Result := f end - - populate_form (a_form: WSF_FORM; a_user: detachable CMS_USER) -- Fill the web form `a_form' with data from `a_node' if set, -- and apply this to content type `a_content_type'. @@ -531,5 +529,4 @@ feature -- Generation Result := l_token + url_encoded (u.name) + u.creation_date.out end - end diff --git a/modules/auth/cms_authentication_module.e b/modules/auth/cms_authentication_module.e index e1080fc..df70865 100644 --- a/modules/auth/cms_authentication_module.e +++ b/modules/auth/cms_authentication_module.e @@ -1,7 +1,7 @@ note description: "Module Auth" - date: "$Date: 2016-04-13 10:59:18 +0200 (mer., 13 avr. 2016) $" - revision: "$Revision: 98616 $" + date: "$Date$" + revision: "$Revision$" class CMS_AUTHENTICATION_MODULE @@ -62,6 +62,7 @@ feature -- Access Result.force ("account reject") Result.force ("account reactivate") Result.force ("admin registration") + Result.force ("change own username") end feature -- Access: docs @@ -242,7 +243,6 @@ feature -- Handler r: CMS_RESPONSE l_user: detachable CMS_USER b: STRING - f: CMS_FORM lnk: CMS_LOCAL_LINK do create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) @@ -264,11 +264,18 @@ feature -- Handler lnk.set_weight (2) r.add_to_primary_tabs (lnk) - f := new_change_password_form (r) - f.append_to_html (r.wsf_theme, b) - - f := new_change_email_form (r) - f.append_to_html (r.wsf_theme, b) + if + r.has_permission ("change own username") and then + attached new_change_username_form (r) as f + then + f.append_to_html (r.wsf_theme, b) + end + if attached new_change_password_form (r) as f then + f.append_to_html (r.wsf_theme, b) + end + if attached new_change_email_form (r) as f then + f.append_to_html (r.wsf_theme, b) + end r.set_main_content (b) @@ -721,6 +728,29 @@ feature -- Handler f := new_change_email_form (r) r.set_main_content (f.to_html (r.wsf_theme)) end + elseif l_fieldname.is_case_insensitive_equal ("username") then + if api.has_permission ("change own username") then + f := new_change_username_form (r) + f.process (r) + if + attached f.last_data as fd and then + not fd.has_error and then + attached fd.string_item ("new_username") as l_new_username + then + check api.user_api.is_valid_username (l_new_username) end + check api.user_api.user_by_name (l_new_username) = Void end + + l_user_api.update_username (l_user, l_new_username) + r.add_success_message ("Username updated.") + r.set_redirection ("account/") + r.set_redirection_delay (3) + else + r.add_error_message ("Invalid form data!") + r.set_main_content (f.to_html (r.wsf_theme)) + end + else + r.add_error_message ("You are not allowed to change your username!") + end else r.add_error_message ("You can not change %"" + l_fieldname + "%" information!") end @@ -733,6 +763,11 @@ feature -- Handler elseif l_fieldname.is_case_insensitive_equal_general ("email") then f := new_change_email_form (r) f.append_to_html (r.wsf_theme, b) + elseif l_fieldname.is_case_insensitive_equal_general ("new_username") then + if api.has_permission ("change own username") then + f := new_change_username_form (r) + f.append_to_html (r.wsf_theme, b) + end end r.set_main_content (b) end @@ -852,6 +887,37 @@ feature -- Handler end end + new_change_username_form (a_response: CMS_RESPONSE): CMS_FORM + local + fs: WSF_FORM_FIELD_SET + txt: WSF_FORM_TEXT_INPUT + do + create Result.make (a_response.url ("account/change/username", Void), "change-username-form") + create fs.make + fs.set_legend ("Change username") + Result.extend (fs) + + create txt.make ("new_username") + txt.set_label ("Username") + txt.set_validation_action (agent (fd: WSF_FORM_DATA; api: CMS_API) + do + if + attached fd.string_item ("new_username") as l_new and then + api.user_api.is_valid_username (l_new) + then + if api.user_api.user_by_name (l_new) /= Void then + fd.report_invalid_field ("new_username", "Username is already taken!") + end + else + fd.report_invalid_field ("new_username", "Invalid username!") + end + end (?, a_response.api) + ) + txt.enable_required + fs.extend (txt) + fs.extend_html_text ("") + end + new_change_password_form (a_response: CMS_RESPONSE): CMS_FORM local fs: WSF_FORM_FIELD_SET diff --git a/src/persistence/user/cms_user_storage_i.e b/src/persistence/user/cms_user_storage_i.e index f96b037..3b77ab2 100644 --- a/src/persistence/user/cms_user_storage_i.e +++ b/src/persistence/user/cms_user_storage_i.e @@ -1,7 +1,7 @@ note description: "Summary description for {CMS_USER_STORAGE_I}." - date: "$Date: 2015-01-27 19:15:02 +0100 (mar., 27 janv. 2015) $" - revision: "$Revision: 96542 $" + date: "$Date$" + revision: "$Revision$" deferred class CMS_USER_STORAGE_I @@ -104,6 +104,13 @@ feature -- Change: user deferred end + update_username (a_user: CMS_USER; a_new_username: READABLE_STRING_32) + -- Update username of `a_user' to `a_new_username`. + require + has_id: a_user.has_id + deferred + end + update_user (a_user: CMS_USER) -- Save user `a_user'. require @@ -282,7 +289,6 @@ feature -- New Temp User deferred end - note copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" diff --git a/src/persistence/user/cms_user_storage_null.e b/src/persistence/user/cms_user_storage_null.e index 8aaf444..3572485 100644 --- a/src/persistence/user/cms_user_storage_null.e +++ b/src/persistence/user/cms_user_storage_null.e @@ -1,6 +1,5 @@ note description: "Summary description for {CMS_USER_STORAGE_NULL}." - author: "" date: "$Date$" revision: "$Revision$" @@ -65,12 +64,15 @@ feature -- Change: user a_user.set_id (1) end + update_username (a_user: CMS_USER; a_new_username: READABLE_STRING_32) + do + end + update_user (a_user: CMS_USER) -- Update user `a_user'. do end - delete_user (a_user: CMS_USER) -- Delete user `a_user'. do diff --git a/src/persistence/user/cms_user_storage_sql_i.e b/src/persistence/user/cms_user_storage_sql_i.e index cd44891..25bce70 100644 --- a/src/persistence/user/cms_user_storage_sql_i.e +++ b/src/persistence/user/cms_user_storage_sql_i.e @@ -1,7 +1,7 @@ note description: "Summary description for {CMS_USER_STORAGE_SQL_I}." - date: "$Date: 2015-02-13 13:08:13 +0100 (ven., 13 févr. 2015) $" - revision: "$Revision: 96616 $" + date: "$Date$" + revision: "$Revision$" deferred class CMS_USER_STORAGE_SQL_I @@ -242,6 +242,58 @@ feature -- Change: user end end + update_username (a_user: CMS_USER; a_new_username: READABLE_STRING_32) + -- Update username of `a_user' to `a_new_username`. + local + l_parameters: STRING_TABLE [detachable ANY] + l_password_salt, l_password_hash: detachable READABLE_STRING_8 + l_security: SECURITY_PROVIDER + do + error_handler.reset + if attached a_user.password as l_password then + -- New password! + create l_security + l_password_salt := l_security.salt + l_password_hash := l_security.password_hash (l_password, l_password_salt) + else + -- Existing hashed password + l_password_hash := a_user.hashed_password + l_password_salt := user_salt (a_user.name) + end + if + l_password_hash /= Void and l_password_salt /= Void and + attached a_user.email as l_email + then + sql_begin_transaction + + write_information_log (generator + ".update_user") + create l_parameters.make (7) + l_parameters.put (a_user.id, "uid") + l_parameters.put (a_new_username, "name") + l_parameters.put (l_password_hash, "password") + l_parameters.put (l_password_salt, "salt") + l_parameters.put (l_email, "email") + l_parameters.put (a_user.status, "status") + l_parameters.put (a_user.last_login_date, "signed") + + sql_modify (sql_update_user, l_parameters) + sql_finalize + if not error_handler.has_error then + a_user.set_name (a_new_username) + update_user_roles (a_user) + end + if not error_handler.has_error then + sql_commit_transaction + else + sql_rollback_transaction + end + sql_finalize + else + -- set error + error_handler.add_custom_error (-1, "bad request" , "Missing password or email") + end + end + update_user (a_user: CMS_USER) -- Save user `a_user'. local diff --git a/src/service/user/cms_user_api.e b/src/service/user/cms_user_api.e index ba7b512..6db7be2 100644 --- a/src/service/user/cms_user_api.e +++ b/src/service/user/cms_user_api.e @@ -1,7 +1,7 @@ note description: "API providing user related features." - date: "$Date: 2015-02-13 13:08:13 +0100 (ven., 13 févr. 2015) $" - revision: "$Revision: 96616 $" + date: "$Date$" + revision: "$Revision$" class CMS_USER_API @@ -14,6 +14,34 @@ inherit create make +feature -- Validation + + is_valid_username (a_name: READABLE_STRING_32): BOOLEAN + local + c: CHARACTER_32 + do + if a_name.is_empty or a_name.is_whitespace then + Result := False + elseif a_name[1].is_space then + Result := False + elseif a_name[a_name.count].is_space then + Result := False + else + Result := True + across + a_name as ic + until + not Result + loop + c := ic.item + if c.is_alpha_numeric or c = '-' or c = '_' then + else + Result := False + end + end + end + end + feature -- Access: user user_by_id (a_id: like {CMS_USER}.id): detachable CMS_USER @@ -77,6 +105,18 @@ feature -- Change User end end + update_username (a_user: CMS_USER; a_new_username: READABLE_STRING_32) + -- Update username of `a_user' to `a_new_username'. + require + has_id: a_user.has_id + valid_user_name: is_valid_username (a_new_username) + user_by_name (a_new_username) = Void + do + reset_error + storage.update_username (a_user, a_new_username) + error_handler.append (storage.error_handler) + end + update_user (a_user: CMS_USER) -- Update user `a_user'. require