Updated CMS with Login Module.
-- The module handle basic_auth (at the moment).
-- Handle login, logout, register user, activate/reactivate an account, password recovery.
-- Send notification emails.
CMS Updates
-- Added a new service: email.
-- Updated Basic Auth Module to handle logout based on the browser type.
-- Updated persistence layer to save and remove and query activation token and password token.
-- Updated CMS_USER to handle status {active, not_active, trashed}.
-- Updated MySQL scripts to be in sync with SQLite scripts
This commit is contained in:
@@ -28,6 +28,7 @@
|
|||||||
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
|
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
|
||||||
<library name="wsf_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension-safe.ecf" readonly="false"/>
|
<library name="wsf_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension-safe.ecf" readonly="false"/>
|
||||||
<library name="wsf_html" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf_html\wsf_html-safe.ecf" readonly="false"/>
|
<library name="wsf_html" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf_html\wsf_html-safe.ecf" readonly="false"/>
|
||||||
|
<library name="net" location="$ISE_LIBRARY\library\net\net-safe.ecf"/>
|
||||||
<cluster name="src" location=".\src\" recursive="true"/>
|
<cluster name="src" location=".\src\" recursive="true"/>
|
||||||
</target>
|
</target>
|
||||||
</system>
|
</system>
|
||||||
|
|||||||
1
cms.ecf
1
cms.ecf
@@ -28,6 +28,7 @@
|
|||||||
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf.ecf"/>
|
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf.ecf"/>
|
||||||
<library name="wsf_html" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf_html\wsf_html.ecf" readonly="false"/>
|
<library name="wsf_html" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf_html\wsf_html.ecf" readonly="false"/>
|
||||||
<library name="wsf_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension.ecf" readonly="false"/>
|
<library name="wsf_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension.ecf" readonly="false"/>
|
||||||
|
<library name="net" location="$ISE_LIBRARY\library\net\net.ecf"/>
|
||||||
<cluster name="src" location=".\src\" recursive="true"/>
|
<cluster name="src" location=".\src\" recursive="true"/>
|
||||||
</target>
|
</target>
|
||||||
</system>
|
</system>
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
<library name="cms" location="..\..\cms-safe.ecf" readonly="false"/>
|
<library name="cms" location="..\..\cms-safe.ecf" readonly="false"/>
|
||||||
<library name="cms_app_env" location="..\..\library\app_env\app_env-safe.ecf" readonly="false"/>
|
<library name="cms_app_env" location="..\..\library\app_env\app_env-safe.ecf" readonly="false"/>
|
||||||
<library name="cms_basic_auth_module" location="..\..\modules\basic_auth\basic_auth-safe.ecf" readonly="false"/>
|
<library name="cms_basic_auth_module" location="..\..\modules\basic_auth\basic_auth-safe.ecf" readonly="false"/>
|
||||||
|
<library name="cms_login_module" location="..\..\modules\login\login-safe.ecf" readonly="false"/>
|
||||||
<library name="cms_blog_module" location="modules\blog\cms_blog_module-safe.ecf" readonly="false"/>
|
<library name="cms_blog_module" location="modules\blog\cms_blog_module-safe.ecf" readonly="false"/>
|
||||||
<library name="cms_demo_module" location="modules\demo\cms_demo_module-safe.ecf" readonly="false"/>
|
<library name="cms_demo_module" location="modules\demo\cms_demo_module-safe.ecf" readonly="false"/>
|
||||||
<library name="cms_model" location="..\..\library\model\cms_model-safe.ecf" readonly="false"/>
|
<library name="cms_model" location="..\..\library\model\cms_model-safe.ecf" readonly="false"/>
|
||||||
|
|||||||
5
examples/demo/site/config/login/login.json
Normal file
5
examples/demo/site/config/login/login.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"email": "webmaster@example.com",
|
||||||
|
"subjet": "Thank you for regitering with us",
|
||||||
|
"smtp": "127.0.0.1"
|
||||||
|
}
|
||||||
@@ -31,4 +31,20 @@ CREATE TABLE "role_permissions"(
|
|||||||
"module" VARCHAR(255)
|
"module" VARCHAR(255)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "users_activations" (
|
||||||
|
"aid" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK ("aid" >= 0),
|
||||||
|
"token" VARCHAR(255) NOT NULL,
|
||||||
|
"uid" INTEGER NOT NULL CHECK ("uid" >= 0),
|
||||||
|
"created" DATETIME NOT NULL,
|
||||||
|
CONSTRAINT "token" UNIQUE ("token")
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "users_password_recovery" (
|
||||||
|
"aid" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK ("aid" >= 0),
|
||||||
|
"token" VARCHAR(255) NOT NULL,
|
||||||
|
"uid" INTEGER NOT NULL CHECK ("uid" >= 0),
|
||||||
|
"created" DATETIME NOT NULL,
|
||||||
|
CONSTRAINT "token" UNIQUE ("token")
|
||||||
|
);
|
||||||
|
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
var ROC_AUTH = ROC_AUTH || { };
|
var ROC_AUTH = ROC_AUTH || { };
|
||||||
|
|
||||||
var loginURL = "/login";
|
var loginURL = "/basic_auth_login";
|
||||||
var logoutURL = "/logoff";
|
var logoutURL = "/basic_auth_logoff";
|
||||||
|
|
||||||
var userAgent = navigator.userAgent.toLowerCase();
|
var userAgent = navigator.userAgent.toLowerCase();
|
||||||
var firstLogIn = true;
|
var firstLogIn = true;
|
||||||
|
|
||||||
@@ -305,3 +306,16 @@ ROC_AUTH.create_form = function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
var password = document.getElementById("password")
|
||||||
|
, confirm_password = document.getElementById("confirm_password");
|
||||||
|
|
||||||
|
ROC_AUTH.validatePassword =function(){
|
||||||
|
if(password.value != confirm_password.value) {
|
||||||
|
confirm_password.setCustomValidity("Passwords Don't Match");
|
||||||
|
} else {
|
||||||
|
confirm_password.setCustomValidity('');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
password.onchange = ROC_AUTH.validatePassword();
|
||||||
|
confirm_password.onkeyup = ROC_AUTH.validatePassword;
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
<div>
|
||||||
|
{if isset="$user"}
|
||||||
|
<h3><a href="/basic_auth_logoff">Logout</a> </h3>
|
||||||
|
{/if}
|
||||||
|
{unless isset="$user"}
|
||||||
|
<h3>Login or <a href="/roc-register">Register</a></h3>
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<form action method="POST">
|
||||||
|
<div>
|
||||||
|
<input type="text" name="username" required>
|
||||||
|
<label>Username</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<input type="password" name="password" required>
|
||||||
|
<label>Password</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="button" onclick="ROC_AUTH.login();">Login</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<p>
|
||||||
|
<a href="/new-password">Forgot password?</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/unless}
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<div>
|
||||||
|
<form action="/new-password" method="post">
|
||||||
|
<fieldset>
|
||||||
|
<legend>Require new password</legend>
|
||||||
|
<div>
|
||||||
|
<input type="email" id="email" name="email" value="{$email/}" required/>
|
||||||
|
<label for="email">Email</label>
|
||||||
|
{if isset="$error_email"}
|
||||||
|
<span><i>{$error_email/}</i></span> <br>
|
||||||
|
{/if}
|
||||||
|
<br>
|
||||||
|
</div>
|
||||||
|
<button type="submit">Send</button>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
<div>
|
||||||
|
<p>We have send you a new token code, check your email to generate a new password</p>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
<div>
|
||||||
|
<p>We have send you a new activation code, check your email to activate your account.</p>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
<div>
|
||||||
|
<p>Thanks for register, check your email to activate your account.</p>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
<div>
|
||||||
|
<p>You new password has been saved!</p>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<div>
|
||||||
|
<form action="/reactivate" method="post">
|
||||||
|
<fieldset>
|
||||||
|
<legend>Reactivate Form</legend>
|
||||||
|
<div>
|
||||||
|
<input type="email" id="email" name="email" value="{$email/}" required/>
|
||||||
|
<label for="email">Email</label>
|
||||||
|
{if isset="$error_email"}
|
||||||
|
<span><i>{$error_email/}</i></span> <br>
|
||||||
|
{/if}
|
||||||
|
<br>
|
||||||
|
{if isset="$is_active"}
|
||||||
|
<span><i>{$is_active/}</i></span> <br>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
<button type="submit">Reactivate</button>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<div>
|
||||||
|
<form action="/roc-register" method="post">
|
||||||
|
<fieldset>
|
||||||
|
<legend>Register Form</legend>
|
||||||
|
<div>
|
||||||
|
<input type="text" id="name" name="name" value="{$name/}" required autofocus />
|
||||||
|
<label for="name">Name</label>
|
||||||
|
{if isset="$error_name"}
|
||||||
|
<span><i>{$error_name/}</i></span> <br>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input type="password" id="password" name="password" value="" required/>
|
||||||
|
<label for="password">Password</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input type="email" id="email" name="email" value="{$email/}" required/>
|
||||||
|
<label for="email">Email</label>
|
||||||
|
{if isset="$error_email"}
|
||||||
|
<span><i>{$error_email/}</i></span> <br>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<button type="submit">Register</button>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<div>
|
||||||
|
<form action="/reset-password" method="post">
|
||||||
|
<fieldset>
|
||||||
|
<legend>Generate New Password Form</legend>
|
||||||
|
<div>
|
||||||
|
<input type="text" id="token" name="token" value="{$token/}" required />
|
||||||
|
<label for="token">Token</label>
|
||||||
|
{if isset="$error_token"}
|
||||||
|
<span><i>{$error_token/}</i></span> <br>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input type="password" id="password" name="password" value="" required/>
|
||||||
|
<label for="password">Password</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input type="password" id="confirm_password" name="confirm_password" value="" required/>
|
||||||
|
<label for="password">Confirm Password</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit">Confirm</button>
|
||||||
|
{if isset="$error_password"}
|
||||||
|
<span><i>{$error_password/}</i></span> <br>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
@@ -135,6 +135,11 @@ feature -- CMS setup
|
|||||||
m.enable
|
m.enable
|
||||||
a_setup.register_module (m)
|
a_setup.register_module (m)
|
||||||
|
|
||||||
|
create {LOGIN_MODULE} m.make
|
||||||
|
m.enable
|
||||||
|
a_setup.register_module (m)
|
||||||
|
|
||||||
|
|
||||||
create {BASIC_AUTH_MODULE} m.make
|
create {BASIC_AUTH_MODULE} m.make
|
||||||
if not a_setup.module_with_same_type_registered (m) then
|
if not a_setup.module_with_same_type_registered (m) then
|
||||||
m.enable
|
m.enable
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ feature {NONE} -- Initialization
|
|||||||
initialize
|
initialize
|
||||||
ensure
|
ensure
|
||||||
name_set: name = a_name
|
name_set: name = a_name
|
||||||
|
status_not_active: status = not_active
|
||||||
end
|
end
|
||||||
|
|
||||||
make_with_id (a_id: INTEGER_64)
|
make_with_id (a_id: INTEGER_64)
|
||||||
@@ -38,11 +39,13 @@ feature {NONE} -- Initialization
|
|||||||
initialize
|
initialize
|
||||||
ensure
|
ensure
|
||||||
id_set: id = a_id
|
id_set: id = a_id
|
||||||
|
status_not_active: status = not_active
|
||||||
end
|
end
|
||||||
|
|
||||||
initialize
|
initialize
|
||||||
do
|
do
|
||||||
create creation_date.make_now_utc
|
create creation_date.make_now_utc
|
||||||
|
mark_not_active
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Access
|
feature -- Access
|
||||||
@@ -71,6 +74,13 @@ feature -- Access
|
|||||||
last_login_date: detachable DATE_TIME
|
last_login_date: detachable DATE_TIME
|
||||||
-- User last login.
|
-- User last login.
|
||||||
|
|
||||||
|
status: INTEGER
|
||||||
|
-- Associated status for the current user.
|
||||||
|
-- default: not_active
|
||||||
|
-- active
|
||||||
|
-- trashed
|
||||||
|
|
||||||
|
|
||||||
feature -- Roles
|
feature -- Roles
|
||||||
|
|
||||||
roles: detachable LIST [CMS_USER_ROLE]
|
roles: detachable LIST [CMS_USER_ROLE]
|
||||||
@@ -118,6 +128,12 @@ feature -- Status report
|
|||||||
Result := other /= Void and then id = other.id
|
Result := other /= Void and then id = other.id
|
||||||
end
|
end
|
||||||
|
|
||||||
|
is_active: BOOLEAN
|
||||||
|
-- is the current user active?
|
||||||
|
do
|
||||||
|
Result := status = {CMS_USER}.active
|
||||||
|
end
|
||||||
|
|
||||||
feature -- Change element
|
feature -- Change element
|
||||||
|
|
||||||
set_id (a_id: like id)
|
set_id (a_id: like id)
|
||||||
@@ -225,6 +241,52 @@ feature -- Change element: data
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
feature -- Status change
|
||||||
|
|
||||||
|
mark_not_active
|
||||||
|
-- Set status to not_active
|
||||||
|
do
|
||||||
|
set_status (not_active)
|
||||||
|
ensure
|
||||||
|
status_not_active: status = not_active
|
||||||
|
end
|
||||||
|
|
||||||
|
mark_active
|
||||||
|
-- Set status to active.
|
||||||
|
do
|
||||||
|
set_status (active)
|
||||||
|
ensure
|
||||||
|
status_active: status = active
|
||||||
|
end
|
||||||
|
|
||||||
|
mark_trashed
|
||||||
|
-- Set status to trashed.
|
||||||
|
do
|
||||||
|
set_status (trashed)
|
||||||
|
ensure
|
||||||
|
status_trash: status = trashed
|
||||||
|
end
|
||||||
|
|
||||||
|
set_status (a_status: like status)
|
||||||
|
-- Assign `status' with `a_status'.
|
||||||
|
do
|
||||||
|
status := a_status
|
||||||
|
ensure
|
||||||
|
status_set: status = a_status
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
feature -- User status
|
||||||
|
|
||||||
|
not_active: INTEGER = 0
|
||||||
|
-- The user is not active.
|
||||||
|
|
||||||
|
active: INTEGER = 1
|
||||||
|
-- The user is active
|
||||||
|
|
||||||
|
Trashed: INTEGER = -1
|
||||||
|
-- The user is trashed (soft delete), ready to be deleted/destroyed from storage.
|
||||||
|
|
||||||
invariant
|
invariant
|
||||||
|
|
||||||
id_or_name_set: id > 0 or else not name.is_whitespace
|
id_or_name_set: id > 0 or else not name.is_whitespace
|
||||||
|
|||||||
30
library/persistence/mysql/scripts/core.sql
Normal file
30
library/persistence/mysql/scripts/core.sql
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
BEGIN;
|
||||||
|
|
||||||
|
CREATE TABLE `logs` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`category` VARCHAR(255) NOT NULL,
|
||||||
|
`level` int(11) NOT NULL,
|
||||||
|
`uid` int(11) DEFAULT NULL,
|
||||||
|
`message` text NOT NULL,
|
||||||
|
`info` text,
|
||||||
|
`link` text,
|
||||||
|
`date` datetime NOT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE `custom_values` (
|
||||||
|
`type` VARCHAR(255) NOT NULL,
|
||||||
|
`name` VARCHAR(255) NOT NULL,
|
||||||
|
`value` VARCHAR(255) NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE `path_aliases` (
|
||||||
|
`pid` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`source` varchar(255) NOT NULL,
|
||||||
|
`alias` varchar(255) NOT NULL,
|
||||||
|
`lang` varchar(12) DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`pid`)
|
||||||
|
);
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
@@ -1,163 +0,0 @@
|
|||||||
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
|
|
||||||
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
|
|
||||||
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';
|
|
||||||
|
|
||||||
-- -----------------------------------------------------
|
|
||||||
-- Schema mydb
|
|
||||||
-- -----------------------------------------------------
|
|
||||||
-- -----------------------------------------------------
|
|
||||||
-- Schema cms_dev
|
|
||||||
-- -----------------------------------------------------
|
|
||||||
CREATE SCHEMA IF NOT EXISTS `cms_dev` DEFAULT CHARACTER SET latin1 ;
|
|
||||||
USE `cms_dev` ;
|
|
||||||
|
|
||||||
-- -----------------------------------------------------
|
|
||||||
-- Table `cms_dev`.`users`
|
|
||||||
-- -----------------------------------------------------
|
|
||||||
CREATE TABLE IF NOT EXISTS `cms_dev`.`users` (
|
|
||||||
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
||||||
`username` VARCHAR(100) NOT NULL,
|
|
||||||
`password` VARCHAR(100) NOT NULL,
|
|
||||||
`salt` VARCHAR(100) NOT NULL,
|
|
||||||
`email` VARCHAR(250) NOT NULL,
|
|
||||||
`creation_date` DATETIME NULL DEFAULT NULL,
|
|
||||||
`last_login_date` DATETIME NULL DEFAULT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
UNIQUE INDEX `username` (`username` ASC))
|
|
||||||
ENGINE = InnoDB
|
|
||||||
AUTO_INCREMENT = 2
|
|
||||||
DEFAULT CHARACTER SET = latin1;
|
|
||||||
|
|
||||||
|
|
||||||
-- -----------------------------------------------------
|
|
||||||
-- Table `cms_dev`.`nodes`
|
|
||||||
-- -----------------------------------------------------
|
|
||||||
CREATE TABLE IF NOT EXISTS `cms_dev`.`nodes` (
|
|
||||||
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
||||||
`publication_date` DATE NOT NULL,
|
|
||||||
`creation_date` DATE NOT NULL,
|
|
||||||
`modification_date` DATE NOT NULL,
|
|
||||||
`title` VARCHAR(255) NOT NULL,
|
|
||||||
`summary` TEXT NOT NULL,
|
|
||||||
`content` MEDIUMTEXT NOT NULL,
|
|
||||||
`author_id` INT(10) UNSIGNED NULL DEFAULT NULL,
|
|
||||||
`version` INT(10) UNSIGNED ZEROFILL NULL DEFAULT NULL,
|
|
||||||
`editor_id` INT(10) UNSIGNED NULL DEFAULT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
INDEX `fk_nodes_users1_idx` (`author_id` ASC),
|
|
||||||
INDEX `fk_nodes_users2_idx` (`editor_id` ASC),
|
|
||||||
CONSTRAINT `fk_nodes_users1`
|
|
||||||
FOREIGN KEY (`author_id`)
|
|
||||||
REFERENCES `cms_dev`.`users` (`id`)
|
|
||||||
ON DELETE NO ACTION
|
|
||||||
ON UPDATE NO ACTION,
|
|
||||||
CONSTRAINT `fk_nodes_users2`
|
|
||||||
FOREIGN KEY (`editor_id`)
|
|
||||||
REFERENCES `cms_dev`.`users` (`id`)
|
|
||||||
ON DELETE NO ACTION
|
|
||||||
ON UPDATE NO ACTION)
|
|
||||||
ENGINE = InnoDB
|
|
||||||
AUTO_INCREMENT = 11
|
|
||||||
DEFAULT CHARACTER SET = latin1;
|
|
||||||
|
|
||||||
|
|
||||||
-- -----------------------------------------------------
|
|
||||||
-- Table `cms_dev`.`roles`
|
|
||||||
-- -----------------------------------------------------
|
|
||||||
CREATE TABLE IF NOT EXISTS `cms_dev`.`roles` (
|
|
||||||
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
||||||
`role` VARCHAR(100) NOT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
UNIQUE INDEX `role` (`role` ASC))
|
|
||||||
ENGINE = InnoDB
|
|
||||||
DEFAULT CHARACTER SET = latin1;
|
|
||||||
|
|
||||||
|
|
||||||
-- -----------------------------------------------------
|
|
||||||
-- Table `cms_dev`.`permissions`
|
|
||||||
-- -----------------------------------------------------
|
|
||||||
CREATE TABLE IF NOT EXISTS `cms_dev`.`permissions` (
|
|
||||||
`id` INT(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`name` VARCHAR(45) NOT NULL,
|
|
||||||
`roles_id` INT(10) UNSIGNED NOT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
UNIQUE INDEX `name_UNIQUE` (`name` ASC),
|
|
||||||
INDEX `fk_permissions_roles1_idx` (`roles_id` ASC),
|
|
||||||
CONSTRAINT `fk_permissions_roles1`
|
|
||||||
FOREIGN KEY (`roles_id`)
|
|
||||||
REFERENCES `cms_dev`.`roles` (`id`)
|
|
||||||
ON DELETE NO ACTION
|
|
||||||
ON UPDATE NO ACTION)
|
|
||||||
ENGINE = InnoDB
|
|
||||||
DEFAULT CHARACTER SET = latin1;
|
|
||||||
|
|
||||||
|
|
||||||
-- -----------------------------------------------------
|
|
||||||
-- Table `cms_dev`.`profiles`
|
|
||||||
-- -----------------------------------------------------
|
|
||||||
CREATE TABLE IF NOT EXISTS `cms_dev`.`profiles` (
|
|
||||||
`id` INT(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`key` VARCHAR(45) NOT NULL,
|
|
||||||
`value` VARCHAR(100) NULL DEFAULT NULL,
|
|
||||||
`users_id` INT(10) UNSIGNED NOT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
UNIQUE INDEX `key_UNIQUE` (`key` ASC),
|
|
||||||
INDEX `fk_profiles_users1_idx` (`users_id` ASC),
|
|
||||||
CONSTRAINT `fk_profiles_users1`
|
|
||||||
FOREIGN KEY (`users_id`)
|
|
||||||
REFERENCES `cms_dev`.`users` (`id`)
|
|
||||||
ON DELETE NO ACTION
|
|
||||||
ON UPDATE NO ACTION)
|
|
||||||
ENGINE = InnoDB
|
|
||||||
DEFAULT CHARACTER SET = latin1;
|
|
||||||
|
|
||||||
|
|
||||||
-- -----------------------------------------------------
|
|
||||||
-- Table `cms_dev`.`users_nodes`
|
|
||||||
-- -----------------------------------------------------
|
|
||||||
CREATE TABLE IF NOT EXISTS `cms_dev`.`users_nodes` (
|
|
||||||
`users_id` INT(10) UNSIGNED NOT NULL,
|
|
||||||
`nodes_id` INT(10) UNSIGNED NOT NULL,
|
|
||||||
PRIMARY KEY (`users_id`, `nodes_id`),
|
|
||||||
INDEX `fk_users_has_nodes_nodes1_idx` (`nodes_id` ASC),
|
|
||||||
INDEX `fk_users_has_nodes_users_idx` (`users_id` ASC),
|
|
||||||
CONSTRAINT `fk_users_has_nodes_nodes1`
|
|
||||||
FOREIGN KEY (`nodes_id`)
|
|
||||||
REFERENCES `cms_dev`.`nodes` (`id`)
|
|
||||||
ON DELETE NO ACTION
|
|
||||||
ON UPDATE NO ACTION,
|
|
||||||
CONSTRAINT `fk_users_has_nodes_users`
|
|
||||||
FOREIGN KEY (`users_id`)
|
|
||||||
REFERENCES `cms_dev`.`users` (`id`)
|
|
||||||
ON DELETE NO ACTION
|
|
||||||
ON UPDATE NO ACTION)
|
|
||||||
ENGINE = InnoDB
|
|
||||||
DEFAULT CHARACTER SET = latin1;
|
|
||||||
|
|
||||||
|
|
||||||
-- -----------------------------------------------------
|
|
||||||
-- Table `cms_dev`.`users_roles`
|
|
||||||
-- -----------------------------------------------------
|
|
||||||
CREATE TABLE IF NOT EXISTS `cms_dev`.`users_roles` (
|
|
||||||
`users_id` INT(10) UNSIGNED NOT NULL,
|
|
||||||
`roles_id` INT(10) UNSIGNED NOT NULL,
|
|
||||||
PRIMARY KEY (`users_id`, `roles_id`),
|
|
||||||
INDEX `fk_users_has_roles_roles1_idx` (`roles_id` ASC),
|
|
||||||
INDEX `fk_users_has_roles_users1_idx` (`users_id` ASC),
|
|
||||||
CONSTRAINT `fk_users_has_roles_roles1`
|
|
||||||
FOREIGN KEY (`roles_id`)
|
|
||||||
REFERENCES `cms_dev`.`roles` (`id`)
|
|
||||||
ON DELETE NO ACTION
|
|
||||||
ON UPDATE NO ACTION,
|
|
||||||
CONSTRAINT `fk_users_has_roles_users1`
|
|
||||||
FOREIGN KEY (`users_id`)
|
|
||||||
REFERENCES `cms_dev`.`users` (`id`)
|
|
||||||
ON DELETE NO ACTION
|
|
||||||
ON UPDATE NO ACTION)
|
|
||||||
ENGINE = InnoDB
|
|
||||||
DEFAULT CHARACTER SET = latin1;
|
|
||||||
|
|
||||||
|
|
||||||
SET SQL_MODE=@OLD_SQL_MODE;
|
|
||||||
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
|
|
||||||
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
|
|
||||||
24
library/persistence/mysql/scripts/node.sql
Normal file
24
library/persistence/mysql/scripts/node.sql
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
BEGIN;
|
||||||
|
|
||||||
|
CREATE TABLE nodes (
|
||||||
|
nid INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL CHECK( nid >=0),
|
||||||
|
revision INTEGER,
|
||||||
|
type TEXT NOT NULL,
|
||||||
|
title VARCHAR(255) NOT NULL,
|
||||||
|
summary TEXT,
|
||||||
|
content MEDIUMTEXT NOT NULL,
|
||||||
|
format VARCHAR(255),
|
||||||
|
author INTEGER,
|
||||||
|
publish DATETIME,
|
||||||
|
created DATETIME NOT NULL,
|
||||||
|
changed DATETIME NOT NULL,
|
||||||
|
status INTEGER
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE page_nodes(
|
||||||
|
nid INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL CHECK( nid >=0),
|
||||||
|
revision INTEGER,
|
||||||
|
parent INTEGER
|
||||||
|
);
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
|
|
||||||
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
|
|
||||||
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';
|
|
||||||
|
|
||||||
-- -----------------------------------------------------
|
|
||||||
-- Schema mydb
|
|
||||||
-- -----------------------------------------------------
|
|
||||||
-- -----------------------------------------------------
|
|
||||||
-- Schema roc_cms
|
|
||||||
-- -----------------------------------------------------
|
|
||||||
DROP SCHEMA IF EXISTS `roc_cms` ;
|
|
||||||
CREATE SCHEMA IF NOT EXISTS `roc_cms` DEFAULT CHARACTER SET latin1 ;
|
|
||||||
USE `roc_cms` ;
|
|
||||||
|
|
||||||
-- -----------------------------------------------------
|
|
||||||
-- Table `roc_cms`.`nodes`
|
|
||||||
-- -----------------------------------------------------
|
|
||||||
DROP TABLE IF EXISTS `roc_cms`.`nodes` ;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `roc_cms`.`nodes` (
|
|
||||||
`nid` INT(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`version` INT(11) NULL DEFAULT NULL,
|
|
||||||
`type` INT(11) NULL DEFAULT NULL,
|
|
||||||
`title` VARCHAR(255) NOT NULL,
|
|
||||||
`summary` TEXT NOT NULL,
|
|
||||||
`content` MEDIUMTEXT NOT NULL,
|
|
||||||
`author` INT(11) NULL DEFAULT NULL,
|
|
||||||
`publish` DATETIME NULL DEFAULT NULL,
|
|
||||||
`created` DATETIME NOT NULL,
|
|
||||||
`changed` DATETIME NOT NULL,
|
|
||||||
PRIMARY KEY (`nid`))
|
|
||||||
ENGINE = InnoDB
|
|
||||||
DEFAULT CHARACTER SET = latin1;
|
|
||||||
|
|
||||||
|
|
||||||
-- -----------------------------------------------------
|
|
||||||
-- Table `roc_cms`.`users`
|
|
||||||
-- -----------------------------------------------------
|
|
||||||
DROP TABLE IF EXISTS `roc_cms`.`users` ;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `roc_cms`.`users` (
|
|
||||||
`uid` INT(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`name` VARCHAR(100) NOT NULL,
|
|
||||||
`password` VARCHAR(100) NOT NULL,
|
|
||||||
`salt` VARCHAR(100) NOT NULL,
|
|
||||||
`email` VARCHAR(250) NOT NULL,
|
|
||||||
`status` INT(11) NULL DEFAULT NULL,
|
|
||||||
`created` DATETIME NOT NULL,
|
|
||||||
`signed` DATETIME NULL DEFAULT NULL,
|
|
||||||
PRIMARY KEY (`uid`),
|
|
||||||
UNIQUE INDEX `name` (`name` ASC))
|
|
||||||
ENGINE = InnoDB
|
|
||||||
DEFAULT CHARACTER SET = latin1;
|
|
||||||
|
|
||||||
|
|
||||||
-- -----------------------------------------------------
|
|
||||||
-- Table `roc_cms`.`users_roles`
|
|
||||||
-- -----------------------------------------------------
|
|
||||||
DROP TABLE IF EXISTS `roc_cms`.`users_roles` ;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `roc_cms`.`users_roles` (
|
|
||||||
`rid` INT(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`role` VARCHAR(100) NOT NULL,
|
|
||||||
PRIMARY KEY (`rid`),
|
|
||||||
UNIQUE INDEX `role` (`role` ASC))
|
|
||||||
ENGINE = InnoDB
|
|
||||||
DEFAULT CHARACTER SET = latin1;
|
|
||||||
|
|
||||||
|
|
||||||
SET SQL_MODE=@OLD_SQL_MODE;
|
|
||||||
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
|
|
||||||
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
DROP TABLE IF EXISTS nodes;
|
|
||||||
|
|
||||||
CREATE TABLE nodes
|
|
||||||
(
|
|
||||||
id smallint unsigned NOT NULL auto_increment,
|
|
||||||
publication_date date NOT NULL, #When the article was published
|
|
||||||
creation_date date NOT NULL, #When the article was created
|
|
||||||
modification_date date NOT NULL, #When the article was updated
|
|
||||||
title varchar(255) NOT NULL, #Full title of the article
|
|
||||||
summary text NOT NULL, #A short summary of the articule
|
|
||||||
content mediumtext NOT NULL, #The HTML content of the article
|
|
||||||
|
|
||||||
PRIMARY KEY (ID)
|
|
||||||
);
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
DELIMITER $$
|
|
||||||
CREATE TRIGGER update_editor
|
|
||||||
AFTER INSERT ON `users_nodes` FOR EACH ROW
|
|
||||||
UPDATE Nodes
|
|
||||||
SET editor_id = NEW.users_id
|
|
||||||
WHERE id = NEW.nodes_id;
|
|
||||||
$$
|
|
||||||
DELIMITER ;
|
|
||||||
66
library/persistence/mysql/scripts/user.sql
Normal file
66
library/persistence/mysql/scripts/user.sql
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
BEGIN;
|
||||||
|
|
||||||
|
CREATE TABLE `users` (
|
||||||
|
`uid` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`name` varchar(100) NOT NULL,
|
||||||
|
`password` varchar(100) NOT NULL,
|
||||||
|
`salt` varchar(100) NOT NULL,
|
||||||
|
`email` varchar(250) NOT NULL,
|
||||||
|
`status` int(11) DEFAULT NULL,
|
||||||
|
`created` datetime NOT NULL,
|
||||||
|
`signed` datetime DEFAULT NULL,
|
||||||
|
CHECK (`uid` >= 0),
|
||||||
|
PRIMARY KEY (`uid`),
|
||||||
|
UNIQUE KEY `name` (`name`)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE `roles` (
|
||||||
|
`rid` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`name` varchar(100) NOT NULL,
|
||||||
|
CHECK (`rid` >= 0),
|
||||||
|
PRIMARY KEY (`rid`),
|
||||||
|
UNIQUE KEY `name` (`name`)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE `users_roles` (
|
||||||
|
`uid` int(11) NOT NULL,
|
||||||
|
`rid` int(11) NOT NULL,
|
||||||
|
CHECK (`uid` >= 0),
|
||||||
|
CHECK (`rid` >= 0)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE `role_permissions` (
|
||||||
|
`rid` int(11) NOT NULL,
|
||||||
|
`permission` varchar(255) NOT NULL,
|
||||||
|
`module` varchar(255) DEFAULT NULL,
|
||||||
|
CHECK (`rid` >= 0)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE `users_activations` (
|
||||||
|
`aid` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`token` varchar(255) NOT NULL,
|
||||||
|
`uid` int(11) NOT NULL,
|
||||||
|
`created` datetime NOT NULL,
|
||||||
|
CHECK (`aid` >= 0),
|
||||||
|
CHECK (`uid` >= 0),
|
||||||
|
PRIMARY KEY (`aid`),
|
||||||
|
UNIQUE KEY `token` (`token`)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE `users_password_recovery` (
|
||||||
|
`aid` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`token` varchar(255) NOT NULL,
|
||||||
|
`uid` int(11) NOT NULL,
|
||||||
|
`created` datetime NOT NULL,
|
||||||
|
CHECK (`aid` >= 0),
|
||||||
|
CHECK (`uid` >= 0),
|
||||||
|
PRIMARY KEY (`aid`),
|
||||||
|
UNIQUE KEY `token` (`token`)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
@@ -108,14 +108,14 @@ feature -- Hooks
|
|||||||
local
|
local
|
||||||
lnk: CMS_LOCAL_LINK
|
lnk: CMS_LOCAL_LINK
|
||||||
do
|
do
|
||||||
if attached a_response.current_user (a_response.request) as u then
|
-- if attached a_response.current_user (a_response.request) as u then
|
||||||
create lnk.make (u.name + " (Logout)", "basic_auth_logoff?destination=" + a_response.request.request_uri)
|
-- create lnk.make (u.name + " (Logout)", "basic_auth_logoff?destination=" + a_response.request.request_uri)
|
||||||
else
|
-- else
|
||||||
create lnk.make ("Login", "basic_auth_login?destination=" + a_response.request.request_uri)
|
-- create lnk.make ("Login", "basic_auth_login?destination=" + a_response.request.request_uri)
|
||||||
end
|
-- end
|
||||||
-- if not a_menu_system.primary_menu.has (lnk) then
|
-- if not a_menu_system.primary_menu.has (lnk) then
|
||||||
lnk.set_weight (99)
|
-- lnk.set_weight (99)
|
||||||
a_menu_system.primary_menu.extend (lnk)
|
-- a_menu_system.primary_menu.extend (lnk)
|
||||||
-- end
|
-- end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -55,21 +55,62 @@ feature -- HTTP Methods
|
|||||||
else
|
else
|
||||||
create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api)
|
create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api)
|
||||||
unset_current_user (req)
|
unset_current_user (req)
|
||||||
l_page.set_status_code ({HTTP_STATUS_CODE}.found) -- Note: can not use {HTTP_STATUS_CODE}.unauthorized for redirection
|
l_page.set_status_code ({HTTP_STATUS_CODE}.unauthorized) -- Note: can not use {HTTP_STATUS_CODE}.unauthorized for redirection
|
||||||
if attached {WSF_STRING} req.query_parameter ("destination") as l_uri then
|
l_url := req.absolute_script_url ("")
|
||||||
l_url := req.absolute_script_url (l_uri.url_encoded_value)
|
|
||||||
else
|
|
||||||
l_url := req.absolute_script_url ("")
|
|
||||||
end
|
|
||||||
i := l_url.substring_index ("://", 1)
|
i := l_url.substring_index ("://", 1)
|
||||||
if i > 0 then
|
if i > 0 then
|
||||||
-- Note: this is a hack to have the logout effective on various browser
|
-- Note: this is a hack to have the logout effective on various browser
|
||||||
-- (firefox requires this).
|
-- (firefox requires this).
|
||||||
l_url.replace_substring ("://_logout_basic_auth_@", i, i + 2)
|
l_url.replace_substring ("://_logout_basic_auth_@", i, i + 2)
|
||||||
end
|
end
|
||||||
l_page.set_redirection (l_url)
|
if
|
||||||
|
attached req.http_user_agent as l_user_agent and then
|
||||||
|
browser_name (l_user_agent).is_case_insensitive_equal_general ("Firefox")
|
||||||
|
then
|
||||||
|
-- Set status to refirect
|
||||||
|
-- and redirect to the host page.
|
||||||
|
l_page.set_status_code ({HTTP_STATUS_CODE}.found)
|
||||||
|
l_page.set_redirection (l_url)
|
||||||
|
end
|
||||||
l_page.execute
|
l_page.execute
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
browser_name (a_user_agent: READABLE_STRING_8): READABLE_STRING_32
|
||||||
|
-- Browser name.
|
||||||
|
-- Must contain Must not contain
|
||||||
|
-- Firefox Firefox/xyz Seamonkey/xyz
|
||||||
|
-- Seamonkey Seamonkey/xyz
|
||||||
|
-- Chrome Chrome/xyz Chromium/xyz
|
||||||
|
-- Chromium Chromium/xyz
|
||||||
|
-- Safari Safari/xyz Chrome/xyz
|
||||||
|
-- Chromium/xyz
|
||||||
|
-- Opera OPR/xyz [1]
|
||||||
|
-- Opera/xyz [2]
|
||||||
|
-- Internet Explorer ;MSIE xyz; Internet Explorer doesn't put its name in the BrowserName/VersionNumber format
|
||||||
|
|
||||||
|
do
|
||||||
|
if
|
||||||
|
a_user_agent.has_substring ("Firefox") and then
|
||||||
|
not a_user_agent.has_substring ("Seamonkey")
|
||||||
|
then
|
||||||
|
Result := "Firefox"
|
||||||
|
elseif a_user_agent.has_substring ("Seamonkey") then
|
||||||
|
Result := "Seamonkey"
|
||||||
|
elseif a_user_agent.has_substring ("Chrome") and then not a_user_agent.has_substring ("Chromium")then
|
||||||
|
Result := "Chrome"
|
||||||
|
elseif a_user_agent.has_substring ("Chromium") then
|
||||||
|
Result := "Chromiun"
|
||||||
|
elseif a_user_agent.has_substring ("Safari") and then not (a_user_agent.has_substring ("Chrome") or else a_user_agent.has_substring ("Chromium")) then
|
||||||
|
Result := "Safari"
|
||||||
|
elseif a_user_agent.has_substring ("OPR") or else a_user_agent.has_substring ("Opera") then
|
||||||
|
Result := "Opera"
|
||||||
|
elseif a_user_agent.has_substring ("MSIE") or else a_user_agent.has_substring ("Trident")then
|
||||||
|
Result := "Internet Explorer"
|
||||||
|
else
|
||||||
|
Result := "Unknown"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
23
modules/login/login-safe.ecf
Normal file
23
modules/login/login-safe.ecf
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?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="login" uuid="AAB9EE7D-A671-4727-8658-D417A48B2B57" library_target="login">
|
||||||
|
<target name="login">
|
||||||
|
<root all_classes="true"/>
|
||||||
|
<file_rule>
|
||||||
|
<exclude>/.git$</exclude>
|
||||||
|
<exclude>/EIFGENs$</exclude>
|
||||||
|
<exclude>/.svn$</exclude>
|
||||||
|
</file_rule>
|
||||||
|
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="standard">
|
||||||
|
</option>
|
||||||
|
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||||
|
<library name="cms" location="$ISE_LIBRARY\unstable\library\web\cms\cms-safe.ecf" readonly="false"/>
|
||||||
|
<library name="cms_app_env" location="$ISE_LIBRARY\unstable\library\web\cms\library\app_env\app_env-safe.ecf" readonly="false"/>
|
||||||
|
<library name="cms_model" location="$ISE_LIBRARY\unstable\library\web\cms\library\model\cms_model-safe.ecf" readonly="false"/>
|
||||||
|
<library name="config" location="$ISE_LIBRARY\unstable\library\web\cms\library\configuration\config-safe.ecf"/>
|
||||||
|
<library name="encoder" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\text\encoder\encoder-safe.ecf"/>
|
||||||
|
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http-safe.ecf"/>
|
||||||
|
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
|
||||||
|
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
|
||||||
|
<cluster name="src" location=".\" recursive="true"/>
|
||||||
|
</target>
|
||||||
|
</system>
|
||||||
45
modules/login/login_email_service.e
Normal file
45
modules/login/login_email_service.e
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
note
|
||||||
|
description: "Summary description for {LOGIN_EMAIL_SERVICE}."
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
class
|
||||||
|
LOGIN_EMAIL_SERVICE
|
||||||
|
|
||||||
|
inherit
|
||||||
|
EMAIL_SERVICE
|
||||||
|
redefine
|
||||||
|
initialize,
|
||||||
|
parameters
|
||||||
|
end
|
||||||
|
|
||||||
|
create
|
||||||
|
make
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
initialize
|
||||||
|
do
|
||||||
|
Precursor
|
||||||
|
contact_email := parameters.contact_email
|
||||||
|
end
|
||||||
|
|
||||||
|
parameters: LOGIN_EMAIL_SERVICE_PARAMETERS
|
||||||
|
-- Associated parameters.
|
||||||
|
|
||||||
|
feature -- Access
|
||||||
|
|
||||||
|
contact_email: IMMUTABLE_STRING_8
|
||||||
|
-- contact email.
|
||||||
|
|
||||||
|
feature -- Basic Operations
|
||||||
|
|
||||||
|
send_contact_email (a_to, a_content: READABLE_STRING_8)
|
||||||
|
-- Send successful contact message `a_token' to `a_to'.
|
||||||
|
require
|
||||||
|
attached_to: a_to /= Void
|
||||||
|
do
|
||||||
|
send_message (contact_email, a_to, parameters.contact_subject_text, a_content)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
73
modules/login/login_email_service_parameters.e
Normal file
73
modules/login/login_email_service_parameters.e
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
note
|
||||||
|
description: "Summary description for {LOGIN_EMAIL_SERVICE_PARAMETERS}."
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
class
|
||||||
|
LOGIN_EMAIL_SERVICE_PARAMETERS
|
||||||
|
|
||||||
|
inherit
|
||||||
|
EMAIL_SERVICE_PARAMETERS
|
||||||
|
|
||||||
|
create
|
||||||
|
make
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
make (a_cms_api: CMS_API)
|
||||||
|
local
|
||||||
|
utf: UTF_CONVERTER
|
||||||
|
l_site_name: READABLE_STRING_8
|
||||||
|
s: detachable READABLE_STRING_32
|
||||||
|
l_contact_email, l_contact_subject: detachable READABLE_STRING_8
|
||||||
|
do
|
||||||
|
-- Use global smtp setting if any, otherwise "localhost"
|
||||||
|
smtp_server := utf.escaped_utf_32_string_to_utf_8_string_8 (a_cms_api.setup.text_item_or_default ("smtp", "localhost"))
|
||||||
|
l_site_name := utf.escaped_utf_32_string_to_utf_8_string_8 (a_cms_api.setup.site_name)
|
||||||
|
admin_email := a_cms_api.setup.site_email
|
||||||
|
|
||||||
|
if not admin_email.has ('<') then
|
||||||
|
admin_email := l_site_name + " <" + admin_email +">"
|
||||||
|
end
|
||||||
|
|
||||||
|
if attached {CONFIG_READER} a_cms_api.module_configuration ("login", Void) as cfg then
|
||||||
|
if attached cfg.text_item ("smtp") as l_smtp then
|
||||||
|
-- Overwrite global smtp setting if any.
|
||||||
|
smtp_server := utf.utf_32_string_to_utf_8_string_8 (l_smtp)
|
||||||
|
end
|
||||||
|
s := cfg.text_item ("email")
|
||||||
|
if s /= Void then
|
||||||
|
l_contact_email := utf.utf_32_string_to_utf_8_string_8 (s)
|
||||||
|
end
|
||||||
|
s := cfg.text_item ("subject")
|
||||||
|
if s /= Void then
|
||||||
|
l_contact_subject := utf.utf_32_string_to_utf_8_string_8 (s)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if l_contact_email /= Void then
|
||||||
|
if not l_contact_email.has ('<') then
|
||||||
|
l_contact_email := l_site_name + " <" + l_contact_email + ">"
|
||||||
|
end
|
||||||
|
contact_email := l_contact_email
|
||||||
|
else
|
||||||
|
contact_email := admin_email
|
||||||
|
end
|
||||||
|
if l_contact_subject /= Void then
|
||||||
|
contact_subject_text := l_contact_subject
|
||||||
|
else
|
||||||
|
contact_subject_text := "Thank you for registering with us"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Access
|
||||||
|
|
||||||
|
smtp_server: IMMUTABLE_STRING_8
|
||||||
|
|
||||||
|
admin_email: IMMUTABLE_STRING_8
|
||||||
|
|
||||||
|
contact_email: IMMUTABLE_STRING_8
|
||||||
|
-- Contact email.
|
||||||
|
|
||||||
|
contact_subject_text: IMMUTABLE_STRING_8
|
||||||
|
|
||||||
|
end
|
||||||
675
modules/login/login_module.e
Normal file
675
modules/login/login_module.e
Normal file
@@ -0,0 +1,675 @@
|
|||||||
|
note
|
||||||
|
description: "Module Logging supporting different authentication strategies"
|
||||||
|
date: "$Date: 2015-05-20 06:50:50 -0300 (mi. 20 de may. de 2015) $"
|
||||||
|
revision: "$Revision: 97328 $"
|
||||||
|
|
||||||
|
class
|
||||||
|
LOGIN_MODULE
|
||||||
|
|
||||||
|
inherit
|
||||||
|
CMS_MODULE
|
||||||
|
redefine
|
||||||
|
register_hooks
|
||||||
|
end
|
||||||
|
|
||||||
|
CMS_HOOK_BLOCK
|
||||||
|
|
||||||
|
CMS_HOOK_AUTO_REGISTER
|
||||||
|
|
||||||
|
CMS_HOOK_MENU_SYSTEM_ALTER
|
||||||
|
|
||||||
|
CMS_HOOK_VALUE_TABLE_ALTER
|
||||||
|
|
||||||
|
SHARED_EXECUTION_ENVIRONMENT
|
||||||
|
export
|
||||||
|
{NONE} all
|
||||||
|
end
|
||||||
|
|
||||||
|
REFACTORING_HELPER
|
||||||
|
|
||||||
|
SHARED_LOGGER
|
||||||
|
|
||||||
|
CMS_REQUEST_UTIL
|
||||||
|
|
||||||
|
create
|
||||||
|
make
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
make
|
||||||
|
-- Create current module
|
||||||
|
do
|
||||||
|
name := "login"
|
||||||
|
version := "1.0"
|
||||||
|
description := "Eiffel login module"
|
||||||
|
package := "login"
|
||||||
|
|
||||||
|
create root_dir.make_current
|
||||||
|
cache_duration := 0
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Access: docs
|
||||||
|
|
||||||
|
root_dir: PATH
|
||||||
|
|
||||||
|
cache_duration: INTEGER
|
||||||
|
-- Caching duration
|
||||||
|
--| 0: disable
|
||||||
|
--| -1: cache always valie
|
||||||
|
--| nb: cache expires after nb seconds.
|
||||||
|
|
||||||
|
cache_disabled: BOOLEAN
|
||||||
|
do
|
||||||
|
Result := cache_duration = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Router
|
||||||
|
|
||||||
|
setup_router (a_router: WSF_ROUTER; a_api: CMS_API)
|
||||||
|
-- Router configuration.
|
||||||
|
do
|
||||||
|
a_router.handle_with_request_methods ("/roc-login", create {WSF_URI_AGENT_HANDLER}.make (agent handle_login (a_api, ?, ?)), a_router.methods_head_get)
|
||||||
|
a_router.handle_with_request_methods ("/roc-register", create {WSF_URI_AGENT_HANDLER}.make (agent handle_register (a_api, ?, ?)), a_router.methods_get_post)
|
||||||
|
a_router.handle_with_request_methods ("/activate/{token}", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_activation (a_api, ?, ?)), a_router.methods_head_get)
|
||||||
|
a_router.handle_with_request_methods ("/reactivate", create {WSF_URI_AGENT_HANDLER}.make (agent handle_reactivation (a_api, ?, ?)), a_router.methods_get_post)
|
||||||
|
a_router.handle_with_request_methods ("/new-password", create {WSF_URI_AGENT_HANDLER}.make (agent handle_new_password (a_api, ?, ?)), a_router.methods_get_post)
|
||||||
|
a_router.handle_with_request_methods ("/reset-password", create {WSF_URI_AGENT_HANDLER}.make (agent handle_reset_password (a_api, ?, ?)), a_router.methods_get_post)
|
||||||
|
a_router.handle_with_request_methods ("/roc-logout", create {WSF_URI_AGENT_HANDLER}.make (agent handle_logout (a_api, ?, ?)), a_router.methods_get_post)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Hooks configuration
|
||||||
|
|
||||||
|
register_hooks (a_response: CMS_RESPONSE)
|
||||||
|
-- Module hooks configuration.
|
||||||
|
do
|
||||||
|
auto_subscribe_to_hooks (a_response)
|
||||||
|
a_response.subscribe_to_block_hook (Current)
|
||||||
|
a_response.subscribe_to_value_table_alter_hook (Current)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Hooks
|
||||||
|
|
||||||
|
value_table_alter (a_value: CMS_VALUE_TABLE; a_response: CMS_RESPONSE)
|
||||||
|
-- <Precursor>
|
||||||
|
do
|
||||||
|
if attached current_user (a_response.request) as l_user then
|
||||||
|
a_value.force (l_user, "user")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
menu_system_alter (a_menu_system: CMS_MENU_SYSTEM; a_response: CMS_RESPONSE)
|
||||||
|
-- Hook execution on collection of menu contained by `a_menu_system'
|
||||||
|
-- for related response `a_response'.
|
||||||
|
local
|
||||||
|
lnk: CMS_LOCAL_LINK
|
||||||
|
do
|
||||||
|
if attached a_response.current_user (a_response.request) as u then
|
||||||
|
create lnk.make (u.name + " (Logout)", "roc-logout" )
|
||||||
|
else
|
||||||
|
create lnk.make ("Login", "roc-login")
|
||||||
|
end
|
||||||
|
a_menu_system.primary_menu.extend (lnk)
|
||||||
|
lnk.set_weight (98)
|
||||||
|
end
|
||||||
|
|
||||||
|
block_list: ITERABLE [like {CMS_BLOCK}.name]
|
||||||
|
local
|
||||||
|
l_string: STRING
|
||||||
|
do
|
||||||
|
Result := <<"login","register","reactivate","new_password", "reset_password">>
|
||||||
|
create l_string.make_empty
|
||||||
|
across Result as ic loop
|
||||||
|
l_string.append (ic.item)
|
||||||
|
l_string.append_character (' ')
|
||||||
|
end
|
||||||
|
write_debug_log (generator + ".block_list:" + l_string )
|
||||||
|
end
|
||||||
|
|
||||||
|
get_block_view (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE)
|
||||||
|
local
|
||||||
|
vals: CMS_VALUE_TABLE
|
||||||
|
do
|
||||||
|
if
|
||||||
|
a_block_id.is_case_insensitive_equal_general ("login") and then
|
||||||
|
a_response.request.path_info.starts_with ("/roc-login")
|
||||||
|
then
|
||||||
|
if attached template_block (a_block_id, a_response) as l_tpl_block then
|
||||||
|
create vals.make (1)
|
||||||
|
-- add the variable to the block
|
||||||
|
value_table_alter (vals, a_response)
|
||||||
|
across
|
||||||
|
vals as ic
|
||||||
|
loop
|
||||||
|
l_tpl_block.set_value (ic.item, ic.key)
|
||||||
|
end
|
||||||
|
a_response.add_block (l_tpl_block, "content")
|
||||||
|
else
|
||||||
|
debug ("cms")
|
||||||
|
a_response.add_warning_message ("Error with block [" + a_block_id + "]")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif
|
||||||
|
a_block_id.is_case_insensitive_equal_general ("register") and then
|
||||||
|
a_response.request.path_info.starts_with ("/roc-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
|
||||||
|
a_response.add_block (l_tpl_block, "content")
|
||||||
|
else
|
||||||
|
debug ("cms")
|
||||||
|
a_response.add_warning_message ("Error with block [" + a_block_id + "]")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif a_response.request.is_post_request_method then
|
||||||
|
if a_response.values.has ("error_name") or else a_response.values.has ("error_email") then
|
||||||
|
if attached template_block (a_block_id, a_response) as l_tpl_block then
|
||||||
|
l_tpl_block.set_value (a_response.values.item ("error_name"), "error_name")
|
||||||
|
l_tpl_block.set_value (a_response.values.item ("error_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")
|
||||||
|
a_response.add_block (l_tpl_block, "content")
|
||||||
|
else
|
||||||
|
debug ("cms")
|
||||||
|
a_response.add_warning_message ("Error with block [" + a_block_id + "]")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if attached template_block ("post_register", a_response) as l_tpl_block then
|
||||||
|
a_response.add_block (l_tpl_block, "content")
|
||||||
|
else
|
||||||
|
debug ("cms")
|
||||||
|
a_response.add_warning_message ("Error with block [" + a_block_id + "]")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif
|
||||||
|
a_block_id.is_case_insensitive_equal_general ("reactivate") and then
|
||||||
|
a_response.request.path_info.starts_with ("/reactivate")
|
||||||
|
then
|
||||||
|
if a_response.request.is_get_request_method then
|
||||||
|
if attached template_block (a_block_id, a_response) as l_tpl_block then
|
||||||
|
a_response.add_block (l_tpl_block, "content")
|
||||||
|
else
|
||||||
|
debug ("cms")
|
||||||
|
a_response.add_warning_message ("Error with block [" + a_block_id + "]")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif a_response.request.is_post_request_method then
|
||||||
|
if a_response.values.has ("error_email") or else a_response.values.has ("is_active") then
|
||||||
|
if attached template_block (a_block_id, a_response) as l_tpl_block then
|
||||||
|
l_tpl_block.set_value (a_response.values.item ("error_email"), "error_email")
|
||||||
|
l_tpl_block.set_value (a_response.values.item ("email"), "email")
|
||||||
|
l_tpl_block.set_value (a_response.values.item ("is_active"), "is_active")
|
||||||
|
a_response.add_block (l_tpl_block, "content")
|
||||||
|
else
|
||||||
|
debug ("cms")
|
||||||
|
a_response.add_warning_message ("Error with block [" + a_block_id + "]")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if attached template_block ("post_reactivate", a_response) as l_tpl_block then
|
||||||
|
a_response.add_block (l_tpl_block, "content")
|
||||||
|
else
|
||||||
|
debug ("cms")
|
||||||
|
a_response.add_warning_message ("Error with block [" + a_block_id + "]")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif
|
||||||
|
a_block_id.is_case_insensitive_equal_general ("new_password") and then
|
||||||
|
a_response.request.path_info.starts_with ("/new-password")
|
||||||
|
then
|
||||||
|
if a_response.request.is_get_request_method then
|
||||||
|
if attached template_block (a_block_id, a_response) as l_tpl_block then
|
||||||
|
a_response.add_block (l_tpl_block, "content")
|
||||||
|
else
|
||||||
|
debug ("cms")
|
||||||
|
a_response.add_warning_message ("Error with block [" + a_block_id + "]")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif a_response.request.is_post_request_method then
|
||||||
|
if a_response.values.has ("error_email") then
|
||||||
|
if attached template_block (a_block_id, a_response) as l_tpl_block then
|
||||||
|
l_tpl_block.set_value (a_response.values.item ("error_email"), "error_email")
|
||||||
|
l_tpl_block.set_value (a_response.values.item ("email"), "email")
|
||||||
|
a_response.add_block (l_tpl_block, "content")
|
||||||
|
else
|
||||||
|
debug ("cms")
|
||||||
|
a_response.add_warning_message ("Error with block [" + a_block_id + "]")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if attached template_block ("post_password", a_response) as l_tpl_block then
|
||||||
|
a_response.add_block (l_tpl_block, "content")
|
||||||
|
else
|
||||||
|
debug ("cms")
|
||||||
|
a_response.add_warning_message ("Error with block [" + a_block_id + "]")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif
|
||||||
|
a_block_id.is_case_insensitive_equal_general ("reset_password") and then
|
||||||
|
a_response.request.path_info.starts_with ("/reset-password")
|
||||||
|
then
|
||||||
|
if a_response.request.is_get_request_method then
|
||||||
|
if attached template_block (a_block_id, a_response) as l_tpl_block then
|
||||||
|
l_tpl_block.set_value (a_response.values.item ("token"), "token")
|
||||||
|
l_tpl_block.set_value (a_response.values.item ("error_token"), "error_token")
|
||||||
|
a_response.add_block (l_tpl_block, "content")
|
||||||
|
else
|
||||||
|
debug ("cms")
|
||||||
|
a_response.add_warning_message ("Error with block [" + a_block_id + "]")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif a_response.request.is_post_request_method then
|
||||||
|
if a_response.values.has ("error_token") or else a_response.values.has ("error_password") then
|
||||||
|
if attached template_block (a_block_id, a_response) as l_tpl_block then
|
||||||
|
l_tpl_block.set_value (a_response.values.item ("error_token"), "error_token")
|
||||||
|
l_tpl_block.set_value (a_response.values.item ("error_password"), "error_password")
|
||||||
|
l_tpl_block.set_value (a_response.values.item ("token"), "token")
|
||||||
|
a_response.add_block (l_tpl_block, "content")
|
||||||
|
else
|
||||||
|
debug ("cms")
|
||||||
|
a_response.add_warning_message ("Error with block [" + a_block_id + "]")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if attached template_block ("post_reset", a_response) as l_tpl_block then
|
||||||
|
a_response.add_block (l_tpl_block, "content")
|
||||||
|
else
|
||||||
|
debug ("cms")
|
||||||
|
a_response.add_warning_message ("Error with block [" + a_block_id + "]")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
handle_login (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
local
|
||||||
|
r: CMS_RESPONSE
|
||||||
|
br: BAD_REQUEST_ERROR_CMS_RESPONSE
|
||||||
|
do
|
||||||
|
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
|
||||||
|
r.set_value ("Login", "optional_content_type")
|
||||||
|
r.execute
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
handle_logout (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
local
|
||||||
|
r: CMS_RESPONSE
|
||||||
|
br: BAD_REQUEST_ERROR_CMS_RESPONSE
|
||||||
|
l_url: STRING
|
||||||
|
do
|
||||||
|
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
|
||||||
|
r.set_status_code ({HTTP_CONSTANTS}.found)
|
||||||
|
l_url := req.absolute_script_url ("")
|
||||||
|
l_url.append ("/basic_auth_logoff")
|
||||||
|
r.set_redirection (l_url)
|
||||||
|
r.execute
|
||||||
|
end
|
||||||
|
|
||||||
|
handle_register (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
local
|
||||||
|
r: CMS_RESPONSE
|
||||||
|
l_user_api: CMS_USER_API
|
||||||
|
u: CMS_USER
|
||||||
|
l_roles: LIST [CMS_USER_ROLE]
|
||||||
|
l_exist: BOOLEAN
|
||||||
|
es: LOGIN_EMAIL_SERVICE
|
||||||
|
l_link: STRING
|
||||||
|
l_token: STRING
|
||||||
|
l_message: STRING
|
||||||
|
do
|
||||||
|
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
|
||||||
|
r.set_value ("Register", "optional_content_type")
|
||||||
|
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
|
||||||
|
then
|
||||||
|
l_user_api := api.user_api
|
||||||
|
|
||||||
|
if attached l_user_api.user_by_name (l_name.value) then
|
||||||
|
-- Username already exist.
|
||||||
|
r.values.force ("The user name exist!", "error_name")
|
||||||
|
l_exist := True
|
||||||
|
end
|
||||||
|
if attached l_user_api.user_by_email (l_email.value) then
|
||||||
|
-- Emails already exist.
|
||||||
|
r.values.force ("The email exist!", "error_email")
|
||||||
|
l_exist := True
|
||||||
|
end
|
||||||
|
|
||||||
|
if not l_exist then
|
||||||
|
-- New user
|
||||||
|
create {ARRAYED_LIST [CMS_USER_ROLE]}l_roles.make (1)
|
||||||
|
l_roles.force (l_user_api.authenticated_user_role)
|
||||||
|
|
||||||
|
create u.make (l_name.value)
|
||||||
|
u.set_email (l_email.value)
|
||||||
|
u.set_password (l_password.value)
|
||||||
|
u.set_roles (l_roles)
|
||||||
|
l_user_api.new_user (u)
|
||||||
|
|
||||||
|
-- Create activation token
|
||||||
|
l_token := new_token
|
||||||
|
l_user_api.new_activation (l_token, u.id)
|
||||||
|
create l_link.make_from_string (req.server_url)
|
||||||
|
l_link.append ("/activate/")
|
||||||
|
l_link.append (l_token)
|
||||||
|
|
||||||
|
create l_message.make_from_string (account_activation)
|
||||||
|
l_message.replace_substring_all ("$link", l_link)
|
||||||
|
|
||||||
|
-- Send Email
|
||||||
|
create es.make (create {LOGIN_EMAIL_SERVICE_PARAMETERS}.make (api))
|
||||||
|
write_debug_log (generator + ".handle register: send_contact_email")
|
||||||
|
es.send_contact_email (l_email.value, l_message)
|
||||||
|
|
||||||
|
else
|
||||||
|
r.values.force (l_name.value, "name")
|
||||||
|
r.values.force (l_email.value, "email")
|
||||||
|
r.set_status_code ({HTTP_CONSTANTS}.bad_request)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
r.execute
|
||||||
|
end
|
||||||
|
|
||||||
|
handle_activation (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
local
|
||||||
|
r: CMS_RESPONSE
|
||||||
|
l_user_api: CMS_USER_API
|
||||||
|
l_id: INTEGER_64
|
||||||
|
l_ir: INTERNAL_SERVER_ERROR_CMS_RESPONSE
|
||||||
|
l_link: CMS_LOCAL_LINK
|
||||||
|
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 {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_value ("Account activated", "optional_content_type")
|
||||||
|
r.set_main_content ("<p> Your account <i>"+ l_user.name +"</i> has been activated</p>")
|
||||||
|
else
|
||||||
|
-- the token does not exist, or it was already used.
|
||||||
|
r.set_status_code ({HTTP_CONSTANTS}.bad_request)
|
||||||
|
r.set_value ("Account not activated", "optional_content_type")
|
||||||
|
r.set_main_content ("<p>The token <i>"+ l_token.value +"</i> is not valid <a href=%"/reactivate%">Reactivate Account</a></p>" )
|
||||||
|
|
||||||
|
end
|
||||||
|
r.execute
|
||||||
|
else
|
||||||
|
create l_ir.make (req, res, api)
|
||||||
|
l_ir.execute
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
handle_reactivation (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
local
|
||||||
|
r: CMS_RESPONSE
|
||||||
|
br: BAD_REQUEST_ERROR_CMS_RESPONSE
|
||||||
|
es: LOGIN_EMAIL_SERVICE
|
||||||
|
l_user_api: CMS_USER_API
|
||||||
|
l_token: STRING
|
||||||
|
l_link: STRING
|
||||||
|
l_message: 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.values.force ("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)
|
||||||
|
create l_link.make_from_string (req.server_url)
|
||||||
|
l_link.append ("/activate/")
|
||||||
|
l_link.append (l_token)
|
||||||
|
|
||||||
|
create l_message.make_from_string (account_activation)
|
||||||
|
l_message.replace_substring_all ("$link", l_link)
|
||||||
|
|
||||||
|
-- Send Email
|
||||||
|
create es.make (create {LOGIN_EMAIL_SERVICE_PARAMETERS}.make (api))
|
||||||
|
write_debug_log (generator + ".handle register: send_contact_email")
|
||||||
|
es.send_contact_email (l_email.value, l_message)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
r.values.force ("The email does not exist or !", "error_email")
|
||||||
|
r.values.force (l_email.value, "email")
|
||||||
|
r.set_status_code ({HTTP_CONSTANTS}.bad_request)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
r.execute
|
||||||
|
end
|
||||||
|
|
||||||
|
handle_new_password (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
local
|
||||||
|
r: CMS_RESPONSE
|
||||||
|
br: BAD_REQUEST_ERROR_CMS_RESPONSE
|
||||||
|
es: LOGIN_EMAIL_SERVICE
|
||||||
|
l_user_api: CMS_USER_API
|
||||||
|
l_token: STRING
|
||||||
|
l_link: STRING
|
||||||
|
l_message: STRING
|
||||||
|
do
|
||||||
|
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
|
||||||
|
if req.is_post_request_method then
|
||||||
|
l_user_api := api.user_api
|
||||||
|
if attached {WSF_STRING} req.form_parameter ("email") as l_email then
|
||||||
|
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.
|
||||||
|
l_token := new_token
|
||||||
|
l_user_api.new_password (l_token, l_user.id)
|
||||||
|
create l_link.make_from_string (req.server_url)
|
||||||
|
l_link.append ("/reset-password?token=")
|
||||||
|
l_link.append (l_token)
|
||||||
|
|
||||||
|
create l_message.make_from_string (account_new_password)
|
||||||
|
l_message.replace_substring_all ("$link", l_link)
|
||||||
|
|
||||||
|
-- Send Email
|
||||||
|
create es.make (create {LOGIN_EMAIL_SERVICE_PARAMETERS}.make (api))
|
||||||
|
write_debug_log (generator + ".handle register: send_contact_email")
|
||||||
|
es.send_contact_email (l_email.value, l_message)
|
||||||
|
else
|
||||||
|
r.values.force ("The email does not exist !", "error_email")
|
||||||
|
r.values.force (l_email.value, "email")
|
||||||
|
r.set_status_code ({HTTP_CONSTANTS}.bad_request)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
r.execute
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
handle_reset_password (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
local
|
||||||
|
r: CMS_RESPONSE
|
||||||
|
br: BAD_REQUEST_ERROR_CMS_RESPONSE
|
||||||
|
es: LOGIN_EMAIL_SERVICE
|
||||||
|
l_user_api: CMS_USER_API
|
||||||
|
l_link: STRING
|
||||||
|
l_message: STRING
|
||||||
|
do
|
||||||
|
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
|
||||||
|
l_user_api := api.user_api
|
||||||
|
if attached {WSF_STRING} req.query_parameter ("token") as l_token then
|
||||||
|
r.values.force (l_token.value, "token")
|
||||||
|
if l_user_api.user_by_password_token (l_token.value) = Void then
|
||||||
|
r.values.force ("The token " + l_token.value + " is not valid, click <a href=%"/new-password%">here</a> to generate a new token.", "error_token")
|
||||||
|
r.set_status_code ({HTTP_CONSTANTS}.bad_request)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if req.is_post_request_method then
|
||||||
|
|
||||||
|
if
|
||||||
|
attached {WSF_STRING} req.form_parameter ("token") as l_token and then
|
||||||
|
attached {WSF_STRING} req.form_parameter ("password") as l_password and then
|
||||||
|
attached {WSF_STRING} req.form_parameter ("confirm_password") as l_confirm_password
|
||||||
|
then
|
||||||
|
-- Does the passwords match?
|
||||||
|
if l_password.value.same_string (l_confirm_password.value) then
|
||||||
|
-- is the token valid?
|
||||||
|
if attached {CMS_USER} l_user_api.user_by_password_token (l_token.value) as l_user then
|
||||||
|
l_user.set_password (l_password.value)
|
||||||
|
l_user_api.update_user (l_user)
|
||||||
|
l_user_api.remove_password (l_token.value)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
r.values.force ("Passwords Don't Match", "error_password")
|
||||||
|
r.values.force (l_token.value, "token")
|
||||||
|
r.set_status_code ({HTTP_CONSTANTS}.bad_request)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
r.execute
|
||||||
|
end
|
||||||
|
|
||||||
|
feature {NONE} -- Helpers
|
||||||
|
|
||||||
|
template_block (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE): detachable CMS_SMARTY_TEMPLATE_BLOCK
|
||||||
|
-- Smarty content block for `a_block_id'
|
||||||
|
local
|
||||||
|
p: detachable PATH
|
||||||
|
do
|
||||||
|
create p.make_from_string ("templates")
|
||||||
|
p := p.extended ("block_").appended (a_block_id).appended_with_extension ("tpl")
|
||||||
|
p := a_response.module_resource_path (Current, p)
|
||||||
|
if p /= Void then
|
||||||
|
if attached p.entry as e then
|
||||||
|
create Result.make (a_block_id, Void, p.parent, e)
|
||||||
|
else
|
||||||
|
create Result.make (a_block_id, Void, p.parent, p)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
feature {NONE} -- Token Generation
|
||||||
|
|
||||||
|
new_token: STRING
|
||||||
|
-- Generate a new token activation token
|
||||||
|
local
|
||||||
|
l_token: STRING
|
||||||
|
l_security: SECURITY_PROVIDER
|
||||||
|
l_encode: URL_ENCODER
|
||||||
|
do
|
||||||
|
create l_security
|
||||||
|
l_token := l_security.token
|
||||||
|
create l_encode
|
||||||
|
from until l_token.same_string (l_encode.encoded_string (l_token)) loop
|
||||||
|
-- Loop ensure that we have a security token that does not contain characters that need encoding.
|
||||||
|
-- We cannot simply to an encode-decode because the email sent to the user will contain an encoded token
|
||||||
|
-- but the user will need to use an unencoded token if activation has to be done manually.
|
||||||
|
l_token := l_security.token
|
||||||
|
end
|
||||||
|
Result := l_token
|
||||||
|
end
|
||||||
|
|
||||||
|
feature --{NONE} -- Message email
|
||||||
|
|
||||||
|
account_activation: STRING= "[
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Eiffel.org Activation</title>
|
||||||
|
<meta name="description" content="Eiffel.org Activation">
|
||||||
|
<meta name="author" content="Eiffel.org">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<p>Thank you for registering at <a href="eiffel.org">Eiffel.org</a></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>
|
||||||
|
</html>
|
||||||
|
]"
|
||||||
|
|
||||||
|
account_new_password: STRING= "[
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Eiffel.org New Password</title>
|
||||||
|
<meta name="description" content="Eiffel.org New Password">
|
||||||
|
<meta name="author" content="Eiffel.org">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<p>You have required a new password at <a href="eiffel.org">Eiffel.org</a></p>
|
||||||
|
|
||||||
|
<p>To complete your request, please click on this link to genereate a new password:<p>
|
||||||
|
|
||||||
|
<p><a href="$link">$link</a></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
]"
|
||||||
|
|
||||||
|
feature {NONE} -- Implementation: date and time
|
||||||
|
|
||||||
|
http_date_format_to_date (s: READABLE_STRING_8): detachable DATE_TIME
|
||||||
|
local
|
||||||
|
d: HTTP_DATE
|
||||||
|
do
|
||||||
|
create d.make_from_string (s)
|
||||||
|
if not d.has_error then
|
||||||
|
Result := d.date_time
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
file_date (p: PATH): DATE_TIME
|
||||||
|
require
|
||||||
|
path_exists: (create {FILE_UTILITIES}).file_path_exists (p)
|
||||||
|
local
|
||||||
|
f: RAW_FILE
|
||||||
|
do
|
||||||
|
create f.make_with_path (p)
|
||||||
|
Result := timestamp_to_date (f.date)
|
||||||
|
end
|
||||||
|
|
||||||
|
timestamp_to_date (n: INTEGER): DATE_TIME
|
||||||
|
local
|
||||||
|
d: HTTP_DATE
|
||||||
|
do
|
||||||
|
create d.make_from_timestamp (n)
|
||||||
|
Result := d.date_time
|
||||||
|
end
|
||||||
|
|
||||||
|
note
|
||||||
|
copyright: "Copyright (c) 1984-2013, 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
|
||||||
@@ -36,6 +36,7 @@ feature -- Initialization
|
|||||||
create u.make ("admin")
|
create u.make ("admin")
|
||||||
u.set_password ("istrator#")
|
u.set_password ("istrator#")
|
||||||
u.set_email (a_setup.site_email)
|
u.set_email (a_setup.site_email)
|
||||||
|
u.set_status ({CMS_USER}.active)
|
||||||
a_storage.new_user (u)
|
a_storage.new_user (u)
|
||||||
|
|
||||||
--| Node
|
--| Node
|
||||||
@@ -74,16 +75,19 @@ feature -- Initialization
|
|||||||
create u.make ("auth")
|
create u.make ("auth")
|
||||||
u.set_password ("enticated#")
|
u.set_password ("enticated#")
|
||||||
u.set_email (a_setup.site_email)
|
u.set_email (a_setup.site_email)
|
||||||
|
u.set_status ({CMS_USER}.active)
|
||||||
a_storage.new_user (u)
|
a_storage.new_user (u)
|
||||||
|
|
||||||
create u.make ("test")
|
create u.make ("test")
|
||||||
u.set_password ("test#")
|
u.set_password ("test#")
|
||||||
u.set_email (a_setup.site_email)
|
u.set_email (a_setup.site_email)
|
||||||
|
u.set_status ({CMS_USER}.active)
|
||||||
a_storage.new_user (u)
|
a_storage.new_user (u)
|
||||||
|
|
||||||
create u.make ("view")
|
create u.make ("view")
|
||||||
u.set_password ("only#")
|
u.set_password ("only#")
|
||||||
u.set_email (a_setup.site_email)
|
u.set_email (a_setup.site_email)
|
||||||
|
u.set_status ({CMS_USER}.active)
|
||||||
u.set_roles (l_roles)
|
u.set_roles (l_roles)
|
||||||
a_storage.new_user (u)
|
a_storage.new_user (u)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -56,6 +56,20 @@ feature -- Access
|
|||||||
password: Result /= Void implies (Result.hashed_password /= Void and Result.password = Void)
|
password: Result /= Void implies (Result.hashed_password /= Void and Result.password = Void)
|
||||||
end
|
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
|
||||||
|
|
||||||
|
user_by_password_token (a_token: READABLE_STRING_32): detachable CMS_USER
|
||||||
|
-- User with password token `a_token', if any.
|
||||||
|
deferred
|
||||||
|
ensure
|
||||||
|
password: Result /= Void implies (Result.hashed_password /= Void and Result.password = Void)
|
||||||
|
end
|
||||||
|
|
||||||
is_valid_credential (a_u, a_p: READABLE_STRING_32): BOOLEAN
|
is_valid_credential (a_u, a_p: READABLE_STRING_32): BOOLEAN
|
||||||
-- Does account with username `a_username' and password `a_password' exist?
|
-- Does account with username `a_username' and password `a_password' exist?
|
||||||
deferred
|
deferred
|
||||||
@@ -141,4 +155,27 @@ feature -- Change: roles and permissions
|
|||||||
deferred
|
deferred
|
||||||
end
|
end
|
||||||
|
|
||||||
|
feature -- Change: User activation
|
||||||
|
|
||||||
|
save_activation (a_token: READABLE_STRING_32; a_id: INTEGER_64)
|
||||||
|
-- <Precursor>.
|
||||||
|
deferred
|
||||||
|
end
|
||||||
|
|
||||||
|
remove_activation (a_token: READABLE_STRING_32)
|
||||||
|
-- <Precursor>.
|
||||||
|
deferred
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Change: User password recovery
|
||||||
|
|
||||||
|
save_password (a_token: READABLE_STRING_32; a_id: INTEGER_64)
|
||||||
|
-- <Precursor>.
|
||||||
|
deferred
|
||||||
|
end
|
||||||
|
|
||||||
|
remove_password (a_token: READABLE_STRING_32)
|
||||||
|
-- <Precursor>.
|
||||||
|
deferred
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -34,6 +34,14 @@ feature -- Access: user
|
|||||||
do
|
do
|
||||||
end
|
end
|
||||||
|
|
||||||
|
user_by_activation_token (a_token: READABLE_STRING_32): detachable CMS_USER
|
||||||
|
do
|
||||||
|
end
|
||||||
|
|
||||||
|
user_by_password_token (a_token: READABLE_STRING_32): detachable CMS_USER
|
||||||
|
do
|
||||||
|
end
|
||||||
|
|
||||||
is_valid_credential (l_auth_login, l_auth_password: READABLE_STRING_32): BOOLEAN
|
is_valid_credential (l_auth_login, l_auth_password: READABLE_STRING_32): BOOLEAN
|
||||||
do
|
do
|
||||||
end
|
end
|
||||||
@@ -76,4 +84,27 @@ feature -- Change: roles and permissions
|
|||||||
do
|
do
|
||||||
end
|
end
|
||||||
|
|
||||||
|
feature -- Change: User activation
|
||||||
|
|
||||||
|
save_activation (a_token: READABLE_STRING_32; a_id: INTEGER_64)
|
||||||
|
-- <Precursor>.
|
||||||
|
do
|
||||||
|
end
|
||||||
|
|
||||||
|
remove_activation (a_token: READABLE_STRING_32)
|
||||||
|
-- <Precursor>.
|
||||||
|
do
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Change: User password recovery
|
||||||
|
|
||||||
|
save_password (a_token: READABLE_STRING_32; a_id: INTEGER_64)
|
||||||
|
-- <Precursor>.
|
||||||
|
do
|
||||||
|
end
|
||||||
|
|
||||||
|
remove_password (a_token: READABLE_STRING_32)
|
||||||
|
-- <Precursor>.
|
||||||
|
do
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ feature -- Access: user
|
|||||||
l_parameters: STRING_TABLE [detachable ANY]
|
l_parameters: STRING_TABLE [detachable ANY]
|
||||||
do
|
do
|
||||||
error_handler.reset
|
error_handler.reset
|
||||||
write_information_log (generator + ".user")
|
write_information_log (generator + ".user_by_id")
|
||||||
create l_parameters.make (1)
|
create l_parameters.make (1)
|
||||||
l_parameters.put (a_id, "uid")
|
l_parameters.put (a_id, "uid")
|
||||||
sql_query (select_user_by_id, l_parameters)
|
sql_query (select_user_by_id, l_parameters)
|
||||||
@@ -107,6 +107,40 @@ feature -- Access: user
|
|||||||
end
|
end
|
||||||
end
|
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 sql_rows_count = 1 then
|
||||||
|
Result := fetch_user
|
||||||
|
else
|
||||||
|
check no_more_than_one: sql_rows_count = 0 end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
user_by_password_token (a_token: READABLE_STRING_32): detachable CMS_USER
|
||||||
|
-- User for the given password token `a_token', if any.
|
||||||
|
local
|
||||||
|
l_parameters: STRING_TABLE [detachable ANY]
|
||||||
|
do
|
||||||
|
error_handler.reset
|
||||||
|
write_information_log (generator + ".user_by_password_token")
|
||||||
|
create l_parameters.make (1)
|
||||||
|
l_parameters.put (a_token, "token")
|
||||||
|
sql_query (select_user_by_password_token, l_parameters)
|
||||||
|
if sql_rows_count = 1 then
|
||||||
|
Result := fetch_user
|
||||||
|
else
|
||||||
|
check no_more_than_one: sql_rows_count = 0 end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
is_valid_credential (l_auth_login, l_auth_password: READABLE_STRING_32): BOOLEAN
|
is_valid_credential (l_auth_login, l_auth_password: READABLE_STRING_32): BOOLEAN
|
||||||
local
|
local
|
||||||
l_security: SECURITY_PROVIDER
|
l_security: SECURITY_PROVIDER
|
||||||
@@ -155,6 +189,7 @@ feature -- Change: user
|
|||||||
l_parameters.put (l_password_salt, "salt")
|
l_parameters.put (l_password_salt, "salt")
|
||||||
l_parameters.put (l_email, "email")
|
l_parameters.put (l_email, "email")
|
||||||
l_parameters.put (create {DATE_TIME}.make_now_utc, "created")
|
l_parameters.put (create {DATE_TIME}.make_now_utc, "created")
|
||||||
|
l_parameters.put (a_user.status, "status")
|
||||||
|
|
||||||
sql_change (sql_insert_user, l_parameters)
|
sql_change (sql_insert_user, l_parameters)
|
||||||
if not error_handler.has_error then
|
if not error_handler.has_error then
|
||||||
@@ -197,6 +232,7 @@ feature -- Change: user
|
|||||||
l_parameters.put (l_password_salt, "salt")
|
l_parameters.put (l_password_salt, "salt")
|
||||||
l_parameters.put (l_email, "email")
|
l_parameters.put (l_email, "email")
|
||||||
l_parameters.put (create {DATE_TIME}.make_now_utc, "changed")
|
l_parameters.put (create {DATE_TIME}.make_now_utc, "changed")
|
||||||
|
l_parameters.put (a_user.status, "status")
|
||||||
|
|
||||||
sql_change (sql_update_user, l_parameters)
|
sql_change (sql_update_user, l_parameters)
|
||||||
else
|
else
|
||||||
@@ -441,6 +477,108 @@ feature -- Change: roles and permissions
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
feature -- Access: User activation
|
||||||
|
|
||||||
|
activation_elapsed_time (a_token: READABLE_STRING_32): INTEGER_32
|
||||||
|
-- amount of time that has passed in days since the token `a_token' was saved.
|
||||||
|
local
|
||||||
|
l_parameters: STRING_TABLE [detachable ANY]
|
||||||
|
do
|
||||||
|
error_handler.reset
|
||||||
|
write_information_log (generator + ".activation_elapsed_time")
|
||||||
|
create l_parameters.make (1)
|
||||||
|
l_parameters.put (a_token, "token")
|
||||||
|
sql_query (sql_select_activation_expiration, l_parameters)
|
||||||
|
if sql_rows_count = 1 then
|
||||||
|
Result := sql_read_integer_32 (1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
user_id_by_activation (a_token: READABLE_STRING_32): INTEGER_64
|
||||||
|
-- User id associatied with a token `a_token', if any.
|
||||||
|
local
|
||||||
|
l_parameters: STRING_TABLE [detachable ANY]
|
||||||
|
do
|
||||||
|
error_handler.reset
|
||||||
|
write_information_log (generator + ".user_id_by_actication")
|
||||||
|
create l_parameters.make (1)
|
||||||
|
l_parameters.put (a_token, "token")
|
||||||
|
sql_query (sql_select_userid_activation, l_parameters)
|
||||||
|
if sql_rows_count = 1 then
|
||||||
|
Result := sql_read_integer_32 (1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Change: User activation
|
||||||
|
|
||||||
|
save_activation (a_token: READABLE_STRING_32; a_id: INTEGER_64)
|
||||||
|
-- <Precursor>
|
||||||
|
local
|
||||||
|
l_parameters: STRING_TABLE [detachable ANY]
|
||||||
|
l_utc_date: DATE_TIME
|
||||||
|
do
|
||||||
|
error_handler.reset
|
||||||
|
sql_begin_transaction
|
||||||
|
write_information_log (generator + ".save_activation")
|
||||||
|
create l_utc_date.make_now_utc
|
||||||
|
create l_parameters.make (2)
|
||||||
|
l_parameters.put (a_token, "token")
|
||||||
|
l_parameters.put (a_id, "uid")
|
||||||
|
l_parameters.put (l_utc_date, "utc_date")
|
||||||
|
sql_change (sql_insert_activation, l_parameters)
|
||||||
|
sql_commit_transaction
|
||||||
|
end
|
||||||
|
|
||||||
|
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_change (sql_remove_activation, l_parameters)
|
||||||
|
sql_commit_transaction
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Change: User password recovery
|
||||||
|
|
||||||
|
save_password (a_token: READABLE_STRING_32; a_id: INTEGER_64)
|
||||||
|
-- <Precursor>
|
||||||
|
local
|
||||||
|
l_parameters: STRING_TABLE [detachable ANY]
|
||||||
|
l_utc_date: DATE_TIME
|
||||||
|
do
|
||||||
|
error_handler.reset
|
||||||
|
sql_begin_transaction
|
||||||
|
write_information_log (generator + ".save_password")
|
||||||
|
create l_utc_date.make_now_utc
|
||||||
|
create l_parameters.make (2)
|
||||||
|
l_parameters.put (a_token, "token")
|
||||||
|
l_parameters.put (a_id, "uid")
|
||||||
|
l_parameters.put (l_utc_date, "utc_date")
|
||||||
|
sql_change (sql_insert_password, l_parameters)
|
||||||
|
sql_commit_transaction
|
||||||
|
end
|
||||||
|
|
||||||
|
remove_password (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_password")
|
||||||
|
create l_parameters.make (1)
|
||||||
|
l_parameters.put (a_token, "token")
|
||||||
|
sql_change (sql_remove_password, l_parameters)
|
||||||
|
sql_commit_transaction
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
feature {NONE} -- Implementation: User
|
feature {NONE} -- Implementation: User
|
||||||
|
|
||||||
user_salt (a_username: READABLE_STRING_32): detachable READABLE_STRING_8
|
user_salt (a_username: READABLE_STRING_32): detachable READABLE_STRING_8
|
||||||
@@ -489,6 +627,9 @@ feature {NONE} -- Implementation: User
|
|||||||
if attached sql_read_string (5) as l_email then
|
if attached sql_read_string (5) as l_email then
|
||||||
Result.set_email (l_email)
|
Result.set_email (l_email)
|
||||||
end
|
end
|
||||||
|
if attached sql_read_integer_32 (6) as l_status then
|
||||||
|
Result.set_status (l_status)
|
||||||
|
end
|
||||||
else
|
else
|
||||||
check expected_valid_user: False end
|
check expected_valid_user: False end
|
||||||
end
|
end
|
||||||
@@ -551,10 +692,11 @@ feature {NONE} -- Sql Queries: USER
|
|||||||
Select_salt_by_username: STRING = "SELECT salt FROM Users WHERE name =:name;"
|
Select_salt_by_username: STRING = "SELECT salt FROM Users WHERE name =:name;"
|
||||||
-- Retrieve salt by username if exists.
|
-- Retrieve salt by username if exists.
|
||||||
|
|
||||||
sql_insert_user: STRING = "INSERT INTO users (name, password, salt, email, created) VALUES (:name, :password, :salt, :email, :created);"
|
sql_insert_user: STRING = "INSERT INTO users (name, password, salt, email, created, status) VALUES (:name, :password, :salt, :email, :created, :status);"
|
||||||
-- SQL Insert to add a new node.
|
-- SQL Insert to add a new user.
|
||||||
|
|
||||||
sql_update_user: STRING = "UPDATE users SET name=:name, password=:password, salt=:salt, email=:email WHERE uid=:uid;"
|
sql_update_user: STRING = "UPDATE users SET name=:name, password=:password, salt=:salt, email=:email, status=:status WHERE uid=:uid;"
|
||||||
|
-- SQL update to update an existing user.
|
||||||
|
|
||||||
feature {NONE} -- Sql Queries: USER ROLE
|
feature {NONE} -- Sql Queries: USER ROLE
|
||||||
|
|
||||||
@@ -584,4 +726,34 @@ feature {NONE} -- Sql Queries: USER ROLE
|
|||||||
select_role_permissions_by_role_id: STRING = "SELECT permission, module FROM role_permissions WHERE rid=:rid;"
|
select_role_permissions_by_role_id: STRING = "SELECT permission, module FROM role_permissions WHERE rid=:rid;"
|
||||||
-- User role permissions for role id :rid;
|
-- User role permissions for role id :rid;
|
||||||
|
|
||||||
|
feature {NONE} -- Sql Queries: USER ACTIVATION
|
||||||
|
|
||||||
|
sql_insert_activation: STRING = "INSERT INTO users_activations (token, uid, created) VALUES (:token, :uid, :utc_date);"
|
||||||
|
-- SQL insert a new activation :token.
|
||||||
|
|
||||||
|
sql_select_activation_expiration: STRING = "SELECT DATEDIFF(day,created,UTC_DATE()) FROM users_activations where token = :token;"
|
||||||
|
-- elapsed time that has passed in days since the token `a_token' was saved.
|
||||||
|
|
||||||
|
sql_select_userid_activation: STRING = "SELECT uid FROM users_activations where token = :token;"
|
||||||
|
-- Retrieve userid given the activation token.
|
||||||
|
|
||||||
|
Select_user_by_activation_token: STRING = "SELECT u.* FROM users 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.
|
||||||
|
|
||||||
|
feature {NONE}
|
||||||
|
|
||||||
|
sql_insert_password: STRING = "INSERT INTO users_password_recovery (token, uid, created) VALUES (:token, :uid, :utc_date);"
|
||||||
|
-- SQL insert a new password recovery :token.
|
||||||
|
|
||||||
|
Sql_remove_password: STRING = "DELETE FROM users_password_recovery WHERE token = :token;"
|
||||||
|
-- Retrieve password if exist.
|
||||||
|
|
||||||
|
Select_user_by_password_token: STRING = "SELECT u.* FROM users as u JOIN users_password_recovery as ua ON ua.uid = u.uid and ua.token = :token;"
|
||||||
|
-- Retrieve user by password token if exist.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
102
src/service/email/email_service.e
Normal file
102
src/service/email/email_service.e
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
note
|
||||||
|
description: "Basic Email Service"
|
||||||
|
date: "$Date: 2015-04-30 05:45:25 -0300 (ju. 30 de abr. de 2015) $"
|
||||||
|
revision: "$Revision: 97218 $"
|
||||||
|
|
||||||
|
class
|
||||||
|
EMAIL_SERVICE
|
||||||
|
|
||||||
|
inherit
|
||||||
|
|
||||||
|
SHARED_ERROR
|
||||||
|
SHARED_LOGGER
|
||||||
|
|
||||||
|
create
|
||||||
|
make
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
make (a_params: like parameters)
|
||||||
|
-- Create instance of {EMAIL_SERVICE} with smtp_server `a_params.smtp_server'.
|
||||||
|
-- Using `a_params.admin_email' as admin email.
|
||||||
|
do
|
||||||
|
parameters := a_params
|
||||||
|
initialize
|
||||||
|
end
|
||||||
|
|
||||||
|
initialize
|
||||||
|
-- Initialize service.
|
||||||
|
local
|
||||||
|
l_address_factory: INET_ADDRESS_FACTORY
|
||||||
|
do
|
||||||
|
admin_email := parameters.admin_email
|
||||||
|
|
||||||
|
-- Get local host name needed in creation of SMTP_PROTOCOL.
|
||||||
|
create l_address_factory
|
||||||
|
create smtp_protocol.make (parameters.smtp_server, l_address_factory.create_localhost.host_name)
|
||||||
|
set_successful
|
||||||
|
end
|
||||||
|
|
||||||
|
parameters: EMAIL_SERVICE_PARAMETERS
|
||||||
|
-- Associated parameters.
|
||||||
|
|
||||||
|
admin_email: IMMUTABLE_STRING_8
|
||||||
|
-- Site admin's email.
|
||||||
|
|
||||||
|
smtp_protocol: SMTP_PROTOCOL
|
||||||
|
-- SMTP protocol.
|
||||||
|
|
||||||
|
feature -- Basic Operations
|
||||||
|
|
||||||
|
send_internal_email (a_content: READABLE_STRING_GENERAL)
|
||||||
|
do
|
||||||
|
send_message (admin_email, admin_email, "Notification Contact", a_content)
|
||||||
|
end
|
||||||
|
|
||||||
|
send_email_internal_server_error (a_content: READABLE_STRING_GENERAL)
|
||||||
|
do
|
||||||
|
send_message (admin_email, admin_email, "Internal Server Error", a_content)
|
||||||
|
end
|
||||||
|
|
||||||
|
send_message (a_from_address, a_to_address: READABLE_STRING_8; a_subjet: READABLE_STRING_GENERAL; a_content: READABLE_STRING_GENERAL)
|
||||||
|
local
|
||||||
|
l_email: EMAIL
|
||||||
|
utf: UTF_CONVERTER
|
||||||
|
do
|
||||||
|
write_debug_log (generator + ".send_message: [from:" + a_from_address + ", to:" + a_to_address + ", subject:" + a_subjet + ", content:" + a_content)
|
||||||
|
create l_email.make_with_entry (a_from_address, a_to_address)
|
||||||
|
l_email.set_message (utf.escaped_utf_32_string_to_utf_8_string_8 (a_content))
|
||||||
|
l_email.add_header_entry ({EMAIL_CONSTANTS}.H_subject, utf.escaped_utf_32_string_to_utf_8_string_8 (a_subjet))
|
||||||
|
l_email.add_header_entry ("MIME-Version:", "1.0")
|
||||||
|
l_email.add_header_entry ("Content-Type", "text/html; charset=utf-8")
|
||||||
|
send_email (l_email)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature {NONE} -- Implementation
|
||||||
|
|
||||||
|
send_email (a_email: EMAIL)
|
||||||
|
-- Send the email represented by `a_email'.
|
||||||
|
local
|
||||||
|
l_retried: BOOLEAN
|
||||||
|
do
|
||||||
|
if not l_retried then
|
||||||
|
write_information_log (generator + ".send_email Process send email.")
|
||||||
|
smtp_protocol.initiate_protocol
|
||||||
|
smtp_protocol.transfer (a_email)
|
||||||
|
smtp_protocol.close_protocol
|
||||||
|
write_information_log (generator + ".send_email Email sent.")
|
||||||
|
if smtp_protocol.error then
|
||||||
|
set_last_error ("smtp_protocol reported an error", generator + ".send_email")
|
||||||
|
else
|
||||||
|
set_successful
|
||||||
|
end
|
||||||
|
else
|
||||||
|
write_error_log (generator + ".send_email Email not send " + last_error_message )
|
||||||
|
end
|
||||||
|
rescue
|
||||||
|
set_last_error_from_exception (generator + ".send_email")
|
||||||
|
l_retried := True
|
||||||
|
retry
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
20
src/service/email/email_service_parameters.e
Normal file
20
src/service/email/email_service_parameters.e
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
note
|
||||||
|
description: "Basic Email Service customized for cms site"
|
||||||
|
author: ""
|
||||||
|
date: "$Date: 2015-01-16 07:17:14 -0300 (vi. 16 de ene. de 2015) $"
|
||||||
|
revision: "$Revision: 96467 $"
|
||||||
|
|
||||||
|
deferred class
|
||||||
|
EMAIL_SERVICE_PARAMETERS
|
||||||
|
|
||||||
|
feature -- Access
|
||||||
|
|
||||||
|
smtp_server: IMMUTABLE_STRING_8
|
||||||
|
deferred
|
||||||
|
end
|
||||||
|
|
||||||
|
admin_email: IMMUTABLE_STRING_8
|
||||||
|
deferred
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@@ -29,6 +29,24 @@ feature -- Access
|
|||||||
Result := storage.user_by_name (a_username)
|
Result := storage.user_by_name (a_username)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
user_by_email (a_email: READABLE_STRING_32): detachable CMS_USER
|
||||||
|
-- User by email `a_email', if any.
|
||||||
|
do
|
||||||
|
Result := 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 := storage.user_by_activation_token (a_token)
|
||||||
|
end
|
||||||
|
|
||||||
|
user_by_password_token (a_token: READABLE_STRING_32): detachable CMS_USER
|
||||||
|
-- User by password token `a_token'.
|
||||||
|
do
|
||||||
|
Result := storage.user_by_password_token (a_token)
|
||||||
|
end
|
||||||
|
|
||||||
feature -- Status report
|
feature -- Status report
|
||||||
|
|
||||||
is_valid_credential (a_auth_login, a_auth_password: READABLE_STRING_32): BOOLEAN
|
is_valid_credential (a_auth_login, a_auth_password: READABLE_STRING_32): BOOLEAN
|
||||||
@@ -133,4 +151,43 @@ feature -- Change User
|
|||||||
storage.update_user (a_user)
|
storage.update_user (a_user)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
feature -- User Activation
|
||||||
|
|
||||||
|
new_activation (a_token: READABLE_STRING_32; a_id: INTEGER_64)
|
||||||
|
-- Save activation token `a_token', for the user with the id `a_id'.
|
||||||
|
do
|
||||||
|
storage.save_activation (a_token, a_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
remove_activation (a_token: READABLE_STRING_32)
|
||||||
|
-- Remove activation token `a_token', from the storage.
|
||||||
|
do
|
||||||
|
storage.remove_activation (a_token)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- User Password Recovery
|
||||||
|
|
||||||
|
new_password (a_token: READABLE_STRING_32; a_id: INTEGER_64)
|
||||||
|
-- Save password token `a_token', for the user with the id `a_id'.
|
||||||
|
do
|
||||||
|
storage.save_password (a_token, a_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
remove_password (a_token: READABLE_STRING_32)
|
||||||
|
-- Remove password token `a_token', from the storage.
|
||||||
|
do
|
||||||
|
storage.remove_password (a_token)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- User status
|
||||||
|
|
||||||
|
not_active: INTEGER = 0
|
||||||
|
-- The user is not active.
|
||||||
|
|
||||||
|
active: INTEGER = 1
|
||||||
|
-- The user is active
|
||||||
|
|
||||||
|
Trashed: INTEGER = -1
|
||||||
|
-- The user is trashed (soft delete), ready to be deleted/destroyed from storage.
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user