feat: automatically sign out after 403 response

This commit is contained in:
sBubshait 2025-07-27 10:37:22 +03:00
parent e0ad0b8e29
commit a6babf18ac
5 changed files with 39 additions and 16 deletions

View File

@ -7,6 +7,8 @@ import 'services/notification_service.dart';
import 'services/auth_service.dart'; import 'services/auth_service.dart';
import 'services/user_service.dart'; import 'services/user_service.dart';
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
void main() async { void main() async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
@ -21,6 +23,7 @@ class MyApp extends StatelessWidget {
title: 'Wesal', title: 'Wesal',
theme: ThemeData(primarySwatch: Colors.blue, fontFamily: 'Roboto'), theme: ThemeData(primarySwatch: Colors.blue, fontFamily: 'Roboto'),
home: SplashScreen(), home: SplashScreen(),
navigatorKey: navigatorKey,
debugShowCheckedModeBanner: false, debugShowCheckedModeBanner: false,
); );
} }

View File

@ -1,7 +1,9 @@
import 'dart:convert'; import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import '../constants/api_constants.dart'; import '../constants/api_constants.dart';
import '../main.dart';
class AuthService { class AuthService {
static const FlutterSecureStorage _storage = FlutterSecureStorage(); static const FlutterSecureStorage _storage = FlutterSecureStorage();
@ -87,4 +89,13 @@ class AuthService {
static Future<void> clearUserData() async { static Future<void> clearUserData() async {
await _storage.delete(key: _userDataKey); await _storage.delete(key: _userDataKey);
} }
static Future<void> handleAuthenticationError() async {
await logout();
final context = navigatorKey.currentContext;
if (context != null && context.mounted) {
Navigator.of(context).pushNamedAndRemoveUntil('/', (route) => false);
}
}
} }

View File

@ -2,6 +2,7 @@ import 'dart:convert';
import '../constants/api_constants.dart'; import '../constants/api_constants.dart';
import '../models/invitation_models.dart'; import '../models/invitation_models.dart';
import 'http_service.dart'; import 'http_service.dart';
import 'auth_service.dart';
class InvitationsService { class InvitationsService {
static Future<Map<String, dynamic>> getAllInvitations() async { static Future<Map<String, dynamic>> getAllInvitations() async {
@ -23,16 +24,12 @@ class InvitationsService {
invitationsResponse.message ?? 'Failed to fetch invitations', invitationsResponse.message ?? 'Failed to fetch invitations',
}; };
} }
} else if (response.statusCode == 401) { } else if (response.statusCode == 401 || response.statusCode == 403) {
await AuthService.handleAuthenticationError();
return { return {
'success': false, 'success': false,
'message': 'Session expired. Please login again.', 'message': 'Session expired. Please login again.',
}; };
} else if (response.statusCode == 403) {
return {
'success': false,
'message': 'Access denied. Invalid credentials.',
};
} else { } else {
return { return {
'success': false, 'success': false,

View File

@ -1,15 +1,15 @@
import 'dart:convert'; import 'dart:convert';
import '../models/post_models.dart'; import '../models/post_models.dart';
import 'http_service.dart'; import 'http_service.dart';
import 'auth_service.dart';
class PostService { class PostService {
static Future<Map<String, dynamic>> getAllPosts() async { static Future<Map<String, dynamic>> getAllPosts() async {
try { try {
final response = await HttpService.get('/posts/all'); final response = await HttpService.get('/posts/all');
final responseData = jsonDecode(response.body);
if (response.statusCode == 200) { if (response.statusCode == 200) {
final responseData = jsonDecode(response.body);
return { return {
'success': responseData['status'] ?? false, 'success': responseData['status'] ?? false,
'message': responseData['message'] ?? '', 'message': responseData['message'] ?? '',
@ -19,12 +19,28 @@ class PostService {
.toList() ?? .toList() ??
[], [],
}; };
} else { } else if (response.statusCode == 401 || response.statusCode == 403) {
await AuthService.handleAuthenticationError();
return { return {
'success': false, 'success': false,
'message': responseData['message'] ?? 'Failed to fetch posts', 'message': 'Session expired. Please login again.',
'posts': <Post>[], 'posts': <Post>[],
}; };
} else {
try {
final responseData = jsonDecode(response.body);
return {
'success': false,
'message': responseData['message'] ?? 'Failed to fetch posts',
'posts': <Post>[],
};
} catch (e) {
return {
'success': false,
'message': 'Server error (${response.statusCode})',
'posts': <Post>[],
};
}
} }
} catch (e) { } catch (e) {
print('Error fetching posts: $e'); print('Error fetching posts: $e');

View File

@ -21,16 +21,12 @@ class UserService {
final data = jsonDecode(response.body); final data = jsonDecode(response.body);
await AuthService.saveUserData(data); await AuthService.saveUserData(data);
return {'success': true, 'data': data}; return {'success': true, 'data': data};
} else if (response.statusCode == 401) { } else if (response.statusCode == 401 || response.statusCode == 403) {
await AuthService.handleAuthenticationError();
return { return {
'success': false, 'success': false,
'message': 'Session expired. Please login again.', 'message': 'Session expired. Please login again.',
}; };
} else if (response.statusCode == 403) {
return {
'success': false,
'message': 'Access denied. Invalid credentials.',
};
} else { } else {
return { return {
'success': false, 'success': false,