Version 15.225.12

This commit is contained in:
Antonio Cañas Vargas 2016-06-16 14:34:17 +02:00
parent 0d64b8b337
commit 8dcb6aed49
9 changed files with 297 additions and 181 deletions

View File

@ -32,7 +32,7 @@ OBJS = swad_account.o swad_action.o swad_announcement.o swad_assignment.o \
swad_calendar.o swad_centre.o swad_chat.o swad_config.o \
swad_connected.o swad_country.o swad_course.o swad_cryptography.o \
swad_database.o swad_date.o swad_degree.o swad_degree_type.o \
swad_department.o \
swad_department.o swad_duplicate.o \
swad_enrollment.o swad_exam.o \
swad_file.o swad_file_browser.o swad_follow.o swad_forum.o \
swad_global.o swad_group.o \

View File

@ -746,7 +746,7 @@ void Acc_CompletelyEliminateAccount (struct UsrData *UsrDat,
DB_QueryDELETE (Query,"can not remove user's requests for inscription");
/***** Remove user from possible duplicate users *****/
Usr_RemoveUsrFromDuplicated (UsrDat->UsrCod);
Dup_RemoveUsrFromDuplicated (UsrDat->UsrCod);
/***** Remove user from the table of courses and users *****/
sprintf (Query,"DELETE FROM crs_usr"

View File

@ -2451,7 +2451,7 @@ struct Act_Actions Act_Actions[Act_NUM_ACTIONS] =
/* ActReqRemOldUsr */{ 590,-1,TabUsr,ActLstOth ,0x100,0x100,0x100,Act_CONTENT_NORM,Act_MAIN_WINDOW,NULL ,Enr_AskRemoveOldUsrs ,NULL},
/* ActRemOldUsr */{ 773,-1,TabUsr,ActLstOth ,0x100,0x100,0x100,Act_CONTENT_NORM,Act_MAIN_WINDOW,NULL ,Enr_RemoveOldUsrs ,NULL},
/* ActLstDupUsr */{1578,-1,TabUsr,ActLstOth ,0x100,0x100,0x100,Act_CONTENT_NORM,Act_MAIN_WINDOW,NULL ,Usr_ListDuplicateUsrs ,NULL},
/* ActLstDupUsr */{1578,-1,TabUsr,ActLstOth ,0x100,0x100,0x100,Act_CONTENT_NORM,Act_MAIN_WINDOW,NULL ,Dup_ListDuplicateUsrs ,NULL},
/* ActLstClk */{ 989,-1,TabUsr,ActLstCon ,0x1FE,0x1FE,0x1FE,Act_CONTENT_NORM,Act_MAIN_WINDOW,NULL ,Con_ShowLastClicks ,NULL},

View File

@ -128,13 +128,14 @@
/****************************** Public constants *****************************/
/*****************************************************************************/
#define Log_PLATFORM_VERSION "SWAD 15.225.11 (2016-06-16)"
#define Log_PLATFORM_VERSION "SWAD 15.225.12 (2016-06-16)"
#define CSS_FILE "swad15.225.11.css"
#define JS_FILE "swad15.216.js"
// Number of lines (includes comments but not blank lines) has been got with the following command:
// nl swad*.c swad*.h css/swad*.css py/swad*.py js/swad*.js soap/swad*.h sql/swad*.sql | tail -1
/*
Version 15.225.12:Jun 16, 2016 New module swad_duplicate for possible duplicate users. (202758 lines)
Version 15.225.11:Jun 16, 2016 Listing possible duplicate users. (202667 lines)
Version 15.225.10:Jun 15, 2016 Listing possible duplicate users. (202626 lines)
Version 15.225.9: Jun 15, 2016 Code refactoring in list of students and teachers. (202636 lines)

236
swad_duplicate.c Normal file
View File

@ -0,0 +1,236 @@
// swad_duplicate.c: duplicate users
/*
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-2016 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 <ctype.h> // For isalnum, isdigit, etc.
// #include <limits.h> // For maximum values
// #include <linux/limits.h> // For PATH_MAX
// #include <linux/stddef.h> // For NULL
// #include <stdlib.h> // For exit, system, malloc, free, rand, etc.
// #include <string.h> // For string functions
// #include <sys/wait.h> // For the macro WEXITSTATUS
// #include <unistd.h> // For access, lstat, getpid, chdir, symlink, unlink
#include "swad_database.h"
#include "swad_global.h"
#include "swad_layout.h"
#include "swad_role.h"
#include "swad_user.h"
/*****************************************************************************/
/****************************** Public constants *****************************/
/*****************************************************************************/
/*****************************************************************************/
/***************************** Private constants *****************************/
/*****************************************************************************/
/*****************************************************************************/
/****************************** Internal types *******************************/
/*****************************************************************************/
/*****************************************************************************/
/************** External global variables from others modules ****************/
/*****************************************************************************/
extern struct Globals Gbl;
/*****************************************************************************/
/************************* Internal global variables *************************/
/*****************************************************************************/
/*****************************************************************************/
/***************************** Private prototypes ****************************/
/*****************************************************************************/
/*****************************************************************************/
/******************** Report a user as possible duplicate ********************/
/*****************************************************************************/
void Dup_ReportUsrAsPossibleDuplicate (void)
{
extern const char *Txt_Thank_you_for_reporting_a_possible_duplicate_user;
extern const char *Txt_User_not_found_or_you_do_not_have_permission_;
char Query[256];
bool ItsMe;
/***** Get user to be reported as possible duplicate *****/
if (Usr_GetParamOtherUsrCodEncryptedAndGetUsrData ())
{
/* Check if it's allowed to me to report users as possible duplicatedr */
ItsMe = (Gbl.Usrs.Me.UsrDat.UsrCod == Gbl.Usrs.Other.UsrDat.UsrCod);
if (!ItsMe && Gbl.Usrs.Me.LoggedRole >= Rol_TEACHER)
{
/***** Insert possible duplicate into database *****/
sprintf (Query,"REPLACE INTO usr_duplicated (UsrCod,InformerCod,InformTime)"
" VALUES ('%ld','%ld',NOW())",
Gbl.Usrs.Other.UsrDat.UsrCod,
Gbl.Usrs.Me.UsrDat.UsrCod);
DB_QueryINSERT (Query,"can not report duplicate");
/***** Show feedback message *****/
Lay_ShowAlert (Lay_SUCCESS,Txt_Thank_you_for_reporting_a_possible_duplicate_user);
}
else
Lay_ShowAlert (Lay_WARNING,Txt_User_not_found_or_you_do_not_have_permission_);
}
else
Lay_ShowAlert (Lay_WARNING,Txt_User_not_found_or_you_do_not_have_permission_);
}
/*****************************************************************************/
/************ Put a link (form) to list possible duplicate users *************/
/*****************************************************************************/
void Dup_PutLinkToListDupUsrs (void)
{
extern const char *Txt_Duplicate_USERS;
/***** Put form to remove old users *****/
Lay_PutContextualLink (ActLstDupUsr,NULL,"usrs64x64.gif",
Txt_Duplicate_USERS,Txt_Duplicate_USERS);
}
/*****************************************************************************/
/*********************** List possible duplicate users ***********************/
/*****************************************************************************/
void Dup_ListDuplicateUsrs (void)
{
extern const char *Usr_UsrDatMainFieldNames[Usr_NUM_MAIN_FIELDS_DATA_USR];
extern const char *Txt_Possibly_duplicate_users;
extern const char *Txt_Informants;
extern const char *Txt_No_users_found[Rol_NUM_ROLES];
char Query[1024];
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned NumCol;
unsigned NumUsrs;
unsigned NumUsr;
struct UsrData UsrDat;
unsigned NumInformants;
/***** Start frame with list of possible duplicate users *****/
Lay_StartRoundFrame (NULL,Txt_Possibly_duplicate_users,NULL);
/***** Build query *****/
sprintf (Query,"SELECT UsrCod,COUNT(*) AS N,MIN(UNIX_TIMESTAMP(InformTime)) AS T"
" FROM usr_duplicated"
" GROUP BY UsrCod"
" ORDER BY N DESC,T DESC");
NumUsrs = (unsigned) DB_QuerySELECT (Query,&mysql_res,"can not get requests for enrollment");
/***** List possible duplicated users *****/
if (NumUsrs)
{
/***** Initialize field names *****/
Usr_SetUsrDatMainFieldNames ();
/***** Initialize structure with user's data *****/
Usr_UsrDataConstructor (&UsrDat);
/***** Start table *****/
fprintf (Gbl.F.Out,"<table class=\"CELLS_PAD_2\">");
/***** Heading row with column names *****/
/* Start row */
fprintf (Gbl.F.Out,"<tr>");
for (NumCol = 0;
NumCol < Usr_NUM_MAIN_FIELDS_DATA_USR;
NumCol++)
fprintf (Gbl.F.Out,"<th class=\"LEFT_MIDDLE LIGHT_BLUE\">"
"%s&nbsp;"
"</th>",
Usr_UsrDatMainFieldNames[NumCol]);
/* End row */
fprintf (Gbl.F.Out,"</tr>");
/***** List users *****/
for (NumUsr = 0, Gbl.RowEvenOdd = 0;
NumUsr < NumUsrs;
NumUsr++)
{
row = mysql_fetch_row (mysql_res);
/* Get user code (row[0]) */
UsrDat.UsrCod = Str_ConvertStrCodToLongCod (row[0]);
if (Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&UsrDat))
{
UsrDat.Accepted = false; // TODO: Get this from database
/* Write data of this user */
Usr_WriteRowUsrMainData (NumUsrs - NumUsr,&UsrDat,false);
/* Write number of informants (row[1]) if greater than 1 */
if (sscanf (row[1],"%u",&NumInformants) != 1)
Lay_ShowErrorAndExit ("Wrong number of informers.");
if (NumInformants > 1)
fprintf (Gbl.F.Out,"<tr>"
"<td colspan=\"2\"></td>"
"<td colspan=\"%u\" class=\"DAT\">%s: %u</td>"
"</tr>",
Usr_NUM_MAIN_FIELDS_DATA_USR-2,
Txt_Informants,
NumInformants);
/* Write all the courses this user belongs to */
Crs_GetAndWriteCrssOfAUsr (&UsrDat,Rol_TEACHER);
Crs_GetAndWriteCrssOfAUsr (&UsrDat,Rol_STUDENT);
Gbl.RowEvenOdd = 1 - Gbl.RowEvenOdd;
}
else // User does not exists ==>
// remove user from table of possible duplicate users
Dup_RemoveUsrFromDuplicated (UsrDat.UsrCod);
}
/***** End table *****/
fprintf (Gbl.F.Out,"</table>");
/***** Free memory used for user's data *****/
Usr_UsrDataDestructor (&UsrDat);
}
else // There are no users
Lay_ShowAlert (Lay_INFO,Txt_No_users_found[Rol_UNKNOWN]);
/***** End frame *****/
Lay_EndRoundFrame ();
}
/*****************************************************************************/
/********************* Remove a request for enrollment ***********************/
/*****************************************************************************/
void Dup_RemoveUsrFromDuplicated (long UsrCod)
{
char Query[128];
/***** Remove enrollment request *****/
sprintf (Query,"DELETE FROM usr_duplicated WHERE UsrCod='%ld'",
UsrCod);
DB_QueryDELETE (Query,"can not remove a user from possible duplicates");
}

47
swad_duplicate.h Normal file
View File

@ -0,0 +1,47 @@
// swad_duplicate.h: duplicate users
#ifndef _SWAD_DUP
#define _SWAD_DUP
/*
SWAD (Shared Workspace At a Distance in Spanish),
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-2016 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 <http://www.gnu.org/licenses/>.
*/
/*****************************************************************************/
/********************************** Headers **********************************/
/*****************************************************************************/
/*****************************************************************************/
/****************************** Public constants *****************************/
/*****************************************************************************/
/*****************************************************************************/
/******************************** Public types *******************************/
/*****************************************************************************/
/*****************************************************************************/
/****************************** Public prototypes ****************************/
/*****************************************************************************/
void Dup_ReportUsrAsPossibleDuplicate (void);
void Dup_PutLinkToListDupUsrs (void);
void Dup_ListDuplicateUsrs (void);
void Dup_RemoveUsrFromDuplicated (long UsrCod);
#endif

View File

@ -3750,7 +3750,7 @@ void Enr_ModifyUsr (void)
break;
case Enr_REPORT_USR_AS_POSSIBLE_DUPLICATE:
if (!ItsMe && Gbl.Usrs.Me.LoggedRole >= Rol_TEACHER)
Usr_ReportUsrAsPossibleDuplicate ();
Dup_ReportUsrAsPossibleDuplicate ();
else
Error = true;
break;

View File

@ -157,7 +157,6 @@ static Usr_Sex_t Usr_GetSexOfUsrsLst (struct ListUsers *LstUsrs);
static void Usr_PutCheckboxToSelectUser (struct UsrData *UsrDat,bool UsrIsTheMsgSender);
static void Usr_PutCheckboxListWithPhotos (void);
static void Usr_SetUsrDatMainFieldNames (void);
static void Usr_ListMainDataGsts (bool PutCheckBoxToSelectUsr);
static void Usr_ListMainDataStds (bool PutCheckBoxToSelectUsr);
static void Usr_ListMainDataTchs (bool PutCheckBoxToSelectUsr);
@ -5072,7 +5071,7 @@ static void Usr_PutCheckboxListWithPhotos (void)
/*********************** Set field names of user's data **********************/
/*****************************************************************************/
static void Usr_SetUsrDatMainFieldNames (void)
void Usr_SetUsrDatMainFieldNames (void)
{
extern const char *Txt_No_INDEX;
extern const char *Txt_Photo;
@ -5937,7 +5936,7 @@ void Usr_ListDataAdms (void)
Enr_PutLinkToAdminOneUsr (ActReqMdfOneOth);
/* Put link to list possible duplicate users */
Usr_PutLinkToListDupUsrs ();
Dup_PutLinkToListDupUsrs ();
/* Put link to remove old users */
Enr_PutLinkToRemOldUsrs ();
@ -7686,172 +7685,3 @@ void Usr_RemoveUsrFromUsrBanned (long UsrCod)
UsrCod);
DB_QueryDELETE (Query,"can not remove user from users banned");
}
/*****************************************************************************/
/******************** Report a user as possible duplicate ********************/
/*****************************************************************************/
void Usr_ReportUsrAsPossibleDuplicate (void)
{
extern const char *Txt_Thank_you_for_reporting_a_possible_duplicate_user;
extern const char *Txt_User_not_found_or_you_do_not_have_permission_;
char Query[256];
bool ItsMe;
/***** Get user to be reported as possible duplicate *****/
if (Usr_GetParamOtherUsrCodEncryptedAndGetUsrData ())
{
/* Check if it's allowed to me to report users as possible duplicatedr */
ItsMe = (Gbl.Usrs.Me.UsrDat.UsrCod == Gbl.Usrs.Other.UsrDat.UsrCod);
if (!ItsMe && Gbl.Usrs.Me.LoggedRole >= Rol_TEACHER)
{
/***** Insert possible duplicate into database *****/
sprintf (Query,"REPLACE INTO usr_duplicated (UsrCod,InformerCod,InformTime)"
" VALUES ('%ld','%ld',NOW())",
Gbl.Usrs.Other.UsrDat.UsrCod,
Gbl.Usrs.Me.UsrDat.UsrCod);
DB_QueryINSERT (Query,"can not report duplicate");
/***** Show feedback message *****/
Lay_ShowAlert (Lay_SUCCESS,Txt_Thank_you_for_reporting_a_possible_duplicate_user);
}
else
Lay_ShowAlert (Lay_WARNING,Txt_User_not_found_or_you_do_not_have_permission_);
}
else
Lay_ShowAlert (Lay_WARNING,Txt_User_not_found_or_you_do_not_have_permission_);
}
/*****************************************************************************/
/************ Put a link (form) to list possible duplicate users *************/
/*****************************************************************************/
void Usr_PutLinkToListDupUsrs (void)
{
extern const char *Txt_Duplicate_USERS;
/***** Put form to remove old users *****/
Lay_PutContextualLink (ActLstDupUsr,NULL,"usrs64x64.gif",
Txt_Duplicate_USERS,Txt_Duplicate_USERS);
}
/*****************************************************************************/
/*********************** List possible duplicate users ***********************/
/*****************************************************************************/
void Usr_ListDuplicateUsrs (void)
{
extern const char *Txt_Possibly_duplicate_users;
extern const char *Txt_User[Usr_NUM_SEXS];
extern const char *Txt_Informants;
extern const char *Txt_No_users_found[Rol_NUM_ROLES];
char Query[1024];
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned NumCol;
unsigned NumUsrs;
unsigned NumUsr;
struct UsrData UsrDat;
unsigned NumInformants;
/***** Start frame with list of possible duplicate users *****/
Lay_StartRoundFrame (NULL,Txt_Possibly_duplicate_users,NULL);
/***** Build query *****/
sprintf (Query,"SELECT UsrCod,COUNT(*) AS N,MIN(UNIX_TIMESTAMP(InformTime)) AS T"
" FROM usr_duplicated"
" GROUP BY UsrCod"
" ORDER BY N DESC,T DESC");
NumUsrs = (unsigned) DB_QuerySELECT (Query,&mysql_res,"can not get requests for enrollment");
/***** List possible duplicated users *****/
if (NumUsrs)
{
/***** Initialize field names *****/
Usr_SetUsrDatMainFieldNames ();
/***** Initialize structure with user's data *****/
Usr_UsrDataConstructor (&UsrDat);
/***** Start table *****/
fprintf (Gbl.F.Out,"<table class=\"CELLS_PAD_2\">");
/***** Heading row with column names *****/
/* Start row */
fprintf (Gbl.F.Out,"<tr>");
for (NumCol = 0;
NumCol < Usr_NUM_MAIN_FIELDS_DATA_USR;
NumCol++)
fprintf (Gbl.F.Out,"<th class=\"LEFT_MIDDLE LIGHT_BLUE\">"
"%s&nbsp;"
"</th>",
Usr_UsrDatMainFieldNames[NumCol]);
/* End row */
fprintf (Gbl.F.Out,"</tr>");
/***** List users *****/
for (NumUsr = 0, Gbl.RowEvenOdd = 0;
NumUsr < NumUsrs;
NumUsr++)
{
row = mysql_fetch_row (mysql_res);
/* Get user code (row[0]) */
UsrDat.UsrCod = Str_ConvertStrCodToLongCod (row[0]);
if (Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&UsrDat))
{
UsrDat.Accepted = false; // TODO: Get this from database
/* Write data of this user */
Usr_WriteRowUsrMainData (NumUsrs - NumUsr,&UsrDat,false);
/* Write number of informants (row[1]) if greater than 1 */
if (sscanf (row[1],"%u",&NumInformants) != 1)
Lay_ShowErrorAndExit ("Wrong number of informers.");
if (NumInformants > 1)
fprintf (Gbl.F.Out,"<tr>"
"<td colspan=\"2\"></td>"
"<td colspan=\"%u\" class=\"DAT\">%s: %u</td>"
"</tr>",
Usr_NUM_MAIN_FIELDS_DATA_USR-2,
Txt_Informants,
NumInformants);
/* Write all the courses this user belongs to */
Crs_GetAndWriteCrssOfAUsr (&UsrDat,Rol_TEACHER);
Crs_GetAndWriteCrssOfAUsr (&UsrDat,Rol_STUDENT);
Gbl.RowEvenOdd = 1 - Gbl.RowEvenOdd;
}
else // User does not exists ==>
// remove user from table of possible duplicate users
Usr_RemoveUsrFromDuplicated (UsrDat.UsrCod);
}
/***** End table *****/
fprintf (Gbl.F.Out,"</table>");
/***** Free memory used for user's data *****/
Usr_UsrDataDestructor (&UsrDat);
}
else // There are no users
Lay_ShowAlert (Lay_INFO,Txt_No_users_found[Rol_UNKNOWN]);
/***** End frame *****/
Lay_EndRoundFrame ();
}
/*****************************************************************************/
/********************* Remove a request for enrollment ***********************/
/*****************************************************************************/
void Usr_RemoveUsrFromDuplicated (long UsrCod)
{
char Query[128];
/***** Remove enrollment request *****/
sprintf (Query,"DELETE FROM usr_duplicated WHERE UsrCod='%ld'",
UsrCod);
DB_QueryDELETE (Query,"can not remove a user from possible duplicates");
}

View File

@ -315,6 +315,8 @@ void Usr_FreeListOtherRecipients (void);
void Usr_ShowFormsToSelectUsrListType (Act_Action_t NextAction);
void Usr_PutCheckboxToSelectAllTheUsers (Rol_Role_t Role);
unsigned Usr_GetColumnsForSelectUsrs (void);
void Usr_SetUsrDatMainFieldNames (void);
void Usr_PutExtraParamsUsrList (Act_Action_t NextAction);
void Usr_ListUsersToSelect (Rol_Role_t Role);
@ -350,9 +352,9 @@ void Usr_GetAndShowNumUsrsInPlatform (Rol_Role_t Role);
bool Usr_CheckIfUsrBanned (long UsrCod);
void Usr_RemoveUsrFromUsrBanned (long UsrCod);
void Usr_ReportUsrAsPossibleDuplicate (void);
void Usr_PutLinkToListDupUsrs (void);
void Usr_ListDuplicateUsrs (void);
void Usr_RemoveUsrFromDuplicated (long UsrCod);
void Dup_ReportUsrAsPossibleDuplicate (void);
void Dup_PutLinkToListDupUsrs (void);
void Dup_ListDuplicateUsrs (void);
void Dup_RemoveUsrFromDuplicated (long UsrCod);
#endif