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\basic_auth --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\blog --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\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\node --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\oauth20 --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\openid --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\recent_changes --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\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) api.logger.put_error ("Could not initialize database for demo module", generating_type)
end end
end end
Precursor {CMS_MODULE}(api)
end end
-- For this demo, be flexible, and do not required sql.
Precursor {CMS_MODULE}(api)
end end
feature -- Access: router feature -- Access: router

View File

@@ -4,9 +4,13 @@ root-dir=site/www
#modules-dir=site/modules #modules-dir=site/modules
[site] [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 of the site, for the title, and eventual message.
name=Eiffel CMS name=Eiffel CMS
# Properties used for SEO.
property[headline]=Eiffel CMS -- the demo property[headline]=Eiffel CMS -- the demo
property[description]=Demo for Eiffel ROC CMS. property[description]=Demo for Eiffel ROC CMS.
property[keywords]=eiffel,cms,demo property[keywords]=eiffel,cms,demo
@@ -43,6 +47,14 @@ output=site\db\mailer.log
[blocks] [blocks]
@include=blocks.ini @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] [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

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 feature {CMS_API} -- Module management
install (api: CMS_API) install (a_api: CMS_API)
local
sql: STRING
do do
-- Schema -- Schema
if attached api.storage.as_sql_storage as l_sql_storage then if attached a_api.storage.as_sql_storage as l_sql_storage then
if not l_sql_storage.sql_table_exists ("blog_post_nodes") then l_sql_storage.sql_execute_file_script (a_api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended ("install.sql")), Void)
sql := "[
CREATE TABLE blog_post_nodes( if l_sql_storage.has_error then
`nid` INTEGER NOT NULL CHECK("nid">=0), a_api.logger.put_error ("Could not initialize database for module [" + name + "]", generating_type)
`revision` INTEGER NOT NULL, else
`tags` VARCHAR(255), Precursor {CMS_MODULE} (a_api)
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
end end
Precursor (api)
end end
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 module_api as contact_api
redefine redefine
setup_hooks, setup_hooks,
is_installed,
install, install,
initialize, initialize,
contact_api contact_api
@@ -53,7 +52,6 @@ feature {NONE} -- Initialization
package := "messaging" package := "messaging"
end end
feature -- Access feature -- Access
name: STRING = "contact" name: STRING = "contact"
@@ -86,14 +84,6 @@ feature {CMS_API} -- Module Initialization
feature {CMS_API} -- Module management 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) install (api: CMS_API)
local local
retried: BOOLEAN retried: BOOLEAN
@@ -102,6 +92,7 @@ feature {CMS_API} -- Module management
if not retried then if not retried then
create d.make_with_path (file_system_storage_path (api)) create d.make_with_path (file_system_storage_path (api))
d.recursive_create_dir d.recursive_create_dir
Precursor {CMS_MODULE}(api) -- Marked installed
end end
rescue rescue
retried := True retried := True

View File

@@ -127,8 +127,13 @@ feature {CMS_API} -- Module management
-- Schema -- Schema
if attached a_api.storage.as_sql_storage as l_sql_storage then 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) 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 end
Precursor {CMS_MODULE}(a_api)
end end
feature {CMS_API} -- Access: API feature {CMS_API} -- Access: API

View File

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

View File

@@ -1,6 +1,7 @@
note note
description: "[ 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$" date: "$Date$"
revision: "$Revision$" revision: "$Revision$"
@@ -10,6 +11,7 @@ class
inherit inherit
WSF_URI_TEMPLATE_HANDLER WSF_URI_TEMPLATE_HANDLER
CMS_HANDLER CMS_HANDLER
rename rename
make as make_handler make as make_handler
@@ -25,10 +27,10 @@ feature {NONE} -- Initialization
make (a_api: CMS_API; a_user_oauth_api: CMS_OAUTH_20_API) make (a_api: CMS_API; a_user_oauth_api: CMS_OAUTH_20_API)
do do
make_handler (a_api) make_handler (a_api)
user_oauth_api := a_user_oauth_api oauth_api := a_user_oauth_api
end end
user_oauth_api: CMS_OAUTH_20_API oauth_api: CMS_OAUTH_20_API
feature -- Basic operations feature -- Basic operations
@@ -38,9 +40,9 @@ feature -- Basic operations
api.logger.put_debug (generator + ".execute ", Void) api.logger.put_debug (generator + ".execute ", Void)
-- A valid user -- A valid user
if 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 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) set_current_user (req, l_user)
else else
api.logger.put_error (generator + ".execute login_valid failed for: " + l_roc_auth_session_token.value , Void) 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 class
CMS_OPENID_API CMS_OPENID_API
inherit inherit
CMS_MODULE_API CMS_MODULE_API
@@ -19,9 +20,25 @@ feature {NONE} -- Initialization
make_with_storage (a_api: CMS_API; a_openid_storage: CMS_OPENID_STORAGE_I) 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'. -- Create an object with api `a_api' and storage `a_openid_storage'.
local
s: detachable READABLE_STRING_8
do do
openid_storage := a_openid_storage openid_storage := a_openid_storage
make (a_api) 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 ensure
openid_storage_set: openid_storage = a_openid_storage openid_storage_set: openid_storage = a_openid_storage
end end
@@ -31,6 +48,16 @@ feature {CMS_MODULE} -- Access: User openid storage.
openid_storage: CMS_OPENID_STORAGE_I openid_storage: CMS_OPENID_STORAGE_I
-- storage interface. -- 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 feature -- Access: User Openid
user_openid_by_userid_identity (a_uid: like {CMS_USER}.id; a_identity: READABLE_STRING_GENERAL): detachable CMS_USER 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 inherit
CMS_MODULE CMS_MODULE
rename rename
module_api as user_openid_api module_api as openid_api
redefine redefine
filters, filters,
setup_hooks, setup_hooks,
initialize, initialize,
install, install,
user_openid_api openid_api
end end
@@ -68,7 +68,7 @@ feature {CMS_API} -- Module Initialization
initialize (a_api: CMS_API) initialize (a_api: CMS_API)
-- <Precursor> -- <Precursor>
local local
l_openid_api: like user_openid_api l_openid_api: like openid_api
l_openid_storage: CMS_OPENID_STORAGE_I l_openid_storage: CMS_OPENID_STORAGE_I
do do
Precursor (a_api) Precursor (a_api)
@@ -83,9 +83,9 @@ feature {CMS_API} -- Module Initialization
-- API initialization -- API initialization
create l_openid_api.make_with_storage (a_api, l_openid_storage) 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 ensure then
user_opend_api_set: user_openid_api /= Void user_opend_api_set: openid_api /= Void
end end
feature {CMS_API} -- Module management feature {CMS_API} -- Module management
@@ -94,30 +94,33 @@ feature {CMS_API} -- Module management
do do
-- Schema -- Schema
if attached api.storage.as_sql_storage as l_sql_storage then if attached api.storage.as_sql_storage as l_sql_storage then
if not l_sql_storage.sql_table_exists ("openid_consumers") then
--| Schema --| 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 if l_sql_storage.has_error then
api.logger.put_error ("Could not initialize database for openid module", generating_type) api.logger.put_error ("Could not initialize database for module [" + name + "]", generating_type)
end else
-- TODO workaround. -- 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) 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 -- TODO workaround, until we have an admin module
if l_sql_storage.has_error then if l_sql_storage.has_error then
api.logger.put_error ("Could not initialize database for different consumers", generating_type) api.logger.put_error ("Could not initialize openid consumer table for module [" + name + "]", generating_type)
else else
l_sql_storage.sql_execute_file_script (api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended ("openid_items.sql")),Void) 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 end
Precursor {CMS_MODULE}(api)
end end
end end
feature {CMS_API} -- Access: API feature {CMS_API} -- Access: API
user_openid_api: detachable CMS_OPENID_API openid_api: detachable CMS_OPENID_API
-- <Precursor> -- <Precursor>
feature -- Filters feature -- Filters
@@ -125,9 +128,9 @@ feature -- Filters
filters (a_api: CMS_API): detachable LIST [WSF_FILTER] filters (a_api: CMS_API): detachable LIST [WSF_FILTER]
-- Possibly list of Filter's module. -- Possibly list of Filter's module.
do 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) 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
end end
@@ -151,18 +154,24 @@ feature -- Router
setup_router (a_router: WSF_ROUTER; a_api: CMS_API) setup_router (a_router: WSF_ROUTER; a_api: CMS_API)
-- <Precursor> -- <Precursor>
do do
if attached user_openid_api as l_user_openid_api then if attached openid_api as l_openid_api then
configure_web (a_api, l_user_openid_api, a_router) 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
end end
configure_web (a_api: CMS_API; a_user_openid_api: CMS_OPENID_API; a_router: WSF_ROUTER) openid_consumer_path_parameter: STRING = "consumer"
do -- Consumer path parameter name.
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
feature -- Hooks configuration feature -- Hooks configuration
@@ -181,7 +190,8 @@ feature -- Hooks
do do
if if
attached a_response.user as u and then 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 then
a_value.force ("account/roc-openid-logout", "auth_login_strategy") a_value.force ("account/roc-openid-logout", "auth_login_strategy")
end end
@@ -196,7 +206,8 @@ feature -- Hooks
do do
if if
attached a_response.user as u and then 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 then
across across
a_menu_system.primary_menu.items as ic a_menu_system.primary_menu.items as ic
@@ -280,17 +291,17 @@ feature -- Hooks
end end
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 local
r: CMS_RESPONSE r: CMS_RESPONSE
l_cookie: WSF_COOKIE l_cookie: WSF_COOKIE
do do
if 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 and then
attached {CMS_USER} current_user (req) as l_user attached {WSF_STRING} req.cookie (a_openid_api.session_token) as l_cookie_token
then then
-- Logout OAuth -- 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_path ("/")
l_cookie.set_max_age (-1) l_cookie.set_max_age (-1)
res.add_cookie (l_cookie) res.add_cookie (l_cookie)
@@ -339,7 +350,7 @@ feature {NONE} -- Block views
l_tpl_block.set_value (ic.item, ic.key) l_tpl_block.set_value (ic.item, ic.key)
end end
if 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 attached l_openid_api.openid_consumers as l_list
then then
l_tpl_block.set_value (l_list, "openid_consumers") l_tpl_block.set_value (l_list, "openid_consumers")
@@ -356,14 +367,16 @@ feature {NONE} -- Block views
feature -- Openid Login 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 local
r: CMS_RESPONSE r: CMS_RESPONSE
b: STRING b: STRING
o: OPENID_CONSUMER o: OPENID_CONSUMER
do do
if attached {WSF_STRING} req.path_parameter ({CMS_OPENID_CONSTANTS}.consumer) as p_openid and then if
attached {CMS_OPENID_CONSUMER} a_oauth_api.openid_consumer_by_name (p_openid.value) as l_oc then 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 {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
create b.make_empty create b.make_empty
b.append ("Check openID: " + p_openid.value) b.append ("Check openID: " + p_openid.value)
@@ -383,7 +396,7 @@ feature -- Openid Login
end end
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 local
r: CMS_RESPONSE r: CMS_RESPONSE
l_user_api: CMS_USER_API l_user_api: CMS_USER_API
@@ -410,14 +423,14 @@ feature -- Openid Login
l_user_api := api.user_api l_user_api := api.user_api
if attached l_user_api.user_by_email (l_email) as p_user then if attached l_user_api.user_by_email (l_email) as p_user then
-- User with email exist -- 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? -- Update openid entry?
else else
-- create a oauth entry -- 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 end
create l_cookie.make ({CMS_OPENID_CONSTANTS}.openid_session, l_identity) create l_cookie.make (a_openid_api.session_token, l_identity)
l_cookie.set_max_age (3600) l_cookie.set_max_age (a_openid_api.session_max_age)
l_cookie.set_path ("/") l_cookie.set_path ("/")
res.add_cookie (l_cookie) res.add_cookie (l_cookie)
else else
@@ -434,9 +447,9 @@ feature -- Openid Login
l_user_api.new_user (l_user) l_user_api.new_user (l_user)
-- Add oauth entry -- Add oauth entry
a_user_openid_api.new_user_openid (l_identity, l_user ) a_openid_api.new_user_openid (l_identity, l_user )
create l_cookie.make ({CMS_OPENID_CONSTANTS}.openid_session, l_identity) create l_cookie.make (a_openid_api.session_token, l_identity)
l_cookie.set_max_age (3600) l_cookie.set_max_age (a_openid_api.session_max_age)
l_cookie.set_path ("/") l_cookie.set_path ("/")
res.add_cookie (l_cookie) res.add_cookie (l_cookie)
@@ -475,37 +488,6 @@ feature {NONE} -- Token Generation
Result := l_token Result := l_token
end 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 note
copyright: "Copyright (c) 1984-2013, Eiffel Software and others" copyright: "Copyright (c) 1984-2013, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"

View File

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

View File

@@ -6,7 +6,6 @@ note
class class
CMS_SESSION_API CMS_SESSION_API
inherit inherit
CMS_MODULE_API 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) 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'. -- Create an object with api `a_api' and storage `a_session_auth_storage'.
local
s: detachable READABLE_STRING_8
do do
session_auth_storage := a_session_auth_storage session_auth_storage := a_session_auth_storage
make (a_api) 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 ensure
session_auth_storage_set: session_auth_storage = a_session_auth_storage session_auth_storage_set: session_auth_storage = a_session_auth_storage
end end
@@ -31,6 +46,17 @@ feature {CMS_MODULE} -- Access: User session storage.
session_auth_storage: CMS_SESSION_AUTH_STORAGE_I session_auth_storage: CMS_SESSION_AUTH_STORAGE_I
-- storage interface. -- 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 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

View File

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

View File

@@ -23,31 +23,28 @@ create
feature {NONE} -- Initialization 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 do
make_handler (a_api) make_handler (a_api)
session_oauth_api := a_session_oauth_api session_api := a_session_api
end end
session_oauth_api: CMS_SESSION_API session_api: CMS_SESSION_API
feature -- Basic operations feature -- Basic operations
execute (req: WSF_REQUEST; res: WSF_RESPONSE) execute (req: WSF_REQUEST; res: WSF_RESPONSE)
-- Execute the filter. -- Execute the filter.
do do
api.logger.put_debug (generator + ".execute ", Void)
-- A valid user -- A valid user
if 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 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) set_current_user (req, l_user)
else else
api.logger.put_error (generator + ".execute login_valid failed for: " + l_roc_auth_session_token.value , Void) api.logger.put_error (generator + ".execute login_valid failed for: " + l_roc_auth_session_token.value , Void)
end end
else
api.logger.put_debug (generator + ".execute without authentication", Void)
end end
execute_next (req, res) execute_next (req, res)
end end

View File

@@ -7,7 +7,6 @@ class
CMS_SESSION_AUTH_STORAGE_SQL CMS_SESSION_AUTH_STORAGE_SQL
inherit inherit
CMS_SESSION_AUTH_STORAGE_I CMS_SESSION_AUTH_STORAGE_I
CMS_PROXY_STORAGE_SQL CMS_PROXY_STORAGE_SQL
@@ -27,23 +26,27 @@ feature -- Access User
-- Retrieve user by token `a_token', if any. -- Retrieve user by token `a_token', if any.
local local
l_parameters: STRING_TABLE [detachable ANY] l_parameters: STRING_TABLE [detachable ANY]
l_uid: INTEGER_64
do do
error_handler.reset error_handler.reset
write_information_log (generator + ".user_by_session_token") write_information_log (generator + ".user_by_session_token")
create l_parameters.make (1) create l_parameters.make (1)
l_parameters.put (a_token, "token") 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 if not has_error and not sql_after then
Result := fetch_user l_uid := sql_read_integer_64 (1)
sql_forth sql_forth
if not sql_after then if not sql_after then
check check
no_more_than_one: False no_more_than_one: False
end end
Result := Void l_uid := 0
end end
end end
sql_finalize 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 end
has_user_token (a_user: CMS_USER): BOOLEAN has_user_token (a_user: CMS_USER): BOOLEAN
@@ -68,7 +71,7 @@ feature -- Access User
feature -- Change User token 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>. -- <Precursor>.
local local
l_parameters: STRING_TABLE [detachable ANY] l_parameters: STRING_TABLE [detachable ANY]
@@ -102,54 +105,14 @@ feature -- Change User token
sql_finalize sql_finalize
end 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 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;" 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;"
--| FIXME: replace the u.* by a list of field names, to avoid breaking `featch_user' if two fieds are swiped.
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 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 do
-- Schema -- Schema
if attached {CMS_STORAGE_SQL_I} api.storage as l_sql_storage then 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 if l_sql_storage.has_error then
api.logger.put_error ("Could not install database for taxonomy module", generating_type) api.logger.put_error ("Could not install database for taxonomy module", generating_type)
end else
Precursor (api) Precursor (api)
create l_taxonomy_api.make (api) -- Populate
create voc.make ("Tags") create l_taxonomy_api.make (api)
voc.set_description ("Enter comma separated tags.") create voc.make ("Tags")
l_taxonomy_api.save_vocabulary (voc) voc.set_description ("Enter comma separated tags.")
voc.set_is_tags (True) l_taxonomy_api.save_vocabulary (voc)
l_taxonomy_api.associate_vocabulary_with_type (voc, "page") voc.set_is_tags (True)
l_taxonomy_api.associate_vocabulary_with_type (voc, "page")
end
end end
end end