18 Commits
0.6.0 ... 0.7.2

Author SHA1 Message Date
Dirk Klimpel
c6b6e54617 Fix broken redirect to login page (#116) 2021-03-16 12:13:32 +01:00
Michael Albert
8ff0ac913c Add missing translations
Change-Id: Ie46554bcd10dde771c03e7d3fd0c3639f904429d
2021-03-16 12:12:54 +01:00
dependabot[bot]
96d2c96740 Bump elliptic from 6.5.3 to 6.5.4 (#122)
Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.3 to 6.5.4.
- [Release notes](https://github.com/indutny/elliptic/releases)
- [Commits](https://github.com/indutny/elliptic/compare/v6.5.3...v6.5.4)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-11 13:29:43 +01:00
Aaron Raimist
8adab0e927 Name device used by Synapse Admin and hook up logout button (#113)
* Name device used by Synapse Admin

* Actually logout when the logout button is pressed so that old sessions get deleted

* Fix lint
2021-03-02 11:45:05 +01:00
Dirk Klimpel
536ffc2fbf Disable telemetry which was introduced with react-admin v3.11.0 (#109) 2021-03-01 09:26:58 +01:00
Michael Albert
684c44e470 Bump version to 0.7.0
Change-Id: I5b854ae8720c12e0895c2c614f4c02f1257c0d09
2021-02-11 21:26:23 +01:00
Dirk Klimpel
7f92e1a3c0 Add new list with information about users' media (#89) 2021-02-11 21:14:02 +01:00
Dirk Klimpel
ea59d0dd02 Add a new tab to user page with media (#87)
* Add a new tab to user page with media
2021-02-11 21:11:34 +01:00
Dirk Klimpel
706114a382 Add a new tab to user page with room memberships (#73)
The admin API for user's room memberships is new in synapse v1.21.0.

Co-authored-by: Michael Albert <37796947+awesome-michael@users.noreply.github.com>
2021-02-11 20:45:02 +01:00
Dirk Klimpel
f2a1275673 Add a new tab to user page with pushers (#85)
* Add a new tab to user page with pushers

* Update pushers `total` and `id`
2021-02-11 20:37:20 +01:00
Dirk Klimpel
425c210cfc Add delete button to room detail page (#97)
* Add delete button to room detail page

* Add confirmation dialog for room deletion
2021-02-11 20:24:17 +01:00
Dirk Klimpel
b184954ffa Update total in dataProvider (#101) 2021-02-11 20:20:42 +01:00
Dirk Klimpel
2f96951c19 Add view of reported events (#84) 2021-01-04 09:14:33 +01:00
dependabot[bot]
1706cd3c9d Bump ini from 1.3.5 to 1.3.7
Bumps [ini](https://github.com/isaacs/ini) from 1.3.5 to 1.3.7.
- [Release notes](https://github.com/isaacs/ini/releases)
- [Commits](https://github.com/isaacs/ini/compare/v1.3.5...v1.3.7)

Signed-off-by: dependabot[bot] <support@github.com>
2020-12-14 13:13:16 +01:00
Dirk Klimpel
eadc04a6a0 Update helper text for activate an user (#95) 2020-12-14 13:12:13 +01:00
Manuel Stahl
1432724a64 yarn: Upgrade packages
- react-admin: 3.10.0
 - react-dom: 16.14.0
 - react-scripts: 3.4.4

Change-Id: I805bcd2f65419747f7e8c5a3e2c6b9896010ca9e
2020-11-16 13:31:39 +01:00
Manuel Stahl
c841720f0c Fix style
Change-Id: I345a942905f15edfa21f51de228efd7671f080c7
2020-11-16 10:55:00 +01:00
Dirk Klimpel
60ecafdf54 Bugfix translation in users' device tab (#86) 2020-11-16 10:54:43 +01:00
12 changed files with 1647 additions and 1076 deletions

View File

@@ -4,15 +4,15 @@
This project is built using [react-admin](https://marmelab.com/react-admin/).
It needs at least Synapse v1.18.0 for all functions to work as expected!
It needs at least Synapse v1.23.0 for all functions to work as expected!
You get your server version with the request `/_synapse/admin/v1/server_version`.
See also [Synapse version API](https://github.com/matrix-org/synapse/blob/develop/docs/admin_api/version_api.rst).
After entering the URL on the login page of synapse-admin the server version appears below the input field.
You need access to the following endpoints:
- `/_matrix`
- `/_synapse/admin`

View File

@@ -1,6 +1,6 @@
{
"name": "synapse-admin",
"version": "0.2.1",
"version": "0.7.0",
"description": "Admin GUI for the Matrix.org server Synapse",
"author": "Awesome Technologies Innovationslabor GmbH",
"license": "Apache-2.0",
@@ -22,13 +22,13 @@
"prettier": "^2.0.0"
},
"dependencies": {
"papaparse": "^5.2.0",
"prop-types": "^15.7.2",
"ra-language-german": "^2.1.2",
"papaparse": "^5.2.0",
"react": "^16.13.1",
"react-admin": "^3.7.0",
"react-dom": "^16.13.1",
"react-scripts": "^3.4.1"
"react-admin": "^3.10.0",
"react-dom": "^16.14.0",
"react-scripts": "^3.4.4"
},
"scripts": {
"start": "REACT_APP_VERSION=$(git describe --tags) react-scripts start",

View File

@@ -5,9 +5,13 @@ import authProvider from "./synapse/authProvider";
import dataProvider from "./synapse/dataProvider";
import { UserList, UserCreate, UserEdit } from "./components/users";
import { RoomList, RoomShow } from "./components/rooms";
import { ReportList, ReportShow } from "./components/EventReports";
import LoginPage from "./components/LoginPage";
import UserIcon from "@material-ui/icons/Group";
import { ViewListIcon as RoomIcon } from "@material-ui/icons/ViewList";
import EqualizerIcon from "@material-ui/icons/Equalizer";
import { UserMediaStatsList } from "./components/statistics";
import RoomIcon from "@material-ui/icons/ViewList";
import ReportIcon from "@material-ui/icons/Warning";
import { ImportFeature } from "./components/ImportFeature";
import { Route } from "react-router-dom";
import germanMessages from "./i18n/de";
@@ -25,6 +29,7 @@ const i18nProvider = polyglotI18nProvider(
const App = () => (
<Admin
disableTelemetry
loginPage={LoginPage}
authProvider={authProvider}
dataProvider={dataProvider}
@@ -41,9 +46,23 @@ const App = () => (
icon={UserIcon}
/>
<Resource name="rooms" list={RoomList} show={RoomShow} icon={RoomIcon} />
<Resource
name="user_media_statistics"
list={UserMediaStatsList}
icon={EqualizerIcon}
/>
<Resource
name="reports"
list={ReportList}
show={ReportShow}
icon={ReportIcon}
/>
<Resource name="connections" />
<Resource name="devices" />
<Resource name="room_members" />
<Resource name="users_media" />
<Resource name="joined_rooms" />
<Resource name="pushers" />
<Resource name="servernotices" />
</Admin>
);

View File

@@ -0,0 +1,135 @@
import React from "react";
import {
Datagrid,
DateField,
List,
NumberField,
Pagination,
ReferenceField,
Show,
Tab,
TabbedShowLayout,
TextField,
useTranslate,
} from "react-admin";
import PageviewIcon from "@material-ui/icons/Pageview";
import ViewListIcon from "@material-ui/icons/ViewList";
const ReportPagination = props => (
<Pagination {...props} rowsPerPageOptions={[10, 25, 50, 100, 500, 1000]} />
);
export const ReportShow = props => {
const translate = useTranslate();
return (
<Show {...props}>
<TabbedShowLayout>
<Tab
label={translate("synapseadmin.reports.tabs.basic", {
smart_count: 1,
})}
icon={<ViewListIcon />}
>
<DateField
source="received_ts"
showTime
options={{
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
}}
sortable={true}
/>
<ReferenceField source="user_id" reference="users">
<TextField source="id" />
</ReferenceField>
<NumberField source="score" />
<TextField source="reason" />
<TextField source="name" />
<TextField
source="canonical_alias"
label="resources.rooms.fields.canonical_alias"
/>
<ReferenceField
source="room_id"
reference="rooms"
link="show"
label="resources.rooms.fields.room_id"
>
<TextField source="id" />
</ReferenceField>
</Tab>
<Tab
label="synapseadmin.reports.tabs.detail"
icon={<PageviewIcon />}
path="detail"
>
{" "}
<DateField
source="event_json.origin_server_ts"
showTime
options={{
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
}}
sortable={true}
/>
<ReferenceField source="sender" reference="users">
<TextField source="id" />
</ReferenceField>
<TextField source="event_id" />
<TextField source="event_json.origin" />
<TextField source="event_json.type" />
<TextField source="event_json.content.msgtype" />
<TextField source="event_json.content.body" />
<TextField source="event_json.content.format" />
<TextField source="event_json.content.formatted_body" />
<TextField source="event_json.content.algorithm" />
<TextField
source="event_json.content.device_id"
label="resources.users.fields.device_id"
/>
</Tab>
</TabbedShowLayout>
</Show>
);
};
export const ReportList = ({ ...props }) => {
return (
<List
{...props}
pagination={<ReportPagination />}
sort={{ field: "received_ts", order: "DESC" }}
bulkActionButtons={false}
>
<Datagrid rowClick="show">
<TextField source="id" sortable={false} />
<DateField
source="received_ts"
showTime
options={{
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
}}
sortable={true}
/>
<TextField sortable={false} source="user_id" />
<TextField sortable={false} source="name" />
<TextField sortable={false} source="score" />
</Datagrid>
</List>
);
};

View File

@@ -4,6 +4,7 @@ import {
BooleanField,
BulkDeleteWithConfirmButton,
Datagrid,
DeleteButton,
Filter,
List,
Pagination,
@@ -15,6 +16,7 @@ import {
Tab,
TabbedShowLayout,
TextField,
TopToolbar,
useTranslate,
} from "react-admin";
import get from "lodash/get";
@@ -70,10 +72,26 @@ const RoomTitle = ({ record }) => {
);
};
const RoomShowActions = ({ basePath, data, resource }) => {
const translate = useTranslate();
return (
<TopToolbar>
<DeleteButton
basePath={basePath}
record={data}
resource={resource}
undoable={false}
confirmTitle={translate("synapseadmin.rooms.delete.title")}
confirmContent={translate("synapseadmin.rooms.delete.message")}
/>
</TopToolbar>
);
};
export const RoomShow = props => {
const translate = useTranslate();
return (
<Show {...props} title={<RoomTitle />}>
<Show {...props} actions={<RoomShowActions />} title={<RoomTitle />}>
<TabbedShowLayout>
<Tab label="synapseadmin.rooms.tabs.basic" icon={<ViewListIcon />}>
<TextField source="room_id" />

View File

@@ -0,0 +1,42 @@
import React from "react";
import {
Datagrid,
Filter,
List,
NumberField,
TextField,
SearchInput,
Pagination,
} from "react-admin";
const UserMediaStatsPagination = props => (
<Pagination {...props} rowsPerPageOptions={[10, 25, 50, 100, 500, 1000]} />
);
const UserMediaStatsFilter = props => (
<Filter {...props}>
<SearchInput source="search_term" alwaysOn />
</Filter>
);
export const UserMediaStatsList = props => {
return (
<List
{...props}
filters={<UserMediaStatsFilter />}
pagination={<UserMediaStatsPagination />}
sort={{ field: "media_length", order: "DESC" }}
bulkActionButtons={false}
>
<Datagrid rowClick={(id, basePath, record) => "/users/" + id + "/media"}>
<TextField source="user_id" label="resources.users.fields.id" />
<TextField
source="displayname"
label="resources.users.fields.displayname"
/>
<NumberField source="media_count" />
<NumberField source="media_length" />
</Datagrid>
</List>
);
};

View File

@@ -5,6 +5,9 @@ import ContactMailIcon from "@material-ui/icons/ContactMail";
import DevicesIcon from "@material-ui/icons/Devices";
import GetAppIcon from "@material-ui/icons/GetApp";
import SettingsInputComponentIcon from "@material-ui/icons/SettingsInputComponent";
import NotificationsIcon from "@material-ui/icons/Notifications";
import PermMediaIcon from "@material-ui/icons/PermMedia";
import ViewListIcon from "@material-ui/icons/ViewList";
import {
ArrayInput,
ArrayField,
@@ -40,6 +43,7 @@ import {
ExportButton,
TopToolbar,
sanitizeListRestProps,
NumberField,
} from "react-admin";
import { ServerNoticeButton, ServerNoticeBulkButton } from "./ServerNotices";
import { DeviceRemoveButton } from "./devices";
@@ -312,6 +316,7 @@ export const UserEdit = props => {
/>
<TextField source="consent_version" />
</FormTab>
<FormTab
label="resources.users.threepid"
icon={<ContactMailIcon />}
@@ -330,6 +335,7 @@ export const UserEdit = props => {
</SimpleFormIterator>
</ArrayInput>
</FormTab>
<FormTab
label={translate("resources.devices.name", { smart_count: 2 })}
icon={<DevicesIcon />}
@@ -361,6 +367,7 @@ export const UserEdit = props => {
</Datagrid>
</ReferenceManyField>
</FormTab>
<FormTab
label="resources.connections.name"
icon={<SettingsInputComponentIcon />}
@@ -400,6 +407,111 @@ export const UserEdit = props => {
</ArrayField>
</ReferenceField>
</FormTab>
<FormTab
label={translate("resources.users_media.name", { smart_count: 2 })}
icon={<PermMediaIcon />}
path="media"
>
<ReferenceManyField
reference="users_media"
target="user_id"
addLabel={false}
pagination={<UserPagination />}
perPage={50}
>
<Datagrid style={{ width: "100%" }}>
<DateField
source="created_ts"
showTime
options={{
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
}}
sortable={false}
/>
<DateField
source="last_access_ts"
showTime
options={{
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
}}
sortable={false}
/>
<TextField source="media_id" sortable={false} />
<NumberField source="media_length" sortable={false} />
<TextField source="media_type" sortable={false} />
<TextField source="upload_name" sortable={false} />
<TextField source="quarantined_by" sortable={false} />
<BooleanField source="safe_from_quarantine" sortable={false} />
<DeleteButton undoable={false} redirect={false} />
</Datagrid>
</ReferenceManyField>
</FormTab>
<FormTab
label={translate("resources.rooms.name", { smart_count: 2 })}
icon={<ViewListIcon />}
path="rooms"
>
<ReferenceManyField
reference="joined_rooms"
target="user_id"
addLabel={false}
>
<Datagrid
style={{ width: "100%" }}
rowClick={(id, basePath, record) => "/rooms/" + id + "/show"}
>
<TextField
source="id"
sortable={false}
label="resources.rooms.fields.room_id"
/>
<ReferenceField
label="resources.rooms.fields.name"
source="id"
reference="rooms"
sortable={false}
link=""
>
<TextField source="name" sortable={false} />
</ReferenceField>
</Datagrid>
</ReferenceManyField>
</FormTab>
<FormTab
label={translate("resources.pushers.name", { smart_count: 2 })}
icon={<NotificationsIcon />}
path="pushers"
>
<ReferenceManyField
reference="pushers"
target="user_id"
addLabel={false}
>
<Datagrid style={{ width: "100%" }}>
<TextField source="kind" sortable={false} />
<TextField source="app_display_name" sortable={false} />
<TextField source="app_id" sortable={false} />
<TextField source="data.url" sortable={false} />
<TextField source="device_display_name" sortable={false} />
<TextField source="lang" sortable={false} />
<TextField source="profile_tag" sortable={false} />
<TextField source="pushkey" sortable={false} />
</Datagrid>
</ReferenceManyField>
</FormTab>
</TabbedForm>
</Edit>
);

View File

@@ -25,9 +25,11 @@ export default {
},
delete: {
title: "Raum löschen",
message: "Sind Sie sicher dass Sie den Raum löschen möchten? Diese Aktion kann nicht rückgängig gemacht werden. Alle Nachrichten und Medien, die der Raum beinhaltet werden vom Server gelöscht!",
message:
"Sind Sie sicher dass Sie den Raum löschen möchten? Diese Aktion kann nicht rückgängig gemacht werden. Alle Nachrichten und Medien, die der Raum beinhaltet werden vom Server gelöscht!",
},
},
reports: { tabs: { basic: "Allgemein", detail: "Details" } },
},
import_users: {
error: {
@@ -123,14 +125,10 @@ export default {
address: "Adresse",
creation_ts_ms: "Zeitpunkt der Erstellung",
consent_version: "Zugestimmte Geschäftsbedingungen",
// Devices:
device_id: "Geräte-ID",
display_name: "Gerätename",
last_seen_ts: "Zeitstempel",
last_seen_ip: "IP-Adresse",
},
helper: {
deactivate: "Deaktivierte Nutzer können nicht wieder aktiviert werden.",
deactivate:
"Sie müssen ein Passwort angeben, um ein Konto wieder zu aktivieren.",
erase: "DSGVO konformes Löschen der Benutzerdaten",
},
action: {
@@ -176,6 +174,30 @@ export default {
unencrypted: "Nicht verschlüsselt",
},
},
reports: {
name: "Ereignisbericht |||| Ereignisberichte",
fields: {
id: "ID",
received_ts: "Meldezeit",
user_id: "Meldender",
name: "Raumname",
score: "Wert",
reason: "Grund",
event_id: "Event-ID",
event_json: {
origin: "Ursprungsserver",
origin_server_ts: "Sendezeit",
type: "Eventtyp",
content: {
msgtype: "Inhaltstyp",
body: "Nachrichteninhalt",
format: "Nachrichtenformat",
formatted_body: "Formatierter Nachrichteninhalt",
algorithm: "Verschlüsselungsalgorithmus",
},
},
},
},
connections: {
name: "Verbindungen",
fields: {
@@ -186,6 +208,12 @@ export default {
},
devices: {
name: "Gerät |||| Geräte",
fields: {
device_id: "Geräte-ID",
display_name: "Gerätename",
last_seen_ts: "Zeitstempel",
last_seen_ip: "IP-Adresse",
},
action: {
erase: {
title: "Entferne %{id}",
@@ -195,6 +223,33 @@ export default {
},
},
},
users_media: {
name: "Medien",
fields: {
media_id: "Medien ID",
media_length: "Größe",
media_type: "Typ",
upload_name: "Dateiname",
quarantined_by: "Zur Quarantäne hinzugefügt",
safe_from_quarantine: "Geschützt vor Quarantäne",
created_ts: "Erstellt",
last_access_ts: "Letzter Zugriff",
},
},
pushers: {
name: "Pusher |||| Pushers",
fields: {
app: "App",
app_display_name: "App-Anzeigename",
app_id: "App ID",
device_display_name: "Geräte-Anzeigename",
kind: "Art",
lang: "Sprache",
profile_tag: "Profil-Tag",
pushkey: "Pushkey",
data: { url: "URL" },
},
},
servernotices: {
name: "Serverbenachrichtigungen",
send: "Servernachricht versenden",
@@ -211,9 +266,20 @@ export default {
'Sendet eine Serverbenachrichtigung an die ausgewählten Nutzer. Hierfür muss das Feature "Server Notices" auf dem Server aktiviert sein.',
},
},
user_media_statistics: {
name: "Dateien je Benutzer",
fields: {
media_count: "Anzahl der Dateien",
media_length: "Größe der Dateien",
},
},
},
ra: {
...germanMessages.ra,
action: {
...germanMessages.ra.action,
unselect: "Abwählen",
},
auth: {
...germanMessages.ra.auth,
auth_check_error: "Anmeldung fehlgeschlagen",

View File

@@ -6,6 +6,7 @@ export default {
auth: {
base_url: "Homeserver URL",
welcome: "Welcome to Synapse-admin",
server_version: "Synapse version",
username_error: "Please enter fully qualified user ID: '@user:domain'",
protocol_error: "URL has to start with 'http://' or 'https://'",
url_error: "Not a valid Matrix server URL",
@@ -23,9 +24,11 @@ export default {
},
delete: {
title: "Delete room",
message: "Are you sure you want to delete the room? This cannot be undone. All messages and shared media in the room will be deleted from the server!",
message:
"Are you sure you want to delete the room? This cannot be undone. All messages and shared media in the room will be deleted from the server!",
},
},
reports: { tabs: { basic: "Basic", detail: "Details" } },
},
import_users: {
error: {
@@ -121,14 +124,9 @@ export default {
address: "Address",
creation_ts_ms: "Creation timestamp",
consent_version: "Consent version",
// Devices:
device_id: "Device-ID",
display_name: "Device name",
last_seen_ts: "Timestamp",
last_seen_ip: "IP address",
},
helper: {
deactivate: "Deactivated users cannot be reactivated",
deactivate: "You must provide a password to re-activate an account.",
erase: "Mark the user as GDPR-erased",
},
action: {
@@ -142,7 +140,7 @@ export default {
name: "Name",
canonical_alias: "Alias",
joined_members: "Members",
joined_local_members: "local members",
joined_local_members: "Local members",
state_events: "State events",
version: "Version",
is_encrypted: "Encrypted",
@@ -174,6 +172,30 @@ export default {
unencrypted: "Unencrypted",
},
},
reports: {
name: "Reported event |||| Reported events",
fields: {
id: "ID",
received_ts: "report time",
user_id: "announcer",
name: "name of the room",
score: "score",
reason: "reason",
event_id: "event ID",
event_json: {
origin: "origin server",
origin_server_ts: "time of send",
type: "event typ",
content: {
msgtype: "content type",
body: "content",
format: "format",
formatted_body: "formatted content",
algorithm: "algorithm",
},
},
},
},
connections: {
name: "Connections",
fields: {
@@ -184,6 +206,12 @@ export default {
},
devices: {
name: "Device |||| Devices",
fields: {
device_id: "Device-ID",
display_name: "Device name",
last_seen_ts: "Timestamp",
last_seen_ip: "IP address",
},
action: {
erase: {
title: "Removing %{id}",
@@ -193,6 +221,33 @@ export default {
},
},
},
users_media: {
name: "Media",
fields: {
media_id: "Media ID",
media_length: "Lenght",
media_type: "Type",
upload_name: "File name",
quarantined_by: "Quarantined by",
safe_from_quarantine: "Safe from quarantine",
created_ts: "Created",
last_access_ts: "Last access",
},
},
pushers: {
name: "Pusher |||| Pushers",
fields: {
app: "App",
app_display_name: "App display name",
app_id: "App ID",
device_display_name: "Device display name",
kind: "Kind",
lang: "Language",
profile_tag: "Profile tag",
pushkey: "Pushkey",
data: { url: "URL" },
},
},
servernotices: {
name: "Server Notices",
send: "Send server notices",
@@ -209,5 +264,12 @@ export default {
'Sends a server notice to the selected users. The feature "Server Notices" has to be activated at the server.',
},
},
user_media_statistics: {
name: "Users' media",
fields: {
media_count: "Media count",
media_length: "Media length",
},
},
},
};

View File

@@ -10,6 +10,7 @@ const authProvider = {
type: "m.login.password",
user: username,
password: password,
initial_device_display_name: "Synapse Admin",
}),
};
@@ -30,8 +31,26 @@ const authProvider = {
},
// called when the user clicks on the logout button
logout: () => {
console.log("logout ");
localStorage.removeItem("access_token");
console.log("logout");
const logout_api_url =
localStorage.getItem("base_url") + "/_matrix/client/r0/logout";
const access_token = localStorage.getItem("access_token");
const options = {
method: "POST",
user: {
authenticated: true,
token: `Bearer ${access_token}`,
},
};
if (typeof access_token === "string") {
fetchUtils.fetchJson(logout_api_url, options).then(({ json }) => {
localStorage.removeItem("access_token");
localStorage.removeItem("device_id");
});
}
return Promise.resolve();
},
// called when the API returns an error
@@ -46,7 +65,7 @@ const authProvider = {
checkAuth: () => {
const access_token = localStorage.getItem("access_token");
console.log("checkAuth " + access_token);
return typeof access_token == "string"
return typeof access_token === "string"
? Promise.resolve()
: Promise.reject();
},

View File

@@ -72,12 +72,24 @@ const resourceMap = {
method: "POST",
}),
},
reports: {
path: "/_synapse/admin/v1/event_reports",
map: er => ({
...er,
id: er.id,
}),
data: "event_reports",
total: json => json.total,
},
devices: {
map: d => ({
...d,
id: d.device_id,
}),
data: "devices",
total: json => {
return json.total;
},
reference: id => ({
endpoint: `/_synapse/admin/v2/users/${id}/devices`,
}),
@@ -101,6 +113,52 @@ const resourceMap = {
endpoint: `/_synapse/admin/v1/rooms/${id}/members`,
}),
data: "members",
total: json => {
return json.total;
},
},
pushers: {
map: p => ({
...p,
id: p.pushkey,
}),
reference: id => ({
endpoint: `/_synapse/admin/v1/users/${id}/pushers`,
}),
data: "pushers",
total: json => {
return json.total;
},
},
joined_rooms: {
map: jr => ({
id: jr,
}),
reference: id => ({
endpoint: `/_synapse/admin/v1/users/${id}/joined_rooms`,
}),
data: "joined_rooms",
total: json => {
return json.total;
},
},
users_media: {
map: um => ({
...um,
id: um.media_id,
}),
reference: id => ({
endpoint: `/_synapse/admin/v1/users/${id}/media`,
}),
data: "media",
total: json => {
return json.total;
},
delete: params => ({
endpoint: `/_synapse/admin/v1/media/${localStorage.getItem(
"home_server"
)}/${params.id}`,
}),
},
servernotices: {
map: n => ({ id: n.event_id }),
@@ -116,6 +174,17 @@ const resourceMap = {
method: "POST",
}),
},
user_media_statistics: {
path: "/_synapse/admin/v1/statistics/users/media",
map: usms => ({
...usms,
id: usms.user_id,
}),
data: "users",
total: json => {
return json.total;
},
},
};
function filterNullValues(key, value) {
@@ -191,11 +260,18 @@ const dataProvider = {
params.ids.map(id => jsonClient(`${endpoint_url}/${id}`))
).then(responses => ({
data: responses.map(({ json }) => res.map(json)),
total: responses.length,
}));
},
getManyReference: (resource, params) => {
console.log("getManyReference " + resource);
const { page, perPage } = params.pagination;
const from = (page - 1) * perPage;
const query = {
from: from,
limit: perPage,
};
const homeserver = localStorage.getItem("base_url");
if (!homeserver || !(resource in resourceMap)) return Promise.reject();
@@ -203,10 +279,11 @@ const dataProvider = {
const res = resourceMap[resource];
const ref = res["reference"](params.id);
const endpoint_url = homeserver + ref.endpoint;
const endpoint_url = `${homeserver}${ref.endpoint}?${stringify(query)}`;
return jsonClient(endpoint_url).then(({ headers, json }) => ({
data: json[res.data].map(res.map),
total: res.total(json, from, perPage),
}));
},

2117
yarn.lock

File diff suppressed because it is too large Load Diff