From 013b16774ed9bbd34e09c8be1a43ba9e7a932eba Mon Sep 17 00:00:00 2001 From: bivanalhar <bivan.alzacky@gmail.com> Date: Fri, 27 Dec 2024 14:31:35 +0800 Subject: [PATCH 1/2] feat(keycloak): use CM userId for keycloak user ID --- authentication/import/coursemology_realm.json | 20 +++++++++---------- authentication/script/cm_db_federation.sql | 10 +++++----- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/authentication/import/coursemology_realm.json b/authentication/import/coursemology_realm.json index 9714c2af38c..8fcf23b203d 100644 --- a/authentication/import/coursemology_realm.json +++ b/authentication/import/coursemology_realm.json @@ -1800,22 +1800,22 @@ "false" ], "findBySearchTerm": [ - "select ue.id as \"id\", users.id as \"user_id\", ue.email as \"username\", ue.email as \"email\", users.name as \"firstName\", CASE WHEN ue.confirmed_at IS NOT NULL THEN 'TRUE' ELSE NULL END as \"EMAIL_VERIFIED\"from user_emails ue left join users on ue.user_id = users.id where LOWER(ue.email) like LOWER(concat('%', ?, '%')) or LOWER(users.name) like LOWER(concat('%', ?, '%'))" + "SELECT users.id AS \"id\", users.id AS \"user_id\", pe.email AS \"username\", pe.email AS \"email\", users.name AS \"firstName\", CASE WHEN MAX(CASE WHEN pe.confirmed_at IS NOT NULL THEN 1 ELSE 0 END) = 1 THEN 'TRUE' ELSE NULL END AS \"EMAIL_VERIFIED\" FROM user_emails ue LEFT JOIN users ON ue.user_id = users.id LEFT JOIN user_emails pe ON ue.user_id = pe.user_id AND pe.primary = TRUE WHERE LOWER(pe.email) LIKE LOWER(CONCAT('%', ?, '%')) OR LOWER(users.name) LIKE LOWER(CONCAT('%', ?, '%')) OR (ue.primary = FALSE AND ue.confirmed_at IS NOT NULL AND LOWER(ue.email) LIKE LOWER(CONCAT('%', ?, '%'))) GROUP BY pe.id, users.id, pe.email, users.name" ], "password": [ "password" ], "findByUsername": [ - "select ue.id as \"id\", users.id as \"user_id\", ue.email as \"username\", ue.email as \"email\", users.name as \"firstName\", CASE WHEN ue.confirmed_at IS NOT NULL THEN 'TRUE' ELSE NULL END as \"EMAIL_VERIFIED\" from user_emails ue left join users on ue.user_id = users.id where LOWER(ue.email) = LOWER(?)" + "SELECT users.id as \"id\", users.id as \"user_id\", pe.email as \"username\", pe.email as \"email\", users.name as \"firstName\", CASE WHEN ue.confirmed_at IS NOT NULL THEN 'TRUE' ELSE NULL END as \"EMAIL_VERIFIED\" from user_emails ue left join users on ue.user_id = users.id left join user_emails pe on ue.user_id = pe.user_id AND pe.primary = TRUE where LOWER(ue.email) = LOWER(?) AND ue.confirmed_at IS NOT NULL GROUP BY pe.id, users.id, pe.email, users.name, ue.confirmed_at" ], "findById": [ - "select ue.id as \"id\", users.id as \"user_id\", ue.email as \"username\", ue.email as \"email\", users.name as \"firstName\", CASE WHEN ue.confirmed_at IS NOT NULL THEN 'TRUE' ELSE NULL END as \"EMAIL_VERIFIED\" from user_emails ue left join users on ue.user_id = users.id where cast(ue.id as character varying) = ?" + "SELECT users.id as \"id\", users.id as \"user_id\", pe.email as \"username\", pe.email as \"email\", users.name as \"firstName\", CASE WHEN ue.confirmed_at IS NOT NULL THEN 'TRUE' ELSE NULL END as \"EMAIL_VERIFIED\" from user_emails ue left join users on ue.user_id = users.id left join user_emails pe ON ue.user_id = pe.user_id AND pe.primary = TRUE where cast(users.id as character varying) = ? AND ue.confirmed_at IS NOT NULL GROUP BY pe.id, users.id, pe.email, users.name, ue.confirmed_at" ], "listAll": [ - "select ue.id as \"id\", users.id as \"user_id\", ue.email as \"username\", ue.email as \"email\", users.name as \"firstName\", CASE WHEN ue.confirmed_at IS NOT NULL THEN 'TRUE' ELSE NULL END as \"EMAIL_VERIFIED\" from user_emails ue left join users on ue.user_id = users.id" + "SELECT users.id as \"id\", users.id as \"user_id\", pe.email as \"username\", pe.email as \"email\", users.name as \"firstName\", CASE WHEN pe.confirmed_at IS NOT NULL THEN 'TRUE' ELSE NULL END as \"EMAIL_VERIFIED\" from user_emails pe left join users on pe.user_id = users.id where pe.primary = TRUE" ], "findByEmail": [ - "select ue.id as \"id\", users.id as \"user_id\", ue.email as \"username\", ue.email as \"email\", users.name as \"firstName\", CASE WHEN ue.confirmed_at IS NOT NULL THEN 'TRUE' ELSE NULL END as \"EMAIL_VERIFIED\" from user_emails ue left join users on ue.user_id = users.id where LOWER(ue.email) = LOWER(?)" + "SELECT users.id as \"id\", users.id as \"user_id\", pe.email as \"username\", pe.email as \"email\", users.name as \"firstName\", CASE WHEN ue.confirmed_at IS NOT NULL THEN 'TRUE' ELSE NULL END as \"EMAIL_VERIFIED\" from user_emails ue left join users on ue.user_id = users.id left join user_emails pe on ue.user_id = pe.user_id AND pe.primary = TRUE where LOWER(ue.email) = LOWER(?) AND ue.confirmed_at IS NOT NULL GROUP BY pe.id, users.id, pe.email, users.name, ue.confirmed_at" ], "user": [ "postgres" @@ -4192,19 +4192,19 @@ "false" ], "findBySearchTerm": [ - "select ue.id as \"id\", users.id as \"user_id\", ue.email as \"username\", ue.email as \"email\", users.name as \"firstName\", CASE WHEN ue.confirmed_at IS NOT NULL THEN 'TRUE' ELSE NULL END as \"EMAIL_VERIFIED\"from user_emails ue left join users on ue.user_id = users.id where LOWER(ue.email) like LOWER(concat('%', ?, '%')) or LOWER(users.name) like LOWER(concat('%', ?, '%'))" + "SELECT users.id AS \"id\", users.id AS \"user_id\", pe.email AS \"username\", pe.email AS \"email\", users.name AS \"firstName\", CASE WHEN MAX(CASE WHEN pe.confirmed_at IS NOT NULL THEN 1 ELSE 0 END) = 1 THEN 'TRUE' ELSE NULL END AS \"EMAIL_VERIFIED\" FROM user_emails ue LEFT JOIN users ON ue.user_id = users.id LEFT JOIN user_emails pe ON ue.user_id = pe.user_id AND pe.primary = TRUE WHERE LOWER(pe.email) LIKE LOWER(CONCAT('%', ?, '%')) OR LOWER(users.name) LIKE LOWER(CONCAT('%', ?, '%')) OR (ue.primary = FALSE AND ue.confirmed_at IS NOT NULL AND LOWER(ue.email) LIKE LOWER(CONCAT('%', ?, '%'))) GROUP BY pe.id, users.id, pe.email, users.name" ], "findByUsername": [ - "select ue.id as \"id\", users.id as \"user_id\", ue.email as \"username\", ue.email as \"email\", users.name as \"firstName\", CASE WHEN ue.confirmed_at IS NOT NULL THEN 'TRUE' ELSE NULL END as \"EMAIL_VERIFIED\" from user_emails ue left join users on ue.user_id = users.id where LOWER(ue.email) = LOWER(?)" + "SELECT users.id as \"id\", users.id as \"user_id\", pe.email as \"username\", pe.email as \"email\", users.name as \"firstName\", CASE WHEN ue.confirmed_at IS NOT NULL THEN 'TRUE' ELSE NULL END as \"EMAIL_VERIFIED\" from user_emails ue left join users on ue.user_id = users.id left join user_emails pe on ue.user_id = pe.user_id AND pe.primary = TRUE where LOWER(ue.email) = LOWER(?) AND ue.confirmed_at IS NOT NULL GROUP BY pe.id, users.id, pe.email, users.name, ue.confirmed_at" ], "findById": [ - "select ue.id as \"id\", users.id as \"user_id\", ue.email as \"username\", ue.email as \"email\", users.name as \"firstName\", CASE WHEN ue.confirmed_at IS NOT NULL THEN 'TRUE' ELSE NULL END as \"EMAIL_VERIFIED\" from user_emails ue left join users on ue.user_id = users.id where cast(ue.id as character varying) = ?" + "SELECT users.id as \"id\", users.id as \"user_id\", pe.email as \"username\", pe.email as \"email\", users.name as \"firstName\", CASE WHEN ue.confirmed_at IS NOT NULL THEN 'TRUE' ELSE NULL END as \"EMAIL_VERIFIED\" from user_emails ue left join users on ue.user_id = users.id left join user_emails pe ON ue.user_id = pe.user_id AND pe.primary = TRUE where cast(users.id as character varying) = ? AND ue.confirmed_at IS NOT NULL GROUP BY pe.id, users.id, pe.email, users.name, ue.confirmed_at" ], "listAll": [ - "select ue.id as \"id\", users.id as \"user_id\", ue.email as \"username\", ue.email as \"email\", users.name as \"firstName\", CASE WHEN ue.confirmed_at IS NOT NULL THEN 'TRUE' ELSE NULL END as \"EMAIL_VERIFIED\" from user_emails ue left join users on ue.user_id = users.id" + "SELECT users.id as \"id\", users.id as \"user_id\", pe.email as \"username\", pe.email as \"email\", users.name as \"firstName\", CASE WHEN pe.confirmed_at IS NOT NULL THEN 'TRUE' ELSE NULL END as \"EMAIL_VERIFIED\" from user_emails pe left join users on pe.user_id = users.id where pe.primary = TRUE" ], "findByEmail": [ - "select ue.id as \"id\", users.id as \"user_id\", ue.email as \"username\", ue.email as \"email\", users.name as \"firstName\", CASE WHEN ue.confirmed_at IS NOT NULL THEN 'TRUE' ELSE NULL END as \"EMAIL_VERIFIED\" from user_emails ue left join users on ue.user_id = users.id where LOWER(ue.email) = LOWER(?)" + "SELECT users.id as \"id\", users.id as \"user_id\", pe.email as \"username\", pe.email as \"email\", users.name as \"firstName\", CASE WHEN ue.confirmed_at IS NOT NULL THEN 'TRUE' ELSE NULL END as \"EMAIL_VERIFIED\" from user_emails ue left join users on ue.user_id = users.id left join user_emails pe on ue.user_id = pe.user_id AND pe.primary = TRUE where LOWER(ue.email) = LOWER(?) AND ue.confirmed_at IS NOT NULL GROUP BY pe.id, users.id, pe.email, users.name, ue.confirmed_at" ], "user": [ "postgres" diff --git a/authentication/script/cm_db_federation.sql b/authentication/script/cm_db_federation.sql index 8e9b319280c..d8033865ad1 100644 --- a/authentication/script/cm_db_federation.sql +++ b/authentication/script/cm_db_federation.sql @@ -2,19 +2,19 @@ select count(*) from users; -- List All Users SQL query -select ue.id as "id", users.id as "user_id", ue.email as "username", ue.email as "email", users.name as "firstName", CASE WHEN ue.confirmed_at IS NOT NULL THEN 'TRUE' ELSE NULL END as "EMAIL_VERIFIED" from user_emails ue left join users on ue.user_id = users.id +select users.id as "id", users.id as "user_id", pe.email as "username", pe.email as "email", users.name as "firstName", CASE WHEN pe.confirmed_at IS NOT NULL THEN 'TRUE' ELSE NULL END as "EMAIL_VERIFIED" from user_emails pe left join users on pe.user_id = users.id where pe.primary = TRUE -- Find user by id SQL query -select ue.id as "id", users.id as "user_id", ue.email as "username", ue.email as "email", users.name as "firstName", CASE WHEN ue.confirmed_at IS NOT NULL THEN 'TRUE' ELSE NULL END as "EMAIL_VERIFIED" from user_emails ue left join users on ue.user_id = users.id where cast(ue.id as character varying) = ? +select users.id as "id", users.id as "user_id", pe.email as "username", pe.email as "email", users.name as "firstName", CASE WHEN ue.confirmed_at IS NOT NULL THEN 'TRUE' ELSE NULL END as "EMAIL_VERIFIED" from user_emails ue left join users on ue.user_id = users.id left join user_emails pe ON ue.user_id = pe.user_id AND pe.primary = TRUE where cast(users.id as character varying) = ? AND ue.confirmed_at IS NOT NULL GROUP BY pe.id, users.id, pe.email, users.name, ue.confirmed_at -- Find user by username SQL query -select ue.id as "id", users.id as "user_id", ue.email as "username", ue.email as "email", users.name as "firstName", CASE WHEN ue.confirmed_at IS NOT NULL THEN 'TRUE' ELSE NULL END as "EMAIL_VERIFIED" from user_emails ue left join users on ue.user_id = users.id where LOWER(ue.email) = LOWER(?) +select users.id as "id", users.id as "user_id", pe.email as "username", pe.email as "email", users.name as "firstName", CASE WHEN ue.confirmed_at IS NOT NULL THEN 'TRUE' ELSE NULL END as "EMAIL_VERIFIED" from user_emails ue left join users on ue.user_id = users.id LEFT JOIN user_emails pe ON ue.user_id = pe.user_id AND pe.primary = TRUE where LOWER(ue.email) = LOWER(?) AND ue.confirmed_at IS NOT NULL GROUP BY pe.id, users.id, pe.email, users.name, ue.confirmed_at -- Find user by email SQL query -select ue.id as "id", users.id as "user_id", ue.email as "username", ue.email as "email", users.name as "firstName", CASE WHEN ue.confirmed_at IS NOT NULL THEN 'TRUE' ELSE NULL END as "EMAIL_VERIFIED" from user_emails ue left join users on ue.user_id = users.id where LOWER(ue.email) = LOWER(?) +select users.id as "id", users.id as "user_id", pe.email as "username", pe.email as "email", users.name as "firstName", CASE WHEN ue.confirmed_at IS NOT NULL THEN 'TRUE' ELSE NULL END as "EMAIL_VERIFIED" from user_emails ue left join users on ue.user_id = users.id LEFT JOIN user_emails pe ON ue.user_id = pe.user_id AND pe.primary = TRUE where LOWER(ue.email) = LOWER(?) AND ue.confirmed_at IS NOT NULL GROUP BY pe.id, users.id, pe.email, users.name, ue.confirmed_at -- Find user by search term SQL query -select ue.id as "id", users.id as "user_id", ue.email as "username", ue.email as "email", users.name as "firstName", CASE WHEN ue.confirmed_at IS NOT NULL THEN 'TRUE' ELSE NULL END as "EMAIL_VERIFIED"from user_emails ue left join users on ue.user_id = users.id where LOWER(ue.email) like LOWER(concat('%', ?, '%')) or LOWER(users.name) like LOWER(concat('%', ?, '%')) +SELECT users.id AS "id", users.id AS "user_id", pe.email AS "username", pe.email AS "email", users.name AS "firstName", CASE WHEN MAX(CASE WHEN pe.confirmed_at IS NOT NULL THEN 1 ELSE 0 END) = 1 THEN 'TRUE' ELSE NULL END AS "EMAIL_VERIFIED" FROM user_emails ue LEFT JOIN users ON ue.user_id = users.id LEFT JOIN user_emails pe ON ue.user_id = pe.user_id AND pe.primary = TRUE WHERE LOWER(pe.email) LIKE LOWER(CONCAT('%', ?, '%')) OR LOWER(users.name) LIKE LOWER(CONCAT('%', ?, '%')) OR (ue.primary = FALSE AND ue.confirmed_at IS NOT NULL AND LOWER(ue.email) LIKE LOWER(CONCAT('%', ?, '%'))) GROUP BY pe.id, users.id, pe.email, users.name -- Find password hash (blowfish or hash digest hex) SQL query select encrypted_password as hash_pwd from users right join user_emails ue on users.id = ue.user_id where ue.email = ? From e62be73c1a9bda24e256ecb09f527e3ff0af5a79 Mon Sep 17 00:00:00 2001 From: bivanalhar <bivan.alzacky@gmail.com> Date: Fri, 27 Dec 2024 14:31:49 +0800 Subject: [PATCH 2/2] feat(user): prevent destroying primary email --- app/controllers/user/emails_controller.rb | 7 ++++++ authentication/import/coursemology_realm.json | 14 +++++------ authentication/script/cm_db_federation.sql | 10 ++++---- config/locales/en/user/emails.yml | 1 + config/locales/ko/user/emails.yml | 1 + config/locales/zh/user/emails.yml | 1 + .../user/emails_controller_spec.rb | 25 +++++++++++++------ 7 files changed, 39 insertions(+), 20 deletions(-) diff --git a/app/controllers/user/emails_controller.rb b/app/controllers/user/emails_controller.rb index e2a125bded2..985caa4bb9f 100644 --- a/app/controllers/user/emails_controller.rb +++ b/app/controllers/user/emails_controller.rb @@ -14,6 +14,13 @@ def create end def destroy + if @email.primary? + @email.errors.add(:base, I18n.t('user.emails.index.cannot_delete_primary')) + render json: { errors: @email.errors.full_messages.to_sentence }, status: :bad_request + + return + end + if @email.destroy render_emails else diff --git a/authentication/import/coursemology_realm.json b/authentication/import/coursemology_realm.json index 8fcf23b203d..f5da68b0ccd 100644 --- a/authentication/import/coursemology_realm.json +++ b/authentication/import/coursemology_realm.json @@ -1788,7 +1788,7 @@ "select encrypted_password as hash_pwd from users right join user_emails ue on users.id = ue.user_id where LOWER(ue.email) = LOWER(?)" ], "cachePolicy": [ - "DEFAULT" + "NO_CACHE" ], "url": [ "jdbc:postgresql://host.docker.internal:5432/coursemology" @@ -1800,22 +1800,22 @@ "false" ], "findBySearchTerm": [ - "SELECT users.id AS \"id\", users.id AS \"user_id\", pe.email AS \"username\", pe.email AS \"email\", users.name AS \"firstName\", CASE WHEN MAX(CASE WHEN pe.confirmed_at IS NOT NULL THEN 1 ELSE 0 END) = 1 THEN 'TRUE' ELSE NULL END AS \"EMAIL_VERIFIED\" FROM user_emails ue LEFT JOIN users ON ue.user_id = users.id LEFT JOIN user_emails pe ON ue.user_id = pe.user_id AND pe.primary = TRUE WHERE LOWER(pe.email) LIKE LOWER(CONCAT('%', ?, '%')) OR LOWER(users.name) LIKE LOWER(CONCAT('%', ?, '%')) OR (ue.primary = FALSE AND ue.confirmed_at IS NOT NULL AND LOWER(ue.email) LIKE LOWER(CONCAT('%', ?, '%'))) GROUP BY pe.id, users.id, pe.email, users.name" + "SELECT users.id AS \"id\", users.id AS \"user_id\", pe.email AS \"username\", pe.email AS \"email\", users.name AS \"firstName\", CASE WHEN MAX(CASE WHEN pe.confirmed_at IS NOT NULL THEN 1 ELSE 0 END) = 1 THEN 'TRUE' ELSE 'FALSE' END AS \"EMAIL_VERIFIED\" FROM user_emails ue LEFT JOIN users ON ue.user_id = users.id LEFT JOIN user_emails pe ON ue.user_id = pe.user_id AND pe.primary = TRUE WHERE LOWER(pe.email) LIKE LOWER(CONCAT('%', ?, '%')) OR LOWER(users.name) LIKE LOWER(CONCAT('%', ?, '%')) OR (ue.primary = FALSE AND ue.confirmed_at IS NOT NULL AND LOWER(ue.email) LIKE LOWER(CONCAT('%', ?, '%'))) GROUP BY pe.id, users.id, pe.email, users.name" ], "password": [ "password" ], "findByUsername": [ - "SELECT users.id as \"id\", users.id as \"user_id\", pe.email as \"username\", pe.email as \"email\", users.name as \"firstName\", CASE WHEN ue.confirmed_at IS NOT NULL THEN 'TRUE' ELSE NULL END as \"EMAIL_VERIFIED\" from user_emails ue left join users on ue.user_id = users.id left join user_emails pe on ue.user_id = pe.user_id AND pe.primary = TRUE where LOWER(ue.email) = LOWER(?) AND ue.confirmed_at IS NOT NULL GROUP BY pe.id, users.id, pe.email, users.name, ue.confirmed_at" + "SELECT users.id as \"id\", users.id as \"user_id\", ue.email as \"username\", ue.email as \"email\", users.name as \"firstName\", CASE WHEN ue.confirmed_at IS NOT NULL THEN 'TRUE' ELSE 'FALSE' END as \"EMAIL_VERIFIED\" from user_emails ue left join users on ue.user_id = users.id where LOWER(ue.email) = LOWER(?) GROUP BY users.id, ue.email, users.name, ue.confirmed_at" ], "findById": [ - "SELECT users.id as \"id\", users.id as \"user_id\", pe.email as \"username\", pe.email as \"email\", users.name as \"firstName\", CASE WHEN ue.confirmed_at IS NOT NULL THEN 'TRUE' ELSE NULL END as \"EMAIL_VERIFIED\" from user_emails ue left join users on ue.user_id = users.id left join user_emails pe ON ue.user_id = pe.user_id AND pe.primary = TRUE where cast(users.id as character varying) = ? AND ue.confirmed_at IS NOT NULL GROUP BY pe.id, users.id, pe.email, users.name, ue.confirmed_at" + "SELECT users.id as \"id\", users.id as \"user_id\", pe.email as \"username\", pe.email as \"email\", users.name as \"firstName\" from user_emails pe left join users on pe.user_id = users.id where cast(users.id as character varying) = ? AND pe.primary = TRUE AND pe.confirmed_at IS NOT NULL GROUP BY users.id, pe.email, users.name" ], "listAll": [ - "SELECT users.id as \"id\", users.id as \"user_id\", pe.email as \"username\", pe.email as \"email\", users.name as \"firstName\", CASE WHEN pe.confirmed_at IS NOT NULL THEN 'TRUE' ELSE NULL END as \"EMAIL_VERIFIED\" from user_emails pe left join users on pe.user_id = users.id where pe.primary = TRUE" + "SELECT users.id as \"id\", users.id as \"user_id\", pe.email as \"username\", pe.email as \"email\", users.name as \"firstName\", CASE WHEN pe.confirmed_at IS NOT NULL THEN 'TRUE' ELSE 'FALSE' END as \"EMAIL_VERIFIED\" from user_emails pe left join users on pe.user_id = users.id where pe.primary = TRUE" ], "findByEmail": [ - "SELECT users.id as \"id\", users.id as \"user_id\", pe.email as \"username\", pe.email as \"email\", users.name as \"firstName\", CASE WHEN ue.confirmed_at IS NOT NULL THEN 'TRUE' ELSE NULL END as \"EMAIL_VERIFIED\" from user_emails ue left join users on ue.user_id = users.id left join user_emails pe on ue.user_id = pe.user_id AND pe.primary = TRUE where LOWER(ue.email) = LOWER(?) AND ue.confirmed_at IS NOT NULL GROUP BY pe.id, users.id, pe.email, users.name, ue.confirmed_at" + "SELECT users.id as \"id\", users.id as \"user_id\", ue.email as \"username\", ue.email as \"email\", users.name as \"firstName\", CASE WHEN ue.confirmed_at IS NOT NULL THEN 'TRUE' ELSE 'FALSE' END as \"EMAIL_VERIFIED\" from user_emails ue left join users on ue.user_id = users.id where LOWER(ue.email) = LOWER(?) GROUP BY users.id, ue.email, users.name, ue.confirmed_at" ], "user": [ "postgres" @@ -4180,7 +4180,7 @@ "select count(*) from users" ], "cachePolicy": [ - "DEFAULT" + "NO_CACHE" ], "url": [ "jdbc:postgresql://host.docker.internal:5432/coursemology_test" diff --git a/authentication/script/cm_db_federation.sql b/authentication/script/cm_db_federation.sql index d8033865ad1..de2bc9717ee 100644 --- a/authentication/script/cm_db_federation.sql +++ b/authentication/script/cm_db_federation.sql @@ -2,19 +2,19 @@ select count(*) from users; -- List All Users SQL query -select users.id as "id", users.id as "user_id", pe.email as "username", pe.email as "email", users.name as "firstName", CASE WHEN pe.confirmed_at IS NOT NULL THEN 'TRUE' ELSE NULL END as "EMAIL_VERIFIED" from user_emails pe left join users on pe.user_id = users.id where pe.primary = TRUE +select users.id as "id", users.id as "user_id", pe.email as "username", pe.email as "email", users.name as "firstName", CASE WHEN pe.confirmed_at IS NOT NULL THEN 'TRUE' ELSE 'FALSE' END as "EMAIL_VERIFIED" from user_emails pe left join users on pe.user_id = users.id where pe.primary = TRUE -- Find user by id SQL query -select users.id as "id", users.id as "user_id", pe.email as "username", pe.email as "email", users.name as "firstName", CASE WHEN ue.confirmed_at IS NOT NULL THEN 'TRUE' ELSE NULL END as "EMAIL_VERIFIED" from user_emails ue left join users on ue.user_id = users.id left join user_emails pe ON ue.user_id = pe.user_id AND pe.primary = TRUE where cast(users.id as character varying) = ? AND ue.confirmed_at IS NOT NULL GROUP BY pe.id, users.id, pe.email, users.name, ue.confirmed_at +select users.id as "id", users.id as "user_id", pe.email as "username", pe.email as "email", users.name as "firstName" from user_emails pe left join users on pe.user_id = users.id where cast(users.id as character varying) = ? AND pe.primary = TRUE and pe.confirmed_at IS NOT NULL GROUP BY users.id, pe.email, users.name -- Find user by username SQL query -select users.id as "id", users.id as "user_id", pe.email as "username", pe.email as "email", users.name as "firstName", CASE WHEN ue.confirmed_at IS NOT NULL THEN 'TRUE' ELSE NULL END as "EMAIL_VERIFIED" from user_emails ue left join users on ue.user_id = users.id LEFT JOIN user_emails pe ON ue.user_id = pe.user_id AND pe.primary = TRUE where LOWER(ue.email) = LOWER(?) AND ue.confirmed_at IS NOT NULL GROUP BY pe.id, users.id, pe.email, users.name, ue.confirmed_at +select users.id as "id", users.id as "user_id", ue.email as "username", ue.email as "email", users.name as "firstName", CASE WHEN ue.confirmed_at IS NOT NULL THEN 'TRUE' ELSE 'FALSE' END as "EMAIL_VERIFIED" from user_emails ue left join users on ue.user_id = users.id where LOWER(ue.email) = LOWER(?) GROUP BY users.id, ue.email, users.name, ue.confirmed_at -- Find user by email SQL query -select users.id as "id", users.id as "user_id", pe.email as "username", pe.email as "email", users.name as "firstName", CASE WHEN ue.confirmed_at IS NOT NULL THEN 'TRUE' ELSE NULL END as "EMAIL_VERIFIED" from user_emails ue left join users on ue.user_id = users.id LEFT JOIN user_emails pe ON ue.user_id = pe.user_id AND pe.primary = TRUE where LOWER(ue.email) = LOWER(?) AND ue.confirmed_at IS NOT NULL GROUP BY pe.id, users.id, pe.email, users.name, ue.confirmed_at +select users.id as "id", users.id as "user_id", ue.email as "username", ue.email as "email", users.name as "firstName", CASE WHEN ue.confirmed_at IS NOT NULL THEN 'TRUE' ELSE 'FALSE' END as "EMAIL_VERIFIED" from user_emails ue left join users on ue.user_id = users.id where LOWER(ue.email) = LOWER(?) GROUP BY users.id, ue.email, users.name, ue.confirmed_at -- Find user by search term SQL query -SELECT users.id AS "id", users.id AS "user_id", pe.email AS "username", pe.email AS "email", users.name AS "firstName", CASE WHEN MAX(CASE WHEN pe.confirmed_at IS NOT NULL THEN 1 ELSE 0 END) = 1 THEN 'TRUE' ELSE NULL END AS "EMAIL_VERIFIED" FROM user_emails ue LEFT JOIN users ON ue.user_id = users.id LEFT JOIN user_emails pe ON ue.user_id = pe.user_id AND pe.primary = TRUE WHERE LOWER(pe.email) LIKE LOWER(CONCAT('%', ?, '%')) OR LOWER(users.name) LIKE LOWER(CONCAT('%', ?, '%')) OR (ue.primary = FALSE AND ue.confirmed_at IS NOT NULL AND LOWER(ue.email) LIKE LOWER(CONCAT('%', ?, '%'))) GROUP BY pe.id, users.id, pe.email, users.name +SELECT users.id AS "id", users.id AS "user_id", pe.email AS "username", pe.email AS "email", users.name AS "firstName", CASE WHEN MAX(CASE WHEN pe.confirmed_at IS NOT NULL THEN 1 ELSE 0 END) = 1 THEN 'TRUE' ELSE 'FALSE' END AS "EMAIL_VERIFIED" FROM user_emails ue LEFT JOIN users ON ue.user_id = users.id LEFT JOIN user_emails pe ON ue.user_id = pe.user_id AND pe.primary = TRUE WHERE LOWER(pe.email) LIKE LOWER(CONCAT('%', ?, '%')) OR LOWER(users.name) LIKE LOWER(CONCAT('%', ?, '%')) OR (ue.primary = FALSE AND ue.confirmed_at IS NOT NULL AND LOWER(ue.email) LIKE LOWER(CONCAT('%', ?, '%'))) GROUP BY pe.id, users.id, pe.email, users.name -- Find password hash (blowfish or hash digest hex) SQL query select encrypted_password as hash_pwd from users right join user_emails ue on users.id = ue.user_id where ue.email = ? diff --git a/config/locales/en/user/emails.yml b/config/locales/en/user/emails.yml index 5e7a2469847..d298d5648fe 100644 --- a/config/locales/en/user/emails.yml +++ b/config/locales/en/user/emails.yml @@ -3,6 +3,7 @@ en: emails: index: header: 'Emails' + cannot_delete_primary: 'You cannot delete the primary email.' set_primary: no_confirmed_emails: 'There are no confirmed emails to set as the primary email.' send_confirmation: diff --git a/config/locales/ko/user/emails.yml b/config/locales/ko/user/emails.yml index 7dab3b9c37a..53139d09eea 100644 --- a/config/locales/ko/user/emails.yml +++ b/config/locales/ko/user/emails.yml @@ -3,6 +3,7 @@ ko: emails: index: header: '이메일' + cannot_delete_primary: '기본 이메일을 삭제할 수 없습니다.' set_primary: no_confirmed_emails: '기본 이메일로 설정할 수 있는 확인된 이메일 주소가 없습니다.' send_confirmation: diff --git a/config/locales/zh/user/emails.yml b/config/locales/zh/user/emails.yml index 5f774cabe34..86b0e12708e 100644 --- a/config/locales/zh/user/emails.yml +++ b/config/locales/zh/user/emails.yml @@ -3,6 +3,7 @@ zh: emails: index: header: '邮箱' + cannot_delete_primary: '不能删除主要邮箱。' set_primary: no_confirmed_emails: '没有已验证的邮箱地址可以设置为主要邮箱。' send_confirmation: diff --git a/spec/controllers/user/emails_controller_spec.rb b/spec/controllers/user/emails_controller_spec.rb index 4ce17138014..3bae3a97b34 100644 --- a/spec/controllers/user/emails_controller_spec.rb +++ b/spec/controllers/user/emails_controller_spec.rb @@ -6,10 +6,12 @@ with_tenant(:instance) do let!(:user) { create(:administrator) } + let!(:primary_email) { user.send(:default_email_record) } + let!(:non_primary_email) { create(:user_email, user: user, primary: false) } before { controller_sign_in(controller, user) } - describe '#destroy' do - subject { delete :destroy, as: :json, params: { id: user.send(:default_email_record) } } + describe '#destroy_primary_email' do + subject { delete :destroy, as: :json, params: { id: primary_email.id } } context 'when the user only has one email address' do it 'cannot be deleted' do @@ -19,16 +21,23 @@ end context 'when destroying a primary email' do - let!(:non_primary_email) { create(:user_email, user: user, primary: false) } before { controller_sign_in(controller, user) } - it 'deletes the primary email' do - expect { subject }.to change { user.emails.count }.by(-1) + it 'cannot be deleted' do + expect { subject }.to change { user.emails.count }.by(0) end + it { is_expected.to have_http_status(:bad_request) } + end + end - it 'sets another email as primary' do - subject - expect(non_primary_email.reload).to be_primary + describe '#destroy_non_primary_email' do + subject { delete :destroy, as: :json, params: { id: non_primary_email.id } } + + context 'when destroying a non-primary email' do + before { controller_sign_in(controller, user) } + + it 'deletes that email' do + expect { subject }.to change { user.emails.count }.by(-1) end end end