LoginController.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. <?php
  2. namespace App\Http\Controllers;
  3. use Illuminate\Http\Request;
  4. use Illuminate\Support\Facades\Validator;
  5. use Illuminate\Support\Facades\DB;
  6. use Illuminate\Support\Facades\Hash;
  7. use Illuminate\Support\Carbon;
  8. use Firebase\JWT\JWT;
  9. use Firebase\JWT\Key;
  10. use Exception;
  11. use PDOException;
  12. use Jenssegers\Agent\Agent;
  13. class LoginController extends Controller{
  14. private $responseController;
  15. private $encryptionController;
  16. private $functionsController;
  17. private $secretKey = "ydl27x22cNsNY0z6o3Fr6XZoUvsX0QMZx6MaiwN+KCnM6APS4Xbb7GDfudOYD5uD/r8TzQElh4d4HIal5Os0XA==";
  18. private $publicKey = "zOgD0uF22+xg37nTmA+bg/6/E80BJYeHeByGpeTrNFw=";
  19. public function __construct(){
  20. $this->responseController = new ResponseController();
  21. $this->encryptionController = new EncryptionController();
  22. $this->functionsController = new FunctionsController;
  23. }
  24. public function login(Request $request){
  25. DB::enableQueryLog();
  26. $validator = Validator::make($request->all(), [
  27. 'email' => 'required|string|email',
  28. 'password' => 'required|string',
  29. 'linea' => 'required|integer|max: 2',
  30. 'latitude' => 'required|numeric|between:-90,90',
  31. 'longitude' => 'required|numeric|between:-180,180',
  32. 'accuracy' => 'required|numeric|between:0,1000000',
  33. 'city' => 'string|max:100',
  34. 'state' => 'string|max:100',
  35. 'country' => 'required|string|max:50',
  36. ]);
  37. if($validator->fails()){
  38. return $this->responseController->makeResponse(
  39. true,
  40. "Se encontraron uno o más errores.",
  41. $this->responseController->makeErrors(
  42. $validator->errors()->messages()
  43. ),
  44. 401
  45. );
  46. }
  47. $login = $request->all();
  48. //Se obtiene la dirección IP de la solicitud
  49. $ipv = $request->ip();
  50. $v4 = filter_var($ipv, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) ? true : false;
  51. //Se obtiene el dispositivo utilizado
  52. $agent = new Agent();
  53. $device = 'Desconocido';
  54. if($agent->isDesktop()) $device = 'PC';
  55. else if($agent->device()) $device = $agent->device();
  56. //Se obtiene el SO utilizado y la versión del mismo
  57. $platform = $agent->platform() ? $agent->platform() : 'Desconocido';
  58. $version = 'N/A';
  59. if($platform != 'Desconocido') $version = $agent->version($platform);
  60. //Se obtiene el navegador web utilizado
  61. $browser = $agent->browser() ? $agent->browser() : 'Desconocido';
  62. //Se consulta el correo electrónico enviado
  63. $usr = DB::table('S002V01TUSUA')->where('USUA_COEL', '=', $login['email'])->first();
  64. if(is_null($usr)){
  65. return $this->responseController->makeResponse(true, "El correo electrónico no está registrado.", [], 404);
  66. }else if($usr->USUA_ESTA != 'Activo'){
  67. $statusStr = strtolower($usr->USUA_ESTA);
  68. return $this->responseController->makeResponse(true, "El usuario se encuentra $statusStr, por favor contacte al administrador para solucionarlo.", [], 401);
  69. }
  70. $now = Carbon::now('America/Mexico_city');
  71. $nowStr = $now->toDateTimeString();
  72. $contra = $login['password'];
  73. $contra = $this->encryptionController->decrypt($contra);
  74. if(!$contra){
  75. return $this->responseController->makeResponse(true, 'La contraseña no fue encriptada correctamente.', [], 400);
  76. }
  77. $usrContra = $usr->USUA_CONT;
  78. if(!Hash::check($contra, $usrContra)){
  79. $attempts = $usr->USUA_ININ + 1;
  80. $status = $attempts >= 10 ? 'Inactivo' : 'Activo';
  81. DB::table('S002V01TUSUA')->where('USUA_IDUS', '=', $usr->USUA_IDUS)->update([
  82. "USUA_ININ" => $attempts,
  83. "USUA_ESTA" => $status
  84. ]);
  85. return $this->responseController->makeResponse(true, "La contraseña es incorrecta, intento $attempts de 10.", [], 401);
  86. }
  87. $controlPanel = DB::table('S002V01TPACO')->where([
  88. ['PACO_NULI', '=', $login['linea']],
  89. ['PACO_IDPC', '=', $usr->USUA_PCRE]
  90. ])->first();
  91. DB::table('S002V01TUSUA')->where('USUA_IDUS', '=', $usr->USUA_IDUS)->update([
  92. "USUA_ININ" => 0,
  93. "USUA_ESTA" => 'Activo'
  94. ]);
  95. $iat = $now->timestamp;
  96. $cad = $now->addDay()->timestamp;
  97. $state = isset($login['state']) ? $login['state'] : '-';
  98. $ulco = DB::table('S002V01TBIAC')->insertGetId([
  99. 'BIAC_NULI' => $login['linea'],
  100. 'BIAC_IDUS' => $usr->USUA_IDUS,
  101. 'BIAC_FECO' => $nowStr,
  102. 'BIAC_IPV4' => $v4 ? $ipv : null,
  103. 'BIAC_IPV6' => !$v4 ? $ipv : null,
  104. 'BIAC_LATI' => $login['latitude'],
  105. 'BIAC_LONG' => $login['longitude'],
  106. 'BIAC_PREC' => $login['accuracy'],
  107. 'BIAC_CIUD' => $login['city'],
  108. 'BIAC_ESTA' => $state,
  109. 'BIAC_PAIS' => $login['country'],
  110. 'BIAC_DISP' => $device,
  111. 'BIAC_SIOP' => $platform,
  112. 'BIAC_VSOP' => $version,
  113. 'BIAC_NAVE' => $browser,
  114. ]);
  115. DB::table('S002V01TUSUA')->where('USUA_COEL', '=', $login['email'])->update(['USUA_ULCO' => $ulco]);
  116. //Antes de crear el token revisamos los permisos de su perfil
  117. $profile = DB::table('S002V01TPERF')->where('PERF_IDPE', '=', $usr->USUA_PERF)->get()->first();
  118. $permissions = $this->encryptionController->encrypt($profile->PERF_PERM);
  119. $payload = [
  120. "iss" => $login['email'],
  121. "aud" => "dominio.syp.mx",
  122. "iat" => $iat,
  123. "cad" => $cad
  124. ];
  125. $token = JWT::encode($payload, $this->secretKey, 'EdDSA');
  126. //Antes de realizar el return obtenemos todos los querys ejecutados en esta consulta
  127. $querys = DB::getQueryLog();
  128. $name = $this->functionsController->joinName($usr->USUA_NOMB, $usr->USUA_APPA, $usr->USUA_APMA);
  129. //Se registra la acción realizada
  130. $idac = $this->functionsController->registerActivity(
  131. $login['linea'],
  132. 'LOGIN',
  133. '-',
  134. '-',
  135. 'Registro',
  136. "El usuario $name (" . $usr->USUA_IDUS . ") inició sesión.",
  137. $usr->USUA_IDUS,
  138. $nowStr
  139. );
  140. $this->functionsController->registerLog($querys, $usr->USUA_IDUS, $nowStr, $idac, $login['linea']);
  141. return $this->responseController->makeResponse(false, "EXITO.", [
  142. "IDUSUARIO" => $this->encryptionController->encrypt($usr->USUA_IDUS),
  143. "NOMBREUSUARIO" => $this->encryptionController->encrypt($usr->USUA_NOMB),
  144. "CORREO" => $this->encryptionController->encrypt($usr->USUA_COEL),
  145. "PERFIL" => $this->encryptionController->encrypt($usr->USUA_PERF),
  146. "PANEL" => isset($controlPanel) ? $this->encryptionController->encrypt($usr->USUA_PCRE) : null,
  147. "PERMISOS" => $permissions,
  148. "TOKEN" => $token,
  149. ]);
  150. }
  151. public function verifyToken(Request $request){
  152. DB::enableQueryLog();
  153. $validator = Validator::make($request->all(), [
  154. 'token' => 'required|string',
  155. 'linea' => 'required|integer'
  156. ]);
  157. if($validator->fails()){
  158. return $this->responseController->makeResponse(
  159. true,
  160. "Se encontraron uno o más errores.",
  161. $this->responseController->makeErrors(
  162. $validator->errors()->messages()
  163. ),
  164. 401
  165. );
  166. }
  167. $tokenInfo = $request->all();
  168. try{
  169. $decoded = JWT::decode($tokenInfo['token'], new Key($this->publicKey, 'EdDSA'));
  170. }catch(Exception $e){
  171. return $this->responseController->makeResponse(false, "Token inválido", [
  172. "validToken" => false
  173. ]);
  174. }
  175. $usr = DB::table('S002V01TUSUA')->where('USUA_COEL', '=', $decoded->iss)->first();
  176. if(is_null($usr)){
  177. return $this->responseController->makeResponse(false, "El usuario que generó el token no está registrado en la base.", [
  178. "validToken" => false
  179. ]);
  180. }else if($usr->USUA_ESTA == 'Inactivo'){
  181. return $this->responseController->makeResponse(false, "El usuario que generó el token está desactivado.", [
  182. "validToken" => false
  183. ]);
  184. }else if($usr->USUA_ESTA == 'Eliminado'){
  185. return $this->responseController->makeResponse(false, "El usuario que generó el token está eliminado.", [
  186. "validToken" => false
  187. ]);
  188. }
  189. if($decoded->aud != "dominio.syp.mx"){
  190. return $this->responseController->makeResponse(false, "El token enviado fue generado en un sitio diferente.", [
  191. "validToken" => false
  192. ]);
  193. }
  194. $now = Carbon::now('America/Mexico_city')->timestamp;
  195. if($now > $decoded->cad){
  196. return $this->responseController->makeResponse(false, "Token expirado.", [
  197. "validToken" => false
  198. ]);
  199. }
  200. $nowStr = Carbon::now('America/Mexico_city')->toDateTimeString();
  201. $name = $this->functionsController->joinName($usr->USUA_NOMB, $usr->USUA_APPA, $usr->USUA_APMA);
  202. //Se registra la acción realizada
  203. $idac = $this->functionsController->registerActivity(
  204. $tokenInfo['linea'],
  205. 'LOGIN',
  206. '-',
  207. '-',
  208. 'Registro',
  209. "El usuario $name (" . $usr->USUA_IDUS . ") verificó su token de acceso.",
  210. $usr->USUA_IDUS,
  211. $nowStr
  212. );
  213. $actions = DB::getQueryLog();
  214. $this->functionsController->registerLog($actions, $usr->USUA_IDUS, $nowStr, $idac, $tokenInfo['linea']);
  215. return $this->responseController->makeResponse(false, "Token válido.", [
  216. "validToken" => true
  217. ]);
  218. }
  219. public function createPasword(Request $request){
  220. $timestamp = Carbon::now('America/Mexico_city')->timestamp;
  221. $id = $this->functionsController->generateID('José Luis Brito Nava', $timestamp);
  222. var_dump(Hash::make('ITTEC2022'));
  223. $uuid = $this->functionsController->uuidv5('1546058f-5a25-4334-85ae-e68f2a44bbaf', 'jose.b@ittec.mx');
  224. return $this->responseController->makeResponse(false, $id, []);
  225. }
  226. public function shortEncryption(Request $request){
  227. $validator = Validator::make($request->all(), [
  228. 'string' => 'required|string',
  229. ]);
  230. if($validator->fails()){
  231. return $this->responseController->makeResponse(
  232. true,
  233. "Se encontraron uno o más errores.",
  234. $this->responseController->makeErrors(
  235. $validator->errors()->messages()
  236. ),
  237. 401
  238. );
  239. }
  240. $info = $request->all();
  241. $strDec = $this->encryptionController->decrypt($info['string']);
  242. if(!$strDec){
  243. return $this->responseController->makeResponse(true, 'La cadena enviada no fue encriptada correctamente', [], 404);
  244. }
  245. $shorterStr = $this->encryptionController->shortEnc($strDec);
  246. $shorterStr = str_replace("+", "=P=", $shorterStr);
  247. $shorterStr = str_replace("/", "=S=", $shorterStr);
  248. return $this->responseController->makeResponse(false, 'EXITO', ['encrypted' => $shorterStr]);
  249. }
  250. }