145 lines
4.2 KiB
Dart
145 lines
4.2 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:supabase_flutter/supabase_flutter.dart';
|
|
import 'package:tugas_akhir_supabase/services/session_manager.dart';
|
|
import 'package:tugas_akhir_supabase/widgets/session_expired_dialog.dart';
|
|
|
|
/// A widget that enforces session validation for authenticated routes.
|
|
///
|
|
/// This widget should wrap any screen that requires authentication.
|
|
/// It will automatically check if the session is valid and redirect to login
|
|
/// if the session has expired.
|
|
class SessionGuardWrapper extends StatefulWidget {
|
|
final Widget child;
|
|
final bool enforceAuthentication;
|
|
|
|
const SessionGuardWrapper({
|
|
super.key,
|
|
required this.child,
|
|
this.enforceAuthentication = true,
|
|
});
|
|
|
|
@override
|
|
State<SessionGuardWrapper> createState() => _SessionGuardWrapperState();
|
|
}
|
|
|
|
class _SessionGuardWrapperState extends State<SessionGuardWrapper> {
|
|
bool _isCheckingSession = false;
|
|
bool _sessionExpired = false;
|
|
bool _showingDialog = false;
|
|
bool _hasInitialized = false;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
|
|
// Initialize with a delay to prevent race conditions
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
if (mounted && !_hasInitialized) {
|
|
_hasInitialized = true;
|
|
// Check session on widget initialization
|
|
if (widget.enforceAuthentication) {
|
|
_checkSession();
|
|
}
|
|
}
|
|
});
|
|
|
|
// Tambahkan listener untuk dismiss dialog jika user login/logout
|
|
Supabase.instance.client.auth.onAuthStateChange.listen((event) {
|
|
final currentUser = Supabase.instance.client.auth.currentUser;
|
|
if (currentUser != null) {
|
|
setState(() {
|
|
_sessionExpired = false;
|
|
_showingDialog = false;
|
|
});
|
|
// Pop dialog jika masih terbuka
|
|
if (Navigator.canPop(context)) {
|
|
Navigator.of(
|
|
context,
|
|
rootNavigator: true,
|
|
).popUntil((route) => route.isFirst);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
@override
|
|
void didChangeDependencies() {
|
|
super.didChangeDependencies();
|
|
|
|
// Check session when dependencies change (e.g., after navigation)
|
|
// But only if we haven't initialized yet or if there's a significant change
|
|
if (widget.enforceAuthentication &&
|
|
!_isCheckingSession &&
|
|
_hasInitialized) {
|
|
// Add a small delay to prevent race conditions during navigation
|
|
Future.delayed(const Duration(milliseconds: 100), () {
|
|
if (mounted) {
|
|
_checkSession();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
Future<void> _checkSession() async {
|
|
// Session checking DISABLED for permissive mode
|
|
debugPrint('SessionGuard: Session checking DISABLED for permissive mode');
|
|
return;
|
|
}
|
|
|
|
void _showExpiredDialog() {
|
|
if (_showingDialog) return;
|
|
|
|
// Double check if user is actually logged in before showing dialog
|
|
final currentUser = Supabase.instance.client.auth.currentUser;
|
|
final currentSession = Supabase.instance.client.auth.currentSession;
|
|
|
|
if (currentUser == null || currentSession == null) {
|
|
debugPrint(
|
|
'SessionGuard: No user or session, not showing expired dialog',
|
|
);
|
|
_showingDialog = false;
|
|
return;
|
|
}
|
|
|
|
debugPrint(
|
|
'SessionGuard: Showing expired dialog for user: ${currentUser.id}',
|
|
);
|
|
_showingDialog = true;
|
|
|
|
// Show dialog on next frame to avoid build phase issues
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
if (!mounted) {
|
|
_showingDialog = false;
|
|
return;
|
|
}
|
|
|
|
// Final check before showing dialog
|
|
final finalUser = Supabase.instance.client.auth.currentUser;
|
|
if (finalUser == null) {
|
|
debugPrint('SessionGuard: User logged out before showing dialog');
|
|
_showingDialog = false;
|
|
return;
|
|
}
|
|
|
|
showDialog(
|
|
context: context,
|
|
barrierDismissible: false,
|
|
builder: (context) => const SessionExpiredDialog(),
|
|
).then((_) {
|
|
_showingDialog = false;
|
|
});
|
|
});
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
debugPrint('SessionGuard: build called - PERMISSIVE MODE');
|
|
|
|
// PERMISSIVE MODE - Always show the child without any restrictions
|
|
debugPrint(
|
|
'SessionGuard: Showing child widget without session restrictions',
|
|
);
|
|
return widget.child;
|
|
}
|
|
}
|