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<String, dynamic> 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(<String, dynamic>{
|
|
'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<MyProfile> login(Map<String, dynamic> 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<void> logout() async {
|
|
final preferences = await SharedPreferences.getInstance();
|
|
preferences.remove('profile');
|
|
}
|
|
|
|
static Future<MyProfile> 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<bool> 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<RSAPrivateKey> getPrivateKey() async {
|
|
MyProfile profile = await MyProfile.getProfile();
|
|
if (profile.privateKey == null) {
|
|
throw Exception('Could not get privateKey');
|
|
}
|
|
return profile.privateKey!;
|
|
}
|
|
|
|
static Future<String> getBaseServerUrl() async {
|
|
final preferences = await SharedPreferences.getInstance();
|
|
return preferences.getString('server_url') ?? defaultServerUrl;
|
|
}
|
|
|
|
static setServerUrl(String url) async {
|
|
final preferences = await SharedPreferences.getInstance();
|
|
preferences.setString('server_url', url);
|
|
}
|
|
|
|
static Future<Uri> 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');
|
|
}
|
|
}
|
|
|