Compare commits

...

19 Commits

Author SHA1 Message Date
Dirk Klimpel 0a616a7a32 Create node.js.yml 2021-06-24 16:24:57 +02:00
Dirk Klimpel 774beb07ec Merge pull request #33 from Awesome-Technologies/master
bring up2date
2021-04-23 08:36:42 +02:00
Lukas Wolfsteiner f8331a459d Add notes about the docker-compose usage
Change-Id: I73c8467ab58caf2082740e682c9175f3eb494a14
2021-04-21 10:51:19 +02:00
Lukas Wolfsteiner a12cf95457 Add docker-compose.yml 2021-04-21 10:51:17 +02:00
dklimpel 60854bcc60 Add button to delete media by size and date 2021-04-21 10:51:14 +02:00
Manuel Stahl 62b3d094b7 yarn: Upgrade packages
- babel: 7.13
- material-ui: 4.11
- prettier: 2.2
- react-admin: 3.14

Change-Id: I26ab6d9d75110f3522282b83cd1131af98b8c43c
2021-04-21 10:50:49 +02:00
dependabot[bot] 81231b5ea6 Bump y18n from 4.0.0 to 4.0.1
Bumps [y18n](https://github.com/yargs/y18n) from 4.0.0 to 4.0.1.
- [Release notes](https://github.com/yargs/y18n/releases)
- [Changelog](https://github.com/yargs/y18n/blob/master/CHANGELOG.md)
- [Commits](https://github.com/yargs/y18n/commits)

Signed-off-by: dependabot[bot] <support@github.com>
2021-04-21 09:35:59 +02:00
dependabot[bot] c114e58278 Bump ssri from 6.0.1 to 6.0.2
Bumps [ssri](https://github.com/npm/ssri) from 6.0.1 to 6.0.2.
- [Release notes](https://github.com/npm/ssri/releases)
- [Changelog](https://github.com/npm/ssri/blob/v6.0.2/CHANGELOG.md)
- [Commits](https://github.com/npm/ssri/compare/v6.0.1...v6.0.2)

Signed-off-by: dependabot[bot] <support@github.com>
2021-04-19 18:23:21 +00:00
Dirk Klimpel c6b6e54617 Fix broken redirect to login page (#116) 2021-03-16 12:13:32 +01:00
Michael Albert 8ff0ac913c Add missing translations
Change-Id: Ie46554bcd10dde771c03e7d3fd0c3639f904429d
2021-03-16 12:12:54 +01:00
dependabot[bot] 96d2c96740 Bump elliptic from 6.5.3 to 6.5.4 (#122)
Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.3 to 6.5.4.
- [Release notes](https://github.com/indutny/elliptic/releases)
- [Commits](https://github.com/indutny/elliptic/compare/v6.5.3...v6.5.4)

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

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

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

* Fix lint
2021-03-02 11:45:05 +01:00
Dirk Klimpel 536ffc2fbf Disable telemetry which was introduced with react-admin v3.11.0 (#109) 2021-03-01 09:26:58 +01:00
Dirk Klimpel e88ee20a19 Merge pull request #29 from Awesome-Technologies/master
import orign/master
2020-12-13 20:56:06 +01:00
Dirk Klimpel 4861835d02 Merge pull request #15 from Awesome-Technologies/master
sync master
2020-05-05 18:15:27 +02:00
Dirk Klimpel f33ad41242 Revert "sync master" (#14)
This reverts commit 36fbd70a42.
2020-05-05 18:14:34 +02:00
Dirk Klimpel 36fbd70a42 sync master 2020-05-04 19:25:22 +02:00
dklimpel e6a1be74de Revert "init"
This reverts commit ca48495bbf.
2020-03-28 21:44:02 +01:00
dklimpel ca48495bbf init 2020-03-28 21:41:38 +01:00
14 changed files with 1925 additions and 1478 deletions
+29
View File
@@ -0,0 +1,29 @@
name: Create release tarball and attach to tag
on:
push:
tags:
- "*"
jobs:
build:
runs-on: ubuntu-latest
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
rm -r synapse-admin-$version
- uses: softprops/action-gh-release@b7e450da2a4b4cb4bfbae528f788167786cfcedf
with:
files: dist/*.tar.gz
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+20 -1
View File
@@ -35,7 +35,26 @@ Steps for 1):
Steps for 2): Steps for 2):
- run the Docker container: `docker run -p 8080:80 awesometechnologies/synapse-admin` - 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.
```yml
version: "3"
services:
synapse-admin:
container_name: synapse-admin
hostname: synapse-admin
build:
context: https://github.com/Awesome-Technologies/synapse-admin.git
# args:
# - NODE_OPTIONS="--max_old_space_size=1024"
ports:
- "8080:80"
restart: unless-stopped
```
- browse to http://localhost:8080 - browse to http://localhost:8080
## Screenshots ## Screenshots
+21
View File
@@ -0,0 +1,21 @@
version: "3"
services:
synapse-admin:
container_name: synapse-admin
hostname: synapse-admin
image: awesometechnologies/synapse-admin:latest
# build:
# context: .
# to use the docker-compose as standalone without a local repo clone,
# replace the context definition with this:
# context: https://github.com/Awesome-Technologies/synapse-admin.git
# if you're building on an architecture other than amd64, make sure
# to define a maximum ram for node. otherwise the build will fail.
# args:
# - NODE_OPTIONS="--max_old_space_size=1024"
ports:
- "8080:80"
restart: unless-stopped
+4 -3
View File
@@ -19,14 +19,15 @@
"eslint-config-prettier": "^6.10.1", "eslint-config-prettier": "^6.10.1",
"eslint-plugin-prettier": "^3.1.2", "eslint-plugin-prettier": "^3.1.2",
"jest-fetch-mock": "^3.0.3", "jest-fetch-mock": "^3.0.3",
"prettier": "^2.0.0" "prettier": "^2.0.0",
"ra-test": "^3.14.0"
}, },
"dependencies": { "dependencies": {
"papaparse": "^5.2.0", "papaparse": "^5.2.0",
"prop-types": "^15.7.2", "prop-types": "^15.7.2",
"ra-language-german": "^2.1.2", "ra-language-german": "^2.1.2",
"react": "^16.13.1", "react": "^17.0.0",
"react-admin": "^3.10.0", "react-admin": "^3.14.0",
"react-dom": "^16.14.0", "react-dom": "^16.14.0",
"react-scripts": "^3.4.4" "react-scripts": "^3.4.4"
}, },
+1
View File
@@ -29,6 +29,7 @@ const i18nProvider = polyglotI18nProvider(
const App = () => ( const App = () => (
<Admin <Admin
disableTelemetry
loginPage={LoginPage} loginPage={LoginPage}
authProvider={authProvider} authProvider={authProvider}
dataProvider={dataProvider} dataProvider={dataProvider}
+1 -1
View File
@@ -1,5 +1,5 @@
import React from "react"; import React from "react";
import { TestContext } from "react-admin"; import { TestContext } from "ra-test";
import { shallow } from "enzyme"; import { shallow } from "enzyme";
import App from "./App"; import App from "./App";
+1 -1
View File
@@ -1,5 +1,5 @@
import React from "react"; import React from "react";
import { TestContext } from "react-admin"; import { TestContext } from "ra-test";
import { shallow } from "enzyme"; import { shallow } from "enzyme";
import LoginPage from "./LoginPage"; import LoginPage from "./LoginPage";
+145
View File
@@ -0,0 +1,145 @@
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 {
BooleanInput,
Button,
DateTimeInput,
NumberInput,
SaveButton,
SimpleForm,
Toolbar,
useDelete,
useNotify,
useTranslate,
} from "react-admin";
import IconCancel from "@material-ui/icons/Cancel";
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";
const useStyles = makeStyles(
theme => ({
deleteButton: {
color: theme.palette.error.main,
"&:hover": {
backgroundColor: fade(theme.palette.error.main, 0.12),
// Reset on mouse devices
"@media (hover: none)": {
backgroundColor: "transparent",
},
},
},
}),
{ name: "RaDeleteDeviceButton" }
);
const DeleteMediaDialog = ({ open, loading, onClose, onSend }) => {
const translate = useTranslate();
const dateParser = v => {
const d = new Date(v);
if (isNaN(d)) return 0;
return d.getTime();
};
const DeleteMediaToolbar = props => {
return (
<Toolbar {...props}>
<SaveButton
label="resources.delete_media.action.send"
icon={<DeleteSweepIcon />}
/>
<Button label="ra.action.cancel" onClick={onClose}>
<IconCancel />
</Button>
</Toolbar>
);
};
return (
<Dialog open={open} onClose={onClose} loading={loading}>
<DialogTitle>
{translate("resources.delete_media.action.send")}
</DialogTitle>
<DialogContent>
<DialogContentText>
{translate("resources.delete_media.helper.send")}
</DialogContentText>
<SimpleForm
toolbar={<DeleteMediaToolbar />}
submitOnEnter={false}
redirect={false}
save={onSend}
>
<DateTimeInput
fullWidth
source="before_ts"
label="resources.delete_media.fields.before_ts"
defaultValue={0}
parse={dateParser}
/>
<NumberInput
fullWidth
source="size_gt"
label="resources.delete_media.fields.size_gt"
defaultValue={0}
min={0}
step={1024}
/>
<BooleanInput
fullWidth
source="keep_profiles"
label="resources.delete_media.fields.keep_profiles"
defaultValue={true}
/>
</SimpleForm>
</DialogContent>
</Dialog>
);
};
export const DeleteMediaButton = props => {
const classes = useStyles(props);
const [open, setOpen] = useState(false);
const notify = useNotify();
const [deleteOne, { loading }] = useDelete("delete_media");
const handleDialogOpen = () => setOpen(true);
const handleDialogClose = () => setOpen(false);
const handleSend = values => {
deleteOne(
{ payload: { ...values } },
{
onSuccess: () => {
notify("resources.delete_media.action.send_success");
handleDialogClose();
},
onFailure: () =>
notify("resources.delete_media.action.send_failure", "error"),
}
);
};
return (
<Fragment>
<Button
label="resources.delete_media.action.send"
onClick={handleDialogOpen}
disabled={loading}
className={classnames("ra-delete-button", classes.deleteButton)}
>
<DeleteSweepIcon />
</Button>
<DeleteMediaDialog
open={open}
onClose={handleDialogClose}
onSend={handleSend}
/>
</Fragment>
);
};
+41 -2
View File
@@ -1,13 +1,51 @@
import React from "react"; import React from "react";
import { cloneElement } from "react";
import { import {
Datagrid, Datagrid,
ExportButton,
Filter, Filter,
List, List,
NumberField, NumberField,
TextField,
SearchInput,
Pagination, Pagination,
sanitizeListRestProps,
SearchInput,
TextField,
TopToolbar,
useListContext,
} from "react-admin"; } from "react-admin";
import { DeleteMediaButton } from "./media";
const ListActions = props => {
const { className, exporter, filters, maxResults, ...rest } = props;
const {
currentSort,
resource,
displayedFilters,
filterValues,
showFilter,
total,
} = useListContext();
return (
<TopToolbar className={className} {...sanitizeListRestProps(rest)}>
{filters &&
cloneElement(filters, {
resource,
showFilter,
displayedFilters,
filterValues,
context: "button",
})}
<DeleteMediaButton />
<ExportButton
disabled={total === 0}
resource={resource}
sort={currentSort}
filterValues={filterValues}
maxResults={maxResults}
/>
</TopToolbar>
);
};
const UserMediaStatsPagination = props => ( const UserMediaStatsPagination = props => (
<Pagination {...props} rowsPerPageOptions={[10, 25, 50, 100, 500, 1000]} /> <Pagination {...props} rowsPerPageOptions={[10, 25, 50, 100, 500, 1000]} />
@@ -23,6 +61,7 @@ export const UserMediaStatsList = props => {
return ( return (
<List <List
{...props} {...props}
actions={<ListActions />}
filters={<UserMediaStatsFilter />} filters={<UserMediaStatsFilter />}
pagination={<UserMediaStatsPagination />} pagination={<UserMediaStatsPagination />}
sort={{ field: "media_length", order: "DESC" }} sort={{ field: "media_length", order: "DESC" }}
+21
View File
@@ -236,6 +236,23 @@ export default {
last_access_ts: "Letzter Zugriff", last_access_ts: "Letzter Zugriff",
}, },
}, },
delete_media: {
name: "Medien",
fields: {
before_ts: "Letzter Zugriff vor",
size_gt: "Größer als (in Bytes)",
keep_profiles: "Behalte Profilbilder",
},
action: {
send: "Medien löschen",
send_success: "Anfrage erfolgreich versendet.",
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.",
},
},
pushers: { pushers: {
name: "Pusher |||| Pushers", name: "Pusher |||| Pushers",
fields: { fields: {
@@ -276,6 +293,10 @@ export default {
}, },
ra: { ra: {
...germanMessages.ra, ...germanMessages.ra,
action: {
...germanMessages.ra.action,
unselect: "Abwählen",
},
auth: { auth: {
...germanMessages.ra.auth, ...germanMessages.ra.auth,
auth_check_error: "Anmeldung fehlgeschlagen", auth_check_error: "Anmeldung fehlgeschlagen",
+19 -1
View File
@@ -6,6 +6,7 @@ export default {
auth: { auth: {
base_url: "Homeserver URL", base_url: "Homeserver URL",
welcome: "Welcome to Synapse-admin", welcome: "Welcome to Synapse-admin",
server_version: "Synapse version",
username_error: "Please enter fully qualified user ID: '@user:domain'", username_error: "Please enter fully qualified user ID: '@user:domain'",
protocol_error: "URL has to start with 'http://' or 'https://'", protocol_error: "URL has to start with 'http://' or 'https://'",
url_error: "Not a valid Matrix server URL", url_error: "Not a valid Matrix server URL",
@@ -139,7 +140,7 @@ export default {
name: "Name", name: "Name",
canonical_alias: "Alias", canonical_alias: "Alias",
joined_members: "Members", joined_members: "Members",
joined_local_members: "local members", joined_local_members: "Local members",
state_events: "State events", state_events: "State events",
version: "Version", version: "Version",
is_encrypted: "Encrypted", is_encrypted: "Encrypted",
@@ -233,6 +234,23 @@ export default {
last_access_ts: "Last access", last_access_ts: "Last access",
}, },
}, },
delete_media: {
name: "Media",
fields: {
before_ts: "last access before",
size_gt: "Larger then (in bytes)",
keep_profiles: "Keep profile images",
},
action: {
send: "Delete media",
send_success: "Request successfully sent.",
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.",
},
},
pushers: { pushers: {
name: "Pusher |||| Pushers", name: "Pusher |||| Pushers",
fields: { fields: {
+21 -2
View File
@@ -10,6 +10,7 @@ const authProvider = {
type: "m.login.password", type: "m.login.password",
user: username, user: username,
password: password, password: password,
initial_device_display_name: "Synapse Admin",
}), }),
}; };
@@ -30,8 +31,26 @@ const authProvider = {
}, },
// called when the user clicks on the logout button // called when the user clicks on the logout button
logout: () => { logout: () => {
console.log("logout "); console.log("logout");
const logout_api_url =
localStorage.getItem("base_url") + "/_matrix/client/r0/logout";
const access_token = localStorage.getItem("access_token");
const options = {
method: "POST",
user: {
authenticated: true,
token: `Bearer ${access_token}`,
},
};
if (typeof access_token === "string") {
fetchUtils.fetchJson(logout_api_url, options).then(({ json }) => {
localStorage.removeItem("access_token"); localStorage.removeItem("access_token");
localStorage.removeItem("device_id");
});
}
return Promise.resolve(); return Promise.resolve();
}, },
// called when the API returns an error // called when the API returns an error
@@ -46,7 +65,7 @@ const authProvider = {
checkAuth: () => { checkAuth: () => {
const access_token = localStorage.getItem("access_token"); const access_token = localStorage.getItem("access_token");
console.log("checkAuth " + access_token); console.log("checkAuth " + access_token);
return typeof access_token == "string" return typeof access_token === "string"
? Promise.resolve() ? Promise.resolve()
: Promise.reject(); : Promise.reject();
}, },
+10
View File
@@ -160,6 +160,16 @@ const resourceMap = {
)}/${params.id}`, )}/${params.id}`,
}), }),
}, },
delete_media: {
delete: params => ({
endpoint: `/_synapse/admin/v1/media/${localStorage.getItem(
"home_server"
)}/delete?before_ts=${params.before_ts}&size_gt=${
params.size_gt
}&keep_profiles=${params.keep_profiles}`,
method: "POST",
}),
},
servernotices: { servernotices: {
map: n => ({ id: n.event_id }), map: n => ({ id: n.event_id }),
create: data => ({ create: data => ({
+1590 -1466
View File
File diff suppressed because it is too large Load Diff