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} - - +
+ + + {if isset="$error_application"} + {$error_application/}
+ {/if} +
+ {unless isempty="$recaptcha_site_key"} +
+
+ {/unless} 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.

]" + default_template_account_activation_confirmation: STRING = "[ + + + + + Activation + + + + + +

Your account has been confirmed ROC CMS $email

+ +

Thank you for joining us.

+ + + ]" + + default_template_account_rejected: STRING = "[ + + + + + New Activation + + + + + +

You requested has been rejected, your application does not conform our rules ROC CMS

+ + + ]" + default_template_account_re_activation: STRING = "[ diff --git a/modules/auth/cms_authentication_module.e b/modules/auth/cms_authentication_module.e index 3787b75..b4bba83 100644 --- a/modules/auth/cms_authentication_module.e +++ b/modules/auth/cms_authentication_module.e @@ -8,13 +8,20 @@ class inherit CMS_MODULE + rename + module_api as auth_api redefine setup_hooks, - permissions + permissions, + initialize, + install, + auth_api end CMS_HOOK_AUTO_REGISTER + CMS_HOOK_RESPONSE_ALTER + CMS_HOOK_VALUE_TABLE_ALTER CMS_HOOK_BLOCK @@ -74,6 +81,53 @@ feature -- Access: docs Result := cache_duration = 0 end +feature {CMS_API} -- Module Initialization + + initialize (a_api: CMS_API) + -- + local + l_auth_api: like auth_api + l_user_auth_storage: CMS_AUTH_STORAGE_I + do + Precursor (a_api) + + -- Storage initialization + if attached a_api.storage.as_sql_storage as l_storage_sql then + create {CMS_AUTH_STORAGE_SQL} l_user_auth_storage.make (l_storage_sql) + else + -- FIXME: in case of NULL storage, should Current be disabled? + create {CMS_AUTH_STORAGE_NULL} l_user_auth_storage + end + + -- API initialization + create l_auth_api.make_with_storage (a_api, l_user_auth_storage) + auth_api := l_auth_api + ensure then + auth_api_set: auth_api /= Void + end + + install (api: CMS_API) + do + -- Schema + if attached api.storage.as_sql_storage as l_sql_storage then + if not l_sql_storage.sql_table_exists ("auth_temp_user") then + --| Schema + l_sql_storage.sql_execute_file_script (api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended ("auth_temp_user.sql")), Void) + + if l_sql_storage.has_error then + api.logger.put_error ("Could not initialize database for auth_module", generating_type) + end + end + l_sql_storage.sql_finalize + Precursor {CMS_MODULE}(api) + end + end + +feature {CMS_API} -- Access: API + + auth_api: detachable CMS_AUTH_API + -- + feature -- Router setup_router (a_router: WSF_ROUTER; a_api: CMS_API) @@ -89,6 +143,7 @@ feature -- Router 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/activate/{token}", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_activation (a_api, ?, ?)), a_router.methods_head_get) + a_router.handle ("/account/reject/{token}", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_reject (a_api, ?, ?)), a_router.methods_head_get) a_router.handle ("/account/reactivate", create {WSF_URI_AGENT_HANDLER}.make (agent handle_reactivation (a_api, ?, ?)), a_router.methods_get_post) a_router.handle ("/account/new-password", create {WSF_URI_AGENT_HANDLER}.make (agent handle_new_password (a_api, ?, ?)), a_router.methods_get_post) a_router.handle ("/account/reset-password", create {WSF_URI_AGENT_HANDLER}.make (agent handle_reset_password (a_api, ?, ?)), a_router.methods_get_post) @@ -182,53 +237,82 @@ feature -- Handler local r: CMS_RESPONSE l_user_api: CMS_USER_API - u: CMS_USER + u: CMS_TEMPORAL_USER l_exist: BOOLEAN es: CMS_AUTHENTICATON_EMAIL_SERVICE - l_url: STRING + l_url_activate: STRING + l_url_reject: STRING l_token: STRING + l_captcha_passed: BOOLEAN do create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) - if r.has_permission ("account register") then + if + r.has_permission ("account register") and then + attached auth_api as l_auth_api + 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 + attached {WSF_STRING} req.form_parameter ("email") as l_email and then + attached {WSF_STRING} req.form_parameter ("application") as l_application then l_user_api := api.user_api - if attached l_user_api.user_by_name (l_name.value) then + if attached l_user_api.user_by_name (l_name.value) or else attached l_auth_api.user_by_name (l_name.value) then -- Username already exist. r.set_value ("User name already exists!", "error_name") l_exist := True end - if attached l_user_api.user_by_email (l_email.value) then + if attached l_user_api.user_by_email (l_email.value) or else attached l_auth_api.user_by_email (l_email.value) then -- Emails already exist. r.set_value ("An account is already associated with that email address!", "error_email") l_exist := True end + if attached recaptcha_secret_key (api) as l_recaptcha_key then + if + attached {WSF_STRING} req.form_parameter ("g-recaptcha-response") as l_recaptcha_response and then + is_captcha_verified (l_recaptcha_key, l_recaptcha_response.value) + then + l_captcha_passed := True + else + --| Bad or missing captcha + l_captcha_passed := False + end + else + --| reCaptcha is not setup, so no verification + l_captcha_passed := True + end + if not l_exist then - -- New user + + -- New temp user create u.make (l_name.value) u.set_email (l_email.value) u.set_password (l_password.value) - l_user_api.new_user (u) + u.set_application (l_application.value) + l_auth_api.new_temp_user (u) -- Create activation token l_token := new_token l_user_api.new_activation (l_token, u.id) - l_url := req.absolute_script_url ("/account/activate/" + l_token) + l_url_activate := req.absolute_script_url ("/account/activate/" + l_token) + l_url_reject := req.absolute_script_url ("/account/reject/" + l_token) - -- Send Email + -- 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_application.value, l_url_activate, l_url_reject) + + -- 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_url) - + es.send_contact_email (l_email.value, l_name.value) else r.set_value (l_name.value, "name") r.set_value (l_email.value, "email") + r.set_value (l_application.value, "application") r.set_status_code ({HTTP_CONSTANTS}.bad_request) end end @@ -246,67 +330,127 @@ feature -- Handler r: CMS_RESPONSE l_user_api: CMS_USER_API l_ir: INTERNAL_SERVER_ERROR_CMS_RESPONSE + es: CMS_AUTHENTICATON_EMAIL_SERVICE do - l_user_api := api.user_api - create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) - if attached {WSF_STRING} req.path_parameter ("token") as l_token then + if attached auth_api as l_auth_api then + l_user_api := api.user_api + create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) + if attached {WSF_STRING} req.path_parameter ("token") as l_token then - if attached {CMS_USER} l_user_api.user_by_activation_token (l_token.value) as l_user then - -- Valid user_id - l_user.mark_active - l_user_api.update_user (l_user) - l_user_api.remove_activation (l_token.value) - r.set_main_content ("

Your account "+ l_user.name +" has been activated

") + if attached {CMS_TEMPORAL_USER} l_auth_api.user_by_activation_token (l_token.value) as l_user then + -- Delete temporal User + l_auth_api.delete_user (l_user) + + -- Valid user_id + l_user.set_id (0) + l_user.mark_active + l_user_api.new_user (l_user) + l_auth_api.remove_activation (l_token.value) + + r.set_main_content ("

The account "+ l_user.name +" has been activated

") + -- Send Email + if attached l_user.email as l_email then + create es.make (create {CMS_AUTHENTICATION_EMAIL_SERVICE_PARAMETERS}.make (api)) + write_debug_log (generator + ".handle register: send_contact_activation_confirmation_email") + es.send_contact_activation_confirmation_email (l_email, req.absolute_script_url ("")) + end + else + -- the token does not exist, or it was already used. + r.set_status_code ({HTTP_CONSTANTS}.bad_request) + r.set_main_content ("

The token " + l_token.value +" is not valid " + r.link ("Reactivate Account", "account/reactivate", Void) + "

") + end + r.execute else - -- the token does not exist, or it was already used. - r.set_status_code ({HTTP_CONSTANTS}.bad_request) - r.set_main_content ("

The token " + l_token.value +" is not valid " + r.link ("Reactivate Account", "account/reactivate", Void) + "

") + create l_ir.make (req, res, api) + l_ir.execute end - r.execute else - create l_ir.make (req, res, api) - l_ir.execute + create {INTERNAL_SERVER_ERROR_CMS_RESPONSE} r.make (req, res, api) +-- r.set_main_content ("...") + r.execute end end + handle_reject (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE) + local + r: CMS_RESPONSE + l_user_api: CMS_USER_API + l_ir: INTERNAL_SERVER_ERROR_CMS_RESPONSE + es: CMS_AUTHENTICATON_EMAIL_SERVICE + do + if attached auth_api as l_auth_api then + create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) + if attached {WSF_STRING} req.path_parameter ("token") as l_token then + if attached {CMS_TEMPORAL_USER} l_auth_api.user_by_activation_token (l_token.value) as l_user then + l_auth_api.delete_user (l_user) + r.set_main_content ("

The temporal account for "+ l_user.name +" has been removed

") + -- Send Email + if attached l_user.email as l_email then + create es.make (create {CMS_AUTHENTICATION_EMAIL_SERVICE_PARAMETERS}.make (api)) + write_debug_log (generator + ".handle register: send_contact_activation_reject_email") + es.send_contact_activation_reject_email (l_email, req.absolute_script_url ("")) + end + else + -- the token does not exist, or it was already used. + r.set_status_code ({HTTP_CONSTANTS}.bad_request) + r.set_main_content ("

The token " + l_token.value +" is not valid ") + end + r.execute + else + create l_ir.make (req, res, api) + l_ir.execute + end + else + create {INTERNAL_SERVER_ERROR_CMS_RESPONSE} r.make (req, res, api) + r.execute + end + end + handle_reactivation (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE) local r: CMS_RESPONSE es: CMS_AUTHENTICATON_EMAIL_SERVICE l_user_api: CMS_USER_API l_token: STRING - l_url: STRING + l_url_activate: STRING + l_url_reject: STRING do - create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) - if req.is_post_request_method then - if - attached {WSF_STRING} req.form_parameter ("email") as l_email - then - l_user_api := api.user_api - if attached {CMS_USER} l_user_api.user_by_email (l_email.value) as l_user then - -- User exist create a new token and send a new email. - if l_user.is_active then - r.set_value ("The asociated user to the given email " + l_email.value + " , is already active", "is_active") - r.set_status_code ({HTTP_CONSTANTS}.bad_request) - else - l_token := new_token - l_user_api.new_activation (l_token, l_user.id) - l_url := req.absolute_script_url ("/account/activate/" + l_token) + if attached auth_api as l_auth_api then + create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) + if req.is_post_request_method then + if + attached {WSF_STRING} req.form_parameter ("email") as l_email + then + l_user_api := api.user_api + if attached {CMS_TEMPORAL_USER} l_auth_api.user_by_email (l_email.value) as l_user then + -- User exist create a new token and send a new email. + if l_user.is_active then + r.set_value ("The asociated user to the given email " + l_email.value + " , is already active", "is_active") + r.set_status_code ({HTTP_CONSTANTS}.bad_request) + else + l_token := new_token + l_user_api.new_activation (l_token, l_user.id) + l_url_activate := req.absolute_script_url ("/account/activate/" + l_token) + l_url_reject := req.absolute_script_url ("/account/reject/" + l_token) - -- Send Email - create es.make (create {CMS_AUTHENTICATION_EMAIL_SERVICE_PARAMETERS}.make (api)) - write_debug_log (generator + ".handle register: send_contact_activation_email") - es.send_contact_activation_email (l_email.value, l_url) + -- Send Email to webmaster + if attached l_user.application as l_application then + create es.make (create {CMS_AUTHENTICATION_EMAIL_SERVICE_PARAMETERS}.make (api)) + write_debug_log (generator + ".handle register: send_register_email") + es.send_account_evaluation (l_user, l_application, l_url_activate, l_url_reject) + end + end + else + r.set_value ("The email does not exist or !", "error_email") + r.set_value (l_email.value, "email") + r.set_status_code ({HTTP_CONSTANTS}.bad_request) end - else - r.set_value ("The email does not exist or !", "error_email") - r.set_value (l_email.value, "email") - r.set_status_code ({HTTP_CONSTANTS}.bad_request) end end + else + create {INTERNAL_SERVER_ERROR_CMS_RESPONSE} r.make (req, res, api) end - r.execute end @@ -556,6 +700,9 @@ feature {NONE} -- Block views if a_response.has_permission ("account register") then if a_response.request.is_get_request_method then if attached template_block (a_block_id, a_response) as l_tpl_block then + if attached 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") else debug ("cms") @@ -569,6 +716,9 @@ feature {NONE} -- Block views -- l_tpl_block.set_value (a_response.values.item ("error_email"), "error_email") -- l_tpl_block.set_value (a_response.values.item ("email"), "email") -- l_tpl_block.set_value (a_response.values.item ("name"), "name") + if attached recaptcha_site_key (a_response.api) as l_recaptcha_site_key then + l_tpl_block.set_value (l_recaptcha_site_key, "recaptcha_site_key") + end a_response.add_block (l_tpl_block, "content") else debug ("cms") @@ -693,6 +843,67 @@ feature {NONE} -- Block views end end + +feature -- Recaptcha + + recaptcha_secret_key (api: CMS_API): detachable READABLE_STRING_8 + -- Get recaptcha security key. + local + utf: UTF_CONVERTER + do + if attached api.module_configuration (Current, Void) as cfg then + if + attached cfg.text_item ("recaptcha.secret_key") as l_recaptcha_key and then + not l_recaptcha_key.is_empty + then + Result := utf.utf_32_string_to_utf_8_string_8 (l_recaptcha_key) + end + end + end + + recaptcha_site_key (api: CMS_API): detachable READABLE_STRING_8 + -- Get recaptcha security key. + local + utf: UTF_CONVERTER + do + if attached api.module_configuration (Current, Void) as cfg then + if + attached cfg.text_item ("recaptcha.site_key") as l_recaptcha_key and then + not l_recaptcha_key.is_empty + then + Result := utf.utf_32_string_to_utf_8_string_8 (l_recaptcha_key) + end + end + end + + +feature -- Response Alter + + response_alter (a_response: CMS_RESPONSE) + do + a_response.add_javascript_url ("https://www.google.com/recaptcha/api.js") + end + +feature {NONE} -- Implementation + + is_captcha_verified (a_secret, a_response: READABLE_STRING_8): BOOLEAN + local + api: RECAPTCHA_API + l_errors: STRING + do + write_debug_log (generator + ".is_captcha_verified with response: [" + a_response + "]") + create api.make (a_secret, a_response) + Result := api.verify + if not Result and then attached api.errors as l_api_errors then + create l_errors.make_empty + l_errors.append_character ('%N') + across l_api_errors as ic loop + l_errors.append ( ic.item ) + l_errors.append_character ('%N') + end + write_error_log (generator + ".is_captcha_verified api_errors [" + l_errors + "]") + end + end note copyright: "Copyright (c) 1984-2013, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" diff --git a/modules/auth/cms_authenticaton_email_service.e b/modules/auth/cms_authenticaton_email_service.e index d4a1984..48758f7 100644 --- a/modules/auth/cms_authenticaton_email_service.e +++ b/modules/auth/cms_authenticaton_email_service.e @@ -34,15 +34,34 @@ feature -- Access feature -- Basic Operations - send_contact_email (a_to, a_content: READABLE_STRING_8) - -- Send successful contact message `a_token' to `a_to'. + send_account_evaluation (a_user: CMS_USER; a_application, a_url_activate, a_url_reject: 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 ("$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 ("$activate", a_url_activate) + l_message.replace_substring_all ("$reject", a_url_reject) + send_message (contact_email, contact_email, parameters.contact_subject_account_evaluation, l_message) + end + + + send_contact_email (a_to, a_user: 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 ("$link", a_content) + l_message.replace_substring_all ("$user", a_user) send_message (contact_email, a_to, parameters.contact_subject_register, l_message) end @@ -60,6 +79,33 @@ feature -- Basic Operations end + send_contact_activation_confirmation_email (a_to, a_content: READABLE_STRING_8) + -- Send successful contact 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 ("$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: READABLE_STRING_8) + -- Send successful contact activation reject 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 ("$link", a_content) + send_message (contact_email, a_to, parameters.contact_subject_activate, l_message) + end + + + send_contact_password_email (a_to, a_content: READABLE_STRING_8) -- Send successful contact message `a_token' to `a_to'. require diff --git a/modules/auth/model/cms_temporal_user.e b/modules/auth/model/cms_temporal_user.e new file mode 100644 index 0000000..4ea4af4 --- /dev/null +++ b/modules/auth/model/cms_temporal_user.e @@ -0,0 +1,32 @@ +note + description: "Summary description for {CMS_TEMPORAL_USER}." + date: "$Date$" + revision: "$Revision$" + +class + CMS_TEMPORAL_USER + +inherit + + CMS_USER + +create + make, + make_with_id + +feature -- Access + + application: detachable STRING_32 + -- User application + +feature -- Element change + + set_application (an_application: like application) + -- Assign `application' with `an_application'. + do + application := an_application + ensure + application_assigned: application = an_application + end + +end diff --git a/modules/auth/persistence/cms_auth_storage_i.e b/modules/auth/persistence/cms_auth_storage_i.e new file mode 100644 index 0000000..48851ad --- /dev/null +++ b/modules/auth/persistence/cms_auth_storage_i.e @@ -0,0 +1,75 @@ +note + description: "[ + API to handle OAUTH storage + ]" + date: "$Date$" + revision: "$Revision$" + +deferred class + CMS_AUTH_STORAGE_I + +inherit + SHARED_LOGGER + +feature -- Error Handling + + error_handler: ERROR_HANDLER + -- Error handler. + deferred + end + +feature -- Access: Users + + user_temp_by_id (a_uid: like {CMS_USER}.id; a_consumer_table: READABLE_STRING_GENERAL): detachable CMS_USER + -- Retrieve a user by id `a_uid' for the consumer `a_consumer', if aby. + deferred + end + + user_by_name (a_name: like {CMS_USER}.name): detachable CMS_USER + -- User with name `a_name', if any. + require + a_name /= Void and then not a_name.is_empty + deferred + ensure + same_name: Result /= Void implies a_name ~ Result.name + password: Result /= Void implies (Result.hashed_password /= Void and Result.password = Void) + end + + user_by_email (a_email: like {CMS_USER}.email): detachable CMS_USER + -- User with name `a_email', if any. + deferred + ensure + same_email: Result /= Void implies a_email ~ Result.email + password: Result /= Void implies (Result.hashed_password /= Void and Result.password = Void) + end + + + user_by_activation_token (a_token: READABLE_STRING_32): detachable CMS_USER + -- User with activation token `a_token', if any. + deferred + ensure + password: Result /= Void implies (Result.hashed_password /= Void and Result.password = Void) + end + +feature -- New Temp User + + remove_activation (a_token: READABLE_STRING_32) + -- Remove activation by token `a_token'. + deferred + end + + new_temp_user (a_user: CMS_TEMPORAL_USER) + -- New temp user `a_user'. + require + no_id: not a_user.has_id + deferred + end + + delete_user (a_user: CMS_TEMPORAL_USER) + -- Delete user `a_user'. + require + has_id: a_user.has_id + deferred + end + +end diff --git a/modules/auth/persistence/cms_auth_storage_null.e b/modules/auth/persistence/cms_auth_storage_null.e new file mode 100644 index 0000000..505b558 --- /dev/null +++ b/modules/auth/persistence/cms_auth_storage_null.e @@ -0,0 +1,62 @@ +note + description: "Summary description for {CMS_AUTH_STORAGE_NULL}." + date: "$Date$" + revision: "$Revision$" + +class + CMS_AUTH_STORAGE_NULL + +inherit + + CMS_AUTH_STORAGE_I + + +feature -- Error handler + + error_handler: ERROR_HANDLER + -- Error handler. + do + create Result.make + end + +feature -- Access: Users + + user_temp_by_id (a_uid: like {CMS_USER}.id; a_consumer_table: READABLE_STRING_GENERAL): detachable CMS_USER + -- + do + end + + user_by_name (a_name: like {CMS_USER}.name): detachable CMS_USER + -- + do + end + + user_by_email (a_email: like {CMS_USER}.email): detachable CMS_USER + -- + do + end + + user_by_activation_token (a_token: READABLE_STRING_32): detachable CMS_USER + -- + do + end + +feature -- Temp Users + + remove_activation (a_token: READABLE_STRING_32) + -- . + do + end + + new_temp_user (a_user: CMS_TEMPORAL_USER) + -- + do + end + + delete_user (a_user: CMS_TEMPORAL_USER) + -- + do + end + + +end diff --git a/modules/auth/persistence/cms_auth_storage_sql.e b/modules/auth/persistence/cms_auth_storage_sql.e new file mode 100644 index 0000000..ea2fe44 --- /dev/null +++ b/modules/auth/persistence/cms_auth_storage_sql.e @@ -0,0 +1,256 @@ +note + description: "Summary description for {CMS_AUTH_STORAGE_SQL}." + date: "$Date$" + revision: "$Revision$" + +class + CMS_AUTH_STORAGE_SQL + +inherit + CMS_AUTH_STORAGE_I + + CMS_PROXY_STORAGE_SQL + + CMS_STORAGE_SQL_I + + REFACTORING_HELPER + +create + make + +feature -- Access User Outh + + + user_temp_by_id (a_uid: like {CMS_USER}.id; a_consumer: READABLE_STRING_GENERAL): detachable CMS_USER + -- + local + l_parameters: STRING_TABLE [detachable ANY] + l_string: STRING + do + error_handler.reset + write_information_log (generator + ".user_temp_by_id") + create l_parameters.make (1) + l_parameters.put (a_uid, "uid") + create l_string.make_from_string (select_user_auth_temp_by_id) + sql_query (l_string, l_parameters) + if not has_error and not sql_after then + Result := fetch_user + sql_forth + if not sql_after then + check no_more_than_one: False end + Result := Void + end + end + sql_finalize + end + + user_by_name (a_name: like {CMS_USER}.name): detachable CMS_USER + -- User for the given name `a_name', if any. + local + l_parameters: STRING_TABLE [detachable ANY] + do + error_handler.reset + write_information_log (generator + ".user_by_name") + create l_parameters.make (1) + l_parameters.put (a_name, "name") + sql_query (select_user_by_name, l_parameters) + if not sql_after then + Result := fetch_user + sql_forth + check one_row: sql_after end + end + sql_finalize + end + + user_by_email (a_email: like {CMS_USER}.email): detachable CMS_USER + -- User for the given email `a_email', if any. + local + l_parameters: STRING_TABLE [detachable ANY] + do + error_handler.reset + write_information_log (generator + ".user_by_email") + create l_parameters.make (1) + l_parameters.put (a_email, "email") + sql_query (select_user_by_email, l_parameters) + if not sql_after then + Result := fetch_user + sql_forth + check one_row: sql_after end + end + sql_finalize + end + + user_by_activation_token (a_token: READABLE_STRING_32): detachable CMS_USER + -- User for the given activation token `a_token', if any. + local + l_parameters: STRING_TABLE [detachable ANY] + do + error_handler.reset + write_information_log (generator + ".user_by_activation_token") + create l_parameters.make (1) + l_parameters.put (a_token, "token") + sql_query (select_user_by_activation_token, l_parameters) + if not sql_after then + Result := fetch_user + sql_forth + check one_row: sql_after end + end + sql_finalize + end + + +feature {NONE} -- Implementation: User + + fetch_user: detachable CMS_TEMPORAL_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_password (l_password) + end + if attached sql_read_string (5) as l_email then + Result.set_email (l_email) + end + if attached sql_read_string (6) as l_application then + Result.set_application (l_application) + end + else + check expected_valid_user: False end + end + end + + +feature -- New Temp User + + new_temp_user (a_user: CMS_TEMPORAL_USER) + -- Add a new temp_user `a_user'. + local + l_parameters: STRING_TABLE [detachable ANY] + l_password_salt, l_password_hash: STRING + l_security: SECURITY_PROVIDER + do + error_handler.reset + if + attached a_user.password as l_password and then + attached a_user.email as l_email and then + attached a_user.application as l_application + then + + create l_security + l_password_salt := l_security.salt + l_password_hash := l_security.password_hash (l_password, l_password_salt) + + write_information_log (generator + ".new_temp_user") + create l_parameters.make (4) + l_parameters.put (a_user.name, "name") + l_parameters.put (l_password_hash, "password") + l_parameters.put (l_password_salt, "salt") + l_parameters.put (l_email, "email") + l_parameters.put (l_application, "application") + + sql_begin_transaction + sql_insert (sql_insert_user, l_parameters) + if not error_handler.has_error then + a_user.set_id (last_inserted_user_id) + sql_commit_transaction + else + sql_rollback_transaction + end + sql_finalize + else + -- set error + error_handler.add_custom_error (-1, "bad request" , "Missing password or email") + end + end + + +feature -- Remove Activation + + remove_activation (a_token: READABLE_STRING_32) + -- . + local + l_parameters: STRING_TABLE [detachable ANY] + do + error_handler.reset + sql_begin_transaction + write_information_log (generator + ".remove_activation") + create l_parameters.make (1) + l_parameters.put (a_token, "token") + sql_modify (sql_remove_activation, l_parameters) + sql_commit_transaction + sql_finalize + end + + delete_user (a_user: CMS_TEMPORAL_USER) + -- Delete user `a_user'. + local + l_parameters: STRING_TABLE [detachable ANY] + do + error_handler.reset + sql_begin_transaction + write_information_log (generator + ".delete_user") + create l_parameters.make (1) + l_parameters.put (a_user.id, "uid") + sql_modify (sql_delete_user, l_parameters) + sql_commit_transaction + sql_finalize + end +feature {NONE} -- Implementation + + last_inserted_user_id: INTEGER_64 + -- Last insert user id. + do + error_handler.reset + write_information_log (generator + ".last_inserted_user_id") + sql_query (Sql_last_insert_user_id, Void) + if not sql_after then + Result := sql_read_integer_64 (1) + sql_forth + check one_row: sql_after end + end + sql_finalize + end + +feature {NONE} -- SQL select + + Sql_last_insert_user_id: STRING = "SELECT MAX(uid) FROM auth_temp_user;" + + Select_user_auth_temp_by_id: STRING = "SELECT uid, name, password, salt, email, application FROM auth_temp_user as u where uid=:uid;" + + + sql_insert_user: STRING = "INSERT INTO auth_temp_user (name, password, salt, email, application) VALUES (:name, :password, :salt, :email, :application);" + -- SQL Insert to add a new user. + + Select_user_by_name: STRING = "SELECT uid, name, password, salt, email, application FROM auth_temp_user WHERE name =:name;" + -- Retrieve user by name if exists. + + Select_user_by_email: STRING = "SELECT uid, name, password, salt, email, application FROM auth_temp_user WHERE email =:email;" + -- Retrieve user by email if exists. + + Select_user_by_activation_token: STRING = "SELECT u.uid, u.name, u.password, u.salt, u.email, u.application FROM auth_temp_user as u JOIN users_activations as ua ON ua.uid = u.uid and ua.token = :token;" + -- Retrieve user by activation token if exist. + + Sql_remove_activation: STRING = "DELETE FROM users_activations WHERE token = :token;" + -- Remove activation token. + + Sql_delete_user: STRING = "DELETE FROM auth_temp_user WHERE uid=:uid;" +end diff --git a/modules/auth/site/config/auth.json b/modules/auth/site/config/auth.json new file mode 100644 index 0000000..a81ab66 --- /dev/null +++ b/modules/auth/site/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/modules/auth/site/mail_templates/account_activation.html b/modules/auth/site/mail_templates/account_activation.html index 0ab4c4f..0d404a0 100644 --- a/modules/auth/site/mail_templates/account_activation.html +++ b/modules/auth/site/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/modules/auth/site/mail_templates/account_activation_confirmation.html b/modules/auth/site/mail_templates/account_activation_confirmation.html new file mode 100644 index 0000000..950fccf --- /dev/null +++ b/modules/auth/site/mail_templates/account_activation_confirmation.html @@ -0,0 +1,14 @@ + + + + + Activation + + + + + +

Your account has been confirmed ROC CMS $email

+

Thank you for joining us.

+ + \ No newline at end of file diff --git a/modules/auth/site/mail_templates/account_evaluation.html b/modules/auth/site/mail_templates/account_evaluation.html new file mode 100644 index 0000000..002292d --- /dev/null +++ b/modules/auth/site/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/modules/auth/site/mail_templates/account_rejected.html b/modules/auth/site/mail_templates/account_rejected.html new file mode 100644 index 0000000..9cefb80 --- /dev/null +++ b/modules/auth/site/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/modules/auth/site/scripts/auth_temp_user.tpl b/modules/auth/site/scripts/auth_temp_user.tpl new file mode 100644 index 0000000..38ae29b --- /dev/null +++ b/modules/auth/site/scripts/auth_temp_user.tpl @@ -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/modules/auth/site/templates/block_post_reactivate.tpl b/modules/auth/site/templates/block_post_reactivate.tpl index 09e7206..c76cbb5 100644 --- a/modules/auth/site/templates/block_post_reactivate.tpl +++ b/modules/auth/site/templates/block_post_reactivate.tpl @@ -1,3 +1,3 @@
-

We have send you a new activation code, check your email to activate your account.

+

Thanks for your application, we will review it to activate your account.

diff --git a/modules/auth/site/templates/block_post_register.tpl b/modules/auth/site/templates/block_post_register.tpl index d59f75a..c76cbb5 100644 --- a/modules/auth/site/templates/block_post_register.tpl +++ b/modules/auth/site/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.