193 lines
6.1 KiB
Dart
Executable File
193 lines
6.1 KiB
Dart
Executable File
import 'dart:convert';
|
|
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
|
import 'package:go_router/go_router.dart';
|
|
import 'package:http/http.dart' as http;
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
import '../../config/environment.dart';
|
|
import '../../customAppBar/toastHelper.dart';
|
|
import '../../logger.dart';
|
|
import '../../router/app_router.dart';
|
|
import 'SessionManager.dart';
|
|
import 'web_session_storage.dart';
|
|
|
|
class TokenService {
|
|
static const postTokenKey = 'post_token';
|
|
static const preTokenKey = 'pre_token';
|
|
|
|
static const _secureStorage = FlutterSecureStorage(
|
|
iOptions: IOSOptions(
|
|
accessibility: KeychainAccessibility.first_unlock_this_device,
|
|
),
|
|
);
|
|
|
|
/// Web: tokens live only in [sessionStorage] (tab-scoped). Mobile: secure storage.
|
|
static Future<void> saveTokens({String? postToken, String? preToken}) async {
|
|
if (kIsWeb) {
|
|
if (postToken != null) {
|
|
WebSessionStorage.write(postTokenKey, postToken);
|
|
}
|
|
if (preToken != null) {
|
|
WebSessionStorage.write(preTokenKey, preToken);
|
|
}
|
|
} else {
|
|
if (postToken != null) {
|
|
await _secureStorage.write(key: postTokenKey, value: postToken);
|
|
}
|
|
if (preToken != null) {
|
|
await _secureStorage.write(key: preTokenKey, value: preToken);
|
|
}
|
|
}
|
|
}
|
|
|
|
static Future<String?> getPostToken() async {
|
|
if (kIsWeb) {
|
|
return WebSessionStorage.read(postTokenKey);
|
|
}
|
|
return _secureStorage.read(key: postTokenKey);
|
|
}
|
|
|
|
static Future<String?> getPreToken() async {
|
|
if (kIsWeb) {
|
|
return WebSessionStorage.read(preTokenKey);
|
|
}
|
|
return _secureStorage.read(key: preTokenKey);
|
|
}
|
|
|
|
/// Clears auth tokens. On web, clears entire [sessionStorage] (logout / session end).
|
|
static Future<void> clearTokens() async {
|
|
if (kIsWeb) {
|
|
WebSessionStorage.clearAll();
|
|
} else {
|
|
await _secureStorage.delete(key: postTokenKey);
|
|
await _secureStorage.delete(key: preTokenKey);
|
|
}
|
|
}
|
|
|
|
static Future<bool> hasValidToken() async {
|
|
final post = await getPostToken();
|
|
final pre = await getPreToken();
|
|
return (post != null && post.isNotEmpty) ||
|
|
(pre != null && pre.isNotEmpty);
|
|
}
|
|
|
|
/// Post token → home; pre-only → enrollment ([empDetails]).
|
|
static Future<String> defaultRouteForStoredTokens() async {
|
|
final post = await getPostToken();
|
|
if (post != null && post.isNotEmpty) return '/home';
|
|
final pre = await getPreToken();
|
|
if (pre != null && pre.isNotEmpty) return '/empDetails';
|
|
return '/login';
|
|
}
|
|
|
|
/// Clears auth tokens that older web builds stored in SharedPreferences (localStorage).
|
|
/// Call once at startup so they cannot be mistaken for a valid session.
|
|
static Future<void> clearLegacyWebAuthFromSharedPreferences() async {
|
|
if (!kIsWeb) return;
|
|
final p = await SharedPreferences.getInstance();
|
|
await p.remove(postTokenKey);
|
|
await p.remove(preTokenKey);
|
|
}
|
|
|
|
Future<String?> checkLoginPin() async {
|
|
try {
|
|
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
|
final empMobileNo = prefs.getString('empMobileNo');
|
|
final empEmailid = prefs.getString('empEmailid');
|
|
|
|
var params = <String, dynamic>{};
|
|
if (empMobileNo != null && empMobileNo.isNotEmpty) {
|
|
params = {'mobile_number': empMobileNo};
|
|
} else if (empEmailid != null && empEmailid.isNotEmpty) {
|
|
params = {'email_id': empEmailid};
|
|
}
|
|
|
|
final response = await http.post(
|
|
Uri.parse(Environment.apiUrlEnrollment + 'checkMpin'),
|
|
body: json.encode(params),
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'APP-SIGNATURE': 'nhance-2025-signature-T8f6gV9k5fK2wf5V5c4vId3b0J8z6cAm2x8Y',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
Map<String, dynamic> data = json.decode(response.body);
|
|
|
|
if (data['status'] == 'success') {
|
|
if (data['data'] != null) {
|
|
prefs.setString('mpinText', data['data']);
|
|
}
|
|
if (data['Mpin'] != null) {
|
|
prefs.setString('mpin', data['Mpin']);
|
|
}
|
|
if (data['is_biometric_enabled'] != null) {
|
|
prefs.setString(
|
|
'is_biometric_enabled', data['is_biometric_enabled']);
|
|
}
|
|
if (data['is_mpin_skipped'] != null) {
|
|
prefs.setString('is_mpin_skipped', data['is_mpin_skipped']);
|
|
return data['is_mpin_skipped'].toString();
|
|
}
|
|
}
|
|
} else {
|
|
logDebug('checkLoginPin API failed: ${response.statusCode}');
|
|
return null;
|
|
}
|
|
} catch (e) {
|
|
logDebug('checkLoginPin error: $e');
|
|
return null;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
void _goAfterLogout(BuildContext context, String location) {
|
|
if (context.mounted && GoRouter.maybeOf(context) != null) {
|
|
context.go(location);
|
|
} else {
|
|
navigateAppTo(location);
|
|
}
|
|
}
|
|
|
|
Future<void> logout(BuildContext context) async {
|
|
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
|
|
|
String? mobileNumber = prefs.getString('empMobileNo');
|
|
String? mailID = prefs.getString('empEmailid');
|
|
|
|
final postToken = await getPostToken();
|
|
final hasPostToken = postToken != null && postToken.isNotEmpty;
|
|
|
|
String? isMpinSkipped;
|
|
if (!kIsWeb && hasPostToken) {
|
|
isMpinSkipped = await checkLoginPin();
|
|
}
|
|
logDebug('isMpinSkipped $isMpinSkipped hasPostToken $hasPostToken');
|
|
|
|
await SessionManager().clear();
|
|
|
|
if (kIsWeb) {
|
|
await prefs.clear();
|
|
_goAfterLogout(context, '/login');
|
|
} else {
|
|
if (mobileNumber != null) {
|
|
await prefs.setString('empMobileNo', mobileNumber);
|
|
}
|
|
if (mailID != null) {
|
|
await prefs.setString('empEmailid', mailID);
|
|
}
|
|
if (isMpinSkipped != null) {
|
|
await prefs.setString('is_mpin_skipped', isMpinSkipped);
|
|
}
|
|
if (hasPostToken && isMpinSkipped != null && isMpinSkipped == '0') {
|
|
_goAfterLogout(context, '/pinPage');
|
|
} else {
|
|
_goAfterLogout(context, '/login');
|
|
}
|
|
}
|
|
}
|
|
}
|