diff --git a/examples/demo/site/modules/auth/config/auth.json b/examples/demo/site/modules/auth/config/auth.json
new file mode 100644
index 0000000..a81ab66
--- /dev/null
+++ b/examples/demo/site/modules/auth/config/auth.json
@@ -0,0 +1,8 @@
+{
+ "email": "webmaster@eiffel.org",
+ "subject": "Thank you for contacting us",
+ "recaptcha": {
+ "site_key":"6Lex9RMTAAAAAKleC4x6TaRlFcpLbEWgH_U7MSiD",
+ "secret_key":"6Lex9RMTAAAAAAkBczvX5DUiyg_xoM_EthVVgRRx"
+ }
+}
diff --git a/examples/demo/site/modules/auth/mail_templates/account_activation.html b/examples/demo/site/modules/auth/mail_templates/account_activation.html
index 0ab4c4f..0d404a0 100644
--- a/examples/demo/site/modules/auth/mail_templates/account_activation.html
+++ b/examples/demo/site/modules/auth/mail_templates/account_activation.html
@@ -1,5 +1,5 @@
-
+
Activation
@@ -8,11 +8,7 @@
- Thank you for registering at ROC CMS
-
- To complete your registration, please click on this link to activate your account:
-
-
$link
- Thank you for joining us.
+ Thank you for applying to ROC CMS $user
+ We will review your application and send you a resolution
-
+
\ No newline at end of file
diff --git a/examples/demo/site/modules/auth/mail_templates/account_activation_confirmation.html b/examples/demo/site/modules/auth/mail_templates/account_activation_confirmation.html
new file mode 100644
index 0000000..efc5087
--- /dev/null
+++ b/examples/demo/site/modules/auth/mail_templates/account_activation_confirmation.html
@@ -0,0 +1,14 @@
+
+
+
+
+ Activation
+
+
+
+
+
+ Your account has been confirmed ROC CMS
+ Thank you for joining us.
+
+
\ No newline at end of file
diff --git a/examples/demo/site/modules/auth/mail_templates/account_evaluation.html b/examples/demo/site/modules/auth/mail_templates/account_evaluation.html
new file mode 100644
index 0000000..002292d
--- /dev/null
+++ b/examples/demo/site/modules/auth/mail_templates/account_evaluation.html
@@ -0,0 +1,26 @@
+
+
+
+
+ Account Evaluation
+
+
+
+
+
+ Account Evaluation
+ The user $user ($email) wants to register to the site ROC CMS
+
+ This is his/her application.
+ $application
+
+
+ To complete the registration, please click on the following link to activate the user account:
+
+
$activate
+
+ To reject the registration, please click on the following link
+
+
$reject
+
+
diff --git a/examples/demo/site/modules/auth/mail_templates/account_rejected.html b/examples/demo/site/modules/auth/mail_templates/account_rejected.html
new file mode 100644
index 0000000..9cefb80
--- /dev/null
+++ b/examples/demo/site/modules/auth/mail_templates/account_rejected.html
@@ -0,0 +1,13 @@
+
+
+
+
+ New Activation
+
+
+
+
+
+ You requested has been rejected, your application does not conform our rules ROC CMS
+
+
\ No newline at end of file
diff --git a/examples/demo/site/modules/auth/scripts/auth_temp_user.sql b/examples/demo/site/modules/auth/scripts/auth_temp_user.sql
new file mode 100644
index 0000000..38ae29b
--- /dev/null
+++ b/examples/demo/site/modules/auth/scripts/auth_temp_user.sql
@@ -0,0 +1,13 @@
+
+DROP TABLE IF EXISTS "auth_temp_user";
+CREATE TABLE `auth_temp_user` (
+ `uid` INTEGER PRIMARY KEY AUTOINCREMENT 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`)
+);
+
diff --git a/examples/demo/site/modules/auth/templates/block_post_register.tpl b/examples/demo/site/modules/auth/templates/block_post_register.tpl
index d59f75a..c76cbb5 100644
--- a/examples/demo/site/modules/auth/templates/block_post_register.tpl
+++ b/examples/demo/site/modules/auth/templates/block_post_register.tpl
@@ -1,3 +1,3 @@
-
Thanks for register, check your email to activate your account.
+
Thanks for your application, we will review it to activate your account.
diff --git a/examples/demo/site/modules/auth/templates/block_register.tpl b/examples/demo/site/modules/auth/templates/block_register.tpl
index 9e7c478..2b56ea9 100644
--- a/examples/demo/site/modules/auth/templates/block_register.tpl
+++ b/examples/demo/site/modules/auth/templates/block_register.tpl
@@ -20,8 +20,19 @@
{$error_email/}
{/if}
-
-
+
+
+ Application Sentence
+ {if isset="$error_application"}
+ {$error_application/}
+ {/if}
+
+ {unless isempty="$recaptcha_site_key"}
+
+
+ {/unless}
Register
diff --git a/library/email/email_service.e b/library/email/email_service.e
index 1e1c19b..03073a7 100644
--- a/library/email/email_service.e
+++ b/library/email/email_service.e
@@ -35,12 +35,14 @@ feature {NONE} -- Initialization
parameters: EMAIL_SERVICE_PARAMETERS
-- Associated parameters.
- admin_email: IMMUTABLE_STRING_8
- -- Site admin's email.
-
mailer: NOTIFICATION_MAILER
-- SMTP protocol.
+feature -- Access
+
+ admin_email: IMMUTABLE_STRING_8
+ -- Site admin's email.
+
feature -- Basic Operations
send_internal_email (a_content: READABLE_STRING_GENERAL)
diff --git a/library/recaptcha/Readme.md b/library/recaptcha/Readme.md
new file mode 100644
index 0000000..aaa8522
--- /dev/null
+++ b/library/recaptcha/Readme.md
@@ -0,0 +1,4 @@
+Recaptcha Eiffel Lbrary
+
+Based on https://developers.google.com/recaptcha/
+
diff --git a/library/recaptcha/license.lic b/library/recaptcha/license.lic
new file mode 100644
index 0000000..93c113a
--- /dev/null
+++ b/library/recaptcha/license.lic
@@ -0,0 +1,10 @@
+${NOTE_KEYWORD}
+ copyright: "2011-${YEAR} Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
+ license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
+ source: "[
+ Eiffel Software
+ 5949 Hollister Ave., Goleta, CA 93117 USA
+ Telephone 805-685-1006, Fax 805-685-6869
+ Website http://www.eiffel.com
+ Customer support http://support.eiffel.com
+ ]"
diff --git a/library/recaptcha/recaptcha-safe.ecf b/library/recaptcha/recaptcha-safe.ecf
new file mode 100644
index 0000000..ca1015e
--- /dev/null
+++ b/library/recaptcha/recaptcha-safe.ecf
@@ -0,0 +1,20 @@
+
+
+
+
+
+ /.git$
+ /EIFGENs$
+ /CVS$
+ /.svn$
+
+
+
+
+
+
+
+
+
+
+
diff --git a/library/recaptcha/recaptcha.ecf b/library/recaptcha/recaptcha.ecf
new file mode 100644
index 0000000..ad960b8
--- /dev/null
+++ b/library/recaptcha/recaptcha.ecf
@@ -0,0 +1,22 @@
+
+
+
+
+
+ /.git$
+ /EIFGENs$
+ /CVS$
+ /.svn$
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/library/recaptcha/src/recaptcha_api.e b/library/recaptcha/src/recaptcha_api.e
new file mode 100644
index 0000000..1149a4b
--- /dev/null
+++ b/library/recaptcha/src/recaptcha_api.e
@@ -0,0 +1,147 @@
+note
+ description: "[
+ Simple API to call {RECAPTCHA} Google API.
+ Example call:
+ https://www.google.com/recaptcha/api/siteverify?secret=your_secret&response=response_string&remoteip=user_ip_address
+ ]"
+ date: "$Date: 2015-01-28 11:44:15 -0300 (mi. 28 de ene. de 2015) $"
+ revision: "$Revision: 96551 $"
+ EIS: "name=RECAPTCHA", "src=https://developers.google.com/recaptcha/", "protocol=uri"
+ EIS: "name=RECAPTCHA API verify", "src=https://developers.google.com/recaptcha/docs/verify", "protocol=uri"
+
+class
+ RECAPTCHA_API
+
+create
+ make
+
+feature {NONE} -- Initialization
+
+ make (a_secret_key, a_response: READABLE_STRING_8)
+ -- Create an object Recaptcha with secret key `a_secret_key' and response token `a_response'.
+ do
+ secret := a_secret_key
+ response := a_response
+ ensure
+ secret_set: secret.same_string (a_secret_key)
+ response_set: response.same_string (a_response)
+ end
+
+feature -- Access
+
+ base_uri: STRING_8 = "https://www.google.com/recaptcha/api/siteverify"
+ -- Recaptcha base URI
+
+ secret: READABLE_STRING_8
+ -- Required. The shared key between your site and ReCAPTCHA.
+
+ response: READABLE_STRING_8
+ -- Required. The user response token provided by the reCAPTCHA to the user and provided to your site on.
+
+ remoteip: detachable READABLE_STRING_8
+ -- Optional. The user's IP address.
+
+feature -- Status Reports
+
+ errors: detachable LIST [READABLE_STRING_8]
+ -- optional table of error codes
+ -- missing-input-secret The secret parameter is missing.
+ -- invalid-input-secret The secret parameter is invalid or malformed.
+ -- missing-input-response The response parameter is missing.
+ -- invalid-input-response The response parameter is invalid or malformed.
+
+feature -- Change Element
+
+ set_remoteip (a_remoteip: READABLE_STRING_8)
+ -- Set `remoteip' with `a_remoteip'.
+ do
+ remoteip := a_remoteip
+ ensure
+ remoteip_set: remoteip = a_remoteip
+ end
+
+feature -- API
+
+ verify: BOOLEAN
+ -- Verify the user's response
+ local
+ l_parser: JSON_PARSER
+ do
+ if attached get as l_response then
+ if attached l_response.body as l_body then
+ create l_parser.make_with_string (l_body)
+ l_parser.parse_content
+ if
+ l_parser.is_parsed and then attached {JSON_OBJECT} l_parser.parsed_json_object as jv and then
+ attached {JSON_BOOLEAN} jv.item ("success") as l_success
+ then
+ Result := l_success.item
+ if not Result and then attached {JSON_ARRAY} jv.item ("error-codes") as l_error_codes then
+ across
+ l_error_codes as c
+ loop
+ if attached {JSON_STRING} c.item as ji then
+ put_error (ji.unescaped_string_32)
+ end
+ end
+ end
+ end
+ else
+ put_error (l_response.status.out)
+ end
+ else
+ put_error ("unknown")
+ end
+ end
+
+feature {NONE} -- REST API
+
+ get: detachable RESPONSE
+ -- Reading Data
+ local
+ l_request: REQUEST
+ do
+ create l_request.make ("GET", new_uri)
+ Result := l_request.execute
+ end
+
+feature {NONE} -- Implementation
+
+ new_uri: STRING_8
+ -- new uri (BaseUri?secret=secret_value&response=response_value[&remoteip=remoteip_value]
+ do
+ create Result.make_from_string (base_uri)
+ Result.append ("?secret=")
+ Result.append (secret)
+ Result.append ("&response=")
+ Result.append (response)
+ if attached remoteip as l_remoteip then
+ Result.append ("&remoteip=" + l_remoteip)
+ end
+ end
+
+ put_error (a_code: READABLE_STRING_GENERAL)
+ local
+ l_errors: like errors
+ utf: UTF_CONVERTER
+ do
+ l_errors := errors
+ if l_errors = Void then
+ create {ARRAYED_LIST [STRING]} l_errors.make (1)
+ errors := l_errors
+ end
+ l_errors.force (utf.utf_32_string_to_utf_8_string_8 (a_code))
+ end
+
+note
+ copyright: "2011-2015 Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
+ license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
+ source: "[
+ Eiffel Software
+ 5949 Hollister Ave., Goleta, CA 93117 USA
+ Telephone 805-685-1006, Fax 805-685-6869
+ Website http://www.eiffel.com
+ Customer support http://support.eiffel.com
+ ]"
+
+end
diff --git a/library/recaptcha/test/application.e b/library/recaptcha/test/application.e
new file mode 100644
index 0000000..2e0e25b
--- /dev/null
+++ b/library/recaptcha/test/application.e
@@ -0,0 +1,61 @@
+note
+ description : "test application root class"
+ date : "$Date: 2015-01-14 15:37:57 -0300 (mi. 14 de ene. de 2015) $"
+ revision : "$Revision: 96458 $"
+
+class
+ APPLICATION
+
+inherit
+ ARGUMENTS
+
+create
+ make
+
+feature {NONE} -- Initialization
+
+ make
+ -- Run application.
+ do
+ test_invalid_input
+ test_missing_input
+ test_missing_key_input
+ end
+
+
+ test_invalid_input
+ -- invalid-input-response
+ local
+ l_captcha: RECAPTCHA_API
+ do
+ create l_captcha.make ("","234")
+ check
+ not_true:not l_captcha.verify
+ end
+ end
+
+ test_missing_input
+ -- missing-input-response
+ local
+ l_captcha: RECAPTCHA_API
+ do
+ create l_captcha.make ("key","")
+ check
+ not_true:not l_captcha.verify
+ end
+ end
+
+ test_missing_key_input
+ -- missing-input-response
+ -- invalid-input-response
+ local
+ l_captcha: RECAPTCHA_API
+ do
+ create l_captcha.make ("","")
+ l_captcha.set_remoteip("localhost")
+ check
+ not_true:not l_captcha.verify
+ end
+ end
+
+end
diff --git a/library/recaptcha/test/recaptcha_api_test_set.e b/library/recaptcha/test/recaptcha_api_test_set.e
new file mode 100644
index 0000000..4deb220
--- /dev/null
+++ b/library/recaptcha/test/recaptcha_api_test_set.e
@@ -0,0 +1,69 @@
+note
+ description: "[
+ Eiffel tests that can be executed by testing tool.
+ ]"
+ author: "EiffelStudio test wizard"
+ date: "$Date: 2015-01-14 15:37:57 -0300 (mi. 14 de ene. de 2015) $"
+ revision: "$Revision: 96458 $"
+ testing: "type/manual"
+
+class
+ RECAPTCHA_API_TEST_SET
+
+inherit
+ EQA_TEST_SET
+
+feature -- Test routines
+
+ test_invalid_input
+ -- invalid-input-response
+ local
+ l_captcha: RECAPTCHA_API
+ do
+ create l_captcha.make ("","234")
+ check
+ not_true:not l_captcha.verify
+ end
+ assert ("Not true", not l_captcha.verify)
+ assert ("Has error invalid-input-response",has_error (l_captcha,"invalid-input-response"))
+ end
+
+ test_missing_input
+ -- missing-input-response
+ local
+ l_captcha: RECAPTCHA_API
+ do
+ create l_captcha.make ("key","")
+ check
+ not_true:not l_captcha.verify
+ end
+ assert ("Not true", not l_captcha.verify)
+ assert ("Has error missing-input-response",has_error (l_captcha,"missing-input-response"))
+ end
+
+ test_missing_key_input
+ -- missing-input-response
+ -- invalid-input-response
+ local
+ l_captcha: RECAPTCHA_API
+ do
+ create l_captcha.make ("","")
+ l_captcha.set_remoteip("localhost")
+ assert ("Not true", not l_captcha.verify)
+ assert ("Has error missing-input-response",has_error (l_captcha,"missing-input-response"))
+ assert ("Has error invalid-input-response",has_error (l_captcha,"invalid-input-response"))
+ end
+
+feature {NONE} -- Implementation
+
+ has_error (l_captcha: RECAPTCHA_API; a_error: READABLE_STRING_32): BOOLEAN
+ do
+ if attached l_captcha.errors as l_errors then
+ l_errors.compare_objects
+ Result := l_errors.has (a_error)
+ end
+ end
+
+end
+
+
diff --git a/library/recaptcha/test/test.ecf b/library/recaptcha/test/test.ecf
new file mode 100644
index 0000000..879c446
--- /dev/null
+++ b/library/recaptcha/test/test.ecf
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /EIFGENs$
+ /CVS$
+ /.svn$
+
+
+
+
diff --git a/modules/auth/auth-safe.ecf b/modules/auth/auth-safe.ecf
index 5824089..29c2183 100644
--- a/modules/auth/auth-safe.ecf
+++ b/modules/auth/auth-safe.ecf
@@ -23,6 +23,7 @@
+
diff --git a/modules/auth/cms_auth_api.e b/modules/auth/cms_auth_api.e
new file mode 100644
index 0000000..22bbf0d
--- /dev/null
+++ b/modules/auth/cms_auth_api.e
@@ -0,0 +1,93 @@
+note
+ description: "Summary description for {CMS_AUTH_API}."
+ author: ""
+ date: "$Date$"
+ revision: "$Revision$"
+
+class
+ CMS_AUTH_API
+
+inherit
+ CMS_MODULE_API
+
+ REFACTORING_HELPER
+
+create {CMS_AUTHENTICATION_MODULE}
+ make_with_storage
+
+feature {NONE} -- Initialization
+
+ make_with_storage (a_api: CMS_API; a_auth_storage: CMS_AUTH_STORAGE_I)
+ -- Create an object with api `a_api' and storage `a_auth_storage'.
+ do
+ auth_storage := a_auth_storage
+ make (a_api)
+ ensure
+ auht_storage_set: auth_storage = a_auth_storage
+ end
+
+feature -- Access
+
+ user_by_name (a_username: READABLE_STRING_32): detachable CMS_USER
+ -- User by name `a_user_name', if any.
+ do
+ Result := auth_storage.user_by_name (a_username)
+ end
+
+ user_by_email (a_email: READABLE_STRING_32): detachable CMS_USER
+ -- User by email `a_email', if any.
+ do
+ Result := auth_storage.user_by_email (a_email)
+ end
+
+ user_by_activation_token (a_token: READABLE_STRING_32): detachable CMS_USER
+ -- User by activation token `a_token'.
+ do
+ Result := auth_storage.user_by_activation_token (a_token)
+ end
+
+
+feature -- Temp User
+
+ new_temp_user (a_user: CMS_TEMPORAL_USER)
+ -- Add a new user `a_user'.
+ require
+ no_id: not a_user.has_id
+ no_hashed_password: a_user.hashed_password = Void
+ do
+ reset_error
+ if
+ attached a_user.password as l_password and then
+ attached a_user.email as l_email
+ then
+ auth_storage.new_temp_user (a_user)
+ error_handler.append (storage.error_handler)
+ else
+ error_handler.add_custom_error (0, "bad new user request", "Missing password or email to create new user!")
+ end
+ end
+
+ remove_activation (a_token: READABLE_STRING_32)
+ -- Remove activation token `a_token', from the storage.
+ do
+ auth_storage.remove_activation (a_token)
+ end
+
+ delete_user (a_user: CMS_TEMPORAL_USER)
+ -- Delete user `a_user'.
+ require
+ has_id: a_user.has_id
+ do
+ reset_error
+ auth_storage.delete_user (a_user)
+ error_handler.append (storage.error_handler)
+ end
+
+feature {CMS_MODULE} -- Access: User auth storage.
+
+ auth_storage: CMS_AUTH_STORAGE_I
+ -- storage interface.
+
+feature -- Access: User Temp
+
+end
diff --git a/modules/auth/cms_authentication_email_service_parameters.e b/modules/auth/cms_authentication_email_service_parameters.e
index efb7b2a..d340cf5 100644
--- a/modules/auth/cms_authentication_email_service_parameters.e
+++ b/modules/auth/cms_authentication_email_service_parameters.e
@@ -88,6 +88,11 @@ feature {NONE} -- Initialization
contact_subject_oauth := "Welcome."
end
+ contact_subject_account_evaluation := "New register, account evalution"
+
+ contact_subject_rejected := "Your account was rejected"
+
+ contact_subject_activated := "Your account was activated"
end
feature -- Access
@@ -101,10 +106,20 @@ feature -- Access
contact_email: IMMUTABLE_STRING_8
-- Contact email.
+ contact_subject_account_evaluation: IMMUTABLE_STRING_8
contact_subject_register: IMMUTABLE_STRING_8
contact_subject_activate: IMMUTABLE_STRING_8
contact_subject_password: IMMUTABLE_STRING_8
contact_subject_oauth: IMMUTABLE_STRING_8
+ contact_subject_rejected: IMMUTABLE_STRING_8
+ contact_subject_activated: IMMUTABLE_STRING_8
+
+
+ account_evaluation: STRING
+ -- Account evaluation template email message.
+ do
+ Result := template_string ("account_evaluation.html", default_template_account_evaluation)
+ end
account_activation: STRING
-- Account activation template email message.
@@ -112,12 +127,24 @@ feature -- Access
Result := template_string ("account_activation.html", default_template_account_activation)
end
+ account_activation_confirmation: STRING
+ -- Account activation confirmation template email message.
+ do
+ Result := template_string ("account_activation_confirmation.html", default_template_account_activation_confirmation)
+ end
+
account_re_activation: STRING
-- Account re_activation template email message.
do
Result := template_string ("accunt_re_activation.html", default_template_account_re_activation)
end
+ account_rejected: STRING
+ -- Account rejected template email message.
+ do
+ Result := template_string ("accunt_rejected.html", default_template_account_rejected)
+ end
+
account_password: STRING
-- Account password template email message.
do
@@ -146,7 +173,7 @@ feature {NONE} -- Implementation: Template
local
p: PATH
do
- p := template_path ("account_activation.html")
+ p := template_path (a_name)
if attached read_template_file (p) as l_content then
Result := l_content
else
@@ -177,6 +204,36 @@ feature {NONE} -- Implementation
feature {NONE} -- Message email
+ default_template_account_evaluation: STRING = "[
+
+
+
+
+ Account Evaluation
+
+
+
+
+
+ Account Evaluation
+ The user $user ($email) wants to register to the site
+
+ This is his/her application.
+ $application
+
+
+ To complete the registration, please click on the following link to activate the user account:
+
+
$activate
+
+ To reject the registration, please click on the following link
+
+
$reject
+
+
+ ]"
+
+
default_template_account_activation: STRING = "[
@@ -188,17 +245,49 @@ feature {NONE} -- Message email
- Thank you for registering at ROC CMS
+ Thank you for applying to ROC CMS $user
- To complete your registration, please click on the following link to activate your account:
-
-
$link
+ We will review your application and send you an email
Thank you for joining us.