diff --git a/swad_account.c b/swad_account.c index c09b54544..6afe76947 100644 --- a/swad_account.c +++ b/swad_account.c @@ -50,6 +50,7 @@ #include "swad_ID.h" #include "swad_ID_database.h" #include "swad_language.h" +#include "swad_mail_database.h" #include "swad_match.h" #include "swad_message.h" #include "swad_network.h" diff --git a/swad_changelog.h b/swad_changelog.h index fb1b2949a..3bec05865 100644 --- a/swad_changelog.h +++ b/swad_changelog.h @@ -602,13 +602,14 @@ TODO: FIX BUG, URGENT! En las fechas como par TODO: En las encuestas, que los estudiantes no puedan ver los resultados hasta que no finalice el plazo. */ -#define Log_PLATFORM_VERSION "SWAD 21.14 (2021-09-22)" +#define Log_PLATFORM_VERSION "SWAD 21.14.1 (2021-09-23)" #define CSS_FILE "swad20.45.css" #define JS_FILE "swad20.69.1.js" /* TODO: Rename CENTRE to CENTER in help wiki. TODO: Rename ASSESSMENT.Announcements to ASSESSMENT.Calls_for_exams + Version 21.14.1: Sep 23, 2021 Queries moved to module swad_mail_database. (316687 lines) Version 21.14: Sep 22, 2021 New module swad_mail_database for database queries related to mail domains. (316594 lines) Version 21.13: Sep 22, 2021 New module swad_log_database for database queries related to access logs. (316510 lines) Version 21.12: Sep 22, 2021 New module swad_link_database for database queries related to institutional links. (316361 lines) diff --git a/swad_enrolment.c b/swad_enrolment.c index 2b3261305..b5c67e867 100644 --- a/swad_enrolment.c +++ b/swad_enrolment.c @@ -49,6 +49,7 @@ #include "swad_HTML.h" #include "swad_ID.h" #include "swad_info_database.h" +#include "swad_mail_database.h" #include "swad_match.h" #include "swad_message.h" #include "swad_notification.h" @@ -1118,7 +1119,7 @@ static void Enr_ReceiveFormUsrsCrs (Rol_Role_t Role) } else if (Mai_CheckIfEmailIsValid (UsrDat.UsrIDNickOrEmail)) // 2: It's an email { - if ((UsrDat.UsrCod = Mai_GetUsrCodFromEmail (UsrDat.UsrIDNickOrEmail)) > 0) + if ((UsrDat.UsrCod = Mai_DB_GetUsrCodFromEmail (UsrDat.UsrIDNickOrEmail)) > 0) { ListUsrCods.NumUsrs = 1; Usr_AllocateListUsrCods (&ListUsrCods); @@ -1246,7 +1247,7 @@ static void Enr_ReceiveFormUsrsCrs (Rol_Role_t Role) } else if (Mai_CheckIfEmailIsValid (UsrDat.UsrIDNickOrEmail)) // 2: It's an email { - if ((UsrDat.UsrCod = Mai_GetUsrCodFromEmail (UsrDat.UsrIDNickOrEmail)) > 0) + if ((UsrDat.UsrCod = Mai_DB_GetUsrCodFromEmail (UsrDat.UsrIDNickOrEmail)) > 0) { ListUsrCods.NumUsrs = 1; Usr_AllocateListUsrCods (&ListUsrCods); diff --git a/swad_mail.c b/swad_mail.c index 2575f374a..4867e6937 100644 --- a/swad_mail.c +++ b/swad_mail.c @@ -55,8 +55,6 @@ extern struct Globals Gbl; /***************************** Private constants *****************************/ /*****************************************************************************/ -#define Mai_LENGTH_EMAIL_CONFIRM_KEY Cry_BYTES_ENCRYPTED_STR_SHA256_BASE64 - /*****************************************************************************/ /******************************* Private types *******************************/ /*****************************************************************************/ @@ -97,8 +95,6 @@ static void Mai_PutParamsRemoveMyEmail (void *Email); static void Mai_PutParamsRemoveOtherEmail (void *Email); static void Mai_RemoveEmail (struct UsrData *UsrDat); -static void Mai_DB_RemoveEmail (long UsrCod, - const char Email[Cns_MAX_BYTES_EMAIL_ADDRESS + 1]); static void Mai_NewUsrEmail (struct UsrData *UsrDat,bool ItsMe); static void Mai_InsertMailKey (const char Email[Cns_MAX_BYTES_EMAIL_ADDRESS + 1], const char MailKey[Mai_LENGTH_EMAIL_CONFIRM_KEY + 1]); @@ -968,20 +964,7 @@ bool Mai_GetEmailFromUsrCod (struct UsrData *UsrDat) bool Found; /***** Get current (last updated) user's nickname from database *****/ - if (DB_QuerySELECT (&mysql_res,"can not get email address", - "SELECT E_mail," // row[0] - "Confirmed" // row[1] - " FROM usr_emails" - " WHERE UsrCod=%ld" - " ORDER BY CreatTime DESC" - " LIMIT 1", - UsrDat->UsrCod) == 0) - { - UsrDat->Email[0] = '\0'; - UsrDat->EmailConfirmed = false; - Found = false; - } - else + if (Mai_DB_GetEmailFromUsrCod (&mysql_res,UsrDat->UsrCod)) { /* Get email */ row = mysql_fetch_row (mysql_res); @@ -989,6 +972,12 @@ bool Mai_GetEmailFromUsrCod (struct UsrData *UsrDat) UsrDat->EmailConfirmed = (row[1][0] == 'Y'); Found = true; } + else + { + UsrDat->Email[0] = '\0'; + UsrDat->EmailConfirmed = false; + Found = false; + } /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); @@ -996,31 +985,6 @@ bool Mai_GetEmailFromUsrCod (struct UsrData *UsrDat) return Found; } -/*****************************************************************************/ -/************* Get user's code of a user from his/her email ******************/ -/*****************************************************************************/ -// Returns -1L if email not found - -long Mai_GetUsrCodFromEmail (const char Email[Cns_MAX_BYTES_EMAIL_ADDRESS + 1]) - { - /***** Trivial check 1: email should be not null ******/ - if (!Email) - return -1L; - - /***** Trivial check 2: email should be not empty ******/ - if (!Email[0]) - return -1L; - - /***** Get user's code from database *****/ - return DB_QuerySELECTCode ("can not get user's code", - "SELECT usr_emails.UsrCod" - " FROM usr_emails," - "usr_data" - " WHERE usr_emails.E_mail='%s'" - " AND usr_emails.UsrCod=usr_data.UsrCod", - Email); - } - /*****************************************************************************/ /*********************** Show form to change my email ************************/ /*****************************************************************************/ @@ -1121,14 +1085,7 @@ static void Mai_ShowFormChangeUsrEmail (bool ItsMe, Ale_ShowAlert (Ale_WARNING,Txt_Please_confirm_your_email_address); /***** Get my emails *****/ - NumEmails = (unsigned) - DB_QuerySELECT (&mysql_res,"can not get old email addresses of a user", - "SELECT E_mail," // row[0] - "Confirmed" // row[1] - " FROM usr_emails" - " WHERE UsrCod=%ld" - " ORDER BY CreatTime DESC", - UsrDat->UsrCod); + NumEmails = Mai_DB_GetMyEmails (&mysql_res,UsrDat->UsrCod); /***** Begin table *****/ HTM_TABLE_BeginWidePadding (2); @@ -1364,46 +1321,6 @@ static void Mai_RemoveEmail (struct UsrData *UsrDat) Ale_ShowAlertUserNotFoundOrYouDoNotHavePermission (); } -/*****************************************************************************/ -/*************** Remove an old email address from database *******************/ -/*****************************************************************************/ - -static void Mai_DB_RemoveEmail (long UsrCod, - const char Email[Cns_MAX_BYTES_EMAIL_ADDRESS + 1]) - { - /***** Remove an old email address *****/ - DB_QueryREPLACE ("can not remove an old email address", - "DELETE FROM usr_emails" - " WHERE UsrCod=%ld" - " AND E_mail='%s'", - UsrCod, - Email); - } - -/*****************************************************************************/ -/**************************** Remove user's emails ***************************/ -/*****************************************************************************/ - -void Mai_DB_RemoveUsrEmails (long UsrCod) - { - DB_QueryDELETE ("can not remove user's emails", - "DELETE FROM usr_emails" - " WHERE UsrCod=%ld", - UsrCod); - } - -/*****************************************************************************/ -/************** Remove a given user from list of pending emails **************/ -/*****************************************************************************/ - -void Mai_DB_RemoveUsrPendingEmails (long UsrCod) - { - DB_QueryDELETE ("can not remove pending user's emails", - "DELETE FROM usr_pending_emails" - " WHERE UsrCod=%ld", - UsrCod); - } - /*****************************************************************************/ /************************* New user's email for me ***************************/ /*****************************************************************************/ @@ -1511,40 +1428,15 @@ static void Mai_NewUsrEmail (struct UsrData *UsrDat,bool ItsMe) bool Mai_UpdateEmailInDB (const struct UsrData *UsrDat,const char NewEmail[Cns_MAX_BYTES_EMAIL_ADDRESS + 1]) { /***** Check if the new email matches any of the confirmed emails of other users *****/ - if (DB_QueryCOUNT ("can not check if email already existed", - "SELECT COUNT(*)" - " FROM usr_emails" - " WHERE E_mail='%s'" - " AND Confirmed='Y'" - " AND UsrCod<>%ld", - NewEmail, - UsrDat->UsrCod)) // An email of another user is the same that my email + if (Mai_DB_CheckIfEmailBelongToAnotherUsr (UsrDat->UsrCod,NewEmail)) // An email of another user is the same that my email return false; // Don't update /***** Delete email (not confirmed) for other users *****/ - DB_QueryDELETE ("can not remove pending email for other users", - "DELETE FROM usr_pending_emails" - " WHERE E_mail='%s'" - " AND UsrCod<>%ld", - NewEmail, - UsrDat->UsrCod); - - DB_QueryDELETE ("can not remove not confirmed email for other users", - "DELETE FROM usr_emails" - " WHERE E_mail='%s'" - " AND Confirmed='N'" - " AND UsrCod<>%ld", - NewEmail, - UsrDat->UsrCod); + Mai_DB_RemovePendingEmailForOtherUsrs (UsrDat->UsrCod,NewEmail); + Mai_DB_RemoveNotConfirmedEmailForOtherUsrs (UsrDat->UsrCod,NewEmail); /***** Update email in database *****/ - DB_QueryREPLACE ("can not update email", - "REPLACE INTO usr_emails" - " (UsrCod,E_mail,CreatTime)" - " VALUES" - " (%ld,'%s',NOW())", - UsrDat->UsrCod, - NewEmail); + Mai_DB_UpdateEmail (UsrDat->UsrCod,NewEmail); return true; // Successfully updated } @@ -1640,20 +1532,10 @@ static void Mai_InsertMailKey (const char Email[Cns_MAX_BYTES_EMAIL_ADDRESS + 1] const char MailKey[Mai_LENGTH_EMAIL_CONFIRM_KEY + 1]) { /***** Remove expired pending emails from database *****/ - DB_QueryDELETE ("can not remove old pending mail keys", - "DELETE LOW_PRIORITY FROM usr_pending_emails" - " WHERE DateAndTime // For NULL -// #include // For calloc -// #include // For string functions -// #include // For the macro WEXITSTATUS -// #include // For access, lstat, getpid, chdir, symlink, unlink - -// #include "swad_account.h" -// #include "swad_box.h" #include "swad_database.h" -// #include "swad_error.h" -// #include "swad_form.h" #include "swad_global.h" -// #include "swad_HTML.h" -// #include "swad_language.h" #include "swad_mail.h" #include "swad_mail_database.h" -// #include "swad_parameter.h" -// #include "swad_QR.h" -// #include "swad_tab.h" /*****************************************************************************/ /************** External global variables from others modules ****************/ @@ -67,6 +52,253 @@ extern struct Globals Gbl; /***************************** Private prototypes ****************************/ /*****************************************************************************/ +/*****************************************************************************/ +/*************************** Update a user's email ***************************/ +/*****************************************************************************/ + +void Mai_DB_UpdateEmail (long UsrCod,const char NewEmail[Cns_MAX_BYTES_EMAIL_ADDRESS + 1]) + { + DB_QueryREPLACE ("can not update email", + "REPLACE INTO usr_emails" + " (UsrCod,E_mail,CreatTime)" + " VALUES" + " (%ld,'%s',NOW())", + UsrCod, + NewEmail); + } + +/*****************************************************************************/ +/*************************** Confirm a user's email **************************/ +/*****************************************************************************/ + +void Mai_DB_ConfirmEmail (long UsrCod,const char Email[Cns_MAX_BYTES_EMAIL_ADDRESS + 1]) + { + DB_QueryUPDATE ("can not confirm email", + "UPDATE usr_emails" + " SET Confirmed='Y'" + " WHERE usr_emails.UsrCod=%ld" + " AND usr_emails.E_mail='%s'", + UsrCod, + Email); + } + +/*****************************************************************************/ +/********************************* Get my emails *****************************/ +/*****************************************************************************/ + +unsigned Mai_DB_GetMyEmails (MYSQL_RES **mysql_res,long UsrCod) + { + return (unsigned) + DB_QuerySELECT (mysql_res,"can not get old email addresses of a user", + "SELECT E_mail," // row[0] + "Confirmed" // row[1] + " FROM usr_emails" + " WHERE UsrCod=%ld" + " ORDER BY CreatTime DESC", + UsrCod); + } + +/*****************************************************************************/ +/********** Get email address of a user from his/her user's code *************/ +/*****************************************************************************/ + +unsigned Mai_DB_GetEmailFromUsrCod (MYSQL_RES **mysql_res,long UsrCod) + { + return (unsigned) + DB_QuerySELECT (mysql_res,"can not get email address", + "SELECT E_mail," // row[0] + "Confirmed" // row[1] + " FROM usr_emails" + " WHERE UsrCod=%ld" + " ORDER BY CreatTime DESC" + " LIMIT 1", + UsrCod); + } + +/*****************************************************************************/ +/************* Get user's code of a user from his/her email ******************/ +/*****************************************************************************/ +// Returns -1L if email not found + +long Mai_DB_GetUsrCodFromEmail (const char Email[Cns_MAX_BYTES_EMAIL_ADDRESS + 1]) + { + /***** Trivial check 1: email should be not null ******/ + if (!Email) + return -1L; + + /***** Trivial check 2: email should be not empty ******/ + if (!Email[0]) + return -1L; + + /***** Get user's code from database *****/ + return DB_QuerySELECTCode ("can not get user's code", + "SELECT usr_emails.UsrCod" + " FROM usr_emails," + "usr_data" + " WHERE usr_emails.E_mail='%s'" + " AND usr_emails.UsrCod=usr_data.UsrCod", + Email); + } + +/*****************************************************************************/ +/******************** Check if a user's email is confirmed *******************/ +/*****************************************************************************/ + +char Mai_DB_CheckIfEmailIsConfirmed (long UsrCod,const char Email[Cns_MAX_BYTES_EMAIL_ADDRESS + 1]) + { + char StrConfirmed[1 + 1]; + + DB_QuerySELECTString (StrConfirmed,1,"can not check if email is confirmed", + "SELECT Confirmed" + " FROM usr_emails" + " WHERE UsrCod=%ld" + " AND E_mail='%s'", + UsrCod, + Email); + + return StrConfirmed[0]; + } + +/*****************************************************************************/ +/**** Check if an email matches any of the confirmed emails of other users ***/ +/*****************************************************************************/ + +bool Mai_DB_CheckIfEmailBelongToAnotherUsr (long UsrCod,const char Email[Cns_MAX_BYTES_EMAIL_ADDRESS + 1]) + { + return (DB_QueryCOUNT ("can not check if email already existed", + "SELECT COUNT(*)" + " FROM usr_emails" + " WHERE E_mail='%s'" + " AND Confirmed='Y'" + " AND UsrCod<>%ld", + Email, + UsrCod) != 0); + } + +/*****************************************************************************/ +/**************** Remove not confirmed email for other users *****************/ +/*****************************************************************************/ + +void Mai_DB_RemoveNotConfirmedEmailForOtherUsrs (long UsrCod,const char Email[Cns_MAX_BYTES_EMAIL_ADDRESS + 1]) + { + DB_QueryDELETE ("can not remove not confirmed email for other users", + "DELETE FROM usr_emails" + " WHERE E_mail='%s'" + " AND Confirmed='N'" + " AND UsrCod<>%ld", + Email, + UsrCod); + } + +/*****************************************************************************/ +/*************** Remove an old email address from database *******************/ +/*****************************************************************************/ + +void Mai_DB_RemoveEmail (long UsrCod,const char Email[Cns_MAX_BYTES_EMAIL_ADDRESS + 1]) + { + DB_QueryREPLACE ("can not remove an old email address", + "DELETE FROM usr_emails" + " WHERE UsrCod=%ld" + " AND E_mail='%s'", + UsrCod, + Email); + } + +/*****************************************************************************/ +/**************************** Remove user's emails ***************************/ +/*****************************************************************************/ + +void Mai_DB_RemoveUsrEmails (long UsrCod) + { + DB_QueryDELETE ("can not remove user's emails", + "DELETE FROM usr_emails" + " WHERE UsrCod=%ld", + UsrCod); + } + +/*****************************************************************************/ +/************************* Insert mail key in database ***********************/ +/*****************************************************************************/ + +void Mai_DB_InsertPendingEmail (const char Email[Cns_MAX_BYTES_EMAIL_ADDRESS + 1], + const char MailKey[Mai_LENGTH_EMAIL_CONFIRM_KEY + 1]) + { + DB_QueryREPLACE ("can not create pending password", + "INSERT INTO usr_pending_emails" + " (UsrCod,E_mail,MailKey,DateAndTime)" + " VALUES" + " (%ld,'%s','%s',NOW())", + Gbl.Usrs.Me.UsrDat.UsrCod, + Email, + MailKey); + } + +/*****************************************************************************/ +/******************** Get user's code and email from key *********************/ +/*****************************************************************************/ + +unsigned Mai_DB_GetPendingEmail (MYSQL_RES **mysql_res, + const char MailKey[Mai_LENGTH_EMAIL_CONFIRM_KEY + 1]) + { + return (unsigned) + DB_QuerySELECT (mysql_res,"can not get user's code and email from key", + "SELECT UsrCod," // row[0] + "E_mail" // row[1] + " FROM usr_pending_emails" + " WHERE MailKey='%s'", + MailKey); + } + +/*****************************************************************************/ +/*************************** Remove pending email ****************************/ +/*****************************************************************************/ + +void Mai_DB_RemovePendingEmailForOtherUsrs (long UsrCod,const char Email[Cns_MAX_BYTES_EMAIL_ADDRESS + 1]) + { + DB_QueryDELETE ("can not remove pending email for other users", + "DELETE FROM usr_pending_emails" + " WHERE E_mail='%s'" + " AND UsrCod<>%ld", + Email, + UsrCod); + } + +/*****************************************************************************/ +/*************************** Remove pending email ****************************/ +/*****************************************************************************/ + +void Mai_DB_RemovePendingEmail (const char MailKey[Mai_LENGTH_EMAIL_CONFIRM_KEY + 1]) + { + DB_QueryDELETE ("can not remove an email key", + "DELETE FROM usr_pending_emails" + " WHERE MailKey='%s'", + MailKey); + } + +/*****************************************************************************/ +/************** Remove a given user from list of pending emails **************/ +/*****************************************************************************/ + +void Mai_DB_RemoveUsrPendingEmails (long UsrCod) + { + DB_QueryDELETE ("can not remove pending user's emails", + "DELETE FROM usr_pending_emails" + " WHERE UsrCod=%ld", + UsrCod); + } + +/*****************************************************************************/ +/**************** Remove expired pending emails from database ****************/ +/*****************************************************************************/ + +void Mai_DB_RemoveExpiredPendingEmails (void) + { + DB_QueryDELETE ("can not remove old pending mail keys", + "DELETE LOW_PRIORITY FROM usr_pending_emails" + " WHERE DateAndTime 0) + if ((Gbl.Usrs.Me.UsrDat.UsrCod = Mai_DB_GetUsrCodFromEmail (Gbl.Usrs.Me.UsrIdLogin)) > 0) { /* Get user's data */ ListUsrCods.NumUsrs = 1; diff --git a/swad_user.c b/swad_user.c index b565e0bf7..2dcd747ad 100644 --- a/swad_user.c +++ b/swad_user.c @@ -61,6 +61,7 @@ #include "swad_HTML.h" #include "swad_ID.h" #include "swad_language.h" +#include "swad_mail_database.h" #include "swad_MFU.h" #include "swad_nickname.h" #include "swad_notification.h" @@ -2925,7 +2926,7 @@ unsigned Usr_GetParamOtherUsrIDNickOrEMailAndGetUsrCods (struct ListUsrCods *Lis } else if (Mai_CheckIfEmailIsValid (Gbl.Usrs.Other.UsrDat.UsrIDNickOrEmail)) // 2: It's an email { - if ((Gbl.Usrs.Other.UsrDat.UsrCod = Mai_GetUsrCodFromEmail (Gbl.Usrs.Other.UsrDat.UsrIDNickOrEmail)) > 0) + if ((Gbl.Usrs.Other.UsrDat.UsrCod = Mai_DB_GetUsrCodFromEmail (Gbl.Usrs.Other.UsrDat.UsrIDNickOrEmail)) > 0) { ListUsrCods->NumUsrs = 1; // One user found Usr_AllocateListUsrCods (ListUsrCods); @@ -3230,7 +3231,7 @@ static bool Usr_ChkUsrAndGetUsrDataFromDirectLogin (void) else if (Mai_CheckIfEmailIsValid (Gbl.Usrs.Me.UsrIdLogin)) // 2: It's an email { // User is trying to log using his/her email - if ((Gbl.Usrs.Me.UsrDat.UsrCod = Mai_GetUsrCodFromEmail (Gbl.Usrs.Me.UsrIdLogin)) <= 0) + if ((Gbl.Usrs.Me.UsrDat.UsrCod = Mai_DB_GetUsrCodFromEmail (Gbl.Usrs.Me.UsrIdLogin)) <= 0) { Usr_ShowAlertUsrDoesNotExistsOrWrongPassword (); return false; @@ -6041,7 +6042,7 @@ bool Usr_GetListMsgRecipientsWrittenExplicitelyBySender (bool WriteErrorMsgs) } else if (Mai_CheckIfEmailIsValid (UsrIDNickOrEmail)) // 2: It's an email { - if ((UsrDat.UsrCod = Mai_GetUsrCodFromEmail (UsrIDNickOrEmail)) > 0) + if ((UsrDat.UsrCod = Mai_DB_GetUsrCodFromEmail (UsrIDNickOrEmail)) > 0) { ListUsrCods.NumUsrs = 1; Usr_AllocateListUsrCods (&ListUsrCods);