26 Commits
0.8.2 ... 0.8.4

Author SHA1 Message Date
Michael Albert
b9e81b2278 Bump version and update dependencies
Change-Id: I0c0349b4429ce06bea51453c092f0a11156aaa05
2021-12-17 20:38:18 +01:00
sakkiii
f6f437b17a version tag on docker hub (#187)
* version tag on docker hub

* resolve name collision

* master branch added for latest tag

* prettier-ignore fix
2021-12-08 22:02:43 +01:00
Dirk Klimpel
91af8f1c04 Add sorting users by creation timestamp (#174)
* Add `creation_ts` to list users

* remove filter

* Bring back origin columns sort order
2021-12-08 21:59:09 +01:00
Aaron R
abc9d5154e Switch Dockerfile to use current LTS version of Node (#205)
Node 17 current fails due to https://github.com/webpack/webpack/issues/14532. It probably makes sense to use the current LTS version of Node instead of the absolute latest version of Node so these kinds of bleeding edge issues are less likely to happen.
2021-11-15 21:35:23 +01:00
dependabot[bot]
8228d7d2c2 Bump tar from 6.1.8 to 6.1.11 (#207)
Bumps [tar](https://github.com/npm/node-tar) from 6.1.8 to 6.1.11.
- [Release notes](https://github.com/npm/node-tar/releases)
- [Changelog](https://github.com/npm/node-tar/blob/main/CHANGELOG.md)
- [Commits](https://github.com/npm/node-tar/compare/v6.1.8...v6.1.11)

---
updated-dependencies:
- dependency-name: tar
  dependency-type: indirect
...

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-15 21:18:58 +01:00
Dirk Klimpel
4adc20f80d replace undoable prop with mutationMode prop (#202) 2021-11-15 21:18:29 +01:00
Dirk Klimpel
a5c7d7dd22 Make items in "Room directory" are clickable (#199) 2021-11-15 21:15:11 +01:00
dependabot[bot]
dc5c2c1d68 Bump tmpl from 1.0.4 to 1.0.5 (#193)
Bumps [tmpl](https://github.com/daaku/nodejs-tmpl) from 1.0.4 to 1.0.5.
- [Release notes](https://github.com/daaku/nodejs-tmpl/releases)
- [Commits](https://github.com/daaku/nodejs-tmpl/commits/v1.0.5)

---
updated-dependencies:
- dependency-name: tmpl
  dependency-type: indirect
...

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-15 21:11:49 +01:00
Dirk Klimpel
42b3252353 Add pristine to UserEdit and ServerNotice (#185) 2021-11-15 21:02:47 +01:00
Dirk Klimpel
1a17d3e69b Automatically set the homeserver for a new user (#184)
and enhance form validation
2021-11-15 20:57:38 +01:00
Dirk Klimpel
79ef38ee6b Enable modify user external_ids (#179)
* Enable modify user `external_ids`

* add input validation
2021-11-15 20:40:05 +01:00
Manuel Stahl
0ff4b30d71 Remove update repo stop from docker release action
See https://github.com/peter-evans/dockerhub-description/issues/10

Change-Id: I42d2d4e1a28117be1419591f7d43653591182f0c
2021-08-26 10:43:11 +02:00
Manuel Stahl
6c4ff6c791 Add write permissions to github release action
Change-Id: Ie7db1e7410bbc1c0fccbc2d00119363629e10f22
2021-08-26 10:40:11 +02:00
Manuel Stahl
9c36ed6566 Increment version
Change-Id: I48fb812632dc2e498ad267477809a16fc882cf4c
2021-08-25 10:42:34 +02:00
dklimpel
8536f552d4 Add button to quarantine media (#180)
Change-Id: I6496826fdf75ab8b7b3ed5a9056abf86a50caea3
2021-08-25 10:42:34 +02:00
Manuel Stahl
aaf782d24f Use .gitignore for prettier as well
Change-Id: Ibfe73812a5375cc251b859b8aa441583c0cdcd41
2021-08-25 10:42:34 +02:00
Manuel Stahl
2886203594 Add github action that builds docker images and pushes them to docker hub
Change-Id: I60d39cc266c2e8b905e2ac4a367bd5a22b79b57b
2021-08-25 10:42:34 +02:00
csett86
865fc98336 Add github action that packages a release tarball (#148)
Change-Id: I368a834a27f69550596a041c1e6b84afd40011b7
2021-08-24 09:58:35 +02:00
Dirk Klimpel
e6f01f035b Add buttons to protect and unprotect users' media from quarantine (#150) 2021-08-19 11:51:07 +02:00
Manuel Stahl
32e088ac5a yarn: Upgrade packages
- babel 7.15
- eslint 7.32
- react-admin 3.17

Change-Id: Ief4ad5870ae721fb432e19686607376b83eff12a
2021-08-18 09:48:41 +02:00
Dirk Klimpel
bf3d13916f Add SSO external_ids to user (#168) 2021-08-18 09:33:22 +02:00
Manuel Stahl
07b1df5855 Add Github action badge for build checks 2021-08-18 09:27:25 +02:00
Dirk Klimpel
634341ea07 Add GitHub Action to run CI tests (#162) 2021-08-18 09:18:09 +02:00
Dirk Klimpel
361643c3da Fix link in README.md (#175) 2021-08-17 08:22:36 +02:00
Dirk Klimpel
5262518699 Update links to new Synapse documentation (#164) 2021-07-06 09:57:44 +02:00
Dirk Klimpel
78a282863a Fix broken CI with language files (#165) 2021-07-06 09:56:09 +02:00
16 changed files with 2293 additions and 1886 deletions

21
.github/workflows/build-test.yml vendored Normal file
View File

@@ -0,0 +1,21 @@
name: build-test
on:
push:
branches: ["master"]
pull_request:
jobs:
check:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup node
uses: actions/setup-node@v2
with:
node-version: 14
- name: Install dependencies
run: yarn --frozen-lockfile
- name: Run tests
run: yarn test

51
.github/workflows/docker-release.yml vendored Normal file
View File

@@ -0,0 +1,51 @@
name: Create docker image(s) and push to docker hub
on:
push:
# Sequence of patterns matched against refs/heads
# prettier-ignore
branches:
# Push events on master branch
- master
# Sequence of patterns matched against refs/tags
tags:
- '[0-9]+\.[0-9]+\.[0-9]+' # Push events to 0.X.X tag
jobs:
docker:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Calculate docker image tag
id: set-tag
run: |
case "${GITHUB_REF}" in
refs/heads/master|refs/heads/main)
tag=latest
;;
refs/tags/*)
tag=${GITHUB_REF#refs/tags/}
;;
*)
tag=${GITHUB_SHA}
;;
esac
echo "::set-output name=tag::$tag"
- name: Build and Push Tag
uses: docker/build-push-action@v2
with:
context: .
push: true
tags: "awesometechnologies/synapse-admin:${{ steps.set-tag.outputs.tag }}"
platforms: linux/amd64,linux/arm64

31
.github/workflows/github-release.yml vendored Normal file
View File

@@ -0,0 +1,31 @@
name: Create release tarball and attach to tag
on:
push:
tags:
- "*"
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: write
packages: write
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: "14"
- run: yarn install
- run: yarn build
- run: |
version=`git describe --dirty --tags || echo unknown`
mkdir -p dist
cp -r build synapse-admin-$version
tar chvzf dist/synapse-admin-$version.tar.gz synapse-admin-$version
- uses: softprops/action-gh-release@b7e450da2a4b4cb4bfbae528f788167786cfcedf
with:
files: dist/*.tar.gz
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,5 +1,5 @@
# Builder
FROM node:current as builder
FROM node:lts as builder
WORKDIR /src

View File

@@ -1,13 +1,14 @@
[![Build Status](https://travis-ci.org/Awesome-Technologies/synapse-admin.svg?branch=master)](https://travis-ci.org/Awesome-Technologies/synapse-admin)
[![build-test](https://github.com/Awesome-Technologies/synapse-admin/actions/workflows/build-test.yml/badge.svg)](https://github.com/Awesome-Technologies/synapse-admin/actions/workflows/build-test.yml)
# Synapse admin ui
This project is built using [react-admin](https://marmelab.com/react-admin/).
It needs at least Synapse v1.34.0 for all functions to work as expected!
It needs at least Synapse v1.41.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).
See also [Synapse version API](https://matrix-org.github.io/synapse/develop/admin_api/version_api.html).
After entering the URL on the login page of synapse-admin the server version appears below the input field.
@@ -16,17 +17,27 @@ You need access to the following endpoints:
- `/_matrix`
- `/_synapse/admin`
See also [Synapse administration endpoints](https://github.com/matrix-org/synapse/blob/develop/docs/reverse_proxy.md#synapse-administration-endpoints)
See also [Synapse administration endpoints](https://matrix-org.github.io/synapse/develop/reverse_proxy.html#synapse-administration-endpoints)
## Step-By-Step install:
You have two options:
You have three options:
1. Download the source code from github and run using nodejs
2. Run the Docker container
1. Download the tarball and serve with any webserver
2. Download the source code from github and run using nodejs
3. Run the Docker container
Steps for 1):
- 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
- unpack the .tar.gz
- move or symlink the `synapse-admin-x.x.x` 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`
- change into downloaded directory: `cd synapse-admin`
@@ -38,9 +49,9 @@ Either you define it at startup (e.g. `REACT_APP_SERVER=https://yourmatrixserver
or by editing it in the [.env](.env) file. See also the
[documentation](https://create-react-app.dev/docs/adding-custom-environment-variables/).
Steps for 2):
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 awesometechnologies/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.

View File

@@ -1,6 +1,6 @@
{
"name": "synapse-admin",
"version": "0.8.2",
"version": "0.8.4",
"description": "Admin GUI for the Matrix.org server Synapse",
"author": "Awesome Technologies Innovationslabor GmbH",
"license": "Apache-2.0",
@@ -36,7 +36,7 @@
"fix:other": "yarn prettier --write",
"fix:code": "yarn test:lint --fix",
"fix": "yarn fix:code && yarn fix:other",
"prettier": "prettier \"**/*.{js,jsx,json,md,scss,yaml,yml}\"",
"prettier": "prettier --ignore-path .gitignore \"**/*.{js,jsx,json,md,scss,yaml,yml}\"",
"test:code": "react-scripts test",
"test:lint": "eslint --ignore-path .gitignore --ext .js,.jsx .",
"test:style": "yarn prettier --list-different",

View File

@@ -59,7 +59,7 @@ export const RoomDirectoryBulkDeleteButton = props => (
<BulkDeleteButton
{...props}
label="resources.room_directory.action.erase"
undoable={false}
mutationMode="pessimistic"
confirmTitle="resources.room_directory.action.title"
confirmContent="resources.room_directory.action.content"
resource="room_directory"
@@ -191,7 +191,7 @@ export const FilterableRoomDirectoryList = ({
filters={<RoomDirectoryFilter />}
perPage={100}
>
<Datagrid>
<Datagrid rowClick={(id, basePath, record) => "/rooms/" + id + "/show"}>
<AvatarField
source="avatar_src"
sortable={false}

View File

@@ -24,7 +24,10 @@ const ServerNoticeDialog = ({ open, loading, onClose, onSend }) => {
const ServerNoticeToolbar = props => (
<Toolbar {...props}>
<SaveButton label="resources.servernotices.action.send" />
<SaveButton
label="resources.servernotices.action.send"
disabled={props.pristine}
/>
<Button label="ra.action.cancel" onClick={onClose}>
<IconCancel />
</Button>

View File

@@ -2,6 +2,7 @@ import React, { Fragment, useState } from "react";
import classnames from "classnames";
import { fade } from "@material-ui/core/styles/colorManipulator";
import { makeStyles } from "@material-ui/core/styles";
import { Tooltip } from "@material-ui/core";
import {
BooleanInput,
Button,
@@ -10,16 +11,22 @@ import {
SaveButton,
SimpleForm,
Toolbar,
useCreate,
useDelete,
useNotify,
useRefresh,
useTranslate,
} from "react-admin";
import IconCancel from "@material-ui/icons/Cancel";
import BlockIcon from "@material-ui/icons/Block";
import ClearIcon from "@material-ui/icons/Clear";
import DeleteSweepIcon from "@material-ui/icons/DeleteSweep";
import Dialog from "@material-ui/core/Dialog";
import DialogContent from "@material-ui/core/DialogContent";
import DialogContentText from "@material-ui/core/DialogContentText";
import DialogTitle from "@material-ui/core/DialogTitle";
import DeleteSweepIcon from "@material-ui/icons/DeleteSweep";
import IconCancel from "@material-ui/icons/Cancel";
import LockIcon from "@material-ui/icons/Lock";
import LockOpenIcon from "@material-ui/icons/LockOpen";
const useStyles = makeStyles(
theme => ({
@@ -143,3 +150,178 @@ export const DeleteMediaButton = props => {
</Fragment>
);
};
export const ProtectMediaButton = props => {
const { record } = props;
const translate = useTranslate();
const refresh = useRefresh();
const notify = useNotify();
const [create, { loading }] = useCreate("protect_media");
const [deleteOne] = useDelete("protect_media");
if (!record) return null;
const handleProtect = () => {
create(
{ payload: { data: record } },
{
onSuccess: () => {
notify("resources.protect_media.action.send_success");
refresh();
},
onFailure: () =>
notify("resources.protect_media.action.send_failure", "error"),
}
);
};
const handleUnprotect = () => {
deleteOne(
{ payload: { ...record } },
{
onSuccess: () => {
notify("resources.protect_media.action.send_success");
refresh();
},
onFailure: () =>
notify("resources.protect_media.action.send_failure", "error"),
}
);
};
return (
/*
Wrapping Tooltip with <div>
https://github.com/marmelab/react-admin/issues/4349#issuecomment-578594735
*/
<Fragment>
{record.quarantined_by && (
<Tooltip
title={translate("resources.protect_media.action.none", {
_: "resources.protect_media.action.none",
})}
>
<div>
{/*
Button instead BooleanField for
consistent appearance and position in the column
*/}
<Button disabled={true}>
<ClearIcon />
</Button>
</div>
</Tooltip>
)}
{record.safe_from_quarantine && (
<Tooltip
title={translate("resources.protect_media.action.delete", {
_: "resources.protect_media.action.delete",
})}
arrow
>
<div>
<Button onClick={handleUnprotect} disabled={loading}>
<LockIcon />
</Button>
</div>
</Tooltip>
)}
{!record.safe_from_quarantine && !record.quarantined_by && (
<Tooltip
title={translate("resources.protect_media.action.create", {
_: "resources.protect_media.action.create",
})}
>
<div>
<Button onClick={handleProtect} disabled={loading}>
<LockOpenIcon />
</Button>
</div>
</Tooltip>
)}
</Fragment>
);
};
export const QuarantineMediaButton = props => {
const { record } = props;
const translate = useTranslate();
const refresh = useRefresh();
const notify = useNotify();
const [create, { loading }] = useCreate("quarantine_media");
const [deleteOne] = useDelete("quarantine_media");
if (!record) return null;
const handleQuarantaine = () => {
create(
{ payload: { data: record } },
{
onSuccess: () => {
notify("resources.quarantine_media.action.send_success");
refresh();
},
onFailure: () =>
notify("resources.quarantine_media.action.send_failure", "error"),
}
);
};
const handleRemoveQuarantaine = () => {
deleteOne(
{ payload: { ...record } },
{
onSuccess: () => {
notify("resources.quarantine_media.action.send_success");
refresh();
},
onFailure: () =>
notify("resources.quarantine_media.action.send_failure", "error"),
}
);
};
return (
<Fragment>
{record.safe_from_quarantine && (
<Tooltip
title={translate("resources.quarantine_media.action.none", {
_: "resources.quarantine_media.action.none",
})}
>
<div>
<Button disabled={true}>
<ClearIcon />
</Button>
</div>
</Tooltip>
)}
{record.quarantined_by && (
<Tooltip
title={translate("resources.quarantine_media.action.delete", {
_: "resources.quarantine_media.action.delete",
})}
>
<div>
<Button onClick={handleRemoveQuarantaine} disabled={loading}>
<BlockIcon color="error" />
</Button>
</div>
</Tooltip>
)}
{!record.safe_from_quarantine && !record.quarantined_by && (
<Tooltip
title={translate("resources.quarantine_media.action.create", {
_: "resources.quarantine_media.action.create",
})}
>
<div>
<Button onClick={handleQuarantaine} disabled={loading}>
<BlockIcon />
</Button>
</div>
</Tooltip>
)}
</Fragment>
);
};

View File

@@ -315,7 +315,7 @@ const RoomBulkActionButtons = props => (
{...props}
confirmTitle="resources.rooms.action.erase.title"
confirmContent="resources.rooms.action.erase.content"
undoable={false}
mutationMode="pessimistic"
/>
</Fragment>
);

View File

@@ -1,12 +1,13 @@
import React, { cloneElement, Fragment } from "react";
import Avatar from "@material-ui/core/Avatar";
import PersonPinIcon from "@material-ui/icons/PersonPin";
import AssignmentIndIcon from "@material-ui/icons/AssignmentInd";
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 PersonPinIcon from "@material-ui/icons/PersonPin";
import SettingsInputComponentIcon from "@material-ui/icons/SettingsInputComponent";
import ViewListIcon from "@material-ui/icons/ViewList";
import {
ArrayInput,
@@ -35,7 +36,9 @@ import {
BulkDeleteButton,
DeleteButton,
SaveButton,
maxLength,
regex,
required,
useTranslate,
Pagination,
CreateButton,
@@ -47,6 +50,7 @@ import {
import { Link } from "react-router-dom";
import { ServerNoticeButton, ServerNoticeBulkButton } from "./ServerNotices";
import { DeviceRemoveButton } from "./devices";
import { ProtectMediaButton, QuarantineMediaButton } from "./media";
import { makeStyles } from "@material-ui/core/styles";
const redirect = () => {
@@ -140,7 +144,7 @@ const UserBulkActionButtons = props => (
{...props}
label="resources.users.action.erase"
confirmTitle="resources.users.helper.erase"
undoable={false}
mutationMode="pessimistic"
/>
</Fragment>
);
@@ -172,16 +176,35 @@ export const UserList = props => {
<BooleanField source="is_guest" />
<BooleanField source="admin" />
<BooleanField source="deactivated" />
<DateField
source="creation_ts"
label="resources.users.fields.creation_ts_ms"
showTime
options={{
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
}}
/>
</Datagrid>
</List>
);
};
// https://matrix.org/docs/spec/appendices#user-identifiers
const validateUser = regex(
/^@[a-z0-9._=\-/]+:.*/,
"synapseadmin.users.invalid_user_id"
);
// here only local part of user_id
// maxLength = 255 - "@" - ":" - localStorage.getItem("home_server").length
// localStorage.getItem("home_server").length is not valid here
const validateUser = [
required(),
maxLength(253),
regex(/^[a-z0-9._=\-/]+$/, "synapseadmin.users.invalid_user_id"),
];
const validateAddress = [required(), maxLength(255)];
export function generateRandomUser() {
const homeserver = localStorage.getItem("home_server");
@@ -228,7 +251,7 @@ const UserEditToolbar = props => {
const translate = useTranslate();
return (
<Toolbar {...props}>
<SaveButton submitOnEnter={true} />
<SaveButton submitOnEnter={true} disabled={props.pristine} />
<DeleteButton
label="resources.users.action.erase"
confirmTitle={translate("resources.users.helper.erase", {
@@ -245,8 +268,12 @@ export const UserCreate = props => (
<Create {...props}>
<SimpleForm>
<TextInput source="id" autoComplete="off" validate={validateUser} />
<TextInput source="displayname" />
<PasswordInput source="password" autoComplete="new-password" />
<TextInput source="displayname" validate={maxLength(256)} />
<PasswordInput
source="password"
autoComplete="new-password"
validate={maxLength(512)}
/>
<BooleanInput source="admin" />
<ArrayInput source="threepids">
<SimpleFormIterator>
@@ -256,8 +283,19 @@ export const UserCreate = props => (
{ id: "email", name: "resources.users.email" },
{ id: "msisdn", name: "resources.users.msisdn" },
]}
validate={required()}
/>
<TextInput source="address" validate={validateAddress} />
</SimpleFormIterator>
</ArrayInput>
<ArrayInput source="external_ids" label="synapseadmin.users.tabs.sso">
<SimpleFormIterator>
<TextInput source="auth_provider" validate={required()} />
<TextInput
source="external_id"
label="resources.users.fields.id"
validate={required()}
/>
<TextInput source="address" />
</SimpleFormIterator>
</ArrayInput>
</SimpleForm>
@@ -332,6 +370,23 @@ export const UserEdit = props => {
</ArrayInput>
</FormTab>
<FormTab
label="synapseadmin.users.tabs.sso"
icon={<AssignmentIndIcon />}
path="sso"
>
<ArrayInput source="external_ids" label={false}>
<SimpleFormIterator>
<TextInput source="auth_provider" validate={required()} />
<TextInput
source="external_id"
label="resources.users.fields.id"
validate={required()}
/>
</SimpleFormIterator>
</ArrayInput>
</FormTab>
<FormTab
label={translate("resources.devices.name", { smart_count: 2 })}
icon={<DevicesIcon />}
@@ -447,7 +502,8 @@ export const UserEdit = props => {
<TextField source="media_type" />
<TextField source="upload_name" />
<TextField source="quarantined_by" />
<BooleanField source="safe_from_quarantine" />
<QuarantineMediaButton label="resources.quarantine_media.action.name" />
<ProtectMediaButton label="resources.users_media.fields.safe_from_quarantine" />
<DeleteButton mutationMode="pessimistic" redirect={false} />
</Datagrid>
</ReferenceManyField>

View File

@@ -12,8 +12,8 @@ const de = {
url_error: "Keine gültige Matrix Server URL",
},
users: {
invalid_user_id:
"Muss eine vollständige Matrix Benutzer-ID sein, z.B. @benutzer_id:homeserver",
invalid_user_id: "Lokaler Anteil der Matrix Benutzer-ID ohne Homeserver.",
tabs: { sso: "SSO" },
},
rooms: {
details: "Raumdetails",
@@ -120,6 +120,7 @@ const de = {
address: "Adresse",
creation_ts_ms: "Zeitpunkt der Erstellung",
consent_version: "Zugestimmte Geschäftsbedingungen",
auth_provider: "Provider",
},
helper: {
deactivate:
@@ -240,7 +241,7 @@ const de = {
media_type: "Typ",
upload_name: "Dateiname",
quarantined_by: "Zur Quarantäne hinzugefügt",
safe_from_quarantine: "Geschützt vor Quarantäne",
safe_from_quarantine: "Schutz vor Quarantäne",
created_ts: "Erstellt",
last_access_ts: "Letzter Zugriff",
},
@@ -258,8 +259,26 @@ const de = {
send_failure: "Beim Versenden ist ein Fehler aufgetreten.",
},
helper: {
send:
"Diese API löscht die lokalen Medien von der Festplatte des eigenen Servers. Dies umfasst alle lokalen Miniaturbilder und Kopien von Medien. Diese API wirkt sich nicht auf Medien aus, die sich in externen Medien-Repositories befinden.",
send: "Diese API löscht die lokalen Medien von der Festplatte des eigenen Servers. Dies umfasst alle lokalen Miniaturbilder und Kopien von Medien. Diese API wirkt sich nicht auf Medien aus, die sich in externen Medien-Repositories befinden.",
},
},
protect_media: {
action: {
create: "Ungeschützt, Schutz erstellen",
delete: "Geschützt, Schutz aufheben",
none: "In Quarantäne",
send_success: "Erfolgreich den Schutz-Status geändert.",
send_failure: "Beim Versenden ist ein Fehler aufgetreten.",
},
},
quarantine_media: {
action: {
name: "Quarantäne",
create: "Zur Quarantäne hinzufügen",
delete: "In Quarantäne, Quarantäne aufheben",
none: "Geschützt vor Quarantäne",
send_success: "Erfolgreich den Quarantäne-Status geändert.",
send_failure: "Beim Versenden ist ein Fehler aufgetreten.",
},
},
pushers: {
@@ -288,8 +307,7 @@ const de = {
send_failure: "Beim Versenden ist ein Fehler aufgetreten.",
},
helper: {
send:
'Sendet eine Serverbenachrichtigung an die ausgewählten Nutzer. Hierfür muss das Feature "Server Notices" auf dem Server aktiviert sein.',
send: 'Sendet eine Serverbenachrichtigung an die ausgewählten Nutzer. Hierfür muss das Feature "Server Notices" auf dem Server aktiviert sein.',
},
},
user_media_statistics: {

View File

@@ -12,8 +12,8 @@ const en = {
url_error: "Not a valid Matrix server URL",
},
users: {
invalid_user_id:
"Must be a fully qualified Matrix user-id, e.g. @user_id:homeserver",
invalid_user_id: "Localpart of a Matrix user-id without homeserver.",
tabs: { sso: "SSO" },
},
rooms: {
tabs: {
@@ -119,6 +119,7 @@ const en = {
address: "Address",
creation_ts_ms: "Creation timestamp",
consent_version: "Consent version",
auth_provider: "Provider",
},
helper: {
deactivate: "You must provide a password to re-activate an account.",
@@ -254,8 +255,26 @@ const en = {
send_failure: "An error has occurred.",
},
helper: {
send:
"This API deletes the local media from the disk of your own server. This includes any local thumbnails and copies of media downloaded. This API will not affect media that has been uploaded to external media repositories.",
send: "This API deletes the local media from the disk of your own server. This includes any local thumbnails and copies of media downloaded. This API will not affect media that has been uploaded to external media repositories.",
},
},
protect_media: {
action: {
create: "Unprotected, create protection",
delete: "Protected, remove protection",
none: "In quarantine",
send_success: "Successfully changed the protection status.",
send_failure: "An error has occurred.",
},
},
quarantine_media: {
action: {
name: "Quarantine",
create: "Add to quarantine",
delete: "In quarantine, unquarantine",
none: "Protected from quarantine",
send_success: "Successfully changed the quarantine status.",
send_failure: "An error has occurred.",
},
},
pushers: {
@@ -284,8 +303,7 @@ const en = {
send_failure: "An error has occurred.",
},
helper: {
send:
'Sends a server notice to the selected users. The feature "Server Notices" has to be activated at the server.',
send: 'Sends a server notice to the selected users. The feature "Server Notices" has to be activated at the server.',
},
},
user_media_statistics: {

View File

@@ -245,8 +245,7 @@ const zh = {
send_failure: "出现了一个错误。",
},
helper: {
send:
"这个API会删除您硬盘上的本地媒体。包含了任何的本地缓存和下载的媒体备份。这个API不会影响上传到外部媒体存储库上的媒体文件。",
send: "这个API会删除您硬盘上的本地媒体。包含了任何的本地缓存和下载的媒体备份。这个API不会影响上传到外部媒体存储库上的媒体文件。",
},
},
pushers: {
@@ -275,8 +274,7 @@ const zh = {
send_failure: "出现了一个错误。",
},
helper: {
send:
'向选中的用户发送服务器提示。服务器配置中的 "服务器提示(Server Notices)" 选项需要被设置为启用。',
send: '向选中的用户发送服务器提示。服务器配置中的 "服务器提示(Server Notices)" 选项需要被设置为启用。',
},
},
user_media_statistics: {

View File

@@ -41,7 +41,9 @@ const resourceMap = {
data: "users",
total: json => json.total,
create: data => ({
endpoint: `/_synapse/admin/v2/users/${data.id}`,
endpoint: `/_synapse/admin/v2/users/@${data.id}:${localStorage.getItem(
"home_server"
)}`,
body: data,
method: "PUT",
}),
@@ -182,6 +184,32 @@ const resourceMap = {
method: "POST",
}),
},
protect_media: {
map: pm => ({ id: pm.media_id }),
create: params => ({
endpoint: `/_synapse/admin/v1/media/protect/${params.media_id}`,
method: "POST",
}),
delete: params => ({
endpoint: `/_synapse/admin/v1/media/unprotect/${params.media_id}`,
method: "POST",
}),
},
quarantine_media: {
map: qm => ({ id: qm.media_id }),
create: params => ({
endpoint: `/_synapse/admin/v1/media/quarantine/${localStorage.getItem(
"home_server"
)}/${params.media_id}`,
method: "POST",
}),
delete: params => ({
endpoint: `/_synapse/admin/v1/media/unquarantine/${localStorage.getItem(
"home_server"
)}/${params.media_id}`,
method: "POST",
}),
},
servernotices: {
map: n => ({ id: n.event_id }),
create: data => ({

3668
yarn.lock

File diff suppressed because it is too large Load Diff