108 Commits

Author SHA1 Message Date
d6749b413a 更新 'src/synapse/dataProvider.js' 2022-07-09 15:20:06 +08:00
d8df2fa2e8 更新 'src/synapse/dataProvider.js' 2022-07-09 14:54:05 +08:00
cef7e31cb2 更新 'src/i18n/zh.js' 2022-07-09 14:37:58 +08:00
b2d1dc0be1 更新 'src/components/users.js' 2022-07-09 14:34:45 +08:00
72bc40f322 更新 'src/synapse/dataProvider.js' 2022-07-09 14:25:55 +08:00
44b9aca138 更新 'src/synapse/dataProvider.js' 2022-07-09 14:21:33 +08:00
ab673a91a1 更新 'src/components/rooms.js' 2022-07-09 14:20:08 +08:00
e2ecf90f66 更新 'src/components/users.js' 2022-07-09 14:18:20 +08:00
1ac7d8d87b 更新 'src/App.js' 2022-07-09 14:16:28 +08:00
7914caa70e 更新 'src/components/users.js' 2022-07-09 14:15:10 +08:00
24952cba56 更新 'src/synapse/dataProvider.js' 2022-07-09 14:13:50 +08:00
6f26a31604 更新 'src/synapse/dataProvider.js' 2022-07-09 14:10:09 +08:00
dbb9a7f547 更新 'src/components/users.js' 2022-07-09 14:07:42 +08:00
705244b4fc 更新 'src/synapse/dataProvider.js' 2022-07-09 11:05:56 +08:00
46259d3740 更新 'src/synapse/dataProvider.js' 2022-07-09 10:43:40 +08:00
4772083040 更新 'src/synapse/dataProvider.js' 2022-07-09 10:23:28 +08:00
61e4444727 更新 'src/synapse/dataProvider.js' 2022-07-09 10:20:21 +08:00
df57f5f908 更新 'src/synapse/dataProvider.js' 2022-07-09 10:12:46 +08:00
94d8bb2772 更新 'src/components/users.js' 2022-07-09 10:10:43 +08:00
e6f7f1d591 更新 'src/synapse/dataProvider.js' 2022-07-09 10:09:12 +08:00
de7e8d1ff3 更新 'src/App.js' 2022-07-09 10:05:50 +08:00
317de6ce80 更新 'src/components/users.js' 2022-07-09 10:04:54 +08:00
f74249073a 更新 'src/synapse/dataProvider.js' 2022-07-09 10:04:05 +08:00
33dcd46f74 更新 'src/components/users.js' 2022-07-09 09:59:13 +08:00
2ab4ab66e3 更新 'src/components/users.js' 2022-07-09 09:56:42 +08:00
3410deb510 更新 'src/components/users.js' 2022-07-09 09:44:42 +08:00
b1c35b670f 更新 'src/components/rooms.js' 2022-07-09 09:44:34 +08:00
39dea09895 更新 'src/components/users.js' 2022-07-09 09:26:50 +08:00
8804bdc94d 更新 'src/i18n/zh.js' 2022-07-09 08:22:08 +08:00
36bf2dff3e 更新 'src/synapse/dataProvider.js' 2022-07-07 12:01:58 +08:00
0958f376a9 更新 'src/synapse/dataProvider.js' 2022-07-07 11:59:08 +08:00
f287555d53 更新 'src/App.js' 2022-07-07 11:56:24 +08:00
b66a4596e4 更新 'src/components/rooms.js' 2022-07-07 11:54:31 +08:00
4ff83bf261 更新 'src/synapse/dataProvider.js' 2022-07-07 11:48:21 +08:00
c79453f4f4 更新 'src/components/rooms.js' 2022-07-07 11:12:09 +08:00
149c8590c2 更新 'src/synapse/dataProvider.js' 2022-07-07 11:08:21 +08:00
eefd5796d0 更新 'src/components/rooms.js' 2022-07-07 09:48:03 +08:00
2b712e5bd9 更新 'src/components/rooms.js' 2022-07-07 09:46:28 +08:00
26014820dc 更新 'src/components/rooms.js' 2022-07-07 09:43:48 +08:00
fbb82c99a5 更新 'src/i18n/zh.js' 2022-07-07 09:43:38 +08:00
27655602da 更新 'src/components/rooms.js' 2022-07-07 09:38:16 +08:00
dcf6dbe8ae 更新 'src/components/users.js' 2022-07-06 21:30:37 +08:00
216a23cbb2 更新 'src/components/users.js' 2022-07-06 21:27:18 +08:00
e83087444c 更新 'src/components/users.js' 2022-07-06 21:25:53 +08:00
07bb80a1e6 更新 'src/components/users.js' 2022-07-06 21:22:07 +08:00
fdb43c9193 更新 'src/components/users.js' 2022-07-06 21:18:37 +08:00
2c002afe8e 更新 'src/synapse/dataProvider.js' 2022-07-06 21:17:43 +08:00
29aa686e70 更新 'src/components/users.js' 2022-07-06 21:15:49 +08:00
edd7f12e5d 更新 'src/synapse/dataProvider.js' 2022-07-06 20:40:23 +08:00
c5b73a222c 更新 'src/synapse/dataProvider.js' 2022-07-06 20:33:36 +08:00
5b6edfbf11 更新 'src/synapse/dataProvider.js' 2022-07-06 20:31:49 +08:00
573857ed4a 更新 'src/components/users.js' 2022-07-06 20:30:51 +08:00
9b1e3dbfd2 更新 'src/components/users.js' 2022-07-06 20:26:42 +08:00
e78c2bedaa 更新 'src/i18n/zh.js' 2022-07-06 20:23:16 +08:00
0872e31411 更新 'src/components/users.js' 2022-07-06 20:18:36 +08:00
84a253f50b 更新 'src/components/users.js' 2022-07-06 20:16:25 +08:00
0726dc788d 更新 'src/components/users.js' 2022-07-06 20:08:09 +08:00
b9501c77f0 更新 'src/i18n/zh.js' 2022-07-06 20:04:17 +08:00
558ed60bb4 更新 'src/i18n/zh.js' 2022-07-06 19:54:36 +08:00
2197356a1e 更新 'src/i18n/zh.js' 2022-07-06 19:52:29 +08:00
96c718e45f 更新 'src/i18n/zh.js' 2022-07-06 19:51:11 +08:00
339848e117 更新 'src/i18n/zh.js' 2022-07-06 19:44:06 +08:00
7faf321346 更新 'src/i18n/zh.js' 2022-07-06 19:41:37 +08:00
5cdd110bf1 更新 'src/i18n/zh.js' 2022-07-06 19:35:31 +08:00
9a05dfee7a 更新 'src/i18n/zh.js' 2022-07-06 19:29:08 +08:00
9110a8ac99 更新 'README.md' 2022-07-06 17:19:07 +08:00
Dirk Klimpel
0b153ddcbb Update README.md
Co-authored-by: Dominik Fuchß <develop@fuchss.org>
2022-05-23 14:07:49 +02:00
Dirk Klimpel
784c284723 Add note to GH pages 2022-05-23 14:07:49 +02:00
dependabot[bot]
e5f73ea8b4 Bump minimist from 1.2.5 to 1.2.6
Bumps [minimist](https://github.com/substack/minimist) from 1.2.5 to 1.2.6.
- [Release notes](https://github.com/substack/minimist/releases)
- [Commits](https://github.com/substack/minimist/compare/1.2.5...1.2.6)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-23 14:07:01 +02:00
dependabot[bot]
96551259c5 Bump cross-fetch from 3.1.4 to 3.1.5
Bumps [cross-fetch](https://github.com/lquixada/cross-fetch) from 3.1.4 to 3.1.5.
- [Release notes](https://github.com/lquixada/cross-fetch/releases)
- [Commits](https://github.com/lquixada/cross-fetch/compare/v3.1.4...v3.1.5)

---
updated-dependencies:
- dependency-name: cross-fetch
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-23 14:06:50 +02:00
dependabot[bot]
b2fa533ef0 Bump async from 2.6.3 to 2.6.4
Bumps [async](https://github.com/caolan/async) from 2.6.3 to 2.6.4.
- [Release notes](https://github.com/caolan/async/releases)
- [Changelog](https://github.com/caolan/async/blob/v2.6.4/CHANGELOG.md)
- [Commits](https://github.com/caolan/async/compare/v2.6.3...v2.6.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-23 14:06:40 +02:00
Leon Schmidt
7aa0f9f50d Make PUBLIC_URL and REACT_APP_SERVER configurable (#266)
* Adjust Dockerfile to include args in build process
* Adjust README.md
2022-05-23 14:06:04 +02:00
Dirk Klimpel
5aa90c25f7 Add path to rooms tab "members" (#232) 2022-03-22 19:11:12 +01:00
dependabot[bot]
38d58db08d Bump url-parse from 1.5.7 to 1.5.10 (#253)
Bumps [url-parse](https://github.com/unshiftio/url-parse) from 1.5.7 to 1.5.10.
- [Release notes](https://github.com/unshiftio/url-parse/releases)
- [Commits](https://github.com/unshiftio/url-parse/compare/1.5.7...1.5.10)

---
updated-dependencies:
- dependency-name: url-parse
  dependency-type: indirect
...

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-22 18:17:18 +01:00
Dirk Klimpel
e637df232a Upgrade react-admin to ^3.19.7 (#241) 2022-03-22 18:13:01 +01:00
Dirk Klimpel
d97c633cd0 Remove not needed {" "} from EventReports (#235) 2022-03-22 17:59:48 +01:00
Dirk Klimpel
b02396c61f disableReordering in users' SimpleFormIterator (#219) 2022-03-22 17:58:28 +01:00
Michael Albert
95de50b925 Bump version to 0.8.5
Change-Id: I8c8f0af01d693bb76dbf706a92fdd4dfa6ba9a8b
2022-02-17 20:56:27 +01:00
dependabot[bot]
1a150a10fd Bump url-parse from 1.5.3 to 1.5.7 (#244)
Bumps [url-parse](https://github.com/unshiftio/url-parse) from 1.5.3 to 1.5.7.
- [Release notes](https://github.com/unshiftio/url-parse/releases)
- [Commits](https://github.com/unshiftio/url-parse/compare/1.5.3...1.5.7)

---
updated-dependencies:
- dependency-name: url-parse
  dependency-type: indirect
...

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-17 20:53:56 +01:00
Dirk Klimpel
158e7dbe98 Move date format to a constant in EventReports.js (#237) 2022-02-17 20:52:13 +01:00
Dirk Klimpel
a642f11503 Fix typo notification in german language file (#233) 2022-02-17 20:51:42 +01:00
Dirk Klimpel
888a3f001b Move date format to a constant in rooms.js (#238) 2022-02-17 20:51:11 +01:00
Dirk Klimpel
4b0845bee8 Move date format to a constant in users.js (#223)
* Move date format to a constant in `users.js`

* yarn prettier
2022-02-17 20:50:38 +01:00
Dirk Klimpel
f449e3277a Replace deprecated fade in devices.js (#220) 2022-02-17 20:49:34 +01:00
Dirk Klimpel
3303f253b4 Replace deprecated fade in media.js (#221) 2022-02-17 20:49:19 +01:00
dependabot[bot]
0250954ee7 Bump follow-redirects from 1.14.7 to 1.14.8 (#243)
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.14.7 to 1.14.8.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.14.7...v1.14.8)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-17 20:45:37 +01:00
Dirk Klimpel
efed8b2774 Add token based registration creation and management (#200)
* Add token based registration creation and management

* yarn fix

* Apply suggestions from code review

Remove empty line

* move date to `const date_format`
2022-02-17 20:45:21 +01:00
Nya Candy
c891afa611 feat: support SSO login (#196)
* feat: support SSO login

* fix: lint

* fix: add back homeserver force protection

* fix: add back login notice

* fix: simplify login options
2022-02-17 20:24:46 +01:00
Michael Albert
38541b8f02 Fix english translation for room deletion
Change-Id: I5bb02e64832902a79379d66c77d3128169d3fca8
2022-02-17 20:15:49 +01:00
Dirk Klimpel
0f4c382c18 Remove not needed translation backtolist (#208) 2022-01-31 17:50:14 +01:00
Dirk Klimpel
b90d4ef00f Add more headlines for installation to README (#216) 2022-01-31 17:39:18 +01:00
Dominik Fuchß
3fb33facc5 GitHub Pages Deploy (#189)
* Create edge_ghpage.yml

Added Build and Deploy Edge version to GH Pages

* Update edge_ghpage.yml

Added missing node setup

* Update edge_ghpage.yml

Restrict building of GH Pages to main / master branch & workflow dispatch

* Update .github/workflows/edge_ghpage.yml

Co-authored-by: Dirk Klimpel <5740567+dklimpel@users.noreply.github.com>

* Update .github/workflows/edge_ghpage.yml

Co-authored-by: Dirk Klimpel <5740567+dklimpel@users.noreply.github.com>

* Update .github/workflows/edge_ghpage.yml

Co-authored-by: Dirk Klimpel <5740567+dklimpel@users.noreply.github.com>

* Update .github/workflows/edge_ghpage.yml

Co-authored-by: Dirk Klimpel <5740567+dklimpel@users.noreply.github.com>

Co-authored-by: Dirk Klimpel <5740567+dklimpel@users.noreply.github.com>
2022-01-31 17:38:34 +01:00
Dirk Klimpel
c4a68ff1d5 Fix typo in .prettierrc (#224) 2022-01-31 17:24:37 +01:00
dependabot[bot]
c4f0fa48ec Bump nanoid from 3.1.30 to 3.2.0 (#229)
Bumps [nanoid](https://github.com/ai/nanoid) from 3.1.30 to 3.2.0.
- [Release notes](https://github.com/ai/nanoid/releases)
- [Changelog](https://github.com/ai/nanoid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ai/nanoid/compare/3.1.30...3.2.0)

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

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-31 17:20:39 +01:00
dependabot[bot]
26ed63d65e Bump follow-redirects from 1.14.6 to 1.14.7 (#227)
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.14.6 to 1.14.7.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.14.6...v1.14.7)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-31 17:20:29 +01:00
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
23 changed files with 2259 additions and 1905 deletions

View File

@@ -2,8 +2,14 @@ name: Create docker image(s) and push to docker hub
on:
push:
tags:
- '[0-9]+\.[0-9]+\.[0-9]+'
# 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:
@@ -21,16 +27,25 @@ jobs:
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push
- 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: .
platforms: linux/amd64,linux/arm64
push: true
tags: awesometechnologies/synapse-admin:latest
- name: Update repo description
uses: peter-evans/dockerhub-description@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
repository: awesometechnologies/synapse-admin
tags: "awesometechnologies/synapse-admin:${{ steps.set-tag.outputs.tag }}"
platforms: linux/amd64,linux/arm64

26
.github/workflows/edge_ghpage.yml vendored Normal file
View File

@@ -0,0 +1,26 @@
name: Build and Deploy Edge version to GH Pages
on:
workflow_dispatch:
push:
branches:
- main
- master
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout 🛎️
uses: actions/checkout@v2.3.1
- uses: actions/setup-node@v2
with:
node-version: "14"
- name: Install and Build 🔧
run: |
yarn install
yarn build
- name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@4.1.5
with:
branch: gh-pages
folder: build

View File

@@ -8,6 +8,9 @@ on:
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: write
packages: write
steps:
- uses: actions/checkout@v2

View File

@@ -7,5 +7,5 @@
"trailingComma": "es5",
"bracketSpacing": true,
"jsxBracketSameLine": false,
"arrowParens": "avoid",
"arrowParens": "avoid"
}

View File

@@ -1,11 +1,14 @@
# Builder
FROM node:current as builder
FROM node:lts as builder
ARG PUBLIC_URL=/
ARG REACT_APP_SERVER
WORKDIR /src
COPY . /src
RUN yarn --network-timeout=100000 install
RUN yarn build
RUN PUBLIC_URL=$PUBLIC_URL REACT_APP_SERVER=$REACT_APP_SERVER yarn build
# App

View File

@@ -5,13 +5,33 @@
This project is built using [react-admin](https://marmelab.com/react-admin/).
It needs at least Synapse v1.38.0 for all functions to work as expected!
```
curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -
## Run `sudo apt-get install -y nodejs` to install Node.js 14.x and npm
## You may also need development tools to build native addons:
sudo apt-get install gcc g++ make
## To install the Yarn package manager, run:
curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --dearmor | sudo tee /usr/share/keyrings/yarnkey.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/yarnkey.gpg] https://dl.yarnpkg.com/debian stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo apt-get update && sudo apt-get install yarn
```
## Usage
### Supported Synapse
It needs at least [Synapse](https://github.com/matrix-org/synapse) v1.42.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://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.
### Prerequisites
You need access to the following endpoints:
- `/_matrix`
@@ -19,15 +39,25 @@ You need access to the following endpoints:
See also [Synapse administration endpoints](https://matrix-org.github.io/synapse/develop/reverse_proxy.html#synapse-administration-endpoints)
## Step-By-Step install:
### 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/).
**Note:**
If you want to use the deployment, you have to make sure that the admin endpoints (`/_synapse/admin`) are accessible for your browser.
**Remember: You have no need to expose these endpoints to the internet but to your network.**
If you want your own deployment, follow the [Step-By-Step Install Guide](#step-by-step-install) below.
### Step-By-Step install
You have three options:
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
1. [Download the tarball and serve with any webserver](#steps-for-1)
2. [Download the source code from github and run using nodejs](#steps-for-2)
3. [Run the Docker container](#steps-for-3)
Steps for 1):
#### 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
@@ -36,7 +66,7 @@ Steps for 1):
- 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):
#### 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`
@@ -49,7 +79,7 @@ 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 3):
#### 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`
@@ -66,6 +96,9 @@ Steps for 3):
context: https://github.com/Awesome-Technologies/synapse-admin.git
# args:
# - NODE_OPTIONS="--max_old_space_size=1024"
# # see #266
# - PUBLIC_URL="/synapse-admin"
# - REACT_APP_SERVER="https://matrix.example.com"
ports:
- "8080:80"
restart: unless-stopped

View File

@@ -1,6 +1,6 @@
{
"name": "synapse-admin",
"version": "0.8.3",
"version": "0.8.5",
"description": "Admin GUI for the Matrix.org server Synapse",
"author": "Awesome Technologies Innovationslabor GmbH",
"license": "Apache-2.0",
@@ -26,7 +26,7 @@
"ra-language-chinese": "^2.0.10",
"ra-language-german": "^3.13.4",
"react": "^17.0.0",
"react-admin": "^3.15.0",
"react-admin": "^3.19.7",
"react-dom": "^17.0.2",
"react-scripts": "^4.0.0"
},

View File

@@ -8,12 +8,18 @@ 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 ConfirmationNumberIcon from "@material-ui/icons/ConfirmationNumber";
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 FolderSharedIcon from "@material-ui/icons/FolderShared";
import { ImportFeature } from "./components/ImportFeature";
import {
RegistrationTokenCreate,
RegistrationTokenEdit,
RegistrationTokenList,
} from "./components/RegistrationTokens";
import { RoomDirectoryList } from "./components/RoomDirectory";
import { Route } from "react-router-dom";
import germanMessages from "./i18n/de";
@@ -66,6 +72,13 @@ const App = () => (
list={RoomDirectoryList}
icon={FolderSharedIcon}
/>
<Resource
name="registration_tokens"
list={RegistrationTokenList}
create={RegistrationTokenCreate}
edit={RegistrationTokenEdit}
icon={ConfirmationNumberIcon}
/>
<Resource name="connections" />
<Resource name="devices" />
<Resource name="room_members" />
@@ -75,6 +88,7 @@ const App = () => (
<Resource name="servernotices" />
<Resource name="forward_extremities" />
<Resource name="room_state" />
<Resource name="user_urlpreview" />
</Admin>
);

View File

@@ -15,6 +15,15 @@ import {
import PageviewIcon from "@material-ui/icons/Pageview";
import ViewListIcon from "@material-ui/icons/ViewList";
const date_format = {
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
};
const ReportPagination = props => (
<Pagination {...props} rowsPerPageOptions={[10, 25, 50, 100, 500, 1000]} />
);
@@ -33,14 +42,7 @@ export const ReportShow = props => {
<DateField
source="received_ts"
showTime
options={{
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
}}
options={date_format}
sortable={true}
/>
<ReferenceField source="user_id" reference="users">
@@ -68,18 +70,10 @@ export const ReportShow = props => {
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",
}}
options={date_format}
sortable={true}
/>
<ReferenceField source="sender" reference="users">
@@ -116,14 +110,7 @@ export const ReportList = ({ ...props }) => {
<DateField
source="received_ts"
showTime
options={{
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
}}
options={date_format}
sortable={true}
/>
<TextField sortable={false} source="user_id" />

View File

@@ -78,11 +78,48 @@ const LoginPage = ({ theme }) => {
const login = useLogin();
const notify = useNotify();
const [loading, setLoading] = useState(false);
const [supportPassAuth, setSupportPassAuth] = useState(true);
var locale = useLocale();
const setLocale = useSetLocale();
const translate = useTranslate();
const base_url = localStorage.getItem("base_url");
const cfg_base_url = process.env.REACT_APP_SERVER;
const [ssoBaseUrl, setSSOBaseUrl] = useState("");
const loginToken = /\?loginToken=([a-zA-Z0-9_-]+)/.exec(window.location.href);
if (loginToken) {
const ssoToken = loginToken[1];
console.log("SSO token is", ssoToken);
// Prevent further requests
window.history.replaceState(
{},
"",
window.location.href.replace(loginToken[0], "#").split("#")[0]
);
const baseUrl = localStorage.getItem("sso_base_url");
localStorage.removeItem("sso_base_url");
if (baseUrl) {
const auth = {
base_url: baseUrl,
username: null,
password: null,
loginToken: ssoToken,
};
console.log("Base URL is:", baseUrl);
console.log("SSO Token is:", ssoToken);
console.log("Let's try token login...");
login(auth).catch(error => {
alert(
typeof error === "string"
? error
: typeof error === "undefined" || !error.message
? "ra.auth.sign_in_error"
: error.message
);
console.error(error);
});
}
}
const renderInput = ({
meta: { touched, error } = {},
@@ -137,6 +174,14 @@ const LoginPage = ({ theme }) => {
});
};
const handleSSO = () => {
localStorage.setItem("sso_base_url", ssoBaseUrl);
const ssoFullUrl = `${ssoBaseUrl}/_matrix/client/r0/login/sso/redirect?redirectUrl=${encodeURIComponent(
window.location.href
)}`;
window.location.href = ssoFullUrl;
};
const extractHomeServer = username => {
const usernameRegex = /@[a-zA-Z0-9._=\-/]+:([a-zA-Z0-9\-.]+\.[a-zA-Z]+)/;
if (!username) return null;
@@ -188,6 +233,31 @@ const LoginPage = ({ theme }) => {
.catch(_ => {
setServerVersion("");
});
// Set SSO Url
const authMethodUrl = `${formData.base_url}/_matrix/client/r0/login`;
let supportPass = false,
supportSSO = false;
fetchUtils
.fetchJson(authMethodUrl, { method: "GET" })
.then(({ json }) => {
json.flows.forEach(f => {
if (f.type === "m.login.password") {
supportPass = true;
} else if (f.type === "m.login.sso") {
supportSSO = true;
}
});
setSupportPassAuth(supportPass);
if (supportSSO) {
setSSOBaseUrl(formData.base_url);
} else {
setSSOBaseUrl("");
}
})
.catch(_ => {
setSSOBaseUrl("");
});
},
[formData.base_url]
);
@@ -200,7 +270,7 @@ const LoginPage = ({ theme }) => {
name="username"
component={renderInput}
label={translate("ra.auth.username")}
disabled={loading}
disabled={loading || !supportPassAuth}
onBlur={handleUsernameChange}
resettable
fullWidth
@@ -212,7 +282,7 @@ const LoginPage = ({ theme }) => {
component={renderInput}
label={translate("ra.auth.password")}
type="password"
disabled={loading}
disabled={loading || !supportPassAuth}
resettable
fullWidth
/>
@@ -273,13 +343,24 @@ const LoginPage = ({ theme }) => {
variant="contained"
type="submit"
color="primary"
disabled={loading}
disabled={loading || !supportPassAuth}
className={classes.button}
fullWidth
>
{loading && <CircularProgress size={25} thickness={2} />}
{translate("ra.auth.sign_in")}
</Button>
<Button
variant="contained"
color="secondary"
onClick={handleSSO}
disabled={loading || ssoBaseUrl === ""}
className={classes.button}
fullWidth
>
{loading && <CircularProgress size={25} thickness={2} />}
{translate("synapseadmin.auth.sso_sign_in")}
</Button>
</CardActions>
</Card>
<Notification />

View File

@@ -0,0 +1,132 @@
import React from "react";
import {
BooleanInput,
Create,
Datagrid,
DateField,
DateTimeInput,
Edit,
Filter,
List,
maxValue,
number,
NumberField,
NumberInput,
regex,
SimpleForm,
TextInput,
TextField,
Toolbar,
} from "react-admin";
const date_format = {
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
};
const validateToken = [regex(/^[A-Za-z0-9._~-]{0,64}$/)];
const validateUsesAllowed = [number()];
const validateLength = [number(), maxValue(64)];
const dateParser = v => {
const d = new Date(v);
if (isNaN(d)) return 0;
return d.getTime();
};
const dateFormatter = v => {
if (v === undefined || v === null) return;
const d = new Date(v);
const pad = "00";
const year = d.getFullYear().toString();
const month = (pad + (d.getMonth() + 1).toString()).slice(-2);
const day = (pad + d.getDate().toString()).slice(-2);
const hour = (pad + d.getHours().toString()).slice(-2);
const minute = (pad + d.getMinutes().toString()).slice(-2);
// target format yyyy-MM-ddThh:mm
return `${year}-${month}-${day}T${hour}:${minute}`;
};
const RegistrationTokenFilter = props => (
<Filter {...props}>
<BooleanInput source="valid" alwaysOn />
</Filter>
);
export const RegistrationTokenList = props => {
return (
<List
{...props}
filters={<RegistrationTokenFilter />}
filterDefaultValues={{ valid: true }}
pagination={false}
perPage={500}
>
<Datagrid rowClick="edit">
<TextField source="token" sortable={false} />
<NumberField source="uses_allowed" sortable={false} />
<NumberField source="pending" sortable={false} />
<NumberField source="completed" sortable={false} />
<DateField
source="expiry_time"
showTime
options={date_format}
sortable={false}
/>
</Datagrid>
</List>
);
};
export const RegistrationTokenCreate = props => (
<Create {...props}>
<SimpleForm redirect="list" toolbar={<Toolbar alwaysEnableSaveButton />}>
<TextInput
source="token"
autoComplete="off"
validate={validateToken}
resettable
/>
<NumberInput
source="length"
validate={validateLength}
helperText="resources.registration_tokens.helper.length"
step={1}
/>
<NumberInput
source="uses_allowed"
validate={validateUsesAllowed}
step={1}
/>
<DateTimeInput source="expiry_time" parse={dateParser} />
</SimpleForm>
</Create>
);
export const RegistrationTokenEdit = props => {
return (
<Edit {...props}>
<SimpleForm>
<TextInput source="token" disabled />
<NumberInput source="pending" disabled />
<NumberInput source="completed" disabled />
<NumberInput
source="uses_allowed"
validate={validateUsesAllowed}
step={1}
/>
<DateTimeInput
source="expiry_time"
parse={dateParser}
format={dateFormatter}
/>
</SimpleForm>
</Edit>
);
};

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

@@ -8,7 +8,7 @@ import {
} from "react-admin";
import ActionDelete from "@material-ui/icons/Delete";
import { makeStyles } from "@material-ui/core/styles";
import { fade } from "@material-ui/core/styles/colorManipulator";
import { alpha } from "@material-ui/core/styles/colorManipulator";
import classnames from "classnames";
const useStyles = makeStyles(
@@ -16,7 +16,7 @@ const useStyles = makeStyles(
deleteButton: {
color: theme.palette.error.main,
"&:hover": {
backgroundColor: fade(theme.palette.error.main, 0.12),
backgroundColor: alpha(theme.palette.error.main, 0.12),
// Reset on mouse devices
"@media (hover: none)": {
backgroundColor: "transparent",

View File

@@ -1,6 +1,6 @@
import React, { Fragment, useState } from "react";
import classnames from "classnames";
import { fade } from "@material-ui/core/styles/colorManipulator";
import { alpha } from "@material-ui/core/styles/colorManipulator";
import { makeStyles } from "@material-ui/core/styles";
import { Tooltip } from "@material-ui/core";
import {
@@ -33,7 +33,7 @@ const useStyles = makeStyles(
deleteButton: {
color: theme.palette.error.main,
"&:hover": {
backgroundColor: fade(theme.palette.error.main, 0.12),
backgroundColor: alpha(theme.palette.error.main, 0.12),
// Reset on mouse devices
"@media (hover: none)": {
backgroundColor: "transparent",

View File

@@ -34,6 +34,7 @@ import UserIcon from "@material-ui/icons/Group";
import ViewListIcon from "@material-ui/icons/ViewList";
import VisibilityIcon from "@material-ui/icons/Visibility";
import EventIcon from "@material-ui/icons/Event";
import {
RoomDirectoryBulkDeleteButton,
RoomDirectoryBulkSaveButton,
@@ -41,6 +42,15 @@ import {
RoomDirectorySaveButton,
} from "./RoomDirectory";
const date_format = {
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
};
const useStyles = makeStyles(theme => ({
helper_forward_extremities: {
fontFamily: "Roboto, Helvetica, Arial, sans-serif",
@@ -149,7 +159,11 @@ export const RoomShow = props => {
/>
</Tab>
<Tab label="synapseadmin.rooms.tabs.members" icon={<UserIcon />}>
<Tab
label="synapseadmin.rooms.tabs.members"
icon={<UserIcon />}
path="members"
>
<ReferenceManyField
reference="room_members"
target="room_id"
@@ -247,14 +261,7 @@ export const RoomShow = props => {
<DateField
source="origin_server_ts"
showTime
options={{
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
}}
options={date_format}
sortable={false}
/>
<TextField source="content" sortable={false} />
@@ -287,14 +294,7 @@ export const RoomShow = props => {
<DateField
source="received_ts"
showTime
options={{
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
}}
options={date_format}
sortable={false}
/>
<NumberField source="depth" sortable={false} />
@@ -302,6 +302,8 @@ export const RoomShow = props => {
</Datagrid>
</ReferenceManyField>
</Tab>
</TabbedShowLayout>
</Show>
);
@@ -315,7 +317,7 @@ const RoomBulkActionButtons = props => (
{...props}
confirmTitle="resources.rooms.action.erase.title"
confirmContent="resources.rooms.action.erase.content"
undoable={false}
mutationMode="pessimistic"
/>
</Fragment>
);

View File

@@ -9,6 +9,7 @@ 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,
ArrayField,
@@ -36,7 +37,9 @@ import {
BulkDeleteButton,
DeleteButton,
SaveButton,
maxLength,
regex,
required,
useTranslate,
Pagination,
CreateButton,
@@ -69,6 +72,15 @@ const useStyles = makeStyles({
},
});
const date_format = {
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
};
const UserListActions = ({
currentSort,
className,
@@ -142,7 +154,7 @@ const UserBulkActionButtons = props => (
{...props}
label="resources.users.action.erase"
confirmTitle="resources.users.helper.erase"
undoable={false}
mutationMode="pessimistic"
/>
</Fragment>
);
@@ -174,16 +186,28 @@ 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={date_format}
/>
</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");
@@ -230,7 +254,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", {
@@ -247,19 +271,34 @@ 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>
<SimpleFormIterator disableReordering>
<SelectInput
source="medium"
choices={[
{ 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 disableReordering>
<TextInput source="auth_provider" validate={required()} />
<TextInput
source="external_id"
label="resources.users.fields.id"
validate={required()}
/>
<TextInput source="address" />
</SimpleFormIterator>
</ArrayInput>
</SimpleForm>
@@ -300,18 +339,7 @@ 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",
}}
/>
<DateField source="creation_ts_ms" showTime options={date_format} />
<TextField source="consent_version" />
</FormTab>
@@ -321,7 +349,7 @@ export const UserEdit = props => {
path="threepid"
>
<ArrayInput source="threepids">
<SimpleFormIterator>
<SimpleFormIterator disableReordering>
<SelectInput
source="medium"
choices={[
@@ -339,16 +367,16 @@ export const UserEdit = props => {
icon={<AssignmentIndIcon />}
path="sso"
>
<ArrayField source="external_ids" label={false}>
<Datagrid style={{ width: "100%" }}>
<TextField source="auth_provider" sortable={false} />
<TextField
<ArrayInput source="external_ids" label={false}>
<SimpleFormIterator disableReordering>
<TextInput source="auth_provider" validate={required()} />
<TextInput
source="external_id"
label="resources.users.fields.id"
sortable={false}
validate={required()}
/>
</Datagrid>
</ArrayField>
</SimpleFormIterator>
</ArrayInput>
</FormTab>
<FormTab
@@ -368,14 +396,7 @@ export const UserEdit = props => {
<DateField
source="last_seen_ts"
showTime
options={{
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
}}
options={date_format}
sortable={false}
/>
<DeviceRemoveButton />
@@ -400,23 +421,18 @@ export const UserEdit = props => {
>
<Datagrid style={{ width: "100%" }}>
<TextField source="ip" sortable={false} />
<TextField source="port" sortable={false} emptyText="13001" />
<DateField
source="last_seen"
showTime
options={{
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
}}
options={date_format}
sortable={false}
/>
<TextField
source="user_agent"
sortable={false}
style={{ width: "100%" }}
style={{ width: "90%" }}
/>
</Datagrid>
</ArrayField>
@@ -437,29 +453,11 @@ export const UserEdit = props => {
sort={{ field: "created_ts", order: "DESC" }}
>
<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",
}}
/>
<DateField source="created_ts" showTime options={date_format} />
<DateField
source="last_access_ts"
showTime
options={{
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
}}
options={date_format}
/>
<TextField source="media_id" />
<NumberField source="media_length" />
@@ -473,6 +471,27 @@ export const UserEdit = props => {
</ReferenceManyField>
</FormTab>
<FormTab
label={translate("resources.urlpreview.name", { smart_count: 2 })}
icon={<PermMediaIcon />}
path="user_urlpreview"
>
<ReferenceManyField
reference="user_urlpreview"
target="user_id"
addLabel={false}
pagination={<UserPagination />}
perPage={50}
sort={{ field: "created_ts", order: "DESC" }}
>
<Datagrid style={{ width: "100%" }}>
<DateField source="created_ts" showTime options={date_format} sortable={false} />
<TextField source="media_id" sortable={false} />
<TextField source="url_cache" sortable={false} />
</Datagrid>
</ReferenceManyField>
</FormTab>
<FormTab
label={translate("resources.rooms.name", { smart_count: 2 })}
icon={<ViewListIcon />}

View File

@@ -10,10 +10,10 @@ const de = {
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",
sso_sign_in: "Anmeldung mit SSO",
},
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: {
@@ -97,7 +97,6 @@ const de = {
},
resources: {
users: {
backtolist: "Zurück zur Liste",
name: "Benutzer",
email: "E-Mail",
msisdn: "Telefon",
@@ -353,6 +352,19 @@ const de = {
send_failure: "Beim Entfernen ist ein Fehler aufgetreten.",
},
},
registration_tokens: {
name: "Registrierungstoken",
fields: {
token: "Token",
valid: "Gültige Token",
uses_allowed: "Anzahl",
pending: "Ausstehend",
completed: "Abgeschlossen",
expiry_time: "Ablaufzeit",
length: "Länge",
},
helper: { length: "Länge des Tokens, wenn kein Token vorgegeben wird." },
},
},
ra: {
...germanMessages.ra,
@@ -373,7 +385,7 @@ const de = {
},
},
notification: {
...germanMessages.ra.notifiaction,
...germanMessages.ra.notification,
logged_out: "Abgemeldet",
},
page: {

View File

@@ -10,10 +10,10 @@ const en = {
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",
sso_sign_in: "Sign in with SSO",
},
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: {
@@ -96,7 +96,6 @@ const en = {
},
resources: {
users: {
backtolist: "Back to list",
name: "User |||| Users",
email: "Email",
msisdn: "Phone",
@@ -175,10 +174,12 @@ const en = {
},
unencrypted: "Unencrypted",
},
erase: {
title: "Delete room",
content:
"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!",
action: {
erase: {
title: "Delete room",
content:
"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: {
@@ -350,5 +351,18 @@ const en = {
},
},
},
registration_tokens: {
name: "Registration tokens",
fields: {
token: "Token",
valid: "Valid token",
uses_allowed: "Uses allowed",
pending: "Pending",
completed: "Completed",
expiry_time: "Expiry time",
length: "Length",
},
helper: { length: "Length of the token if no token is given." },
},
};
export default en;

View File

@@ -10,10 +10,12 @@ const zh = {
username_error: "请输入完整有效的用户 ID: '@user:domain'",
protocol_error: "URL 需要以'http://'或'https://'作为起始",
url_error: "不是一个有效的 Matrix 服务器地址",
sso_sign_in: "使用 SSO 登录",
},
users: {
invalid_user_id:
"必须要是一个有效的 Matrix 用户 ID ,例如 @user_id:homeserver",
tabs: { sso: "SSO" },
},
rooms: {
tabs: {
@@ -98,7 +100,6 @@ const zh = {
},
resources: {
users: {
backtolist: "回到列表",
name: "用户",
email: "邮箱",
msisdn: "电话",
@@ -122,6 +123,7 @@ const zh = {
address: "地址",
creation_ts_ms: "创建时间戳",
consent_version: "协议版本",
device_id: "设备ID"
},
helper: {
deactivate: "您必须提供一串密码来激活账户。",
@@ -169,13 +171,16 @@ const zh = {
},
unencrypted: "未加密",
},
helper: {
forward_extremities: "转发"
}
},
reports: {
name: "报事件",
name: "报事件",
fields: {
id: "ID",
received_ts: "报时间",
user_id: "报者",
received_ts: "报时间",
user_id: "报者",
name: "房间名",
score: "分数",
reason: "原因",
@@ -198,7 +203,8 @@ const zh = {
name: "连接",
fields: {
last_seen: "日期",
ip: "IP 地址",
ip: "IP地址",
port: "源端口",
user_agent: "用户代理 (UA)",
},
},
@@ -284,6 +290,29 @@ const zh = {
media_length: "媒体文件长度",
},
},
room_state: {
name: "状态"
},
room_directory:{
name: "目录",
action: {
create: "新建"
}
},
forward_extremities: {
name: "转发"
},
registration_tokens: {
name: "注册"
},
urlpreview: {
name: "第三方链接"
},
quarantine_media: {
action: {
name: "隔离"
}
}
},
};
export default zh;

View File

@@ -2,20 +2,31 @@ import { fetchUtils } from "react-admin";
const authProvider = {
// called when the user attempts to log in
login: ({ base_url, username, password }) => {
login: ({ base_url, username, password, loginToken }) => {
// force homeserver for protection in case the form is manipulated
base_url = process.env.REACT_APP_SERVER || base_url;
console.log("login ");
const options = {
method: "POST",
body: JSON.stringify({
type: "m.login.password",
user: username,
password: password,
device_id: localStorage.getItem("device_id"),
initial_device_display_name: "Synapse Admin",
}),
body: JSON.stringify(
Object.assign(
{
device_id: localStorage.getItem("device_id"),
initial_device_display_name: "Synapse Admin",
},
loginToken
? {
type: "m.login.token",
token: loginToken,
}
: {
type: "m.login.password",
user: username,
password: password,
}
)
),
};
// use the base_url from login instead of the well_known entry from the

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",
}),
@@ -100,7 +102,7 @@ const resourceMap = {
path: "/_synapse/admin/v1/whois",
map: c => ({
...c,
id: c.user_id,
id: c.user_id
}),
data: "connections",
},
@@ -154,6 +156,19 @@ const resourceMap = {
return json.total;
},
},
user_urlpreview: {
map: uu => ({
...uu,
id: uu.media_id,
}),
reference: id => ({
endpoint: `/_synapse/admin/v1/users/${id}/urlpreview`,
}),
data: "urlpreview",
total: json => {
return json.total;
},
},
users_media: {
map: um => ({
...um,
@@ -273,6 +288,25 @@ const resourceMap = {
method: "PUT",
}),
},
registration_tokens: {
path: "/_synapse/admin/v1/registration_tokens",
map: rt => ({
...rt,
id: rt.token,
}),
data: "registration_tokens",
total: json => {
return json.registration_tokens.length;
},
create: params => ({
endpoint: "/_synapse/admin/v1/registration_tokens/new",
body: params,
method: "POST",
}),
delete: params => ({
endpoint: `/_synapse/admin/v1/registration_tokens/${params.id}`,
}),
}
};
function filterNullValues(key, value) {
@@ -294,7 +328,8 @@ function getSearchOrder(order) {
const dataProvider = {
getList: (resource, params) => {
console.log("getList " + resource);
const { user_id, name, guests, deactivated, search_term } = params.filter;
const { user_id, name, guests, deactivated, search_term, valid } =
params.filter;
const { page, perPage } = params.pagination;
const { field, order } = params.sort;
const from = (page - 1) * perPage;
@@ -306,6 +341,7 @@ const dataProvider = {
name: name,
guests: guests,
deactivated: deactivated,
valid: valid,
order_by: field,
dir: getSearchOrder(order),
};

3402
yarn.lock

File diff suppressed because it is too large Load Diff