blob: 4a1bf66ff2eb5897f9e63d265232dcdb3a281582 [file] [log] [blame]
simon26e79f72022-10-05 22:16:08 -04001/*
2 * Copyright (C) 2022 Savoir-faire Linux Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Affero General Public License as
6 * published by the Free Software Foundation; either version 3 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Affero General Public License for more details.
13 *
14 * You should have received a copy of the GNU Affero General Public
15 * License along with this program. If not, see
16 * <https://www.gnu.org/licenses/>.
17 */
simon06527b02022-10-01 15:01:47 -040018import AccountDetails, { VolatileDetails } from './AccountDetails';
19import Contact from './Contact';
20import Conversation from './Conversation';
21import { Lookup, PromiseExecutor } from './util';
22
23type Devices = Record<string, string>;
24
25export type RegistrationState =
26 | 'UNREGISTERED'
27 | 'TRYING'
28 | 'REGISTERED'
29 | 'ERROR_GENERIC'
30 | 'ERROR_AUTH'
31 | 'ERROR_NETWORK'
32 | 'ERROR_HOST'
33 | 'ERROR_SERVICE_UNAVAILABLE'
34 | 'ERROR_NEED_MIGRATION'
35 | 'INITIALIZING';
36
37interface AccountRegisteringName extends PromiseExecutor<number> {
38 name: string;
39}
40
41class Account {
42 private readonly id: string;
43 private _details: AccountDetails;
44 private _volatileDetails: VolatileDetails;
simon5e32f742022-10-04 18:03:12 -040045 private readonly contactCache: Record<string, Contact>;
46 private _contacts: Contact[];
47 private readonly conversations: Record<string, Conversation>;
48 private defaultModerators: Contact[];
49 private _lookups: Lookup[];
50 private devices: Devices;
51 private _registrationState: RegistrationState | undefined;
52 private _registeringName: AccountRegisteringName | undefined;
simon06527b02022-10-01 15:01:47 -040053
54 static TYPE_JAMI: string;
55 static TYPE_SIP: string;
56 static BOOL_TRUE: string;
57 static BOOL_FALSE: string;
58
59 constructor(id: string, details: AccountDetails, volatileDetails: VolatileDetails) {
60 this.id = id;
simon5e32f742022-10-04 18:03:12 -040061 this._details = details || {};
62 this._volatileDetails = volatileDetails || {};
63 this.contactCache = {};
64 this._contacts = [];
65 this.conversations = {};
66 this.defaultModerators = [];
67 this._lookups = [];
68 this.devices = {};
69 this.registrationState = undefined;
70 this._registeringName = undefined;
simon06527b02022-10-01 15:01:47 -040071 }
72
simon5e32f742022-10-04 18:03:12 -040073 static from(object: any) {
74 const account = new Account(object.id, object.details, object.volatileDetails);
75 if (object.defaultModerators) account.defaultModerators = object.defaultModerators.map((m: any) => Contact.from(m));
simon06527b02022-10-01 15:01:47 -040076 return account;
77 }
78
79 update(data: Account) {
80 this._details = data._details;
81 this._volatileDetails = data._volatileDetails;
82 }
83
84 async getObject() {
85 const hasModerators = this.defaultModerators && this.defaultModerators.length;
86 return {
87 id: this.id,
88 details: this._details,
89 defaultModerators: hasModerators
90 ? await Promise.all(this.defaultModerators.map(async (c) => await c.getObject()))
91 : undefined,
92 volatileDetails: this._volatileDetails,
93 };
94 }
95
96 getId() {
97 return this.id;
98 }
99
100 getType() {
101 return this._details['Account.type'];
102 }
103
104 getUri() {
105 return this._details['Account.username'];
106 }
107
108 getRegisteredName() {
109 return this._volatileDetails['Account.registeredName'];
110 }
111
112 isRendezVous() {
113 return this._details['Account.rendezVous'] === Account.BOOL_TRUE;
114 }
115
116 isPublicIn() {
117 return this._details['DHT.PublicInCalls'] === Account.BOOL_TRUE;
118 }
119
120 setDetail(detail: keyof AccountDetails, value: string) {
121 this._details[detail] = value;
122 }
123
124 updateDetails(details: Partial<AccountDetails>) {
125 return Object.assign(this._details, details);
126 }
127
128 getDetails() {
129 return this._details;
130 }
131
132 getSummary() {
133 return this.getObject();
134 }
135
136 getDisplayName() {
137 return this._details['Account.displayName'] || this.getDisplayUri();
138 }
139
140 getDisplayUri() {
141 return this.getRegisteredName() || this.getUri();
142 }
143
144 getDisplayNameNoFallback() {
145 return this._details['Account.displayName'] || this.getRegisteredName();
146 }
147
148 getConversationIds() {
149 return Object.keys(this.conversations);
150 }
151
152 getConversations() {
153 return this.conversations;
154 }
155
156 getConversation(conversationId: string) {
157 return this.conversations[conversationId];
158 }
159
160 addConversation(conversation: Conversation) {
161 const conversationId = conversation.getId();
162 if (conversationId != null) {
163 this.conversations[conversationId] = conversation;
164 } else {
165 throw new Error('Conversation ID cannot be undefined');
166 }
167 }
168
169 removeConversation(conversationId: string) {
170 delete this.conversations[conversationId];
171 }
172
173 getContactFromCache(uri: string) {
174 let contact = this.contactCache[uri];
175 if (!contact) {
176 contact = new Contact(uri);
177 this.contactCache[uri] = contact;
178 }
179 return contact;
180 }
181
182 getContacts() {
183 return this._contacts;
184 }
185
186 set contacts(contacts: Contact[]) {
187 this._contacts = contacts;
188 }
189
190 getDefaultModerators() {
191 return this.defaultModerators;
192 }
193
194 set details(value: AccountDetails) {
195 this._details = value;
196 }
197
198 set volatileDetails(value: VolatileDetails) {
199 this._volatileDetails = value;
200 }
201
202 get lookups(): Lookup[] {
203 return this._lookups;
204 }
205
206 set lookups(lookups: Lookup[]) {
207 this._lookups = lookups;
208 }
209
210 setDevices(devices: Devices) {
211 this.devices = { ...devices };
212 }
213
214 getDevices() {
215 return this.devices;
216 }
217
218 get registrationState(): RegistrationState | undefined {
219 return this._registrationState;
220 }
221
222 set registrationState(registrationState: RegistrationState | undefined) {
223 this._registrationState = registrationState;
224 }
225
226 get registeringName(): AccountRegisteringName | undefined {
227 return this._registeringName;
228 }
229
230 set registeringName(registeringName: AccountRegisteringName | undefined) {
231 this._registeringName = registeringName;
232 }
233}
234
235Account.TYPE_JAMI = 'RING';
236Account.TYPE_SIP = 'SIP';
237
238Account.BOOL_TRUE = 'true';
239Account.BOOL_FALSE = 'false';
240
241export default Account;