o365consumer.cs
1 using System;
2 using System.Collections.Generic;
3 using Sage.DriveManagement.Interfaces;
4 using sage.ew.usuario;
5 using Sage.O365Management.Classes;
6 using System.Web.Script.Serialization;
7 using System.Data;
8 using Sage.O365Management.Classes.OData;
9 using sage.ew.db;
10 using sage.ew.functions.Clases;
11 
12 namespace sage.ew.o365
13 {
17  public abstract class o365consumer
18  {
19  #region User calendar Data
20 
21 
25  internal static string _Sage50User
26  {
27  get { return _cSage50User; }
28  set
29  {
30  //if user is diferent from stored, Logout() required
31  if (!String.IsNullOrWhiteSpace(_cSage50User) && _cSage50User != value && _O365ManagementUser != null)
32  {
33  _O365ManagementUser.Logout();
34  _O365ManagementUser.RefreshToken = "";
35  }
36  _cSage50User = value;
37  }
38  }
39  private static string _cSage50User = "";
40 
44  public static string _ClientId
45  {
46  get
47  {
48  return Usuario._This._ClientId;
49  }
50  set
51  {
52  Usuario._This._ClientId = value;
53  }
54  }
55 
59  public static string _ServiceResourceIds
60  {
61  get
62  {
64  }
65  set
66  {
68  }
69  }
70 
74  public static string _RefreshToken
75  {
76  get
77  {
79  }
80  set
81  {
82  Usuario._This._RefreshToken = value;
83  }
84  }
85 
86  #endregion User calendar Data
87 
88  #region Shared calendar Data
89 
93  protected static internal bool _lRegisterMode = false;
94 
98  private static SharedCalendarData _oSharedCalendarData = new SharedCalendarData();
99 
100  internal static SharedCalendarData OSharedCalendarData
101  {
102  get
103  { if(_oSharedCalendarData == null)
104  _oSharedCalendarData = new SharedCalendarData();
105  return _oSharedCalendarData;
106  }
107  set { _oSharedCalendarData = value; }
108  }
109 
113  internal static string _SharedServiceResourceIds
114  {
115  get { return OSharedCalendarData._RRIdsO365; }
116  set { OSharedCalendarData._RRIdsO365 = value; }
117  }
118 
122  internal static string _SharedRefreshToken
123  {
124  get { return OSharedCalendarData._TokenO365; }
125  set { OSharedCalendarData._TokenO365 = value; }
126  }
127 
131  internal static string _SharedEmail
132  {
133  get { return OSharedCalendarData._EmailO365; }
134  set
135  {
136  //ReadOnly except for register operations
137  if (_lRegisterMode) OSharedCalendarData._EmailO365 = value;
138  }
139  }
140 
144  internal static string _SharedCalendarId
145  {
146  get { return OSharedCalendarData._IdCalO365; }
147  set
148  {
149  //ReadOnly except for register operations
150  if (_lRegisterMode) OSharedCalendarData._IdCalO365 = value;
151  }
152  }
153 
157  internal static bool _SharedCalendarActive
158  {
159  get { return OSharedCalendarData._ShareCalendar; }
160  set { OSharedCalendarData._ShareCalendar = value; }
161  }
162 
166  public bool _IsSharingCalendar
167  {
168  get
169  {
170  //Is sharing when the option is true and email is SET
171  return (OSharedCalendarData._ShareCalendar && !String.IsNullOrWhiteSpace(OSharedCalendarData._EmailO365));
172  }
173  }
174 
175  #endregion Shared calendar Data
176 
180  protected static string _UserCalendars
181  {
182  get
183  {
185  }
186  set
187  {
188  Usuario._This._UserCalendars = value;
189  }
190  }
191 
195  protected static string _CurrentUserCode
196  {
197  get
198  {
199  return Usuario._This._Codigo.TrimEnd();
200  }
201  }
202 
203 
207  public string _ErrorMessage
208  {
209  get { return _cErrorMessage; }
210  set { _cErrorMessage = value; }
211  }
212  private string _cErrorMessage = "";
213 
214  #region Eventos
215 
219  public delegate void _Authentication_Failed(object sender, EventArgs e);
220 
224  public event _Authentication_Failed _OnAuthenticationFailed;
225 
229  private void _Throw_Authentication_Failed_Event()
230  {
231  //local copy for threadsafe
232  var handler = _OnAuthenticationFailed;
233  //if suscriptors
234  if (handler != null)
235  handler(this, null);
236  }
237 
238  #endregion Eventos
239 
240  #region O365Management
241 
246  private static bool RenewToken()
247  {
248  _IsLogged = _O365ManagementUser.Login();
249  if (_IsLogged)
250  {
251  //Get the account info of the login
252  AccountInfo loAccount = (AccountInfo)_O365ManagementUser.GetAccountInfo();
253  if (loAccount != null) _OperatingAs = loAccount.Id;
254 
255 
256  _ClientId = _O365ManagementUser.ClientId;
257  _RefreshToken = _O365ManagementUser.RefreshToken;
258  _ServiceResourceIds = new JavaScriptSerializer().Serialize(O365Management.ServiceResourceIds); //_O365Management.ClientId;
259  Usuario._This._Save(); //Forced save to BBDD
260  }
261  else
262  {
263  //login skiped / failed
264  }
265  return _IsLogged;
266  }
267 
271  private void Clear_User_Data()
272  {
273  _ClientId = "";
274  _RefreshToken = "";
275  _ServiceResourceIds = "";
276  _UserCalendars = "";
277  Usuario._This._Save(); //Forced save to BBDD
278  }
279 
280  private static string _OperatingAs { get; set; }
281 
285  private static bool _IsLogged = false;
286 
291  protected void _ValidateCalendarId(ref string tcCalendarId)
292  {
293  //If we where operating against shared calendar the Id must be forced to the correct one (from BBDD)
294  if (_lUseSharedCalendar) tcCalendarId = _SharedCalendarId;
295  }
296 
301  private static bool RenewTokenSage50()
302  {
303  _IsLogged = _O365ManagementSage50.Login();
304  if (_IsLogged)
305  {
306  //Get the account info of the login
307  AccountInfo loAccount = (AccountInfo)_O365ManagementSage50.GetAccountInfo();
308  if (loAccount != null) _OperatingAs = loAccount.Id;
309 
310  if (String.IsNullOrWhiteSpace(_SharedEmail) || loAccount.Id.Trim() == _SharedEmail.Trim()) //Cuenta coincidente o no establecida la directriz
311  {
312  _SharedRefreshToken = _O365ManagementSage50.RefreshToken;
313  _SharedServiceResourceIds = new JavaScriptSerializer().Serialize(O365ManagementSage50.ServiceResourceIds);
314  }
315  else
316  {
317  string lcErrorMessage = "Para esta operación se requiere la cuenta: " + Environment.NewLine + _SharedEmail.Trim();
318 
319  functions.FUNCTIONS._MessageBox(lcErrorMessage, "Error operación o365",
320  System.Windows.Forms.MessageBoxButtons.OK,
321  System.Windows.Forms.MessageBoxIcon.Error,
322  System.Windows.Forms.MessageBoxDefaultButton.Button1);
323 
324  //Cuenta no concordante
325  _O365ManagementSage50.Logout();
326  }
327 
328  }
329  return _IsLogged;
330  }
331 
335  public virtual bool _UseSharedCalendar
336  {
337  get { return _lUseSharedCalendar; }
338  set { _lUseSharedCalendar = value; }
339  }
340  private static bool _lUseSharedCalendar = false;
341 
345  public static IManagement O365Management
346  {
347  get
348  {
349  if (_lUseSharedCalendar || _lRegisterMode)
351  else
353  }
354  }
355 
360  protected static IManagement O365ManagementUser
361  {
362  get
363  {
364  //To check user changed
365  _Sage50User = Usuario._This._Codigo.TrimEnd();
366 
367  if (_O365ManagementUser == null || String.IsNullOrEmpty(_O365ManagementUser.RefreshToken) || String.IsNullOrEmpty(_O365ManagementUser.ClientId))
368  {
369  _O365ManagementUser = new O365Management();
370 
371  if (!String.IsNullOrWhiteSpace(_RefreshToken) && !String.IsNullOrWhiteSpace(_ServiceResourceIds))
372  {
373  _O365ManagementUser.RefreshToken = _RefreshToken;
374 
375  _O365ManagementUser.ServiceResourceIds = new JavaScriptSerializer().Deserialize<O365Service[]>(_ServiceResourceIds);
376 
377  _O365ManagementUser.ClientId = _ClientId;
378  }
379  else
380  {
381  RenewToken();
382  }
383  }
384  return _O365ManagementUser;
385  }
386  }
387  private static IManagement _O365ManagementUser;
388 
393  public static void _Resetear_Credenciales(Usuario toUsuario)
394  {
395  _Reset_User_Credentials(toUsuario);
396  }
397 
402  protected static void _Reset_User_Credentials(Usuario toUser)
403  {
404 
405  //Si es el mismo usuario de la conexion => Fuerzo logout
406  if (!String.IsNullOrWhiteSpace(_Sage50User) && _O365ManagementUser != null && _Sage50User == toUser._Codigo)
407  {
408  //El usuario actual concuerda con el de las credenciales
409  //Estos campos apuntan al usuario _This
410  _ClientId = "";
411  _RefreshToken = "";
412  _ServiceResourceIds = "";
413  _UserCalendars = "";
414  _O365ManagementUser = null;
415  }
416  else
417  _Sage50User = toUser._Codigo; //Si el usuario almacenado no concuerda hace un logout
418 
419  //Creo un manager no vinculado a nada
420  IManagement oManager = new O365Management();
421  //Logout forzado por si reaprovecha conexión preexistente (static 2 usos seguidos)
422  oManager.Logout();
423 
424  //Solicito login
425  _IsLogged = oManager.Login();
426  if (_IsLogged) //Si me lo da lo guardo
427  {
428  toUser._ClientId = oManager.ClientId;
429  toUser._RefreshToken = oManager.RefreshToken;
430  toUser._ServiceResourceIds = new JavaScriptSerializer().Serialize(oManager.ServiceResourceIds); //_O365Management.ClientId;
431  }
432  else //No hace el login
433  {
434  //Vaciar los datos
435  toUser._ClientId = "";
436  toUser._RefreshToken = "";
437  toUser._ServiceResourceIds = "";
438  }
439 
440  //Con o sin login salvo los datos
441  toUser._UserCalendars = ""; //Sin calendarios prefijados
442  toUser._Save(); //Forced save to BBDD
443  }
444 
449  protected static IManagement O365ManagementSage50
450  {
451  get
452  {
453  if (_O365ManagementSage50 == null || String.IsNullOrEmpty(_O365ManagementSage50.RefreshToken) || String.IsNullOrEmpty(_O365ManagementSage50.ClientId))
454  {
455  _O365ManagementSage50 = new O365Management();
456 
457  if (!String.IsNullOrWhiteSpace(_SharedRefreshToken) && !String.IsNullOrWhiteSpace(_SharedServiceResourceIds))
458  {
459  _O365ManagementSage50.RefreshToken = _SharedRefreshToken;
460  _O365ManagementSage50.ServiceResourceIds = new JavaScriptSerializer().Deserialize<O365Service[]>(_SharedServiceResourceIds);
461  }
462  else
463  {
464  RenewTokenSage50();
465  }
466  }
467  return _O365ManagementSage50;
468  }
469  }
470  private static IManagement _O365ManagementSage50;
471 
472 
473  #endregion
474 
475 
476  #region Constructors
477 
481  public o365consumer()
482  {
483 
484  }
485 
486  #endregion Constructors
487 
488  #region Public methods
489 
494  public virtual string _ShowUsers()
495  {
496  //String to store selected users email
497  string lcUsuariosSeleccionados = "";
498 
499  //Configure the user browser form
500  sage.ew.botones.btBrowser lbtBrowser = new botones.btBrowser();
501  lbtBrowser._Seleccion_Multiple = true; //Multiselection enabled
502  lbtBrowser._Tabla = "USUARIOS";
503  lbtBrowser._DataBase = "COMUNES";
504  lbtBrowser._Codigo = "NOMBRE";
505  lbtBrowser._Clave = "NOMBRE";
506  lbtBrowser._Campo_Predet = "NOMBRE";
507  lbtBrowser._Titulos_Campos = "Nombre, Email";
508  lbtBrowser._Campos = "NOMBRE, MAIL";
509  lbtBrowser._Condicion = "MAIL<>'' ";
510  lbtBrowser.PerformClick();
511 
512  //Proccess the result selecction
513  if (lbtBrowser._Codigo_List != null && lbtBrowser._Codigo_List.Count > 0)
514  {
515  //_Codigo_List is a KeyValuePair
516  foreach (KeyValuePair<string,object> lkvpISelectedItem in lbtBrowser._Codigo_List)
517  {
518  //The value is (all) the browser row
519  DataRow loRow = lkvpISelectedItem.Value as DataRow;
520  if (loRow != null)
521  {
522  try
523  {
524  string lcUsuario = Convert.ToString(loRow["mail"]).Trim();
525  if (!String.IsNullOrWhiteSpace(lcUsuario) && !lcUsuario.EndsWith(";")) lcUsuario += ";";
526  lcUsuariosSeleccionados += lcUsuario;
527  }
528  catch (Exception loEx)
529  {
530  _RaiseException(loEx);
531  }
532  }
533  }
534  }
535  return lcUsuariosSeleccionados;
536  }
537 
542  public void _RaiseException(Exception toException)
543  {
544  if (_IsLogged)
545  {
546  string lcErrorMessage = "";
547 
548  //PE-97256
549  if (O365Management.MessageError != null && O365Management.MessageError.Contains("The user or administrator has not consented to use the application"))
550  {
551  lcErrorMessage = "Se ha poducido una incidencia en la validación de la cuenta de correo al acceder al calendario en Microsoft 365. " +
552  "Deberá revisar los siguientes apartados de configuración:" + Environment.NewLine +
553  "- No se trata de una cuenta de Microsoft 365" + Environment.NewLine +
554  "- No existen los permisos necesarios en la aplicación" + Environment.NewLine +
555  "- Se han denegado los permisos en la aplicación";
556  //At this moment we know that it were invalid to operate credencials stored in the DDBB. We call a clean function
557  Clear_User_Data();
558  }
559  else
560  {
561  lcErrorMessage = "Se ha producido un error cuando se ha intentado realizar la comunicación con Microsoft 365" +
562  Environment.NewLine + "El mensaje por parte de Microsoft 365 es: " + Environment.NewLine + toException.Message +
563  Environment.NewLine + Environment.NewLine +
564  "Revisa la configuración de la cuenta en Microsoft 365"; //PE-97418
565 
566  //Detectado en instalación propia un error que resulta bloqueante:
567  //Teniendo unas credenciales válidas pero con un refreshtoken expirado (90 días) Login devuelve true pero no recarga el token y falla
568  //Cuando detectamos este caso concreto purgamos las credenciales para forzar un login completo
569  if(toException.Message.Contains("refresh token has expired due to inactivity"))
570  {
571  Clear_User_Data();
572  }
573  }
574 
575  functions.FUNCTIONS._MessageBox(lcErrorMessage, "Error operación o365",
576  System.Windows.Forms.MessageBoxButtons.OK,
577  System.Windows.Forms.MessageBoxIcon.Error,
578  System.Windows.Forms.MessageBoxDefaultButton.Button1);
579  _ErrorMessage = toException.Message;
580  db.DB.Registrar_Error(toException);
581  }
582  else
583  {
584  string lcErrorMessage = "No ha sido posible obtener el código de autenticación.";
585  functions.FUNCTIONS._MessageBox(lcErrorMessage, "Error operación o365",
586  System.Windows.Forms.MessageBoxButtons.OK,
587  System.Windows.Forms.MessageBoxIcon.Error,
588  System.Windows.Forms.MessageBoxDefaultButton.Button1);
589  _ErrorMessage = toException.Message;
590  db.DB.Registrar_Error(toException);
591 
592  //PE-97171
593  _Throw_Authentication_Failed_Event();
594  }
595  }
596 
597  #endregion Public methods
598 
602  internal void _ResetOManagers()
603  {
604  if(_O365ManagementSage50 != null) _O365ManagementSage50.Logout();
605  _O365ManagementSage50 = null;
606  _O365ManagementSage50 = new O365Management();
607  if (_O365ManagementUser != null) _O365ManagementUser.Logout();
608  _O365ManagementUser = null;
609  _O365ManagementUser = new O365Management();
610  OSharedCalendarData = null;
611  }
612 
617  internal void _ResetUserStoredCalendars()
618  {
619  bool llOk = false;
620  string lcSql = "UPDATE " + DB.SQLDatabase("COMUNES","USUARIOS") + " SET USERCALENDARS = ''"; //For all of the users
621  llOk = DB.SQLExec(lcSql);
622 
623  //Referencia estática al USUARIO._This
624  _UserCalendars = "";
625  }
626  }
627 
631  internal class SharedCalendarData
632  {
633  #region Encryption
634 
638  private Criptografia _oCifrado = new Criptografia();
643  private string _cClaveCifrado = "#Nice to see you";
644 
645  #endregion Encryption
646 
647  #region Public properties
648 
652  public bool _ShareCalendar
653  {
654  get { return _lShareCalendar; }
655  set
656  {
657  _lShareCalendar = value;
658  _SetDataField("CMPCALO365", value.ToString());
659  }
660  }
661  private bool _lShareCalendar;
662 
666  public string _EmailO365
667  {
668  get { return _cEmailO365; }
669  set { _cEmailO365 = value; }
670  }
671  private string _cEmailO365;
672 
676  public string _IdCalO365
677  {
678  get { return _cIdCalO365; }
679  set { _cIdCalO365 = value; }
680  }
681  private string _cIdCalO365;
682 
686  public string _TokenO365
687  {
688  get { return _cTokenO365; }
689  set { _cTokenO365 = value; }
690  }
691  private string _cTokenO365;
692 
696  public string _RRIdsO365
697  {
698  get { return _cRRIdsO365; }
699  set { _cRRIdsO365 = value; }
700  }
701  private string _cRRIdsO365;
702 
703  #endregion Public properties
704 
705  #region Constructors
706 
710  public SharedCalendarData()
711  {
712  _Load();
713  }
714 
715  #endregion Constructors
716 
717  #region Public methods
718 
723  public bool _Load()
724  {
725  string lcSql = "SELECT CMPCALO365, EMAILO365, IDCALO365, TOKENO365, RRIDSO365 FROM" + DB.SQLDatabase("COMUNES", "CODCOM");
726  bool llOk = false;
727  DataTable ldtResultado = new DataTable();
728 
729  llOk = DB.SQLExec(lcSql, ref ldtResultado);
730  if (llOk && ldtResultado.Rows.Count > 0)
731  {
732  _lShareCalendar = Convert.ToBoolean(ldtResultado.Rows[0]["CMPCALO365"]);
733  _cEmailO365 = _oCifrado.DesencriptaSimetricaAES(Convert.ToString(ldtResultado.Rows[0]["EMAILO365"]).TrimEnd(), _cClaveCifrado);
734  _cIdCalO365 = _oCifrado.DesencriptaSimetricaAES(Convert.ToString(ldtResultado.Rows[0]["IDCALO365"]).TrimEnd(), _cClaveCifrado);
735  _cTokenO365 = _oCifrado.DesencriptaSimetricaAES(Convert.ToString(ldtResultado.Rows[0]["TOKENO365"]).TrimEnd(), _cClaveCifrado);
736  _cRRIdsO365 = _oCifrado.DesencriptaSimetricaAES(Convert.ToString(ldtResultado.Rows[0]["RRIDSO365"]).TrimEnd(), _cClaveCifrado);
737  }
738  return llOk;
739  }
740 
745  public bool _Save()
746  {
747  string lcSql = "UPDATE " + DB.SQLDatabase("COMUNES", "CODCOM") + " SET " +
748  " CMPCALO365 = " + DB.SQLString(_lShareCalendar) + ", " +
749  " EMAILO365 = " + DB.SQLString(_oCifrado.EncriptaSimetricaAES(_cEmailO365, _cClaveCifrado)) + ", " +
750  " IDCALO365 = " + DB.SQLString(_oCifrado.EncriptaSimetricaAES(_cIdCalO365, _cClaveCifrado)) + ", " +
751  " TOKENO365 = " + DB.SQLString(_oCifrado.EncriptaSimetricaAES(_cTokenO365, _cClaveCifrado)) + ", " +
752  " RRIDSO365 = " + DB.SQLString(_oCifrado.EncriptaSimetricaAES(_cRRIdsO365, _cClaveCifrado));
753 
754  return DB.SQLExec(lcSql);
755  }
756 
763  public void _Update(AccountInfo toAccount, string tcRefreshToken, string tcResoucesServiceIds)
764  {
765  //Exit if not the correct account
766  if (toAccount.Id != _cEmailO365) return;
767 
768  _cTokenO365 = tcRefreshToken;
769  _cRRIdsO365 = tcResoucesServiceIds;
770  }
771 
772  #endregion Public methods
773 
774  #region Private methods
775 
782  private bool _GetDataField(string tcDataFieldName, out string tcDataValue)
783  {
784  string lcSql = "SELECT [" + tcDataFieldName.TrimEnd() + "] FROM" + DB.SQLDatabase("COMUNES", "CODCOM");
785  bool llOk = false;
786  string lcDataValue = "";
787  DataTable ldtResultado = new DataTable();
788 
789  llOk = DB.SQLExec(lcSql, ref ldtResultado);
790  if (llOk && ldtResultado.Rows.Count > 0)
791  {
792 
793  lcDataValue = _oCifrado.DesencriptaSimetricaAES(Convert.ToString(ldtResultado.Rows[0][tcDataFieldName]).TrimEnd(), _cClaveCifrado);
794  }
795 
796  tcDataValue = lcDataValue;
797  return llOk;
798  }
799 
806  private bool _SetDataField(string tcDataFieldName, string tcDataValue)
807  {
808  if (tcDataFieldName == "CMPCALO365") //bool not encripted
809  {
810  string lcSql = "UPDATE " + DB.SQLDatabase("COMUNES", "CODCOM") + " SET [" + tcDataFieldName + "] = " +
811  DB.SQLString(tcDataValue);
812 
813  return DB.SQLExec(lcSql);
814  }
815  else
816  {
817  string lcSql = "UPDATE " + DB.SQLDatabase("COMUNES", "CODCOM") + " SET [" + tcDataFieldName + "] = " +
818  DB.SQLString(_oCifrado.EncriptaSimetricaAES(tcDataValue, _cClaveCifrado));
819 
820  return DB.SQLExec(lcSql);
821  }
822  }
823 
824  #endregion Private methods
825  }
826 }
_Authentication_Failed _OnAuthenticationFailed
Authentication failed event
void _ValidateCalendarId(ref string tcCalendarId)
During shared calendar operations may get invalid calendar id. This function enforces the correct one...
static IManagement O365ManagementUser
Property O365Management: Returns the O365Management for user calendar operations creates the instance...
string _ServiceResourceIds
Get or set the ServiceResourceIds Uses encryption. BBDD Name RESOURCEIDS not SERVICERESOURCEIDS for b...
Definition: clsUsuario.cs:860
static sage.ew.usuario.Usuario _This
Instancia estática del objeto usuario con los datos del usuario actual (wc_usuario) ...
Definition: clsUsuario.cs:341
string _ClientId
Get or set the ClientId Uses encryption.
Definition: clsUsuario.cs:772
string _UserCalendars
Get or set the UserCalendars Uses encryption. Serialitzed dictionary Calendar Name (key) - Calendar I...
Definition: clsUsuario.cs:905
static void _Resetear_Credenciales(Usuario toUsuario)
Método estatico para resetear las credenciales de un usuario
Browser, basat en sage.ew.objetos.ewbutton
PE-85105: Clase donde se implementaran aquellas funciones de encriptación y desencriptación utilizand...
Definition: Criptografia.cs:15
o365consumer()
Default Constructor
virtual string _ShowUsers()
Method show the program users with email informed
new string _Codigo
Valor de campo clave
Definition: clsUsuario.cs:1020
static void _Reset_User_Credentials(Usuario toUser)
Método para restablecer las credenciales de un usuario
Class to consume the O365 API
Definition: o365consumer.cs:17
static IManagement O365ManagementSage50
Property O365Management: Returns the O365Management for shared calendar operations creates the instan...
void _RaiseException(Exception toException)
Method to inform the user and log an exception
string EncriptaSimetricaAES(string tcMensaje)
Encriptación simétrica AES. Para encriptar un mensaje que después se puede desencriptar con la funció...
Definition: Criptografia.cs:31
string DesencriptaSimetricaAES(string tcMensajeEncriptado)
Encriptación simétrica AES. Para encriptar un mensaje que después se puede desencriptar con la funció...
Definition: Criptografia.cs:41
override bool _Save()
Override del método SAVE
Definition: clsUsuario.cs:5326
string _RefreshToken
Get or set the RefreshToken Uses encryption.
Definition: clsUsuario.cs:816
Definición de la clase Usuario
Definition: clsUsuario.cs:113