ricostruzione sessione manuale per aggirare gorouter che distrugge il token
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flux/main.dart';
|
||||||
import 'package:supabase_flutter/supabase_flutter.dart';
|
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||||
|
|
||||||
class SetPasswordScreen extends StatefulWidget {
|
class SetPasswordScreen extends StatefulWidget {
|
||||||
@@ -16,6 +17,15 @@ class _SetPasswordScreenState extends State<SetPasswordScreen> {
|
|||||||
bool _obscurePassword = true;
|
bool _obscurePassword = true;
|
||||||
String? _errorMessage;
|
String? _errorMessage;
|
||||||
|
|
||||||
|
// Variabile per abilitare l'inserimento
|
||||||
|
bool _isSessionReady = false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_forceSessionRecovery();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_passwordController.dispose();
|
_passwordController.dispose();
|
||||||
@@ -23,17 +33,58 @@ class _SetPasswordScreenState extends State<SetPasswordScreen> {
|
|||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 🎯 LA VERA MAGIA: RICOSTRUIAMO LA SESSIONE A MANO
|
||||||
|
Future<void> _forceSessionRecovery() async {
|
||||||
|
try {
|
||||||
|
// 1. Prendiamo il frammento dalla cassaforte
|
||||||
|
final fragment = initialRecoveryFragment ?? Uri.base.fragment;
|
||||||
|
|
||||||
|
if (fragment.contains('access_token=')) {
|
||||||
|
// 2. Dividiamo la stringa in una mappa chiave:valore
|
||||||
|
final params = Uri.splitQueryString(fragment);
|
||||||
|
final refreshToken = params['refresh_token'];
|
||||||
|
|
||||||
|
if (refreshToken != null) {
|
||||||
|
// 3. Forziamo Supabase a loggare l'utente col refresh token!
|
||||||
|
await Supabase.instance.client.auth.setSession(refreshToken);
|
||||||
|
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {
|
||||||
|
_isSessionReady = true;
|
||||||
|
_errorMessage = null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback: se Supabase ce l'aveva già fatta miracolosamente
|
||||||
|
if (Supabase.instance.client.auth.currentSession != null) {
|
||||||
|
setState(() => _isSessionReady = true);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print("Errore ripristino manuale sessione: $e");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> _submitNewPassword() async {
|
Future<void> _submitNewPassword() async {
|
||||||
if (!_formKey.currentState!.validate()) return;
|
if (!_formKey.currentState!.validate()) return;
|
||||||
|
|
||||||
|
if (!_isSessionReady) {
|
||||||
|
setState(() {
|
||||||
|
_errorMessage =
|
||||||
|
"Sincronizzazione di sicurezza fallita. Il link potrebbe essere scaduto.";
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
_isLoading = true;
|
_isLoading = true;
|
||||||
_errorMessage = null;
|
_errorMessage = null;
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 🥷 LA MOFFA DEL NINJA: Aggiorniamo la password dell'utente corrente
|
// Ora questo updateUser troverà la sessione viva e vegeta!
|
||||||
// che si è loggato in automatico grazie al token nell'URL
|
|
||||||
await Supabase.instance.client.auth.updateUser(
|
await Supabase.instance.client.auth.updateUser(
|
||||||
UserAttributes(password: _passwordController.text.trim()),
|
UserAttributes(password: _passwordController.text.trim()),
|
||||||
);
|
);
|
||||||
@@ -47,11 +98,6 @@ class _SetPasswordScreenState extends State<SetPasswordScreen> {
|
|||||||
backgroundColor: Colors.green,
|
backgroundColor: Colors.green,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Non serve forzare i redirect qui!
|
|
||||||
// Il SessionCubit nel costruttore ha un listener su 'onAuthStateChange'.
|
|
||||||
// Sentirà che l'utente ora è perfettamente valido, richiamerà 'initializeSession()'
|
|
||||||
// e lo scaricherà automaticamente nella pagina di Onboarding corretta.
|
|
||||||
}
|
}
|
||||||
} on AuthException catch (e) {
|
} on AuthException catch (e) {
|
||||||
setState(() {
|
setState(() {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import 'dart:developer';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:firebase_core/firebase_core.dart';
|
import 'package:firebase_core/firebase_core.dart';
|
||||||
@@ -48,9 +49,16 @@ import 'package:flux/features/settings/ui/settings.dart';
|
|||||||
import 'package:flutter_web_plugins/url_strategy.dart';
|
import 'package:flutter_web_plugins/url_strategy.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
|
String? initialRecoveryFragment;
|
||||||
void main() async {
|
void main() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
print("URL VERO ALL'AVVIO: ${Uri.base.toString()}");
|
final initialUri = Uri.base;
|
||||||
|
if (initialUri.fragment.contains('access_token=')) {
|
||||||
|
initialRecoveryFragment = initialUri.fragment;
|
||||||
|
log(
|
||||||
|
"Ninja attivato: Token catturato in cassaforte! $initialRecoveryFragment",
|
||||||
|
);
|
||||||
|
}
|
||||||
await dotenv.load(fileName: ".env");
|
await dotenv.load(fileName: ".env");
|
||||||
|
|
||||||
// Inizializza le dipendenze PRIMA di lanciare l'app
|
// Inizializza le dipendenze PRIMA di lanciare l'app
|
||||||
|
|||||||
Reference in New Issue
Block a user