@viridial/shared 1.0.2
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 +114 -0
- package/USER-MODULE.md +268 -0
- package/dist/api/auth.service.d.ts +35 -0
- package/dist/api/auth.service.d.ts.map +1 -0
- package/dist/api/auth.service.js +63 -0
- package/dist/api/http.client.d.ts +19 -0
- package/dist/api/http.client.d.ts.map +1 -0
- package/dist/api/http.client.js +97 -0
- package/dist/api/property.service.d.ts +31 -0
- package/dist/api/property.service.d.ts.map +1 -0
- package/dist/api/property.service.js +47 -0
- package/dist/api/user.service.d.ts +86 -0
- package/dist/api/user.service.d.ts.map +1 -0
- package/dist/api/user.service.js +145 -0
- package/dist/composables/useAuth.d.ts +21 -0
- package/dist/composables/useAuth.d.ts.map +1 -0
- package/dist/composables/useAuth.js +43 -0
- package/dist/composables/useUser.d.ts +173 -0
- package/dist/composables/useUser.d.ts.map +1 -0
- package/dist/composables/useUser.js +132 -0
- package/dist/constants/api.constants.d.ts +32 -0
- package/dist/constants/api.constants.d.ts.map +1 -0
- package/dist/constants/api.constants.js +35 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/stores/auth.store.d.ts +75 -0
- package/dist/stores/auth.store.d.ts.map +1 -0
- package/dist/stores/auth.store.js +71 -0
- package/dist/stores/user.store.d.ts +748 -0
- package/dist/stores/user.store.d.ts.map +1 -0
- package/dist/stores/user.store.js +264 -0
- package/dist/types/api.types.d.ts +27 -0
- package/dist/types/api.types.d.ts.map +1 -0
- package/dist/types/api.types.js +4 -0
- package/dist/types/auth.types.d.ts +38 -0
- package/dist/types/auth.types.d.ts.map +1 -0
- package/dist/types/auth.types.js +4 -0
- package/dist/types/property.types.d.ts +66 -0
- package/dist/types/property.types.d.ts.map +1 -0
- package/dist/types/property.types.js +20 -0
- package/dist/types/user.types.d.ts +103 -0
- package/dist/types/user.types.d.ts.map +1 -0
- package/dist/types/user.types.js +21 -0
- package/dist/utils/token.utils.d.ts +30 -0
- package/dist/utils/token.utils.d.ts.map +1 -0
- package/dist/utils/token.utils.js +56 -0
- package/package.json +96 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { User, UserCreate, UserUpdate, UserSearchParams, UserProfile, UserStats, UserActivity } from '../types/user.types';
|
|
2
|
+
/**
|
|
3
|
+
* Service de gestion des utilisateurs SaaS
|
|
4
|
+
*/
|
|
5
|
+
export declare const userService: {
|
|
6
|
+
/**
|
|
7
|
+
* Récupérer tous les utilisateurs avec filtres et pagination
|
|
8
|
+
*/
|
|
9
|
+
getAll(params?: UserSearchParams): Promise<{
|
|
10
|
+
users: User[];
|
|
11
|
+
total: number;
|
|
12
|
+
}>;
|
|
13
|
+
/**
|
|
14
|
+
* Récupérer un utilisateur par ID
|
|
15
|
+
*/
|
|
16
|
+
getById(id: number): Promise<User>;
|
|
17
|
+
/**
|
|
18
|
+
* Récupérer le profil de l'utilisateur connecté
|
|
19
|
+
*/
|
|
20
|
+
getProfile(): Promise<UserProfile>;
|
|
21
|
+
/**
|
|
22
|
+
* Créer un nouvel utilisateur
|
|
23
|
+
*/
|
|
24
|
+
create(data: UserCreate): Promise<User>;
|
|
25
|
+
/**
|
|
26
|
+
* Mettre à jour un utilisateur
|
|
27
|
+
*/
|
|
28
|
+
update(id: number, data: UserUpdate): Promise<User>;
|
|
29
|
+
/**
|
|
30
|
+
* Mettre à jour le profil de l'utilisateur connecté
|
|
31
|
+
*/
|
|
32
|
+
updateProfile(data: UserUpdate): Promise<UserProfile>;
|
|
33
|
+
/**
|
|
34
|
+
* Supprimer un utilisateur (soft delete)
|
|
35
|
+
*/
|
|
36
|
+
delete(id: number): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Activer un utilisateur
|
|
39
|
+
*/
|
|
40
|
+
activate(id: number): Promise<User>;
|
|
41
|
+
/**
|
|
42
|
+
* Désactiver un utilisateur
|
|
43
|
+
*/
|
|
44
|
+
deactivate(id: number): Promise<User>;
|
|
45
|
+
/**
|
|
46
|
+
* Suspendre un utilisateur
|
|
47
|
+
*/
|
|
48
|
+
suspend(id: number, reason?: string): Promise<User>;
|
|
49
|
+
/**
|
|
50
|
+
* Réinitialiser le mot de passe d'un utilisateur
|
|
51
|
+
*/
|
|
52
|
+
resetPassword(id: number, newPassword: string): Promise<void>;
|
|
53
|
+
/**
|
|
54
|
+
* Changer le mot de passe de l'utilisateur connecté
|
|
55
|
+
*/
|
|
56
|
+
changePassword(currentPassword: string, newPassword: string): Promise<void>;
|
|
57
|
+
/**
|
|
58
|
+
* Vérifier l'email d'un utilisateur
|
|
59
|
+
*/
|
|
60
|
+
verifyEmail(token: string): Promise<void>;
|
|
61
|
+
/**
|
|
62
|
+
* Renvoyer l'email de vérification
|
|
63
|
+
*/
|
|
64
|
+
resendVerificationEmail(): Promise<void>;
|
|
65
|
+
/**
|
|
66
|
+
* Récupérer les statistiques des utilisateurs
|
|
67
|
+
*/
|
|
68
|
+
getStats(): Promise<UserStats>;
|
|
69
|
+
/**
|
|
70
|
+
* Récupérer l'activité d'un utilisateur
|
|
71
|
+
*/
|
|
72
|
+
getActivity(userId: number, limit?: number): Promise<UserActivity[]>;
|
|
73
|
+
/**
|
|
74
|
+
* Rechercher des utilisateurs
|
|
75
|
+
*/
|
|
76
|
+
search(query: string, params?: UserSearchParams): Promise<User[]>;
|
|
77
|
+
/**
|
|
78
|
+
* Assigner des rôles à un utilisateur
|
|
79
|
+
*/
|
|
80
|
+
assignRoles(userId: number, roles: string[]): Promise<User>;
|
|
81
|
+
/**
|
|
82
|
+
* Retirer des rôles d'un utilisateur
|
|
83
|
+
*/
|
|
84
|
+
removeRoles(userId: number, roles: string[]): Promise<User>;
|
|
85
|
+
};
|
|
86
|
+
//# sourceMappingURL=user.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user.service.d.ts","sourceRoot":"","sources":["../../api/user.service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,gBAAgB,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAG/H;;GAEG;AACH,eAAO,MAAM,WAAW;IACtB;;OAEG;oBACmB,gBAAgB,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAWlF;;OAEG;gBACe,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKxC;;OAEG;kBACiB,OAAO,CAAC,WAAW,CAAC;IAKxC;;OAEG;iBACgB,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAK7C;;OAEG;eACc,MAAM,QAAQ,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAKzD;;OAEG;wBACuB,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC;IAK3D;;OAEG;eACc,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvC;;OAEG;iBACgB,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKzC;;OAEG;mBACkB,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK3C;;OAEG;gBACe,MAAM,WAAW,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKzD;;OAEG;sBACqB,MAAM,eAAe,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAInE;;OAEG;oCACmC,MAAM,eAAe,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOjF;;OAEG;uBACsB,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/C;;OAEG;+BAC8B,OAAO,CAAC,IAAI,CAAC;IAI9C;;OAEG;gBACe,OAAO,CAAC,SAAS,CAAC;IAKpC;;OAEG;wBACuB,MAAM,UAAU,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAQ1E;;OAEG;kBACiB,MAAM,WAAW,gBAAgB,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAOvE;;OAEG;wBACuB,MAAM,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAKjE;;OAEG;wBACuB,MAAM,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAMlE,CAAA"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { httpClient } from './http.client';
|
|
2
|
+
import { API_ENDPOINTS } from '../constants/api.constants';
|
|
3
|
+
/**
|
|
4
|
+
* Service de gestion des utilisateurs SaaS
|
|
5
|
+
*/
|
|
6
|
+
export const userService = {
|
|
7
|
+
/**
|
|
8
|
+
* Récupérer tous les utilisateurs avec filtres et pagination
|
|
9
|
+
*/
|
|
10
|
+
async getAll(params) {
|
|
11
|
+
const response = await httpClient.get(API_ENDPOINTS.USERS.BASE, { params });
|
|
12
|
+
return {
|
|
13
|
+
users: response.data?.content || response.data || [],
|
|
14
|
+
total: response.data?.totalElements || 0
|
|
15
|
+
};
|
|
16
|
+
},
|
|
17
|
+
/**
|
|
18
|
+
* Récupérer un utilisateur par ID
|
|
19
|
+
*/
|
|
20
|
+
async getById(id) {
|
|
21
|
+
const response = await httpClient.get(API_ENDPOINTS.USERS.BY_ID(id));
|
|
22
|
+
return response.data;
|
|
23
|
+
},
|
|
24
|
+
/**
|
|
25
|
+
* Récupérer le profil de l'utilisateur connecté
|
|
26
|
+
*/
|
|
27
|
+
async getProfile() {
|
|
28
|
+
const response = await httpClient.get(API_ENDPOINTS.USERS.PROFILE);
|
|
29
|
+
return response.data;
|
|
30
|
+
},
|
|
31
|
+
/**
|
|
32
|
+
* Créer un nouvel utilisateur
|
|
33
|
+
*/
|
|
34
|
+
async create(data) {
|
|
35
|
+
const response = await httpClient.post(API_ENDPOINTS.USERS.BASE, data);
|
|
36
|
+
return response.data;
|
|
37
|
+
},
|
|
38
|
+
/**
|
|
39
|
+
* Mettre à jour un utilisateur
|
|
40
|
+
*/
|
|
41
|
+
async update(id, data) {
|
|
42
|
+
const response = await httpClient.put(API_ENDPOINTS.USERS.BY_ID(id), data);
|
|
43
|
+
return response.data;
|
|
44
|
+
},
|
|
45
|
+
/**
|
|
46
|
+
* Mettre à jour le profil de l'utilisateur connecté
|
|
47
|
+
*/
|
|
48
|
+
async updateProfile(data) {
|
|
49
|
+
const response = await httpClient.put(API_ENDPOINTS.USERS.PROFILE, data);
|
|
50
|
+
return response.data;
|
|
51
|
+
},
|
|
52
|
+
/**
|
|
53
|
+
* Supprimer un utilisateur (soft delete)
|
|
54
|
+
*/
|
|
55
|
+
async delete(id) {
|
|
56
|
+
await httpClient.delete(API_ENDPOINTS.USERS.BY_ID(id));
|
|
57
|
+
},
|
|
58
|
+
/**
|
|
59
|
+
* Activer un utilisateur
|
|
60
|
+
*/
|
|
61
|
+
async activate(id) {
|
|
62
|
+
const response = await httpClient.patch(`${API_ENDPOINTS.USERS.BY_ID(id)}/activate`);
|
|
63
|
+
return response.data;
|
|
64
|
+
},
|
|
65
|
+
/**
|
|
66
|
+
* Désactiver un utilisateur
|
|
67
|
+
*/
|
|
68
|
+
async deactivate(id) {
|
|
69
|
+
const response = await httpClient.patch(`${API_ENDPOINTS.USERS.BY_ID(id)}/deactivate`);
|
|
70
|
+
return response.data;
|
|
71
|
+
},
|
|
72
|
+
/**
|
|
73
|
+
* Suspendre un utilisateur
|
|
74
|
+
*/
|
|
75
|
+
async suspend(id, reason) {
|
|
76
|
+
const response = await httpClient.patch(`${API_ENDPOINTS.USERS.BY_ID(id)}/suspend`, { reason });
|
|
77
|
+
return response.data;
|
|
78
|
+
},
|
|
79
|
+
/**
|
|
80
|
+
* Réinitialiser le mot de passe d'un utilisateur
|
|
81
|
+
*/
|
|
82
|
+
async resetPassword(id, newPassword) {
|
|
83
|
+
await httpClient.post(`${API_ENDPOINTS.USERS.BY_ID(id)}/reset-password`, { password: newPassword });
|
|
84
|
+
},
|
|
85
|
+
/**
|
|
86
|
+
* Changer le mot de passe de l'utilisateur connecté
|
|
87
|
+
*/
|
|
88
|
+
async changePassword(currentPassword, newPassword) {
|
|
89
|
+
await httpClient.post(`${API_ENDPOINTS.USERS.PROFILE}/change-password`, {
|
|
90
|
+
currentPassword,
|
|
91
|
+
newPassword
|
|
92
|
+
});
|
|
93
|
+
},
|
|
94
|
+
/**
|
|
95
|
+
* Vérifier l'email d'un utilisateur
|
|
96
|
+
*/
|
|
97
|
+
async verifyEmail(token) {
|
|
98
|
+
await httpClient.post(`${API_ENDPOINTS.USERS.PROFILE}/verify-email`, { token });
|
|
99
|
+
},
|
|
100
|
+
/**
|
|
101
|
+
* Renvoyer l'email de vérification
|
|
102
|
+
*/
|
|
103
|
+
async resendVerificationEmail() {
|
|
104
|
+
await httpClient.post(`${API_ENDPOINTS.USERS.PROFILE}/resend-verification`);
|
|
105
|
+
},
|
|
106
|
+
/**
|
|
107
|
+
* Récupérer les statistiques des utilisateurs
|
|
108
|
+
*/
|
|
109
|
+
async getStats() {
|
|
110
|
+
const response = await httpClient.get(`${API_ENDPOINTS.USERS.BASE}/stats`);
|
|
111
|
+
return response.data;
|
|
112
|
+
},
|
|
113
|
+
/**
|
|
114
|
+
* Récupérer l'activité d'un utilisateur
|
|
115
|
+
*/
|
|
116
|
+
async getActivity(userId, limit) {
|
|
117
|
+
const response = await httpClient.get(`${API_ENDPOINTS.USERS.BY_ID(userId)}/activity`, { params: { limit } });
|
|
118
|
+
return response.data || [];
|
|
119
|
+
},
|
|
120
|
+
/**
|
|
121
|
+
* Rechercher des utilisateurs
|
|
122
|
+
*/
|
|
123
|
+
async search(query, params) {
|
|
124
|
+
const response = await httpClient.get(`${API_ENDPOINTS.USERS.BASE}/search`, {
|
|
125
|
+
params: { q: query, ...params }
|
|
126
|
+
});
|
|
127
|
+
return response.data || [];
|
|
128
|
+
},
|
|
129
|
+
/**
|
|
130
|
+
* Assigner des rôles à un utilisateur
|
|
131
|
+
*/
|
|
132
|
+
async assignRoles(userId, roles) {
|
|
133
|
+
const response = await httpClient.post(`${API_ENDPOINTS.USERS.BY_ID(userId)}/roles`, { roles });
|
|
134
|
+
return response.data;
|
|
135
|
+
},
|
|
136
|
+
/**
|
|
137
|
+
* Retirer des rôles d'un utilisateur
|
|
138
|
+
*/
|
|
139
|
+
async removeRoles(userId, roles) {
|
|
140
|
+
const response = await httpClient.delete(`${API_ENDPOINTS.USERS.BY_ID(userId)}/roles`, {
|
|
141
|
+
data: { roles }
|
|
142
|
+
});
|
|
143
|
+
return response.data;
|
|
144
|
+
}
|
|
145
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { LoginRequest } from '../types/auth.types';
|
|
2
|
+
/**
|
|
3
|
+
* Composable pour l'authentification
|
|
4
|
+
*/
|
|
5
|
+
export declare function useAuth(): {
|
|
6
|
+
user: import("vue").ComputedRef<{
|
|
7
|
+
id: number;
|
|
8
|
+
email: string;
|
|
9
|
+
name: string;
|
|
10
|
+
roles?: string[] | undefined;
|
|
11
|
+
organizationId?: number | undefined;
|
|
12
|
+
} | null>;
|
|
13
|
+
isAuthenticated: import("vue").ComputedRef<boolean>;
|
|
14
|
+
isLoading: import("vue").ComputedRef<boolean>;
|
|
15
|
+
isAdmin: import("vue").ComputedRef<boolean>;
|
|
16
|
+
isAgent: import("vue").ComputedRef<boolean>;
|
|
17
|
+
login: (credentials: LoginRequest) => Promise<void>;
|
|
18
|
+
logout: () => Promise<void>;
|
|
19
|
+
requireAuth: () => void;
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=useAuth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAuth.d.ts","sourceRoot":"","sources":["../../composables/useAuth.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAEvD;;GAEG;AACH,wBAAgB,OAAO;;;;;;;;;;;;yBAUa,YAAY;;;EA8B/C"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { computed } from 'vue';
|
|
2
|
+
import { useRouter } from 'vue-router';
|
|
3
|
+
import { useAuthStore } from '../stores/auth.store';
|
|
4
|
+
/**
|
|
5
|
+
* Composable pour l'authentification
|
|
6
|
+
*/
|
|
7
|
+
export function useAuth() {
|
|
8
|
+
const router = useRouter();
|
|
9
|
+
const authStore = useAuthStore();
|
|
10
|
+
const user = computed(() => authStore.user);
|
|
11
|
+
const isAuthenticated = computed(() => authStore.isAuthenticated);
|
|
12
|
+
const isLoading = computed(() => authStore.loading);
|
|
13
|
+
const isAdmin = computed(() => authStore.isAdmin);
|
|
14
|
+
const isAgent = computed(() => authStore.isAgent);
|
|
15
|
+
async function login(credentials) {
|
|
16
|
+
try {
|
|
17
|
+
await authStore.login(credentials);
|
|
18
|
+
router.push('/');
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
throw error;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
async function logout() {
|
|
25
|
+
await authStore.logout();
|
|
26
|
+
router.push('/login');
|
|
27
|
+
}
|
|
28
|
+
function requireAuth() {
|
|
29
|
+
if (!authStore.isAuthenticated) {
|
|
30
|
+
router.push('/login');
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
user,
|
|
35
|
+
isAuthenticated,
|
|
36
|
+
isLoading,
|
|
37
|
+
isAdmin,
|
|
38
|
+
isAgent,
|
|
39
|
+
login,
|
|
40
|
+
logout,
|
|
41
|
+
requireAuth
|
|
42
|
+
};
|
|
43
|
+
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import type { User, UserCreate, UserUpdate, UserSearchParams } from '../types/user.types';
|
|
2
|
+
import { UserRole, UserStatus } from '../types/user.types';
|
|
3
|
+
/**
|
|
4
|
+
* Composable pour la gestion des utilisateurs
|
|
5
|
+
*/
|
|
6
|
+
export declare function useUser(): {
|
|
7
|
+
users: import("vue").ComputedRef<{
|
|
8
|
+
id: number;
|
|
9
|
+
email: string;
|
|
10
|
+
name: string;
|
|
11
|
+
firstName?: string | undefined;
|
|
12
|
+
lastName?: string | undefined;
|
|
13
|
+
phone?: string | undefined;
|
|
14
|
+
avatar?: string | undefined;
|
|
15
|
+
status: UserStatus;
|
|
16
|
+
roles: UserRole[];
|
|
17
|
+
organizationId?: number | undefined;
|
|
18
|
+
organizationName?: string | undefined;
|
|
19
|
+
createdAt: string;
|
|
20
|
+
updatedAt: string;
|
|
21
|
+
lastLoginAt?: string | undefined;
|
|
22
|
+
emailVerified: boolean;
|
|
23
|
+
metadata?: Record<string, any> | undefined;
|
|
24
|
+
}[]>;
|
|
25
|
+
currentUser: import("vue").ComputedRef<{
|
|
26
|
+
preferences?: {
|
|
27
|
+
language: string;
|
|
28
|
+
timezone: string;
|
|
29
|
+
theme: "light" | "dark" | "auto";
|
|
30
|
+
emailNotifications: boolean;
|
|
31
|
+
} | undefined;
|
|
32
|
+
notifications?: {
|
|
33
|
+
email: boolean;
|
|
34
|
+
push: boolean;
|
|
35
|
+
sms: boolean;
|
|
36
|
+
marketing: boolean;
|
|
37
|
+
} | undefined;
|
|
38
|
+
id: number;
|
|
39
|
+
email: string;
|
|
40
|
+
name: string;
|
|
41
|
+
firstName?: string | undefined;
|
|
42
|
+
lastName?: string | undefined;
|
|
43
|
+
phone?: string | undefined;
|
|
44
|
+
avatar?: string | undefined;
|
|
45
|
+
status: UserStatus;
|
|
46
|
+
roles: UserRole[];
|
|
47
|
+
organizationId?: number | undefined;
|
|
48
|
+
organizationName?: string | undefined;
|
|
49
|
+
createdAt: string;
|
|
50
|
+
updatedAt: string;
|
|
51
|
+
lastLoginAt?: string | undefined;
|
|
52
|
+
emailVerified: boolean;
|
|
53
|
+
metadata?: Record<string, any> | undefined;
|
|
54
|
+
} | null>;
|
|
55
|
+
selectedUser: import("vue").ComputedRef<{
|
|
56
|
+
id: number;
|
|
57
|
+
email: string;
|
|
58
|
+
name: string;
|
|
59
|
+
firstName?: string | undefined;
|
|
60
|
+
lastName?: string | undefined;
|
|
61
|
+
phone?: string | undefined;
|
|
62
|
+
avatar?: string | undefined;
|
|
63
|
+
status: UserStatus;
|
|
64
|
+
roles: UserRole[];
|
|
65
|
+
organizationId?: number | undefined;
|
|
66
|
+
organizationName?: string | undefined;
|
|
67
|
+
createdAt: string;
|
|
68
|
+
updatedAt: string;
|
|
69
|
+
lastLoginAt?: string | undefined;
|
|
70
|
+
emailVerified: boolean;
|
|
71
|
+
metadata?: Record<string, any> | undefined;
|
|
72
|
+
} | null>;
|
|
73
|
+
stats: import("vue").ComputedRef<{
|
|
74
|
+
totalUsers: number;
|
|
75
|
+
activeUsers: number;
|
|
76
|
+
newUsersThisMonth: number;
|
|
77
|
+
usersByRole: {
|
|
78
|
+
SUPER_ADMIN: number;
|
|
79
|
+
ADMIN: number;
|
|
80
|
+
AGENT: number;
|
|
81
|
+
FREELANCE: number;
|
|
82
|
+
AUTO_ENTREPRENEUR: number;
|
|
83
|
+
PARTICULAR: number;
|
|
84
|
+
USER: number;
|
|
85
|
+
};
|
|
86
|
+
usersByStatus: {
|
|
87
|
+
ACTIVE: number;
|
|
88
|
+
INACTIVE: number;
|
|
89
|
+
SUSPENDED: number;
|
|
90
|
+
PENDING: number;
|
|
91
|
+
DELETED: number;
|
|
92
|
+
};
|
|
93
|
+
} | null>;
|
|
94
|
+
loading: import("vue").ComputedRef<boolean>;
|
|
95
|
+
total: import("vue").ComputedRef<number>;
|
|
96
|
+
currentPage: import("vue").ComputedRef<number>;
|
|
97
|
+
pageSize: import("vue").ComputedRef<number>;
|
|
98
|
+
activeUsers: import("vue").ComputedRef<{
|
|
99
|
+
id: number;
|
|
100
|
+
email: string;
|
|
101
|
+
name: string;
|
|
102
|
+
firstName?: string | undefined;
|
|
103
|
+
lastName?: string | undefined;
|
|
104
|
+
phone?: string | undefined;
|
|
105
|
+
avatar?: string | undefined;
|
|
106
|
+
status: UserStatus;
|
|
107
|
+
roles: UserRole[];
|
|
108
|
+
organizationId?: number | undefined;
|
|
109
|
+
organizationName?: string | undefined;
|
|
110
|
+
createdAt: string;
|
|
111
|
+
updatedAt: string;
|
|
112
|
+
lastLoginAt?: string | undefined;
|
|
113
|
+
emailVerified: boolean;
|
|
114
|
+
metadata?: Record<string, any> | undefined;
|
|
115
|
+
}[]>;
|
|
116
|
+
inactiveUsers: import("vue").ComputedRef<{
|
|
117
|
+
id: number;
|
|
118
|
+
email: string;
|
|
119
|
+
name: string;
|
|
120
|
+
firstName?: string | undefined;
|
|
121
|
+
lastName?: string | undefined;
|
|
122
|
+
phone?: string | undefined;
|
|
123
|
+
avatar?: string | undefined;
|
|
124
|
+
status: UserStatus;
|
|
125
|
+
roles: UserRole[];
|
|
126
|
+
organizationId?: number | undefined;
|
|
127
|
+
organizationName?: string | undefined;
|
|
128
|
+
createdAt: string;
|
|
129
|
+
updatedAt: string;
|
|
130
|
+
lastLoginAt?: string | undefined;
|
|
131
|
+
emailVerified: boolean;
|
|
132
|
+
metadata?: Record<string, any> | undefined;
|
|
133
|
+
}[]>;
|
|
134
|
+
suspendedUsers: import("vue").ComputedRef<{
|
|
135
|
+
id: number;
|
|
136
|
+
email: string;
|
|
137
|
+
name: string;
|
|
138
|
+
firstName?: string | undefined;
|
|
139
|
+
lastName?: string | undefined;
|
|
140
|
+
phone?: string | undefined;
|
|
141
|
+
avatar?: string | undefined;
|
|
142
|
+
status: UserStatus;
|
|
143
|
+
roles: UserRole[];
|
|
144
|
+
organizationId?: number | undefined;
|
|
145
|
+
organizationName?: string | undefined;
|
|
146
|
+
createdAt: string;
|
|
147
|
+
updatedAt: string;
|
|
148
|
+
lastLoginAt?: string | undefined;
|
|
149
|
+
emailVerified: boolean;
|
|
150
|
+
metadata?: Record<string, any> | undefined;
|
|
151
|
+
}[]>;
|
|
152
|
+
usersByRole: import("vue").ComputedRef<Record<UserRole, User[]>>;
|
|
153
|
+
loadUsers: (params?: UserSearchParams) => Promise<void>;
|
|
154
|
+
loadUser: (id: number) => Promise<void>;
|
|
155
|
+
loadProfile: () => Promise<void>;
|
|
156
|
+
createUser: (data: UserCreate) => Promise<User>;
|
|
157
|
+
updateUser: (id: number, data: UserUpdate) => Promise<User>;
|
|
158
|
+
updateProfile: (data: UserUpdate) => Promise<import("..").UserProfile>;
|
|
159
|
+
deleteUser: (id: number) => Promise<void>;
|
|
160
|
+
activateUser: (id: number) => Promise<User>;
|
|
161
|
+
deactivateUser: (id: number) => Promise<User>;
|
|
162
|
+
suspendUser: (id: number, reason?: string) => Promise<User>;
|
|
163
|
+
loadStats: () => Promise<void>;
|
|
164
|
+
setPage: (page: number) => void;
|
|
165
|
+
setPageSize: (size: number) => void;
|
|
166
|
+
selectUser: (user: User | null) => void;
|
|
167
|
+
hasRole: (userId: number, role: UserRole) => boolean;
|
|
168
|
+
isCurrentUser: (userId: number) => boolean;
|
|
169
|
+
canEditUser: (userId: number) => boolean;
|
|
170
|
+
canDeleteUser: (userId: number) => boolean;
|
|
171
|
+
canManageRoles: (userId: number) => boolean;
|
|
172
|
+
};
|
|
173
|
+
//# sourceMappingURL=useUser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useUser.d.ts","sourceRoot":"","sources":["../../composables/useUser.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AACzF,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAE1D;;GAEG;AACH,wBAAgB,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAqBa,gBAAgB;mBAItB,MAAM;;uBAQF,UAAU,KAAG,OAAO,CAAC,IAAI,CAAC;qBAI5B,MAAM,QAAQ,UAAU,KAAG,OAAO,CAAC,IAAI,CAAC;0BAInC,UAAU;qBAIf,MAAM;uBAIJ,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;yBAIpB,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;sBAIzB,MAAM,WAAW,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;;oBAQ/C,MAAM;wBAIF,MAAM;uBAIP,IAAI,GAAG,IAAI;sBAIZ,MAAM,QAAQ,QAAQ,KAAG,OAAO;4BAI1B,MAAM,KAAG,OAAO;0BAIlB,MAAM,KAAG,OAAO;4BAUd,MAAM,KAAG,OAAO;6BAOf,MAAM,KAAG,OAAO;EA0CjD"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { computed } from 'vue';
|
|
2
|
+
import { useRouter } from 'vue-router';
|
|
3
|
+
import { useUserStore } from '../stores/user.store';
|
|
4
|
+
import { UserRole } from '../types/user.types';
|
|
5
|
+
/**
|
|
6
|
+
* Composable pour la gestion des utilisateurs
|
|
7
|
+
*/
|
|
8
|
+
export function useUser() {
|
|
9
|
+
const router = useRouter();
|
|
10
|
+
const userStore = useUserStore();
|
|
11
|
+
// State
|
|
12
|
+
const users = computed(() => userStore.users);
|
|
13
|
+
const currentUser = computed(() => userStore.currentUser);
|
|
14
|
+
const selectedUser = computed(() => userStore.selectedUser);
|
|
15
|
+
const stats = computed(() => userStore.stats);
|
|
16
|
+
const loading = computed(() => userStore.loading);
|
|
17
|
+
const total = computed(() => userStore.total);
|
|
18
|
+
const currentPage = computed(() => userStore.currentPage);
|
|
19
|
+
const pageSize = computed(() => userStore.pageSize);
|
|
20
|
+
// Getters
|
|
21
|
+
const activeUsers = computed(() => userStore.activeUsers);
|
|
22
|
+
const inactiveUsers = computed(() => userStore.inactiveUsers);
|
|
23
|
+
const suspendedUsers = computed(() => userStore.suspendedUsers);
|
|
24
|
+
const usersByRole = computed(() => userStore.usersByRole);
|
|
25
|
+
// Actions
|
|
26
|
+
async function loadUsers(params) {
|
|
27
|
+
await userStore.fetchUsers(params);
|
|
28
|
+
}
|
|
29
|
+
async function loadUser(id) {
|
|
30
|
+
await userStore.fetchUserById(id);
|
|
31
|
+
}
|
|
32
|
+
async function loadProfile() {
|
|
33
|
+
await userStore.fetchProfile();
|
|
34
|
+
}
|
|
35
|
+
async function createUser(data) {
|
|
36
|
+
return await userStore.createUser(data);
|
|
37
|
+
}
|
|
38
|
+
async function updateUser(id, data) {
|
|
39
|
+
return await userStore.updateUser(id, data);
|
|
40
|
+
}
|
|
41
|
+
async function updateProfile(data) {
|
|
42
|
+
return await userStore.updateProfile(data);
|
|
43
|
+
}
|
|
44
|
+
async function deleteUser(id) {
|
|
45
|
+
await userStore.deleteUser(id);
|
|
46
|
+
}
|
|
47
|
+
async function activateUser(id) {
|
|
48
|
+
return await userStore.activateUser(id);
|
|
49
|
+
}
|
|
50
|
+
async function deactivateUser(id) {
|
|
51
|
+
return await userStore.deactivateUser(id);
|
|
52
|
+
}
|
|
53
|
+
async function suspendUser(id, reason) {
|
|
54
|
+
return await userStore.suspendUser(id, reason);
|
|
55
|
+
}
|
|
56
|
+
async function loadStats() {
|
|
57
|
+
await userStore.fetchStats();
|
|
58
|
+
}
|
|
59
|
+
function setPage(page) {
|
|
60
|
+
userStore.setPage(page);
|
|
61
|
+
}
|
|
62
|
+
function setPageSize(size) {
|
|
63
|
+
userStore.setPageSize(size);
|
|
64
|
+
}
|
|
65
|
+
function selectUser(user) {
|
|
66
|
+
userStore.setSelectedUser(user);
|
|
67
|
+
}
|
|
68
|
+
function hasRole(userId, role) {
|
|
69
|
+
return userStore.hasRole(userId, role);
|
|
70
|
+
}
|
|
71
|
+
function isCurrentUser(userId) {
|
|
72
|
+
return userStore.isCurrentUser(userId);
|
|
73
|
+
}
|
|
74
|
+
function canEditUser(userId) {
|
|
75
|
+
// Un utilisateur peut éditer son propre profil ou être admin
|
|
76
|
+
if (isCurrentUser(userId))
|
|
77
|
+
return true;
|
|
78
|
+
if (currentUser.value?.roles.includes(UserRole.ADMIN) ||
|
|
79
|
+
currentUser.value?.roles.includes(UserRole.SUPER_ADMIN)) {
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
function canDeleteUser(userId) {
|
|
85
|
+
// Seuls les admins peuvent supprimer, et pas leur propre compte
|
|
86
|
+
if (isCurrentUser(userId))
|
|
87
|
+
return false;
|
|
88
|
+
return currentUser.value?.roles.includes(UserRole.ADMIN) ||
|
|
89
|
+
currentUser.value?.roles.includes(UserRole.SUPER_ADMIN) || false;
|
|
90
|
+
}
|
|
91
|
+
function canManageRoles(userId) {
|
|
92
|
+
// Seuls les super admins peuvent gérer les rôles
|
|
93
|
+
return currentUser.value?.roles.includes(UserRole.SUPER_ADMIN) || false;
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
// State
|
|
97
|
+
users,
|
|
98
|
+
currentUser,
|
|
99
|
+
selectedUser,
|
|
100
|
+
stats,
|
|
101
|
+
loading,
|
|
102
|
+
total,
|
|
103
|
+
currentPage,
|
|
104
|
+
pageSize,
|
|
105
|
+
// Getters
|
|
106
|
+
activeUsers,
|
|
107
|
+
inactiveUsers,
|
|
108
|
+
suspendedUsers,
|
|
109
|
+
usersByRole,
|
|
110
|
+
// Actions
|
|
111
|
+
loadUsers,
|
|
112
|
+
loadUser,
|
|
113
|
+
loadProfile,
|
|
114
|
+
createUser,
|
|
115
|
+
updateUser,
|
|
116
|
+
updateProfile,
|
|
117
|
+
deleteUser,
|
|
118
|
+
activateUser,
|
|
119
|
+
deactivateUser,
|
|
120
|
+
suspendUser,
|
|
121
|
+
loadStats,
|
|
122
|
+
setPage,
|
|
123
|
+
setPageSize,
|
|
124
|
+
selectUser,
|
|
125
|
+
// Permissions
|
|
126
|
+
hasRole,
|
|
127
|
+
isCurrentUser,
|
|
128
|
+
canEditUser,
|
|
129
|
+
canDeleteUser,
|
|
130
|
+
canManageRoles
|
|
131
|
+
};
|
|
132
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Constantes pour les endpoints API
|
|
3
|
+
*/
|
|
4
|
+
export declare const API_ENDPOINTS: {
|
|
5
|
+
readonly AUTH: {
|
|
6
|
+
readonly LOGIN: "/identity/auth/login";
|
|
7
|
+
readonly REGISTER: "/identity/auth/register";
|
|
8
|
+
readonly LOGOUT: "/identity/auth/logout";
|
|
9
|
+
readonly REFRESH: "/identity/auth/refresh";
|
|
10
|
+
readonly FORGOT_PASSWORD: "/identity/auth/forgot-password";
|
|
11
|
+
readonly RESET_PASSWORD: "/identity/auth/reset-password";
|
|
12
|
+
};
|
|
13
|
+
readonly PROPERTIES: {
|
|
14
|
+
readonly BASE: "/property-service/api/properties";
|
|
15
|
+
readonly SEARCH: "/property-service/api/properties/search";
|
|
16
|
+
readonly BY_ID: (id: number) => string;
|
|
17
|
+
};
|
|
18
|
+
readonly USERS: {
|
|
19
|
+
readonly BASE: "/identity-service/api/users";
|
|
20
|
+
readonly BY_ID: (id: number) => string;
|
|
21
|
+
readonly PROFILE: "/identity-service/api/users/profile";
|
|
22
|
+
readonly STATS: "/identity-service/api/users/stats";
|
|
23
|
+
readonly SEARCH: "/identity-service/api/users/search";
|
|
24
|
+
readonly ACTIVITY: (id: number) => string;
|
|
25
|
+
};
|
|
26
|
+
readonly ORGANIZATIONS: {
|
|
27
|
+
readonly BASE: "/organization-service/api/organizations";
|
|
28
|
+
readonly BY_ID: (id: number) => string;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
export declare const API_BASE_URL = "/api";
|
|
32
|
+
//# sourceMappingURL=api.constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.constants.d.ts","sourceRoot":"","sources":["../../constants/api.constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,aAAa;;;;;;;;;;;;6BAcV,MAAM;;;;6BAKN,MAAM;;;;gCAIH,MAAM;;;;6BAKT,MAAM;;CAEZ,CAAA;AAEV,eAAO,MAAM,YAAY,SAAS,CAAA"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Constantes pour les endpoints API
|
|
3
|
+
*/
|
|
4
|
+
export const API_ENDPOINTS = {
|
|
5
|
+
// Authentication
|
|
6
|
+
AUTH: {
|
|
7
|
+
LOGIN: '/identity/auth/login',
|
|
8
|
+
REGISTER: '/identity/auth/register',
|
|
9
|
+
LOGOUT: '/identity/auth/logout',
|
|
10
|
+
REFRESH: '/identity/auth/refresh',
|
|
11
|
+
FORGOT_PASSWORD: '/identity/auth/forgot-password',
|
|
12
|
+
RESET_PASSWORD: '/identity/auth/reset-password'
|
|
13
|
+
},
|
|
14
|
+
// Properties
|
|
15
|
+
PROPERTIES: {
|
|
16
|
+
BASE: '/property-service/api/properties',
|
|
17
|
+
SEARCH: '/property-service/api/properties/search',
|
|
18
|
+
BY_ID: (id) => `/property-service/api/properties/${id}`
|
|
19
|
+
},
|
|
20
|
+
// Users
|
|
21
|
+
USERS: {
|
|
22
|
+
BASE: '/identity-service/api/users',
|
|
23
|
+
BY_ID: (id) => `/identity-service/api/users/${id}`,
|
|
24
|
+
PROFILE: '/identity-service/api/users/profile',
|
|
25
|
+
STATS: '/identity-service/api/users/stats',
|
|
26
|
+
SEARCH: '/identity-service/api/users/search',
|
|
27
|
+
ACTIVITY: (id) => `/identity-service/api/users/${id}/activity`
|
|
28
|
+
},
|
|
29
|
+
// Organizations
|
|
30
|
+
ORGANIZATIONS: {
|
|
31
|
+
BASE: '/organization-service/api/organizations',
|
|
32
|
+
BY_ID: (id) => `/organization-service/api/organizations/${id}`
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
export const API_BASE_URL = '/api';
|