Merge branch 'master' into purge_room
This commit is contained in:
commit
5f5b6284b7
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "synapse-admin",
|
||||
"version": "0.1.0",
|
||||
"version": "0.2.1",
|
||||
"description": "Admin GUI for the Matrix.org server Synapse",
|
||||
"author": "Awesome Technologies Innovationslabor GmbH",
|
||||
"license": "Apache-2.0",
|
||||
@ -29,8 +29,8 @@
|
||||
"react-scripts": "^3.4.1"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"start": "REACT_APP_VERSION=$(git describe --tags) react-scripts start",
|
||||
"build": "REACT_APP_VERSION=$(git describe --tags) react-scripts build",
|
||||
"fix:other": "yarn prettier --write",
|
||||
"fix:code": "yarn test:lint --fix",
|
||||
"fix": "yarn fix:code && yarn fix:other",
|
||||
|
@ -38,5 +38,12 @@
|
||||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
-->
|
||||
<footer
|
||||
style="position: relative; z-index: 2; height: 2em; margin-top: -2em; line-height: 2em; background-color: #eee; border: 0.5px solid #ddd">
|
||||
<a id="copyright" href="https://github.com/Awesome-Technologies/synapse-admin"
|
||||
style="margin-left: 1em; color: #888; font-family: Roboto, Helvetica, Arial, sans-serif; font-weight: 100; font-size: 0.8em; text-decoration: none;">
|
||||
Synapse-Admin <b>(%REACT_APP_VERSION%)</b> by Awesome Technologies Innovationslabor GmbH
|
||||
</a>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
@ -1,4 +1,4 @@
|
||||
import React, { useState } from "react";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import {
|
||||
fetchUtils,
|
||||
FormDataConsumer,
|
||||
@ -29,7 +29,7 @@ const useStyles = makeStyles(theme => ({
|
||||
main: {
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
minHeight: "100vh",
|
||||
minHeight: "calc(100vh - 1em)",
|
||||
alignItems: "center",
|
||||
justifyContent: "flex-start",
|
||||
background: "url(./images/floating-cogs.svg)",
|
||||
@ -40,6 +40,7 @@ const useStyles = makeStyles(theme => ({
|
||||
card: {
|
||||
minWidth: "30em",
|
||||
marginTop: "6em",
|
||||
marginBottom: "6em",
|
||||
},
|
||||
avatar: {
|
||||
margin: "1em",
|
||||
@ -64,6 +65,12 @@ const useStyles = makeStyles(theme => ({
|
||||
actions: {
|
||||
padding: "0 1em 1em 1em",
|
||||
},
|
||||
serverVersion: {
|
||||
color: "#9e9e9e",
|
||||
fontFamily: "Roboto, Helvetica, Arial, sans-serif",
|
||||
marginBottom: "1em",
|
||||
marginLeft: "0.5em",
|
||||
},
|
||||
}));
|
||||
|
||||
const LoginPage = ({ theme }) => {
|
||||
@ -137,6 +144,7 @@ const LoginPage = ({ theme }) => {
|
||||
|
||||
const UserData = ({ formData }) => {
|
||||
const form = useForm();
|
||||
const [serverVersion, setServerVersion] = useState("");
|
||||
|
||||
const handleUsernameChange = _ => {
|
||||
if (formData.base_url) return;
|
||||
@ -157,6 +165,30 @@ const LoginPage = ({ theme }) => {
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(
|
||||
_ => {
|
||||
if (
|
||||
!formData.base_url ||
|
||||
!formData.base_url.match(/^(http|https):\/\/[a-zA-Z0-9\-.]+$/)
|
||||
)
|
||||
return;
|
||||
const versionUrl = `${formData.base_url}/_synapse/admin/v1/server_version`;
|
||||
fetchUtils
|
||||
.fetchJson(versionUrl, { method: "GET" })
|
||||
.then(({ json }) => {
|
||||
setServerVersion(
|
||||
`${translate("synapseadmin.auth.server_version")} ${
|
||||
json["server_version"]
|
||||
}`
|
||||
);
|
||||
})
|
||||
.catch(_ => {
|
||||
setServerVersion("");
|
||||
});
|
||||
},
|
||||
[formData.base_url]
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className={classes.input}>
|
||||
@ -189,6 +221,7 @@ const LoginPage = ({ theme }) => {
|
||||
fullWidth
|
||||
/>
|
||||
</div>
|
||||
<div className={classes.serverVersion}>{serverVersion}</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -1,12 +1,18 @@
|
||||
import React, { Fragment } from "react";
|
||||
import React from "react";
|
||||
import {
|
||||
Datagrid,
|
||||
List,
|
||||
TextField,
|
||||
Pagination,
|
||||
BulkDeleteButton,
|
||||
BooleanField,
|
||||
useTranslate,
|
||||
} from "react-admin";
|
||||
import get from "lodash/get";
|
||||
import { Tooltip, Typography } from "@material-ui/core";
|
||||
import HttpsIcon from "@material-ui/icons/Https";
|
||||
import NoEncryptionIcon from "@material-ui/icons/NoEncryption";
|
||||
|
||||
const RoomPagination = props => (
|
||||
<Pagination {...props} rowsPerPageOptions={[10, 25, 50, 100, 500, 1000]} />
|
||||
@ -25,17 +31,54 @@ const RoomBulkActionButtons = props => {
|
||||
);
|
||||
};
|
||||
|
||||
const EncryptionField = ({ source, record = {}, emptyText }) => {
|
||||
const translate = useTranslate();
|
||||
const value = get(record, source);
|
||||
let ariaLabel = value === false ? "ra.boolean.false" : "ra.boolean.true";
|
||||
|
||||
if (value === false || value === true) {
|
||||
return (
|
||||
<Typography component="span" variant="body2">
|
||||
<Tooltip title={translate(ariaLabel, { _: ariaLabel })}>
|
||||
{value === true ? (
|
||||
<HttpsIcon data-testid="true" htmlColor="limegreen" />
|
||||
) : (
|
||||
<NoEncryptionIcon data-testid="false" color="error" />
|
||||
)}
|
||||
</Tooltip>
|
||||
</Typography>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Typography component="span" variant="body2">
|
||||
{emptyText}
|
||||
</Typography>
|
||||
);
|
||||
};
|
||||
|
||||
export const RoomList = props => (
|
||||
<List
|
||||
{...props}
|
||||
pagination={<RoomPagination />}
|
||||
bulkActionButtons={<RoomBulkActionButtons />}
|
||||
sort={{ field: "name", order: "ASC" }}
|
||||
>
|
||||
<Datagrid>
|
||||
<TextField source="room_id" />
|
||||
<EncryptionField
|
||||
source="is_encrypted"
|
||||
sortBy="encryption"
|
||||
label={<HttpsIcon />}
|
||||
/>
|
||||
<TextField source="room_id" sortable={false} />
|
||||
<TextField source="name" />
|
||||
<TextField source="canonical_alias" />
|
||||
<TextField source="joined_members" />
|
||||
<TextField source="joined_local_members" />
|
||||
<TextField source="state_events" />
|
||||
<TextField source="version" />
|
||||
<BooleanField source="federatable" />
|
||||
<BooleanField source="public" />
|
||||
</Datagrid>
|
||||
</List>
|
||||
);
|
||||
|
@ -1,5 +1,6 @@
|
||||
import React, { Fragment } from "react";
|
||||
import PersonPinIcon from "@material-ui/icons/PersonPin";
|
||||
import ContactMailIcon from "@material-ui/icons/ContactMail";
|
||||
import SettingsInputComponentIcon from "@material-ui/icons/SettingsInputComponent";
|
||||
import {
|
||||
ArrayInput,
|
||||
@ -78,7 +79,7 @@ export const UserList = props => (
|
||||
>
|
||||
<ImageField source="avatar_url" title="displayname" />
|
||||
</ReferenceField>
|
||||
<TextField source="id" />
|
||||
<TextField source="id" sortable={false} />
|
||||
{/* Hack since the users endpoint does not give displaynames in the list*/}
|
||||
<ReferenceField
|
||||
source="name"
|
||||
@ -159,6 +160,25 @@ export const UserEdit = props => (
|
||||
source="deactivated"
|
||||
helperText="resources.users.helper.deactivate"
|
||||
/>
|
||||
<DateField
|
||||
source="creation_ts_ms"
|
||||
showTime
|
||||
options={{
|
||||
year: "numeric",
|
||||
month: "2-digit",
|
||||
day: "2-digit",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
second: "2-digit",
|
||||
}}
|
||||
/>
|
||||
<TextField source="consent_version" />
|
||||
</FormTab>
|
||||
<FormTab
|
||||
label="resources.users.threepid"
|
||||
icon={<ContactMailIcon />}
|
||||
path="threepid"
|
||||
>
|
||||
<ArrayInput source="threepids">
|
||||
<SimpleFormIterator>
|
||||
<SelectInput
|
||||
@ -175,8 +195,14 @@ export const UserEdit = props => (
|
||||
<FormTab
|
||||
label="resources.connections.name"
|
||||
icon={<SettingsInputComponentIcon />}
|
||||
path="connections"
|
||||
>
|
||||
<ReferenceField reference="connections" source="id" addLabel={false}>
|
||||
<ReferenceField
|
||||
reference="connections"
|
||||
source="id"
|
||||
addLabel={false}
|
||||
link={false}
|
||||
>
|
||||
<ArrayField
|
||||
source="devices[].sessions[0].connections"
|
||||
label="resources.connections.name"
|
||||
|
@ -6,6 +6,7 @@ export default {
|
||||
auth: {
|
||||
base_url: "Heimserver URL",
|
||||
welcome: "Willkommen bei Synapse-admin",
|
||||
server_version: "Synapse Version",
|
||||
username_error: "Bitte vollständigen Nutzernamen angeben: '@user:domain'",
|
||||
protocol_error: "Die URL muss mit 'http://' oder 'https://' beginnen",
|
||||
url_error: "Keine gültige Matrix Server URL",
|
||||
@ -21,6 +22,7 @@ export default {
|
||||
name: "Benutzer",
|
||||
email: "E-Mail",
|
||||
msisdn: "Telefon",
|
||||
threepid: "E-Mail / Telefon",
|
||||
fields: {
|
||||
avatar: "Avatar",
|
||||
id: "Benutzer-ID",
|
||||
@ -37,6 +39,8 @@ export default {
|
||||
medium: "Medium",
|
||||
threepids: "3PIDs",
|
||||
address: "Adresse",
|
||||
creation_ts_ms: "Zeitpunkt der Erstellung",
|
||||
consent_version: "Zugestimmte Geschäftsbedingungen",
|
||||
},
|
||||
helper: {
|
||||
deactivate: "Deaktivierte Nutzer können nicht wieder aktiviert werden.",
|
||||
@ -53,6 +57,12 @@ export default {
|
||||
name: "Name",
|
||||
canonical_alias: "Alias",
|
||||
joined_members: "Mitglieder",
|
||||
joined_local_members: "lokale Mitglieder",
|
||||
state_events: "Ereignisse",
|
||||
version: "Version",
|
||||
is_encrypted: "Verschlüsselt",
|
||||
federatable: "Föderiert",
|
||||
public: "Öffentlich",
|
||||
},
|
||||
helper: {
|
||||
purge:
|
||||
|
@ -21,6 +21,7 @@ export default {
|
||||
name: "User |||| Users",
|
||||
email: "Email",
|
||||
msisdn: "Phone",
|
||||
threepid: "Email / Phone",
|
||||
fields: {
|
||||
avatar: "Avatar",
|
||||
id: "User-ID",
|
||||
@ -37,6 +38,8 @@ export default {
|
||||
medium: "Medium",
|
||||
threepids: "3PIDs",
|
||||
address: "Address",
|
||||
creation_ts_ms: "Creation timestamp",
|
||||
consent_version: "Consent version",
|
||||
},
|
||||
helper: {
|
||||
deactivate: "Deactivated users cannot be reactivated",
|
||||
@ -53,6 +56,12 @@ export default {
|
||||
name: "Name",
|
||||
canonical_alias: "Alias",
|
||||
joined_members: "Members",
|
||||
joined_local_members: "local members",
|
||||
state_events: "State events",
|
||||
version: "Version",
|
||||
is_encrypted: "Encrypted",
|
||||
federatable: "Federatable",
|
||||
public: "Public",
|
||||
},
|
||||
helper: {
|
||||
purge:
|
||||
|
@ -23,6 +23,8 @@ const resourceMap = {
|
||||
is_guest: !!u.is_guest,
|
||||
admin: !!u.admin,
|
||||
deactivated: !!u.deactivated,
|
||||
// need timestamp in milliseconds
|
||||
creation_ts_ms: u.creation_ts * 1000,
|
||||
}),
|
||||
data: "users",
|
||||
total: (json, from, perPage) => {
|
||||
@ -48,6 +50,9 @@ const resourceMap = {
|
||||
id: r.room_id,
|
||||
alias: r.canonical_alias,
|
||||
members: r.joined_members,
|
||||
is_encrypted: !!r.encryption,
|
||||
federatable: !!r.federatable,
|
||||
public: !!r.public,
|
||||
}),
|
||||
data: "rooms",
|
||||
total: json => {
|
||||
@ -91,11 +96,20 @@ function filterNullValues(key, value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
function getSearchOrder(order) {
|
||||
if (order === "DESC") {
|
||||
return "b";
|
||||
} else {
|
||||
return "f";
|
||||
}
|
||||
}
|
||||
|
||||
const dataProvider = {
|
||||
getList: (resource, params) => {
|
||||
console.log("getList " + resource);
|
||||
const { user_id, guests, deactivated } = params.filter;
|
||||
const { page, perPage } = params.pagination;
|
||||
const { field, order } = params.sort;
|
||||
const from = (page - 1) * perPage;
|
||||
const query = {
|
||||
from: from,
|
||||
@ -103,6 +117,8 @@ const dataProvider = {
|
||||
user_id: user_id,
|
||||
guests: guests,
|
||||
deactivated: deactivated,
|
||||
order_by: field,
|
||||
dir: getSearchOrder(order),
|
||||
};
|
||||
const homeserver = localStorage.getItem("base_url");
|
||||
if (!homeserver || !(resource in resourceMap)) return Promise.reject();
|
||||
|
@ -11444,9 +11444,9 @@ websocket-driver@>=0.5.1:
|
||||
websocket-extensions ">=0.1.1"
|
||||
|
||||
websocket-extensions@>=0.1.1:
|
||||
version "0.1.3"
|
||||
resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29"
|
||||
integrity sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42"
|
||||
integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==
|
||||
|
||||
whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3, whatwg-encoding@^1.0.5:
|
||||
version "1.0.5"
|
||||
|
Loading…
Reference in New Issue
Block a user