Compare commits

3 Commits

Author SHA1 Message Date
Aine
1d5511421d better rate limits handling 2024-11-07 12:15:18 +02:00
Aine
b925c63171 clear storage on logout 2024-11-07 10:46:25 +02:00
Aine
6faebaf9df properly handle restrictBaseUrl config option, fixes #128 2024-11-07 10:34:06 +02:00
12 changed files with 59 additions and 18 deletions

View File

@@ -2,6 +2,7 @@ import { AppBar, TitlePortal, InspectorButton, Confirm, Layout, Logout, Menu, us
import { LoginMethod } from "../pages/LoginPage";
import { useEffect, useState, Suspense } from "react";
import { Icons, DefaultIcon } from "./icons";
import { ClearConfig } from "./config";
const AdminUserMenu = () => {
const [open, setOpen] = useState(false);
@@ -21,8 +22,7 @@ const AdminUserMenu = () => {
const handleDialogClose = () => {
setOpen(false);
localStorage.removeItem("access_token");
localStorage.removeItem("login_type");
ClearConfig();
window.location.reload();
};

View File

@@ -4,11 +4,16 @@ import { useDataProvider, useNotify, useRecordContext, useTranslate } from "reac
import { TextField } from "@mui/material";
import { useFormContext } from "react-hook-form";
const RateLimitRow = ({ limit, value, updateRateLimit }: { limit: string, value: number, updateRateLimit: (limit: string, value: number) => void }) => {
const RateLimitRow = ({ limit, value, updateRateLimit }: { limit: string, value: any, updateRateLimit: (limit: string, value: any) => void }) => {
const translate = useTranslate();
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
updateRateLimit(limit, parseInt(event.target.value));
const value = parseInt(event.target.value);
if (isNaN(value)) {
updateRateLimit(limit, null);
return;
}
updateRateLimit(limit, value);
};
return <Stack
@@ -48,8 +53,8 @@ export const UserRateLimits = () => {
const form = useFormContext();
const dataProvider = useDataProvider();
const [rateLimits, setRateLimits] = useState({
messages_per_second: 0,
burst_count: 0,
messages_per_second: "", // we are setting string here to make the number field empty by default, null is prohibited by the field validation
burst_count: "",
});
if (!record) {
@@ -67,7 +72,7 @@ export const UserRateLimits = () => {
fetchRateLimits();
}, []);
const updateRateLimit = async (limit: string, value: number) => {
const updateRateLimit = async (limit: string, value: any) => {
let updatedRateLimits = { ...rateLimits, [limit]: value };
setRateLimits(updatedRateLimits);
form.setValue(`rates.${limit}`, value, { shouldDirty: true });

View File

@@ -43,6 +43,13 @@ export const LoadConfig = (context: Config): Config => {
// below we try to calculate "final" config, which will contain values from context and already set values in storage
// because LoadConfig could be called multiple times to get config from different sources
let finalRestrictBaseUrl: string | string[] = "";
try {
finalRestrictBaseUrl = JSON.parse(storage.getItem("restrict_base_url") || "");
if (Array.isArray(finalRestrictBaseUrl) && finalRestrictBaseUrl.length == 1) {
finalRestrictBaseUrl = finalRestrictBaseUrl[0];
}
} catch (e) {}
let finalAsManagedUsers: string[] = [];
try {
finalAsManagedUsers = JSON.parse(storage.getItem("as_managed_users") || "");
@@ -54,10 +61,27 @@ export const LoadConfig = (context: Config): Config => {
} catch (e) {}
return {
restrictBaseUrl: storage.getItem("restrict_base_url") || "",
restrictBaseUrl: finalRestrictBaseUrl,
asManagedUsers: finalAsManagedUsers,
supportURL: storage.getItem("support_url") || "",
menu: finalMenu,
} as Config;
}
export const ClearConfig = () => {
// config.json
storage.removeItem("restrict_base_url");
storage.removeItem("as_managed_users");
storage.removeItem("support_url");
storage.removeItem("menu");
// session
storage.removeItem("home_server");
storage.removeItem("base_url");
storage.removeItem("user_id");
storage.removeItem("device_id");
storage.removeItem("access_token");
storage.removeItem("login_type");
}

View File

@@ -194,7 +194,7 @@ const de: SynapseTranslationMessages = {
},
limits: {
messages_per_second: "Nachrichten pro Sekunde",
messages_per_second_text: "Die Anzahl der Aktionen, die in einer Sekunde durchgeführt werden können. 0 bedeutet, dass die Rate-Limitierung für diesen Benutzer deaktiviert ist.",
messages_per_second_text: "Die Anzahl der Aktionen, die in einer Sekunde durchgeführt werden können.",
burst_count: "Burst-Anzahl",
burst_count_text: "Die Anzahl der Aktionen, die vor der Begrenzung durchgeführt werden können.",
}

View File

@@ -167,7 +167,7 @@ const en: SynapseTranslationMessages = {
},
limits: {
messages_per_second: "Messages per second",
messages_per_second_text: "The number of actions that can be performed in a second. 0 mean that ratelimiting is disabled for this user",
messages_per_second_text: "The number of actions that can be performed in a second.",
burst_count: "Burst count",
burst_count_text: "How many actions that can be performed before being limited.",
}

View File

@@ -159,7 +159,7 @@ const fa: SynapseTranslationMessages = {
},
limits: {
messages_per_second: "پیام در ثانیه",
messages_per_second_text: "تعداد عملیاتی که می تواند در یک ثانیه انجام شود. 0 به معنای غیرفعال کردن محدودیت برای این کاربر است.",
messages_per_second_text: "تعداد عملیاتی که می تواند در یک ثانیه انجام شود.",
burst_count: "تعداد پیچیدگی",
burst_count_text: "تعداد عملیاتی که می تواند قبل از محدودیت انجام شود.",
}

View File

@@ -161,7 +161,7 @@ const fr: SynapseTranslationMessages = {
},
limits: {
messages_per_second: "Messages par seconde",
messages_per_second_text: "Le nombre d'actions que l'utilisateur peut effectuer par seconde. 0 signifie que la limitation est désactivée pour cet utilisateur.",
messages_per_second_text: "Le nombre d'actions que l'utilisateur peut effectuer par seconde.",
burst_count: "Compteur de pics",
burst_count_text: "Le nombre d'actions que l'utilisateur peut effectuer avant d'être limité.",
}

View File

@@ -160,7 +160,7 @@ const it: SynapseTranslationMessages = {
},
limits: {
messages_per_second: "Messaggi al secondo",
messages_per_second_text: "Il numero di azioni che l'utente può eseguire al secondo. 0 significa che la limitazione è disabilitata per questo utente.",
messages_per_second_text: "Il numero di azioni che l'utente può eseguire al secondo.",
burst_count: "Burst-conteggio",
burst_count_text: "Il numero di azioni che l'utente può eseguire prima di essere limitato.",
}

View File

@@ -197,7 +197,7 @@ const ru: SynapseTranslationMessages = {
},
limits: {
messages_per_second: "Сообщений в секунду",
messages_per_second_text: "Количество действий, которые могут быть выполнены в секунду. 0 означает, что ограничение на количество действий отключено для этого пользователя.",
messages_per_second_text: "Количество действий, которые могут быть выполнены в секунду.",
burst_count: "Burst-счётчик",
burst_count_text: "Количество действий, которые могут быть выполнены до ограничения.",
}

View File

@@ -184,7 +184,7 @@ const zh: SynapseTranslationMessages = {
},
limits: {
messages_per_second: "每秒消息数",
messages_per_second_text: "每秒可以执行的操作数。0 表示禁用此用户的限制。",
messages_per_second_text: "每秒可以执行的操作数。",
burst_count: "Burst-计数",
burst_count_text: "在限制之前可以执行的操作数。",
}

View File

@@ -3,6 +3,7 @@ import { AuthProvider, HttpError, Options, fetchUtils } from "react-admin";
import storage from "../storage";
import { MatrixError, displayError } from "../components/error";
import { fetchAuthenticatedMedia } from "../utils/fetchMedia";
import { ClearConfig } from "../components/config";
const authProvider: AuthProvider = {
// called when the user attempts to log in
@@ -154,8 +155,7 @@ const authProvider: AuthProvider = {
} catch (err) {
console.log("Error logging out", err);
} finally {
storage.removeItem("access_token");
storage.removeItem("login_type");
ClearConfig();
}
}
},

View File

@@ -830,9 +830,21 @@ const baseDataProvider: SynapseDataProvider = {
return json as RateLimitsModel;
},
setRateLimits: async (id: Identifier, rateLimits: RateLimitsModel) => {
const filtered = Object.entries(rateLimits).
filter(([key, value]) => value !== null && value !== undefined).
reduce((obj, [key, value]) => {
obj[key] = value;
return obj;
}, {});
const base_url = storage.getItem("base_url");
const endpoint_url = `${base_url}/_synapse/admin/v1/users/${encodeURIComponent(returnMXID(id))}/override_ratelimit`;
await jsonClient(endpoint_url, { method: "POST", body: JSON.stringify(rateLimits) });
if (Object.keys(filtered).length === 0) {
await jsonClient(endpoint_url, { method: "DELETE" });
return
}
await jsonClient(endpoint_url, { method: "POST", body: JSON.stringify(filtered) });
},
};