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

View File

@ -1,7 +1,9 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:http/http.dart' as http;
import '../constants/api_constants.dart';
import '../main.dart';
class AuthService {
static const FlutterSecureStorage _storage = FlutterSecureStorage();
@ -87,4 +89,13 @@ class AuthService {
static Future<void> clearUserData() async {
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 '../models/invitation_models.dart';
import 'http_service.dart';
import 'auth_service.dart';
class InvitationsService {
static Future<Map<String, dynamic>> getAllInvitations() async {
@ -23,16 +24,12 @@ class InvitationsService {
invitationsResponse.message ?? 'Failed to fetch invitations',
};
}
} else if (response.statusCode == 401) {
} else if (response.statusCode == 401 || response.statusCode == 403) {
await AuthService.handleAuthenticationError();
return {
'success': false,
'message': 'Session expired. Please login again.',
};
} else if (response.statusCode == 403) {
return {
'success': false,
'message': 'Access denied. Invalid credentials.',
};
} else {
return {
'success': false,

View File

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

View File

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