Added masquerade dev module and disabled it by default.

- it allows to login as a given user by passing security check.
  - it must be used only during development!
  - disabled by default!
Updated the session auth module to make it easier to be reused.
  - masquerade module is based on the session auth module.
This commit is contained in:
Jocelyn Fiat
2017-04-06 15:33:10 +02:00
parent ad2b30f52b
commit 5915af6a9c
9 changed files with 490 additions and 61 deletions

View File

@@ -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

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="masquerade_auth" uuid="73DA3649-BA18-426C-91CD-5892D52C811C" library_target="masquerade_auth">
<target name="masquerade_auth">
<root all_classes="true"/>
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true">
</option>
<setting name="concurrency" value="scoop"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="cms" location="..\..\cms-safe.ecf"/>
<library name="cms_app_env" location="..\..\library\app_env\app_env-safe.ecf" readonly="false"/>
<library name="cms_auth_module" location="..\..\modules\auth\auth-safe.ecf" readonly="false"/>
<library name="cms_session_auth_module" location="..\..\modules\session_auth\cms_session_auth-safe.ecf" readonly="false"/>
<library name="cms_model" location="..\..\library\model\cms_model-safe.ecf" readonly="false"/>
<library name="crypto" location="$ISE_LIBRARY\unstable\library\text\encryption\crypto\crypto-safe.ecf"/>
<library name="encoder" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\text\encoder\encoder-safe.ecf"/>
<library name="error" location="$ISE_LIBRARY\contrib\library\utility\general\error\error-safe.ecf"/>
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http-safe.ecf"/>
<library name="http_authorization" location="$ISE_LIBRARY\contrib\library\web\authentication\http_authorization\http_authorization-safe.ecf" readonly="false"/>
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
<library name="wsf_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension-safe.ecf" readonly="false"/>
<cluster name="src" location=".\" recursive="true"/>
</target>
</system>

View File

@@ -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)
-- <Precursor>
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
-- <Precursor>
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
-- <Precursor>
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)
-- <Precursor>
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 ("<div class=%"login-box%">")
if a_err /= Void then
Result.append ("<div class=%"error%">")
Result.append (a_err)
Result.append ("</div>")
end
Result.append ("<form name=%"masquerade_auth%" action=%"" + a_response.site_url + login_location + "%" method=%"POST%">%N")
Result.append ("<div><input type=%"text%" name=%"username%" id=%"username%" required value=%"%"><label>Username</label></div>")
Result.append ("<button type=%"submit%">Login</button>")
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 ("<li>")
Result.append (a_response.html_encoded (a_response.api.user_display_name (u)))
Result.append ("</li>%N")
end
Result.append ("</form></div>")
end
end

View File

@@ -31,7 +31,6 @@
<library name="cms_email_service" location="..\..\library\email\email-safe.ecf" readonly="false"/> <library name="cms_email_service" location="..\..\library\email\email-safe.ecf" readonly="false"/>
<library name="cms_feed_aggregator_module" location="..\..\modules\feed_aggregator\feed_aggregator-safe.ecf" readonly="false"/> <library name="cms_feed_aggregator_module" location="..\..\modules\feed_aggregator\feed_aggregator-safe.ecf" readonly="false"/>
<library name="cms_files_module" location="..\..\modules\files\files-safe.ecf" readonly="false"/> <library name="cms_files_module" location="..\..\modules\files\files-safe.ecf" readonly="false"/>
<library name="cms_google_search_module" location="..\..\modules\google_search\google_search-safe.ecf" readonly="false" use_application_options="true"/>
<library name="cms_google_search_20_module" location="..\..\modules\google_search_20\google_search_20-safe.ecf" readonly="false" use_application_options="true"/> <library name="cms_google_search_20_module" location="..\..\modules\google_search_20\google_search_20-safe.ecf" readonly="false" use_application_options="true"/>
<library name="cms_messaging_module" location="..\..\modules\messaging\messaging-safe.ecf" readonly="false"/> <library name="cms_messaging_module" location="..\..\modules\messaging\messaging-safe.ecf" readonly="false"/>
<library name="cms_model" location="..\..\library\model\cms_model-safe.ecf" readonly="false"/> <library name="cms_model" location="..\..\library\model\cms_model-safe.ecf" readonly="false"/>
@@ -42,6 +41,7 @@
<library name="cms_seo_module" location="..\..\modules\seo\seo-safe.ecf" readonly="false"/> <library name="cms_seo_module" location="..\..\modules\seo\seo-safe.ecf" readonly="false"/>
<library name="cms_sitemap_module" location="..\..\modules\sitemap\sitemap-safe.ecf" readonly="false"/> <library name="cms_sitemap_module" location="..\..\modules\sitemap\sitemap-safe.ecf" readonly="false"/>
<library name="cms_session_auth_module" location="..\..\modules\session_auth\cms_session_auth-safe.ecf" readonly="false"/> <library name="cms_session_auth_module" location="..\..\modules\session_auth\cms_session_auth-safe.ecf" readonly="false"/>
<library name="masquerade_auth_module" location="..\..\dev_modules\masquerade_auth\masquerade_auth-safe.ecf" readonly="false"/>
<library name="cms_taxnomy_module" location="..\..\modules\taxonomy\taxonomy-safe.ecf" readonly="false"/> <library name="cms_taxnomy_module" location="..\..\modules\taxonomy\taxonomy-safe.ecf" readonly="false"/>
<library name="embedded_video_module" location="..\..\modules\embedded_video\embedded_video-safe.ecf" readonly="false"/> <library name="embedded_video_module" location="..\..\modules\embedded_video\embedded_video-safe.ecf" readonly="false"/>
<library name="cms_wikitext_module" location="..\..\modules\wikitext\wikitext-safe.ecf" readonly="false"/> <library name="cms_wikitext_module" location="..\..\modules\wikitext\wikitext-safe.ecf" readonly="false"/>

View File

@@ -26,6 +26,7 @@
"embedded_video": { "location": "../../modules/embedded_video" }, "embedded_video": { "location": "../../modules/embedded_video" },
"wikitext": { "location": "../../modules/wikitext" }, "wikitext": { "location": "../../modules/wikitext" },
"messaging": { "location": "../../modules/messaging" }, "messaging": { "location": "../../modules/messaging" },
"comments": { "location": "../../modules/comments" } "comments": { "location": "../../modules/comments" },
"masquerade": { "location": "../../dev_modules/masquerade" }
} }
} }

View File

@@ -63,3 +63,7 @@ base_path=/roc-admin
#theme=admin #theme=admin
# CMS Installation, are accessible by "all", "none" or uppon "permission". (default is none) # CMS Installation, are accessible by "all", "none" or uppon "permission". (default is none)
installation_access=all installation_access=all
[dev]
# masquerade: all, none, permission. Default is none.
masquerade=none

View File

@@ -91,6 +91,9 @@ feature -- CMS modules
a_setup.register_module (create {CMS_DEBUG_MODULE}.make) a_setup.register_module (create {CMS_DEBUG_MODULE}.make)
a_setup.register_module (create {CMS_DEMO_MODULE}.make) a_setup.register_module (create {CMS_DEMO_MODULE}.make)
-- Dev
a_setup.register_module (create {MASQUERADE_AUTH_MODULE}.make)
end end
end end

View File

@@ -57,6 +57,18 @@ feature -- Settings
session_max_age: INTEGER session_max_age: INTEGER
-- Value of the Max-Age, before the cookie expires. -- 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 feature -- Access
user_by_session_token (a_token: READABLE_STRING_32): detachable CMS_USER 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) Result := session_auth_storage.has_user_token (a_user)
end 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 feature -- Change User session
new_user_session_auth (a_token: READABLE_STRING_GENERAL; a_user: CMS_USER;) 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) session_auth_storage.update_user_session_auth (a_token, a_user)
end 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 end

View File

@@ -100,11 +100,9 @@ feature -- Access: auth strategy
-- <Precursor> -- <Precursor>
do do
if if
a_response.is_authenticated and then attached session_api as l_session_api
attached session_api as l_session_api and then
attached a_response.request.cookie (l_session_api.session_token)
then then
Result := True Result := l_session_api.is_authenticating (a_response)
end end
end end
@@ -116,7 +114,7 @@ feature -- Access: router
if attached session_api as l_session_api then 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 ("/" + 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 ("/" + 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
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) handle_logout (api: CMS_API; a_session_api: CMS_SESSION_API ; req: WSF_REQUEST; res: WSF_RESPONSE)
local local
r: CMS_RESPONSE r: CMS_RESPONSE
l_cookie: WSF_COOKIE
tok: STRING
do do
tok := a_session_api.session_token if attached api.user as l_user then
if a_session_api.process_user_logout (l_user, req, res)
attached {WSF_STRING} req.cookie (tok) as l_cookie_token and then create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
attached api.user as l_user else
then -- Not loggued in ... redirect to home
-- 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
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
r.set_status_code ({HTTP_CONSTANTS}.found) 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 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 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 local
r: CMS_RESPONSE r: CMS_RESPONSE
l_token: STRING
l_cookie: WSF_COOKIE
do do
if 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 ("username") as l_username and then
attached {WSF_STRING} req.form_parameter ("password") as l_password attached {WSF_STRING} req.form_parameter ("password") as l_password
then then
@@ -204,18 +196,7 @@ feature {NONE} -- Implementation: routes
api.user_api.is_valid_credential (l_username.value, l_password.value) and then 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 attached api.user_api.user_by_name (l_username.value) as l_user
then then
l_token := generate_token a_session_api.process_user_login (l_user, req, res)
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)
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
if if
@@ -295,23 +276,4 @@ feature {NONE} -- Block views
end end
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 end