mirror of
https://github.com/strapi/strapi.git
synced 2025-12-15 17:22:57 +00:00
WIP add redux support to license limit hook, various minor changes
Co-authored-by: Gustav Hansen <gu@stav.dev>
This commit is contained in:
parent
a0144c1565
commit
ebdf9c06c2
@ -1,14 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
// This wrapper is needed for ee_else_ce component substitution to add ee specific license context in ee mode
|
||||
const LicenseContextWrapper = ({ children }) => {
|
||||
// eslint-disable-next-line react/jsx-no-useless-fragment
|
||||
return <>{children}</>;
|
||||
};
|
||||
|
||||
LicenseContextWrapper.propTypes = {
|
||||
children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]).isRequired,
|
||||
};
|
||||
|
||||
export default LicenseContextWrapper;
|
||||
@ -9,7 +9,7 @@ import {
|
||||
} from '@strapi/helper-plugin';
|
||||
import { useQueries } from 'react-query';
|
||||
import get from 'lodash/get';
|
||||
import LicenseContextWrapper from 'ee_else_ce/components/AuthenticatedApp/LicenseContextWrapper';
|
||||
import useLicenseLimitInfos from 'ee_else_ce/hooks/useLicenseLimitInfos';
|
||||
import packageJSON from '../../../../package.json';
|
||||
import { useConfigurations } from '../../hooks';
|
||||
import PluginsInitializer from '../PluginsInitializer';
|
||||
@ -73,6 +73,10 @@ const AuthenticatedApp = () => {
|
||||
}
|
||||
}, [userRoles, appInfos]);
|
||||
|
||||
// This hook fetches license allowances in 'ee' mode and stores data in redux for global access.
|
||||
// It does nothing in 'ce'.
|
||||
useLicenseLimitInfos();
|
||||
|
||||
useEffect(() => {
|
||||
const getUserId = async () => {
|
||||
const userId = await hashAdminUserEmail(userInfo);
|
||||
@ -110,13 +114,11 @@ const AuthenticatedApp = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<LicenseContextWrapper>
|
||||
<AppInfosContext.Provider value={appInfosValue}>
|
||||
<RBACProvider permissions={permissions} refetchPermissions={refetch}>
|
||||
<PluginsInitializer />
|
||||
</RBACProvider>
|
||||
</AppInfosContext.Provider>
|
||||
</LicenseContextWrapper>
|
||||
<AppInfosContext.Provider value={appInfosValue}>
|
||||
<RBACProvider permissions={permissions} refetchPermissions={refetch}>
|
||||
<PluginsInitializer />
|
||||
</RBACProvider>
|
||||
</AppInfosContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -1,9 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
// Shallow component that is overridden in EE
|
||||
const EENotification = () => {
|
||||
// eslint-disable-next-line react/jsx-no-useless-fragment
|
||||
return <></>;
|
||||
};
|
||||
|
||||
export default EENotification;
|
||||
@ -67,7 +67,14 @@ const Notification = ({ dispatch, notification }) => {
|
||||
}
|
||||
|
||||
if (title) {
|
||||
alertTitle = typeof title === 'string' ? title : formatMessage(title);
|
||||
alertTitle =
|
||||
typeof title === 'string'
|
||||
? title
|
||||
: formattedMessage({
|
||||
id: title?.id || title,
|
||||
defaultMessage: title?.defaultMessage || title?.id || title,
|
||||
values: title?.values,
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@ -10,3 +10,4 @@ export { default as usePermissionsDataManager } from './usePermissionsDataManage
|
||||
export { default as useReleaseNotification } from './useReleaseNotification';
|
||||
export { default as useThemeToggle } from './useThemeToggle';
|
||||
export { default as useRegenerate } from './useRegenerate';
|
||||
export { default as useLicenseLimitInfos } from './useLicenseLimitInfos';
|
||||
|
||||
@ -0,0 +1,5 @@
|
||||
const useLicenseLimitInfos = () => {
|
||||
return null;
|
||||
};
|
||||
|
||||
export default useLicenseLimitInfos;
|
||||
@ -0,0 +1,5 @@
|
||||
const useLicenseLimitNotification = () => {
|
||||
return null;
|
||||
};
|
||||
|
||||
export default useLicenseLimitNotification;
|
||||
@ -13,7 +13,7 @@ import { Layout } from '@strapi/design-system/Layout';
|
||||
import { Main } from '@strapi/design-system/Main';
|
||||
import { Box } from '@strapi/design-system/Box';
|
||||
import { Grid, GridItem } from '@strapi/design-system/Grid';
|
||||
import EENotification from 'ee_else_ce/components/EENotification';
|
||||
import useLicenseLimitNotification from 'ee_else_ce/hooks/useLicenseLimitNotification';
|
||||
import cornerOrnamentPath from './assets/corner-ornament.svg';
|
||||
import { useModels } from '../../hooks';
|
||||
import isGuidedTourCompleted from '../../components/GuidedTour/utils/isGuidedTourCompleted';
|
||||
@ -36,6 +36,7 @@ const HomePage = () => {
|
||||
// Temporary until we develop the menu API
|
||||
const { collectionTypes, singleTypes, isLoading: isLoadingForModels } = useModels();
|
||||
const { guidedTourState, isGuidedTourVisible, isSkipped } = useGuidedTour();
|
||||
useLicenseLimitNotification();
|
||||
|
||||
const showGuidedTour =
|
||||
!isGuidedTourCompleted(guidedTourState) && isGuidedTourVisible && !isSkipped;
|
||||
@ -61,7 +62,6 @@ const HomePage = () => {
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<EENotification />
|
||||
<FormattedMessage id="HomePage.helmet.title" defaultMessage="Homepage">
|
||||
{(title) => <Helmet title={title[0]} />}
|
||||
</FormattedMessage>
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
const AdminSeatInfo = () => {};
|
||||
const AdminSeatInfo = () => {
|
||||
return null;
|
||||
};
|
||||
|
||||
export default AdminSeatInfo;
|
||||
|
||||
@ -18,7 +18,6 @@ import { Button } from '@strapi/design-system/Button';
|
||||
import { Link } from '@strapi/design-system/v2/Link';
|
||||
import ExternalLink from '@strapi/icons/ExternalLink';
|
||||
import Check from '@strapi/icons/Check';
|
||||
import EENotification from 'ee_else_ce/components/EENotification';
|
||||
import AdminSeatInfo from 'ee_else_ce/pages/SettingsPage/pages/ApplicationInfosPage/components/AdminSeatInfo';
|
||||
import adminPermissions from '../../../../permissions';
|
||||
import { useConfigurations } from '../../../../hooks';
|
||||
@ -95,7 +94,6 @@ const ApplicationInfosPage = () => {
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<EENotification />
|
||||
<SettingsPageTitle name="Application" />
|
||||
<Main>
|
||||
<form onSubmit={handleSubmit}>
|
||||
|
||||
@ -14,8 +14,8 @@ import { useNotifyAT } from '@strapi/design-system/LiveRegions';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { useMutation, useQuery, useQueryClient } from 'react-query';
|
||||
import EENotification from 'ee_else_ce/components/EENotification';
|
||||
import CreateAction from 'ee_else_ce/pages/SettingsPage/pages/Users/ListPage/CreateAction';
|
||||
import useLicenseLimitNotification from 'ee_else_ce/hooks/useLicenseLimitNotification';
|
||||
import adminPermissions from '../../../../../permissions';
|
||||
import TableRows from './DynamicTable/TableRows';
|
||||
import Filters from './Filters';
|
||||
@ -35,6 +35,7 @@ const ListPage = () => {
|
||||
const { formatMessage } = useIntl();
|
||||
const { search } = useLocation();
|
||||
useFocusWhenNavigate();
|
||||
useLicenseLimitNotification();
|
||||
const { notifyStatus } = useNotifyAT();
|
||||
const queryName = ['users', search];
|
||||
|
||||
@ -104,7 +105,6 @@ const ListPage = () => {
|
||||
|
||||
return (
|
||||
<Main aria-busy={isLoading}>
|
||||
<EENotification />
|
||||
<SettingsPageTitle name="Users" />
|
||||
<HeaderLayout
|
||||
primaryAction={createAction}
|
||||
|
||||
@ -844,7 +844,9 @@
|
||||
"notification.warning.title": "Warning:",
|
||||
"notification.warning.404": "404 - Not found",
|
||||
"notification.ee.warning.over-seat-limit": "Add seats to re-enable Users. If you already did it but it's not reflected in Strapi yet, make sure to restart your app.",
|
||||
"notification.ee.warning.over-seat-limit.title": "Over seat limit ({currentUserCount}/{permittedSeats})",
|
||||
"notification.ee.warning.at-seat-limit": "Add seats to invite more Users. If you already did it but it's not reflected in Strapi yet, make sure to restart your app.",
|
||||
"notification.ee.warning.at-seat-limit.title": "At seat limit ({currentUserCount}/{permittedSeats})",
|
||||
"or": "OR",
|
||||
"request.error.model.unknown": "This model doesn't exist",
|
||||
"skipToContent": "Skip to content",
|
||||
|
||||
@ -1,23 +0,0 @@
|
||||
import React from 'react';
|
||||
import { useQuery } from 'react-query';
|
||||
import PropTypes from 'prop-types';
|
||||
import { fetchLicenseLimitInfo } from './utils/api';
|
||||
import { LicenseLimitInfosContext } from '../../contexts';
|
||||
|
||||
const LicenseContextWrapper = ({ children }) => {
|
||||
const { data: licenseLimitInfo } = useQuery('license-limit-info', fetchLicenseLimitInfo, {
|
||||
initialData: {},
|
||||
});
|
||||
|
||||
return (
|
||||
<LicenseLimitInfosContext.Provider value={licenseLimitInfo}>
|
||||
{children}
|
||||
</LicenseLimitInfosContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
LicenseContextWrapper.propTypes = {
|
||||
children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]).isRequired,
|
||||
};
|
||||
|
||||
export default LicenseContextWrapper;
|
||||
@ -1,17 +0,0 @@
|
||||
import { axiosInstance } from '../../../../../admin/src/core/utils';
|
||||
|
||||
const fetchLicenseLimitInfo = async () => {
|
||||
try {
|
||||
const { data, headers } = await axiosInstance.get('/admin/license-limit-information');
|
||||
|
||||
if (!headers['content-type'].includes('application/json')) {
|
||||
throw new Error('Not found');
|
||||
}
|
||||
|
||||
return data.data;
|
||||
} catch (error) {
|
||||
throw new Error(error);
|
||||
}
|
||||
};
|
||||
|
||||
export { fetchLicenseLimitInfo };
|
||||
@ -1,22 +0,0 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useLicenseLimitNotification, useLicenseLimitInfos } from '../../hooks';
|
||||
|
||||
// Shallow component that is overridden in EE
|
||||
const EENotification = () => {
|
||||
const licenseLimitNotification = useLicenseLimitNotification();
|
||||
const licenseLimitInfos = useLicenseLimitInfos();
|
||||
const { shouldNotify } = licenseLimitInfos;
|
||||
|
||||
useEffect(() => {
|
||||
if (shouldNotify) {
|
||||
licenseLimitNotification(() => {
|
||||
window.sessionStorage.setItem('licenseNotificationShownOnHome', true);
|
||||
});
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
export default EENotification;
|
||||
@ -1,5 +0,0 @@
|
||||
import { createContext } from 'react';
|
||||
|
||||
const LicenseLimitInfosContext = createContext({});
|
||||
|
||||
export default LicenseLimitInfosContext;
|
||||
@ -1 +0,0 @@
|
||||
export { default as LicenseLimitInfosContext } from './LicenseLimitInfosContext';
|
||||
@ -1,10 +1,68 @@
|
||||
import { useContext } from 'react';
|
||||
import { LicenseLimitInfosContext } from '../../contexts';
|
||||
import { useEffect } from 'react';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
import { useFetchClient } from '@strapi/helper-plugin';
|
||||
import { useQuery } from 'react-query';
|
||||
import { produce } from 'immer';
|
||||
|
||||
import { useInjectReducer } from '../../../../admin/src/hooks/useInjectReducer';
|
||||
|
||||
const NS = 'StrapiAdmin/ee_license-info';
|
||||
const ACTION_EE_LICENSE_INFO_SET_DATA = 'StrapiAdmin/EE_LICENSE_INFO_GET_DATA';
|
||||
|
||||
const initalState = {
|
||||
serverState: {
|
||||
currentUserCount: null,
|
||||
permittedSeats: null,
|
||||
shouldNotify: false,
|
||||
licenseLimitStatus: null,
|
||||
},
|
||||
};
|
||||
|
||||
const reducer = (state = initalState, action) =>
|
||||
/* eslint-disable-next-line consistent-return */
|
||||
produce(state, (draft) => {
|
||||
switch (action.type) {
|
||||
case ACTION_EE_LICENSE_INFO_SET_DATA: {
|
||||
draft.serverState = action.payload;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return draft;
|
||||
}
|
||||
});
|
||||
|
||||
const actionSetData = (payload) => {
|
||||
return {
|
||||
type: ACTION_EE_LICENSE_INFO_SET_DATA,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
const useLicenseLimitInfos = () => {
|
||||
const context = useContext(LicenseLimitInfosContext);
|
||||
const instance = useFetchClient();
|
||||
const fetchLicenseLimitInfo = async () => {
|
||||
const {
|
||||
data: { data },
|
||||
} = await instance.get('/admin/license-limit-information');
|
||||
|
||||
return context;
|
||||
return data;
|
||||
};
|
||||
|
||||
const { data, status } = useQuery('license-limit-info', fetchLicenseLimitInfo);
|
||||
|
||||
const state = useSelector((state) => state?.[NS] ?? initalState);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
useInjectReducer(NS, reducer);
|
||||
|
||||
useEffect(() => {
|
||||
if (status === 'success') {
|
||||
dispatch(actionSetData(data));
|
||||
}
|
||||
}, [data, status, dispatch]);
|
||||
|
||||
return state.serverState;
|
||||
};
|
||||
|
||||
export default useLicenseLimitInfos;
|
||||
|
||||
@ -3,7 +3,8 @@
|
||||
* useLicenseLimitNotification
|
||||
*
|
||||
*/
|
||||
// import { useRef } from 'react';
|
||||
import { useEffect } from 'react';
|
||||
import { useLocation } from 'react-router';
|
||||
import { useNotification } from '@strapi/helper-plugin';
|
||||
import useLicenseLimitInfos from '../useLicenseLimitInfos';
|
||||
|
||||
@ -18,7 +19,12 @@ const notificationBody = (currentUserCount, permittedSeats, licenseLimitStatus)
|
||||
defaultMessage:
|
||||
"Add seats to re-enable users. If you already did it but it's not reflected in Strapi yet, make sure to restart your app.",
|
||||
},
|
||||
title: `Over seat limit (${currentUserCount}/${permittedSeats})`,
|
||||
// Title is translated in the Notification component
|
||||
title: {
|
||||
id: 'notification.ee.warning.over-seat-limit.title',
|
||||
defaultMessage: 'Over seat limit ({currentUserCount}/{permittedSeats})',
|
||||
values: { currentUserCount, permittedSeats },
|
||||
},
|
||||
link: {
|
||||
url: 'test url',
|
||||
label: 'ADD SEATS',
|
||||
@ -37,7 +43,11 @@ const notificationBody = (currentUserCount, permittedSeats, licenseLimitStatus)
|
||||
defaultMessage:
|
||||
"Add seats to re-enable users. If you already did it but it's not reflected in Strapi yet, make sure to restart your app.",
|
||||
},
|
||||
title: `At seat limit (${currentUserCount}/${permittedSeats})`,
|
||||
title: {
|
||||
id: 'notification.ee.warning.at-seat-limit.title',
|
||||
defaultMessage: 'At seat limit ({currentUserCount}/{permittedSeats})',
|
||||
values: { currentUserCount, permittedSeats },
|
||||
},
|
||||
link: {
|
||||
url: 'test url',
|
||||
label: 'ADD SEATS',
|
||||
@ -51,21 +61,38 @@ const notificationBody = (currentUserCount, permittedSeats, licenseLimitStatus)
|
||||
return notification;
|
||||
};
|
||||
|
||||
const shouldDisplayNotification = (pathname) => {
|
||||
const isLocation = (string) => pathname.includes(string);
|
||||
const shownInSession = window.sessionStorage.getItem(`notification-${pathname}`);
|
||||
|
||||
if (isLocation('/') && shownInSession) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isLocation('users') && shownInSession) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
const useLicenseLimitNotification = () => {
|
||||
const licenseLimitInfos = useLicenseLimitInfos();
|
||||
let licenseLimitInfos = useLicenseLimitInfos();
|
||||
const toggleNotification = useNotification();
|
||||
const { currentUserCount, permittedSeats, licenseLimitStatus } = licenseLimitInfos;
|
||||
|
||||
if (!licenseLimitInfos) return;
|
||||
|
||||
// Won't notify if license user and seat info is not present
|
||||
|
||||
const notification = notificationBody(currentUserCount, permittedSeats, licenseLimitStatus);
|
||||
const location = useLocation();
|
||||
|
||||
// eslint-disable-next-line consistent-return
|
||||
return (onClose) => {
|
||||
useEffect(() => {
|
||||
if (!licenseLimitInfos) return;
|
||||
|
||||
if (!shouldDisplayNotification(location.pathname)) return;
|
||||
|
||||
const { currentUserCount, permittedSeats, licenseLimitStatus } = licenseLimitInfos;
|
||||
const notification = notificationBody(currentUserCount, permittedSeats, licenseLimitStatus);
|
||||
const onClose = () => window.sessionStorage.setItem(`notification-${location.pathname}`, true);
|
||||
toggleNotification({ ...notification, onClose });
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
};
|
||||
|
||||
export default useLicenseLimitNotification;
|
||||
|
||||
@ -2,7 +2,11 @@ import React from 'react';
|
||||
import { useIntl } from 'react-intl';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Button } from '@strapi/design-system/Button';
|
||||
import { Tooltip } from '@strapi/design-system/Tooltip';
|
||||
import { Icon } from '@strapi/design-system/Icon';
|
||||
import { Stack } from '@strapi/design-system';
|
||||
import Envelop from '@strapi/icons/Envelop';
|
||||
import ExclamationMarkCircle from '@strapi/icons/ExclamationMarkCircle';
|
||||
import { useLicenseLimitInfos } from '../../../../../../hooks';
|
||||
|
||||
const CreateAction = ({ onClick }) => {
|
||||
@ -11,18 +15,34 @@ const CreateAction = ({ onClick }) => {
|
||||
const { licenseLimitStatus } = licenseLimitInfos;
|
||||
|
||||
return (
|
||||
<Button
|
||||
data-testid="create-user-button"
|
||||
onClick={onClick}
|
||||
startIcon={<Envelop />}
|
||||
size="S"
|
||||
disabled={!!licenseLimitStatus}
|
||||
>
|
||||
{formatMessage({
|
||||
id: 'Settings.permissions.users.create',
|
||||
defaultMessage: 'Invite new user',
|
||||
})}
|
||||
</Button>
|
||||
<Stack spacing={2} horizontal>
|
||||
<Tooltip
|
||||
description={formatMessage({
|
||||
id: 'Settings.application.admin-seats.at-limit-tooltip',
|
||||
defaultMessage: 'At limit: add seats to invite more users',
|
||||
})}
|
||||
position="left"
|
||||
>
|
||||
<Icon
|
||||
width={`${14 / 16}rem`}
|
||||
height={`${14 / 16}rem`}
|
||||
color="danger500"
|
||||
as={ExclamationMarkCircle}
|
||||
/>
|
||||
</Tooltip>
|
||||
<Button
|
||||
data-testid="create-user-button"
|
||||
onClick={onClick}
|
||||
startIcon={<Envelop />}
|
||||
size="S"
|
||||
disabled={!!licenseLimitStatus}
|
||||
>
|
||||
{formatMessage({
|
||||
id: 'Settings.permissions.users.create',
|
||||
defaultMessage: 'Invite new user',
|
||||
})}
|
||||
</Button>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -2,14 +2,25 @@
|
||||
|
||||
module.exports = {
|
||||
async licenseLimitInformation() {
|
||||
const currentUserCount = await strapi.db
|
||||
let shouldNotify = false;
|
||||
let licenseLimitStatus = null;
|
||||
let currentUserCount;
|
||||
const permittedSeats = 5;
|
||||
|
||||
const currentActiveUserCount = await strapi.db
|
||||
.query('admin::user')
|
||||
.count({ where: { isActive: true } });
|
||||
|
||||
const permittedSeats = 5;
|
||||
const data = await strapi.db.query('strapi::ee-store').findOne({
|
||||
where: { key: 'ee_disabled_users' },
|
||||
});
|
||||
|
||||
let shouldNotify = false;
|
||||
let licenseLimitStatus = null;
|
||||
if (data.value) {
|
||||
const eeDisabledUsers = JSON.parse(data.value);
|
||||
currentUserCount = currentActiveUserCount + eeDisabledUsers.length;
|
||||
} else {
|
||||
currentUserCount = currentActiveUserCount;
|
||||
}
|
||||
|
||||
if (currentUserCount > permittedSeats) {
|
||||
shouldNotify = true;
|
||||
|
||||
@ -4,7 +4,10 @@ const { _, get } = require('lodash');
|
||||
const { pick } = require('lodash/fp');
|
||||
const { ApplicationError } = require('@strapi/utils').errors;
|
||||
const { validateUserCreationInput } = require('../validation/user');
|
||||
const { validateUserUpdateInput } = require('../../../server/validation/user');
|
||||
const {
|
||||
validateUserUpdateInput,
|
||||
validateUsersDeleteInput,
|
||||
} = require('../../../server/validation/user');
|
||||
const { getService } = require('../../../server/utils');
|
||||
|
||||
const pickUserCreationAttributes = pick(['firstname', 'lastname', 'email', 'roles']);
|
||||
@ -68,4 +71,39 @@ module.exports = {
|
||||
data: getService('user').sanitizeUser(updatedUser),
|
||||
};
|
||||
},
|
||||
|
||||
async deleteOne(ctx) {
|
||||
const { id } = ctx.params;
|
||||
|
||||
const deletedUser = await getService('user').deleteById(id);
|
||||
|
||||
if (!deletedUser) {
|
||||
return ctx.notFound('User not found');
|
||||
}
|
||||
|
||||
await getService('user').shouldRemoveFromEEDisabledUsersList(id);
|
||||
|
||||
return ctx.deleted({
|
||||
data: getService('user').sanitizeUser(deletedUser),
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Delete several users
|
||||
* @param {KoaContext} ctx - koa context
|
||||
*/
|
||||
async deleteMany(ctx) {
|
||||
const { body } = ctx.request;
|
||||
await validateUsersDeleteInput(body);
|
||||
|
||||
const users = await getService('user').deleteByIds(body.ids);
|
||||
|
||||
await getService('user').shouldRemoveFromEEDisabledUsersList(body.ids);
|
||||
|
||||
const sanitizedUsers = users.map(getService('user').sanitizeUser);
|
||||
|
||||
return ctx.deleted({
|
||||
data: sanitizedUsers,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
@ -7,7 +7,6 @@ const _ = require('lodash');
|
||||
* @param {object} input
|
||||
*/
|
||||
const shouldUpdateEEDisabledUsersList = async (id, input) => {
|
||||
console.log('update service');
|
||||
const data = await strapi.db.query('strapi::ee-store').findOne({
|
||||
where: { key: 'ee_disabled_users' },
|
||||
});
|
||||
@ -19,7 +18,6 @@ const shouldUpdateEEDisabledUsersList = async (id, input) => {
|
||||
|
||||
if (user.isActive !== input.isActive) {
|
||||
const newDisabledUsersList = _.filter(disabledUsers, (user) => user.id !== Number(id));
|
||||
console.log(newDisabledUsersList);
|
||||
await strapi.db.query('strapi::ee-store').update({
|
||||
where: { id: data.id },
|
||||
data: { value: JSON.stringify(newDisabledUsersList) },
|
||||
@ -27,6 +25,29 @@ const shouldUpdateEEDisabledUsersList = async (id, input) => {
|
||||
}
|
||||
};
|
||||
|
||||
const shouldRemoveFromEEDisabledUsersList = async (ids) => {
|
||||
let idsToCheck;
|
||||
if (typeof ids === 'object') {
|
||||
idsToCheck = [...ids];
|
||||
} else {
|
||||
idsToCheck = [Number(ids)];
|
||||
}
|
||||
|
||||
const data = await strapi.db.query('strapi::ee-store').findOne({
|
||||
where: { key: 'ee_disabled_users' },
|
||||
});
|
||||
|
||||
if (!data || !data.value || data.value.length === 0) return;
|
||||
const disabledUsers = JSON.parse(data.value);
|
||||
|
||||
const newDisabledUsersList = _.filter(disabledUsers, (user) => !idsToCheck.includes(user.id));
|
||||
await strapi.db.query('strapi::ee-store').update({
|
||||
where: { id: data.id },
|
||||
data: { value: JSON.stringify(newDisabledUsersList) },
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
shouldUpdateEEDisabledUsersList,
|
||||
shouldRemoveFromEEDisabledUsersList,
|
||||
};
|
||||
|
||||
@ -6,12 +6,12 @@ const { ApplicationError } = require('@strapi/utils/lib/errors');
|
||||
const { PolicyError } = utils.errors;
|
||||
|
||||
module.exports = async (policyCtx, config = {}) => {
|
||||
if (!strapi.EE) return true;
|
||||
if (!strapi.isEE) return true;
|
||||
if (userCount < permittedSeats) return true;
|
||||
|
||||
const userCount = await strapi.db.query('admin::user').count({
|
||||
where: { isActive: true },
|
||||
});
|
||||
|
||||
const permittedSeats = 5;
|
||||
|
||||
if (userCount >= permittedSeats && config.isCreating) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user