Compare commits

..
Author SHA1 Message Date
jocelyn 41ac45d07b Fixed various CMS_MODULE.install, by not marked module installed if an error occurred!
Improved Auth related module implementation by having a way to change settings like token, max age.
  - use CMS_SETUP.site_id and related "auth.$module.token" ... configuration values.
  - removed related CMS_..._CONSTANTS classes.

For auth session module, use auth_session as table name, and use VARCHAR(64).
Extracted sql from blog module, and store it under site/scripts/install.sql .
Renamed a few $modulename.sql as install.sql
2016-01-27 18:22:20 +01:00
jocelyn d3b485f4d3 Removed unused local variable. 2016-01-22 22:19:24 +01:00
jocelyn 2b1d5f9693 Updated to new routine type. 2016-01-22 21:41:56 +01:00
jocelyn 59c03c5f4d Added CMS_STRING_EXPANDER.
For now with basic implementation.
  It will be improved later

Added SEO related attribute in CMS_RESPONSE.
Added improved Contact module.
Added basic SEO module.
2016-01-22 21:33:06 +01:00
jocelyn 39ab19d20e Eiffel code and ECFs update to support new agent notations.
Accepts /account and /account/ .
2016-01-19 16:15:13 +01:00
jocelyn fd5e396b72 Code cleaning. 2016-01-15 18:35:53 +01:00
jocelyn 5bd28326c2 Added source for sql scripts. 2016-01-15 17:59:21 +01:00
jocelyn 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
jocelyn a013efd6f7 Cosmetic in DEMO_CMS_EXECUTION
Removed persistence/mysql which is not used.
2016-01-15 13:30:07 +01:00
jocelyn f6885ff581 remove roc.exe 2016-01-13 22:05:49 +01:00
jocelyn a179ee3239 Reverted executable name to "demo" 2016-01-13 10:38:27 +01:00
jocelyn ed0d9c8d07 Use {CMS_LOG}.level_notice and related constant when using api.log(..) 2016-01-12 16:14:54 +01:00
jocelyn 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
jocelyn 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
109 changed files with 3116 additions and 1114 deletions
+3 -3
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"/>
+3 -3
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"/>
+10 -7
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">
@@ -23,17 +24,19 @@
<library name="cms_auth_module" location="..\..\modules\auth\auth-safe.ecf" readonly="false"/> <library name="cms_auth_module" location="..\..\modules\auth\auth-safe.ecf" readonly="false"/>
<library name="cms_basic_auth_module" location="..\..\modules\basic_auth\basic_auth-safe.ecf" readonly="false"/> <library name="cms_basic_auth_module" location="..\..\modules\basic_auth\basic_auth-safe.ecf" readonly="false"/>
<library name="cms_blog_module" location="..\..\modules\blog\cms_blog_module-safe.ecf" readonly="false"/> <library name="cms_blog_module" location="..\..\modules\blog\cms_blog_module-safe.ecf" readonly="false"/>
<library name="cms_contact_module" location="..\..\modules\contact\contact-safe.ecf" readonly="false"/>
<library name="cms_demo_module" location="modules\demo\cms_demo_module-safe.ecf" readonly="false"/> <library name="cms_demo_module" location="modules\demo\cms_demo_module-safe.ecf" readonly="false"/>
<library name="cms_email_service" location="..\..\library\email\email-safe.ecf" readonly="false"/> <library name="cms_email_service" location="..\..\library\email\email-safe.ecf" readonly="false"/>
<library name="cms_feed_aggregator_module" location="..\..\modules\feed_aggregator\feed_aggregator-safe.ecf" readonly="false"/> <library name="cms_feed_aggregator_module" location="..\..\modules\feed_aggregator\feed_aggregator-safe.ecf" readonly="false"/>
<library name="cms_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_session_auth_module" location="..\..\modules\session_auth\cms_session_auth-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_seo_module" location="..\..\modules\seo\seo-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/>
@@ -41,13 +44,13 @@
</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>
<target name="demo_any" extends="common"> <target name="demo_any" extends="common">
<setting name="concurrency" value="thread"/> <setting name="concurrency" value="scoop"/>
<library name="any_launcher" location="..\..\launcher\any-safe.ecf" readonly="false"/> <library name="any_launcher" location="..\..\launcher\any-safe.ecf" readonly="false"/>
<cluster name="src" location=".\src\" recursive="true"/> <cluster name="src" location=".\src\" recursive="true"/>
</target> </target>
+5 -2
View File
@@ -6,10 +6,13 @@ set ROC_CMS_DIR=%~dp0
%ROC_CMD% install --module ..\..\modules\auth --dir %ROC_CMS_DIR% %ROC_CMD% install --module ..\..\modules\auth --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\basic_auth --dir %ROC_CMS_DIR% %ROC_CMD% install --module ..\..\modules\basic_auth --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\blog --dir %ROC_CMS_DIR% %ROC_CMD% install --module ..\..\modules\blog --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\contact --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\feed_aggregator --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\google_search --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\node --dir %ROC_CMS_DIR% %ROC_CMD% install --module ..\..\modules\node --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\oauth20 --dir %ROC_CMS_DIR% %ROC_CMD% install --module ..\..\modules\oauth20 --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\openid --dir %ROC_CMS_DIR% %ROC_CMD% install --module ..\..\modules\openid --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\recent_changes --dir %ROC_CMS_DIR% %ROC_CMD% install --module ..\..\modules\recent_changes --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\feed_aggregator --dir %ROC_CMS_DIR% %ROC_CMD% install --module ..\..\modules\seo --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\google_search --dir %ROC_CMS_DIR% %ROC_CMD% install --module ..\..\modules\session_auth --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\taxonomy --dir %ROC_CMS_DIR% %ROC_CMD% install --module ..\..\modules\taxonomy --dir %ROC_CMS_DIR%
@@ -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>
+3 -2
View File
@@ -70,8 +70,9 @@ CREATE TABLE tb_demo(
api.logger.put_error ("Could not initialize database for demo module", generating_type) api.logger.put_error ("Could not initialize database for demo module", generating_type)
end end
end end
Precursor {CMS_MODULE}(api)
end end
-- For this demo, be flexible, and do not required sql.
Precursor {CMS_MODULE}(api)
end end
feature -- Access: router feature -- Access: router
@@ -151,7 +152,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
+34 -4
View File
@@ -4,14 +4,36 @@ root-dir=site/www
#modules-dir=site/modules #modules-dir=site/modules
[site] [site]
# General token that could be use for cookies, and related.
id=_EIFFEL_CMS_
# Name of the site, for the title, and eventual message.
name=Eiffel CMS name=Eiffel CMS
email=your@email.com
# Properties used for SEO.
property[headline]=Eiffel CMS -- the demo
property[description]=Demo for Eiffel ROC CMS.
property[keywords]=eiffel,cms,demo
# 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
@@ -25,6 +47,14 @@ output=@stderr
[blocks] [blocks]
@include=blocks.ini @include=blocks.ini
[auth]
# token, default is $site.id or built-in.
#token=_ROC_AUTH_TOKEN_
#session.token=
#session.max_age=86400
#openid.token=
#oauth.token=
[admin] [admin]
# CMS Installation, are accessible by "all", "none" or uppon "permission". (default is none) # CMS Installation, are accessible by "all", "none" or uppon "permission". (default is none)
installation_access=all installation_access=all
@@ -1,8 +1,7 @@
{ {
"email": "webmaster@eiffel.org",
"subject": "Thank you for contacting us", "subject": "Thank you for contacting us",
"recaptcha": { "recaptcha": {
"site_key":"6Lex9RMTAAAAAKleC4x6TaRlFcpLbEWgH_U7MSiD", "site_key":"6Lex9RMTAAAAAKleC4x6TaRlFcpLbEWgH_U7MSiD",
"secret_key":"6Lex9RMTAAAAAAkBczvX5DUiyg_xoM_EthVVgRRx" "secret_key":"6Lex9RMTAAAAAAkBczvX5DUiyg_xoM_EthVVgRRx"
} }
} }
@@ -1,22 +1,28 @@
ul.cms-temp-users { ul.cms-temp-users {
list-style-type: none; list-style-type: none;
padding: 3px 3px 3px 3px; padding: 3px 3px 3px 3px;
border: solid 1px #ccc; } border: solid 1px #ccc;
ul.cms-temp-users li { }
border-top: dotted 1px #ccc; } ul.cms-temp-users li {
ul.cms-temp-users li:first-child { border-top: dotted 1px #ccc;
border-top: none; } }
ul.cms-temp-users li.cms_temp_user ul.cms_temp_user_details { ul.cms-temp-users li:first-child {
list-style-type: none; border-top: none;
padding: 3px 3px 3px 3px; }
border: solid 1px #ccc; } ul.cms-temp-users li.cms_temp_user ul.cms_temp_user_details {
ul.cms-temp-users li.cms_temp_user ul.cms_temp_user_details li { list-style-type: none;
border-top: dotted 1px #ccc; } padding: 3px 3px 3px 3px;
ul.cms-temp-users li.cms_temp_user ul.cms_temp_user_details li:first-child { border: solid 1px #ccc;
border-top: none; } }
ul.cms-temp-users li.cms_temp_user ul.cms_temp_user_details li.cms_temp_user_detail_information::before { ul.cms-temp-users li.cms_temp_user ul.cms_temp_user_details li {
content: "[personal information] "; } border-top: dotted 1px #ccc;
ul.cms-temp-users li.cms_temp_user ul.cms_temp_user_details li.cms_temp_user_detail_email::before { }
content: "[email] "; } ul.cms-temp-users li.cms_temp_user ul.cms_temp_user_details li:first-child {
border-top: none;
/*# sourceMappingURL=auth.css.map */ }
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] ";
}
@@ -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] "
}
}
}
}
@@ -1,14 +1,13 @@
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<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="$sitename"> <meta name="author" content="$sitename">
</head> </head>
<body> <body>
<p>Thank you for applying to <a href="$host">$sitename</a> $user</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>We will review your application and send you a resolution.<p>
</body> </body>
</html> </html>
@@ -6,9 +6,8 @@
<meta name="description" content="Activation Confirmation"> <meta name="description" content="Activation Confirmation">
<meta name="author" content="$sitename"> <meta name="author" content="$sitename">
</head> </head>
<body> <body>
<p>Your account has been confirmed <a href="$host">$sitename</a> $email</p> <p>Your account "$user ($email)" is confirmed at <a href="$host">$sitename</a>.</p>
<p>Thank you for joining us.</p> <p>Thank you for joining us.</p>
</body> </body>
</html> </html>
@@ -6,12 +6,10 @@
<meta name="description" content="New Password"> <meta name="description" content="New Password">
<meta name="author" content="$sitename"> <meta name="author" content="$sitename">
</head> </head>
<body> <body>
<p>You have required a new password at <a href="$host">$sitename</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 generate a new password:<p> <ul><a href="$link">$link</a></ul>
</p>
<p><a href="$link">$link</a></p>
</body> </body>
</html> </html>
@@ -6,13 +6,12 @@
<meta name="description" content="New Activation token"> <meta name="description" content="New Activation token">
<meta name="author" content="$sitename"> <meta name="author" content="$sitename">
</head> </head>
<body> <body>
<p>You have request a new activation token at <a href="$host">$sitename</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>
@@ -6,8 +6,7 @@
<meta name="description" content="Application Rejected"> <meta name="description" content="Application Rejected">
<meta name="author" content="$sitename"> <meta name="author" content="$sitename">
</head> </head>
<body> <body>
<p>You requested has been rejected, your application does not conform our rules <a href="$host">$sitename</a></p> <p>Your account application is rejected, it was not respecting the requirements from <a href="$host">$sitename</a>.</p>
</body> </body>
</html> </html>
@@ -7,7 +7,13 @@
<meta name="author" content="$sitename"> <meta name="author" content="$sitename">
</head> </head>
<body> <body>
<p>Welcome to <a href="$host">$sitename</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>
@@ -1,13 +0,0 @@
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`)
);
@@ -0,0 +1,6 @@
CREATE TABLE blog_post_nodes(
`nid` INTEGER NOT NULL CHECK("nid">=0),
`revision` INTEGER NOT NULL,
`tags` VARCHAR(255),
CONSTRAINT PK_nid_revision PRIMARY KEY (nid,revision)
);
@@ -0,0 +1,8 @@
{
"--email": "webmaster@example.com",
"subjet": "Thank you for contacting us",
"recaptcha": {
"site_key":"",
"secret_key":""
}
}
@@ -0,0 +1,124 @@
.contact-box {
background-color: #F2F7F9;
width: 465px;
padding: 20px;
border: 6px solid #8FB5C1;
-moz-border-radius: 15px;
-webkit-border-radius: 15px;
border-radius: 15px;
position: relative;
/* Remove box shadow firefox, chrome and opera put around required fields.
* It looks rubbish.
*/
/* Normalize placeholder styles */
/* chrome, safari */
/* mozilla */
/* ie (faux placeholder) */
}
.contact-box h1 {
font-size: 42px;
}
.contact-box h2 {
margin-bottom: 15px;
font-style: italic;
font-weight: normal;
}
.contact-box label {
font-size: 15px;
margin-bottom: 2px;
display: block;
}
.contact-box input, .contact-box select, .contact-box textarea {
width: 100%;
font-size: 15px;
border: 1px solid #CEE1E8;
margin-bottom: 20px;
padding: 4px;
}
.contact-box input:focus, .contact-box select:focus, .contact-box textarea:focus {
border: 1px solid #AFCDD8;
background-color: #EBF2F4;
}
.contact-box textarea {
height: 150px;
resize: none;
}
.contact-box span.required {
font-weight: bold;
color: #F00;
}
.contact-box input[type=submit] {
width: 100px;
background-color: #333;
color: #FFF;
border: none;
display: block;
float: right;
margin-bottom: 0px;
margin-right: 6px;
background-color: #8FB5C1;
-moz-border-radius: 8px;
}
.contact-box input[type=submit]:hover {
background-color: #A6CFDD;
}
.contact-box input[type=submit]:active {
position: relative;
top: 1px;
}
.contact-box .message {
width: 95%;
margin: 25px 0px;
padding: 10px;
display: block;
border: solid 1px #ccc;
border-radius: 8px;
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
}
.contact-box .message.hidden {
display: none;
}
.contact-box .message.error {
border-color: #E58E8E;
background-color: #FFE6E6;
}
.contact-box .message.error li {
padding: 2px;
list-style: none;
}
.contact-box .message.error li:before {
content: ' - ';
}
.contact-box .message.error #info {
font-weight: bold;
}
.contact-box .message.error #info:before {
content: '';
}
.contact-box .message.success {
border-color: #83D186;
padding-top: 25px;
background-color: #D3EDD3;
}
.contact-box .req-field-desc {
font-style: italic;
}
.contact-box input:required, .contact-box textarea:required {
-moz-box-shadow: none;
-webkit-box-shadow: none;
-o-box-shadow: none;
box-shadow: none;
}
.contact-box ::-webkit-input-placeholder {
color: #CCC;
font-style: italic;
}
.contact-box input:-moz-placeholder, .contact-box textarea:-moz-placeholder {
color: #CCC;
font-style: italic;
}
.contact-box input.placeholder-text, .contact-box textarea.placeholder-text {
color: #CCC;
font-style: italic;
}
@@ -0,0 +1,140 @@
.contact-box {
background-color:#F2F7F9;
width:465px;
padding:20px;
border: 6px solid #8FB5C1;
-moz-border-radius:15px;
-webkit-border-radius:15px;
border-radius:15px;
position:relative;
h1 {
font-size:42px;
}
h2 {
margin-bottom:15px;
font-style:italic;
font-weight:normal;
}
label {
font-size:15px;
margin-bottom:2px;
display:block;
}
input, select, textarea {
width:100%;
font-size:15px;
border: 1px solid #CEE1E8;
margin-bottom:20px;
padding:4px;
&:focus {
border: 1px solid #AFCDD8;
background-color: #EBF2F4;
}
}
textarea {
height:150px;
resize: none;
}
span.required {
font-weight:bold;
color:#F00;
}
input[type=submit] {
width: 100px;
background-color:#333;
color:#FFF;
border:none;
display:block;
float:right;
margin-bottom:0px;
margin-right:6px;
background-color:#8FB5C1;
-moz-border-radius:8px;
&:hover {
background-color: #A6CFDD;
}
&:active {
position:relative;
top:1px;
}
}
.message {
width:95%;
margin:25px 0px;
padding:10px;
display:block;
border:solid 1px #ccc;
border-radius:8px;
-webkit-border-radius:8px;
-moz-border-radius:8px;
&.hidden {
display: none;
}
&.error {
border-color: #E58E8E;
background-color:#FFE6E6;
li {
padding:2px;
list-style:none;
&:before { content: ' - '; }
}
#info {
font-weight:bold;
&:before { content: ''; }
}
}
&.success {
border-color: #83D186;
padding-top: 25px;
background-color:#D3EDD3;
}
}
.req-field-desc {
font-style:italic;
}
/* Remove box shadow firefox, chrome and opera put around required fields.
* It looks rubbish.
*/
input:required, textarea:required {
-moz-box-shadow:none;
-webkit-box-shadow:none;
-o-box-shadow:none;
box-shadow:none;
}
/* Normalize placeholder styles */
/* chrome, safari */
::-webkit-input-placeholder {
color:#CCC;
font-style:italic;
}
/* mozilla */
input:-moz-placeholder, textarea:-moz-placeholder {
color:#CCC;
font-style:italic;
}
/* ie (faux placeholder) */
input.placeholder-text, textarea.placeholder-text {
color:#CCC;
font-style:italic;
}
}
@@ -0,0 +1,25 @@
<div class="contact-box clearfix">
<h1>Contact us!</h1>
<form method="post" action="{$site_url/}contact" id="contact-form">
<label for="name">Name: <span class="required">*</span></label>
<input type="text" id="name" name="name" value="{$name/}" required="required" autofocus="autofocus" />
<label for="email">Email Address: <span class="required">*</span></label>
<input type="email" id="email" name="email" value="{$email/}" required="required" />
<label for="message">Message: <span class="required">*</span></label>
<textarea id="message" name="message" required="required" data-minlength="20" minlength="20" >{$message/}</textarea>
{unless isempty="$recaptcha_site_key"}
<div class="g-recaptcha" data-sitekey="{$recaptcha_site_key/}"></div>
<br/>
{/unless}
<input type="submit" value="Send" class="submit-button" />
<p class="req-field-desc"><span class="required">*</span> indicates a required field</p>
</form>
{unless isempty="$error_response"}
<ul class="message error">
{foreach item="item" from="$error_response"}<li class="info">{$item/}</li>{/foreach}
</ul>
<div class="notice"> Try again later </div>
{/unless}
</div>
@@ -0,0 +1,15 @@
<div class="contact-box">
{if condition="$has_error"}
<div class="message error">
<strong>Internal Server Error <small>Error 500</small></strong>
<p>The page you requested could not be served because the server is down,
either contact the webmaster or try again.
Use your browser's <strong>Back</strong> button to navigate to the page you came from.</p>
<p><strong>Or you could just press this link:</strong> <a href="{$site_url/}" itemprop="home" rel="home">Take Me Home</a></p>
</div>
{/if}
{unless condition="$has_error"}
<p class="message success">Thank you for contacting the Eiffel Programming Language community.<br/>
We will get back to you promptly on your contact request.</p>
{/unless}
</div>
@@ -0,0 +1,10 @@
<p>
Thank you for contacting {$sitename/}.<br/>
We will get back to you promptly about your contact message.
</p>
<h2>Your contact information:</h2>
<div>
<strong>Name<strong>: {$name/} <br/>
<strong>Email<strong>: {$email/} <br/>
<strong>Message<strong>: {$message/} <br/>
</div>
@@ -0,0 +1,6 @@
<h2>Contact information:</h2>
<div>
<strong>Name<strong>: {$name/}<br/>
<strong>Email<strong>: {$email/} <br/>
<strong>Message<strong>: {$message/} <br/>
</div>
@@ -3,22 +3,17 @@ ul.cms-nodes {
list-style-type: none; list-style-type: none;
padding: 3px 3px 3px 3px; padding: 3px 3px 3px 3px;
border: solid 1px #ccc; border: solid 1px #ccc;
li{ li{
border-top: dotted 1px #ccc; border-top: dotted 1px #ccc;
&:first-child { &:first-child {
border-top: none; border-top: none;
} }
} }
li.cms_type_page a::before { li.cms_type_page a::before {
content: "[page] "; content: "[page] ";
} }
li.cms_type_blog a::before { li.cms_type_blog a::before {
content: "[blog] "; content: "[blog] ";
} }
} }
@@ -0,0 +1,9 @@
CREATE TABLE auth_session (
`uid` INTEGER PRIMARY KEY NOT NULL CHECK(`uid`>=0),
`access_token` VARCHAR(64) NOT NULL,
`created` DATETIME NOT NULL,
CONSTRAINT `uid` UNIQUE(`uid`),
CONSTRAINT `access_token` UNIQUE(`access_token`)
);
@@ -1,11 +0,0 @@
CREATE TABLE session_auth (
`uid` INTEGER PRIMARY KEY NOT NULL CHECK(`uid`>=0),
`access_token` TEXT NOT NULL,
`created` DATETIME NOT NULL,
CONSTRAINT `uid`
UNIQUE(`uid`),
CONSTRAINT `access_token`
UNIQUE(`access_token`)
);
+23 -39
View File
@@ -34,64 +34,48 @@ feature -- CMS storage
setup_storage (a_setup: CMS_SETUP) setup_storage (a_setup: CMS_SETUP)
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) a_setup.register_module (create {CMS_SESSION_AUTH_MODULE}.make)
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 -- Contact
a_setup.register_module (m) a_setup.register_module (create {CMS_CONTACT_MODULE}.make)
-- Misc
a_setup.register_module (create {CMS_SEO_MODULE}.make)
-- 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 {GOOGLE_CUSTOM_SEARCH_MODULE}.make)
a_setup.register_module (m) a_setup.register_module (create {CMS_DEBUG_MODULE}.make)
a_setup.register_module (create {CMS_DEMO_MODULE}.make)
create {CMS_DEMO_MODULE} m.make
a_setup.register_module (m)
create {GOOGLE_CUSTOM_SEARCH_MODULE} m.make
a_setup.register_module (m)
create {CMS_SESSION_AUTH_MODULE} m.make
a_setup.register_module (m)
end end
end end
+8 -7
View File
@@ -1,5 +1,5 @@
note note
description: "Summary description for {CMS_TEMP_USER}." description: "User for temporary account."
date: "$Date$" date: "$Date$"
revision: "$Revision$" revision: "$Revision$"
@@ -7,7 +7,6 @@ class
CMS_TEMP_USER CMS_TEMP_USER
inherit inherit
CMS_USER CMS_USER
create create
@@ -22,15 +21,14 @@ feature -- Access
salt: detachable STRING_32 salt: detachable STRING_32
-- User's password salt. -- User's password salt.
feature -- Element change feature -- Element change
set_personal_information (an_personal_information: like personal_information) set_personal_information (a_personal_information: like personal_information)
-- Assign `personal_information' with `an_personal_information'. -- Assign `personal_information' with `a_personal_information'.
do do
personal_information := an_personal_information personal_information := a_personal_information
ensure ensure
personal_information_assigned: personal_information = an_personal_information personal_information_assigned: personal_information = a_personal_information
end end
set_salt (a_salt: like salt) set_salt (a_salt: like salt)
@@ -41,4 +39,7 @@ feature -- Element change
salt_assigned: salt = a_salt salt_assigned: salt = a_salt
end 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 end
+1 -1
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,7 @@ feature -- Cursor
feature -- Action feature -- Action
action: FUNCTION [ANY, detachable TUPLE, G] action: FUNCTION [DB_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
@@ -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;
@@ -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;
@@ -1,76 +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`)
);
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`)
);
COMMIT;
@@ -1,8 +1,9 @@
<?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="store_mysql" uuid="DC757CBD-D8C4-44D6-A07F-C1148D8D233E" library_target="store_mysql"> <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="store_mysql" uuid="DC757CBD-D8C4-44D6-A07F-C1148D8D233E" library_target="store_mysql">
<description>CMS Eiffel Store MySQL persistence solution</description>
<target name="store_mysql"> <target name="store_mysql">
<root all_classes="true"/> <root all_classes="true"/>
<option warning="true" void_safety="all"> <option warning="true" is_obsolete_routine_type="false" void_safety="all">
<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"/>
</option> </option>
<setting name="console_application" value="true"/> <setting name="console_application" value="true"/>
@@ -26,9 +27,9 @@
</cluster> </cluster>
<cluster name="persistence_store_mysql" location=".\src\" recursive="true"> <cluster name="persistence_store_mysql" location=".\src\" recursive="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>
</cluster> </cluster>
</target> </target>
@@ -1,8 +1,9 @@
<?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="persistence_store_odbc" uuid="8FD9D3B3-5FC1-495F-A05D-0205EC966841" library_target="persistence_store_odbc"> <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="persistence_store_odbc" uuid="8FD9D3B3-5FC1-495F-A05D-0205EC966841" library_target="persistence_store_odbc">
<target name="persistence_store_odbc"> <target name="persistence_store_odbc">
<description>CMS Eiffel Store ODBC persistence solution</description>
<root all_classes="true"/> <root all_classes="true"/>
<option warning="true" void_safety="all"> <option warning="true" is_obsolete_routine_type="false" void_safety="all">
<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"/>
</option> </option>
<setting name="console_application" value="true"/> <setting name="console_application" value="true"/>
@@ -22,9 +23,9 @@
<cluster name="common" location="..\implementation\store\" recursive="true"/> <cluster name="common" location="..\implementation\store\" recursive="true"/>
<cluster name="persistence_store_odbc" location=".\src\" recursive="true"> <cluster name="persistence_store_odbc" location=".\src\" recursive="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>
</cluster> </cluster>
</target> </target>
@@ -73,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: ")
+1 -5
View File
@@ -26,10 +26,6 @@
<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"/>
<cluster name="src" location=".\" recursive="true"> <cluster name="src" location=".\" recursive="true"/>
<file_rule>
<exclude>^persistence$</exclude>
</file_rule>
</cluster>
</target> </target>
</system> </system>
@@ -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
@@ -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
@@ -18,23 +15,20 @@ feature {NONE} -- Initialization
local local
utf: UTF_CONVERTER utf: UTF_CONVERTER
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
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 := 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)
@@ -55,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 := 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
@@ -87,11 +80,9 @@ feature {NONE} -- Initialization
contact_subject_oauth := "Welcome." contact_subject_oauth := "Welcome."
end end
contact_subject_account_evaluation := "New register, account evalution" contact_subject_account_evaluation := "New register, account evalution."
contact_subject_rejected := "Your account was rejected."
contact_subject_rejected := "Your account was rejected" contact_subject_activated := "Your account was activated."
contact_subject_activated := "Your account was activated"
end end
@@ -100,14 +91,14 @@ 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.
site_name: IMMUTABLE_STRING_8 utf_8_site_name: IMMUTABLE_STRING_8
-- UTF-8 encoded Site name. -- UTF-8 encoded Site name.
contact_subject_account_evaluation: IMMUTABLE_STRING_8 contact_subject_account_evaluation: IMMUTABLE_STRING_8
@@ -118,7 +109,6 @@ feature -- Access
contact_subject_rejected: IMMUTABLE_STRING_8 contact_subject_rejected: IMMUTABLE_STRING_8
contact_subject_activated: IMMUTABLE_STRING_8 contact_subject_activated: IMMUTABLE_STRING_8
account_evaluation: STRING account_evaluation: STRING
-- Account evaluation template email message. -- Account evaluation template email message.
do do
+138 -98
View File
@@ -90,8 +90,12 @@ feature -- 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.map (m, a_router.methods_head_get)
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/roc-login", create {WSF_URI_AGENT_HANDLER}.make (agent handle_login(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/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-register", create {WSF_URI_AGENT_HANDLER}.make (agent handle_register(a_api, ?, ?)), a_router.methods_get_post)
@@ -203,68 +207,84 @@ feature -- Handler
l_user_api: CMS_USER_API l_user_api: CMS_USER_API
u: CMS_TEMP_USER u: CMS_TEMP_USER
l_exist: BOOLEAN l_exist: BOOLEAN
es: CMS_AUTHENTICATON_EMAIL_SERVICE es: CMS_AUTHENTICATION_EMAIL_SERVICE
l_url_activate: STRING l_url_activate: STRING
l_url_reject: STRING l_url_reject: STRING
l_token: STRING l_token: STRING
l_captcha_passed: BOOLEAN 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
if req.is_post_request_method then if req.is_post_request_method then
if 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 ("email") as l_email and then attached {WSF_STRING} req.form_parameter ("personal_information") as l_personal_information then if
l_user_api := api.user_api attached {WSF_STRING} req.form_parameter ("name") as l_name and then
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 attached {WSF_STRING} req.form_parameter ("password") as l_password and then
-- Username already exist. attached {WSF_STRING} req.form_parameter ("email") as p_email and then
r.set_value ("User name already exists!", "error_name") attached {WSF_STRING} req.form_parameter ("personal_information") as l_personal_information
l_exist := True then
end if p_email.value.is_valid_as_string_8 then
if attached l_user_api.user_by_email (l_email.value) or else attached l_user_api.temp_user_by_email (l_email.value) then l_email := p_email.value.to_string_8
-- Emails already exist. l_user_api := api.user_api
r.set_value ("An account is already associated with that email address!", "error_email") 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
l_exist := True -- Username already exist.
end r.set_value ("User name already exists!", "error_name")
if attached recaptcha_secret_key (api) as l_recaptcha_key then l_exist := True
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 end
l_captcha_passed := True 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 else
--| Bad or missing captcha --| reCaptcha is not setup, so no verification
l_captcha_passed := False 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)
-- Create activation token
l_token := new_token
l_user_api.new_activation (l_token, u.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
create es.make (create {CMS_AUTHENTICATION_EMAIL_SERVICE_PARAMETERS}.make (api))
write_debug_log (generator + ".handle register: send_register_email")
es.send_account_evaluation (u, l_personal_information.value, l_url_activate, l_url_reject, req.absolute_script_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 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.value)
u.set_password (l_password.value)
u.set_personal_information (l_personal_information.value)
l_user_api.new_temp_user (u)
-- Create activation token
l_token := new_token
l_user_api.new_activation (l_token, u.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
create es.make (create {CMS_AUTHENTICATION_EMAIL_SERVICE_PARAMETERS}.make (api))
write_debug_log (generator + ".handle register: send_register_email")
es.send_account_evaluation (u, l_personal_information.value, l_url_activate, l_url_reject, req.absolute_script_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.value, l_name.value, req.absolute_script_url (""))
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_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
@@ -279,7 +299,7 @@ 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_AUTHENTICATON_EMAIL_SERVICE 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)
@@ -299,12 +319,12 @@ feature -- Handler
l_user.mark_active l_user.mark_active
l_user_api.new_user_from_temp_user (l_user) l_user_api.new_user_from_temp_user (l_user)
l_user_api.remove_activation (l_token.value) l_user_api.remove_activation (l_token.value)
r.set_main_content ("<p> The account <i>" + l_user.name + "</i> has been activated</p>") r.set_main_content ("<p> The account <i>" + html_encoded (l_user.name) + "</i> has been activated</p>")
-- Send Email -- Send Email
if attached l_user.email as l_email then if attached l_user.email as l_email then
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_activation_confirmation_email") write_debug_log (generator + ".handle register: send_contact_activation_confirmation_email")
es.send_contact_activation_confirmation_email (l_email, "", req.absolute_script_url ("")) es.send_contact_activation_confirmation_email (l_email, l_user, req.absolute_script_url (""))
end end
else else
-- the token does not exist, or it was already used. -- the token does not exist, or it was already used.
@@ -325,8 +345,8 @@ feature -- Handler
handle_reject (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE) handle_reject (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE)
local local
r: CMS_RESPONSE r: CMS_RESPONSE
es: CMS_AUTHENTICATION_EMAIL_SERVICE
l_ir: INTERNAL_SERVER_ERROR_CMS_RESPONSE l_ir: INTERNAL_SERVER_ERROR_CMS_RESPONSE
es: CMS_AUTHENTICATON_EMAIL_SERVICE
l_user_api: CMS_USER_API l_user_api: CMS_USER_API
do do
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
@@ -335,12 +355,12 @@ feature -- Handler
l_user_api := api.user_api 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 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) l_user_api.delete_temp_user (l_user)
r.set_main_content ("<p> The temporal account for <i>" + l_user.name + "</i> has been removed</p>") r.set_main_content ("<p> The temporal account for <i>" + html_encoded (l_user.name) + "</i> has been removed</p>")
-- Send Email -- Send Email
if attached l_user.email as l_email then if attached l_user.email as l_email then
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_activation_reject_email") write_debug_log (generator + ".handle register: send_contact_activation_reject_email")
es.send_contact_activation_reject_email (l_email, "", req.absolute_script_url ("")) es.send_contact_activation_reject_email (l_email, l_user, req.absolute_script_url (""))
end end
else else
-- the token does not exist, or it was already used. -- the token does not exist, or it was already used.
@@ -361,37 +381,45 @@ feature -- Handler
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_activate: STRING l_url_activate: STRING
l_url_reject: 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 r.has_permission ("account reactivate") then if r.has_permission ("account reactivate") then
if req.is_post_request_method then if req.is_post_request_method then
if attached {WSF_STRING} req.form_parameter ("email") as l_email then if attached {WSF_STRING} req.form_parameter ("email") as p_email then
l_user_api := api.user_api if p_email.value.is_valid_as_string_8 then
if attached {CMS_TEMP_USER} l_user_api.temp_user_by_email (l_email.value) as l_user then l_email := p_email.value.to_string_8
-- User exist create a new token and send a new email. l_user_api := api.user_api
if l_user.is_active then if attached {CMS_TEMP_USER} l_user_api.temp_user_by_email (l_email) as l_user then
r.set_value ("The asociated user to the given email " + l_email.value + " , is already active", "is_active") -- User exist create a new token and send a new email.
r.set_status_code ({HTTP_CONSTANTS}.bad_request) if l_user.is_active then
else r.set_value ("The asociated user to the given email " + l_email + " , is already active", "is_active")
l_token := new_token r.set_status_code ({HTTP_CONSTANTS}.bad_request)
l_user_api.new_activation (l_token, l_user.id) else
l_url_activate := req.absolute_script_url ("/account/activate/" + l_token) l_token := new_token
l_url_reject := req.absolute_script_url ("/account/reject/" + l_token) l_user_api.new_activation (l_token, l_user.id)
-- Send Email to webmaster l_url_activate := req.absolute_script_url ("/account/activate/" + l_token)
if attached l_user.personal_information as l_personal_information then l_url_reject := req.absolute_script_url ("/account/reject/" + l_token)
create es.make (create {CMS_AUTHENTICATION_EMAIL_SERVICE_PARAMETERS}.make (api)) -- Send Email to webmaster
write_debug_log (generator + ".handle register: send_register_email") if attached l_user.personal_information as l_personal_information then
es.send_account_evaluation (l_user, l_personal_information, l_url_activate, l_url_reject, req.absolute_script_url ("")) 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 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 end
else else
r.set_value ("The email does not exist or !", "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
end end
@@ -406,32 +434,43 @@ feature -- Handler
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
-- User exist create a new token and send a new email. l_email := p_email.value.to_string_8
l_token := new_token if attached {CMS_USER} l_user_api.user_by_email (l_email) as l_user then
l_user_api.new_password (l_token, l_user.id) -- User exist create a new token and send a new email.
l_url := req.absolute_script_url ("/account/reset-password?token=" + l_token) l_token := new_token
l_user_api.new_password (l_token, l_user.id)
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, req.absolute_script_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 attached l_user.email as l_email then if
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
-- 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)
@@ -440,7 +479,7 @@ feature -- Handler
-- 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, req.absolute_script_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")
@@ -524,7 +563,6 @@ feature -- Handler
r.execute r.execute
end end
handle_admin_pending_registrations (req: WSF_REQUEST; res: WSF_RESPONSE; api: CMS_API) handle_admin_pending_registrations (req: WSF_REQUEST; res: WSF_RESPONSE; api: CMS_API)
local local
l_response: CMS_RESPONSE l_response: CMS_RESPONSE
@@ -573,11 +611,11 @@ feature -- Handler
loop loop
u := ic.item u := ic.item
s.append ("<li class=%"cms_temp_user%">") s.append ("<li class=%"cms_temp_user%">")
s.append ("User:" + u.name) s.append ("User:" + html_encoded (u.name))
s.append ("<ul class=%"cms_temp_user_details%">") s.append ("<ul class=%"cms_temp_user_details%">")
if attached u.personal_information as l_information then if attached u.personal_information as l_information then
s.append ("<li class=%"cms_temp_user_detail_information%">") s.append ("<li class=%"cms_temp_user_detail_information%">")
s.append (l_information) s.append (html_encoded (l_information))
s.append ("</li>%N") s.append ("</li>%N")
end end
if attached u.email as l_email then if attached u.email as l_email then
@@ -616,7 +654,6 @@ feature -- Handler
end end
end end
block_list: ITERABLE [like {CMS_BLOCK}.name] block_list: ITERABLE [like {CMS_BLOCK}.name]
local local
l_string: STRING l_string: STRING
@@ -635,16 +672,19 @@ feature -- Handler
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)
local
loc: READABLE_STRING_8
do do
if a_block_id.is_case_insensitive_equal_general ("register") and then a_response.location.starts_with ("account/roc-register") then loc := a_response.location
if a_block_id.is_case_insensitive_equal_general ("register") and then loc.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 a_block_id.is_case_insensitive_equal_general ("reactivate") and then a_response.location.starts_with ("account/reactivate") then elseif a_block_id.is_case_insensitive_equal_general ("reactivate") and then loc.starts_with ("account/reactivate") then
get_block_view_reactivate (a_block_id, a_response) get_block_view_reactivate (a_block_id, a_response)
elseif a_block_id.is_case_insensitive_equal_general ("new_password") and then a_response.location.starts_with ("account/new-password") then elseif a_block_id.is_case_insensitive_equal_general ("new_password") and then loc.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 a_block_id.is_case_insensitive_equal_general ("reset_password") and then a_response.location.starts_with ("account/reset-password") then elseif a_block_id.is_case_insensitive_equal_general ("reset_password") and then loc.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 elseif a_block_id.is_case_insensitive_equal_general ("registration") and then loc.starts_with ("admin/pending-registrations") then
get_block_view_registration (a_block_id, a_response) get_block_view_registration (a_block_id, a_response)
end end
end end
@@ -1,148 +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_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.site_name)
l_message.replace_substring_all ("$user", a_user.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, contact_email, parameters.contact_subject_account_evaluation, l_message)
end
send_contact_email (a_to, a_user, a_host: READABLE_STRING_8)
-- Send successful contact message 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.site_name)
l_message.replace_substring_all ("$user", a_user)
send_message (contact_email, a_to, parameters.contact_subject_register, l_message)
end
send_contact_activation_email (a_to, a_content, a_host: READABLE_STRING_8)
-- Send successful contact activation message 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.site_name)
l_message.replace_substring_all ("$link", a_content)
send_message (contact_email, a_to, parameters.contact_subject_activate, l_message)
end
send_contact_activation_confirmation_email (a_to, a_content, 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.site_name)
l_message.replace_substring_all ("$email", a_content)
send_message (contact_email, a_to, parameters.contact_subject_activated, l_message)
end
send_contact_activation_reject_email (a_to, a_content, 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.site_name)
l_message.replace_substring_all ("$link", a_content)
send_message (contact_email, a_to, parameters.contact_subject_rejected, l_message)
end
send_contact_password_email (a_to, a_content, 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.site_name)
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, 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 ("$sitenme", parameters.site_name)
l_message.replace_substring_all ("$link", a_content)
send_message (contact_email, a_to, parameters.contact_subject_oauth, l_message)
end
end
+4 -5
View File
@@ -1,8 +1,7 @@
{ {
"email": "webmaster@eiffel.org",
"subject": "Thank you for contacting us", "subject": "Thank you for contacting us",
"recaptcha": { "recaptcha": {
"site_key":"6Lex9RMTAAAAAKleC4x6TaRlFcpLbEWgH_U7MSiD", "site_key":"6Lex9RMTAAAAAKleC4x6TaRlFcpLbEWgH_U7MSiD",
"secret_key":"6Lex9RMTAAAAAAkBczvX5DUiyg_xoM_EthVVgRRx" "secret_key":"6Lex9RMTAAAAAAkBczvX5DUiyg_xoM_EthVVgRRx"
} }
} }
+25 -19
View File
@@ -1,22 +1,28 @@
ul.cms-temp-users { ul.cms-temp-users {
list-style-type: none; list-style-type: none;
padding: 3px 3px 3px 3px; padding: 3px 3px 3px 3px;
border: solid 1px #ccc; } border: solid 1px #ccc;
ul.cms-temp-users li { }
border-top: dotted 1px #ccc; } ul.cms-temp-users li {
ul.cms-temp-users li:first-child { border-top: dotted 1px #ccc;
border-top: none; } }
ul.cms-temp-users li.cms_temp_user ul.cms_temp_user_details { ul.cms-temp-users li:first-child {
list-style-type: none; border-top: none;
padding: 3px 3px 3px 3px; }
border: solid 1px #ccc; } ul.cms-temp-users li.cms_temp_user ul.cms_temp_user_details {
ul.cms-temp-users li.cms_temp_user ul.cms_temp_user_details li { list-style-type: none;
border-top: dotted 1px #ccc; } padding: 3px 3px 3px 3px;
ul.cms-temp-users li.cms_temp_user ul.cms_temp_user_details li:first-child { border: solid 1px #ccc;
border-top: none; } }
ul.cms-temp-users li.cms_temp_user ul.cms_temp_user_details li.cms_temp_user_detail_information::before { ul.cms-temp-users li.cms_temp_user ul.cms_temp_user_details li {
content: "[personal information] "; } border-top: dotted 1px #ccc;
ul.cms-temp-users li.cms_temp_user ul.cms_temp_user_details li.cms_temp_user_detail_email::before { }
content: "[email] "; } ul.cms-temp-users li.cms_temp_user ul.cms_temp_user_details li:first-child {
border-top: none;
/*# sourceMappingURL=auth.css.map */ }
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] ";
}
-22
View File
@@ -1,22 +0,0 @@
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] "; }
/*# sourceMappingURL=auth.css.map */
@@ -1,7 +0,0 @@
{
"version": 3,
"mappings": "AAAA,iBAAkB;EAEjB,eAAe,EAAE,IAAI;EACrB,OAAO,EAAE,eAAe;EACxB,MAAM,EAAE,cAAc;EAEtB,oBAAE;IACD,UAAU,EAAE,eAAe;IAC3B,gCAAc;MACb,UAAU,EAAE,IAAI;EAMjB,2DAAyB;IACxB,eAAe,EAAE,IAAI;IACrB,OAAO,EAAE,eAAe;IACxB,MAAM,EAAE,cAAc;IAEtB,8DAAE;MACD,UAAU,EAAE,eAAe;MAC3B,0EAAc;QACb,UAAU,EAAE,IAAI;IAGlB,uGAA2C;MAC1C,OAAO,EAAE,yBAAyB;IAEnC,iGAAqC;MACpC,OAAO,EAAE,UAAU",
"sources": ["auth.scss"],
"names": [],
"file": "auth.css"
}
@@ -1,14 +1,13 @@
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<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="$sitename"> <meta name="author" content="$sitename">
</head> </head>
<body> <body>
<p>Thank you for applying to <a href="$host">$sitename</a> $user</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>We will review your application and send you a resolution.<p>
</body> </body>
</html> </html>
@@ -6,9 +6,8 @@
<meta name="description" content="Activation Confirmation"> <meta name="description" content="Activation Confirmation">
<meta name="author" content="$sitename"> <meta name="author" content="$sitename">
</head> </head>
<body> <body>
<p>Your account has been confirmed <a href="$host">$sitename</a> $email</p> <p>Your account "$user ($email)" is confirmed at <a href="$host">$sitename</a>.</p>
<p>Thank you for joining us.</p> <p>Thank you for joining us.</p>
</body> </body>
</html> </html>
@@ -6,12 +6,10 @@
<meta name="description" content="New Password"> <meta name="description" content="New Password">
<meta name="author" content="$sitename"> <meta name="author" content="$sitename">
</head> </head>
<body> <body>
<p>You have required a new password at <a href="$host">$sitename</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 generate a new password:<p> <ul><a href="$link">$link</a></ul>
</p>
<p><a href="$link">$link</a></p>
</body> </body>
</html> </html>
@@ -6,13 +6,12 @@
<meta name="description" content="New Activation token"> <meta name="description" content="New Activation token">
<meta name="author" content="$sitename"> <meta name="author" content="$sitename">
</head> </head>
<body> <body>
<p>You have request a new activation token at <a href="$host">$sitename</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>
@@ -6,8 +6,7 @@
<meta name="description" content="Application Rejected"> <meta name="description" content="Application Rejected">
<meta name="author" content="$sitename"> <meta name="author" content="$sitename">
</head> </head>
<body> <body>
<p>You requested has been rejected, your application does not conform our rules <a href="$host">$sitename</a></p> <p>Your account application is rejected, it was not respecting the requirements from <a href="$host">$sitename</a>.</p>
</body> </body>
</html> </html>
@@ -7,7 +7,13 @@
<meta name="author" content="$sitename"> <meta name="author" content="$sitename">
</head> </head>
<body> <body>
<p>Welcome to <a href="$host">$sitename</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>
@@ -1,13 +0,0 @@
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`)
);
+8 -18
View File
@@ -78,27 +78,17 @@ feature {CMS_API} -- Module Initialization
feature {CMS_API} -- Module management feature {CMS_API} -- Module management
install (api: CMS_API) install (a_api: CMS_API)
local
sql: STRING
do do
-- Schema -- Schema
if attached api.storage.as_sql_storage as l_sql_storage then if attached a_api.storage.as_sql_storage as l_sql_storage then
if not l_sql_storage.sql_table_exists ("blog_post_nodes") then l_sql_storage.sql_execute_file_script (a_api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended ("install.sql")), Void)
sql := "[
CREATE TABLE blog_post_nodes( if l_sql_storage.has_error then
`nid` INTEGER NOT NULL CHECK("nid">=0), a_api.logger.put_error ("Could not initialize database for module [" + name + "]", generating_type)
`revision` INTEGER NOT NULL, else
`tags` VARCHAR(255), Precursor {CMS_MODULE} (a_api)
CONSTRAINT PK_nid_revision PRIMARY KEY (nid,revision)
);
]"
l_sql_storage.sql_execute_script (sql, Void)
if l_sql_storage.has_error then
api.logger.put_error ("Could not initialize database for blog module", generating_type)
end
end end
Precursor (api)
end end
end end
+1 -1
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
+6
View File
@@ -0,0 +1,6 @@
CREATE TABLE blog_post_nodes(
`nid` INTEGER NOT NULL CHECK("nid">=0),
`revision` INTEGER NOT NULL,
`tags` VARCHAR(255),
CONSTRAINT PK_nid_revision PRIMARY KEY (nid,revision)
);
+21
View File
@@ -0,0 +1,21 @@
<?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="contact" uuid="5F9BB4AA-FB62-4550-B314-DED374843DC0" library_target="contact">
<target name="contact">
<root all_classes="true"/>
<option is_obsolete_routine_type="true">
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<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_config" location="..\..\library\configuration\config-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="net" location="$ISE_LIBRARY\library\net\net-safe.ecf"/>
<library name="recaptcha" location="..\..\library\recaptcha\recaptcha-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_encoder" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\text\encoder\encoder-safe.ecf"/>
<library name="wsf_html" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf_html\wsf_html-safe.ecf"/>
<cluster name="src" location="src\" recursive="true"/>
</target>
</system>
+8
View File
@@ -0,0 +1,8 @@
{
"--email": "webmaster@example.com",
"subjet": "Thank you for contacting us",
"recaptcha": {
"site_key":"",
"secret_key":""
}
}
+124
View File
@@ -0,0 +1,124 @@
.contact-box {
background-color: #F2F7F9;
width: 465px;
padding: 20px;
border: 6px solid #8FB5C1;
-moz-border-radius: 15px;
-webkit-border-radius: 15px;
border-radius: 15px;
position: relative;
/* Remove box shadow firefox, chrome and opera put around required fields.
* It looks rubbish.
*/
/* Normalize placeholder styles */
/* chrome, safari */
/* mozilla */
/* ie (faux placeholder) */
}
.contact-box h1 {
font-size: 42px;
}
.contact-box h2 {
margin-bottom: 15px;
font-style: italic;
font-weight: normal;
}
.contact-box label {
font-size: 15px;
margin-bottom: 2px;
display: block;
}
.contact-box input, .contact-box select, .contact-box textarea {
width: 100%;
font-size: 15px;
border: 1px solid #CEE1E8;
margin-bottom: 20px;
padding: 4px;
}
.contact-box input:focus, .contact-box select:focus, .contact-box textarea:focus {
border: 1px solid #AFCDD8;
background-color: #EBF2F4;
}
.contact-box textarea {
height: 150px;
resize: none;
}
.contact-box span.required {
font-weight: bold;
color: #F00;
}
.contact-box input[type=submit] {
width: 100px;
background-color: #333;
color: #FFF;
border: none;
display: block;
float: right;
margin-bottom: 0px;
margin-right: 6px;
background-color: #8FB5C1;
-moz-border-radius: 8px;
}
.contact-box input[type=submit]:hover {
background-color: #A6CFDD;
}
.contact-box input[type=submit]:active {
position: relative;
top: 1px;
}
.contact-box .message {
width: 95%;
margin: 25px 0px;
padding: 10px;
display: block;
border: solid 1px #ccc;
border-radius: 8px;
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
}
.contact-box .message.hidden {
display: none;
}
.contact-box .message.error {
border-color: #E58E8E;
background-color: #FFE6E6;
}
.contact-box .message.error li {
padding: 2px;
list-style: none;
}
.contact-box .message.error li:before {
content: ' - ';
}
.contact-box .message.error #info {
font-weight: bold;
}
.contact-box .message.error #info:before {
content: '';
}
.contact-box .message.success {
border-color: #83D186;
padding-top: 25px;
background-color: #D3EDD3;
}
.contact-box .req-field-desc {
font-style: italic;
}
.contact-box input:required, .contact-box textarea:required {
-moz-box-shadow: none;
-webkit-box-shadow: none;
-o-box-shadow: none;
box-shadow: none;
}
.contact-box ::-webkit-input-placeholder {
color: #CCC;
font-style: italic;
}
.contact-box input:-moz-placeholder, .contact-box textarea:-moz-placeholder {
color: #CCC;
font-style: italic;
}
.contact-box input.placeholder-text, .contact-box textarea.placeholder-text {
color: #CCC;
font-style: italic;
}
@@ -0,0 +1,140 @@
.contact-box {
background-color:#F2F7F9;
width:465px;
padding:20px;
border: 6px solid #8FB5C1;
-moz-border-radius:15px;
-webkit-border-radius:15px;
border-radius:15px;
position:relative;
h1 {
font-size:42px;
}
h2 {
margin-bottom:15px;
font-style:italic;
font-weight:normal;
}
label {
font-size:15px;
margin-bottom:2px;
display:block;
}
input, select, textarea {
width:100%;
font-size:15px;
border: 1px solid #CEE1E8;
margin-bottom:20px;
padding:4px;
&:focus {
border: 1px solid #AFCDD8;
background-color: #EBF2F4;
}
}
textarea {
height:150px;
resize: none;
}
span.required {
font-weight:bold;
color:#F00;
}
input[type=submit] {
width: 100px;
background-color:#333;
color:#FFF;
border:none;
display:block;
float:right;
margin-bottom:0px;
margin-right:6px;
background-color:#8FB5C1;
-moz-border-radius:8px;
&:hover {
background-color: #A6CFDD;
}
&:active {
position:relative;
top:1px;
}
}
.message {
width:95%;
margin:25px 0px;
padding:10px;
display:block;
border:solid 1px #ccc;
border-radius:8px;
-webkit-border-radius:8px;
-moz-border-radius:8px;
&.hidden {
display: none;
}
&.error {
border-color: #E58E8E;
background-color:#FFE6E6;
li {
padding:2px;
list-style:none;
&:before { content: ' - '; }
}
#info {
font-weight:bold;
&:before { content: ''; }
}
}
&.success {
border-color: #83D186;
padding-top: 25px;
background-color:#D3EDD3;
}
}
.req-field-desc {
font-style:italic;
}
/* Remove box shadow firefox, chrome and opera put around required fields.
* It looks rubbish.
*/
input:required, textarea:required {
-moz-box-shadow:none;
-webkit-box-shadow:none;
-o-box-shadow:none;
box-shadow:none;
}
/* Normalize placeholder styles */
/* chrome, safari */
::-webkit-input-placeholder {
color:#CCC;
font-style:italic;
}
/* mozilla */
input:-moz-placeholder, textarea:-moz-placeholder {
color:#CCC;
font-style:italic;
}
/* ie (faux placeholder) */
input.placeholder-text, textarea.placeholder-text {
color:#CCC;
font-style:italic;
}
}
@@ -0,0 +1,25 @@
<div class="contact-box clearfix">
<h1>Contact us!</h1>
<form method="post" action="{$site_url/}contact" id="contact-form">
<label for="name">Name: <span class="required">*</span></label>
<input type="text" id="name" name="name" value="{$name/}" required="required" autofocus="autofocus" />
<label for="email">Email Address: <span class="required">*</span></label>
<input type="email" id="email" name="email" value="{$email/}" required="required" />
<label for="message">Message: <span class="required">*</span></label>
<textarea id="message" name="message" required="required" data-minlength="20" minlength="20" >{$message/}</textarea>
{unless isempty="$recaptcha_site_key"}
<div class="g-recaptcha" data-sitekey="{$recaptcha_site_key/}"></div>
<br/>
{/unless}
<input type="submit" value="Send" class="submit-button" />
<p class="req-field-desc"><span class="required">*</span> indicates a required field</p>
</form>
{unless isempty="$error_response"}
<ul class="message error">
{foreach item="item" from="$error_response"}<li class="info">{$item/}</li>{/foreach}
</ul>
<div class="notice"> Try again later </div>
{/unless}
</div>
@@ -0,0 +1,15 @@
<div class="contact-box">
{if condition="$has_error"}
<div class="message error">
<strong>Internal Server Error <small>Error 500</small></strong>
<p>The page you requested could not be served because the server is down,
either contact the webmaster or try again.
Use your browser's <strong>Back</strong> button to navigate to the page you came from.</p>
<p><strong>Or you could just press this link:</strong> <a href="{$site_url/}" itemprop="home" rel="home">Take Me Home</a></p>
</div>
{/if}
{unless condition="$has_error"}
<p class="message success">Thank you for contacting the Eiffel Programming Language community.<br/>
We will get back to you promptly on your contact request.</p>
{/unless}
</div>
@@ -0,0 +1,10 @@
<p>
Thank you for contacting {$sitename/}.<br/>
We will get back to you promptly about your contact message.
</p>
<h2>Your contact information:</h2>
<div>
<strong>Name<strong>: {$name/} <br/>
<strong>Email<strong>: {$email/} <br/>
<strong>Message<strong>: {$message/} <br/>
</div>
@@ -0,0 +1,6 @@
<h2>Contact information:</h2>
<div>
<strong>Name<strong>: {$name/}<br/>
<strong>Email<strong>: {$email/} <br/>
<strong>Message<strong>: {$message/} <br/>
</div>
+546
View File
@@ -0,0 +1,546 @@
note
description: "[
Module that provide contact us web form functionality.
]"
author: "$Author: jfiat $"
date: "$Date: 2016-01-08 22:43:12 +0100 (ven., 08 janv. 2016) $"
revision: "$Revision: 98369 $"
class
CMS_CONTACT_MODULE
inherit
CMS_MODULE
rename
module_api as contact_api
redefine
setup_hooks,
install,
initialize,
contact_api
end
SHARED_HTML_ENCODER
CMS_HOOK_BLOCK
CMS_HOOK_BLOCK_HELPER
CMS_HOOK_AUTO_REGISTER
CMS_HOOK_MENU_SYSTEM_ALTER
SHARED_EXECUTION_ENVIRONMENT
export
{NONE} all
end
REFACTORING_HELPER
SHARED_LOGGER
create
make
feature {NONE} -- Initialization
make
-- Create current module
do
version := "1.0"
description := "Contact form module"
package := "messaging"
end
feature -- Access
name: STRING = "contact"
-- <Precursor>
feature {CMS_API} -- Module Initialization
initialize (api: CMS_API)
-- <Precursor>
local
l_contact_api: like contact_api
ut: FILE_UTILITIES
p: PATH
contact_storage: CONTACT_STORAGE_I
do
Precursor (api)
-- if attached api.storage.as_sql_storage as l_storage_sql then
-- create {CONTACT_STORAGE_SQL} contact_storage.make (l_storage_sql)
-- else
p := file_system_storage_path (api)
if ut.directory_path_exists (p) then
create {CONTACT_STORAGE_FS} contact_storage.make (p, api)
else
create {CONTACT_STORAGE_NULL} contact_storage.make
end
create l_contact_api.make (api, contact_storage)
contact_api := l_contact_api
end
feature {CMS_API} -- Module management
install (api: CMS_API)
local
retried: BOOLEAN
d: DIRECTORY
do
if not retried then
create d.make_with_path (file_system_storage_path (api))
d.recursive_create_dir
Precursor {CMS_MODULE}(api) -- Marked installed
end
rescue
retried := True
retry
end
file_system_storage_path (api: CMS_API): PATH
-- Location of eventual file system based storage for contact messages.
do
Result := api.site_location.extended ("db").extended (name).extended ("messages")
end
feature {CMS_API} -- Access: API
contact_api: detachable CONTACT_API
feature -- Router
setup_router (a_router: WSF_ROUTER; a_api: CMS_API)
-- Router configuration.
local
m: WSF_URI_MAPPING
do
create m.make_trailing_slash_ignored ("/contact", create {WSF_URI_AGENT_HANDLER}.make (agent handle_contact (a_api, ?, ?)))
a_router.map (m, a_router.methods_head_get)
a_router.handle ("/contact", create {WSF_URI_AGENT_HANDLER}.make (agent handle_post_contact (a_api, ?, ?)), a_router.methods_put_post)
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 -- 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)
end
feature -- Hooks
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'.
do
debug ("refactor_fixme")
fixme ("add contact to menu")
end
end
block_list: ITERABLE [like {CMS_BLOCK}.name]
do
Result := <<"?contact">>
end
get_block_view (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE)
do
if a_block_id.is_case_insensitive_equal_general ("contact") then
-- "contact", "post_contact"
if a_response.request.is_get_request_method then
if attached template_block (Current, 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_style (a_response.url ("/module/" + name + "/files/css/contact.css", Void), Void)
else
debug ("cms")
a_response.add_warning_message ("Error with block [" + a_block_id + "]")
end
end
end
end
end
new_html_contact_form (a_response: CMS_RESPONSE; api: CMS_API): STRING
local
f: CMS_FORM
do
a_response.add_style (a_response.url ("/module/" + name + "/files/css/contact.css", Void), Void)
if attached template_block (Current, "contact", a_response) as l_tpl_block then
if attached recaptcha_site_key (api) as l_recaptcha_site_key then
l_tpl_block.set_value (l_recaptcha_site_key, "recaptcha_site_key")
end
across
a_response.values as tb
loop
l_tpl_block.set_value (tb.item, tb.key)
end
Result := l_tpl_block.to_html (a_response.theme)
else
f := new_contact_form (a_response, api)
api.hooks.invoke_form_alter (f, f.last_data, a_response)
Result := "<div class=%"contact-box%"><h1>Contact us!</h1>" + f.to_html (a_response.wsf_theme) + "<br/></div>"
end
end
new_contact_form (a_response: CMS_RESPONSE; api: CMS_API): CMS_FORM
local
f: CMS_FORM
f_name: WSF_FORM_TEXT_INPUT
f_email: WSF_FORM_EMAIL_INPUT
f_msg: WSF_FORM_TEXTAREA
f_submit: WSF_FORM_SUBMIT_INPUT
do
create f.make (a_response.url ("contact", Void), "contact-form")
create f_name.make ("name")
f_name.set_label ("Name")
f_name.set_is_required (True)
f.extend (f_name)
create f_email.make ("email")
f_email.set_label ("Email Address")
f_email.set_is_required (True)
f.extend (f_email)
create f_msg.make ("message")
f_msg.set_label ("Message")
f_msg.set_rows (5)
f_msg.set_is_required (True)
f.extend (f_msg)
if attached recaptcha_site_key (api) as l_recaptcha_site_key then
f.extend_html_text ("<div class=%"g-recaptcha%" data-sitekey=%"" + l_recaptcha_site_key + "%"></div><br/>")
end
create f_submit.make_with_text ("submit-op", "Send")
f.extend (f_submit)
-- f.extend_html_text ("[
-- <p class="req-field-desc"><span class="required">*</span> indicates a required field</p>
-- ]")
Result := f
end
handle_contact (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE)
local
r: CMS_RESPONSE
do
-- FIXME: we should use WSF_FORM, and integrate the recaptcha using the form alter hook.
write_debug_log (generator + ".handle_contact")
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
r.values.force ("contact", "contact")
r.set_main_content (new_html_contact_form (r, api))
r.execute
end
handle_post_contact (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE)
local
r: CMS_RESPONSE
msg: CONTACT_MESSAGE
l_params: CONTACT_EMAIL_SERVICE_PARAMETERS
e: CMS_EMAIL
vars: STRING_TABLE [READABLE_STRING_8]
l_contact_email_address: READABLE_STRING_8
do
write_information_log (generator + ".handle_post_contact")
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
r.add_style (r.url ("/module/" + name + "/files/css/contact.css", Void), Void)
r.values.force (False, "has_error")
create vars.make_caseless (5)
vars.put (html_encoded (api.setup.site_url), "siteurl")
vars.put (html_encoded (api.setup.site_name), "sitename")
write_debug_log (generator + ".handle_post_contact {Form Parameters:" + form_parameters_as_string (req) + "}")
if
attached {WSF_STRING} req.form_parameter ("name") as l_name and then
attached {WSF_STRING} req.form_parameter ("email") as l_email and then
attached {WSF_STRING} req.form_parameter ("message") as l_message
then
if
is_form_captcha_verified (req, "g-recaptcha-response", api) and then
l_email.value.is_valid_as_string_8
then
l_contact_email_address := l_email.value.to_string_8
if attached contact_api as l_contact_api then
create msg.make (l_name.value, l_message.value)
msg.set_email (l_contact_email_address)
l_contact_api.save_contact_message (msg)
end
create l_params.make (api, Current)
-- Send internal email to admin.
vars.put (html_encoded (l_name.value), "name")
vars.put (html_encoded (l_contact_email_address), "email")
vars.put (html_encoded (l_message.value), "message")
write_debug_log (generator + ".handle_post_contact: send notification email")
e := api.new_email (l_params.admin_email, "Notification Contact", email_html_message ("notification", r, vars))
e.set_from_address (l_params.admin_email)
e.add_header_line ("MIME-Version:1.0")
e.add_header_line ("Content-Type: text/html; charset=utf-8")
api.process_email (e)
if not api.has_error then
-- Send Contact email to the user
write_information_log (generator + ".handle_post_contact: preparing the message.")
e := api.new_email (l_contact_email_address, l_params.contact_subject_text, email_html_message ("message", r, vars))
e.set_from_address (l_params.admin_email)
e.add_header_line ("MIME-Version:1.0")
e.add_header_line ("Content-Type: text/html; charset=utf-8")
write_debug_log (generator + ".handle_post_contact: send_contact_email")
api.process_email (e)
end
if api.has_error then
write_error_log (generator + ".handle_post_contact: error message:["+ api.string_representation_of_errors +"]")
r.set_status_code ({HTTP_CONSTANTS}.internal_server_error)
r.values.force (True, "has_error")
vars.put ("True", "has_error")
end
if attached template_block_with_values (Current, "post_contact", r, vars) as l_tpl_block then
across
r.values as tb
loop
l_tpl_block.set_value (tb.item, tb.key)
end
r.set_main_content (l_tpl_block.to_html (r.theme))
else
r.set_main_content ("Thank you for your message.")
end
r.execute
else
-- send a bad request status code and redisplay the form with the previous data loaded.
r.set_value (False, "error")
r.set_status_code ({HTTP_STATUS_CODE}.bad_request)
if attached template_block_with_values (Current, "contact", r, vars) as l_tpl_block then
across
r.values as tb
loop
l_tpl_block.set_value (tb.item, tb.key)
end
if attached recaptcha_site_key (api) as l_recaptcha_site_key then
l_tpl_block.set_value (l_recaptcha_site_key, "recaptcha_site_key")
l_tpl_block.set_value (<<"Missing Captcha", "Internal Server Error">>, "error_response")
end
r.set_main_content (l_tpl_block.to_html (r.theme))
else
debug ("cms")
r.add_warning_message ("Error with block [contact]")
end
end
r.execute
end
else
-- Internal server error
write_error_log (generator + ".handle_post_contact: Internal Server error")
r.values.force (True, "has_error")
r.set_status_code ({HTTP_CONSTANTS}.internal_server_error)
if attached template_block_with_values (Current, "post_contact", r, vars) as l_tpl_block then
across
r.values as tb
loop
l_tpl_block.set_value (tb.item, tb.key)
end
r.set_main_content (l_tpl_block.to_html (r.theme))
end
r.execute
end
end
is_form_captcha_verified (req: WSF_REQUEST; a_form_field_id: READABLE_STRING_GENERAL; api: CMS_API): BOOLEAN
do
if attached recaptcha_secret_key (api) as l_recaptcha_key then
if
attached {WSF_STRING} req.form_parameter (a_form_field_id) as l_recaptcha_response and then
is_captcha_verified (l_recaptcha_key, l_recaptcha_response.value)
then
Result := True
else
--| Bad or missing captcha
Result := False
end
else
--| reCaptcha is not setup, so no verification
Result := True
end
end
feature {NONE} -- Helpers
form_parameters_as_string (req: WSF_REQUEST): STRING
do
create Result.make_empty
across req.form_parameters as ic loop
Result.append (ic.item.key)
Result.append_character ('=')
Result.append_string (ic.item.string_representation)
Result.append_character ('%N')
end
end
feature {NONE} -- HTML ENCODING.
html_encoded (s: detachable READABLE_STRING_GENERAL): STRING_8
do
if s /= Void then
Result := html_encoder.general_encoded_string (s)
else
create Result.make_empty
end
end
feature {NONE} -- Contact Message
template_block_with_values (a_module: CMS_MODULE; a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE; a_values: STRING_TABLE [ANY]): like template_block
do
Result := template_block (a_module, a_block_id, a_response)
if Result /= Void then
across
a_values as ic
loop
Result.set_value (ic.item, ic.key)
end
end
end
email_html_message (a_message_id: READABLE_STRING_8; a_response: CMS_RESPONSE; a_html_encoded_values: STRING_TABLE [READABLE_STRING_8]): STRING
-- html message related to `a_message_id'.
local
res: PATH
p: detachable PATH
tpl: CMS_SMARTY_TEMPLATE_BLOCK
exp: CMS_STRING_EXPANDER [STRING_8]
do
write_debug_log (generator + ".email_html_message for [" + a_message_id + " ]")
create res.make_from_string ("templates")
res := res.extended ("email_").appended (a_message_id).appended_with_extension ("tpl")
p := a_response.api.module_theme_resource_location (Current, res)
if p /= Void then
if attached p.entry as e then
create tpl.make (a_message_id, Void, p.parent, e)
write_debug_log (generator + ".email_html_message from smarty template:" + tpl.out)
else
create tpl.make (a_message_id, Void, p.parent, p)
write_debug_log (generator + ".email_html_message from smarty template:" + tpl.out)
end
across
a_html_encoded_values as ic
loop
tpl.set_value (ic.item, ic.key)
end
Result := tpl.to_html (a_response.theme)
else
if a_message_id.is_case_insensitive_equal_general ("message") then
create Result.make_from_string (contact_message_template)
elseif a_message_id.is_case_insensitive_equal_general ("notification") then
create Result.make_from_string (contact_notification_message_template)
else
create Result.make_from_string (a_message_id)
across
a_html_encoded_values as ic
loop
Result.append ("<li>")
Result.append (html_encoded (ic.key))
Result.append (": ")
Result.append (ic.item) -- Already html encoded.
Result.append ("</li>%N")
end
end
create exp.make
across
a_html_encoded_values as ic
loop
exp.put (ic.item, ic.key)
end
exp.expand_string (Result)
write_debug_log (generator + ".email_html_message using built-in message:" + Result)
end
end
contact_message_template: STRING
do
Result := "[
<p>Thank you for contacting $sitename.<br/>
We will get back to you promptly on your contact request.
</p>
]"
+ contact_notification_message_template
end
contact_notification_message_template: STRING = "[
<h2>Contact information:</h2>
<div>
<strong>Name<strong>: $name <br/>
<strong>Email<strong>: $email <br/>
<strong>Message<strong>: $message <br/>
</div>
]"
feature {NONE} -- Google recaptcha uri template
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
end
+40
View File
@@ -0,0 +1,40 @@
note
description: "API for the contact module."
date: "$Date: 2015-05-22 23:00:09 +0200 (ven., 22 mai 2015) $"
revision: "$Revision: 97349 $"
class
CONTACT_API
inherit
CMS_MODULE_API
rename
make as make_api
end
REFACTORING_HELPER
create
make
feature {NONE} -- Initialization
make (a_api: CMS_API; a_contact_storage: like contact_storage)
-- <Precursor>.
do
make_api (a_api)
contact_storage := a_contact_storage
end
feature {CMS_MODULE} -- Access nodes storage.
contact_storage: CONTACT_STORAGE_I
feature -- Basic operation
save_contact_message (msg: CONTACT_MESSAGE)
do
contact_storage.save_contact_message (msg)
end
end
@@ -0,0 +1,63 @@
note
description: "Summary description for {CONTACT_EMAIL_SERVICE_PARAMETERS}."
date: "$Date: 2015-07-03 19:04:52 +0200 (ven., 03 juil. 2015) $"
revision: "$Revision: 97646 $"
class
CONTACT_EMAIL_SERVICE_PARAMETERS
create
make
feature {NONE} -- Initialization
make (a_cms_api: CMS_API; a_contact_module: CMS_CONTACT_MODULE)
local
utf: UTF_CONVERTER
l_site_name: READABLE_STRING_8
s: detachable READABLE_STRING_32
l_contact_email, l_contact_subject: detachable READABLE_STRING_8
do
-- Use global smtp setting if any, otherwise "localhost"
l_site_name := utf.escaped_utf_32_string_to_utf_8_string_8 (a_cms_api.setup.site_name)
admin_email := a_cms_api.setup.site_email
if not admin_email.has ('<') then
admin_email := l_site_name + " <" + admin_email + ">"
end
if attached {CONFIG_READER} a_cms_api.module_configuration (a_contact_module, Void) as cfg then
s := cfg.text_item ("email")
if s /= Void then
l_contact_email := utf.utf_32_string_to_utf_8_string_8 (s)
end
s := cfg.text_item ("subject")
if s /= Void then
l_contact_subject := utf.utf_32_string_to_utf_8_string_8 (s)
end
end
if l_contact_email /= Void then
if not l_contact_email.has ('<') then
l_contact_email := l_site_name + " <" + l_contact_email + ">"
end
contact_email := l_contact_email
else
contact_email := admin_email
end
if l_contact_subject /= Void then
contact_subject_text := l_contact_subject
else
contact_subject_text := "Thank you for contacting us"
end
end
feature -- Access
admin_email: IMMUTABLE_STRING_8
contact_email: IMMUTABLE_STRING_8
-- Contact email.
contact_subject_text: IMMUTABLE_STRING_8
end
+43
View File
@@ -0,0 +1,43 @@
note
description: "Interface {CONTACT_MESSAGE} representing the contact's message."
date: "$Date: 2015-07-03 19:04:52 +0200 (ven., 03 juil. 2015) $"
revision: "$Revision: 97646 $"
class
CONTACT_MESSAGE
create
make
feature {NONE} -- Initialization
make (a_name: like username; a_message: like message)
do
username := a_name
message := a_message
create date.make_now_utc
end
feature -- Access
username: READABLE_STRING_32
email: detachable READABLE_STRING_8
message: READABLE_STRING_32
date: DATE_TIME
feature -- Change
set_email (e: like email)
do
email := e
end
set_date (d: like date)
do
date := d
end
end
@@ -0,0 +1,56 @@
note
description: "[
Contact message storage based on SQL statements.
]"
date: "$Date: 2015-07-03 19:04:52 +0200 (ven., 03 juil. 2015) $"
revision: "$Revision: 97646 $"
class
CONTACT_STORAGE_FS
inherit
CONTACT_STORAGE_I
CMS_STORAGE_FS_I
REFACTORING_HELPER
create
make
feature -- Access
feature -- Change
save_contact_message (m: CONTACT_MESSAGE)
local
s: STRING
utf: UTF_CONVERTER
now: DATE_TIME
do
error_handler.reset
create now.make_now_utc
write_information_log (generator + ".save_contact_message")
create s.make_empty
s.append ("date=")
s.append (m.date.out)
s.append_character ('%N')
s.append ("name=")
s.append (utf.utf_32_string_to_utf_8_string_8 (m.username))
s.append_character ('%N')
if attached m.email as l_email then
s.append ("email=")
s.append (l_email)
s.append_character ('%N')
end
s.append ("message=%N")
s.append (utf.utf_32_string_to_utf_8_string_8 (m.message))
s.append_character ('%N')
save_to_file (s, date_to_yyyymmdd_hhmmss_string (now))
end
end
@@ -0,0 +1,27 @@
note
description: "[
Persistence interface for CONTACT_MODULE.
]"
author: "$Author: jfiat $"
date: "$Date: 2015-05-22 23:00:09 +0200 (ven., 22 mai 2015) $"
revision: "$Revision: 97349 $"
deferred class
CONTACT_STORAGE_I
feature -- Error Handling
error_handler: ERROR_HANDLER
-- Error handler.
deferred
end
feature -- Access
feature -- Change
save_contact_message (m: CONTACT_MESSAGE)
deferred
end
end
@@ -0,0 +1,39 @@
note
description: "[
Objects that ...
]"
author: "$Author: jfiat $"
date: "$Date: 2015-05-22 23:00:09 +0200 (ven., 22 mai 2015) $"
revision: "$Revision: 97349 $"
class
CONTACT_STORAGE_NULL
inherit
CONTACT_STORAGE_I
create
make
feature {NONE} -- Initialization
make
-- Initialize `Current'.
do
create error_handler.make
end
feature -- Error Handling
error_handler: ERROR_HANDLER
-- Error handler.
feature -- Access
feature -- Change
save_contact_message (m: CONTACT_MESSAGE)
do
end
end
@@ -0,0 +1,49 @@
note
description: "[
Contact message storage based on SQL statements.
]"
date: "$Date: 2015-02-13 13:08:13 +0100 (ven., 13 févr. 2015) $"
revision: "$Revision: 96616 $"
class
CONTACT_STORAGE_SQL
inherit
CMS_PROXY_STORAGE_SQL
CONTACT_STORAGE_I
CMS_STORAGE_SQL_I
REFACTORING_HELPER
create
make
feature -- Access
feature -- Change
save_contact_message (m: CONTACT_MESSAGE)
local
l_parameters: STRING_TABLE [detachable ANY]
now: DATE_TIME
do
create now.make_now_utc
error_handler.reset
write_information_log (generator + ".save_contact_message")
create l_parameters.make (9)
l_parameters.put (m, "message")
l_parameters.put (now, "changed")
sql_begin_transaction
sql_modify (sql_insert_contact_message, l_parameters)
sql_commit_transaction
end
feature {NONE} -- Queries
sql_insert_contact_message: STRING = "INSERT INTO contact_messages (name, email, date, message) VALUES (:name, :email, :date, :message);"
-- SQL Insert to add a new contact message.
end
+6 -1
View File
@@ -127,8 +127,13 @@ feature {CMS_API} -- Module management
-- Schema -- Schema
if attached a_api.storage.as_sql_storage as l_sql_storage then if attached a_api.storage.as_sql_storage as l_sql_storage then
l_sql_storage.sql_execute_file_script (a_api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended (name).appended_with_extension ("sql")), Void) l_sql_storage.sql_execute_file_script (a_api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended (name).appended_with_extension ("sql")), Void)
if l_sql_storage.has_error then
a_api.logger.put_error ("Could not initialize database for module [" + name + "]", generating_type)
else
Precursor {CMS_MODULE} (a_api)
end
end end
Precursor {CMS_MODULE}(a_api)
end end
feature {CMS_API} -- Access: API feature {CMS_API} -- Access: API
+2 -2
View File
@@ -278,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.")
-5
View File
@@ -3,22 +3,17 @@ ul.cms-nodes {
list-style-type: none; list-style-type: none;
padding: 3px 3px 3px 3px; padding: 3px 3px 3px 3px;
border: solid 1px #ccc; border: solid 1px #ccc;
li{ li{
border-top: dotted 1px #ccc; border-top: dotted 1px #ccc;
&:first-child { &:first-child {
border-top: none; border-top: none;
} }
} }
li.cms_type_page a::before { li.cms_type_page a::before {
content: "[page] "; content: "[page] ";
} }
li.cms_type_blog a::before { li.cms_type_blog a::before {
content: "[blog] "; content: "[blog] ";
} }
} }
+22 -5
View File
@@ -1,7 +1,7 @@
note note
description: "[ description: "[
API to manage CMS User OAuth authentication. API to manage CMS User OAuth authentication.
]" ]"
date: "$Date$" date: "$Date$"
revision: "$Revision$" revision: "$Revision$"
@@ -20,19 +20,36 @@ feature {NONE} -- Initialization
make_with_storage (a_api: CMS_API; a_oauth_storage: CMS_OAUTH_20_STORAGE_I) make_with_storage (a_api: CMS_API; a_oauth_storage: CMS_OAUTH_20_STORAGE_I)
-- Create an object with api `a_api' and storage `a_oauth_storage'. -- Create an object with api `a_api' and storage `a_oauth_storage'.
local
s: detachable READABLE_STRING_8
do do
oauth_20_storage := a_oauth_storage oauth_20_storage := a_oauth_storage
make (a_api) make (a_api)
-- Initialize session related settings.
s := a_api.setup.string_8_item ("auth.oauth.token")
if s = Void then
s := a_api.setup.site_id + default_session_token_suffix
end
create session_token.make_from_string (s)
ensure ensure
oauht_20_storage_set: oauth_20_storage = a_oauth_storage oauth_20_storage_set: oauth_20_storage = a_oauth_storage
end end
feature {CMS_MODULE} -- Access: User oauth storage. feature {CMS_MODULE} -- Access: Oauth storage.
oauth_20_storage: CMS_OAUTH_20_STORAGE_I oauth_20_storage: CMS_OAUTH_20_STORAGE_I
-- storage interface. -- storage interface.
feature -- Access: User Oauth20 feature -- Access: tokens
default_session_token_suffix: STRING = "_OAUTH_TOKEN_"
-- Default value for `session_auth_token'.
session_token: IMMUTABLE_STRING_8
-- Name of Cookie used to keep the session info.
feature -- Access: Oauth20
user_oauth2_by_id (a_uid: like {CMS_USER}.id; a_consumer: READABLE_STRING_GENERAL): detachable CMS_USER user_oauth2_by_id (a_uid: like {CMS_USER}.id; a_consumer: READABLE_STRING_GENERAL): detachable CMS_USER
-- Retrieve a user by id `a_uid' for the consumer `a_consumer', if any. -- Retrieve a user by id `a_uid' for the consumer `a_consumer', if any.
-21
View File
@@ -1,21 +0,0 @@
note
description: "Summary description for {CMS_OAUTH_20_CONSTANTS}."
date: "$Date$"
revision: "$Revision$"
class
CMS_OAUTH_20_CONSTANTS
feature -- Access
oauth_session: STRING = "EWF_ROC_OAUTH_TOKEN_"
-- Name of Cookie used to keep the session info.
-- FIXME: make this configurable.
oauth_callback: STRING = "callback"
-- Callback parameter.
oauth_code: STRING = "code"
-- Code query parameter.
end
+102 -85
View File
@@ -1,5 +1,7 @@
note note
description: "Generic OAuth Module supporting authentication using different providers." description: "[
Generic OAuth Module supporting authentication using different providers.
]"
date: "$Date: 2015-05-20 06:50:50 -0300 (mi. 20 de may. de 2015) $" date: "$Date: 2015-05-20 06:50:50 -0300 (mi. 20 de may. de 2015) $"
revision: "$Revision: 97328 $" revision: "$Revision: 97328 $"
@@ -9,16 +11,15 @@ class
inherit inherit
CMS_MODULE CMS_MODULE
rename rename
module_api as user_oauth_api module_api as oauth20_api
redefine redefine
filters, filters,
setup_hooks, setup_hooks,
initialize, initialize,
install, install,
user_oauth_api oauth20_api
end end
CMS_HOOK_BLOCK CMS_HOOK_BLOCK
CMS_HOOK_AUTO_REGISTER CMS_HOOK_AUTO_REGISTER
@@ -38,7 +39,6 @@ inherit
CMS_REQUEST_UTIL CMS_REQUEST_UTIL
create create
make make
@@ -66,24 +66,24 @@ feature {CMS_API} -- Module Initialization
initialize (a_api: CMS_API) initialize (a_api: CMS_API)
-- <Precursor> -- <Precursor>
local local
l_user_auth_api: like user_oauth_api l_oauth20_api: like oauth20_api
l_user_auth_storage: CMS_OAUTH_20_STORAGE_I l_auth_storage: CMS_OAUTH_20_STORAGE_I
do do
Precursor (a_api) Precursor (a_api)
-- Storage initialization -- Storage initialization
if attached a_api.storage.as_sql_storage as l_storage_sql then if attached a_api.storage.as_sql_storage as l_storage_sql then
create {CMS_OAUTH_20_STORAGE_SQL} l_user_auth_storage.make (l_storage_sql) create {CMS_OAUTH_20_STORAGE_SQL} l_auth_storage.make (l_storage_sql)
else else
-- FIXME: in case of NULL storage, should Current be disabled? -- FIXME: in case of NULL storage, should Current be disabled?
create {CMS_OAUTH_20_STORAGE_NULL} l_user_auth_storage create {CMS_OAUTH_20_STORAGE_NULL} l_auth_storage
end end
-- API initialization -- API initialization
create l_user_auth_api.make_with_storage (a_api, l_user_auth_storage) create l_oauth20_api.make_with_storage (a_api, l_auth_storage)
user_oauth_api := l_user_auth_api oauth20_api := l_oauth20_api
ensure then ensure then
user_oauth_api_set: user_oauth_api /= Void user_oauth_api_set: oauth20_api /= Void
end end
feature {CMS_API} -- Module management feature {CMS_API} -- Module management
@@ -94,52 +94,56 @@ feature {CMS_API} -- Module management
do do
-- Schema -- Schema
if attached api.storage.as_sql_storage as l_sql_storage then if attached api.storage.as_sql_storage as l_sql_storage then
if not l_sql_storage.sql_table_exists ("oauth2_consumers") then
--| Schema --| Schema
l_sql_storage.sql_execute_file_script (api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended ("oauth2_consumers.sql")), Void) l_sql_storage.sql_execute_file_script (api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended ("oauth2_consumers.sql")), Void)
if l_sql_storage.has_error then if l_sql_storage.has_error then
api.logger.put_error ("Could not initialize database for oauth_20 module", generating_type) api.logger.put_error ("Could not initialize database for module [" + name + "]", generating_type)
end else
-- TODO workaround. -- TODO workaround.
l_sql_storage.sql_execute_file_script (api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended ("oauth2_consumers_initialize.sql")), Void) l_sql_storage.sql_execute_file_script (api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended ("oauth2_consumers_initialize.sql")), Void)
end if l_sql_storage.has_error then
api.logger.put_error ("Could not initialize oauth2_consumers for module [" + name + "]", generating_type)
else
-- TODO workaround, until we have an admin module
l_sql_storage.sql_query ("SELECT name FROM oauth2_consumers;", Void)
if l_sql_storage.has_error then
api.logger.put_error ("Could not initialize database for different consumers", generating_type)
else
from
l_sql_storage.sql_start
create {ARRAYED_LIST [STRING]} l_consumers.make (2)
until
l_sql_storage.sql_after
loop
if attached l_sql_storage.sql_read_string (1) as l_name then
l_consumers.force ("oauth2_" + l_name)
end
l_sql_storage.sql_forth
end
l_sql_storage.sql_finalize
-- TODO workaround, until we have an admin module across l_consumers as ic loop
l_sql_storage.sql_query ("SELECT name FROM oauth2_consumers;", Void) if not l_sql_storage.sql_table_exists (ic.item) then
if l_sql_storage.has_error then if attached l_sql_storage.sql_script_content (api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended ("oauth2_table.sql.tpl"))) as sql then
api.logger.put_error ("Could not initialize database for differnent consumers", generating_type) -- FIXME: shouldn't we use a unique table for all oauth providers? or as it is .. one table per oauth provider?
else sql.replace_substring_all ("$table_name", ic.item)
from l_sql_storage.sql_execute_script (sql, Void)
l_sql_storage.sql_start end
create {ARRAYED_LIST [STRING]} l_consumers.make (2) end
until
l_sql_storage.sql_after
loop
if attached l_sql_storage.sql_read_string (1) as l_name then
l_consumers.force ("oauth2_" + l_name)
end
l_sql_storage.sql_forth
end
l_sql_storage.sql_finalize
across l_consumers as ic loop
if not l_sql_storage.sql_table_exists (ic.item) then
if attached l_sql_storage.sql_script_content (api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended ("oauth2_table.sql.tpl"))) as sql then
-- FIXME: shouldn't we use a unique table for all oauth providers? or as it is .. one table per oauth provider?
sql.replace_substring_all ("$table_name", ic.item)
l_sql_storage.sql_execute_script (sql, Void)
end end
end end
l_sql_storage.sql_finalize
Precursor {CMS_MODULE}(api) -- Marked as installed.
end end
end end
l_sql_storage.sql_finalize
Precursor {CMS_MODULE}(api)
end end
end end
feature {CMS_API} -- Access: API feature {CMS_API} -- Access: API
user_oauth_api: detachable CMS_OAUTH_20_API oauth20_api: detachable CMS_OAUTH_20_API
-- <Precursor> -- <Precursor>
feature -- Filters feature -- Filters
@@ -148,8 +152,8 @@ feature -- Filters
-- Possibly list of Filter's module. -- Possibly list of Filter's module.
do do
create {ARRAYED_LIST [WSF_FILTER]} Result.make (1) create {ARRAYED_LIST [WSF_FILTER]} Result.make (1)
if attached user_oauth_api as l_user_oauth_api then if attached oauth20_api as l_oauth_api then
Result.extend (create {CMS_OAUTH_20_FILTER}.make (a_api, l_user_oauth_api)) Result.extend (create {CMS_OAUTH_20_FILTER}.make (a_api, l_oauth_api))
end end
end end
@@ -173,20 +177,34 @@ feature -- Router
setup_router (a_router: WSF_ROUTER; a_api: CMS_API) setup_router (a_router: WSF_ROUTER; a_api: CMS_API)
-- <Precursor> -- <Precursor>
do do
if attached user_oauth_api as l_user_oauth_api then if attached oauth20_api as l_oauth_api then
configure_web (a_api, l_user_oauth_api, a_router) a_router.handle ("/account/roc-oauth-login",
create {WSF_URI_AGENT_HANDLER}.make (agent handle_login (a_api, ?, ?)), a_router.methods_head_get)
a_router.handle ("/account/roc-oauth-logout",
create {WSF_URI_AGENT_HANDLER}.make (agent handle_logout (a_api, l_oauth_api, ?, ?)),
a_router.methods_get_post)
a_router.handle ("/account/login-with-oauth/{" + oauth_callback_path_parameter + "}",
create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_login_with_oauth (a_api, l_oauth_api, ?, ?)),
a_router.methods_get_post)
a_router.handle ("/account/oauth-callback/{" + oauth_callback_path_parameter + "}",
create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_callback_oauth (a_api, l_oauth_api, ?, ?)),
a_router.methods_get_post)
a_router.handle ("/account/oauth-associate",
create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_associate (a_api, l_oauth_api, ?, ?)),
a_router.methods_post)
a_router.handle ("/account/oauth-un-associate",
create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_un_associate (a_api, l_oauth_api, ?, ?)),
a_router.methods_post)
end end
end end
configure_web (a_api: CMS_API; a_user_oauth_api: CMS_OAUTH_20_API; a_router: WSF_ROUTER) oauth_callback_path_parameter: STRING = "callback"
do -- Callback path parameter.
a_router.handle ("/account/roc-oauth-login", create {WSF_URI_AGENT_HANDLER}.make (agent handle_login (a_api, ?, ?)), a_router.methods_head_get)
a_router.handle ("/account/roc-oauth-logout", create {WSF_URI_AGENT_HANDLER}.make (agent handle_logout (a_api, ?, ?)), a_router.methods_get_post) oauth_code_query_parameter: STRING = "code"
a_router.handle ("/account/login-with-oauth/{callback}", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_login_with_oauth (a_api,a_user_oauth_api, ?, ?)), a_router.methods_get_post) -- Code query parameter, specific to OAuth protocol.
a_router.handle ("/account/oauth-callback/{callback}", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_callback_oauth (a_api, a_user_oauth_api, ?, ?)), a_router.methods_get_post) -- FIXME: should we have a way to change this value?
a_router.handle ("/account/oauth-associate", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_associate (a_api, a_user_oauth_api, ?, ?)), a_router.methods_post) -- : if a OAuth provider is not using "code" query name.
a_router.handle ("/account/oauth-un-associate", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_un_associate (a_api, a_user_oauth_api, ?, ?)), a_router.methods_post)
end
feature -- Hooks configuration feature -- Hooks configuration
@@ -205,7 +223,8 @@ feature -- Hooks
do do
if if
attached a_response.user as u and then attached a_response.user as u and then
attached {WSF_STRING} a_response.request.cookie ({CMS_OAUTH_20_CONSTANTS}.oauth_session) attached oauth20_api as l_oauth20_api and then
attached a_response.request.cookie (l_oauth20_api.session_token)
then then
a_value.force ("account/roc-oauth-logout", "auth_login_strategy") a_value.force ("account/roc-oauth-logout", "auth_login_strategy")
end end
@@ -220,7 +239,8 @@ feature -- Hooks
do do
if if
attached a_response.user as u and then attached a_response.user as u and then
attached {WSF_STRING} a_response.request.cookie ({CMS_OAUTH_20_CONSTANTS}.oauth_session) as l_roc_auth_session_token attached oauth20_api as l_oauth20_api and then
attached {WSF_STRING} a_response.request.cookie (l_oauth20_api.session_token) as l_roc_auth_session_token
then then
across across
a_menu_system.primary_menu.items as ic a_menu_system.primary_menu.items as ic
@@ -297,17 +317,17 @@ feature -- Hooks
r.execute r.execute
end end
handle_logout (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE) handle_logout (api: CMS_API; a_oauth20_api: CMS_OAUTH_20_API; req: WSF_REQUEST; res: WSF_RESPONSE)
local local
r: CMS_RESPONSE r: CMS_RESPONSE
l_cookie: WSF_COOKIE l_cookie: WSF_COOKIE
do do
if if
attached {WSF_STRING} req.cookie ({CMS_OAUTH_20_CONSTANTS}.oauth_session) as l_cookie_token and then attached {CMS_USER} current_user (req) as l_user and then
attached {CMS_USER} current_user (req) as l_user attached {WSF_STRING} req.cookie (a_oauth20_api.session_token) as l_cookie_token
then then
-- Logout OAuth -- Logout OAuth
create l_cookie.make ({CMS_OAUTH_20_CONSTANTS}.oauth_session, l_cookie_token.value) create l_cookie.make (a_oauth20_api.session_token, l_cookie_token.value)
l_cookie.set_path ("/") l_cookie.set_path ("/")
l_cookie.set_max_age (-1) l_cookie.set_max_age (-1)
res.add_cookie (l_cookie) res.add_cookie (l_cookie)
@@ -329,7 +349,7 @@ feature {NONE} -- Associate
l_associated: LIST [STRING] l_associated: LIST [STRING]
l_not_associated: LIST [STRING] l_not_associated: LIST [STRING]
do do
if attached user_oauth_api as l_oauth_api then if attached oauth20_api as l_oauth_api then
create {ARRAYED_LIST [STRING]} l_associated.make (1) create {ARRAYED_LIST [STRING]} l_associated.make (1)
create {ARRAYED_LIST [STRING]} l_not_associated.make (1) create {ARRAYED_LIST [STRING]} l_not_associated.make (1)
across l_oauth_api.oauth2_consumers as ic loop across l_oauth_api.oauth2_consumers as ic loop
@@ -379,7 +399,7 @@ feature {NONE} -- Block views
l_tpl_block.set_value (ic.item, ic.key) l_tpl_block.set_value (ic.item, ic.key)
end end
if if
attached user_oauth_api as l_auth_api and then attached oauth20_api as l_auth_api and then
attached l_auth_api.oauth2_consumers as l_list attached l_auth_api.oauth2_consumers as l_list
then then
l_tpl_block.set_value (l_list, "oauth_consumers") l_tpl_block.set_value (l_list, "oauth_consumers")
@@ -402,7 +422,7 @@ feature -- OAuth2 Login with Provider
l_oauth: CMS_OAUTH_20_WORKFLOW l_oauth: CMS_OAUTH_20_WORKFLOW
do do
if if
attached {WSF_STRING} req.path_parameter ({CMS_OAUTH_20_CONSTANTS}.oauth_callback) as p_consumer and then attached {WSF_STRING} req.path_parameter (oauth_callback_path_parameter) as p_consumer and then
attached {CMS_OAUTH_20_CONSUMER} a_oauth_api.oauth_consumer_by_name (p_consumer.value) as l_consumer attached {CMS_OAUTH_20_CONSUMER} a_oauth_api.oauth_consumer_by_name (p_consumer.value) as l_consumer
then then
create l_oauth.make (req.server_url, l_consumer) create l_oauth.make (req.server_url, l_consumer)
@@ -422,7 +442,7 @@ feature -- OAuth2 Login with Provider
end end
end end
handle_callback_oauth (api: CMS_API; a_user_oauth_api: CMS_OAUTH_20_API; req: WSF_REQUEST; res: WSF_RESPONSE) handle_callback_oauth (api: CMS_API; a_oauth_api: CMS_OAUTH_20_API; req: WSF_REQUEST; res: WSF_RESPONSE)
local local
r: CMS_RESPONSE r: CMS_RESPONSE
l_auth: CMS_OAUTH_20_WORKFLOW l_auth: CMS_OAUTH_20_WORKFLOW
@@ -430,11 +450,11 @@ 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 (oauth_callback_path_parameter) as l_callback and then
attached {CMS_OAUTH_20_CONSUMER} a_user_oauth_api.oauth_consumer_by_callback (l_callback.value) as l_consumer and then attached {CMS_OAUTH_20_CONSUMER} a_oauth_api.oauth_consumer_by_callback (l_callback.value) as l_consumer and then
attached {WSF_STRING} req.query_parameter ({CMS_OAUTH_20_CONSTANTS}.oauth_code) as l_code attached {WSF_STRING} req.query_parameter (oauth_code_query_parameter) as l_code
then then
create l_auth.make (req.server_url, l_consumer) create l_auth.make (req.server_url, l_consumer)
l_auth.sign_request (l_code.value) l_auth.sign_request (l_code.value)
@@ -452,20 +472,20 @@ feature -- OAuth2 Login with Provider
then then
if attached l_user_api.user_by_email (l_email) as p_user then if attached l_user_api.user_by_email (l_email) as p_user then
-- User with email exist -- User with email exist
if attached a_user_oauth_api.user_oauth2_by_id (p_user.id, l_consumer.name) then if attached a_oauth_api.user_oauth2_by_id (p_user.id, l_consumer.name) then
-- Update oauth entry -- Update oauth entry
a_user_oauth_api.update_user_oauth2 (l_access_token.token, l_user_profile, p_user, l_consumer.name ) a_oauth_api.update_user_oauth2 (l_access_token.token, l_user_profile, p_user, l_consumer.name )
else else
-- create a oauth entry -- create a oauth entry
a_user_oauth_api.new_user_oauth2 (l_access_token.token, l_user_profile, p_user, l_consumer.name ) a_oauth_api.new_user_oauth2 (l_access_token.token, l_user_profile, p_user, l_consumer.name )
end end
create l_cookie.make ({CMS_OAUTH_20_CONSTANTS}.oauth_session, l_access_token.token) create l_cookie.make (a_oauth_api.session_token, l_access_token.token)
l_cookie.set_max_age (l_access_token.expires_in) l_cookie.set_max_age (l_access_token.expires_in)
l_cookie.set_path ("/") l_cookie.set_path ("/")
res.add_cookie (l_cookie) res.add_cookie (l_cookie)
elseif attached a_user_oauth_api.user_oauth2_by_email (l_email, l_consumer.name) as p_user then elseif attached a_oauth_api.user_oauth2_by_email (l_email, l_consumer.name) as p_user then
a_user_oauth_api.update_user_oauth2 (l_access_token.token, l_user_profile, p_user, l_consumer.name ) a_oauth_api.update_user_oauth2 (l_access_token.token, l_user_profile, p_user, l_consumer.name )
create l_cookie.make ({CMS_OAUTH_20_CONSTANTS}.oauth_session, l_access_token.token) create l_cookie.make (a_oauth_api.session_token, l_access_token.token)
l_cookie.set_max_age (l_access_token.expires_in) l_cookie.set_max_age (l_access_token.expires_in)
l_cookie.set_path ("/") l_cookie.set_path ("/")
res.add_cookie (l_cookie) res.add_cookie (l_cookie)
@@ -482,8 +502,8 @@ feature -- OAuth2 Login with Provider
l_user_api.new_user (l_user) l_user_api.new_user (l_user)
-- Add oauth entry -- Add oauth entry
a_user_oauth_api.new_user_oauth2 (l_access_token.token, l_user_profile, l_user, l_consumer.name ) a_oauth_api.new_user_oauth2 (l_access_token.token, l_user_profile, l_user, l_consumer.name )
create l_cookie.make ({CMS_OAUTH_20_CONSTANTS}.oauth_session, l_access_token.token) create l_cookie.make (a_oauth_api.session_token, l_access_token.token)
l_cookie.set_max_age (l_access_token.expires_in) l_cookie.set_max_age (l_access_token.expires_in)
l_cookie.set_path ("/") l_cookie.set_path ("/")
res.add_cookie (l_cookie) res.add_cookie (l_cookie)
@@ -493,15 +513,13 @@ 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, "", req.absolute_script_url ("")) 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)
r.execute r.execute
end end
end end
end end
handle_associate (api: CMS_API; a_oauth_api: CMS_OAUTH_20_API; req: WSF_REQUEST; res: WSF_RESPONSE) handle_associate (api: CMS_API; a_oauth_api: CMS_OAUTH_20_API; req: WSF_REQUEST; res: WSF_RESPONSE)
@@ -518,14 +536,13 @@ feature -- OAuth2 Login with Provider
then then
l_user.set_email (l_email.value) l_user.set_email (l_email.value)
a_oauth_api.new_user_oauth2 ("none", "none", l_user, l_consumer.value ) a_oauth_api.new_user_oauth2 ("none", "none", l_user, l_consumer.value )
-- TODO send email? -- TODO send email?
end end
end end
r.set_redirection (req.absolute_script_url ("/account")) r.set_redirection (req.absolute_script_url ("/account"))
r.execute r.execute
end end
handle_un_associate (api: CMS_API; a_oauth_api: CMS_OAUTH_20_API; req: WSF_REQUEST; res: WSF_RESPONSE) handle_un_associate (api: CMS_API; a_oauth_api: CMS_OAUTH_20_API; req: WSF_REQUEST; res: WSF_RESPONSE)
local local
r: CMS_RESPONSE r: CMS_RESPONSE
+7 -5
View File
@@ -1,6 +1,7 @@
note note
description: "[ description: "[
Extracts an OAuth2 token from the incoming request (cookie) and uses it to populate the user (or cms user context) Extracts an OAuth2 token from the incoming request (cookie) and
uses it to populate the user (or cms user context).
]" ]"
date: "$Date$" date: "$Date$"
revision: "$Revision$" revision: "$Revision$"
@@ -10,6 +11,7 @@ class
inherit inherit
WSF_URI_TEMPLATE_HANDLER WSF_URI_TEMPLATE_HANDLER
CMS_HANDLER CMS_HANDLER
rename rename
make as make_handler make as make_handler
@@ -25,10 +27,10 @@ feature {NONE} -- Initialization
make (a_api: CMS_API; a_user_oauth_api: CMS_OAUTH_20_API) make (a_api: CMS_API; a_user_oauth_api: CMS_OAUTH_20_API)
do do
make_handler (a_api) make_handler (a_api)
user_oauth_api := a_user_oauth_api oauth_api := a_user_oauth_api
end end
user_oauth_api: CMS_OAUTH_20_API oauth_api: CMS_OAUTH_20_API
feature -- Basic operations feature -- Basic operations
@@ -38,9 +40,9 @@ feature -- Basic operations
api.logger.put_debug (generator + ".execute ", Void) api.logger.put_debug (generator + ".execute ", Void)
-- A valid user -- A valid user
if if
attached {WSF_STRING} req.cookie ({CMS_OAUTH_20_CONSTANTS}.oauth_session) as l_roc_auth_session_token attached {WSF_STRING} req.cookie (oauth_api.session_token) as l_roc_auth_session_token
then then
if attached user_oauth_api.user_oauth2_without_consumer_by_token (l_roc_auth_session_token.value) as l_user then if attached oauth_api.user_oauth2_without_consumer_by_token (l_roc_auth_session_token.value) as l_user then
set_current_user (req, l_user) set_current_user (req, l_user)
else else
api.logger.put_error (generator + ".execute login_valid failed for: " + l_roc_auth_session_token.value , Void) api.logger.put_error (generator + ".execute login_valid failed for: " + l_roc_auth_session_token.value , Void)
+27
View File
@@ -7,6 +7,7 @@ note
class class
CMS_OPENID_API CMS_OPENID_API
inherit inherit
CMS_MODULE_API CMS_MODULE_API
@@ -19,9 +20,25 @@ feature {NONE} -- Initialization
make_with_storage (a_api: CMS_API; a_openid_storage: CMS_OPENID_STORAGE_I) make_with_storage (a_api: CMS_API; a_openid_storage: CMS_OPENID_STORAGE_I)
-- Create an object with api `a_api' and storage `a_openid_storage'. -- Create an object with api `a_api' and storage `a_openid_storage'.
local
s: detachable READABLE_STRING_8
do do
openid_storage := a_openid_storage openid_storage := a_openid_storage
make (a_api) make (a_api)
-- Initialize openid related settings.
s := a_api.setup.string_8_item ("auth.openid.token")
if s = Void then
s := a_api.setup.site_id + default_session_token_suffix
end
create session_token.make_from_string (s)
s := a_api.setup.string_8_item ("auth.openid.max_age")
if s /= Void and then s.is_integer then
session_max_age := s.to_integer
else
session_max_age := 3600 --| one hour: *60(min) *60(sec)
end
ensure ensure
openid_storage_set: openid_storage = a_openid_storage openid_storage_set: openid_storage = a_openid_storage
end end
@@ -31,6 +48,16 @@ feature {CMS_MODULE} -- Access: User openid storage.
openid_storage: CMS_OPENID_STORAGE_I openid_storage: CMS_OPENID_STORAGE_I
-- storage interface. -- storage interface.
feature -- Access: token
default_session_token_suffix: STRING = "_OPENID_TOKEN_"
session_token: IMMUTABLE_STRING_8
-- Name of Cookie used to keep the session info.
session_max_age: INTEGER
-- Max age.
feature -- Access: User Openid feature -- Access: User Openid
user_openid_by_userid_identity (a_uid: like {CMS_USER}.id; a_identity: READABLE_STRING_GENERAL): detachable CMS_USER user_openid_by_userid_identity (a_uid: like {CMS_USER}.id; a_identity: READABLE_STRING_GENERAL): detachable CMS_USER
-16
View File
@@ -1,16 +0,0 @@
note
description: "Summary description for {CMS_OPENID_CONSTANTS}."
date: "$Date$"
revision: "$Revision$"
class
CMS_OPENID_CONSTANTS
feature -- Access
openid_session: STRING = "EWF_ROC_OPENID_TOKEN_"
-- Name of Cookie used to keep the session info.
-- FIXME: make this configurable.
consumer: STRING = "consumer"
end
+62 -80
View File
@@ -11,13 +11,13 @@ class
inherit inherit
CMS_MODULE CMS_MODULE
rename rename
module_api as user_openid_api module_api as openid_api
redefine redefine
filters, filters,
setup_hooks, setup_hooks,
initialize, initialize,
install, install,
user_openid_api openid_api
end end
@@ -68,7 +68,7 @@ feature {CMS_API} -- Module Initialization
initialize (a_api: CMS_API) initialize (a_api: CMS_API)
-- <Precursor> -- <Precursor>
local local
l_openid_api: like user_openid_api l_openid_api: like openid_api
l_openid_storage: CMS_OPENID_STORAGE_I l_openid_storage: CMS_OPENID_STORAGE_I
do do
Precursor (a_api) Precursor (a_api)
@@ -83,9 +83,9 @@ feature {CMS_API} -- Module Initialization
-- API initialization -- API initialization
create l_openid_api.make_with_storage (a_api, l_openid_storage) create l_openid_api.make_with_storage (a_api, l_openid_storage)
user_openid_api := l_openid_api openid_api := l_openid_api
ensure then ensure then
user_opend_api_set: user_openid_api /= Void user_opend_api_set: openid_api /= Void
end end
feature {CMS_API} -- Module management feature {CMS_API} -- Module management
@@ -94,30 +94,33 @@ feature {CMS_API} -- Module management
do do
-- Schema -- Schema
if attached api.storage.as_sql_storage as l_sql_storage then if attached api.storage.as_sql_storage as l_sql_storage then
if not l_sql_storage.sql_table_exists ("openid_consumers") then
--| Schema --| Schema
l_sql_storage.sql_execute_file_script (api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended ("openid_consumers.sql")), Void) l_sql_storage.sql_execute_file_script (api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended ("openid_consumers.sql")), Void)
if l_sql_storage.has_error then if l_sql_storage.has_error then
api.logger.put_error ("Could not initialize database for openid module", generating_type) api.logger.put_error ("Could not initialize database for module [" + name + "]", generating_type)
end else
-- TODO workaround. -- TODO workaround.
l_sql_storage.sql_execute_file_script (api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended ("openid_consumers_initialize.sql")), Void) l_sql_storage.sql_execute_file_script (api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended ("openid_consumers_initialize.sql")), Void)
end
-- TODO workaround, until we have an admin module -- TODO workaround, until we have an admin module
if l_sql_storage.has_error then if l_sql_storage.has_error then
api.logger.put_error ("Could not initialize database for different consumers", generating_type) api.logger.put_error ("Could not initialize openid consumer table for module [" + name + "]", generating_type)
else else
l_sql_storage.sql_execute_file_script (api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended ("openid_items.sql")),Void) l_sql_storage.sql_execute_file_script (api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended ("openid_items.sql")),Void)
if l_sql_storage.has_error then
api.logger.put_error ("Could not initialize openid items for module [" + name + "]", generating_type)
else
Precursor {CMS_MODULE}(api) -- Mark it installed.
end
end
end end
Precursor {CMS_MODULE}(api)
end end
end end
feature {CMS_API} -- Access: API feature {CMS_API} -- Access: API
user_openid_api: detachable CMS_OPENID_API openid_api: detachable CMS_OPENID_API
-- <Precursor> -- <Precursor>
feature -- Filters feature -- Filters
@@ -125,9 +128,9 @@ feature -- Filters
filters (a_api: CMS_API): detachable LIST [WSF_FILTER] filters (a_api: CMS_API): detachable LIST [WSF_FILTER]
-- Possibly list of Filter's module. -- Possibly list of Filter's module.
do do
if attached user_openid_api as l_user_openid_api then if attached openid_api as l_openid_api then
create {ARRAYED_LIST [WSF_FILTER]} Result.make (1) create {ARRAYED_LIST [WSF_FILTER]} Result.make (1)
Result.extend (create {CMS_OPENID_FILTER}.make (a_api, l_user_openid_api)) Result.extend (create {CMS_OPENID_FILTER}.make (a_api, l_openid_api))
end end
end end
@@ -151,18 +154,24 @@ feature -- Router
setup_router (a_router: WSF_ROUTER; a_api: CMS_API) setup_router (a_router: WSF_ROUTER; a_api: CMS_API)
-- <Precursor> -- <Precursor>
do do
if attached user_openid_api as l_user_openid_api then if attached openid_api as l_openid_api then
configure_web (a_api, l_user_openid_api, a_router) a_router.handle ("/account/roc-openid-login",
create {WSF_URI_AGENT_HANDLER}.make (agent handle_openid_login (a_api, ?, ?)),
a_router.methods_get_post)
a_router.handle ("/account/roc-openid-logout",
create {WSF_URI_AGENT_HANDLER}.make (agent handle_logout (a_api, l_openid_api, ?, ?)),
a_router.methods_get_post)
a_router.handle ("/account/login-with-openid/{" + openid_consumer_path_parameter + "}",
create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_login_with_openid (a_api, l_openid_api, ?, ?)),
a_router.methods_get_post)
a_router.handle ("/account/openid-callback",
create {WSF_URI_AGENT_HANDLER}.make (agent handle_callback_openid (a_api, l_openid_api, ?, ?)),
a_router.methods_get_post)
end end
end end
configure_web (a_api: CMS_API; a_user_openid_api: CMS_OPENID_API; a_router: WSF_ROUTER) openid_consumer_path_parameter: STRING = "consumer"
do -- Consumer path parameter name.
a_router.handle ("/account/roc-openid-login", create {WSF_URI_AGENT_HANDLER}.make (agent handle_openid_login (a_api, ?, ?)), a_router.methods_get_post)
a_router.handle ("/account/roc-openid-logout", create {WSF_URI_AGENT_HANDLER}.make (agent handle_logout (a_api, ?, ?)), a_router.methods_get_post)
a_router.handle ("/account/login-with-openid/{consumer}", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_login_with_openid (a_api,a_user_openid_api, ?, ?)), a_router.methods_get_post)
a_router.handle ("/account/openid-callback", create {WSF_URI_AGENT_HANDLER}.make (agent handle_callback_openid (a_api, a_user_openid_api, ?, ?)), a_router.methods_get_post)
end
feature -- Hooks configuration feature -- Hooks configuration
@@ -181,7 +190,8 @@ feature -- Hooks
do do
if if
attached a_response.user as u and then attached a_response.user as u and then
attached {WSF_STRING} a_response.request.cookie ({CMS_OPENID_CONSTANTS}.openid_session) attached openid_api as l_openid_api and then
attached {WSF_STRING} a_response.request.cookie (l_openid_api.session_token)
then then
a_value.force ("account/roc-openid-logout", "auth_login_strategy") a_value.force ("account/roc-openid-logout", "auth_login_strategy")
end end
@@ -196,7 +206,8 @@ feature -- Hooks
do do
if if
attached a_response.user as u and then attached a_response.user as u and then
attached {WSF_STRING} a_response.request.cookie ({CMS_OPENID_CONSTANTS}.openid_session) as l_roc_auth_session_token attached openid_api as l_openid_api and then
attached {WSF_STRING} a_response.request.cookie (l_openid_api.session_token) as l_roc_auth_session_token
then then
across across
a_menu_system.primary_menu.items as ic a_menu_system.primary_menu.items as ic
@@ -280,17 +291,17 @@ feature -- Hooks
end end
end end
handle_logout (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE) handle_logout (api: CMS_API; a_openid_api: CMS_OPENID_API; req: WSF_REQUEST; res: WSF_RESPONSE)
local local
r: CMS_RESPONSE r: CMS_RESPONSE
l_cookie: WSF_COOKIE l_cookie: WSF_COOKIE
do do
if if
attached {WSF_STRING} req.cookie ({CMS_OPENID_CONSTANTS}.openid_session) as l_cookie_token and then attached {CMS_USER} current_user (req) as l_user and then
attached {CMS_USER} current_user (req) as l_user attached {WSF_STRING} req.cookie (a_openid_api.session_token) as l_cookie_token
then then
-- Logout OAuth -- Logout OAuth
create l_cookie.make ({CMS_OPENID_CONSTANTS}.openid_session, l_cookie_token.value) create l_cookie.make (a_openid_api.session_token, l_cookie_token.value)
l_cookie.set_path ("/") l_cookie.set_path ("/")
l_cookie.set_max_age (-1) l_cookie.set_max_age (-1)
res.add_cookie (l_cookie) res.add_cookie (l_cookie)
@@ -339,7 +350,7 @@ feature {NONE} -- Block views
l_tpl_block.set_value (ic.item, ic.key) l_tpl_block.set_value (ic.item, ic.key)
end end
if if
attached user_openid_api as l_openid_api and then attached openid_api as l_openid_api and then
attached l_openid_api.openid_consumers as l_list attached l_openid_api.openid_consumers as l_list
then then
l_tpl_block.set_value (l_list, "openid_consumers") l_tpl_block.set_value (l_list, "openid_consumers")
@@ -356,14 +367,16 @@ feature {NONE} -- Block views
feature -- Openid Login feature -- Openid Login
handle_login_with_openid (api: CMS_API; a_oauth_api: CMS_OPENID_API; req: WSF_REQUEST; res: WSF_RESPONSE) handle_login_with_openid (api: CMS_API; a_openid_api: CMS_OPENID_API; req: WSF_REQUEST; res: WSF_RESPONSE)
local local
r: CMS_RESPONSE r: CMS_RESPONSE
b: STRING b: STRING
o: OPENID_CONSUMER o: OPENID_CONSUMER
do do
if attached {WSF_STRING} req.path_parameter ({CMS_OPENID_CONSTANTS}.consumer) as p_openid and then if
attached {CMS_OPENID_CONSUMER} a_oauth_api.openid_consumer_by_name (p_openid.value) as l_oc then attached {WSF_STRING} req.path_parameter (openid_consumer_path_parameter) as p_openid and then
attached {CMS_OPENID_CONSUMER} a_openid_api.openid_consumer_by_name (p_openid.value) as l_oc
then
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
create b.make_empty create b.make_empty
b.append ("Check openID: " + p_openid.value) b.append ("Check openID: " + p_openid.value)
@@ -383,14 +396,14 @@ feature -- Openid Login
end end
end end
handle_callback_openid (api: CMS_API; a_user_openid_api: CMS_OPENID_API; req: WSF_REQUEST; res: WSF_RESPONSE) handle_callback_openid (api: CMS_API; a_openid_api: CMS_OPENID_API; req: WSF_REQUEST; res: WSF_RESPONSE)
local local
r: CMS_RESPONSE r: CMS_RESPONSE
l_user_api: CMS_USER_API l_user_api: CMS_USER_API
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
@@ -410,14 +423,14 @@ feature -- Openid Login
l_user_api := api.user_api l_user_api := api.user_api
if attached l_user_api.user_by_email (l_email) as p_user then if attached l_user_api.user_by_email (l_email) as p_user then
-- User with email exist -- User with email exist
if attached a_user_openid_api.user_openid_by_userid_identity (p_user.id, l_identity) then if attached a_openid_api.user_openid_by_userid_identity (p_user.id, l_identity) then
-- Update openid entry? -- Update openid entry?
else else
-- create a oauth entry -- create a oauth entry
a_user_openid_api.new_user_openid (l_identity,p_user) a_openid_api.new_user_openid (l_identity,p_user)
end end
create l_cookie.make ({CMS_OPENID_CONSTANTS}.openid_session, l_identity) create l_cookie.make (a_openid_api.session_token, l_identity)
l_cookie.set_max_age (3600) l_cookie.set_max_age (a_openid_api.session_max_age)
l_cookie.set_path ("/") l_cookie.set_path ("/")
res.add_cookie (l_cookie) res.add_cookie (l_cookie)
else else
@@ -434,16 +447,16 @@ feature -- Openid Login
l_user_api.new_user (l_user) l_user_api.new_user (l_user)
-- Add oauth entry -- Add oauth entry
a_user_openid_api.new_user_openid (l_identity, l_user ) a_openid_api.new_user_openid (l_identity, l_user )
create l_cookie.make ({CMS_OPENID_CONSTANTS}.openid_session, l_identity) create l_cookie.make (a_openid_api.session_token, l_identity)
l_cookie.set_max_age (3600) l_cookie.set_max_age (a_openid_api.session_max_age)
l_cookie.set_path ("/") l_cookie.set_path ("/")
res.add_cookie (l_cookie) res.add_cookie (l_cookie)
-- 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, "", req.absolute_script_url ("")) 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)
@@ -475,37 +488,6 @@ feature {NONE} -- Token Generation
Result := l_token Result := l_token
end end
feature {NONE} -- Implementation: date and time
http_date_format_to_date (s: READABLE_STRING_8): detachable DATE_TIME
local
d: HTTP_DATE
do
create d.make_from_string (s)
if not d.has_error then
Result := d.date_time
end
end
file_date (p: PATH): DATE_TIME
require
path_exists: (create {FILE_UTILITIES}).file_path_exists (p)
local
f: RAW_FILE
do
create f.make_with_path (p)
Result := timestamp_to_date (f.date)
end
timestamp_to_date (n: INTEGER): DATE_TIME
local
d: HTTP_DATE
do
create d.make_from_timestamp (n)
Result := d.date_time
end
note note
copyright: "Copyright (c) 1984-2013, Eiffel Software and others" copyright: "Copyright (c) 1984-2013, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
+6 -9
View File
@@ -10,6 +10,7 @@ class
inherit inherit
WSF_URI_TEMPLATE_HANDLER WSF_URI_TEMPLATE_HANDLER
CMS_HANDLER CMS_HANDLER
rename rename
make as make_handler make as make_handler
@@ -22,32 +23,28 @@ create
feature {NONE} -- Initialization feature {NONE} -- Initialization
make (a_api: CMS_API; a_user_openid_api: CMS_OPENID_API) make (a_api: CMS_API; a_openid_api: CMS_OPENID_API)
do do
make_handler (a_api) make_handler (a_api)
user_openid_api := a_user_openid_api openid_api := a_openid_api
end end
user_openid_api: CMS_OPENID_API openid_api: CMS_OPENID_API
feature -- Basic operations feature -- Basic operations
execute (req: WSF_REQUEST; res: WSF_RESPONSE) execute (req: WSF_REQUEST; res: WSF_RESPONSE)
-- Execute the filter. -- Execute the filter.
do do
api.logger.put_debug (generator + ".execute ", Void)
-- A valid user -- A valid user
if if
attached {WSF_STRING} req.cookie ({CMS_OPENID_CONSTANTS}.openid_session) as l_roc_openid_session_token attached {WSF_STRING} req.cookie (openid_api.session_token) as l_roc_openid_session_token
then then
if attached user_openid_api.user_openid_by_identity (l_roc_openid_session_token.value) as l_user then if attached openid_api.user_openid_by_identity (l_roc_openid_session_token.value) as l_user then
set_current_user (req, l_user) set_current_user (req, l_user)
else else
api.logger.put_error (generator + ".execute login_valid failed for: " + l_roc_openid_session_token.value , Void) api.logger.put_error (generator + ".execute login_valid failed for: " + l_roc_openid_session_token.value , Void)
end end
else
api.logger.put_debug (generator + ".execute without authentication", Void)
end end
execute_next (req, res) execute_next (req, res)
end end
+14
View File
@@ -0,0 +1,14 @@
<?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="seo" uuid="D53D622D-1F5A-4079-82B9-3E9A1605832B" library_target="seo">
<target name="seo">
<root all_classes="true"/>
<option is_obsolete_routine_type="false">
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="cms" location="..\..\cms-safe.ecf" readonly="false"/>
<library name="error" location="$ISE_LIBRARY\contrib\library\utility\general\error\error-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"/>
<cluster name="src" location="src\" recursive="true"/>
</target>
</system>
+154
View File
@@ -0,0 +1,154 @@
note
description: "[
Module that provides Search Engine Optimization.
]"
date: "$Date: 2016-01-08 22:43:12 +0100 (ven., 08 janv. 2016) $"
revision: "$Revision: 98369 $"
class
CMS_SEO_MODULE
inherit
CMS_MODULE
redefine
setup_hooks
end
CMS_HOOK_AUTO_REGISTER
CMS_HOOK_RESPONSE_ALTER
REFACTORING_HELPER
create
make
feature {NONE} -- Initialization
make
-- Create current module
do
version := "1.0"
description := "Search Engine Optimization"
package := "misc"
end
feature -- Access
name: STRING = "seo"
-- <Precursor>
feature -- Router
setup_router (a_router: WSF_ROUTER; a_api: CMS_API)
-- Router configuration.
do
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_response_alter_hook (Current)
end
feature -- Hook
response_alter (a_response: CMS_RESPONSE)
local
l_siteurl: STRING
l_title, l_desc, l_keywords: detachable READABLE_STRING_32
l_now: DATE_TIME
dt: detachable DATE_TIME
l_props: STRING_TABLE [READABLE_STRING_32]
api: CMS_API
setup: CMS_SETUP
do
api := a_response.api
setup := api.setup
l_siteurl := a_response.absolute_url (a_response.request.percent_encoded_path_info, Void)
create l_props.make_equal_caseless (5)
l_props.put (l_siteurl, "url")
l_props.put (api.setup.site_name, "site_name")
if attached api.setup.site_properties as tb then
across
tb as ic
loop
if ic.key.same_string ("headline") then
l_props.force (ic.item, "site_name")
else
l_props.put (ic.item, ic.key)
end
end
end
l_title := a_response.title
if l_title /= Void then
l_props.put (l_title, "title")
end
l_desc := a_response.description
if l_desc = Void then
l_desc := api.setup.site_description
else
l_props.put (l_desc, "description")
end
l_keywords := a_response.keywords
if l_keywords = Void then
l_keywords := api.setup.site_keywords
else
l_props.put (l_keywords, "keywords")
end
create l_now.make_now_utc
dt := a_response.publication_date
if dt = Void then
dt := l_now
end
l_props.put (date_to_yyyy_mm_dd_string (dt), "published_time")
dt := a_response.modification_date
if dt = Void then
dt := l_now
end
l_props.put (date_to_yyyy_mm_dd_string (dt), "modified_time")
a_response.add_additional_head_line ("<link rel=%"profile%" href=%"http://gmpg.org/xfn/11%" />", False)
if l_desc /= Void then
a_response.add_additional_head_line ("<meta name=%"description%" content=%"" + api.html_encoded (l_desc) + "%" />", False)
end
if l_keywords /= Void then
a_response.add_additional_head_line ("<meta name=%"keywords%" content=%"" + api.html_encoded (l_keywords) + "%" />", False)
end
-- Meta properties
a_response.add_additional_head_line ("<meta property=%"og:type%" content=%"article%" />", False)
across
l_props as ic
loop
a_response.add_additional_head_line ("<meta property=%"og:" + ic.key + "%" content=%"" + api.html_encoded (ic.item) + "%" />", False)
end
a_response.add_additional_head_line ("<link rel='canonical' href='" + l_siteurl + "' />", False)
a_response.add_additional_head_line ("<link rel='shortlink' href='" + l_siteurl + "' />", False)
end
feature -- Helpers: date
date_to_yyyy_mm_dd_string (dt: DATE_TIME): STRING
-- Date to YYYY-mm-dd format.
do
create Result.make (10)
Result.append_integer (dt.year)
Result.append_character ('-')
if dt.month < 10 then
Result.append_character ('0')
end
Result.append_integer (dt.month)
Result.append_character ('-')
if dt.day < 10 then
Result.append_character ('0')
end
Result.append_integer (dt.day)
end
end
+27 -1
View File
@@ -6,7 +6,6 @@ note
class class
CMS_SESSION_API CMS_SESSION_API
inherit inherit
CMS_MODULE_API CMS_MODULE_API
@@ -19,9 +18,25 @@ feature {NONE} -- Initialization
make_with_storage (a_api: CMS_API; a_session_auth_storage: CMS_SESSION_AUTH_STORAGE_I) make_with_storage (a_api: CMS_API; a_session_auth_storage: CMS_SESSION_AUTH_STORAGE_I)
-- Create an object with api `a_api' and storage `a_session_auth_storage'. -- Create an object with api `a_api' and storage `a_session_auth_storage'.
local
s: detachable READABLE_STRING_8
do do
session_auth_storage := a_session_auth_storage session_auth_storage := a_session_auth_storage
make (a_api) make (a_api)
-- Initialize session related settings.
s := a_api.setup.string_8_item ("auth.session.token")
if s = Void then
s := a_api.setup.site_id + default_session_token_suffix
end
create session_token.make_from_string (s)
s := a_api.setup.string_8_item ("auth.session.max_age")
if s /= Void and then s.is_integer then
session_max_age := s.to_integer
else
session_max_age := 86400 --| one day: 24(h) *60(min) *60(sec)
end
ensure ensure
session_auth_storage_set: session_auth_storage = a_session_auth_storage session_auth_storage_set: session_auth_storage = a_session_auth_storage
end end
@@ -31,6 +46,17 @@ feature {CMS_MODULE} -- Access: User session storage.
session_auth_storage: CMS_SESSION_AUTH_STORAGE_I session_auth_storage: CMS_SESSION_AUTH_STORAGE_I
-- storage interface. -- storage interface.
feature -- Settings
default_session_token_suffix: STRING = "_SESSION_TOKEN_"
-- Default value for `session_token'.
session_token: IMMUTABLE_STRING_8
-- Token used for the session related cookies.
session_max_age: INTEGER
-- Value of the Max-Age, before the cookie expires.
feature -- Access feature -- Access
user_by_session_token (a_token: READABLE_STRING_32): detachable CMS_USER user_by_session_token (a_token: READABLE_STRING_32): detachable CMS_USER
+54 -53
View File
@@ -12,13 +12,13 @@ class
inherit inherit
CMS_MODULE CMS_MODULE
rename rename
module_api as user_session_api module_api as session_api
redefine redefine
filters, filters,
setup_hooks, setup_hooks,
initialize, initialize,
install, install,
user_session_api session_api
end end
@@ -51,31 +51,29 @@ feature -- Access
name: STRING = "session_auth" name: STRING = "session_auth"
feature {CMS_API} -- Module Initialization feature {CMS_API} -- Module Initialization
initialize (a_api: CMS_API) initialize (a_api: CMS_API)
-- <Precursor> -- <Precursor>
local local
l_session_auth_api: like user_session_api l_session_auth_api: like session_api
l_user_auth_storage: CMS_SESSION_AUTH_STORAGE_I l_session_auth_storage: CMS_SESSION_AUTH_STORAGE_I
do do
Precursor (a_api) Precursor (a_api)
-- Storage initialization -- Storage initialization
if attached a_api.storage.as_sql_storage as l_storage_sql then if attached a_api.storage.as_sql_storage as l_storage_sql then
create {CMS_SESSION_AUTH_STORAGE_SQL} l_user_auth_storage.make (l_storage_sql) create {CMS_SESSION_AUTH_STORAGE_SQL} l_session_auth_storage.make (l_storage_sql)
else else
-- FIXME: in case of NULL storage, should Current be disabled? -- FIXME: in case of NULL storage, should Current be disabled?
create {CMS_SESSION_AUTH_STORAGE_NULL} l_user_auth_storage create {CMS_SESSION_AUTH_STORAGE_NULL} l_session_auth_storage
end end
-- API initialization -- API initialization
create l_session_auth_api.make_with_storage (a_api, l_user_auth_storage) create l_session_auth_api.make_with_storage (a_api, l_session_auth_storage)
user_session_api := l_session_auth_api session_api := l_session_auth_api
ensure then ensure then
session_auth_api_set: user_session_api /= Void session_auth_api_set: session_api /= Void
end end
feature {CMS_API} -- Module management feature {CMS_API} -- Module management
@@ -84,22 +82,19 @@ feature {CMS_API} -- Module management
do do
-- Schema -- Schema
if attached api.storage.as_sql_storage as l_sql_storage then if attached api.storage.as_sql_storage as l_sql_storage then
if not l_sql_storage.sql_table_exists ("session_auth") then l_sql_storage.sql_execute_file_script (api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended ("install.sql")), Void)
--| Schema
l_sql_storage.sql_execute_file_script (api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended ("session_auth_table.sql")), Void)
if l_sql_storage.has_error then if l_sql_storage.has_error then
api.logger.put_error ("Could not initialize database for session auth module", generating_type) api.logger.put_error ("Could not initialize database for module [" + name + "]", generating_type)
end else
Precursor {CMS_MODULE} (api) -- Mark it as installed.
end end
l_sql_storage.sql_finalize
Precursor {CMS_MODULE}(api)
end end
end end
feature {CMS_API} -- Access: API feature {CMS_API} -- Access: API
user_session_api: detachable CMS_SESSION_API session_api: detachable CMS_SESSION_API
-- <Precursor> -- <Precursor>
feature -- Access: router feature -- Access: router
@@ -107,9 +102,11 @@ feature -- Access: router
setup_router (a_router: WSF_ROUTER; a_api: CMS_API) setup_router (a_router: WSF_ROUTER; a_api: CMS_API)
-- <Precursor> -- <Precursor>
do do
a_router.handle ("/account/roc-session-login", create {WSF_URI_AGENT_HANDLER}.make (agent handle_login(a_api, ?, ?)), a_router.methods_head_get) if attached session_api as l_session_api then
a_router.handle ("/account/roc-session-logout", create {WSF_URI_AGENT_HANDLER}.make (agent handle_logout (a_api, ?, ?)), a_router.methods_get_post) a_router.handle ("/account/roc-session-login", create {WSF_URI_AGENT_HANDLER}.make (agent handle_login (a_api, ?, ?)), a_router.methods_head_get)
a_router.handle ("/account/login-with-session", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_login_with_session (a_api,user_session_api, ?, ?)), a_router.methods_get_post) a_router.handle ("/account/roc-session-logout", create {WSF_URI_AGENT_HANDLER}.make (agent handle_logout (a_api, l_session_api, ?, ?)), a_router.methods_get_post)
a_router.handle ("/account/login-with-session", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_login_with_session (a_api,session_api, ?, ?)), a_router.methods_get_post)
end
end end
feature -- Access: filter feature -- Access: filter
@@ -118,7 +115,7 @@ feature -- Access: filter
-- Possibly list of Filter's module. -- Possibly list of Filter's module.
do do
create {ARRAYED_LIST [WSF_FILTER]} Result.make (1) create {ARRAYED_LIST [WSF_FILTER]} Result.make (1)
if attached user_session_api as l_session_api then if attached session_api as l_session_api then
Result.extend (create {CMS_SESSION_AUTH_FILTER}.make (a_api, l_session_api)) Result.extend (create {CMS_SESSION_AUTH_FILTER}.make (a_api, l_session_api))
end end
end end
@@ -133,17 +130,19 @@ feature {NONE} -- Implementation: routes
r.execute r.execute
end end
handle_logout (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE) handle_logout (api: CMS_API; a_session_api: CMS_SESSION_API ; req: WSF_REQUEST; res: WSF_RESPONSE)
local local
r: CMS_RESPONSE r: CMS_RESPONSE
l_cookie: WSF_COOKIE l_cookie: WSF_COOKIE
tok: STRING
do do
tok := a_session_api.session_token
if if
attached {WSF_STRING} req.cookie ({CMS_SESSION_CONSTANTS}.session_auth_token) as l_cookie_token and then attached {WSF_STRING} req.cookie (tok) as l_cookie_token and then
attached {CMS_USER} current_user (req) as l_user attached {CMS_USER} current_user (req) as l_user
then then
-- Logout Session -- Logout Session
create l_cookie.make ({CMS_SESSION_CONSTANTS}.session_auth_token, l_cookie_token.value) create l_cookie.make (tok, l_cookie_token.value) -- FIXME: unicode issue?
l_cookie.set_path ("/") l_cookie.set_path ("/")
l_cookie.set_max_age (-1) l_cookie.set_max_age (-1)
res.add_cookie (l_cookie) res.add_cookie (l_cookie)
@@ -179,8 +178,8 @@ feature {NONE} -- Implementation: routes
else else
l_session_api.new_user_session_auth (l_token, l_user) l_session_api.new_user_session_auth (l_token, l_user)
end end
create l_cookie.make ({CMS_SESSION_CONSTANTS}.session_auth_token, l_token) create l_cookie.make (a_session_api.session_token, l_token)
l_cookie.set_max_age ({CMS_SESSION_CONSTANTS}.session_max_age) l_cookie.set_max_age (a_session_api.session_max_age)
l_cookie.set_path ("/") l_cookie.set_path ("/")
res.add_cookie (l_cookie) res.add_cookie (l_cookie)
set_current_user (req, l_user) set_current_user (req, l_user)
@@ -217,11 +216,11 @@ feature -- Hooks
do do
if if
attached a_response.user as u and then attached a_response.user as u and then
attached {WSF_STRING} a_response.request.cookie ({CMS_SESSION_CONSTANTS}.session_auth_token) attached session_api as l_session_api and then
attached a_response.request.cookie (l_session_api.session_token)
then then
a_value.force ("account/roc-session-logout", "auth_login_strategy") a_value.force ("account/roc-session-logout", "auth_login_strategy")
end end
end end
menu_system_alter (a_menu_system: CMS_MENU_SYSTEM; a_response: CMS_RESPONSE) menu_system_alter (a_menu_system: CMS_MENU_SYSTEM; a_response: CMS_RESPONSE)
@@ -231,29 +230,32 @@ feature -- Hooks
lnk: CMS_LOCAL_LINK lnk: CMS_LOCAL_LINK
lnk2: detachable CMS_LINK lnk2: detachable CMS_LINK
do do
if if attached a_response.user as u then
attached a_response.user as u and then if
attached {WSF_STRING} a_response.request.cookie ({CMS_SESSION_CONSTANTS}.session_auth_token) attached session_api as l_session_api and then
then attached a_response.request.cookie (l_session_api.session_token)
across then
a_menu_system.primary_menu.items as ic across
until a_menu_system.primary_menu.items as ic
lnk2 /= Void until
loop lnk2 /= Void
if ic.item.location.same_string ("account/roc-logout") or else ic.item.location.same_string ("basic_auth_logoff") then loop
lnk2 := ic.item if
ic.item.location.same_string ("account/roc-logout")
or else ic.item.location.same_string ("basic_auth_logoff")
then
lnk2 := ic.item
end
end end
if lnk2 /= Void then
a_menu_system.primary_menu.remove (lnk2)
end
create lnk.make ("Logout", "account/roc-session-logout" )
a_menu_system.primary_menu.extend (lnk)
end end
if lnk2 /= Void then elseif a_response.location.starts_with ("account/") then
a_menu_system.primary_menu.remove (lnk2) create lnk.make ("Session", "account/roc-session-login")
end a_response.add_to_primary_tabs (lnk)
create lnk.make ("Logout", "account/roc-session-logout" )
a_menu_system.primary_menu.extend (lnk)
else
if a_response.location.starts_with ("account/") then
create lnk.make ("Session", "account/roc-session-login")
a_response.add_to_primary_tabs (lnk)
end
end end
end end
@@ -327,7 +329,6 @@ feature {NONE} -- Block views
end end
end end
generate_token: STRING generate_token: STRING
-- Generate token to use in a Session. -- Generate token to use in a Session.
local local
@@ -1,19 +0,0 @@
note
description: "Summary description for {CMS_SESSION_CONSTANTS}."
date: "$Date$"
revision: "$Revision$"
class
CMS_SESSION_CONSTANTS
feature
session_auth_token: STRING = "EWF_ROC_SESSION_AUTH_TOKEN_"
-- Name of Cookie used to keep the session info.
-- TODO add a config file to be able to customize this value via coniguration file.
session_max_age: INTEGER = 86400
-- Value of the Max-Age, before the cookie expires.
-- TODO add a config file to be able to customize this value via coniguration file.
end
@@ -37,7 +37,7 @@ feature -- Access
password_hash (a_password, a_salt: STRING): STRING password_hash (a_password, a_salt: STRING): STRING
-- Password hash based on password `a_password' and salt value `a_salt'. -- Password hash based on password `a_password' and salt value `a_salt'.
do do
Result := sha1_string (a_password + a_salt ) Result := sha1_string (a_password + a_salt)
end end
feature {NONE} -- Implementation feature {NONE} -- Implementation
@@ -77,7 +77,6 @@ feature {NONE} -- Implementation
feature -- Encoding feature -- Encoding
base_64 (bytes: SPECIAL [INTEGER_8]): STRING_8 base_64 (bytes: SPECIAL [INTEGER_8]): STRING_8
-- Encodes a byte array into a STRING doing base64 encoding. -- Encodes a byte array into a STRING doing base64 encoding.
local local
@@ -23,31 +23,28 @@ create
feature {NONE} -- Initialization feature {NONE} -- Initialization
make (a_api: CMS_API; a_session_oauth_api: CMS_SESSION_API) make (a_api: CMS_API; a_session_api: CMS_SESSION_API)
do do
make_handler (a_api) make_handler (a_api)
session_oauth_api := a_session_oauth_api session_api := a_session_api
end end
session_oauth_api: CMS_SESSION_API session_api: CMS_SESSION_API
feature -- Basic operations feature -- Basic operations
execute (req: WSF_REQUEST; res: WSF_RESPONSE) execute (req: WSF_REQUEST; res: WSF_RESPONSE)
-- Execute the filter. -- Execute the filter.
do do
api.logger.put_debug (generator + ".execute ", Void)
-- A valid user -- A valid user
if if
attached {WSF_STRING} req.cookie ({CMS_SESSION_CONSTANTS}.session_auth_token) as l_roc_auth_session_token attached {WSF_STRING} req.cookie (session_api.session_token) as l_roc_auth_session_token
then then
if attached session_oauth_api.user_by_session_token (l_roc_auth_session_token.value) as l_user then if attached session_api.user_by_session_token (l_roc_auth_session_token.value) as l_user then
set_current_user (req, l_user) set_current_user (req, l_user)
else else
api.logger.put_error (generator + ".execute login_valid failed for: " + l_roc_auth_session_token.value , Void) api.logger.put_error (generator + ".execute login_valid failed for: " + l_roc_auth_session_token.value , Void)
end end
else
api.logger.put_debug (generator + ".execute without authentication", Void)
end end
execute_next (req, res) execute_next (req, res)
end end
@@ -7,7 +7,6 @@ class
CMS_SESSION_AUTH_STORAGE_SQL CMS_SESSION_AUTH_STORAGE_SQL
inherit inherit
CMS_SESSION_AUTH_STORAGE_I CMS_SESSION_AUTH_STORAGE_I
CMS_PROXY_STORAGE_SQL CMS_PROXY_STORAGE_SQL
@@ -27,23 +26,27 @@ feature -- Access User
-- Retrieve user by token `a_token', if any. -- Retrieve user by token `a_token', if any.
local local
l_parameters: STRING_TABLE [detachable ANY] l_parameters: STRING_TABLE [detachable ANY]
l_uid: INTEGER_64
do do
error_handler.reset error_handler.reset
write_information_log (generator + ".user_by_session_token") write_information_log (generator + ".user_by_session_token")
create l_parameters.make (1) create l_parameters.make (1)
l_parameters.put (a_token, "token") l_parameters.put (a_token, "token")
sql_query (Select_user_by_token, l_parameters) sql_query (Select_user_id_by_token, l_parameters)
if not has_error and not sql_after then if not has_error and not sql_after then
Result := fetch_user l_uid := sql_read_integer_64 (1)
sql_forth sql_forth
if not sql_after then if not sql_after then
check check
no_more_than_one: False no_more_than_one: False
end end
Result := Void l_uid := 0
end end
end end
sql_finalize sql_finalize
if l_uid > 0 and attached api as l_cms_api then
Result := l_cms_api.user_api.user_by_id (l_uid)
end
end end
has_user_token (a_user: CMS_USER): BOOLEAN has_user_token (a_user: CMS_USER): BOOLEAN
@@ -68,7 +71,7 @@ feature -- Access User
feature -- Change User token feature -- Change User token
new_user_session_auth (a_token: READABLE_STRING_GENERAL; a_user: CMS_USER;) new_user_session_auth (a_token: READABLE_STRING_GENERAL; a_user: CMS_USER)
-- <Precursor>. -- <Precursor>.
local local
l_parameters: STRING_TABLE [detachable ANY] l_parameters: STRING_TABLE [detachable ANY]
@@ -102,54 +105,14 @@ feature -- Change User token
sql_finalize sql_finalize
end end
feature {NONE} -- Implementation
fetch_user: detachable CMS_USER
local
l_id: INTEGER_64
l_name: detachable READABLE_STRING_32
do
if attached sql_read_integer_64 (1) as i then
l_id := i
end
if attached sql_read_string_32 (2) as s and then not s.is_whitespace then
l_name := s
end
if l_name /= Void then
create Result.make (l_name)
if l_id > 0 then
Result.set_id (l_id)
end
elseif l_id > 0 then
create Result.make_with_id (l_id)
end
if Result /= Void then
if attached sql_read_string (3) as l_password then
-- FIXME: should we return the password here ???
Result.set_hashed_password (l_password)
end
if attached sql_read_string (5) as l_email then
Result.set_email (l_email)
end
if attached sql_read_integer_32 (6) as l_status then
Result.set_status (l_status)
end
else
check
expected_valid_user: False
end
end
end
feature {NONE} -- SQL statements feature {NONE} -- SQL statements
Select_user_by_token: STRING = "SELECT u.* FROM users as u JOIN session_auth as og ON og.uid = u.uid and og.access_token = :token;" Select_user_id_by_token: STRING = "SELECT u.uid FROM users as u JOIN auth_session as og ON og.uid = u.uid AND og.access_token = :token;"
--| FIXME: replace the u.* by a list of field names, to avoid breaking `featch_user' if two fieds are swiped.
Sql_insert_session_auth: STRING = "INSERT INTO session_auth (uid, access_token, created) VALUES (:uid, :token, :utc_date);" sql_insert_session_auth: STRING = "INSERT INTO auth_session (uid, access_token, created) VALUES (:uid, :token, :utc_date);"
Sql_update_session_auth: STRING = "UPDATE session_auth SET access_token = :token, created = :utc_date WHERE uid =:uid;" sql_update_session_auth: STRING = "UPDATE auth_session SET access_token = :token, created = :utc_date WHERE uid =:uid;"
Select_user_token: STRING = "SELECT COUNT(*) FROM session_auth where uid = :uid;" select_user_token: STRING = "SELECT COUNT(*) FROM auth_session where uid = :uid;"
end end
@@ -0,0 +1,9 @@
CREATE TABLE auth_session (
`uid` INTEGER PRIMARY KEY NOT NULL CHECK(`uid`>=0),
`access_token` VARCHAR(64) NOT NULL,
`created` DATETIME NOT NULL,
CONSTRAINT `uid` UNIQUE(`uid`),
CONSTRAINT `access_token` UNIQUE(`access_token`)
);
@@ -1,11 +0,0 @@
CREATE TABLE session_auth (
`uid` INTEGER PRIMARY KEY NOT NULL CHECK(`uid`>=0),
`access_token` TEXT NOT NULL,
`created` DATETIME NOT NULL,
CONSTRAINT `uid`
UNIQUE(`uid`),
CONSTRAINT `access_token`
UNIQUE(`access_token`)
);
+11 -9
View File
@@ -70,18 +70,20 @@ feature {CMS_API} -- Module management
do do
-- Schema -- Schema
if attached {CMS_STORAGE_SQL_I} api.storage as l_sql_storage then if attached {CMS_STORAGE_SQL_I} api.storage as l_sql_storage then
l_sql_storage.sql_execute_file_script (api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended ("install").appended_with_extension ("sql")), Void) l_sql_storage.sql_execute_file_script (api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended ("install.sql")), Void)
if l_sql_storage.has_error then if l_sql_storage.has_error then
api.logger.put_error ("Could not install database for taxonomy module", generating_type) api.logger.put_error ("Could not install database for taxonomy module", generating_type)
end else
Precursor (api) Precursor (api)
create l_taxonomy_api.make (api) -- Populate
create voc.make ("Tags") create l_taxonomy_api.make (api)
voc.set_description ("Enter comma separated tags.") create voc.make ("Tags")
l_taxonomy_api.save_vocabulary (voc) voc.set_description ("Enter comma separated tags.")
voc.set_is_tags (True) l_taxonomy_api.save_vocabulary (voc)
l_taxonomy_api.associate_vocabulary_with_type (voc, "page") voc.set_is_tags (True)
l_taxonomy_api.associate_vocabulary_with_type (voc, "page")
end
end end
end end
BIN
View File
Binary file not shown.
+1 -1
View File
@@ -179,6 +179,6 @@ feature -- Element change
note note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, 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
+92 -14
View File
@@ -16,11 +16,12 @@ feature {NONE} -- Initialization
initialize initialize
local local
l_url: like site_url l_url: like site_url
s, l_email: detachable READABLE_STRING_8
do do
site_location := environment.path site_location := environment.path
--| Site id, used to identified a site, this could be set to a uuid, or else --| Site id, used to identified a site, this could be set to a uuid, or else
site_id := text_item_or_default ("site.id", "_EWF_CMS_NO_ID_") site_id := string_8_item_or_default ("site.id", "_ROC_CMS_NO_ID_")
-- Site url: optional, but ending with a slash -- Site url: optional, but ending with a slash
l_url := string_8_item ("site_url") l_url := string_8_item ("site_url")
@@ -32,30 +33,50 @@ feature {NONE} -- Initialization
site_url := l_url site_url := l_url
-- Site name -- Site name
site_name := text_item_or_default ("site.name", "EWF::CMS") site_name := text_item_or_default ("site.name", "Another Eiffel ROC Website")
-- Site email for any internal notification -- Website email used to send email.
-- Can be also used to precise the "From:" value for email. -- used as real "From:" email.
site_email := text_item_or_default ("site.email", "webmaster") -- Any "From:" header passed to the CMS email sender will appear as "Reply-To:"
-- or ignored if a reply-to header is already set.
l_email := string_8_item ("site.email")
if l_email = Void then
-- FIXME: find better default value!
-- Or handler configuration error (missing value)!!!
l_email := string_8_item_or_default ("mailer.from", "webmaster")
end
if l_email.has ('<') then
l_email := site_name + " <" + l_email + ">"
end
site_email := l_email
-- Email address for current web site
site_notification_email := string_8_item_or_default ("notification.email", site_email)
-- Email subject tuning.
s := string_8_item ("mailer.subject_prefix")
if s /= Void and then not s.ends_with_general (" ") then
s := s + " "
end
site_email_subject_prefix := s
-- Location for public files -- Location for public files
if attached text_item ("files-dir") as s then if attached text_item ("files-dir") as l_files_dir then
create files_location.make_from_string (s) create files_location.make_from_string (l_files_dir)
else else
files_location := site_location.extended ("files") files_location := site_location.extended ("files")
end end
-- Location for modules folders. -- Location for modules folders.
if attached text_item ("modules-dir") as s then if attached text_item ("modules-dir") as l_modules_dir then
create modules_location.make_from_string (s) create modules_location.make_from_string (l_modules_dir)
else else
modules_location := environment.modules_path modules_location := environment.modules_path
end end
-- Location for themes folders. -- Location for themes folders.
if attached text_item ("themes-dir") as s then if attached text_item ("themes-dir") as l_themes_dir then
create themes_location.make_from_string (s) create themes_location.make_from_string (l_themes_dir)
else else
themes_location := environment.themes_path themes_location := environment.themes_path
end end
@@ -180,9 +201,56 @@ feature -- Access: Site
site_name: READABLE_STRING_32 site_name: READABLE_STRING_32
-- Name of the site. -- Name of the site.
utf_8_site_name: READABLE_STRING_8
-- `site_name' encoded with UTF-8.
local
utf: UTF_CONVERTER
do
Result := utf.utf_32_string_to_utf_8_string_8 (site_name)
end
site_properties: detachable STRING_TABLE [READABLE_STRING_32]
-- Optional site properties.
do
Result := text_table_item ("site.property")
end
site_property (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32
do
Result := text_item ({STRING_32} "site." + a_name.as_string_32)
if Result = Void and then attached site_properties as props then
Result := props.item (a_name)
end
end
site_description: detachable READABLE_STRING_32
-- Optional site description.
do
Result := site_property ("description")
end
site_headline: detachable READABLE_STRING_32
-- Optional site headline.
do
Result := site_property ("headline")
end
site_keywords: detachable READABLE_STRING_32
-- Optional site comma separated keywords.
do
Result := site_property ("keywords")
end
site_email: READABLE_STRING_8 site_email: READABLE_STRING_8
-- Admin email address for the site. -- Website email address.
-- Mainly used for internal notification. -- Used as "From:" address when the site is sending emails
-- cf: `CMS_SETUP.mailer'.
site_notification_email: READABLE_STRING_8
-- Email address receiving internal notification.
site_email_subject_prefix: detachable READABLE_STRING_8
-- Optional prefix for any email sent by Current site.
site_url: detachable READABLE_STRING_8 site_url: detachable READABLE_STRING_8
-- Optional url of current CMS site. -- Optional url of current CMS site.
@@ -223,6 +291,16 @@ feature -- Query
deferred deferred
end end
string_8_item_or_default (a_name: READABLE_STRING_GENERAL; a_default_value: READABLE_STRING_8): READABLE_STRING_8
-- `string_8_item' associated with `a_name' or if none, `a_default_value'.
do
if attached string_8_item (a_name) as v then
Result := v
else
Result := a_default_value
end
end
feature -- Access: Theme feature -- Access: Theme
site_location: PATH site_location: PATH
@@ -333,6 +411,6 @@ feature -- Element change
end end
note note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, 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
+1 -1
View File
@@ -27,6 +27,6 @@ feature -- Factory
end end
note note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, 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

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