import 'dart:developer'; import 'dart:typed_data'; import 'package:dart_jsonwebtoken/dart_jsonwebtoken.dart'; import 'package:flutter/material.dart'; import 'package:path/path.dart' as p; import 'package:image_picker/image_picker.dart'; import 'package:supabase_flutter/supabase_flutter.dart'; import 'package:uuid/uuid.dart'; import 'package:nethive_neo/helpers/globals.dart'; import 'package:nethive_neo/helpers/supabase/queries.dart'; import 'package:nethive_neo/router/router.dart'; class UserState extends ChangeNotifier { //EMAIL Future setEmail() async { await prefs.setString('email', emailController.text); } //Controlador para LoginScreen TextEditingController emailController = TextEditingController(); //PASSWORD Future setPassword() async { await prefs.setString('password', passwordController.text); } //Controlador para LoginScreen TextEditingController passwordController = TextEditingController(); bool recuerdame = false; //Variables para editar perfil TextEditingController nombrePerfil = TextEditingController(); TextEditingController apellidosPerfil = TextEditingController(); TextEditingController telefonoPerfil = TextEditingController(); TextEditingController extensionPerfil = TextEditingController(); TextEditingController emailPerfil = TextEditingController(); TextEditingController contrasenaAnteriorPerfil = TextEditingController(); TextEditingController confirmarContrasenaPerfil = TextEditingController(); TextEditingController contrasenaPerfil = TextEditingController(); String? imageName; Uint8List? webImage; int loginAttempts = 0; bool userChangedPasswordInLast90Days = true; //Constructor de provider UserState() { recuerdame = prefs.getBool('recuerdame') ?? false; if (recuerdame == true) { emailController.text = prefs.getString('email') ?? ''; passwordController.text = prefs.getString('password') ?? ''; } } Future actualizarContrasena() async { try { final res = await supabase.rpc('change_user_password', params: { 'current_plain_password': contrasenaAnteriorPerfil.text, 'new_plain_password': contrasenaPerfil.text, }); if (res == null) { log('Error en actualizarContrasena()'); return false; } return true; } catch (e) { log('Error en actualizarContrasena() - $e'); return false; } } // void initPerfilUsuario() { // if (currentUser == null) return; // nombrePerfil.text = currentUser!.nombre; // // apellidosPerfil.text = currentUser!.apellidos; // emailPerfil.text = currentUser!.email; // webImage = null; // contrasenaPerfil.clear(); // contrasenaAnteriorPerfil.clear(); // confirmarContrasenaPerfil.clear(); // } Future selectImage() async { final ImagePicker picker = ImagePicker(); final XFile? pickedImage = await picker.pickImage( source: ImageSource.gallery, ); if (pickedImage == null) return; final String fileExtension = p.extension(pickedImage.name); const uuid = Uuid(); final String fileName = uuid.v1(); imageName = 'avatar-$fileName$fileExtension'; webImage = await pickedImage.readAsBytes(); notifyListeners(); } void clearImage() { webImage = null; imageName = null; notifyListeners(); } Future uploadImage() async { if (webImage != null && imageName != null) { await supabase.storage.from('avatars').uploadBinary( imageName!, webImage!, fileOptions: const FileOptions( cacheControl: '3600', upsert: false, ), ); return imageName; } return null; } Future editarPerfilDeUsuario() async { try { await supabase.from('perfil_usuario').update( { 'nombre': nombrePerfil.text, 'apellidos': apellidosPerfil.text, 'telefono': telefonoPerfil.text, 'imagen': imageName, }, ).eq('perfil_usuario_id', currentUser!.id); return true; } catch (e) { log('Error en editarPerfilDeUsuario() - $e'); return false; } } Future updateRecuerdame() async { recuerdame = !recuerdame; await prefs.setBool('recuerdame', recuerdame); notifyListeners(); } String generateToken(String userId, String email) { //Generar token final jwt = JWT( { 'user_id': userId, 'email': email, 'created': DateTime.now().toUtc().toIso8601String(), }, issuer: 'https://github.com/jonasroussel/dart_jsonwebtoken', ); // Sign it (default with HS256 algorithm) return jwt.sign(SecretKey('secret')); } // Future sendEmailWithToken(String email, String password, String token, String type) async { // //Mandar correo // final response = await http.post( // Uri.parse(bonitaConnectionUrl), // body: json.encode( // { // "user": "Web", // "action": "bonitaBpmCaseVariables", // 'process': 'Alta_de_Usuario', // 'data': { // 'variables': [ // { // 'name': 'correo', // 'value': email, // }, // { // 'name': 'password', // 'value': password, // }, // { // 'name': 'token', // 'value': token, // }, // { // 'name': 'type', // 'value': type, // }, // ] // }, // }, // ), // ); // if (response.statusCode > 204) { // return false; // } // return true; // } // Future sendEmailWithAccessCode(String email, String id) async { // //Mandar correo // final response = await http.post( // Uri.parse(bonitaConnectionUrl), // body: json.encode( // { // "user": "Web", // "action": "bonitaBpmCaseVariables", // 'process': 'DVLogin', // 'data': { // 'variables': [ // { // 'name': 'correo', // 'value': email, // }, // { // 'name': 'id', // 'value': id, // }, // ] // }, // }, // ), // ); // if (response.statusCode > 204) { // return false; // } // return true; // } Future?> resetPassword(String email) async { try { final res = await supabase.from('users').select('id').eq('email', email); if ((res as List).isEmpty) { return {'Error': 'El correo no está registrado'}; } final userId = res[0]['id']; if (userId == null) return {'Error': 'El correo no está registrado'}; final token = generateToken(userId, email); // Guardar token await SupabaseQueries.saveToken( userId, 'token_reset', token, ); // final res2 = await sendEmailWithToken(email, '', token, 'reset'); // if (!res2) return {'Error': 'Error al realizar petición'}; return null; } catch (e) { log('Error en resetPassword() - $e'); } return {'Error': 'There was an error after sending request'}; } Future getUserId(String email) async { try { final res = await supabase.from('users').select('id').eq('email', email); if ((res as List).isNotEmpty) { return res[0]['id']; } return null; } catch (e) { log('Error en getUserId - $e'); return null; } } Future validateAccessCode(String userId, String accessCode) async { try { final res = await supabase.rpc('validate_access_code', params: { 'id': userId, 'access_code_attempt': accessCode, }); return res; } catch (e) { log('Error en getAccessCode() - $e'); return false; } } Future sendAccessCode(String userId) async { try { final codeSaved = await supabase.rpc( 'save_access_code', params: {'id': userId}, ); if (!codeSaved) return false; // final emailSent = await sendEmailWithAccessCode( // emailController.text, // userId, // ); // if (!emailSent) return false; return true; } catch (e) { log('Error en sendEmailWithAccessCode() -$e'); return false; } } Future incrementLoginAttempts(String email) async { loginAttempts += 1; if (loginAttempts >= 3) { try { await supabase.rpc('block_user', params: {'email': email}); } catch (e) { log('Error en incrementLoginAttempts() - $e'); } finally { loginAttempts = 0; } } notifyListeners(); } Future registerLogin(String userId) async { try { await supabase.from('login_historico').insert({'usuario_fk': userId}); } catch (e) { log('registerLogin() - $e'); } } Future checkIfUserBlocked(String email) async { try { final res = await supabase.rpc('check_if_user_blocked', params: { 'email': email, }); return res; } catch (e) { log('Error en checkIfUserIsBlocked() - $e'); return true; } } Future checkIfUserChangedPasswordInLast90Days(String userId) async { try { final res = await supabase.rpc('usuario_cambio_contrasena', params: { 'user_id': userId, }); userChangedPasswordInLast90Days = res; } catch (e) { log('Error en checkIfUserChangedPasswordInLast90Days() - $e'); } } Future logout() async { await supabase.auth.signOut(); currentUser = null; await prefs.remove('currentRol'); /* Configuration? conf = await SupabaseQueries.getDefaultTheme(); AppTheme.initConfiguration(conf); */ router.pushReplacement('/'); } @override void dispose() { emailController.dispose(); passwordController.dispose(); nombrePerfil.dispose(); emailPerfil.dispose(); contrasenaPerfil.dispose(); super.dispose(); } }