diff --git a/dev_modules/masquerade_auth/masquerade_api.e b/dev_modules/masquerade_auth/masquerade_api.e new file mode 100644 index 0000000..b7bc732 --- /dev/null +++ b/dev_modules/masquerade_auth/masquerade_api.e @@ -0,0 +1,87 @@ +note + description: "API to manage CMS User session authentication" + date: "$Date$" + revision: "$Revision$" + +class + MASQUERADE_API + +inherit + CMS_AUTH_API_I + + REFACTORING_HELPER + +create {MASQUERADE_AUTH_MODULE} + make_with_session_api + +feature {NONE} -- Initialization + + make_with_session_api (a_api: CMS_API; a_session_api: CMS_SESSION_API) + do + session_api := a_session_api + make (a_api) + end + +feature -- Access + + session_api: CMS_SESSION_API + +feature -- Status report + + has_permission_to_masquerade (a_user: detachable CMS_USER): BOOLEAN + local + v: STRING + do + if attached cms_api.setup.string_8_item_or_default ("dev.masquerade", "permission") as s then + v := s + v.left_adjust + v.right_adjust + if v.is_case_insensitive_equal_general ("none") then + elseif v.is_case_insensitive_equal_general ("all") then + Result := True + elseif v.is_case_insensitive_equal_general ("permission") then + Result := cms_api.user_has_permission (a_user, "masquerade") + else + -- no! + end + end + end + + is_authenticating (a_response: CMS_RESPONSE): BOOLEAN + do + if + a_response.is_authenticated and then + attached a_response.request.cookie (session_api.session_token) + then + Result := True + end + end + +feature -- Basic operation + + process_user_login (a_user: CMS_USER; req: WSF_REQUEST; res: WSF_RESPONSE) + do + session_api.process_user_login (a_user, req, res) + end + + process_user_logout (a_user: CMS_USER; req: WSF_REQUEST; res: WSF_RESPONSE) + do + session_api.process_user_logout (a_user, req, res) + end + +feature -- Access + +-- user_by_session_token (a_token: READABLE_STRING_32): detachable CMS_USER +-- -- Retrieve user by token `a_token', if any. +-- do +-- Result := session_auth_storage.user_by_session_token (a_token) +-- end + +-- has_user_token (a_user: CMS_USER): BOOLEAN +-- -- Has the user `a_user' and associated session token? +-- do +-- Result := session_auth_storage.has_user_token (a_user) +-- end + + +end diff --git a/dev_modules/masquerade_auth/masquerade_auth-safe.ecf b/dev_modules/masquerade_auth/masquerade_auth-safe.ecf new file mode 100644 index 0000000..1da46a6 --- /dev/null +++ b/dev_modules/masquerade_auth/masquerade_auth-safe.ecf @@ -0,0 +1,3 @@ + + + diff --git a/dev_modules/masquerade_auth/masquerade_auth.ecf b/dev_modules/masquerade_auth/masquerade_auth.ecf new file mode 100644 index 0000000..8ebacd5 --- /dev/null +++ b/dev_modules/masquerade_auth/masquerade_auth.ecf @@ -0,0 +1,26 @@ + + + + + + /.svn$ + /CVS$ + /EIFGENs$ + + + + + + + + + + + + + + + + + + diff --git a/dev_modules/masquerade_auth/masquerade_auth_module.e b/dev_modules/masquerade_auth/masquerade_auth_module.e new file mode 100644 index 0000000..ca8a1c1 --- /dev/null +++ b/dev_modules/masquerade_auth/masquerade_auth_module.e @@ -0,0 +1,268 @@ +note + description: "[ + This module allows the use Session Based Authentication using Cookies to restrict access + by looking up users in the given providers. + ]" + date: "$Date$" + revision: "$Revision$" + +class + MASQUERADE_AUTH_MODULE + +inherit + CMS_AUTH_MODULE_I + rename + module_api as masquerade_api + redefine + make, + setup_hooks, + initialize, + install, + permissions, + masquerade_api, + menu_system_alter + end + + CMS_HOOK_BLOCK + + CMS_HOOK_MENU_SYSTEM_ALTER + +create + make + +feature {NONE} -- Initialization + + make + do + Precursor + version := "1.0" + description := "Service to easily log as user at development time" + package := "debug" + disable -- Disabled by default + add_dependency ({CMS_SESSION_AUTH_MODULE}) + end + +feature -- Access + + name: STRING = "masquerade_auth" + + permissions: LIST [READABLE_STRING_8] + -- List of permission ids, used by this module, and declared. + do + Result := Precursor + Result.extend ("masquerade") + end + +feature {CMS_API} -- Module Initialization + + initialize (a_api: CMS_API) + -- + do + Precursor (a_api) + + if attached {CMS_SESSION_API} a_api.module_api ({CMS_SESSION_AUTH_MODULE}) as l_session_api then + -- API initialization + create masquerade_api.make_with_session_api (a_api, l_session_api) + end + end + +feature {CMS_API} -- Module management + + install (api: CMS_API) + do + Precursor {CMS_AUTH_MODULE_I} (api) -- Mark it as installed. + end + +feature {CMS_API} -- Access: API + + masquerade_api: detachable MASQUERADE_API + -- + +feature -- Access: auth strategy + + login_title: STRING = "Masquerade" + -- Module specific login title. + + login_location: STRING = "account/auth/roc-masquerade-login" + + logout_location: STRING = "account/auth/roc-masquerade-logout" + + is_authenticating (a_response: CMS_RESPONSE): BOOLEAN + -- + do + if attached masquerade_api as l_masquerade_api then + Result := l_masquerade_api.is_authenticating (a_response) + end + end + +feature -- Access: router + + setup_router (a_router: WSF_ROUTER; a_api: CMS_API) + -- + do + if attached masquerade_api as l_masquerade_api then + a_router.handle ("/" + login_location, create {WSF_URI_AGENT_HANDLER}.make (agent handle_login (a_api, ?, ?)), a_router.methods_head_get) + a_router.handle ("/" + logout_location, create {WSF_URI_AGENT_HANDLER}.make (agent handle_logout (a_api, l_masquerade_api, ?, ?)), a_router.methods_get_post) + a_router.handle ("/" + login_location, create {WSF_URI_AGENT_HANDLER}.make (agent handle_login_with_masquerade (a_api, l_masquerade_api,?, ?)), a_router.methods_post) + end + end + +feature {NONE} -- Implementation: routes + + handle_login (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE) + local + r: CMS_RESPONSE + do + create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) + if + attached masquerade_api as l_masquerade_api and then + l_masquerade_api.has_permission_to_masquerade (api.user) + then + if api.user_is_authenticated then + r.add_warning_message ("You are signed.") + end + r.add_block (login_block ("login", Void, r), "content") + else + r.add_error_message ("You are not allowed to use masquerade authentication!") + end + r.execute + end + + handle_logout (api: CMS_API; a_masquerade_api: MASQUERADE_API ; req: WSF_REQUEST; res: WSF_RESPONSE) local + r: CMS_RESPONSE + do + if attached api.user as l_user then + a_masquerade_api.process_user_logout (l_user, req, res) + create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) + else + -- Not loggued in ... redirect to home + create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) + r.set_status_code ({HTTP_CONSTANTS}.found) + end + if + attached {WSF_STRING} req.item ("destination") as p_destination and then + attached p_destination.value as v and then + v.is_valid_as_string_8 + then + r.set_redirection (v.to_string_8) + else + r.set_redirection (req.absolute_script_url ("")) + end + + r.execute + end + + handle_login_with_masquerade (api: CMS_API; a_masquerade_api: MASQUERADE_API; req: WSF_REQUEST; res: WSF_RESPONSE) + local + r: CMS_RESPONSE + do + if a_masquerade_api.has_permission_to_masquerade (api.user) then + if + attached {WSF_STRING} req.form_parameter ("username") as l_username + then + if + attached api.user_api.user_by_name (l_username.value) as l_user + then + a_masquerade_api.process_user_login (l_user, req, res) + + create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) + if + attached {WSF_STRING} req.item ("destination") as p_destination and then + attached p_destination.value as v and then + v.is_valid_as_string_8 + then + r.set_redirection (v.to_string_8) + else + r.set_redirection ("") + end + else + create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) + r.add_block (login_block ("login", Void, r), "content") + end + else + create {BAD_REQUEST_ERROR_CMS_RESPONSE} r.make (req, res, api) + r.add_block (login_block ("login", "Wrong username", r), "content") + end + else + create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api) + end + r.execute + end + +feature -- Hooks configuration + + setup_hooks (a_hooks: CMS_HOOK_CORE_MANAGER) + -- Module hooks configuration. + do + Precursor (a_hooks) + a_hooks.subscribe_to_block_hook (Current) + a_hooks.subscribe_to_menu_system_alter_hook (Current) + end + +feature -- Hooks + + block_list: ITERABLE [like {CMS_BLOCK}.name] + do + Result := <<"?login">> + end + + get_block_view (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE) + do + if a_block_id.is_case_insensitive_equal_general ("login") then + a_response.add_block (login_block (a_block_id, Void, a_response), "content") + end + 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'. + local + u: detachable CMS_USER + do + u := a_response.api.user + if + attached masquerade_api as l_masquerade_api and then + l_masquerade_api.has_permission_to_masquerade (u) + then + Precursor (a_menu_system, a_response) + if u /= Void then + a_menu_system.navigation_menu.extend (a_response.local_link ("Masquerade", login_location)) + end + end + end + +feature {NONE} -- Block views + + login_block (a_block_id: READABLE_STRING_8; a_err: detachable READABLE_STRING_8; a_response: CMS_RESPONSE): CMS_CONTENT_BLOCK + do + create Result.make (a_block_id, Void, login_html (a_err, a_response), Void) + end + + login_html (a_err: detachable READABLE_STRING_8; a_response: CMS_RESPONSE): STRING + local + params: CMS_DATA_QUERY_PARAMETERS + u: CMS_USER + do + create Result.make_from_string ("
") + if a_err /= Void then + Result.append ("
") + Result.append (a_err) + Result.append ("
") + end + Result.append ("
%N") + Result.append ("
") + Result.append ("") + + create params.make (0, a_response.api.user_api.users_count.as_natural_32) + across + a_response.api.user_api.recent_users (params) as ic + loop + u := ic.item + Result.append ("
  • ") + Result.append (a_response.html_encoded (a_response.api.user_display_name (u))) + Result.append ("
  • %N") + end + Result.append ("
    ") + end + +end diff --git a/examples/demo/demo.ecf b/examples/demo/demo.ecf index 7df2c04..8163de4 100644 --- a/examples/demo/demo.ecf +++ b/examples/demo/demo.ecf @@ -29,7 +29,7 @@ - + @@ -40,8 +40,9 @@ - + +
    -
    -
    - - -
    -
    + {$page.regions.search/}
    + {/if}
    diff --git a/examples/demo/site/themes/bootstrap/search.tpl b/examples/demo/site/themes/bootstrap/search.tpl new file mode 100644 index 0000000..1cedbb4 --- /dev/null +++ b/examples/demo/site/themes/bootstrap/search.tpl @@ -0,0 +1,6 @@ +
    +
    + + +
    +
    diff --git a/examples/demo/site/themes/bootstrap/theme.info b/examples/demo/site/themes/bootstrap/theme.info index 6c96570..9ba80a7 100644 --- a/examples/demo/site/themes/bootstrap/theme.info +++ b/examples/demo/site/themes/bootstrap/theme.info @@ -4,6 +4,7 @@ author=jvelilla version=0.1 regions[page_top] = Top regions[header] = Header +regions[search] = Search regions[content] = Content regions[highlighted] = Highlighted regions[help] = Help diff --git a/examples/demo/src/demo_cms_execution.e b/examples/demo/src/demo_cms_execution.e index 4dc81a2..71613e4 100644 --- a/examples/demo/src/demo_cms_execution.e +++ b/examples/demo/src/demo_cms_execution.e @@ -86,11 +86,14 @@ feature -- CMS modules -- Miscellanious a_setup.register_module (create {CMS_MESSAGING_MODULE}.make) - a_setup.register_module (create {GOOGLE_CUSTOM_SEARCH_MODULE}.make) + a_setup.register_module (create {GOOGLE_CUSTOM_SEARCH_MODULE_20}.make) a_setup.register_module (create {CMS_CUSTOM_BLOCK_MODULE}.make) a_setup.register_module (create {CMS_DEBUG_MODULE}.make) a_setup.register_module (create {CMS_DEMO_MODULE}.make) + -- Dev + a_setup.register_module (create {MASQUERADE_AUTH_MODULE}.make) + end end diff --git a/modules/google_search_20/Readme.md b/modules/google_search_20/Readme.md new file mode 100644 index 0000000..71df20c --- /dev/null +++ b/modules/google_search_20/Readme.md @@ -0,0 +1,13 @@ +Google Custom Search Module 2.0. + +# Based on Google Custom Search Engine (CSE) +- https://developers.google.com/custom-search/docs/element +- Search form provides a parameter `q` for the search query. +- Results are displayed in associated page /gcse2 (using ) + +# Settings +- edit the `site/modules/google_search_20/config/google_search_20.json` file, and set the value `gcse.search_engine_id`. + +# How to get a Custom Search engine ID? +- See https://support.google.com/customsearch/answer/2649143?hl=en +- https://cse.google.com/all diff --git a/modules/google_search_20/google_search_20-safe.ecf b/modules/google_search_20/google_search_20-safe.ecf new file mode 100644 index 0000000..5e0ece5 --- /dev/null +++ b/modules/google_search_20/google_search_20-safe.ecf @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/modules/google_search_20/google_search_20.ecf b/modules/google_search_20/google_search_20.ecf new file mode 100644 index 0000000..4c86d8f --- /dev/null +++ b/modules/google_search_20/google_search_20.ecf @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + diff --git a/modules/google_search_20/site/config/google_search_20.json-dist b/modules/google_search_20/site/config/google_search_20.json-dist new file mode 100644 index 0000000..ea94f8a --- /dev/null +++ b/modules/google_search_20/site/config/google_search_20.json-dist @@ -0,0 +1,5 @@ +{ + "gcse": { + "search_engine_id":"" + } +} diff --git a/modules/google_search_20/site/templates/block_gcse_search_form.tpl b/modules/google_search_20/site/templates/block_gcse_search_form.tpl new file mode 100644 index 0000000..4542f09 --- /dev/null +++ b/modules/google_search_20/site/templates/block_gcse_search_form.tpl @@ -0,0 +1,6 @@ +
    +
    + + +
    +
    diff --git a/modules/google_search_20/site/templates/block_gcse_search_results.tpl b/modules/google_search_20/site/templates/block_gcse_search_results.tpl new file mode 100644 index 0000000..056ad79 --- /dev/null +++ b/modules/google_search_20/site/templates/block_gcse_search_results.tpl @@ -0,0 +1,7 @@ +
    +
    +

    Results for {$cms_search_query/}

    +
    + + +
    diff --git a/modules/google_search_20/src/google_custom_search_module_20.e b/modules/google_search_20/src/google_custom_search_module_20.e new file mode 100644 index 0000000..2c85e12 --- /dev/null +++ b/modules/google_search_20/src/google_custom_search_module_20.e @@ -0,0 +1,156 @@ +note + description: "[ + Module providing Google Custom Search functionality. + ]" + date: "$Date$" + revision: "$Revision$" + +class + GOOGLE_CUSTOM_SEARCH_MODULE_20 + +inherit + CMS_MODULE + redefine + setup_hooks + end + + CMS_HOOK_AUTO_REGISTER + + REFACTORING_HELPER + + CMS_HOOK_BLOCK + + CMS_HOOK_BLOCK_HELPER + + SHARED_EXECUTION_ENVIRONMENT + export + {NONE} all + end + + REFACTORING_HELPER + + SHARED_LOGGER + +create + make + +feature {NONE} -- Initialization + + make + -- Create current module + do + version := "2.0" + description := "Google custome search module 2.0" + package := "search" + end + +feature -- Access + + name: STRING = "google_search_20" + -- + +feature -- Router + + setup_router (a_router: WSF_ROUTER; a_api: CMS_API) + -- Router configuration. + local + m: WSF_URI_MAPPING + do + create m.make_trailing_slash_ignored ("/gcse20", create {WSF_URI_AGENT_HANDLER}.make (agent handle_search (a_api, ?, ?))) + a_router.map (m, a_router.methods_head_get) + end + +feature -- GCSE Keys + + gcse_cx_key (api: CMS_API): detachable READABLE_STRING_8 + -- Get google custom search engine id. + local + utf: UTF_CONVERTER + do + if attached api.module_configuration (Current, Void) as cfg then + if + attached cfg.text_item ("gcse.search_engine_id") as l_gcse_cx_key and then + not l_gcse_cx_key.is_empty + then + Result := utf.utf_32_string_to_utf_8_string_8 (l_gcse_cx_key) + end + end + end + +feature -- Handler + + handle_search (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE) + local + r: CMS_RESPONSE + l_script: STRING + b: CMS_CONTENT_BLOCK + do + write_debug_log (generator + ".handle_search") + create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) + if + attached {WSF_STRING} req.query_parameter ("q") as l_query and then + not l_query.value.is_empty + then + if + attached gcse_cx_key (api) as l_cx + then + r.set_value (l_query.value, "cms_search_query") + if + attached smarty_template_block (Current, "gcse_search_results", api) as l_tpl_block + then + r.add_block (l_tpl_block, "content") + + if attached gcse_cx_key (api) as l_ctx then + create l_script.make_from_string (gcse_20_script) + l_script.replace_substring_all ("#CX_VALUE", l_ctx) + create b.make_raw ("gcse2_js", Void, "", Void) + r.add_block (b, "footer") + end + end + end + else + r.add_message ("No query submitted", Void) + end + r.execute + end + +feature -- Hooks configuration + + setup_hooks (a_hooks: CMS_HOOK_CORE_MANAGER) + -- Module hooks configuration. + do + auto_subscribe_to_hooks (a_hooks) + end + + block_list: ITERABLE [like {CMS_BLOCK}.name] + do + Result := <<"gcse_search_form">> + end + + get_block_view (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE) + do + if a_block_id.is_case_insensitive_equal_general ("gcse_search_form") then + if a_response.request.is_get_request_method then + if attached smarty_template_block (Current, a_block_id, a_response.api) as l_tpl_block then + a_response.add_block (l_tpl_block, "search") + else + debug ("cms") + a_response.add_warning_message ("Error with block [" + a_block_id + "]") + end + end + end + end + end + +feature {NONE} -- Implementation + + gcse_20_script: STRING = "[ + (function() { + var cx = '#CX_VALUE'; + var gcse = document.createElement('script'); gcse.type = 'text/javascript'; gcse.async = true; + gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') + '//www.google.com/cse/cse.js?cx=' + cx; + var s = document.getElementsByTagName('script')[0]; + s.parentNode.insertBefore(gcse, s); + })(); + ]" +end diff --git a/modules/session_auth/cms_session_api.e b/modules/session_auth/cms_session_api.e index ac02417..6def2a0 100644 --- a/modules/session_auth/cms_session_api.e +++ b/modules/session_auth/cms_session_api.e @@ -57,6 +57,18 @@ feature -- Settings session_max_age: INTEGER -- Value of the Max-Age, before the cookie expires. +feature -- Status report + + is_authenticating (a_response: CMS_RESPONSE): BOOLEAN + do + if + a_response.is_authenticated and then + attached a_response.request.cookie (session_token) + then + Result := True + end + end + feature -- Access user_by_session_token (a_token: READABLE_STRING_32): detachable CMS_USER @@ -71,6 +83,47 @@ feature -- Access Result := session_auth_storage.has_user_token (a_user) end +feature -- Basic operation + + process_user_login (a_user: CMS_USER; req: WSF_REQUEST; res: WSF_RESPONSE) + local + l_token: STRING + l_cookie: WSF_COOKIE + do + l_token := new_session_token + if has_user_token (a_user) then + update_user_session_auth (l_token, a_user) + else + new_user_session_auth (l_token, a_user) + end + create l_cookie.make (session_token, l_token) + l_cookie.set_max_age (session_max_age) + l_cookie.set_path ("/") + res.add_cookie (l_cookie) + cms_api.set_user (a_user) + cms_api.record_user_login (a_user) + end + + process_user_logout (a_user: CMS_USER; req: WSF_REQUEST; res: WSF_RESPONSE) + local + l_cookie: WSF_COOKIE + do + if + attached session_token as tok and then + attached {WSF_STRING} req.cookie (tok) as l_cookie_token + then + -- Logout Session + create l_cookie.make (tok, "") -- l_cookie_token.value) -- FIXME: unicode issue? + l_cookie.set_path ("/") + l_cookie.unset_max_age + l_cookie.set_expiration_date (create {DATE_TIME}.make_from_epoch (0)) + res.add_cookie (l_cookie) + else + -- it seems the user was not login, as there is no associated cookie! + end + cms_api.unset_user + end + feature -- Change User session new_user_session_auth (a_token: READABLE_STRING_GENERAL; a_user: CMS_USER;) @@ -86,4 +139,26 @@ feature -- Change User session session_auth_storage.update_user_session_auth (a_token, a_user) end +feature -- Token + + new_session_token: STRING + -- Generate token to use in a Session. + local + l_token: STRING + l_security: CMS_TOKEN_GENERATOR + l_encode: URL_ENCODER + do + create l_security + l_token := l_security.token + create l_encode + from until l_token.same_string (l_encode.encoded_string (l_token)) loop + -- Loop ensure that we have a security token that does not contain characters that need encoding. + -- We cannot simply to an encode-decode because the email sent to the user will contain an encoded token + -- but the user will need to use an unencoded token if activation has to be done manually. + l_token := l_security.token + end + Result := l_token + end + + end diff --git a/modules/session_auth/cms_session_auth_module.e b/modules/session_auth/cms_session_auth_module.e index b9f4e5b..9abc865 100644 --- a/modules/session_auth/cms_session_auth_module.e +++ b/modules/session_auth/cms_session_auth_module.e @@ -100,11 +100,9 @@ feature -- Access: auth strategy -- do if - a_response.is_authenticated and then - attached session_api as l_session_api and then - attached a_response.request.cookie (l_session_api.session_token) + attached session_api as l_session_api then - Result := True + Result := l_session_api.is_authenticating (a_response) end end @@ -116,7 +114,7 @@ feature -- Access: router if attached session_api as l_session_api then a_router.handle ("/" + login_location, create {WSF_URI_AGENT_HANDLER}.make (agent handle_login (a_api, ?, ?)), a_router.methods_head_get) a_router.handle ("/" + logout_location, create {WSF_URI_AGENT_HANDLER}.make (agent handle_logout (a_api, l_session_api, ?, ?)), a_router.methods_get_post) - a_router.handle ("/" + login_location, create {WSF_URI_AGENT_HANDLER}.make (agent handle_login_with_session (a_api,session_api, ?, ?)), a_router.methods_post) + a_router.handle ("/" + login_location, create {WSF_URI_AGENT_HANDLER}.make (agent handle_login_with_session (a_api, l_session_api, ?, ?)), a_router.methods_post) end end @@ -164,39 +162,33 @@ feature {NONE} -- Implementation: routes handle_logout (api: CMS_API; a_session_api: CMS_SESSION_API ; req: WSF_REQUEST; res: WSF_RESPONSE) local r: CMS_RESPONSE - l_cookie: WSF_COOKIE - tok: STRING do - tok := a_session_api.session_token - if - attached {WSF_STRING} req.cookie (tok) as l_cookie_token and then - attached api.user as l_user - then - -- Logout Session - create l_cookie.make (tok, "") -- l_cookie_token.value) -- FIXME: unicode issue? - l_cookie.set_path ("/") - l_cookie.unset_max_age - l_cookie.set_expiration_date (create {DATE_TIME}.make_from_epoch (0)) - res.add_cookie (l_cookie) - api.unset_user - + if attached api.user as l_user then + a_session_api.process_user_logout (l_user, req, res) + create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) + else + -- Not loggued in ... redirect to home create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) r.set_status_code ({HTTP_CONSTANTS}.found) - r.set_redirection (req.absolute_script_url ("")) - r.execute - else - fixme (generator + ": missing else implementation in handle_logout!") end + if + attached {WSF_STRING} req.item ("destination") as p_destination and then + attached p_destination.value as v and then + v.is_valid_as_string_8 + then + r.set_redirection (v.to_string_8) + else + r.set_redirection (req.absolute_script_url ("")) + end + + r.execute end - handle_login_with_session (api: CMS_API; a_session_api: detachable CMS_SESSION_API; req: WSF_REQUEST; res: WSF_RESPONSE) + handle_login_with_session (api: CMS_API; a_session_api: CMS_SESSION_API; req: WSF_REQUEST; res: WSF_RESPONSE) local r: CMS_RESPONSE - l_token: STRING - l_cookie: WSF_COOKIE do if - attached a_session_api as l_session_api and then attached {WSF_STRING} req.form_parameter ("username") as l_username and then attached {WSF_STRING} req.form_parameter ("password") as l_password then @@ -204,18 +196,7 @@ feature {NONE} -- Implementation: routes api.user_api.is_valid_credential (l_username.value, l_password.value) and then attached api.user_api.user_by_name (l_username.value) as l_user then - l_token := generate_token - if a_session_api.has_user_token (l_user) then - l_session_api.update_user_session_auth (l_token, l_user) - else - l_session_api.new_user_session_auth (l_token, l_user) - end - create l_cookie.make (a_session_api.session_token, l_token) - l_cookie.set_max_age (a_session_api.session_max_age) - l_cookie.set_path ("/") - res.add_cookie (l_cookie) - api.set_user (l_user) - api.record_user_login (l_user) + a_session_api.process_user_login (l_user, req, res) create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) if @@ -295,23 +276,4 @@ feature {NONE} -- Block views end end - generate_token: STRING - -- Generate token to use in a Session. - local - l_token: STRING - l_security: CMS_TOKEN_GENERATOR - l_encode: URL_ENCODER - do - create l_security - l_token := l_security.token - create l_encode - from until l_token.same_string (l_encode.encoded_string (l_token)) loop - -- Loop ensure that we have a security token that does not contain characters that need encoding. - -- We cannot simply to an encode-decode because the email sent to the user will contain an encoded token - -- but the user will need to use an unencoded token if activation has to be done manually. - l_token := l_security.token - end - Result := l_token - end - end