Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b9e81b2278 | |||
| f6f437b17a | |||
| 91af8f1c04 | |||
| abc9d5154e | |||
| 8228d7d2c2 | |||
| 4adc20f80d | |||
| a5c7d7dd22 | |||
| dc5c2c1d68 | |||
| 42b3252353 | |||
| 1a17d3e69b | |||
| 79ef38ee6b | |||
| 0ff4b30d71 | |||
| 6c4ff6c791 |
@@ -2,8 +2,14 @@ name: Create docker image(s) and push to docker hub
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
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:
|
tags:
|
||||||
- '[0-9]+\.[0-9]+\.[0-9]+'
|
- '[0-9]+\.[0-9]+\.[0-9]+' # Push events to 0.X.X tag
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
docker:
|
docker:
|
||||||
@@ -21,16 +27,25 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
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
|
uses: docker/build-push-action@v2
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
platforms: linux/amd64,linux/arm64
|
|
||||||
push: true
|
push: true
|
||||||
tags: awesometechnologies/synapse-admin:latest
|
tags: "awesometechnologies/synapse-admin:${{ steps.set-tag.outputs.tag }}"
|
||||||
- name: Update repo description
|
platforms: linux/amd64,linux/arm64
|
||||||
uses: peter-evans/dockerhub-description@v2
|
|
||||||
with:
|
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
||||||
repository: awesometechnologies/synapse-admin
|
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
packages: write
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
# Builder
|
# Builder
|
||||||
FROM node:current as builder
|
FROM node:lts as builder
|
||||||
|
|
||||||
WORKDIR /src
|
WORKDIR /src
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
This project is built using [react-admin](https://marmelab.com/react-admin/).
|
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!
|
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`.
|
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).
|
See also [Synapse version API](https://matrix-org.github.io/synapse/develop/admin_api/version_api.html).
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "synapse-admin",
|
"name": "synapse-admin",
|
||||||
"version": "0.8.3",
|
"version": "0.8.4",
|
||||||
"description": "Admin GUI for the Matrix.org server Synapse",
|
"description": "Admin GUI for the Matrix.org server Synapse",
|
||||||
"author": "Awesome Technologies Innovationslabor GmbH",
|
"author": "Awesome Technologies Innovationslabor GmbH",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ export const RoomDirectoryBulkDeleteButton = props => (
|
|||||||
<BulkDeleteButton
|
<BulkDeleteButton
|
||||||
{...props}
|
{...props}
|
||||||
label="resources.room_directory.action.erase"
|
label="resources.room_directory.action.erase"
|
||||||
undoable={false}
|
mutationMode="pessimistic"
|
||||||
confirmTitle="resources.room_directory.action.title"
|
confirmTitle="resources.room_directory.action.title"
|
||||||
confirmContent="resources.room_directory.action.content"
|
confirmContent="resources.room_directory.action.content"
|
||||||
resource="room_directory"
|
resource="room_directory"
|
||||||
@@ -191,7 +191,7 @@ export const FilterableRoomDirectoryList = ({
|
|||||||
filters={<RoomDirectoryFilter />}
|
filters={<RoomDirectoryFilter />}
|
||||||
perPage={100}
|
perPage={100}
|
||||||
>
|
>
|
||||||
<Datagrid>
|
<Datagrid rowClick={(id, basePath, record) => "/rooms/" + id + "/show"}>
|
||||||
<AvatarField
|
<AvatarField
|
||||||
source="avatar_src"
|
source="avatar_src"
|
||||||
sortable={false}
|
sortable={false}
|
||||||
|
|||||||
@@ -24,7 +24,10 @@ const ServerNoticeDialog = ({ open, loading, onClose, onSend }) => {
|
|||||||
|
|
||||||
const ServerNoticeToolbar = props => (
|
const ServerNoticeToolbar = props => (
|
||||||
<Toolbar {...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}>
|
<Button label="ra.action.cancel" onClick={onClose}>
|
||||||
<IconCancel />
|
<IconCancel />
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -315,7 +315,7 @@ const RoomBulkActionButtons = props => (
|
|||||||
{...props}
|
{...props}
|
||||||
confirmTitle="resources.rooms.action.erase.title"
|
confirmTitle="resources.rooms.action.erase.title"
|
||||||
confirmContent="resources.rooms.action.erase.content"
|
confirmContent="resources.rooms.action.erase.content"
|
||||||
undoable={false}
|
mutationMode="pessimistic"
|
||||||
/>
|
/>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
|
|||||||
+52
-16
@@ -36,7 +36,9 @@ import {
|
|||||||
BulkDeleteButton,
|
BulkDeleteButton,
|
||||||
DeleteButton,
|
DeleteButton,
|
||||||
SaveButton,
|
SaveButton,
|
||||||
|
maxLength,
|
||||||
regex,
|
regex,
|
||||||
|
required,
|
||||||
useTranslate,
|
useTranslate,
|
||||||
Pagination,
|
Pagination,
|
||||||
CreateButton,
|
CreateButton,
|
||||||
@@ -142,7 +144,7 @@ const UserBulkActionButtons = props => (
|
|||||||
{...props}
|
{...props}
|
||||||
label="resources.users.action.erase"
|
label="resources.users.action.erase"
|
||||||
confirmTitle="resources.users.helper.erase"
|
confirmTitle="resources.users.helper.erase"
|
||||||
undoable={false}
|
mutationMode="pessimistic"
|
||||||
/>
|
/>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
@@ -174,16 +176,35 @@ export const UserList = props => {
|
|||||||
<BooleanField source="is_guest" />
|
<BooleanField source="is_guest" />
|
||||||
<BooleanField source="admin" />
|
<BooleanField source="admin" />
|
||||||
<BooleanField source="deactivated" />
|
<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>
|
</Datagrid>
|
||||||
</List>
|
</List>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// https://matrix.org/docs/spec/appendices#user-identifiers
|
// https://matrix.org/docs/spec/appendices#user-identifiers
|
||||||
const validateUser = regex(
|
// here only local part of user_id
|
||||||
/^@[a-z0-9._=\-/]+:.*/,
|
// maxLength = 255 - "@" - ":" - localStorage.getItem("home_server").length
|
||||||
"synapseadmin.users.invalid_user_id"
|
// 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() {
|
export function generateRandomUser() {
|
||||||
const homeserver = localStorage.getItem("home_server");
|
const homeserver = localStorage.getItem("home_server");
|
||||||
@@ -230,7 +251,7 @@ const UserEditToolbar = props => {
|
|||||||
const translate = useTranslate();
|
const translate = useTranslate();
|
||||||
return (
|
return (
|
||||||
<Toolbar {...props}>
|
<Toolbar {...props}>
|
||||||
<SaveButton submitOnEnter={true} />
|
<SaveButton submitOnEnter={true} disabled={props.pristine} />
|
||||||
<DeleteButton
|
<DeleteButton
|
||||||
label="resources.users.action.erase"
|
label="resources.users.action.erase"
|
||||||
confirmTitle={translate("resources.users.helper.erase", {
|
confirmTitle={translate("resources.users.helper.erase", {
|
||||||
@@ -247,8 +268,12 @@ export const UserCreate = props => (
|
|||||||
<Create {...props}>
|
<Create {...props}>
|
||||||
<SimpleForm>
|
<SimpleForm>
|
||||||
<TextInput source="id" autoComplete="off" validate={validateUser} />
|
<TextInput source="id" autoComplete="off" validate={validateUser} />
|
||||||
<TextInput source="displayname" />
|
<TextInput source="displayname" validate={maxLength(256)} />
|
||||||
<PasswordInput source="password" autoComplete="new-password" />
|
<PasswordInput
|
||||||
|
source="password"
|
||||||
|
autoComplete="new-password"
|
||||||
|
validate={maxLength(512)}
|
||||||
|
/>
|
||||||
<BooleanInput source="admin" />
|
<BooleanInput source="admin" />
|
||||||
<ArrayInput source="threepids">
|
<ArrayInput source="threepids">
|
||||||
<SimpleFormIterator>
|
<SimpleFormIterator>
|
||||||
@@ -258,8 +283,19 @@ export const UserCreate = props => (
|
|||||||
{ id: "email", name: "resources.users.email" },
|
{ id: "email", name: "resources.users.email" },
|
||||||
{ id: "msisdn", name: "resources.users.msisdn" },
|
{ 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>
|
</SimpleFormIterator>
|
||||||
</ArrayInput>
|
</ArrayInput>
|
||||||
</SimpleForm>
|
</SimpleForm>
|
||||||
@@ -339,16 +375,16 @@ export const UserEdit = props => {
|
|||||||
icon={<AssignmentIndIcon />}
|
icon={<AssignmentIndIcon />}
|
||||||
path="sso"
|
path="sso"
|
||||||
>
|
>
|
||||||
<ArrayField source="external_ids" label={false}>
|
<ArrayInput source="external_ids" label={false}>
|
||||||
<Datagrid style={{ width: "100%" }}>
|
<SimpleFormIterator>
|
||||||
<TextField source="auth_provider" sortable={false} />
|
<TextInput source="auth_provider" validate={required()} />
|
||||||
<TextField
|
<TextInput
|
||||||
source="external_id"
|
source="external_id"
|
||||||
label="resources.users.fields.id"
|
label="resources.users.fields.id"
|
||||||
sortable={false}
|
validate={required()}
|
||||||
/>
|
/>
|
||||||
</Datagrid>
|
</SimpleFormIterator>
|
||||||
</ArrayField>
|
</ArrayInput>
|
||||||
</FormTab>
|
</FormTab>
|
||||||
|
|
||||||
<FormTab
|
<FormTab
|
||||||
|
|||||||
+1
-2
@@ -12,8 +12,7 @@ const de = {
|
|||||||
url_error: "Keine gültige Matrix Server URL",
|
url_error: "Keine gültige Matrix Server URL",
|
||||||
},
|
},
|
||||||
users: {
|
users: {
|
||||||
invalid_user_id:
|
invalid_user_id: "Lokaler Anteil der Matrix Benutzer-ID ohne Homeserver.",
|
||||||
"Muss eine vollständige Matrix Benutzer-ID sein, z.B. @benutzer_id:homeserver",
|
|
||||||
tabs: { sso: "SSO" },
|
tabs: { sso: "SSO" },
|
||||||
},
|
},
|
||||||
rooms: {
|
rooms: {
|
||||||
|
|||||||
+1
-2
@@ -12,8 +12,7 @@ const en = {
|
|||||||
url_error: "Not a valid Matrix server URL",
|
url_error: "Not a valid Matrix server URL",
|
||||||
},
|
},
|
||||||
users: {
|
users: {
|
||||||
invalid_user_id:
|
invalid_user_id: "Localpart of a Matrix user-id without homeserver.",
|
||||||
"Must be a fully qualified Matrix user-id, e.g. @user_id:homeserver",
|
|
||||||
tabs: { sso: "SSO" },
|
tabs: { sso: "SSO" },
|
||||||
},
|
},
|
||||||
rooms: {
|
rooms: {
|
||||||
|
|||||||
@@ -41,7 +41,9 @@ const resourceMap = {
|
|||||||
data: "users",
|
data: "users",
|
||||||
total: json => json.total,
|
total: json => json.total,
|
||||||
create: data => ({
|
create: data => ({
|
||||||
endpoint: `/_synapse/admin/v2/users/${data.id}`,
|
endpoint: `/_synapse/admin/v2/users/@${data.id}:${localStorage.getItem(
|
||||||
|
"home_server"
|
||||||
|
)}`,
|
||||||
body: data,
|
body: data,
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
}),
|
}),
|
||||||
|
|||||||
Reference in New Issue
Block a user