From a09962c290f3061156fa6db8901db44ecf0bb0df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Garc=C3=ADa=20Jim=C3=A9nez?= Date: Fri, 11 Mar 2022 17:28:07 -0600 Subject: [PATCH] =?UTF-8?q?[Registra]=20emails=20para=20suscribirse=20al?= =?UTF-8?q?=20bolet=C3=ADn=20de=20Nabu?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controllers/communityController.php | 90 ++++++++++++++++++++++++++++- core/routes.php | 1 + db/db.sql | 8 +++ models/communityModel.php | 28 +++++++++ views/emails/suscription.php | 24 ++++++++ views/pages/all-articles.php | 7 ++- 6 files changed, 153 insertions(+), 5 deletions(-) create mode 100644 views/emails/suscription.php diff --git a/controllers/communityController.php b/controllers/communityController.php index d74afff..0671617 100644 --- a/controllers/communityController.php +++ b/controllers/communityController.php @@ -21,7 +21,7 @@ defined('NABU') || exit(); require_once 'models/communityModel.php'; class communityController { - // Elimina un comentario. + // Elimina un comentario con el método GET. static public function delete_comment() { $view = NABU_ROUTES['home']; @@ -50,7 +50,7 @@ class communityController { utils::redirect(NABU_ROUTES['article'] . '&slug=' . $comment['slug']); } - // Registra o elimina el like de un artículo. + // Registra o elimina el like de un artículo con el método GET. static public function likes() { utils::check_session(NABU_ROUTES['login']); @@ -85,6 +85,92 @@ class communityController { utils::redirect(NABU_ROUTES['article'] . '&slug=' . $article['slug']); } + // Cancela la suscripción de un correo con el método GET + // y registra un e-mail al boletín de los artículos más recientes con el método POST. + static public function suscription() { + $view = NABU_ROUTES['all-articles']; + + $validations = new validations($view); + + // Cancela la suscripción. + if (empty($_POST['suscription-form'])) { + // Valida los parámetros de la URL. + $data = $validations -> validate($_GET, array( + array('field' => 'email', 'trim' => true, 'min_length' => 5, 'max_length' => 255, 'not_spaces' => true), + array('field' => 'key', 'min_length' => 1, 'max_length' => 255) + )); + + $email = strtolower($data['email']); + + if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { + messages::add('Por favor ingresa una dirección de correo electrónico válido'); + utils::redirect($view); + } + + $communityModel = new communityModel(); + + // Obtiene los datos de suscripción. + $suscription = $communityModel -> get_suscription($email); + + if (empty($suscription)) + utils::redirect($view); + + messages::add('Tu suscripción se ha cancelado correctamente'); + + utils::redirect($view); + } + + csrf::validate($_POST['csrf']); + + // Valida el email de la suscripción. + $data = $validations -> validate($_POST, array( + array('field' => 'email', 'trim' => true, 'min_length' => 5, 'max_length' => 255, 'not_spaces' => true), + )); + + $email = strtolower($data['email']); + + if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { + messages::add('Por favor ingresa una dirección de correo electrónico válido'); + utils::redirect($view); + } + + $communityModel = new communityModel(); + + // Obtiene los datos de suscripción. + $suscription = $communityModel -> get_suscription($email); + + if (empty($suscription)) { + // Genera una llave aleatoria de cancelación de suscripción. + $key = bin2hex(random_bytes(32)); + + // Genera un hash de cancelación de suscripción. + $hash = hash_hmac('sha256', $email, $key); + + require_once 'libs/emails.php'; + + $emails = new emails(); + $emails -> prepare($email, $email); + + // Genera una URL de cancelación de suscripción. + $url = NABU_ROUTES['suscription'] . '&email=' . urlencode($email) . '&key=' . $key; + + $body = require_once 'views/emails/suscription.php'; + + // Envía primero un mensaje de suscripción antes de registrarlo. + if (!$emails -> send('¡Gracias por suscribirte!', $body)) + messages::errors('¡Lo sentimos mucho! 😞, por el momento no podemos enviar tu mensaje de suscripción', 500); + + // Registra la suscripción. + $communityModel -> save_suscription($email, $hash); + + messages::add('Gracias por suscribirte al boletín de ' . NABU_DEFAULT['website-name']); + } + else + messages::add('Tu correo electrónico está suscripto al boletín de ' . NABU_DEFAULT['website-name']); + + utils::redirect($view); + } + static public function favorites() { // } diff --git a/core/routes.php b/core/routes.php index ac07951..bb9a4b3 100644 --- a/core/routes.php +++ b/core/routes.php @@ -41,4 +41,5 @@ return array( 'registered-users' => array('route' => 'registered-users', 'controller' => 'adminController', 'view' => 'registered_users'), 'review-article' => array('route' => 'review-article', 'controller' => 'adminController', 'view' => 'review_article'), 'signup' => array('route' => 'signup', 'controller' => 'usersController', 'view' => 'signup'), + 'suscription' => array('route' => 'suscription', 'controller' => 'communityController', 'view' => 'suscription'), ); diff --git a/db/db.sql b/db/db.sql index 03f6d25..6179abb 100644 --- a/db/db.sql +++ b/db/db.sql @@ -97,6 +97,14 @@ CREATE TABLE IF NOT EXISTS `favorites` ( CONSTRAINT favorites_article_id_fk FOREIGN KEY(article_id) REFERENCES articles(id) ON UPDATE CASCADE ON DELETE CASCADE ); +CREATE TABLE IF NOT EXISTS `suscriptions` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `email` VARCHAR(255) NOT NULL, + `hash` VARCHAR(255) NOT NULL, + CONSTRAINT suscriptions_pk PRIMARY KEY(id), + CONSTRAINT suscriptions_email_uk UNIQUE(email) +); + INSERT INTO roles(id, name) VALUES(1, 'ADMIN'), (2, 'MODERATOR'), (3, 'USER'); INSERT INTO users VALUES(1, 1, 'root', 'root', 'root@example.com', '$2y$12$.1ycdL5xs4nOpQ3GXga7m.IFNtfMgV5nKVe4R87B3CypgigBaJ55C', TRUE, NOW()); INSERT INTO profiles(id) VALUES(1); diff --git a/models/communityModel.php b/models/communityModel.php index c581318..fa4ebbb 100644 --- a/models/communityModel.php +++ b/models/communityModel.php @@ -109,6 +109,34 @@ class communityModel extends dbConnection { } } + // Obtiene los datos de suscripción de un e-mail. + public function get_suscription(string $email) { + $query = 'SELECT * FROM suscriptions WHERE email = ? LIMIT 1'; + + try { + $prepare = $this -> pdo -> prepare($query); + + $prepare -> execute(array($email)); + + return $prepare -> fetch(); + } + catch (PDOException $e) { + $this -> errors($e -> getMessage(), 'tuvimos un problema para obtener los datos de una suscripción'); + } + } + + // Registra una suscripción. + public function save_suscription(string $email, string $hash) { + $query = 'INSERT INTO suscriptions(email, hash) VALUES(?, ?)'; + + try { + $this -> pdo -> prepare($query) -> execute(array($email, $hash)); + } + catch (PDOException $e) { + $this -> errors($e -> getMessage(), 'tuvimos un problema para registrar una suscripción'); + } + } + public function __destruct() { parent::__destruct(); $this -> pdo = null; diff --git a/views/emails/suscription.php b/views/emails/suscription.php new file mode 100644 index 0000000..037c424 --- /dev/null +++ b/views/emails/suscription.php @@ -0,0 +1,24 @@ +. +*/ + +defined('NABU') || exit(); + +return 'A partir de ahora recibirás correos de parte de nuestro equipo en los que compartiremos ' . + 'contigo blogposts que te pudiesen interesar, así como tips para que tu escritura en medios ' . + 'digitales sea una de tus más grandes cualidades.

' . + '

Cancelar suscripción.

'; diff --git a/views/pages/all-articles.php b/views/pages/all-articles.php index ab5cd05..f53e89a 100644 --- a/views/pages/all-articles.php +++ b/views/pages/all-articles.php @@ -79,9 +79,10 @@

Interesante, ¿No? 🤔

Déjanos tu e-mail y te compartiremos los posts más recientes, además de recursos para mejorar tu escritura en medios digitales. 😉

-
- - + + + +