mirror of
https://github.com/acanas/swad-core.git
synced 2024-09-24 00:01:03 +02:00
1592 lines
54 KiB
C
1592 lines
54 KiB
C
// swad_user_database.c: users, operations with database
|
|
|
|
/*
|
|
SWAD (Shared Workspace At a Distance),
|
|
is a web platform developed at the University of Granada (Spain),
|
|
and used to support university teaching.
|
|
|
|
This file is part of SWAD core.
|
|
Copyright (C) 1999-2021 Antonio Cañas Vargas
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU Affero General 3 License as
|
|
published by the Free Software Foundation, either version 3 of the
|
|
License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU Affero General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Affero General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
/*****************************************************************************/
|
|
/*********************************** Headers *********************************/
|
|
/*****************************************************************************/
|
|
|
|
#include "swad_database.h"
|
|
#include "swad_error.h"
|
|
#include "swad_global.h"
|
|
#include "swad_user_database.h"
|
|
|
|
/*****************************************************************************/
|
|
/************** External global variables from others modules ****************/
|
|
/*****************************************************************************/
|
|
|
|
extern struct Globals Gbl;
|
|
|
|
/*****************************************************************************/
|
|
/******************************* Update my office ****************************/
|
|
/*****************************************************************************/
|
|
|
|
void Usr_DB_UpdateMyOffice (void)
|
|
{
|
|
DB_QueryUPDATE ("can not update office",
|
|
"UPDATE usr_data"
|
|
" SET Office='%s'"
|
|
" WHERE UsrCod=%ld",
|
|
Gbl.Usrs.Me.UsrDat.Tch.Office,
|
|
Gbl.Usrs.Me.UsrDat.UsrCod);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/***************************** Update my office phone ************************/
|
|
/*****************************************************************************/
|
|
|
|
void Usr_DB_UpdateMyOfficePhone (void)
|
|
{
|
|
DB_QueryUPDATE ("can not update office phone",
|
|
"UPDATE usr_data"
|
|
" SET OfficePhone='%s'"
|
|
" WHERE UsrCod=%ld",
|
|
Gbl.Usrs.Me.UsrDat.Tch.OfficePhone,
|
|
Gbl.Usrs.Me.UsrDat.UsrCod);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/************** Check if a user exists with a given user's code **************/
|
|
/*****************************************************************************/
|
|
|
|
bool Usr_DB_ChkIfUsrCodExists (long UsrCod)
|
|
{
|
|
/***** Trivial check: user's code should be > 0 *****/
|
|
if (UsrCod <= 0) // Wrong user's code
|
|
return false;
|
|
|
|
/***** Check if a user exists in database *****/
|
|
return
|
|
DB_QueryEXISTS ("can not check if a user exists",
|
|
"SELECT EXISTS"
|
|
"(SELECT *"
|
|
" FROM usr_data"
|
|
" WHERE UsrCod=%ld)",
|
|
UsrCod);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/******** Get user's code from database using encrypted user's code **********/
|
|
/*****************************************************************************/
|
|
// Input: UsrDat->EncryptedUsrCod must hold user's encrypted code
|
|
|
|
long Usr_DB_GetUsrCodFromEncryptedUsrCod (const char EncryptedUsrCod[Cry_BYTES_ENCRYPTED_STR_SHA256_BASE64 + 1])
|
|
{
|
|
return
|
|
DB_QuerySELECTCode ("can not get user's code",
|
|
"SELECT UsrCod"
|
|
" FROM usr_data"
|
|
" WHERE EncryptedUsrCod='%s'",
|
|
EncryptedUsrCod);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/***************** Get user's code from database using nickname **************/
|
|
/*****************************************************************************/
|
|
|
|
long Usr_DB_GetUsrCodFromNick (const char *NickWithoutArr)
|
|
{
|
|
return
|
|
DB_QuerySELECTCode ("can not get user's code",
|
|
"SELECT UsrCod"
|
|
" FROM usr_nicknames"
|
|
" WHERE Nickname='%s'",
|
|
NickWithoutArr);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/******** Get user's code from database using nickname and password **********/
|
|
/*****************************************************************************/
|
|
|
|
long Usr_DB_GetUsrCodFromNickPwd (const char *NickWithoutArr,const char *Password)
|
|
{
|
|
return
|
|
DB_QuerySELECTCode ("can not get user's code",
|
|
"SELECT usr_nicknames.UsrCod"
|
|
" FROM usr_nicknames,"
|
|
"usr_data"
|
|
" WHERE usr_nicknames.Nickname='%s'"
|
|
" AND usr_nicknames.UsrCod=usr_data.UsrCod"
|
|
" AND usr_data.Password='%s'",
|
|
NickWithoutArr,
|
|
Password);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**************** Get user's code from database using email ******************/
|
|
/*****************************************************************************/
|
|
|
|
long Usr_DB_GetUsrCodFromEmail (const char *Email)
|
|
{
|
|
return
|
|
DB_QuerySELECTCode ("can not get user's code",
|
|
"SELECT UsrCod"
|
|
" FROM usr_emails"
|
|
" WHERE E_mail='%s'", // TODO: Get only if email confirmed?
|
|
Email);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/********** Get user's code from database using email and password ***********/
|
|
/*****************************************************************************/
|
|
|
|
long Usr_DB_GetUsrCodFromEmailPwd (const char *Email,const char *Password)
|
|
{
|
|
return
|
|
DB_QuerySELECTCode ("can not get user's code",
|
|
"SELECT usr_emails.UsrCod"
|
|
" FROM usr_emails,"
|
|
"usr_data"
|
|
" WHERE usr_emails.E_mail='%s'" // TODO: Get only if email confirmed?
|
|
" AND usr_emails.UsrCod=usr_data.UsrCod"
|
|
" AND usr_data.Password='%s'",
|
|
Email,
|
|
Password);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**************** Get user's code from database using ID *********************/
|
|
/*****************************************************************************/
|
|
|
|
long Usr_DB_GetUsrCodFromID (const char *ID)
|
|
{
|
|
return
|
|
DB_QuerySELECTCode ("can not get user's code",
|
|
"SELECT UsrCod"
|
|
" FROM usr_ids"
|
|
" WHERE UsrID='%s'", // TODO: Get only if ID confirmed?
|
|
ID);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/*********** Get user's code from database using ID and password *************/
|
|
/*****************************************************************************/
|
|
|
|
long Usr_DB_GetUsrCodFromIDPwd (const char *ID,const char *Password)
|
|
{
|
|
return
|
|
DB_QuerySELECTCode ("can not get user's code",
|
|
"SELECT usr_ids.UsrCod"
|
|
" FROM usr_ids,"
|
|
"usr_data"
|
|
" WHERE usr_ids.UsrID='%s'" // TODO: Get only if ID confirmed?
|
|
" AND usr_ids.UsrCod=usr_data.UsrCod"
|
|
" AND usr_data.Password='%s'",
|
|
ID,
|
|
Password);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/************ 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);
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/********** Get some user's data from database giving a user's code **********/
|
|
/*****************************************************************************/
|
|
// UsrDat->UsrCod must contain an existing user's code
|
|
|
|
unsigned Usr_DB_GetSomeUsrDataFromUsrCod (MYSQL_RES **mysql_res,long UsrCod)
|
|
{
|
|
return (unsigned)
|
|
DB_QuerySELECT (mysql_res,"can not get user's data",
|
|
"SELECT Surname1," // row[0]
|
|
"Surname2," // row[1]
|
|
"FirstName," // row[2]
|
|
"Photo," // row[3]
|
|
"DATE_FORMAT(Birthday,'%%Y%%m%%d')" // row[4]
|
|
" FROM usr_data"
|
|
" WHERE UsrCod=%ld",
|
|
UsrCod);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/****** Check if a string is found in first name or surnames of anybody ******/
|
|
/*****************************************************************************/
|
|
|
|
bool Usr_DB_FindStrInUsrsNames (const char *Str)
|
|
{
|
|
return
|
|
DB_QueryEXISTS ("can not check if a string matches a first name or a surname",
|
|
"SELECT EXISTS"
|
|
"(SELECT *"
|
|
" FROM usr_data"
|
|
" WHERE FirstName='%s'"
|
|
" OR Surname1='%s'"
|
|
" OR Surname2='%s')",
|
|
Str,
|
|
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_GetListGrpTypesInCurrentCrs (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 ***********************/
|
|
/*****************************************************************************/
|
|
|
|
void Usr_DB_BuildQueryToGetGstsLst (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 *****/
|
|
switch (Scope)
|
|
{
|
|
case HieLvl_SYS:
|
|
DB_BuildQuery (Query,
|
|
"SELECT %s"
|
|
" FROM usr_data"
|
|
" WHERE UsrCod NOT IN"
|
|
" (SELECT UsrCod"
|
|
" FROM crs_users)"
|
|
"%s",
|
|
QueryFields,
|
|
OrderBySubQuery);
|
|
break;
|
|
case HieLvl_CTY:
|
|
DB_BuildQuery (Query,
|
|
"SELECT %s"
|
|
" FROM usr_data"
|
|
" WHERE (CtyCod=%ld"
|
|
" OR"
|
|
" InsCtyCod=%ld)"
|
|
" AND UsrCod NOT IN"
|
|
" (SELECT UsrCod"
|
|
" FROM crs_users)"
|
|
"%s",
|
|
QueryFields,
|
|
Gbl.Hierarchy.Cty.CtyCod,
|
|
Gbl.Hierarchy.Cty.CtyCod,
|
|
OrderBySubQuery);
|
|
break;
|
|
case HieLvl_INS:
|
|
DB_BuildQuery (Query,
|
|
"SELECT %s"
|
|
" FROM usr_data"
|
|
" WHERE InsCod=%ld"
|
|
" AND UsrCod NOT IN"
|
|
" (SELECT UsrCod"
|
|
" FROM crs_users)"
|
|
"%s",
|
|
QueryFields,
|
|
Gbl.Hierarchy.Ins.InsCod,
|
|
OrderBySubQuery);
|
|
break;
|
|
case HieLvl_CTR:
|
|
DB_BuildQuery (Query,
|
|
"SELECT %s"
|
|
" FROM usr_data"
|
|
" WHERE CtrCod=%ld"
|
|
" AND UsrCod NOT IN"
|
|
" (SELECT UsrCod"
|
|
" FROM crs_users)"
|
|
"%s",
|
|
QueryFields,
|
|
Gbl.Hierarchy.Ctr.CtrCod,
|
|
OrderBySubQuery);
|
|
break;
|
|
default: // not aplicable
|
|
Err_WrongScopeExit ();
|
|
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 ******/
|
|
/*****************************************************************************/
|
|
|
|
void Usr_DB_BuildQueryToGetUnorderedStdsCodesInDeg (long DegCod,char **Query)
|
|
{
|
|
DB_BuildQuery (Query,
|
|
"SELECT 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]
|
|
" FROM crs_courses,"
|
|
"crs_users,"
|
|
"usr_data"
|
|
" WHERE crs_courses.DegCod=%ld"
|
|
" AND crs_courses.CrsCod=crs_users.CrsCod"
|
|
" AND crs_users.Role=%u"
|
|
" AND crs_users.UsrCod=usr_data.UsrCod",
|
|
DegCod,
|
|
(unsigned) Rol_STD);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/************** Get number of users who have chosen an option ****************/
|
|
/*****************************************************************************/
|
|
|
|
unsigned Usr_DB_GetNumUsrsWhoChoseAnOption (const char *SubQuery)
|
|
{
|
|
switch (Gbl.Scope.Current)
|
|
{
|
|
case HieLvl_SYS:
|
|
return (unsigned)
|
|
DB_QueryCOUNT ("can not get the number of users who have chosen an option",
|
|
"SELECT COUNT(*)"
|
|
" FROM usr_data"
|
|
" WHERE %s",
|
|
SubQuery);
|
|
case HieLvl_CTY:
|
|
return (unsigned)
|
|
DB_QueryCOUNT ("can not get the number of users who have chosen an option",
|
|
"SELECT COUNT(DISTINCT usr_data.UsrCod)"
|
|
" FROM ins_instits,"
|
|
"ctr_centers,"
|
|
"deg_degrees,"
|
|
"crs_courses,"
|
|
"crs_users,"
|
|
"usr_data"
|
|
" WHERE ins_instits.CtyCod=%ld"
|
|
" AND ins_instits.InsCod=ctr_centers.InsCod"
|
|
" AND ctr_centers.CtrCod=deg_degrees.CtrCod"
|
|
" AND deg_degrees.DegCod=crs_courses.DegCod"
|
|
" AND crs_courses.CrsCod=crs_users.CrsCod"
|
|
" AND crs_users.UsrCod=usr_data.UsrCod"
|
|
" AND %s",
|
|
Gbl.Hierarchy.Cty.CtyCod,SubQuery);
|
|
case HieLvl_INS:
|
|
return (unsigned)
|
|
DB_QueryCOUNT ("can not get the number of users who have chosen an option",
|
|
"SELECT COUNT(DISTINCT usr_data.UsrCod)"
|
|
" FROM ctr_centers,"
|
|
"deg_degrees,"
|
|
"crs_courses,"
|
|
"crs_users,"
|
|
"usr_data"
|
|
" WHERE ctr_centers.InsCod=%ld"
|
|
" AND ctr_centers.CtrCod=deg_degrees.CtrCod"
|
|
" AND deg_degrees.DegCod=crs_courses.DegCod"
|
|
" AND crs_courses.CrsCod=crs_users.CrsCod"
|
|
" AND crs_users.UsrCod=usr_data.UsrCod"
|
|
" AND %s",
|
|
Gbl.Hierarchy.Ins.InsCod,SubQuery);
|
|
case HieLvl_CTR:
|
|
return (unsigned)
|
|
DB_QueryCOUNT ("can not get the number of users who have chosen an option",
|
|
"SELECT COUNT(DISTINCT usr_data.UsrCod)"
|
|
" FROM deg_degrees,"
|
|
"crs_courses,"
|
|
"crs_users,"
|
|
"usr_data"
|
|
" WHERE deg_degrees.CtrCod=%ld"
|
|
" AND deg_degrees.DegCod=crs_courses.DegCod"
|
|
" AND crs_courses.CrsCod=crs_users.CrsCod"
|
|
" AND crs_users.UsrCod=usr_data.UsrCod"
|
|
" AND %s",
|
|
Gbl.Hierarchy.Ctr.CtrCod,SubQuery);
|
|
case HieLvl_DEG:
|
|
return (unsigned)
|
|
DB_QueryCOUNT ("can not get the number of users who have chosen an option",
|
|
"SELECT COUNT(DISTINCT usr_data.UsrCod)"
|
|
" FROM crs_courses,"
|
|
"crs_users,"
|
|
"usr_data"
|
|
" WHERE crs_courses.DegCod=%ld"
|
|
" AND crs_courses.CrsCod=crs_users.CrsCod"
|
|
" AND crs_users.UsrCod=usr_data.UsrCod"
|
|
" AND %s",
|
|
Gbl.Hierarchy.Deg.DegCod,SubQuery);
|
|
case HieLvl_CRS:
|
|
return (unsigned)
|
|
DB_QueryCOUNT ("can not get the number of users who have chosen an option",
|
|
"SELECT COUNT(DISTINCT usr_data.UsrCod)"
|
|
" FROM crs_users,"
|
|
"usr_data"
|
|
" WHERE crs_users.CrsCod=%ld"
|
|
" AND crs_users.UsrCod=usr_data.UsrCod"
|
|
" AND %s",
|
|
Gbl.Hierarchy.Crs.CrsCod,SubQuery);
|
|
default:
|
|
Err_WrongScopeExit ();
|
|
return 0; // Not reached
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/************************* Get old users from database ***********************/
|
|
/*****************************************************************************/
|
|
|
|
unsigned Usr_DB_GetOldUsrs (MYSQL_RES **mysql_res,time_t SecondsWithoutAccess)
|
|
{
|
|
return (unsigned)
|
|
DB_QuerySELECT (mysql_res,"can not get old users",
|
|
"SELECT UsrCod"
|
|
" FROM (SELECT UsrCod"
|
|
" FROM usr_last"
|
|
" WHERE LastTime<FROM_UNIXTIME(UNIX_TIMESTAMP()-%llu)"
|
|
" UNION "
|
|
"SELECT UsrCod"
|
|
" FROM usr_data"
|
|
" WHERE UsrCod NOT IN"
|
|
" (SELECT UsrCod"
|
|
" FROM usr_last)"
|
|
") AS candidate_usrs"
|
|
" WHERE UsrCod NOT IN"
|
|
" (SELECT DISTINCT "
|
|
"UsrCod"
|
|
" FROM crs_users)",
|
|
(unsigned long long) SecondsWithoutAccess);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/*************** Create temporary table with candidate users *****************/
|
|
/*****************************************************************************/
|
|
|
|
void Usr_DB_CreateTmpTableAndSearchCandidateUsrs (const char SearchQuery[Sch_MAX_BYTES_SEARCH_QUERY + 1])
|
|
{
|
|
/***** 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");
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/****************************** Remove user's data ***************************/
|
|
/*****************************************************************************/
|
|
|
|
void Usr_DB_RemoveUsrData (long UsrCod)
|
|
{
|
|
/***** Remove user's data *****/
|
|
DB_QueryDELETE ("can not remove user's data",
|
|
"DELETE FROM usr_data"
|
|
" WHERE UsrCod=%ld",
|
|
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 ***/
|
|
/*****************************************************************************/
|
|
|
|
void Usr_DB_MarkMyBirthdayAsCongratulated (void)
|
|
{
|
|
DB_QueryINSERT ("can not insert birthday",
|
|
"INSERT INTO usr_birthdays_today"
|
|
" (UsrCod,Today)"
|
|
" VALUES"
|
|
" (%ld,CURDATE())",
|
|
Gbl.Usrs.Me.UsrDat.UsrCod);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/*************** Check if my birthday is already congratulated ***************/
|
|
/*****************************************************************************/
|
|
|
|
bool Usr_DB_CheckIfMyBirthdayHasNotBeenCongratulated (void)
|
|
{
|
|
return
|
|
DB_QueryEXISTS ("can not check if my birthday has been congratulated",
|
|
"SELECT EXISTS"
|
|
"(SELECT *"
|
|
" FROM usr_birthdays_today"
|
|
" WHERE UsrCod=%ld)",
|
|
Gbl.Usrs.Me.UsrDat.UsrCod);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/****************************** Delete old birthdays *************************/
|
|
/*****************************************************************************/
|
|
|
|
void Usr_DB_DeleteOldBirthdays (void)
|
|
{
|
|
DB_QueryDELETE ("can not delete old birthdays",
|
|
"DELETE FROM usr_birthdays_today"
|
|
" WHERE Today<>CURDATE()");
|
|
}
|