@strapi/plugin-users-permissions 0.0.0-4fc90398602f → 0.0.0-8581854cb3
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/admin/src/components/BoundRoute/getMethodColor.js +1 -1
- package/admin/src/components/BoundRoute/index.js +1 -1
- package/admin/src/components/FormModal/Input/index.js +1 -1
- package/admin/src/components/FormModal/index.js +9 -7
- package/admin/src/components/Permissions/PermissionRow/CheckboxWrapper.js +3 -3
- package/admin/src/components/Permissions/PermissionRow/SubCategory.js +14 -10
- package/admin/src/components/Permissions/PermissionRow/index.js +1 -1
- package/admin/src/components/Permissions/index.js +2 -2
- package/admin/src/components/Permissions/init.js +1 -1
- package/admin/src/components/Permissions/reducer.js +1 -1
- package/admin/src/components/Policies/index.js +1 -1
- package/admin/src/components/UsersPermissions/index.js +5 -5
- package/admin/src/components/UsersPermissions/reducer.js +1 -1
- package/admin/src/hooks/useFetchRole/index.js +3 -3
- package/admin/src/hooks/useFetchRole/reducer.js +1 -1
- package/admin/src/hooks/useForm/index.js +1 -1
- package/admin/src/hooks/useForm/reducer.js +1 -1
- package/admin/src/hooks/usePlugins/index.js +1 -1
- package/admin/src/hooks/usePlugins/reducer.js +1 -1
- package/admin/src/hooks/useRolesList/reducer.js +1 -1
- package/admin/src/index.js +5 -5
- package/admin/src/pages/AdvancedSettings/index.js +10 -11
- package/admin/src/pages/AdvancedSettings/utils/api.js +1 -1
- package/admin/src/pages/AdvancedSettings/utils/schema.js +4 -2
- package/admin/src/pages/EmailTemplates/index.js +8 -8
- package/admin/src/pages/EmailTemplates/utils/api.js +1 -1
- package/admin/src/pages/EmailTemplates/utils/schema.js +4 -1
- package/admin/src/pages/Providers/index.js +22 -22
- package/admin/src/pages/Providers/reducer.js +1 -1
- package/admin/src/pages/Providers/utils/api.js +2 -2
- package/admin/src/pages/Providers/utils/createProvidersArray.js +1 -1
- package/admin/src/pages/Roles/CreatePage/index.js +1 -1
- package/admin/src/pages/Roles/EditPage/index.js +1 -1
- package/admin/src/pages/Roles/ListPage/components/TableBody.js +4 -5
- package/admin/src/pages/Roles/ListPage/index.js +2 -2
- package/admin/src/utils/axiosInstance.js +4 -4
- package/admin/src/utils/cleanPermissions.js +1 -1
- package/admin/src/utils/formatPolicies.js +1 -1
- package/admin/src/utils/getRequestURL.js +1 -1
- package/admin/src/utils/getTrad.js +1 -1
- package/jest.config.front.js +1 -1
- package/package.json +8 -5
- package/server/bootstrap/grant-config.js +1 -1
- package/server/bootstrap/index.js +39 -39
- package/server/controllers/auth.js +5 -2
- package/server/controllers/content-manager-user.js +12 -4
- package/server/controllers/settings.js +1 -1
- package/server/controllers/user.js +2 -2
- package/server/controllers/validation/auth.js +12 -3
- package/server/controllers/validation/email-template.js +2 -3
- package/server/controllers/validation/user.js +16 -4
- package/server/graphql/mutations/auth/change-password.js +4 -1
- package/server/graphql/mutations/auth/forgot-password.js +4 -1
- package/server/graphql/mutations/auth/login.js +4 -1
- package/server/graphql/mutations/auth/register.js +4 -1
- package/server/graphql/mutations/auth/reset-password.js +4 -1
- package/server/graphql/mutations/crud/role/create-role.js +4 -1
- package/server/graphql/mutations/crud/role/delete-role.js +4 -1
- package/server/graphql/mutations/crud/role/update-role.js +4 -1
- package/server/graphql/mutations/crud/user/create-user.js +4 -1
- package/server/graphql/mutations/crud/user/delete-user.js +4 -1
- package/server/graphql/mutations/crud/user/update-user.js +4 -1
- package/server/graphql/mutations/index.js +1 -1
- package/server/graphql/types/index.js +1 -1
- package/server/middlewares/rateLimit.js +25 -22
- package/server/register.js +4 -2
- package/server/services/jwt.js +9 -11
- package/server/services/providers-registry.js +42 -33
- package/server/services/providers.js +5 -5
- package/server/services/role.js +7 -7
- package/server/services/user.js +1 -1
- package/server/services/users-permissions.js +12 -12
- package/server/strategies/users-permissions.js +3 -3
- package/server/utils/index.js +1 -1
|
@@ -53,26 +53,26 @@ export const ProvidersPage = () => {
|
|
|
53
53
|
allowedActions: { canUpdate },
|
|
54
54
|
} = useRBAC(updatePermissions);
|
|
55
55
|
|
|
56
|
-
const {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
56
|
+
const { isLoading: isLoadingForData, data: modifiedData, isFetching } = useQuery(
|
|
57
|
+
'get-providers',
|
|
58
|
+
() => fetchData(toggleNotification),
|
|
59
|
+
{
|
|
60
|
+
onSuccess: () => {
|
|
61
|
+
notifyStatus(
|
|
62
|
+
formatMessage({
|
|
63
|
+
id: getTrad('Providers.data.loaded'),
|
|
64
|
+
defaultMessage: 'Providers have been loaded',
|
|
65
|
+
})
|
|
66
|
+
);
|
|
67
|
+
},
|
|
68
|
+
initialData: {},
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
71
|
|
|
72
72
|
const isLoading = isLoadingForData || isFetching;
|
|
73
73
|
|
|
74
74
|
const submitMutation = useMutation(putProvider, {
|
|
75
|
-
async
|
|
75
|
+
onSuccess: async () => {
|
|
76
76
|
await queryClient.invalidateQueries('get-providers');
|
|
77
77
|
toggleNotification({
|
|
78
78
|
type: 'info',
|
|
@@ -84,7 +84,7 @@ export const ProvidersPage = () => {
|
|
|
84
84
|
handleToggleModal();
|
|
85
85
|
unlockApp();
|
|
86
86
|
},
|
|
87
|
-
onError() {
|
|
87
|
+
onError: () => {
|
|
88
88
|
toggleNotification({
|
|
89
89
|
type: 'warning',
|
|
90
90
|
message: { id: 'notification.error' },
|
|
@@ -104,7 +104,7 @@ export const ProvidersPage = () => {
|
|
|
104
104
|
return false;
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
-
const providerToEdit = providers.find(
|
|
107
|
+
const providerToEdit = providers.find(obj => obj.name === providerToEditName);
|
|
108
108
|
|
|
109
109
|
return has(providerToEdit, 'subdomain');
|
|
110
110
|
}, [providers, providerToEditName]);
|
|
@@ -127,17 +127,17 @@ export const ProvidersPage = () => {
|
|
|
127
127
|
}, [providerToEditName, isProviderWithSubdomain]);
|
|
128
128
|
|
|
129
129
|
const handleToggleModal = () => {
|
|
130
|
-
setIsOpen(
|
|
130
|
+
setIsOpen(prev => !prev);
|
|
131
131
|
};
|
|
132
132
|
|
|
133
|
-
const handleClickEdit =
|
|
133
|
+
const handleClickEdit = provider => {
|
|
134
134
|
if (canUpdate) {
|
|
135
135
|
setProviderToEditName(provider.name);
|
|
136
136
|
handleToggleModal();
|
|
137
137
|
}
|
|
138
138
|
};
|
|
139
139
|
|
|
140
|
-
const handleSubmit = async
|
|
140
|
+
const handleSubmit = async values => {
|
|
141
141
|
setIsSubmiting(true);
|
|
142
142
|
|
|
143
143
|
lockApp();
|
|
@@ -196,7 +196,7 @@ export const ProvidersPage = () => {
|
|
|
196
196
|
</Tr>
|
|
197
197
|
</Thead>
|
|
198
198
|
<Tbody>
|
|
199
|
-
{providers.map(
|
|
199
|
+
{providers.map(provider => (
|
|
200
200
|
<Tr
|
|
201
201
|
key={provider.name}
|
|
202
202
|
{...onRowClick({
|
|
@@ -10,7 +10,7 @@ const initialState = {
|
|
|
10
10
|
|
|
11
11
|
const reducer = (state, action) =>
|
|
12
12
|
// eslint-disable-next-line consistent-return
|
|
13
|
-
produce(state,
|
|
13
|
+
produce(state, draftState => {
|
|
14
14
|
switch (action.type) {
|
|
15
15
|
case 'GET_DATA': {
|
|
16
16
|
draftState.isLoading = true;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getRequestURL, axiosInstance } from '../../../utils';
|
|
2
2
|
|
|
3
3
|
// eslint-disable-next-line import/prefer-default-export
|
|
4
|
-
export const fetchData = async
|
|
4
|
+
export const fetchData = async toggleNotification => {
|
|
5
5
|
try {
|
|
6
6
|
const { data } = await axiosInstance.get(getRequestURL('providers'));
|
|
7
7
|
|
|
@@ -16,6 +16,6 @@ export const fetchData = async (toggleNotification) => {
|
|
|
16
16
|
}
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
export const putProvider =
|
|
19
|
+
export const putProvider = body => {
|
|
20
20
|
return axiosInstance.put(getRequestURL('providers'), body);
|
|
21
21
|
};
|
|
@@ -36,7 +36,7 @@ const EditPage = () => {
|
|
|
36
36
|
const { trackUsage } = useTracking();
|
|
37
37
|
const permissionsRef = useRef();
|
|
38
38
|
|
|
39
|
-
const handleCreateRoleSubmit = async
|
|
39
|
+
const handleCreateRoleSubmit = async data => {
|
|
40
40
|
// Set loading state
|
|
41
41
|
lockApp();
|
|
42
42
|
setIsSubmitting(true);
|
|
@@ -40,7 +40,7 @@ const EditPage = () => {
|
|
|
40
40
|
const { role, onSubmitSucceeded, isLoading: isLoadingRole } = useFetchRole(id);
|
|
41
41
|
const permissionsRef = useRef();
|
|
42
42
|
|
|
43
|
-
const handleEditRoleSubmit = async
|
|
43
|
+
const handleEditRoleSubmit = async data => {
|
|
44
44
|
// Set loading state
|
|
45
45
|
lockApp();
|
|
46
46
|
setIsSubmitting(true);
|
|
@@ -17,21 +17,20 @@ const TableBody = ({ sortedRoles, canDelete, permissions, setRoleToDelete, onDel
|
|
|
17
17
|
const { push } = useHistory();
|
|
18
18
|
const [showConfirmDelete, setShowConfirmDelete] = onDelete;
|
|
19
19
|
|
|
20
|
-
const checkCanDeleteRole = (role)
|
|
21
|
-
canDelete && !['public', 'authenticated'].includes(role.type);
|
|
20
|
+
const checkCanDeleteRole = role => canDelete && !['public', 'authenticated'].includes(role.type);
|
|
22
21
|
|
|
23
|
-
const handleClickDelete =
|
|
22
|
+
const handleClickDelete = id => {
|
|
24
23
|
setRoleToDelete(id);
|
|
25
24
|
setShowConfirmDelete(!showConfirmDelete);
|
|
26
25
|
};
|
|
27
26
|
|
|
28
|
-
const handleClickEdit =
|
|
27
|
+
const handleClickEdit = id => {
|
|
29
28
|
push(`/settings/${pluginId}/roles/${id}`);
|
|
30
29
|
};
|
|
31
30
|
|
|
32
31
|
return (
|
|
33
32
|
<Tbody>
|
|
34
|
-
{sortedRoles?.map(
|
|
33
|
+
{sortedRoles?.map(role => (
|
|
35
34
|
<Tr key={role.name} {...onRowClick({ fn: () => handleClickEdit(role.id) })}>
|
|
36
35
|
<Td width="20%">
|
|
37
36
|
<Typography>{role.name}</Typography>
|
|
@@ -97,8 +97,8 @@ const RoleListPage = () => {
|
|
|
97
97
|
defaultMessage: 'Roles',
|
|
98
98
|
});
|
|
99
99
|
|
|
100
|
-
const deleteMutation = useMutation(
|
|
101
|
-
async
|
|
100
|
+
const deleteMutation = useMutation(id => deleteData(id, toggleNotification), {
|
|
101
|
+
onSuccess: async () => {
|
|
102
102
|
await queryClient.invalidateQueries('get-roles');
|
|
103
103
|
},
|
|
104
104
|
});
|
|
@@ -6,7 +6,7 @@ const instance = axios.create({
|
|
|
6
6
|
});
|
|
7
7
|
|
|
8
8
|
instance.interceptors.request.use(
|
|
9
|
-
async
|
|
9
|
+
async config => {
|
|
10
10
|
config.headers = {
|
|
11
11
|
Authorization: `Bearer ${auth.getToken()}`,
|
|
12
12
|
Accept: 'application/json',
|
|
@@ -15,14 +15,14 @@ instance.interceptors.request.use(
|
|
|
15
15
|
|
|
16
16
|
return config;
|
|
17
17
|
},
|
|
18
|
-
|
|
18
|
+
error => {
|
|
19
19
|
Promise.reject(error);
|
|
20
20
|
}
|
|
21
21
|
);
|
|
22
22
|
|
|
23
23
|
instance.interceptors.response.use(
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
response => response,
|
|
25
|
+
error => {
|
|
26
26
|
// whatever you want to do with the error
|
|
27
27
|
if (error.response?.status === 401) {
|
|
28
28
|
auth.clearAppStorage();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isEmpty } from 'lodash';
|
|
2
2
|
|
|
3
|
-
const cleanPermissions =
|
|
3
|
+
const cleanPermissions = permissions =>
|
|
4
4
|
Object.keys(permissions).reduce((acc, current) => {
|
|
5
5
|
const currentPermission = permissions[current].controllers;
|
|
6
6
|
const cleanedControllers = Object.keys(currentPermission).reduce((acc2, curr) => {
|
package/jest.config.front.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@strapi/plugin-users-permissions",
|
|
3
|
-
"version": "0.0.0-
|
|
3
|
+
"version": "0.0.0-8581854cb3",
|
|
4
4
|
"description": "Protect your API with a full-authentication process based on JWT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -27,12 +27,11 @@
|
|
|
27
27
|
"test:front:watch:ce": "cross-env IS_EE=false jest --config ./jest.config.front.js --watchAll"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@strapi/helper-plugin": "0.0.0-
|
|
31
|
-
"@strapi/utils": "0.0.0-
|
|
30
|
+
"@strapi/helper-plugin": "0.0.0-8581854cb3",
|
|
31
|
+
"@strapi/utils": "0.0.0-8581854cb3",
|
|
32
32
|
"bcryptjs": "2.4.3",
|
|
33
33
|
"grant-koa": "5.4.8",
|
|
34
34
|
"jsonwebtoken": "^8.1.0",
|
|
35
|
-
"koa": "^2.13.4",
|
|
36
35
|
"koa2-ratelimit": "^1.1.1",
|
|
37
36
|
"lodash": "4.17.21",
|
|
38
37
|
"purest": "4.0.2",
|
|
@@ -42,9 +41,13 @@
|
|
|
42
41
|
"react-redux": "7.2.8",
|
|
43
42
|
"react-router": "^5.2.0",
|
|
44
43
|
"react-router-dom": "5.2.0",
|
|
44
|
+
"redux-saga": "^0.16.0",
|
|
45
45
|
"request": "^2.83.0",
|
|
46
46
|
"url-join": "4.0.1"
|
|
47
47
|
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"koa": "^2.13.4"
|
|
50
|
+
},
|
|
48
51
|
"engines": {
|
|
49
52
|
"node": ">=14.19.1 <=16.x.x",
|
|
50
53
|
"npm": ">=6.0.0"
|
|
@@ -56,5 +59,5 @@
|
|
|
56
59
|
"required": true,
|
|
57
60
|
"kind": "plugin"
|
|
58
61
|
},
|
|
59
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "8581854cb3c817ae42b829ea686a1b0702ed9245"
|
|
60
63
|
}
|
|
@@ -15,7 +15,42 @@ const getGrantConfig = require('./grant-config');
|
|
|
15
15
|
|
|
16
16
|
const usersPermissionsActions = require('./users-permissions-actions');
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
module.exports = async ({ strapi }) => {
|
|
19
|
+
const pluginStore = strapi.store({ type: 'plugin', name: 'users-permissions' });
|
|
20
|
+
|
|
21
|
+
await initGrant(pluginStore);
|
|
22
|
+
await initEmails(pluginStore);
|
|
23
|
+
await initAdvancedOptions(pluginStore);
|
|
24
|
+
|
|
25
|
+
await strapi.admin.services.permission.actionProvider.registerMany(
|
|
26
|
+
usersPermissionsActions.actions
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
await getService('users-permissions').initialize();
|
|
30
|
+
|
|
31
|
+
if (!strapi.config.get('plugin.users-permissions.jwtSecret')) {
|
|
32
|
+
if (process.env.NODE_ENV !== 'development') {
|
|
33
|
+
throw new Error(
|
|
34
|
+
`Missing jwtSecret. Please, set configuration variable "jwtSecret" for the users-permissions plugin in config/plugins.js (ex: you can generate one using Node with \`crypto.randomBytes(16).toString('base64')\`).
|
|
35
|
+
For security reasons, prefer storing the secret in an environment variable and read it in config/plugins.js. See https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/configurations/optional/environment.html#configuration-using-environment-variables.`
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const jwtSecret = crypto.randomBytes(16).toString('base64');
|
|
40
|
+
|
|
41
|
+
strapi.config.set('plugin.users-permissions.jwtSecret', jwtSecret);
|
|
42
|
+
|
|
43
|
+
if (!process.env.JWT_SECRET) {
|
|
44
|
+
const envPath = process.env.ENV_PATH || '.env';
|
|
45
|
+
strapi.fs.appendFile(envPath, `JWT_SECRET=${jwtSecret}\n`);
|
|
46
|
+
strapi.log.info(
|
|
47
|
+
`The Users & Permissions plugin automatically generated a jwt secret and stored it in ${envPath} under the name JWT_SECRET.`
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const initGrant = async pluginStore => {
|
|
19
54
|
const apiPrefix = strapi.config.get('api.rest.prefix');
|
|
20
55
|
const baseURL = urljoin(strapi.config.server.url, apiPrefix, 'auth');
|
|
21
56
|
|
|
@@ -27,7 +62,7 @@ const initGrant = async (pluginStore) => {
|
|
|
27
62
|
// or we have added/deleted provider here.
|
|
28
63
|
if (!prevGrantConfig || !_.isEqual(_.keys(prevGrantConfig), _.keys(grantConfig))) {
|
|
29
64
|
// merge with the previous provider config.
|
|
30
|
-
_.keys(grantConfig).forEach(
|
|
65
|
+
_.keys(grantConfig).forEach(key => {
|
|
31
66
|
if (key in prevGrantConfig) {
|
|
32
67
|
grantConfig[key] = _.merge(grantConfig[key], prevGrantConfig[key]);
|
|
33
68
|
}
|
|
@@ -36,7 +71,7 @@ const initGrant = async (pluginStore) => {
|
|
|
36
71
|
}
|
|
37
72
|
};
|
|
38
73
|
|
|
39
|
-
const initEmails = async
|
|
74
|
+
const initEmails = async pluginStore => {
|
|
40
75
|
if (!(await pluginStore.get({ key: 'email' }))) {
|
|
41
76
|
const value = {
|
|
42
77
|
reset_password: {
|
|
@@ -82,7 +117,7 @@ const initEmails = async (pluginStore) => {
|
|
|
82
117
|
}
|
|
83
118
|
};
|
|
84
119
|
|
|
85
|
-
const initAdvancedOptions = async
|
|
120
|
+
const initAdvancedOptions = async pluginStore => {
|
|
86
121
|
if (!(await pluginStore.get({ key: 'advanced' }))) {
|
|
87
122
|
const value = {
|
|
88
123
|
unique_email: true,
|
|
@@ -96,38 +131,3 @@ const initAdvancedOptions = async (pluginStore) => {
|
|
|
96
131
|
await pluginStore.set({ key: 'advanced', value });
|
|
97
132
|
}
|
|
98
133
|
};
|
|
99
|
-
|
|
100
|
-
module.exports = async ({ strapi }) => {
|
|
101
|
-
const pluginStore = strapi.store({ type: 'plugin', name: 'users-permissions' });
|
|
102
|
-
|
|
103
|
-
await initGrant(pluginStore);
|
|
104
|
-
await initEmails(pluginStore);
|
|
105
|
-
await initAdvancedOptions(pluginStore);
|
|
106
|
-
|
|
107
|
-
await strapi.admin.services.permission.actionProvider.registerMany(
|
|
108
|
-
usersPermissionsActions.actions
|
|
109
|
-
);
|
|
110
|
-
|
|
111
|
-
await getService('users-permissions').initialize();
|
|
112
|
-
|
|
113
|
-
if (!strapi.config.get('plugin.users-permissions.jwtSecret')) {
|
|
114
|
-
if (process.env.NODE_ENV !== 'development') {
|
|
115
|
-
throw new Error(
|
|
116
|
-
`Missing jwtSecret. Please, set configuration variable "jwtSecret" for the users-permissions plugin in config/plugins.js (ex: you can generate one using Node with \`crypto.randomBytes(16).toString('base64')\`).
|
|
117
|
-
For security reasons, prefer storing the secret in an environment variable and read it in config/plugins.js. See https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/configurations/optional/environment.html#configuration-using-environment-variables.`
|
|
118
|
-
);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
const jwtSecret = crypto.randomBytes(16).toString('base64');
|
|
122
|
-
|
|
123
|
-
strapi.config.set('plugin.users-permissions.jwtSecret', jwtSecret);
|
|
124
|
-
|
|
125
|
-
if (!process.env.JWT_SECRET) {
|
|
126
|
-
const envPath = process.env.ENV_PATH || '.env';
|
|
127
|
-
strapi.fs.appendFile(envPath, `JWT_SECRET=${jwtSecret}\n`);
|
|
128
|
-
strapi.log.info(
|
|
129
|
-
`The Users & Permissions plugin automatically generated a jwt secret and stored it in ${envPath} under the name JWT_SECRET.`
|
|
130
|
-
);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
};
|
|
@@ -247,7 +247,10 @@ module.exports = {
|
|
|
247
247
|
await getService('user').edit(user.id, { resetPasswordToken });
|
|
248
248
|
|
|
249
249
|
// Send an email to the user.
|
|
250
|
-
await strapi
|
|
250
|
+
await strapi
|
|
251
|
+
.plugin('email')
|
|
252
|
+
.service('email')
|
|
253
|
+
.send(emailToSend);
|
|
251
254
|
|
|
252
255
|
ctx.send({ ok: true });
|
|
253
256
|
},
|
|
@@ -311,7 +314,7 @@ module.exports = {
|
|
|
311
314
|
}
|
|
312
315
|
}
|
|
313
316
|
|
|
314
|
-
|
|
317
|
+
let newUser = {
|
|
315
318
|
...params,
|
|
316
319
|
role: role.id,
|
|
317
320
|
email: email.toLowerCase(),
|
|
@@ -2,8 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
const _ = require('lodash');
|
|
4
4
|
const { contentTypes: contentTypesUtils } = require('@strapi/utils');
|
|
5
|
-
const {
|
|
6
|
-
|
|
5
|
+
const {
|
|
6
|
+
ApplicationError,
|
|
7
|
+
ValidationError,
|
|
8
|
+
NotFoundError,
|
|
9
|
+
ForbiddenError,
|
|
10
|
+
} = require('@strapi/utils').errors;
|
|
7
11
|
const { validateCreateUserBody, validateUpdateUserBody } = require('./validation/user');
|
|
8
12
|
|
|
9
13
|
const { UPDATED_BY_ATTRIBUTE, CREATED_BY_ATTRIBUTE } = contentTypesUtils.constants;
|
|
@@ -128,13 +132,17 @@ module.exports = {
|
|
|
128
132
|
|
|
129
133
|
const { email, username, password } = body;
|
|
130
134
|
|
|
131
|
-
|
|
135
|
+
let pm;
|
|
136
|
+
let user;
|
|
137
|
+
|
|
138
|
+
const { pm: permissionManager, entity } = await findEntityAndCheckPermissions(
|
|
132
139
|
userAbility,
|
|
133
140
|
ACTIONS.edit,
|
|
134
141
|
userModel,
|
|
135
142
|
id
|
|
136
143
|
);
|
|
137
|
-
|
|
144
|
+
pm = permissionManager;
|
|
145
|
+
user = entity;
|
|
138
146
|
|
|
139
147
|
await validateUpdateUserBody(ctx.request.body);
|
|
140
148
|
|
|
@@ -17,7 +17,7 @@ module.exports = {
|
|
|
17
17
|
|
|
18
18
|
const emailTemplates = ctx.request.body['email-templates'];
|
|
19
19
|
|
|
20
|
-
for (
|
|
20
|
+
for (let key in emailTemplates) {
|
|
21
21
|
const template = emailTemplates[key].options.message;
|
|
22
22
|
|
|
23
23
|
if (!isValidEmailTemplate(template)) {
|
|
@@ -121,7 +121,7 @@ module.exports = {
|
|
|
121
121
|
ctx.request.body.email = ctx.request.body.email.toLowerCase();
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
-
|
|
124
|
+
let updateData = {
|
|
125
125
|
...ctx.request.body,
|
|
126
126
|
};
|
|
127
127
|
|
|
@@ -138,7 +138,7 @@ module.exports = {
|
|
|
138
138
|
async find(ctx) {
|
|
139
139
|
const users = await getService('user').fetchAll(ctx.query);
|
|
140
140
|
|
|
141
|
-
ctx.body = await Promise.all(users.map(
|
|
141
|
+
ctx.body = await Promise.all(users.map(user => sanitizeOutput(user, ctx)));
|
|
142
142
|
},
|
|
143
143
|
|
|
144
144
|
/**
|
|
@@ -8,13 +8,19 @@ const callbackSchema = yup.object({
|
|
|
8
8
|
});
|
|
9
9
|
|
|
10
10
|
const registerSchema = yup.object({
|
|
11
|
-
email: yup
|
|
11
|
+
email: yup
|
|
12
|
+
.string()
|
|
13
|
+
.email()
|
|
14
|
+
.required(),
|
|
12
15
|
username: yup.string().required(),
|
|
13
16
|
password: yup.string().required(),
|
|
14
17
|
});
|
|
15
18
|
|
|
16
19
|
const sendEmailConfirmationSchema = yup.object({
|
|
17
|
-
email: yup
|
|
20
|
+
email: yup
|
|
21
|
+
.string()
|
|
22
|
+
.email()
|
|
23
|
+
.required(),
|
|
18
24
|
});
|
|
19
25
|
|
|
20
26
|
const validateEmailConfirmationSchema = yup.object({
|
|
@@ -23,7 +29,10 @@ const validateEmailConfirmationSchema = yup.object({
|
|
|
23
29
|
|
|
24
30
|
const forgotPasswordSchema = yup
|
|
25
31
|
.object({
|
|
26
|
-
email: yup
|
|
32
|
+
email: yup
|
|
33
|
+
.string()
|
|
34
|
+
.email()
|
|
35
|
+
.required(),
|
|
27
36
|
})
|
|
28
37
|
.noUnknown();
|
|
29
38
|
|
|
@@ -19,7 +19,6 @@ const matchAll = (pattern, src) => {
|
|
|
19
19
|
let match;
|
|
20
20
|
|
|
21
21
|
const regexPatternWithGlobal = RegExp(pattern, 'g');
|
|
22
|
-
// eslint-disable-next-line no-cond-assign
|
|
23
22
|
while ((match = regexPatternWithGlobal.exec(src))) {
|
|
24
23
|
const [, group] = match;
|
|
25
24
|
|
|
@@ -28,8 +27,8 @@ const matchAll = (pattern, src) => {
|
|
|
28
27
|
return matches;
|
|
29
28
|
};
|
|
30
29
|
|
|
31
|
-
const isValidEmailTemplate =
|
|
32
|
-
for (
|
|
30
|
+
const isValidEmailTemplate = template => {
|
|
31
|
+
for (let reg of invalidPatternsRegexes) {
|
|
33
32
|
if (reg.test(template)) {
|
|
34
33
|
return false;
|
|
35
34
|
}
|
|
@@ -7,14 +7,26 @@ const deleteRoleSchema = yup.object().shape({
|
|
|
7
7
|
});
|
|
8
8
|
|
|
9
9
|
const createUserBodySchema = yup.object().shape({
|
|
10
|
-
email: yup
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
email: yup
|
|
11
|
+
.string()
|
|
12
|
+
.email()
|
|
13
|
+
.required(),
|
|
14
|
+
username: yup
|
|
15
|
+
.string()
|
|
16
|
+
.min(1)
|
|
17
|
+
.required(),
|
|
18
|
+
password: yup
|
|
19
|
+
.string()
|
|
20
|
+
.min(1)
|
|
21
|
+
.required(),
|
|
13
22
|
role: yup.strapiID(),
|
|
14
23
|
});
|
|
15
24
|
|
|
16
25
|
const updateUserBodySchema = yup.object().shape({
|
|
17
|
-
email: yup
|
|
26
|
+
email: yup
|
|
27
|
+
.string()
|
|
28
|
+
.email()
|
|
29
|
+
.min(1),
|
|
18
30
|
username: yup.string().min(1),
|
|
19
31
|
password: yup.string().min(1),
|
|
20
32
|
});
|
|
@@ -23,7 +23,10 @@ module.exports = ({ nexus, strapi }) => {
|
|
|
23
23
|
|
|
24
24
|
koaContext.request.body = toPlainObject(args);
|
|
25
25
|
|
|
26
|
-
await strapi
|
|
26
|
+
await strapi
|
|
27
|
+
.plugin('users-permissions')
|
|
28
|
+
.controller('auth')
|
|
29
|
+
.changePassword(koaContext);
|
|
27
30
|
|
|
28
31
|
const output = koaContext.body;
|
|
29
32
|
|
|
@@ -21,7 +21,10 @@ module.exports = ({ nexus, strapi }) => {
|
|
|
21
21
|
|
|
22
22
|
koaContext.request.body = toPlainObject(args);
|
|
23
23
|
|
|
24
|
-
await strapi
|
|
24
|
+
await strapi
|
|
25
|
+
.plugin('users-permissions')
|
|
26
|
+
.controller('auth')
|
|
27
|
+
.forgotPassword(koaContext);
|
|
25
28
|
|
|
26
29
|
const output = koaContext.body;
|
|
27
30
|
|
|
@@ -20,7 +20,10 @@ module.exports = ({ nexus, strapi }) => {
|
|
|
20
20
|
koaContext.params = { provider: args.input.provider };
|
|
21
21
|
koaContext.request.body = toPlainObject(args.input);
|
|
22
22
|
|
|
23
|
-
await strapi
|
|
23
|
+
await strapi
|
|
24
|
+
.plugin('users-permissions')
|
|
25
|
+
.controller('auth')
|
|
26
|
+
.callback(koaContext);
|
|
24
27
|
|
|
25
28
|
const output = koaContext.body;
|
|
26
29
|
|
|
@@ -21,7 +21,10 @@ module.exports = ({ nexus, strapi }) => {
|
|
|
21
21
|
|
|
22
22
|
koaContext.request.body = toPlainObject(args.input);
|
|
23
23
|
|
|
24
|
-
await strapi
|
|
24
|
+
await strapi
|
|
25
|
+
.plugin('users-permissions')
|
|
26
|
+
.controller('auth')
|
|
27
|
+
.register(koaContext);
|
|
25
28
|
|
|
26
29
|
const output = koaContext.body;
|
|
27
30
|
|
|
@@ -23,7 +23,10 @@ module.exports = ({ nexus, strapi }) => {
|
|
|
23
23
|
|
|
24
24
|
koaContext.request.body = toPlainObject(args);
|
|
25
25
|
|
|
26
|
-
await strapi
|
|
26
|
+
await strapi
|
|
27
|
+
.plugin('users-permissions')
|
|
28
|
+
.controller('auth')
|
|
29
|
+
.resetPassword(koaContext);
|
|
27
30
|
|
|
28
31
|
const output = koaContext.body;
|
|
29
32
|
|