import 'dart:convert'; import 'dart:io'; import 'package:Envelope/utils/storage/get_file.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:pointycastle/impl.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '/utils/encryption/aes_helper.dart'; import '/utils/encryption/crypto_utils.dart'; // TODO: Replace this with the prod url when server is deployed String defaultServerUrl = dotenv.env['SERVER_URL'] ?? 'http://localhost:8080/'; class MyProfile { String id; String username; String? friendId; RSAPrivateKey? privateKey; RSAPublicKey? publicKey; String? symmetricKey; DateTime? loggedInAt; File? image; String? imageLink; String messageExpiryDefault = 'no_expiry'; MyProfile({ required this.id, required this.username, this.friendId, this.privateKey, this.publicKey, this.symmetricKey, this.loggedInAt, this.image, this.imageLink, required this.messageExpiryDefault, }); factory MyProfile._fromJson(Map json) { DateTime loggedInAt = DateTime.now(); if (json.containsKey('logged_in_at')) { loggedInAt = DateTime.parse(json['logged_in_at']); } RSAPrivateKey privateKey = CryptoUtils.rsaPrivateKeyFromPem(json['asymmetric_private_key']); RSAPublicKey publicKey = CryptoUtils.rsaPublicKeyFromPem(json['asymmetric_public_key']); return MyProfile( id: json['user_id'], username: json['username'], privateKey: privateKey, publicKey: publicKey, symmetricKey: json['symmetric_key'], loggedInAt: loggedInAt, messageExpiryDefault: json['message_expiry_default'], image: json['file'] != null ? File(json['file']) : null, imageLink: json['image_link'], ); } @override String toString() { return ''' user_id: $id username: $username logged_in_at: $loggedInAt public_key: $publicKey private_key: $privateKey '''; } String toJson() { return jsonEncode({ 'user_id': id, 'username': username, 'asymmetric_private_key': privateKey != null ? CryptoUtils.encodeRSAPrivateKeyToPem(privateKey!) : null, 'asymmetric_public_key': publicKey != null ? CryptoUtils.encodeRSAPublicKeyToPem(publicKey!) : null, 'symmetric_key': symmetricKey, 'logged_in_at': loggedInAt?.toIso8601String(), 'message_expiry_default': messageExpiryDefault, 'file': image?.path, 'image_link': imageLink, }); } static Future login(Map json, String password) async { json['asymmetric_private_key'] = AesHelper.aesDecrypt( password, base64.decode(json['asymmetric_private_key']) ); json['symmetric_key'] = base64.encode(CryptoUtils.rsaDecrypt( base64.decode(json['symmetric_key']), CryptoUtils.rsaPrivateKeyFromPem(json['asymmetric_private_key']), )); if (json['image_link'] != '') { File profileIcon = await getFile( '$defaultServerUrl/files/${['image_link']}', json['user_id'], json['symmetric_key'], ); json['file'] = profileIcon.path; } MyProfile profile = MyProfile._fromJson(json); final preferences = await SharedPreferences.getInstance(); preferences.setString('profile', profile.toJson()); return profile; } static Future logout() async { final preferences = await SharedPreferences.getInstance(); preferences.remove('profile'); } static Future getProfile() async { final preferences = await SharedPreferences.getInstance(); String? profileJson = preferences.getString('profile'); if (profileJson == null) { throw Exception('No profile'); } return MyProfile._fromJson(json.decode(profileJson)); } static Future isLoggedIn() async { MyProfile profile = await MyProfile.getProfile(); if (profile.loggedInAt == null) { return false; } return profile.loggedInAt!.add(const Duration(hours: 12)).isAfter( (DateTime.now()) ); } static Future getPrivateKey() async { MyProfile profile = await MyProfile.getProfile(); if (profile.privateKey == null) { throw Exception('Could not get privateKey'); } return profile.privateKey!; } static setServerUrl(String url) async { final preferences = await SharedPreferences.getInstance(); preferences.setString('server_url', url); } static Future getServerUrl(String path) async { final preferences = await SharedPreferences.getInstance(); String? baseUrl = preferences.getString('server_url'); if (baseUrl == null) { setServerUrl(defaultServerUrl); return Uri.parse('$defaultServerUrl$path'); } return Uri.parse('$baseUrl$path'); } }