\ No newline at end of file
diff --git a/examples/demo/site/themes/bootstrap/modules/login/templates/block_new_password.tpl b/examples/demo/site/themes/bootstrap/modules/login/templates/block_new_password.tpl
new file mode 100644
index 0000000..84b5de0
--- /dev/null
+++ b/examples/demo/site/themes/bootstrap/modules/login/templates/block_new_password.tpl
@@ -0,0 +1,16 @@
+
+
+
diff --git a/examples/demo/site/themes/bootstrap/modules/login/templates/block_post_password.tpl b/examples/demo/site/themes/bootstrap/modules/login/templates/block_post_password.tpl
new file mode 100644
index 0000000..0ec7a7c
--- /dev/null
+++ b/examples/demo/site/themes/bootstrap/modules/login/templates/block_post_password.tpl
@@ -0,0 +1,3 @@
+
+
We have send you a new token code, check your email to generate a new password
+
diff --git a/examples/demo/site/themes/bootstrap/modules/login/templates/block_post_reactivate.tpl b/examples/demo/site/themes/bootstrap/modules/login/templates/block_post_reactivate.tpl
new file mode 100644
index 0000000..09e7206
--- /dev/null
+++ b/examples/demo/site/themes/bootstrap/modules/login/templates/block_post_reactivate.tpl
@@ -0,0 +1,3 @@
+
+
We have send you a new activation code, check your email to activate your account.
+
diff --git a/examples/demo/site/themes/bootstrap/modules/login/templates/block_post_register.tpl b/examples/demo/site/themes/bootstrap/modules/login/templates/block_post_register.tpl
new file mode 100644
index 0000000..d59f75a
--- /dev/null
+++ b/examples/demo/site/themes/bootstrap/modules/login/templates/block_post_register.tpl
@@ -0,0 +1,3 @@
+
+
Thanks for register, check your email to activate your account.
+
diff --git a/examples/demo/site/themes/bootstrap/modules/login/templates/block_post_reset.tpl b/examples/demo/site/themes/bootstrap/modules/login/templates/block_post_reset.tpl
new file mode 100644
index 0000000..9ccecfb
--- /dev/null
+++ b/examples/demo/site/themes/bootstrap/modules/login/templates/block_post_reset.tpl
@@ -0,0 +1,3 @@
+
+
You new password has been saved!
+
diff --git a/examples/demo/site/themes/bootstrap/modules/login/templates/block_reactivate.tpl b/examples/demo/site/themes/bootstrap/modules/login/templates/block_reactivate.tpl
new file mode 100644
index 0000000..01a7960
--- /dev/null
+++ b/examples/demo/site/themes/bootstrap/modules/login/templates/block_reactivate.tpl
@@ -0,0 +1,19 @@
+
+
+
diff --git a/examples/demo/site/themes/bootstrap/modules/login/templates/block_register.tpl b/examples/demo/site/themes/bootstrap/modules/login/templates/block_register.tpl
new file mode 100644
index 0000000..522bde9
--- /dev/null
+++ b/examples/demo/site/themes/bootstrap/modules/login/templates/block_register.tpl
@@ -0,0 +1,28 @@
+
+
+
diff --git a/examples/demo/site/themes/bootstrap/modules/login/templates/block_reset_password.tpl b/examples/demo/site/themes/bootstrap/modules/login/templates/block_reset_password.tpl
new file mode 100644
index 0000000..aa2ee81
--- /dev/null
+++ b/examples/demo/site/themes/bootstrap/modules/login/templates/block_reset_password.tpl
@@ -0,0 +1,28 @@
+
+
+
diff --git a/examples/demo/src/ewf_roc_server.e b/examples/demo/src/ewf_roc_server.e
index d284825..86a7dd4 100644
--- a/examples/demo/src/ewf_roc_server.e
+++ b/examples/demo/src/ewf_roc_server.e
@@ -135,6 +135,11 @@ feature -- CMS setup
m.enable
a_setup.register_module (m)
+ create {LOGIN_MODULE} m.make
+ m.enable
+ a_setup.register_module (m)
+
+
create {BASIC_AUTH_MODULE} m.make
if not a_setup.module_with_same_type_registered (m) then
m.enable
diff --git a/library/model/src/user/cms_user.e b/library/model/src/user/cms_user.e
index 5abb436..713ca65 100644
--- a/library/model/src/user/cms_user.e
+++ b/library/model/src/user/cms_user.e
@@ -27,6 +27,7 @@ feature {NONE} -- Initialization
initialize
ensure
name_set: name = a_name
+ status_not_active: status = not_active
end
make_with_id (a_id: INTEGER_64)
@@ -38,11 +39,13 @@ feature {NONE} -- Initialization
initialize
ensure
id_set: id = a_id
+ status_not_active: status = not_active
end
initialize
do
create creation_date.make_now_utc
+ mark_not_active
end
feature -- Access
@@ -71,6 +74,13 @@ feature -- Access
last_login_date: detachable DATE_TIME
-- User last login.
+ status: INTEGER
+ -- Associated status for the current user.
+ -- default: not_active
+ -- active
+ -- trashed
+
+
feature -- Roles
roles: detachable LIST [CMS_USER_ROLE]
@@ -118,6 +128,12 @@ feature -- Status report
Result := other /= Void and then id = other.id
end
+ is_active: BOOLEAN
+ -- is the current user active?
+ do
+ Result := status = {CMS_USER}.active
+ end
+
feature -- Change element
set_id (a_id: like id)
@@ -225,6 +241,52 @@ feature -- Change element: data
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
id_or_name_set: id > 0 or else not name.is_whitespace
diff --git a/library/persistence/mysql/scripts/core.sql b/library/persistence/mysql/scripts/core.sql
new file mode 100644
index 0000000..366ccbd
--- /dev/null
+++ b/library/persistence/mysql/scripts/core.sql
@@ -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;
+
diff --git a/library/persistence/mysql/scripts/create_database.sql b/library/persistence/mysql/scripts/create_database.sql
deleted file mode 100644
index a78dd4e..0000000
--- a/library/persistence/mysql/scripts/create_database.sql
+++ /dev/null
@@ -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;
diff --git a/library/persistence/mysql/scripts/node.sql b/library/persistence/mysql/scripts/node.sql
new file mode 100644
index 0000000..a4a053e
--- /dev/null
+++ b/library/persistence/mysql/scripts/node.sql
@@ -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;
diff --git a/library/persistence/mysql/scripts/schema.sql b/library/persistence/mysql/scripts/schema.sql
deleted file mode 100644
index 382707e..0000000
--- a/library/persistence/mysql/scripts/schema.sql
+++ /dev/null
@@ -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;
diff --git a/library/persistence/mysql/scripts/tables.sql b/library/persistence/mysql/scripts/tables.sql
deleted file mode 100644
index 4b1a4ba..0000000
--- a/library/persistence/mysql/scripts/tables.sql
+++ /dev/null
@@ -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)
-);
\ No newline at end of file
diff --git a/library/persistence/mysql/scripts/triggers.sql b/library/persistence/mysql/scripts/triggers.sql
deleted file mode 100644
index b3e10a4..0000000
--- a/library/persistence/mysql/scripts/triggers.sql
+++ /dev/null
@@ -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 ;
\ No newline at end of file
diff --git a/library/persistence/mysql/scripts/user.sql b/library/persistence/mysql/scripts/user.sql
new file mode 100644
index 0000000..e99072a
--- /dev/null
+++ b/library/persistence/mysql/scripts/user.sql
@@ -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;
\ No newline at end of file
diff --git a/modules/basic_auth/basic_auth_module.e b/modules/basic_auth/basic_auth_module.e
index 515cac7..0d9d649 100644
--- a/modules/basic_auth/basic_auth_module.e
+++ b/modules/basic_auth/basic_auth_module.e
@@ -108,14 +108,14 @@ feature -- Hooks
local
lnk: CMS_LOCAL_LINK
do
- 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)
- else
- create lnk.make ("Login", "basic_auth_login?destination=" + a_response.request.request_uri)
- end
+-- 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)
+-- else
+-- create lnk.make ("Login", "basic_auth_login?destination=" + a_response.request.request_uri)
+-- end
-- if not a_menu_system.primary_menu.has (lnk) then
- lnk.set_weight (99)
- a_menu_system.primary_menu.extend (lnk)
+-- lnk.set_weight (99)
+-- a_menu_system.primary_menu.extend (lnk)
-- end
end
diff --git a/modules/basic_auth/handler/basic_auth_logoff_handler.e b/modules/basic_auth/handler/basic_auth_logoff_handler.e
index 40ca330..5e8a667 100644
--- a/modules/basic_auth/handler/basic_auth_logoff_handler.e
+++ b/modules/basic_auth/handler/basic_auth_logoff_handler.e
@@ -55,21 +55,62 @@ feature -- HTTP Methods
else
create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api)
unset_current_user (req)
- l_page.set_status_code ({HTTP_STATUS_CODE}.found) -- 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_uri.url_encoded_value)
- else
- l_url := req.absolute_script_url ("")
- end
+ l_page.set_status_code ({HTTP_STATUS_CODE}.unauthorized) -- Note: can not use {HTTP_STATUS_CODE}.unauthorized for redirection
+ l_url := req.absolute_script_url ("")
i := l_url.substring_index ("://", 1)
if i > 0 then
-- Note: this is a hack to have the logout effective on various browser
-- (firefox requires this).
l_url.replace_substring ("://_logout_basic_auth_@", i, i + 2)
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
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
diff --git a/modules/login/login-safe.ecf b/modules/login/login-safe.ecf
new file mode 100644
index 0000000..eaba1d4
--- /dev/null
+++ b/modules/login/login-safe.ecf
@@ -0,0 +1,23 @@
+
+
+
+
+
+ /.git$
+ /EIFGENs$
+ /.svn$
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/login/login_email_service.e b/modules/login/login_email_service.e
new file mode 100644
index 0000000..2ada59e
--- /dev/null
+++ b/modules/login/login_email_service.e
@@ -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
diff --git a/modules/login/login_email_service_parameters.e b/modules/login/login_email_service_parameters.e
new file mode 100644
index 0000000..d356af0
--- /dev/null
+++ b/modules/login/login_email_service_parameters.e
@@ -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
diff --git a/modules/login/login_module.e b/modules/login/login_module.e
new file mode 100644
index 0000000..32f7249
--- /dev/null
+++ b/modules/login/login_module.e
@@ -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)
+ --
+ 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 ("
Your account "+ l_user.name +" has been activated
")
+ 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 ("
" )
+
+ 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 here 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= "[
+
+
+
+
+ Eiffel.org Activation
+
+
+
+
+
+