added frontend

This commit is contained in:
verboomp
2026-01-21 16:08:09 +01:00
parent d2e6f5164a
commit b3de3eec8c
74 changed files with 4938 additions and 26 deletions

View File

@@ -0,0 +1,102 @@
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();
Future<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
await _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 = await _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)
await _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
Future<bool> isUsingJwtAuth() async {
return await _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");
}
}