Fixed various CMS_MODULE.install, by not marked module installed if an error occurred!

Improved Auth related module implementation by having a way to change settings like token, max age.
  - use CMS_SETUP.site_id and related "auth.$module.token" ... configuration values.
  - removed related CMS_..._CONSTANTS classes.

For auth session module, use auth_session as table name, and use VARCHAR(64).
Extracted sql from blog module, and store it under site/scripts/install.sql .
Renamed a few $modulename.sql as install.sql
This commit is contained in:
2016-01-27 18:22:20 +01:00
parent d3b485f4d3
commit 41ac45d07b
28 changed files with 396 additions and 414 deletions

View File

@@ -7,11 +7,12 @@ set ROC_CMS_DIR=%~dp0
%ROC_CMD% install --module ..\..\modules\basic_auth --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\blog --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\contact --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\feed_aggregator --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\google_search --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\node --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\oauth20 --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\openid --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\recent_changes --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\feed_aggregator --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\google_search --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\taxonomy --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\seo --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\session_auth --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\taxonomy --dir %ROC_CMS_DIR%

View File

@@ -70,8 +70,9 @@ CREATE TABLE tb_demo(
api.logger.put_error ("Could not initialize database for demo module", generating_type)
end
end
Precursor {CMS_MODULE}(api)
end
-- For this demo, be flexible, and do not required sql.
Precursor {CMS_MODULE}(api)
end
feature -- Access: router

View File

@@ -4,9 +4,13 @@ root-dir=site/www
#modules-dir=site/modules
[site]
# General token that could be use for cookies, and related.
id=_EIFFEL_CMS_
# Name of the site, for the title, and eventual message.
name=Eiffel CMS
# Properties used for SEO.
property[headline]=Eiffel CMS -- the demo
property[description]=Demo for Eiffel ROC CMS.
property[keywords]=eiffel,cms,demo
@@ -43,6 +47,14 @@ output=site\db\mailer.log
[blocks]
@include=blocks.ini
[auth]
# token, default is $site.id or built-in.
#token=_ROC_AUTH_TOKEN_
#session.token=
#session.max_age=86400
#openid.token=
#oauth.token=
[admin]
# CMS Installation, are accessible by "all", "none" or uppon "permission". (default is none)
installation_access=all

View File

@@ -0,0 +1,6 @@
CREATE TABLE blog_post_nodes(
`nid` INTEGER NOT NULL CHECK("nid">=0),
`revision` INTEGER NOT NULL,
`tags` VARCHAR(255),
CONSTRAINT PK_nid_revision PRIMARY KEY (nid,revision)
);

View File

@@ -0,0 +1,9 @@
CREATE TABLE auth_session (
`uid` INTEGER PRIMARY KEY NOT NULL CHECK(`uid`>=0),
`access_token` VARCHAR(64) NOT NULL,
`created` DATETIME NOT NULL,
CONSTRAINT `uid` UNIQUE(`uid`),
CONSTRAINT `access_token` UNIQUE(`access_token`)
);

View File

@@ -1,11 +0,0 @@
CREATE TABLE session_auth (
`uid` INTEGER PRIMARY KEY NOT NULL CHECK(`uid`>=0),
`access_token` TEXT NOT NULL,
`created` DATETIME NOT NULL,
CONSTRAINT `uid`
UNIQUE(`uid`),
CONSTRAINT `access_token`
UNIQUE(`access_token`)
);

View File

@@ -78,27 +78,17 @@ feature {CMS_API} -- Module Initialization
feature {CMS_API} -- Module management
install (api: CMS_API)
local
sql: STRING
install (a_api: CMS_API)
do
-- Schema
if attached api.storage.as_sql_storage as l_sql_storage then
if not l_sql_storage.sql_table_exists ("blog_post_nodes") then
sql := "[
CREATE TABLE blog_post_nodes(
`nid` INTEGER NOT NULL CHECK("nid">=0),
`revision` INTEGER NOT NULL,
`tags` VARCHAR(255),
CONSTRAINT PK_nid_revision PRIMARY KEY (nid,revision)
);
]"
l_sql_storage.sql_execute_script (sql, Void)
if l_sql_storage.has_error then
api.logger.put_error ("Could not initialize database for blog module", generating_type)
end
if attached a_api.storage.as_sql_storage as l_sql_storage then
l_sql_storage.sql_execute_file_script (a_api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended ("install.sql")), Void)
if l_sql_storage.has_error then
a_api.logger.put_error ("Could not initialize database for module [" + name + "]", generating_type)
else
Precursor {CMS_MODULE} (a_api)
end
Precursor (api)
end
end

View File

@@ -0,0 +1,6 @@
CREATE TABLE blog_post_nodes(
`nid` INTEGER NOT NULL CHECK("nid">=0),
`revision` INTEGER NOT NULL,
`tags` VARCHAR(255),
CONSTRAINT PK_nid_revision PRIMARY KEY (nid,revision)
);

View File

@@ -15,7 +15,6 @@ inherit
module_api as contact_api
redefine
setup_hooks,
is_installed,
install,
initialize,
contact_api
@@ -53,7 +52,6 @@ feature {NONE} -- Initialization
package := "messaging"
end
feature -- Access
name: STRING = "contact"
@@ -86,14 +84,6 @@ feature {CMS_API} -- Module Initialization
feature {CMS_API} -- Module management
is_installed (api: CMS_API): BOOLEAN
-- Is Current module installed?
local
ut: FILE_UTILITIES
do
Result := ut.directory_path_exists (file_system_storage_path (api))
end
install (api: CMS_API)
local
retried: BOOLEAN
@@ -102,6 +92,7 @@ feature {CMS_API} -- Module management
if not retried then
create d.make_with_path (file_system_storage_path (api))
d.recursive_create_dir
Precursor {CMS_MODULE}(api) -- Marked installed
end
rescue
retried := True

View File

@@ -127,8 +127,13 @@ feature {CMS_API} -- Module management
-- Schema
if attached a_api.storage.as_sql_storage as l_sql_storage then
l_sql_storage.sql_execute_file_script (a_api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended (name).appended_with_extension ("sql")), Void)
if l_sql_storage.has_error then
a_api.logger.put_error ("Could not initialize database for module [" + name + "]", generating_type)
else
Precursor {CMS_MODULE} (a_api)
end
end
Precursor {CMS_MODULE}(a_api)
end
feature {CMS_API} -- Access: API

View File

@@ -1,7 +1,7 @@
note
description: "[
API to manage CMS User OAuth authentication.
]"
API to manage CMS User OAuth authentication.
]"
date: "$Date$"
revision: "$Revision$"
@@ -20,19 +20,36 @@ feature {NONE} -- Initialization
make_with_storage (a_api: CMS_API; a_oauth_storage: CMS_OAUTH_20_STORAGE_I)
-- Create an object with api `a_api' and storage `a_oauth_storage'.
local
s: detachable READABLE_STRING_8
do
oauth_20_storage := a_oauth_storage
make (a_api)
-- Initialize session related settings.
s := a_api.setup.string_8_item ("auth.oauth.token")
if s = Void then
s := a_api.setup.site_id + default_session_token_suffix
end
create session_token.make_from_string (s)
ensure
oauht_20_storage_set: oauth_20_storage = a_oauth_storage
oauth_20_storage_set: oauth_20_storage = a_oauth_storage
end
feature {CMS_MODULE} -- Access: User oauth storage.
feature {CMS_MODULE} -- Access: Oauth storage.
oauth_20_storage: CMS_OAUTH_20_STORAGE_I
-- storage interface.
feature -- Access: User Oauth20
feature -- Access: tokens
default_session_token_suffix: STRING = "_OAUTH_TOKEN_"
-- Default value for `session_auth_token'.
session_token: IMMUTABLE_STRING_8
-- Name of Cookie used to keep the session info.
feature -- Access: Oauth20
user_oauth2_by_id (a_uid: like {CMS_USER}.id; a_consumer: READABLE_STRING_GENERAL): detachable CMS_USER
-- Retrieve a user by id `a_uid' for the consumer `a_consumer', if any.

View File

@@ -1,21 +0,0 @@
note
description: "Summary description for {CMS_OAUTH_20_CONSTANTS}."
date: "$Date$"
revision: "$Revision$"
class
CMS_OAUTH_20_CONSTANTS
feature -- Access
oauth_session: STRING = "EWF_ROC_OAUTH_TOKEN_"
-- Name of Cookie used to keep the session info.
-- FIXME: make this configurable.
oauth_callback: STRING = "callback"
-- Callback parameter.
oauth_code: STRING = "code"
-- Code query parameter.
end

View File

@@ -1,5 +1,7 @@
note
description: "Generic OAuth Module supporting authentication using different providers."
description: "[
Generic OAuth Module supporting authentication using different providers.
]"
date: "$Date: 2015-05-20 06:50:50 -0300 (mi. 20 de may. de 2015) $"
revision: "$Revision: 97328 $"
@@ -9,16 +11,15 @@ class
inherit
CMS_MODULE
rename
module_api as user_oauth_api
module_api as oauth20_api
redefine
filters,
setup_hooks,
initialize,
install,
user_oauth_api
oauth20_api
end
CMS_HOOK_BLOCK
CMS_HOOK_AUTO_REGISTER
@@ -38,7 +39,6 @@ inherit
CMS_REQUEST_UTIL
create
make
@@ -66,24 +66,24 @@ feature {CMS_API} -- Module Initialization
initialize (a_api: CMS_API)
-- <Precursor>
local
l_user_auth_api: like user_oauth_api
l_user_auth_storage: CMS_OAUTH_20_STORAGE_I
l_oauth20_api: like oauth20_api
l_auth_storage: CMS_OAUTH_20_STORAGE_I
do
Precursor (a_api)
-- Storage initialization
if attached a_api.storage.as_sql_storage as l_storage_sql then
create {CMS_OAUTH_20_STORAGE_SQL} l_user_auth_storage.make (l_storage_sql)
create {CMS_OAUTH_20_STORAGE_SQL} l_auth_storage.make (l_storage_sql)
else
-- FIXME: in case of NULL storage, should Current be disabled?
create {CMS_OAUTH_20_STORAGE_NULL} l_user_auth_storage
create {CMS_OAUTH_20_STORAGE_NULL} l_auth_storage
end
-- API initialization
create l_user_auth_api.make_with_storage (a_api, l_user_auth_storage)
user_oauth_api := l_user_auth_api
create l_oauth20_api.make_with_storage (a_api, l_auth_storage)
oauth20_api := l_oauth20_api
ensure then
user_oauth_api_set: user_oauth_api /= Void
user_oauth_api_set: oauth20_api /= Void
end
feature {CMS_API} -- Module management
@@ -94,52 +94,56 @@ feature {CMS_API} -- Module management
do
-- Schema
if attached api.storage.as_sql_storage as l_sql_storage then
if not l_sql_storage.sql_table_exists ("oauth2_consumers") then
--| Schema
l_sql_storage.sql_execute_file_script (api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended ("oauth2_consumers.sql")), Void)
l_sql_storage.sql_execute_file_script (api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended ("oauth2_consumers.sql")), Void)
if l_sql_storage.has_error then
api.logger.put_error ("Could not initialize database for oauth_20 module", generating_type)
end
if l_sql_storage.has_error then
api.logger.put_error ("Could not initialize database for module [" + name + "]", generating_type)
else
-- TODO workaround.
l_sql_storage.sql_execute_file_script (api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended ("oauth2_consumers_initialize.sql")), Void)
end
if l_sql_storage.has_error then
api.logger.put_error ("Could not initialize oauth2_consumers for module [" + name + "]", generating_type)
else
-- TODO workaround, until we have an admin module
l_sql_storage.sql_query ("SELECT name FROM oauth2_consumers;", Void)
if l_sql_storage.has_error then
api.logger.put_error ("Could not initialize database for different consumers", generating_type)
else
from
l_sql_storage.sql_start
create {ARRAYED_LIST [STRING]} l_consumers.make (2)
until
l_sql_storage.sql_after
loop
if attached l_sql_storage.sql_read_string (1) as l_name then
l_consumers.force ("oauth2_" + l_name)
end
l_sql_storage.sql_forth
end
l_sql_storage.sql_finalize
-- TODO workaround, until we have an admin module
l_sql_storage.sql_query ("SELECT name FROM oauth2_consumers;", Void)
if l_sql_storage.has_error then
api.logger.put_error ("Could not initialize database for differnent consumers", generating_type)
else
from
l_sql_storage.sql_start
create {ARRAYED_LIST [STRING]} l_consumers.make (2)
until
l_sql_storage.sql_after
loop
if attached l_sql_storage.sql_read_string (1) as l_name then
l_consumers.force ("oauth2_" + l_name)
end
l_sql_storage.sql_forth
end
l_sql_storage.sql_finalize
across l_consumers as ic loop
if not l_sql_storage.sql_table_exists (ic.item) then
if attached l_sql_storage.sql_script_content (api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended ("oauth2_table.sql.tpl"))) as sql then
-- FIXME: shouldn't we use a unique table for all oauth providers? or as it is .. one table per oauth provider?
sql.replace_substring_all ("$table_name", ic.item)
l_sql_storage.sql_execute_script (sql, Void)
across l_consumers as ic loop
if not l_sql_storage.sql_table_exists (ic.item) then
if attached l_sql_storage.sql_script_content (api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended ("oauth2_table.sql.tpl"))) as sql then
-- FIXME: shouldn't we use a unique table for all oauth providers? or as it is .. one table per oauth provider?
sql.replace_substring_all ("$table_name", ic.item)
l_sql_storage.sql_execute_script (sql, Void)
end
end
end
end
l_sql_storage.sql_finalize
Precursor {CMS_MODULE}(api) -- Marked as installed.
end
end
l_sql_storage.sql_finalize
Precursor {CMS_MODULE}(api)
end
end
feature {CMS_API} -- Access: API
user_oauth_api: detachable CMS_OAUTH_20_API
oauth20_api: detachable CMS_OAUTH_20_API
-- <Precursor>
feature -- Filters
@@ -148,8 +152,8 @@ feature -- Filters
-- Possibly list of Filter's module.
do
create {ARRAYED_LIST [WSF_FILTER]} Result.make (1)
if attached user_oauth_api as l_user_oauth_api then
Result.extend (create {CMS_OAUTH_20_FILTER}.make (a_api, l_user_oauth_api))
if attached oauth20_api as l_oauth_api then
Result.extend (create {CMS_OAUTH_20_FILTER}.make (a_api, l_oauth_api))
end
end
@@ -173,20 +177,34 @@ feature -- Router
setup_router (a_router: WSF_ROUTER; a_api: CMS_API)
-- <Precursor>
do
if attached user_oauth_api as l_user_oauth_api then
configure_web (a_api, l_user_oauth_api, a_router)
if attached oauth20_api as l_oauth_api then
a_router.handle ("/account/roc-oauth-login",
create {WSF_URI_AGENT_HANDLER}.make (agent handle_login (a_api, ?, ?)), a_router.methods_head_get)
a_router.handle ("/account/roc-oauth-logout",
create {WSF_URI_AGENT_HANDLER}.make (agent handle_logout (a_api, l_oauth_api, ?, ?)),
a_router.methods_get_post)
a_router.handle ("/account/login-with-oauth/{" + oauth_callback_path_parameter + "}",
create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_login_with_oauth (a_api, l_oauth_api, ?, ?)),
a_router.methods_get_post)
a_router.handle ("/account/oauth-callback/{" + oauth_callback_path_parameter + "}",
create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_callback_oauth (a_api, l_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, l_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, l_oauth_api, ?, ?)),
a_router.methods_post)
end
end
configure_web (a_api: CMS_API; a_user_oauth_api: CMS_OAUTH_20_API; a_router: WSF_ROUTER)
do
a_router.handle ("/account/roc-oauth-login", create {WSF_URI_AGENT_HANDLER}.make (agent handle_login (a_api, ?, ?)), a_router.methods_head_get)
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
oauth_callback_path_parameter: STRING = "callback"
-- Callback path parameter.
oauth_code_query_parameter: STRING = "code"
-- Code query parameter, specific to OAuth protocol.
-- FIXME: should we have a way to change this value?
-- : if a OAuth provider is not using "code" query name.
feature -- Hooks configuration
@@ -205,7 +223,8 @@ feature -- Hooks
do
if
attached a_response.user as u and then
attached {WSF_STRING} a_response.request.cookie ({CMS_OAUTH_20_CONSTANTS}.oauth_session)
attached oauth20_api as l_oauth20_api and then
attached a_response.request.cookie (l_oauth20_api.session_token)
then
a_value.force ("account/roc-oauth-logout", "auth_login_strategy")
end
@@ -220,7 +239,8 @@ feature -- Hooks
do
if
attached a_response.user as u and then
attached {WSF_STRING} a_response.request.cookie ({CMS_OAUTH_20_CONSTANTS}.oauth_session) as l_roc_auth_session_token
attached oauth20_api as l_oauth20_api and then
attached {WSF_STRING} a_response.request.cookie (l_oauth20_api.session_token) as l_roc_auth_session_token
then
across
a_menu_system.primary_menu.items as ic
@@ -297,17 +317,17 @@ feature -- Hooks
r.execute
end
handle_logout (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE)
handle_logout (api: CMS_API; a_oauth20_api: CMS_OAUTH_20_API; req: WSF_REQUEST; res: WSF_RESPONSE)
local
r: CMS_RESPONSE
l_cookie: WSF_COOKIE
do
if
attached {WSF_STRING} req.cookie ({CMS_OAUTH_20_CONSTANTS}.oauth_session) as l_cookie_token and then
attached {CMS_USER} current_user (req) as l_user
attached {CMS_USER} current_user (req) as l_user and then
attached {WSF_STRING} req.cookie (a_oauth20_api.session_token) as l_cookie_token
then
-- Logout OAuth
create l_cookie.make ({CMS_OAUTH_20_CONSTANTS}.oauth_session, l_cookie_token.value)
create l_cookie.make (a_oauth20_api.session_token, l_cookie_token.value)
l_cookie.set_path ("/")
l_cookie.set_max_age (-1)
res.add_cookie (l_cookie)
@@ -329,7 +349,7 @@ feature {NONE} -- Associate
l_associated: LIST [STRING]
l_not_associated: LIST [STRING]
do
if attached user_oauth_api as l_oauth_api then
if attached oauth20_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
@@ -379,7 +399,7 @@ feature {NONE} -- Block views
l_tpl_block.set_value (ic.item, ic.key)
end
if
attached user_oauth_api as l_auth_api and then
attached oauth20_api as l_auth_api and then
attached l_auth_api.oauth2_consumers as l_list
then
l_tpl_block.set_value (l_list, "oauth_consumers")
@@ -402,7 +422,7 @@ feature -- OAuth2 Login with Provider
l_oauth: CMS_OAUTH_20_WORKFLOW
do
if
attached {WSF_STRING} req.path_parameter ({CMS_OAUTH_20_CONSTANTS}.oauth_callback) as p_consumer and then
attached {WSF_STRING} req.path_parameter (oauth_callback_path_parameter) as p_consumer and then
attached {CMS_OAUTH_20_CONSUMER} a_oauth_api.oauth_consumer_by_name (p_consumer.value) as l_consumer
then
create l_oauth.make (req.server_url, l_consumer)
@@ -422,7 +442,7 @@ feature -- OAuth2 Login with Provider
end
end
handle_callback_oauth (api: CMS_API; a_user_oauth_api: CMS_OAUTH_20_API; req: WSF_REQUEST; res: WSF_RESPONSE)
handle_callback_oauth (api: CMS_API; a_oauth_api: CMS_OAUTH_20_API; req: WSF_REQUEST; res: WSF_RESPONSE)
local
r: CMS_RESPONSE
l_auth: CMS_OAUTH_20_WORKFLOW
@@ -432,9 +452,9 @@ feature -- OAuth2 Login with Provider
l_cookie: WSF_COOKIE
es: CMS_AUTHENTICATION_EMAIL_SERVICE
do
if attached {WSF_STRING} req.path_parameter ({CMS_OAUTH_20_CONSTANTS}.oauth_callback) as l_callback and then
attached {CMS_OAUTH_20_CONSUMER} a_user_oauth_api.oauth_consumer_by_callback (l_callback.value) as l_consumer and then
attached {WSF_STRING} req.query_parameter ({CMS_OAUTH_20_CONSTANTS}.oauth_code) as l_code
if attached {WSF_STRING} req.path_parameter (oauth_callback_path_parameter) as l_callback and then
attached {CMS_OAUTH_20_CONSUMER} a_oauth_api.oauth_consumer_by_callback (l_callback.value) as l_consumer and then
attached {WSF_STRING} req.query_parameter (oauth_code_query_parameter) as l_code
then
create l_auth.make (req.server_url, l_consumer)
l_auth.sign_request (l_code.value)
@@ -452,20 +472,20 @@ 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_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 )
a_oauth_api.update_user_oauth2 (l_access_token.token, l_user_profile, p_user, l_consumer.name )
else
-- create a oauth entry
a_user_oauth_api.new_user_oauth2 (l_access_token.token, l_user_profile, p_user, l_consumer.name )
a_oauth_api.new_user_oauth2 (l_access_token.token, l_user_profile, p_user, l_consumer.name )
end
create l_cookie.make ({CMS_OAUTH_20_CONSTANTS}.oauth_session, l_access_token.token)
create l_cookie.make (a_oauth_api.session_token, l_access_token.token)
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)
elseif attached a_oauth_api.user_oauth2_by_email (l_email, l_consumer.name) as p_user then
a_oauth_api.update_user_oauth2 (l_access_token.token, l_user_profile, p_user, l_consumer.name )
create l_cookie.make (a_oauth_api.session_token, l_access_token.token)
l_cookie.set_max_age (l_access_token.expires_in)
l_cookie.set_path ("/")
res.add_cookie (l_cookie)
@@ -482,8 +502,8 @@ feature -- OAuth2 Login with Provider
l_user_api.new_user (l_user)
-- Add oauth entry
a_user_oauth_api.new_user_oauth2 (l_access_token.token, l_user_profile, l_user, l_consumer.name )
create l_cookie.make ({CMS_OAUTH_20_CONSTANTS}.oauth_session, l_access_token.token)
a_oauth_api.new_user_oauth2 (l_access_token.token, l_user_profile, l_user, l_consumer.name )
create l_cookie.make (a_oauth_api.session_token, l_access_token.token)
l_cookie.set_max_age (l_access_token.expires_in)
l_cookie.set_path ("/")
res.add_cookie (l_cookie)
@@ -499,9 +519,7 @@ feature -- OAuth2 Login with Provider
r.set_redirection (r.front_page_url)
r.execute
end
end
end
handle_associate (api: CMS_API; a_oauth_api: CMS_OAUTH_20_API; req: WSF_REQUEST; res: WSF_RESPONSE)
@@ -518,14 +536,13 @@ feature -- OAuth2 Login with Provider
then
l_user.set_email (l_email.value)
a_oauth_api.new_user_oauth2 ("none", "none", l_user, l_consumer.value )
-- TODO send email?
-- 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

View File

@@ -1,6 +1,7 @@
note
description: "[
Extracts an OAuth2 token from the incoming request (cookie) and uses it to populate the user (or cms user context)
Extracts an OAuth2 token from the incoming request (cookie) and
uses it to populate the user (or cms user context).
]"
date: "$Date$"
revision: "$Revision$"
@@ -10,6 +11,7 @@ class
inherit
WSF_URI_TEMPLATE_HANDLER
CMS_HANDLER
rename
make as make_handler
@@ -25,10 +27,10 @@ feature {NONE} -- Initialization
make (a_api: CMS_API; a_user_oauth_api: CMS_OAUTH_20_API)
do
make_handler (a_api)
user_oauth_api := a_user_oauth_api
oauth_api := a_user_oauth_api
end
user_oauth_api: CMS_OAUTH_20_API
oauth_api: CMS_OAUTH_20_API
feature -- Basic operations
@@ -38,9 +40,9 @@ feature -- Basic operations
api.logger.put_debug (generator + ".execute ", Void)
-- A valid user
if
attached {WSF_STRING} req.cookie ({CMS_OAUTH_20_CONSTANTS}.oauth_session) as l_roc_auth_session_token
attached {WSF_STRING} req.cookie (oauth_api.session_token) as l_roc_auth_session_token
then
if attached user_oauth_api.user_oauth2_without_consumer_by_token (l_roc_auth_session_token.value) as l_user then
if attached oauth_api.user_oauth2_without_consumer_by_token (l_roc_auth_session_token.value) as l_user then
set_current_user (req, l_user)
else
api.logger.put_error (generator + ".execute login_valid failed for: " + l_roc_auth_session_token.value , Void)

View File

@@ -7,6 +7,7 @@ note
class
CMS_OPENID_API
inherit
CMS_MODULE_API
@@ -19,9 +20,25 @@ feature {NONE} -- Initialization
make_with_storage (a_api: CMS_API; a_openid_storage: CMS_OPENID_STORAGE_I)
-- Create an object with api `a_api' and storage `a_openid_storage'.
local
s: detachable READABLE_STRING_8
do
openid_storage := a_openid_storage
make (a_api)
-- Initialize openid related settings.
s := a_api.setup.string_8_item ("auth.openid.token")
if s = Void then
s := a_api.setup.site_id + default_session_token_suffix
end
create session_token.make_from_string (s)
s := a_api.setup.string_8_item ("auth.openid.max_age")
if s /= Void and then s.is_integer then
session_max_age := s.to_integer
else
session_max_age := 3600 --| one hour: *60(min) *60(sec)
end
ensure
openid_storage_set: openid_storage = a_openid_storage
end
@@ -31,6 +48,16 @@ feature {CMS_MODULE} -- Access: User openid storage.
openid_storage: CMS_OPENID_STORAGE_I
-- storage interface.
feature -- Access: token
default_session_token_suffix: STRING = "_OPENID_TOKEN_"
session_token: IMMUTABLE_STRING_8
-- Name of Cookie used to keep the session info.
session_max_age: INTEGER
-- Max age.
feature -- Access: User Openid
user_openid_by_userid_identity (a_uid: like {CMS_USER}.id; a_identity: READABLE_STRING_GENERAL): detachable CMS_USER

View File

@@ -1,16 +0,0 @@
note
description: "Summary description for {CMS_OPENID_CONSTANTS}."
date: "$Date$"
revision: "$Revision$"
class
CMS_OPENID_CONSTANTS
feature -- Access
openid_session: STRING = "EWF_ROC_OPENID_TOKEN_"
-- Name of Cookie used to keep the session info.
-- FIXME: make this configurable.
consumer: STRING = "consumer"
end

View File

@@ -11,13 +11,13 @@ class
inherit
CMS_MODULE
rename
module_api as user_openid_api
module_api as openid_api
redefine
filters,
setup_hooks,
initialize,
install,
user_openid_api
openid_api
end
@@ -68,7 +68,7 @@ feature {CMS_API} -- Module Initialization
initialize (a_api: CMS_API)
-- <Precursor>
local
l_openid_api: like user_openid_api
l_openid_api: like openid_api
l_openid_storage: CMS_OPENID_STORAGE_I
do
Precursor (a_api)
@@ -83,9 +83,9 @@ feature {CMS_API} -- Module Initialization
-- API initialization
create l_openid_api.make_with_storage (a_api, l_openid_storage)
user_openid_api := l_openid_api
openid_api := l_openid_api
ensure then
user_opend_api_set: user_openid_api /= Void
user_opend_api_set: openid_api /= Void
end
feature {CMS_API} -- Module management
@@ -94,30 +94,33 @@ feature {CMS_API} -- Module management
do
-- Schema
if attached api.storage.as_sql_storage as l_sql_storage then
if not l_sql_storage.sql_table_exists ("openid_consumers") then
--| Schema
l_sql_storage.sql_execute_file_script (api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended ("openid_consumers.sql")), Void)
l_sql_storage.sql_execute_file_script (api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended ("openid_consumers.sql")), Void)
if l_sql_storage.has_error then
api.logger.put_error ("Could not initialize database for openid module", generating_type)
end
if l_sql_storage.has_error then
api.logger.put_error ("Could not initialize database for module [" + name + "]", generating_type)
else
-- TODO workaround.
l_sql_storage.sql_execute_file_script (api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended ("openid_consumers_initialize.sql")), Void)
end
-- TODO workaround, until we have an admin module
if l_sql_storage.has_error then
api.logger.put_error ("Could not initialize database for different consumers", generating_type)
else
l_sql_storage.sql_execute_file_script (api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended ("openid_items.sql")),Void)
-- TODO workaround, until we have an admin module
if l_sql_storage.has_error then
api.logger.put_error ("Could not initialize openid consumer table for module [" + name + "]", generating_type)
else
l_sql_storage.sql_execute_file_script (api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended ("openid_items.sql")),Void)
if l_sql_storage.has_error then
api.logger.put_error ("Could not initialize openid items for module [" + name + "]", generating_type)
else
Precursor {CMS_MODULE}(api) -- Mark it installed.
end
end
end
Precursor {CMS_MODULE}(api)
end
end
feature {CMS_API} -- Access: API
user_openid_api: detachable CMS_OPENID_API
openid_api: detachable CMS_OPENID_API
-- <Precursor>
feature -- Filters
@@ -125,9 +128,9 @@ feature -- Filters
filters (a_api: CMS_API): detachable LIST [WSF_FILTER]
-- Possibly list of Filter's module.
do
if attached user_openid_api as l_user_openid_api then
if attached openid_api as l_openid_api then
create {ARRAYED_LIST [WSF_FILTER]} Result.make (1)
Result.extend (create {CMS_OPENID_FILTER}.make (a_api, l_user_openid_api))
Result.extend (create {CMS_OPENID_FILTER}.make (a_api, l_openid_api))
end
end
@@ -151,18 +154,24 @@ feature -- Router
setup_router (a_router: WSF_ROUTER; a_api: CMS_API)
-- <Precursor>
do
if attached user_openid_api as l_user_openid_api then
configure_web (a_api, l_user_openid_api, a_router)
if attached openid_api as l_openid_api then
a_router.handle ("/account/roc-openid-login",
create {WSF_URI_AGENT_HANDLER}.make (agent handle_openid_login (a_api, ?, ?)),
a_router.methods_get_post)
a_router.handle ("/account/roc-openid-logout",
create {WSF_URI_AGENT_HANDLER}.make (agent handle_logout (a_api, l_openid_api, ?, ?)),
a_router.methods_get_post)
a_router.handle ("/account/login-with-openid/{" + openid_consumer_path_parameter + "}",
create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_login_with_openid (a_api, l_openid_api, ?, ?)),
a_router.methods_get_post)
a_router.handle ("/account/openid-callback",
create {WSF_URI_AGENT_HANDLER}.make (agent handle_callback_openid (a_api, l_openid_api, ?, ?)),
a_router.methods_get_post)
end
end
configure_web (a_api: CMS_API; a_user_openid_api: CMS_OPENID_API; a_router: WSF_ROUTER)
do
a_router.handle ("/account/roc-openid-login", create {WSF_URI_AGENT_HANDLER}.make (agent handle_openid_login (a_api, ?, ?)), a_router.methods_get_post)
a_router.handle ("/account/roc-openid-logout", create {WSF_URI_AGENT_HANDLER}.make (agent handle_logout (a_api, ?, ?)), a_router.methods_get_post)
a_router.handle ("/account/login-with-openid/{consumer}", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_login_with_openid (a_api,a_user_openid_api, ?, ?)), a_router.methods_get_post)
a_router.handle ("/account/openid-callback", create {WSF_URI_AGENT_HANDLER}.make (agent handle_callback_openid (a_api, a_user_openid_api, ?, ?)), a_router.methods_get_post)
end
openid_consumer_path_parameter: STRING = "consumer"
-- Consumer path parameter name.
feature -- Hooks configuration
@@ -181,7 +190,8 @@ feature -- Hooks
do
if
attached a_response.user as u and then
attached {WSF_STRING} a_response.request.cookie ({CMS_OPENID_CONSTANTS}.openid_session)
attached openid_api as l_openid_api and then
attached {WSF_STRING} a_response.request.cookie (l_openid_api.session_token)
then
a_value.force ("account/roc-openid-logout", "auth_login_strategy")
end
@@ -196,7 +206,8 @@ feature -- Hooks
do
if
attached a_response.user as u and then
attached {WSF_STRING} a_response.request.cookie ({CMS_OPENID_CONSTANTS}.openid_session) as l_roc_auth_session_token
attached openid_api as l_openid_api and then
attached {WSF_STRING} a_response.request.cookie (l_openid_api.session_token) as l_roc_auth_session_token
then
across
a_menu_system.primary_menu.items as ic
@@ -280,17 +291,17 @@ feature -- Hooks
end
end
handle_logout (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE)
handle_logout (api: CMS_API; a_openid_api: CMS_OPENID_API; req: WSF_REQUEST; res: WSF_RESPONSE)
local
r: CMS_RESPONSE
l_cookie: WSF_COOKIE
do
if
attached {WSF_STRING} req.cookie ({CMS_OPENID_CONSTANTS}.openid_session) as l_cookie_token and then
attached {CMS_USER} current_user (req) as l_user
attached {CMS_USER} current_user (req) as l_user and then
attached {WSF_STRING} req.cookie (a_openid_api.session_token) as l_cookie_token
then
-- Logout OAuth
create l_cookie.make ({CMS_OPENID_CONSTANTS}.openid_session, l_cookie_token.value)
create l_cookie.make (a_openid_api.session_token, l_cookie_token.value)
l_cookie.set_path ("/")
l_cookie.set_max_age (-1)
res.add_cookie (l_cookie)
@@ -339,7 +350,7 @@ feature {NONE} -- Block views
l_tpl_block.set_value (ic.item, ic.key)
end
if
attached user_openid_api as l_openid_api and then
attached openid_api as l_openid_api and then
attached l_openid_api.openid_consumers as l_list
then
l_tpl_block.set_value (l_list, "openid_consumers")
@@ -356,14 +367,16 @@ feature {NONE} -- Block views
feature -- Openid Login
handle_login_with_openid (api: CMS_API; a_oauth_api: CMS_OPENID_API; req: WSF_REQUEST; res: WSF_RESPONSE)
handle_login_with_openid (api: CMS_API; a_openid_api: CMS_OPENID_API; req: WSF_REQUEST; res: WSF_RESPONSE)
local
r: CMS_RESPONSE
b: STRING
o: OPENID_CONSUMER
do
if attached {WSF_STRING} req.path_parameter ({CMS_OPENID_CONSTANTS}.consumer) as p_openid and then
attached {CMS_OPENID_CONSUMER} a_oauth_api.openid_consumer_by_name (p_openid.value) as l_oc then
if
attached {WSF_STRING} req.path_parameter (openid_consumer_path_parameter) as p_openid and then
attached {CMS_OPENID_CONSUMER} a_openid_api.openid_consumer_by_name (p_openid.value) as l_oc
then
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
create b.make_empty
b.append ("Check openID: " + p_openid.value)
@@ -383,7 +396,7 @@ feature -- Openid Login
end
end
handle_callback_openid (api: CMS_API; a_user_openid_api: CMS_OPENID_API; req: WSF_REQUEST; res: WSF_RESPONSE)
handle_callback_openid (api: CMS_API; a_openid_api: CMS_OPENID_API; req: WSF_REQUEST; res: WSF_RESPONSE)
local
r: CMS_RESPONSE
l_user_api: CMS_USER_API
@@ -410,14 +423,14 @@ feature -- Openid Login
l_user_api := api.user_api
if attached l_user_api.user_by_email (l_email) as p_user then
-- User with email exist
if attached a_user_openid_api.user_openid_by_userid_identity (p_user.id, l_identity) then
if attached a_openid_api.user_openid_by_userid_identity (p_user.id, l_identity) then
-- Update openid entry?
else
-- create a oauth entry
a_user_openid_api.new_user_openid (l_identity,p_user)
a_openid_api.new_user_openid (l_identity,p_user)
end
create l_cookie.make ({CMS_OPENID_CONSTANTS}.openid_session, l_identity)
l_cookie.set_max_age (3600)
create l_cookie.make (a_openid_api.session_token, l_identity)
l_cookie.set_max_age (a_openid_api.session_max_age)
l_cookie.set_path ("/")
res.add_cookie (l_cookie)
else
@@ -434,9 +447,9 @@ feature -- Openid Login
l_user_api.new_user (l_user)
-- Add oauth entry
a_user_openid_api.new_user_openid (l_identity, l_user )
create l_cookie.make ({CMS_OPENID_CONSTANTS}.openid_session, l_identity)
l_cookie.set_max_age (3600)
a_openid_api.new_user_openid (l_identity, l_user )
create l_cookie.make (a_openid_api.session_token, l_identity)
l_cookie.set_max_age (a_openid_api.session_max_age)
l_cookie.set_path ("/")
res.add_cookie (l_cookie)
@@ -475,37 +488,6 @@ feature {NONE} -- Token Generation
Result := l_token
end
feature {NONE} -- Implementation: date and time
http_date_format_to_date (s: READABLE_STRING_8): detachable DATE_TIME
local
d: HTTP_DATE
do
create d.make_from_string (s)
if not d.has_error then
Result := d.date_time
end
end
file_date (p: PATH): DATE_TIME
require
path_exists: (create {FILE_UTILITIES}).file_path_exists (p)
local
f: RAW_FILE
do
create f.make_with_path (p)
Result := timestamp_to_date (f.date)
end
timestamp_to_date (n: INTEGER): DATE_TIME
local
d: HTTP_DATE
do
create d.make_from_timestamp (n)
Result := d.date_time
end
note
copyright: "Copyright (c) 1984-2013, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"

View File

@@ -10,6 +10,7 @@ class
inherit
WSF_URI_TEMPLATE_HANDLER
CMS_HANDLER
rename
make as make_handler
@@ -22,32 +23,28 @@ create
feature {NONE} -- Initialization
make (a_api: CMS_API; a_user_openid_api: CMS_OPENID_API)
make (a_api: CMS_API; a_openid_api: CMS_OPENID_API)
do
make_handler (a_api)
user_openid_api := a_user_openid_api
openid_api := a_openid_api
end
user_openid_api: CMS_OPENID_API
openid_api: CMS_OPENID_API
feature -- Basic operations
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
-- Execute the filter.
do
api.logger.put_debug (generator + ".execute ", Void)
-- A valid user
if
attached {WSF_STRING} req.cookie ({CMS_OPENID_CONSTANTS}.openid_session) as l_roc_openid_session_token
attached {WSF_STRING} req.cookie (openid_api.session_token) as l_roc_openid_session_token
then
if attached user_openid_api.user_openid_by_identity (l_roc_openid_session_token.value) as l_user then
if attached openid_api.user_openid_by_identity (l_roc_openid_session_token.value) as l_user then
set_current_user (req, l_user)
else
api.logger.put_error (generator + ".execute login_valid failed for: " + l_roc_openid_session_token.value , Void)
end
else
api.logger.put_debug (generator + ".execute without authentication", Void)
end
execute_next (req, res)
end

View File

@@ -6,7 +6,6 @@ note
class
CMS_SESSION_API
inherit
CMS_MODULE_API
@@ -19,9 +18,25 @@ feature {NONE} -- Initialization
make_with_storage (a_api: CMS_API; a_session_auth_storage: CMS_SESSION_AUTH_STORAGE_I)
-- Create an object with api `a_api' and storage `a_session_auth_storage'.
local
s: detachable READABLE_STRING_8
do
session_auth_storage := a_session_auth_storage
make (a_api)
-- Initialize session related settings.
s := a_api.setup.string_8_item ("auth.session.token")
if s = Void then
s := a_api.setup.site_id + default_session_token_suffix
end
create session_token.make_from_string (s)
s := a_api.setup.string_8_item ("auth.session.max_age")
if s /= Void and then s.is_integer then
session_max_age := s.to_integer
else
session_max_age := 86400 --| one day: 24(h) *60(min) *60(sec)
end
ensure
session_auth_storage_set: session_auth_storage = a_session_auth_storage
end
@@ -31,6 +46,17 @@ feature {CMS_MODULE} -- Access: User session storage.
session_auth_storage: CMS_SESSION_AUTH_STORAGE_I
-- storage interface.
feature -- Settings
default_session_token_suffix: STRING = "_SESSION_TOKEN_"
-- Default value for `session_token'.
session_token: IMMUTABLE_STRING_8
-- Token used for the session related cookies.
session_max_age: INTEGER
-- Value of the Max-Age, before the cookie expires.
feature -- Access
user_by_session_token (a_token: READABLE_STRING_32): detachable CMS_USER

View File

@@ -12,13 +12,13 @@ class
inherit
CMS_MODULE
rename
module_api as user_session_api
module_api as session_api
redefine
filters,
setup_hooks,
initialize,
install,
user_session_api
session_api
end
@@ -51,31 +51,29 @@ feature -- Access
name: STRING = "session_auth"
feature {CMS_API} -- Module Initialization
initialize (a_api: CMS_API)
-- <Precursor>
local
l_session_auth_api: like user_session_api
l_user_auth_storage: CMS_SESSION_AUTH_STORAGE_I
l_session_auth_api: like session_api
l_session_auth_storage: CMS_SESSION_AUTH_STORAGE_I
do
Precursor (a_api)
-- Storage initialization
if attached a_api.storage.as_sql_storage as l_storage_sql then
create {CMS_SESSION_AUTH_STORAGE_SQL} l_user_auth_storage.make (l_storage_sql)
create {CMS_SESSION_AUTH_STORAGE_SQL} l_session_auth_storage.make (l_storage_sql)
else
-- FIXME: in case of NULL storage, should Current be disabled?
create {CMS_SESSION_AUTH_STORAGE_NULL} l_user_auth_storage
create {CMS_SESSION_AUTH_STORAGE_NULL} l_session_auth_storage
end
-- API initialization
create l_session_auth_api.make_with_storage (a_api, l_user_auth_storage)
user_session_api := l_session_auth_api
create l_session_auth_api.make_with_storage (a_api, l_session_auth_storage)
session_api := l_session_auth_api
ensure then
session_auth_api_set: user_session_api /= Void
session_auth_api_set: session_api /= Void
end
feature {CMS_API} -- Module management
@@ -84,22 +82,19 @@ feature {CMS_API} -- Module management
do
-- Schema
if attached api.storage.as_sql_storage as l_sql_storage then
if not l_sql_storage.sql_table_exists ("session_auth") then
--| Schema
l_sql_storage.sql_execute_file_script (api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended ("session_auth_table.sql")), Void)
l_sql_storage.sql_execute_file_script (api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended ("install.sql")), Void)
if l_sql_storage.has_error then
api.logger.put_error ("Could not initialize database for session auth module", generating_type)
end
if l_sql_storage.has_error then
api.logger.put_error ("Could not initialize database for module [" + name + "]", generating_type)
else
Precursor {CMS_MODULE} (api) -- Mark it as installed.
end
l_sql_storage.sql_finalize
Precursor {CMS_MODULE}(api)
end
end
feature {CMS_API} -- Access: API
user_session_api: detachable CMS_SESSION_API
session_api: detachable CMS_SESSION_API
-- <Precursor>
feature -- Access: router
@@ -107,9 +102,11 @@ feature -- Access: router
setup_router (a_router: WSF_ROUTER; a_api: CMS_API)
-- <Precursor>
do
a_router.handle ("/account/roc-session-login", create {WSF_URI_AGENT_HANDLER}.make (agent handle_login(a_api, ?, ?)), a_router.methods_head_get)
a_router.handle ("/account/roc-session-logout", create {WSF_URI_AGENT_HANDLER}.make (agent handle_logout (a_api, ?, ?)), a_router.methods_get_post)
a_router.handle ("/account/login-with-session", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_login_with_session (a_api,user_session_api, ?, ?)), a_router.methods_get_post)
if attached session_api as l_session_api then
a_router.handle ("/account/roc-session-login", create {WSF_URI_AGENT_HANDLER}.make (agent handle_login (a_api, ?, ?)), a_router.methods_head_get)
a_router.handle ("/account/roc-session-logout", create {WSF_URI_AGENT_HANDLER}.make (agent handle_logout (a_api, l_session_api, ?, ?)), a_router.methods_get_post)
a_router.handle ("/account/login-with-session", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_login_with_session (a_api,session_api, ?, ?)), a_router.methods_get_post)
end
end
feature -- Access: filter
@@ -118,7 +115,7 @@ feature -- Access: filter
-- Possibly list of Filter's module.
do
create {ARRAYED_LIST [WSF_FILTER]} Result.make (1)
if attached user_session_api as l_session_api then
if attached session_api as l_session_api then
Result.extend (create {CMS_SESSION_AUTH_FILTER}.make (a_api, l_session_api))
end
end
@@ -133,17 +130,19 @@ feature {NONE} -- Implementation: routes
r.execute
end
handle_logout (api: CMS_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
r: CMS_RESPONSE
l_cookie: WSF_COOKIE
tok: STRING
do
tok := a_session_api.session_token
if
attached {WSF_STRING} req.cookie ({CMS_SESSION_CONSTANTS}.session_auth_token) as l_cookie_token and then
attached {WSF_STRING} req.cookie (tok) as l_cookie_token and then
attached {CMS_USER} current_user (req) as l_user
then
-- Logout Session
create l_cookie.make ({CMS_SESSION_CONSTANTS}.session_auth_token, l_cookie_token.value)
create l_cookie.make (tok, l_cookie_token.value) -- FIXME: unicode issue?
l_cookie.set_path ("/")
l_cookie.set_max_age (-1)
res.add_cookie (l_cookie)
@@ -179,8 +178,8 @@ feature {NONE} -- Implementation: routes
else
l_session_api.new_user_session_auth (l_token, l_user)
end
create l_cookie.make ({CMS_SESSION_CONSTANTS}.session_auth_token, l_token)
l_cookie.set_max_age ({CMS_SESSION_CONSTANTS}.session_max_age)
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)
set_current_user (req, l_user)
@@ -217,11 +216,11 @@ feature -- Hooks
do
if
attached a_response.user as u and then
attached {WSF_STRING} a_response.request.cookie ({CMS_SESSION_CONSTANTS}.session_auth_token)
attached session_api as l_session_api and then
attached a_response.request.cookie (l_session_api.session_token)
then
a_value.force ("account/roc-session-logout", "auth_login_strategy")
end
end
menu_system_alter (a_menu_system: CMS_MENU_SYSTEM; a_response: CMS_RESPONSE)
@@ -231,29 +230,32 @@ feature -- Hooks
lnk: CMS_LOCAL_LINK
lnk2: detachable CMS_LINK
do
if
attached a_response.user as u and then
attached {WSF_STRING} a_response.request.cookie ({CMS_SESSION_CONSTANTS}.session_auth_token)
then
across
a_menu_system.primary_menu.items as ic
until
lnk2 /= Void
loop
if ic.item.location.same_string ("account/roc-logout") or else ic.item.location.same_string ("basic_auth_logoff") then
lnk2 := ic.item
if attached a_response.user as u then
if
attached session_api as l_session_api and then
attached a_response.request.cookie (l_session_api.session_token)
then
across
a_menu_system.primary_menu.items as ic
until
lnk2 /= Void
loop
if
ic.item.location.same_string ("account/roc-logout")
or else ic.item.location.same_string ("basic_auth_logoff")
then
lnk2 := ic.item
end
end
if lnk2 /= Void then
a_menu_system.primary_menu.remove (lnk2)
end
create lnk.make ("Logout", "account/roc-session-logout" )
a_menu_system.primary_menu.extend (lnk)
end
if lnk2 /= Void then
a_menu_system.primary_menu.remove (lnk2)
end
create lnk.make ("Logout", "account/roc-session-logout" )
a_menu_system.primary_menu.extend (lnk)
else
if a_response.location.starts_with ("account/") then
create lnk.make ("Session", "account/roc-session-login")
a_response.add_to_primary_tabs (lnk)
end
elseif a_response.location.starts_with ("account/") then
create lnk.make ("Session", "account/roc-session-login")
a_response.add_to_primary_tabs (lnk)
end
end
@@ -327,7 +329,6 @@ feature {NONE} -- Block views
end
end
generate_token: STRING
-- Generate token to use in a Session.
local

View File

@@ -1,19 +0,0 @@
note
description: "Summary description for {CMS_SESSION_CONSTANTS}."
date: "$Date$"
revision: "$Revision$"
class
CMS_SESSION_CONSTANTS
feature
session_auth_token: STRING = "EWF_ROC_SESSION_AUTH_TOKEN_"
-- Name of Cookie used to keep the session info.
-- TODO add a config file to be able to customize this value via coniguration file.
session_max_age: INTEGER = 86400
-- Value of the Max-Age, before the cookie expires.
-- TODO add a config file to be able to customize this value via coniguration file.
end

View File

@@ -37,7 +37,7 @@ feature -- Access
password_hash (a_password, a_salt: STRING): STRING
-- Password hash based on password `a_password' and salt value `a_salt'.
do
Result := sha1_string (a_password + a_salt )
Result := sha1_string (a_password + a_salt)
end
feature {NONE} -- Implementation
@@ -77,7 +77,6 @@ feature {NONE} -- Implementation
feature -- Encoding
base_64 (bytes: SPECIAL [INTEGER_8]): STRING_8
-- Encodes a byte array into a STRING doing base64 encoding.
local

View File

@@ -23,31 +23,28 @@ create
feature {NONE} -- Initialization
make (a_api: CMS_API; a_session_oauth_api: CMS_SESSION_API)
make (a_api: CMS_API; a_session_api: CMS_SESSION_API)
do
make_handler (a_api)
session_oauth_api := a_session_oauth_api
session_api := a_session_api
end
session_oauth_api: CMS_SESSION_API
session_api: CMS_SESSION_API
feature -- Basic operations
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
-- Execute the filter.
do
api.logger.put_debug (generator + ".execute ", Void)
-- A valid user
if
attached {WSF_STRING} req.cookie ({CMS_SESSION_CONSTANTS}.session_auth_token) as l_roc_auth_session_token
attached {WSF_STRING} req.cookie (session_api.session_token) as l_roc_auth_session_token
then
if attached session_oauth_api.user_by_session_token (l_roc_auth_session_token.value) as l_user then
if attached session_api.user_by_session_token (l_roc_auth_session_token.value) as l_user then
set_current_user (req, l_user)
else
api.logger.put_error (generator + ".execute login_valid failed for: " + l_roc_auth_session_token.value , Void)
end
else
api.logger.put_debug (generator + ".execute without authentication", Void)
end
execute_next (req, res)
end

View File

@@ -7,7 +7,6 @@ class
CMS_SESSION_AUTH_STORAGE_SQL
inherit
CMS_SESSION_AUTH_STORAGE_I
CMS_PROXY_STORAGE_SQL
@@ -27,23 +26,27 @@ feature -- Access User
-- Retrieve user by token `a_token', if any.
local
l_parameters: STRING_TABLE [detachable ANY]
l_uid: INTEGER_64
do
error_handler.reset
write_information_log (generator + ".user_by_session_token")
create l_parameters.make (1)
l_parameters.put (a_token, "token")
sql_query (Select_user_by_token, l_parameters)
sql_query (Select_user_id_by_token, l_parameters)
if not has_error and not sql_after then
Result := fetch_user
l_uid := sql_read_integer_64 (1)
sql_forth
if not sql_after then
check
no_more_than_one: False
end
Result := Void
l_uid := 0
end
end
sql_finalize
if l_uid > 0 and attached api as l_cms_api then
Result := l_cms_api.user_api.user_by_id (l_uid)
end
end
has_user_token (a_user: CMS_USER): BOOLEAN
@@ -68,7 +71,7 @@ feature -- Access User
feature -- Change User token
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)
-- <Precursor>.
local
l_parameters: STRING_TABLE [detachable ANY]
@@ -102,54 +105,14 @@ feature -- Change User token
sql_finalize
end
feature {NONE} -- Implementation
fetch_user: detachable CMS_USER
local
l_id: INTEGER_64
l_name: detachable READABLE_STRING_32
do
if attached sql_read_integer_64 (1) as i then
l_id := i
end
if attached sql_read_string_32 (2) as s and then not s.is_whitespace then
l_name := s
end
if l_name /= Void then
create Result.make (l_name)
if l_id > 0 then
Result.set_id (l_id)
end
elseif l_id > 0 then
create Result.make_with_id (l_id)
end
if Result /= Void then
if attached sql_read_string (3) as l_password then
-- FIXME: should we return the password here ???
Result.set_hashed_password (l_password)
end
if attached sql_read_string (5) as l_email then
Result.set_email (l_email)
end
if attached sql_read_integer_32 (6) as l_status then
Result.set_status (l_status)
end
else
check
expected_valid_user: False
end
end
end
feature {NONE} -- SQL statements
Select_user_by_token: STRING = "SELECT u.* FROM users as u JOIN session_auth as og ON og.uid = u.uid and og.access_token = :token;"
--| FIXME: replace the u.* by a list of field names, to avoid breaking `featch_user' if two fieds are swiped.
Select_user_id_by_token: STRING = "SELECT u.uid FROM users as u JOIN auth_session as og ON og.uid = u.uid AND og.access_token = :token;"
Sql_insert_session_auth: STRING = "INSERT INTO session_auth (uid, access_token, created) VALUES (:uid, :token, :utc_date);"
sql_insert_session_auth: STRING = "INSERT INTO auth_session (uid, access_token, created) VALUES (:uid, :token, :utc_date);"
Sql_update_session_auth: STRING = "UPDATE session_auth SET access_token = :token, created = :utc_date WHERE uid =:uid;"
sql_update_session_auth: STRING = "UPDATE auth_session SET access_token = :token, created = :utc_date WHERE uid =:uid;"
Select_user_token: STRING = "SELECT COUNT(*) FROM session_auth where uid = :uid;"
select_user_token: STRING = "SELECT COUNT(*) FROM auth_session where uid = :uid;"
end

View File

@@ -0,0 +1,9 @@
CREATE TABLE auth_session (
`uid` INTEGER PRIMARY KEY NOT NULL CHECK(`uid`>=0),
`access_token` VARCHAR(64) NOT NULL,
`created` DATETIME NOT NULL,
CONSTRAINT `uid` UNIQUE(`uid`),
CONSTRAINT `access_token` UNIQUE(`access_token`)
);

View File

@@ -1,11 +0,0 @@
CREATE TABLE session_auth (
`uid` INTEGER PRIMARY KEY NOT NULL CHECK(`uid`>=0),
`access_token` TEXT NOT NULL,
`created` DATETIME NOT NULL,
CONSTRAINT `uid`
UNIQUE(`uid`),
CONSTRAINT `access_token`
UNIQUE(`access_token`)
);

View File

@@ -70,18 +70,20 @@ feature {CMS_API} -- Module management
do
-- Schema
if attached {CMS_STORAGE_SQL_I} api.storage as l_sql_storage then
l_sql_storage.sql_execute_file_script (api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended ("install").appended_with_extension ("sql")), Void)
l_sql_storage.sql_execute_file_script (api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended ("install.sql")), Void)
if l_sql_storage.has_error then
api.logger.put_error ("Could not install database for taxonomy module", generating_type)
end
Precursor (api)
else
Precursor (api)
create l_taxonomy_api.make (api)
create voc.make ("Tags")
voc.set_description ("Enter comma separated tags.")
l_taxonomy_api.save_vocabulary (voc)
voc.set_is_tags (True)
l_taxonomy_api.associate_vocabulary_with_type (voc, "page")
-- Populate
create l_taxonomy_api.make (api)
create voc.make ("Tags")
voc.set_description ("Enter comma separated tags.")
l_taxonomy_api.save_vocabulary (voc)
voc.set_is_tags (True)
l_taxonomy_api.associate_vocabulary_with_type (voc, "page")
end
end
end