@communecter/cocolight-api-client 1.0.9 → 1.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +281 -1
- package/dist/405.cocolight-api-client.browser.js +1 -0
- package/dist/405.cocolight-api-client.cjs +1 -0
- package/dist/790.cocolight-api-client.mjs.js +1 -0
- package/dist/cocolight-api-client.browser.js +3 -3
- package/dist/cocolight-api-client.cjs +1 -1
- package/dist/cocolight-api-client.mjs.js +1 -1
- package/package.json +4 -2
- package/src/Api.js +59 -22
- package/src/ApiClient.js +95 -31
- package/src/api/News.js +129 -88
- package/src/api/Organization.js +248 -166
- package/src/api/Project.js +263 -172
- package/src/api/User.js +355 -49
- package/src/api/UserApi.js +25 -2
- package/src/endpoints.module.js +1 -1
- package/src/index.js +3 -1
- package/src/mixin/DraftStateMixin.js +176 -0
- package/src/mixin/EntityMixin.js +96 -35
- package/src/mixin/MutualEntityMixin.js +48 -0
- package/src/mixin/NewsMixin.js +35 -1
- package/src/mixin/UtilMixin.js +49 -1
- package/src/utils/FileStorageStrategy.node.js +60 -0
- package/src/utils/TokenStorage.js +93 -0
- package/src/utils/createDefaultTokenStorageStrategy.js +45 -0
package/src/api/User.js
CHANGED
|
@@ -1,34 +1,67 @@
|
|
|
1
|
-
import { ApiResponseError } from "../error.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { NewsMixin } from "../mixin/NewsMixin.js";
|
|
1
|
+
import { ApiError, ApiResponseError } from "../error.js";
|
|
2
|
+
import { DraftStateMixin } from "../mixin/DraftStateMixin.js";
|
|
3
|
+
import { MutualEntityMixin } from "../mixin/MutualEntityMixin.js";
|
|
5
4
|
import { UserMixin } from "../mixin/UserMixin.js";
|
|
6
5
|
import { UtilMixin } from "../mixin/UtilMixin.js";
|
|
7
6
|
|
|
8
7
|
// User.js
|
|
9
8
|
export class User {
|
|
10
|
-
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
|
|
9
|
+
#draftData = {};
|
|
10
|
+
#initialDraftData = {};
|
|
11
|
+
#serverData = null;
|
|
12
|
+
|
|
13
|
+
static entityType = "citoyens";
|
|
14
|
+
|
|
15
|
+
static SCHEMA_CONSTANTS = [
|
|
16
|
+
"UPDATE_BLOCK_DESCRIPTION",
|
|
17
|
+
"UPDATE_BLOCK_INFO",
|
|
18
|
+
"UPDATE_BLOCK_SOCIAL",
|
|
19
|
+
"UPDATE_BLOCK_LOCALITY",
|
|
20
|
+
"UPDATE_BLOCK_SLUG",
|
|
21
|
+
"PROFIL_IMAGE"
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
static UPDATE_BLOCKS = new Map([
|
|
25
|
+
["UPDATE_BLOCK_DESCRIPTION", "updateDescription"],
|
|
26
|
+
["UPDATE_BLOCK_SOCIAL", "updateSocial"],
|
|
27
|
+
["UPDATE_BLOCK_LOCALITY", "updateLocality"],
|
|
28
|
+
["UPDATE_BLOCK_INFO", "updateInfo"],
|
|
29
|
+
["UPDATE_BLOCK_SLUG", "updateSlug"],
|
|
30
|
+
["PROFIL_IMAGE", "updateImageProfil"]
|
|
31
|
+
]);
|
|
14
32
|
|
|
15
33
|
/**
|
|
16
34
|
* Crée une instance de User.
|
|
17
|
-
*
|
|
18
|
-
* @param {
|
|
19
|
-
* @param {Object}
|
|
20
|
-
* @param {
|
|
21
|
-
* @param {
|
|
35
|
+
*
|
|
36
|
+
* @param {ApiClient} apiClient - Le client API connecté.
|
|
37
|
+
* @param {Object} data - Données initiales (peuvent inclure `id`, `slug`, etc.).
|
|
38
|
+
* @param {string} [data.id] - ID de l'utilisateur.
|
|
39
|
+
* @param {string} [data.slug] - Slug de l'utilisateur.
|
|
40
|
+
* @param {Object} deps - Dépendances injectées.
|
|
41
|
+
* @param {function|object} deps.EndpointApi - Classe ou instance de EndpointApi.
|
|
42
|
+
* @param {function} deps.Organization - Classe Organization.
|
|
43
|
+
* @param {function} deps.Project - Classe Project.
|
|
44
|
+
* @param {function} deps.News - Classe News.
|
|
45
|
+
*
|
|
46
|
+
* @throws {ApiError} - Si des dépendances nécessaires sont manquantes ou invalides.
|
|
22
47
|
*/
|
|
23
48
|
|
|
24
|
-
constructor(apiClient,
|
|
49
|
+
constructor(apiClient, data = {}, deps = {}) {
|
|
50
|
+
this.__entityTag = "User";
|
|
51
|
+
|
|
25
52
|
if(!deps.EndpointApi){
|
|
26
|
-
throw new
|
|
53
|
+
throw new ApiError("EndpointApi class must be injected to avoid circular dependency.");
|
|
27
54
|
}
|
|
28
|
-
if (!id && !slug) {
|
|
29
|
-
throw new
|
|
55
|
+
if (!data?.id && !data?.slug) {
|
|
56
|
+
throw new ApiError("Vous devez fournir un id ou un slug pour créer un User.");
|
|
30
57
|
}
|
|
58
|
+
|
|
59
|
+
if (!deps.Organization) throw new ApiError("Organization class must be injected.");
|
|
60
|
+
if (!deps.Project) throw new ApiError("Project class must be injected.");
|
|
61
|
+
if (!deps.News) throw new ApiError("News class must be injected.");
|
|
62
|
+
|
|
31
63
|
this.apiClient = apiClient;
|
|
64
|
+
|
|
32
65
|
this.deps = deps;
|
|
33
66
|
|
|
34
67
|
// Gérer les deux cas : fonction constructeur ou instance
|
|
@@ -37,47 +70,59 @@ export class User {
|
|
|
37
70
|
} else if (typeof deps.EndpointApi === "object") {
|
|
38
71
|
this.endpointApi = deps.EndpointApi;
|
|
39
72
|
} else {
|
|
40
|
-
throw new
|
|
73
|
+
throw new ApiError("deps.EndpointApi doit être une classe ou une instance valide.");
|
|
41
74
|
}
|
|
42
|
-
|
|
43
|
-
this.#
|
|
44
|
-
|
|
45
|
-
|
|
75
|
+
|
|
76
|
+
this.#serverData = null;
|
|
77
|
+
|
|
78
|
+
const { draft, proxy } = this.buildDraftAndProxy({
|
|
79
|
+
data: { ...data, ...this.defaultFields },
|
|
80
|
+
serverData: this.#serverData,
|
|
81
|
+
constant: User.SCHEMA_CONSTANTS,
|
|
82
|
+
apiClient: this.apiClient,
|
|
83
|
+
transforms: this.transforms,
|
|
84
|
+
removeFields: this.removeFields
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
this.#initialDraftData = JSON.parse(JSON.stringify(draft)); // snapshot propre
|
|
88
|
+
this.#draftData = draft;
|
|
89
|
+
this.data = proxy;
|
|
46
90
|
}
|
|
47
|
-
|
|
48
|
-
// Getters en lecture seule pour chaque propriété
|
|
91
|
+
|
|
49
92
|
get id() {
|
|
50
|
-
return this.#id;
|
|
93
|
+
return this.#draftData.id || null;
|
|
51
94
|
}
|
|
52
95
|
|
|
53
96
|
_id(newId) {
|
|
54
|
-
this.#id = newId;
|
|
97
|
+
this.#draftData.id = newId;
|
|
55
98
|
}
|
|
56
|
-
|
|
99
|
+
|
|
57
100
|
get slug() {
|
|
58
|
-
return this.#slug;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
_slug(newSlug) {
|
|
62
|
-
this.#slug = newSlug;
|
|
101
|
+
return this.#draftData.slug || null;
|
|
63
102
|
}
|
|
64
103
|
|
|
65
104
|
get isConnected() {
|
|
66
105
|
return this.apiClient.isConnected;
|
|
67
106
|
}
|
|
68
107
|
|
|
69
|
-
// Getter pour accéder aux données
|
|
70
|
-
get data() {
|
|
71
|
-
return this.#data;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Méthode interne qui permet de mettre à jour les données
|
|
75
108
|
_setData(newData) {
|
|
76
|
-
this.#
|
|
109
|
+
this.#serverData = { ...newData };
|
|
110
|
+
|
|
111
|
+
const { draft, proxy } = this.buildDraftAndProxy({
|
|
112
|
+
data: { ...newData, ...this.defaultFields },
|
|
113
|
+
serverData: this.#serverData,
|
|
114
|
+
constant: User.SCHEMA_CONSTANTS,
|
|
115
|
+
apiClient: this.apiClient,
|
|
116
|
+
transforms: this.transforms,
|
|
117
|
+
removeFields: this.removeFields
|
|
118
|
+
});
|
|
119
|
+
this.#initialDraftData = JSON.parse(JSON.stringify(draft));
|
|
120
|
+
this.#draftData = draft;
|
|
121
|
+
this.data = proxy;
|
|
77
122
|
}
|
|
78
123
|
|
|
79
124
|
getEntityType() {
|
|
80
|
-
return
|
|
125
|
+
return User.entityType;
|
|
81
126
|
}
|
|
82
127
|
|
|
83
128
|
get userId() {
|
|
@@ -88,6 +133,23 @@ export class User {
|
|
|
88
133
|
return this.isConnected && this.userId === this.id;
|
|
89
134
|
}
|
|
90
135
|
|
|
136
|
+
get draftData() {
|
|
137
|
+
return this.#draftData;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
get initialDraftData() {
|
|
141
|
+
return this.#initialDraftData;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
get serverData() {
|
|
145
|
+
return this.#serverData;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
async refresh() {
|
|
149
|
+
if (!this.id) throw new ApiError("Impossible de rafraîchir sans ID.");
|
|
150
|
+
return this.get();
|
|
151
|
+
}
|
|
152
|
+
|
|
91
153
|
/**
|
|
92
154
|
* Récupère le profil complet de l'utilisateur.
|
|
93
155
|
* Si l'utilisateur est connecté, on appelle le endpoint ME_INFO_URL,
|
|
@@ -95,13 +157,15 @@ export class User {
|
|
|
95
157
|
*
|
|
96
158
|
* @returns {Promise<Object>} Le profil complet.
|
|
97
159
|
*/
|
|
98
|
-
async
|
|
160
|
+
async get() {
|
|
99
161
|
return this.apiClient.safeCall(async () => {
|
|
100
162
|
if (this.isMe) {
|
|
101
163
|
const data = await this.endpointApi.meInfoUrl();
|
|
164
|
+
this._setData(data);
|
|
102
165
|
return data;
|
|
103
166
|
} else {
|
|
104
167
|
const data = await this.getPublicProfile();
|
|
168
|
+
this._setData(data);
|
|
105
169
|
return data;
|
|
106
170
|
}
|
|
107
171
|
});
|
|
@@ -123,12 +187,74 @@ export class User {
|
|
|
123
187
|
return this.callIsMe(() => this.endpointApi.deleteAccount(data));
|
|
124
188
|
}
|
|
125
189
|
|
|
190
|
+
/**
|
|
191
|
+
* Sauvegarde les modifications de l'utilisateur en appelant les endpoints correspondants.
|
|
192
|
+
* Seul l'utilisateur connecté peut se modifier lui-même.
|
|
193
|
+
*
|
|
194
|
+
* @returns {Promise<Object>} - Données serveur mises à jour si applicable.
|
|
195
|
+
* @throws {ApiError} - Si l'utilisateur n'est pas autorisé.
|
|
196
|
+
*/
|
|
197
|
+
async save() {
|
|
198
|
+
|
|
199
|
+
if(!this.isMe){
|
|
200
|
+
throw new ApiError("Vous devez être connecté et être l'utilisateur pour sauvegarder.");
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const payload = { ...this.#draftData };
|
|
204
|
+
|
|
205
|
+
if (this.id) {
|
|
206
|
+
const hasChanged = await this._update(payload);
|
|
207
|
+
if (hasChanged) {
|
|
208
|
+
// this._updateInitialDraftSnapshot();
|
|
209
|
+
await this.refresh();
|
|
210
|
+
}
|
|
211
|
+
return this.#serverData;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Met à jour les blocs modifiés de l'utilisateur via les constantes de schéma définies.
|
|
218
|
+
*
|
|
219
|
+
* @param {Object} payload - Données courantes à comparer et envoyer.
|
|
220
|
+
* @returns {Promise<boolean>} - Indique s'il y a eu une modification réelle.
|
|
221
|
+
*/
|
|
222
|
+
async _update(payload){
|
|
223
|
+
if(payload.id){
|
|
224
|
+
delete payload.id;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
let hasChanged = false;
|
|
228
|
+
|
|
229
|
+
// Sinon, on fait les updates en blocs
|
|
230
|
+
for (const [constant, methodName] of User.UPDATE_BLOCKS) {
|
|
231
|
+
const blockData = this.extractChangedFieldsFromSchema(
|
|
232
|
+
this.apiClient,
|
|
233
|
+
constant,
|
|
234
|
+
{ ...payload, ...this.defaultFields},
|
|
235
|
+
() => this.initialDraftData,
|
|
236
|
+
this.removeFields
|
|
237
|
+
);
|
|
238
|
+
if (blockData && Object.keys(blockData).length > 0) {
|
|
239
|
+
await this[methodName](blockData);
|
|
240
|
+
hasChanged = true;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return hasChanged;
|
|
245
|
+
}
|
|
246
|
+
|
|
126
247
|
/**
|
|
127
248
|
* Mettre à jour les paramètres utilisateur : Mise à jour des paramètres spécifiques d'un utilisateur.
|
|
128
249
|
* Constant : UPDATE_SETTINGS
|
|
250
|
+
* @param {Object} data - Données à mettre à jour.
|
|
251
|
+
* @param {"birthDate"|"email"|"locality"|"phone"|"directory"} data.type - Type de paramètre à mettre à jour.
|
|
252
|
+
* @param {"private"|"public"|"mask"} data.value - Nouvelle valeur du paramètre.
|
|
253
|
+
* @returns {Promise<void>} - Résultat de la mise à jour.
|
|
129
254
|
*/
|
|
130
255
|
async updateSettings(data = {}) {
|
|
131
|
-
|
|
256
|
+
await this.callIsMe(() => this.endpointApi.updateSettings(data));
|
|
257
|
+
await this.refresh();
|
|
132
258
|
}
|
|
133
259
|
|
|
134
260
|
/**
|
|
@@ -167,7 +293,7 @@ export class User {
|
|
|
167
293
|
* Mettre à jour le slug d'un élément : Permet de mettre à jour le slug pour une URL simplifiée.
|
|
168
294
|
* Constant : UPDATE_BLOCK_SLUG
|
|
169
295
|
*/
|
|
170
|
-
async updateSlug(slug) {
|
|
296
|
+
async updateSlug({ slug }) {
|
|
171
297
|
try {
|
|
172
298
|
await this.endpointApi.check({ slug });
|
|
173
299
|
} catch (error) {
|
|
@@ -183,13 +309,143 @@ export class User {
|
|
|
183
309
|
* Mettre à jour l'image de profil : Permet de mettre à jour l'image de profil d'un utilisateur ou d'une entité.
|
|
184
310
|
* Constant : PROFIL_IMAGE
|
|
185
311
|
*/
|
|
186
|
-
async updateImageProfil(image) {
|
|
312
|
+
async updateImageProfil({ profil_avatar: image }) {
|
|
187
313
|
image = await this.validateImage(image);
|
|
188
314
|
return this.callIsMe(() => this.endpointApi.profilImage({ profil_avatar: image }));
|
|
189
315
|
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Récupérer les organisations d'un utilisateur : Récupère la liste des organisations auxquelles l'utilisateur appartient.
|
|
319
|
+
* Constant : GET_ORGANIZATIONS_ADMIN | GET_ORGANIZATIONS_NO_ADMIN
|
|
320
|
+
*/
|
|
321
|
+
async getOrganizations(data = {}) {
|
|
322
|
+
delete data?.pathParams;
|
|
323
|
+
|
|
324
|
+
const fetchFn = this.isMe
|
|
325
|
+
? () => this.callIsMe(() => this.endpointApi.getOrganizationsAdmin(data))
|
|
326
|
+
: () => this.endpointApi.getOrganizationsNoAdmin(data);
|
|
327
|
+
|
|
328
|
+
if (!this.isMe && !data.filters) {
|
|
329
|
+
data.filters = {
|
|
330
|
+
[`links.members.${this.id}`]: { "$exists": true },
|
|
331
|
+
[`links.members.${this.id}.toBeValidated`]: { "$exists": false },
|
|
332
|
+
[`links.members.${this.id}.isInviting`]: { "$exists": false }
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
const arrayObjetOrganizations = await fetchFn();
|
|
337
|
+
|
|
338
|
+
if (!Array.isArray(arrayObjetOrganizations.results)) {
|
|
339
|
+
throw new ApiResponseError("Erreur lors de la récupération des organisations.", 500, arrayObjetOrganizations.results);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// nettoyage du count
|
|
343
|
+
delete arrayObjetOrganizations?.count?.spam;
|
|
344
|
+
|
|
345
|
+
// calcul du total
|
|
346
|
+
const totalCount = Object.values(arrayObjetOrganizations.count || {}).reduce((acc, val) => acc + val, 0);
|
|
347
|
+
arrayObjetOrganizations.count.total = totalCount;
|
|
348
|
+
|
|
349
|
+
// transformation des résultats
|
|
350
|
+
const rawOrganizationsList = arrayObjetOrganizations.results.map((orgData) =>
|
|
351
|
+
this.deps.Organization.fromServerData(orgData, this, {
|
|
352
|
+
User,
|
|
353
|
+
Project: this.deps.Project,
|
|
354
|
+
News: this.deps.News,
|
|
355
|
+
EndpointApi: this.deps.EndpointApi
|
|
356
|
+
})
|
|
357
|
+
);
|
|
358
|
+
|
|
359
|
+
return {
|
|
360
|
+
count: arrayObjetOrganizations.count,
|
|
361
|
+
results: rawOrganizationsList
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* Crée une instance d'organisation et récupère son profil si nécessaire.
|
|
367
|
+
*
|
|
368
|
+
* @param {Object} organizationData - Les données nécessaires pour initialiser l'organisation.
|
|
369
|
+
* @returns {Promise<Organization>} Une promesse qui résout l'objet Organisation créé.
|
|
370
|
+
* @throws {Error} Si une erreur se produit lors de la création de l'organisation.
|
|
371
|
+
*/
|
|
372
|
+
async organization(organizationData = {}, ) {
|
|
373
|
+
try {
|
|
374
|
+
const organization = new this.deps.Organization(this, organizationData, { User, Project: this.deps.Project, News: this.deps.News, EndpointApi : this.deps.EndpointApi });
|
|
375
|
+
if (organizationData.id || organizationData.slug) {
|
|
376
|
+
await organization.get();
|
|
377
|
+
}
|
|
378
|
+
return organization;
|
|
379
|
+
} catch (error) {
|
|
380
|
+
this.apiClient._logger.error(`[Api.${this.__entityTag}.organization] Erreur lors de la création d'une instance organization :`, error.message);
|
|
381
|
+
throw error;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Récupérer les projets d'un utilisateur : Récupère la liste des projets auxquels l'utilisateur contribue.
|
|
387
|
+
* Constant : GET_PROJECTS_ADMIN | GET_PROJECTS_NO_ADMIN
|
|
388
|
+
*/
|
|
389
|
+
async getProjects(data = {}) {
|
|
390
|
+
delete data?.pathParams;
|
|
391
|
+
|
|
392
|
+
const fetchFn = this.isMe
|
|
393
|
+
? () => this.callIsMe(() => this.endpointApi.getProjectsAdmin(data))
|
|
394
|
+
: () => this.endpointApi.getProjectsNoAdmin(data);
|
|
395
|
+
|
|
396
|
+
if (!this.isMe && !data.filters) {
|
|
397
|
+
data.filters = {
|
|
398
|
+
"$or": {
|
|
399
|
+
[`links.contributors.${this.id}`]: { "$exists": true },
|
|
400
|
+
[`parent.${this.id}`]: { "$exists": true }
|
|
401
|
+
},
|
|
402
|
+
[`links.contributors.${this.id}`]: { "$exists": true }
|
|
403
|
+
// TODO : revoir les filtres pour harmoniser avec orga (schema pris de cocolight)
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
const arrayObjetProjects = await fetchFn();
|
|
408
|
+
|
|
409
|
+
if (!Array.isArray(arrayObjetProjects.results)) {
|
|
410
|
+
throw new ApiResponseError("Erreur lors de la récupération des projets.", 500, arrayObjetProjects.results);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
const rawProjectsList = arrayObjetProjects.results.map((projectData) =>
|
|
414
|
+
this.deps.Project.fromServerData(projectData, this, {
|
|
415
|
+
User,
|
|
416
|
+
News: this.deps.News,
|
|
417
|
+
EndpointApi: this.deps.EndpointApi
|
|
418
|
+
})
|
|
419
|
+
);
|
|
420
|
+
|
|
421
|
+
return {
|
|
422
|
+
count: arrayObjetProjects?.count?.projects ?? 0,
|
|
423
|
+
results: rawProjectsList
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Crée une instance de projet et récupère son profil si nécessaire.
|
|
429
|
+
*
|
|
430
|
+
* @param {Object} projectData - Les données nécessaires pour initialiser le projet.
|
|
431
|
+
* @returns {Promise<Project>} Une promesse qui résout l'objet Projet créé.
|
|
432
|
+
* @throws {Error} Si une erreur se produit lors de la création du projet.
|
|
433
|
+
*/
|
|
434
|
+
async project(projectData = {}, ) {
|
|
435
|
+
try {
|
|
436
|
+
const project = new this.deps.Project(this, projectData, { User, News: this.deps.News, EndpointApi : this.deps.EndpointApi });
|
|
437
|
+
if (projectData.id || projectData.slug) {
|
|
438
|
+
await project.get();
|
|
439
|
+
}
|
|
440
|
+
return project;
|
|
441
|
+
} catch (error) {
|
|
442
|
+
this.apiClient._logger.error(`[Api.${this.__entityTag}.project] Erreur lors de la création d'une instance project :`, error.message);
|
|
443
|
+
throw error;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
190
446
|
|
|
191
447
|
/**
|
|
192
|
-
* Récupérer les actualités : Récupère la liste
|
|
448
|
+
* Récupérer les actualités : Récupère la liste des actualités liées à l'utilisateur.
|
|
193
449
|
* Constant : GET_NEWS
|
|
194
450
|
*/
|
|
195
451
|
async getNews(data = {}) {
|
|
@@ -205,26 +461,76 @@ export class User {
|
|
|
205
461
|
throw new ApiResponseError("Erreur lors de la récupération des actualités.", 500, arrayObjetNews);
|
|
206
462
|
}
|
|
207
463
|
const rawNewsList = arrayObjetNews.map((newsData) =>
|
|
208
|
-
News.fromServerData(newsData, this, { User, EndpointApi: this.deps.EndpointApi })
|
|
464
|
+
this.deps.News.fromServerData(newsData, this, { User, EndpointApi: this.deps.EndpointApi })
|
|
209
465
|
);
|
|
210
466
|
|
|
211
467
|
return this._createFilteredProxy(rawNewsList);
|
|
212
468
|
}
|
|
213
469
|
|
|
470
|
+
/**
|
|
471
|
+
* Crée une instance de news et la récupère si nécessaire.
|
|
472
|
+
*
|
|
473
|
+
* @param {Object} newsData - Les données nécessaires pour initialiser la news.
|
|
474
|
+
* @returns {Promise<News>} Une promesse qui résout l'objet News créé.
|
|
475
|
+
* @throws {Error} Si une erreur se produit lors de la création de la news.
|
|
476
|
+
*/
|
|
214
477
|
async news(newsData = {}, ) {
|
|
215
478
|
try {
|
|
216
|
-
const news = new News(this, newsData, { User, EndpointApi : this.deps.EndpointApi });
|
|
479
|
+
const news = new this.deps.News(this, newsData, { User, EndpointApi : this.deps.EndpointApi });
|
|
217
480
|
if (newsData.id) {
|
|
218
481
|
await news.get();
|
|
219
482
|
}
|
|
220
483
|
return news;
|
|
221
484
|
} catch (error) {
|
|
222
|
-
|
|
485
|
+
this.apiClient._logger.error(`[Api.${this.__entityTag}.news] Erreur lors de la création d'une instance news :`, error.message);
|
|
223
486
|
throw error;
|
|
224
487
|
}
|
|
225
488
|
}
|
|
489
|
+
|
|
490
|
+
_updateInitialDraftSnapshot() {
|
|
491
|
+
this.#initialDraftData = JSON.parse(JSON.stringify(this.#draftData));
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
hasChanges() {
|
|
495
|
+
return JSON.stringify(this.#draftData) !== JSON.stringify(this.#initialDraftData);
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* Champs par défaut pour les schemas json ou l'on extrait les fields. (pour les if/else/then)
|
|
500
|
+
*
|
|
501
|
+
* @property {Object} defaultFields - Un objet contenant les propriétés par défaut pour l'entité User.
|
|
502
|
+
*/
|
|
503
|
+
defaultFields = {
|
|
504
|
+
typeElement: this.getEntityType(),
|
|
505
|
+
};
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* Champs à supprimer de draft lors de la construction du proxy.
|
|
509
|
+
*
|
|
510
|
+
* @property {Array<string>} removeFields - Un tableau de chaînes représentant les champs à supprimer.
|
|
511
|
+
*/
|
|
512
|
+
removeFields = [
|
|
513
|
+
"typeElement",
|
|
514
|
+
];
|
|
515
|
+
|
|
516
|
+
/**
|
|
517
|
+
* Transformateurs appliqués lors de la lecture du draft.
|
|
518
|
+
*
|
|
519
|
+
* @type {Object<string, function>}
|
|
520
|
+
*/
|
|
521
|
+
transforms = {
|
|
522
|
+
github: (val, full) => full?.socialNetwork?.github,
|
|
523
|
+
gitlab: (val, full) => full?.socialNetwork?.gitlab,
|
|
524
|
+
facebook: (val, full) => full?.socialNetwork?.facebook,
|
|
525
|
+
twitter: (val, full) => full?.socialNetwork?.twitter,
|
|
526
|
+
instagram: (val, full) => full?.socialNetwork?.instagram,
|
|
527
|
+
diaspora: (val, full) => full?.socialNetwork?.diaspora,
|
|
528
|
+
mastodon: (val, full) => full?.socialNetwork?.mastodon,
|
|
529
|
+
telegram: (val, full) => full?.socialNetwork?.telegram,
|
|
530
|
+
signal: (val, full) => full?.socialNetwork?.signal
|
|
531
|
+
};
|
|
226
532
|
}
|
|
227
533
|
|
|
228
534
|
// Incorporation des mixins dans User
|
|
229
|
-
Object.assign(User.prototype,
|
|
535
|
+
Object.assign(User.prototype, MutualEntityMixin, UtilMixin, UserMixin, DraftStateMixin);
|
|
230
536
|
|
package/src/api/UserApi.js
CHANGED
|
@@ -1,26 +1,48 @@
|
|
|
1
1
|
// UserApi.js
|
|
2
2
|
import ApiClient from "../ApiClient.js";
|
|
3
|
-
import { ApiResponseError } from "../error.js";
|
|
3
|
+
import { ApiError, ApiResponseError } from "../error.js";
|
|
4
4
|
import EndpointApi from "./EndpointApi.js";
|
|
5
|
+
import { News } from "./News.js";
|
|
6
|
+
import { Organization } from "./Organization.js";
|
|
7
|
+
import { Project } from "./Project.js";
|
|
5
8
|
import { User } from "./User.js";
|
|
6
9
|
|
|
7
10
|
export class UserApi {
|
|
8
11
|
constructor(options) {
|
|
9
12
|
// Injection de dépendance : ApiClient est créé à partir des options
|
|
10
13
|
this.client = new ApiClient(options);
|
|
14
|
+
// si l'option "tokenStorageStrategy" est définie, on l'utilise pour créer une instance de ApiClient
|
|
11
15
|
this.loggedUser = null;
|
|
12
16
|
}
|
|
17
|
+
|
|
18
|
+
get isConnected() {
|
|
19
|
+
return this.client.isConnected;
|
|
20
|
+
}
|
|
21
|
+
get userId() {
|
|
22
|
+
return this.client.userId;
|
|
23
|
+
}
|
|
24
|
+
|
|
13
25
|
// Méthode d'authentification : récupère les données utilisateur depuis un endpoint
|
|
14
26
|
async login(email, password) {
|
|
15
27
|
return this.client.safeCall(async () => {
|
|
16
28
|
// Appel à un endpoint d'authentification
|
|
17
29
|
const response = await this.client.callEndpoint("AUTHENTICATE_URL", { email, password });
|
|
18
30
|
// Création d'une instance de LoggedInUser à partir des données reçues
|
|
19
|
-
this.loggedUser = new User(this.client,
|
|
31
|
+
this.loggedUser = new User(this.client, response.data.user, { EndpointApi, Organization, Project, News });
|
|
20
32
|
return this.loggedUser;
|
|
21
33
|
});
|
|
22
34
|
}
|
|
23
35
|
|
|
36
|
+
async meIsconnected() {
|
|
37
|
+
if(!this.client.isConnected || !this.client.userId) {
|
|
38
|
+
throw new ApiError("User not connected", 401);
|
|
39
|
+
}
|
|
40
|
+
this.client._logger.info("UserApi", "meIsconnected", this.client.userId);
|
|
41
|
+
this.loggedUser = new User(this.client, { id: this.client.userId }, { EndpointApi, Organization, Project, News });
|
|
42
|
+
return this.loggedUser;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
|
|
24
46
|
async register({
|
|
25
47
|
name,
|
|
26
48
|
username,
|
|
@@ -46,4 +68,5 @@ export class UserApi {
|
|
|
46
68
|
return response.data;
|
|
47
69
|
});
|
|
48
70
|
}
|
|
71
|
+
|
|
49
72
|
}
|