@driveflux/auth 4.0.89 → 4.0.91
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/AuthProvider.d.ts.map +1 -1
- package/dist/AuthProvider.js +77 -62
- package/dist/authorization/constants.js +45 -24
- package/dist/authorization/define.js +57 -28
- package/dist/authorization/fields/index.js +4 -7
- package/dist/authorization/helpers.js +10 -8
- package/dist/authorization/index.js +6 -6
- package/dist/authorization/permissions-list.js +5 -7
- package/dist/authorization/quick.js +1 -1
- package/dist/authorization/roles/admin/business-development-executive.js +20 -7
- package/dist/authorization/roles/admin/ceo.js +4 -2
- package/dist/authorization/roles/admin/common.d.ts.map +1 -1
- package/dist/authorization/roles/admin/common.js +5 -3
- package/dist/authorization/roles/admin/concierge.js +35 -10
- package/dist/authorization/roles/admin/customer-success-executive.js +40 -10
- package/dist/authorization/roles/admin/data-analyst.js +7 -4
- package/dist/authorization/roles/admin/designer.js +7 -4
- package/dist/authorization/roles/admin/engineer.js +7 -4
- package/dist/authorization/roles/admin/finance-executive.js +11 -4
- package/dist/authorization/roles/admin/head-of-business-development.js +14 -4
- package/dist/authorization/roles/admin/head-of-data-analytics.js +14 -4
- package/dist/authorization/roles/admin/head-of-engineering.js +17 -6
- package/dist/authorization/roles/admin/head-of-finance.js +8 -3
- package/dist/authorization/roles/admin/head-of-human-resources.js +13 -5
- package/dist/authorization/roles/admin/head-of-marketing.js +17 -5
- package/dist/authorization/roles/admin/head-of-operations.js +8 -3
- package/dist/authorization/roles/admin/head-of-product.js +17 -6
- package/dist/authorization/roles/admin/head-of-sales.js +17 -5
- package/dist/authorization/roles/admin/human-resources-executive.js +12 -5
- package/dist/authorization/roles/admin/marketing-executive.js +7 -4
- package/dist/authorization/roles/admin/product-manager.js +7 -4
- package/dist/authorization/roles/admin/sales-executive.js +24 -8
- package/dist/authorization/roles/consumer/business-admin.js +19 -6
- package/dist/authorization/roles/consumer/business-user.js +18 -6
- package/dist/authorization/roles/consumer/member.js +16 -6
- package/dist/authorization/types.js +1 -1
- package/dist/authorization/update-user-permissions.js +22 -15
- package/dist/authorization/utils.js +26 -11
- package/dist/constants.js +2 -4
- package/dist/context.js +8 -9
- package/dist/default.js +1 -1
- package/dist/server/authenticate-user.js +11 -7
- package/dist/server/cors.js +23 -12
- package/dist/server/credentials-provider.js +2 -2
- package/dist/server/next-auth.d.ts +1 -1
- package/dist/server/next-auth.d.ts.map +1 -1
- package/dist/server/next-auth.js +104 -109
- package/dist/server/prisma-adapter.js +88 -52
- package/dist/server/verfiy-token.js +39 -24
- package/dist/translations.js +4 -4
- package/dist/use-auth.js +1 -1
- package/dist/use-session.js +1 -1
- package/package.json +16 -16
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthProvider.d.ts","sourceRoot":"","sources":["../src/AuthProvider.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AuthProvider.d.ts","sourceRoot":"","sources":["../src/AuthProvider.tsx"],"names":[],"mappings":"AAWA,OAAO,EACN,KAAK,EAAE,EACP,KAAK,iBAAiB,EAMtB,MAAM,OAAO,CAAA;AAed,QAAA,MAAM,YAAY,EAAE,EAAE,CAAC,iBAAiB,CAyKvC,CAAA;AAED,eAAe,YAAY,CAAA"}
|
package/dist/AuthProvider.js
CHANGED
|
@@ -5,40 +5,35 @@ import { enhancedFetch } from '@driveflux/fetch';
|
|
|
5
5
|
import { useToastResult } from '@driveflux/ui/toast';
|
|
6
6
|
import { useTrackEvent } from '@driveflux/web-analytics/track';
|
|
7
7
|
import Cookies from 'js-cookie';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
import Router, { useRouter } from 'next/dist/client/router.js';
|
|
11
|
-
import { useCallback, useEffect, useMemo, useRef, useState, } from 'react';
|
|
8
|
+
import Router, { useRouter } from 'next/router';
|
|
9
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
12
10
|
import useSWR from 'swr';
|
|
13
11
|
import { AuthContext } from './context.js';
|
|
14
12
|
import { translations } from './translations.js';
|
|
15
|
-
const AuthProvider = ({ children })
|
|
13
|
+
const AuthProvider = ({ children })=>{
|
|
16
14
|
const { data: session, status, update } = useAuthSession();
|
|
17
15
|
const { setUserData } = useTrackEvent();
|
|
18
16
|
const [token, setToken] = useState(null);
|
|
19
17
|
/**
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const newTokenPromise = useRef(null);
|
|
18
|
+
* A reference to a promise that fetches a new access token from the server.
|
|
19
|
+
* This is used to prevent multiple token requests from being sent simultaneously.
|
|
20
|
+
*/ const newTokenPromise = useRef(null);
|
|
24
21
|
const localeLogicRan = useRef(false);
|
|
25
22
|
const router = useRouter();
|
|
26
23
|
const { pathname, asPath, query, locale } = router;
|
|
27
24
|
const { toastResult } = useToastResult();
|
|
28
|
-
const { data: user, isValidating, mutate, error
|
|
29
|
-
fallbackData: session
|
|
30
|
-
?.user,
|
|
25
|
+
const { data: user, isValidating, mutate, error } = useSWR(session ? `${config.apiUrl}/user` : null, {
|
|
26
|
+
fallbackData: session?.user
|
|
31
27
|
});
|
|
32
28
|
const isLoadingUser = status !== 'unauthenticated' && isValidating && !user;
|
|
33
29
|
/**
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const getAccessToken = useCallback(async () => {
|
|
30
|
+
* Retrieves an access token for the current user. If a token is already available and has not expired, it will be returned immediately.
|
|
31
|
+
* Otherwise, the function will attempt to retrieve the token from cookies, and if that fails, it will fetch a new token from the server.
|
|
32
|
+
* If a new token is fetched, it will be stored in cookies and returned.
|
|
33
|
+
* If the user is not authenticated, the function will return null and display an error message.
|
|
34
|
+
* @returns {Promise<string | null>} A promise that resolves to the access token string, or null if the user is not authenticated.
|
|
35
|
+
*/ // biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
|
|
36
|
+
const getAccessToken = useCallback(async ()=>{
|
|
42
37
|
// Check the state first, if we have a token, return it
|
|
43
38
|
if (token && token.expiresAt > new Date()) {
|
|
44
39
|
return token.accessToken;
|
|
@@ -51,19 +46,17 @@ const AuthProvider = ({ children }) => {
|
|
|
51
46
|
if (expiresAt > new Date()) {
|
|
52
47
|
setToken({
|
|
53
48
|
accessToken: tokenFromCookies.accessToken,
|
|
54
|
-
expiresAt
|
|
49
|
+
expiresAt
|
|
55
50
|
});
|
|
56
51
|
}
|
|
57
52
|
return tokenFromCookies.accessToken;
|
|
58
53
|
}
|
|
54
|
+
} catch (_e) {
|
|
55
|
+
// TODO
|
|
56
|
+
// Nothing to do here
|
|
59
57
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
// Nothing to do here
|
|
63
|
-
}
|
|
64
|
-
const tokenPromise = newTokenPromise.current ||
|
|
65
|
-
// biome-ignore lint/suspicious/noAssignInExpressions: <explanation>
|
|
66
|
-
(newTokenPromise.current = enhancedFetch(`${config.apiUrl}/user/token`));
|
|
58
|
+
const tokenPromise = newTokenPromise.current || // biome-ignore lint/suspicious/noAssignInExpressions: <explanation>
|
|
59
|
+
(newTokenPromise.current = enhancedFetch(`${config.apiUrl}/user/token`));
|
|
67
60
|
// As a last resort, fetch a new token
|
|
68
61
|
const newToken = await tokenPromise;
|
|
69
62
|
// Resets the newTokenPromise reference to null after the new token has been fetched.
|
|
@@ -72,42 +65,50 @@ const AuthProvider = ({ children }) => {
|
|
|
72
65
|
toastResult(newToken, {
|
|
73
66
|
error: {
|
|
74
67
|
title: translations.unauthenticated,
|
|
75
|
-
description: translations.unauthenticatedDescription
|
|
76
|
-
}
|
|
68
|
+
description: translations.unauthenticatedDescription
|
|
69
|
+
}
|
|
77
70
|
});
|
|
78
71
|
return null;
|
|
79
72
|
}
|
|
80
73
|
const newTokenDetils = {
|
|
81
74
|
accessToken: newToken.val.id,
|
|
82
|
-
expiresAt: new Date(newToken.val.expiresAt)
|
|
75
|
+
expiresAt: new Date(newToken.val.expiresAt)
|
|
83
76
|
};
|
|
84
77
|
Cookies.set('accessTokenDetails', JSON.stringify(newTokenDetils));
|
|
85
78
|
setToken(newTokenDetils);
|
|
86
79
|
return newToken.val.id;
|
|
87
|
-
}, [
|
|
88
|
-
|
|
80
|
+
}, [
|
|
81
|
+
token
|
|
82
|
+
]);
|
|
83
|
+
const refresh = useCallback(async ()=>{
|
|
89
84
|
await update();
|
|
90
85
|
return await mutate();
|
|
91
|
-
}, [
|
|
92
|
-
|
|
93
|
-
|
|
86
|
+
}, [
|
|
87
|
+
mutate,
|
|
88
|
+
update
|
|
89
|
+
]);
|
|
90
|
+
const logout = useCallback(async ()=>{
|
|
91
|
+
await signOut({
|
|
92
|
+
redirect: false
|
|
93
|
+
});
|
|
94
94
|
await refresh();
|
|
95
|
-
}, [
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
95
|
+
}, [
|
|
96
|
+
refresh
|
|
97
|
+
]);
|
|
98
|
+
const context = useMemo(()=>({
|
|
99
|
+
user,
|
|
100
|
+
isLoadingUser,
|
|
101
|
+
refresh,
|
|
102
|
+
error,
|
|
103
|
+
getAccessToken,
|
|
104
|
+
// TODO
|
|
105
|
+
/**
|
|
106
|
+
* @deprecated do not use this property, use getAccessToken instead
|
|
107
|
+
*/ accessToken: token?.accessToken,
|
|
108
|
+
signIn,
|
|
109
|
+
logout,
|
|
110
|
+
status
|
|
111
|
+
}), [
|
|
111
112
|
user,
|
|
112
113
|
isLoadingUser,
|
|
113
114
|
refresh,
|
|
@@ -115,11 +116,11 @@ const AuthProvider = ({ children }) => {
|
|
|
115
116
|
getAccessToken,
|
|
116
117
|
logout,
|
|
117
118
|
token,
|
|
118
|
-
status
|
|
119
|
+
status
|
|
119
120
|
]);
|
|
120
121
|
// Add preferredLocal if any
|
|
121
122
|
// biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
|
|
122
|
-
useEffect(()
|
|
123
|
+
useEffect(()=>{
|
|
123
124
|
if (localeLogicRan.current || !user) {
|
|
124
125
|
return;
|
|
125
126
|
}
|
|
@@ -127,23 +128,37 @@ const AuthProvider = ({ children }) => {
|
|
|
127
128
|
const langFromCookies = Cookies.get('NEXT_LOCALE');
|
|
128
129
|
if (user?.preferredLocale && langFromCookies !== user?.preferredLocale) {
|
|
129
130
|
Cookies.set('NEXT_LOCALE', user.preferredLocale);
|
|
130
|
-
Router.push({
|
|
131
|
+
Router.push({
|
|
132
|
+
pathname,
|
|
133
|
+
query
|
|
134
|
+
}, asPath, {
|
|
135
|
+
locale: user.preferredLocale
|
|
136
|
+
});
|
|
131
137
|
}
|
|
132
|
-
}, [
|
|
138
|
+
}, [
|
|
139
|
+
user?.preferredLocale,
|
|
140
|
+
pathname,
|
|
141
|
+
query,
|
|
142
|
+
asPath
|
|
143
|
+
]);
|
|
133
144
|
// Add user to the tracking
|
|
134
145
|
// biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
|
|
135
|
-
useEffect(()
|
|
136
|
-
if (!user)
|
|
137
|
-
return;
|
|
146
|
+
useEffect(()=>{
|
|
147
|
+
if (!user) return;
|
|
138
148
|
setUserData({
|
|
139
149
|
id: user.id,
|
|
140
150
|
email: user.email,
|
|
141
151
|
phoneNumber: user.phoneNumber,
|
|
142
152
|
firstName: user.firstName,
|
|
143
153
|
lastName: user.lastName,
|
|
144
|
-
addresses: user.addresses
|
|
154
|
+
addresses: user.addresses
|
|
145
155
|
});
|
|
146
|
-
}, [
|
|
147
|
-
|
|
156
|
+
}, [
|
|
157
|
+
user
|
|
158
|
+
]);
|
|
159
|
+
return /*#__PURE__*/ _jsx(AuthContext.Provider, {
|
|
160
|
+
value: context,
|
|
161
|
+
children: children
|
|
162
|
+
});
|
|
148
163
|
};
|
|
149
164
|
export default AuthProvider;
|
|
@@ -6,7 +6,7 @@ export const DEPARTMENTS = {
|
|
|
6
6
|
SALES: 'sales',
|
|
7
7
|
FINANCE: 'finance',
|
|
8
8
|
DATA_ANALYTICS: 'dataAnalytics',
|
|
9
|
-
PRODUCT: 'product'
|
|
9
|
+
PRODUCT: 'product'
|
|
10
10
|
};
|
|
11
11
|
export const ROLES = {
|
|
12
12
|
CEO: 'ceo',
|
|
@@ -32,43 +32,54 @@ export const ROLES = {
|
|
|
32
32
|
PRODUCT_MANAGER: 'productManager',
|
|
33
33
|
MEMBER: 'member',
|
|
34
34
|
BUSINESS_ADMIN: 'businessAdmin',
|
|
35
|
-
BUSINESS_USER: 'businessUser'
|
|
35
|
+
BUSINESS_USER: 'businessUser'
|
|
36
36
|
};
|
|
37
37
|
export const DEPARTMENTS_MAP = {
|
|
38
38
|
[DEPARTMENTS.CEO_OFFICE]: [
|
|
39
39
|
ROLES.CEO,
|
|
40
40
|
ROLES.HEAD_OF_HUMAN_RESOURCES,
|
|
41
|
-
ROLES.HUMAN_RESOURCES_EXECUTIVE
|
|
41
|
+
ROLES.HUMAN_RESOURCES_EXECUTIVE
|
|
42
42
|
],
|
|
43
43
|
[DEPARTMENTS.OPERATIONS]: [
|
|
44
44
|
ROLES.HEAD_OF_OPERATIONS,
|
|
45
45
|
ROLES.CUSTOMER_SUCCESS_EXECUTIVE,
|
|
46
|
-
ROLES.CONCIERGE
|
|
46
|
+
ROLES.CONCIERGE
|
|
47
|
+
],
|
|
48
|
+
[DEPARTMENTS.MARKETING]: [
|
|
49
|
+
ROLES.HEAD_OF_MARKETING,
|
|
50
|
+
ROLES.MARKETING_EXECUTIVE
|
|
47
51
|
],
|
|
48
|
-
[DEPARTMENTS.MARKETING]: [ROLES.HEAD_OF_MARKETING, ROLES.MARKETING_EXECUTIVE],
|
|
49
52
|
[DEPARTMENTS.BUSINESS_DEVELOPMENT]: [
|
|
50
53
|
ROLES.HEAD_OF_BUSINESS_DEVELOPMENT,
|
|
51
|
-
ROLES.BUSINESS_DEVELOPMENT_EXECUTIVE
|
|
54
|
+
ROLES.BUSINESS_DEVELOPMENT_EXECUTIVE
|
|
55
|
+
],
|
|
56
|
+
[DEPARTMENTS.SALES]: [
|
|
57
|
+
ROLES.HEAD_OF_SALES,
|
|
58
|
+
ROLES.SALES_EXECUTIVE
|
|
59
|
+
],
|
|
60
|
+
[DEPARTMENTS.FINANCE]: [
|
|
61
|
+
ROLES.HEAD_OF_FINANCE,
|
|
62
|
+
ROLES.FINANCE_EXECUTIVE
|
|
52
63
|
],
|
|
53
|
-
[DEPARTMENTS.SALES]: [ROLES.HEAD_OF_SALES, ROLES.SALES_EXECUTIVE],
|
|
54
|
-
[DEPARTMENTS.FINANCE]: [ROLES.HEAD_OF_FINANCE, ROLES.FINANCE_EXECUTIVE],
|
|
55
64
|
[DEPARTMENTS.DATA_ANALYTICS]: [
|
|
56
65
|
ROLES.HEAD_OF_DATA_ANALYTICS,
|
|
57
|
-
ROLES.DATA_ANALYST
|
|
66
|
+
ROLES.DATA_ANALYST
|
|
58
67
|
],
|
|
59
68
|
[DEPARTMENTS.PRODUCT]: [
|
|
60
69
|
ROLES.HEAD_OF_PRODUCT,
|
|
61
70
|
ROLES.HEAD_OF_ENGINEERING,
|
|
62
71
|
ROLES.DESIGNER,
|
|
63
72
|
ROLES.ENGINEER,
|
|
64
|
-
ROLES.PRODUCT_MANAGER
|
|
65
|
-
]
|
|
73
|
+
ROLES.PRODUCT_MANAGER
|
|
74
|
+
]
|
|
66
75
|
};
|
|
67
|
-
export const OWNER_ROLES = [
|
|
76
|
+
export const OWNER_ROLES = [
|
|
77
|
+
ROLES.CEO
|
|
78
|
+
];
|
|
68
79
|
export const HIGHER_ADMIN_ROLES = [
|
|
69
80
|
ROLES.HEAD_OF_HUMAN_RESOURCES,
|
|
70
81
|
ROLES.HEAD_OF_PRODUCT,
|
|
71
|
-
ROLES.HEAD_OF_ENGINEERING
|
|
82
|
+
ROLES.HEAD_OF_ENGINEERING
|
|
72
83
|
];
|
|
73
84
|
export const ADMIN_ROLES = [
|
|
74
85
|
...HIGHER_ADMIN_ROLES,
|
|
@@ -88,28 +99,38 @@ export const ADMIN_ROLES = [
|
|
|
88
99
|
ROLES.DATA_ANALYST,
|
|
89
100
|
ROLES.DESIGNER,
|
|
90
101
|
ROLES.ENGINEER,
|
|
91
|
-
ROLES.PRODUCT_MANAGER
|
|
102
|
+
ROLES.PRODUCT_MANAGER
|
|
103
|
+
];
|
|
104
|
+
export const ALL_ADMIN_ROLES = [
|
|
105
|
+
...ADMIN_ROLES,
|
|
106
|
+
...OWNER_ROLES
|
|
92
107
|
];
|
|
93
|
-
export const ALL_ADMIN_ROLES = [...ADMIN_ROLES, ...OWNER_ROLES];
|
|
94
108
|
export const BUSINESS_ROLES = [
|
|
95
109
|
ROLES.BUSINESS_ADMIN,
|
|
96
|
-
ROLES.BUSINESS_USER
|
|
110
|
+
ROLES.BUSINESS_USER
|
|
111
|
+
];
|
|
112
|
+
export const CONSUMER_ROLES = [
|
|
113
|
+
...BUSINESS_ROLES,
|
|
114
|
+
ROLES.MEMBER
|
|
115
|
+
];
|
|
116
|
+
export const ASSIGNABLE_ROLES = [
|
|
117
|
+
...ADMIN_ROLES,
|
|
118
|
+
...CONSUMER_ROLES
|
|
97
119
|
];
|
|
98
|
-
export const CONSUMER_ROLES = [...BUSINESS_ROLES, ROLES.MEMBER];
|
|
99
|
-
export const ASSIGNABLE_ROLES = [...ADMIN_ROLES, ...CONSUMER_ROLES];
|
|
100
120
|
/**
|
|
101
121
|
* This is to make it easier for some libraries like zod to understand
|
|
102
122
|
* the roles types. Keep this in sync with the above ROLES constant
|
|
103
|
-
*/
|
|
104
|
-
|
|
123
|
+
*/ export const GENERAL_ROLES = [
|
|
124
|
+
...ALL_ADMIN_ROLES,
|
|
125
|
+
...CONSUMER_ROLES
|
|
126
|
+
];
|
|
105
127
|
export const GUEST_PERMISSIONS = [
|
|
106
128
|
{
|
|
107
129
|
action: 'create',
|
|
108
|
-
subject: 'Inquiry'
|
|
130
|
+
subject: 'Inquiry'
|
|
109
131
|
},
|
|
110
132
|
{
|
|
111
133
|
action: 'read',
|
|
112
|
-
subject: 'Vehicle'
|
|
113
|
-
|
|
114
|
-
},
|
|
134
|
+
subject: 'Vehicle'
|
|
135
|
+
}
|
|
115
136
|
];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AbilityBuilder } from '@casl/ability';
|
|
2
2
|
import { createPrismaAbility } from '@casl/prisma';
|
|
3
|
-
import { ALL_ADMIN_ROLES, CONSUMER_ROLES, GENERAL_ROLES, HIGHER_ADMIN_ROLES, OWNER_ROLES
|
|
3
|
+
import { ALL_ADMIN_ROLES, CONSUMER_ROLES, GENERAL_ROLES, HIGHER_ADMIN_ROLES, OWNER_ROLES } from './constants.js';
|
|
4
4
|
import { defineRoleAbilitiesBusinessDevelopmentExecutive } from './roles/admin/business-development-executive.js';
|
|
5
5
|
import { defineRoleAbilitiesCeo } from './roles/admin/ceo.js';
|
|
6
6
|
import { defineRoleAbilitiesCommonAdmin } from './roles/admin/common.js';
|
|
@@ -26,45 +26,64 @@ import { defineRoleAbilitiesSalesExecutive } from './roles/admin/sales-executive
|
|
|
26
26
|
import { defineRoleAbilitiesBusinessAdmin } from './roles/consumer/business-admin.js';
|
|
27
27
|
import { defineRoleAbilitiesBusinessUser } from './roles/consumer/business-user.js';
|
|
28
28
|
import { defineRoleAbilitiesMember } from './roles/consumer/member.js';
|
|
29
|
-
export const defineAbilityFor = async (user)
|
|
29
|
+
export const defineAbilityFor = async (user)=>{
|
|
30
30
|
const { can, cannot, build } = new AbilityBuilder(createPrismaAbility);
|
|
31
31
|
if (!user) {
|
|
32
32
|
return build();
|
|
33
33
|
}
|
|
34
|
-
const groups = Array.isArray(user.groups)
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
34
|
+
const groups = Array.isArray(user.groups) ? user.groups.map((r)=>`${r}`) : typeof user.groups === 'string' ? [
|
|
35
|
+
user.groups
|
|
36
|
+
] : [];
|
|
37
|
+
const consumerGroups = groups.filter((g)=>CONSUMER_ROLES.includes(g));
|
|
38
|
+
const adminGroups = groups.filter((g)=>!consumerGroups.includes(g));
|
|
39
|
+
const sortedGroups = [
|
|
40
|
+
...consumerGroups,
|
|
41
|
+
...adminGroups
|
|
42
|
+
];
|
|
43
|
+
for (const role of sortedGroups){
|
|
43
44
|
await defineSpecificRoleAbilities(role, can, cannot, user);
|
|
44
45
|
}
|
|
45
46
|
// Common admin abilities
|
|
46
|
-
if (user.groups.some((g)
|
|
47
|
+
if (user.groups.some((g)=>adminGroups.includes(g))) {
|
|
47
48
|
await defineRoleAbilitiesCommonAdmin(can);
|
|
48
49
|
}
|
|
49
50
|
// General abilities
|
|
50
|
-
can([
|
|
51
|
-
|
|
51
|
+
can([
|
|
52
|
+
'read',
|
|
53
|
+
'update'
|
|
54
|
+
], 'User', {
|
|
55
|
+
id: user.id
|
|
56
|
+
});
|
|
57
|
+
can([
|
|
58
|
+
'read'
|
|
59
|
+
], 'Invoice', {
|
|
60
|
+
payerId: user.id
|
|
61
|
+
});
|
|
52
62
|
if (user.businessId) {
|
|
53
|
-
can([
|
|
63
|
+
can([
|
|
64
|
+
'read'
|
|
65
|
+
], 'Invoice', {
|
|
66
|
+
payerId: user.businessId
|
|
67
|
+
});
|
|
54
68
|
}
|
|
55
|
-
can('reserveVehicle', 'User', {
|
|
69
|
+
can('reserveVehicle', 'User', {
|
|
70
|
+
banned: false,
|
|
71
|
+
consented: true
|
|
72
|
+
});
|
|
56
73
|
// Prevent updating the groups for all users
|
|
57
|
-
cannot('update', 'User', [
|
|
74
|
+
cannot('update', 'User', [
|
|
75
|
+
'groups'
|
|
76
|
+
]);
|
|
58
77
|
return build();
|
|
59
78
|
};
|
|
60
|
-
const defineSpecificRoleAbilities = async (r, can, cannot, rawUser)
|
|
79
|
+
const defineSpecificRoleAbilities = async (r, can, cannot, rawUser)=>{
|
|
61
80
|
if (!~GENERAL_ROLES.indexOf(r)) {
|
|
62
81
|
return;
|
|
63
82
|
}
|
|
64
83
|
// Type issue
|
|
65
84
|
const user = rawUser;
|
|
66
85
|
const role = r;
|
|
67
|
-
switch
|
|
86
|
+
switch(role){
|
|
68
87
|
// Owners
|
|
69
88
|
case 'ceo':
|
|
70
89
|
defineRoleAbilitiesCeo(can);
|
|
@@ -142,20 +161,30 @@ const defineSpecificRoleAbilities = async (r, can, cannot, rawUser) => {
|
|
|
142
161
|
case 'businessAdmin':
|
|
143
162
|
defineRoleAbilitiesBusinessAdmin(can, user);
|
|
144
163
|
break;
|
|
145
|
-
default:
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
164
|
+
default:
|
|
165
|
+
{
|
|
166
|
+
const _exhaustiveCheck = role;
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
149
169
|
}
|
|
150
|
-
if (![
|
|
170
|
+
if (![
|
|
171
|
+
...OWNER_ROLES,
|
|
172
|
+
...HIGHER_ADMIN_ROLES
|
|
173
|
+
].includes(role)) {
|
|
151
174
|
cannot('manageAdmin', 'User');
|
|
152
|
-
cannot([
|
|
175
|
+
cannot([
|
|
176
|
+
'create',
|
|
177
|
+
'update',
|
|
178
|
+
'delete'
|
|
179
|
+
], 'User', undefined, {
|
|
153
180
|
groups: {
|
|
154
|
-
hasSome: [
|
|
155
|
-
|
|
181
|
+
hasSome: [
|
|
182
|
+
...ALL_ADMIN_ROLES
|
|
183
|
+
]
|
|
184
|
+
}
|
|
156
185
|
}).because('You are not allowed to update admin users');
|
|
157
186
|
can('update', 'User', undefined, {
|
|
158
|
-
id: user.id
|
|
187
|
+
id: user.id
|
|
159
188
|
});
|
|
160
189
|
}
|
|
161
190
|
};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Prisma, prisma } from '@driveflux/db';
|
|
2
|
-
export const MODEL_FIELDS = Object.keys(Prisma.ModelName)
|
|
3
|
-
.map((k) => {
|
|
2
|
+
export const MODEL_FIELDS = Object.keys(Prisma.ModelName).map((k)=>{
|
|
4
3
|
if (!(k in Prisma.ModelName)) {
|
|
5
4
|
return null;
|
|
6
5
|
}
|
|
@@ -8,17 +7,15 @@ export const MODEL_FIELDS = Object.keys(Prisma.ModelName)
|
|
|
8
7
|
return {
|
|
9
8
|
// TODO
|
|
10
9
|
// @ts-expect-error
|
|
11
|
-
[key]: prisma._runtimeDataModel.models[key].fields.map((f)
|
|
10
|
+
[key]: prisma._runtimeDataModel.models[key].fields.map((f)=>f.name)
|
|
12
11
|
};
|
|
13
|
-
})
|
|
14
|
-
.filter((m) => m)
|
|
15
|
-
.reduce((carry, current) => {
|
|
12
|
+
}).filter((m)=>m).reduce((carry, current)=>{
|
|
16
13
|
if (current) {
|
|
17
14
|
Object.assign(carry, current);
|
|
18
15
|
}
|
|
19
16
|
return carry;
|
|
20
17
|
}, {});
|
|
21
|
-
export const getModelFields = (model)
|
|
18
|
+
export const getModelFields = (model)=>{
|
|
22
19
|
const fields = MODEL_FIELDS[model];
|
|
23
20
|
return fields;
|
|
24
21
|
};
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { ALL_ADMIN_ROLES, CONSUMER_ROLES, OWNER_ROLES } from './constants';
|
|
2
|
-
export const extractAdminRoles = (userGroups)
|
|
3
|
-
return userGroups?.filter((group)
|
|
2
|
+
export const extractAdminRoles = (userGroups)=>{
|
|
3
|
+
return userGroups?.filter((group)=>isAdmin(group));
|
|
4
4
|
};
|
|
5
|
-
export const extractNonAdminRoles = (userGroups)
|
|
6
|
-
return userGroups?.filter((group)
|
|
5
|
+
export const extractNonAdminRoles = (userGroups)=>{
|
|
6
|
+
return userGroups?.filter((group)=>!isAdmin(group));
|
|
7
7
|
};
|
|
8
|
-
export const isConsumer = (group)
|
|
8
|
+
export const isConsumer = (group)=>{
|
|
9
9
|
return CONSUMER_ROLES.includes(group);
|
|
10
10
|
};
|
|
11
|
-
export const isOwner = (group)
|
|
12
|
-
return [
|
|
11
|
+
export const isOwner = (group)=>{
|
|
12
|
+
return [
|
|
13
|
+
...OWNER_ROLES
|
|
14
|
+
]?.map((r)=>group === r)?.[0];
|
|
13
15
|
};
|
|
14
|
-
export const isAdmin = (group)
|
|
16
|
+
export const isAdmin = (group)=>{
|
|
15
17
|
return ALL_ADMIN_ROLES.includes(group);
|
|
16
18
|
};
|
|
@@ -4,15 +4,15 @@ import { ErrorWithResult } from '@driveflux/result';
|
|
|
4
4
|
import { GUEST_PERMISSIONS } from './constants.js';
|
|
5
5
|
import buildAbilityFromJson from './quick.js';
|
|
6
6
|
import { updateUserPermissions } from './update-user-permissions.js';
|
|
7
|
-
export const buildOrDefineAbility = async (user, refresh)
|
|
7
|
+
export const buildOrDefineAbility = async (user, refresh)=>{
|
|
8
8
|
if (!user) {
|
|
9
|
-
return createPrismaAbility([
|
|
10
|
-
|
|
9
|
+
return createPrismaAbility([
|
|
10
|
+
...GUEST_PERMISSIONS
|
|
11
|
+
], {
|
|
12
|
+
detectSubjectType: detectSubjectType
|
|
11
13
|
});
|
|
12
14
|
}
|
|
13
|
-
if (!Array.isArray(user.permissions) ||
|
|
14
|
-
!user.permissions?.length ||
|
|
15
|
-
refresh) {
|
|
15
|
+
if (!Array.isArray(user.permissions) || !user.permissions?.length || refresh) {
|
|
16
16
|
const result = await updateUserPermissions(user);
|
|
17
17
|
if (result.err) {
|
|
18
18
|
throw new ErrorWithResult(result);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { s } from './utils.js';
|
|
2
|
-
export const getPermissionsFromAbility = (ability)
|
|
2
|
+
export const getPermissionsFromAbility = (ability)=>{
|
|
3
3
|
return {
|
|
4
4
|
// Lists
|
|
5
5
|
viewContractsList: ability.can('read', 'SubscriptionContract'),
|
|
@@ -53,7 +53,7 @@ export const getPermissionsFromAbility = (ability) => {
|
|
|
53
53
|
updateVehicleServiceCenters: ability.can('update', 'Vehicle', 'allowedServiceCenterIds'),
|
|
54
54
|
readPricingInput: ability.can('readPricingInput', 'Vehicle'),
|
|
55
55
|
updatePricingInput: ability.can('update', 'Vehicle', 'pricing'),
|
|
56
|
-
testPricingInput: ability.can('testPricingInput', 'Vehicle'),
|
|
56
|
+
testPricingInput: ability.can('testPricingInput', 'Vehicle'),
|
|
57
57
|
// Users ( Members )
|
|
58
58
|
createMember: ability.can('create', 'User'),
|
|
59
59
|
updateMember: ability.can('update', s('User')),
|
|
@@ -84,8 +84,7 @@ export const getPermissionsFromAbility = (ability) => {
|
|
|
84
84
|
updateInvoice: ability.can('update', s('Invoice', 'payerId')),
|
|
85
85
|
cancelInvoice: ability.can('cancelInvoice', 'Invoice'),
|
|
86
86
|
markInvoiceAsPaid: ability.can('markInvoice', 'Invoice', 'paid'),
|
|
87
|
-
markInvoiceAsRefunded: ability.can('markInvoice', 'Invoice', 'totalRefunded') &&
|
|
88
|
-
ability.can('create', 'Refund'),
|
|
87
|
+
markInvoiceAsRefunded: ability.can('markInvoice', 'Invoice', 'totalRefunded') && ability.can('create', 'Refund'),
|
|
89
88
|
readPaymentMethodsUser: ability.can('read', s('User'), 'paymentMethods'),
|
|
90
89
|
readPaymentMethodsBusiness: ability.can('read', s('Business'), 'paymentMethods'),
|
|
91
90
|
addPaymentMethodUser: ability.can('update', s('User'), 'paymentMethods'),
|
|
@@ -133,8 +132,7 @@ export const getPermissionsFromAbility = (ability) => {
|
|
|
133
132
|
// TODO add logs permision or remove the comments
|
|
134
133
|
// Logs
|
|
135
134
|
// Website Settings
|
|
136
|
-
uploadBanners: ability.can('update', 'PlatformConfig') &&
|
|
137
|
-
ability.can('create', 'PlatformConfig'),
|
|
135
|
+
uploadBanners: ability.can('update', 'PlatformConfig') && ability.can('create', 'PlatformConfig'),
|
|
138
136
|
deleteBanners: ability.can('update', 'PlatformConfig'),
|
|
139
137
|
// Quotations
|
|
140
138
|
createQuotation: ability.can('create', 'Quotation'),
|
|
@@ -143,6 +141,6 @@ export const getPermissionsFromAbility = (ability) => {
|
|
|
143
141
|
createVacancy: ability.can('create', 'Vacancy'),
|
|
144
142
|
updateVacancy: ability.can('update', 'Vacancy'),
|
|
145
143
|
readApplicant: ability.can('read', 'Applicant'),
|
|
146
|
-
readVacancy: ability.can('read', 'Vacancy')
|
|
144
|
+
readVacancy: ability.can('read', 'Vacancy')
|
|
147
145
|
};
|
|
148
146
|
};
|
|
@@ -2,7 +2,7 @@ import { createPrismaAbility } from '@casl/prisma';
|
|
|
2
2
|
import { detectSubjectType } from './utils.js';
|
|
3
3
|
export function buildAbilityFromJson(user) {
|
|
4
4
|
return createPrismaAbility(user.permissions, {
|
|
5
|
-
detectSubjectType
|
|
5
|
+
detectSubjectType
|
|
6
6
|
});
|
|
7
7
|
}
|
|
8
8
|
export default buildAbilityFromJson;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getDocumentsFields } from '../../utils.js';
|
|
2
|
-
export const defineRoleAbilitiesBusinessDevelopmentExecutive = async (can, cannot)
|
|
2
|
+
export const defineRoleAbilitiesBusinessDevelopmentExecutive = async (can, cannot)=>{
|
|
3
3
|
can('read', [
|
|
4
4
|
'Subscription',
|
|
5
5
|
'Vehicle',
|
|
@@ -13,22 +13,35 @@ export const defineRoleAbilitiesBusinessDevelopmentExecutive = async (can, canno
|
|
|
13
13
|
'PaymentLink',
|
|
14
14
|
'Invoice',
|
|
15
15
|
'Transaction',
|
|
16
|
-
'Refund'
|
|
16
|
+
'Refund'
|
|
17
17
|
]);
|
|
18
18
|
cannot('update', 'Invoice');
|
|
19
|
-
can('manage', [
|
|
19
|
+
can('manage', [
|
|
20
|
+
'Vehicle',
|
|
21
|
+
'ServiceCenter',
|
|
22
|
+
'Host',
|
|
23
|
+
'Inquiry',
|
|
24
|
+
'Token'
|
|
25
|
+
]);
|
|
20
26
|
can('readPricingInput', 'Vehicle');
|
|
21
27
|
can('connectHostToStripe', 'Host');
|
|
22
|
-
can('update', 'Subscription', [
|
|
28
|
+
can('update', 'Subscription', [
|
|
29
|
+
'vehicleId'
|
|
30
|
+
]);
|
|
23
31
|
cannot('read', 'User', 'status');
|
|
24
32
|
cannot('read', 'User', [
|
|
25
33
|
...getDocumentsFields('identification'),
|
|
26
34
|
...getDocumentsFields('drivingHistory'),
|
|
27
35
|
...getDocumentsFields('financial'),
|
|
28
|
-
...getDocumentsFields('offerLetter')
|
|
36
|
+
...getDocumentsFields('offerLetter')
|
|
37
|
+
]);
|
|
38
|
+
can([
|
|
39
|
+
'viewSubscriptionApproval'
|
|
40
|
+
], 'Subscription');
|
|
41
|
+
cannot('read', [
|
|
42
|
+
'Vacancy',
|
|
43
|
+
'Applicant'
|
|
29
44
|
]);
|
|
30
|
-
can(['viewSubscriptionApproval'], 'Subscription');
|
|
31
|
-
cannot('read', ['Vacancy', 'Applicant']);
|
|
32
45
|
can('read', 'Activity');
|
|
33
46
|
can('read', 'ActivityTask');
|
|
34
47
|
};
|