@communecter/cocolight-api-client 1.0.22 → 1.0.24
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/dist/cocolight-api-client.browser.js +2 -2
- package/dist/cocolight-api-client.cjs +1 -1
- package/dist/cocolight-api-client.mjs.js +1 -1
- package/package.json +1 -1
- package/src/api/Badge.js +20 -12
- package/src/api/BaseEntity.js +642 -21
- package/src/api/EndpointApi.js +20 -4
- package/src/api/EndpointApi.types.d.ts +23 -2
- package/src/api/Event.js +38 -11
- package/src/api/Organization.js +129 -45
- package/src/api/Poi.js +38 -12
- package/src/api/Project.js +158 -8
- package/src/api/User.js +273 -18
- package/src/endpoints.module.js +2 -2
- package/src/index.js +21 -1
- package/src/utils/reactive.js +279 -0
package/src/api/Project.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ApiError, ApiResponseError } from "../error.js";
|
|
1
2
|
import BaseEntity from "./BaseEntity.js";
|
|
2
3
|
|
|
3
4
|
export class Project extends BaseEntity {
|
|
@@ -63,7 +64,7 @@ export class Project extends BaseEntity {
|
|
|
63
64
|
|
|
64
65
|
async _add(payload) {
|
|
65
66
|
if (!this._calledFromSave) {
|
|
66
|
-
throw new
|
|
67
|
+
throw new ApiError("utilisation invalide de _add, utilisez save");
|
|
67
68
|
}
|
|
68
69
|
|
|
69
70
|
payload.id = this._newId?.();
|
|
@@ -87,8 +88,12 @@ export class Project extends BaseEntity {
|
|
|
87
88
|
}
|
|
88
89
|
|
|
89
90
|
async _update(payload) {
|
|
91
|
+
if(!this.isAdmin()){
|
|
92
|
+
throw new ApiError("Vous n'avez pas les droits pour modifier ce projet", 403);
|
|
93
|
+
}
|
|
94
|
+
|
|
90
95
|
if (!this._calledFromSave) {
|
|
91
|
-
throw new
|
|
96
|
+
throw new ApiError("utilisation invalide de _update, utilisez save");
|
|
92
97
|
}
|
|
93
98
|
|
|
94
99
|
if (payload.id) delete payload.id;
|
|
@@ -126,7 +131,7 @@ export class Project extends BaseEntity {
|
|
|
126
131
|
}
|
|
127
132
|
|
|
128
133
|
async getOrganizations() {
|
|
129
|
-
throw new
|
|
134
|
+
throw new ApiError(`getOrganizations n'existe pas dans ${this.constructor.name}`);
|
|
130
135
|
}
|
|
131
136
|
|
|
132
137
|
async getProjects(data = {}) {
|
|
@@ -134,7 +139,7 @@ export class Project extends BaseEntity {
|
|
|
134
139
|
}
|
|
135
140
|
|
|
136
141
|
async getEvents() {
|
|
137
|
-
throw new
|
|
142
|
+
throw new ApiError(`getEvents pas encore implémenté dans ${this.constructor.name}`);
|
|
138
143
|
}
|
|
139
144
|
|
|
140
145
|
async getPois(data = {}) {
|
|
@@ -153,6 +158,70 @@ export class Project extends BaseEntity {
|
|
|
153
158
|
return super.getSubscribers(data);
|
|
154
159
|
}
|
|
155
160
|
|
|
161
|
+
/**
|
|
162
|
+
* Récupérer les contributeurs d'un projet.
|
|
163
|
+
* Constant : GET_CONTRIBUTORS_ADMIN / GET_CONTRIBUTORS_NO_ADMIN
|
|
164
|
+
* @param {Object} data - Les données de requête.
|
|
165
|
+
* @param {Object} options - Options supplémentaires.
|
|
166
|
+
* @param {boolean} options.toBeValidated - Indique si les contributeurs doivent être validés.
|
|
167
|
+
* @param {boolean} options.isAdmin - Indique si l'utilisateur est admin.
|
|
168
|
+
* @param {boolean} options.isInviting - Indique si l'utilisateur est en attente d'invitation.
|
|
169
|
+
* @param {Array} options.roles - Liste des rôles à filtrer.
|
|
170
|
+
* @returns {Promise<Object>} - Un objet contenant le nombre de contributeurs et la liste des contributeurs.
|
|
171
|
+
* @throws {ApiResponseError} - Si une erreur se produit lors de la récupération des contributeurs.
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* // Récupérer tous les contributeurs
|
|
175
|
+
* const contributors = await project.getContributors();
|
|
176
|
+
*
|
|
177
|
+
* // Récupérer les contributeurs avec validation en attente
|
|
178
|
+
* const contributorsToBeValidated = await project.getContributors({}, { toBeValidated: true });
|
|
179
|
+
*
|
|
180
|
+
* // Récupérer les contributeurs avec un rôle spécifique
|
|
181
|
+
* const contributorsWithRole = await project.getContributors({}, { roles: ["admin"] });
|
|
182
|
+
*
|
|
183
|
+
* // Récupérer les contributeurs administrateurs
|
|
184
|
+
* const adminContributors = await project.getContributors({}, { isAdmin: true });
|
|
185
|
+
*
|
|
186
|
+
* // Récupérer les contributeurs en attente d'invitation
|
|
187
|
+
* const invitingContributors = await project.getContributors({}, { isInviting: true });
|
|
188
|
+
*
|
|
189
|
+
*/
|
|
190
|
+
async getContributors(data = {}, options = {}) {
|
|
191
|
+
const { toBeValidated, isAdmin, isInviting, isAdminPending, roles = [] } = options;
|
|
192
|
+
|
|
193
|
+
if(this.isMe){
|
|
194
|
+
data.pathParams = { type: this.getEntityType(), id: this.id };
|
|
195
|
+
// NOTE : dans le schema je crois que si pas de data.filters alors le default ce fait avec data.pathParams
|
|
196
|
+
// data.filters = {
|
|
197
|
+
// [`links.projects.${this.id}`]: { "$exists": true },
|
|
198
|
+
// [`links.projects.${this.id}.toBeValidated`]: { "$exists": false },
|
|
199
|
+
// [`links.projects.${this.id}.isInviting`]: { "$exists": false }
|
|
200
|
+
// };
|
|
201
|
+
data.filters = this._buildLinkFilters(this.id, { linkType: "projects", toBeValidated, isAdmin, isAdminPending, isInviting, roles });
|
|
202
|
+
} else {
|
|
203
|
+
delete data?.pathParams;
|
|
204
|
+
data.filters = this._buildLinkFilters(this.id, { linkType: "projects", toBeValidated: "false", isAdmin, isInviting, roles });
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const fetchFn = this.isMe
|
|
208
|
+
? () => this.callIsMe(() => this.endpointApi.getContributorsAdmin(data))
|
|
209
|
+
: () => this.endpointApi.getContributorsNoAdmin(data);
|
|
210
|
+
|
|
211
|
+
const arrayObjet = await fetchFn();
|
|
212
|
+
if (!Array.isArray(arrayObjet.results)) {
|
|
213
|
+
throw new ApiResponseError("Erreur lors de la récupération des contributeurs", 500, arrayObjet.results);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// lier les entités au objets
|
|
217
|
+
const rawList = this._linkEntities(arrayObjet.results);
|
|
218
|
+
|
|
219
|
+
return {
|
|
220
|
+
count: arrayObjet.count,
|
|
221
|
+
results: rawList
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
|
|
156
225
|
/**
|
|
157
226
|
* Crée une instance de projet et récupère son profil si nécessaire.
|
|
158
227
|
*
|
|
@@ -161,7 +230,9 @@ export class Project extends BaseEntity {
|
|
|
161
230
|
* @throws {Error} Si une erreur se produit lors de la création du projet.
|
|
162
231
|
*/
|
|
163
232
|
async project(projectData = {}) {
|
|
164
|
-
|
|
233
|
+
if(!this.isAdmin()){
|
|
234
|
+
throw new ApiError("Vous n'avez pas les droits pour créer un projet dans ce projet", 403);
|
|
235
|
+
}
|
|
165
236
|
return super.project(projectData);
|
|
166
237
|
}
|
|
167
238
|
|
|
@@ -173,7 +244,9 @@ export class Project extends BaseEntity {
|
|
|
173
244
|
* @throws {Error} Si une erreur se produit lors de la création du POI.
|
|
174
245
|
*/
|
|
175
246
|
async poi(poiData = {}) {
|
|
176
|
-
|
|
247
|
+
if(!this.isAdmin()){
|
|
248
|
+
throw new ApiError("Vous n'avez pas les droits pour créer un POI dans ce projet", 403);
|
|
249
|
+
}
|
|
177
250
|
return super.poi(poiData);
|
|
178
251
|
}
|
|
179
252
|
|
|
@@ -185,7 +258,9 @@ export class Project extends BaseEntity {
|
|
|
185
258
|
* @throws {Error} Si une erreur se produit lors de la création de l'événement.
|
|
186
259
|
*/
|
|
187
260
|
async event(eventData = {}) {
|
|
188
|
-
|
|
261
|
+
if(!this.isAdmin()){
|
|
262
|
+
throw new ApiError("Vous n'avez pas les droits pour créer un événement dans ce projet", 403);
|
|
263
|
+
}
|
|
189
264
|
return super.event(eventData);
|
|
190
265
|
}
|
|
191
266
|
|
|
@@ -197,7 +272,9 @@ export class Project extends BaseEntity {
|
|
|
197
272
|
* @throws {Error} Si une erreur se produit lors de la création du badge.
|
|
198
273
|
*/
|
|
199
274
|
async badge(badgeData = {}) {
|
|
200
|
-
|
|
275
|
+
if(!this.isAdmin()){
|
|
276
|
+
throw new ApiError("Vous n'avez pas les droits pour créer un badge dans ce projet", 403);
|
|
277
|
+
}
|
|
201
278
|
return super.badge(badgeData);
|
|
202
279
|
}
|
|
203
280
|
|
|
@@ -209,7 +286,80 @@ export class Project extends BaseEntity {
|
|
|
209
286
|
* @throws {Error} Si une erreur se produit lors de la création de la news.
|
|
210
287
|
*/
|
|
211
288
|
async news(newsData = {}) {
|
|
289
|
+
// TODO: qui peut créer une news sur le projet ?
|
|
212
290
|
return super.news(newsData);
|
|
213
291
|
}
|
|
214
292
|
|
|
293
|
+
/**
|
|
294
|
+
* ───────────────────────────────
|
|
295
|
+
* Lien utilisateur ↔ projet
|
|
296
|
+
* (rejoindre, valider, quitter, devenir admin)
|
|
297
|
+
* ───────────────────────────────
|
|
298
|
+
*/
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Envoie une demande pour rejoindre le projet en tant que contributeur.
|
|
302
|
+
* L'action est soumise à validation par un administrateur du projet.
|
|
303
|
+
*
|
|
304
|
+
* @returns {Promise<Object>} - Résultat de la requête d'adhésion.
|
|
305
|
+
* @throws {ApiError} - Si l'utilisateur n'est pas connecté ou si le projet ne supporte pas l'action.
|
|
306
|
+
*/
|
|
307
|
+
async requestToJoin(){
|
|
308
|
+
return super.requestToJoin();
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Envoie une demande pour devenir administrateur du projet.
|
|
313
|
+
* L'action est soumise à validation par un administrateur existant.
|
|
314
|
+
*
|
|
315
|
+
* @returns {Promise<Object>} - Résultat de la requête d'administration.
|
|
316
|
+
* @throws {ApiError} - Si l'utilisateur n'est pas connecté ou si le projet ne supporte pas l'action.
|
|
317
|
+
*/
|
|
318
|
+
async requestToJoinAdmin(){
|
|
319
|
+
return super.requestToJoinAdmin();
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Accepte une invitation à rejoindre le projet.
|
|
324
|
+
* Cette action valide un lien en attente avec l'option `isInviting`.
|
|
325
|
+
*
|
|
326
|
+
* @returns {Promise<Object>} - Résultat de la validation du lien.
|
|
327
|
+
* @throws {ApiError} - Si aucune invitation n'est en attente ou si le projet ne supporte pas l'action.
|
|
328
|
+
*/
|
|
329
|
+
async acceptInvitation(){
|
|
330
|
+
return super.acceptInvitation();
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Quitte le projet, que ce soit en tant que contributeur ou administrateur.
|
|
335
|
+
* Cette action supprime le lien entre l'utilisateur et le projet.
|
|
336
|
+
*
|
|
337
|
+
* @returns {Promise<Object>} - Résultat de la déconnexion.
|
|
338
|
+
* @throws {ApiError} - Si l'utilisateur n'est pas connecté ou non contributeur.
|
|
339
|
+
*/
|
|
340
|
+
async leave() {
|
|
341
|
+
return super.leave();
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Suivre un projet.
|
|
346
|
+
* Cette action permet à l'utilisateur de suivre le projet.
|
|
347
|
+
*
|
|
348
|
+
* @returns {Promise<Object>} - Résultat de l'action de suivi.
|
|
349
|
+
* @throws {ApiError} - Si l'utilisateur n'est pas connecté ou si l'entité ne supporte pas l'action.
|
|
350
|
+
*/
|
|
351
|
+
async follow() {
|
|
352
|
+
return super.follow();
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Se désabonne d'un projet.
|
|
357
|
+
*
|
|
358
|
+
* @returns {Promise<Object>} - Résultat de la désinscription.
|
|
359
|
+
* @throws {ApiError} - Si l'utilisateur n'est pas connecté ou si l'entité n'est pas enregistrée.
|
|
360
|
+
*/
|
|
361
|
+
async unfollow() {
|
|
362
|
+
return super.unfollow();
|
|
363
|
+
}
|
|
364
|
+
|
|
215
365
|
}
|
package/src/api/User.js
CHANGED
|
@@ -81,7 +81,7 @@ export class User extends BaseEntity {
|
|
|
81
81
|
|
|
82
82
|
super(parent, data, deps);
|
|
83
83
|
}
|
|
84
|
-
|
|
84
|
+
|
|
85
85
|
get slug() {
|
|
86
86
|
return this._draftData.slug || null;
|
|
87
87
|
}
|
|
@@ -90,6 +90,14 @@ export class User extends BaseEntity {
|
|
|
90
90
|
return this.isConnected && this.userId === this.id;
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
+
get parentIsMe() {
|
|
94
|
+
return super.isMe;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
get isActingUser() {
|
|
98
|
+
return this.parentIsMe && !this.isMe;
|
|
99
|
+
}
|
|
100
|
+
|
|
93
101
|
/**
|
|
94
102
|
* Récupère le profil complet de l'utilisateur.
|
|
95
103
|
* Si l'utilisateur est connecté, on appelle le endpoint ME_INFO_URL,
|
|
@@ -181,23 +189,7 @@ export class User extends BaseEntity {
|
|
|
181
189
|
}
|
|
182
190
|
|
|
183
191
|
static fromServerData(data, parent, deps) {
|
|
184
|
-
|
|
185
|
-
instance._serverData = { ...data };
|
|
186
|
-
// est ce que je besoin de ça si il est contruit dans le constructeur ?
|
|
187
|
-
// il doit y avaoir une raison pour les autres objets
|
|
188
|
-
const { draft, proxy } = instance._buildDraftAndProxy({
|
|
189
|
-
data: { ...data, ...instance.defaultFields },
|
|
190
|
-
serverData: instance._serverData,
|
|
191
|
-
constant: User.SCHEMA_CONSTANTS,
|
|
192
|
-
apiClient: instance.apiClient,
|
|
193
|
-
transforms: instance.transforms,
|
|
194
|
-
removeFields: instance.removeFields
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
instance._draftData = draft;
|
|
198
|
-
instance.data = proxy;
|
|
199
|
-
|
|
200
|
-
return instance;
|
|
192
|
+
return new User(parent.apiClient, data, deps);
|
|
201
193
|
}
|
|
202
194
|
|
|
203
195
|
/**
|
|
@@ -451,6 +443,18 @@ export class User extends BaseEntity {
|
|
|
451
443
|
return filteredBadges;
|
|
452
444
|
}
|
|
453
445
|
|
|
446
|
+
async user(userData) {
|
|
447
|
+
if(!this.isMe){
|
|
448
|
+
throw new ApiError("Vous devez être connecté et être l'utilisateur");
|
|
449
|
+
}
|
|
450
|
+
if (!userData.id && !userData.slug) {
|
|
451
|
+
throw new ApiError("Vous devez fournir un id ou un slug pour créer un User.");
|
|
452
|
+
}
|
|
453
|
+
const user = new User(this, userData, this.deps);
|
|
454
|
+
await user.get();
|
|
455
|
+
return user;
|
|
456
|
+
}
|
|
457
|
+
|
|
454
458
|
/**
|
|
455
459
|
* Crée une instance d'organisation et récupère son profil si nécessaire.
|
|
456
460
|
*
|
|
@@ -535,6 +539,257 @@ export class User extends BaseEntity {
|
|
|
535
539
|
return super.badge(badgeData);
|
|
536
540
|
}
|
|
537
541
|
|
|
542
|
+
/**
|
|
543
|
+
* ───────────────────────────────
|
|
544
|
+
* Lien utilisateur ↔ utilisateur (ami)
|
|
545
|
+
* (demander, valider, se retirer)
|
|
546
|
+
* ───────────────────────────────
|
|
547
|
+
*/
|
|
548
|
+
|
|
549
|
+
/**
|
|
550
|
+
* Envoie une demande d'amitié à cet utilisateur.
|
|
551
|
+
* L'utilisateur ciblé devra valider la demande pour établir la relation.
|
|
552
|
+
*
|
|
553
|
+
* @returns {Promise<Object>} - Résultat de la requête.
|
|
554
|
+
* @throws {ApiError} - Si l'utilisateur n'est pas connecté ou si l'action est interdite.
|
|
555
|
+
*/
|
|
556
|
+
async sendFriendRequest() {
|
|
557
|
+
if (!this.isActingUser) {
|
|
558
|
+
throw new ApiError("Vous devez être connecté pour envoyer une demande d'amis.");
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
this._checkLinkableEntity();
|
|
562
|
+
if (!this.id) {
|
|
563
|
+
throw new ApiError(`${this.constructor.name} non enregistrée.`);
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
const { connectTypeConnect } = this._getLinkMeta();
|
|
567
|
+
const userLink = this._getLinkFromConnectedUser();
|
|
568
|
+
|
|
569
|
+
if (!userLink) {
|
|
570
|
+
const data = {
|
|
571
|
+
parentType: this.getEntityType(),
|
|
572
|
+
parentId: this.id,
|
|
573
|
+
connectType: connectTypeConnect
|
|
574
|
+
};
|
|
575
|
+
const retour = await this.endpointApi.connect(data);
|
|
576
|
+
// TODO : reflechier au moyen de remplir parent.serverData et this.serverData avec les data de retour pour eviter un refresh
|
|
577
|
+
await this.userContext.refresh();
|
|
578
|
+
return retour;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
if (userLink.isInviting && userLink.invitorId === this.id) {
|
|
582
|
+
return this.acceptFriendRequest();
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
if (userLink.isInviting && userLink.invitorId === this.userId) {
|
|
586
|
+
throw new ApiError("Vous avez déjà envoyé une demande d'amis à cet utilisateur.");
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
throw new ApiError("Vous êtes déjà connecté à cette entité.");
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
/**
|
|
593
|
+
* Accepte une demande d'amitié envoyée par cet utilisateur.
|
|
594
|
+
* Cette action établit un lien entre les deux utilisateurs.
|
|
595
|
+
*
|
|
596
|
+
* @returns {Promise<Object>} - Résultat de la validation du lien.
|
|
597
|
+
* @throws {ApiError} - Si aucune invitation n'est en attente ou si l'action est interdite.
|
|
598
|
+
*/
|
|
599
|
+
async acceptFriendRequest() {
|
|
600
|
+
if (!this.isActingUser) {
|
|
601
|
+
throw new ApiError("Vous devez être connecté pour accepter une demande d'amitié.");
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
this._checkLinkableEntity();
|
|
605
|
+
if (!this.id) {
|
|
606
|
+
throw new ApiError(`${this.constructor.name} non enregistrée.`);
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
const userLink = this._getLinkFromConnectedUser();
|
|
610
|
+
|
|
611
|
+
if (userLink?.isInviting && userLink.invitorId === this.id) {
|
|
612
|
+
const data = {
|
|
613
|
+
parentType: this.getEntityType(),
|
|
614
|
+
parentId: this.id,
|
|
615
|
+
linkOption: "isInviting"
|
|
616
|
+
};
|
|
617
|
+
const retour = await this.endpointApi.linkValidate(data);
|
|
618
|
+
// TODO : reflechier au moyen de remplir parent.serverData et this.serverData avec les data de retour pour eviter un refresh
|
|
619
|
+
await this.userContext.refresh();
|
|
620
|
+
return retour;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
throw new ApiError("Vous n'avez pas d'invitation à valider.");
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
/**
|
|
627
|
+
* Supprime la relation d'amitié avec cet utilisateur.
|
|
628
|
+
* Cette action annule tout lien existant entre les deux profils.
|
|
629
|
+
*
|
|
630
|
+
* @returns {Promise<Object>} - Résultat de la suppression.
|
|
631
|
+
* @throws {ApiError} - Si aucune relation n'existe.
|
|
632
|
+
*/
|
|
633
|
+
async removeFriend() {
|
|
634
|
+
if (!this.isActingUser) {
|
|
635
|
+
throw new ApiError("Vous devez être connecté pour supprimer un ami.");
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
this._checkLinkableEntity();
|
|
639
|
+
if (!this.id) {
|
|
640
|
+
throw new ApiError(`${this.constructor.name} non enregistrée.`);
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
const { connectTypeDisconnect } = this._getLinkMeta();
|
|
644
|
+
const userLink = this._getLinkFromConnectedUser();
|
|
645
|
+
|
|
646
|
+
if (!userLink) {
|
|
647
|
+
throw new ApiError("Vous n'êtes pas connecté à cette entité.");
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
const data = {
|
|
651
|
+
parentType: this.getEntityType(),
|
|
652
|
+
parentId: this.id,
|
|
653
|
+
connectType: connectTypeDisconnect
|
|
654
|
+
};
|
|
655
|
+
const retour = await this.endpointApi.disconnect(data);
|
|
656
|
+
// TODO : reflechier au moyen de remplir parent.serverData et this.serverData avec les data de retour pour eviter un refresh
|
|
657
|
+
await this.userContext.refresh();
|
|
658
|
+
return retour;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
|
|
662
|
+
requestToJoin() {
|
|
663
|
+
throw new ApiError("l'utilisation de requestToJoin n'est pas autorisée sur un utilisateur.");
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
requestToJoinAdmin() {
|
|
667
|
+
throw new ApiError("l'utilisation de requestToJoinAdmin n'est pas autorisée sur un utilisateur.");
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
acceptInvitation() {
|
|
671
|
+
throw new ApiError("l'utilisation de acceptInvitation n'est pas autorisée sur un utilisateur.");
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
leave() {
|
|
675
|
+
throw new ApiError("l'utilisation de leave n'est pas autorisée sur un utilisateur.");
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
/**
|
|
679
|
+
* Suivre un utilisateur
|
|
680
|
+
* Cette action permet à l'utilisateur connecté de suivre un autre utilisateur.
|
|
681
|
+
* Elle nécessite que l'utilisateur soit connecté.
|
|
682
|
+
*
|
|
683
|
+
* @returns {Promise<Object>} - Résultat de la requête.
|
|
684
|
+
* @throws {ApiError} - Si l'utilisateur n'est pas connecté ou si l'action est interdite.
|
|
685
|
+
*/
|
|
686
|
+
async follow() {
|
|
687
|
+
if (!this.isActingUser) {
|
|
688
|
+
throw new ApiError("Vous devez être connecté pour suivre un utilisateur.");
|
|
689
|
+
}
|
|
690
|
+
if (!this.id) {
|
|
691
|
+
throw new ApiError(`${this.constructor.name} non enregistrée.`);
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
const userLink = this.userContext?.serverData?.links?.["follows"]?.[this.id] || null;
|
|
695
|
+
|
|
696
|
+
if (!userLink) {
|
|
697
|
+
const data = {
|
|
698
|
+
parentType: this.getEntityType(),
|
|
699
|
+
parentId: this.id
|
|
700
|
+
};
|
|
701
|
+
const retour = await this.endpointApi.follow(data);
|
|
702
|
+
// TODO : reflechier au moyen de remplir parent.serverData et this.serverData avec les data de retour pour eviter un refresh
|
|
703
|
+
await this.userContext.refresh();
|
|
704
|
+
return retour;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
throw new ApiError("Vous êtes déjà abonné à cet utilisateur.");
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
/**
|
|
711
|
+
* Se désabonner d'un utilisateur
|
|
712
|
+
* Cette action permet à l'utilisateur connecté de se désabonner d'un autre utilisateur.
|
|
713
|
+
* Elle nécessite que l'utilisateur soit connecté.
|
|
714
|
+
*
|
|
715
|
+
* @returns {Promise<Object>} - Résultat de la requête.
|
|
716
|
+
* @throws {ApiError} - Si l'utilisateur n'est pas connecté ou si l'action est interdite.
|
|
717
|
+
*/
|
|
718
|
+
async unfollow() {
|
|
719
|
+
if (!this.isActingUser) {
|
|
720
|
+
throw new ApiError("Vous devez être connecté pour vous désabonner d'un utilisateur.");
|
|
721
|
+
}
|
|
722
|
+
if (!this.id) {
|
|
723
|
+
throw new ApiError(`${this.constructor.name} non enregistrée.`);
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
const userLink = this.userContext?.serverData?.links?.["follows"]?.[this.id] || null;
|
|
727
|
+
|
|
728
|
+
if (userLink) {
|
|
729
|
+
const data = {
|
|
730
|
+
parentType: this.getEntityType(),
|
|
731
|
+
parentId: this.id,
|
|
732
|
+
connectType: "followers"
|
|
733
|
+
};
|
|
734
|
+
const retour = await this.endpointApi.disconnect(data);
|
|
735
|
+
// TODO : reflechir au moyen de remplir parent.serverData et this.serverData avec les data de retour pour eviter un refresh
|
|
736
|
+
await this.userContext.refresh();
|
|
737
|
+
return retour;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
throw new ApiError("Vous n'êtes pas abonné à cet utilisateur.");
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
/**
|
|
744
|
+
* Vérifie si l'utilisateur connecté est ami avec cet utilisateur.
|
|
745
|
+
*
|
|
746
|
+
* @returns {boolean} - True si l'utilisateur connecté est ami, sinon false.
|
|
747
|
+
* @throws {ApiError} - Si l'utilisateur n'est pas connecté.
|
|
748
|
+
*/
|
|
749
|
+
isFriend() {
|
|
750
|
+
if (!this.isActingUser) {
|
|
751
|
+
throw new ApiError("Vous devez être connecté pour vérifier si vous êtes ami.");
|
|
752
|
+
}
|
|
753
|
+
this._assertEntityType("citoyens");
|
|
754
|
+
const userLink = this._getLinkFromConnectedUser();
|
|
755
|
+
return this._validateUserLink(userLink);
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
/**
|
|
759
|
+
* Vérifie si l'utilisateur suit l'entité.
|
|
760
|
+
*
|
|
761
|
+
* @returns {boolean} - `true` si l'utilisateur suit l'entité, `false` sinon.
|
|
762
|
+
* @throws {ApiError}
|
|
763
|
+
*/
|
|
764
|
+
isFollower() {
|
|
765
|
+
if (!this.isActingUser) {
|
|
766
|
+
throw new ApiError("Vous devez être connecté pour vérifier si il vous suit.");
|
|
767
|
+
}
|
|
768
|
+
if (!this.id) {
|
|
769
|
+
throw new ApiError(`${this.constructor.name} non enregistrée.`);
|
|
770
|
+
}
|
|
771
|
+
this._assertEntityType("citoyens");
|
|
772
|
+
return this._isLinked("followers");
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
/**
|
|
776
|
+
* Vérifie si l'utilisateur est abonné à l'entité.
|
|
777
|
+
*
|
|
778
|
+
* @returns {boolean} - `true` si l'utilisateur est abonné, `false` sinon.
|
|
779
|
+
* @throws {ApiError}
|
|
780
|
+
*/
|
|
781
|
+
isFollowing() {
|
|
782
|
+
if (!this.isActingUser) {
|
|
783
|
+
throw new ApiError("Vous devez être connecté pour vérifier si vous le suivez.");
|
|
784
|
+
}
|
|
785
|
+
if (!this.id) {
|
|
786
|
+
throw new ApiError(`${this.constructor.name} non enregistrée.`);
|
|
787
|
+
}
|
|
788
|
+
this._assertEntityType("citoyens");
|
|
789
|
+
return this._isLinked("follows");
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
|
|
538
793
|
}
|
|
539
794
|
|
|
540
795
|
// Incorporation des mixins dans User
|