Merge branch 'jvelilla-roc_v1_mailer' into ewf_v1

This commit is contained in:
jvelilla
2015-06-30 19:28:08 -03:00
27 changed files with 1380 additions and 137 deletions

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="ISO-8859-1"?> <?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-14-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-14-0 http://www.eiffel.com/developers/xml/configuration-1-14-0.xsd" name="demo" uuid="3643E657-BCBE-46AA-931B-71EAEA877A18" library_target="demo"> <system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="demo" uuid="3643E657-BCBE-46AA-931B-71EAEA877A18" library_target="demo">
<description>Example/demo for Eiffel ROC CMS library</description> <description>Example/demo for Eiffel ROC CMS library</description>
<target name="common" abstract="true"> <target name="common" abstract="true">
<file_rule> <file_rule>
@@ -15,15 +15,13 @@
<library name="cms" location="..\..\cms-safe.ecf" readonly="false"/> <library name="cms" location="..\..\cms-safe.ecf" readonly="false"/>
<library name="cms_app_env" location="..\..\library\app_env\app_env-safe.ecf" readonly="false"/> <library name="cms_app_env" location="..\..\library\app_env\app_env-safe.ecf" readonly="false"/>
<library name="cms_auth_module" location="..\..\modules\auth\auth-safe.ecf" readonly="false"/> <library name="cms_auth_module" location="..\..\modules\auth\auth-safe.ecf" readonly="false"/>
<library name="cms_oauth_20_module" location="..\..\modules\oauth20\oauth20-safe.ecf" readonly="false"/>
<library name="cms_basic_auth_module" location="..\..\modules\basic_auth\basic_auth-safe.ecf" readonly="false"/> <library name="cms_basic_auth_module" location="..\..\modules\basic_auth\basic_auth-safe.ecf" readonly="false"/>
<library name="cms_blog_module" location="modules\blog\cms_blog_module-safe.ecf" readonly="false"/> <library name="cms_blog_module" location="modules\blog\cms_blog_module-safe.ecf" readonly="false"/>
<library name="cms_demo_module" location="modules\demo\cms_demo_module-safe.ecf" readonly="false"/> <library name="cms_demo_module" location="modules\demo\cms_demo_module-safe.ecf" readonly="false"/>
<library name="cms_model" location="..\..\library\model\cms_model-safe.ecf" readonly="false"/> <library name="cms_model" location="..\..\library\model\cms_model-safe.ecf" readonly="false"/>
<library name="cms_node_module" location="..\..\modules\node\node-safe.ecf" readonly="false"/> <library name="cms_node_module" location="..\..\modules\node\node-safe.ecf" readonly="false"/>
<!-- <library name="cms_oauth_20_module" location="..\..\modules\oauth20\oauth20-safe.ecf" readonly="false"/>
<library name="persistence_store_mysql" location="..\..\library\persistence\store_mysql\store_mysql-safe.ecf" readonly="false"/> <library name="cms_openid_module" location="..\..\modules\openid\openid-safe.ecf" readonly="false"/>
-->
<library name="persistence_store_odbc" location="..\..\library\persistence\store_odbc\store_odbc-safe.ecf" readonly="false"/> <library name="persistence_store_odbc" location="..\..\library\persistence\store_odbc\store_odbc-safe.ecf" readonly="false"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/> <library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
<library name="wsf_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension-safe.ecf" readonly="false"/> <library name="wsf_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension-safe.ecf" readonly="false"/>

View File

@@ -0,0 +1,11 @@
CREATE TABLE openid_consumers(
`cid` INTEGER PRIMARY KEY NOT NULL CHECK(`cid`>=0),
`name` VARCHAR(255) NOT NULL,
`endpoint` VARCHAR (255) NOT NULL,
CONSTRAINT `cid`
UNIQUE(`cid`),
CONSTRAINT `name`
UNIQUE(`name`)
);

View File

@@ -0,0 +1,4 @@
-- Change the values TO_COMPLETE based on your API.
-- API SECTET KEY AND API PUBLIC KEY
INSERT INTO openid_consumers (name, endpoint)
VALUES ('yahoo', 'https://me.yahoo.com/');

View File

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

View File

@@ -0,0 +1,18 @@
<div>
<form action="{$site_url/}account/roc-openid-login" id="openid-login" method="POST">
<div>
<strong><label for="openid">OpenID identifier</label></strong><br/>
<input type="text" name="openid" value="" size="50"/>
</div>
<div><input type="submit" name="op" value="Validate"/></div>
<div hgv vtid="openid">Login with
{foreach item="item" from="$openid_consumers"}
<a href="{$site_url/}account/login-with-openid/{$item/}">{$item/}</a><br>
{/foreach}
</form>
<div>
{if isset="$error"}
<span><i>{$error/}</i></span> <br>
{/if}
</div>
</div>

View File

@@ -73,6 +73,10 @@ feature -- CMS setup
m.enable m.enable
a_setup.register_module (m) a_setup.register_module (m)
create {CMS_OPENID_MODULE} m.make
m.enable
a_setup.register_module (m)
create {CMS_DEBUG_MODULE} m.make create {CMS_DEBUG_MODULE} m.make
m.enable m.enable
a_setup.register_module (m) a_setup.register_module (m)

View File

@@ -116,13 +116,13 @@ feature -- Hooks
create lnk.make (u.name + " (Logout)", "account/roc-logout" ) create lnk.make (u.name + " (Logout)", "account/roc-logout" )
else else
create lnk.make ("Login", "account/roc-login") create lnk.make ("Login", "account/roc-login")
end a_menu_system.primary_menu.extend (lnk)
a_menu_system.primary_menu.extend (lnk) lnk.set_weight (98)
lnk.set_weight (98) if a_response.location.starts_with ("account/") then
if a_response.location.starts_with ("account/roc-login") then create lnk.make ("Basic Auth", "account/roc-basic-auth")
create lnk.make ("Basic Auth", "account/roc-basic-auth") lnk.set_expandable (True)
lnk.set_expandable (True) a_response.add_to_primary_tabs (lnk)
a_response.add_to_primary_tabs (lnk) end
end end
end end

View File

@@ -34,19 +34,6 @@ feature -- Access
feature -- Basic Operations feature -- Basic Operations
send_contact_email (a_to, a_content: READABLE_STRING_8)
-- Send successful contact message `a_token' to `a_to'.
require
attached_to: a_to /= Void
local
l_message: STRING
do
create l_message.make_from_string (parameters.account_activation)
l_message.replace_substring_all ("$link", a_content)
send_message (contact_email, a_to, parameters.contact_subject_register, l_message)
end
send_contact_welcome_email (a_to, a_content: READABLE_STRING_8) send_contact_welcome_email (a_to, a_content: READABLE_STRING_8)
-- Send successful contact message `a_token' to `a_to'. -- Send successful contact message `a_token' to `a_to'.
require require
@@ -56,8 +43,7 @@ feature -- Basic Operations
do do
create l_message.make_from_string (parameters.account_welcome) create l_message.make_from_string (parameters.account_welcome)
l_message.replace_substring_all ("$link", a_content) l_message.replace_substring_all ("$link", a_content)
send_message (contact_email, a_to, parameters.contact_subject_oauth, l_message) send_message (contact_email, a_to, parameters.contact_subject_register, l_message)
end end
end end

View File

@@ -71,23 +71,6 @@ feature {NONE} -- Initialization
else else
contact_subject_register := "Thank you for registering with us." contact_subject_register := "Thank you for registering with us."
end end
if l_subject_activate /= Void then
contact_subject_activate := l_subject_activate
else
contact_subject_activate := "New account activation token."
end
if l_subject_password /= Void then
contact_subject_password := l_subject_password
else
contact_subject_password := "Password Recovery."
end
if l_subject_oauth /= Void then
contact_subject_oauth := l_subject_oauth
else
contact_subject_oauth := "Welcome."
end
end end
feature -- Access feature -- Access
@@ -100,27 +83,6 @@ feature -- Access
-- Contact email. -- Contact email.
contact_subject_register: IMMUTABLE_STRING_8 contact_subject_register: IMMUTABLE_STRING_8
contact_subject_activate: IMMUTABLE_STRING_8
contact_subject_password: IMMUTABLE_STRING_8
contact_subject_oauth: IMMUTABLE_STRING_8
account_activation: STRING
-- Account activation template email message.
do
Result := template_string ("account_activation.html", default_template_account_activation)
end
account_re_activation: STRING
-- Account re_activation template email message.
do
Result := template_string ("accunt_re_activation.html", default_template_account_re_activation)
end
account_password: STRING
-- Account password template email message.
do
Result := template_string ("account_new_password.html", default_template_account_new_password)
end
account_welcome: STRING account_welcome: STRING
-- Account welcome template email message. -- Account welcome template email message.
@@ -174,72 +136,6 @@ feature {NONE} -- Implementation
feature {NONE} -- Message email feature {NONE} -- Message email
default_template_account_activation: STRING = "[
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Activation</title>
<meta name="description" content="Activation">
<meta name="author" content="ROC CMS">
</head>
<body>
<p>Thank you for registering at <a href="...">ROC CMS</a></p>
<p>To complete your registration, please click on the following link to activate your account:<p>
<p><a href="$link">$link</a></p>
<p>Thank you for joining us.</p>
</body>
</html>
]"
default_template_account_re_activation: STRING = "[
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>New Activation</title>
<meta name="description" content="New Activation token">
<meta name="author" content="ROC CMS">
</head>
<body>
<p>You have requested a new activation token at <a href="...">ROC CMS</a></p>
<p>To complete your registration, please click on the following link to activate your account:<p>
<p><a href="$link">$link</a></p>
<p>Thank you for joining us.</p>
</body>
</html>
]"
default_template_account_new_password: STRING = "[
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>New Password</title>
<meta name="description" content="New Password">
<meta name="author" content="ROC CMS">
</head>
<body>
<p>You have required a new password at <a href="...">ROC CMS</a></p>
<p>To complete your request, please click on this link to generate a new password:<p>
<p><a href="$link">$link</a></p>
</body>
</html>
]"
default_template_account_welcome: STRING = "[ default_template_account_welcome: STRING = "[
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en">

View File

@@ -179,7 +179,7 @@ feature -- 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-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/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/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/{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-callback/{callback}", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_callback_oauth (a_api, a_user_oauth_api, ?, ?)), a_router.methods_get_post)
end end
feature -- Hooks configuration feature -- Hooks configuration
@@ -227,10 +227,11 @@ feature -- Hooks
end end
create lnk.make (u.name + " (Logout)", "account/roc-oauth-logout" ) create lnk.make (u.name + " (Logout)", "account/roc-oauth-logout" )
a_menu_system.primary_menu.extend (lnk) a_menu_system.primary_menu.extend (lnk)
end else
if a_response.location.starts_with ("account/roc-login") then if a_response.location.starts_with ("account/") then
create lnk.make ("OAuth", "account/roc-oauth-login") create lnk.make ("OAuth", "account/roc-oauth-login")
a_response.add_to_primary_tabs (lnk) a_response.add_to_primary_tabs (lnk)
end
end end
end end

View File

@@ -20,7 +20,7 @@ feature {NONE} -- Initialization
do do
initilize (a_consumer) initilize (a_consumer)
create config.make_default (a_consumer.api_key, a_consumer.api_secret) create config.make_default (a_consumer.api_key, a_consumer.api_secret)
config.set_callback (a_host + "/account/"+ a_consumer.callback_name) config.set_callback (a_host + "/account/oauth-callback/"+ a_consumer.callback_name)
config.set_scope (a_consumer.scope) config.set_scope (a_consumer.scope)
--Todo create a generic OAUTH_20_GENERIC_API --Todo create a generic OAUTH_20_GENERIC_API
create oauth_api.make (a_consumer.endpoint, a_consumer.authorize_url, a_consumer.extractor) create oauth_api.make (a_consumer.endpoint, a_consumer.authorize_url, a_consumer.extractor)

View File

@@ -0,0 +1,72 @@
note
description: "[
API to manage CMS User Openid authentication.
]"
date: "$Date$"
revision: "$Revision$"
class
CMS_OPENID_API
inherit
CMS_MODULE_API
REFACTORING_HELPER
create {CMS_OPENID_MODULE}
make_with_storage
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'.
do
openid_storage := a_openid_storage
make (a_api)
ensure
openid_storage_set: openid_storage = a_openid_storage
end
feature {CMS_MODULE} -- Access: User openid storage.
openid_storage: CMS_OPENID_STORAGE_I
-- storage interface.
feature -- Access: User Openid
user_openid_by_userid_identity (a_uid: like {CMS_USER}.id; a_identity: READABLE_STRING_GENERAL): detachable CMS_USER
-- Retrieve a user by id `a_uid' with identity `a_identity', if any.
do
Result := openid_storage.user_openid_by_userid_identity (a_uid, a_identity)
end
user_openid_by_identity (a_identity: READABLE_STRING_GENERAL): detachable CMS_USER
do
Result := openid_storage.user_openid_by_identity (a_identity)
end
feature -- Access: Consumers OAuth20
openid_consumers: LIST [STRING]
-- List of Openid consumers, if any, empty in other case.
do
Result := openid_storage.openid_consumers
end
openid_consumer_by_name (a_name: READABLE_STRING_8): detachable CMS_OPENID_CONSUMER
-- Retrieve a consumer by name `a_name', if any.
do
Result := openid_storage.openid_consumer_by_name (a_name)
end
feature -- Change: User Openid
new_user_openid (a_identity: READABLE_STRING_GENERAL; a_user: CMS_USER)
-- Add a new user with openid using the identity `a_identity'.
require
has_id: a_user.has_id
do
openid_storage.new_user_openid (a_identity,a_user)
end
end

View File

@@ -0,0 +1,16 @@
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

@@ -0,0 +1,71 @@
note
description: "Summary description for {CMS_OPENID_CONSUMER}."
date: "$Date$"
revision: "$Revision$"
class
CMS_OPENID_CONSUMER
inherit
ANY
redefine
default_create
end
create
default_create,
make_with_id
feature {NONE} -- Initialization
make_with_id (a_id: like id)
do
id := a_id
default_create
end
default_create
do
set_endpoint ("")
set_name ("")
end
feature -- Access
endpoint: READABLE_STRING_8
-- Url to authorize the user.
name: READABLE_STRING_8
-- consumer name.
id: INTEGER_64
-- unique identifier.
feature -- Element change
set_endpoint (a_endpoint: like endpoint)
-- Assign `endpoint' with `a_endpoint'.
do
endpoint := a_endpoint
ensure
endpoint_assigned: endpoint = a_endpoint
end
set_name (a_name: like name)
-- Assign `name' with `a_name'.
do
name := a_name
ensure
name_assigned: name = a_name
end
set_id (an_id: like id)
-- Assign `id' with `an_id'.
do
id := an_id
ensure
id_assigned: id = an_id
end
end

View File

@@ -0,0 +1,50 @@
note
description: "Summary description for {CMS_OPENID_EMAIL_SERVICE}."
date: "$Date$"
revision: "$Revision$"
class
CMS_OPENID_EMAIL_SERVICE
inherit
EMAIL_SERVICE
redefine
initialize,
parameters
end
create
make
feature {NONE} -- Initialization
initialize
do
Precursor
contact_email := parameters.contact_email
end
parameters: CMS_OPENID_EMAIL_SERVICE_PARAMETERS
-- Associated parameters.
feature -- Access
contact_email: IMMUTABLE_STRING_8
-- contact email.
feature -- Basic Operations
send_contact_welcome_email (a_to, a_content: READABLE_STRING_8)
-- Send successful contact message `a_token' to `a_to'.
require
attached_to: a_to /= Void
local
l_message: STRING
do
create l_message.make_from_string (parameters.account_welcome)
l_message.replace_substring_all ("$link", a_content)
send_message (contact_email, a_to, parameters.contact_subject_register, l_message)
end
end

View File

@@ -0,0 +1,156 @@
note
description: "Summary description for {CMS_OPENID_EMAIL_SERVICE_PARAMETERS}."
date: "$Date$"
revision: "$Revision$"
class
CMS_OPENID_EMAIL_SERVICE_PARAMETERS
inherit
EMAIL_SERVICE_PARAMETERS
create
make
feature {NONE} -- Initialization
make (a_cms_api: CMS_API)
local
utf: UTF_CONVERTER
l_site_name: READABLE_STRING_8
s: detachable READABLE_STRING_32
l_contact_email, l_subject_register, l_subject_activate, l_subject_password, l_subject_oauth: detachable READABLE_STRING_8
do
cms_api := a_cms_api
-- Use global smtp setting if any, otherwise "localhost"
smtp_server := utf.escaped_utf_32_string_to_utf_8_string_8 (a_cms_api.setup.text_item_or_default ("smtp", "localhost"))
l_site_name := utf.escaped_utf_32_string_to_utf_8_string_8 (a_cms_api.setup.site_name)
admin_email := a_cms_api.setup.site_email
if not admin_email.has ('<') then
admin_email := l_site_name + " <" + admin_email +">"
end
if attached {CONFIG_READER} a_cms_api.module_configuration_by_name ({CMS_AUTHENTICATION_MODULE}.name, Void) as cfg then
if attached cfg.text_item ("smtp") as l_smtp then
-- Overwrite global smtp setting if any.
smtp_server := utf.utf_32_string_to_utf_8_string_8 (l_smtp)
end
s := cfg.text_item ("email")
if s /= Void then
l_contact_email := utf.utf_32_string_to_utf_8_string_8 (s)
end
s := cfg.text_item ("subject_register")
if s /= Void then
l_subject_register := utf.utf_32_string_to_utf_8_string_8 (s)
end
s := cfg.text_item ("subject_activate")
if s /= Void then
l_subject_register := utf.utf_32_string_to_utf_8_string_8 (s)
end
s := cfg.text_item ("subject_password")
if s /= Void then
l_subject_register := utf.utf_32_string_to_utf_8_string_8 (s)
end
s := cfg.text_item ("subject_oauth")
if s /= Void then
l_subject_oauth := utf.utf_32_string_to_utf_8_string_8 (s)
end
end
if l_contact_email /= Void then
if not l_contact_email.has ('<') then
l_contact_email := l_site_name + " <" + l_contact_email + ">"
end
contact_email := l_contact_email
else
contact_email := admin_email
end
if l_subject_register /= Void then
contact_subject_register := l_subject_register
else
contact_subject_register := "Thank you for registering with us."
end
end
feature -- Access
smtp_server: IMMUTABLE_STRING_8
admin_email: IMMUTABLE_STRING_8
contact_email: IMMUTABLE_STRING_8
-- Contact email.
contact_subject_register: IMMUTABLE_STRING_8
account_welcome: STRING
-- Account welcome template email message.
do
Result := template_string ("account_welcome.html", default_template_account_welcome)
end
feature {NONE} -- Implementation: Template
template_path (a_name: READABLE_STRING_GENERAL): PATH
-- Location of template named `a_name'.
do
Result := cms_api.module_location_by_name ({CMS_AUTHENTICATION_MODULE}.name).extended (a_name)
end
template_string (a_name: READABLE_STRING_GENERAL; a_default: STRING): STRING
-- Content of template named `a_name', or `a_default' if template is not found.
local
p: PATH
do
p := template_path ("account_activation.html")
if attached read_template_file (p) as l_content then
Result := l_content
else
create Result.make_from_string (a_default)
end
end
feature {NONE} -- Implementation
cms_api: CMS_API
read_template_file (a_path: PATH): detachable STRING
-- Read the content of the file at path `a_path'.
local
l_file: FILE
n: INTEGER
do
create {PLAIN_TEXT_FILE} l_file.make_with_path (a_path)
if l_file.exists and then l_file.is_readable then
n := l_file.count
l_file.open_read
l_file.read_stream (n)
Result := l_file.last_string
l_file.close
else
-- Error
end
end
feature {NONE} -- Message email
default_template_account_welcome: STRING = "[
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Welcome</title>
<meta name="description" content="Welcome">
<meta name="author" content="ROC CMS">
</head>
<body>
<p>Welcome to<a href="...">ROC CMS</a></p>
<p>Thank you for joining us.</p>
</body>
</html>
]"
end

View File

@@ -0,0 +1,511 @@
note
description: "[
Generic OpenID Module supporting authentication using different providers.
]"
date: "$Date$"
revision: "$Revision$"
class
CMS_OPENID_MODULE
inherit
CMS_MODULE
rename
module_api as user_openid_api
redefine
filters,
register_hooks,
initialize,
install,
user_openid_api
end
CMS_HOOK_BLOCK
CMS_HOOK_AUTO_REGISTER
CMS_HOOK_MENU_SYSTEM_ALTER
CMS_HOOK_VALUE_TABLE_ALTER
SHARED_EXECUTION_ENVIRONMENT
export
{NONE} all
end
REFACTORING_HELPER
SHARED_LOGGER
CMS_REQUEST_UTIL
create
make
feature {NONE} -- Initialization
make
-- Create current module
do
version := "1.0"
description := "Openid module"
package := "openid"
create root_dir.make_current
cache_duration := 0
end
feature -- Access
name: STRING = "openid"
-- <Precursor>
feature {CMS_API} -- Module Initialization
initialize (a_api: CMS_API)
-- <Precursor>
local
l_openid_api: like user_openid_api
l_openid_storage: CMS_OPENID_STORAGE_I
do
Precursor (a_api)
-- Storage initialization
if attached {CMS_STORAGE_SQL_I} a_api.storage as l_storage_sql then
create {CMS_OPENID_STORAGE_SQL} l_openid_storage.make (l_storage_sql)
else
-- FIXME: in case of NULL storage, should Current be disabled?
create {CMS_OPENID_STORAGE_NULL} l_openid_storage
end
-- API initialization
create l_openid_api.make_with_storage (a_api, l_openid_storage)
user_openid_api := l_openid_api
ensure then
user_opend_api_set: user_openid_api /= Void
end
feature {CMS_API} -- Module management
install (api: CMS_API)
do
-- Schema
if attached {CMS_STORAGE_SQL_I} api.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)
if l_sql_storage.has_error then
api.logger.put_error ("Could not initialize database for openid module", generating_type)
end
-- 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)
end
Precursor {CMS_MODULE}(api)
end
end
feature {CMS_API} -- Access: API
user_openid_api: detachable CMS_OPENID_API
-- <Precursor>
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
create {ARRAYED_LIST [WSF_FILTER]} Result.make (1)
Result.extend (create {CMS_OPENID_FILTER}.make (a_api, l_user_openid_api))
end
end
feature -- Access: docs
root_dir: PATH
cache_duration: INTEGER
-- Caching duration
--| 0: disable
--| -1: cache always valie
--| nb: cache expires after nb seconds.
cache_disabled: BOOLEAN
do
Result := cache_duration = 0
end
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)
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
feature -- Hooks configuration
register_hooks (a_response: CMS_RESPONSE)
-- Module hooks configuration.
do
auto_subscribe_to_hooks (a_response)
a_response.subscribe_to_block_hook (Current)
a_response.subscribe_to_value_table_alter_hook (Current)
end
feature -- Hooks
value_table_alter (a_value: CMS_VALUE_TABLE; a_response: CMS_RESPONSE)
-- <Precursor>
do
if attached current_user (a_response.request) as l_user then
a_value.force (l_user, "user")
end
end
menu_system_alter (a_menu_system: CMS_MENU_SYSTEM; a_response: CMS_RESPONSE)
-- Hook execution on collection of menu contained by `a_menu_system'
-- for related response `a_response'.
local
lnk: CMS_LOCAL_LINK
lnk2: detachable CMS_LINK
do
if
attached a_response.current_user (a_response.request) as u and then
attached {WSF_STRING} a_response.request.cookie ({CMS_OPENID_CONSTANTS}.openid_session) as l_roc_auth_session_token
then
across
a_menu_system.primary_menu.items as ic
until
lnk2 /= Void
loop
if ic.item.title.has_substring ("(Logout)") then
lnk2 := ic.item
end
end
if lnk2 /= Void then
a_menu_system.primary_menu.remove (lnk2)
end
create lnk.make (u.name + " (Logout)", "account/roc-openid-logout" )
a_menu_system.primary_menu.extend (lnk)
else
if a_response.location.starts_with ("account/") then
create lnk.make ("Openid", "account/roc-openid-login")
a_response.add_to_primary_tabs (lnk)
end
end
end
block_list: ITERABLE [like {CMS_BLOCK}.name]
local
l_string: STRING
do
Result := <<"login">>
debug ("roc")
create l_string.make_empty
across
Result as ic
loop
l_string.append (ic.item)
l_string.append_character (' ')
end
write_debug_log (generator + ".block_list:" + l_string )
end
end
get_block_view (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE)
do
if
a_block_id.is_case_insensitive_equal_general ("login") and then
a_response.location.starts_with ("account/roc-openid-login")
then
get_block_view_login (a_block_id, a_response)
end
end
handle_openid_login (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE)
local
r: CMS_RESPONSE
o: OPENID_CONSUMER
s: STRING
do
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
if req.is_get_request_method then
r.set_value ("Login", "optional_content_type")
r.execute
elseif req.is_post_request_method then
create s.make_empty
if attached req.string_item ("openid") as p_openid then
s.append ("Check openID: " + p_openid)
create o.make (req.absolute_script_url ("/account/login-with-openid"))
o.ask_email (True)
o.ask_all_info (False)
if attached o.auth_url (p_openid) as l_url then
r.set_redirection (l_url)
else
s.append (" Failure")
r.set_status_code ({HTTP_CONSTANTS}.bad_request)
r.values.force (s, "error")
r.execute
end
end
end
end
handle_logout (api: CMS_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
then
-- Logout OAuth
create l_cookie.make ({CMS_OPENID_CONSTANTS}.openid_session, l_cookie_token.value)
l_cookie.set_path ("/")
l_cookie.set_max_age (-1)
res.add_cookie (l_cookie)
unset_current_user (req)
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
r.set_status_code ({HTTP_CONSTANTS}.found)
r.set_redirection (req.absolute_script_url (""))
r.execute
end
end
feature {NONE} -- Helpers
template_block (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE): detachable CMS_SMARTY_TEMPLATE_BLOCK
-- Smarty content block for `a_block_id'
local
p: detachable PATH
do
create p.make_from_string ("templates")
p := p.extended ("block_").appended (a_block_id).appended_with_extension ("tpl")
p := a_response.api.module_theme_resource_location (Current, p)
if p /= Void then
if attached p.entry as e then
create Result.make (a_block_id, Void, p.parent, e)
else
create Result.make (a_block_id, Void, p.parent, p)
end
end
end
feature {NONE} -- Block views
get_block_view_login (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE)
local
vals: CMS_VALUE_TABLE
do
if attached template_block (a_block_id, a_response) as l_tpl_block then
create vals.make (1)
-- add the variable to the block
value_table_alter (vals, a_response)
across
vals as ic
loop
l_tpl_block.set_value (ic.item, ic.key)
end
if
attached user_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")
end
a_response.add_block (l_tpl_block, "content")
else
debug ("cms")
a_response.add_warning_message ("Error with block [" + a_block_id + "]")
end
end
end
feature -- Openid Login
handle_login_with_openid (api: CMS_API; a_oauth_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
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
create b.make_empty
b.append ("Check openID: " + p_openid.value)
create o.make (req.absolute_script_url ("/account/openid-callback"))
o.ask_email (True)
o.ask_all_info (False)
if attached o.auth_url (l_oc.endpoint) as l_url then
r.set_redirection (l_url)
else
b.append ("Failure")
end
r.execute
else
create {BAD_REQUEST_ERROR_CMS_RESPONSE} r.make (req, res, api)
r.set_main_content ("Bad request")
r.execute
end
end
handle_callback_openid (api: CMS_API; a_user_openid_api: CMS_OPENID_API; req: WSF_REQUEST; res: WSF_RESPONSE)
local
r: CMS_RESPONSE
l_user_api: CMS_USER_API
l_user: CMS_USER
l_roles: LIST [CMS_USER_ROLE]
l_cookie: WSF_COOKIE
es: CMS_OPENID_EMAIL_SERVICE
b: STRING
o: OPENID_CONSUMER
v: OPENID_CONSUMER_VALIDATION
do
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
create b.make_empty
if attached req.string_item ("openid.mode") as l_openid_mode then
create o.make (req.absolute_script_url ("/"))
o.ask_email (True)
o.ask_nickname (False)
create v.make_from_items (o, req.items_as_string_items)
v.validate
if v.is_valid then
if attached v.identity as l_identity and then
attached v.email_attribute as l_email
then
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
-- Update openid entry?
else
-- create a oauth entry
a_user_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)
l_cookie.set_path ("/")
res.add_cookie (l_cookie)
else
create {ARRAYED_LIST [CMS_USER_ROLE]} l_roles.make (1)
l_roles.force (l_user_api.authenticated_user_role)
-- Create a new user and oauth entry
create l_user.make (l_email)
l_user.set_email (l_email)
l_user.set_password (new_token) -- generate a random password.
l_user.set_roles (l_roles)
l_user.mark_active
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)
l_cookie.set_path ("/")
res.add_cookie (l_cookie)
-- Send Email
create es.make (create {CMS_OPENID_EMAIL_SERVICE_PARAMETERS}.make (api))
write_debug_log (generator + ".handle_callback_openid: send_contact_welcome_email")
es.send_contact_welcome_email (l_email, "")
end
end
r.set_redirection (r.front_page_url)
r.execute
else
b.append ("User authentication failed!!")
end
end
end
feature {NONE} -- Token Generation
new_token: STRING
-- Generate a new token activation token
local
l_token: STRING
l_security: SECURITY_PROVIDER
l_encode: URL_ENCODER
do
create l_security
l_token := l_security.token
create l_encode
from until l_token.same_string (l_encode.encoded_string (l_token)) loop
-- Loop ensure that we have a security token that does not contain characters that need encoding.
-- We cannot simply to an encode-decode because the email sent to the user will contain an encoded token
-- but the user will need to use an unencoded token if activation has to be done manually.
l_token := l_security.token
end
Result := l_token
end
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)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,58 @@
note
description: "[
Extracts an Openid token from the incoming request (cookie) and uses it to populate the user (or cms user context)
]"
date: "$Date$"
revision: "$Revision$"
class
CMS_OPENID_FILTER
inherit
WSF_URI_TEMPLATE_HANDLER
CMS_HANDLER
rename
make as make_handler
end
WSF_FILTER
create
make
feature {NONE} -- Initialization
make (a_api: CMS_API; a_user_openid_api: CMS_OPENID_API)
do
make_handler (a_api)
user_openid_api := a_user_openid_api
end
user_openid_api: CMS_OPENID_API
feature -- Basic operations
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
-- Execute the filter.
local
o: OPENID_CONSUMER
v: OPENID_CONSUMER_VALIDATION
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
then
if attached user_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
end

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="openid_module" uuid="C4CF6FD6-F6F6-4FC9-89DF-D1C8A000DCD6" library_target="openid_module">
<target name="openid_module">
<root all_classes="true"/>
<file_rule>
<exclude>/.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="standard">
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="cms" location="$ISE_LIBRARY\unstable\library\web\cms\cms-safe.ecf" readonly="false"/>
<library name="cms_app_env" location="$ISE_LIBRARY\unstable\library\web\cms\library\app_env\app_env-safe.ecf" readonly="false"/>
<library name="cms_auth_module" location="..\auth\auth-safe.ecf" readonly="false"/>
<library name="cms_model" location="$ISE_LIBRARY\unstable\library\web\cms\library\model\cms_model-safe.ecf" readonly="false"/>
<library name="config" location="$ISE_LIBRARY\unstable\library\web\cms\library\configuration\config-safe.ecf"/>
<library name="email_service" location="..\..\library\email\email-safe.ecf"/>
<library name="encoder" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\text\encoder\encoder-safe.ecf"/>
<library name="error" location="$ISE_LIBRARY\contrib\library\utility\general\error\error-safe.ecf"/>
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http-safe.ecf"/>
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json-safe.ecf" readonly="false"/>
<library name="openid" location="$ISE_LIBRARY\contrib\library\web\authentication\openid\consumer\openid-safe.ecf" readonly="false"/>
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
<cluster name="src" location=".\" recursive="true"/>
</target>
</system>

View File

@@ -0,0 +1,54 @@
note
description: "[
API to handle Openid storage
]"
date: "$Date$"
revision: "$Revision$"
deferred class
CMS_OPENID_STORAGE_I
inherit
SHARED_LOGGER
feature -- Error Handling
error_handler: ERROR_HANDLER
-- Error handler.
deferred
end
feature -- Access: Users
user_openid_by_userid_identity (a_uid: like {CMS_USER}.id; a_consumer_table: READABLE_STRING_GENERAL): detachable CMS_USER
-- Retrieve a user by id `a_uid' for the consumer `a_consumer', if aby.
deferred
end
user_openid_by_identity (a_identity: READABLE_STRING_GENERAL;): detachable CMS_USER
-- Retrieve a user by identity `a_identity'.
deferred
end
feature -- Access: Consumers
openid_consumers: LIST [STRING]
-- Return a list of consumers, or empty
deferred
end
openid_consumer_by_name (a_name: READABLE_STRING_8): detachable CMS_OPENID_CONSUMER
-- Retrieve a consumer by name `a_name', if any.
deferred
end
feature -- Change: User Oauth2
new_user_openid (a_identity: READABLE_STRING_GENERAL; a_user: CMS_USER)
-- Add a new user with openid authentication.
deferred
end
end

View File

@@ -0,0 +1,60 @@
note
description: "Summary description for {CMS_OPENID_STORAGE_NULL}."
date: "$Date$"
revision: "$Revision$"
class
CMS_OPENID_STORAGE_NULL
inherit
CMS_OPENID_STORAGE_I
feature -- Error handler
error_handler: ERROR_HANDLER
-- Error handler.
do
create Result.make
end
feature -- Access: Users
user_openid_by_userid_identity (a_uid: like {CMS_USER}.id; a_identity: READABLE_STRING_GENERAL): detachable CMS_USER
-- <Precursor>
do
end
user_openid_by_identity (a_identity: READABLE_STRING_GENERAL;): detachable CMS_USER
-- <Precursor>
do
end
feature -- Access: Consumers
openid_consumers: LIST [STRING]
-- <Precursor>
do
create {ARRAYED_LIST[STRING]}Result.make(0)
end
openid_consumer_by_name (a_name: READABLE_STRING_8): detachable CMS_OPENID_CONSUMER
-- <Precursor>
do
end
feature -- Change: User Oauth2
new_user_openid (a_token: READABLE_STRING_GENERAL; a_user: CMS_USER)
-- <Precursor>
do
end
update_user_openid (a_token: READABLE_STRING_GENERAL; a_user_profile: READABLE_STRING_32; a_user: CMS_USER; a_consumer_table: READABLE_STRING_GENERAL )
-- Update user `a_user' with oauth2 authentication.
do
end
end

View File

@@ -0,0 +1,194 @@
note
description: "Summary description for {CMS_OPENID_STORAGE_SQL}."
date: "$Date$"
revision: "$Revision$"
class
CMS_OPENID_STORAGE_SQL
inherit
CMS_OPENID_STORAGE_I
CMS_PROXY_STORAGE_SQL
CMS_OPENID_STORAGE_I
CMS_STORAGE_SQL_I
REFACTORING_HELPER
create
make
feature -- Access User Outh
user_openid_by_userid_identity (a_uid: like {CMS_USER}.id; a_identity: READABLE_STRING_GENERAL): detachable CMS_USER
-- <Precursor>
local
l_parameters: STRING_TABLE [detachable ANY]
do
error_handler.reset
write_information_log (generator + ".user_openid_by_userid_identity")
create l_parameters.make (1)
l_parameters.put (a_uid, "uid")
l_parameters.put (a_identity, "identity")
sql_query (Select_user_openid_by_id, l_parameters)
if sql_rows_count = 1 then
Result := fetch_user
else
check no_more_than_one: sql_rows_count = 0 end
end
end
user_openid_by_identity (a_identity: READABLE_STRING_GENERAL): detachable CMS_USER
-- <Precursor>
local
l_parameters: STRING_TABLE [detachable ANY]
do
error_handler.reset
write_information_log (generator + ".user_openid_by_identity")
create l_parameters.make (1)
l_parameters.put (a_identity, "identity")
sql_query (Select_user_by_openid_identity, l_parameters)
if sql_rows_count = 1 then
Result := fetch_user
else
check no_more_than_one: sql_rows_count = 0 end
end
end
feature --Access: Consumers
openid_consumers: LIST [STRING]
-- Return a list of consumers, or empty
do
error_handler.reset
create {ARRAYED_LIST [STRING]} Result.make (0)
write_information_log (generator + ".openid_consumers")
sql_query (Sql_openid_consumers, Void)
if not has_error then
from
sql_start
until
sql_after
loop
if attached sql_read_string (1) as l_name then
Result.force (l_name)
end
sql_forth
end
end
end
openid_consumer_by_name (a_name: READABLE_STRING_8): detachable CMS_OPENID_CONSUMER
-- Retrieve a consumer by name `a_name', if any.
local
l_parameters: STRING_TABLE [detachable ANY]
do
error_handler.reset
write_information_log (generator + ".openid_consumer_by_name")
create l_parameters.make (1)
l_parameters.put (a_name, "name")
sql_query (sql_openid_consumer_name, l_parameters)
if sql_rows_count = 1 then
Result := fetch_consumer
else
check no_more_than_one: sql_rows_count = 0 end
end
end
feature -- Change: User OAuth
new_user_openid (a_identity: READABLE_STRING_GENERAL; a_user: CMS_USER)
-- Add a new user with openid authentication.
-- <Precursor>.
local
l_parameters: STRING_TABLE [detachable ANY]
l_string: STRING
do
error_handler.reset
sql_begin_transaction
write_information_log (generator + ".new_user_openid")
create l_parameters.make (4)
l_parameters.put (a_user.id, "uid")
l_parameters.put (a_identity, "identity")
l_parameters.put (create {DATE_TIME}.make_now_utc, "utc_date")
sql_change (Sql_insert_openid, l_parameters)
sql_commit_transaction
end
feature {NONE} -- Implementation OAuth Consumer
fetch_consumer: detachable CMS_OPENID_CONSUMER
do
if attached sql_read_integer_64 (1) as l_id then
create Result.make_with_id (l_id)
if attached sql_read_string (2) as l_name then
Result.set_name (l_name)
end
if attached sql_read_string (3) as l_endpoint then
Result.set_endpoint (l_endpoint)
end
end
end
feature {NONE} -- Implementation: User
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} -- User OpenID
Select_user_by_openid_identity: STRING = "SELECT u.* FROM users as u JOIN openid_items as og ON og.uid = u.uid and og.identity = :identity;"
--| FIXME: replace the u.* by a list of field names, to avoid breaking `featch_user' if two fieds are swiped.
Select_user_openid_by_id: STRING = "SELECT u.* FROM users as u JOIN openid_items as og ON og.uid = u.uid and og.uid = :uid and og.identity = :identity;"
Sql_insert_openid: STRING = "INSERT INTO openid_items (uid, identity, created) VALUES (:uid, :identity, :utc_date);"
Sql_openid_consumers: STRING = "SELECT name FROM openid_consumers";
feature {NONE} -- Consumer
Sql_openid_consumer_name: STRING = "SELECT * FROM openid_consumers where name =:name;"
end

View File

@@ -0,0 +1,11 @@
CREATE TABLE openid_consumers(
`cid` INTEGER PRIMARY KEY NOT NULL CHECK(`cid`>=0),
`name` VARCHAR(255) NOT NULL,
`endpoint` VARCHAR (255) NOT NULL,
CONSTRAINT `cid`
UNIQUE(`cid`),
CONSTRAINT `name`
UNIQUE(`name`)
);

View File

@@ -0,0 +1,4 @@
-- Change the values TO_COMPLETE based on your API.
-- API SECTET KEY AND API PUBLIC KEY
INSERT INTO openid_consumers (name, endpoint)
VALUES ('yahoo', 'https://me.yahoo.com/');

View File

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

View File

@@ -0,0 +1,18 @@
<div>
<form action="{$site_url/}account/roc-openid-login" id="openid-login" method="POST">
<div>
<strong><label for="openid">OpenID identifier</label></strong><br/>
<input type="text" name="openid" value="" size="50"/>
</div>
<div><input type="submit" name="op" value="Validate"/></div>
<div hgv vtid="openid">Login with
{foreach item="item" from="$openid_consumers"}
<a href="{$site_url/}account/login-with-openid/{$item/}">{$item/}</a><br>
{/foreach}
</form>
<div>
{if isset="$error"}
<span><i>{$error/}</i></span> <br>
{/if}
</div>
</div>

BIN
roc.exe Normal file

Binary file not shown.