From e42a7636aed234e66edfe8bbcf50eb0ce1c93556 Mon Sep 17 00:00:00 2001 From: jvelilla Date: Wed, 15 Jul 2015 12:24:56 -0300 Subject: [PATCH] Updated Account Info Add Link and Unlink account with OAuth. --- .../auth/templates/block_account_info.tpl | 33 ++++++++ .../oauth20/scripts/oauth2_table.sql.tpl | 5 +- modules/auth/cms_authentication_module.e | 6 -- .../site/templates/block_account_info.tpl | 33 ++++++++ modules/oauth20/cms_oauth_20_api.e | 19 ++++- modules/oauth20/cms_oauth_20_module.e | 78 ++++++++++++++++++- .../persistence/cms_oauth_20_storage_i.e | 12 +++ .../persistence/cms_oauth_20_storage_null.e | 11 +++ .../persistence/cms_oauth_20_storage_sql.e | 48 +++++++++++- .../oauth20/site/scripts/oauth2_table.sql.tpl | 5 +- 10 files changed, 237 insertions(+), 13 deletions(-) diff --git a/examples/demo/site/modules/auth/templates/block_account_info.tpl b/examples/demo/site/modules/auth/templates/block_account_info.tpl index 289ce5c..763d51c 100644 --- a/examples/demo/site/modules/auth/templates/block_account_info.tpl +++ b/examples/demo/site/modules/auth/templates/block_account_info.tpl @@ -24,6 +24,39 @@
{include file="block_change_password.tpl" /} +
+

Un-Associate Account with Oauth Consumer

+
+ {foreach item="consumer" from="$oauth_associated"} +
+
+
+ +
+
+ +
+
+
+ {/foreach} +
+

Associate Account with Oauth Consumer

+
+ {foreach item="consumer" from="$oauth_not_associated"} +
+
+
+ +
+
+ + +
+
+
+ {/foreach} +
+

Roles

diff --git a/examples/demo/site/modules/oauth20/scripts/oauth2_table.sql.tpl b/examples/demo/site/modules/oauth20/scripts/oauth2_table.sql.tpl index 3471b1f..925a606 100644 --- a/examples/demo/site/modules/oauth20/scripts/oauth2_table.sql.tpl +++ b/examples/demo/site/modules/oauth20/scripts/oauth2_table.sql.tpl @@ -4,7 +4,10 @@ CREATE TABLE $table_name ( `access_token` TEXT NOT NULL, `created` DATETIME NOT NULL, `details` TEXT NOT NULL, + `email` TEXT NOT NULL, CONSTRAINT `uid` - UNIQUE(`uid`) + UNIQUE(`uid`), + CONSTRAINT `email` + UNIQUE(`email`) ); diff --git a/modules/auth/cms_authentication_module.e b/modules/auth/cms_authentication_module.e index edeb3ff..516fa19 100644 --- a/modules/auth/cms_authentication_module.e +++ b/modules/auth/cms_authentication_module.e @@ -104,7 +104,6 @@ feature -- Hooks configuration do end - menu_system_alter (a_menu_system: CMS_MENU_SYSTEM; a_response: CMS_RESPONSE) -- Hook execution on collection of menu contained by `a_menu_system' -- for related response `a_response'. @@ -145,8 +144,6 @@ feature -- Handler r.execute end - - handle_login (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE) local r: CMS_RESPONSE @@ -172,8 +169,6 @@ feature -- Handler r.execute end - - handle_register (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE) local r: CMS_RESPONSE @@ -490,7 +485,6 @@ feature -- Handler end end - feature {NONE} -- Token Generation new_token: STRING diff --git a/modules/auth/site/templates/block_account_info.tpl b/modules/auth/site/templates/block_account_info.tpl index 289ce5c..763d51c 100644 --- a/modules/auth/site/templates/block_account_info.tpl +++ b/modules/auth/site/templates/block_account_info.tpl @@ -24,6 +24,39 @@

{include file="block_change_password.tpl" /} +
+

Un-Associate Account with Oauth Consumer

+
+ {foreach item="consumer" from="$oauth_associated"} +
+
+
+ +
+
+ +
+
+
+ {/foreach} +
+

Associate Account with Oauth Consumer

+
+ {foreach item="consumer" from="$oauth_not_associated"} +
+
+
+ +
+
+ + +
+
+
+ {/foreach} +
+

Roles

diff --git a/modules/oauth20/cms_oauth_20_api.e b/modules/oauth20/cms_oauth_20_api.e index 22de8a4..8952e2e 100644 --- a/modules/oauth20/cms_oauth_20_api.e +++ b/modules/oauth20/cms_oauth_20_api.e @@ -40,6 +40,12 @@ feature -- Access: User Oauth20 Result := oauth_20_storage.user_oauth2_by_id (a_uid, a_consumer) end + user_oauth2_by_email (a_email: like {CMS_USER}.email; a_consumer: READABLE_STRING_GENERAL): detachable CMS_USER + -- Retrieve a user by email `a_email' for the consumer `a_consumer', if any. + do + Result := oauth_20_storage.user_oauth2_by_email (a_email, a_consumer) + end + user_oauth2_by_token (a_token: READABLE_STRING_GENERAL; a_consumer: READABLE_STRING_GENERAL): detachable CMS_USER -- Retrieve a user by token `a_token' for the consumer `a_consumer'. do @@ -85,11 +91,22 @@ feature -- Change: User OAuth20 update_user_oauth2 (a_token: READABLE_STRING_GENERAL; a_user_profile: READABLE_STRING_32; a_user: CMS_USER; a_consumer_table: READABLE_STRING_GENERAL) - -- Updaate user `a_user' with oauth2 for the consumer `a_consumer'. + -- Update user `a_user' with oauth2 for the consumer `a_consumer'. require has_id: a_user.has_id do oauth_20_storage.update_user_oauth2 (a_token, a_user_profile, a_user, a_consumer_table) end + + remove_user_oauth2 (a_user: CMS_USER; a_consumer_table: READABLE_STRING_GENERAL) + -- Remove user `a_user' with oauth2 for the consumer `a_consumer'. + require + has_id: a_user.has_id + do + oauth_20_storage.remove_user_oauth2 (a_user, a_consumer_table) + end + + + end diff --git a/modules/oauth20/cms_oauth_20_module.e b/modules/oauth20/cms_oauth_20_module.e index 9f7b97a..579994c 100644 --- a/modules/oauth20/cms_oauth_20_module.e +++ b/modules/oauth20/cms_oauth_20_module.e @@ -182,6 +182,8 @@ feature -- Router a_router.handle ("/account/roc-oauth-logout", create {WSF_URI_AGENT_HANDLER}.make (agent handle_logout (a_api, ?, ?)), a_router.methods_get_post) a_router.handle ("/account/login-with-oauth/{callback}", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_login_with_oauth (a_api,a_user_oauth_api, ?, ?)), a_router.methods_get_post) a_router.handle ("/account/oauth-callback/{callback}", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_callback_oauth (a_api, a_user_oauth_api, ?, ?)), a_router.methods_get_post) + a_router.handle ("/account/oauth-associate", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_associate (a_api, a_user_oauth_api, ?, ?)), a_router.methods_post) + a_router.handle ("/account/oauth-un-associate", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_un_associate (a_api, a_user_oauth_api, ?, ?)), a_router.methods_post) end feature -- Hooks configuration @@ -205,6 +207,10 @@ feature -- Hooks then a_value.force ("account/roc-oauth-logout", "auth_login_strategy") end + + if attached a_response.current_user (a_response.request) as u then + associate_account (u, a_value) + end end menu_system_alter (a_menu_system: CMS_MENU_SYSTEM; a_response: CMS_RESPONSE) @@ -298,6 +304,28 @@ feature -- Hooks end end +feature {NONE} -- Associate + + associate_account (a_user: CMS_USER; a_value: CMS_VALUE_TABLE) + local + l_associated: LIST [STRING] + l_not_associated: LIST [STRING] + do + if attached user_oauth_api as l_oauth_api then + create {ARRAYED_LIST [STRING]}l_associated.make (1) + create {ARRAYED_LIST [STRING]}l_not_associated.make (1) + across l_oauth_api.oauth2_consumers as ic loop + if attached l_oauth_api.user_oauth2_by_id (a_user.id, ic.item) then + l_associated.force (ic.item) + else + l_not_associated.force (ic.item) + end + end + a_value.force (l_associated, "oauth_associated") + a_value.force (l_not_associated, "oauth_not_associated") + end + end + feature {NONE} -- Helpers template_block (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE): detachable CMS_SMARTY_TEMPLATE_BLOCK @@ -406,7 +434,7 @@ feature -- OAuth2 Login with Provider then if attached l_user_api.user_by_email (l_email) as p_user then -- User with email exist - if attached a_user_oauth_api.user_oauth2_by_id (p_user.id, l_consumer.name) then + if attached a_user_oauth_api.user_oauth2_by_id (p_user.id, l_consumer.name) then -- Update oauth entry a_user_oauth_api.update_user_oauth2 (l_access_token.token, l_user_profile, p_user, l_consumer.name ) else @@ -417,8 +445,13 @@ feature -- OAuth2 Login with Provider l_cookie.set_max_age (l_access_token.expires_in) l_cookie.set_path ("/") res.add_cookie (l_cookie) + elseif attached a_user_oauth_api.user_oauth2_by_email (l_email, l_consumer.name) as p_user then + a_user_oauth_api.update_user_oauth2 (l_access_token.token, l_user_profile, p_user, l_consumer.name ) + create l_cookie.make ({CMS_OAUTH_20_CONSTANTS}.oauth_session, l_access_token.token) + l_cookie.set_max_age (l_access_token.expires_in) + l_cookie.set_path ("/") + res.add_cookie (l_cookie) else - create {ARRAYED_LIST [CMS_USER_ROLE]} l_roles.make (1) l_roles.force (l_user_api.authenticated_user_role) @@ -453,6 +486,47 @@ feature -- OAuth2 Login with Provider end + handle_associate (api: CMS_API; a_oauth_api: CMS_OAUTH_20_API; req: WSF_REQUEST; res: WSF_RESPONSE) + local + r: CMS_RESPONSE + do + create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) + if req.is_post_request_method then + if + attached {WSF_STRING} req.form_parameter ("consumer") as l_consumer and then + attached {WSF_STRING} req.form_parameter ("email") as l_email and then + attached current_user (req) as l_user + then + l_user.set_email (l_email.value) + a_oauth_api.new_user_oauth2 ("none", "none", l_user, l_consumer.value ) + -- TODO send email? + end + end + r.set_redirection (req.absolute_script_url ("/account")) + r.execute + end + + + handle_un_associate (api: CMS_API; a_oauth_api: CMS_OAUTH_20_API; req: WSF_REQUEST; res: WSF_RESPONSE) + local + r: CMS_RESPONSE + do + create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) + if req.is_post_request_method then + if + attached {WSF_STRING} req.form_parameter ("consumer") as l_consumer and then + attached current_user (req) as l_user + then + a_oauth_api.remove_user_oauth2 (l_user, l_consumer.value) + -- TODO send email? + end + end + r.set_redirection (req.absolute_script_url ("/account")) + r.execute + end + + + feature {NONE} -- Token Generation new_token: STRING diff --git a/modules/oauth20/persistence/cms_oauth_20_storage_i.e b/modules/oauth20/persistence/cms_oauth_20_storage_i.e index d3a65cb..d9fcf5e 100644 --- a/modules/oauth20/persistence/cms_oauth_20_storage_i.e +++ b/modules/oauth20/persistence/cms_oauth_20_storage_i.e @@ -25,6 +25,11 @@ feature -- Access: Users deferred end + user_oauth2_by_email (a_email: like {CMS_USER}.email; a_consumer_table: READABLE_STRING_GENERAL): detachable CMS_USER + -- Retrieve a user by email `a_email' for the consumer `a_consumer', if any. + deferred + end + user_oauth2_by_token (a_token: READABLE_STRING_GENERAL; a_consumer_table: READABLE_STRING_GENERAL): detachable CMS_USER -- Retrieve a user by token `a_token' for the consumer `a_consumer'. deferred @@ -63,4 +68,11 @@ feature -- Change: User Oauth2 deferred end + remove_user_oauth2 (a_user: CMS_USER; a_consumer_table: READABLE_STRING_GENERAL) + -- Remove user `a_user' with oauth2 for the consumer `a_consumer'. + require + has_id: a_user.has_id + deferred + end + end diff --git a/modules/oauth20/persistence/cms_oauth_20_storage_null.e b/modules/oauth20/persistence/cms_oauth_20_storage_null.e index 675b9be..8ddef02 100644 --- a/modules/oauth20/persistence/cms_oauth_20_storage_null.e +++ b/modules/oauth20/persistence/cms_oauth_20_storage_null.e @@ -27,6 +27,11 @@ feature -- Access: Users do end + user_oauth2_by_email (a_email: like {CMS_USER}.email; a_consumer_table: READABLE_STRING_GENERAL): detachable CMS_USER + -- + do + end + user_oauth2_by_token (a_token: READABLE_STRING_GENERAL; a_consumer_table: READABLE_STRING_GENERAL): detachable CMS_USER -- -- CMS User with Oauth credential by access token `a_token' if any. do @@ -65,5 +70,11 @@ feature -- Change: User Oauth2 do end + remove_user_oauth2 (a_user: CMS_USER; a_consumer_table: READABLE_STRING_GENERAL) + -- Remove user `a_user' with oauth2 for the consumer `a_consumer'. + do + end + + end diff --git a/modules/oauth20/persistence/cms_oauth_20_storage_sql.e b/modules/oauth20/persistence/cms_oauth_20_storage_sql.e index deba68b..24f1273 100644 --- a/modules/oauth20/persistence/cms_oauth_20_storage_sql.e +++ b/modules/oauth20/persistence/cms_oauth_20_storage_sql.e @@ -60,6 +60,26 @@ feature -- Access User Outh end end + user_oauth2_by_email (a_email: like {CMS_USER}.email; a_consumer: READABLE_STRING_GENERAL): detachable CMS_USER + -- + local + l_parameters: STRING_TABLE [detachable ANY] + l_string: STRING + do + error_handler.reset + write_information_log (generator + ".user_oauth2_by_email") + create l_parameters.make (1) + l_parameters.put (a_email, "email") + create l_string.make_from_string (select_user_oauth2_template_by_email) + l_string.replace_substring_all ("$table_name", oauth2_sql_table_name (a_consumer)) + sql_query (l_string, l_parameters) + if sql_rows_count = 1 then + Result := fetch_user + else + check no_more_than_one: sql_rows_count = 0 end + end + end + user_oauth2_by_token (a_token: READABLE_STRING_GENERAL; a_consumer: READABLE_STRING_GENERAL): detachable CMS_USER -- local @@ -156,6 +176,8 @@ feature -- Change: User OAuth l_parameters.put (a_token, "token") l_parameters.put (a_user_profile, "profile") l_parameters.put (create {DATE_TIME}.make_now_utc, "utc_date") + l_parameters.put (a_user.email, "email") + create l_string.make_from_string (sql_insert_oauth2_template) l_string.replace_substring_all ("$table_name", oauth2_sql_table_name (a_consumer)) @@ -164,7 +186,6 @@ feature -- Change: User OAuth end update_user_oauth2 (a_token: READABLE_STRING_GENERAL; a_user_profile: READABLE_STRING_32; a_user: CMS_USER; a_consumer: READABLE_STRING_GENERAL ) - -- Update user `a_user' with oauth2 authentication. -- local l_parameters: STRING_TABLE [detachable ANY] @@ -185,6 +206,25 @@ feature -- Change: User OAuth sql_commit_transaction end + remove_user_oauth2 (a_user: CMS_USER; a_consumer: READABLE_STRING_GENERAL) + -- + local + l_parameters: STRING_TABLE [detachable ANY] + l_string: STRING + do + error_handler.reset + sql_begin_transaction + + write_information_log (generator + ".remove_user_oauth2") + create l_parameters.make (1) + l_parameters.put (a_user.id, "uid") + + create l_string.make_from_string (sql_remove_oauth2_template) + l_string.replace_substring_all ("$table_name", oauth2_sql_table_name (a_consumer)) + sql_change (l_string, l_parameters) + sql_commit_transaction + end + feature {NONE} -- Implementation OAuth Consumer fetch_consumer: detachable CMS_OAUTH_20_CONSUMER @@ -294,10 +334,14 @@ feature {NONE} -- User OAuth2 Select_user_oauth2_template_by_id: STRING = "SELECT u.* FROM users as u JOIN $table_name as og ON og.uid = u.uid and og.uid = :uid;" - Sql_insert_oauth2_template: STRING = "INSERT INTO $table_name (uid, access_token, details, created) VALUES (:uid, :token, :profile, :utc_date);" + Select_user_oauth2_template_by_email: STRING = "SELECT u.* FROM users as u JOIN $table_name as og ON og.uid = u.uid and og.email = :email;" + + Sql_insert_oauth2_template: STRING = "INSERT INTO $table_name (uid, access_token, details, created, email) VALUES (:uid, :token, :profile, :utc_date, :email);" Sql_update_oauth2_template: STRING = "UPDATE $table_name SET access_token = :token, details = :profile WHERE uid =:uid;" + Sql_remove_oauth2_template: STRING = "DELETE FROM $table_name WHERE uid =:uid;" + Sql_oauth_consumers: STRING = "SELECT name FROM oauth2_consumers"; Sql_oauth2_table_prefix: STRING = "oauth2_" diff --git a/modules/oauth20/site/scripts/oauth2_table.sql.tpl b/modules/oauth20/site/scripts/oauth2_table.sql.tpl index 3471b1f..925a606 100644 --- a/modules/oauth20/site/scripts/oauth2_table.sql.tpl +++ b/modules/oauth20/site/scripts/oauth2_table.sql.tpl @@ -4,7 +4,10 @@ CREATE TABLE $table_name ( `access_token` TEXT NOT NULL, `created` DATETIME NOT NULL, `details` TEXT NOT NULL, + `email` TEXT NOT NULL, CONSTRAINT `uid` - UNIQUE(`uid`) + UNIQUE(`uid`), + CONSTRAINT `email` + UNIQUE(`email`) );