Compare commits

..

39 Commits

Author SHA1 Message Date
39ab19d20e Eiffel code and ECFs update to support new agent notations.
Accepts /account and /account/ .
2016-01-19 16:15:13 +01:00
fd5e396b72 Code cleaning. 2016-01-15 18:35:53 +01:00
5bd28326c2 Added source for sql scripts. 2016-01-15 17:59:21 +01:00
eef2a52f48 Integrated new registration workflow.
Added optional "mailer.subject_prefix" configuration item.
Added CMS_SETUP.utf_8_site_name for convenience.
Fixed a few potential unicode issues.
Fixed various typos.
2016-01-15 17:46:56 +01:00
a6642e9f3e Fixed location of library "http_client_extension" in recaptcha library. 2016-01-15 14:11:51 +01:00
affe3beb27 Merge branch 'roc_register' of https://github.com/jvelilla/ROC into roc_register 2016-01-15 13:30:58 +01:00
a013efd6f7 Cosmetic in DEMO_CMS_EXECUTION
Removed persistence/mysql which is not used.
2016-01-15 13:30:07 +01:00
jvelilla
2f95c66295 Removed unneeded template
Updated Sql sentence.
2016-01-14 08:39:35 -03:00
f6885ff581 remove roc.exe 2016-01-13 22:05:49 +01:00
de443a2163 Do not use ODBC by default.
(bad for default, since it depends on odbc drivers to be installed)
2016-01-13 17:30:38 +01:00
a179ee3239 Reverted executable name to "demo" 2016-01-13 10:38:27 +01:00
ed0d9c8d07 Use {CMS_LOG}.level_notice and related constant when using api.log(..) 2016-01-12 16:14:54 +01:00
67fbee737d Keep only sqlite3 persistence as default.
To include mysql and other, uncomment related code in demo-safe.ecf and demo_cms_execution.
2016-01-12 16:14:18 +01:00
jvelilla
f244e86f13 Updated user.sql added tabled auth_temp_users.
Added CMS_TEMP_USER as part of the core.
Moved the code from CMS_TEMP_USER_API and CMS_TEMP_USER_STORAGE_* to
CMS_USER_API and CMS_USER_STORAGE_*.
2016-01-12 09:34:39 -03:00
jvelilla
0cf6e59a76 Updated templates and fixed typos.
Renamed classes
2016-01-08 20:26:34 -03:00
56b9355f3c Updated email messaging of Auth modules to use the CMS_API.process_email (..) system.
as a consequence, removed usage of email_service library.
Updated the meaning for site.email to be sender email addressed.
Added notification.email to set the email address that will received system email notification.
2016-01-08 22:24:52 +01:00
jvelilla
0ca336d467 Updated templates
Replaced hardcoded name "ROC CMS" for placeholder $sitename, and
missing href's with $host.
Renamed database script and database table for temporal users.
Renamed CMS_AUTH_API AS CMS_USER_TEMP_API.
Revert design to use CMS_TEMPORAL_USER and clean CMS_USER.
Refactor rename cms_auth_storage_* classes to CMS_TEMPORAL_USER_STORAGE_*
Added Pending Registrations to the admin menu to show the list of pending registrarions
added CSS to display temporal users
2016-01-06 21:29:21 -03:00
jvelilla
5d8ea2065e Rename script name and table name for
temporary users.
Updated message, after account reactivation.
Updated message, post account application.
Updated Form name, Registration instead of Registration Form.
Updated CMS_USER to have two optional features used for temporary users.
Updated CMS_AUTH_API to user CMS_USER instead of CMS_TEMPORAL_USER
Removed CMS_TEMPORAL_USER
Updateed CMS_AUTHENTICATION_MODULE, with new permission to enable
activate, reject or reactivate a pending user registration.
Updated User Storage and API to create a new user from a temporal user.
2016-01-04 21:14:13 -03:00
jvelilla
682193d116 Updated Register Module.
Worlflow

1- Register
1.1 Create a new temporal user
1.2 Email to the new User
1.3 Email to Web Master
2 Web Master Review th Account Application
2.1 Accept and Send an confirmation email to the user and remove the temporal user
2.2 Reject the application send a rejection email to the user and remove the temporal

Added a new table to save temporal users to review their Application to the site.
Updated Register Form with an new input Application and Recaptcha validation.
Updated Emails templates and messages. (TODO improve messages)
Updated mails templates. Simple messages (Todo improve messages).
Added a new handler to reject a user
Updated existing hanlders to handler the new workflow.
2015-12-30 12:32:00 -03:00
0813abe0bb Fixed ROC CMS library compilation. 2015-12-18 15:29:43 +01:00
1094acb3ec Removed unused local variable 2015-12-16 21:05:57 +01:00
e7c9a54f3f Removed unused local. 2015-12-16 21:03:15 +01:00
bbbdac12c8 Moved taxonomy html generation to CMS_TAXONOMY_API. 2015-12-16 21:03:03 +01:00
jvelilla
22528315cb Removed unneeded file. 2015-12-16 16:01:02 +01:00
jvelilla
090a48eb85 Updated class CMS_TOKEN_GENERATOR.
Remove once in sha1 feature.
Updated encoded_base_64 to base_64
2015-12-16 16:01:01 +01:00
jvelilla
e05c4dca3a Fixed typos
Renamed class CMS_SESSION_CONSTANT to CMS_SESSION_CONSTANTS
Removed unneeded classes and files.
Update SQL implementation.
2015-12-16 16:00:59 +01:00
jvelilla
2255fcc0f6 Added Module Session Authentication with Cookies.
Updated Demo example with the Module Session (Authentication with Cookies)
Fixed little issue with SQL query in OpenID module.
2015-12-16 16:00:58 +01:00
e50fb6959e Moved taxonomy integration for web form inside CMS_TAXONOMY_API.
Moved a few helpers routine from CMS_RESPONSE to CMS_API.
Added CMS_CONTENT.identifier: detachable READABLE_STRING_32 .
2015-12-16 15:59:22 +01:00
jvelilla
3b88c746a1 Removed unneeded file. 2015-12-16 10:43:21 -03:00
jvelilla
fa8ef44a4a Merge branch 'jvelilla-roc_login_session' 2015-12-16 10:11:55 -03:00
jvelilla
068943734f Updated class CMS_TOKEN_GENERATOR.
Remove once in sha1 feature.
Updated encoded_base_64 to base_64
2015-12-16 10:03:35 -03:00
jvelilla
089179e60e Fixed typos
Renamed class CMS_SESSION_CONSTANT to CMS_SESSION_CONSTANTS
Removed unneeded classes and files.
Update SQL implementation.
2015-12-15 15:32:31 -03:00
jvelilla
c25590c9cd Added Module Session Authentication with Cookies.
Updated Demo example with the Module Session (Authentication with Cookies)
Fixed little issue with SQL query in OpenID module.
2015-12-13 18:19:25 -03:00
23d266497b Made the SQL storage more flexible with INTEGER_32, by allowing to retrieve INTEGER_64 and convert to INTEGER_32 if value can be converted to integer 32. 2015-12-10 11:26:28 +01:00
ce8de442e9 Implemented taxonomy administration pages
- create term, vocabulary, add or remove term from vocabularies, ...
Fixed content editing related to taxonomy  (especially with multiple terms vs tags).
Fixed various SQL storage issue related to taxonomy and vocabularies.
Added CMS_RESPONSE.wsf_theme as helper.
2015-12-10 11:21:20 +01:00
e3ae564746 Removed an obsolete call to CMS_RESPONSE.hooks . 2015-12-07 22:08:37 +01:00
b0626d5250 Use + instead of concat(..) in javascript. 2015-12-07 21:36:24 +01:00
276dcc6fcd Added back CMS_MODULE.register_modules (CMS_RESPONSE) as obsolete, to avoid breaking existing modules.
Note: all module SHOULD migrate to new hook setup!
2015-12-07 21:24:48 +01:00
6313007fbf Refactored and update CMS hooks design. (Move from CMS_RESPONSE to CMS_API).
Moved content_types and content_type_webform_managers from CMS_RESPONSE to CMS_API.
Updated the way to output content (node, ...) to html page.
   See CMS_CONTENT_TYPE_WEBFORM_MANAGER.append_cointent_as_html_to (...).
   Added notion of "teaser" (short version of the content), as opposed to full content.
One can use CMS_API.html_encoder ... when possible, same for `formats', ...
Added bridge from CMS_MODULE_API to CMS_API's encoders.
Added new CMS_TAXONOMY_HOOK used to retrieve list of content associated with a specific term.
Moved up to CMS_RESPONSE a few features which was available only in specific descendants.

Added /taxonomy/term/{termid} implementation.
2015-12-07 18:21:40 +01:00
140 changed files with 5719 additions and 1448 deletions

View File

@@ -1,11 +1,11 @@
<?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="cms" uuid="8CC0D052-57D1-4CAA-AFF1-448FA290734B" library_target="cms"> <system xmlns="http://www.eiffel.com/developers/xml/configuration-1-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="cms" uuid="8CC0D052-57D1-4CAA-AFF1-448FA290734B" library_target="cms">
<target name="cms"> <target name="cms">
<root all_classes="true"/> <root all_classes="true"/>
<file_rule> <file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude> <exclude>/.svn$</exclude>
<exclude>/CVS$</exclude>
<exclude>/EIFGENs$</exclude>
</file_rule> </file_rule>
<option warning="true" full_class_checking="false" is_attached_by_default="true" void_safety="all" syntax="transitional"> <option warning="true" full_class_checking="false" is_attached_by_default="true" void_safety="all" syntax="transitional">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/> <assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>

View File

@@ -1,12 +1,12 @@
<?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="cms" uuid="8CC0D052-57D1-4CAA-AFF1-448FA290734B" library_target="cms"> <system xmlns="http://www.eiffel.com/developers/xml/configuration-1-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="cms" uuid="8CC0D052-57D1-4CAA-AFF1-448FA290734B" library_target="cms">
<description>ROC CMS library</description> <description>ROC CMS library</description>
<target name="cms"> <target name="cms">
<root all_classes="true"/> <root all_classes="true"/>
<file_rule> <file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude> <exclude>/.svn$</exclude>
<exclude>/CVS$</exclude>
<exclude>/EIFGENs$</exclude>
</file_rule> </file_rule>
<option warning="true" full_class_checking="false" void_safety="none" syntax="transitional"> <option warning="true" full_class_checking="false" void_safety="none" syntax="transitional">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/> <assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>

View File

@@ -1,16 +1,17 @@
<?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-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="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">
<root class="DEMO_CMS_SERVER" feature="make_and_launch"/> <root class="DEMO_CMS_SERVER" feature="make_and_launch"/>
<file_rule> <file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude> <exclude>/.svn$</exclude>
<exclude>/CVS$</exclude>
<exclude>/EIFGENs$</exclude>
</file_rule> </file_rule>
<option debug="true" warning="true" full_class_checking="false" is_attached_by_default="true" void_safety="all" syntax="transitional"> <option debug="true" warning="true" full_class_checking="false" is_attached_by_default="true" void_safety="all" syntax="transitional">
<debug name="dbglog" enabled="true"/> <debug name="dbglog" enabled="true"/>
</option> </option>
<setting name="executable_name" value="demo"/>
<setting name="concurrency" value="thread"/> <setting name="concurrency" value="thread"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/> <library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="cms" location="..\..\cms-safe.ecf" readonly="false"> <library name="cms" location="..\..\cms-safe.ecf" readonly="false">
@@ -29,19 +30,20 @@
<library name="cms_google_search_module" location="..\..\modules\google_search\google_search-safe.ecf" readonly="false" use_application_options="true"/> <library name="cms_google_search_module" location="..\..\modules\google_search\google_search-safe.ecf" readonly="false" use_application_options="true"/>
<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_taxnomy_module" location="..\..\modules\taxonomy\taxonomy-safe.ecf" readonly="false"/>
<library name="cms_oauth_20_module" location="..\..\modules\oauth20\oauth20-safe.ecf" readonly="false"/> <library name="cms_oauth_20_module" location="..\..\modules\oauth20\oauth20-safe.ecf" readonly="false"/>
<library name="cms_openid_module" location="..\..\modules\openid\openid-safe.ecf" readonly="false"/> <library name="cms_openid_module" location="..\..\modules\openid\openid-safe.ecf" readonly="false"/>
<library name="cms_recent_changes_module" location="..\..\modules\recent_changes\recent_changes-safe.ecf" readonly="false"/> <library name="cms_recent_changes_module" location="..\..\modules\recent_changes\recent_changes-safe.ecf" readonly="false"/>
<library name="cms_session_auth_module" location="..\..\modules\session_auth\cms_session_auth-safe.ecf" readonly="false"/>
<library name="cms_taxnomy_module" location="..\..\modules\taxonomy\taxonomy-safe.ecf" readonly="false"/>
<library name="persistence_sqlite3" location="..\..\library\persistence\sqlite3\sqlite3-safe.ecf" readonly="false"> <library name="persistence_sqlite3" location="..\..\library\persistence\sqlite3\sqlite3-safe.ecf" readonly="false">
<option> <option>
<assertions/> <assertions/>
</option> </option>
</library> </library>
<library name="persistence_store_odbc" location="..\..\library\persistence\store_odbc\store_odbc-safe.ecf"/>
<!-- <!--
<library name="persistence_store_odbc" location="..\..\library\persistence\store_odbc\store_odbc-safe.ecf"/>
<library name="persistence_store_mysql" location="..\..\library\persistence\store_mysql\store_mysql-safe.ecf" /> <library name="persistence_store_mysql" location="..\..\library\persistence\store_mysql\store_mysql-safe.ecf" />
--> -->
<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"/>
</target> </target>

View File

@@ -1,11 +1,11 @@
<?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-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="cms_demo_module" uuid="4BB59A54-2544-4C10-BFA6-01D12E541A30" library_target="cms_demo_module"> <system xmlns="http://www.eiffel.com/developers/xml/configuration-1-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="cms_demo_module" uuid="4BB59A54-2544-4C10-BFA6-01D12E541A30" library_target="cms_demo_module">
<target name="cms_demo_module"> <target name="cms_demo_module">
<root all_classes="true"/> <root all_classes="true"/>
<file_rule> <file_rule>
<exclude>/.git$</exclude> <exclude>/.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/.svn$</exclude> <exclude>/.svn$</exclude>
<exclude>/EIFGENs$</exclude>
</file_rule> </file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="standard"> <option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="standard">
</option> </option>
@@ -21,4 +21,3 @@
<cluster name="src" location=".\" recursive="true"/> <cluster name="src" location=".\" recursive="true"/>
</target> </target>
</system> </system>

View File

@@ -10,7 +10,7 @@ class
inherit inherit
CMS_MODULE CMS_MODULE
redefine redefine
register_hooks, setup_hooks,
initialize, initialize,
install install
end end
@@ -85,10 +85,10 @@ feature -- Access: router
feature -- Hooks feature -- Hooks
register_hooks (a_response: CMS_RESPONSE) setup_hooks (a_hooks: CMS_HOOK_CORE_MANAGER)
do do
a_response.hooks.subscribe_to_menu_system_alter_hook (Current) a_hooks.subscribe_to_menu_system_alter_hook (Current)
a_response.hooks.subscribe_to_block_hook (Current) a_hooks.subscribe_to_block_hook (Current)
end end
block_list: ITERABLE [like {CMS_BLOCK}.name] block_list: ITERABLE [like {CMS_BLOCK}.name]
@@ -151,7 +151,7 @@ feature -- Mapping helper: uri template
feature -- Mapping helper: uri template agent feature -- Mapping helper: uri template agent
map_uri_template_agent (a_router: WSF_ROUTER; a_tpl: READABLE_STRING_8; proc: PROCEDURE [ANY, TUPLE [req: WSF_REQUEST; res: WSF_RESPONSE]]; rqst_methods: detachable WSF_REQUEST_METHODS) map_uri_template_agent (a_router: WSF_ROUTER; a_tpl: READABLE_STRING_8; proc: PROCEDURE [WSF_REQUEST, WSF_RESPONSE]; rqst_methods: detachable WSF_REQUEST_METHODS)
-- Map `proc' as handler for `a_tpl' for request methods `rqst_methods'. -- Map `proc' as handler for `a_tpl' for request methods `rqst_methods'.
require require
a_tpl_attached: a_tpl /= Void a_tpl_attached: a_tpl /= Void

View File

@@ -4,14 +4,28 @@ root-dir=site/www
#modules-dir=site/modules #modules-dir=site/modules
[site] [site]
# Name of the site, for the title, and eventual message.
name=Eiffel CMS name=Eiffel CMS
email=your@email.com
# Email used for notification
email=noreply@example.com
# Name of website theme.
theme=bootstrap theme=bootstrap
[notification]
# By default, notification.email = site.email
# you can change here the email that will receive internal messages.
email=webmaster@example.com
[mailer] [mailer]
#smtp=localhost:25 #The mailer is used mostly used by the CMS to send email messages.
#sendmail=/usr/bin/sendmail # you can change the "From:" by setting mailer.from value"
output=@stderr subject_prefix=[Eiffel CMS]
#from=...
smtp=localhost:25
#sendmail=site\bin\roc_sendmail.bat
output=site\db\mailer.log
[modules] [modules]
# Module status # Module status

View File

@@ -0,0 +1,7 @@
{
"subject": "Thank you for contacting us",
"recaptcha": {
"site_key":"6Lex9RMTAAAAAKleC4x6TaRlFcpLbEWgH_U7MSiD",
"secret_key":"6Lex9RMTAAAAAAkBczvX5DUiyg_xoM_EthVVgRRx"
}
}

View File

@@ -0,0 +1,28 @@
ul.cms-temp-users {
list-style-type: none;
padding: 3px 3px 3px 3px;
border: solid 1px #ccc;
}
ul.cms-temp-users li {
border-top: dotted 1px #ccc;
}
ul.cms-temp-users li:first-child {
border-top: none;
}
ul.cms-temp-users li.cms_temp_user ul.cms_temp_user_details {
list-style-type: none;
padding: 3px 3px 3px 3px;
border: solid 1px #ccc;
}
ul.cms-temp-users li.cms_temp_user ul.cms_temp_user_details li {
border-top: dotted 1px #ccc;
}
ul.cms-temp-users li.cms_temp_user ul.cms_temp_user_details li:first-child {
border-top: none;
}
ul.cms-temp-users li.cms_temp_user ul.cms_temp_user_details li.cms_temp_user_detail_information::before {
content: "[personal information] ";
}
ul.cms-temp-users li.cms_temp_user ul.cms_temp_user_details li.cms_temp_user_detail_email::before {
content: "[email] ";
}

View File

@@ -0,0 +1,37 @@
ul.cms-temp-users {
list-style-type: none;
padding: 3px 3px 3px 3px;
border: solid 1px #ccc;
li{
border-top: dotted 1px #ccc;
&:first-child {
border-top: none;
}
}
li.cms_temp_user {
ul.cms_temp_user_details {
list-style-type: none;
padding: 3px 3px 3px 3px;
border: solid 1px #ccc;
li{
border-top: dotted 1px #ccc;
&:first-child {
border-top: none;
}
}
li.cms_temp_user_detail_information::before{
content: "[personal information] "
}
li.cms_temp_user_detail_email::before{
content: "[email] "
}
}
}
}

View File

@@ -4,15 +4,10 @@
<meta charset="utf-8"> <meta charset="utf-8">
<title>Activation</title> <title>Activation</title>
<meta name="description" content="Activation"> <meta name="description" content="Activation">
<meta name="author" content="ROC CMS"> <meta name="author" content="$sitename">
</head> </head>
<body> <body>
<p>Thank you for registering at <a href="$host">ROC CMS</a></p> <p>"$user ($email)", thank you for applying to <a href="$host">$sitename</a>.</p>
<p>We will review your application and send you a resolution.<p>
<p>To complete your registration, please click on this link to activate your account:<p>
<p><a href="$link">$link</a></p>
<p>Thank you for joining us.</p>
</body> </body>
</html> </html>

View File

@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Activation Confirmation</title>
<meta name="description" content="Activation Confirmation">
<meta name="author" content="$sitename">
</head>
<body>
<p>Your account "$user ($email)" is confirmed at <a href="$host">$sitename</a>.</p>
<p>Thank you for joining us.</p>
</body>
</html>

View File

@@ -4,14 +4,12 @@
<meta charset="utf-8"> <meta charset="utf-8">
<title>New Password</title> <title>New Password</title>
<meta name="description" content="New Password"> <meta name="description" content="New Password">
<meta name="author" content="ROC CMS"> <meta name="author" content="$sitename">
</head> </head>
<body> <body>
<p>You have required a new password at <a href="$host">ROC CMS</a></p> <p>You have requested a new password at <a href="$host">$sitename</a>.</p>
<p>To complete your request, please click on the following link to generate a new password:
<p>To complete your request, please click on this link to genereate a new password:<p> <ul><a href="$link">$link</a></ul>
</p>
<p><a href="$link">$link</a></p>
</body> </body>
</html> </html>

View File

@@ -4,15 +4,14 @@
<meta charset="utf-8"> <meta charset="utf-8">
<title>New Activation</title> <title>New Activation</title>
<meta name="description" content="New Activation token"> <meta name="description" content="New Activation token">
<meta name="author" content="ROC CMS"> <meta name="author" content="$sitename">
</head> </head>
<body> <body>
<p>You have request a new activation token at <a href="$host">ROC CMS</a></p> <p>You have requested a new activation token at <a href="$host">$sitename</a>.</p>
<p>To complete your registration, please click on this link to activate your account:<p> <p>To complete your registration, please click on the following link to re-activate your account:
<ul><a href="$link">$link</a></ul>
<p><a href="$link">$link</a></p> </p>
<p>Thank you for joining us.</p> <p>Thank you for joining us.</p>
</body> </body>
</html> </html>

View File

@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Application Rejected</title>
<meta name="description" content="Application Rejected">
<meta name="author" content="$sitename">
</head>
<body>
<p>Your account application is rejected, it was not respecting the requirements from <a href="$host">$sitename</a>.</p>
</body>
</html>

View File

@@ -4,10 +4,16 @@
<meta charset="utf-8"> <meta charset="utf-8">
<title>Welcome</title> <title>Welcome</title>
<meta name="description" content="Welcome"> <meta name="description" content="Welcome">
<meta name="author" content="ROC CMS"> <meta name="author" content="$sitename">
</head> </head>
<body> <body>
<p>Welcome to<a href="$host">ROC CMS</a></p> <p>Welcome to <a href="$host">$sitename</a>.</p>
<p>Your account information:
<ul>
<li>Email address: "$email" .</li>
<li>User name: "$user" .</li>
</ul>
</p>
<p>Thank you for joining us.</p> <p>Thank you for joining us.</p>
</body> </body>
</html> </html>

View File

@@ -0,0 +1,26 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Account Evaluation</title>
<meta name="description" content="Account Evaluation">
<meta name="author" content="$sitename">
</head>
<body>
<h2> Account Evaluation </h2>
<p>The user $user ($email) wants to register to the site <a href="$host">$sitename</a></p>
<blockquote><p>User application:</p>
<p>$application</p>
</blockquote>
<p>To complete the registration, please click on the following link to activate the user account:<p>
<p><a href="$activation_url">$activation_url</a></p>
<p>To reject the registration, please click on the following link <p>
<p><a href="$rejection_url<">$rejection_url</a></p>
</body>
</html>

View File

@@ -1,3 +1,3 @@
<div> <div>
<p>We have send you a new activation code, check your email to activate your account.</p> <p>Thanks for your application, we will review it to activate your account.</p>
</div> </div>

View File

@@ -1,3 +1,3 @@
<div> <div>
<p>Thanks for register, check your email to activate your account.</p> <p>Thanks for your application, we will review it to activate your account.</p>
</div> </div>

View File

@@ -1,7 +1,7 @@
<div> <div>
<form action="{$site_url/}account/roc-register" method="post"> <form action="{$site_url/}account/roc-register" method="post">
<fieldset> <fieldset>
<legend>Register Form</legend> <legend>Registration</legend>
<div> <div>
<input type="text" id="name" name="name" value="{$name/}" required autofocus /> <input type="text" id="name" name="name" value="{$name/}" required autofocus />
<label for="name">Name</label> <label for="name">Name</label>
@@ -20,8 +20,19 @@
<span><i>{$error_email/}</i></span> <br> <span><i>{$error_email/}</i></span> <br>
{/if} {/if}
</div> </div>
<div>
<textarea rows="4" cols="50" name="personal_information" id="personal_information" required>
{$personal_information/}
</textarea>
<label for="personal_information">Tell us why you want to register an account</label>
{if isset="$error_application"}
<span><i>{$error_application/}</i></span> <br>
{/if}
</div>
{unless isempty="$recaptcha_site_key"}
<div class="g-recaptcha" data-sitekey="{$recaptcha_site_key/}"></div>
<br/>
{/unless}
<button type="submit">Register</button> <button type="submit">Register</button>
</fieldset> </fieldset>
</form> </form>

View File

@@ -11,7 +11,7 @@ ROC_AUTH.login = function() {
var username = form.username.value; var username = form.username.value;
var password = form.password.value; var password = form.password.value;
//var host = form.host.value; //var host = form.host.value;
var origin = window.location.origin.concat(window.location.pathname); var origin = window.location.origin + window.location.pathname;
var _login = function(){ var _login = function(){
@@ -322,4 +322,4 @@ ROC_AUTH.validatePassword =function(){
if ((password != null) && (confirm_password != null)) { if ((password != null) && (confirm_password != null)) {
password.onchange = ROC_AUTH.validatePassword(); password.onchange = ROC_AUTH.validatePassword();
confirm_password.onkeyup = ROC_AUTH.validatePassword; confirm_password.onkeyup = ROC_AUTH.validatePassword;
} }

View File

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

@@ -0,0 +1,37 @@
<div class="primary-tabs">
{unless isset="$user"}
<h3>Login or <a href="{$site_url/}account/roc-register">Register</a></h3>
<div>
<div>
<form name="cms_session_auth" action="{$site_url/}account/login-with-session" method="POST">
<div>
<input type="text" name="username" id="username" required value="{$username/}">
<label>Username</label>
</div>
<div>
<input type="password" name="password" id="password" required >
<label>Password</label>
</div>
<button type="submit">Login</button>
</form>
</div>
</div>
<div>
<div>
<p>
<a href="{$site_url/}account/new-password">Forgot password?</a>
</p>
</div>
</div>
{/unless}
{if isset=$error}
<div>
<div>
<p>
<strong>{$error/}
</p>
</div>
</div>
{/if}
</div>

View File

@@ -19,3 +19,8 @@ ul.taxonomy li:hover {
border-bottom: solid 1px #66f; border-bottom: solid 1px #66f;
background-color: #ddf; background-color: #ddf;
} }
table.taxonomy td {
border: solid 1px #ccc;
padding: 2px;
}

View File

@@ -19,3 +19,9 @@ ul.taxonomy {
} }
} }
} }
table.taxonomy {
td {
border: solid 1px #ccc;
padding: 2px;
}
}

View File

@@ -46,3 +46,18 @@ CREATE TABLE `users_password_recovery` (
CONSTRAINT `token` UNIQUE (`token`) CONSTRAINT `token` UNIQUE (`token`)
); );
CREATE TABLE `auth_temp_users` (
`uid` INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL,
`name` VARCHAR(100) NOT NULL,
`password` VARCHAR(100) NOT NULL,
`salt` VARCHAR(100) NOT NULL,
`email` VARCHAR(250) NOT NULL,
`application` TEXT NOT NULL,
CONSTRAINT `name`
UNIQUE(`name`)
);

View File

@@ -90,3 +90,11 @@ ul.horizontal li {
border: solid 1px red; border: solid 1px red;
padding: 5px 2px 5px 2px; padding: 5px 2px 5px 2px;
} }
table.with_border thead td {
font-weight: bold;
}
table.with_border td {
border: solid 1px #ccc;
padding: 2px 5px 2px 5px;
}

View File

@@ -95,3 +95,13 @@ ul.horizontal {
border: solid 1px red; border: solid 1px red;
padding: 5px 2px 5px 2px; padding: 5px 2px 5px 2px;
} }
table.with_border {
thead td {
font-weight: bold;
}
td {
border: solid 1px #ccc;
padding: 2px 5px 2px 5px;
}
}

View File

@@ -35,60 +35,41 @@ feature -- CMS storage
do do
a_setup.storage_drivers.force (create {CMS_STORAGE_SQLITE3_BUILDER}.make, "sqlite3") a_setup.storage_drivers.force (create {CMS_STORAGE_SQLITE3_BUILDER}.make, "sqlite3")
-- a_setup.storage_drivers.force (create {CMS_STORAGE_STORE_MYSQL_BUILDER}.make, "mysql") -- a_setup.storage_drivers.force (create {CMS_STORAGE_STORE_MYSQL_BUILDER}.make, "mysql")
a_setup.storage_drivers.force (create {CMS_STORAGE_STORE_ODBC_BUILDER}.make, "odbc") -- a_setup.storage_drivers.force (create {CMS_STORAGE_STORE_ODBC_BUILDER}.make, "odbc")
end end
feature -- CMS modules feature -- CMS modules
setup_modules (a_setup: CMS_SETUP) setup_modules (a_setup: CMS_SETUP)
-- Setup additional modules. -- Setup additional modules.
local
m: CMS_MODULE
do do
create {CMS_ADMIN_MODULE} m.make -- Admin
a_setup.register_module (m) a_setup.register_module (create {CMS_ADMIN_MODULE}.make)
-- Auth -- Auth
create {CMS_AUTHENTICATION_MODULE} m.make a_setup.register_module (create {CMS_AUTHENTICATION_MODULE}.make)
a_setup.register_module (m) a_setup.register_module (create {CMS_BASIC_AUTH_MODULE}.make)
a_setup.register_module (create {CMS_OAUTH_20_MODULE}.make)
create {CMS_BASIC_AUTH_MODULE} m.make a_setup.register_module (create {CMS_OPENID_MODULE}.make)
a_setup.register_module (m)
create {CMS_OAUTH_20_MODULE} m.make
a_setup.register_module (m)
create {CMS_OPENID_MODULE} m.make
a_setup.register_module (m)
-- Nodes -- Nodes
create {CMS_NODE_MODULE} m.make (a_setup) a_setup.register_module (create {CMS_NODE_MODULE}.make (a_setup))
a_setup.register_module (m) a_setup.register_module (create {CMS_BLOG_MODULE}.make)
create {CMS_BLOG_MODULE} m.make
a_setup.register_module (m)
-- Taxonomy -- Taxonomy
create {CMS_TAXONOMY_MODULE} m.make a_setup.register_module (create {CMS_TAXONOMY_MODULE}.make)
a_setup.register_module (m)
-- Recent changes -- Recent changes
create {CMS_RECENT_CHANGES_MODULE} m.make a_setup.register_module (create {CMS_RECENT_CHANGES_MODULE}.make)
a_setup.register_module (m)
-- Recent changes -- Feed aggregator
create {FEED_AGGREGATOR_MODULE} m.make a_setup.register_module (create {FEED_AGGREGATOR_MODULE}.make)
a_setup.register_module (m)
-- Miscellanious -- Miscellanious
create {CMS_DEBUG_MODULE} m.make a_setup.register_module (create {CMS_DEBUG_MODULE}.make)
a_setup.register_module (m) a_setup.register_module (create {CMS_DEMO_MODULE}.make)
a_setup.register_module (create {GOOGLE_CUSTOM_SEARCH_MODULE}.make)
create {CMS_DEMO_MODULE} m.make a_setup.register_module (create {CMS_SESSION_AUTH_MODULE}.make)
a_setup.register_module (m)
create {GOOGLE_CUSTOM_SEARCH_MODULE} m.make
a_setup.register_module (m)
end end
end end

View File

@@ -35,12 +35,14 @@ feature {NONE} -- Initialization
parameters: EMAIL_SERVICE_PARAMETERS parameters: EMAIL_SERVICE_PARAMETERS
-- Associated parameters. -- Associated parameters.
admin_email: IMMUTABLE_STRING_8
-- Site admin's email.
mailer: NOTIFICATION_MAILER mailer: NOTIFICATION_MAILER
-- SMTP protocol. -- SMTP protocol.
feature -- Access
admin_email: IMMUTABLE_STRING_8
-- Site admin's email.
feature -- Basic Operations feature -- Basic Operations
send_internal_email (a_content: READABLE_STRING_GENERAL) send_internal_email (a_content: READABLE_STRING_GENERAL)

View File

@@ -0,0 +1,45 @@
note
description: "User for temporary account."
date: "$Date$"
revision: "$Revision$"
class
CMS_TEMP_USER
inherit
CMS_USER
create
make,
make_with_id
feature -- Access
personal_information: detachable STRING_32
-- User personal information.
salt: detachable STRING_32
-- User's password salt.
feature -- Element change
set_personal_information (a_personal_information: like personal_information)
-- Assign `personal_information' with `a_personal_information'.
do
personal_information := a_personal_information
ensure
personal_information_assigned: personal_information = a_personal_information
end
set_salt (a_salt: like salt)
-- Assign `salt' with `a_salt'.
do
salt := a_salt
ensure
salt_assigned: salt = a_salt
end
note
copyright: "2011-2016, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end

View File

@@ -62,7 +62,7 @@ feature -- Access
hashed_password: detachable READABLE_STRING_8 hashed_password: detachable READABLE_STRING_8
-- Hashed user password. -- Hashed user password.
email: detachable READABLE_STRING_32 email: detachable READABLE_STRING_8
-- User email. -- User email.
profile: detachable CMS_USER_PROFILE profile: detachable CMS_USER_PROFILE
@@ -80,7 +80,6 @@ feature -- Access
-- active -- active
-- trashed -- trashed
feature -- Access: helper feature -- Access: helper
utf_8_name: STRING_8 utf_8_name: STRING_8
@@ -302,6 +301,6 @@ invariant
id_or_name_set: id > 0 or else not name.is_whitespace id_or_name_set: id > 0 or else not name.is_whitespace
note note
copyright: "2011-2015, Javier Velilla, Jocelyn Fiat, Eiffel Software and others" copyright: "2011-2016, Javier Velilla, Jocelyn Fiat, 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)"
end end

View File

@@ -152,6 +152,7 @@ feature -- Query
-- Retrieved value at `a_index' position in `item'. -- Retrieved value at `a_index' position in `item'.
local local
l_item: like sql_item l_item: like sql_item
i64: INTEGER_64
do do
l_item := sql_item (a_index) l_item := sql_item (a_index)
if attached {INTEGER_32} l_item as i then if attached {INTEGER_32} l_item as i then
@@ -159,7 +160,18 @@ feature -- Query
elseif attached {INTEGER_32_REF} l_item as l_value then elseif attached {INTEGER_32_REF} l_item as l_value then
Result := l_value.item Result := l_value.item
else else
check is_integer_32: False end if attached {INTEGER_64} l_item as i then
i64 := i
elseif attached {INTEGER_64_REF} l_item as l_value then
i64 := l_value.item
else
check is_integer_32: False end
end
if i64 <= {INTEGER_32}.max_value then
Result := i64.to_integer_32
else
check is_integer_32: False end
end
end end
end end

View File

@@ -80,7 +80,7 @@ feature -- Cursor
feature -- Action feature -- Action
action: FUNCTION [ANY, detachable TUPLE, G] action: FUNCTION [detachable TUPLE, G]
-- Agent to create a new item of type G. -- Agent to create a new item of type G.
feature {NONE} -- Implementation feature {NONE} -- Implementation

View File

@@ -1,30 +0,0 @@
BEGIN;
CREATE TABLE `logs` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`category` VARCHAR(255) NOT NULL,
`level` int(11) NOT NULL,
`uid` int(11) DEFAULT NULL,
`message` text NOT NULL,
`info` text,
`link` text,
`date` datetime NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `custom_values` (
`type` VARCHAR(255) NOT NULL,
`name` VARCHAR(255) NOT NULL,
`value` VARCHAR(255) NOT NULL
);
CREATE TABLE `path_aliases` (
`pid` int(11) NOT NULL AUTO_INCREMENT,
`source` varchar(255) NOT NULL,
`alias` varchar(255) NOT NULL,
`lang` varchar(12) DEFAULT NULL,
PRIMARY KEY (`pid`)
);
COMMIT;

View File

@@ -1,24 +0,0 @@
BEGIN;
CREATE TABLE nodes (
nid INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL CHECK( nid >=0),
revision INTEGER,
type TEXT NOT NULL,
title VARCHAR(255) NOT NULL,
summary TEXT,
content MEDIUMTEXT NOT NULL,
format VARCHAR(255),
author INTEGER,
publish DATETIME,
created DATETIME NOT NULL,
changed DATETIME NOT NULL,
status INTEGER
);
CREATE TABLE page_nodes(
nid INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL CHECK( nid >=0),
revision INTEGER,
parent INTEGER
);
COMMIT;

View File

@@ -1,66 +0,0 @@
BEGIN;
CREATE TABLE `users` (
`uid` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
`password` varchar(100) NOT NULL,
`salt` varchar(100) NOT NULL,
`email` varchar(250) NOT NULL,
`status` int(11) DEFAULT NULL,
`created` datetime NOT NULL,
`signed` datetime DEFAULT NULL,
CHECK (`uid` >= 0),
PRIMARY KEY (`uid`),
UNIQUE KEY `name` (`name`)
);
CREATE TABLE `roles` (
`rid` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
CHECK (`rid` >= 0),
PRIMARY KEY (`rid`),
UNIQUE KEY `name` (`name`)
);
CREATE TABLE `users_roles` (
`uid` int(11) NOT NULL,
`rid` int(11) NOT NULL,
CHECK (`uid` >= 0),
CHECK (`rid` >= 0)
);
CREATE TABLE `role_permissions` (
`rid` int(11) NOT NULL,
`permission` varchar(255) NOT NULL,
`module` varchar(255) DEFAULT NULL,
CHECK (`rid` >= 0)
);
CREATE TABLE `users_activations` (
`aid` int(11) NOT NULL AUTO_INCREMENT,
`token` varchar(255) NOT NULL,
`uid` int(11) NOT NULL,
`created` datetime NOT NULL,
CHECK (`aid` >= 0),
CHECK (`uid` >= 0),
PRIMARY KEY (`aid`),
UNIQUE KEY `token` (`token`)
);
CREATE TABLE `users_password_recovery` (
`aid` int(11) NOT NULL AUTO_INCREMENT,
`token` varchar(255) NOT NULL,
`uid` int(11) NOT NULL,
`created` datetime NOT NULL,
CHECK (`aid` >= 0),
CHECK (`uid` >= 0),
PRIMARY KEY (`aid`),
UNIQUE KEY `token` (`token`)
);
COMMIT;

View File

@@ -0,0 +1,4 @@
Recaptcha Eiffel Lbrary
Based on https://developers.google.com/recaptcha/

View File

@@ -0,0 +1,10 @@
${NOTE_KEYWORD}
copyright: "2011-${YEAR} Javier Velilla, Jocelyn Fiat, 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
]"

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="recaptcha" uuid="2A966489-284A-48A0-91BC-31E84EA9C3B1" library_target="recaptcha">
<target name="recaptcha">
<root all_classes="true"/>
<file_rule>
<exclude>/.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" is_obsolete_routine_type="true" void_safety="all">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<setting name="console_application" value="true"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="http_client_extension" location="..\http_client_extension\http_client_extension-safe.ecf"/>
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json-safe.ecf" readonly="false"/>
<cluster name="recaptcha" location=".\src\" recursive="true"/>
</target>
</system>

View File

@@ -0,0 +1,22 @@
<?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="recaptcha" uuid="2A966489-284A-48A0-91BC-31E84EA9C3B1" library_target="recaptcha">
<target name="recaptcha">
<root all_classes="true"/>
<file_rule>
<exclude>/.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" void_safety="none">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<setting name="console_application" value="true"/>
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
<library name="base_extension" location="$ISE_LIBRARY\library\base_extension\base_extension.ecf"/>
<library name="http_client_extension" location="..\http_client_extension\http_client_extension.ecf"/>
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json.ecf" readonly="false"/>
<cluster name="recaptcha" location=".\src\" recursive="true">
</cluster>
</target>
</system>

View File

@@ -0,0 +1,147 @@
note
description: "[
Simple API to call {RECAPTCHA} Google API.
Example call:
https://www.google.com/recaptcha/api/siteverify?secret=your_secret&response=response_string&remoteip=user_ip_address
]"
date: "$Date: 2015-01-28 11:44:15 -0300 (mi. 28 de ene. de 2015) $"
revision: "$Revision: 96551 $"
EIS: "name=RECAPTCHA", "src=https://developers.google.com/recaptcha/", "protocol=uri"
EIS: "name=RECAPTCHA API verify", "src=https://developers.google.com/recaptcha/docs/verify", "protocol=uri"
class
RECAPTCHA_API
create
make
feature {NONE} -- Initialization
make (a_secret_key, a_response: READABLE_STRING_8)
-- Create an object Recaptcha with secret key `a_secret_key' and response token `a_response'.
do
secret := a_secret_key
response := a_response
ensure
secret_set: secret.same_string (a_secret_key)
response_set: response.same_string (a_response)
end
feature -- Access
base_uri: STRING_8 = "https://www.google.com/recaptcha/api/siteverify"
-- Recaptcha base URI
secret: READABLE_STRING_8
-- Required. The shared key between your site and ReCAPTCHA.
response: READABLE_STRING_8
-- Required. The user response token provided by the reCAPTCHA to the user and provided to your site on.
remoteip: detachable READABLE_STRING_8
-- Optional. The user's IP address.
feature -- Status Reports
errors: detachable LIST [READABLE_STRING_8]
-- optional table of error codes
-- missing-input-secret The secret parameter is missing.
-- invalid-input-secret The secret parameter is invalid or malformed.
-- missing-input-response The response parameter is missing.
-- invalid-input-response The response parameter is invalid or malformed.
feature -- Change Element
set_remoteip (a_remoteip: READABLE_STRING_8)
-- Set `remoteip' with `a_remoteip'.
do
remoteip := a_remoteip
ensure
remoteip_set: remoteip = a_remoteip
end
feature -- API
verify: BOOLEAN
-- Verify the user's response
local
l_parser: JSON_PARSER
do
if attached get as l_response then
if attached l_response.body as l_body then
create l_parser.make_with_string (l_body)
l_parser.parse_content
if
l_parser.is_parsed and then attached {JSON_OBJECT} l_parser.parsed_json_object as jv and then
attached {JSON_BOOLEAN} jv.item ("success") as l_success
then
Result := l_success.item
if not Result and then attached {JSON_ARRAY} jv.item ("error-codes") as l_error_codes then
across
l_error_codes as c
loop
if attached {JSON_STRING} c.item as ji then
put_error (ji.unescaped_string_32)
end
end
end
end
else
put_error (l_response.status.out)
end
else
put_error ("unknown")
end
end
feature {NONE} -- REST API
get: detachable RESPONSE
-- Reading Data
local
l_request: REQUEST
do
create l_request.make ("GET", new_uri)
Result := l_request.execute
end
feature {NONE} -- Implementation
new_uri: STRING_8
-- new uri (BaseUri?secret=secret_value&response=response_value[&remoteip=remoteip_value]
do
create Result.make_from_string (base_uri)
Result.append ("?secret=")
Result.append (secret)
Result.append ("&response=")
Result.append (response)
if attached remoteip as l_remoteip then
Result.append ("&remoteip=" + l_remoteip)
end
end
put_error (a_code: READABLE_STRING_GENERAL)
local
l_errors: like errors
utf: UTF_CONVERTER
do
l_errors := errors
if l_errors = Void then
create {ARRAYED_LIST [STRING]} l_errors.make (1)
errors := l_errors
end
l_errors.force (utf.utf_32_string_to_utf_8_string_8 (a_code))
end
note
copyright: "2011-2015 Javier Velilla, Jocelyn Fiat, 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,61 @@
note
description : "test application root class"
date : "$Date: 2015-01-14 15:37:57 -0300 (mi. 14 de ene. de 2015) $"
revision : "$Revision: 96458 $"
class
APPLICATION
inherit
ARGUMENTS
create
make
feature {NONE} -- Initialization
make
-- Run application.
do
test_invalid_input
test_missing_input
test_missing_key_input
end
test_invalid_input
-- invalid-input-response
local
l_captcha: RECAPTCHA_API
do
create l_captcha.make ("","234")
check
not_true:not l_captcha.verify
end
end
test_missing_input
-- missing-input-response
local
l_captcha: RECAPTCHA_API
do
create l_captcha.make ("key","")
check
not_true:not l_captcha.verify
end
end
test_missing_key_input
-- missing-input-response
-- invalid-input-response
local
l_captcha: RECAPTCHA_API
do
create l_captcha.make ("","")
l_captcha.set_remoteip("localhost")
check
not_true:not l_captcha.verify
end
end
end

View File

@@ -0,0 +1,69 @@
note
description: "[
Eiffel tests that can be executed by testing tool.
]"
author: "EiffelStudio test wizard"
date: "$Date: 2015-01-14 15:37:57 -0300 (mi. 14 de ene. de 2015) $"
revision: "$Revision: 96458 $"
testing: "type/manual"
class
RECAPTCHA_API_TEST_SET
inherit
EQA_TEST_SET
feature -- Test routines
test_invalid_input
-- invalid-input-response
local
l_captcha: RECAPTCHA_API
do
create l_captcha.make ("","234")
check
not_true:not l_captcha.verify
end
assert ("Not true", not l_captcha.verify)
assert ("Has error invalid-input-response",has_error (l_captcha,"invalid-input-response"))
end
test_missing_input
-- missing-input-response
local
l_captcha: RECAPTCHA_API
do
create l_captcha.make ("key","")
check
not_true:not l_captcha.verify
end
assert ("Not true", not l_captcha.verify)
assert ("Has error missing-input-response",has_error (l_captcha,"missing-input-response"))
end
test_missing_key_input
-- missing-input-response
-- invalid-input-response
local
l_captcha: RECAPTCHA_API
do
create l_captcha.make ("","")
l_captcha.set_remoteip("localhost")
assert ("Not true", not l_captcha.verify)
assert ("Has error missing-input-response",has_error (l_captcha,"missing-input-response"))
assert ("Has error invalid-input-response",has_error (l_captcha,"invalid-input-response"))
end
feature {NONE} -- Implementation
has_error (l_captcha: RECAPTCHA_API; a_error: READABLE_STRING_32): BOOLEAN
do
if attached l_captcha.errors as l_errors then
l_errors.compare_objects
Result := l_errors.has (a_error)
end
end
end

View File

@@ -0,0 +1,21 @@
<?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="test" uuid="CE9FCE69-EE0A-4028-AA02-BD9F8ABA7586">
<target name="test">
<root class="APPLICATION" feature="make"/>
<option warning="true" void_safety="transitional">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<setting name="console_application" value="true"/>
<precompile name="base_pre" location="$ISE_PRECOMP\base-safe.ecf"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="recaptcha" location="..\recaptcha-safe.ecf" readonly="false"/>
<library name="testing" location="$ISE_LIBRARY\library\testing\testing-safe.ecf"/>
<cluster name="test" location=".\" recursive="true">
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
</cluster>
</target>
</system>

View File

@@ -9,7 +9,7 @@ class
inherit inherit
CMS_MODULE CMS_MODULE
redefine redefine
register_hooks, setup_hooks,
permissions permissions
end end
@@ -116,11 +116,11 @@ feature -- Security
feature -- Hooks feature -- Hooks
register_hooks (a_response: CMS_RESPONSE) setup_hooks (a_hooks: CMS_HOOK_CORE_MANAGER)
-- <Precursor> -- <Precursor>
do do
a_response.hooks.subscribe_to_menu_system_alter_hook (Current) a_hooks.subscribe_to_menu_system_alter_hook (Current)
a_response.hooks.subscribe_to_response_alter_hook (Current) a_hooks.subscribe_to_response_alter_hook (Current)
end end
response_alter (a_response: CMS_RESPONSE) response_alter (a_response: CMS_RESPONSE)

View File

@@ -44,7 +44,7 @@ feature -- Execution
create {GENERIC_VIEW_CMS_RESPONSE} l_response.make (req, res, api) create {GENERIC_VIEW_CMS_RESPONSE} l_response.make (req, res, api)
f := clear_cache_web_form (l_response) f := clear_cache_web_form (l_response)
create s.make_empty create s.make_empty
f.append_to_html (create {CMS_TO_WSF_THEME}.make (l_response, l_response.theme), s) f.append_to_html (l_response.wsf_theme, s)
l_response.set_main_content (s) l_response.set_main_content (s)
l_response.execute l_response.execute
end end
@@ -63,14 +63,14 @@ feature -- Execution
fd.is_valid fd.is_valid
then then
if attached fd.string_item ("op") as l_op and then l_op.same_string (text_clear_all_caches) then if attached fd.string_item ("op") as l_op and then l_op.same_string (text_clear_all_caches) then
l_response.hooks.invoke_clear_cache (Void, l_response) api.hooks.invoke_clear_cache (Void, l_response)
l_response.add_notice_message ("Caches cleared (if allowed)!") l_response.add_notice_message ("Caches cleared (if allowed)!")
else else
fd.report_error ("Invalid form data!") fd.report_error ("Invalid form data!")
end end
end end
create s.make_empty create s.make_empty
f.append_to_html (create {CMS_TO_WSF_THEME}.make (l_response, l_response.theme), s) f.append_to_html (l_response.wsf_theme, s)
l_response.set_main_content (s) l_response.set_main_content (s)
l_response.execute l_response.execute
end end

View File

@@ -44,7 +44,7 @@ feature -- Execution
create {GENERIC_VIEW_CMS_RESPONSE} l_response.make (req, res, api) create {GENERIC_VIEW_CMS_RESPONSE} l_response.make (req, res, api)
f := exportation_web_form (l_response) f := exportation_web_form (l_response)
create s.make_empty create s.make_empty
f.append_to_html (create {CMS_TO_WSF_THEME}.make (l_response, l_response.theme), s) f.append_to_html (l_response.wsf_theme, s)
l_response.set_main_content (s) l_response.set_main_content (s)
l_response.execute l_response.execute
end end
@@ -69,8 +69,7 @@ feature -- Execution
else else
create l_exportation_parameters.make (api.site_location.extended ("export").extended ((create {DATE_TIME}.make_now_utc).formatted_out ("yyyy-[0]mm-[0]dd---hh24-[0]mi-[0]ss"))) create l_exportation_parameters.make (api.site_location.extended ("export").extended ((create {DATE_TIME}.make_now_utc).formatted_out ("yyyy-[0]mm-[0]dd---hh24-[0]mi-[0]ss")))
end end
api.hooks.invoke_export_to (Void, l_exportation_parameters, l_response)
l_response.hooks.invoke_export_to (Void, l_exportation_parameters, l_response)
l_response.add_notice_message ("All data exported (if allowed)!") l_response.add_notice_message ("All data exported (if allowed)!")
create s.make_empty create s.make_empty
across across
@@ -86,7 +85,7 @@ feature -- Execution
end end
end end
create s.make_empty create s.make_empty
f.append_to_html (create {CMS_TO_WSF_THEME}.make (l_response, l_response.theme), s) f.append_to_html (l_response.wsf_theme, s)
l_response.set_main_content (s) l_response.set_main_content (s)
l_response.execute l_response.execute
end end

View File

@@ -88,7 +88,7 @@ feature -- Execution
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
f := modules_collection_web_form (r) f := modules_collection_web_form (r)
create s.make_empty create s.make_empty
f.append_to_html (create {CMS_TO_WSF_THEME}.make (r, r.theme), s) f.append_to_html (r.wsf_theme, s)
r.set_page_title ("Modules") r.set_page_title ("Modules")
r.set_main_content (s) r.set_main_content (s)
r.execute r.execute
@@ -133,7 +133,7 @@ feature -- Execution
then then
r.add_error_message ("Error occurred.") r.add_error_message ("Error occurred.")
create s.make_empty create s.make_empty
f.append_to_html (create {CMS_TO_WSF_THEME}.make (r, r.theme), s) f.append_to_html (r.wsf_theme, s)
r.set_page_title ("Modules") r.set_page_title ("Modules")
r.set_main_content (s) r.set_main_content (s)
else else

View File

@@ -8,30 +8,10 @@ class
inherit inherit
CMS_RESPONSE CMS_RESPONSE
redefine
make,
initialize
end
create create
make make
feature {NONE} -- Initialization
make (req: WSF_REQUEST; res: WSF_RESPONSE; a_api: like api)
do
create {WSF_NULL_THEME} wsf_theme.make
Precursor (req, res, a_api)
end
initialize
do
Precursor
create {CMS_TO_WSF_THEME} wsf_theme.make (Current, theme)
end
wsf_theme: WSF_THEME
feature -- Process feature -- Process
process process

View File

@@ -8,32 +8,12 @@ class
inherit inherit
CMS_RESPONSE CMS_RESPONSE
redefine
make,
initialize
end
CMS_SHARED_SORTING_UTILITIES CMS_SHARED_SORTING_UTILITIES
create create
make make
feature {NONE} -- Initialization
make (req: WSF_REQUEST; res: WSF_RESPONSE; a_api: like api)
do
create {WSF_NULL_THEME} wsf_theme.make
Precursor (req, res, a_api)
end
initialize
do
Precursor
create {CMS_TO_WSF_THEME} wsf_theme.make (Current, theme)
end
wsf_theme: WSF_THEME
feature -- Query feature -- Query
role_id_path_parameter (req: WSF_REQUEST): INTEGER_64 role_id_path_parameter (req: WSF_REQUEST): INTEGER_64
@@ -84,7 +64,7 @@ feature -- Process Edit
do do
create b.make_empty create b.make_empty
f := new_edit_form (a_role, url (request.percent_encoded_path_info, Void), "edit-user") f := new_edit_form (a_role, url (request.percent_encoded_path_info, Void), "edit-user")
hooks.invoke_form_alter (f, fd, Current) api.hooks.invoke_form_alter (f, fd, Current)
if request.is_post_request_method then if request.is_post_request_method then
f.validation_actions.extend (agent edit_form_validate(?,a_role, b)) f.validation_actions.extend (agent edit_form_validate(?,a_role, b))
f.submit_actions.extend (agent edit_form_submit(?, a_role, b)) f.submit_actions.extend (agent edit_form_submit(?, a_role, b))
@@ -117,7 +97,7 @@ feature -- Process Delete
do do
create b.make_empty create b.make_empty
f := new_delete_form (a_role, url (request.percent_encoded_path_info, Void), "edit-user") f := new_delete_form (a_role, url (request.percent_encoded_path_info, Void), "edit-user")
hooks.invoke_form_alter (f, fd, Current) api.hooks.invoke_form_alter (f, fd, Current)
if request.is_post_request_method then if request.is_post_request_method then
f.process (Current) f.process (Current)
fd := f.last_data fd := f.last_data
@@ -149,7 +129,7 @@ feature -- Process New
do do
create b.make_empty create b.make_empty
f := new_edit_form (l_role, url (request.percent_encoded_path_info, Void), "create-role") f := new_edit_form (l_role, url (request.percent_encoded_path_info, Void), "create-role")
hooks.invoke_form_alter (f, fd, Current) api.hooks.invoke_form_alter (f, fd, Current)
if request.is_post_request_method then if request.is_post_request_method then
f.validation_actions.extend (agent new_form_validate(?, b)) f.validation_actions.extend (agent new_form_validate(?, b))
f.submit_actions.extend (agent edit_form_submit(?, l_role, b)) f.submit_actions.extend (agent edit_form_submit(?, l_role, b))

View File

@@ -8,31 +8,10 @@ class
inherit inherit
CMS_RESPONSE CMS_RESPONSE
redefine
make,
initialize
end
create create
make make
feature {NONE} -- Initialization
make (req: WSF_REQUEST; res: WSF_RESPONSE; a_api: like api;)
do
create {WSF_NULL_THEME} wsf_theme.make
Precursor (req, res, a_api)
end
initialize
do
Precursor
create {CMS_TO_WSF_THEME} wsf_theme.make (Current, theme)
end
wsf_theme: WSF_THEME
feature -- Query feature -- Query
role_id_path_parameter (req: WSF_REQUEST): INTEGER_64 role_id_path_parameter (req: WSF_REQUEST): INTEGER_64

View File

@@ -7,32 +7,11 @@ class
CMS_USER_FORM_RESPONSE CMS_USER_FORM_RESPONSE
inherit inherit
CMS_RESPONSE CMS_RESPONSE
redefine
make,
initialize
end
create create
make make
feature {NONE} -- Initialization
make (req: WSF_REQUEST; res: WSF_RESPONSE; a_api: like api)
do
create {WSF_NULL_THEME} wsf_theme.make
Precursor (req, res, a_api)
end
initialize
do
Precursor
create {CMS_TO_WSF_THEME} wsf_theme.make (Current, theme)
end
wsf_theme: WSF_THEME
feature -- Query feature -- Query
user_id_path_parameter (req: WSF_REQUEST): INTEGER_64 user_id_path_parameter (req: WSF_REQUEST): INTEGER_64
@@ -86,7 +65,7 @@ feature -- Process Edit
do do
create b.make_empty create b.make_empty
f := new_edit_form (a_user, url (location, Void), "edit-user") f := new_edit_form (a_user, url (location, Void), "edit-user")
hooks.invoke_form_alter (f, fd, Current) api.hooks.invoke_form_alter (f, fd, Current)
if request.is_post_request_method then if request.is_post_request_method then
f.submit_actions.extend (agent edit_form_submit (?, a_user, b)) f.submit_actions.extend (agent edit_form_submit (?, a_user, b))
f.process (Current) f.process (Current)
@@ -118,7 +97,7 @@ feature -- Process Delete
do do
create b.make_empty create b.make_empty
f := new_delete_form (a_user, url (location, Void), "edit-user") f := new_delete_form (a_user, url (location, Void), "edit-user")
hooks.invoke_form_alter (f, fd, Current) api.hooks.invoke_form_alter (f, fd, Current)
if request.is_post_request_method then if request.is_post_request_method then
f.process (Current) f.process (Current)
fd := f.last_data fd := f.last_data
@@ -151,7 +130,7 @@ feature -- Process New
do do
create b.make_empty create b.make_empty
f := new_edit_form (l_user, url (location, Void), "create-user") f := new_edit_form (l_user, url (location, Void), "create-user")
hooks.invoke_form_alter (f, fd, Current) api.hooks.invoke_form_alter (f, fd, Current)
if request.is_post_request_method then if request.is_post_request_method then
f.validation_actions.extend (agent new_form_validate (?, b)) f.validation_actions.extend (agent new_form_validate (?, b))
f.submit_actions.extend (agent edit_form_submit (?, l_user, b)) f.submit_actions.extend (agent edit_form_submit (?, l_user, b))

View File

@@ -8,31 +8,10 @@ class
inherit inherit
CMS_RESPONSE CMS_RESPONSE
redefine
make,
initialize
end
create create
make make
feature {NONE} -- Initialization
make (req: WSF_REQUEST; res: WSF_RESPONSE; a_api: like api;)
do
create {WSF_NULL_THEME} wsf_theme.make
Precursor (req, res, a_api)
end
initialize
do
Precursor
create {CMS_TO_WSF_THEME} wsf_theme.make (Current, theme)
end
wsf_theme: WSF_THEME
feature -- Query feature -- Query
user_id_path_parameter (req: WSF_REQUEST): INTEGER_64 user_id_path_parameter (req: WSF_REQUEST): INTEGER_64
@@ -94,7 +73,7 @@ feature -- Execution
s.append ("<div class=%"info%"> ") s.append ("<div class=%"info%"> ")
s.append ("<h4>Account Information</h4>") s.append ("<h4>Account Information</h4>")
s.append ("<p>Username: ") s.append ("<p>Username: ")
s.append (a_user.name) s.append (html_encoded (a_user.name))
s.append ("</p>") s.append ("</p>")
if attached a_user.email as l_email then if attached a_user.email as l_email then
s.append ("<p>Email: ") s.append ("<p>Email: ")

View File

@@ -1,34 +1,31 @@
<?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-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="auth_module" uuid="AAB9EE7D-A671-4727-8658-D417A48B2B57" library_target="auth_module"> <system xmlns="http://www.eiffel.com/developers/xml/configuration-1-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="auth_module" uuid="AAB9EE7D-A671-4727-8658-D417A48B2B57" library_target="auth_module">
<target name="auth_module"> <target name="auth_module">
<root all_classes="true"/> <root all_classes="true"/>
<file_rule> <file_rule>
<exclude>/.git$</exclude> <exclude>/.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/.svn$</exclude> <exclude>/.svn$</exclude>
<exclude>/EIFGENs$</exclude>
</file_rule> </file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="standard"> <option warning="true" full_class_checking="true" is_attached_by_default="true" is_obsolete_routine_type="true" void_safety="all" syntax="standard">
</option> </option>
<library name="apis" location="$ISE_LIBRARY\contrib\library\web\authentication\oauth\cypress\consumer\apis\apis.ecf" readonly="false"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/> <library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<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_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="config" location="..\..\library\configuration\config-safe.ecf"/> <library name="config" location="..\..\library\configuration\config-safe.ecf"/>
<library name="cypress_consumer" location="$ISE_LIBRARY\contrib\library\web\authentication\oauth\cypress\consumer-safe.ecf" readonly="false"/>
<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="encoder" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\text\encoder\encoder-safe.ecf"/>
<library name="error" location="$ISE_LIBRARY\contrib\library\utility\general\error\error-safe.ecf"/>
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http-safe.ecf"/> <library name="http" 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="recaptcha" location="..\..\library\recaptcha\recaptcha-safe.ecf"/>
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/> <library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/> <library name="wsf" 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"/>
<library name="wsf_html" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf_html\wsf_html-safe.ecf" readonly="false"/> <library name="wsf_html" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf_html\wsf_html-safe.ecf" readonly="false"/>
<library name="error" location="$ISE_LIBRARY\contrib\library\utility\general\error\error-safe.ecf"/>
<library name="email_service" location="..\..\library\email\email-safe.ecf"/>
<library name="apis" location="$ISE_LIBRARY\contrib\library\web\authentication\oauth\cypress\consumer\apis\apis.ecf" readonly="false"/>
<library name="cypress_consumer" location="$ISE_LIBRARY\contrib\library\web\authentication\oauth\cypress\consumer-safe.ecf" readonly="false"/>
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json-safe.ecf" readonly="false"/>
<cluster name="src" location=".\" recursive="true"/> <cluster name="src" location=".\" recursive="true"/>
</target> </target>
</system> </system>

View File

@@ -0,0 +1,209 @@
note
description: "Summary description for {CMS_AUTHENTICATION_EMAIL_SERVICE}."
date: "$Date$"
revision: "$Revision$"
class
CMS_AUTHENTICATION_EMAIL_SERVICE
create
make
feature {NONE} -- Initialization
make (a_params: like parameters)
-- Create instance of email service with `a_params' data.
do
parameters := a_params
initialize
end
initialize
-- Initialize service.
do
create error_handler.make
reset_error
end
feature -- Access
parameters: CMS_AUTHENTICATION_EMAIL_SERVICE_PARAMETERS
-- Associated parameters.
cms_api: CMS_API
do
Result := parameters.cms_api
end
contact_email_address: IMMUTABLE_STRING_8
-- contact email.
do
Result := parameters.contact_email_address
end
notif_email_address: IMMUTABLE_STRING_8
-- Site admin's email.
do
Result := parameters.notif_email_address
end
sender_email_address: IMMUTABLE_STRING_8
-- Site sender's email.
do
Result := parameters.sender_email_address
end
feature -- Error
error_handler: ERROR_HANDLER
has_error: BOOLEAN
do
Result := error_handler.has_error
end
reset_error
do
error_handler.reset
end
feature -- Basic Operations / Internal
send_internal_email (a_content: READABLE_STRING_GENERAL)
do
send_message (sender_email_address, notif_email_address, "Notification Contact", a_content)
end
send_email_internal_server_error (a_content: READABLE_STRING_GENERAL)
do
send_message (sender_email_address, notif_email_address, "Internal Server Error", a_content)
end
feature -- Basic Operations / Contact
send_account_evaluation (a_user: CMS_USER; a_application, a_url_activate, a_url_reject, a_host: READABLE_STRING_8)
-- Send new user register to webmaster to confirm or reject itt.
local
l_message: STRING
do
create l_message.make_from_string (parameters.account_evaluation)
l_message.replace_substring_all ("$host", a_host)
l_message.replace_substring_all ("$sitename", parameters.utf_8_site_name)
l_message.replace_substring_all ("$user", a_user.utf_8_name)
if attached a_user.email as l_email then
l_message.replace_substring_all ("$email", l_email)
else
l_message.replace_substring_all ("$email", "unknown email")
end
l_message.replace_substring_all ("$application", a_application)
l_message.replace_substring_all ("$activation_url", a_url_activate)
l_message.replace_substring_all ("$rejection_url", a_url_reject)
send_message (contact_email_address, contact_email_address, parameters.contact_subject_account_evaluation, l_message)
end
send_contact_email (a_to: READABLE_STRING_8; a_user: CMS_USER; a_host: READABLE_STRING_8)
-- Send successful contact message for user `a_user' 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 ("$host", a_host)
l_message.replace_substring_all ("$sitename", parameters.utf_8_site_name)
l_message.replace_substring_all ("$user", a_user.utf_8_name)
send_message (contact_email_address, a_to, parameters.contact_subject_register, l_message)
end
send_contact_activation_email (a_to: READABLE_STRING_8; a_user: CMS_USER; a_link, a_host: READABLE_STRING_8)
-- Send successful message activation to `a_to'.
require
attached_to: a_to /= Void
local
l_message: STRING
do
create l_message.make_from_string (parameters.account_re_activation)
l_message.replace_substring_all ("$host", a_host)
l_message.replace_substring_all ("$sitename", parameters.utf_8_site_name)
l_message.replace_substring_all ("$link", a_link)
send_message (contact_email_address, a_to, parameters.contact_subject_activate, l_message)
end
send_contact_activation_confirmation_email (a_to: READABLE_STRING_8; a_user: CMS_USER; a_host: READABLE_STRING_8)
-- Send successful message activation to a_to.
require
attached_to: a_to /= Void
local
l_message: STRING
do
create l_message.make_from_string (parameters.account_activation_confirmation)
l_message.replace_substring_all ("$hot", a_host)
l_message.replace_substring_all ("$sitename", parameters.utf_8_site_name)
l_message.replace_substring_all ("$user", a_user.utf_8_name)
l_message.replace_substring_all ("$email", a_to)
send_message (contact_email_address, a_to, parameters.contact_subject_activated, l_message)
end
send_contact_activation_reject_email (a_to: READABLE_STRING_8; a_user: CMS_USER; a_host: READABLE_STRING_8)
-- Send successful contact activation reject message to `a_to'.
require
attached_to: a_to /= Void
local
l_message: STRING
do
create l_message.make_from_string (parameters.account_rejected)
l_message.replace_substring_all ("$host", a_host)
l_message.replace_substring_all ("$sitename", parameters.utf_8_site_name)
l_message.replace_substring_all ("$email", a_to)
l_message.replace_substring_all ("$user", a_user.utf_8_name)
send_message (contact_email_address, a_to, parameters.contact_subject_rejected, l_message)
end
send_contact_password_email (a_to: READABLE_STRING_8; a_user: CMS_USER; a_link, a_host: READABLE_STRING_8)
-- Send successful new account password message to `a_to'.
require
attached_to: a_to /= Void
local
l_message: STRING
do
create l_message.make_from_string (parameters.account_password)
l_message.replace_substring_all ("$host", a_host)
l_message.replace_substring_all ("$sitename", parameters.utf_8_site_name)
l_message.replace_substring_all ("$link", a_link)
send_message (contact_email_address, a_to, parameters.contact_subject_password, l_message)
end
send_contact_welcome_email (a_to: READABLE_STRING_8; a_user: CMS_USER; a_host: READABLE_STRING_8)
-- Send successful welcome message 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 ("$host", a_host)
l_message.replace_substring_all ("$sitename", parameters.utf_8_site_name)
l_message.replace_substring_all ("$email", a_to)
l_message.replace_substring_all ("$user", a_user.utf_8_name)
send_message (contact_email_address, a_to, parameters.contact_subject_oauth, l_message)
end
feature {NONE} -- Implementation
send_message (a_from_address, a_to_address: READABLE_STRING_8; a_subjet: READABLE_STRING_GENERAL; a_content: READABLE_STRING_GENERAL)
local
l_email: CMS_EMAIL
utf: UTF_CONVERTER
do
reset_error
l_email := cms_api.new_email (a_to_address, utf.escaped_utf_32_string_to_utf_8_string_8 (a_subjet), utf.escaped_utf_32_string_to_utf_8_string_8 (a_content))
l_email.set_from_address (a_from_address)
l_email.add_header_line ("MIME-Version:1.0")
l_email.add_header_line ("Content-Type: text/html; charset=utf-8")
cms_api.process_email (l_email)
if cms_api.has_error then
error_handler.add_custom_error (-1, generator + "send_message failed", cms_api.string_representation_of_errors)
end
end
end

View File

@@ -6,9 +6,6 @@ note
class class
CMS_AUTHENTICATION_EMAIL_SERVICE_PARAMETERS CMS_AUTHENTICATION_EMAIL_SERVICE_PARAMETERS
inherit
EMAIL_SERVICE_PARAMETERS
create create
make make
@@ -17,25 +14,21 @@ feature {NONE} -- Initialization
make (a_cms_api: CMS_API) make (a_cms_api: CMS_API)
local local
utf: UTF_CONVERTER utf: UTF_CONVERTER
l_site_name: READABLE_STRING_8
s: detachable READABLE_STRING_32 s: detachable READABLE_STRING_32
l_utf8_site_name: IMMUTABLE_STRING_8
l_contact_email, l_subject_register, l_subject_activate, l_subject_password, l_subject_oauth: detachable READABLE_STRING_8 l_contact_email, l_subject_register, l_subject_activate, l_subject_password, l_subject_oauth: detachable READABLE_STRING_8
do do
cms_api := a_cms_api cms_api := a_cms_api
-- Use global smtp setting if any, otherwise "localhost" create l_utf8_site_name.make_from_string (a_cms_api.setup.utf_8_site_name)
smtp_server := utf.escaped_utf_32_string_to_utf_8_string_8 (a_cms_api.setup.text_item_or_default ("smtp", "localhost")) utf_8_site_name := l_utf8_site_name
l_site_name := utf.escaped_utf_32_string_to_utf_8_string_8 (a_cms_api.setup.site_name) notif_email_address := a_cms_api.setup.site_notification_email
admin_email := a_cms_api.setup.site_email sender_email_address := a_cms_api.setup.site_email
if not admin_email.has ('<') then if not notif_email_address.has ('<') then
admin_email := l_site_name + " <" + admin_email +">" notif_email_address := l_utf8_site_name + " <" + notif_email_address + ">"
end end
if attached {CONFIG_READER} a_cms_api.module_configuration_by_name ({CMS_AUTHENTICATION_MODULE}.name, Void) as cfg then if attached 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") s := cfg.text_item ("email")
if s /= Void then if s /= Void then
l_contact_email := utf.utf_32_string_to_utf_8_string_8 (s) l_contact_email := utf.utf_32_string_to_utf_8_string_8 (s)
@@ -56,16 +49,15 @@ feature {NONE} -- Initialization
if s /= Void then if s /= Void then
l_subject_oauth := utf.utf_32_string_to_utf_8_string_8 (s) l_subject_oauth := utf.utf_32_string_to_utf_8_string_8 (s)
end end
end
if l_contact_email = Void then
l_contact_email := notif_email_address
end
if not l_contact_email.has ('<') then
l_contact_email := l_utf8_site_name + " <" + l_contact_email + ">"
end
contact_email_address := l_contact_email
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 if l_subject_register /= Void then
contact_subject_register := l_subject_register contact_subject_register := l_subject_register
else else
@@ -88,23 +80,40 @@ feature {NONE} -- Initialization
contact_subject_oauth := "Welcome." contact_subject_oauth := "Welcome."
end end
contact_subject_account_evaluation := "New register, account evalution."
contact_subject_rejected := "Your account was rejected."
contact_subject_activated := "Your account was activated."
end end
feature -- Access feature -- Access
cms_api: CMS_API cms_api: CMS_API
smtp_server: IMMUTABLE_STRING_8 notif_email_address: IMMUTABLE_STRING_8
admin_email: IMMUTABLE_STRING_8 sender_email_address: IMMUTABLE_STRING_8
contact_email: IMMUTABLE_STRING_8 contact_email_address: IMMUTABLE_STRING_8
-- Contact email. -- Contact email.
utf_8_site_name: IMMUTABLE_STRING_8
-- UTF-8 encoded Site name.
contact_subject_account_evaluation: IMMUTABLE_STRING_8
contact_subject_register: IMMUTABLE_STRING_8 contact_subject_register: IMMUTABLE_STRING_8
contact_subject_activate: IMMUTABLE_STRING_8 contact_subject_activate: IMMUTABLE_STRING_8
contact_subject_password: IMMUTABLE_STRING_8 contact_subject_password: IMMUTABLE_STRING_8
contact_subject_oauth: IMMUTABLE_STRING_8 contact_subject_oauth: IMMUTABLE_STRING_8
contact_subject_rejected: IMMUTABLE_STRING_8
contact_subject_activated: IMMUTABLE_STRING_8
account_evaluation: STRING
-- Account evaluation template email message.
do
Result := template_string ("admin_account_evaluation.html", default_template_account_evaluation)
end
account_activation: STRING account_activation: STRING
-- Account activation template email message. -- Account activation template email message.
@@ -112,12 +121,24 @@ feature -- Access
Result := template_string ("account_activation.html", default_template_account_activation) Result := template_string ("account_activation.html", default_template_account_activation)
end end
account_activation_confirmation: STRING
-- Account activation confirmation template email message.
do
Result := template_string ("account_activation_confirmation.html", default_template_account_activation_confirmation)
end
account_re_activation: STRING account_re_activation: STRING
-- Account re_activation template email message. -- Account re_activation template email message.
do do
Result := template_string ("accunt_re_activation.html", default_template_account_re_activation) Result := template_string ("accunt_re_activation.html", default_template_account_re_activation)
end end
account_rejected: STRING
-- Account rejected template email message.
do
Result := template_string ("accunt_rejected.html", default_template_account_rejected)
end
account_password: STRING account_password: STRING
-- Account password template email message. -- Account password template email message.
do do
@@ -146,7 +167,7 @@ feature {NONE} -- Implementation: Template
local local
p: PATH p: PATH
do do
p := template_path ("account_activation.html") p := template_path (a_name)
if attached read_template_file (p) as l_content then if attached read_template_file (p) as l_content then
Result := l_content Result := l_content
else else
@@ -177,6 +198,36 @@ feature {NONE} -- Implementation
feature {NONE} -- Message email feature {NONE} -- Message email
default_template_account_evaluation: STRING = "[
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Account Evaluation</title>
<meta name="description" content="Account Evaluation">
<meta name="author" content="$sitename">
</head>
<body>
<h2> Account Evaluation </h2>
<p>The user $user ($email) wants to register to the site <a href="$host">$sitename</a></p>
<blockquote><p>This is his/her application.</p>
<p>$application</p>
</blockquote>
<p>To complete the registration, please click on the following link to activate the user account:<p>
<p><a href="$activation_url">$activation_url</a></p>
<p>To reject the registration, please click on the following link <p>
<p><a href="$rejection_url">$rejection_url</a></p>
</body>
</html>
]"
default_template_account_activation: STRING = "[ default_template_account_activation: STRING = "[
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en">
@@ -184,21 +235,53 @@ feature {NONE} -- Message email
<meta charset="utf-8"> <meta charset="utf-8">
<title>Activation</title> <title>Activation</title>
<meta name="description" content="Activation"> <meta name="description" content="Activation">
<meta name="author" content="ROC CMS"> <meta name="author" content="$sitename">
</head> </head>
<body> <body>
<p>Thank you for registering at <a href="...">ROC CMS</a></p> <p>Thank you for applying to <a href="$host">$sitename</a> $user</p>
<p>To complete your registration, please click on the following link to activate your account:<p> <p>We will review your application and send you an email<p>
<p><a href="$link">$link</a></p>
<p>Thank you for joining us.</p> <p>Thank you for joining us.</p>
</body> </body>
</html> </html>
]" ]"
default_template_account_activation_confirmation: STRING = "[
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Activation</title>
<meta name="description" content="Activation Confirmation">
<meta name="author" content="$sitename">
</head>
<body>
<p>Your account has been confirmed <a href="$host">$sitename</a> $email</p>
<p>Thank you for joining us.</p>
</body>
</html>
]"
default_template_account_rejected: STRING = "[
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Application Rejected</title>
<meta name="description" content="Application Rejected">
<meta name="author" content="$sitename">
</head>
<body>
<p>You requested has been rejected, your application does not conform our rules <a href="$host">$sitename</a></p>
</body>
</html>
]"
default_template_account_re_activation: STRING = "[ default_template_account_re_activation: STRING = "[
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en">
@@ -206,11 +289,11 @@ feature {NONE} -- Message email
<meta charset="utf-8"> <meta charset="utf-8">
<title>New Activation</title> <title>New Activation</title>
<meta name="description" content="New Activation token"> <meta name="description" content="New Activation token">
<meta name="author" content="ROC CMS"> <meta name="author" content="$sitename">
</head> </head>
<body> <body>
<p>You have requested a new activation token at <a href="...">ROC CMS</a></p> <p>You have requested a new activation token at <a href="$host">$sitename</a></p>
<p>To complete your registration, please click on the following link to activate your account:<p> <p>To complete your registration, please click on the following link to activate your account:<p>
@@ -229,11 +312,11 @@ feature {NONE} -- Message email
<meta charset="utf-8"> <meta charset="utf-8">
<title>New Password</title> <title>New Password</title>
<meta name="description" content="New Password"> <meta name="description" content="New Password">
<meta name="author" content="ROC CMS"> <meta name="author" content="$sitename">
</head> </head>
<body> <body>
<p>You have required a new password at <a href="...">ROC CMS</a></p> <p>You have required a new password at <a href="$host">$sitename</a></p>
<p>To complete your request, please click on this link to generate a new password:<p> <p>To complete your request, please click on this link to generate a new password:<p>
@@ -250,11 +333,11 @@ feature {NONE} -- Message email
<meta charset="utf-8"> <meta charset="utf-8">
<title>Welcome</title> <title>Welcome</title>
<meta name="description" content="Welcome"> <meta name="description" content="Welcome">
<meta name="author" content="ROC CMS"> <meta name="author" content="$sitename">
</head> </head>
<body> <body>
<p>Welcome to<a href="...">ROC CMS</a></p> <p>Welcome to<a href="...">$sitename</a></p>
<p>Thank you for joining us.</p> <p>Thank you for joining us.</p>
</body> </body>
</html> </html>

View File

@@ -7,14 +7,17 @@ class
CMS_AUTHENTICATION_MODULE CMS_AUTHENTICATION_MODULE
inherit inherit
CMS_MODULE CMS_MODULE
redefine redefine
register_hooks setup_hooks,
permissions
end end
CMS_HOOK_AUTO_REGISTER CMS_HOOK_AUTO_REGISTER
CMS_HOOK_RESPONSE_ALTER
CMS_HOOK_VALUE_TABLE_ALTER CMS_HOOK_VALUE_TABLE_ALTER
CMS_HOOK_BLOCK CMS_HOOK_BLOCK
@@ -43,7 +46,6 @@ feature {NONE} -- Initialization
version := "1.0" version := "1.0"
description := "Authentication module" description := "Authentication module"
package := "authentication" package := "authentication"
create root_dir.make_current create root_dir.make_current
cache_duration := 0 cache_duration := 0
end end
@@ -52,6 +54,17 @@ feature -- Access
name: STRING = "auth" name: STRING = "auth"
permissions: LIST [READABLE_STRING_8]
-- List of permission ids, used by this module, and declared.
do
Result := Precursor
Result.force ("account register")
Result.force ("account activate")
Result.force ("account reject")
Result.force ("account reactivate")
Result.force ("admin registration")
end
feature -- Access: docs feature -- Access: docs
root_dir: PATH root_dir: PATH
@@ -73,30 +86,44 @@ feature -- Router
-- <Precursor> -- <Precursor>
do do
configure_web (a_api, a_router) configure_web (a_api, a_router)
configure_web_admin (a_api, a_router)
end end
configure_web (a_api: CMS_API; a_router: WSF_ROUTER) configure_web (a_api: CMS_API; a_router: WSF_ROUTER)
local
m: WSF_URI_MAPPING
do do
a_router.handle ("/account", create {WSF_URI_AGENT_HANDLER}.make (agent handle_account (a_api, ?, ?)), a_router.methods_head_get) create m.make_trailing_slash_ignored ("/account", create {WSF_URI_AGENT_HANDLER}.make (agent handle_account(a_api, ?, ?)))
a_router.handle ("/account/roc-login", create {WSF_URI_AGENT_HANDLER}.make (agent handle_login (a_api, ?, ?)), a_router.methods_head_get) a_router.map (m, a_router.methods_head_get)
a_router.handle ("/account/roc-logout", create {WSF_URI_AGENT_HANDLER}.make (agent handle_logout (a_api, ?, ?)), a_router.methods_head_get)
a_router.handle ("/account/roc-register", create {WSF_URI_AGENT_HANDLER}.make (agent handle_register (a_api, ?, ?)), a_router.methods_get_post) a_router.handle ("/account/roc-login", create {WSF_URI_AGENT_HANDLER}.make (agent handle_login(a_api, ?, ?)), a_router.methods_head_get)
a_router.handle ("/account/activate/{token}", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_activation (a_api, ?, ?)), a_router.methods_head_get) a_router.handle ("/account/roc-logout", create {WSF_URI_AGENT_HANDLER}.make (agent handle_logout(a_api, ?, ?)), a_router.methods_head_get)
a_router.handle ("/account/reactivate", create {WSF_URI_AGENT_HANDLER}.make (agent handle_reactivation (a_api, ?, ?)), a_router.methods_get_post) a_router.handle ("/account/roc-register", create {WSF_URI_AGENT_HANDLER}.make (agent handle_register(a_api, ?, ?)), a_router.methods_get_post)
a_router.handle ("/account/new-password", create {WSF_URI_AGENT_HANDLER}.make (agent handle_new_password (a_api, ?, ?)), a_router.methods_get_post) a_router.handle ("/account/activate/{token}", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_activation(a_api, ?, ?)), a_router.methods_head_get)
a_router.handle ("/account/reset-password", create {WSF_URI_AGENT_HANDLER}.make (agent handle_reset_password (a_api, ?, ?)), a_router.methods_get_post) a_router.handle ("/account/reject/{token}", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_reject(a_api, ?, ?)), a_router.methods_head_get)
a_router.handle ("/account/change-password", create {WSF_URI_AGENT_HANDLER}.make (agent handle_change_password (a_api, ?, ?)), a_router.methods_get_post) a_router.handle ("/account/reactivate", create {WSF_URI_AGENT_HANDLER}.make (agent handle_reactivation(a_api, ?, ?)), a_router.methods_get_post)
a_router.handle ("/account/post-change-password", create {WSF_URI_AGENT_HANDLER}.make (agent handle_post_change_password (a_api, ?, ?)), a_router.methods_get) a_router.handle ("/account/new-password", create {WSF_URI_AGENT_HANDLER}.make (agent handle_new_password(a_api, ?, ?)), a_router.methods_get_post)
a_router.handle ("/account/reset-password", create {WSF_URI_AGENT_HANDLER}.make (agent handle_reset_password(a_api, ?, ?)), a_router.methods_get_post)
a_router.handle ("/account/change-password", create {WSF_URI_AGENT_HANDLER}.make (agent handle_change_password(a_api, ?, ?)), a_router.methods_get_post)
a_router.handle ("/account/post-change-password", create {WSF_URI_AGENT_HANDLER}.make (agent handle_post_change_password(a_api, ?, ?)), a_router.methods_get)
end
configure_web_admin (a_api: CMS_API; a_router: WSF_ROUTER)
-- Configure router mapping for admin web interface.
do
a_router.handle ("/admin/pending-registrations/", create {WSF_URI_AGENT_HANDLER}.make (agent handle_admin_pending_registrations (?, ?, a_api)), a_router.methods_get)
end end
feature -- Hooks configuration feature -- Hooks configuration
register_hooks (a_response: CMS_RESPONSE) setup_hooks (a_hooks: CMS_HOOK_CORE_MANAGER)
-- Module hooks configuration. -- Module hooks configuration.
do do
auto_subscribe_to_hooks (a_response) auto_subscribe_to_hooks (a_hooks)
a_response.hooks.subscribe_to_block_hook (Current) a_hooks.subscribe_to_block_hook (Current)
a_response.hooks.subscribe_to_value_table_alter_hook (Current) a_hooks.subscribe_to_value_table_alter_hook (Current)
a_hooks.subscribe_to_menu_system_alter_hook (Current)
end end
value_table_alter (a_value: CMS_VALUE_TABLE; a_response: CMS_RESPONSE) value_table_alter (a_value: CMS_VALUE_TABLE; a_response: CMS_RESPONSE)
@@ -112,7 +139,7 @@ feature -- Hooks configuration
lnk: CMS_LOCAL_LINK lnk: CMS_LOCAL_LINK
do do
if attached a_response.user as u then if attached a_response.user as u then
create lnk.make (u.name, "account" ) create lnk.make (u.name, "account")
lnk.set_weight (97) lnk.set_weight (97)
a_menu_system.primary_menu.extend (lnk) a_menu_system.primary_menu.extend (lnk)
create lnk.make ("Logout", "account/roc-logout") create lnk.make ("Logout", "account/roc-logout")
@@ -123,7 +150,11 @@ feature -- Hooks configuration
lnk.set_weight (98) lnk.set_weight (98)
a_menu_system.primary_menu.extend (lnk) a_menu_system.primary_menu.extend (lnk)
end end
-- Add the link to the taxonomy to the main menu
if a_response.has_permission ("admin registration") then
create lnk.make ("Registration", "admin/pending-registrations/")
a_menu_system.management_menu.extend (lnk)
end
end end
feature -- Handler feature -- Handler
@@ -133,7 +164,6 @@ feature -- Handler
r: CMS_RESPONSE r: CMS_RESPONSE
do do
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
if attached template_block ("account_info", r) as l_tpl_block then if attached template_block ("account_info", r) as l_tpl_block then
if attached r.user as l_user then if attached r.user as l_user then
r.set_value (api.user_api.user_roles (l_user), "roles") r.set_value (api.user_api.user_roles (l_user), "roles")
@@ -175,11 +205,14 @@ feature -- Handler
local local
r: CMS_RESPONSE r: CMS_RESPONSE
l_user_api: CMS_USER_API l_user_api: CMS_USER_API
u: CMS_USER u: CMS_TEMP_USER
l_exist: BOOLEAN l_exist: BOOLEAN
es: CMS_AUTHENTICATON_EMAIL_SERVICE es: CMS_AUTHENTICATION_EMAIL_SERVICE
l_url: STRING l_url_activate: STRING
l_url_reject: STRING
l_token: STRING l_token: STRING
l_captcha_passed: BOOLEAN
l_email: READABLE_STRING_8
do do
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
if r.has_permission ("account register") then if r.has_permission ("account register") then
@@ -187,49 +220,77 @@ feature -- Handler
if if
attached {WSF_STRING} req.form_parameter ("name") as l_name and then attached {WSF_STRING} req.form_parameter ("name") as l_name and then
attached {WSF_STRING} req.form_parameter ("password") as l_password and then attached {WSF_STRING} req.form_parameter ("password") as l_password and then
attached {WSF_STRING} req.form_parameter ("email") as l_email attached {WSF_STRING} req.form_parameter ("email") as p_email and then
attached {WSF_STRING} req.form_parameter ("personal_information") as l_personal_information
then then
l_user_api := api.user_api if p_email.value.is_valid_as_string_8 then
l_email := p_email.value.to_string_8
l_user_api := api.user_api
if attached l_user_api.user_by_name (l_name.value) or else attached l_user_api.temp_user_by_name (l_name.value) then
-- Username already exist.
r.set_value ("User name already exists!", "error_name")
l_exist := True
end
if attached l_user_api.user_by_email (l_email) or else attached l_user_api.temp_user_by_email (l_email) then
-- Emails already exist.
r.set_value ("An account is already associated with that email address!", "error_email")
l_exist := True
end
if attached recaptcha_secret_key (api) as l_recaptcha_key then
if attached {WSF_STRING} req.form_parameter ("g-recaptcha-response") as l_recaptcha_response and then is_captcha_verified (l_recaptcha_key, l_recaptcha_response.value) then
l_captcha_passed := True
else
--| Bad or missing captcha
l_captcha_passed := False
end
else
--| reCaptcha is not setup, so no verification
l_captcha_passed := True
end
if not l_exist then
-- New temp user
create u.make (l_name.value)
u.set_email (l_email)
u.set_password (l_password.value)
u.set_personal_information (l_personal_information.value)
l_user_api.new_temp_user (u)
if attached l_user_api.user_by_name (l_name.value) then -- Create activation token
-- Username already exist. l_token := new_token
r.set_value ("User name already exists!", "error_name") l_user_api.new_activation (l_token, u.id)
l_exist := True l_url_activate := req.absolute_script_url ("/account/activate/" + l_token)
end l_url_reject := req.absolute_script_url ("/account/reject/" + l_token)
if attached l_user_api.user_by_email (l_email.value) then
-- Emails already exist.
r.set_value ("An account is already associated with that email address!", "error_email")
l_exist := True
end
if not l_exist then -- Send Email to webmaster
-- New user create es.make (create {CMS_AUTHENTICATION_EMAIL_SERVICE_PARAMETERS}.make (api))
create u.make (l_name.value) write_debug_log (generator + ".handle register: send_register_email")
u.set_email (l_email.value) es.send_account_evaluation (u, l_personal_information.value, l_url_activate, l_url_reject, req.absolute_script_url (""))
u.set_password (l_password.value)
l_user_api.new_user (u)
-- Create activation token
l_token := new_token
l_user_api.new_activation (l_token, u.id)
l_url := req.absolute_script_url ("/account/activate/" + l_token)
-- Send Email
create es.make (create {CMS_AUTHENTICATION_EMAIL_SERVICE_PARAMETERS}.make (api))
write_debug_log (generator + ".handle register: send_contact_email")
es.send_contact_email (l_email.value, l_url)
-- Send Email to user
create es.make (create {CMS_AUTHENTICATION_EMAIL_SERVICE_PARAMETERS}.make (api))
write_debug_log (generator + ".handle register: send_contact_email")
es.send_contact_email (l_email, u, req.absolute_script_url (""))
else
r.set_value (l_name.value, "name")
r.set_value (l_email, "email")
r.set_value (l_personal_information.value, "personal_information")
r.set_status_code ({HTTP_CONSTANTS}.bad_request)
end
else else
r.set_value (l_name.value, "name") r.set_value (l_name.value, "name")
r.set_value (l_email.value, "email") r.set_value (p_email.value, "email")
r.set_value (l_personal_information.value, "personal_information")
r.set_status_code ({HTTP_CONSTANTS}.bad_request) r.set_status_code ({HTTP_CONSTANTS}.bad_request)
end end
else
create {BAD_REQUEST_ERROR_CMS_RESPONSE} r.make (req, res, api)
r.set_main_content ("There were issue with your application, invalid or missing values.")
end end
end end
else else
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api) create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api)
r.set_main_content ("You can also contact the webmaster to ask for an account.")
end end
r.execute r.execute
end end
@@ -238,110 +299,187 @@ feature -- Handler
r: CMS_RESPONSE r: CMS_RESPONSE
l_user_api: CMS_USER_API l_user_api: CMS_USER_API
l_ir: INTERNAL_SERVER_ERROR_CMS_RESPONSE l_ir: INTERNAL_SERVER_ERROR_CMS_RESPONSE
es: CMS_AUTHENTICATION_EMAIL_SERVICE
do do
l_user_api := api.user_api l_user_api := api.user_api
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
if attached {WSF_STRING} req.path_parameter ("token") as l_token then if r.has_permission ("account activate") then
if attached {WSF_STRING} req.path_parameter ("token") as l_token then
if attached {CMS_TEMP_USER} l_user_api.temp_user_by_activation_token (l_token.value) as l_user then
if attached {CMS_USER} l_user_api.user_by_activation_token (l_token.value) as l_user then -- TODO copy the personal information
-- Valid user_id --! to CMS_USER_PROFILE and persist data
l_user.mark_active --! check also CMS_USER.data_items
l_user_api.update_user (l_user)
l_user_api.remove_activation (l_token.value) -- Delete temporal User
r.set_main_content ("<p> Your account <i>"+ l_user.name +"</i> has been activated</p>") l_user_api.delete_temp_user (l_user)
-- Valid user_id
l_user.set_id (0)
l_user.mark_active
l_user_api.new_user_from_temp_user (l_user)
l_user_api.remove_activation (l_token.value)
r.set_main_content ("<p> The account <i>" + html_encoded (l_user.name) + "</i> has been activated</p>")
-- Send Email
if attached l_user.email as l_email then
create es.make (create {CMS_AUTHENTICATION_EMAIL_SERVICE_PARAMETERS}.make (api))
write_debug_log (generator + ".handle register: send_contact_activation_confirmation_email")
es.send_contact_activation_confirmation_email (l_email, l_user, req.absolute_script_url (""))
end
else
-- the token does not exist, or it was already used.
r.set_status_code ({HTTP_CONSTANTS}.bad_request)
r.set_main_content ("<p>The token <i>" + l_token.value + "</i> is not valid " + r.link ("Reactivate Account", "account/reactivate", Void) + "</p>")
end
r.execute
else else
-- the token does not exist, or it was already used. create l_ir.make (req, res, api)
r.set_status_code ({HTTP_CONSTANTS}.bad_request) l_ir.execute
r.set_main_content ("<p>The token <i>" + l_token.value +"</i> is not valid " + r.link ("Reactivate Account", "account/reactivate", Void) + "</p>")
end end
r.execute
else else
create l_ir.make (req, res, api) create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api)
l_ir.execute r.execute
end end
end end
handle_reject (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE)
local
r: CMS_RESPONSE
es: CMS_AUTHENTICATION_EMAIL_SERVICE
l_ir: INTERNAL_SERVER_ERROR_CMS_RESPONSE
l_user_api: CMS_USER_API
do
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
if r.has_permission ("account reject") then
if attached {WSF_STRING} req.path_parameter ("token") as l_token then
l_user_api := api.user_api
if attached {CMS_TEMP_USER} l_user_api.temp_user_by_activation_token (l_token.value) as l_user then
l_user_api.delete_temp_user (l_user)
r.set_main_content ("<p> The temporal account for <i>" + html_encoded (l_user.name) + "</i> has been removed</p>")
-- Send Email
if attached l_user.email as l_email then
create es.make (create {CMS_AUTHENTICATION_EMAIL_SERVICE_PARAMETERS}.make (api))
write_debug_log (generator + ".handle register: send_contact_activation_reject_email")
es.send_contact_activation_reject_email (l_email, l_user, req.absolute_script_url (""))
end
else
-- the token does not exist, or it was already used.
r.set_status_code ({HTTP_CONSTANTS}.bad_request)
r.set_main_content ("<p>The token <i>" + l_token.value + "</i> is not valid ")
end
r.execute
else
create l_ir.make (req, res, api)
l_ir.execute
end
else
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api)
r.execute
end
end
handle_reactivation (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE) handle_reactivation (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE)
local local
r: CMS_RESPONSE r: CMS_RESPONSE
es: CMS_AUTHENTICATON_EMAIL_SERVICE es: CMS_AUTHENTICATION_EMAIL_SERVICE
l_user_api: CMS_USER_API l_user_api: CMS_USER_API
l_token: STRING l_token: STRING
l_url: STRING l_url_activate: STRING
l_url_reject: STRING
l_email: READABLE_STRING_8
do do
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
if req.is_post_request_method then if r.has_permission ("account reactivate") then
if if req.is_post_request_method then
attached {WSF_STRING} req.form_parameter ("email") as l_email if attached {WSF_STRING} req.form_parameter ("email") as p_email then
then if p_email.value.is_valid_as_string_8 then
l_user_api := api.user_api l_email := p_email.value.to_string_8
if attached {CMS_USER} l_user_api.user_by_email (l_email.value) as l_user then l_user_api := api.user_api
-- User exist create a new token and send a new email. if attached {CMS_TEMP_USER} l_user_api.temp_user_by_email (l_email) as l_user then
if l_user.is_active then -- User exist create a new token and send a new email.
r.set_value ("The asociated user to the given email " + l_email.value + " , is already active", "is_active") if l_user.is_active then
r.set_status_code ({HTTP_CONSTANTS}.bad_request) r.set_value ("The asociated user to the given email " + l_email + " , is already active", "is_active")
r.set_status_code ({HTTP_CONSTANTS}.bad_request)
else
l_token := new_token
l_user_api.new_activation (l_token, l_user.id)
l_url_activate := req.absolute_script_url ("/account/activate/" + l_token)
l_url_reject := req.absolute_script_url ("/account/reject/" + l_token)
-- Send Email to webmaster
if attached l_user.personal_information as l_personal_information then
create es.make (create {CMS_AUTHENTICATION_EMAIL_SERVICE_PARAMETERS}.make (api))
write_debug_log (generator + ".handle register: send_register_email")
es.send_account_evaluation (l_user, l_personal_information, l_url_activate, l_url_reject, req.absolute_script_url (""))
end
end
else
r.set_value ("The email does not exist !", "error_email")
r.set_value (l_email, "email")
r.set_status_code ({HTTP_CONSTANTS}.bad_request)
end
else else
l_token := new_token r.set_value ("The email is not valid!", "error_email")
l_user_api.new_activation (l_token, l_user.id) r.set_value (p_email.value, "email")
l_url := req.absolute_script_url ("/account/activate/" + l_token) r.set_status_code ({HTTP_CONSTANTS}.bad_request)
-- Send Email
create es.make (create {CMS_AUTHENTICATION_EMAIL_SERVICE_PARAMETERS}.make (api))
write_debug_log (generator + ".handle register: send_contact_activation_email")
es.send_contact_activation_email (l_email.value, l_url)
end end
else
r.set_value ("The email does not exist or !", "error_email")
r.set_value (l_email.value, "email")
r.set_status_code ({HTTP_CONSTANTS}.bad_request)
end end
end end
else
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api)
r.execute
end end
r.execute r.execute
end end
handle_new_password (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE) handle_new_password (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE)
local local
r: CMS_RESPONSE r: CMS_RESPONSE
es: CMS_AUTHENTICATON_EMAIL_SERVICE es: CMS_AUTHENTICATION_EMAIL_SERVICE
l_user_api: CMS_USER_API l_user_api: CMS_USER_API
l_token: STRING l_token: STRING
l_url: STRING l_url: STRING
l_email: READABLE_STRING_8
do do
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
if req.is_post_request_method then if req.is_post_request_method then
l_user_api := api.user_api l_user_api := api.user_api
if attached {WSF_STRING} req.form_parameter ("email") as l_email then if attached {WSF_STRING} req.form_parameter ("email") as p_email then
if attached {CMS_USER} l_user_api.user_by_email (l_email.value) as l_user then if p_email.value.is_valid_as_string_8 then
l_email := p_email.value.to_string_8
if attached {CMS_USER} l_user_api.user_by_email (l_email) as l_user then
-- User exist create a new token and send a new email. -- User exist create a new token and send a new email.
l_token := new_token l_token := new_token
l_user_api.new_password (l_token, l_user.id) l_user_api.new_password (l_token, l_user.id)
l_url := req.absolute_script_url ("/account/reset-password?token=" + l_token) l_url := req.absolute_script_url ("/account/reset-password?token=" + l_token)
-- Send Email -- Send Email
create es.make (create {CMS_AUTHENTICATION_EMAIL_SERVICE_PARAMETERS}.make (api)) create es.make (create {CMS_AUTHENTICATION_EMAIL_SERVICE_PARAMETERS}.make (api))
write_debug_log (generator + ".handle register: send_contact_password_email") write_debug_log (generator + ".handle register: send_contact_password_email")
es.send_contact_password_email (l_email.value, l_url) es.send_contact_password_email (l_email, l_user, l_url, req.absolute_script_url (""))
else
r.set_value ("The email does not exist !", "error_email")
r.set_value (p_email.value, "email")
r.set_status_code ({HTTP_CONSTANTS}.bad_request)
end
else else
r.set_value ("The email does not exist !", "error_email") r.set_value ("The email is not valid!", "error_email")
r.set_value (l_email.value, "email") r.set_value (p_email.value, "email")
r.set_status_code ({HTTP_CONSTANTS}.bad_request) r.set_status_code ({HTTP_CONSTANTS}.bad_request)
end end
elseif attached {WSF_STRING} req.form_parameter ("username") as l_username then elseif attached {WSF_STRING} req.form_parameter ("username") as l_username then
if attached {CMS_USER} l_user_api.user_by_name (l_username) as l_user and then if
attached l_user.email as l_email attached {CMS_USER} l_user_api.user_by_name (l_username) as l_user and then
attached l_user.email as l_user_email
then then
-- User exist create a new token and send a new email. -- User exist create a new token and send a new email.
l_token := new_token l_token := new_token
l_user_api.new_password (l_token, l_user.id) l_user_api.new_password (l_token, l_user.id)
l_url := req.absolute_script_url ("/account/reset-password?token=" + l_token) l_url := req.absolute_script_url ("/account/reset-password?token=" + l_token)
-- Send Email -- Send Email
create es.make (create {CMS_AUTHENTICATION_EMAIL_SERVICE_PARAMETERS}.make (api)) create es.make (create {CMS_AUTHENTICATION_EMAIL_SERVICE_PARAMETERS}.make (api))
write_debug_log (generator + ".handle register: send_contact_password_email") write_debug_log (generator + ".handle register: send_contact_password_email")
es.send_contact_password_email (l_email, l_url) es.send_contact_password_email (l_user_email, l_user, l_url, req.absolute_script_url (""))
else else
r.set_value ("The username does not exist !", "error_username") r.set_value ("The username does not exist !", "error_username")
r.set_value (l_username.value, "username") r.set_value (l_username.value, "username")
@@ -352,7 +490,6 @@ feature -- Handler
r.execute r.execute
end end
handle_reset_password (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE) handle_reset_password (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE)
local local
r: CMS_RESPONSE r: CMS_RESPONSE
@@ -360,24 +497,18 @@ feature -- Handler
do do
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
l_user_api := api.user_api l_user_api := api.user_api
if attached {WSF_STRING} req.query_parameter ("token") as l_token then if attached {WSF_STRING} req.query_parameter ("token") as l_token then
r.set_value (l_token.value, "token") r.set_value (l_token.value, "token")
if l_user_api.user_by_password_token (l_token.value) = Void then if l_user_api.user_by_password_token (l_token.value) = Void then
r.set_value ("The token " + l_token.value + " is not valid, " + r.link ("click here" , "account/new-password", Void) + " to generate a new token.", "error_token") r.set_value ("The token " + l_token.value + " is not valid, " + r.link ("click here", "account/new-password", Void) + " to generate a new token.", "error_token")
r.set_status_code ({HTTP_CONSTANTS}.bad_request) r.set_status_code ({HTTP_CONSTANTS}.bad_request)
end end
end end
if req.is_post_request_method then if req.is_post_request_method then
if attached {WSF_STRING} req.form_parameter ("token") as l_token and then attached {WSF_STRING} req.form_parameter ("password") as l_password and then attached {WSF_STRING} req.form_parameter ("confirm_password") as l_confirm_password then
if -- Does the passwords match?
attached {WSF_STRING} req.form_parameter ("token") as l_token and then
attached {WSF_STRING} req.form_parameter ("password") as l_password and then
attached {WSF_STRING} req.form_parameter ("confirm_password") as l_confirm_password
then
-- Does the passwords match?
if l_password.value.same_string (l_confirm_password.value) then if l_password.value.same_string (l_confirm_password.value) then
-- is the token valid? -- is the token valid?
if attached {CMS_USER} l_user_api.user_by_password_token (l_token.value) as l_user then if attached {CMS_USER} l_user_api.user_by_password_token (l_token.value) as l_user then
l_user.set_password (l_password.value) l_user.set_password (l_password.value)
l_user_api.update_user (l_user) l_user_api.update_user (l_user)
@@ -400,22 +531,17 @@ feature -- Handler
do do
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
l_user_api := api.user_api l_user_api := api.user_api
if req.is_post_request_method then if req.is_post_request_method then
if attached r.user as l_user then if attached r.user as l_user then
r.set_value (api.user_api.user_roles (l_user), "roles") r.set_value (api.user_api.user_roles (l_user), "roles")
if if attached {WSF_STRING} req.form_parameter ("password") as l_password and then attached {WSF_STRING} req.form_parameter ("confirm_password") as l_confirm_password and then l_password.value.same_string (l_confirm_password.value) then
attached {WSF_STRING} req.form_parameter ("password") as l_password and then -- Does the passwords match?
attached {WSF_STRING} req.form_parameter ("confirm_password") as l_confirm_password and then
l_password.value.same_string (l_confirm_password.value)
then
-- Does the passwords match?
l_user.set_password (l_password.value) l_user.set_password (l_password.value)
l_user_api.update_user (l_user) l_user_api.update_user (l_user)
r.set_redirection (req.absolute_script_url ("/account/post-change-password")) r.set_redirection (req.absolute_script_url ("/account/post-change-password"))
else else
if attached template_block ("account_info", r) as l_tpl_block then if attached template_block ("account_info", r) as l_tpl_block then
-- r.set_value (l_user, "user") -- r.set_value (l_user, "user")
r.set_value ("Passwords Don't Match", "error_password") r.set_value ("Passwords Don't Match", "error_password")
r.set_status_code ({HTTP_CONSTANTS}.bad_request) r.set_status_code ({HTTP_CONSTANTS}.bad_request)
r.add_block (l_tpl_block, "content") r.add_block (l_tpl_block, "content")
@@ -437,11 +563,102 @@ feature -- Handler
r.execute r.execute
end end
handle_admin_pending_registrations (req: WSF_REQUEST; res: WSF_RESPONSE; api: CMS_API)
local
l_response: CMS_RESPONSE
s: STRING
u: CMS_TEMP_USER
l_page_helper: CMS_PAGINATION_GENERATOR
s_pager: STRING
l_count: INTEGER
l_user_api: CMS_USER_API
do
-- At the moment the template are hardcoded, but we can
-- get them from the configuration file and load them into
-- the setup class.
create {FORBIDDEN_ERROR_CMS_RESPONSE} l_response.make (req, res, api)
if
l_response.has_permission ("admin registration")
then
l_user_api := api.user_api
l_count := l_user_api.temp_users_count
create {GENERIC_VIEW_CMS_RESPONSE} l_response.make (req, res, api)
create s.make_empty
if l_count > 1 then
l_response.set_title ("Listing " + l_count.out + " Pending Registrations")
else
l_response.set_title ("Listing " + l_count.out + " Pending Registration")
end
create s_pager.make_empty
create l_page_helper.make ("admin/pending-registrations/?page={page}&size={size}", l_user_api.temp_users_count.as_natural_64, 25) -- FIXME: Make this default page size a global CMS settings
l_page_helper.get_setting_from_request (req)
if l_page_helper.has_upper_limit and then l_page_helper.pages_count > 1 then
l_page_helper.append_to_html (l_response, s_pager)
if l_page_helper.page_size > 25 then
s.append (s_pager)
end
end
if attached l_user_api.temp_recent_users (create {CMS_DATA_QUERY_PARAMETERS}.make (l_page_helper.current_page_offset, l_page_helper.page_size)) as lst then
s.append ("<ul class=%"cms-temp-users%">%N")
across
lst as ic
loop
u := ic.item
s.append ("<li class=%"cms_temp_user%">")
s.append ("User:" + html_encoded (u.name))
s.append ("<ul class=%"cms_temp_user_details%">")
if attached u.personal_information as l_information then
s.append ("<li class=%"cms_temp_user_detail_information%">")
s.append (html_encoded (l_information))
s.append ("</li>%N")
end
if attached u.email as l_email then
s.append ("<li class=%"cms_temp_user_detail_email%">")
s.append (l_email)
s.append ("</li>%N")
end
if attached l_user_api.token_by_temp_user_id (u.id) as l_token then
s.append ("<li>")
s.append ("<a href=%"")
s.append (req.absolute_script_url ("/account/activate/" + l_token))
s.append ("%">")
s.append (html_encoded ("Activate"))
s.append ("</a>")
s.append ("</li>%N")
s.append ("<li>")
s.append ("<a href=%"")
s.append (req.absolute_script_url ("/account/reject/" + l_token))
s.append ("%">")
s.append (html_encoded ("Reject"))
s.append ("</a>")
s.append ("</li>%N")
end
s.append ("</ul>%N")
s.append ("</li>%N")
end
s.append ("</ul>%N")
end
-- Again the pager at the bottom, if needed
s.append (s_pager)
l_response.set_main_content (s)
l_response.execute
else
l_response.execute
end
end
block_list: ITERABLE [like {CMS_BLOCK}.name] block_list: ITERABLE [like {CMS_BLOCK}.name]
local local
l_string: STRING l_string: STRING
do do
Result := <<"register", "reactivate", "new_password", "reset_password">> Result := <<"register", "reactivate", "new_password", "reset_password", "registration">>
debug ("roc") debug ("roc")
create l_string.make_empty create l_string.make_empty
across across
@@ -450,32 +667,22 @@ feature -- Handler
l_string.append (ic.item) l_string.append (ic.item)
l_string.append_character (' ') l_string.append_character (' ')
end end
write_debug_log (generator + ".block_list:" + l_string ) write_debug_log (generator + ".block_list:" + l_string)
end end
end end
get_block_view (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE) get_block_view (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE)
do do
if if a_block_id.is_case_insensitive_equal_general ("register") and then a_response.location.starts_with ("account/roc-register") then
a_block_id.is_case_insensitive_equal_general ("register") and then
a_response.location.starts_with ("account/roc-register")
then
get_block_view_register (a_block_id, a_response) get_block_view_register (a_block_id, a_response)
elseif elseif a_block_id.is_case_insensitive_equal_general ("reactivate") and then a_response.location.starts_with ("account/reactivate") then
a_block_id.is_case_insensitive_equal_general ("reactivate") and then
a_response.location.starts_with ("account/reactivate")
then
get_block_view_reactivate (a_block_id, a_response) get_block_view_reactivate (a_block_id, a_response)
elseif elseif a_block_id.is_case_insensitive_equal_general ("new_password") and then a_response.location.starts_with ("account/new-password") then
a_block_id.is_case_insensitive_equal_general ("new_password") and then
a_response.location.starts_with ("account/new-password")
then
get_block_view_new_password (a_block_id, a_response) get_block_view_new_password (a_block_id, a_response)
elseif elseif a_block_id.is_case_insensitive_equal_general ("reset_password") and then a_response.location.starts_with ("account/reset-password") then
a_block_id.is_case_insensitive_equal_general ("reset_password") and then
a_response.location.starts_with ("account/reset-password")
then
get_block_view_reset_password (a_block_id, a_response) get_block_view_reset_password (a_block_id, a_response)
elseif a_block_id.is_case_insensitive_equal_general ("registration") and then a_response.location.starts_with ("admin/pending-registrations") then
get_block_view_registration (a_block_id, a_response)
end end
end end
@@ -491,10 +698,13 @@ feature {NONE} -- Token Generation
create l_security create l_security
l_token := l_security.token l_token := l_security.token
create l_encode create l_encode
from until l_token.same_string (l_encode.encoded_string (l_token)) loop from
-- Loop ensure that we have a security token that does not contain characters that need encoding. until
-- We cannot simply to an encode-decode because the email sent to the user will contain an encoded token l_token.same_string (l_encode.encoded_string (l_token))
-- but the user will need to use an unencoded token if activation has to be done manually. 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 l_token := l_security.token
end end
Result := l_token Result := l_token
@@ -509,7 +719,6 @@ feature {NONE} -- Helpers
do do
create p.make_from_string ("templates") create p.make_from_string ("templates")
p := p.extended ("block_").appended (a_block_id).appended_with_extension ("tpl") p := p.extended ("block_").appended (a_block_id).appended_with_extension ("tpl")
p := a_response.api.module_theme_resource_location (Current, p) p := a_response.api.module_theme_resource_location (Current, p)
if p /= Void then if p /= Void then
if attached p.entry as e then if attached p.entry as e then
@@ -522,32 +731,14 @@ feature {NONE} -- Helpers
feature {NONE} -- Block views 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
-- a_response.put_required_block (l_tpl_block, "content")
-- else
-- debug ("cms")
-- a_response.add_warning_message ("Error with block [" + a_block_id + "]")
-- end
-- end
-- end
get_block_view_register (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE) get_block_view_register (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE)
do do
if a_response.has_permission ("account register") then if a_response.has_permission ("account register") then
if a_response.request.is_get_request_method then if a_response.request.is_get_request_method then
if attached template_block (a_block_id, a_response) as l_tpl_block then if attached template_block (a_block_id, a_response) as l_tpl_block then
if attached recaptcha_site_key (a_response.api) as l_recaptcha_site_key then
l_tpl_block.set_value (l_recaptcha_site_key, "recaptcha_site_key")
end
a_response.add_block (l_tpl_block, "content") a_response.add_block (l_tpl_block, "content")
else else
debug ("cms") debug ("cms")
@@ -557,10 +748,13 @@ feature {NONE} -- Block views
elseif a_response.request.is_post_request_method then elseif a_response.request.is_post_request_method then
if a_response.values.has ("error_name") or else a_response.values.has ("error_email") then if a_response.values.has ("error_name") or else a_response.values.has ("error_email") then
if attached template_block (a_block_id, a_response) as l_tpl_block then if attached template_block (a_block_id, a_response) as l_tpl_block then
-- l_tpl_block.set_value (a_response.values.item ("error_name"), "error_name") -- l_tpl_block.set_value (a_response.values.item ("error_name"), "error_name")
-- l_tpl_block.set_value (a_response.values.item ("error_email"), "error_email") -- l_tpl_block.set_value (a_response.values.item ("error_email"), "error_email")
-- l_tpl_block.set_value (a_response.values.item ("email"), "email") -- l_tpl_block.set_value (a_response.values.item ("email"), "email")
-- l_tpl_block.set_value (a_response.values.item ("name"), "name") -- l_tpl_block.set_value (a_response.values.item ("name"), "name")
if attached recaptcha_site_key (a_response.api) as l_recaptcha_site_key then
l_tpl_block.set_value (l_recaptcha_site_key, "recaptcha_site_key")
end
a_response.add_block (l_tpl_block, "content") a_response.add_block (l_tpl_block, "content")
else else
debug ("cms") debug ("cms")
@@ -593,9 +787,9 @@ feature {NONE} -- Block views
elseif a_response.request.is_post_request_method then elseif a_response.request.is_post_request_method then
if a_response.values.has ("error_email") or else a_response.values.has ("is_active") then if a_response.values.has ("error_email") or else a_response.values.has ("is_active") then
if attached template_block (a_block_id, a_response) as l_tpl_block then if attached template_block (a_block_id, a_response) as l_tpl_block then
-- l_tpl_block.set_value (a_response.values.item ("error_email"), "error_email") -- l_tpl_block.set_value (a_response.values.item ("error_email"), "error_email")
-- l_tpl_block.set_value (a_response.values.item ("email"), "email") -- l_tpl_block.set_value (a_response.values.item ("email"), "email")
-- l_tpl_block.set_value (a_response.values.item ("is_active"), "is_active") -- l_tpl_block.set_value (a_response.values.item ("is_active"), "is_active")
a_response.add_block (l_tpl_block, "content") a_response.add_block (l_tpl_block, "content")
else else
debug ("cms") debug ("cms")
@@ -625,12 +819,12 @@ feature {NONE} -- Block views
end end
end end
elseif a_response.request.is_post_request_method then elseif a_response.request.is_post_request_method then
if a_response.values.has ("error_email") or else a_response.values.has ("error_username") then if a_response.values.has ("error_email") or else a_response.values.has ("error_username") then
if attached template_block (a_block_id, a_response) as l_tpl_block then if attached template_block (a_block_id, a_response) as l_tpl_block then
-- l_tpl_block.set_value (a_response.values.item ("error_email"), "error_email") -- l_tpl_block.set_value (a_response.values.item ("error_email"), "error_email")
-- l_tpl_block.set_value (a_response.values.item ("email"), "email") -- l_tpl_block.set_value (a_response.values.item ("email"), "email")
-- l_tpl_block.set_value (a_response.values.item ("error_username"), "error_username") -- l_tpl_block.set_value (a_response.values.item ("error_username"), "error_username")
-- l_tpl_block.set_value (a_response.values.item ("username"), "username") -- l_tpl_block.set_value (a_response.values.item ("username"), "username")
a_response.add_block (l_tpl_block, "content") a_response.add_block (l_tpl_block, "content")
else else
debug ("cms") debug ("cms")
@@ -653,8 +847,8 @@ feature {NONE} -- Block views
do do
if a_response.request.is_get_request_method then if a_response.request.is_get_request_method then
if attached template_block (a_block_id, a_response) as l_tpl_block then if attached template_block (a_block_id, a_response) as l_tpl_block then
-- l_tpl_block.set_value (a_response.values.item ("token"), "token") -- l_tpl_block.set_value (a_response.values.item ("token"), "token")
-- l_tpl_block.set_value (a_response.values.item ("error_token"), "error_token") -- l_tpl_block.set_value (a_response.values.item ("error_token"), "error_token")
a_response.add_block (l_tpl_block, "content") a_response.add_block (l_tpl_block, "content")
else else
debug ("cms") debug ("cms")
@@ -662,11 +856,11 @@ feature {NONE} -- Block views
end end
end end
elseif a_response.request.is_post_request_method then elseif a_response.request.is_post_request_method then
if a_response.values.has ("error_token") or else a_response.values.has ("error_password") then if a_response.values.has ("error_token") or else a_response.values.has ("error_password") then
if attached template_block (a_block_id, a_response) as l_tpl_block then if attached template_block (a_block_id, a_response) as l_tpl_block then
-- l_tpl_block.set_value (a_response.values.item ("error_token"), "error_token") -- l_tpl_block.set_value (a_response.values.item ("error_token"), "error_token")
-- l_tpl_block.set_value (a_response.values.item ("error_password"), "error_password") -- l_tpl_block.set_value (a_response.values.item ("error_password"), "error_password")
-- l_tpl_block.set_value (a_response.values.item ("token"), "token") -- l_tpl_block.set_value (a_response.values.item ("token"), "token")
a_response.add_block (l_tpl_block, "content") a_response.add_block (l_tpl_block, "content")
else else
debug ("cms") debug ("cms")
@@ -685,14 +879,75 @@ feature {NONE} -- Block views
end end
end end
get_block_view_registration (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE)
do
end
feature -- Recaptcha
recaptcha_secret_key (api: CMS_API): detachable READABLE_STRING_8
-- Get recaptcha security key.
local
utf: UTF_CONVERTER
do
if attached api.module_configuration (Current, Void) as cfg then
if attached cfg.text_item ("recaptcha.secret_key") as l_recaptcha_key and then not l_recaptcha_key.is_empty then
Result := utf.utf_32_string_to_utf_8_string_8 (l_recaptcha_key)
end
end
end
recaptcha_site_key (api: CMS_API): detachable READABLE_STRING_8
-- Get recaptcha security key.
local
utf: UTF_CONVERTER
do
if attached api.module_configuration (Current, Void) as cfg then
if attached cfg.text_item ("recaptcha.site_key") as l_recaptcha_key and then not l_recaptcha_key.is_empty then
Result := utf.utf_32_string_to_utf_8_string_8 (l_recaptcha_key)
end
end
end
feature -- Response Alter
response_alter (a_response: CMS_RESPONSE)
do
a_response.add_javascript_url ("https://www.google.com/recaptcha/api.js")
a_response.add_style (a_response.url ("/module/" + name + "/files/css/auth.css", Void), Void)
end
feature {NONE} -- Implementation
is_captcha_verified (a_secret, a_response: READABLE_STRING_8): BOOLEAN
local
api: RECAPTCHA_API
l_errors: STRING
do
write_debug_log (generator + ".is_captcha_verified with response: [" + a_response + "]")
create api.make (a_secret, a_response)
Result := api.verify
if not Result and then attached api.errors as l_api_errors then
create l_errors.make_empty
l_errors.append_character ('%N')
across
l_api_errors as ic
loop
l_errors.append (ic.item)
l_errors.append_character ('%N')
end
write_error_log (generator + ".is_captcha_verified api_errors [" + l_errors + "]")
end
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)"
source: "[ source: "[
Eiffel Software Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA 5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869 Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com Website http://www.eiffel.com
Customer support http://support.eiffel.com Customer support http://support.eiffel.com
]" ]"
end end

View File

@@ -1,88 +0,0 @@
note
description: "Summary description for {CMS_AUTHENTICATON_EMAIL_SERVICE}."
date: "$Date$"
revision: "$Revision$"
class
CMS_AUTHENTICATON_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_AUTHENTICATION_EMAIL_SERVICE_PARAMETERS
-- Associated parameters.
feature -- Access
contact_email: IMMUTABLE_STRING_8
-- contact email.
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_activation_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_re_activation)
l_message.replace_substring_all ("$link", a_content)
send_message (contact_email, a_to, parameters.contact_subject_activate, l_message)
end
send_contact_password_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_password)
l_message.replace_substring_all ("$link", a_content)
send_message (contact_email, a_to, parameters.contact_subject_password, l_message)
end
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_oauth, l_message)
end
end

View File

@@ -0,0 +1,7 @@
{
"subject": "Thank you for contacting us",
"recaptcha": {
"site_key":"6Lex9RMTAAAAAKleC4x6TaRlFcpLbEWgH_U7MSiD",
"secret_key":"6Lex9RMTAAAAAAkBczvX5DUiyg_xoM_EthVVgRRx"
}
}

View File

@@ -0,0 +1,28 @@
ul.cms-temp-users {
list-style-type: none;
padding: 3px 3px 3px 3px;
border: solid 1px #ccc;
}
ul.cms-temp-users li {
border-top: dotted 1px #ccc;
}
ul.cms-temp-users li:first-child {
border-top: none;
}
ul.cms-temp-users li.cms_temp_user ul.cms_temp_user_details {
list-style-type: none;
padding: 3px 3px 3px 3px;
border: solid 1px #ccc;
}
ul.cms-temp-users li.cms_temp_user ul.cms_temp_user_details li {
border-top: dotted 1px #ccc;
}
ul.cms-temp-users li.cms_temp_user ul.cms_temp_user_details li:first-child {
border-top: none;
}
ul.cms-temp-users li.cms_temp_user ul.cms_temp_user_details li.cms_temp_user_detail_information::before {
content: "[personal information] ";
}
ul.cms-temp-users li.cms_temp_user ul.cms_temp_user_details li.cms_temp_user_detail_email::before {
content: "[email] ";
}

View File

@@ -0,0 +1,37 @@
ul.cms-temp-users {
list-style-type: none;
padding: 3px 3px 3px 3px;
border: solid 1px #ccc;
li{
border-top: dotted 1px #ccc;
&:first-child {
border-top: none;
}
}
li.cms_temp_user {
ul.cms_temp_user_details {
list-style-type: none;
padding: 3px 3px 3px 3px;
border: solid 1px #ccc;
li{
border-top: dotted 1px #ccc;
&:first-child {
border-top: none;
}
}
li.cms_temp_user_detail_information::before{
content: "[personal information] "
}
li.cms_temp_user_detail_email::before{
content: "[email] "
}
}
}
}

View File

@@ -4,15 +4,10 @@
<meta charset="utf-8"> <meta charset="utf-8">
<title>Activation</title> <title>Activation</title>
<meta name="description" content="Activation"> <meta name="description" content="Activation">
<meta name="author" content="ROC CMS"> <meta name="author" content="$sitename">
</head> </head>
<body> <body>
<p>Thank you for registering at <a href="$host">ROC CMS</a></p> <p>"$user ($email)", thank you for applying to <a href="$host">$sitename</a>.</p>
<p>We will review your application and send you a resolution.<p>
<p>To complete your registration, please click on this link to activate your account:<p>
<p><a href="$link">$link</a></p>
<p>Thank you for joining us.</p>
</body> </body>
</html> </html>

View File

@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Activation Confirmation</title>
<meta name="description" content="Activation Confirmation">
<meta name="author" content="$sitename">
</head>
<body>
<p>Your account "$user ($email)" is confirmed at <a href="$host">$sitename</a>.</p>
<p>Thank you for joining us.</p>
</body>
</html>

View File

@@ -4,14 +4,12 @@
<meta charset="utf-8"> <meta charset="utf-8">
<title>New Password</title> <title>New Password</title>
<meta name="description" content="New Password"> <meta name="description" content="New Password">
<meta name="author" content="ROC CMS"> <meta name="author" content="$sitename">
</head> </head>
<body> <body>
<p>You have required a new password at <a href="$host">ROC CMS</a></p> <p>You have requested a new password at <a href="$host">$sitename</a>.</p>
<p>To complete your request, please click on the following link to generate a new password:
<p>To complete your request, please click on this link to genereate a new password:<p> <ul><a href="$link">$link</a></ul>
</p>
<p><a href="$link">$link</a></p>
</body> </body>
</html> </html>

View File

@@ -4,15 +4,14 @@
<meta charset="utf-8"> <meta charset="utf-8">
<title>New Activation</title> <title>New Activation</title>
<meta name="description" content="New Activation token"> <meta name="description" content="New Activation token">
<meta name="author" content="ROC CMS"> <meta name="author" content="$sitename">
</head> </head>
<body> <body>
<p>You have request a new activation token at <a href="$host">ROC CMS</a></p> <p>You have requested a new activation token at <a href="$host">$sitename</a>.</p>
<p>To complete your registration, please click on this link to activate your account:<p> <p>To complete your registration, please click on the following link to re-activate your account:
<ul><a href="$link">$link</a></ul>
<p><a href="$link">$link</a></p> </p>
<p>Thank you for joining us.</p> <p>Thank you for joining us.</p>
</body> </body>
</html> </html>

View File

@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Application Rejected</title>
<meta name="description" content="Application Rejected">
<meta name="author" content="$sitename">
</head>
<body>
<p>Your account application is rejected, it was not respecting the requirements from <a href="$host">$sitename</a>.</p>
</body>
</html>

View File

@@ -4,10 +4,16 @@
<meta charset="utf-8"> <meta charset="utf-8">
<title>Welcome</title> <title>Welcome</title>
<meta name="description" content="Welcome"> <meta name="description" content="Welcome">
<meta name="author" content="ROC CMS"> <meta name="author" content="$sitename">
</head> </head>
<body> <body>
<p>Welcome to<a href="$host">ROC CMS</a></p> <p>Welcome to <a href="$host">$sitename</a>.</p>
<p>Your account information:
<ul>
<li>Email address: "$email" .</li>
<li>User name: "$user" .</li>
</ul>
</p>
<p>Thank you for joining us.</p> <p>Thank you for joining us.</p>
</body> </body>
</html> </html>

View File

@@ -0,0 +1,26 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Account Evaluation</title>
<meta name="description" content="Account Evaluation">
<meta name="author" content="$sitename">
</head>
<body>
<h2> Account Evaluation </h2>
<p>The user $user ($email) wants to register to the site <a href="$host">$sitename</a></p>
<blockquote><p>User application:</p>
<p>$application</p>
</blockquote>
<p>To complete the registration, please click on the following link to activate the user account:<p>
<p><a href="$activation_url">$activation_url</a></p>
<p>To reject the registration, please click on the following link <p>
<p><a href="$rejection_url<">$rejection_url</a></p>
</body>
</html>

View File

@@ -1,3 +1,3 @@
<div> <div>
<p>We have send you a new activation code, check your email to activate your account.</p> <p>Thanks for your application, we will review it to activate your account.</p>
</div> </div>

View File

@@ -1,3 +1,3 @@
<div> <div>
<p>Thanks for register, check your email to activate your account.</p> <p>Thanks for your application, we will review it to activate your account.</p>
</div> </div>

View File

@@ -1,7 +1,7 @@
<div> <div>
<form action="{$site_url/}account/roc-register" method="post"> <form action="{$site_url/}account/roc-register" method="post">
<fieldset> <fieldset>
<legend>Register Form</legend> <legend>Registration</legend>
<div> <div>
<input type="text" id="name" name="name" value="{$name/}" required autofocus /> <input type="text" id="name" name="name" value="{$name/}" required autofocus />
<label for="name">Name</label> <label for="name">Name</label>
@@ -20,8 +20,19 @@
<span><i>{$error_email/}</i></span> <br> <span><i>{$error_email/}</i></span> <br>
{/if} {/if}
</div> </div>
<div>
<textarea rows="4" cols="50" name="personal_information" id="personal_information" required>
{$personal_information/}
</textarea>
<label for="personal_information">Tell us why you want to register an account</label>
{if isset="$error_application"}
<span><i>{$error_application/}</i></span> <br>
{/if}
</div>
{unless isempty="$recaptcha_site_key"}
<div class="g-recaptcha" data-sitekey="{$recaptcha_site_key/}"></div>
<br/>
{/unless}
<button type="submit">Register</button> <button type="submit">Register</button>
</fieldset> </fieldset>
</form> </form>

View File

@@ -13,7 +13,7 @@ inherit
CMS_MODULE CMS_MODULE
redefine redefine
filters, filters,
register_hooks setup_hooks
end end
CMS_HOOK_AUTO_REGISTER CMS_HOOK_AUTO_REGISTER
@@ -101,12 +101,12 @@ feature {NONE} -- Implementation: routes
feature -- Hooks configuration feature -- Hooks configuration
register_hooks (a_response: CMS_RESPONSE) setup_hooks (a_hooks: CMS_HOOK_CORE_MANAGER)
-- Module hooks configuration. -- Module hooks configuration.
do do
auto_subscribe_to_hooks (a_response) auto_subscribe_to_hooks (a_hooks)
a_response.hooks.subscribe_to_block_hook (Current) a_hooks.subscribe_to_block_hook (Current)
a_response.hooks.subscribe_to_value_table_alter_hook (Current) a_hooks.subscribe_to_value_table_alter_hook (Current)
end end
feature -- Hooks feature -- Hooks

View File

@@ -11,7 +11,7 @@ ROC_AUTH.login = function() {
var username = form.username.value; var username = form.username.value;
var password = form.password.value; var password = form.password.value;
//var host = form.host.value; //var host = form.host.value;
var origin = window.location.origin.concat(window.location.pathname); var origin = window.location.origin + window.location.pathname;
var _login = function(){ var _login = function(){
@@ -322,4 +322,4 @@ ROC_AUTH.validatePassword =function(){
if ((password != null) && (confirm_password != null)) { if ((password != null) && (confirm_password != null)) {
password.onchange = ROC_AUTH.validatePassword(); password.onchange = ROC_AUTH.validatePassword();
confirm_password.onkeyup = ROC_AUTH.validatePassword; confirm_password.onkeyup = ROC_AUTH.validatePassword;
} }

View File

@@ -12,7 +12,7 @@ inherit
rename rename
module_api as blog_api module_api as blog_api
redefine redefine
register_hooks, setup_hooks,
initialize, initialize,
install, install,
blog_api blog_api
@@ -66,7 +66,7 @@ feature {CMS_API} -- Module Initialization
ct.extend_format (ic.item) ct.extend_format (ic.item)
end end
l_node_api.add_node_type (ct) l_node_api.add_node_type (ct)
l_node_api.add_content_type_webform_manager (create {CMS_BLOG_NODE_TYPE_WEBFORM_MANAGER}.make (ct)) l_node_api.add_node_type_webform_manager (create {CMS_BLOG_NODE_TYPE_WEBFORM_MANAGER}.make (ct, l_node_api))
-- Add support for CMS_BLOG, which requires a storage extension to store the optional "tags" value -- Add support for CMS_BLOG, which requires a storage extension to store the optional "tags" value
-- For now, we only have extension based on SQL statement. -- For now, we only have extension based on SQL statement.
@@ -153,11 +153,11 @@ feature -- Access: router
feature -- Hooks feature -- Hooks
register_hooks (a_response: CMS_RESPONSE) setup_hooks (a_hooks: CMS_HOOK_CORE_MANAGER)
do do
a_response.hooks.subscribe_to_menu_system_alter_hook (Current) a_hooks.subscribe_to_menu_system_alter_hook (Current)
a_response.hooks.subscribe_to_response_alter_hook (Current) a_hooks.subscribe_to_response_alter_hook (Current)
a_response.hooks.subscribe_to_export_hook (Current) a_hooks.subscribe_to_export_hook (Current)
end end
response_alter (a_response: CMS_RESPONSE) response_alter (a_response: CMS_RESPONSE)

View File

@@ -13,7 +13,7 @@ inherit
populate_form, populate_form,
update_node, update_node,
new_node, new_node,
append_html_output_to append_content_as_html_to
end end
create create
@@ -76,34 +76,24 @@ feature -- form
feature -- Output feature -- Output
append_html_output_to (a_node: CMS_NODE; a_response: NODE_RESPONSE) append_content_as_html_to (a_node: CMS_BLOG; is_teaser: BOOLEAN; a_output: STRING; a_response: detachable CMS_RESPONSE)
-- <Precursor> -- <Precursor>
local
s: STRING
do do
Precursor (a_node, a_response) Precursor (a_node, is_teaser, a_output, a_response)
if attached a_response.main_content as l_main_content then
s := l_main_content
else
create s.make_empty
end
if attached {CMS_BLOG} a_node as l_blog_post then if attached {CMS_BLOG} a_node as l_blog_post then
if attached l_blog_post.tags as l_tags then if attached l_blog_post.tags as l_tags then
s.append ("<div><strong>Tags:</strong> ") a_output.append ("<div><strong>Tags:</strong> ")
across across
l_tags as ic l_tags as ic
loop loop
s.append ("<span class=%"tag%">") a_output.append ("<span class=%"tag%">")
s.append (a_response.html_encoded (ic.item)) a_output.append (cms_api.html_encoded (ic.item))
s.append ("</span> ") a_output.append ("</span> ")
end end
s.append ("</div>") a_output.append ("</div>")
end end
end end
a_response.set_main_content (s)
end end
end end

View File

@@ -206,7 +206,7 @@ feature -- HTML Output
do do
if attached n.author as l_author then if attached n.author as l_author then
a_output.append ("by ") a_output.append ("by ")
a_output.append ("<a class=%"blog_user_link%" href=%"/blogs/user/" + l_author.id.out + "%">" + l_author.name + "</a>") a_output.append ("<a class=%"blog_user_link%" href=%"/blogs/user/" + l_author.id.out + "%">" + html_encoded (l_author.name) + "</a>")
end end
end end
@@ -232,7 +232,7 @@ feature -- HTML Output
if attached api.format (n.format) as f then if attached api.format (n.format) as f then
f.append_formatted_to (l_summary, a_output) f.append_formatted_to (l_summary, a_output)
else else
page.formats.default_format.append_formatted_to (l_summary, a_output) api.formats.default_format.append_formatted_to (l_summary, a_output)
end end
a_output.append ("<br />") a_output.append ("<br />")
a_output.append (page.link ("See more...", lnk.location, Void)) a_output.append (page.link ("See more...", lnk.location, Void))

View File

@@ -12,7 +12,7 @@ inherit
module_api as feed_aggregator_api module_api as feed_aggregator_api
redefine redefine
initialize, initialize,
register_hooks, setup_hooks,
permissions, permissions,
feed_aggregator_api feed_aggregator_api
end end
@@ -181,13 +181,13 @@ feature -- Handle
feature -- Hooks configuration feature -- Hooks configuration
register_hooks (a_response: CMS_RESPONSE) setup_hooks (a_hooks: CMS_HOOK_CORE_MANAGER)
-- Module hooks configuration. -- Module hooks configuration.
do do
a_response.hooks.subscribe_to_block_hook (Current) a_hooks.subscribe_to_block_hook (Current)
a_response.hooks.subscribe_to_response_alter_hook (Current) a_hooks.subscribe_to_response_alter_hook (Current)
a_response.hooks.subscribe_to_menu_system_alter_hook (Current) a_hooks.subscribe_to_menu_system_alter_hook (Current)
a_response.hooks.subscribe_to_cache_hook (Current) a_hooks.subscribe_to_cache_hook (Current)
end end
feature -- Hook feature -- Hook

View File

@@ -41,7 +41,6 @@ feature {NONE} -- Initialization
ct: CMS_PAGE_NODE_TYPE ct: CMS_PAGE_NODE_TYPE
do do
-- Initialize node content types. -- Initialize node content types.
create content_type_webform_managers.make (1)
create ct create ct
--| For now, add all available formats to content type `ct'. --| For now, add all available formats to content type `ct'.
across across
@@ -50,7 +49,7 @@ feature {NONE} -- Initialization
ct.extend_format (ic.item) ct.extend_format (ic.item)
end end
add_node_type (ct) add_node_type (ct)
add_content_type_webform_manager (create {CMS_PAGE_NODE_TYPE_WEBFORM_MANAGER}.make (ct)) add_node_type_webform_manager (create {CMS_PAGE_NODE_TYPE_WEBFORM_MANAGER}.make (ct, Current))
end end
feature {CMS_MODULE} -- Access nodes storage. feature {CMS_MODULE} -- Access nodes storage.
@@ -106,31 +105,16 @@ feature -- Content type
feature -- Content type webform feature -- Content type webform
content_type_webform_managers: ARRAYED_LIST [CMS_CONTENT_TYPE_WEBFORM_MANAGER] content_type_webform_managers: ARRAYED_LIST [CMS_CONTENT_TYPE_WEBFORM_MANAGER [CMS_CONTENT]]
-- Available content types -- Available content types
add_content_type_webform_manager (a_manager: CMS_CONTENT_TYPE_WEBFORM_MANAGER)
-- Register webform manager `a_manager'.
do do
content_type_webform_managers.force (a_manager) Result := cms_api.content_type_webform_managers
end end
content_type_webform_manager (a_content_type: CMS_CONTENT_TYPE): detachable CMS_CONTENT_TYPE_WEBFORM_MANAGER add_node_type_webform_manager (a_manager: CMS_NODE_TYPE_WEBFORM_MANAGER [CMS_NODE])
-- Web form manager for content type `a_content_type' if any. -- Register webform manager `a_manager'.
local
l_type_name: READABLE_STRING_GENERAL
do do
l_type_name := a_content_type.name cms_api.add_content_type_webform_manager (a_manager)
across
content_type_webform_managers as ic
until
Result /= Void
loop
Result := ic.item
if not l_type_name.is_case_insensitive_equal (Result.name) then
Result := Void
end
end
end end
node_type_webform_manager (a_node_type: CMS_CONTENT_TYPE): detachable CMS_NODE_TYPE_WEBFORM_MANAGER_I [CMS_NODE] node_type_webform_manager (a_node_type: CMS_CONTENT_TYPE): detachable CMS_NODE_TYPE_WEBFORM_MANAGER_I [CMS_NODE]

View File

@@ -9,7 +9,7 @@ class
inherit inherit
CMS_MODULE CMS_MODULE
redefine redefine
register_hooks, setup_hooks,
initialize, initialize,
is_installed, is_installed,
install, install,
@@ -25,6 +25,8 @@ inherit
CMS_RECENT_CHANGES_HOOK CMS_RECENT_CHANGES_HOOK
CMS_TAXONOMY_HOOK
CMS_HOOK_EXPORT CMS_HOOK_EXPORT
CMS_EXPORT_NODE_UTILITIES CMS_EXPORT_NODE_UTILITIES
@@ -234,16 +236,17 @@ feature -- Access: router
feature -- Hooks feature -- Hooks
register_hooks (a_response: CMS_RESPONSE) setup_hooks (a_hooks: CMS_HOOK_CORE_MANAGER)
-- <Precursor> -- <Precursor>
do do
a_response.hooks.subscribe_to_menu_system_alter_hook (Current) a_hooks.subscribe_to_menu_system_alter_hook (Current)
a_response.hooks.subscribe_to_block_hook (Current) a_hooks.subscribe_to_block_hook (Current)
a_response.hooks.subscribe_to_response_alter_hook (Current) a_hooks.subscribe_to_response_alter_hook (Current)
a_response.hooks.subscribe_to_export_hook (Current) a_hooks.subscribe_to_export_hook (Current)
-- Module specific hook, if available. -- Module specific hook, if available.
a_response.hooks.subscribe_to_hook (Current, {CMS_RECENT_CHANGES_HOOK}) a_hooks.subscribe_to_hook (Current, {CMS_RECENT_CHANGES_HOOK})
a_hooks.subscribe_to_hook (Current, {CMS_TAXONOMY_HOOK})
end end
response_alter (a_response: CMS_RESPONSE) response_alter (a_response: CMS_RESPONSE)
@@ -364,6 +367,51 @@ feature -- Hooks
end end
end end
populate_content_associated_with_term (t: CMS_TERM; a_contents: CMS_TAXONOMY_ENTITY_CONTAINER)
local
l_node_typenames: ARRAYED_LIST [READABLE_STRING_8]
nid: INTEGER_64
l_info_to_remove: ARRAYED_LIST [TUPLE [entity: READABLE_STRING_32; typename: detachable READABLE_STRING_32]]
do
if
attached node_api as l_node_api and then
attached l_node_api.node_types as l_node_types and then
not l_node_types.is_empty
then
create l_node_typenames.make (l_node_types.count)
across
l_node_types as ic
loop
l_node_typenames.force (ic.item.name)
end
create l_info_to_remove.make (0)
across
a_contents.taxonomy_info as ic
loop
if
attached ic.item.typename as l_typename and then
across l_node_typenames as t_ic some t_ic.item.same_string (l_typename) end
then
if ic.item.entity.is_integer then
nid := ic.item.entity.to_integer_64
if nid > 0 and then attached l_node_api.node (nid) as l_node then
if l_node.link = Void then
l_node.set_link (l_node_api.node_link (l_node))
end
a_contents.force (create {CMS_TAXONOMY_ENTITY}.make (l_node, l_node.modification_date))
l_info_to_remove.force (ic.item)
end
end
end
end
across
l_info_to_remove as ic
loop
a_contents.taxonomy_info.prune_all (ic.item)
end
end
end
export_to (a_export_id_list: detachable ITERABLE [READABLE_STRING_GENERAL]; a_export_parameters: CMS_EXPORT_PARAMETERS; a_response: CMS_RESPONSE) export_to (a_export_id_list: detachable ITERABLE [READABLE_STRING_GENERAL]; a_export_parameters: CMS_EXPORT_PARAMETERS; a_response: CMS_RESPONSE)
-- Export data identified by `a_export_id_list', -- Export data identified by `a_export_id_list',
-- or export all data if `a_export_id_list' is Void. -- or export all data if `a_export_id_list' is Void.

View File

@@ -11,8 +11,10 @@ deferred class
inherit inherit
CMS_CONTENT CMS_CONTENT
rename
has_identifier as has_id
redefine redefine
debug_output debug_output, has_id
end end
REFACTORING_HELPER REFACTORING_HELPER
@@ -63,6 +65,12 @@ feature -- Conversion
feature -- Access feature -- Access
identifier: detachable IMMUTABLE_STRING_32
-- Optional identifier.
do
create Result.make_from_string_general (id.out)
end
id: INTEGER_64 assign set_id id: INTEGER_64 assign set_id
-- Unique id. -- Unique id.
--| Should we use NATURAL_64 instead? --| Should we use NATURAL_64 instead?

View File

@@ -1,33 +0,0 @@
note
description: "[
Html builder for content type `content_type'.
This is used to build webform and html output for a specific node, or node content type.
]"
date: "$Date$"
revision: "$Revision$"
deferred class
CMS_CONTENT_TYPE_WEBFORM_MANAGER
inherit
CMS_API_ACCESS
feature {NONE} -- Initialization
make (a_type: like content_type)
do
content_type := a_type
end
feature -- Access
content_type: CMS_CONTENT_TYPE
-- Associated content type.
name: READABLE_STRING_8
-- Associated content type name.
do
Result := content_type.name
end
end

View File

@@ -92,228 +92,15 @@ feature -- Forms ...
f.extend (fset) f.extend (fset)
-- Path alias -- Path alias
populate_form_with_taxonomy (response, f, a_node) populate_form_with_taxonomy (response, f, a_node)
populate_form_with_path_alias (response, f, a_node) populate_form_with_path_alias (response, f, a_node)
end end
populate_form_with_taxonomy (response: NODE_RESPONSE; f: CMS_FORM; a_node: detachable CMS_NODE) populate_form_with_taxonomy (response: CMS_RESPONSE; f: CMS_FORM; a_content: detachable CMS_CONTENT)
local
ti: detachable WSF_FORM_TEXT_INPUT
w_set: WSF_FORM_FIELD_SET
w_select: WSF_FORM_SELECT
w_opt: WSF_FORM_SELECT_OPTION
w_cb: WSF_FORM_CHECKBOX_INPUT
w_voc_set: WSF_FORM_FIELD_SET
s: STRING_32
voc: CMS_VOCABULARY
t: detachable CMS_TERM
l_terms: detachable CMS_TERM_COLLECTION
l_has_edit_permission: BOOLEAN
do do
if if attached {CMS_TAXONOMY_API} response.api.module_api ({CMS_TAXONOMY_MODULE}) as l_taxonomy_api then
attached {CMS_TAXONOMY_API} response.api.module_api ({CMS_TAXONOMY_MODULE}) as l_taxonomy_api and then l_taxonomy_api.populate_edit_form (response, f, content_type.name, a_content)
attached l_taxonomy_api.vocabularies_for_type (content_type.name) as l_vocs and then not l_vocs.is_empty
then
l_has_edit_permission := response.has_permissions (<<"update any taxonomy", "update " + content_type.name + " taxonomy">>)
-- Handle Taxonomy fields, if any associated with `content_type'.
create w_set.make
w_set.add_css_class ("taxonomy")
l_vocs.sort
across
l_vocs as vocs_ic
loop
voc := vocs_ic.item
l_terms := Void
if a_node /= Void and then a_node.has_id then
l_terms := l_taxonomy_api.terms_of_entity (a_node.content_type, a_node.id.out, voc)
if l_terms /= Void then
l_terms.sort
end
end
create w_voc_set.make
w_set.extend (w_voc_set)
if voc.is_tags then
w_voc_set.set_legend (response.translation (voc.name, Void))
create ti.make ({STRING_32} "taxonomy_terms[" + voc.name + "]")
w_voc_set.extend (ti)
if voc.is_term_required then
ti.enable_required
end
if attached voc.description as l_desc then
ti.set_description (response.html_encoded (response.translation (l_desc, Void)))
else
ti.set_description (response.html_encoded (response.translation (voc.name, Void)))
end
ti.set_size (70)
if l_terms /= Void then
create s.make_empty
across
l_terms as ic
loop
t := ic.item
if not s.is_empty then
s.append_character (',')
s.append_character (' ')
end
if ic.item.text.has (' ') then
s.append_character ('"')
s.append (t.text)
s.append_character ('"')
else
s.append (t.text)
end
end
ti.set_text_value (s)
end
if not l_has_edit_permission then
ti.set_is_readonly (True)
end
else
l_taxonomy_api.fill_vocabularies_with_terms (voc)
if not voc.terms.is_empty then
if voc.multiple_terms_allowed then
if attached voc.description as l_desc then
w_voc_set.set_legend (response.html_encoded (l_desc))
else
w_voc_set.set_legend (response.html_encoded (voc.name))
end
across
voc as voc_terms_ic
loop
t := voc_terms_ic.item
create w_cb.make_with_value ({STRING_32} "taxonomy_terms[" + voc.name + "]", t.text)
w_voc_set.extend (w_cb)
if l_terms /= Void and then across l_terms as ic some ic.item.text.same_string (t.text) end then
w_cb.set_checked (True)
end
if not l_has_edit_permission then
w_cb.set_is_readonly (True)
end
end
else
create w_select.make ({STRING_32} "taxonomy_terms[" + voc.name + "]")
w_voc_set.extend (w_select)
if attached voc.description as l_desc then
w_select.set_description (response.html_encoded (l_desc))
else
w_select.set_description (response.html_encoded (voc.name))
end
w_voc_set.set_legend (response.html_encoded (voc.name))
across
voc as voc_terms_ic
loop
t := voc_terms_ic.item
create w_opt.make (response.html_encoded (t.text), response.html_encoded (t.text))
w_select.add_option (w_opt)
if l_terms /= Void and then across l_terms as ic some ic.item.text.same_string (t.text) end then
w_opt.set_is_selected (True)
end
end
if not l_has_edit_permission then
w_select.set_is_readonly (True)
end
end
end
end
end
f.submit_actions.extend (agent taxonomy_submit_action (response, l_taxonomy_api, l_vocs, a_node, ?))
if
attached f.fields_by_name ("title") as l_title_fields and then
attached l_title_fields.first as l_title_field
then
f.insert_after (w_set, l_title_field)
else
f.extend (w_set)
end
end
end
taxonomy_submit_action (a_response: CMS_RESPONSE; a_taxonomy_api: CMS_TAXONOMY_API; a_vocs: CMS_VOCABULARY_COLLECTION; a_node: detachable CMS_NODE fd: WSF_FORM_DATA)
require
vocs_not_empty: not a_vocs.is_empty
local
l_voc_name: READABLE_STRING_32
l_terms_to_remove: ARRAYED_LIST [CMS_TERM]
l_new_terms: LIST [READABLE_STRING_32]
l_text: READABLE_STRING_GENERAL
l_found: BOOLEAN
t: detachable CMS_TERM
do
if
a_node /= Void and then a_node.has_id and then
attached fd.table_item ("taxonomy_terms") as fd_terms
then
across
fd_terms.values as ic
loop
if attached {WSF_STRING} ic.item as l_string then
l_voc_name := ic.key
l_new_terms := a_taxonomy_api.splitted_string (l_string.value, ',')
if attached a_vocs.item_by_name (l_voc_name) as voc then
if a_response.has_permissions (<<{STRING_32} "update any taxonomy", {STRING_32} "update " + content_type.name + " taxonomy">>) then
create l_terms_to_remove.make (0)
if attached a_taxonomy_api.terms_of_entity (content_type.name, a_node.id.out, voc) as l_existing_terms then
across
l_existing_terms as t_ic
loop
l_text := t_ic.item.text
from
l_found := False
l_new_terms.start
until
l_new_terms.after
loop
if l_new_terms.item.same_string_general (l_text) then
-- Already associated with term `t_ic.text'.
l_found := True
l_new_terms.remove
else
l_new_terms.forth
end
end
if not l_found then
-- Remove term
l_terms_to_remove.force (t_ic.item)
end
end
across
l_terms_to_remove as t_ic
loop
a_taxonomy_api.unassociate_term_from_entity (t_ic.item, content_type.name, a_node.id.out)
end
end
across
l_new_terms as t_ic
loop
t := a_taxonomy_api.term_by_text (t_ic.item, voc)
if
t = Void and voc.is_tags
then
-- Create new term!
create t.make (t_ic.item)
a_taxonomy_api.save_term (t, voc)
if a_taxonomy_api.has_error then
t := Void
end
end
if t /= Void then
a_taxonomy_api.associate_term_with_entity (t, content_type.name, a_node.id.out)
end
end
end
end
end
end
end end
end end
@@ -400,7 +187,7 @@ feature -- Forms ...
elseif a_node /= Void and then attached a_node.format as s_format and then attached response.api.format (s_format) as f_format then elseif a_node /= Void and then attached a_node.format as s_format and then attached response.api.format (s_format) as f_format then
f := f_format f := f_format
else else
f := response.formats.default_format f := cms_api.formats.default_format
end end
-- Update node with summary and body content -- Update node with summary and body content
@@ -464,7 +251,7 @@ feature -- Forms ...
elseif a_node /= Void and then attached a_node.format as s_format and then attached response.api.format (s_format) as f_format then elseif a_node /= Void and then attached a_node.format as s_format and then attached response.api.format (s_format) as f_format then
f := f_format f := f_format
else else
f := response.formats.default_format f := cms_api.formats.default_format
end end
-- Update node with summary and content -- Update node with summary and content
@@ -476,133 +263,104 @@ feature -- Forms ...
feature -- Output feature -- Output
append_html_output_to (a_node: CMS_NODE; a_response: NODE_RESPONSE) append_content_as_html_to (a_node: G; is_teaser: BOOLEAN; a_output: STRING; a_response: detachable CMS_RESPONSE)
-- <Precursor> -- <Precursor>
local local
lnk: CMS_LOCAL_LINK lnk: detachable CMS_LOCAL_LINK
hdate: HTTP_DATE hdate: HTTP_DATE
s: STRING l_node_api: CMS_NODE_API
node_api: CMS_NODE_API
do do
node_api := a_response.node_api l_node_api := node_api
a_response.set_value (a_node, "node")
-- Show tabs only if a user is authenticated. -- Show tabs only if a user is authenticated.
if attached a_response.user as l_user then if
lnk := a_response.node_local_link (a_node, a_response.translation ("View", Void)) not is_teaser and then
a_response /= Void and then
attached a_response.user as l_user
then
lnk := a_node.link
if lnk /= Void then
lnk := a_response.local_link (a_response.translation ("View", Void), lnk.location)
else
lnk := a_response.local_link (a_response.translation ("View", Void), l_node_api.node_path (a_node))
end
lnk.set_weight (1) lnk.set_weight (1)
a_response.add_to_primary_tabs (lnk) a_response.add_to_primary_tabs (lnk)
if a_node.status = {CMS_NODE_API}.trashed then if a_node.status = {CMS_NODE_API}.trashed then
create lnk.make ("Delete", node_api.node_path (a_node) + "/delete") create lnk.make ("Delete", l_node_api.node_path (a_node) + "/delete")
lnk.set_weight (2) lnk.set_weight (2)
a_response.add_to_primary_tabs (lnk) a_response.add_to_primary_tabs (lnk)
elseif a_node.has_id then elseif a_node.has_id then
-- Node in {{CMS_NODE_API}.published} or {CMS_NODE_API}.not_published} status. -- Node in {{CMS_NODE_API}.published} or {CMS_NODE_API}.not_published} status.
create lnk.make ("Edit", node_api.node_path (a_node) + "/edit") create lnk.make ("Edit", l_node_api.node_path (a_node) + "/edit")
lnk.set_weight (2) lnk.set_weight (2)
a_response.add_to_primary_tabs (lnk) a_response.add_to_primary_tabs (lnk)
if if
node_api.has_permission_for_action_on_node ("view revisions", a_node, l_user) l_node_api.has_permission_for_action_on_node ("view revisions", a_node, l_user)
then then
create lnk.make ("Revisions", node_api.node_path (a_node) + "/revision") create lnk.make ("Revisions", l_node_api.node_path (a_node) + "/revision")
lnk.set_weight (3) lnk.set_weight (3)
a_response.add_to_primary_tabs (lnk) a_response.add_to_primary_tabs (lnk)
end end
if if
node_api.has_permission_for_action_on_node ("trash", a_node, l_user) l_node_api.has_permission_for_action_on_node ("trash", a_node, l_user)
then then
create lnk.make ("Move to trash", node_api.node_path (a_node) + "/trash") create lnk.make ("Move to trash", l_node_api.node_path (a_node) + "/trash")
lnk.set_weight (3) lnk.set_weight (3)
a_response.add_to_primary_tabs (lnk) a_response.add_to_primary_tabs (lnk)
end end
end end
end end
create s.make_empty a_output.append ("<div class=%"")
s.append ("<div class=%"cms-node node-" + a_node.content_type + "%">") if is_teaser then
s.append ("<div class=%"info%"> ") a_output.append (" cms-teaser")
end
a_output.append ("cms-node node-" + a_node.content_type + "%">")
a_output.append ("<div class=%"info%"> ")
if attached a_node.author as l_author then if attached a_node.author as l_author then
s.append (" by ") a_output.append (" by ")
s.append (a_response.html_encoded (l_author.name)) a_output.append (l_node_api.html_encoded (l_author.name))
end end
if attached a_node.modification_date as l_modified then if attached a_node.modification_date as l_modified then
s.append (" (modified: ") a_output.append (" (modified: ")
create hdate.make_from_date_time (l_modified) create hdate.make_from_date_time (l_modified)
s.append (hdate.yyyy_mmm_dd_string) a_output.append (hdate.yyyy_mmm_dd_string)
s.append (")") a_output.append (")")
end end
s.append ("</div>") a_output.append ("</div>")
if if
attached {CMS_TAXONOMY_API} a_response.api.module_api ({CMS_TAXONOMY_MODULE}) as l_taxonomy_api and then a_response /= Void and then
attached l_taxonomy_api.vocabularies_for_type (content_type.name) as vocs and then not vocs.is_empty attached {CMS_TAXONOMY_API} cms_api.module_api ({CMS_TAXONOMY_MODULE}) as l_taxonomy_api
then then
vocs.sort l_taxonomy_api.append_taxonomy_to_xhtml (a_node, a_response, a_output)
across
vocs as ic
loop
if
attached l_taxonomy_api.terms_of_entity (content_type.name, a_node.id.out, ic.item) as l_terms and then
not l_terms.is_empty
then
s.append ("<ul class=%"taxonomy term-" + ic.item.id.out + "%">")
s.append (a_response.html_encoded (ic.item.name))
s.append (": ")
across
l_terms as t_ic
loop
s.append ("<li>")
a_response.append_link_to_html (t_ic.item.text, "taxonomy/term/" + t_ic.item.id.out, Void, s)
s.append ("</li>")
end
s.append ("</ul>%N")
end
end
end end
-- We don't show the summary on the detail page, since its just a short view of the full content. Otherwise we would write the same thing twice. -- We don't show the summary on the detail page, since its just a short view of the full content. Otherwise we would write the same thing twice.
-- The usage of the summary is to give a short overview in the list of nodes or for the meta tag "description" -- The usage of the summary is to give a short overview in the list of nodes or for the meta tag "description"
if is_teaser then
-- if attached a_node.summary as l_summary then if attached a_node.summary as l_summary then
-- s.append ("<p class=%"summary%">") a_output.append ("<p class=%"summary%">")
-- if attached node_api.cms_api.format (a_node.format) as f then if attached cms_api.format (a_node.format) as f then
-- append_formatted_output (l_content, f, s) append_formatted_content_to (l_summary, f, a_output)
-- else else
-- append_formatted_output (l_content, a_response.formats.default_format, s) append_formatted_content_to (l_summary, cms_api.formats.default_format, a_output)
-- end end
a_output.append ("</p>")
-- s.append ("</p>")
-- end
if attached a_node.content as l_content then
s.append ("<p class=%"content%">")
if attached node_api.cms_api.format (a_node.format) as f then
append_formatted_output (l_content, f, s)
else
append_formatted_output (l_content, a_response.formats.default_format, s)
end end
elseif attached a_node.content as l_content then
s.append ("</p>") a_output.append ("<p class=%"content%">")
end if attached cms_api.format (a_node.format) as f then
s.append ("</div>") append_formatted_content_to (l_content, f, a_output)
else
a_response.set_title (a_node.title) append_formatted_content_to (l_content, cms_api.formats.default_format, a_output)
a_response.set_main_content (s) end
end a_output.append ("</p>")
append_formatted_output (a_content: READABLE_STRING_GENERAL; a_format: CONTENT_FORMAT; a_output: STRING_8)
-- Format `a_content' with format `a_format'.
do
if a_content.is_valid_as_string_8 then
a_output.append (a_format.formatted_output (a_content.to_string_8))
else
a_format.append_formatted_to (a_content, a_output)
end end
a_output.append ("</div>")
end end
end end

View File

@@ -10,16 +10,35 @@ deferred class
CMS_NODE_TYPE_WEBFORM_MANAGER_I [G -> CMS_NODE] CMS_NODE_TYPE_WEBFORM_MANAGER_I [G -> CMS_NODE]
inherit inherit
CMS_CONTENT_TYPE_WEBFORM_MANAGER CMS_CONTENT_TYPE_WEBFORM_MANAGER [CMS_NODE]
rename
make as old_make
redefine redefine
content_type content_type
end end
feature {NONE} -- Initialization
make (a_type: like content_type; a_node_api: CMS_NODE_API)
do
node_api := a_node_api
old_make (a_type)
end
feature -- Access feature -- Access
content_type: CMS_NODE_TYPE [G] content_type: CMS_NODE_TYPE [G]
-- Associated content type. -- Associated content type.
cms_api: CMS_API
-- API for current instance of CMS.
do
Result := node_api.cms_api
end
node_api: CMS_NODE_API
-- Associated node API.
feature -- Query feature -- Query
has_valid_node_type (a_node: CMS_NODE): BOOLEAN has_valid_node_type (a_node: CMS_NODE): BOOLEAN
@@ -57,11 +76,18 @@ feature -- Node ...
feature -- Output feature -- Output
append_html_output_to (a_node: CMS_NODE; a_response: NODE_RESPONSE) append_content_as_html_to_page (a_node: G; a_response: NODE_RESPONSE)
-- Append an html representation of `a_node' to response `a_response'. -- Append an html representation of `a_node' to response `a_response'.
require require
has_valid_node_type (a_node) has_valid_node_type (a_node)
deferred local
s: STRING
do
create s.make_empty
a_response.set_value (a_node, "node")
a_response.set_title (a_node.title)
append_content_as_html_to (a_node, False, s, a_response)
a_response.set_main_content (s)
end end
end end

View File

@@ -10,7 +10,7 @@ inherit
CMS_NODE_TYPE_WEBFORM_MANAGER [CMS_PAGE] CMS_NODE_TYPE_WEBFORM_MANAGER [CMS_PAGE]
redefine redefine
content_type, content_type,
append_html_output_to, append_content_as_html_to,
populate_form, populate_form,
new_node, new_node,
update_node update_node
@@ -102,27 +102,27 @@ feature -- Forms ...
parent_validation (a_response: NODE_RESPONSE; fd: WSF_FORM_DATA) parent_validation (a_response: NODE_RESPONSE; fd: WSF_FORM_DATA)
local local
node_api: CMS_NODE_API l_node_api: CMS_NODE_API
l_parent_id: INTEGER_64 l_parent_id: INTEGER_64
nid: INTEGER_64 nid: INTEGER_64
l_parent_node: detachable CMS_NODE l_parent_node: detachable CMS_NODE
do do
node_api := a_response.node_api l_node_api := node_api
if attached fd.integer_item ("select_parent_node") as s_parent_node then if attached fd.integer_item ("select_parent_node") as s_parent_node then
l_parent_id := s_parent_node.to_integer_64 l_parent_id := s_parent_node.to_integer_64
else else
l_parent_id := 0 l_parent_id := 0
end end
if l_parent_id > 0 then if l_parent_id > 0 then
l_parent_node := node_api.node (l_parent_id) l_parent_node := l_node_api.node (l_parent_id)
if l_parent_node = Void then if l_parent_node = Void then
fd.report_invalid_field ("select_parent_node", "Invalid parent, not found id #" + l_parent_id.out) fd.report_invalid_field ("select_parent_node", "Invalid parent, not found id #" + l_parent_id.out)
else else
nid := a_response.node_id_path_parameter nid := a_response.node_id_path_parameter
if if
nid > 0 and then nid > 0 and then
attached node_api.node (nid) as l_node and then attached l_node_api.node (nid) as l_node and then
node_api.is_node_a_parent_of (l_node, l_parent_node) l_node_api.is_node_a_parent_of (l_node, l_parent_node)
then then
fd.report_invalid_field ("select_parent_node", "Invalid parent due to cycle (node #" + nid.out + " is already a parent of node #" + l_parent_id.out) fd.report_invalid_field ("select_parent_node", "Invalid parent due to cycle (node #" + nid.out + " is already a parent of node #" + l_parent_id.out)
end end
@@ -137,50 +137,51 @@ feature -- Forms ...
feature -- Output feature -- Output
append_html_output_to (a_node: CMS_NODE; a_response: NODE_RESPONSE) append_content_as_html_to (a_node: CMS_PAGE; is_teaser: BOOLEAN; a_output: STRING; a_response: detachable CMS_RESPONSE)
-- <Precursor> -- <Precursor>
local local
s: STRING l_node_api: CMS_NODE_API
node_api: CMS_NODE_API
lnk: CMS_LOCAL_LINK lnk: CMS_LOCAL_LINK
do do
node_api := a_response.node_api Precursor (a_node, is_teaser, a_output, a_response)
Precursor (a_node, a_response)
if not is_teaser then
if a_node.has_id and then not a_node.is_trashed then l_node_api := node_api
if node_api.has_permission_for_action_on_node ("create", a_node, a_response.user) then if
create lnk.make ("Add Child", "node/add/page?parent=" + a_node.id.out) a_response /= Void and then
lnk.set_weight (3) a_node.has_id and then not a_node.is_trashed
a_response.add_to_primary_tabs (lnk) then
end if
end l_node_api.has_permission_for_action_on_node ("create", a_node, a_response.user)
then
if attached a_response.main_content as l_main_content then create lnk.make ("Add Child", "node/add/page?parent=" + a_node.id.out)
s := l_main_content lnk.set_weight (3)
else a_response.add_to_primary_tabs (lnk)
create s.make_empty
end
if attached {CMS_PAGE} a_node as l_node_page then
s.append ("<ul class=%"page-navigation%">")
if attached l_node_page.parent as l_parent_node then
s.append ("<li class=%"page-parent%">Go to parent page ")
s.append (a_response.link (l_parent_node.title, a_response.node_api.node_path (l_parent_node), Void))
s.append ("</li>")
end
if attached node_api.children (a_node) as l_children then
across
l_children as ic
loop
s.append ("<li>")
s.append (a_response.link (ic.item.title, a_response.node_api.node_path (ic.item), Void))
s.append ("</li>")
end end
end end
s.append ("</ul>")
end
a_response.set_main_content (s) if
a_response /= Void and then
attached {CMS_PAGE} a_node as l_node_page
then
a_output.append ("<ul class=%"page-navigation%">")
if attached l_node_page.parent as l_parent_node then
a_output.append ("<li class=%"page-parent%">Go to parent page ")
a_output.append (a_response.link (l_parent_node.title, l_node_api.node_path (l_parent_node), Void))
a_output.append ("</li>")
end
if attached l_node_api.children (a_node) as l_children then
across
l_children as ic
loop
a_output.append ("<li>")
a_output.append (a_response.link (ic.item.title, l_node_api.node_path (ic.item), Void))
a_output.append ("</li>")
end
end
a_output.append ("</ul>")
end
end
end end
end end

View File

@@ -7,30 +7,10 @@ class
inherit inherit
NODE_RESPONSE NODE_RESPONSE
redefine
make,
initialize
end
create create
make make
feature {NONE} -- Initialization
make (req: WSF_REQUEST; res: WSF_RESPONSE; a_api: like api; a_node_api: like node_api)
do
create {WSF_NULL_THEME} wsf_theme.make
Precursor (req, res, a_api, a_node_api)
end
initialize
do
Precursor
create {CMS_TO_WSF_THEME} wsf_theme.make (Current, theme)
end
wsf_theme: WSF_THEME
feature -- Execution feature -- Execution
process process
@@ -114,7 +94,7 @@ feature {NONE} -- Create a new node
if attached a_type.new_node (Void) as l_node then if attached a_type.new_node (Void) as l_node then
-- create new node -- create new node
f := new_edit_form (l_node, url (location, Void), "edit-" + a_type.name, a_type) f := new_edit_form (l_node, url (location, Void), "edit-" + a_type.name, a_type)
hooks.invoke_form_alter (f, fd, Current) api.hooks.invoke_form_alter (f, fd, Current)
if request.is_post_request_method then if request.is_post_request_method then
f.validation_actions.extend (agent edit_form_validate (?, b)) f.validation_actions.extend (agent edit_form_validate (?, b))
f.submit_actions.put_front (agent edit_form_submit (?, l_node, a_type, b)) f.submit_actions.put_front (agent edit_form_submit (?, l_node, a_type, b))
@@ -144,7 +124,7 @@ feature {NONE} -- Create a new node
fd: detachable WSF_FORM_DATA fd: detachable WSF_FORM_DATA
do do
f := new_edit_form (A_node, url (location, Void), "edit-" + a_type.name, a_type) f := new_edit_form (A_node, url (location, Void), "edit-" + a_type.name, a_type)
hooks.invoke_form_alter (f, fd, Current) api.hooks.invoke_form_alter (f, fd, Current)
if request.is_post_request_method then if request.is_post_request_method then
f.validation_actions.extend (agent edit_form_validate (?, b)) f.validation_actions.extend (agent edit_form_validate (?, b))
f.submit_actions.put_front (agent edit_form_submit (?, a_node, a_type, b)) f.submit_actions.put_front (agent edit_form_submit (?, a_node, a_type, b))
@@ -175,7 +155,7 @@ feature {NONE} -- Create a new node
do do
if a_node.is_trashed then if a_node.is_trashed then
f := new_delete_form (a_node, url (location, Void), "delete-" + a_type.name, a_type) f := new_delete_form (a_node, url (location, Void), "delete-" + a_type.name, a_type)
hooks.invoke_form_alter (f, fd, Current) api.hooks.invoke_form_alter (f, fd, Current)
if request.is_post_request_method then if request.is_post_request_method then
f.process (Current) f.process (Current)
fd := f.last_data fd := f.last_data
@@ -206,7 +186,7 @@ feature {NONE} -- Create a new node
fd: detachable WSF_FORM_DATA fd: detachable WSF_FORM_DATA
do do
f := new_trash_form (a_node, url (location, Void), "trash-" + a_type.name, a_type) f := new_trash_form (a_node, url (location, Void), "trash-" + a_type.name, a_type)
hooks.invoke_form_alter (f, fd, Current) api.hooks.invoke_form_alter (f, fd, Current)
if request.is_post_request_method then if request.is_post_request_method then
f.process (Current) f.process (Current)
fd := f.last_data fd := f.last_data
@@ -298,10 +278,10 @@ feature -- Form
if attached user as u then if attached user as u then
api.log ("node", api.log ("node",
"User %"" + user_html_link (u) + "%" " + s + " node " + node_html_link (l_node, a_type.name + " #" + l_node.id.out), "User %"" + user_html_link (u) + "%" " + s + " node " + node_html_link (l_node, a_type.name + " #" + l_node.id.out),
0, node_local_link (l_node, Void) {CMS_LOG}.level_notice, node_local_link (l_node, Void)
) )
else else
api.log ("node", "Anonymous " + s + " node " + a_type.name +" #" + l_node.id.out, 0, node_local_link (l_node, Void)) api.log ("node", "Anonymous " + s + " node " + a_type.name +" #" + l_node.id.out, {CMS_LOG}.level_notice, node_local_link (l_node, Void))
end end
if node_api.has_error then if node_api.has_error then
add_error_message ("Node #" + l_node.id.out + " failed to save.") add_error_message ("Node #" + l_node.id.out + " failed to save.")

View File

@@ -42,15 +42,6 @@ feature -- Helpers
feature -- Helpers: cms link feature -- Helpers: cms link
user_local_link (u: CMS_USER; a_opt_title: detachable READABLE_STRING_GENERAL): CMS_LOCAL_LINK
do
if a_opt_title /= Void then
create Result.make (a_opt_title, user_url (u))
else
create Result.make (u.name, user_url (u))
end
end
node_local_link (n: CMS_NODE; a_opt_title: detachable READABLE_STRING_GENERAL): CMS_LOCAL_LINK node_local_link (n: CMS_NODE; a_opt_title: detachable READABLE_STRING_GENERAL): CMS_LOCAL_LINK
do do
if attached n.link as lnk then if attached n.link as lnk then
@@ -59,17 +50,12 @@ feature -- Helpers: cms link
Result := node_api.node_link (n) Result := node_api.node_link (n)
end end
if a_opt_title /= Void and then not Result.title.same_string_general (a_opt_title) then if a_opt_title /= Void and then not Result.title.same_string_general (a_opt_title) then
create Result.make (a_opt_title, Result.location) Result := local_link (a_opt_title, Result.location)
end end
end end
feature -- Helpers: html link feature -- Helpers: html link
user_html_link (u: CMS_USER): like link
do
Result := link (u.name, "user/" + u.id.out, Void)
end
node_html_link (n: CMS_NODE; a_opt_title: detachable READABLE_STRING_GENERAL): like link node_html_link (n: CMS_NODE; a_opt_title: detachable READABLE_STRING_GENERAL): like link
local local
l_title: detachable READABLE_STRING_GENERAL l_title: detachable READABLE_STRING_GENERAL
@@ -80,18 +66,10 @@ feature -- Helpers: html link
l_title := n.title l_title := n.title
end end
Result := link (l_title, node_api.node_path (n), Void) Result := link (l_title, node_api.node_path (n), Void)
end end
feature -- Helpers: URL feature -- Helpers: URL
user_url (u: CMS_USER): like url
require
u_with_id: u.has_id
do
Result := url ("user/" + u.id.out, Void)
end
node_url (n: CMS_NODE): like url node_url (n: CMS_NODE): like url
require require
n_with_id: n.has_id n_with_id: n.has_id

View File

@@ -8,30 +8,10 @@ class
inherit inherit
NODE_RESPONSE NODE_RESPONSE
redefine
make,
initialize
end
create create
make make
feature {NONE} -- Initialization
make (req: WSF_REQUEST; res: WSF_RESPONSE; a_api: like api; a_node_api: like node_api)
do
create {WSF_NULL_THEME} wsf_theme.make
Precursor (req, res, a_api, a_node_api)
end
initialize
do
Precursor
create {CMS_TO_WSF_THEME} wsf_theme.make (Current, theme)
end
wsf_theme: WSF_THEME
feature -- Access feature -- Access
node: detachable CMS_NODE node: detachable CMS_NODE
@@ -71,7 +51,7 @@ feature -- Execution
attached node_api.node_type_for (l_node) as l_content_type and then attached node_api.node_type_for (l_node) as l_content_type and then
attached node_api.node_type_webform_manager (l_content_type) as l_manager attached node_api.node_type_webform_manager (l_content_type) as l_manager
then then
l_manager.append_html_output_to (l_node, Current) l_manager.append_content_as_html_to_page (l_node, Current)
end end
elseif revision > 0 then elseif revision > 0 then
set_main_content ("Missing revision node!") set_main_content ("Missing revision node!")

View File

@@ -12,7 +12,7 @@ inherit
module_api as user_oauth_api module_api as user_oauth_api
redefine redefine
filters, filters,
register_hooks, setup_hooks,
initialize, initialize,
install, install,
user_oauth_api user_oauth_api
@@ -99,7 +99,7 @@ feature {CMS_API} -- Module management
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 blog module", generating_type) api.logger.put_error ("Could not initialize database for oauth_20 module", generating_type)
end end
-- 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)
@@ -108,7 +108,7 @@ feature {CMS_API} -- Module management
-- TODO workaround, until we have an admin module -- TODO workaround, until we have an admin module
l_sql_storage.sql_query ("SELECT name FROM oauth2_consumers;", Void) l_sql_storage.sql_query ("SELECT name FROM oauth2_consumers;", Void)
if l_sql_storage.has_error then if l_sql_storage.has_error then
api.logger.put_error ("Could not initialize database for differnent consumerns", generating_type) api.logger.put_error ("Could not initialize database for differnent consumers", generating_type)
else else
from from
l_sql_storage.sql_start l_sql_storage.sql_start
@@ -190,12 +190,12 @@ feature -- Router
feature -- Hooks configuration feature -- Hooks configuration
register_hooks (a_response: CMS_RESPONSE) setup_hooks (a_hooks: CMS_HOOK_CORE_MANAGER)
-- Module hooks configuration. -- Module hooks configuration.
do do
auto_subscribe_to_hooks (a_response) auto_subscribe_to_hooks (a_hooks)
a_response.hooks.subscribe_to_block_hook (Current) a_hooks.subscribe_to_block_hook (Current)
a_response.hooks.subscribe_to_value_table_alter_hook (Current) a_hooks.subscribe_to_value_table_alter_hook (Current)
end end
feature -- Hooks feature -- Hooks
@@ -227,7 +227,10 @@ feature -- Hooks
until until
lnk2 /= Void lnk2 /= Void
loop loop
if ic.item.location.same_string ("account/roc-logout") then if
ic.item.location.same_string ("account/roc-logout") or else
ic.item.location.same_string ("basic_auth_logoff")
then
lnk2 := ic.item lnk2 := ic.item
end end
end end
@@ -427,7 +430,7 @@ feature -- OAuth2 Login with Provider
l_user: CMS_USER l_user: CMS_USER
l_roles: LIST [CMS_USER_ROLE] l_roles: LIST [CMS_USER_ROLE]
l_cookie: WSF_COOKIE l_cookie: WSF_COOKIE
es: CMS_AUTHENTICATON_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 ({CMS_OAUTH_20_CONSTANTS}.oauth_callback) as l_callback and then
attached {CMS_OAUTH_20_CONSUMER} a_user_oauth_api.oauth_consumer_by_callback (l_callback.value) as l_consumer and then attached {CMS_OAUTH_20_CONSUMER} a_user_oauth_api.oauth_consumer_by_callback (l_callback.value) as l_consumer and then
@@ -490,7 +493,7 @@ feature -- OAuth2 Login with Provider
-- Send Email -- Send Email
create es.make (create {CMS_AUTHENTICATION_EMAIL_SERVICE_PARAMETERS}.make (api)) create es.make (create {CMS_AUTHENTICATION_EMAIL_SERVICE_PARAMETERS}.make (api))
write_debug_log (generator + ".handle_callback_oauth: send_contact_welcome_email") write_debug_log (generator + ".handle_callback_oauth: send_contact_welcome_email")
es.send_contact_welcome_email (l_email, "") es.send_contact_welcome_email (l_email, l_user, req.absolute_script_url (""))
end end
end end
r.set_redirection (r.front_page_url) r.set_redirection (r.front_page_url)

View File

@@ -14,7 +14,7 @@ inherit
module_api as user_openid_api module_api as user_openid_api
redefine redefine
filters, filters,
register_hooks, setup_hooks,
initialize, initialize,
install, install,
user_openid_api user_openid_api
@@ -166,12 +166,12 @@ feature -- Router
feature -- Hooks configuration feature -- Hooks configuration
register_hooks (a_response: CMS_RESPONSE) setup_hooks (a_hooks: CMS_HOOK_CORE_MANAGER)
-- Module hooks configuration. -- Module hooks configuration.
do do
auto_subscribe_to_hooks (a_response) auto_subscribe_to_hooks (a_hooks)
a_response.hooks.subscribe_to_block_hook (Current) a_hooks.subscribe_to_block_hook (Current)
a_response.hooks.subscribe_to_value_table_alter_hook (Current) a_hooks.subscribe_to_value_table_alter_hook (Current)
end end
feature -- Hooks feature -- Hooks
@@ -203,7 +203,10 @@ feature -- Hooks
until until
lnk2 /= Void lnk2 /= Void
loop loop
if ic.item.location.same_string ("account/roc-logout") then if
ic.item.location.same_string ("account/roc-logout") or else
ic.item.location.same_string ("basic_auth_logoff")
then
lnk2 := ic.item lnk2 := ic.item
end end
end end
@@ -387,7 +390,7 @@ feature -- Openid Login
l_user: CMS_USER l_user: CMS_USER
l_roles: LIST [CMS_USER_ROLE] l_roles: LIST [CMS_USER_ROLE]
l_cookie: WSF_COOKIE l_cookie: WSF_COOKIE
es: CMS_AUTHENTICATON_EMAIL_SERVICE es: CMS_AUTHENTICATION_EMAIL_SERVICE
b: STRING b: STRING
o: OPENID_CONSUMER o: OPENID_CONSUMER
v: OPENID_CONSUMER_VALIDATION v: OPENID_CONSUMER_VALIDATION
@@ -440,7 +443,7 @@ feature -- Openid Login
-- Send Email -- Send Email
create es.make (create {CMS_AUTHENTICATION_EMAIL_SERVICE_PARAMETERS}.make (api)) create es.make (create {CMS_AUTHENTICATION_EMAIL_SERVICE_PARAMETERS}.make (api))
write_debug_log (generator + ".handle_callback_openid: send_contact_welcome_email") write_debug_log (generator + ".handle_callback_openid: send_contact_welcome_email")
es.send_contact_welcome_email (l_email, "") es.send_contact_welcome_email (l_email, l_user, req.absolute_script_url (""))
end end
end end
r.set_redirection (r.front_page_url) r.set_redirection (r.front_page_url)

View File

@@ -197,7 +197,7 @@ feature {NONE} -- User OpenID
Sql_insert_openid: STRING = "INSERT INTO openid_items (uid, identity, created) VALUES (:uid, :identity, :utc_date);" 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"; Sql_openid_consumers: STRING = "SELECT name FROM openid_consumers;"
feature {NONE} -- Consumer feature {NONE} -- Consumer

View File

@@ -11,7 +11,7 @@ inherit
rename rename
module_api as recent_changes_api module_api as recent_changes_api
redefine redefine
register_hooks, setup_hooks,
permissions permissions
end end
@@ -110,7 +110,7 @@ feature -- Hook
do do
l_user := Void -- Public access for the feed! l_user := Void -- Public access for the feed!
create l_changes.make (a_size, create {DATE_TIME}.make_now_utc, a_source) create l_changes.make (a_size, create {DATE_TIME}.make_now_utc, a_source)
if attached a_response.hooks.subscribers ({CMS_RECENT_CHANGES_HOOK}) as lst then if attached a_response.api.hooks.subscribers ({CMS_RECENT_CHANGES_HOOK}) as lst then
across across
lst as ic lst as ic
loop loop
@@ -236,7 +236,7 @@ feature -- Handler
create l_changes.make (l_size, l_until_date, l_filter_source) create l_changes.make (l_size, l_until_date, l_filter_source)
create l_content.make (1024) create l_content.make (1024)
if attached r.hooks.subscribers ({CMS_RECENT_CHANGES_HOOK}) as lst then if attached api.hooks.subscribers ({CMS_RECENT_CHANGES_HOOK}) as lst then
create l_sources.make (lst.count) create l_sources.make (lst.count)
across across
@@ -284,7 +284,7 @@ feature -- Handler
create l_submit.make_with_text ("op", "Filter") create l_submit.make_with_text ("op", "Filter")
l_form.extend (l_submit) l_form.extend (l_submit)
l_form.extend_html_text ("<br/>") l_form.extend_html_text ("<br/>")
l_form.append_to_html (create {CMS_TO_WSF_THEME}.make (r, r.theme), l_content) l_form.append_to_html (r.wsf_theme, l_content)
end end
l_changes.reverse_sort l_changes.reverse_sort
@@ -397,12 +397,12 @@ feature -- Handler
feature -- Hooks configuration feature -- Hooks configuration
register_hooks (a_response: CMS_RESPONSE) setup_hooks (a_hooks: CMS_HOOK_CORE_MANAGER)
-- Module hooks configuration. -- Module hooks configuration.
do do
a_response.hooks.subscribe_to_menu_system_alter_hook (Current) a_hooks.subscribe_to_menu_system_alter_hook (Current)
a_response.hooks.subscribe_to_response_alter_hook (Current) a_hooks.subscribe_to_response_alter_hook (Current)
a_response.hooks.subscribe_to_block_hook (Current) a_hooks.subscribe_to_block_hook (Current)
end end
feature -- Hook feature -- Hook

View File

@@ -0,0 +1,63 @@
note
description: "API to manage CMS User session authentication"
date: "$Date$"
revision: "$Revision$"
class
CMS_SESSION_API
inherit
CMS_MODULE_API
REFACTORING_HELPER
create {CMS_SESSION_AUTH_MODULE}
make_with_storage
feature {NONE} -- Initialization
make_with_storage (a_api: CMS_API; a_session_auth_storage: CMS_SESSION_AUTH_STORAGE_I)
-- Create an object with api `a_api' and storage `a_session_auth_storage'.
do
session_auth_storage := a_session_auth_storage
make (a_api)
ensure
session_auth_storage_set: session_auth_storage = a_session_auth_storage
end
feature {CMS_MODULE} -- Access: User session storage.
session_auth_storage: CMS_SESSION_AUTH_STORAGE_I
-- storage interface.
feature -- Access
user_by_session_token (a_token: READABLE_STRING_32): detachable CMS_USER
-- Retrieve user by token `a_token', if any.
do
Result := session_auth_storage.user_by_session_token (a_token)
end
has_user_token (a_user: CMS_USER): BOOLEAN
-- Has the user `a_user' and associated session token?
do
Result := session_auth_storage.has_user_token (a_user)
end
feature -- Change User session
new_user_session_auth (a_token: READABLE_STRING_GENERAL; a_user: CMS_USER;)
-- New user session for user `a_user' with token `a_token'.
do
session_auth_storage.new_user_session_auth (a_token, a_user)
end
update_user_session_auth (a_token: READABLE_STRING_GENERAL; a_user: CMS_USER )
-- Update user session for user `a_user' with token `a_token'.
do
session_auth_storage.update_user_session_auth (a_token, a_user)
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-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="session_auth" uuid="8A43B6DD-6B39-472C-9A96-978414CBF1E3" library_target="session_auth">
<target name="session_auth">
<root all_classes="true"/>
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="false" is_attached_by_default="true" is_obsolete_routine_type="true" void_safety="all" syntax="transitional">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="cms" location="..\..\cms-safe.ecf"/>
<library name="cms_app_env" location="..\..\library\app_env\app_env-safe.ecf" readonly="false"/>
<library name="cms_auth_module" location="..\..\modules\auth\auth-safe.ecf" readonly="false"/>
<library name="cms_model" location="..\..\library\model\cms_model-safe.ecf" readonly="false"/>
<library name="crypto" location="$ISE_LIBRARY\unstable\library\text\encryption\crypto\crypto-safe.ecf"/>
<library name="encoder" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\text\encoder\encoder-safe.ecf"/>
<library name="error" location="$ISE_LIBRARY\contrib\library\utility\general\error\error-safe.ecf"/>
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http-safe.ecf"/>
<library name="http_authorization" location="$ISE_LIBRARY\contrib\library\web\authentication\http_authorization\http_authorization-safe.ecf" readonly="false"/>
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
<library name="wsf_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension-safe.ecf" readonly="false"/>
<cluster name="src" location=".\" recursive="true"/>
</target>
</system>

View File

@@ -0,0 +1,349 @@
note
description: "[
This module allows the use Session Based Authentication using Cookies to restrict access
by looking up users in the given providers.
]"
date: "$Date$"
revision: "$Revision$"
class
CMS_SESSION_AUTH_MODULE
inherit
CMS_MODULE
rename
module_api as user_session_api
redefine
filters,
setup_hooks,
initialize,
install,
user_session_api
end
CMS_HOOK_AUTO_REGISTER
CMS_HOOK_BLOCK
CMS_HOOK_MENU_SYSTEM_ALTER
CMS_HOOK_VALUE_TABLE_ALTER
SHARED_LOGGER
CMS_REQUEST_UTIL
create
make
feature {NONE} -- Initialization
make
do
version := "1.0"
description := "Service to manage cookie based authentication"
package := "authentication"
add_dependency ({CMS_AUTHENTICATION_MODULE})
end
feature -- Access
name: STRING = "session_auth"
feature {CMS_API} -- Module Initialization
initialize (a_api: CMS_API)
-- <Precursor>
local
l_session_auth_api: like user_session_api
l_user_auth_storage: CMS_SESSION_AUTH_STORAGE_I
do
Precursor (a_api)
-- Storage initialization
if attached a_api.storage.as_sql_storage as l_storage_sql then
create {CMS_SESSION_AUTH_STORAGE_SQL} l_user_auth_storage.make (l_storage_sql)
else
-- FIXME: in case of NULL storage, should Current be disabled?
create {CMS_SESSION_AUTH_STORAGE_NULL} l_user_auth_storage
end
-- API initialization
create l_session_auth_api.make_with_storage (a_api, l_user_auth_storage)
user_session_api := l_session_auth_api
ensure then
session_auth_api_set: user_session_api /= Void
end
feature {CMS_API} -- Module management
install (api: CMS_API)
do
-- Schema
if attached api.storage.as_sql_storage as l_sql_storage then
if not l_sql_storage.sql_table_exists ("session_auth") then
--| Schema
l_sql_storage.sql_execute_file_script (api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended ("session_auth_table.sql")), Void)
if l_sql_storage.has_error then
api.logger.put_error ("Could not initialize database for session auth module", generating_type)
end
end
l_sql_storage.sql_finalize
Precursor {CMS_MODULE}(api)
end
end
feature {CMS_API} -- Access: API
user_session_api: detachable CMS_SESSION_API
-- <Precursor>
feature -- Access: router
setup_router (a_router: WSF_ROUTER; a_api: CMS_API)
-- <Precursor>
do
a_router.handle ("/account/roc-session-login", create {WSF_URI_AGENT_HANDLER}.make (agent handle_login(a_api, ?, ?)), a_router.methods_head_get)
a_router.handle ("/account/roc-session-logout", create {WSF_URI_AGENT_HANDLER}.make (agent handle_logout (a_api, ?, ?)), a_router.methods_get_post)
a_router.handle ("/account/login-with-session", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_login_with_session (a_api,user_session_api, ?, ?)), a_router.methods_get_post)
end
feature -- Access: filter
filters (a_api: CMS_API): detachable LIST [WSF_FILTER]
-- Possibly list of Filter's module.
do
create {ARRAYED_LIST [WSF_FILTER]} Result.make (1)
if attached user_session_api as l_session_api then
Result.extend (create {CMS_SESSION_AUTH_FILTER}.make (a_api, l_session_api))
end
end
feature {NONE} -- Implementation: routes
handle_login (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE)
local
r: CMS_RESPONSE
do
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
r.execute
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_SESSION_CONSTANTS}.session_auth_token) as l_cookie_token and then
attached {CMS_USER} current_user (req) as l_user
then
-- Logout Session
create l_cookie.make ({CMS_SESSION_CONSTANTS}.session_auth_token, l_cookie_token.value)
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
else
fixme (generator + ": missing else implementation in handle_logout!")
end
end
handle_login_with_session (api: CMS_API; a_session_api: detachable CMS_SESSION_API; req: WSF_REQUEST; res: WSF_RESPONSE)
local
r: CMS_RESPONSE
l_token: STRING
l_cookie: WSF_COOKIE
do
if
attached a_session_api as l_session_api and then
attached {WSF_STRING} req.form_parameter ("username") as l_username and then
attached {WSF_STRING} req.form_parameter ("password") as l_password and then
api.user_api.is_valid_credential (l_username.value, l_password.value) and then
attached api.user_api.user_by_name (l_username.value) as l_user
then
l_token := generate_token
if
a_session_api.has_user_token (l_user)
then
l_session_api.update_user_session_auth (l_token, l_user)
else
l_session_api.new_user_session_auth (l_token, l_user)
end
create l_cookie.make ({CMS_SESSION_CONSTANTS}.session_auth_token, l_token)
l_cookie.set_max_age ({CMS_SESSION_CONSTANTS}.session_max_age)
l_cookie.set_path ("/")
res.add_cookie (l_cookie)
set_current_user (req, l_user)
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
r.set_redirection (req.absolute_script_url (""))
r.execute
else
create {BAD_REQUEST_ERROR_CMS_RESPONSE} r.make (req, res, api)
if attached template_block ("login", r) as l_tpl_block then
if attached {WSF_STRING} req.form_parameter ("username") as l_username then
l_tpl_block.set_value (l_username.value, "username")
end
l_tpl_block.set_value ("Wrong: Username or password ", "error")
r.add_block (l_tpl_block, "content")
end
r.execute
end
end
feature -- Hooks configuration
setup_hooks (a_hooks: CMS_HOOK_CORE_MANAGER)
-- Module hooks configuration.
do
auto_subscribe_to_hooks (a_hooks)
a_hooks.subscribe_to_block_hook (Current)
a_hooks.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 a_response.user as u and then
attached {WSF_STRING} a_response.request.cookie ({CMS_SESSION_CONSTANTS}.session_auth_token)
then
a_value.force ("account/roc-session-logout", "auth_login_strategy")
end
end
menu_system_alter (a_menu_system: CMS_MENU_SYSTEM; a_response: CMS_RESPONSE)
-- 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.user as u and then
attached {WSF_STRING} a_response.request.cookie ({CMS_SESSION_CONSTANTS}.session_auth_token)
then
across
a_menu_system.primary_menu.items as ic
until
lnk2 /= Void
loop
if ic.item.location.same_string ("account/roc-logout") or else ic.item.location.same_string ("basic_auth_logoff") then
lnk2 := ic.item
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)
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
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-session-login")
then
get_block_view_login (a_block_id, a_response)
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
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
generate_token: STRING
-- Generate token to use in a Session.
local
l_token: STRING
l_security: CMS_TOKEN_GENERATOR
l_encode: URL_ENCODER
do
create l_security
l_token := l_security.token
create l_encode
from until l_token.same_string (l_encode.encoded_string (l_token)) loop
-- Loop ensure that we have a security token that does not contain characters that need encoding.
-- We cannot simply to an encode-decode because the email sent to the user will contain an encoded token
-- but the user will need to use an unencoded token if activation has to be done manually.
l_token := l_security.token
end
Result := l_token
end
end

View File

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

@@ -0,0 +1,55 @@
note
description: "[
Processes a HTTP request's checking Session cookies, putting the result into the execution variable user.
]"
date: "$Date: 2015-02-13 13:08:13 +0100 (ven., 13 févr. 2015) $"
revision: "$Revision: 96616 $"
class
CMS_SESSION_AUTH_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_session_oauth_api: CMS_SESSION_API)
do
make_handler (a_api)
session_oauth_api := a_session_oauth_api
end
session_oauth_api: CMS_SESSION_API
feature -- Basic operations
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
-- Execute the filter.
do
api.logger.put_debug (generator + ".execute ", Void)
-- A valid user
if
attached {WSF_STRING} req.cookie ({CMS_SESSION_CONSTANTS}.session_auth_token) as l_roc_auth_session_token
then
if attached session_oauth_api.user_by_session_token (l_roc_auth_session_token.value) as l_user then
set_current_user (req, l_user)
else
api.logger.put_error (generator + ".execute login_valid failed for: " + l_roc_auth_session_token.value , Void)
end
else
api.logger.put_debug (generator + ".execute without authentication", Void)
end
execute_next (req, res)
end
end

View File

@@ -0,0 +1,46 @@
note
description: "[
API to handle OAUTH storage
]"
date: "$Date$"
revision: "$Revision$"
deferred class
CMS_SESSION_AUTH_STORAGE_I
inherit
SHARED_LOGGER
feature -- Error Handling
error_handler: ERROR_HANDLER
-- Error handler.
deferred
end
feature -- Access: Users
user_by_session_token (a_token: READABLE_STRING_32): detachable CMS_USER
-- Retrieve user by token `a_token', if any.
deferred
end
has_user_token (a_user: CMS_USER): BOOLEAN
-- Has the user `a_user' and associated session token?
deferred
end
feature -- Change User session
new_user_session_auth (a_token: READABLE_STRING_GENERAL; a_user: CMS_USER;)
-- New user session for user `a_user' with token `a_token'.
deferred
end
update_user_session_auth (a_token: READABLE_STRING_GENERAL; a_user: CMS_USER )
-- Update user session for user `a_user' with token `a_token'.
deferred
end
end

View File

@@ -0,0 +1,47 @@
note
description: "Summary description for {CMS_SESSION_AUTH_STORAGE_NULL}."
date: "$Date$"
revision: "$Revision$"
class
CMS_SESSION_AUTH_STORAGE_NULL
inherit
CMS_SESSION_AUTH_STORAGE_I
feature -- Error handler
error_handler: ERROR_HANDLER
-- Error handler.
do
create Result.make
end
feature -- Access
user_by_session_token (a_token: READABLE_STRING_32): detachable CMS_USER
-- Retrieve user by token `a_token', if any.
do
end
has_user_token (a_user: CMS_USER): BOOLEAN
-- Has the user `a_user' and associated session token?
do
end
feature -- Change User session
new_user_session_auth (a_token: READABLE_STRING_GENERAL; a_user: CMS_USER;)
-- New user session for user `a_user' with token `a_token'.
do
end
update_user_session_auth (a_token: READABLE_STRING_GENERAL; a_user: CMS_USER )
-- Update user session for user `a_user' with token `a_token'.
do
end
end

View File

@@ -0,0 +1,155 @@
note
description: "Summary description for {CMS_SESSION_AUTH_STORAGE_SQL}."
date: "$Date$"
revision: "$Revision$"
class
CMS_SESSION_AUTH_STORAGE_SQL
inherit
CMS_SESSION_AUTH_STORAGE_I
CMS_PROXY_STORAGE_SQL
CMS_SESSION_AUTH_STORAGE_I
CMS_STORAGE_SQL_I
REFACTORING_HELPER
create
make
feature -- Access User
user_by_session_token (a_token: READABLE_STRING_32): detachable CMS_USER
-- Retrieve user by token `a_token', if any.
local
l_parameters: STRING_TABLE [detachable ANY]
do
error_handler.reset
write_information_log (generator + ".user_by_session_token")
create l_parameters.make (1)
l_parameters.put (a_token, "token")
sql_query (Select_user_by_token, l_parameters)
if not has_error and not sql_after then
Result := fetch_user
sql_forth
if not sql_after then
check
no_more_than_one: False
end
Result := Void
end
end
sql_finalize
end
has_user_token (a_user: CMS_USER): BOOLEAN
-- Has the user `a_user' and associated session token?
local
l_parameters: STRING_TABLE [detachable ANY]
do
error_handler.reset
write_information_log (generator + ".has_user_token")
create l_parameters.make (1)
l_parameters.put (a_user.id, "uid")
sql_query (Select_user_token, l_parameters)
if not has_error and not sql_after then
if sql_read_integer_64 (1) = 1 then
Result := True
else
Result := False
end
end
sql_finalize
end
feature -- Change User token
new_user_session_auth (a_token: READABLE_STRING_GENERAL; a_user: CMS_USER;)
-- <Precursor>.
local
l_parameters: STRING_TABLE [detachable ANY]
do
error_handler.reset
write_information_log (generator + ".new_user_session")
create l_parameters.make (3)
l_parameters.put (a_user.id, "uid")
l_parameters.put (a_token, "token")
l_parameters.put (create {DATE_TIME}.make_now_utc, "utc_date")
sql_begin_transaction
sql_insert (sql_insert_session_auth, l_parameters)
sql_commit_transaction
sql_finalize
end
update_user_session_auth (a_token: READABLE_STRING_GENERAL; a_user: CMS_USER)
-- <Precursor>
local
l_parameters: STRING_TABLE [detachable ANY]
do
error_handler.reset
write_information_log (generator + ".update_user_session_auth")
create l_parameters.make (3)
l_parameters.put (a_user.id, "uid")
l_parameters.put (a_token, "token")
l_parameters.put (create {DATE_TIME}.make_now_utc, "utc_date")
sql_begin_transaction
sql_modify (sql_update_session_auth, l_parameters)
sql_commit_transaction
sql_finalize
end
feature {NONE} -- Implementation
fetch_user: detachable CMS_USER
local
l_id: INTEGER_64
l_name: detachable READABLE_STRING_32
do
if attached sql_read_integer_64 (1) as i then
l_id := i
end
if attached sql_read_string_32 (2) as s and then not s.is_whitespace then
l_name := s
end
if l_name /= Void then
create Result.make (l_name)
if l_id > 0 then
Result.set_id (l_id)
end
elseif l_id > 0 then
create Result.make_with_id (l_id)
end
if Result /= Void then
if attached sql_read_string (3) as l_password then
-- FIXME: should we return the password here ???
Result.set_hashed_password (l_password)
end
if attached sql_read_string (5) as l_email then
Result.set_email (l_email)
end
if attached sql_read_integer_32 (6) as l_status then
Result.set_status (l_status)
end
else
check
expected_valid_user: False
end
end
end
feature {NONE} -- SQL statements
Select_user_by_token: STRING = "SELECT u.* FROM users as u JOIN session_auth as og ON og.uid = u.uid and og.access_token = :token;"
--| FIXME: replace the u.* by a list of field names, to avoid breaking `featch_user' if two fieds are swiped.
Sql_insert_session_auth: STRING = "INSERT INTO session_auth (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;"
Select_user_token: STRING = "SELECT COUNT(*) FROM session_auth where uid = :uid;"
end

View File

@@ -0,0 +1,153 @@
note
description: "Provides security routine helpers"
date: "$Date$"
revision: "$Revision$"
class
CMS_TOKEN_GENERATOR
inherit
REFACTORING_HELPER
feature -- Access
token: STRING
-- Cryptographic random base 64 string.
do
Result := salt_with_size (16)
-- Remove trailing equal sign
Result.keep_head (Result.count - 2)
end
salt: STRING
-- Cryptographic random number of 16 bytes.
do
Result := salt_with_size (16)
end
password: STRING
-- Cryptographic random password of 10 bytes.
do
Result := salt_with_size (10)
-- Remove trailing equal signs
Result.keep_head (Result.count - 2)
end
password_hash (a_password, a_salt: STRING): STRING
-- Password hash based on password `a_password' and salt value `a_salt'.
do
Result := sha1_string (a_password + a_salt )
end
feature {NONE} -- Implementation
salt_with_size (a_val: INTEGER): STRING
-- Return a salt with size `a_val'.
local
l_salt: SALT_XOR_SHIFT_64_GENERATOR
l_array: ARRAY [INTEGER_8]
i: INTEGER
do
create l_salt.make (a_val)
create l_array.make_empty
i := 1
across
l_salt.new_sequence as c
loop
l_array.force (c.item.as_integer_8, i)
i := i + 1
end
Result := base_64 (l_array)
end
sha1_string (a_str: STRING): STRING
-- SHA1 diggest of `a_str'.
do
sha1.update_from_string (a_str)
Result := sha1.digest_as_string
sha1.reset
end
sha1: SHA1
-- Create a SHA1 object.
do
create Result.make
end
feature -- Encoding
base_64 (bytes: SPECIAL [INTEGER_8]): STRING_8
-- Encodes a byte array into a STRING doing base64 encoding.
local
l_output: SPECIAL [INTEGER_8]
l_remaining: INTEGER
i, ptr: INTEGER
char: CHARACTER
do
to_implement ("Check existing code to do that!!!.")
create l_output.make_filled (0, ((bytes.count + 2) // 3) * 4)
l_remaining := bytes.count
from
i := 0
ptr := 0
until
l_remaining <= 3
loop
l_output [ptr] := encode_value (bytes [i] |>> 2)
ptr := ptr + 1
l_output [ptr] := encode_value (((bytes [i] & 0x3) |<< 4) | ((bytes [i + 1] |>> 4) & 0xF))
ptr := ptr + 1
l_output [ptr] := encode_value (((bytes [i + 1] & 0xF) |<< 2) | ((bytes [i + 2] |>> 6) & 0x3))
ptr := ptr + 1
l_output [ptr] := encode_value (bytes [i + 2] & 0x3F)
ptr := ptr + 1
l_remaining := l_remaining - 3
i := i + 3
end
-- encode when exactly 1 element (left) to encode
char := '='
if l_remaining = 1 then
l_output [ptr] := encode_value (bytes [i] |>> 2)
ptr := ptr + 1
l_output [ptr] := encode_value (((bytes [i]) & 0x3) |<< 4)
ptr := ptr + 1
l_output [ptr] := char.code.as_integer_8
ptr := ptr + 1
l_output [ptr] := char.code.as_integer_8
ptr := ptr + 1
end
-- encode when exactly 2 elements (left) to encode
if l_remaining = 2 then
l_output [ptr] := encode_value (bytes [i] |>> 2)
ptr := ptr + 1
l_output [ptr] := encode_value (((bytes [i] & 0x3) |<< 4) | ((bytes [i + 1] |>> 4) & 0xF));
ptr := ptr + 1
l_output [ptr] := encode_value ((bytes [i + 1] & 0xF) |<< 2);
ptr := ptr + 1
l_output [ptr] := char.code.as_integer_8
ptr := ptr + 1
end
create Result.make_empty
across
l_output as elem
loop
Result.append_character (elem.item.to_character_8)
end
end
base64_map: SPECIAL [CHARACTER_8]
-- Table for Base64 encoding.
once
Result := ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/").area
end
encode_value (i: INTEGER_8): INTEGER_8
-- Encode `i'.
do
Result := base64_map [i & 0x3F].code.as_integer_8
end
end

Some files were not shown because too many files have changed in this diff Show More