]> git.proxmox.com Git - flutter/proxmox_login_manager.git/blob - lib/proxmox_login_model.dart
tree-wide: use super-initializer parameters where possible
[flutter/proxmox_login_manager.git] / lib / proxmox_login_model.dart
1 import 'package:built_collection/built_collection.dart';
2 import 'package:built_value/built_value.dart';
3 import 'package:built_value/serializer.dart';
4 import 'package:proxmox_login_manager/proxmox_general_settings_model.dart';
5 import 'package:proxmox_login_manager/serializers.dart';
6 import 'package:shared_preferences/shared_preferences.dart';
7 import 'dart:convert';
8 import 'package:proxmox_dart_api_client/proxmox_dart_api_client.dart'
9 as proxclient;
10 part 'proxmox_login_model.g.dart';
11
12 abstract class ProxmoxLoginStorage
13 implements Built<ProxmoxLoginStorage, ProxmoxLoginStorageBuilder> {
14 BuiltList<ProxmoxLoginModel>? get logins;
15
16 ProxmoxLoginStorage._();
17 factory ProxmoxLoginStorage(
18 [void Function(ProxmoxLoginStorageBuilder)? updates]) =
19 _$ProxmoxLoginStorage;
20
21 Object? toJson() {
22 return serializers.serializeWith(ProxmoxLoginStorage.serializer, this);
23 }
24
25 static ProxmoxLoginStorage? fromJson(Object? json) {
26 return serializers.deserializeWith(ProxmoxLoginStorage.serializer, json);
27 }
28
29 static Serializer<ProxmoxLoginStorage> get serializer =>
30 _$proxmoxLoginStorageSerializer;
31
32 static Future<ProxmoxLoginStorage?> fromLocalStorage() async {
33 final SharedPreferences prefs = await SharedPreferences.getInstance();
34 if (prefs.containsKey('ProxmoxLoginList')) {
35 final decodedJson = json.decode(prefs.getString('ProxmoxLoginList')!);
36 return fromJson(decodedJson);
37 }
38 return ProxmoxLoginStorage();
39 }
40
41 Future<void> saveToDisk() async {
42 final SharedPreferences prefs = await SharedPreferences.getInstance();
43 prefs.setString('ProxmoxLoginList', json.encode(toJson()));
44 }
45
46 Future<proxclient.ProxmoxApiClient> recoverLatestSession() async {
47 final latestSession = logins!.singleWhere((e) => e.ticket!.isNotEmpty);
48 final settings = await ProxmoxGeneralSettingsModel.fromLocalStorage();
49 final apiClient = await proxclient.authenticate(latestSession.fullUsername,
50 latestSession.ticket!, latestSession.origin!, settings.sslValidation!);
51 return apiClient;
52 }
53
54 Future<void> invalidateAllSessions() async {
55 final invalidatedList =
56 logins!.map((e) => e.rebuild((login) => login..ticket = ''));
57 await rebuild((e) => e.logins.replace(invalidatedList)).saveToDisk();
58 }
59 }
60
61 abstract class ProxmoxLoginModel
62 implements Built<ProxmoxLoginModel, ProxmoxLoginModelBuilder> {
63 Uri? get origin;
64
65 String? get username;
66
67 String? get realm;
68
69 bool? get passwordSaved;
70
71 ProxmoxProductType? get productType;
72
73 String? get ticket;
74
75 /// The username with the corresponding realm e.g. root@pam
76 String get fullUsername => '$username@$realm';
77
78 bool get activeSession =>
79 ticket != null && ticket!.isNotEmpty && !ticketExpired();
80
81 String? get hostname;
82
83 String get fullHostname {
84 var location = origin;
85 if (location == null) {
86 return 'Unknown';
87 }
88 var name = hostname;
89 if (name == null || name.isEmpty) {
90 return location.host;
91 }
92 if (location.host == name) {
93 return name;
94 }
95 return '${location.host} - $hostname';
96 }
97
98 String? get identifier {
99 if (origin == null) {
100 return null;
101 }
102
103 var host = origin!.host;
104 var port = origin!.port;
105 return '$username@$realm@$host:$port';
106 }
107
108 ProxmoxLoginModel._();
109
110 factory ProxmoxLoginModel(
111 [void Function(ProxmoxLoginModelBuilder)? updates]) = _$ProxmoxLoginModel;
112
113 Map<String, dynamic>? toJson() {
114 return serializers.serializeWith(ProxmoxLoginModel.serializer, this)
115 as Map<String, dynamic>?;
116 }
117
118 static ProxmoxLoginModel? fromJson(Map<String, dynamic> json) {
119 return serializers.deserializeWith(ProxmoxLoginModel.serializer, json);
120 }
121
122 static Serializer<ProxmoxLoginModel> get serializer =>
123 _$proxmoxLoginModelSerializer;
124
125 bool ticketExpired() {
126 final ticketRegex = RegExp(r'(PVE|PMG)(?:QUAR)?:(?:(\S+):)?([A-Z0-9]{8})::')
127 .firstMatch(ticket!)!;
128 final time = DateTime.fromMillisecondsSinceEpoch(
129 int.parse(ticketRegex.group(3)!, radix: 16) * 1000);
130 return DateTime.now().isAfter(time.add(const Duration(hours: 1)));
131 }
132 }
133
134 class ProxmoxProductType extends EnumClass {
135 static const ProxmoxProductType pve = _$pve;
136 static const ProxmoxProductType pmg = _$pmg;
137 static const ProxmoxProductType pbs = _$pbs;
138
139 const ProxmoxProductType._(super.name);
140
141 static BuiltSet<ProxmoxProductType> get values => _$ProxmoxProductTypeValues;
142 static ProxmoxProductType valueOf(String name) =>
143 _$ProxmoxProductTypeValueOf(name);
144
145 static Serializer<ProxmoxProductType> get serializer =>
146 _$proxmoxProductTypeSerializer;
147 }