Compare commits
7 Commits
v0.10.3-et
...
v0.10.3-et
Author | SHA1 | Date | |
---|---|---|---|
![]() |
02bee92806 | ||
![]() |
b7f8e03894 | ||
![]() |
59bb4b4183 | ||
![]() |
bb53d53692 | ||
![]() |
52a2f1c936 | ||
![]() |
e328380c77 | ||
![]() |
a277ded227 |
134
README.md
134
README.md
@@ -1,7 +1,32 @@
|
||||
# Synapse Admin UI [](https://github.com/Awesome-Technologies/synapse-admin/blob/master/LICENSE)
|
||||
|
||||

|
||||
|
||||
This project is built using [react-admin](https://marmelab.com/react-admin/).
|
||||
|
||||
<!-- vim-markdown-toc GFM -->
|
||||
|
||||
* [Fork differences](#fork-differences)
|
||||
* [Available via CDN](#available-via-cdn)
|
||||
* [Changes](#changes)
|
||||
* [Development](#development)
|
||||
* [Configuration](#configuration)
|
||||
* [Restricting available homeserver](#restricting-available-homeserver)
|
||||
* [Protecting appservice managed users](#protecting-appservice-managed-users)
|
||||
* [Providing support URL](#providing-support-url)
|
||||
* [Usage](#usage)
|
||||
* [Supported Synapse](#supported-synapse)
|
||||
* [Prerequisites](#prerequisites)
|
||||
* [Use without install](#use-without-install)
|
||||
* [Step-By-Step install](#step-by-step-install)
|
||||
* [Steps for 1)](#steps-for-1)
|
||||
* [Steps for 2)](#steps-for-2)
|
||||
* [Steps for 3)](#steps-for-3)
|
||||
* [Serving Synapse-Admin on a different path](#serving-synapse-admin-on-a-different-path)
|
||||
* [Development](#development-1)
|
||||
|
||||
<!-- vim-markdown-toc -->
|
||||
|
||||
## Fork differences
|
||||
|
||||
With [Awesome-Technologies/synapse-admin](https://github.com/Awesome-Technologies/synapse-admin) as the upstream, this
|
||||
@@ -33,6 +58,8 @@ The following changes are already implemented:
|
||||
* [Fix requests with invalid MXIDs on Bulk registration](https://github.com/etkecc/synapse-admin/pull/33)
|
||||
* [Expose user avatar URL field in the UI](https://github.com/etkecc/synapse-admin/pull/27)
|
||||
* [Upgrade react-admin to v5](https://github.com/etkecc/synapse-admin/pull/40)
|
||||
* [Restrict actions on specific users](https://github.com/etkecc/synapse-admin/pull/42)
|
||||
* [Add `Contact support` menu item](https://github.com/etkecc/synapse-admin/pull/45)
|
||||
|
||||
_the list will be updated as new changes are added_
|
||||
|
||||
@@ -47,6 +74,64 @@ After that open `http://localhost:5173` in your browser, login using the followi
|
||||
* Password: admin
|
||||
* Homeserver URL: http://localhost:8008
|
||||
|
||||
## Configuration
|
||||
|
||||
You can use `config.json` file to configure synapse-admin
|
||||
|
||||
The `config.json` can be injected into a Docker container using a bind mount.
|
||||
|
||||
```yml
|
||||
services:
|
||||
synapse-admin:
|
||||
...
|
||||
volumes:
|
||||
./config.json:/app/config.json:ro
|
||||
...
|
||||
```
|
||||
|
||||
### Restricting available homeserver
|
||||
|
||||
You can restrict the homeserver(s), so that the user can no longer define it himself.
|
||||
|
||||
Edit `config.json` to restrict either to a single homeserver:
|
||||
|
||||
```json
|
||||
{
|
||||
"restrictBaseUrl": "https://your-matrixs-erver.example.com"
|
||||
}
|
||||
```
|
||||
|
||||
or to a list of homeservers:
|
||||
|
||||
```json
|
||||
{
|
||||
"restrictBaseUrl": ["https://your-first-matrix-server.example.com", "https://your-second-matrix-server.example.com"]
|
||||
}
|
||||
```
|
||||
|
||||
### Protecting appservice managed users
|
||||
|
||||
To avoid accidental adjustments of appservice-managed users (e.g., puppets created by a bridge) and breaking the bridge,
|
||||
you can specify the list of MXIDs (regexp) that should be prohibited from any changes, except display name and avatar.
|
||||
|
||||
Example for [mautrix-telegram](https://github.com/mautrix/telegram)
|
||||
|
||||
```json
|
||||
{
|
||||
"asManagedUsers": ["^@telegram_[a-zA-Z0-9]+:example\\.com$"]
|
||||
}
|
||||
```
|
||||
|
||||
### Providing support URL
|
||||
|
||||
Synapse-Admin provides a support link in the main menu - `Contact support`. By default, the link points to the GitHub issues page of the project. You can change this link by providing a `supportURL` in the `config.json`.
|
||||
|
||||
```json
|
||||
{
|
||||
"supportURL": "https://example.com/support"
|
||||
}
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Supported Synapse
|
||||
@@ -70,7 +155,7 @@ See also [Synapse administration endpoints](https://element-hq.github.io/synapse
|
||||
### Use without install
|
||||
|
||||
You can use the current version of Synapse Admin without own installation direct
|
||||
via [GitHub Pages](https://awesome-technologies.github.io/synapse-admin/).
|
||||
via [admin.etke.cc](https://admin.etke.cc).
|
||||
|
||||
**Note:**
|
||||
If you want to use the deployment, you have to make sure that the admin endpoints (`/_synapse/admin`) are accessible for your browser.
|
||||
@@ -89,22 +174,22 @@ You have three options:
|
||||
|
||||
- make sure you have a webserver installed that can serve static files (any webserver like nginx or apache will do)
|
||||
- configure a vhost for synapse admin on your webserver
|
||||
- download the .tar.gz from the latest release: https://github.com/Awesome-Technologies/synapse-admin/releases/latest
|
||||
- download the .tar.gz [from the latest release](https://github.com/etkecc/synapse-admin/releases/latest)
|
||||
- unpack the .tar.gz
|
||||
- move or symlink the `synapse-admin-x.x.x` into your vhosts root dir
|
||||
- move or symlink the `synapse-admin` into your vhosts root dir
|
||||
- open the url of the vhost in your browser
|
||||
|
||||
#### Steps for 2)
|
||||
|
||||
- make sure you have installed the following: git, yarn, nodejs
|
||||
- download the source code: `git clone https://github.com/Awesome-Technologies/synapse-admin.git`
|
||||
- download the source code: `git clone https://github.com/etkecc/synapse-admin.git`
|
||||
- change into downloaded directory: `cd synapse-admin`
|
||||
- download dependencies: `yarn install`
|
||||
- start web server: `yarn start`
|
||||
|
||||
#### Steps for 3)
|
||||
|
||||
- run the Docker container from the public docker registry: `docker run -p 8080:80 awesometechnologies/synapse-admin` or use the [docker-compose.yml](docker-compose.yml): `docker-compose up -d`
|
||||
- run the Docker container from the public docker registry: `docker run -p 8080:80 ghcr.io/etkecc/synapse-admin` or use the [docker-compose.yml](docker-compose.yml): `docker-compose up -d`
|
||||
|
||||
> note: if you're building on an architecture other than amd64 (for example a raspberry pi), make sure to define a maximum ram for node. otherwise the build will fail.
|
||||
|
||||
@@ -114,7 +199,7 @@ You have three options:
|
||||
container_name: synapse-admin
|
||||
hostname: synapse-admin
|
||||
build:
|
||||
context: https://github.com/Awesome-Technologies/synapse-admin.git
|
||||
context: https://github.com/etkecc/synapse-admin.git
|
||||
args:
|
||||
- BUILDKIT_CONTEXT_KEEP_GIT_DIR=1
|
||||
# - NODE_OPTIONS="--max_old_space_size=1024"
|
||||
@@ -126,37 +211,6 @@ You have three options:
|
||||
|
||||
- browse to http://localhost:8080
|
||||
|
||||
### Restricting available homeserver
|
||||
|
||||
You can restrict the homeserver(s), so that the user can no longer define it himself.
|
||||
|
||||
Edit `config.json` to restrict either to a single homeserver:
|
||||
|
||||
```json
|
||||
{
|
||||
"restrictBaseUrl": "https://your-matrixs-erver.example.com"
|
||||
}
|
||||
```
|
||||
|
||||
or to a list of homeservers:
|
||||
|
||||
```json
|
||||
{
|
||||
"restrictBaseUrl": ["https://your-first-matrix-server.example.com", "https://your-second-matrix-server.example.com"]
|
||||
}
|
||||
```
|
||||
|
||||
The `config.json` can be injected into a Docker container using a bind mount.
|
||||
|
||||
```yml
|
||||
services:
|
||||
synapse-admin:
|
||||
...
|
||||
volumes:
|
||||
./config.json:/app/config.json:ro
|
||||
...
|
||||
```
|
||||
|
||||
### Serving Synapse-Admin on a different path
|
||||
|
||||
The path prefix where synapse-admin is served can only be changed during the build step.
|
||||
@@ -183,7 +237,7 @@ services:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
|
||||
synapse-admin:
|
||||
image: awesometechnologies/synapse-admin:latest
|
||||
image: etkecc/synapse-admin:latest
|
||||
restart: unless-stopped
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
@@ -194,10 +248,6 @@ services:
|
||||
- "traefik.http.middlewares.admin_path.stripprefix.prefixes=/admin"
|
||||
```
|
||||
|
||||
## Screenshots
|
||||
|
||||

|
||||
|
||||
## Development
|
||||
|
||||
- See https://yarnpkg.com/getting-started/editor-sdks how to setup your IDE
|
||||
|
65
src/App.tsx
65
src/App.tsx
@@ -4,6 +4,7 @@ import polyglotI18nProvider from "ra-i18n-polyglot";
|
||||
import { Admin, CustomRoutes, Resource, resolveBrowserLocale } from "react-admin";
|
||||
import { Route } from "react-router-dom";
|
||||
|
||||
import { AdminLayout } from "./components/AdminLayout";
|
||||
import { ImportFeature } from "./components/ImportFeature";
|
||||
import germanMessages from "./i18n/de";
|
||||
import englishMessages from "./i18n/en";
|
||||
@@ -21,6 +22,7 @@ import userMediaStats from "./resources/user_media_statistics";
|
||||
import users from "./resources/users";
|
||||
import authProvider from "./synapse/authProvider";
|
||||
import dataProvider from "./synapse/dataProvider";
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
|
||||
// TODO: Can we use lazy loading together with browser locale?
|
||||
const messages = {
|
||||
@@ -45,36 +47,41 @@ const i18nProvider = polyglotI18nProvider(
|
||||
]
|
||||
);
|
||||
|
||||
const queryClient = new QueryClient();
|
||||
|
||||
const App = () => (
|
||||
<Admin
|
||||
disableTelemetry
|
||||
requireAuth
|
||||
loginPage={LoginPage}
|
||||
authProvider={authProvider}
|
||||
dataProvider={dataProvider}
|
||||
i18nProvider={i18nProvider}
|
||||
>
|
||||
<CustomRoutes>
|
||||
<Route path="/import_users" element={<ImportFeature />} />
|
||||
</CustomRoutes>
|
||||
<Resource {...users} />
|
||||
<Resource {...rooms} />
|
||||
<Resource {...userMediaStats} />
|
||||
<Resource {...reports} />
|
||||
<Resource {...roomDirectory} />
|
||||
<Resource {...destinations} />
|
||||
<Resource {...registrationToken} />
|
||||
<Resource name="connections" />
|
||||
<Resource name="devices" />
|
||||
<Resource name="room_members" />
|
||||
<Resource name="users_media" />
|
||||
<Resource name="joined_rooms" />
|
||||
<Resource name="pushers" />
|
||||
<Resource name="servernotices" />
|
||||
<Resource name="forward_extremities" />
|
||||
<Resource name="room_state" />
|
||||
<Resource name="destination_rooms" />
|
||||
</Admin>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<Admin
|
||||
disableTelemetry
|
||||
requireAuth
|
||||
layout={AdminLayout}
|
||||
loginPage={LoginPage}
|
||||
authProvider={authProvider}
|
||||
dataProvider={dataProvider}
|
||||
i18nProvider={i18nProvider}
|
||||
>
|
||||
<CustomRoutes>
|
||||
<Route path="/import_users" element={<ImportFeature />} />
|
||||
</CustomRoutes>
|
||||
<Resource {...users} />
|
||||
<Resource {...rooms} />
|
||||
<Resource {...userMediaStats} />
|
||||
<Resource {...reports} />
|
||||
<Resource {...roomDirectory} />
|
||||
<Resource {...destinations} />
|
||||
<Resource {...registrationToken} />
|
||||
<Resource name="connections" />
|
||||
<Resource name="devices" />
|
||||
<Resource name="room_members" />
|
||||
<Resource name="users_media" />
|
||||
<Resource name="joined_rooms" />
|
||||
<Resource name="pushers" />
|
||||
<Resource name="servernotices" />
|
||||
<Resource name="forward_extremities" />
|
||||
<Resource name="room_state" />
|
||||
<Resource name="destination_rooms" />
|
||||
</Admin>
|
||||
</QueryClientProvider>
|
||||
);
|
||||
|
||||
export default App;
|
||||
|
@@ -2,6 +2,8 @@ import { createContext, useContext } from "react";
|
||||
|
||||
interface AppContextType {
|
||||
restrictBaseUrl: string | string[];
|
||||
asManagedUsers: string[];
|
||||
supportURL: string;
|
||||
}
|
||||
|
||||
export const AppContext = createContext({});
|
||||
|
26
src/components/AdminLayout.tsx
Normal file
26
src/components/AdminLayout.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
import { Layout, Menu } from 'react-admin';
|
||||
import LiveHelpIcon from '@mui/icons-material/LiveHelp';
|
||||
|
||||
const DEFAULT_SUPPORT_LINK = "https://github.com/etkecc/synapse-admin/issues";
|
||||
const supportLink = (): string => {
|
||||
try {
|
||||
new URL(localStorage.getItem("support_url") || ''); // Check if the URL is valid
|
||||
return localStorage.getItem("support_url") || DEFAULT_SUPPORT_LINK;
|
||||
} catch (e) {
|
||||
return DEFAULT_SUPPORT_LINK;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const AdminMenu = () => (
|
||||
<Menu>
|
||||
<Menu.ResourceItems />
|
||||
<Menu.Item to={supportLink()} target="_blank" primaryText="Contact support" leftIcon={<LiveHelpIcon />} />
|
||||
</Menu>
|
||||
);
|
||||
|
||||
export const AdminLayout = ({ children }) => (
|
||||
<Layout menu={AdminMenu}>
|
||||
{children}
|
||||
</Layout>
|
||||
);
|
@@ -1,9 +1,15 @@
|
||||
import { DeleteWithConfirmButton, DeleteWithConfirmButtonProps, useRecordContext } from "react-admin";
|
||||
import { isASManaged } from "./mxid";
|
||||
|
||||
export const DeviceRemoveButton = (props: DeleteWithConfirmButtonProps) => {
|
||||
const record = useRecordContext();
|
||||
if (!record) return null;
|
||||
|
||||
let isASManagedUser = false;
|
||||
if (record.user_id) {
|
||||
isASManagedUser = isASManaged(record.user_id);
|
||||
}
|
||||
|
||||
return (
|
||||
<DeleteWithConfirmButton
|
||||
{...props}
|
||||
@@ -12,6 +18,7 @@ export const DeviceRemoveButton = (props: DeleteWithConfirmButtonProps) => {
|
||||
confirmContent="resources.devices.action.erase.content"
|
||||
mutationMode="pessimistic"
|
||||
redirect={false}
|
||||
disabled={isASManagedUser}
|
||||
translateOptions={{
|
||||
id: record.id,
|
||||
name: record.display_name ? record.display_name : record.id,
|
||||
|
16
src/components/mxid.tsx
Normal file
16
src/components/mxid.tsx
Normal file
@@ -0,0 +1,16 @@
|
||||
import { Identifier } from "ra-core";
|
||||
|
||||
/**
|
||||
* Check if a user is managed by an application service
|
||||
* @param id The user ID to check
|
||||
* @returns Whether the user is managed by an application service
|
||||
*/
|
||||
export const isASManaged = (id: string | Identifier): boolean => {
|
||||
const managedUsersString = localStorage.getItem("as_managed_users") || '';
|
||||
try {
|
||||
const asManagedUsers = JSON.parse(managedUsersString).map(regex => new RegExp(regex));
|
||||
return asManagedUsers.some(regex => regex.test(id));
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
@@ -150,8 +150,9 @@ const de: SynapseTranslationMessages = {
|
||||
helper: {
|
||||
password: "Durch die Änderung des Passworts wird der Benutzer von allen Sitzungen abgemeldet.",
|
||||
deactivate: "Sie müssen ein Passwort angeben, um ein Konto wieder zu aktivieren.",
|
||||
erase: "DSGVO konformes Löschen der Benutzerdaten",
|
||||
erase_admin_error: "Das Löschen des eigenen Benutzers ist nicht erlaubt",
|
||||
erase: "DSGVO konformes Löschen der Benutzerdaten.",
|
||||
erase_admin_error: "Das Löschen des eigenen Benutzers ist nicht erlaubt.",
|
||||
modify_managed_user_error: "Das Ändern eines vom System verwalteten Benutzers ist nicht zulässig.",
|
||||
},
|
||||
action: {
|
||||
erase: "Lösche Benutzerdaten",
|
||||
|
@@ -143,6 +143,7 @@ const en: SynapseTranslationMessages = {
|
||||
deactivate: "You must provide a password to re-activate an account.",
|
||||
erase: "Mark the user as GDPR-erased",
|
||||
erase_admin_error: "Deleting own user is not allowed.",
|
||||
modify_managed_user_error: "Modifying a system-managed user is not allowed.",
|
||||
},
|
||||
action: {
|
||||
erase: "Erase user data",
|
||||
|
@@ -138,6 +138,8 @@ const fa: SynapseTranslationMessages = {
|
||||
password: "با تغییر رمز عبور کاربر از تمام دستگاه ها خارج می شود.",
|
||||
deactivate: "برای فعالسازی مجدد حساب باید رمز عبور وارد کنید.",
|
||||
erase: "کاربر را به عنوان GDPR پاک شده علامت گذاری کنید",
|
||||
erase_admin_error: "حذف المستخدم الخاص غير مسموح به.",
|
||||
modify_managed_user_error: "لا يُسمح بتغيير المستخدم الذي يديره النظام.",
|
||||
},
|
||||
action: {
|
||||
erase: "پاک کردن اطلاعات کاربر",
|
||||
|
@@ -141,6 +141,7 @@ const fr: SynapseTranslationMessages = {
|
||||
deactivate: "Vous devrez fournir un mot de passe pour réactiver le compte.",
|
||||
erase: "Marquer l'utilisateur comme effacé conformément au RGPD",
|
||||
erase_admin_error: "La suppression de son propre utilisateur n'est pas autorisée.",
|
||||
modify_managed_user_error: "La modification d'un utilisateur géré par le système n'est pas autorisée.",
|
||||
},
|
||||
action: {
|
||||
erase: "Effacer les données de l'utilisateur",
|
||||
|
1
src/i18n/index.d.ts
vendored
1
src/i18n/index.d.ts
vendored
@@ -139,6 +139,7 @@ interface SynapseTranslationMessages extends TranslationMessages {
|
||||
deactivate: string;
|
||||
erase: string;
|
||||
erase_admin_error: string;
|
||||
modify_managed_user_error: string;
|
||||
};
|
||||
action: {
|
||||
erase: string;
|
||||
|
@@ -143,6 +143,7 @@ const it: SynapseTranslationMessages = {
|
||||
action: {
|
||||
erase: "Cancella i dati dell'utente",
|
||||
erase_admin_error: "Non è consentito eliminare il proprio utente.",
|
||||
modify_managed_user_error: "La modifica di un utente gestito dal sistema non è consentita.",
|
||||
},
|
||||
},
|
||||
rooms: {
|
||||
|
@@ -160,6 +160,7 @@ const ru: SynapseTranslationMessages = {
|
||||
deactivate: "Вы должны предоставить пароль для реактивации учётной записи.",
|
||||
erase: "Пометить пользователя как удалённого в соответствии с GDPR",
|
||||
erase_admin_error: "Удаление собственного пользователя запрещено.",
|
||||
modify_managed_user_error: "Изменение пользователя, управляемого системой, не допускается.",
|
||||
},
|
||||
action: {
|
||||
erase: "Удалить данные пользователя",
|
||||
|
@@ -144,6 +144,7 @@ const zh: SynapseTranslationMessages = {
|
||||
deactivate: "您必须提供一串密码来激活账户。",
|
||||
erase: "将用户标记为根据 GDPR 的要求抹除了",
|
||||
erase_admin_error: "不允许删除自己的用户",
|
||||
modify_managed_user_error: "不允许修改系统管理的用户。",
|
||||
},
|
||||
action: {
|
||||
erase: "抹除用户信息",
|
||||
|
@@ -4,15 +4,18 @@ import { createRoot } from "react-dom/client";
|
||||
|
||||
import App from "./App";
|
||||
import { AppContext } from "./AppContext";
|
||||
import storage from "./storage";
|
||||
|
||||
fetch("config.json")
|
||||
.then(res => res.json())
|
||||
.then(props =>
|
||||
createRoot(document.getElementById("root")).render(
|
||||
.then(props => {
|
||||
storage.setItem("as_managed_users", JSON.stringify(props.asManagedUsers));
|
||||
storage.setItem("support_url", props.supportURL);
|
||||
return createRoot(document.getElementById("root")).render(
|
||||
<React.StrictMode>
|
||||
<AppContext.Provider value={props}>
|
||||
<App />
|
||||
</AppContext.Provider>
|
||||
</React.StrictMode>
|
||||
)
|
||||
);
|
||||
});
|
||||
|
@@ -61,6 +61,7 @@ import {
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
import AvatarField from "../components/AvatarField";
|
||||
import { isASManaged } from "../components/mxid";
|
||||
import { ServerNoticeButton, ServerNoticeBulkButton } from "../components/ServerNotices";
|
||||
import { DATE_FORMAT } from "../components/date";
|
||||
import { DeviceRemoveButton } from "../components/devices";
|
||||
@@ -103,8 +104,9 @@ const userFilters = [
|
||||
<BooleanInput label="resources.users.fields.show_locked" source="locked" alwaysOn />,
|
||||
];
|
||||
|
||||
const UserPreventSelfDelete: React.FC<{ children: React.ReactNode; ownUserIsSelected: boolean }> = props => {
|
||||
const UserPreventSelfDelete: React.FC<{ children: React.ReactNode; ownUserIsSelected: boolean; asManagedUserIsSelected: boolean }> = props => {
|
||||
const ownUserIsSelected = props.ownUserIsSelected;
|
||||
const asManagedUserIsSelected = props.asManagedUserIsSelected;
|
||||
const notify = useNotify();
|
||||
const translate = useTranslate();
|
||||
|
||||
@@ -112,6 +114,9 @@ const UserPreventSelfDelete: React.FC<{ children: React.ReactNode; ownUserIsSele
|
||||
if (ownUserIsSelected) {
|
||||
notify(<Alert severity="error">{translate("resources.users.helper.erase_admin_error")}</Alert>);
|
||||
ev.stopPropagation();
|
||||
} else if (asManagedUserIsSelected) {
|
||||
notify(<Alert severity="error">{translate("resources.users.helper.modify_managed_user_error")}</Alert>);
|
||||
ev.stopPropagation();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -121,6 +126,7 @@ const UserPreventSelfDelete: React.FC<{ children: React.ReactNode; ownUserIsSele
|
||||
const UserBulkActionButtons = () => {
|
||||
const record = useListContext();
|
||||
const [ownUserIsSelected, setOwnUserIsSelected] = useState(false);
|
||||
const [asManagedUserIsSelected, setAsManagedUserIsSelected] = useState(false);
|
||||
const selectedIds = record.selectedIds;
|
||||
const ownUserId = localStorage.getItem("user_id");
|
||||
const notify = useNotify();
|
||||
@@ -128,12 +134,13 @@ const UserBulkActionButtons = () => {
|
||||
|
||||
useEffect(() => {
|
||||
setOwnUserIsSelected(selectedIds.includes(ownUserId));
|
||||
setAsManagedUserIsSelected(selectedIds.some(id => isASManaged(id)));
|
||||
}, [selectedIds]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ServerNoticeBulkButton />
|
||||
<UserPreventSelfDelete ownUserIsSelected={ownUserIsSelected}>
|
||||
<UserPreventSelfDelete ownUserIsSelected={ownUserIsSelected} asManagedUserIsSelected={asManagedUserIsSelected}>
|
||||
<BulkDeleteButton
|
||||
label="resources.users.action.erase"
|
||||
confirmTitle="resources.users.helper.erase"
|
||||
@@ -184,14 +191,16 @@ const UserEditActions = () => {
|
||||
const translate = useTranslate();
|
||||
const ownUserId = localStorage.getItem("user_id");
|
||||
let ownUserIsSelected = false;
|
||||
let asManagedUserIsSelected = false;
|
||||
if (record && record.id) {
|
||||
ownUserIsSelected = record.id === ownUserId;
|
||||
asManagedUserIsSelected = isASManaged(record.id);
|
||||
}
|
||||
|
||||
return (
|
||||
<TopToolbar>
|
||||
{!record?.deactivated && <ServerNoticeButton />}
|
||||
<UserPreventSelfDelete ownUserIsSelected={ownUserIsSelected}>
|
||||
<UserPreventSelfDelete ownUserIsSelected={ownUserIsSelected} asManagedUserIsSelected={asManagedUserIsSelected}>
|
||||
<DeleteButton
|
||||
label="resources.users.action.erase"
|
||||
confirmTitle={translate("resources.users.helper.erase", {
|
||||
@@ -235,13 +244,21 @@ export const UserCreate = (props: CreateProps) => (
|
||||
|
||||
const UserTitle = () => {
|
||||
const record = useRecordContext();
|
||||
if (!record) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const translate = useTranslate();
|
||||
let username = record ? (record.displayname ? `"${record.displayname}"` : `"${record.name}"`) : ""
|
||||
if (isASManaged(record?.id)) {
|
||||
username += " 🤖";
|
||||
}
|
||||
return (
|
||||
<span>
|
||||
{translate("resources.users.name", {
|
||||
smart_count: 1,
|
||||
})}{" "}
|
||||
{record ? (record.displayname ? `"${record.displayname}"` : `"${record.name}"`) : ""}
|
||||
{username}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
@@ -250,8 +267,10 @@ const UserEditToolbar = () => {
|
||||
const record = useRecordContext();
|
||||
const ownUserId = localStorage.getItem("user_id");
|
||||
let ownUserIsSelected = false;
|
||||
let asManagedUserIsSelected = false;
|
||||
if (record && record.id) {
|
||||
ownUserIsSelected = record.id === ownUserId;
|
||||
asManagedUserIsSelected = isASManaged(record.id);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -259,7 +278,7 @@ const UserEditToolbar = () => {
|
||||
<div className={ToolbarClasses.defaultToolbar}>
|
||||
<Toolbar sx={{ justifyContent: "space-between" }}>
|
||||
<SaveButton />
|
||||
<UserPreventSelfDelete ownUserIsSelected={ownUserIsSelected}>
|
||||
<UserPreventSelfDelete ownUserIsSelected={ownUserIsSelected} asManagedUserIsSelected={asManagedUserIsSelected}>
|
||||
<DeleteButton />
|
||||
</UserPreventSelfDelete>
|
||||
</Toolbar>
|
||||
@@ -272,17 +291,31 @@ const UserBooleanInput = props => {
|
||||
const record = useRecordContext();
|
||||
const ownUserId = localStorage.getItem("user_id");
|
||||
let ownUserIsSelected = false;
|
||||
if (record && record.id === ownUserId) {
|
||||
ownUserIsSelected = true;
|
||||
let asManagedUserIsSelected = false;
|
||||
if (record) {
|
||||
ownUserIsSelected = record.id === ownUserId;
|
||||
asManagedUserIsSelected = isASManaged(record.id);
|
||||
}
|
||||
|
||||
return (
|
||||
<UserPreventSelfDelete ownUserIsSelected={ownUserIsSelected}>
|
||||
<BooleanInput {...props} disabled={ownUserIsSelected} />
|
||||
<UserPreventSelfDelete ownUserIsSelected={ownUserIsSelected} asManagedUserIsSelected={asManagedUserIsSelected}>
|
||||
<BooleanInput {...props} disabled={ownUserIsSelected || asManagedUserIsSelected} />
|
||||
</UserPreventSelfDelete>
|
||||
);
|
||||
};
|
||||
|
||||
const UserPasswordInput = props => {
|
||||
const record = useRecordContext();
|
||||
let asManagedUserIsSelected = false;
|
||||
if (record) {
|
||||
asManagedUserIsSelected = isASManaged(record.id);
|
||||
}
|
||||
|
||||
return (
|
||||
<PasswordInput {...props} helperText="resources.users.helper.modify_managed_user_error" disabled={asManagedUserIsSelected} />
|
||||
);
|
||||
};
|
||||
|
||||
export const UserEdit = (props: EditProps) => {
|
||||
const translate = useTranslate();
|
||||
|
||||
@@ -301,10 +334,10 @@ export const UserEdit = (props: EditProps) => {
|
||||
</ImageInput>
|
||||
<TextInput source="id" readOnly />
|
||||
<TextInput source="displayname" />
|
||||
<PasswordInput source="password" autoComplete="new-password" helperText="resources.users.helper.password" />
|
||||
<UserPasswordInput source="password" autoComplete="new-password" helperText="resources.users.helper.password" />
|
||||
<SelectInput source="user_type" choices={choices_type} translateChoice={false} resettable />
|
||||
<BooleanInput source="admin" />
|
||||
<BooleanInput source="locked" />
|
||||
<UserBooleanInput source="locked" />
|
||||
<UserBooleanInput source="deactivated" helperText="resources.users.helper.deactivate" />
|
||||
<BooleanInput source="erased" disabled />
|
||||
<DateField source="creation_ts_ms" showTime options={DATE_FORMAT} />
|
||||
@@ -331,7 +364,7 @@ export const UserEdit = (props: EditProps) => {
|
||||
|
||||
<FormTab label={translate("resources.devices.name", { smart_count: 2 })} icon={<DevicesIcon />} path="devices">
|
||||
<ReferenceManyField reference="devices" target="user_id" label={false}>
|
||||
<Datagrid style={{ width: "100%" }}>
|
||||
<Datagrid style={{ width: "100%" }} bulkActionButtons={false}>
|
||||
<TextField source="device_id" sortable={false} />
|
||||
<TextField source="display_name" sortable={false} />
|
||||
<TextField source="last_seen_ip" sortable={false} />
|
||||
|
166
yarn.lock
166
yarn.lock
@@ -1058,85 +1058,85 @@
|
||||
resolved "https://registry.npmjs.org/@remix-run/router/-/router-1.19.2.tgz"
|
||||
integrity sha512-baiMx18+IMuD1yyvOGaHM9QrVUPGGG0jC+z+IPHnRJWUAUvaKuWKyE8gjDj2rzv3sz9zOGoRSPgeBVHRhZnBlA==
|
||||
|
||||
"@rollup/rollup-android-arm-eabi@4.22.0":
|
||||
version "4.22.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.0.tgz#e8c16c336f060b4cb592f62eb4f0e543d79d51fe"
|
||||
integrity sha512-/IZQvg6ZR0tAkEi4tdXOraQoWeJy9gbQ/cx4I7k9dJaCk9qrXEcdouxRVz5kZXt5C2bQ9pILoAA+KB4C/d3pfw==
|
||||
"@rollup/rollup-android-arm-eabi@4.22.4":
|
||||
version "4.22.4"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.4.tgz#8b613b9725e8f9479d142970b106b6ae878610d5"
|
||||
integrity sha512-Fxamp4aEZnfPOcGA8KSNEohV8hX7zVHOemC8jVBoBUHu5zpJK/Eu3uJwt6BMgy9fkvzxDaurgj96F/NiLukF2w==
|
||||
|
||||
"@rollup/rollup-android-arm64@4.22.0":
|
||||
version "4.22.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.0.tgz#7a44160a14017fa744912d7037c7d81d6f8a46e7"
|
||||
integrity sha512-ETHi4bxrYnvOtXeM7d4V4kZWixib2jddFacJjsOjwbgYSRsyXYtZHC4ht134OsslPIcnkqT+TKV4eU8rNBKyyQ==
|
||||
"@rollup/rollup-android-arm64@4.22.4":
|
||||
version "4.22.4"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.4.tgz#654ca1049189132ff602bfcf8df14c18da1f15fb"
|
||||
integrity sha512-VXoK5UMrgECLYaMuGuVTOx5kcuap1Jm8g/M83RnCHBKOqvPPmROFJGQaZhGccnsFtfXQ3XYa4/jMCJvZnbJBdA==
|
||||
|
||||
"@rollup/rollup-darwin-arm64@4.22.0":
|
||||
version "4.22.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.0.tgz#6122dc37d4a09521d8abe18925956d3b46cfbac9"
|
||||
integrity sha512-ZWgARzhSKE+gVUX7QWaECoRQsPwaD8ZR0Oxb3aUpzdErTvlEadfQpORPXkKSdKbFci9v8MJfkTtoEHnnW9Ulng==
|
||||
"@rollup/rollup-darwin-arm64@4.22.4":
|
||||
version "4.22.4"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.4.tgz#6d241d099d1518ef0c2205d96b3fa52e0fe1954b"
|
||||
integrity sha512-xMM9ORBqu81jyMKCDP+SZDhnX2QEVQzTcC6G18KlTQEzWK8r/oNZtKuZaCcHhnsa6fEeOBionoyl5JsAbE/36Q==
|
||||
|
||||
"@rollup/rollup-darwin-x64@4.22.0":
|
||||
version "4.22.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.0.tgz#453f345899cbf544aa0d6f5808d24d2e42f605b7"
|
||||
integrity sha512-h0ZAtOfHyio8Az6cwIGS+nHUfRMWBDO5jXB8PQCARVF6Na/G6XS2SFxDl8Oem+S5ZsHQgtsI7RT4JQnI1qrlaw==
|
||||
"@rollup/rollup-darwin-x64@4.22.4":
|
||||
version "4.22.4"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.4.tgz#42bd19d292a57ee11734c980c4650de26b457791"
|
||||
integrity sha512-aJJyYKQwbHuhTUrjWjxEvGnNNBCnmpHDvrb8JFDbeSH3m2XdHcxDd3jthAzvmoI8w/kSjd2y0udT+4okADsZIw==
|
||||
|
||||
"@rollup/rollup-linux-arm-gnueabihf@4.22.0":
|
||||
version "4.22.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.0.tgz#3a32fa4e80a62a6d733014838b1123fe76b060fe"
|
||||
integrity sha512-9pxQJSPwFsVi0ttOmqLY4JJ9pg9t1gKhK0JDbV1yUEETSx55fdyCjt39eBQ54OQCzAF0nVGO6LfEH1KnCPvelA==
|
||||
"@rollup/rollup-linux-arm-gnueabihf@4.22.4":
|
||||
version "4.22.4"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.4.tgz#f23555ee3d8fe941c5c5fd458cd22b65eb1c2232"
|
||||
integrity sha512-j63YtCIRAzbO+gC2L9dWXRh5BFetsv0j0va0Wi9epXDgU/XUi5dJKo4USTttVyK7fGw2nPWK0PbAvyliz50SCQ==
|
||||
|
||||
"@rollup/rollup-linux-arm-musleabihf@4.22.0":
|
||||
version "4.22.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.0.tgz#55d3953c54419e93efe124882a3103c8a2f65641"
|
||||
integrity sha512-YJ5Ku5BmNJZb58A4qSEo3JlIG4d3G2lWyBi13ABlXzO41SsdnUKi3HQHe83VpwBVG4jHFTW65jOQb8qyoR+qzg==
|
||||
"@rollup/rollup-linux-arm-musleabihf@4.22.4":
|
||||
version "4.22.4"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.4.tgz#f3bbd1ae2420f5539d40ac1fde2b38da67779baa"
|
||||
integrity sha512-dJnWUgwWBX1YBRsuKKMOlXCzh2Wu1mlHzv20TpqEsfdZLb3WoJW2kIEsGwLkroYf24IrPAvOT/ZQ2OYMV6vlrg==
|
||||
|
||||
"@rollup/rollup-linux-arm64-gnu@4.22.0":
|
||||
version "4.22.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.0.tgz#cd626963b9962baf8e09d792e67b87269a5bcfff"
|
||||
integrity sha512-U4G4u7f+QCqHlVg1Nlx+qapZy+QoG+NV6ux+upo/T7arNGwKvKP2kmGM4W5QTbdewWFgudQxi3kDNST9GT1/mg==
|
||||
"@rollup/rollup-linux-arm64-gnu@4.22.4":
|
||||
version "4.22.4"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.4.tgz#7abe900120113e08a1f90afb84c7c28774054d15"
|
||||
integrity sha512-AdPRoNi3NKVLolCN/Sp4F4N1d98c4SBnHMKoLuiG6RXgoZ4sllseuGioszumnPGmPM2O7qaAX/IJdeDU8f26Aw==
|
||||
|
||||
"@rollup/rollup-linux-arm64-musl@4.22.0":
|
||||
version "4.22.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.0.tgz#ad209270c9937a27346fce5b0670cbdfb1e6a0a6"
|
||||
integrity sha512-aQpNlKmx3amwkA3a5J6nlXSahE1ijl0L9KuIjVOUhfOh7uw2S4piR3mtpxpRtbnK809SBtyPsM9q15CPTsY7HQ==
|
||||
"@rollup/rollup-linux-arm64-musl@4.22.4":
|
||||
version "4.22.4"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.4.tgz#9e655285c8175cd44f57d6a1e8e5dedfbba1d820"
|
||||
integrity sha512-Gl0AxBtDg8uoAn5CCqQDMqAx22Wx22pjDOjBdmG0VIWX3qUBHzYmOKh8KXHL4UpogfJ14G4wk16EQogF+v8hmA==
|
||||
|
||||
"@rollup/rollup-linux-powerpc64le-gnu@4.22.0":
|
||||
version "4.22.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.0.tgz#fdd173929a5bba8b7e8b37314380213d9604088f"
|
||||
integrity sha512-9fx6Zj/7vve/Fp4iexUFRKb5+RjLCff6YTRQl4CoDhdMfDoobWmhAxQWV3NfShMzQk1Q/iCnageFyGfqnsmeqQ==
|
||||
"@rollup/rollup-linux-powerpc64le-gnu@4.22.4":
|
||||
version "4.22.4"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.4.tgz#9a79ae6c9e9d8fe83d49e2712ecf4302db5bef5e"
|
||||
integrity sha512-3aVCK9xfWW1oGQpTsYJJPF6bfpWfhbRnhdlyhak2ZiyFLDaayz0EP5j9V1RVLAAxlmWKTDfS9wyRyY3hvhPoOg==
|
||||
|
||||
"@rollup/rollup-linux-riscv64-gnu@4.22.0":
|
||||
version "4.22.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.0.tgz#90b11314fbf45d04083f658e08dc3b32fd713061"
|
||||
integrity sha512-VWQiCcN7zBgZYLjndIEh5tamtnKg5TGxyZPWcN9zBtXBwfcGSZ5cHSdQZfQH/GB4uRxk0D3VYbOEe/chJhPGLQ==
|
||||
"@rollup/rollup-linux-riscv64-gnu@4.22.4":
|
||||
version "4.22.4"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.4.tgz#67ac70eca4ace8e2942fabca95164e8874ab8128"
|
||||
integrity sha512-ePYIir6VYnhgv2C5Xe9u+ico4t8sZWXschR6fMgoPUK31yQu7hTEJb7bCqivHECwIClJfKgE7zYsh1qTP3WHUA==
|
||||
|
||||
"@rollup/rollup-linux-s390x-gnu@4.22.0":
|
||||
version "4.22.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.0.tgz#46bb2f1135aeec646b720d6032d7c86915f8b2ec"
|
||||
integrity sha512-EHmPnPWvyYqncObwqrosb/CpH3GOjE76vWVs0g4hWsDRUVhg61hBmlVg5TPXqF+g+PvIbqkC7i3h8wbn4Gp2Fg==
|
||||
"@rollup/rollup-linux-s390x-gnu@4.22.4":
|
||||
version "4.22.4"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.4.tgz#9f883a7440f51a22ed7f99e1d070bd84ea5005fc"
|
||||
integrity sha512-GqFJ9wLlbB9daxhVlrTe61vJtEY99/xB3C8e4ULVsVfflcpmR6c8UZXjtkMA6FhNONhj2eA5Tk9uAVw5orEs4Q==
|
||||
|
||||
"@rollup/rollup-linux-x64-gnu@4.22.0":
|
||||
version "4.22.0"
|
||||
resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.0.tgz"
|
||||
integrity sha512-tsSWy3YQzmpjDKnQ1Vcpy3p9Z+kMFbSIesCdMNgLizDWFhrLZIoN21JSq01g+MZMDFF+Y1+4zxgrlqPjid5ohg==
|
||||
"@rollup/rollup-linux-x64-gnu@4.22.4":
|
||||
version "4.22.4"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.4.tgz#70116ae6c577fe367f58559e2cffb5641a1dd9d0"
|
||||
integrity sha512-87v0ol2sH9GE3cLQLNEy0K/R0pz1nvg76o8M5nhMR0+Q+BBGLnb35P0fVz4CQxHYXaAOhE8HhlkaZfsdUOlHwg==
|
||||
|
||||
"@rollup/rollup-linux-x64-musl@4.22.0":
|
||||
version "4.22.0"
|
||||
resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.0.tgz"
|
||||
integrity sha512-anr1Y11uPOQrpuU8XOikY5lH4Qu94oS6j0xrulHk3NkLDq19MlX8Ng/pVipjxBJ9a2l3+F39REZYyWQFkZ4/fw==
|
||||
"@rollup/rollup-linux-x64-musl@4.22.4":
|
||||
version "4.22.4"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.4.tgz#f473f88219feb07b0b98b53a7923be716d1d182f"
|
||||
integrity sha512-UV6FZMUgePDZrFjrNGIWzDo/vABebuXBhJEqrHxrGiU6HikPy0Z3LfdtciIttEUQfuDdCn8fqh7wiFJjCNwO+g==
|
||||
|
||||
"@rollup/rollup-win32-arm64-msvc@4.22.0":
|
||||
version "4.22.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.0.tgz#6bd66c198f80c8e7050cfd901701cfb9555d768a"
|
||||
integrity sha512-7LB+Bh+Ut7cfmO0m244/asvtIGQr5pG5Rvjz/l1Rnz1kDzM02pSX9jPaS0p+90H5I1x4d1FkCew+B7MOnoatNw==
|
||||
"@rollup/rollup-win32-arm64-msvc@4.22.4":
|
||||
version "4.22.4"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.4.tgz#4349482d17f5d1c58604d1c8900540d676f420e0"
|
||||
integrity sha512-BjI+NVVEGAXjGWYHz/vv0pBqfGoUH0IGZ0cICTn7kB9PyjrATSkX+8WkguNjWoj2qSr1im/+tTGRaY+4/PdcQw==
|
||||
|
||||
"@rollup/rollup-win32-ia32-msvc@4.22.0":
|
||||
version "4.22.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.0.tgz#58daea1f1e65143c44c8f3311f30ff8eefa62bae"
|
||||
integrity sha512-+3qZ4rer7t/QsC5JwMpcvCVPRcJt1cJrYS/TMJZzXIJbxWFQEVhrIc26IhB+5Z9fT9umfVc+Es2mOZgl+7jdJQ==
|
||||
"@rollup/rollup-win32-ia32-msvc@4.22.4":
|
||||
version "4.22.4"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.4.tgz#a6fc39a15db618040ec3c2a24c1e26cb5f4d7422"
|
||||
integrity sha512-SiWG/1TuUdPvYmzmYnmd3IEifzR61Tragkbx9D3+R8mzQqDBz8v+BvZNDlkiTtI9T15KYZhP0ehn3Dld4n9J5g==
|
||||
|
||||
"@rollup/rollup-win32-x64-msvc@4.22.0":
|
||||
version "4.22.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.0.tgz#956948629f6b87de0bdf526b28d940221540bbb6"
|
||||
integrity sha512-YdicNOSJONVx/vuPkgPTyRoAPx3GbknBZRCOUkK84FJ/YTfs/F0vl/YsMscrB6Y177d+yDRcj+JWMPMCgshwrA==
|
||||
"@rollup/rollup-win32-x64-msvc@4.22.4":
|
||||
version "4.22.4"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.4.tgz#3dd5d53e900df2a40841882c02e56f866c04d202"
|
||||
integrity sha512-j8pPKp53/lq9lMXN57S8cFz0MynJk8OWNuUnXct/9KCpKU7DgU3bYMJhwWmcqC0UU29p8Lr0/7KEVcaM6bf47Q==
|
||||
|
||||
"@rtsao/scc@^1.1.0":
|
||||
version "1.1.0"
|
||||
@@ -4992,28 +4992,28 @@ rimraf@3.0.2, rimraf@^3.0.2:
|
||||
glob "^7.1.3"
|
||||
|
||||
rollup@^4.20.0:
|
||||
version "4.22.0"
|
||||
resolved "https://registry.npmjs.org/rollup/-/rollup-4.22.0.tgz"
|
||||
integrity sha512-W21MUIFPZ4+O2Je/EU+GP3iz7PH4pVPUXSbEZdatQnxo29+3rsUjgrJmzuAZU24z7yRAnFN6ukxeAhZh/c7hzg==
|
||||
version "4.22.4"
|
||||
resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.22.4.tgz#4135a6446671cd2a2453e1ad42a45d5973ec3a0f"
|
||||
integrity sha512-vD8HJ5raRcWOyymsR6Z3o6+RzfEPCnVLMFJ6vRslO1jt4LO6dUo5Qnpg7y4RkZFM2DMe3WUirkI5c16onjrc6A==
|
||||
dependencies:
|
||||
"@types/estree" "1.0.5"
|
||||
optionalDependencies:
|
||||
"@rollup/rollup-android-arm-eabi" "4.22.0"
|
||||
"@rollup/rollup-android-arm64" "4.22.0"
|
||||
"@rollup/rollup-darwin-arm64" "4.22.0"
|
||||
"@rollup/rollup-darwin-x64" "4.22.0"
|
||||
"@rollup/rollup-linux-arm-gnueabihf" "4.22.0"
|
||||
"@rollup/rollup-linux-arm-musleabihf" "4.22.0"
|
||||
"@rollup/rollup-linux-arm64-gnu" "4.22.0"
|
||||
"@rollup/rollup-linux-arm64-musl" "4.22.0"
|
||||
"@rollup/rollup-linux-powerpc64le-gnu" "4.22.0"
|
||||
"@rollup/rollup-linux-riscv64-gnu" "4.22.0"
|
||||
"@rollup/rollup-linux-s390x-gnu" "4.22.0"
|
||||
"@rollup/rollup-linux-x64-gnu" "4.22.0"
|
||||
"@rollup/rollup-linux-x64-musl" "4.22.0"
|
||||
"@rollup/rollup-win32-arm64-msvc" "4.22.0"
|
||||
"@rollup/rollup-win32-ia32-msvc" "4.22.0"
|
||||
"@rollup/rollup-win32-x64-msvc" "4.22.0"
|
||||
"@rollup/rollup-android-arm-eabi" "4.22.4"
|
||||
"@rollup/rollup-android-arm64" "4.22.4"
|
||||
"@rollup/rollup-darwin-arm64" "4.22.4"
|
||||
"@rollup/rollup-darwin-x64" "4.22.4"
|
||||
"@rollup/rollup-linux-arm-gnueabihf" "4.22.4"
|
||||
"@rollup/rollup-linux-arm-musleabihf" "4.22.4"
|
||||
"@rollup/rollup-linux-arm64-gnu" "4.22.4"
|
||||
"@rollup/rollup-linux-arm64-musl" "4.22.4"
|
||||
"@rollup/rollup-linux-powerpc64le-gnu" "4.22.4"
|
||||
"@rollup/rollup-linux-riscv64-gnu" "4.22.4"
|
||||
"@rollup/rollup-linux-s390x-gnu" "4.22.4"
|
||||
"@rollup/rollup-linux-x64-gnu" "4.22.4"
|
||||
"@rollup/rollup-linux-x64-musl" "4.22.4"
|
||||
"@rollup/rollup-win32-arm64-msvc" "4.22.4"
|
||||
"@rollup/rollup-win32-ia32-msvc" "4.22.4"
|
||||
"@rollup/rollup-win32-x64-msvc" "4.22.4"
|
||||
fsevents "~2.3.2"
|
||||
|
||||
run-parallel@^1.1.9:
|
||||
|
Reference in New Issue
Block a user