@communecter/cocolight-api-client 1.0.77 → 1.0.79
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 +3 -3
- package/dist/cocolight-api-client.cjs +1 -1
- package/dist/cocolight-api-client.mjs.js +1 -1
- package/dist/cocolight-api-client.vite.mjs.js +1 -1
- package/dist/cocolight-api-client.vite.mjs.js.map +1 -1
- package/package.json +1 -1
- package/src/api/BaseEntity.ts +7 -6
- package/src/api/EndpointApi.ts +17 -1
- package/src/api/EndpointApi.types.ts +14 -0
- package/src/api/User.ts +664 -1
- package/src/api/serverDataType/common.ts +1 -0
- package/src/endpoints.module.ts +1 -1
- package/types/api/BaseEntity.d.ts +3 -2
- package/types/api/EndpointApi.d.ts +11 -1
- package/types/api/EndpointApi.types.d.ts +12 -0
- package/types/api/User.d.ts +360 -0
- package/types/api/serverDataType/common.d.ts +1 -0
- package/types/endpoints.module.d.ts +356 -0
package/src/api/User.ts
CHANGED
|
@@ -15,7 +15,8 @@ import type {
|
|
|
15
15
|
GetSubscriptionsData,
|
|
16
16
|
GetOrganizationsNoAdminData,
|
|
17
17
|
GetOrganizationsAdminData,
|
|
18
|
-
GetFriendsAdminData
|
|
18
|
+
GetFriendsAdminData,
|
|
19
|
+
DemoteAdminData
|
|
19
20
|
} from "./EndpointApi.types.js";
|
|
20
21
|
import type { Organization } from "./Organization.js";
|
|
21
22
|
import type { EntityTypes } from "@/types/entities.js";
|
|
@@ -888,6 +889,668 @@ export class User extends BaseEntity<UserItemNormalized> {
|
|
|
888
889
|
}
|
|
889
890
|
return super.entityBySlug(slug);
|
|
890
891
|
}
|
|
892
|
+
|
|
893
|
+
/**
|
|
894
|
+
* Valide les préconditions communes pour les méthodes de vérification de rôle.
|
|
895
|
+
* @private
|
|
896
|
+
* @param methodName - Nom de la méthode appelante (pour les messages d'erreur).
|
|
897
|
+
* @param expectedTypes - Types d'entité parent autorisés.
|
|
898
|
+
* @throws {ApiError} 401 - Si l'utilisateur n'est pas connecté.
|
|
899
|
+
* @throws {ApiError} 401 - Si l'utilisateur connecté n'est pas administrateur de l'entité parente.
|
|
900
|
+
* @throws {ApiError} 404 - Si l'utilisateur n'est pas enregistré.
|
|
901
|
+
* @throws {ApiError} 404 - Si l'entité parente n'est pas enregistrée.
|
|
902
|
+
* @throws {ApiError} 400 - Si le type d'entité parent n'est pas valide.
|
|
903
|
+
*/
|
|
904
|
+
private _validateRoleCheckPreconditions(methodName: string, expectedTypes: string[]): void {
|
|
905
|
+
if (!this.userId) {
|
|
906
|
+
throw new ApiError(`Vous devez être connecté pour ${methodName}.`, 401);
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
if(!this.parent?.isAdmin()){
|
|
910
|
+
throw new ApiError("Vous devez être administrateur pour effectuer cette action.", 401);
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
if (!this.id) {
|
|
914
|
+
throw new ApiError(`${this.constructor.name} non enregistrée.`, 404);
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
if(!this.parent?.id){
|
|
918
|
+
throw new ApiError("L'entité parente n'est pas enregistrée.", 404);
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
if (!expectedTypes.includes(this.parent.getEntityType())) {
|
|
922
|
+
throw new ApiError(`L'entité doit être de type : ${expectedTypes.join(", ")}, reçu : ${this.parent.getEntityType()}`, 400);
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
|
|
927
|
+
/**
|
|
928
|
+
* Récupère le lien parent pour l'utilisateur actuel.
|
|
929
|
+
*
|
|
930
|
+
* @returns Le lien parent de l'utilisateur ou `null` s'il n'existe pas.
|
|
931
|
+
* @private
|
|
932
|
+
*/
|
|
933
|
+
private _getParentLinkForUser(): any {
|
|
934
|
+
const { connectTypeDisconnect } = this.parent!._getLinkMeta();
|
|
935
|
+
const userId = this!.id;
|
|
936
|
+
if (!userId) return null;
|
|
937
|
+
return this.parent?.serverData?.links?.[connectTypeDisconnect]?.[userId] || null;
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
/**
|
|
941
|
+
* Vérifie si l'utilisateur est administrateur de l'entité parente.
|
|
942
|
+
*
|
|
943
|
+
* Cette méthode permet de vérifier si un utilisateur possède les droits d'administration
|
|
944
|
+
* sur l'organisation ou le projet parent. Elle est particulièrement utile après avoir
|
|
945
|
+
* récupéré des membres via `getMembers()` pour déterminer leur niveau de permissions.
|
|
946
|
+
*
|
|
947
|
+
* @returns `true` si l'utilisateur est administrateur de l'entité parente, `false` sinon.
|
|
948
|
+
*
|
|
949
|
+
* @throws {ApiError} 401 - Si l'utilisateur n'est pas connecté.
|
|
950
|
+
* @throws {ApiError} 401 - Si l'utilisateur connecté n'est pas administrateur de l'entité parente.
|
|
951
|
+
* @throws {ApiError} 404 - Si l'utilisateur n'est pas enregistré (pas d'ID).
|
|
952
|
+
* @throws {ApiError} 404 - Si l'entité parente n'est pas enregistrée (pas d'ID).
|
|
953
|
+
* @throws {ApiError} 400 - Si l'entité parente n'est pas de type "organizations" ou "projects".
|
|
954
|
+
*
|
|
955
|
+
* @example
|
|
956
|
+
* // Vérifier les admins d'une organisation
|
|
957
|
+
* const org = await me.organization({ slug: "openAtlas" });
|
|
958
|
+
* const members = await org.getMembers();
|
|
959
|
+
*
|
|
960
|
+
* for (const member of members.results) {
|
|
961
|
+
* if (member.getEntityType() === "citoyens") {
|
|
962
|
+
* if (member.isAdmin()) {
|
|
963
|
+
* console.log(`${member.data.name} est administrateur`);
|
|
964
|
+
* }
|
|
965
|
+
* }
|
|
966
|
+
* }
|
|
967
|
+
*
|
|
968
|
+
* @example
|
|
969
|
+
* // Récupérer uniquement les membres admins
|
|
970
|
+
* const org = await me.organization({ slug: "myOrg" });
|
|
971
|
+
* const adminMembers = await org.getMembers({}, { isAdmin: true });
|
|
972
|
+
*
|
|
973
|
+
* // Vérifier chaque admin
|
|
974
|
+
* for (const admin of adminMembers.results) {
|
|
975
|
+
* if (admin.getEntityType() === "citoyens" && admin.isAdmin()) {
|
|
976
|
+
* console.log(`${admin.data.name} a les droits admin`);
|
|
977
|
+
* }
|
|
978
|
+
* }
|
|
979
|
+
*/
|
|
980
|
+
override isAdmin(): boolean {
|
|
981
|
+
this._validateRoleCheckPreconditions("isAdmin", ["organizations", "projects"]);
|
|
982
|
+
const parentLink = this._getParentLinkForUser();
|
|
983
|
+
return this._validateUserLink(parentLink) && parentLink?.isAdmin === true;
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
/**
|
|
987
|
+
* Vérifie si l'utilisateur est membre de l'organisation parente.
|
|
988
|
+
*
|
|
989
|
+
* Cette méthode permet de vérifier si un utilisateur est membre actif d'une organisation.
|
|
990
|
+
* Elle est utile pour déterminer si un utilisateur a accès aux ressources de l'organisation.
|
|
991
|
+
*
|
|
992
|
+
* @returns `true` si l'utilisateur est membre validé de l'organisation parente, `false` sinon.
|
|
993
|
+
*
|
|
994
|
+
* @throws {ApiError} 401 - Si l'utilisateur n'est pas connecté.
|
|
995
|
+
* @throws {ApiError} 401 - Si l'utilisateur connecté n'est pas administrateur de l'entité parente.
|
|
996
|
+
* @throws {ApiError} 404 - Si l'utilisateur n'est pas enregistré (pas d'ID).
|
|
997
|
+
* @throws {ApiError} 404 - Si l'entité parente n'est pas enregistrée (pas d'ID).
|
|
998
|
+
* @throws {ApiError} 400 - Si l'entité parente n'est pas de type "organizations".
|
|
999
|
+
*
|
|
1000
|
+
* @example
|
|
1001
|
+
* // Vérifier les membres d'une organisation
|
|
1002
|
+
* const org = await me.organization({ slug: "myOrg" });
|
|
1003
|
+
* const members = await org.getMembers();
|
|
1004
|
+
*
|
|
1005
|
+
* for (const member of members.results) {
|
|
1006
|
+
* if (member.getEntityType() === "citoyens" && member.isMember()) {
|
|
1007
|
+
* console.log(`${member.data.name} est membre de l'organisation`);
|
|
1008
|
+
* }
|
|
1009
|
+
* }
|
|
1010
|
+
*/
|
|
1011
|
+
override isMember(): boolean {
|
|
1012
|
+
this._validateRoleCheckPreconditions("isMember", ["organizations"]);
|
|
1013
|
+
const parentLink = this._getParentLinkForUser();
|
|
1014
|
+
return this._validateUserLink(parentLink);
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
/**
|
|
1018
|
+
* Vérifie si l'utilisateur est contributeur du projet parent.
|
|
1019
|
+
*
|
|
1020
|
+
* Cette méthode permet de vérifier si un utilisateur est contributeur actif d'un projet.
|
|
1021
|
+
* Elle est utile pour déterminer si un utilisateur peut participer aux activités du projet.
|
|
1022
|
+
*
|
|
1023
|
+
* @returns `true` si l'utilisateur est contributeur validé du projet parent, `false` sinon.
|
|
1024
|
+
*
|
|
1025
|
+
* @throws {ApiError} 401 - Si l'utilisateur n'est pas connecté.
|
|
1026
|
+
* @throws {ApiError} 401 - Si l'utilisateur connecté n'est pas administrateur de l'entité parente.
|
|
1027
|
+
* @throws {ApiError} 404 - Si l'utilisateur n'est pas enregistré (pas d'ID).
|
|
1028
|
+
* @throws {ApiError} 404 - Si l'entité parente n'est pas enregistrée (pas d'ID).
|
|
1029
|
+
* @throws {ApiError} 400 - Si l'entité parente n'est pas de type "projects".
|
|
1030
|
+
*
|
|
1031
|
+
* @example
|
|
1032
|
+
* // Vérifier les contributeurs d'un projet
|
|
1033
|
+
* const project = await me.project({ slug: "myProject" });
|
|
1034
|
+
* const contributors = await project.getContributors();
|
|
1035
|
+
*
|
|
1036
|
+
* for (const contributor of contributors.results) {
|
|
1037
|
+
* if (contributor.getEntityType() === "citoyens" && contributor.isContributor()) {
|
|
1038
|
+
* console.log(`${contributor.data.name} est contributeur du projet`);
|
|
1039
|
+
* }
|
|
1040
|
+
* }
|
|
1041
|
+
*/
|
|
1042
|
+
override isContributor(): boolean {
|
|
1043
|
+
this._validateRoleCheckPreconditions("isContributor", ["projects"]);
|
|
1044
|
+
const parentLink = this._getParentLinkForUser();
|
|
1045
|
+
return this._validateUserLink(parentLink);
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
/**
|
|
1049
|
+
* Vérifie si l'utilisateur est participant de l'événement parent.
|
|
1050
|
+
*
|
|
1051
|
+
* Cette méthode permet de vérifier si un utilisateur est inscrit comme participant à un événement.
|
|
1052
|
+
* Elle est utile pour déterminer si un utilisateur a confirmé sa participation à l'événement.
|
|
1053
|
+
*
|
|
1054
|
+
* @returns `true` si l'utilisateur est participant validé de l'événement parent, `false` sinon.
|
|
1055
|
+
*
|
|
1056
|
+
* @throws {ApiError} 401 - Si l'utilisateur n'est pas connecté.
|
|
1057
|
+
* @throws {ApiError} 401 - Si l'utilisateur connecté n'est pas administrateur de l'entité parente.
|
|
1058
|
+
* @throws {ApiError} 404 - Si l'utilisateur n'est pas enregistré (pas d'ID).
|
|
1059
|
+
* @throws {ApiError} 404 - Si l'entité parente n'est pas enregistrée (pas d'ID).
|
|
1060
|
+
* @throws {ApiError} 400 - Si l'entité parente n'est pas de type "events".
|
|
1061
|
+
*
|
|
1062
|
+
* @example
|
|
1063
|
+
* // Vérifier les participants d'un événement
|
|
1064
|
+
* const event = await me.event({ slug: "myEvent" });
|
|
1065
|
+
* const attendees = await event.getAttendees();
|
|
1066
|
+
*
|
|
1067
|
+
* for (const attendee of attendees.results) {
|
|
1068
|
+
* if (attendee.getEntityType() === "citoyens" && attendee.isAttendee()) {
|
|
1069
|
+
* console.log(`${attendee.data.name} participe à l'événement`);
|
|
1070
|
+
* }
|
|
1071
|
+
* }
|
|
1072
|
+
*/
|
|
1073
|
+
override isAttendee(): boolean {
|
|
1074
|
+
this._validateRoleCheckPreconditions("isAttendee", ["events"]);
|
|
1075
|
+
const parentLink = this._getParentLinkForUser();
|
|
1076
|
+
return this._validateUserLink(parentLink);
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
/**
|
|
1080
|
+
* Vérifie si l'utilisateur a une invitation en attente d'acceptation pour l'entité parente.
|
|
1081
|
+
*
|
|
1082
|
+
* Cette méthode vérifie si l'utilisateur a été invité à rejoindre l'organisation, le projet
|
|
1083
|
+
* ou l'événement parent, mais n'a pas encore accepté l'invitation (`isInviting: true`).
|
|
1084
|
+
*
|
|
1085
|
+
* @returns {boolean} `true` si l'utilisateur a une invitation en attente, `false` sinon
|
|
1086
|
+
* @throws {ApiError} Si l'utilisateur n'est pas connecté, pas admin du parent, ou si le parent n'est pas défini
|
|
1087
|
+
*
|
|
1088
|
+
* @example
|
|
1089
|
+
* ```typescript
|
|
1090
|
+
* const org = await me.organization({ slug: "myOrg" });
|
|
1091
|
+
* const members = await org.getMembers();
|
|
1092
|
+
* const invitedUser = members.results.find(m => m.isInviting());
|
|
1093
|
+
* console.log("Invitation en attente:", invitedUser?.data.name);
|
|
1094
|
+
* ```
|
|
1095
|
+
*/
|
|
1096
|
+
isInviting(): boolean {
|
|
1097
|
+
this._validateRoleCheckPreconditions("isInviting", ["organizations", "projects", "events"]);
|
|
1098
|
+
const parentLink = this._getParentLinkForUser();
|
|
1099
|
+
if (!parentLink) return false;
|
|
1100
|
+
return parentLink?.isInviting === true;
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
/**
|
|
1104
|
+
* Vérifie si l'utilisateur a une invitation en attente avec des droits d'admin.
|
|
1105
|
+
*
|
|
1106
|
+
* Cette méthode vérifie si l'utilisateur a été invité à rejoindre l'organisation ou le projet
|
|
1107
|
+
* parent en tant qu'administrateur, mais n'a pas encore accepté (`isInviting: true` et `isAdmin: true`).
|
|
1108
|
+
*
|
|
1109
|
+
* @returns {boolean} `true` si l'utilisateur a une invitation admin en attente, `false` sinon
|
|
1110
|
+
* @throws {ApiError} Si l'utilisateur n'est pas connecté, pas admin du parent, ou si le parent n'est pas défini
|
|
1111
|
+
*
|
|
1112
|
+
* @example
|
|
1113
|
+
* ```typescript
|
|
1114
|
+
* const org = await me.organization({ slug: "myOrg" });
|
|
1115
|
+
* const members = await org.getMembers();
|
|
1116
|
+
* const invitedAdmin = members.results.find(m => m.isInvitingAdmin());
|
|
1117
|
+
* console.log("Invitation admin en attente:", invitedAdmin?.data.name);
|
|
1118
|
+
* ```
|
|
1119
|
+
*/
|
|
1120
|
+
isInvitingAdmin(): boolean {
|
|
1121
|
+
this._validateRoleCheckPreconditions("isInvitingAdmin", ["organizations", "projects"]);
|
|
1122
|
+
const parentLink = this._getParentLinkForUser();
|
|
1123
|
+
if (!parentLink) return false;
|
|
1124
|
+
return parentLink?.isAdminInviting === true && parentLink?.isAdmin === true;
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
/**
|
|
1128
|
+
* Vérifie si l'utilisateur a une demande de promotion admin en attente de validation.
|
|
1129
|
+
*
|
|
1130
|
+
* Cette méthode vérifie si l'utilisateur a demandé ou a été proposé pour devenir administrateur
|
|
1131
|
+
* de l'organisation ou du projet parent, mais la demande n'a pas encore été validée (`isAdminPending: true`).
|
|
1132
|
+
*
|
|
1133
|
+
* @returns {boolean} `true` si l'utilisateur a une demande admin en attente, `false` sinon
|
|
1134
|
+
* @throws {ApiError} Si l'utilisateur n'est pas connecté, pas admin du parent, ou si le parent n'est pas défini
|
|
1135
|
+
*
|
|
1136
|
+
* @example
|
|
1137
|
+
* ```typescript
|
|
1138
|
+
* const org = await me.organization({ slug: "myOrg" });
|
|
1139
|
+
* const members = await org.getMembers();
|
|
1140
|
+
* const pendingAdmin = members.results.find(m => m.isAdminPending());
|
|
1141
|
+
* if (pendingAdmin) {
|
|
1142
|
+
* await pendingAdmin.validateAdminRequest();
|
|
1143
|
+
* }
|
|
1144
|
+
* ```
|
|
1145
|
+
*/
|
|
1146
|
+
isAdminPending(): boolean {
|
|
1147
|
+
this._validateRoleCheckPreconditions("isAdminPending", ["organizations", "projects"]);
|
|
1148
|
+
const parentLink = this._getParentLinkForUser();
|
|
1149
|
+
return parentLink?.isAdmin === true && parentLink?.isAdminPending === true;
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
/**
|
|
1153
|
+
* Vérifie si l'utilisateur a une demande d'adhésion en attente de validation.
|
|
1154
|
+
*
|
|
1155
|
+
* Cette méthode vérifie si l'utilisateur a demandé à rejoindre l'organisation, le projet
|
|
1156
|
+
* ou l'événement parent, mais la demande n'a pas encore été validée par un administrateur (`toBeValidated: true`).
|
|
1157
|
+
*
|
|
1158
|
+
* @returns {boolean} `true` si l'utilisateur a une demande en attente, `false` sinon
|
|
1159
|
+
* @throws {ApiError} Si l'utilisateur n'est pas connecté, pas admin du parent, ou si le parent n'est pas défini
|
|
1160
|
+
*
|
|
1161
|
+
* @example
|
|
1162
|
+
* ```typescript
|
|
1163
|
+
* const org = await me.organization({ slug: "myOrg" });
|
|
1164
|
+
* const members = await org.getMembers();
|
|
1165
|
+
* const pendingUser = members.results.find(m => m.isToBeValidated());
|
|
1166
|
+
* if (pendingUser) {
|
|
1167
|
+
* await pendingUser.validateMemberRequest();
|
|
1168
|
+
* }
|
|
1169
|
+
* ```
|
|
1170
|
+
*/
|
|
1171
|
+
isToBeValidated(): boolean {
|
|
1172
|
+
this._validateRoleCheckPreconditions("isToBeValidated", ["organizations", "projects", "events"]);
|
|
1173
|
+
const parentLink = this._getParentLinkForUser();
|
|
1174
|
+
return parentLink?.toBeValidated === true;
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
|
|
1178
|
+
// ────────────────────────────────
|
|
1179
|
+
// Actions d'admin sur l'utilisateur par rapport à l'entité parente
|
|
1180
|
+
// ────────────────────────────────
|
|
1181
|
+
|
|
1182
|
+
/**
|
|
1183
|
+
* Envoie une demande pour rejoindre l'entité parente.
|
|
1184
|
+
*
|
|
1185
|
+
* Cette méthode permet à un admin de créer une demande de connexion pour un utilisateur
|
|
1186
|
+
* vers l'organisation ou le projet parent. Si l'utilisateur n'a pas encore de lien,
|
|
1187
|
+
* une demande de connexion est créée.
|
|
1188
|
+
*
|
|
1189
|
+
* @returns {Promise<unknown>} La réponse de l'API après création de la demande
|
|
1190
|
+
* @throws {ApiError} Si l'utilisateur n'est pas connecté, pas admin, ou si le parent n'est pas défini
|
|
1191
|
+
* @throws {ApiError} Si l'utilisateur est déjà en attente de validation
|
|
1192
|
+
* @throws {ApiError} Si l'utilisateur est déjà connecté à l'entité
|
|
1193
|
+
*
|
|
1194
|
+
* @example
|
|
1195
|
+
* ```typescript
|
|
1196
|
+
* // Un admin récupère les membres et envoie une invitation
|
|
1197
|
+
* const org = await me.organization({ slug: "myOrg" });
|
|
1198
|
+
* const users = await org.getMembers();
|
|
1199
|
+
* const user = users.results[0];
|
|
1200
|
+
* await user.sendRequestToJoinParent();
|
|
1201
|
+
* ```
|
|
1202
|
+
*/
|
|
1203
|
+
async sendRequestToJoinParent(): Promise<unknown> {
|
|
1204
|
+
this._validateRoleCheckPreconditions("sendRequestToJoinParent", ["organizations", "projects"]);
|
|
1205
|
+
|
|
1206
|
+
const { connectTypeConnect } = this.parent!._getLinkMeta();
|
|
1207
|
+
|
|
1208
|
+
const parentLink = this._getParentLinkForUser();
|
|
1209
|
+
|
|
1210
|
+
// Cas : aucun lien → on demande à se connecter
|
|
1211
|
+
if (!parentLink) {
|
|
1212
|
+
|
|
1213
|
+
const t = this.parent!.getEntityType();
|
|
1214
|
+
|
|
1215
|
+
// 2) Narrow de type pour TypeScript
|
|
1216
|
+
const parentType = t as ConnectData["parentType"];
|
|
1217
|
+
|
|
1218
|
+
const data: ConnectData = {
|
|
1219
|
+
childId: this.id!,
|
|
1220
|
+
childType: "citoyens",
|
|
1221
|
+
parentType,
|
|
1222
|
+
parentId: this.parent!.id!,
|
|
1223
|
+
connectType: connectTypeConnect
|
|
1224
|
+
};
|
|
1225
|
+
|
|
1226
|
+
const retour = await this.callIsConnected(() => this.endpointApi.connect(data));
|
|
1227
|
+
// Refresh l'utilisateur membre et l'entité parente
|
|
1228
|
+
await this.refresh();
|
|
1229
|
+
if (this.parent) {
|
|
1230
|
+
await this.parent.refresh();
|
|
1231
|
+
}
|
|
1232
|
+
return retour;
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
// Cas : déjà en attente
|
|
1236
|
+
if (parentLink.toBeValidated) {
|
|
1237
|
+
throw new ApiError("Vous êtes déjà en attente de validation.", 400);
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
// Cas par défaut : rien à faire
|
|
1241
|
+
throw new ApiError("Vous êtes déjà connecté à cette entité.", 400);
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
/**
|
|
1245
|
+
* Valide une demande de membre en attente de validation.
|
|
1246
|
+
*
|
|
1247
|
+
* Cette méthode permet à un admin de valider une demande d'adhésion d'un utilisateur
|
|
1248
|
+
* qui est en attente (`toBeValidated: true`). Après validation, l'utilisateur devient
|
|
1249
|
+
* membre actif de l'entité parente.
|
|
1250
|
+
*
|
|
1251
|
+
* @returns {Promise<unknown>} La réponse de l'API après validation
|
|
1252
|
+
* @throws {ApiError} Si l'utilisateur n'est pas connecté, pas admin, ou si le parent n'est pas défini
|
|
1253
|
+
* @throws {ApiError} Si l'utilisateur n'a pas de demande en attente
|
|
1254
|
+
*
|
|
1255
|
+
* @example
|
|
1256
|
+
* ```typescript
|
|
1257
|
+
* // Un admin valide une demande en attente
|
|
1258
|
+
* const org = await me.organization({ slug: "myOrg" });
|
|
1259
|
+
* const members = await org.getMembers();
|
|
1260
|
+
* const pendingUser = members.results.find(u => u.serverData.links?.memberOf?.[org.id]?.toBeValidated);
|
|
1261
|
+
* await pendingUser.validateMemberRequest();
|
|
1262
|
+
* ```
|
|
1263
|
+
*/
|
|
1264
|
+
async validateMemberRequest(): Promise<unknown> {
|
|
1265
|
+
this._validateRoleCheckPreconditions("validateMemberRequest", ["organizations", "projects"]);
|
|
1266
|
+
|
|
1267
|
+
const parentLink = this._getParentLinkForUser();
|
|
1268
|
+
|
|
1269
|
+
if (!parentLink?.toBeValidated) {
|
|
1270
|
+
throw new ApiError("Cet utilisateur n'a pas de demande en attente de validation.", 400);
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1273
|
+
const t = this.parent!.getEntityType();
|
|
1274
|
+
|
|
1275
|
+
const parentType = t as LinkValidateData["parentType"];
|
|
1276
|
+
|
|
1277
|
+
const data: LinkValidateData = {
|
|
1278
|
+
childId: this.id!,
|
|
1279
|
+
childType: "citoyens",
|
|
1280
|
+
parentType,
|
|
1281
|
+
parentId: this.parent!.id!,
|
|
1282
|
+
linkOption: "toBeValidated"
|
|
1283
|
+
};
|
|
1284
|
+
|
|
1285
|
+
const retour = await this.callIsConnected(() => this.endpointApi.linkValidate(data));
|
|
1286
|
+
// Refresh l'utilisateur membre et l'entité parente
|
|
1287
|
+
await this.refresh();
|
|
1288
|
+
if (this.parent) {
|
|
1289
|
+
await this.parent.refresh();
|
|
1290
|
+
}
|
|
1291
|
+
return retour;
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1294
|
+
/**
|
|
1295
|
+
* Valide une invitation en attente d'acceptation.
|
|
1296
|
+
*
|
|
1297
|
+
* Cette méthode permet à un admin de valider une invitation envoyée à un utilisateur
|
|
1298
|
+
* qui est en attente (`isInviting: true`). Après validation, l'utilisateur devient
|
|
1299
|
+
* membre actif de l'entité parente.
|
|
1300
|
+
*
|
|
1301
|
+
* @returns {Promise<unknown>} La réponse de l'API après validation
|
|
1302
|
+
* @throws {ApiError} Si l'utilisateur n'est pas connecté, pas admin, ou si le parent n'est pas défini
|
|
1303
|
+
* @throws {ApiError} Si l'utilisateur n'a pas d'invitation en attente
|
|
1304
|
+
*
|
|
1305
|
+
* @example
|
|
1306
|
+
* ```typescript
|
|
1307
|
+
* // Un admin valide une invitation en attente
|
|
1308
|
+
* const org = await me.organization({ slug: "myOrg" });
|
|
1309
|
+
* const members = await org.getMembers();
|
|
1310
|
+
* const invitedUser = members.results.find(u => u.serverData.links?.memberOf?.[org.id]?.isInviting);
|
|
1311
|
+
* await invitedUser.validateInvitation();
|
|
1312
|
+
* ```
|
|
1313
|
+
*/
|
|
1314
|
+
// async validateInvitation(): Promise<unknown> {
|
|
1315
|
+
// this._validateRoleCheckPreconditions("validateInvitation", ["organizations", "projects"]);
|
|
1316
|
+
|
|
1317
|
+
// const parentLink = this._getParentLinkForUser();
|
|
1318
|
+
|
|
1319
|
+
// if (!parentLink?.isInviting) {
|
|
1320
|
+
// throw new ApiError("Cet utilisateur n'a pas d'invitation en attente.", 400);
|
|
1321
|
+
// }
|
|
1322
|
+
|
|
1323
|
+
// const t = this.parent!.getEntityType();
|
|
1324
|
+
|
|
1325
|
+
// const parentType = t as LinkValidateData["parentType"];
|
|
1326
|
+
|
|
1327
|
+
// const data: LinkValidateData = {
|
|
1328
|
+
// childId: this.id!,
|
|
1329
|
+
// childType: "citoyens",
|
|
1330
|
+
// parentType,
|
|
1331
|
+
// parentId: this.parent!.id!,
|
|
1332
|
+
// linkOption: "isInviting"
|
|
1333
|
+
// };
|
|
1334
|
+
|
|
1335
|
+
// const retour = await this.callIsConnected(() => this.endpointApi.linkValidate(data));
|
|
1336
|
+
// // Refresh l'utilisateur membre et l'entité parente
|
|
1337
|
+
// await this.refresh();
|
|
1338
|
+
// if (this.parent) {
|
|
1339
|
+
// await this.parent.refresh();
|
|
1340
|
+
// }
|
|
1341
|
+
// return retour;
|
|
1342
|
+
// }
|
|
1343
|
+
|
|
1344
|
+
/**
|
|
1345
|
+
* Valide une demande d'admin en attente.
|
|
1346
|
+
*
|
|
1347
|
+
* Cette méthode permet à un admin de valider une demande de promotion au statut d'admin
|
|
1348
|
+
* pour un utilisateur qui est en attente (`isAdminPending: true`). Après validation,
|
|
1349
|
+
* l'utilisateur devient admin de l'entité parente.
|
|
1350
|
+
*
|
|
1351
|
+
* @returns {Promise<unknown>} La réponse de l'API après validation
|
|
1352
|
+
* @throws {ApiError} Si l'utilisateur n'est pas connecté, pas admin, ou si le parent n'est pas défini
|
|
1353
|
+
* @throws {ApiError} Si l'utilisateur n'a pas de demande d'admin en attente
|
|
1354
|
+
*
|
|
1355
|
+
* @example
|
|
1356
|
+
* ```typescript
|
|
1357
|
+
* // Un admin valide une demande de promotion à admin
|
|
1358
|
+
* const org = await me.organization({ slug: "myOrg" });
|
|
1359
|
+
* const members = await org.getMembers();
|
|
1360
|
+
* const pendingAdmin = members.results.find(u => u.serverData.links?.memberOf?.[org.id]?.isAdminPending);
|
|
1361
|
+
* await pendingAdmin.validateAdminRequest();
|
|
1362
|
+
* ```
|
|
1363
|
+
*/
|
|
1364
|
+
async validateAdminRequest(): Promise<unknown> {
|
|
1365
|
+
this._validateRoleCheckPreconditions("validateAdminRequest", ["organizations", "projects"]);
|
|
1366
|
+
|
|
1367
|
+
const parentLink = this._getParentLinkForUser();
|
|
1368
|
+
|
|
1369
|
+
if (!parentLink?.isAdminPending) {
|
|
1370
|
+
throw new ApiError("Cet utilisateur n'a pas de demande d'admin en attente.", 400);
|
|
1371
|
+
}
|
|
1372
|
+
|
|
1373
|
+
const t = this.parent!.getEntityType();
|
|
1374
|
+
|
|
1375
|
+
const parentType = t as LinkValidateData["parentType"];
|
|
1376
|
+
|
|
1377
|
+
const data: LinkValidateData = {
|
|
1378
|
+
childId: this.id!,
|
|
1379
|
+
childType: "citoyens",
|
|
1380
|
+
parentType,
|
|
1381
|
+
parentId: this.parent!.id!,
|
|
1382
|
+
linkOption: "isAdminPending"
|
|
1383
|
+
};
|
|
1384
|
+
|
|
1385
|
+
const retour = await this.callIsConnected(() => this.endpointApi.linkValidate(data));
|
|
1386
|
+
// Refresh l'utilisateur membre et l'entité parente
|
|
1387
|
+
await this.refresh();
|
|
1388
|
+
if (this.parent) {
|
|
1389
|
+
await this.parent.refresh();
|
|
1390
|
+
}
|
|
1391
|
+
return retour;
|
|
1392
|
+
}
|
|
1393
|
+
|
|
1394
|
+
/**
|
|
1395
|
+
* Retire un utilisateur de l'entité parente.
|
|
1396
|
+
*
|
|
1397
|
+
* Cette méthode permet à un admin de déconnecter un membre de l'organisation ou du projet parent.
|
|
1398
|
+
* L'utilisateur perd tous ses liens avec l'entité (membre, admin, etc.).
|
|
1399
|
+
*
|
|
1400
|
+
* @returns {Promise<unknown>} La réponse de l'API après déconnexion
|
|
1401
|
+
* @throws {ApiError} Si l'utilisateur n'est pas connecté, pas admin, ou si le parent n'est pas défini
|
|
1402
|
+
* @throws {ApiError} Si l'utilisateur n'est pas membre de l'entité
|
|
1403
|
+
*
|
|
1404
|
+
* @example
|
|
1405
|
+
* ```typescript
|
|
1406
|
+
* // Un admin retire un membre
|
|
1407
|
+
* const org = await me.organization({ slug: "myOrg" });
|
|
1408
|
+
* const members = await org.getMembers();
|
|
1409
|
+
* const userToRemove = members.results[0];
|
|
1410
|
+
* await userToRemove.removeFromParent();
|
|
1411
|
+
* ```
|
|
1412
|
+
*/
|
|
1413
|
+
async removeFromParent(): Promise<unknown> {
|
|
1414
|
+
this._validateRoleCheckPreconditions("removeFromParent", ["organizations", "projects"]);
|
|
1415
|
+
|
|
1416
|
+
const parentLink = this._getParentLinkForUser();
|
|
1417
|
+
|
|
1418
|
+
if (!parentLink) {
|
|
1419
|
+
throw new ApiError("Cet utilisateur n'est pas connecté à cette entité.", 400);
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
const t = this.parent!.getEntityType();
|
|
1423
|
+
|
|
1424
|
+
const parentType = t as DisconnectData["parentType"];
|
|
1425
|
+
|
|
1426
|
+
const { connectTypeDisconnect } = this.parent!._getLinkMeta();
|
|
1427
|
+
|
|
1428
|
+
const data: DisconnectData = {
|
|
1429
|
+
childId: this.id!,
|
|
1430
|
+
childType: "citoyens",
|
|
1431
|
+
parentType,
|
|
1432
|
+
parentId: this.parent!.id!,
|
|
1433
|
+
connectType: connectTypeDisconnect
|
|
1434
|
+
};
|
|
1435
|
+
|
|
1436
|
+
const retour = await this.callIsConnected(() => this.endpointApi.disconnect(data));
|
|
1437
|
+
// Refresh l'utilisateur membre et l'entité parente
|
|
1438
|
+
await this.refresh();
|
|
1439
|
+
if (this.parent) {
|
|
1440
|
+
await this.parent.refresh();
|
|
1441
|
+
}
|
|
1442
|
+
return retour;
|
|
1443
|
+
}
|
|
1444
|
+
|
|
1445
|
+
/**
|
|
1446
|
+
* Promeut un utilisateur au statut d'admin de l'entité parente.
|
|
1447
|
+
*
|
|
1448
|
+
* Cette méthode permet à un admin de promouvoir un membre ordinaire au statut d'admin
|
|
1449
|
+
* de l'organisation ou du projet parent.
|
|
1450
|
+
*
|
|
1451
|
+
* @returns {Promise<unknown>} La réponse de l'API après promotion
|
|
1452
|
+
* @throws {ApiError} Si l'utilisateur n'est pas connecté, pas admin, ou si le parent n'est pas défini
|
|
1453
|
+
* @throws {ApiError} Si l'utilisateur n'est pas membre de l'entité
|
|
1454
|
+
* @throws {ApiError} Si l'utilisateur est déjà admin
|
|
1455
|
+
*
|
|
1456
|
+
* @example
|
|
1457
|
+
* ```typescript
|
|
1458
|
+
* // Un admin promeut un membre au statut d'admin
|
|
1459
|
+
* const org = await me.organization({ slug: "myOrg" });
|
|
1460
|
+
* const members = await org.getMembers();
|
|
1461
|
+
* const userToPromote = members.results.find(u => !u.isAdmin());
|
|
1462
|
+
* await userToPromote.promoteToAdmin();
|
|
1463
|
+
* ```
|
|
1464
|
+
*/
|
|
1465
|
+
async promoteToAdmin(): Promise<unknown> {
|
|
1466
|
+
this._validateRoleCheckPreconditions("promoteToAdmin", ["organizations", "projects"]);
|
|
1467
|
+
|
|
1468
|
+
const parentLink = this._getParentLinkForUser();
|
|
1469
|
+
|
|
1470
|
+
if (!parentLink) {
|
|
1471
|
+
throw new ApiError("Cet utilisateur n'est pas membre de cette entité.", 400);
|
|
1472
|
+
}
|
|
1473
|
+
|
|
1474
|
+
if (parentLink.isAdmin && !parentLink.isAdminPending) {
|
|
1475
|
+
throw new ApiError("Cet utilisateur est déjà admin.", 400);
|
|
1476
|
+
}
|
|
1477
|
+
|
|
1478
|
+
const t = this.parent!.getEntityType();
|
|
1479
|
+
|
|
1480
|
+
const parentType = t as ConnectData["parentType"];
|
|
1481
|
+
|
|
1482
|
+
const data: ConnectData = {
|
|
1483
|
+
childId: this.id!,
|
|
1484
|
+
childType: "citoyens",
|
|
1485
|
+
parentType,
|
|
1486
|
+
parentId: this.parent!.id!,
|
|
1487
|
+
connectType: "admin"
|
|
1488
|
+
};
|
|
1489
|
+
|
|
1490
|
+
const retour = await this.callIsConnected(() => this.endpointApi.connect(data));
|
|
1491
|
+
// Refresh l'utilisateur membre et l'entité parente
|
|
1492
|
+
await this.refresh();
|
|
1493
|
+
if (this.parent) {
|
|
1494
|
+
await this.parent.refresh();
|
|
1495
|
+
}
|
|
1496
|
+
return retour;
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1499
|
+
/**
|
|
1500
|
+
* Rétrograde un admin au statut de membre ordinaire.
|
|
1501
|
+
*
|
|
1502
|
+
* Cette méthode permet à un admin de rétrograder un autre admin au statut de membre
|
|
1503
|
+
* ordinaire de l'organisation ou du projet parent. L'utilisateur perd ses privilèges d'admin
|
|
1504
|
+
* mais reste membre de l'entité.
|
|
1505
|
+
*
|
|
1506
|
+
* @returns {Promise<unknown>} La réponse de l'API après rétrogradation
|
|
1507
|
+
* @throws {ApiError} Si l'utilisateur n'est pas connecté, pas admin, ou si le parent n'est pas défini
|
|
1508
|
+
* @throws {ApiError} Si l'utilisateur n'est pas admin de l'entité
|
|
1509
|
+
*
|
|
1510
|
+
* @example
|
|
1511
|
+
* ```typescript
|
|
1512
|
+
* // Un admin rétrograde un autre admin
|
|
1513
|
+
* const org = await me.organization({ slug: "myOrg" });
|
|
1514
|
+
* const admins = await org.getMembers({}, { isAdmin: true });
|
|
1515
|
+
* const adminToDemote = admins.results.find(u => u.isAdmin());
|
|
1516
|
+
* await adminToDemote.demoteFromAdmin();
|
|
1517
|
+
* ```
|
|
1518
|
+
*/
|
|
1519
|
+
async demoteFromAdmin(): Promise<unknown> {
|
|
1520
|
+
this._validateRoleCheckPreconditions("demoteFromAdmin", ["organizations", "projects"]);
|
|
1521
|
+
|
|
1522
|
+
const parentLink = this._getParentLinkForUser();
|
|
1523
|
+
|
|
1524
|
+
if (!parentLink?.isAdmin || parentLink.isAdminPending) {
|
|
1525
|
+
throw new ApiError("Cet utilisateur n'est pas admin de cette entité.", 400);
|
|
1526
|
+
}
|
|
1527
|
+
|
|
1528
|
+
const t = this.parent!.getEntityType();
|
|
1529
|
+
|
|
1530
|
+
const { connectTypeDisconnect } = this.parent!._getLinkMeta();
|
|
1531
|
+
|
|
1532
|
+
const parentType = t as DemoteAdminData["parentType"];
|
|
1533
|
+
|
|
1534
|
+
// Pour rétrograder un admin, on déconnecte le lien "admin"
|
|
1535
|
+
// L'utilisateur garde son lien "member"
|
|
1536
|
+
const data: DemoteAdminData = {
|
|
1537
|
+
childId: this.id!,
|
|
1538
|
+
childType: "citoyens",
|
|
1539
|
+
parentType,
|
|
1540
|
+
parentId: this.parent!.id!,
|
|
1541
|
+
connect: connectTypeDisconnect as DemoteAdminData["connect"],
|
|
1542
|
+
isAdmin: false
|
|
1543
|
+
};
|
|
1544
|
+
|
|
1545
|
+
const retour = await this.callIsConnected(() => this.endpointApi.demoteAdmin(data));
|
|
1546
|
+
// Refresh l'utilisateur membre et l'entité parente
|
|
1547
|
+
await this.refresh();
|
|
1548
|
+
if (this.parent) {
|
|
1549
|
+
await this.parent.refresh();
|
|
1550
|
+
}
|
|
1551
|
+
return retour;
|
|
1552
|
+
}
|
|
1553
|
+
|
|
891
1554
|
}
|
|
892
1555
|
|
|
893
1556
|
// Incorporation des mixins dans User
|