feat: Implement role-based session management and refactor authentication flow

This commit is contained in:
Achintha Isuru
2026-02-17 15:10:10 -05:00
parent be40614274
commit 8ce37d2306
13 changed files with 138 additions and 210 deletions

View File

@@ -25,7 +25,9 @@ void main() async {
);
// Initialize session listener for Firebase Auth state changes
DataConnectService.instance.initializeAuthListener();
DataConnectService.instance.initializeAuthListener(
allowedRoles: <String>['STAFF', 'BOTH'], // Only allow users with STAFF or BOTH roles
);
runApp(
ModularApp(

View File

@@ -23,6 +23,7 @@ class SessionListener extends StatefulWidget {
class _SessionListenerState extends State<SessionListener> {
late StreamSubscription<SessionState> _sessionSubscription;
bool _sessionExpiredDialogShown = false;
bool _isInitialState = true;
@override
void initState() {
@@ -35,6 +36,8 @@ class _SessionListenerState extends State<SessionListener> {
.listen((SessionState state) {
_handleSessionChange(state);
});
debugPrint('[SessionListener] Initialized session listener');
}
void _handleSessionChange(SessionState state) {
@@ -45,8 +48,12 @@ class _SessionListenerState extends State<SessionListener> {
debugPrint(
'[SessionListener] Unauthenticated: Session expired or user logged out',
);
// Show expiration dialog if not already shown
if (!_sessionExpiredDialogShown) {
// On initial state (cold start), just proceed to login without dialog
// Only show dialog if user was previously authenticated (session expired)
if (_isInitialState) {
_isInitialState = false;
Modular.to.toGetStartedPage();
} else if (!_sessionExpiredDialogShown) {
_sessionExpiredDialogShown = true;
_showSessionExpiredDialog();
}
@@ -54,6 +61,7 @@ class _SessionListenerState extends State<SessionListener> {
case SessionStateType.authenticated:
// Session restored or user authenticated
_isInitialState = false;
_sessionExpiredDialogShown = false;
debugPrint('[SessionListener] Authenticated: ${state.userId}');
@@ -63,8 +71,14 @@ class _SessionListenerState extends State<SessionListener> {
case SessionStateType.error:
// Show error notification with option to retry or logout
debugPrint('[SessionListener] Session error: ${state.errorMessage}');
_showSessionErrorDialog(state.errorMessage ?? 'Session error occurred');
// Only show if not initial state (avoid showing on cold start)
if (!_isInitialState) {
debugPrint('[SessionListener] Session error: ${state.errorMessage}');
_showSessionErrorDialog(state.errorMessage ?? 'Session error occurred');
} else {
_isInitialState = false;
Modular.to.toInitialPage();
}
break;
case SessionStateType.loading:
@@ -135,7 +149,7 @@ class _SessionListenerState extends State<SessionListener> {
DataConnectService.instance.handleSignOut();
// Navigate to authentication
Modular.to.toGetStarted();
Modular.to.toInitialPage();
}
@override