Updated Register Module.
Worlflow 1- Register 1.1 Create a new temporal user 1.2 Email to the new User 1.3 Email to Web Master 2 Web Master Review th Account Application 2.1 Accept and Send an confirmation email to the user and remove the temporal user 2.2 Reject the application send a rejection email to the user and remove the temporal Added a new table to save temporal users to review their Application to the site. Updated Register Form with an new input Application and Recaptcha validation. Updated Emails templates and messages. (TODO improve messages) Updated mails templates. Simple messages (Todo improve messages). Added a new handler to reject a user Updated existing hanlders to handler the new workflow.
This commit is contained in:
8
examples/demo/site/modules/auth/config/auth.json
Normal file
8
examples/demo/site/modules/auth/config/auth.json
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"email": "webmaster@eiffel.org",
|
||||||
|
"subject": "Thank you for contacting us",
|
||||||
|
"recaptcha": {
|
||||||
|
"site_key":"6Lex9RMTAAAAAKleC4x6TaRlFcpLbEWgH_U7MSiD",
|
||||||
|
"secret_key":"6Lex9RMTAAAAAAkBczvX5DUiyg_xoM_EthVVgRRx"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,11 +8,7 @@
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<p>Thank you for registering at <a href="$host">ROC CMS</a></p>
|
<p>Thank you for applying to <a href="$host">ROC CMS</a> $user</p>
|
||||||
|
<p>We will review your application and send you a resolution<p>
|
||||||
<p>To complete your registration, please click on this link to activate your account:<p>
|
|
||||||
|
|
||||||
<p><a href="$link">$link</a></p>
|
|
||||||
<p>Thank you for joining us.</p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Activation</title>
|
||||||
|
<meta name="description" content="Activation Confirmation">
|
||||||
|
<meta name="author" content="ROC CMS">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<p>Your account has been confirmed <a href="...">ROC CMS</a></p>
|
||||||
|
<p>Thank you for joining us.</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Account Evaluation</title>
|
||||||
|
<meta name="description" content="Account Evaluation">
|
||||||
|
<meta name="author" content="ROC CMS">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h2> Account Evaluation </h2>
|
||||||
|
<p>The user $user ($email) wants to register to the site <a href="$host">ROC CMS</a></p>
|
||||||
|
|
||||||
|
<blockquote><p>This is his/her application.</p>
|
||||||
|
<p>$application</p>
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
<p>To complete the registration, please click on the following link to activate the user account:<p>
|
||||||
|
|
||||||
|
<p><a href="$activate">$activate</a></p>
|
||||||
|
|
||||||
|
<p>To reject the registration, please click on the following link <p>
|
||||||
|
|
||||||
|
<p><a href="$reject">$reject</a></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>New Activation</title>
|
||||||
|
<meta name="description" content="Application Rejected">
|
||||||
|
<meta name="author" content="ROC CMS">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<p>You requested has been rejected, your application does not conform our rules <a href="...">ROC CMS</a></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
13
examples/demo/site/modules/auth/scripts/auth_temp_user.sql
Normal file
13
examples/demo/site/modules/auth/scripts/auth_temp_user.sql
Normal file
@@ -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`)
|
||||||
|
);
|
||||||
|
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
<div>
|
<div>
|
||||||
<p>Thanks for register, check your email to activate your account.</p>
|
<p>Thanks for your application, we will review it to activate your account.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -20,8 +20,19 @@
|
|||||||
<span><i>{$error_email/}</i></span> <br>
|
<span><i>{$error_email/}</i></span> <br>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<textarea rows="4" cols="50" name="application" id="application" required>
|
||||||
|
{$application/}
|
||||||
|
</textarea>
|
||||||
|
<label for="application">Application Sentence</label>
|
||||||
|
{if isset="$error_application"}
|
||||||
|
<span><i>{$error_application/}</i></span> <br>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{unless isempty="$recaptcha_site_key"}
|
||||||
|
<div class="g-recaptcha" data-sitekey="{$recaptcha_site_key/}"></div>
|
||||||
|
<br/>
|
||||||
|
{/unless}
|
||||||
<button type="submit">Register</button>
|
<button type="submit">Register</button>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -35,12 +35,14 @@ feature {NONE} -- Initialization
|
|||||||
parameters: EMAIL_SERVICE_PARAMETERS
|
parameters: EMAIL_SERVICE_PARAMETERS
|
||||||
-- Associated parameters.
|
-- Associated parameters.
|
||||||
|
|
||||||
admin_email: IMMUTABLE_STRING_8
|
|
||||||
-- Site admin's email.
|
|
||||||
|
|
||||||
mailer: NOTIFICATION_MAILER
|
mailer: NOTIFICATION_MAILER
|
||||||
-- SMTP protocol.
|
-- SMTP protocol.
|
||||||
|
|
||||||
|
feature -- Access
|
||||||
|
|
||||||
|
admin_email: IMMUTABLE_STRING_8
|
||||||
|
-- Site admin's email.
|
||||||
|
|
||||||
feature -- Basic Operations
|
feature -- Basic Operations
|
||||||
|
|
||||||
send_internal_email (a_content: READABLE_STRING_GENERAL)
|
send_internal_email (a_content: READABLE_STRING_GENERAL)
|
||||||
|
|||||||
4
library/recaptcha/Readme.md
Normal file
4
library/recaptcha/Readme.md
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
Recaptcha Eiffel Lbrary
|
||||||
|
|
||||||
|
Based on https://developers.google.com/recaptcha/
|
||||||
|
|
||||||
10
library/recaptcha/license.lic
Normal file
10
library/recaptcha/license.lic
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
${NOTE_KEYWORD}
|
||||||
|
copyright: "2011-${YEAR} Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
|
||||||
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
|
source: "[
|
||||||
|
Eiffel Software
|
||||||
|
5949 Hollister Ave., Goleta, CA 93117 USA
|
||||||
|
Telephone 805-685-1006, Fax 805-685-6869
|
||||||
|
Website http://www.eiffel.com
|
||||||
|
Customer support http://support.eiffel.com
|
||||||
|
]"
|
||||||
20
library/recaptcha/recaptcha-safe.ecf
Normal file
20
library/recaptcha/recaptcha-safe.ecf
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||||
|
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="recaptcha" uuid="2A966489-284A-48A0-91BC-31E84EA9C3B1" library_target="recaptcha">
|
||||||
|
<target name="recaptcha">
|
||||||
|
<root all_classes="true"/>
|
||||||
|
<file_rule>
|
||||||
|
<exclude>/.git$</exclude>
|
||||||
|
<exclude>/EIFGENs$</exclude>
|
||||||
|
<exclude>/CVS$</exclude>
|
||||||
|
<exclude>/.svn$</exclude>
|
||||||
|
</file_rule>
|
||||||
|
<option warning="true" is_obsolete_routine_type="true" void_safety="all">
|
||||||
|
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||||
|
</option>
|
||||||
|
<setting name="console_application" value="true"/>
|
||||||
|
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||||
|
<library name="http_client_extension" location="$ISE_LIBRARY\unstable\library\web\cms\library\http_client_extension\http_client_extension-safe.ecf"/>
|
||||||
|
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json-safe.ecf" readonly="false"/>
|
||||||
|
<cluster name="recaptcha" location=".\src\" recursive="true"/>
|
||||||
|
</target>
|
||||||
|
</system>
|
||||||
22
library/recaptcha/recaptcha.ecf
Normal file
22
library/recaptcha/recaptcha.ecf
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||||
|
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="recaptcha" uuid="2A966489-284A-48A0-91BC-31E84EA9C3B1" library_target="recaptcha">
|
||||||
|
<target name="recaptcha">
|
||||||
|
<root all_classes="true"/>
|
||||||
|
<file_rule>
|
||||||
|
<exclude>/.git$</exclude>
|
||||||
|
<exclude>/EIFGENs$</exclude>
|
||||||
|
<exclude>/CVS$</exclude>
|
||||||
|
<exclude>/.svn$</exclude>
|
||||||
|
</file_rule>
|
||||||
|
<option warning="true" void_safety="none">
|
||||||
|
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||||
|
</option>
|
||||||
|
<setting name="console_application" value="true"/>
|
||||||
|
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
|
||||||
|
<library name="base_extension" location="$ISE_LIBRARY\library\base_extension\base_extension.ecf"/>
|
||||||
|
<library name="http_client_extension" location="$ISE_LIBRARY\unstable\library\web\cms\library\http_client_extension\http_client_extension.ecf"/>
|
||||||
|
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json.ecf" readonly="false"/>
|
||||||
|
<cluster name="recaptcha" location=".\src\" recursive="true">
|
||||||
|
</cluster>
|
||||||
|
</target>
|
||||||
|
</system>
|
||||||
147
library/recaptcha/src/recaptcha_api.e
Normal file
147
library/recaptcha/src/recaptcha_api.e
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
note
|
||||||
|
description: "[
|
||||||
|
Simple API to call {RECAPTCHA} Google API.
|
||||||
|
Example call:
|
||||||
|
https://www.google.com/recaptcha/api/siteverify?secret=your_secret&response=response_string&remoteip=user_ip_address
|
||||||
|
]"
|
||||||
|
date: "$Date: 2015-01-28 11:44:15 -0300 (mi. 28 de ene. de 2015) $"
|
||||||
|
revision: "$Revision: 96551 $"
|
||||||
|
EIS: "name=RECAPTCHA", "src=https://developers.google.com/recaptcha/", "protocol=uri"
|
||||||
|
EIS: "name=RECAPTCHA API verify", "src=https://developers.google.com/recaptcha/docs/verify", "protocol=uri"
|
||||||
|
|
||||||
|
class
|
||||||
|
RECAPTCHA_API
|
||||||
|
|
||||||
|
create
|
||||||
|
make
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
make (a_secret_key, a_response: READABLE_STRING_8)
|
||||||
|
-- Create an object Recaptcha with secret key `a_secret_key' and response token `a_response'.
|
||||||
|
do
|
||||||
|
secret := a_secret_key
|
||||||
|
response := a_response
|
||||||
|
ensure
|
||||||
|
secret_set: secret.same_string (a_secret_key)
|
||||||
|
response_set: response.same_string (a_response)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Access
|
||||||
|
|
||||||
|
base_uri: STRING_8 = "https://www.google.com/recaptcha/api/siteverify"
|
||||||
|
-- Recaptcha base URI
|
||||||
|
|
||||||
|
secret: READABLE_STRING_8
|
||||||
|
-- Required. The shared key between your site and ReCAPTCHA.
|
||||||
|
|
||||||
|
response: READABLE_STRING_8
|
||||||
|
-- Required. The user response token provided by the reCAPTCHA to the user and provided to your site on.
|
||||||
|
|
||||||
|
remoteip: detachable READABLE_STRING_8
|
||||||
|
-- Optional. The user's IP address.
|
||||||
|
|
||||||
|
feature -- Status Reports
|
||||||
|
|
||||||
|
errors: detachable LIST [READABLE_STRING_8]
|
||||||
|
-- optional table of error codes
|
||||||
|
-- missing-input-secret The secret parameter is missing.
|
||||||
|
-- invalid-input-secret The secret parameter is invalid or malformed.
|
||||||
|
-- missing-input-response The response parameter is missing.
|
||||||
|
-- invalid-input-response The response parameter is invalid or malformed.
|
||||||
|
|
||||||
|
feature -- Change Element
|
||||||
|
|
||||||
|
set_remoteip (a_remoteip: READABLE_STRING_8)
|
||||||
|
-- Set `remoteip' with `a_remoteip'.
|
||||||
|
do
|
||||||
|
remoteip := a_remoteip
|
||||||
|
ensure
|
||||||
|
remoteip_set: remoteip = a_remoteip
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- API
|
||||||
|
|
||||||
|
verify: BOOLEAN
|
||||||
|
-- Verify the user's response
|
||||||
|
local
|
||||||
|
l_parser: JSON_PARSER
|
||||||
|
do
|
||||||
|
if attached get as l_response then
|
||||||
|
if attached l_response.body as l_body then
|
||||||
|
create l_parser.make_with_string (l_body)
|
||||||
|
l_parser.parse_content
|
||||||
|
if
|
||||||
|
l_parser.is_parsed and then attached {JSON_OBJECT} l_parser.parsed_json_object as jv and then
|
||||||
|
attached {JSON_BOOLEAN} jv.item ("success") as l_success
|
||||||
|
then
|
||||||
|
Result := l_success.item
|
||||||
|
if not Result and then attached {JSON_ARRAY} jv.item ("error-codes") as l_error_codes then
|
||||||
|
across
|
||||||
|
l_error_codes as c
|
||||||
|
loop
|
||||||
|
if attached {JSON_STRING} c.item as ji then
|
||||||
|
put_error (ji.unescaped_string_32)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
put_error (l_response.status.out)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
put_error ("unknown")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
feature {NONE} -- REST API
|
||||||
|
|
||||||
|
get: detachable RESPONSE
|
||||||
|
-- Reading Data
|
||||||
|
local
|
||||||
|
l_request: REQUEST
|
||||||
|
do
|
||||||
|
create l_request.make ("GET", new_uri)
|
||||||
|
Result := l_request.execute
|
||||||
|
end
|
||||||
|
|
||||||
|
feature {NONE} -- Implementation
|
||||||
|
|
||||||
|
new_uri: STRING_8
|
||||||
|
-- new uri (BaseUri?secret=secret_value&response=response_value[&remoteip=remoteip_value]
|
||||||
|
do
|
||||||
|
create Result.make_from_string (base_uri)
|
||||||
|
Result.append ("?secret=")
|
||||||
|
Result.append (secret)
|
||||||
|
Result.append ("&response=")
|
||||||
|
Result.append (response)
|
||||||
|
if attached remoteip as l_remoteip then
|
||||||
|
Result.append ("&remoteip=" + l_remoteip)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
put_error (a_code: READABLE_STRING_GENERAL)
|
||||||
|
local
|
||||||
|
l_errors: like errors
|
||||||
|
utf: UTF_CONVERTER
|
||||||
|
do
|
||||||
|
l_errors := errors
|
||||||
|
if l_errors = Void then
|
||||||
|
create {ARRAYED_LIST [STRING]} l_errors.make (1)
|
||||||
|
errors := l_errors
|
||||||
|
end
|
||||||
|
l_errors.force (utf.utf_32_string_to_utf_8_string_8 (a_code))
|
||||||
|
end
|
||||||
|
|
||||||
|
note
|
||||||
|
copyright: "2011-2015 Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
|
||||||
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
|
source: "[
|
||||||
|
Eiffel Software
|
||||||
|
5949 Hollister Ave., Goleta, CA 93117 USA
|
||||||
|
Telephone 805-685-1006, Fax 805-685-6869
|
||||||
|
Website http://www.eiffel.com
|
||||||
|
Customer support http://support.eiffel.com
|
||||||
|
]"
|
||||||
|
|
||||||
|
end
|
||||||
61
library/recaptcha/test/application.e
Normal file
61
library/recaptcha/test/application.e
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
note
|
||||||
|
description : "test application root class"
|
||||||
|
date : "$Date: 2015-01-14 15:37:57 -0300 (mi. 14 de ene. de 2015) $"
|
||||||
|
revision : "$Revision: 96458 $"
|
||||||
|
|
||||||
|
class
|
||||||
|
APPLICATION
|
||||||
|
|
||||||
|
inherit
|
||||||
|
ARGUMENTS
|
||||||
|
|
||||||
|
create
|
||||||
|
make
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
make
|
||||||
|
-- Run application.
|
||||||
|
do
|
||||||
|
test_invalid_input
|
||||||
|
test_missing_input
|
||||||
|
test_missing_key_input
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
test_invalid_input
|
||||||
|
-- invalid-input-response
|
||||||
|
local
|
||||||
|
l_captcha: RECAPTCHA_API
|
||||||
|
do
|
||||||
|
create l_captcha.make ("","234")
|
||||||
|
check
|
||||||
|
not_true:not l_captcha.verify
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
test_missing_input
|
||||||
|
-- missing-input-response
|
||||||
|
local
|
||||||
|
l_captcha: RECAPTCHA_API
|
||||||
|
do
|
||||||
|
create l_captcha.make ("key","")
|
||||||
|
check
|
||||||
|
not_true:not l_captcha.verify
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
test_missing_key_input
|
||||||
|
-- missing-input-response
|
||||||
|
-- invalid-input-response
|
||||||
|
local
|
||||||
|
l_captcha: RECAPTCHA_API
|
||||||
|
do
|
||||||
|
create l_captcha.make ("","")
|
||||||
|
l_captcha.set_remoteip("localhost")
|
||||||
|
check
|
||||||
|
not_true:not l_captcha.verify
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
69
library/recaptcha/test/recaptcha_api_test_set.e
Normal file
69
library/recaptcha/test/recaptcha_api_test_set.e
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
note
|
||||||
|
description: "[
|
||||||
|
Eiffel tests that can be executed by testing tool.
|
||||||
|
]"
|
||||||
|
author: "EiffelStudio test wizard"
|
||||||
|
date: "$Date: 2015-01-14 15:37:57 -0300 (mi. 14 de ene. de 2015) $"
|
||||||
|
revision: "$Revision: 96458 $"
|
||||||
|
testing: "type/manual"
|
||||||
|
|
||||||
|
class
|
||||||
|
RECAPTCHA_API_TEST_SET
|
||||||
|
|
||||||
|
inherit
|
||||||
|
EQA_TEST_SET
|
||||||
|
|
||||||
|
feature -- Test routines
|
||||||
|
|
||||||
|
test_invalid_input
|
||||||
|
-- invalid-input-response
|
||||||
|
local
|
||||||
|
l_captcha: RECAPTCHA_API
|
||||||
|
do
|
||||||
|
create l_captcha.make ("","234")
|
||||||
|
check
|
||||||
|
not_true:not l_captcha.verify
|
||||||
|
end
|
||||||
|
assert ("Not true", not l_captcha.verify)
|
||||||
|
assert ("Has error invalid-input-response",has_error (l_captcha,"invalid-input-response"))
|
||||||
|
end
|
||||||
|
|
||||||
|
test_missing_input
|
||||||
|
-- missing-input-response
|
||||||
|
local
|
||||||
|
l_captcha: RECAPTCHA_API
|
||||||
|
do
|
||||||
|
create l_captcha.make ("key","")
|
||||||
|
check
|
||||||
|
not_true:not l_captcha.verify
|
||||||
|
end
|
||||||
|
assert ("Not true", not l_captcha.verify)
|
||||||
|
assert ("Has error missing-input-response",has_error (l_captcha,"missing-input-response"))
|
||||||
|
end
|
||||||
|
|
||||||
|
test_missing_key_input
|
||||||
|
-- missing-input-response
|
||||||
|
-- invalid-input-response
|
||||||
|
local
|
||||||
|
l_captcha: RECAPTCHA_API
|
||||||
|
do
|
||||||
|
create l_captcha.make ("","")
|
||||||
|
l_captcha.set_remoteip("localhost")
|
||||||
|
assert ("Not true", not l_captcha.verify)
|
||||||
|
assert ("Has error missing-input-response",has_error (l_captcha,"missing-input-response"))
|
||||||
|
assert ("Has error invalid-input-response",has_error (l_captcha,"invalid-input-response"))
|
||||||
|
end
|
||||||
|
|
||||||
|
feature {NONE} -- Implementation
|
||||||
|
|
||||||
|
has_error (l_captcha: RECAPTCHA_API; a_error: READABLE_STRING_32): BOOLEAN
|
||||||
|
do
|
||||||
|
if attached l_captcha.errors as l_errors then
|
||||||
|
l_errors.compare_objects
|
||||||
|
Result := l_errors.has (a_error)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
21
library/recaptcha/test/test.ecf
Normal file
21
library/recaptcha/test/test.ecf
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||||
|
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="test" uuid="CE9FCE69-EE0A-4028-AA02-BD9F8ABA7586">
|
||||||
|
<target name="test">
|
||||||
|
<root class="APPLICATION" feature="make"/>
|
||||||
|
<option warning="true" void_safety="transitional">
|
||||||
|
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||||
|
</option>
|
||||||
|
<setting name="console_application" value="true"/>
|
||||||
|
<precompile name="base_pre" location="$ISE_PRECOMP\base-safe.ecf"/>
|
||||||
|
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||||
|
<library name="recaptcha" location="..\recaptcha-safe.ecf" readonly="false"/>
|
||||||
|
<library name="testing" location="$ISE_LIBRARY\library\testing\testing-safe.ecf"/>
|
||||||
|
<cluster name="test" location=".\" recursive="true">
|
||||||
|
<file_rule>
|
||||||
|
<exclude>/EIFGENs$</exclude>
|
||||||
|
<exclude>/CVS$</exclude>
|
||||||
|
<exclude>/.svn$</exclude>
|
||||||
|
</file_rule>
|
||||||
|
</cluster>
|
||||||
|
</target>
|
||||||
|
</system>
|
||||||
@@ -23,6 +23,7 @@
|
|||||||
<library name="error" location="$ISE_LIBRARY\contrib\library\utility\general\error\error-safe.ecf"/>
|
<library name="error" location="$ISE_LIBRARY\contrib\library\utility\general\error\error-safe.ecf"/>
|
||||||
|
|
||||||
<library name="email_service" location="..\..\library\email\email-safe.ecf"/>
|
<library name="email_service" location="..\..\library\email\email-safe.ecf"/>
|
||||||
|
<library name="recaptcha" location="..\..\library\recaptcha\recaptcha-safe.ecf"/>
|
||||||
|
|
||||||
<library name="apis" location="$ISE_LIBRARY\contrib\library\web\authentication\oauth\cypress\consumer\apis\apis.ecf" readonly="false"/>
|
<library name="apis" location="$ISE_LIBRARY\contrib\library\web\authentication\oauth\cypress\consumer\apis\apis.ecf" readonly="false"/>
|
||||||
<library name="cypress_consumer" location="$ISE_LIBRARY\contrib\library\web\authentication\oauth\cypress\consumer-safe.ecf" readonly="false"/>
|
<library name="cypress_consumer" location="$ISE_LIBRARY\contrib\library\web\authentication\oauth\cypress\consumer-safe.ecf" readonly="false"/>
|
||||||
|
|||||||
93
modules/auth/cms_auth_api.e
Normal file
93
modules/auth/cms_auth_api.e
Normal file
@@ -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
|
||||||
@@ -88,6 +88,11 @@ feature {NONE} -- Initialization
|
|||||||
contact_subject_oauth := "Welcome."
|
contact_subject_oauth := "Welcome."
|
||||||
end
|
end
|
||||||
|
|
||||||
|
contact_subject_account_evaluation := "New register, account evalution"
|
||||||
|
|
||||||
|
contact_subject_rejected := "Your account was rejected"
|
||||||
|
|
||||||
|
contact_subject_activated := "Your account was activated"
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Access
|
feature -- Access
|
||||||
@@ -101,10 +106,20 @@ feature -- Access
|
|||||||
contact_email: IMMUTABLE_STRING_8
|
contact_email: IMMUTABLE_STRING_8
|
||||||
-- Contact email.
|
-- Contact email.
|
||||||
|
|
||||||
|
contact_subject_account_evaluation: IMMUTABLE_STRING_8
|
||||||
contact_subject_register: IMMUTABLE_STRING_8
|
contact_subject_register: IMMUTABLE_STRING_8
|
||||||
contact_subject_activate: IMMUTABLE_STRING_8
|
contact_subject_activate: IMMUTABLE_STRING_8
|
||||||
contact_subject_password: IMMUTABLE_STRING_8
|
contact_subject_password: IMMUTABLE_STRING_8
|
||||||
contact_subject_oauth: IMMUTABLE_STRING_8
|
contact_subject_oauth: IMMUTABLE_STRING_8
|
||||||
|
contact_subject_rejected: IMMUTABLE_STRING_8
|
||||||
|
contact_subject_activated: IMMUTABLE_STRING_8
|
||||||
|
|
||||||
|
|
||||||
|
account_evaluation: STRING
|
||||||
|
-- Account evaluation template email message.
|
||||||
|
do
|
||||||
|
Result := template_string ("account_evaluation.html", default_template_account_evaluation)
|
||||||
|
end
|
||||||
|
|
||||||
account_activation: STRING
|
account_activation: STRING
|
||||||
-- Account activation template email message.
|
-- Account activation template email message.
|
||||||
@@ -112,12 +127,24 @@ feature -- Access
|
|||||||
Result := template_string ("account_activation.html", default_template_account_activation)
|
Result := template_string ("account_activation.html", default_template_account_activation)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
account_activation_confirmation: STRING
|
||||||
|
-- Account activation confirmation template email message.
|
||||||
|
do
|
||||||
|
Result := template_string ("account_activation_confirmation.html", default_template_account_activation_confirmation)
|
||||||
|
end
|
||||||
|
|
||||||
account_re_activation: STRING
|
account_re_activation: STRING
|
||||||
-- Account re_activation template email message.
|
-- Account re_activation template email message.
|
||||||
do
|
do
|
||||||
Result := template_string ("accunt_re_activation.html", default_template_account_re_activation)
|
Result := template_string ("accunt_re_activation.html", default_template_account_re_activation)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
account_rejected: STRING
|
||||||
|
-- Account rejected template email message.
|
||||||
|
do
|
||||||
|
Result := template_string ("accunt_rejected.html", default_template_account_rejected)
|
||||||
|
end
|
||||||
|
|
||||||
account_password: STRING
|
account_password: STRING
|
||||||
-- Account password template email message.
|
-- Account password template email message.
|
||||||
do
|
do
|
||||||
@@ -146,7 +173,7 @@ feature {NONE} -- Implementation: Template
|
|||||||
local
|
local
|
||||||
p: PATH
|
p: PATH
|
||||||
do
|
do
|
||||||
p := template_path ("account_activation.html")
|
p := template_path (a_name)
|
||||||
if attached read_template_file (p) as l_content then
|
if attached read_template_file (p) as l_content then
|
||||||
Result := l_content
|
Result := l_content
|
||||||
else
|
else
|
||||||
@@ -177,6 +204,36 @@ feature {NONE} -- Implementation
|
|||||||
|
|
||||||
feature {NONE} -- Message email
|
feature {NONE} -- Message email
|
||||||
|
|
||||||
|
default_template_account_evaluation: STRING = "[
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Account Evaluation</title>
|
||||||
|
<meta name="description" content="Account Evaluation">
|
||||||
|
<meta name="author" content="ROC CMS">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h2> Account Evaluation </h2>
|
||||||
|
<p>The user $user ($email) wants to register to the site</p>
|
||||||
|
|
||||||
|
<blockquote><p>This is his/her application.</p>
|
||||||
|
<p>$application</p>
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
<p>To complete the registration, please click on the following link to activate the user account:<p>
|
||||||
|
|
||||||
|
<p><a href="$activate">$activate</a></p>
|
||||||
|
|
||||||
|
<p>To reject the registration, please click on the following link <p>
|
||||||
|
|
||||||
|
<p><a href="$reject">$reject</a></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
]"
|
||||||
|
|
||||||
|
|
||||||
default_template_account_activation: STRING = "[
|
default_template_account_activation: STRING = "[
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
@@ -188,17 +245,49 @@ feature {NONE} -- Message email
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<p>Thank you for registering at <a href="...">ROC CMS</a></p>
|
<p>Thank you for applying to <a href="...">ROC CMS</a> $user</p>
|
||||||
|
|
||||||
<p>To complete your registration, please click on the following link to activate your account:<p>
|
<p>We will review your application and send you an email<p>
|
||||||
|
|
||||||
<p><a href="$link">$link</a></p>
|
|
||||||
<p>Thank you for joining us.</p>
|
<p>Thank you for joining us.</p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
]"
|
]"
|
||||||
|
|
||||||
|
|
||||||
|
default_template_account_activation_confirmation: STRING = "[
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Activation</title>
|
||||||
|
<meta name="description" content="Activation Confirmation">
|
||||||
|
<meta name="author" content="ROC CMS">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<p>Your account has been confirmed <a href="...">ROC CMS</a> $email</p>
|
||||||
|
|
||||||
|
<p>Thank you for joining us.</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
]"
|
||||||
|
|
||||||
|
default_template_account_rejected: STRING = "[
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>New Activation</title>
|
||||||
|
<meta name="description" content="Application Rejected">
|
||||||
|
<meta name="author" content="ROC CMS">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<p>You requested has been rejected, your application does not conform our rules <a href="...">ROC CMS</a></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
]"
|
||||||
|
|
||||||
default_template_account_re_activation: STRING = "[
|
default_template_account_re_activation: STRING = "[
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|||||||
@@ -8,13 +8,20 @@ class
|
|||||||
|
|
||||||
inherit
|
inherit
|
||||||
CMS_MODULE
|
CMS_MODULE
|
||||||
|
rename
|
||||||
|
module_api as auth_api
|
||||||
redefine
|
redefine
|
||||||
setup_hooks,
|
setup_hooks,
|
||||||
permissions
|
permissions,
|
||||||
|
initialize,
|
||||||
|
install,
|
||||||
|
auth_api
|
||||||
end
|
end
|
||||||
|
|
||||||
CMS_HOOK_AUTO_REGISTER
|
CMS_HOOK_AUTO_REGISTER
|
||||||
|
|
||||||
|
CMS_HOOK_RESPONSE_ALTER
|
||||||
|
|
||||||
CMS_HOOK_VALUE_TABLE_ALTER
|
CMS_HOOK_VALUE_TABLE_ALTER
|
||||||
|
|
||||||
CMS_HOOK_BLOCK
|
CMS_HOOK_BLOCK
|
||||||
@@ -74,6 +81,53 @@ feature -- Access: docs
|
|||||||
Result := cache_duration = 0
|
Result := cache_duration = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
feature {CMS_API} -- Module Initialization
|
||||||
|
|
||||||
|
initialize (a_api: CMS_API)
|
||||||
|
-- <Precursor>
|
||||||
|
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
|
||||||
|
-- <Precursor>
|
||||||
|
|
||||||
feature -- Router
|
feature -- Router
|
||||||
|
|
||||||
setup_router (a_router: WSF_ROUTER; a_api: CMS_API)
|
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-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)
|
||||||
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/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/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/new-password", create {WSF_URI_AGENT_HANDLER}.make (agent handle_new_password (a_api, ?, ?)), a_router.methods_get_post)
|
||||||
a_router.handle ("/account/reset-password", create {WSF_URI_AGENT_HANDLER}.make (agent handle_reset_password (a_api, ?, ?)), a_router.methods_get_post)
|
a_router.handle ("/account/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
|
local
|
||||||
r: CMS_RESPONSE
|
r: CMS_RESPONSE
|
||||||
l_user_api: CMS_USER_API
|
l_user_api: CMS_USER_API
|
||||||
u: CMS_USER
|
u: CMS_TEMPORAL_USER
|
||||||
l_exist: BOOLEAN
|
l_exist: BOOLEAN
|
||||||
es: CMS_AUTHENTICATON_EMAIL_SERVICE
|
es: CMS_AUTHENTICATON_EMAIL_SERVICE
|
||||||
l_url: STRING
|
l_url_activate: STRING
|
||||||
|
l_url_reject: STRING
|
||||||
l_token: STRING
|
l_token: STRING
|
||||||
|
l_captcha_passed: BOOLEAN
|
||||||
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") and then
|
||||||
|
attached auth_api as l_auth_api
|
||||||
|
then
|
||||||
if req.is_post_request_method then
|
if req.is_post_request_method then
|
||||||
if
|
if
|
||||||
attached {WSF_STRING} req.form_parameter ("name") as l_name and then
|
attached {WSF_STRING} req.form_parameter ("name") as l_name and then
|
||||||
attached {WSF_STRING} req.form_parameter ("password") as l_password and then
|
attached {WSF_STRING} req.form_parameter ("password") as l_password and then
|
||||||
attached {WSF_STRING} req.form_parameter ("email") as l_email
|
attached {WSF_STRING} req.form_parameter ("email") as l_email and then
|
||||||
|
attached {WSF_STRING} req.form_parameter ("application") as l_application
|
||||||
then
|
then
|
||||||
l_user_api := api.user_api
|
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.
|
-- Username already exist.
|
||||||
r.set_value ("User name already exists!", "error_name")
|
r.set_value ("User name already exists!", "error_name")
|
||||||
l_exist := True
|
l_exist := True
|
||||||
end
|
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.
|
-- Emails already exist.
|
||||||
r.set_value ("An account is already associated with that email address!", "error_email")
|
r.set_value ("An account is already associated with that email address!", "error_email")
|
||||||
l_exist := True
|
l_exist := True
|
||||||
end
|
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
|
if not l_exist then
|
||||||
-- New user
|
|
||||||
|
-- New temp user
|
||||||
create u.make (l_name.value)
|
create u.make (l_name.value)
|
||||||
u.set_email (l_email.value)
|
u.set_email (l_email.value)
|
||||||
u.set_password (l_password.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
|
-- Create activation token
|
||||||
l_token := new_token
|
l_token := new_token
|
||||||
l_user_api.new_activation (l_token, u.id)
|
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))
|
create es.make (create {CMS_AUTHENTICATION_EMAIL_SERVICE_PARAMETERS}.make (api))
|
||||||
write_debug_log (generator + ".handle register: send_contact_email")
|
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
|
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 (l_email.value, "email")
|
||||||
|
r.set_value (l_application.value, "application")
|
||||||
r.set_status_code ({HTTP_CONSTANTS}.bad_request)
|
r.set_status_code ({HTTP_CONSTANTS}.bad_request)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -246,17 +330,30 @@ 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
|
||||||
do
|
do
|
||||||
|
if attached auth_api as l_auth_api then
|
||||||
l_user_api := api.user_api
|
l_user_api := api.user_api
|
||||||
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
|
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
|
||||||
if attached {WSF_STRING} req.path_parameter ("token") as l_token then
|
if 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
|
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
|
-- Valid user_id
|
||||||
|
l_user.set_id (0)
|
||||||
l_user.mark_active
|
l_user.mark_active
|
||||||
l_user_api.update_user (l_user)
|
l_user_api.new_user (l_user)
|
||||||
l_user_api.remove_activation (l_token.value)
|
l_auth_api.remove_activation (l_token.value)
|
||||||
r.set_main_content ("<p> Your account <i>"+ l_user.name +"</i> has been activated</p>")
|
|
||||||
|
r.set_main_content ("<p> The account <i>"+ l_user.name +"</i> has been activated</p>")
|
||||||
|
-- Send Email
|
||||||
|
if attached l_user.email as l_email then
|
||||||
|
create es.make (create {CMS_AUTHENTICATION_EMAIL_SERVICE_PARAMETERS}.make (api))
|
||||||
|
write_debug_log (generator + ".handle register: send_contact_activation_confirmation_email")
|
||||||
|
es.send_contact_activation_confirmation_email (l_email, req.absolute_script_url (""))
|
||||||
|
end
|
||||||
else
|
else
|
||||||
-- the token does not exist, or it was already used.
|
-- the token does not exist, or it was already used.
|
||||||
r.set_status_code ({HTTP_CONSTANTS}.bad_request)
|
r.set_status_code ({HTTP_CONSTANTS}.bad_request)
|
||||||
@@ -267,24 +364,66 @@ feature -- Handler
|
|||||||
create l_ir.make (req, res, api)
|
create l_ir.make (req, res, api)
|
||||||
l_ir.execute
|
l_ir.execute
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
create {INTERNAL_SERVER_ERROR_CMS_RESPONSE} r.make (req, res, api)
|
||||||
|
-- r.set_main_content ("...")
|
||||||
|
r.execute
|
||||||
|
end
|
||||||
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 ("<p> The temporal account for <i>"+ l_user.name +"</i> has been removed</p>")
|
||||||
|
-- Send Email
|
||||||
|
if attached l_user.email as l_email then
|
||||||
|
create es.make (create {CMS_AUTHENTICATION_EMAIL_SERVICE_PARAMETERS}.make (api))
|
||||||
|
write_debug_log (generator + ".handle register: send_contact_activation_reject_email")
|
||||||
|
es.send_contact_activation_reject_email (l_email, req.absolute_script_url (""))
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- the token does not exist, or it was already used.
|
||||||
|
r.set_status_code ({HTTP_CONSTANTS}.bad_request)
|
||||||
|
r.set_main_content ("<p>The token <i>" + l_token.value +"</i> is not valid ")
|
||||||
|
end
|
||||||
|
r.execute
|
||||||
|
else
|
||||||
|
create l_ir.make (req, res, api)
|
||||||
|
l_ir.execute
|
||||||
|
end
|
||||||
|
else
|
||||||
|
create {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)
|
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_AUTHENTICATON_EMAIL_SERVICE
|
||||||
l_user_api: CMS_USER_API
|
l_user_api: CMS_USER_API
|
||||||
l_token: STRING
|
l_token: STRING
|
||||||
l_url: STRING
|
l_url_activate: STRING
|
||||||
|
l_url_reject: STRING
|
||||||
do
|
do
|
||||||
|
if attached auth_api as l_auth_api then
|
||||||
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
|
||||||
if
|
if
|
||||||
attached {WSF_STRING} req.form_parameter ("email") as l_email
|
attached {WSF_STRING} req.form_parameter ("email") as l_email
|
||||||
then
|
then
|
||||||
l_user_api := api.user_api
|
l_user_api := api.user_api
|
||||||
if attached {CMS_USER} l_user_api.user_by_email (l_email.value) as l_user then
|
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.
|
-- User exist create a new token and send a new email.
|
||||||
if l_user.is_active then
|
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_value ("The asociated user to the given email " + l_email.value + " , is already active", "is_active")
|
||||||
@@ -292,12 +431,15 @@ feature -- Handler
|
|||||||
else
|
else
|
||||||
l_token := new_token
|
l_token := new_token
|
||||||
l_user_api.new_activation (l_token, l_user.id)
|
l_user_api.new_activation (l_token, l_user.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
|
||||||
|
if attached l_user.application as l_application 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_email")
|
write_debug_log (generator + ".handle register: send_register_email")
|
||||||
es.send_contact_activation_email (l_email.value, l_url)
|
es.send_account_evaluation (l_user, l_application, l_url_activate, l_url_reject)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
r.set_value ("The email does not exist or !", "error_email")
|
r.set_value ("The email does not exist or !", "error_email")
|
||||||
@@ -306,7 +448,9 @@ feature -- Handler
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
create {INTERNAL_SERVER_ERROR_CMS_RESPONSE} r.make (req, res, api)
|
||||||
|
end
|
||||||
r.execute
|
r.execute
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -556,6 +700,9 @@ feature {NONE} -- Block views
|
|||||||
if a_response.has_permission ("account register") then
|
if a_response.has_permission ("account register") then
|
||||||
if a_response.request.is_get_request_method then
|
if a_response.request.is_get_request_method then
|
||||||
if attached template_block (a_block_id, a_response) as l_tpl_block then
|
if attached template_block (a_block_id, a_response) as l_tpl_block then
|
||||||
|
if attached recaptcha_site_key (a_response.api) as l_recaptcha_site_key then
|
||||||
|
l_tpl_block.set_value (l_recaptcha_site_key, "recaptcha_site_key")
|
||||||
|
end
|
||||||
a_response.add_block (l_tpl_block, "content")
|
a_response.add_block (l_tpl_block, "content")
|
||||||
else
|
else
|
||||||
debug ("cms")
|
debug ("cms")
|
||||||
@@ -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 ("error_email"), "error_email")
|
||||||
-- l_tpl_block.set_value (a_response.values.item ("email"), "email")
|
-- l_tpl_block.set_value (a_response.values.item ("email"), "email")
|
||||||
-- l_tpl_block.set_value (a_response.values.item ("name"), "name")
|
-- l_tpl_block.set_value (a_response.values.item ("name"), "name")
|
||||||
|
if attached recaptcha_site_key (a_response.api) as l_recaptcha_site_key then
|
||||||
|
l_tpl_block.set_value (l_recaptcha_site_key, "recaptcha_site_key")
|
||||||
|
end
|
||||||
a_response.add_block (l_tpl_block, "content")
|
a_response.add_block (l_tpl_block, "content")
|
||||||
else
|
else
|
||||||
debug ("cms")
|
debug ("cms")
|
||||||
@@ -693,6 +843,67 @@ feature {NONE} -- Block views
|
|||||||
end
|
end
|
||||||
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
|
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)"
|
||||||
|
|||||||
@@ -34,15 +34,34 @@ feature -- Access
|
|||||||
|
|
||||||
feature -- Basic Operations
|
feature -- Basic Operations
|
||||||
|
|
||||||
send_contact_email (a_to, a_content: READABLE_STRING_8)
|
send_account_evaluation (a_user: CMS_USER; a_application, a_url_activate, a_url_reject: READABLE_STRING_8)
|
||||||
-- Send successful contact message `a_token' to `a_to'.
|
-- 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
|
require
|
||||||
attached_to: a_to /= Void
|
attached_to: a_to /= Void
|
||||||
local
|
local
|
||||||
l_message: STRING
|
l_message: STRING
|
||||||
do
|
do
|
||||||
create l_message.make_from_string (parameters.account_activation)
|
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)
|
send_message (contact_email, a_to, parameters.contact_subject_register, l_message)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -60,6 +79,33 @@ feature -- Basic Operations
|
|||||||
end
|
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_contact_password_email (a_to, a_content: READABLE_STRING_8)
|
||||||
-- Send successful contact message `a_token' to `a_to'.
|
-- Send successful contact message `a_token' to `a_to'.
|
||||||
require
|
require
|
||||||
|
|||||||
32
modules/auth/model/cms_temporal_user.e
Normal file
32
modules/auth/model/cms_temporal_user.e
Normal file
@@ -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
|
||||||
75
modules/auth/persistence/cms_auth_storage_i.e
Normal file
75
modules/auth/persistence/cms_auth_storage_i.e
Normal file
@@ -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
|
||||||
62
modules/auth/persistence/cms_auth_storage_null.e
Normal file
62
modules/auth/persistence/cms_auth_storage_null.e
Normal file
@@ -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
|
||||||
|
-- <Precursor>
|
||||||
|
do
|
||||||
|
end
|
||||||
|
|
||||||
|
user_by_name (a_name: like {CMS_USER}.name): detachable CMS_USER
|
||||||
|
-- <Precursor>
|
||||||
|
do
|
||||||
|
end
|
||||||
|
|
||||||
|
user_by_email (a_email: like {CMS_USER}.email): detachable CMS_USER
|
||||||
|
-- <Precursor>
|
||||||
|
do
|
||||||
|
end
|
||||||
|
|
||||||
|
user_by_activation_token (a_token: READABLE_STRING_32): detachable CMS_USER
|
||||||
|
-- <Precursor>
|
||||||
|
do
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Temp Users
|
||||||
|
|
||||||
|
remove_activation (a_token: READABLE_STRING_32)
|
||||||
|
-- <Precursor>.
|
||||||
|
do
|
||||||
|
end
|
||||||
|
|
||||||
|
new_temp_user (a_user: CMS_TEMPORAL_USER)
|
||||||
|
-- <Precursor>
|
||||||
|
do
|
||||||
|
end
|
||||||
|
|
||||||
|
delete_user (a_user: CMS_TEMPORAL_USER)
|
||||||
|
-- <Precursor>
|
||||||
|
do
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
256
modules/auth/persistence/cms_auth_storage_sql.e
Normal file
256
modules/auth/persistence/cms_auth_storage_sql.e
Normal file
@@ -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
|
||||||
|
-- <Precursor>
|
||||||
|
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)
|
||||||
|
-- <Precursor>.
|
||||||
|
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
|
||||||
8
modules/auth/site/config/auth.json
Normal file
8
modules/auth/site/config/auth.json
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"email": "webmaster@eiffel.org",
|
||||||
|
"subject": "Thank you for contacting us",
|
||||||
|
"recaptcha": {
|
||||||
|
"site_key":"6Lex9RMTAAAAAKleC4x6TaRlFcpLbEWgH_U7MSiD",
|
||||||
|
"secret_key":"6Lex9RMTAAAAAAkBczvX5DUiyg_xoM_EthVVgRRx"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,11 +8,7 @@
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<p>Thank you for registering at <a href="$host">ROC CMS</a></p>
|
<p>Thank you for applying to <a href="$host">ROC CMS</a> $user</p>
|
||||||
|
<p>We will review your application and send you a resolution<p>
|
||||||
<p>To complete your registration, please click on this link to activate your account:<p>
|
|
||||||
|
|
||||||
<p><a href="$link">$link</a></p>
|
|
||||||
<p>Thank you for joining us.</p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Activation</title>
|
||||||
|
<meta name="description" content="Activation Confirmation">
|
||||||
|
<meta name="author" content="ROC CMS">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<p>Your account has been confirmed <a href="...">ROC CMS</a> $email</p>
|
||||||
|
<p>Thank you for joining us.</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
26
modules/auth/site/mail_templates/account_evaluation.html
Normal file
26
modules/auth/site/mail_templates/account_evaluation.html
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Account Evaluation</title>
|
||||||
|
<meta name="description" content="Account Evaluation">
|
||||||
|
<meta name="author" content="ROC CMS">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h2> Account Evaluation </h2>
|
||||||
|
<p>The user $user ($email) wants to register to the site <a href="$host">ROC CMS</a></p>
|
||||||
|
|
||||||
|
<blockquote><p>This is his/her application.</p>
|
||||||
|
<p>$application</p>
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
<p>To complete the registration, please click on the following link to activate the user account:<p>
|
||||||
|
|
||||||
|
<p><a href="$activate">$activate</a></p>
|
||||||
|
|
||||||
|
<p>To reject the registration, please click on the following link <p>
|
||||||
|
|
||||||
|
<p><a href="$reject">$reject</a></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
13
modules/auth/site/mail_templates/account_rejected.html
Normal file
13
modules/auth/site/mail_templates/account_rejected.html
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>New Activation</title>
|
||||||
|
<meta name="description" content="Application Rejected">
|
||||||
|
<meta name="author" content="ROC CMS">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<p>You requested has been rejected, your application does not conform our rules <a href="...">ROC CMS</a></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
13
modules/auth/site/scripts/auth_temp_user.tpl
Normal file
13
modules/auth/site/scripts/auth_temp_user.tpl
Normal file
@@ -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`)
|
||||||
|
);
|
||||||
|
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
<div>
|
<div>
|
||||||
<p>We have send you a new activation code, check your email to activate your account.</p>
|
<p>Thanks for your application, we will review it to activate your account.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
<div>
|
<div>
|
||||||
<p>Thanks for register, check your email to activate your account.</p>
|
<p>Thanks for your application, we will review it to activate your account.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user