diff --git a/Makefile b/Makefile index 6b5a3bf53..f150f668a 100644 --- a/Makefile +++ b/Makefile @@ -29,8 +29,8 @@ OBJS = swad_account.o swad_account_database.o swad_action.o swad_admin.o \ swad_admin_database.o swad_agenda.o swad_agenda_database.o swad_alert.o \ swad_announcement.o swad_announcement_database.o swad_API.o \ - swad_assignment.o swad_assignment_database.o swad_attendance.o \ - swad_attendance_database.o \ + swad_API_database.o swad_assignment.o swad_assignment_database.o \ + swad_attendance.o swad_attendance_database.o \ swad_banner.o swad_banner_database.o swad_box.o swad_browser.o \ swad_browser_database.o swad_building.o swad_building_database.o \ swad_button.o \ diff --git a/swad_API.c b/swad_API.c index f12492eca..c56a3ead2 100644 --- a/swad_API.c +++ b/swad_API.c @@ -103,9 +103,11 @@ cp -f /home/acanas/swad/swad/swad /var/www/cgi-bin/ #include "swad_account.h" #include "swad_API.h" +#include "swad_API_database.h" #include "swad_attendance_database.h" #include "swad_browser.h" #include "swad_browser_database.h" +#include "swad_course_database.h" #include "swad_database.h" #include "swad_error.h" #include "swad_forum.h" @@ -119,10 +121,12 @@ cp -f /home/acanas/swad/swad/swad /var/www/cgi-bin/ #include "swad_notice.h" #include "swad_notification.h" #include "swad_password.h" +#include "swad_plugin_database.h" #include "swad_question_database.h" #include "swad_role.h" #include "swad_room_database.h" #include "swad_search.h" +#include "swad_session_database.h" #include "swad_test_config.h" #include "swad_test_visibility.h" #include "swad_user.h" @@ -209,8 +213,6 @@ static const API_Role_t API_RolRole_to_SvcRole[Rol_NUM_ROLES] = [Rol_TCH] = API_ROLE_TEACHER, }; -#define API_BYTES_WS_KEY Cry_BYTES_ENCRYPTED_STR_SHA256_BASE64 - /*****************************************************************************/ /***************************** Private prototypes ****************************/ /*****************************************************************************/ @@ -221,16 +223,14 @@ static void API_FreeSoapContext (struct soap *soap); static int API_GetPlgCodFromAppKey (struct soap *soap, const char *appKey); static int API_CheckIdSession (struct soap *soap, - const char *IdSession); -static int API_CheckWSKey (char WSKey[API_BYTES_WS_KEY + 1]); + const char *IdSes); +static int API_CheckAPIKey (char APIKey[API_BYTES_KEY + 1]); static int API_CheckCourseAndGroupCodes (struct soap *soap, long CrsCod,long GrpCod); -static int API_GenerateNewWSKey (struct soap *soap, - long UsrCod, - char WSKey[API_BYTES_WS_KEY + 1]); -static int API_RemoveOldWSKeys (struct soap *soap); -static int API_GetCurrentDegCodFromCurrentCrsCod (void); +static int API_GenerateNewAPIKey (struct soap *soap, + long UsrCod, + char APIKey[API_BYTES_KEY + 1]); static bool API_GetSomeUsrDataFromUsrCod (struct UsrData *UsrDat,long CrsCod); static int API_CheckParamsNewAccount (char *NewNickWithArr, // Input @@ -364,13 +364,8 @@ static void API_FreeSoapContext (struct soap *soap) static int API_GetPlgCodFromAppKey (struct soap *soap, const char *appKey) { - /***** Get number of plugins with a IP address *****/ - Gbl.WebService.PlgCod = DB_QuerySELECTCode ("can not check application key", - "SELECT PlgCod" - " FROM plg_plugins" - " WHERE AppKey='%s'", - appKey); // Session found in table of sessions - if (Gbl.WebService.PlgCod < 0) + /***** Get plugin code from application key *****/ + if ((Gbl.WebService.PlgCod = Plg_DB_GetPlgCodFromAppKey (appKey)) <= 0) return soap_sender_fault (soap, "Unknown application key", "Unknown application"); @@ -394,25 +389,25 @@ const char *API_GetFunctionNameFromFunCod (long FunCod) /*****************************************************************************/ static int API_CheckIdSession (struct soap *soap, - const char *IdSession) + const char *IdSes) { const char *Ptr; unsigned i; /***** Check if pointer is NULL *****/ - if (IdSession == NULL) + if (IdSes == NULL) return soap_sender_fault (soap, "Bad session identifier", "Session identifier is a null pointer"); /***** Check length of session identifier *****/ - if (strlen (IdSession) != Cns_BYTES_SESSION_ID) + if (strlen (IdSes) != Cns_BYTES_SESSION_ID) return soap_sender_fault (soap, "Bad session identifier", "The length of the session identifier is wrong"); /***** Check if session identifier is in base64url *****/ - for (Ptr = IdSession; + for (Ptr = IdSes; *Ptr; Ptr++) { @@ -428,11 +423,7 @@ static int API_CheckIdSession (struct soap *soap, } /***** Query if session identifier already exists in database *****/ - if (DB_QueryCOUNT ("can not get session data", - "SELECT COUNT(*)" - " FROM ses_sessions" - " WHERE SessionId='%s'", - IdSession) != 1) + if (!Ses_DB_CheckIfSessionExists (IdSes)) return soap_receiver_fault (soap, "Bad session identifier", "Session identifier does not exist in database"); @@ -444,7 +435,7 @@ static int API_CheckIdSession (struct soap *soap, /************** Check if a web service key exists in database ****************/ /*****************************************************************************/ -static int API_CheckWSKey (char WSKey[API_BYTES_WS_KEY + 1]) +static int API_CheckAPIKey (char APIKey[API_BYTES_KEY + 1]) { MYSQL_RES *mysql_res; MYSQL_ROW row; @@ -455,12 +446,7 @@ static int API_CheckWSKey (char WSKey[API_BYTES_WS_KEY + 1]) Gbl.WebService.PlgCod = -1L; /***** Check that key does not exist in database *****/ - if (DB_QuerySELECT (&mysql_res,"can not get existence of key", - "SELECT UsrCod," // row[0] - "PlgCod" // row[1] - " FROM api_keys" - " WHERE WSKey='%s'", - WSKey)) // Session found in table of sessions + if (API_DB_GetDataFromAPIKey (&mysql_res,APIKey)) { row = mysql_fetch_row (mysql_res); @@ -489,31 +475,17 @@ static int API_CheckCourseAndGroupCodes (struct soap *soap, "Course code must be a integer greater than 0"); /***** Query if course code already exists in database *****/ - if (DB_QueryCOUNT ("can not get course", - "SELECT COUNT(*)" - " FROM crs_courses" - " WHERE CrsCod=%ld", - CrsCod) != 1) + if (!Crs_DB_CheckIfCrsCodExists (CrsCod)) return soap_sender_fault (soap, "Bad course code", "Course code does not exist in database"); /***** Course code exists in database, so check if group code exists in database and belongs to course *****/ - if (GrpCod > 0) // <=0 means "the whole course" - { - /***** Query if group code already exists in database *****/ - if (DB_QueryCOUNT ("can not get group", - "SELECT COUNT(*)" - " FROM grp_types," - "grp_groups" - " WHERE grp_types.CrsCod=%ld" - " AND grp_types.GrpTypCod=grp_groups.GrpTypCod" - " AND grp_groups.GrpCod=%ld", - CrsCod,GrpCod) != 1) + if (GrpCod > 0) // <= 0 means "the whole course" + if (!Grp_DB_CheckIfGrpBelongsToCrs (GrpCod,CrsCod)) return soap_sender_fault (soap, "Bad group code", "Group code does not exist in database or it's not a group of the specified course"); - } return SOAP_OK; } @@ -522,77 +494,24 @@ static int API_CheckCourseAndGroupCodes (struct soap *soap, /***** Generate a key used in subsequents calls to other web services ********/ /*****************************************************************************/ -static int API_GenerateNewWSKey (struct soap *soap, - long UsrCod, - char WSKey[API_BYTES_WS_KEY + 1]) +static int API_GenerateNewAPIKey (struct soap *soap, + long UsrCod, + char APIKey[API_BYTES_KEY + 1]) { - int ReturnCode; - /***** Remove expired web service keys *****/ - if ((ReturnCode = API_RemoveOldWSKeys (soap)) != SOAP_OK) - return ReturnCode; + API_DB_RemoveOldAPIKeys (); /***** Create a unique name for the key *****/ - Str_Copy (WSKey,Gbl.UniqueNameEncrypted,API_BYTES_WS_KEY); + Str_Copy (APIKey,Gbl.UniqueNameEncrypted,API_BYTES_KEY); /***** Check that key does not exist in database *****/ - if (DB_QueryEXISTS ("can not get existence of key", - "SELECT EXISTS" - "(SELECT *" - " FROM api_keys" - " WHERE WSKey='%s')", - WSKey)) + if (API_DB_CheckIfAPIKeyExists (APIKey)) return soap_receiver_fault (soap, "Error when generating key", "Generated key already existed in database"); /***** Insert key into database *****/ - DB_QueryINSERT ("can not insert new key", - "INSERT INTO api_keys" - " (WSKey,UsrCod,PlgCod,LastTime)" - " VALUES" - " ('%s',%ld,%ld,NOW())", - WSKey, - UsrCod, - Gbl.WebService.PlgCod); - - return SOAP_OK; - } - -/*****************************************************************************/ -/************************ Remove old web service keys ************************/ -/*****************************************************************************/ - -static int API_RemoveOldWSKeys (struct soap *soap) - { - char Query[512]; - - /***** Remove expired sessions *****/ - /* A session expire when last click (LastTime) is too old, - or when there was at least one refresh (navigator supports AJAX) and last refresh is too old (browser probably was closed) */ - sprintf (Query,"DELETE LOW_PRIORITY FROM api_keys" - " WHERE LastTimewsKey = soap_malloc (soap,API_BYTES_WS_KEY + 1); + createAccountOut->wsKey = soap_malloc (soap,API_BYTES_KEY + 1); /***** Default values returned on error *****/ createAccountOut->userCode = 0; // Undefined error @@ -744,7 +663,7 @@ int swad__createAccount (struct soap *soap, createAccountOut->userCode = Gbl.Usrs.Me.UsrDat.UsrCod; /***** Generate a key used in subsequents calls to other web services *****/ - return API_GenerateNewWSKey (soap, + return API_GenerateNewAPIKey (soap, (long) createAccountOut->userCode, createAccountOut->wsKey); } @@ -827,7 +746,7 @@ int swad__loginByUserPasswordKey (struct soap *soap, Gbl.WebService.Function = API_loginByUserPasswordKey; /***** Allocate space for strings *****/ - loginByUserPasswordKeyOut->wsKey = soap_malloc (soap,API_BYTES_WS_KEY + 1); + loginByUserPasswordKeyOut->wsKey = soap_malloc (soap,API_BYTES_KEY + 1); loginByUserPasswordKeyOut->userNickname = soap_malloc (soap,Nck_MAX_BYTES_NICK_WITHOUT_ARROBA + 1); loginByUserPasswordKeyOut->userID = soap_malloc (soap,ID_MAX_BYTES_USR_ID + 1); loginByUserPasswordKeyOut->userFirstname = soap_malloc (soap,Usr_MAX_BYTES_FIRSTNAME_OR_SURNAME + 1); @@ -946,7 +865,7 @@ int swad__loginByUserPasswordKey (struct soap *soap, API_RolRole_to_SvcRole[Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs]; /***** Generate a key used in subsequents calls to other web services *****/ - return API_GenerateNewWSKey (soap, + return API_GenerateNewAPIKey (soap, (long) loginByUserPasswordKeyOut->userCode, loginByUserPasswordKeyOut->wsKey); } @@ -986,7 +905,7 @@ int swad__loginBySessionKey (struct soap *soap, Gbl.WebService.Function = API_loginBySessionKey; /***** Allocate space for strings *****/ - loginBySessionKeyOut->wsKey = soap_malloc (soap,API_BYTES_WS_KEY + 1); + loginBySessionKeyOut->wsKey = soap_malloc (soap,API_BYTES_KEY + 1); loginBySessionKeyOut->userNickname = soap_malloc (soap,Nck_MAX_BYTES_NICK_WITHOUT_ARROBA + 1); loginBySessionKeyOut->userID = soap_malloc (soap,ID_MAX_BYTES_USR_ID + 1); loginBySessionKeyOut->userFirstname = soap_malloc (soap,Usr_MAX_BYTES_FIRSTNAME_OR_SURNAME + 1); @@ -1066,8 +985,7 @@ int swad__loginBySessionKey (struct soap *soap, DB_FreeMySQLResult (&mysql_res); /***** Get degree of current course *****/ - if ((ReturnCode = API_GetCurrentDegCodFromCurrentCrsCod ()) != SOAP_OK) - return ReturnCode; + Gbl.Hierarchy.Deg.DegCod = Crs_DB_GetCurrentDegCodFromCurrentCrsCod (); if (UsrFound) { @@ -1100,7 +1018,7 @@ int swad__loginBySessionKey (struct soap *soap, loginBySessionKeyOut->userRole = API_RolRole_to_SvcRole[Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs]; /***** Generate a key used in subsequents calls to other web services *****/ - return API_GenerateNewWSKey (soap, + return API_GenerateNewAPIKey (soap, (long) loginBySessionKeyOut->userCode, loginBySessionKeyOut->wsKey); } @@ -1134,8 +1052,8 @@ int swad__getAvailableRoles (struct soap *soap, /***** Default value returned on error *****/ getAvailableRolesOut->roles = 0; // error - /***** Check web service key *****/ - if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK) + /***** Check API (web service) key *****/ + if ((ReturnCode = API_CheckAPIKey (wsKey)) != SOAP_OK) return ReturnCode; if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database return soap_receiver_fault (soap, @@ -1258,7 +1176,7 @@ int swad__getCourses (struct soap *soap, Gbl.WebService.Function = API_getCourses; /***** Check web service key *****/ - if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK) + if ((ReturnCode = API_CheckAPIKey (wsKey)) != SOAP_OK) return ReturnCode; if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database return soap_receiver_fault (soap, @@ -1378,7 +1296,7 @@ int swad__getCourseInfo (struct soap *soap, Hie_InitHierarchy (); /***** Check web service key *****/ - if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK) + if ((ReturnCode = API_CheckAPIKey (wsKey)) != SOAP_OK) return ReturnCode; if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database return soap_receiver_fault (soap, @@ -1720,7 +1638,7 @@ int swad__getUsers (struct soap *soap, -1L; /***** Check web service key *****/ - if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK) + if ((ReturnCode = API_CheckAPIKey (wsKey)) != SOAP_OK) return ReturnCode; if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database return soap_receiver_fault (soap, @@ -1750,8 +1668,7 @@ int swad__getUsers (struct soap *soap, "Requester must belong to course"); /***** Get degree of current course *****/ - if ((ReturnCode = API_GetCurrentDegCodFromCurrentCrsCod ()) != SOAP_OK) // TODO: Is this necessary? - return ReturnCode; + Gbl.Hierarchy.Deg.DegCod = Crs_DB_GetCurrentDegCodFromCurrentCrsCod (); /***** Check requested users' role *****/ if (userRole != API_ROLE_STUDENT && // Students @@ -1801,7 +1718,7 @@ int swad__findUsers (struct soap *soap, -1L; /***** Check web service key *****/ - if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK) + if ((ReturnCode = API_CheckAPIKey (wsKey)) != SOAP_OK) return ReturnCode; if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database return soap_receiver_fault (soap, @@ -1833,11 +1750,8 @@ int swad__findUsers (struct soap *soap, "Requester must belong to course"); if (Gbl.Hierarchy.Level == HieLvl_CRS) - { /***** Get degree of current course *****/ - if ((ReturnCode = API_GetCurrentDegCodFromCurrentCrsCod ()) != SOAP_OK) // TODO: Is this necessary? - return ReturnCode; - } + Gbl.Hierarchy.Deg.DegCod = Crs_DB_GetCurrentDegCodFromCurrentCrsCod (); /***** Check requested users' role *****/ if (userRole < API_ROLE_UNKNOWN || @@ -1973,7 +1887,7 @@ int swad__getGroupTypes (struct soap *soap, Grp_OpenGroupsAutomatically (); /***** Check web service key *****/ - if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK) + if ((ReturnCode = API_CheckAPIKey (wsKey)) != SOAP_OK) return ReturnCode; if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database return soap_receiver_fault (soap, @@ -2092,7 +2006,7 @@ int swad__getGroups (struct soap *soap, Grp_OpenGroupsAutomatically (); /***** Check web service key *****/ - if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK) + if ((ReturnCode = API_CheckAPIKey (wsKey)) != SOAP_OK) return ReturnCode; if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database return soap_receiver_fault (soap, @@ -2230,7 +2144,7 @@ int swad__sendMyGroups (struct soap *soap, Gbl.Hierarchy.Crs.CrsCod = (long) courseCode; /***** Check web service key *****/ - if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK) + if ((ReturnCode = API_CheckAPIKey (wsKey)) != SOAP_OK) return ReturnCode; if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database return soap_receiver_fault (soap, @@ -2454,7 +2368,7 @@ int swad__getAttendanceEvents (struct soap *soap, Gbl.Hierarchy.Crs.CrsCod = (long) courseCode; /***** Check web service key *****/ - if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK) + if ((ReturnCode = API_CheckAPIKey (wsKey)) != SOAP_OK) return ReturnCode; if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database return soap_receiver_fault (soap, @@ -2671,7 +2585,7 @@ int swad__sendAttendanceEvent (struct soap *soap, Gbl.Hierarchy.Crs.CrsCod = (long) courseCode; /***** Check web service key *****/ - if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK) + if ((ReturnCode = API_CheckAPIKey (wsKey)) != SOAP_OK) return ReturnCode; if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database return soap_receiver_fault (soap, @@ -2774,7 +2688,7 @@ int swad__removeAttendanceEvent (struct soap *soap, removeAttendanceEventOut->attendanceEventCode = 0; /***** Check web service key *****/ - if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK) + if ((ReturnCode = API_CheckAPIKey (wsKey)) != SOAP_OK) return ReturnCode; if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database return soap_receiver_fault (soap, @@ -2886,7 +2800,7 @@ int swad__getAttendanceUsers (struct soap *soap, Gbl.WebService.Function = API_getAttendanceUsers; /***** Check web service key *****/ - if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK) + if ((ReturnCode = API_CheckAPIKey (wsKey)) != SOAP_OK) return ReturnCode; if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database return soap_receiver_fault (soap, @@ -3096,7 +3010,7 @@ int swad__sendAttendanceUsers (struct soap *soap, sendAttendanceUsersOut->numUsers = 0; /***** Check web service key *****/ - if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK) + if ((ReturnCode = API_CheckAPIKey (wsKey)) != SOAP_OK) return ReturnCode; if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database return soap_receiver_fault (soap, @@ -3243,7 +3157,7 @@ int swad__getNotifications (struct soap *soap, Gbl.WebService.Function = API_getNotifications; /***** Check web service key *****/ - if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK) + if ((ReturnCode = API_CheckAPIKey (wsKey)) != SOAP_OK) return ReturnCode; if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database return soap_receiver_fault (soap, @@ -3519,7 +3433,7 @@ int swad__markNotificationsAsRead (struct soap *soap, Gbl.WebService.Function = API_markNotificationsAsRead; /***** Check web service key *****/ - if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK) + if ((ReturnCode = API_CheckAPIKey (wsKey)) != SOAP_OK) return ReturnCode; if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database return soap_receiver_fault (soap, @@ -3595,7 +3509,7 @@ int swad__sendMessage (struct soap *soap, Gbl.WebService.Function = API_sendMessage; /***** Check web service key *****/ - if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK) + if ((ReturnCode = API_CheckAPIKey (wsKey)) != SOAP_OK) return ReturnCode; if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database return soap_receiver_fault (soap, @@ -3869,7 +3783,7 @@ int swad__sendNotice (struct soap *soap, Gbl.Hierarchy.Crs.CrsCod = (long) courseCode; /***** Check web service key *****/ - if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK) + if ((ReturnCode = API_CheckAPIKey (wsKey)) != SOAP_OK) return ReturnCode; if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database return soap_receiver_fault (soap, @@ -3891,8 +3805,7 @@ int swad__sendNotice (struct soap *soap, return ReturnCode; /***** Get degree of current course *****/ - if ((ReturnCode = API_GetCurrentDegCodFromCurrentCrsCod ()) != SOAP_OK) - return ReturnCode; + Gbl.Hierarchy.Deg.DegCod = Crs_DB_GetCurrentDegCodFromCurrentCrsCod (); /***** Check if I am a teacher *****/ if (Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs != Rol_TCH) @@ -3940,7 +3853,7 @@ int swad__getTestConfig (struct soap *soap, Gbl.Hierarchy.Crs.CrsCod = (long) courseCode; /***** Check web service key *****/ - if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK) + if ((ReturnCode = API_CheckAPIKey (wsKey)) != SOAP_OK) return ReturnCode; if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database return soap_receiver_fault (soap, @@ -3970,8 +3883,7 @@ int swad__getTestConfig (struct soap *soap, "Requester must belong to course"); /***** Get degree of current course *****/ - if ((ReturnCode = API_GetCurrentDegCodFromCurrentCrsCod ()) != SOAP_OK) - return ReturnCode; + Gbl.Hierarchy.Deg.DegCod = Crs_DB_GetCurrentDegCodFromCurrentCrsCod (); /***** Set default result to empty *****/ getTestConfigOut->numQuestions = @@ -4066,7 +3978,7 @@ int swad__getTests (struct soap *soap, Gbl.Hierarchy.Crs.CrsCod = (long) courseCode; /***** Check web service key *****/ - if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK) + if ((ReturnCode = API_CheckAPIKey (wsKey)) != SOAP_OK) return ReturnCode; if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database return soap_receiver_fault (soap, @@ -4096,8 +4008,7 @@ int swad__getTests (struct soap *soap, "Requester must belong to course"); /***** Get degree of current course *****/ - if ((ReturnCode = API_GetCurrentDegCodFromCurrentCrsCod ()) != SOAP_OK) - return ReturnCode; + Gbl.Hierarchy.Deg.DegCod = Crs_DB_GetCurrentDegCodFromCurrentCrsCod (); /***** Set default result to empty *****/ getTestsOut->tagsArray.__size = 0; @@ -4512,7 +4423,7 @@ int swad__getTrivialQuestion (struct soap *soap, Gbl.WebService.Function = API_getTrivialQuestion; /***** Check web service key *****/ - if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK) + if ((ReturnCode = API_CheckAPIKey (wsKey)) != SOAP_OK) return ReturnCode; if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database return soap_receiver_fault (soap, @@ -4748,7 +4659,7 @@ int swad__getGames (struct soap *soap, Gbl.Hierarchy.Crs.CrsCod = (long) courseCode; /***** Check web service key *****/ - if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK) + if ((ReturnCode = API_CheckAPIKey (wsKey)) != SOAP_OK) return ReturnCode; if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database return soap_receiver_fault (soap, @@ -4921,7 +4832,7 @@ int swad__getMatches (struct soap *soap, Gbl.Hierarchy.Crs.CrsCod = (long) courseCode; /***** Check web service key *****/ - if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK) + if ((ReturnCode = API_CheckAPIKey (wsKey)) != SOAP_OK) return ReturnCode; if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database return soap_receiver_fault (soap, @@ -5107,7 +5018,7 @@ int swad__getMatchStatus (struct soap *soap, getMatchStatusOut->answerIndex = -1; /***** Check web service key *****/ - if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK) + if ((ReturnCode = API_CheckAPIKey (wsKey)) != SOAP_OK) return ReturnCode; if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database return soap_receiver_fault (soap, @@ -5230,7 +5141,7 @@ int swad__answerMatchQuestion (struct soap *soap, answerMatchQuestionOut->matchCode = -1; /***** Check web service key *****/ - if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK) + if ((ReturnCode = API_CheckAPIKey (wsKey)) != SOAP_OK) return ReturnCode; if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database return soap_receiver_fault (soap, @@ -5358,7 +5269,7 @@ int swad__getDirectoryTree (struct soap *soap, Gbl.Crs.Grps.GrpCod = (long) groupCode; /***** Check web service key *****/ - if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK) + if ((ReturnCode = API_CheckAPIKey (wsKey)) != SOAP_OK) return ReturnCode; if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database return soap_receiver_fault (soap, @@ -5668,7 +5579,7 @@ int swad__getFile (struct soap *soap, getFileOut->publisherPhoto[0] = '\0'; /***** Check web service key *****/ - if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK) + if ((ReturnCode = API_CheckAPIKey (wsKey)) != SOAP_OK) return ReturnCode; if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database return soap_receiver_fault (soap, @@ -5817,7 +5728,7 @@ int swad__getMarks (struct soap *soap, getMarksOut->content = NULL; /***** Check web service key *****/ - if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK) + if ((ReturnCode = API_CheckAPIKey (wsKey)) != SOAP_OK) return ReturnCode; if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database return soap_receiver_fault (soap, @@ -5913,7 +5824,7 @@ int swad__getLocation (struct soap *soap, Gbl.WebService.Function = API_getLocation; /***** Check web service key *****/ - if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK) + if ((ReturnCode = API_CheckAPIKey (wsKey)) != SOAP_OK) return ReturnCode; if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database return soap_receiver_fault (soap, @@ -5992,7 +5903,7 @@ int swad__sendMyLocation (struct soap *soap, sendMyLocationOut->success = 0; // error /***** Check web service key *****/ - if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK) + if ((ReturnCode = API_CheckAPIKey (wsKey)) != SOAP_OK) return ReturnCode; if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database return soap_receiver_fault (soap, @@ -6044,7 +5955,7 @@ int swad__getLastLocation (struct soap *soap, Gbl.WebService.Function = API_getLastLocation; /***** Check web service key *****/ - if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK) + if ((ReturnCode = API_CheckAPIKey (wsKey)) != SOAP_OK) return ReturnCode; if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database return soap_receiver_fault (soap, diff --git a/swad_API.h b/swad_API.h index a52ec6d20..3a6fd4ec2 100644 --- a/swad_API.h +++ b/swad_API.h @@ -27,12 +27,16 @@ /********************************* Headers ***********************************/ /*****************************************************************************/ +#include "swad_cryptography.h" + /*****************************************************************************/ /***************************** Public constants ******************************/ /*****************************************************************************/ #define API_NUM_FUNCTIONS 35 +#define API_BYTES_KEY Cry_BYTES_ENCRYPTED_STR_SHA256_BASE64 + /*****************************************************************************/ /******************************* Public types ********************************/ /*****************************************************************************/ diff --git a/swad_API_database.c b/swad_API_database.c new file mode 100644 index 000000000..f772f3540 --- /dev/null +++ b/swad_API_database.c @@ -0,0 +1,143 @@ + + +// swad_API.c: SWAD web API provided to external plugins + +/* + 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 Public 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 . +*/ +/*****************************************************************************/ +/********************************* Headers ***********************************/ +/*****************************************************************************/ + +// #include // For scandir, etc. +// #include // For PATH_MAX +// #include // For NULL +// #include +// #include +// #include // For lstat + +// #include "soap/soapH.h" // gSOAP header +// #include "soap/swad.nsmap" // Namespaces map used + +// #include "swad_account.h" +#include "swad_API_database.h" +// #include "swad_attendance_database.h" +// #include "swad_browser.h" +// #include "swad_browser_database.h" +#include "swad_config.h" +#include "swad_database.h" +// #include "swad_error.h" +// #include "swad_forum.h" +// #include "swad_global.h" +// #include "swad_group_database.h" +// #include "swad_hierarchy.h" +// #include "swad_hierarchy_level.h" +// #include "swad_ID.h" +// #include "swad_match.h" +// #include "swad_nickname_database.h" +// #include "swad_notice.h" +// #include "swad_notification.h" +// #include "swad_password.h" +// #include "swad_plugin_database.h" +// #include "swad_question_database.h" +// #include "swad_role.h" +// #include "swad_room_database.h" +// #include "swad_search.h" +// #include "swad_session_database.h" +// #include "swad_test_config.h" +// #include "swad_test_visibility.h" +// #include "swad_user.h" +// #include "swad_user_database.h" +// #include "swad_xml.h" + +/*****************************************************************************/ +/************** External global variables from others modules ****************/ +/*****************************************************************************/ + +// extern struct Globals Gbl; + +/*****************************************************************************/ +/***************************** Private constants *****************************/ +/*****************************************************************************/ + +/*****************************************************************************/ +/***************************** Private prototypes ****************************/ +/*****************************************************************************/ + +/*****************************************************************************/ +/****************************** Insert API key *******************************/ +/*****************************************************************************/ + +void API_DB_CreateAPIKey (char APIKey[API_BYTES_KEY + 1],long UsrCod,long PlgCod) + { + DB_QueryINSERT ("can not insert new key", + "INSERT INTO api_keys" + " (WSKey,UsrCod,PlgCod,LastTime)" + " VALUES" + " ('%s',%ld,%ld,NOW())", + APIKey, + UsrCod, + PlgCod); + } + +/*****************************************************************************/ +/********************** Check API key exists in database *********************/ +/*****************************************************************************/ + +bool API_DB_CheckIfAPIKeyExists (char APIKey[API_BYTES_KEY + 1]) + { + return + DB_QueryEXISTS ("can not get existence of key", + "SELECT EXISTS" + "(SELECT *" + " FROM api_keys" + " WHERE WSKey='%s')", + APIKey); + } + +/*****************************************************************************/ +/************************** Get data from an API key *************************/ +/*****************************************************************************/ + +unsigned API_DB_GetDataFromAPIKey (MYSQL_RES **mysql_res,char APIKey[API_BYTES_KEY + 1]) + { + return (unsigned) + DB_QuerySELECT (mysql_res,"can not data from API key", + "SELECT UsrCod," // row[0] + "PlgCod" // row[1] + " FROM api_keys" + " WHERE WSKey='%s'", + APIKey); + } + +/*****************************************************************************/ +/***************************** Remove old API keys ***************************/ +/*****************************************************************************/ + +void API_DB_RemoveOldAPIKeys (void) + { + /***** Remove expired API keys *****/ + /* A session expire when last click (LastTime) is too old */ + DB_QueryDELETE ("can not remove old API keys", + "DELETE LOW_PRIORITY FROM api_keys" + " WHERE LastTime. +*/ +/*****************************************************************************/ +/********************************* Headers ***********************************/ +/*****************************************************************************/ + +#include // To access MySQL databases + +#include "swad_API.h" + +/*****************************************************************************/ +/***************************** Public constants ******************************/ +/*****************************************************************************/ + +/*****************************************************************************/ +/******************************* Public types ********************************/ +/*****************************************************************************/ + +/*****************************************************************************/ +/***************************** Public prototypes *****************************/ +/*****************************************************************************/ + +void API_DB_CreateAPIKey (char APIKey[API_BYTES_KEY + 1],long UsrCod,long PlgCod); + +bool API_DB_CheckIfAPIKeyExists (char APIKey[API_BYTES_KEY + 1]); +unsigned API_DB_GetDataFromAPIKey (MYSQL_RES **mysql_res,char APIKey[API_BYTES_KEY + 1]); + +void API_DB_RemoveOldAPIKeys (void); + +#endif diff --git a/swad_changelog.h b/swad_changelog.h index 8cd532b56..a16793ff4 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.53.1 (2021-11-07)" +#define Log_PLATFORM_VERSION "SWAD 21.54 (2021-11-07)" #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.54: Nov 07, 2021 New module swad_API_database for database queries related to API. (322001 lines) Version 21.53.1: Nov 07, 2021 Queries moved to module swad_room_database. (321879 lines) 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) diff --git a/swad_config.h b/swad_config.h index cdbe6f622..626fb3689 100644 --- a/swad_config.h +++ b/swad_config.h @@ -500,7 +500,7 @@ #define Cfg_TIME_TO_CHANGE_BANNER ((time_t)( 2UL * 60UL)) // After these seconds, change banner #define Cfg_NUMBER_OF_BANNERS 1 // Number of banners to show simultaneously -#define Cfg_TIME_TO_DELETE_WEB_SERVICE_KEY ((time_t)( 7UL * 24UL * 60UL * 60UL)) // After these seconds, a web service key is removed +#define Cfg_TIME_TO_DELETE_API_KEY ((time_t)( 7UL * 24UL * 60UL * 60UL)) // After these seconds, a web service key is removed #define Cfg_TIME_TO_DELETE_HTML_OUTPUT ((time_t)( 30UL * 60UL)) // Remove the HTML output files older than these seconds diff --git a/swad_course_database.c b/swad_course_database.c index 82e218c90..9a7f80c87 100644 --- a/swad_course_database.c +++ b/swad_course_database.c @@ -158,6 +158,19 @@ unsigned Crs_DB_GetDataOfCourseByCod (MYSQL_RES **mysql_res,long CrsCod) CrsCod); } +/*****************************************************************************/ +/********************* Get degree code from course code **********************/ +/*****************************************************************************/ + +long Crs_DB_GetCurrentDegCodFromCurrentCrsCod (void) + { + return DB_QuerySELECTCode ("can not get the degree of a course", + "SELECT DegCod" + " FROM crs_courses" + " WHERE CrsCod=%ld", + Gbl.Hierarchy.Crs.CrsCod); + } + /*****************************************************************************/ /******* Get the short names of degree and course from a course code *********/ /*****************************************************************************/ @@ -195,6 +208,21 @@ void Crs_DB_GetShortNamesByCod (long CrsCod, DB_FreeMySQLResult (&mysql_res); } +/*****************************************************************************/ +/************** Check if course code exists in existing courses **************/ +/*****************************************************************************/ + +bool Crs_DB_CheckIfCrsCodExists (long CrsCod) + { + return + DB_QueryEXISTS ("can not check if a course already existed", + "SELECT EXISTS" + "(SELECT *" + " FROM crs_courses" + " WHERE CrsCod=%ld)", + CrsCod); + } + /*****************************************************************************/ /********** Check if the name of course exists in existing courses ***********/ /*****************************************************************************/ diff --git a/swad_course_database.h b/swad_course_database.h index f0ebb22a8..8e07d06c4 100644 --- a/swad_course_database.h +++ b/swad_course_database.h @@ -49,9 +49,11 @@ unsigned Crs_DB_GetCrssInDeg (MYSQL_RES **mysql_res,long DegCod); unsigned Crs_DB_GetCrssInCurrentDegBasic (MYSQL_RES **mysql_res); unsigned Crs_DB_GetCrssInCurrentDegFull (MYSQL_RES **mysql_res); unsigned Crs_DB_GetDataOfCourseByCod (MYSQL_RES **mysql_res,long CrsCod); +long Crs_DB_GetCurrentDegCodFromCurrentCrsCod (void); void Crs_DB_GetShortNamesByCod (long CrsCod, char CrsShortName[Cns_HIERARCHY_MAX_BYTES_SHRT_NAME + 1], char DegShortName[Cns_HIERARCHY_MAX_BYTES_SHRT_NAME + 1]); +bool Crs_DB_CheckIfCrsCodExists (long CrsCod); bool Crs_DB_CheckIfCrsNameExistsInYearOfDeg (const char *FieldName,const char *Name,long CrsCod, long DegCod,unsigned Year); unsigned Crs_DB_GetCrssOfAUsr (MYSQL_RES **mysql_res,long UsrCod,Rol_Role_t Role); diff --git a/swad_plugin_database.c b/swad_plugin_database.c index ac929ff94..924c81e07 100644 --- a/swad_plugin_database.c +++ b/swad_plugin_database.c @@ -175,6 +175,7 @@ unsigned Plg_DB_GetListPlugins (MYSQL_RES **mysql_res) " FROM plg_plugins" " ORDER BY Name"); } + /*****************************************************************************/ /*************************** Get data of a plugin ****************************/ /*****************************************************************************/ @@ -194,6 +195,20 @@ unsigned Plg_DB_GetDataOfPluginByCod (MYSQL_RES **mysql_res,long PlgCod) PlgCod); } +/*****************************************************************************/ +/****** Check if the application key of the requester of a web service *******/ +/****** is one of the application keys allowed in the plugins *******/ +/*****************************************************************************/ + +long Plg_DB_GetPlgCodFromAppKey (const char *AppKey) + { + return DB_QuerySELECTCode ("can not check application key", + "SELECT PlgCod" + " FROM plg_plugins" + " WHERE AppKey='%s'", + AppKey); + } + /*****************************************************************************/ /******************** Check if the name of plugin exists *********************/ /*****************************************************************************/ diff --git a/swad_plugin_database.h b/swad_plugin_database.h index 6973f6e12..02b3648dc 100644 --- a/swad_plugin_database.h +++ b/swad_plugin_database.h @@ -59,6 +59,7 @@ void Plg_DB_ChangeIP (long PlgCod, unsigned Plg_DB_GetListPlugins (MYSQL_RES **mysql_res); unsigned Plg_DB_GetDataOfPluginByCod (MYSQL_RES **mysql_res,long PlgCod); +long Plg_DB_GetPlgCodFromAppKey (const char *AppKey); bool Plg_DB_CheckIfPluginNameExists (const char *Name,long PlgCod); void Plg_DB_RemovePlugin (long PlgCod);