Files
hartmann-foto_documentation/hartmann-foto-documentation-frontend/lib/controller/login_controller.dart
2026-02-03 09:51:03 +01:00

103 lines
3.3 KiB
Dart

import 'dart:convert' show base64, utf8;
import 'dart:convert' show jsonDecode, jsonEncode;
import 'package:fotodocumentation/controller/base_controller.dart';
import 'package:fotodocumentation/dto/jwt_token_pair_dto.dart';
import 'package:fotodocumentation/main.dart' show logger;
import 'package:fotodocumentation/utils/di_container.dart';
import 'package:fotodocumentation/utils/jwt_token_storage.dart';
import 'package:http/http.dart' as http;
typedef AuthenticateReply = ({JwtTokenPairDto? jwtTokenPairDto});
abstract interface class LoginController {
Future<AuthenticateReply> authenticate(String username, String password);
Future<bool> refreshAccessToken();
bool isUsingJwtAuth();
}
class LoginControllerImpl extends BaseController implements LoginController {
final String path = "login";
JwtTokenStorage get _jwtTokenStorage => DiContainer.get();
@override
Future<AuthenticateReply> authenticate(String username, String password) async {
http.Client client = httpClientUtils.client;
try {
Header cred = _getLoginHeader(username, password);
String uriStr = '${uriUtils.getBaseUrl()}$path';
Uri uri = Uri.parse(uriStr);
var response = await client.get(uri, headers: {cred.name: cred.value});
if (response.statusCode == 200) {
final Map<String, dynamic> data = Map.castFrom(jsonDecode(response.body));
final tokenPair = JwtTokenPairDto.fromJson(data);
// Store tokens securely
_jwtTokenStorage.saveTokens(tokenPair.accessToken, tokenPair.refreshToken);
// Load user data using the new token
return (jwtTokenPairDto: tokenPair);
} else {
logger.e('Authentication failed: ${response.statusCode} ${response.body}');
return (jwtTokenPairDto: null);
}
} catch (e) {
logger.e("Authentication error: $e");
return (jwtTokenPairDto: null);
}
}
@override
Future<bool> refreshAccessToken() async {
try {
final refreshToken = _jwtTokenStorage.getRefreshToken();
if (refreshToken == null) {
logger.i('No refresh token available');
return false;
}
String uriStr = '${uriUtils.getBaseUrl()}$path/login/refresh';
Uri uri = Uri.parse(uriStr);
final response = await http.post(
uri,
headers: {'Content-Type': 'application/json'},
body: jsonEncode({
'refreshToken': refreshToken,
}),
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
final newAccessToken = data['accessToken'] as String;
// Update only the access token (keep same refresh token)
_jwtTokenStorage.updateAccessToken(newAccessToken);
logger.d('Access token refreshed successfully');
return true;
} else {
logger.d('Token refresh failed: ${response.statusCode} ${response.body}');
return false;
}
} catch (e) {
logger.e('Token refresh error: $e');
return false;
}
}
@override
bool isUsingJwtAuth() {
return _jwtTokenStorage.hasTokens();
}
Header _getLoginHeader(String username, String password) {
String combined = "$username:$password";
final bytes = utf8.encode(combined);
String asBase64 = base64.encode(bytes);
return Header("Authorization", "Basic $asBase64");
}
}