diff --git a/swad_API.c b/swad_API.c index b003f669..53fa20a2 100644 --- a/swad_API.c +++ b/swad_API.c @@ -1859,7 +1859,7 @@ int swad__findUsers (struct soap *soap, { /***** Create temporary table with candidate users *****/ // Search is faster (aproximately x2) using temporary tables - Usr_CreateTmpTableAndSearchCandidateUsrs (SearchQuery); + Usr_DB_CreateTmpTableAndSearchCandidateUsrs (SearchQuery); /***** Search for users *****/ Usr_SearchListUsrs (Role); @@ -1868,7 +1868,7 @@ int swad__findUsers (struct soap *soap, Usr_FreeUsrsList (Role); /***** Drop temporary table with candidate users *****/ - Usr_DropTmpTableWithCandidateUsrs (); + Usr_DB_DropTmpTableWithCandidateUsrs (); } else FilterTooShort = true; diff --git a/swad_admin.c b/swad_admin.c index f77071f5..dfdee8f2 100644 --- a/swad_admin.c +++ b/swad_admin.c @@ -207,6 +207,24 @@ void Adm_AddAdmToDeg (void) Enr_AddAdm (HieLvl_DEG,Gbl.Hierarchy.Deg.DegCod,Gbl.Hierarchy.Deg.FullName); } +/*****************************************************************************/ +/******************** Get list with data of administrators *******************/ +/*****************************************************************************/ + +void Adm_GetAdmsLst (HieLvl_Level_t Scope) + { + char *Query = NULL; + + /***** Build query *****/ + Usr_DB_BuildQueryToGetAdmsLst (Scope,&Query); + + /***** Get list of administrators from database *****/ + Usr_GetListUsrsFromQuery (Query,Rol_DEG_ADM,Scope); + + /***** Free query string *****/ + free (Query); + } + /*****************************************************************************/ /******************* Add an administrator to current degree ******************/ /*****************************************************************************/ diff --git a/swad_admin.h b/swad_admin.h index 4e4a787d..6fbc1451 100644 --- a/swad_admin.h +++ b/swad_admin.h @@ -51,6 +51,8 @@ void Adm_AddAdmToIns (void); void Adm_AddAdmToCtr (void); void Adm_AddAdmToDeg (void); +void Adm_GetAdmsLst (HieLvl_Level_t Scope); + void Adm_ReqRemAdmOfIns (void); void Adm_ReqRemAdmOfCtr (void); void Adm_ReqRemAdmOfDeg (void); diff --git a/swad_admin_database.c b/swad_admin_database.c index 5e3b2ff2..32f62838 100644 --- a/swad_admin_database.c +++ b/swad_admin_database.c @@ -28,6 +28,7 @@ #include "swad_admin.h" #include "swad_admin_database.h" #include "swad_database.h" +#include "swad_error.h" #include "swad_global.h" /*****************************************************************************/ @@ -113,6 +114,23 @@ bool Adm_DB_CheckIfUsrIsAdm (long UsrCod,HieLvl_Level_t Scope,long Cod) Cod); } +/*****************************************************************************/ +/************** Check if a user is a superuser (global admin) ****************/ +/*****************************************************************************/ + +bool Adm_DB_CheckIfUsrIsSuperuser (long UsrCod) + { + return + DB_QueryEXISTS ("can not check if a user is superuser", + "SELECT EXISTS" + "(SELECT *" + " FROM usr_admins" + " WHERE UsrCod=%ld" + " AND Scope='%s')", + UsrCod, + Sco_GetDBStrFromScope (HieLvl_SYS)); + } + /*****************************************************************************/ /***** Remove user as administrator of an institution, center or degree ******/ /*****************************************************************************/ diff --git a/swad_admin_database.h b/swad_admin_database.h index c2944dba..c018303a 100644 --- a/swad_admin_database.h +++ b/swad_admin_database.h @@ -45,6 +45,7 @@ void Adm_DB_InsertAdmin (long UsrCod,HieLvl_Level_t Scope,long Cod); unsigned Adm_DB_GetAdmsCurrentScopeExceptMe (MYSQL_RES **mysql_res); bool Adm_DB_CheckIfUsrIsAdm (long UsrCod,HieLvl_Level_t Scope,long Cod); +bool Adm_DB_CheckIfUsrIsSuperuser (long UsrCod); void Adm_DB_RemAdmin (long UsrCod,HieLvl_Level_t Scope,long Cod); void Adm_DB_RemUsrAsAdmin (long UsrCod); diff --git a/swad_changelog.h b/swad_changelog.h index 9d1045d0..97a60856 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.52.3 (2021-11-06)" +#define Log_PLATFORM_VERSION "SWAD 21.53 (2021-11-06)" #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.53: Nov 06, 2021 Queries moved to module swad_user_database and other modules. (321926 lines) Version 21.52.3: Nov 06, 2021 Queries moved to module swad_user_database. (321894 lines) Version 21.52.2: Nov 06, 2021 Query refactoring related to SELECT DISTINCT and UNION. (321899 lines) Version 21.52.1: Nov 06, 2021 Fixed database query in departments. (321828 lines) diff --git a/swad_search.c b/swad_search.c index 382e56fa..f36da8f3 100644 --- a/swad_search.c +++ b/swad_search.c @@ -146,64 +146,68 @@ static void Sch_PutFormToSearchWithWhatToSearchAndScope (Act_Action_t Action,Hie Sch_WhatToSearch_t WhatToSearch; unsigned WTS; - /***** Begin box *****/ + /***** Begin container *****/ HTM_DIV_Begin ("class=\"CM\""); - Box_BoxBegin (NULL,Txt_Search, - Crs_PutIconToSelectMyCourses,NULL, - Hlp_START_Search,Box_NOT_CLOSABLE); - /***** Begin form *****/ - Frm_BeginForm (Action); + /***** Begin box *****/ + Box_BoxBegin (NULL,Txt_Search, + Crs_PutIconToSelectMyCourses,NULL, + Hlp_START_Search,Box_NOT_CLOSABLE); - /***** Scope (whole platform, current country, current institution, - current center, current degree or current course) *****/ - HTM_DIV_Begin ("class=\"CM\""); - HTM_LABEL_Begin ("class=\"%s\"",The_ClassFormInBox[Gbl.Prefs.Theme]); - HTM_TxtColonNBSP (Txt_Scope); - Gbl.Scope.Allowed = 1 << HieLvl_SYS | - 1 << HieLvl_CTY | - 1 << HieLvl_INS | - 1 << HieLvl_CTR | - 1 << HieLvl_DEG | - 1 << HieLvl_CRS; - Gbl.Scope.Default = DefaultScope; - Sco_GetScope ("ScopeSch"); - Sco_PutSelectorScope ("ScopeSch",HTM_DONT_SUBMIT_ON_CHANGE); - HTM_LABEL_End (); - HTM_DIV_End (); + /***** Begin form *****/ + Frm_BeginForm (Action); - /***** String to find *****/ - Sch_PutInputStringToSearch (""); + /***** Scope (whole platform, current country, current institution, + current center, current degree or current course) *****/ + HTM_DIV_Begin ("class=\"CM\""); + HTM_LABEL_Begin ("class=\"%s\"",The_ClassFormInBox[Gbl.Prefs.Theme]); + HTM_TxtColonNBSP (Txt_Scope); + Gbl.Scope.Allowed = 1 << HieLvl_SYS | + 1 << HieLvl_CTY | + 1 << HieLvl_INS | + 1 << HieLvl_CTR | + 1 << HieLvl_DEG | + 1 << HieLvl_CRS; + Gbl.Scope.Default = DefaultScope; + Sco_GetScope ("ScopeSch"); + Sco_PutSelectorScope ("ScopeSch",HTM_DONT_SUBMIT_ON_CHANGE); + HTM_LABEL_End (); + HTM_DIV_End (); - /***** What to search? *****/ - HTM_LABEL_Begin ("class=\"%s\"",The_ClassFormInBox[Gbl.Prefs.Theme]); - HTM_TxtF (" %s ",Txt_SEARCH_X_in_Y); - HTM_SELECT_Begin (HTM_DONT_SUBMIT_ON_CHANGE, - "name=\"WhatToSearch\" class=\"WHAT_TO_SEARCH\""); - for (WhatToSearch = (Sch_WhatToSearch_t) 0; - WhatToSearch <= (Sch_WhatToSearch_t) (Sch_NUM_WHAT_TO_SEARCH - 1); - WhatToSearch++) - if (Sch_CheckIfIHavePermissionToSearch (WhatToSearch)) - { - WTS = (unsigned) WhatToSearch; - HTM_OPTION (HTM_Type_UNSIGNED,&WTS, - Gbl.Search.WhatToSearch == WhatToSearch,false, - "%s",Titles[WhatToSearch]); - } - HTM_SELECT_End (); - HTM_LABEL_End (); + /***** String to find *****/ + Sch_PutInputStringToSearch (""); - /***** Magnifying glass icon *****/ - Sch_PutMagnifyingGlassButton ("search.svg"); + /***** What to search? *****/ + HTM_LABEL_Begin ("class=\"%s\"",The_ClassFormInBox[Gbl.Prefs.Theme]); + HTM_TxtF (" %s ",Txt_SEARCH_X_in_Y); + HTM_SELECT_Begin (HTM_DONT_SUBMIT_ON_CHANGE, + "name=\"WhatToSearch\" class=\"WHAT_TO_SEARCH\""); + for (WhatToSearch = (Sch_WhatToSearch_t) 0; + WhatToSearch <= (Sch_WhatToSearch_t) (Sch_NUM_WHAT_TO_SEARCH - 1); + WhatToSearch++) + if (Sch_CheckIfIHavePermissionToSearch (WhatToSearch)) + { + WTS = (unsigned) WhatToSearch; + HTM_OPTION (HTM_Type_UNSIGNED,&WTS, + Gbl.Search.WhatToSearch == WhatToSearch,false, + "%s",Titles[WhatToSearch]); + } + HTM_SELECT_End (); + HTM_LABEL_End (); - /***** Send button *****/ - Btn_PutButton (Btn_CONFIRM_BUTTON,Txt_Search); + /***** Magnifying glass icon *****/ + Sch_PutMagnifyingGlassButton ("search.svg"); - /***** End form *****/ - Frm_EndForm (); + /***** Send button *****/ + Btn_PutButton (Btn_CONFIRM_BUTTON,Txt_Search); - /***** End box *****/ - Box_BoxEnd (); + /***** End form *****/ + Frm_EndForm (); + + /***** End box *****/ + Box_BoxEnd (); + + /***** End container *****/ HTM_DIV_End (); } diff --git a/swad_user.c b/swad_user.c index 8011cd21..9d991206 100644 --- a/swad_user.c +++ b/swad_user.c @@ -37,6 +37,8 @@ #include // For access, lstat, getpid, chdir, symlink, unlink #include "swad_account.h" +#include "swad_admin.h" +#include "swad_admin_database.h" #include "swad_agenda.h" #include "swad_announcement.h" #include "swad_box.h" @@ -139,8 +141,6 @@ static const char *Usr_ParamUsrCod[Rol_NUM_ROLES] = #define Usr_NUM_ALL_FIELDS_DATA_TCH 11 const char *Usr_UsrDatMainFieldNames[Usr_NUM_MAIN_FIELDS_DATA_USR]; -#define Usr_MAX_BYTES_QUERY_GET_LIST_USRS (16 * 1024 - 1) - /*****************************************************************************/ /****************************** Private types ********************************/ /*****************************************************************************/ @@ -176,8 +176,6 @@ static void Usr_SetMyPrefsAndRoles (void); static void Usr_PutLinkToLogOut (__attribute__((unused)) void *Args); -static void Usr_DB_InsertMyLastData (void); - static void Usr_WriteRowGstAllData (struct UsrData *UsrDat); static void Usr_WriteRowStdAllData (struct UsrData *UsrDat,char *GroupNames); static void Usr_WriteRowTchAllData (struct UsrData *UsrDat); @@ -189,11 +187,7 @@ static void Usr_WriteUsrData (const char *BgColor, const char *Data,const char *Link, bool NonBreak,bool Accepted); -static void Usr_BuildQueryToGetUsrsLstCrs (char **Query,Rol_Role_t Role); - -static void Usr_GetAdmsLst (HieLvl_Level_t Scope); static void Usr_GetGstsLst (HieLvl_Level_t Scope); -static void Usr_GetListUsrsFromQuery (char *Query,Rol_Role_t Role,HieLvl_Level_t Scope); static void Usr_AllocateUsrsList (Rol_Role_t Role); static void Usr_PutButtonToConfirmIWantToSeeBigList (unsigned NumUsrs, @@ -462,235 +456,152 @@ void Usr_GetUsrDataFromUsrCod (struct UsrData *UsrDat, extern const char *Lan_STR_LANG_ID[1 + Lan_NUM_LANGUAGES]; MYSQL_RES *mysql_res; MYSQL_ROW row; - unsigned NumRows; The_Theme_t Theme; Ico_IconSet_t IconSet; Lan_Language_t Lan; /***** Get user's data from database *****/ - switch (GetPrefs) + if (Usr_DB_GetUsrDataFromUsrCod (&mysql_res,UsrDat->UsrCod,GetPrefs)) { - case Usr_DONT_GET_PREFS: - NumRows = (unsigned) - DB_QuerySELECT (&mysql_res,"can not get user's data", - "SELECT EncryptedUsrCod," // row[ 0] - "Password," // row[ 1] - "Surname1," // row[ 2] - "Surname2," // row[ 3] - "FirstName," // row[ 4] - "Sex," // row[ 5] - "Photo," // row[ 6] - "PhotoVisibility," // row[ 7] - "BaPrfVisibility," // row[ 8] - "ExPrfVisibility," // row[ 9] - "CtyCod," // row[10] - "InsCtyCod," // row[11] - "InsCod," // row[12] - "DptCod," // row[13] - "CtrCod," // row[14] - "Office," // row[15] - "OfficePhone," // row[16] - "LocalPhone," // row[17] - "FamilyPhone," // row[18] - "DATE_FORMAT(Birthday," - "'%%Y%%m%%d')," // row[19] - "Comments," // row[20] - "NotifNtfEvents," // row[21] - "EmailNtfEvents" // row[22] - " FROM usr_data" - " WHERE UsrCod=%ld", - UsrDat->UsrCod); - break; - case Usr_GET_PREFS: - default: - NumRows = (unsigned) - DB_QuerySELECT (&mysql_res,"can not get user's data", - "SELECT EncryptedUsrCod," // row[ 0] - "Password," // row[ 1] - "Surname1," // row[ 2] - "Surname2," // row[ 3] - "FirstName," // row[ 4] - "Sex," // row[ 5] - "Photo," // row[ 6] - "PhotoVisibility," // row[ 7] - "BaPrfVisibility," // row[ 8] - "ExPrfVisibility," // row[ 9] - "CtyCod," // row[10] - "InsCtyCod," // row[11] - "InsCod," // row[12] - "DptCod," // row[13] - "CtrCod," // row[14] - "Office," // row[15] - "OfficePhone," // row[16] - "LocalPhone," // row[17] - "FamilyPhone," // row[18] - "DATE_FORMAT(Birthday," - "'%%Y%%m%%d')," // row[19] - "Comments," // row[20] - "NotifNtfEvents," // row[21] - "EmailNtfEvents," // row[22] + /***** Read user's data *****/ + row = mysql_fetch_row (mysql_res); - // Settings (usually not necessary - // when getting another user's data) - "Language," // row[23] - "FirstDayOfWeek," // row[24] - "DateFormat," // row[25] - "Theme," // row[26] - "IconSet," // row[27] - "Menu," // row[28] - "SideCols," // row[29] - "ThirdPartyCookies" // row[30] - " FROM usr_data" - " WHERE UsrCod=%ld", - UsrDat->UsrCod); - break; - } + /* Get encrypted user's code (row[0]) + and encrypted password (row[1]) */ + Str_Copy (UsrDat->EnUsrCod,row[0],sizeof (UsrDat->EnUsrCod) - 1); + Str_Copy (UsrDat->Password,row[1],sizeof (UsrDat->Password) - 1); - if (NumRows != 1) - Err_WrongUserExit (); - - /***** Read user's data *****/ - row = mysql_fetch_row (mysql_res); - - /* Get encrypted user's code (row[0]) */ - Str_Copy (UsrDat->EnUsrCod,row[0],sizeof (UsrDat->EnUsrCod) - 1); - - /* Get encrypted password (row[1]) */ - Str_Copy (UsrDat->Password,row[1],sizeof (UsrDat->Password) - 1); - - /* Get roles */ - switch (GetRoleInCurrentCrs) - { - case Usr_DONT_GET_ROLE_IN_CURRENT_CRS: - UsrDat->Roles.InCurrentCrs = Rol_UNK; - UsrDat->Roles.InCrss = -1; // Force roles to be got from database - break; - case Usr_GET_ROLE_IN_CURRENT_CRS: - UsrDat->Roles.InCurrentCrs = Rol_GetRoleUsrInCrs (UsrDat->UsrCod, - Gbl.Hierarchy.Crs.CrsCod); - UsrDat->Roles.InCrss = -1; // Force roles to be got from database - break; - } - - /* Get name (row[2], row[3], row[4]) */ - Str_Copy (UsrDat->Surname1,row[2],sizeof (UsrDat->Surname1) - 1); - Str_Copy (UsrDat->Surname2,row[3],sizeof (UsrDat->Surname2) - 1); - Str_Copy (UsrDat->FrstName,row[4],sizeof (UsrDat->FrstName) - 1); - Str_ConvertToTitleType (UsrDat->Surname1 ); - Str_ConvertToTitleType (UsrDat->Surname2 ); - Str_ConvertToTitleType (UsrDat->FrstName); - Usr_BuildFullName (UsrDat); // Create full name using FirstName, Surname1 and Surname2 - - /* Get sex (row[5]) */ - UsrDat->Sex = Usr_GetSexFromStr (row[5]); - - /* Get photo (row[6]) */ - Str_Copy (UsrDat->Photo,row[6],sizeof (UsrDat->Photo) - 1); - - /* Get photo visibility (row[7]) */ - UsrDat->PhotoVisibility = Pri_GetVisibilityFromStr (row[7]); - - /* Get profile visibility (row[8], row[9]) */ - UsrDat->BaPrfVisibility = Pri_GetVisibilityFromStr (row[8]); - UsrDat->ExPrfVisibility = Pri_GetVisibilityFromStr (row[9]); - - /* Get country (row[10]) */ - UsrDat->CtyCod = Str_ConvertStrCodToLongCod (row[10]); - - /* Get institution country (row[11]) and institution (row[12]) */ - UsrDat->InsCtyCod = Str_ConvertStrCodToLongCod (row[11]); - UsrDat->InsCod = Str_ConvertStrCodToLongCod (row[12]); - - /* Get department (row[13]) */ - UsrDat->Tch.DptCod = Str_ConvertStrCodToLongCod (row[13]); - - /* Get center (row[14]) */ - UsrDat->Tch.CtrCod = Str_ConvertStrCodToLongCod (row[14]); - - /* Get office (row[15]) and office phone (row[16]) */ - Str_Copy (UsrDat->Tch.Office ,row[15],sizeof (UsrDat->Tch.Office ) - 1); - Str_Copy (UsrDat->Tch.OfficePhone,row[16],sizeof (UsrDat->Tch.OfficePhone) - 1); - - /* Get phones (row[17]) and row[18] */ - Str_Copy (UsrDat->Phone[0],row[17],sizeof (UsrDat->Phone[0]) - 1); - Str_Copy (UsrDat->Phone[1],row[18],sizeof (UsrDat->Phone[1]) - 1); - - /* Get birthday (row[19]) */ - Dat_GetDateFromYYYYMMDD (&(UsrDat->Birthday),row[19]); - Dat_ConvDateToDateStr (&(UsrDat->Birthday),UsrDat->StrBirthday); - - /* Get comments (row[20]) */ - Usr_GetUsrCommentsFromString (row[20] ? row[20] : - "", - UsrDat); - - /* Get on which events the user wants to be notified inside the platform (row[21]) */ - if (sscanf (row[21],"%u",&UsrDat->NtfEvents.CreateNotif) != 1) - UsrDat->NtfEvents.CreateNotif = (unsigned) -1; // 0xFF..FF - - /* Get on which events the user wants to be notified by email (row[22]) */ - if (sscanf (row[22],"%u",&UsrDat->NtfEvents.SendEmail) != 1) - UsrDat->NtfEvents.SendEmail = 0; - if (UsrDat->NtfEvents.SendEmail >= (1 << Ntf_NUM_NOTIFY_EVENTS)) // Maximum binary value for NotifyEvents is 000...0011...11 - UsrDat->NtfEvents.SendEmail = 0; - - /***** Get user's settings *****/ - if (GetPrefs == Usr_GET_PREFS) - { - /* Get language (row[23]) */ - UsrDat->Prefs.Language = Lan_LANGUAGE_UNKNOWN; // Language unknown - for (Lan = (Lan_Language_t) 1; - Lan <= (Lan_Language_t) Lan_NUM_LANGUAGES; - Lan++) - if (!strcasecmp (row[23],Lan_STR_LANG_ID[Lan])) - { - UsrDat->Prefs.Language = Lan; - break; - } - - /* Get first day of week (row[24]) */ - UsrDat->Prefs.FirstDayOfWeek = Cal_GetFirstDayOfWeekFromStr (row[24]); - - /* Get date format (row[25]) */ - UsrDat->Prefs.DateFormat = Dat_GetDateFormatFromStr (row[25]); - - /* Get theme (row[26]) */ - UsrDat->Prefs.Theme = The_THEME_DEFAULT; - for (Theme = (The_Theme_t) 0; - Theme <= (The_Theme_t) (The_NUM_THEMES - 1); - Theme++) - if (!strcasecmp (row[26],The_ThemeId[Theme])) - { - UsrDat->Prefs.Theme = Theme; - break; - } - - /* Get icon set (row[27]) */ - UsrDat->Prefs.IconSet = Ico_ICON_SET_DEFAULT; - for (IconSet = (Ico_IconSet_t) 0; - IconSet <= (Ico_IconSet_t) (Ico_NUM_ICON_SETS - 1); - IconSet++) - if (!strcasecmp (row[27],Ico_IconSetId[IconSet])) - { - UsrDat->Prefs.IconSet = IconSet; - break; - } - - /* Get menu (row[28]) */ - UsrDat->Prefs.Menu = Mnu_GetMenuFromStr (row[28]); - - /* Get if user wants to show side columns (row[29]) */ - if (sscanf (row[29],"%u",&UsrDat->Prefs.SideCols) == 1) + /* Get roles */ + switch (GetRoleInCurrentCrs) { - if (UsrDat->Prefs.SideCols > Lay_SHOW_BOTH_COLUMNS) - UsrDat->Prefs.SideCols = Cfg_DEFAULT_COLUMNS; + case Usr_DONT_GET_ROLE_IN_CURRENT_CRS: + UsrDat->Roles.InCurrentCrs = Rol_UNK; + UsrDat->Roles.InCrss = -1; // Force roles to be got from database + break; + case Usr_GET_ROLE_IN_CURRENT_CRS: + UsrDat->Roles.InCurrentCrs = Rol_GetRoleUsrInCrs (UsrDat->UsrCod, + Gbl.Hierarchy.Crs.CrsCod); + UsrDat->Roles.InCrss = -1; // Force roles to be got from database + break; } - else - UsrDat->Prefs.SideCols = Cfg_DEFAULT_COLUMNS; - /* Get if user accepts third party cookies (row[30]) */ - UsrDat->Prefs.AcceptThirdPartyCookies = (row[30][0] == 'Y'); + /* Get name (row[2], row[3], row[4]) */ + Str_Copy (UsrDat->Surname1,row[2],sizeof (UsrDat->Surname1) - 1); + Str_Copy (UsrDat->Surname2,row[3],sizeof (UsrDat->Surname2) - 1); + Str_Copy (UsrDat->FrstName,row[4],sizeof (UsrDat->FrstName) - 1); + Str_ConvertToTitleType (UsrDat->Surname1 ); + Str_ConvertToTitleType (UsrDat->Surname2 ); + Str_ConvertToTitleType (UsrDat->FrstName); + Usr_BuildFullName (UsrDat); // Create full name using FirstName, Surname1 and Surname2 + + /* Get sex (row[5]) */ + UsrDat->Sex = Usr_GetSexFromStr (row[5]); + + /* Get photo (row[6]) */ + Str_Copy (UsrDat->Photo,row[6],sizeof (UsrDat->Photo) - 1); + + /* Get photo visibility (row[7]) */ + UsrDat->PhotoVisibility = Pri_GetVisibilityFromStr (row[7]); + + /* Get profile visibility (row[8], row[9]) */ + UsrDat->BaPrfVisibility = Pri_GetVisibilityFromStr (row[8]); + UsrDat->ExPrfVisibility = Pri_GetVisibilityFromStr (row[9]); + + /* Get country (row[10]), institution country (row[11]), + institution (row[12]), department (row[13]) and center (row[14]) */ + UsrDat->CtyCod = Str_ConvertStrCodToLongCod (row[10]); + UsrDat->InsCtyCod = Str_ConvertStrCodToLongCod (row[11]); + UsrDat->InsCod = Str_ConvertStrCodToLongCod (row[12]); + UsrDat->Tch.DptCod = Str_ConvertStrCodToLongCod (row[13]); + UsrDat->Tch.CtrCod = Str_ConvertStrCodToLongCod (row[14]); + + /* Get office (row[15]) and office phone (row[16]) */ + Str_Copy (UsrDat->Tch.Office ,row[15],sizeof (UsrDat->Tch.Office ) - 1); + Str_Copy (UsrDat->Tch.OfficePhone,row[16],sizeof (UsrDat->Tch.OfficePhone) - 1); + + /* Get phones (row[17]) and row[18] */ + Str_Copy (UsrDat->Phone[0],row[17],sizeof (UsrDat->Phone[0]) - 1); + Str_Copy (UsrDat->Phone[1],row[18],sizeof (UsrDat->Phone[1]) - 1); + + /* Get birthday (row[19]) */ + Dat_GetDateFromYYYYMMDD (&(UsrDat->Birthday),row[19]); + Dat_ConvDateToDateStr (&(UsrDat->Birthday),UsrDat->StrBirthday); + + /* Get comments (row[20]) */ + Usr_GetUsrCommentsFromString (row[20] ? row[20] : + "", + UsrDat); + + /* Get on which events the user wants to be notified inside the platform (row[21]) */ + if (sscanf (row[21],"%u",&UsrDat->NtfEvents.CreateNotif) != 1) + UsrDat->NtfEvents.CreateNotif = (unsigned) -1; // 0xFF..FF + + /* Get on which events the user wants to be notified by email (row[22]) */ + if (sscanf (row[22],"%u",&UsrDat->NtfEvents.SendEmail) != 1) + UsrDat->NtfEvents.SendEmail = 0; + if (UsrDat->NtfEvents.SendEmail >= (1 << Ntf_NUM_NOTIFY_EVENTS)) // Maximum binary value for NotifyEvents is 000...0011...11 + UsrDat->NtfEvents.SendEmail = 0; + + /***** Get user's settings *****/ + if (GetPrefs == Usr_GET_PREFS) + { + /* Get language (row[23]) */ + UsrDat->Prefs.Language = Lan_LANGUAGE_UNKNOWN; // Language unknown + for (Lan = (Lan_Language_t) 1; + Lan <= (Lan_Language_t) Lan_NUM_LANGUAGES; + Lan++) + if (!strcasecmp (row[23],Lan_STR_LANG_ID[Lan])) + { + UsrDat->Prefs.Language = Lan; + break; + } + + /* Get first day of week (row[24]) */ + UsrDat->Prefs.FirstDayOfWeek = Cal_GetFirstDayOfWeekFromStr (row[24]); + + /* Get date format (row[25]) */ + UsrDat->Prefs.DateFormat = Dat_GetDateFormatFromStr (row[25]); + + /* Get theme (row[26]) */ + UsrDat->Prefs.Theme = The_THEME_DEFAULT; + for (Theme = (The_Theme_t) 0; + Theme <= (The_Theme_t) (The_NUM_THEMES - 1); + Theme++) + if (!strcasecmp (row[26],The_ThemeId[Theme])) + { + UsrDat->Prefs.Theme = Theme; + break; + } + + /* Get icon set (row[27]) */ + UsrDat->Prefs.IconSet = Ico_ICON_SET_DEFAULT; + for (IconSet = (Ico_IconSet_t) 0; + IconSet <= (Ico_IconSet_t) (Ico_NUM_ICON_SETS - 1); + IconSet++) + if (!strcasecmp (row[27],Ico_IconSetId[IconSet])) + { + UsrDat->Prefs.IconSet = IconSet; + break; + } + + /* Get menu (row[28]) */ + UsrDat->Prefs.Menu = Mnu_GetMenuFromStr (row[28]); + + /* Get if user wants to show side columns (row[29]) */ + if (sscanf (row[29],"%u",&UsrDat->Prefs.SideCols) == 1) + { + if (UsrDat->Prefs.SideCols > Lay_SHOW_BOTH_COLUMNS) + UsrDat->Prefs.SideCols = Cfg_DEFAULT_COLUMNS; + } + else + UsrDat->Prefs.SideCols = Cfg_DEFAULT_COLUMNS; + + /* Get if user accepts third party cookies (row[30]) */ + UsrDat->Prefs.AcceptThirdPartyCookies = (row[30][0] == 'Y'); + } } + else + Err_WrongUserExit (); /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); @@ -720,33 +631,11 @@ static void Usr_GetMyLastData (void) { MYSQL_RES *mysql_res; MYSQL_ROW row; - unsigned NumRows; unsigned UnsignedNum; long ActCod; /***** Get user's last data from database *****/ - NumRows = (unsigned) - DB_QuerySELECT (&mysql_res,"can not get user's last data", - "SELECT WhatToSearch," // row[0] - "LastSco," // row[1] - "LastCod," // row[2] - "LastAct," // row[3] - "LastRole," // row[4] - "UNIX_TIMESTAMP(LastTime)," // row[5] - "UNIX_TIMESTAMP(LastAccNotif)" // row[6] - " FROM usr_last" - " WHERE UsrCod=%ld", - Gbl.Usrs.Me.UsrDat.UsrCod); - if (NumRows == 0) - { - /***** Free structure that stores the query result *****/ - DB_FreeMySQLResult (&mysql_res); - - /***** Create entry for me in table of user's last data *****/ - Usr_ResetMyLastData (); - Usr_DB_InsertMyLastData (); - } - else if (NumRows == 1) + if (Usr_DB_GetMyLastData (&mysql_res)) { row = mysql_fetch_row (mysql_res); @@ -799,12 +688,16 @@ static void Usr_GetMyLastData (void) Gbl.Usrs.Me.UsrLast.LastAccNotif = 0L; if (row[6]) sscanf (row[6],"%ld",&(Gbl.Usrs.Me.UsrLast.LastAccNotif)); - - /***** Free structure that stores the query result *****/ - DB_FreeMySQLResult (&mysql_res); } - else - Err_ShowErrorAndExit ("Error when getting user's last data."); + else // No user's last data found + { + /***** Create entry for me in table of user's last data *****/ + Usr_ResetMyLastData (); + Usr_DB_InsertMyLastData (); + } + + /***** Free structure that stores the query result *****/ + DB_FreeMySQLResult (&mysql_res); } /*****************************************************************************/ @@ -901,15 +794,7 @@ bool Usr_CheckIfUsrIsSuperuser (long UsrCod) /***** 3. Slow check: If not cached, get if a user is superuser from database *****/ Gbl.Cache.UsrIsSuperuser.UsrCod = UsrCod; - Gbl.Cache.UsrIsSuperuser.IsSuperuser = - DB_QueryEXISTS ("can not check if a user is superuser", - "SELECT EXISTS" - "(SELECT *" - " FROM usr_admins" - " WHERE UsrCod=%ld" - " AND Scope='%s')", - UsrCod, - Sco_GetDBStrFromScope (HieLvl_SYS)); + Gbl.Cache.UsrIsSuperuser.IsSuperuser = Adm_DB_CheckIfUsrIsSuperuser (UsrCod); return Gbl.Cache.UsrIsSuperuser.IsSuperuser; } @@ -2290,54 +2175,14 @@ bool Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (struct UsrData *UsrDat, void Usr_UpdateMyLastData (void) { /***** Check if it exists an entry for me *****/ - if (DB_QueryEXISTS ("can not check last user's click", - "SELECT EXISTS" - "(SELECT *" - " FROM usr_last" - " WHERE UsrCod=%ld)", - Gbl.Usrs.Me.UsrDat.UsrCod)) + if (Usr_DB_CheckMyLastData ()) /***** Update my last accessed course, tab and time of click in database *****/ // WhatToSearch, LastAccNotif remain unchanged - DB_QueryUPDATE ("can not update last user's data", - "UPDATE usr_last" - " SET LastSco='%s'," - "LastCod=%ld," - "LastAct=%ld," - "LastRole=%u," - "LastTime=NOW()" - " WHERE UsrCod=%ld", - Sco_GetDBStrFromScope (Gbl.Hierarchy.Level), - Gbl.Hierarchy.Cod, - Act_GetActCod (Gbl.Action.Act), - (unsigned) Gbl.Usrs.Me.Role.Logged, - Gbl.Usrs.Me.UsrDat.UsrCod); + Usr_DB_UpdateMyLastData (); else Usr_DB_InsertMyLastData (); } -/*****************************************************************************/ -/*************** Create new entry for my last data in database ***************/ -/*****************************************************************************/ - -static void Usr_DB_InsertMyLastData (void) - { - /***** Insert my last accessed course, tab and time of click in database *****/ - DB_QueryINSERT ("can not insert last user's data", - "INSERT INTO usr_last" - " (UsrCod,WhatToSearch," - "LastSco,LastCod,LastAct,LastRole,LastTime,LastAccNotif)" - " VALUES" - " (%ld,%u," - "'%s',%ld,%ld,%u,NOW(),FROM_UNIXTIME(%ld))", - Gbl.Usrs.Me.UsrDat.UsrCod, - (unsigned) Sch_SEARCH_ALL, - Sco_GetDBStrFromScope (Gbl.Hierarchy.Level), - Gbl.Hierarchy.Cod, - Act_GetActCod (Gbl.Action.Act), - (unsigned) Gbl.Usrs.Me.Role.Logged, - (long) (time_t) 0); // The user never accessed to notifications - } - /*****************************************************************************/ /*********** Write a row of a table with the main data of a user *************/ /*****************************************************************************/ @@ -2821,198 +2666,6 @@ static void Usr_WriteUsrData (const char *BgColor, HTM_TD_End (); } -/*****************************************************************************/ -/******* Build query to get list with data of users in current course ********/ -/*****************************************************************************/ - -static void Usr_BuildQueryToGetUsrsLstCrs (char **Query,Rol_Role_t Role) - { - unsigned NumPositiveCods = 0; - unsigned NumNegativeCods = 0; - char LongStr[Cns_MAX_DECIMAL_DIGITS_LONG + 1]; - unsigned NumGrpSel; - long GrpCod; - unsigned NumGrpTyp; - bool *AddStdsWithoutGroupOf; - const char *QueryFields = - "usr_data.UsrCod," - "usr_data.EncryptedUsrCod," - "usr_data.Password," - "usr_data.Surname1," - "usr_data.Surname2," - "usr_data.FirstName," - "usr_data.Sex," - "usr_data.Photo," - "usr_data.PhotoVisibility," - "usr_data.CtyCod," - "usr_data.InsCod," - "crs_users.Role," - "crs_users.Accepted"; - /* - row[ 0]: usr_data.UsrCod - row[ 1]: usr_data.EncryptedUsrCod - row[ 2]: usr_data.Password (used to check if a teacher can edit user's data) - row[ 3]: usr_data.Surname1 - row[ 4]: usr_data.Surname2 - row[ 5]: usr_data.FirstName - row[ 6]: usr_data.Sex - row[ 7]: usr_data.Photo - row[ 8]: usr_data.PhotoVisibility - row[ 9]: usr_data.CtyCod - row[10]: usr_data.InsCod - row[11]: crs_users.Role (only if Scope == HieLvl_CRS) - row[12]: crs_users.Accepted (only if Scope == HieLvl_CRS) - */ - - /***** If there are no groups selected, don't do anything *****/ - if (!Gbl.Usrs.ClassPhoto.AllGroups && - !Gbl.Crs.Grps.LstGrpsSel.NumGrps) - { - *Query = NULL; - return; - } - - /***** Allocate space for query *****/ - if ((*Query = malloc (Usr_MAX_BYTES_QUERY_GET_LIST_USRS + 1)) == NULL) - Err_NotEnoughMemoryExit (); - - /***** Create query for users in the course *****/ - if (Gbl.Action.Act == ActReqMsgUsr) // Selecting users to write a message - snprintf (*Query,Usr_MAX_BYTES_QUERY_GET_LIST_USRS + 1, - "SELECT %s" - " FROM crs_users," - "usr_data" - " WHERE crs_users.CrsCod=%ld" - " AND crs_users.Role=%u" - " AND crs_users.UsrCod NOT IN" - " (SELECT ToUsrCod" - " FROM msg_banned" - " WHERE FromUsrCod=%ld)" - " AND crs_users.UsrCod=usr_data.UsrCod", // Do not get banned users - QueryFields, - Gbl.Hierarchy.Crs.CrsCod, - (unsigned) Role, - Gbl.Usrs.Me.UsrDat.UsrCod); - else - snprintf (*Query,Usr_MAX_BYTES_QUERY_GET_LIST_USRS + 1, - "SELECT %s" - " FROM crs_users," - "usr_data" - " WHERE crs_users.CrsCod=%ld" - " AND crs_users.Role=%u" - " AND crs_users.UsrCod=usr_data.UsrCod", - QueryFields, - Gbl.Hierarchy.Crs.CrsCod, - (unsigned) Role); - - /***** Select users in selected groups *****/ - if (!Gbl.Usrs.ClassPhoto.AllGroups) - { - /***** Get list of groups types in current course *****/ - Grp_GetListGrpTypesInThisCrs (Grp_ONLY_GROUP_TYPES_WITH_GROUPS); - - /***** Allocate memory for list of booleans AddStdsWithoutGroupOf *****/ - if ((AddStdsWithoutGroupOf = calloc (Gbl.Crs.Grps.GrpTypes.NumGrpTypes, - sizeof (*AddStdsWithoutGroupOf))) == NULL) - Err_NotEnoughMemoryExit (); - - /***** Initialize vector of booleans that indicates whether it's necessary add to the list - the students who don't belong to any group of each type *****/ - for (NumGrpTyp = 0; - NumGrpTyp < Gbl.Crs.Grps.GrpTypes.NumGrpTypes; - NumGrpTyp++) - AddStdsWithoutGroupOf[NumGrpTyp] = false; - - /***** Create query with the students who belong to the groups selected *****/ - if (Gbl.Crs.Grps.LstGrpsSel.NumGrps) // If there are groups selected... - { - /* Check if there are positive and negative codes in the list */ - for (NumGrpSel = 0; - NumGrpSel < Gbl.Crs.Grps.LstGrpsSel.NumGrps; - NumGrpSel++) - if ((GrpCod = Gbl.Crs.Grps.LstGrpsSel.GrpCods[NumGrpSel]) > 0) - NumPositiveCods++; - else - for (NumGrpTyp = 0; - NumGrpTyp < Gbl.Crs.Grps.GrpTypes.NumGrpTypes; - NumGrpTyp++) - if (Gbl.Crs.Grps.GrpTypes.LstGrpTypes[NumGrpTyp].GrpTypCod == -GrpCod) - { - AddStdsWithoutGroupOf[NumGrpTyp] = true; - break; - } - /* If there are positive codes, add the students who belong to groups with those codes */ - if (NumPositiveCods) - { - Str_Concat (*Query," AND (crs_users.UsrCod IN" - " (SELECT DISTINCT " - "UsrCod" - " FROM grp_users" - " WHERE", - Usr_MAX_BYTES_QUERY_GET_LIST_USRS); - NumPositiveCods = 0; - for (NumGrpSel = 0; - NumGrpSel < Gbl.Crs.Grps.LstGrpsSel.NumGrps; - NumGrpSel++) - if ((GrpCod = Gbl.Crs.Grps.LstGrpsSel.GrpCods[NumGrpSel]) > 0) - { - Str_Concat (*Query,NumPositiveCods ? " OR GrpCod='" : - " GrpCod='", - Usr_MAX_BYTES_QUERY_GET_LIST_USRS); - snprintf (LongStr,sizeof (LongStr),"%ld",GrpCod); - Str_Concat (*Query,LongStr,Usr_MAX_BYTES_QUERY_GET_LIST_USRS); - Str_Concat (*Query,"'",Usr_MAX_BYTES_QUERY_GET_LIST_USRS); - NumPositiveCods++; - } - Str_Concat (*Query,")",Usr_MAX_BYTES_QUERY_GET_LIST_USRS); - } - } - - /***** Create a query with the students who don't belong to any group *****/ - for (NumGrpTyp = 0; - NumGrpTyp < Gbl.Crs.Grps.GrpTypes.NumGrpTypes; - NumGrpTyp++) - if (AddStdsWithoutGroupOf[NumGrpTyp]) - { - if (NumPositiveCods || NumNegativeCods) - Str_Concat (*Query," OR ",Usr_MAX_BYTES_QUERY_GET_LIST_USRS); - else - Str_Concat (*Query," AND (",Usr_MAX_BYTES_QUERY_GET_LIST_USRS); - /* Select all students of the course who don't belong to any group of type GrpTypCod */ - Str_Concat (*Query,"crs_users.UsrCod NOT IN" - " (SELECT DISTINCT " - "grp_users.UsrCod" - " FROM grp_groups," - "grp_users" - " WHERE grp_groups.GrpTypCod='", - Usr_MAX_BYTES_QUERY_GET_LIST_USRS); - snprintf (LongStr,sizeof (LongStr),"%ld", - Gbl.Crs.Grps.GrpTypes.LstGrpTypes[NumGrpTyp].GrpTypCod); - Str_Concat (*Query,LongStr,Usr_MAX_BYTES_QUERY_GET_LIST_USRS); - Str_Concat (*Query,"' AND grp_groups.GrpCod=grp_users.GrpCod)", - Usr_MAX_BYTES_QUERY_GET_LIST_USRS); - NumNegativeCods++; - } - if (NumPositiveCods || - NumNegativeCods) - Str_Concat (*Query,")",Usr_MAX_BYTES_QUERY_GET_LIST_USRS); - - /***** Free memory used by the list of booleans AddStdsWithoutGroupOf *****/ - free (AddStdsWithoutGroupOf); - - /***** Free list of groups types in current course *****/ - Grp_FreeListGrpTypesAndGrps (); - } - - /***** The last part of the query is for ordering the list *****/ - Str_Concat (*Query," ORDER BY " - "usr_data.Surname1," - "usr_data.Surname2," - "usr_data.FirstName," - "usr_data.UsrCod", - Usr_MAX_BYTES_QUERY_GET_LIST_USRS); - } - /*****************************************************************************/ /*********** Get list of users with a given role in a given scope ************/ /*****************************************************************************/ @@ -3024,155 +2677,15 @@ static void Usr_BuildQueryToGetUsrsLstCrs (char **Query,Rol_Role_t Role) void Usr_GetListUsrs (HieLvl_Level_t Scope,Rol_Role_t Role) { char *Query = NULL; - const char *QueryFields = - "DISTINCT " - "usr_data.UsrCod," - "usr_data.EncryptedUsrCod," - "usr_data.Password," - "usr_data.Surname1," - "usr_data.Surname2," - "usr_data.FirstName," - "usr_data.Sex," - "usr_data.Photo," - "usr_data.PhotoVisibility," - "usr_data.CtyCod," - "usr_data.InsCod"; - /* - row[ 0]: usr_data.UsrCod - row[ 1]: usr_data.EncryptedUsrCod - row[ 2]: usr_data.Password - row[ 3]: usr_data.Surname1 - row[ 4]: usr_data.Surname2 - row[ 5]: usr_data.FirstName - row[ 6]: usr_data.Sex - row[ 7]: usr_data.Photo - row[ 8]: usr_data.PhotoVisibility - row[ 9]: usr_data.CtyCod - row[10]: usr_data.InsCod - row[11]: crs_users.Role (only if Scope == HieLvl_CRS) - row[12]: crs_users.Accepted (only if Scope == HieLvl_CRS) - */ /***** Build query *****/ - switch (Scope) - { - case HieLvl_SYS: - /* Get users in courses from the whole platform */ - DB_BuildQuery (&Query, - "SELECT %s" - " FROM usr_data," - "crs_users" - " WHERE usr_data.UsrCod=crs_users.UsrCod" - " AND crs_users.Role=%u" - " ORDER BY usr_data.Surname1," - "usr_data.Surname2," - "usr_data.FirstName," - "usr_data.UsrCod", - QueryFields, - (unsigned) Role); - break; - case HieLvl_CTY: - /* Get users in courses from the current country */ - DB_BuildQuery (&Query, - "SELECT %s" - " FROM usr_data," - "crs_users," - "crs_courses," - "deg_degrees," - "ctr_centers," - "ins_instits" - " WHERE usr_data.UsrCod=crs_users.UsrCod" - " AND crs_users.Role=%u" - " AND crs_users.CrsCod=crs_courses.CrsCod" - " AND crs_courses.DegCod=deg_degrees.DegCod" - " AND deg_degrees.CtrCod=ctr_centers.CtrCod" - " AND ctr_centers.InsCod=ins_instits.InsCod" - " AND ins_instits.CtyCod=%ld" - " ORDER BY usr_data.Surname1," - "usr_data.Surname2," - "usr_data.FirstName," - "usr_data.UsrCod", - QueryFields, - (unsigned) Role, - Gbl.Hierarchy.Cty.CtyCod); - break; - case HieLvl_INS: - /* Get users in courses from the current institution */ - DB_BuildQuery (&Query, - "SELECT %s" - " FROM usr_data," - "crs_users," - "crs_courses," - "deg_degrees," - "ctr_centers" - " WHERE usr_data.UsrCod=crs_users.UsrCod" - " AND crs_users.Role=%u" - " AND crs_users.CrsCod=crs_courses.CrsCod" - " AND crs_courses.DegCod=deg_degrees.DegCod" - " AND deg_degrees.CtrCod=ctr_centers.CtrCod" - " AND ctr_centers.InsCod=%ld" - " ORDER BY usr_data.Surname1," - "usr_data.Surname2," - "usr_data.FirstName," - "usr_data.UsrCod", - QueryFields, - (unsigned) Role, - Gbl.Hierarchy.Ins.InsCod); - break; - case HieLvl_CTR: - /* Get users in courses from the current center */ - DB_BuildQuery (&Query, - "SELECT %s" - " FROM usr_data," - "crs_users," - "crs_courses," - "deg_degrees" - " WHERE usr_data.UsrCod=crs_users.UsrCod" - " AND crs_users.Role=%u" - " AND crs_users.CrsCod=crs_courses.CrsCod" - " AND crs_courses.DegCod=deg_degrees.DegCod" - " AND deg_degrees.CtrCod=%ld" - " ORDER BY usr_data.Surname1," - "usr_data.Surname2," - "usr_data.FirstName," - "usr_data.UsrCod", - QueryFields, - (unsigned) Role, - Gbl.Hierarchy.Ctr.CtrCod); - break; - case HieLvl_DEG: - /* Get users in courses from the current degree */ - DB_BuildQuery (&Query, - "SELECT %s" - " FROM usr_data," - "crs_users," - "crs_courses" - " WHERE usr_data.UsrCod=crs_users.UsrCod" - " AND crs_users.Role=%u" - " AND crs_users.CrsCod=crs_courses.CrsCod" - " AND crs_courses.DegCod=%ld" - " ORDER BY usr_data.Surname1," - "usr_data.Surname2," - "usr_data.FirstName," - "usr_data.UsrCod", - QueryFields, - (unsigned) Role, - Gbl.Hierarchy.Deg.DegCod); - break; - case HieLvl_CRS: - /* Get users from the current course */ - Usr_BuildQueryToGetUsrsLstCrs (&Query,Role); - break; - default: - Err_WrongScopeExit (); - break; - } -/* - if (Gbl.Usrs.Me.Roles.LoggedRole == Rol_SYS_ADM) - Lay_ShowAlert (Lay_INFO,Query); -*/ + Usr_DB_BuildQueryToGetUsrsLst (Scope,Role,&Query); + /***** Get list of users from database given a query *****/ Usr_GetListUsrsFromQuery (Query,Role,Scope); + + /***** Free query string *****/ + free (Query); } /*****************************************************************************/ @@ -3182,584 +2695,15 @@ void Usr_GetListUsrs (HieLvl_Level_t Scope,Rol_Role_t Role) void Usr_SearchListUsrs (Rol_Role_t Role) { char *Query = NULL; - char SubQueryRole[64]; - const char *QueryFields = - "DISTINCT " - "usr_data.UsrCod," - "usr_data.EncryptedUsrCod," - "usr_data.Password," - "usr_data.Surname1," - "usr_data.Surname2," - "usr_data.FirstName," - "usr_data.Sex," - "usr_data.Photo," - "usr_data.PhotoVisibility," - "usr_data.CtyCod," - "usr_data.InsCod"; - /* - row[ 0]: usr_data.UsrCod - row[ 1]: usr_data.EncryptedUsrCod - row[ 2]: usr_data.Password - row[ 3]: usr_data.Surname1 - row[ 4]: usr_data.Surname2 - row[ 5]: usr_data.FirstName - row[ 6]: usr_data.Sex - row[ 7]: usr_data.Photo - row[ 8]: usr_data.PhotoVisibility - row[ 9]: usr_data.CtyCod - row[10]: usr_data.InsCod - row[11]: crs_users.Role (only if Scope == HieLvl_CRS) - row[12]: crs_users.Accepted (only if Scope == HieLvl_CRS) - */ - const char *OrderQuery = "candidate_users.UsrCod=usr_data.UsrCod" - " ORDER BY usr_data.Surname1," - "usr_data.Surname2," - "usr_data.FirstName," - "usr_data.UsrCod"; /***** Build query *****/ - // if Gbl.Scope.Current is course ==> 3 columns are retrieved: UsrCod, Sex, Accepted - // else ==> 2 columns are retrieved: UsrCod, Sex - // Search is faster (aproximately x2) using a temporary table to store users found in the whole platform - switch (Role) - { - case Rol_UNK: // Here Rol_UNK means any rol (role does not matter) - switch (Gbl.Scope.Current) - { - case HieLvl_SYS: - /* Search users from the whole platform */ - DB_BuildQuery (&Query, - "SELECT %s" - " FROM candidate_users,usr_data" - " WHERE %s", - QueryFields,OrderQuery); - break; - case HieLvl_CTY: - /* Search users in courses from the current country */ - DB_BuildQuery (&Query, - "SELECT %s" - " FROM candidate_users," - "crs_users," - "crs_courses," - "deg_degrees," - "ctr_centers," - "ins_instits," - "usr_data" - " WHERE candidate_users.UsrCod=crs_users.UsrCod" - " AND crs_users.CrsCod=crs_courses.CrsCod" - " AND crs_courses.DegCod=deg_degrees.DegCod" - " AND deg_degrees.CtrCod=ctr_centers.CtrCod" - " AND ctr_centers.InsCod=ins_instits.InsCod" - " AND ins_instits.CtyCod=%ld" - " AND %s", - QueryFields, - Gbl.Hierarchy.Cty.CtyCod, - OrderQuery); - break; - case HieLvl_INS: - /* Search users in courses from the current institution */ - DB_BuildQuery (&Query, - "SELECT %s" - " FROM candidate_users," - "crs_users," - "crs_courses," - "deg_degrees," - "ctr_centers," - "usr_data" - " WHERE candidate_users.UsrCod=crs_users.UsrCod" - " AND crs_users.CrsCod=crs_courses.CrsCod" - " AND crs_courses.DegCod=deg_degrees.DegCod" - " AND deg_degrees.CtrCod=ctr_centers.CtrCod" - " AND ctr_centers.InsCod=%ld" - " AND %s", - QueryFields, - Gbl.Hierarchy.Ins.InsCod, - OrderQuery); - break; - case HieLvl_CTR: - /* Search users in courses from the current center */ - DB_BuildQuery (&Query, - "SELECT %s" - " FROM candidate_users," - "crs_users," - "crs_courses," - "deg_degrees," - " usr_data" - " WHERE candidate_users.UsrCod=crs_users.UsrCod" - " AND crs_users.CrsCod=crs_courses.CrsCod" - " AND crs_courses.DegCod=deg_degrees.DegCod" - " AND deg_degrees.CtrCod=%ld" - " AND %s", - QueryFields, - Gbl.Hierarchy.Ctr.CtrCod, - OrderQuery); - break; - case HieLvl_DEG: - /* Search users in courses from the current degree */ - DB_BuildQuery (&Query, - "SELECT %s" - " FROM candidate_users," - "crs_users," - "crs_courses," - "usr_data" - " WHERE candidate_users.UsrCod=crs_users.UsrCod" - " AND crs_users.CrsCod=crs_courses.CrsCod" - " AND crs_courses.DegCod=%ld" - " AND %s", - QueryFields, - Gbl.Hierarchy.Deg.DegCod, - OrderQuery); - break; - case HieLvl_CRS: - /* Search users in courses from the current course */ - DB_BuildQuery (&Query, - "SELECT %s," - "crs_users.Role," - "crs_users.Accepted" - " FROM candidate_users," - "crs_users," - "usr_data" - " WHERE candidate_users.UsrCod=crs_users.UsrCod" - " AND crs_users.CrsCod=%ld" - " AND %s", - QueryFields, - Gbl.Hierarchy.Crs.CrsCod, - OrderQuery); - break; - default: - Err_WrongScopeExit (); - break; - } - break; - case Rol_GST: // Guests (scope is not used) - /* Search users with no courses */ - DB_BuildQuery (&Query, - "SELECT %s" - " FROM candidate_users," - "usr_data" - " WHERE candidate_users.UsrCod NOT IN" - " (SELECT UsrCod" - " FROM crs_users)" - " AND %s", - QueryFields, - OrderQuery); - break; - case Rol_STD: // Student - case Rol_NET: // Non-editing teacher - case Rol_TCH: // Teacher - /* - To achieve maximum speed, it's important to do the things in this order: - 1) Search for user's name (UsrQuery) getting candidate users - 2) Filter the candidate users according to scope - */ - switch (Role) - { - case Rol_STD: // Student - sprintf (SubQueryRole," AND crs_users.Role=%u", - (unsigned) Rol_STD); - break; - case Rol_NET: // Non-editing teacher - case Rol_TCH: // or teacher - sprintf (SubQueryRole," AND (crs_users.Role=%u" - " OR crs_users.Role=%u)", - (unsigned) Rol_NET,(unsigned) Rol_TCH); - break; - default: - SubQueryRole[0] = '\0'; - break; - } - switch (Gbl.Scope.Current) - { - case HieLvl_SYS: - /* Search users in courses from the whole platform */ - DB_BuildQuery (&Query, - "SELECT %s" - " FROM candidate_users," - "crs_users," - "usr_data" - " WHERE candidate_users.UsrCod=crs_users.UsrCod" - "%s" - " AND %s", - QueryFields, - SubQueryRole, - OrderQuery); - break; - case HieLvl_CTY: - /* Search users in courses from the current country */ - DB_BuildQuery (&Query, - "SELECT %s" - " FROM candidate_users," - "crs_users," - "crs_courses," - "deg_degrees," - "ctr_centers," - "ins_instits," - "usr_data" - " WHERE candidate_users.UsrCod=crs_users.UsrCod" - "%s" - " AND crs_users.CrsCod=crs_courses.CrsCod" - " AND crs_courses.DegCod=deg_degrees.DegCod" - " AND deg_degrees.CtrCod=ctr_centers.CtrCod" - " AND ctr_centers.InsCod=ins_instits.InsCod" - " AND ins_instits.CtyCod=%ld" - " AND %s", - QueryFields, - SubQueryRole, - Gbl.Hierarchy.Cty.CtyCod, - OrderQuery); - break; - case HieLvl_INS: - /* Search users in courses from the current institution */ - DB_BuildQuery (&Query, - "SELECT %s" - " FROM candidate_users," - "crs_users," - "crs_courses," - "deg_degrees," - "ctr_centers," - "usr_data" - " WHERE candidate_users.UsrCod=crs_users.UsrCod" - "%s" - " AND crs_users.CrsCod=crs_courses.CrsCod" - " AND crs_courses.DegCod=deg_degrees.DegCod" - " AND deg_degrees.CtrCod=ctr_centers.CtrCod" - " AND ctr_centers.InsCod=%ld" - " AND %s", - QueryFields, - SubQueryRole, - Gbl.Hierarchy.Ins.InsCod, - OrderQuery); - break; - case HieLvl_CTR: - /* Search users in courses from the current center */ - DB_BuildQuery (&Query, - "SELECT %s" - " FROM candidate_users," - "crs_users," - "crs_courses," - "deg_degrees," - "usr_data" - " WHERE candidate_users.UsrCod=crs_users.UsrCod" - "%s" - " AND crs_users.CrsCod=crs_courses.CrsCod" - " AND crs_courses.DegCod=deg_degrees.DegCod" - " AND deg_degrees.CtrCod=%ld" - " AND %s", - QueryFields, - SubQueryRole, - Gbl.Hierarchy.Ctr.CtrCod, - OrderQuery); - break; - case HieLvl_DEG: - /* Search users in courses from the current degree */ - DB_BuildQuery (&Query, - "SELECT %s" - " FROM candidate_users," - "crs_users," - "crs_courses," - "usr_data" - " WHERE candidate_users.UsrCod=crs_users.UsrCod" - "%s" - " AND crs_users.CrsCod=crs_courses.CrsCod" - " AND crs_courses.DegCod=%ld" - " AND %s", - QueryFields, - SubQueryRole, - Gbl.Hierarchy.Deg.DegCod, - OrderQuery); - break; - case HieLvl_CRS: - /* Search users in courses from the current course */ - DB_BuildQuery (&Query, - "SELECT %s," - "crs_users.Role," - "crs_users.Accepted" - " FROM candidate_users," - "crs_users," - "usr_data" - " WHERE candidate_users.UsrCod=crs_users.UsrCod" - "%s" - " AND crs_users.CrsCod=%ld" - " AND %s", - QueryFields, - SubQueryRole, - Gbl.Hierarchy.Crs.CrsCod, - OrderQuery); - break; - default: - Err_WrongScopeExit (); - break; - } - break; - default: - Err_WrongRoleExit (); - break; - } - - // if (Gbl.Usrs.Me.Roles.LoggedRole == Rol_SYS_ADM) - // Lay_ShowAlert (Lay_INFO,Query); + Usr_DB_BuildQueryToSearchListUsrs (Role,&Query); /***** Get list of users from database given a query *****/ Usr_GetListUsrsFromQuery (Query,Role,Gbl.Scope.Current); - } -/*****************************************************************************/ -/*************** Create temporary table with candidate users *****************/ -/*****************************************************************************/ - -void Usr_CreateTmpTableAndSearchCandidateUsrs (const char SearchQuery[Sch_MAX_BYTES_SEARCH_QUERY + 1]) - { - char Query[256 + Sch_MAX_BYTES_SEARCH_QUERY]; - - /***** Create temporary table with candidate users *****/ - /* - - Search is faster (aproximately x2) using temporary tables. - - Searching for names is made in the whole platform - and stored in this table. - */ - sprintf (Query,"CREATE TEMPORARY TABLE candidate_users" - " (UsrCod INT NOT NULL,UNIQUE INDEX(UsrCod)) ENGINE=MEMORY" - " SELECT UsrCod" - " FROM usr_data" - " WHERE %s", - SearchQuery); - if (mysql_query (&Gbl.mysql,Query)) - DB_ExitOnMySQLError ("can not create temporary table"); - } - -/*****************************************************************************/ -/***************** Drop temporary table with candidate users *****************/ -/*****************************************************************************/ - -void Usr_DropTmpTableWithCandidateUsrs (void) - { - char Query[128]; - - sprintf (Query,"DROP TEMPORARY TABLE IF EXISTS candidate_users"); - if (mysql_query (&Gbl.mysql,Query)) - DB_ExitOnMySQLError ("can not remove temporary table"); - } - -/*****************************************************************************/ -/******************** Get list with data of administrators *******************/ -/*****************************************************************************/ - -static void Usr_GetAdmsLst (HieLvl_Level_t Scope) - { - const char *QueryFields = - "UsrCod," - "EncryptedUsrCod," - "Password," - "Surname1," - "Surname2," - "FirstName," - "Sex," - "Photo," - "PhotoVisibility," - "CtyCod," - "InsCod"; - /* - row[ 0]: usr_data.UsrCod - row[ 1]: usr_data.EncryptedUsrCod - row[ 2]: usr_data.Password - row[ 3]: usr_data.Surname1 - row[ 4]: usr_data.Surname2 - row[ 5]: usr_data.FirstName - row[ 6]: usr_data.Sex - row[ 7]: usr_data.Photo - row[ 8]: usr_data.PhotoVisibility - row[ 9]: usr_data.CtyCod - row[10]: usr_data.InsCod - */ - char *Query = NULL; - - /***** Build query *****/ - // Important: it is better to use: - // SELECT... WHERE UsrCod IN (SELECT...) OR UsrCod IN (SELECT...) <-- fast - // instead of using or with different joins: - // SELECT... WHERE (...) OR (...) <-- very slow - switch (Scope) - { - case HieLvl_SYS: // All admins - DB_BuildQuery (&Query, - "SELECT %s" - " FROM usr_data" - " WHERE UsrCod IN " - "(SELECT DISTINCT " - "UsrCod" - " FROM usr_admins)" - " ORDER BY Surname1," - "Surname2," - "FirstName," - "UsrCod", - QueryFields); - break; - case HieLvl_CTY: // System admins - // and admins of the institutions, centers and degrees in the current country - DB_BuildQuery (&Query, - "SELECT %s" - " FROM usr_data" - " WHERE UsrCod IN " - "(SELECT UsrCod" - " FROM usr_admins" - " WHERE Scope='%s')" - " OR UsrCod IN " - "(SELECT usr_admins.UsrCod" - " FROM usr_admins," - "ins_instits" - " WHERE usr_admins.Scope='%s'" - " AND usr_admins.Cod=ins_instits.InsCod" - " AND ins_instits.CtyCod=%ld)" - " OR UsrCod IN " - "(SELECT usr_admins.UsrCod" - " FROM usr_admins," - "ctr_centers," - "ins_instits" - " WHERE usr_admins.Scope='%s'" - " AND usr_admins.Cod=ctr_centers.CtrCod" - " AND ctr_centers.InsCod=ins_instits.InsCod" - " AND ins_instits.CtyCod=%ld)" - " OR UsrCod IN " - "(SELECT usr_admins.UsrCod" - " FROM usr_admins," - "deg_degrees," - "ctr_centers," - "ins_instits" - " WHERE usr_admins.Scope='%s'" - " AND usr_admins.Cod=deg_degrees.DegCod" - " AND deg_degrees.CtrCod=ctr_centers.CtrCod" - " AND ctr_centers.InsCod=ins_instits.InsCod" - " AND ins_instits.CtyCod=%ld)" - " ORDER BY Surname1," - "Surname2," - "FirstName," - "UsrCod", - QueryFields, - Sco_GetDBStrFromScope (HieLvl_SYS), - Sco_GetDBStrFromScope (HieLvl_INS),Gbl.Hierarchy.Cty.CtyCod, - Sco_GetDBStrFromScope (HieLvl_CTR),Gbl.Hierarchy.Cty.CtyCod, - Sco_GetDBStrFromScope (HieLvl_DEG),Gbl.Hierarchy.Cty.CtyCod); - break; - case HieLvl_INS: // System admins, - // admins of the current institution, - // and admins of the centers and degrees in the current institution - DB_BuildQuery (&Query, - "SELECT %s" - " FROM usr_data" - " WHERE UsrCod IN " - "(SELECT UsrCod" - " FROM usr_admins" - " WHERE Scope='%s')" - " OR UsrCod IN " - "(SELECT UsrCod" - " FROM usr_admins" - " WHERE Scope='%s'" - " AND Cod=%ld)" - " OR UsrCod IN " - "(SELECT usr_admins.UsrCod" - " FROM usr_admins," - "ctr_centers" - " WHERE usr_admins.Scope='%s'" - " AND usr_admins.Cod=ctr_centers.CtrCod" - " AND ctr_centers.InsCod=%ld)" - " OR UsrCod IN " - "(SELECT usr_admins.UsrCod" - " FROM usr_admins," - "deg_degrees," - "ctr_centers" - " WHERE usr_admins.Scope='%s'" - " AND usr_admins.Cod=deg_degrees.DegCod" - " AND deg_degrees.CtrCod=ctr_centers.CtrCod" - " AND ctr_centers.InsCod=%ld)" - " ORDER BY Surname1," - "Surname2," - "FirstName," - "UsrCod", - QueryFields, - Sco_GetDBStrFromScope (HieLvl_SYS), - Sco_GetDBStrFromScope (HieLvl_INS),Gbl.Hierarchy.Ins.InsCod, - Sco_GetDBStrFromScope (HieLvl_CTR),Gbl.Hierarchy.Ins.InsCod, - Sco_GetDBStrFromScope (HieLvl_DEG),Gbl.Hierarchy.Ins.InsCod); - break; - case HieLvl_CTR: // System admins, - // admins of the current institution, - // admins and the current center, - // and admins of the degrees in the current center - DB_BuildQuery (&Query, - "SELECT %s" - " FROM usr_data" - " WHERE UsrCod IN " - "(SELECT UsrCod" - " FROM usr_admins" - " WHERE Scope='%s')" - " OR UsrCod IN " - "(SELECT UsrCod" - " FROM usr_admins" - " WHERE Scope='%s'" - " AND Cod=%ld)" - " OR UsrCod IN " - "(SELECT UsrCod" - " FROM usr_admins" - " WHERE Scope='%s'" - " AND Cod=%ld)" - " OR UsrCod IN " - "(SELECT usr_admins.UsrCod" - " FROM usr_admins," - "deg_degrees" - " WHERE usr_admins.Scope='%s'" - " AND usr_admins.Cod=deg_degrees.DegCod" - " AND deg_degrees.CtrCod=%ld)" - " ORDER BY Surname1," - "Surname2," - "FirstName," - "UsrCod", - QueryFields, - Sco_GetDBStrFromScope (HieLvl_SYS), - Sco_GetDBStrFromScope (HieLvl_INS),Gbl.Hierarchy.Ins.InsCod, - Sco_GetDBStrFromScope (HieLvl_CTR),Gbl.Hierarchy.Ctr.CtrCod, - Sco_GetDBStrFromScope (HieLvl_DEG),Gbl.Hierarchy.Ctr.CtrCod); - break; - case HieLvl_DEG: // System admins - // and admins of the current institution, center or degree - DB_BuildQuery (&Query, - "SELECT %s" - " FROM usr_data" - " WHERE UsrCod IN " - "(SELECT UsrCod" - " FROM usr_admins" - " WHERE Scope='%s')" - " OR UsrCod IN " - "(SELECT UsrCod" - " FROM usr_admins" - " WHERE Scope='%s'" - " AND Cod=%ld)" - " OR UsrCod IN " - "(SELECT UsrCod" - " FROM usr_admins" - " WHERE Scope='%s'" - " AND Cod=%ld)" - " OR UsrCod IN " - "(SELECT UsrCod" - " FROM usr_admins" - " WHERE Scope='%s'" - " AND Cod=%ld)" - " ORDER BY Surname1," - "Surname2," - "FirstName," - "UsrCod", - QueryFields, - Sco_GetDBStrFromScope (HieLvl_SYS), - Sco_GetDBStrFromScope (HieLvl_INS),Gbl.Hierarchy.Ins.InsCod, - Sco_GetDBStrFromScope (HieLvl_CTR),Gbl.Hierarchy.Ctr.CtrCod, - Sco_GetDBStrFromScope (HieLvl_DEG),Gbl.Hierarchy.Deg.DegCod); - break; - default: // not aplicable - Err_WrongScopeExit (); - break; - } - - /***** Get list of administrators from database *****/ - Usr_GetListUsrsFromQuery (Query,Rol_DEG_ADM,Scope); + /***** Free query string *****/ + free (Query); } /*****************************************************************************/ @@ -3775,6 +2719,9 @@ static void Usr_GetGstsLst (HieLvl_Level_t Scope) /***** Get list of students from database *****/ Usr_GetListUsrsFromQuery (Query,Rol_GST,Scope); + + /***** Free query string *****/ + free (Query); } /*****************************************************************************/ @@ -3799,7 +2746,7 @@ void Usr_GetUnorderedStdsCodesInDeg (long DegCod) /********************** Get list of users from database **********************/ /*****************************************************************************/ -static void Usr_GetListUsrsFromQuery (char *Query,Rol_Role_t Role,HieLvl_Level_t Scope) +void Usr_GetListUsrsFromQuery (char *Query,Rol_Role_t Role,HieLvl_Level_t Scope) { extern const char *Txt_The_list_of_X_users_is_too_large_to_be_displayed; MYSQL_RES *mysql_res; @@ -5781,7 +4728,7 @@ unsigned Usr_ListUsrsFound (Rol_Role_t Role, /***** Create temporary table with candidate users *****/ // Search is faster (aproximately x2) using temporary tables - Usr_CreateTmpTableAndSearchCandidateUsrs (SearchQuery); + Usr_DB_CreateTmpTableAndSearchCandidateUsrs (SearchQuery); /***** Search for users *****/ Usr_SearchListUsrs (Role); @@ -5862,7 +4809,7 @@ unsigned Usr_ListUsrsFound (Rol_Role_t Role, Usr_FreeUsrsList (Role); /***** Drop temporary table with candidate users *****/ - Usr_DropTmpTableWithCandidateUsrs (); + Usr_DB_DropTmpTableWithCandidateUsrs (); return NumUsrs; } @@ -5938,7 +4885,7 @@ void Usr_ListDataAdms (void) Sco_GetScope ("ScopeUsr"); /***** Get list of administrators *****/ - Usr_GetAdmsLst (Gbl.Scope.Current); + Adm_GetAdmsLst (Gbl.Scope.Current); /***** Begin box with list of administrators *****/ Box_BoxBegin (NULL,Txt_ROLES_PLURAL_Abc[Rol_DEG_ADM][Usr_SEX_UNKNOWN], diff --git a/swad_user.h b/swad_user.h index bbea98fa..0e117352 100644 --- a/swad_user.h +++ b/swad_user.h @@ -349,11 +349,11 @@ void Usr_WriteRowUsrMainData (unsigned NumUsr,struct UsrData *UsrDat, void Usr_GetListUsrs (HieLvl_Level_t Scope,Rol_Role_t Role); void Usr_SearchListUsrs (Rol_Role_t Role); -void Usr_CreateTmpTableAndSearchCandidateUsrs (const char SearchQuery[Sch_MAX_BYTES_SEARCH_QUERY + 1]); -void Usr_DropTmpTableWithCandidateUsrs (void); void Usr_GetUnorderedStdsCodesInDeg (long DegCod); +void Usr_GetListUsrsFromQuery (char *Query,Rol_Role_t Role,HieLvl_Level_t Scope); + void Usr_CopyBasicUsrDataFromList (struct UsrData *UsrDat, const struct UsrInList *UsrInList); void Usr_FreeUsrsList (Rol_Role_t Role); diff --git a/swad_user_database.c b/swad_user_database.c index 7b13ff42..522d9661 100644 --- a/swad_user_database.c +++ b/swad_user_database.c @@ -135,22 +135,6 @@ void Usr_DB_UpdateMyOfficePhone (void) Gbl.Usrs.Me.UsrDat.UsrCod); } -/*****************************************************************************/ -/********************** Update my last type of search ************************/ -/*****************************************************************************/ - -void Usr_DB_UpdateMyLastWhatToSearch (void) - { - // WhatToSearch is stored in usr_last for next time I log in - // In other existing sessions distinct to this, WhatToSearch will remain unchanged - DB_QueryUPDATE ("can not update type of search in user's last data", - "UPDATE usr_last" - " SET WhatToSearch=%u" - " WHERE UsrCod=%ld", - (unsigned) Gbl.Search.WhatToSearch, - Gbl.Usrs.Me.UsrDat.UsrCod); - } - /*****************************************************************************/ /************** Check if a user exists with a given user's code **************/ /*****************************************************************************/ @@ -186,6 +170,91 @@ long Usr_DB_GetUsrCodFromEncryptedUsrCod (const char EncryptedUsrCod[Cry_BYTES_E EncryptedUsrCod); } +/*****************************************************************************/ +/************ Get user's data from database giving a user's code *************/ +/*****************************************************************************/ +// UsrDat->UsrCod must contain an existing user's code + +unsigned Usr_DB_GetUsrDataFromUsrCod (MYSQL_RES **mysql_res,long UsrCod, + Usr_GetPrefs_t GetPrefs) + { + switch (GetPrefs) + { + case Usr_DONT_GET_PREFS: + return (unsigned) + DB_QuerySELECT (mysql_res,"can not get user's data", + "SELECT EncryptedUsrCod," // row[ 0] + "Password," // row[ 1] + "Surname1," // row[ 2] + "Surname2," // row[ 3] + "FirstName," // row[ 4] + "Sex," // row[ 5] + "Photo," // row[ 6] + "PhotoVisibility," // row[ 7] + "BaPrfVisibility," // row[ 8] + "ExPrfVisibility," // row[ 9] + "CtyCod," // row[10] + "InsCtyCod," // row[11] + "InsCod," // row[12] + "DptCod," // row[13] + "CtrCod," // row[14] + "Office," // row[15] + "OfficePhone," // row[16] + "LocalPhone," // row[17] + "FamilyPhone," // row[18] + "DATE_FORMAT(Birthday," + "'%%Y%%m%%d')," // row[19] + "Comments," // row[20] + "NotifNtfEvents," // row[21] + "EmailNtfEvents" // row[22] + " FROM usr_data" + " WHERE UsrCod=%ld", + UsrCod); + case Usr_GET_PREFS: + default: + return (unsigned) + DB_QuerySELECT (mysql_res,"can not get user's data", + "SELECT EncryptedUsrCod," // row[ 0] + "Password," // row[ 1] + "Surname1," // row[ 2] + "Surname2," // row[ 3] + "FirstName," // row[ 4] + "Sex," // row[ 5] + "Photo," // row[ 6] + "PhotoVisibility," // row[ 7] + "BaPrfVisibility," // row[ 8] + "ExPrfVisibility," // row[ 9] + "CtyCod," // row[10] + "InsCtyCod," // row[11] + "InsCod," // row[12] + "DptCod," // row[13] + "CtrCod," // row[14] + "Office," // row[15] + "OfficePhone," // row[16] + "LocalPhone," // row[17] + "FamilyPhone," // row[18] + "DATE_FORMAT(Birthday," + "'%%Y%%m%%d')," // row[19] + "Comments," // row[20] + "NotifNtfEvents," // row[21] + "EmailNtfEvents," // row[22] + + // Settings (usually not necessary + // when getting another user's data) + "Language," // row[23] + "FirstDayOfWeek," // row[24] + "DateFormat," // row[25] + "Theme," // row[26] + "IconSet," // row[27] + "Menu," // row[28] + "SideCols," // row[29] + "ThirdPartyCookies" // row[30] + " FROM usr_data" + " WHERE UsrCod=%ld", + UsrCod); + } + } + /*****************************************************************************/ /****** Check if a string is found in first name or surnames of anybody ******/ /*****************************************************************************/ @@ -205,6 +274,542 @@ bool Usr_DB_FindStrInUsrsNames (const char *Str) Str); } +/*****************************************************************************/ +/*********** Get list of users with a given role in a given scope ************/ +/*****************************************************************************/ +// Role can be: +// - Rol_STD Student +// - Rol_NET Non-editing teacher +// - Rol_TCH Teacher + +void Usr_DB_BuildQueryToGetUsrsLst (HieLvl_Level_t Scope,Rol_Role_t Role,char **Query) + { + const char *QueryFields = + "DISTINCT " + "usr_data.UsrCod," // row[ 0] + "usr_data.EncryptedUsrCod," // row[ 1] + "usr_data.Password," // row[ 2] + "usr_data.Surname1," // row[ 3] + "usr_data.Surname2," // row[ 4] + "usr_data.FirstName," // row[ 5] + "usr_data.Sex," // row[ 6] + "usr_data.Photo," // row[ 7] + "usr_data.PhotoVisibility," // row[ 8] + "usr_data.CtyCod," // row[ 9] + "usr_data.InsCod"; // row[10] + static const char *OrderBySubQuery = + " ORDER BY usr_data.Surname1," + "usr_data.Surname2," + "usr_data.FirstName," + "usr_data.UsrCod"; + + /***** Build query *****/ + switch (Scope) + { + case HieLvl_SYS: + /* Get users in courses from the whole platform */ + DB_BuildQuery (Query, + "SELECT %s" + " FROM usr_data," + "crs_users" + " WHERE usr_data.UsrCod=crs_users.UsrCod" + " AND crs_users.Role=%u" + " %s", + QueryFields, + (unsigned) Role, + OrderBySubQuery); + break; + case HieLvl_CTY: + /* Get users in courses from the current country */ + DB_BuildQuery (Query, + "SELECT %s" + " FROM usr_data," + "crs_users," + "crs_courses," + "deg_degrees," + "ctr_centers," + "ins_instits" + " WHERE usr_data.UsrCod=crs_users.UsrCod" + " AND crs_users.Role=%u" + " AND crs_users.CrsCod=crs_courses.CrsCod" + " AND crs_courses.DegCod=deg_degrees.DegCod" + " AND deg_degrees.CtrCod=ctr_centers.CtrCod" + " AND ctr_centers.InsCod=ins_instits.InsCod" + " AND ins_instits.CtyCod=%ld" + " %s", + QueryFields, + (unsigned) Role, + Gbl.Hierarchy.Cty.CtyCod, + OrderBySubQuery); + break; + case HieLvl_INS: + /* Get users in courses from the current institution */ + DB_BuildQuery (Query, + "SELECT %s" + " FROM usr_data," + "crs_users," + "crs_courses," + "deg_degrees," + "ctr_centers" + " WHERE usr_data.UsrCod=crs_users.UsrCod" + " AND crs_users.Role=%u" + " AND crs_users.CrsCod=crs_courses.CrsCod" + " AND crs_courses.DegCod=deg_degrees.DegCod" + " AND deg_degrees.CtrCod=ctr_centers.CtrCod" + " AND ctr_centers.InsCod=%ld" + " %s", + QueryFields, + (unsigned) Role, + Gbl.Hierarchy.Ins.InsCod, + OrderBySubQuery); + break; + case HieLvl_CTR: + /* Get users in courses from the current center */ + DB_BuildQuery (Query, + "SELECT %s" + " FROM usr_data," + "crs_users," + "crs_courses," + "deg_degrees" + " WHERE usr_data.UsrCod=crs_users.UsrCod" + " AND crs_users.Role=%u" + " AND crs_users.CrsCod=crs_courses.CrsCod" + " AND crs_courses.DegCod=deg_degrees.DegCod" + " AND deg_degrees.CtrCod=%ld" + " ORDER BY usr_data.Surname1," + "usr_data.Surname2," + "usr_data.FirstName," + "usr_data.UsrCod", + QueryFields, + (unsigned) Role, + Gbl.Hierarchy.Ctr.CtrCod); + break; + case HieLvl_DEG: + /* Get users in courses from the current degree */ + DB_BuildQuery (Query, + "SELECT %s" + " FROM usr_data," + "crs_users," + "crs_courses" + " WHERE usr_data.UsrCod=crs_users.UsrCod" + " AND crs_users.Role=%u" + " AND crs_users.CrsCod=crs_courses.CrsCod" + " AND crs_courses.DegCod=%ld" + " ORDER BY usr_data.Surname1," + "usr_data.Surname2," + "usr_data.FirstName," + "usr_data.UsrCod", + QueryFields, + (unsigned) Role, + Gbl.Hierarchy.Deg.DegCod); + break; + case HieLvl_CRS: + /* Get users from the current course */ + Usr_DB_BuildQueryToGetUsrsLstCrs (Query,Role); + break; + default: + Err_WrongScopeExit (); + break; + } +/* + if (Gbl.Usrs.Me.Roles.LoggedRole == Rol_SYS_ADM) + Lay_ShowAlert (Lay_INFO,Query); +*/ + } + +/*****************************************************************************/ +/******* Build query to get list with data of users in current course ********/ +/*****************************************************************************/ + +#define Usr_DB_MAX_BYTES_QUERY_GET_LIST_USRS (16 * 1024 - 1) + +void Usr_DB_BuildQueryToGetUsrsLstCrs (char **Query,Rol_Role_t Role) + { + unsigned NumPositiveCods = 0; + unsigned NumNegativeCods = 0; + char LongStr[Cns_MAX_DECIMAL_DIGITS_LONG + 1]; + unsigned NumGrpSel; + long GrpCod; + unsigned NumGrpTyp; + bool *AddStdsWithoutGroupOf; + const char *QueryFields = + "usr_data.UsrCod," + "usr_data.EncryptedUsrCod," + "usr_data.Password," + "usr_data.Surname1," + "usr_data.Surname2," + "usr_data.FirstName," + "usr_data.Sex," + "usr_data.Photo," + "usr_data.PhotoVisibility," + "usr_data.CtyCod," + "usr_data.InsCod," + "crs_users.Role," + "crs_users.Accepted"; + /* + row[ 0]: usr_data.UsrCod + row[ 1]: usr_data.EncryptedUsrCod + row[ 2]: usr_data.Password (used to check if a teacher can edit user's data) + row[ 3]: usr_data.Surname1 + row[ 4]: usr_data.Surname2 + row[ 5]: usr_data.FirstName + row[ 6]: usr_data.Sex + row[ 7]: usr_data.Photo + row[ 8]: usr_data.PhotoVisibility + row[ 9]: usr_data.CtyCod + row[10]: usr_data.InsCod + row[11]: crs_users.Role (only if Scope == HieLvl_CRS) + row[12]: crs_users.Accepted (only if Scope == HieLvl_CRS) + */ + + /***** If there are no groups selected, don't do anything *****/ + if (!Gbl.Usrs.ClassPhoto.AllGroups && + !Gbl.Crs.Grps.LstGrpsSel.NumGrps) + { + *Query = NULL; + return; + } + + /***** Allocate space for query *****/ + if ((*Query = malloc (Usr_DB_MAX_BYTES_QUERY_GET_LIST_USRS + 1)) == NULL) + Err_NotEnoughMemoryExit (); + + /***** Create query for users in the course *****/ + if (Gbl.Action.Act == ActReqMsgUsr) // Selecting users to write a message + snprintf (*Query,Usr_DB_MAX_BYTES_QUERY_GET_LIST_USRS + 1, + "SELECT %s" + " FROM crs_users," + "usr_data" + " WHERE crs_users.CrsCod=%ld" + " AND crs_users.Role=%u" + " AND crs_users.UsrCod NOT IN" + " (SELECT ToUsrCod" + " FROM msg_banned" + " WHERE FromUsrCod=%ld)" + " AND crs_users.UsrCod=usr_data.UsrCod", // Do not get banned users + QueryFields, + Gbl.Hierarchy.Crs.CrsCod, + (unsigned) Role, + Gbl.Usrs.Me.UsrDat.UsrCod); + else + snprintf (*Query,Usr_DB_MAX_BYTES_QUERY_GET_LIST_USRS + 1, + "SELECT %s" + " FROM crs_users," + "usr_data" + " WHERE crs_users.CrsCod=%ld" + " AND crs_users.Role=%u" + " AND crs_users.UsrCod=usr_data.UsrCod", + QueryFields, + Gbl.Hierarchy.Crs.CrsCod, + (unsigned) Role); + + /***** Select users in selected groups *****/ + if (!Gbl.Usrs.ClassPhoto.AllGroups) + { + /***** Get list of groups types in current course *****/ + Grp_GetListGrpTypesInThisCrs (Grp_ONLY_GROUP_TYPES_WITH_GROUPS); + + /***** Allocate memory for list of booleans AddStdsWithoutGroupOf *****/ + if ((AddStdsWithoutGroupOf = calloc (Gbl.Crs.Grps.GrpTypes.NumGrpTypes, + sizeof (*AddStdsWithoutGroupOf))) == NULL) + Err_NotEnoughMemoryExit (); + + /***** Initialize vector of booleans that indicates whether it's necessary add to the list + the students who don't belong to any group of each type *****/ + for (NumGrpTyp = 0; + NumGrpTyp < Gbl.Crs.Grps.GrpTypes.NumGrpTypes; + NumGrpTyp++) + AddStdsWithoutGroupOf[NumGrpTyp] = false; + + /***** Create query with the students who belong to the groups selected *****/ + if (Gbl.Crs.Grps.LstGrpsSel.NumGrps) // If there are groups selected... + { + /* Check if there are positive and negative codes in the list */ + for (NumGrpSel = 0; + NumGrpSel < Gbl.Crs.Grps.LstGrpsSel.NumGrps; + NumGrpSel++) + if ((GrpCod = Gbl.Crs.Grps.LstGrpsSel.GrpCods[NumGrpSel]) > 0) + NumPositiveCods++; + else + for (NumGrpTyp = 0; + NumGrpTyp < Gbl.Crs.Grps.GrpTypes.NumGrpTypes; + NumGrpTyp++) + if (Gbl.Crs.Grps.GrpTypes.LstGrpTypes[NumGrpTyp].GrpTypCod == -GrpCod) + { + AddStdsWithoutGroupOf[NumGrpTyp] = true; + break; + } + /* If there are positive codes, add the students who belong to groups with those codes */ + if (NumPositiveCods) + { + Str_Concat (*Query," AND (crs_users.UsrCod IN" + " (SELECT DISTINCT " + "UsrCod" + " FROM grp_users" + " WHERE", + Usr_DB_MAX_BYTES_QUERY_GET_LIST_USRS); + NumPositiveCods = 0; + for (NumGrpSel = 0; + NumGrpSel < Gbl.Crs.Grps.LstGrpsSel.NumGrps; + NumGrpSel++) + if ((GrpCod = Gbl.Crs.Grps.LstGrpsSel.GrpCods[NumGrpSel]) > 0) + { + Str_Concat (*Query,NumPositiveCods ? " OR GrpCod='" : + " GrpCod='", + Usr_DB_MAX_BYTES_QUERY_GET_LIST_USRS); + snprintf (LongStr,sizeof (LongStr),"%ld",GrpCod); + Str_Concat (*Query,LongStr,Usr_DB_MAX_BYTES_QUERY_GET_LIST_USRS); + Str_Concat (*Query,"'",Usr_DB_MAX_BYTES_QUERY_GET_LIST_USRS); + NumPositiveCods++; + } + Str_Concat (*Query,")",Usr_DB_MAX_BYTES_QUERY_GET_LIST_USRS); + } + } + + /***** Create a query with the students who don't belong to any group *****/ + for (NumGrpTyp = 0; + NumGrpTyp < Gbl.Crs.Grps.GrpTypes.NumGrpTypes; + NumGrpTyp++) + if (AddStdsWithoutGroupOf[NumGrpTyp]) + { + if (NumPositiveCods || NumNegativeCods) + Str_Concat (*Query," OR ",Usr_DB_MAX_BYTES_QUERY_GET_LIST_USRS); + else + Str_Concat (*Query," AND (",Usr_DB_MAX_BYTES_QUERY_GET_LIST_USRS); + /* Select all students of the course who don't belong to any group of type GrpTypCod */ + Str_Concat (*Query,"crs_users.UsrCod NOT IN" + " (SELECT DISTINCT " + "grp_users.UsrCod" + " FROM grp_groups," + "grp_users" + " WHERE grp_groups.GrpTypCod='", + Usr_DB_MAX_BYTES_QUERY_GET_LIST_USRS); + snprintf (LongStr,sizeof (LongStr),"%ld", + Gbl.Crs.Grps.GrpTypes.LstGrpTypes[NumGrpTyp].GrpTypCod); + Str_Concat (*Query,LongStr,Usr_DB_MAX_BYTES_QUERY_GET_LIST_USRS); + Str_Concat (*Query,"' AND grp_groups.GrpCod=grp_users.GrpCod)", + Usr_DB_MAX_BYTES_QUERY_GET_LIST_USRS); + NumNegativeCods++; + } + if (NumPositiveCods || + NumNegativeCods) + Str_Concat (*Query,")",Usr_DB_MAX_BYTES_QUERY_GET_LIST_USRS); + + /***** Free memory used by the list of booleans AddStdsWithoutGroupOf *****/ + free (AddStdsWithoutGroupOf); + + /***** Free list of groups types in current course *****/ + Grp_FreeListGrpTypesAndGrps (); + } + + /***** The last part of the query is for ordering the list *****/ + Str_Concat (*Query," ORDER BY usr_data.Surname1," + "usr_data.Surname2," + "usr_data.FirstName," + "usr_data.UsrCod", + Usr_DB_MAX_BYTES_QUERY_GET_LIST_USRS); + } + +/*****************************************************************************/ +/************ Build query to get list with data of administrators ************/ +/*****************************************************************************/ + +void Usr_DB_BuildQueryToGetAdmsLst (HieLvl_Level_t Scope,char **Query) + { + static const char *QueryFields = + "UsrCod," // row[ 0] + "EncryptedUsrCod," // row[ 1] + "Password," // row[ 2] + "Surname1," // row[ 3] + "Surname2," // row[ 4] + "FirstName," // row[ 5] + "Sex," // row[ 6] + "Photo," // row[ 7] + "PhotoVisibility," // row[ 8] + "CtyCod," // row[ 9] + "InsCod"; // row[10] + static const char *OrderBySubQuery = + " ORDER BY Surname1," + "Surname2," + "FirstName," + "UsrCod"; + + /***** Build query *****/ + // Important: it is better to use: + // SELECT... WHERE UsrCod IN (SELECT...) OR UsrCod IN (SELECT...) <-- fast + // instead of using or with different joins: + // SELECT... WHERE (...) OR (...) <-- very slow + switch (Scope) + { + case HieLvl_SYS: // All admins + DB_BuildQuery (Query, + "SELECT %s" + " FROM usr_data" + " WHERE UsrCod IN " + "(SELECT DISTINCT " + "UsrCod" + " FROM usr_admins)" + "%s", + QueryFields, + OrderBySubQuery); + break; + case HieLvl_CTY: // System admins + // and admins of the institutions, centers and degrees in the current country + DB_BuildQuery (Query, + "SELECT %s" + " FROM usr_data" + " WHERE UsrCod IN " + "(SELECT UsrCod" + " FROM usr_admins" + " WHERE Scope='%s')" + " OR UsrCod IN " + "(SELECT usr_admins.UsrCod" + " FROM usr_admins," + "ins_instits" + " WHERE usr_admins.Scope='%s'" + " AND usr_admins.Cod=ins_instits.InsCod" + " AND ins_instits.CtyCod=%ld)" + " OR UsrCod IN " + "(SELECT usr_admins.UsrCod" + " FROM usr_admins," + "ctr_centers," + "ins_instits" + " WHERE usr_admins.Scope='%s'" + " AND usr_admins.Cod=ctr_centers.CtrCod" + " AND ctr_centers.InsCod=ins_instits.InsCod" + " AND ins_instits.CtyCod=%ld)" + " OR UsrCod IN " + "(SELECT usr_admins.UsrCod" + " FROM usr_admins," + "deg_degrees," + "ctr_centers," + "ins_instits" + " WHERE usr_admins.Scope='%s'" + " AND usr_admins.Cod=deg_degrees.DegCod" + " AND deg_degrees.CtrCod=ctr_centers.CtrCod" + " AND ctr_centers.InsCod=ins_instits.InsCod" + " AND ins_instits.CtyCod=%ld)" + " %s", + QueryFields, + Sco_GetDBStrFromScope (HieLvl_SYS), + Sco_GetDBStrFromScope (HieLvl_INS),Gbl.Hierarchy.Cty.CtyCod, + Sco_GetDBStrFromScope (HieLvl_CTR),Gbl.Hierarchy.Cty.CtyCod, + Sco_GetDBStrFromScope (HieLvl_DEG),Gbl.Hierarchy.Cty.CtyCod, + OrderBySubQuery); + break; + case HieLvl_INS: // System admins, + // admins of the current institution, + // and admins of the centers and degrees in the current institution + DB_BuildQuery (Query, + "SELECT %s" + " FROM usr_data" + " WHERE UsrCod IN " + "(SELECT UsrCod" + " FROM usr_admins" + " WHERE Scope='%s')" + " OR UsrCod IN " + "(SELECT UsrCod" + " FROM usr_admins" + " WHERE Scope='%s'" + " AND Cod=%ld)" + " OR UsrCod IN " + "(SELECT usr_admins.UsrCod" + " FROM usr_admins," + "ctr_centers" + " WHERE usr_admins.Scope='%s'" + " AND usr_admins.Cod=ctr_centers.CtrCod" + " AND ctr_centers.InsCod=%ld)" + " OR UsrCod IN " + "(SELECT usr_admins.UsrCod" + " FROM usr_admins," + "deg_degrees," + "ctr_centers" + " WHERE usr_admins.Scope='%s'" + " AND usr_admins.Cod=deg_degrees.DegCod" + " AND deg_degrees.CtrCod=ctr_centers.CtrCod" + " AND ctr_centers.InsCod=%ld)" + "%s", + QueryFields, + Sco_GetDBStrFromScope (HieLvl_SYS), + Sco_GetDBStrFromScope (HieLvl_INS),Gbl.Hierarchy.Ins.InsCod, + Sco_GetDBStrFromScope (HieLvl_CTR),Gbl.Hierarchy.Ins.InsCod, + Sco_GetDBStrFromScope (HieLvl_DEG),Gbl.Hierarchy.Ins.InsCod, + OrderBySubQuery); + break; + case HieLvl_CTR: // System admins, + // admins of the current institution, + // admins and the current center, + // and admins of the degrees in the current center + DB_BuildQuery (Query, + "SELECT %s" + " FROM usr_data" + " WHERE UsrCod IN " + "(SELECT UsrCod" + " FROM usr_admins" + " WHERE Scope='%s')" + " OR UsrCod IN " + "(SELECT UsrCod" + " FROM usr_admins" + " WHERE Scope='%s'" + " AND Cod=%ld)" + " OR UsrCod IN " + "(SELECT UsrCod" + " FROM usr_admins" + " WHERE Scope='%s'" + " AND Cod=%ld)" + " OR UsrCod IN " + "(SELECT usr_admins.UsrCod" + " FROM usr_admins," + "deg_degrees" + " WHERE usr_admins.Scope='%s'" + " AND usr_admins.Cod=deg_degrees.DegCod" + " AND deg_degrees.CtrCod=%ld)" + "%s", + QueryFields, + Sco_GetDBStrFromScope (HieLvl_SYS), + Sco_GetDBStrFromScope (HieLvl_INS),Gbl.Hierarchy.Ins.InsCod, + Sco_GetDBStrFromScope (HieLvl_CTR),Gbl.Hierarchy.Ctr.CtrCod, + Sco_GetDBStrFromScope (HieLvl_DEG),Gbl.Hierarchy.Ctr.CtrCod, + OrderBySubQuery); + break; + case HieLvl_DEG: // System admins + // and admins of the current institution, center or degree + DB_BuildQuery (Query, + "SELECT %s" + " FROM usr_data" + " WHERE UsrCod IN " + "(SELECT UsrCod" + " FROM usr_admins" + " WHERE Scope='%s')" + " OR UsrCod IN " + "(SELECT UsrCod" + " FROM usr_admins" + " WHERE Scope='%s'" + " AND Cod=%ld)" + " OR UsrCod IN " + "(SELECT UsrCod" + " FROM usr_admins" + " WHERE Scope='%s'" + " AND Cod=%ld)" + " OR UsrCod IN " + "(SELECT UsrCod" + " FROM usr_admins" + " WHERE Scope='%s'" + " AND Cod=%ld)" + "%s", + QueryFields, + Sco_GetDBStrFromScope (HieLvl_SYS), + Sco_GetDBStrFromScope (HieLvl_INS),Gbl.Hierarchy.Ins.InsCod, + Sco_GetDBStrFromScope (HieLvl_CTR),Gbl.Hierarchy.Ctr.CtrCod, + Sco_GetDBStrFromScope (HieLvl_DEG),Gbl.Hierarchy.Deg.DegCod, + OrderBySubQuery); + break; + default: // not aplicable + Err_WrongScopeExit (); + break; + } + } + /*****************************************************************************/ /************************ Get list with data of guests ***********************/ /*****************************************************************************/ @@ -242,7 +847,7 @@ void Usr_DB_BuildQueryToGetGstsLst (HieLvl_Level_t Scope,char **Query) "%s", QueryFields, OrderBySubQuery); - return; + break; case HieLvl_CTY: DB_BuildQuery (Query, "SELECT %s" @@ -258,7 +863,7 @@ void Usr_DB_BuildQueryToGetGstsLst (HieLvl_Level_t Scope,char **Query) Gbl.Hierarchy.Cty.CtyCod, Gbl.Hierarchy.Cty.CtyCod, OrderBySubQuery); - return; + break; case HieLvl_INS: DB_BuildQuery (Query, "SELECT %s" @@ -271,7 +876,7 @@ void Usr_DB_BuildQueryToGetGstsLst (HieLvl_Level_t Scope,char **Query) QueryFields, Gbl.Hierarchy.Ins.InsCod, OrderBySubQuery); - return; + break; case HieLvl_CTR: DB_BuildQuery (Query, "SELECT %s" @@ -284,13 +889,324 @@ void Usr_DB_BuildQueryToGetGstsLst (HieLvl_Level_t Scope,char **Query) QueryFields, Gbl.Hierarchy.Ctr.CtrCod, OrderBySubQuery); - return; + break; default: // not aplicable Err_WrongScopeExit (); - return; // Not reached + break; // Not reached } } +/*****************************************************************************/ +/*********** Search for users with a given role in current scope *************/ +/*****************************************************************************/ + +void Usr_DB_BuildQueryToSearchListUsrs (Rol_Role_t Role,char **Query) + { + char SubQueryRole[64]; + static const char *QueryFields = + "DISTINCT " + "usr_data.UsrCod," // row[ 0] + "usr_data.EncryptedUsrCod," // row[ 1] + "usr_data.Password," // row[ 2] + "usr_data.Surname1," // row[ 3] + "usr_data.Surname2," // row[ 4] + "usr_data.FirstName," // row[ 5] + "usr_data.Sex," // row[ 6] + "usr_data.Photo," // row[ 7] + "usr_data.PhotoVisibility," // row[ 8] + "usr_data.CtyCod," // row[ 9] + "usr_data.InsCod"; // row[10] + static const char *OrderBySubQuery = + "candidate_users.UsrCod=usr_data.UsrCod" + " ORDER BY usr_data.Surname1," + "usr_data.Surname2," + "usr_data.FirstName," + "usr_data.UsrCod"; + + /***** Build query *****/ + // if Gbl.Scope.Current is course ==> 3 columns are retrieved: UsrCod, Sex, Accepted + // else ==> 2 columns are retrieved: UsrCod, Sex + // Search is faster (aproximately x2) using a temporary table to store users found in the whole platform + switch (Role) + { + case Rol_UNK: // Here Rol_UNK means any rol (role does not matter) + switch (Gbl.Scope.Current) + { + case HieLvl_SYS: + /* Search users from the whole platform */ + DB_BuildQuery (Query, + "SELECT %s" + " FROM candidate_users,usr_data" + " WHERE %s", + QueryFields, + OrderBySubQuery); + break; + case HieLvl_CTY: + /* Search users in courses from the current country */ + DB_BuildQuery (Query, + "SELECT %s" + " FROM candidate_users," + "crs_users," + "crs_courses," + "deg_degrees," + "ctr_centers," + "ins_instits," + "usr_data" + " WHERE candidate_users.UsrCod=crs_users.UsrCod" + " AND crs_users.CrsCod=crs_courses.CrsCod" + " AND crs_courses.DegCod=deg_degrees.DegCod" + " AND deg_degrees.CtrCod=ctr_centers.CtrCod" + " AND ctr_centers.InsCod=ins_instits.InsCod" + " AND ins_instits.CtyCod=%ld" + " AND %s", + QueryFields, + Gbl.Hierarchy.Cty.CtyCod, + OrderBySubQuery); + break; + case HieLvl_INS: + /* Search users in courses from the current institution */ + DB_BuildQuery (Query, + "SELECT %s" + " FROM candidate_users," + "crs_users," + "crs_courses," + "deg_degrees," + "ctr_centers," + "usr_data" + " WHERE candidate_users.UsrCod=crs_users.UsrCod" + " AND crs_users.CrsCod=crs_courses.CrsCod" + " AND crs_courses.DegCod=deg_degrees.DegCod" + " AND deg_degrees.CtrCod=ctr_centers.CtrCod" + " AND ctr_centers.InsCod=%ld" + " AND %s", + QueryFields, + Gbl.Hierarchy.Ins.InsCod, + OrderBySubQuery); + break; + case HieLvl_CTR: + /* Search users in courses from the current center */ + DB_BuildQuery (Query, + "SELECT %s" + " FROM candidate_users," + "crs_users," + "crs_courses," + "deg_degrees," + " usr_data" + " WHERE candidate_users.UsrCod=crs_users.UsrCod" + " AND crs_users.CrsCod=crs_courses.CrsCod" + " AND crs_courses.DegCod=deg_degrees.DegCod" + " AND deg_degrees.CtrCod=%ld" + " AND %s", + QueryFields, + Gbl.Hierarchy.Ctr.CtrCod, + OrderBySubQuery); + break; + case HieLvl_DEG: + /* Search users in courses from the current degree */ + DB_BuildQuery (Query, + "SELECT %s" + " FROM candidate_users," + "crs_users," + "crs_courses," + "usr_data" + " WHERE candidate_users.UsrCod=crs_users.UsrCod" + " AND crs_users.CrsCod=crs_courses.CrsCod" + " AND crs_courses.DegCod=%ld" + " AND %s", + QueryFields, + Gbl.Hierarchy.Deg.DegCod, + OrderBySubQuery); + break; + case HieLvl_CRS: + /* Search users in courses from the current course */ + DB_BuildQuery (Query, + "SELECT %s," + "crs_users.Role," // row[11] + "crs_users.Accepted" // row[12] + " FROM candidate_users," + "crs_users," + "usr_data" + " WHERE candidate_users.UsrCod=crs_users.UsrCod" + " AND crs_users.CrsCod=%ld" + " AND %s", + QueryFields, + Gbl.Hierarchy.Crs.CrsCod, + OrderBySubQuery); + break; + default: + Err_WrongScopeExit (); + break; + } + break; + case Rol_GST: // Guests (scope is not used) + /* Search users with no courses */ + DB_BuildQuery (Query, + "SELECT %s" + " FROM candidate_users," + "usr_data" + " WHERE candidate_users.UsrCod NOT IN" + " (SELECT UsrCod" + " FROM crs_users)" + " AND %s", + QueryFields, + OrderBySubQuery); + break; + case Rol_STD: // Student + case Rol_NET: // Non-editing teacher + case Rol_TCH: // Teacher + /* + To achieve maximum speed, it's important to do the things in this order: + 1) Search for user's name (UsrQuery) getting candidate users + 2) Filter the candidate users according to scope + */ + switch (Role) + { + case Rol_STD: // Student + sprintf (SubQueryRole," AND crs_users.Role=%u", + (unsigned) Rol_STD); + break; + case Rol_NET: // Non-editing teacher + case Rol_TCH: // or teacher + sprintf (SubQueryRole," AND crs_users.Role IN (%u,%u)", + (unsigned) Rol_NET, + (unsigned) Rol_TCH); + break; + default: + SubQueryRole[0] = '\0'; + break; + } + switch (Gbl.Scope.Current) + { + case HieLvl_SYS: + /* Search users in courses from the whole platform */ + DB_BuildQuery (Query, + "SELECT %s" + " FROM candidate_users," + "crs_users," + "usr_data" + " WHERE candidate_users.UsrCod=crs_users.UsrCod" + "%s" + " AND %s", + QueryFields, + SubQueryRole, + OrderBySubQuery); + break; + case HieLvl_CTY: + /* Search users in courses from the current country */ + DB_BuildQuery (Query, + "SELECT %s" + " FROM candidate_users," + "crs_users," + "crs_courses," + "deg_degrees," + "ctr_centers," + "ins_instits," + "usr_data" + " WHERE candidate_users.UsrCod=crs_users.UsrCod" + "%s" + " AND crs_users.CrsCod=crs_courses.CrsCod" + " AND crs_courses.DegCod=deg_degrees.DegCod" + " AND deg_degrees.CtrCod=ctr_centers.CtrCod" + " AND ctr_centers.InsCod=ins_instits.InsCod" + " AND ins_instits.CtyCod=%ld" + " AND %s", + QueryFields, + SubQueryRole, + Gbl.Hierarchy.Cty.CtyCod, + OrderBySubQuery); + break; + case HieLvl_INS: + /* Search users in courses from the current institution */ + DB_BuildQuery (Query, + "SELECT %s" + " FROM candidate_users," + "crs_users," + "crs_courses," + "deg_degrees," + "ctr_centers," + "usr_data" + " WHERE candidate_users.UsrCod=crs_users.UsrCod" + "%s" + " AND crs_users.CrsCod=crs_courses.CrsCod" + " AND crs_courses.DegCod=deg_degrees.DegCod" + " AND deg_degrees.CtrCod=ctr_centers.CtrCod" + " AND ctr_centers.InsCod=%ld" + " AND %s", + QueryFields, + SubQueryRole, + Gbl.Hierarchy.Ins.InsCod, + OrderBySubQuery); + break; + case HieLvl_CTR: + /* Search users in courses from the current center */ + DB_BuildQuery (Query, + "SELECT %s" + " FROM candidate_users," + "crs_users," + "crs_courses," + "deg_degrees," + "usr_data" + " WHERE candidate_users.UsrCod=crs_users.UsrCod" + "%s" + " AND crs_users.CrsCod=crs_courses.CrsCod" + " AND crs_courses.DegCod=deg_degrees.DegCod" + " AND deg_degrees.CtrCod=%ld" + " AND %s", + QueryFields, + SubQueryRole, + Gbl.Hierarchy.Ctr.CtrCod, + OrderBySubQuery); + break; + case HieLvl_DEG: + /* Search users in courses from the current degree */ + DB_BuildQuery (Query, + "SELECT %s" + " FROM candidate_users," + "crs_users," + "crs_courses," + "usr_data" + " WHERE candidate_users.UsrCod=crs_users.UsrCod" + "%s" + " AND crs_users.CrsCod=crs_courses.CrsCod" + " AND crs_courses.DegCod=%ld" + " AND %s", + QueryFields, + SubQueryRole, + Gbl.Hierarchy.Deg.DegCod, + OrderBySubQuery); + break; + case HieLvl_CRS: + /* Search users in courses from the current course */ + DB_BuildQuery (Query, + "SELECT %s," + "crs_users.Role," + "crs_users.Accepted" + " FROM candidate_users," + "crs_users," + "usr_data" + " WHERE candidate_users.UsrCod=crs_users.UsrCod" + "%s" + " AND crs_users.CrsCod=%ld" + " AND %s", + QueryFields, + SubQueryRole, + Gbl.Hierarchy.Crs.CrsCod, + OrderBySubQuery); + break; + default: + Err_WrongScopeExit (); + break; + } + break; + default: + Err_WrongRoleExit (); + break; + } + + // if (Gbl.Usrs.Me.Roles.LoggedRole == Rol_SYS_ADM) + // Lay_ShowAlert (Lay_INFO,Query); + } + /*****************************************************************************/ /****** Build query to get the user's codes of all students of a degree ******/ /*****************************************************************************/ @@ -439,15 +1355,34 @@ unsigned Usr_DB_GetOldUsrs (MYSQL_RES **mysql_res,time_t SecondsWithoutAccess) } /*****************************************************************************/ -/*************************** Remove user's last data *************************/ +/*************** Create temporary table with candidate users *****************/ /*****************************************************************************/ -void Usr_DB_RemoveUsrLastData (long UsrCod) +void Usr_DB_CreateTmpTableAndSearchCandidateUsrs (const char SearchQuery[Sch_MAX_BYTES_SEARCH_QUERY + 1]) { - DB_QueryDELETE ("can not remove user's last data", - "DELETE FROM usr_last" - " WHERE UsrCod=%ld", - UsrCod); + /***** Create temporary table with candidate users *****/ + /* + - Search is faster (aproximately x2) using temporary tables. + - Searching for names is made in the whole platform + and stored in this table. + */ + DB_Query ("can not create temporary table", + "CREATE TEMPORARY TABLE candidate_users" + " (UsrCod INT NOT NULL,UNIQUE INDEX(UsrCod)) ENGINE=MEMORY" + " SELECT UsrCod" + " FROM usr_data" + " WHERE %s", + SearchQuery); + } + +/*****************************************************************************/ +/***************** Drop temporary table with candidate users *****************/ +/*****************************************************************************/ + +void Usr_DB_DropTmpTableWithCandidateUsrs (void) + { + DB_Query ("can not remove temporary table", + "DROP TEMPORARY TABLE IF EXISTS candidate_users"); } /*****************************************************************************/ @@ -463,6 +1398,114 @@ void Usr_DB_RemoveUsrData (long UsrCod) UsrCod); } +/*****************************************************************************/ +/*************** Create new entry for my last data in database ***************/ +/*****************************************************************************/ + +void Usr_DB_InsertMyLastData (void) + { + /***** Insert my last accessed course, tab and time of click in database *****/ + DB_QueryINSERT ("can not insert last user's data", + "INSERT INTO usr_last" + " (UsrCod,WhatToSearch," + "LastSco,LastCod,LastAct,LastRole,LastTime,LastAccNotif)" + " VALUES" + " (%ld,%u," + "'%s',%ld,%ld,%u,NOW(),FROM_UNIXTIME(%ld))", + Gbl.Usrs.Me.UsrDat.UsrCod, + (unsigned) Sch_SEARCH_ALL, + Sco_GetDBStrFromScope (Gbl.Hierarchy.Level), + Gbl.Hierarchy.Cod, + Act_GetActCod (Gbl.Action.Act), + (unsigned) Gbl.Usrs.Me.Role.Logged, + (long) (time_t) 0); // The user never accessed to notifications + } +/*****************************************************************************/ +/********* Update my last accessed course, tab and time in database **********/ +/*****************************************************************************/ + +void Usr_DB_UpdateMyLastData (void) + { + /***** Update my last accessed course, tab and time of click in database *****/ + // WhatToSearch, LastAccNotif remain unchanged + DB_QueryUPDATE ("can not update last user's data", + "UPDATE usr_last" + " SET LastSco='%s'," + "LastCod=%ld," + "LastAct=%ld," + "LastRole=%u," + "LastTime=NOW()" + " WHERE UsrCod=%ld", + Sco_GetDBStrFromScope (Gbl.Hierarchy.Level), + Gbl.Hierarchy.Cod, + Act_GetActCod (Gbl.Action.Act), + (unsigned) Gbl.Usrs.Me.Role.Logged, + Gbl.Usrs.Me.UsrDat.UsrCod); + } + +/*****************************************************************************/ +/********************** Update my last type of search ************************/ +/*****************************************************************************/ + +void Usr_DB_UpdateMyLastWhatToSearch (void) + { + // WhatToSearch is stored in usr_last for next time I log in + // In other existing sessions distinct to this, WhatToSearch will remain unchanged + DB_QueryUPDATE ("can not update type of search in user's last data", + "UPDATE usr_last" + " SET WhatToSearch=%u" + " WHERE UsrCod=%ld", + (unsigned) Gbl.Search.WhatToSearch, + Gbl.Usrs.Me.UsrDat.UsrCod); + } + +/*****************************************************************************/ +/************** Check if it exists an entry for me in last data **************/ +/*****************************************************************************/ + +bool Usr_DB_CheckMyLastData (void) + { + return + DB_QueryEXISTS ("can not check last user's data", + "SELECT EXISTS" + "(SELECT *" + " FROM usr_last" + " WHERE UsrCod=%ld)", + Gbl.Usrs.Me.UsrDat.UsrCod); + } + +/*****************************************************************************/ +/********** Get user's last data from database giving a user's code **********/ +/*****************************************************************************/ + +unsigned Usr_DB_GetMyLastData (MYSQL_RES **mysql_res) + { + return (unsigned) + DB_QuerySELECT (mysql_res,"can not get user's last data", + "SELECT WhatToSearch," // row[0] + "LastSco," // row[1] + "LastCod," // row[2] + "LastAct," // row[3] + "LastRole," // row[4] + "UNIX_TIMESTAMP(LastTime)," // row[5] + "UNIX_TIMESTAMP(LastAccNotif)" // row[6] + " FROM usr_last" + " WHERE UsrCod=%ld", + Gbl.Usrs.Me.UsrDat.UsrCod); + } + +/*****************************************************************************/ +/*************************** Remove user's last data *************************/ +/*****************************************************************************/ + +void Usr_DB_RemoveUsrLastData (long UsrCod) + { + DB_QueryDELETE ("can not remove user's last data", + "DELETE FROM usr_last" + " WHERE UsrCod=%ld", + UsrCod); + } + /*****************************************************************************/ /*** Insert my user's code in the table of birthdays already congratulated ***/ /*****************************************************************************/ diff --git a/swad_user_database.h b/swad_user_database.h index dbada19a..57ef9de3 100644 --- a/swad_user_database.h +++ b/swad_user_database.h @@ -45,7 +45,7 @@ // #include "swad_privacy_visibility_type.h" // #include "swad_role_type.h" // #include "swad_scope.h" -// #include "swad_search.h" +#include "swad_search.h" // #include "swad_string.h" // #include "swad_theme.h" @@ -61,20 +61,37 @@ /****************************** Public prototypes ****************************/ /*****************************************************************************/ +//------------------------------- User's data --------------------------------- void Usr_DB_UpdateMyOffice (void); void Usr_DB_UpdateMyOfficePhone (void); -void Usr_DB_UpdateMyLastWhatToSearch (void); bool Usr_DB_ChkIfUsrCodExists (long UsrCod); long Usr_DB_GetUsrCodFromEncryptedUsrCod (const char EncryptedUsrCod[Cry_BYTES_ENCRYPTED_STR_SHA256_BASE64 + 1]); +unsigned Usr_DB_GetUsrDataFromUsrCod (MYSQL_RES **mysql_res,long UsrCod, + Usr_GetPrefs_t GetPrefs); bool Usr_DB_FindStrInUsrsNames (const char *Str); +void Usr_DB_BuildQueryToGetUsrsLst (HieLvl_Level_t Scope,Rol_Role_t Role,char **Query); +void Usr_DB_BuildQueryToGetUsrsLstCrs (char **Query,Rol_Role_t Role); +void Usr_DB_BuildQueryToGetAdmsLst (HieLvl_Level_t Scope,char **Query); void Usr_DB_BuildQueryToGetGstsLst (HieLvl_Level_t Scope,char **Query); +void Usr_DB_BuildQueryToSearchListUsrs (Rol_Role_t Role,char **Query); void Usr_DB_BuildQueryToGetUnorderedStdsCodesInDeg (long DegCod,char **Query); unsigned Usr_DB_GetNumUsrsWhoChoseAnOption (const char *SubQuery); unsigned Usr_DB_GetOldUsrs (MYSQL_RES **mysql_res,time_t SecondsWithoutAccess); +void Usr_DB_CreateTmpTableAndSearchCandidateUsrs (const char SearchQuery[Sch_MAX_BYTES_SEARCH_QUERY + 1]); +void Usr_DB_DropTmpTableWithCandidateUsrs (void); + +void Usr_DB_RemoveUsrData (long UsrCod); + +//------------------------------ User's last data ----------------------------- +void Usr_DB_InsertMyLastData (void); +void Usr_DB_UpdateMyLastData (void); +void Usr_DB_UpdateMyLastWhatToSearch (void); + +bool Usr_DB_CheckMyLastData (void); +unsigned Usr_DB_GetMyLastData (MYSQL_RES **mysql_res); void Usr_DB_RemoveUsrLastData (long UsrCod); -void Usr_DB_RemoveUsrData (long UsrCod); //------------------------------ Birthdays today ------------------------------ void Usr_DB_MarkMyBirthdayAsCongratulated (void);