migrate config away from localStorage; ensure config is properly loaded on access token auth
This commit is contained in:
parent
eae00a6ccd
commit
cfd8238edc
@ -2,7 +2,7 @@ import { CheckForApplicationUpdate, AppBar, TitlePortal, InspectorButton, Confir
|
||||
import { LoginMethod } from "../pages/LoginPage";
|
||||
import { useEffect, useState, Suspense } from "react";
|
||||
import { Icons, DefaultIcon } from "./icons";
|
||||
import { ClearConfig } from "./config";
|
||||
import { MenuItem, GetConfig, ClearConfig } from "./config";
|
||||
import Footer from "./Footer";
|
||||
|
||||
const AdminUserMenu = () => {
|
||||
@ -53,18 +53,8 @@ const AdminAppBar = () => {
|
||||
};
|
||||
|
||||
const AdminMenu = (props) => {
|
||||
const [menu, setMenu] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
const menuConfig = localStorage.getItem('menu');
|
||||
if (menuConfig) {
|
||||
try {
|
||||
setMenu(JSON.parse(menuConfig));
|
||||
} catch (e) {
|
||||
console.error('Error parsing menu configuration', e);
|
||||
}
|
||||
}
|
||||
}, []);
|
||||
const [menu, setMenu] = useState([] as MenuItem[]);
|
||||
useEffect(() => setMenu(GetConfig().menu), []);
|
||||
|
||||
return (
|
||||
<Menu {...props}>
|
||||
@ -105,4 +95,4 @@ export const AdminLayout = ({ children }) => {
|
||||
</Layout>
|
||||
<Footer />
|
||||
</>
|
||||
};
|
||||
};
|
||||
|
@ -2,8 +2,7 @@ import storage from "../storage";
|
||||
|
||||
export interface Config {
|
||||
restrictBaseUrl: string | string[];
|
||||
asManagedUsers: string[];
|
||||
supportURL: string;
|
||||
asManagedUsers: RegExp[];
|
||||
menu: MenuItem[];
|
||||
}
|
||||
|
||||
@ -15,73 +14,71 @@ export interface MenuItem {
|
||||
|
||||
export const WellKnownKey = "cc.etke.synapse-admin";
|
||||
|
||||
export const LoadConfig = (context: Config): Config => {
|
||||
if (context.restrictBaseUrl) {
|
||||
storage.setItem("restrict_base_url", JSON.stringify(context.restrictBaseUrl));
|
||||
// current configuration
|
||||
let config: Config = {
|
||||
restrictBaseUrl: "",
|
||||
asManagedUsers: [],
|
||||
menu: [],
|
||||
};
|
||||
|
||||
export const FetchConfig = async () => {
|
||||
try {
|
||||
const resp = await fetch("config.json");
|
||||
const configJSON = await resp.json();
|
||||
console.log("Loaded config.json", configJSON);
|
||||
LoadConfig(configJSON);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
if (context.asManagedUsers) {
|
||||
storage.setItem("as_managed_users", JSON.stringify(context.asManagedUsers));
|
||||
// if home_server is set, try to load https://home_server/.well-known/matrix/client
|
||||
const homeserver = storage.getItem("home_server");
|
||||
if (homeserver) {
|
||||
try {
|
||||
const resp = await fetch(`https://${homeserver}/.well-known/matrix/client`);
|
||||
const configWK = await resp.json();
|
||||
if (!configWK[WellKnownKey]) {
|
||||
console.log(`Loaded https://${homeserver}.well-known/matrix/client, but it doesn't contain ${WellKnownKey} key, skipping`, configWK);
|
||||
} else {
|
||||
console.log(`Loaded https://${homeserver}.well-known/matrix/client`, configWK);
|
||||
LoadConfig(configWK[WellKnownKey]);
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(`https://${homeserver}/.well-known/matrix/client not found, skipping`, e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// load config from context
|
||||
export const LoadConfig = (context: any) => {
|
||||
if (context?.restrictBaseUrl) {
|
||||
config.restrictBaseUrl = context.restrictBaseUrl as string | string[];
|
||||
}
|
||||
|
||||
if (context?.asManagedUsers) {
|
||||
config.asManagedUsers = context.asManagedUsers.map((regex: string) => new RegExp(regex));
|
||||
}
|
||||
|
||||
let menu: MenuItem[] = [];
|
||||
if (context.menu) {
|
||||
menu = context.menu;
|
||||
}
|
||||
if (context.supportURL) {
|
||||
const migratedSupportURL = {
|
||||
label: "Contact support",
|
||||
icon: "SupportAgent",
|
||||
url: context.supportURL,
|
||||
};
|
||||
console.warn("supportURL config option is deprecated. Please, use the menu option instead. Automatically migrated to the new menu option:", migratedSupportURL);
|
||||
menu.push(migratedSupportURL as MenuItem);
|
||||
if (context?.menu) {
|
||||
menu = context.menu as MenuItem[];
|
||||
}
|
||||
if (menu.length > 0) {
|
||||
storage.setItem("menu", JSON.stringify(menu));
|
||||
config.menu = menu;
|
||||
}
|
||||
}
|
||||
|
||||
// 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") || "");
|
||||
} catch (e) {}
|
||||
|
||||
let finalMenu: MenuItem[] = [];
|
||||
try {
|
||||
finalMenu = JSON.parse(storage.getItem("menu") || "");
|
||||
} catch (e) {}
|
||||
|
||||
return {
|
||||
restrictBaseUrl: finalRestrictBaseUrl,
|
||||
asManagedUsers: finalAsManagedUsers,
|
||||
supportURL: storage.getItem("support_url") || "",
|
||||
menu: finalMenu,
|
||||
} as Config;
|
||||
|
||||
// get config
|
||||
export const GetConfig = (): Config => {
|
||||
return config;
|
||||
}
|
||||
|
||||
|
||||
// clear config
|
||||
export const ClearConfig = () => {
|
||||
// config.json
|
||||
storage.removeItem("restrict_base_url");
|
||||
storage.removeItem("as_managed_users");
|
||||
storage.removeItem("support_url");
|
||||
storage.removeItem("menu");
|
||||
|
||||
config = {} as Config;
|
||||
// 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");
|
||||
storage.clear();
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { Identifier } from "ra-core";
|
||||
import { GetConfig } from "./config";
|
||||
|
||||
/**
|
||||
* Check if a user is managed by an application service
|
||||
@ -6,11 +7,5 @@ import { Identifier } from "ra-core";
|
||||
* @returns Whether the user is managed by an application service
|
||||
*/
|
||||
export const isASManaged = (id: string | Identifier): boolean => {
|
||||
const managedUsersString = localStorage.getItem("as_managed_users") || '';
|
||||
try {
|
||||
const asManagedUsers = JSON.parse(managedUsersString).map(regex => new RegExp(regex));
|
||||
return asManagedUsers.some(regex => regex.test(id));
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
return GetConfig().asManagedUsers.some(regex => regex.test(id as string));
|
||||
};
|
||||
|
@ -3,46 +3,15 @@ import React from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
|
||||
import App from "./App";
|
||||
import { Config, WellKnownKey, LoadConfig } from "./components/config";
|
||||
import { FetchConfig, GetConfig } from "./components/config";
|
||||
import { AppContext } from "./AppContext";
|
||||
import storage from "./storage";
|
||||
|
||||
// load config.json
|
||||
let props: Config = {
|
||||
restrictBaseUrl: [],
|
||||
asManagedUsers: [],
|
||||
supportURL: "",
|
||||
menu: [],
|
||||
};
|
||||
try {
|
||||
const resp = await fetch("config.json");
|
||||
const configJSON = await resp.json();
|
||||
console.log("Loaded config.json", configJSON);
|
||||
props = LoadConfig(configJSON as Config);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
// if home_server is set, try to load https://home_server/.well-known/matrix/client
|
||||
const homeserver = storage.getItem("home_server");
|
||||
if (homeserver) {
|
||||
try {
|
||||
const resp = await fetch(`https://${homeserver}/.well-known/matrix/client`);
|
||||
const configWK = await resp.json();
|
||||
if (!configWK[WellKnownKey]) {
|
||||
console.log(`Loaded https://${homeserver}.well-known/matrix/client, but it doesn't contain ${WellKnownKey} key, skipping`, configWK);
|
||||
} else {
|
||||
console.log(`Loaded https://${homeserver}.well-known/matrix/client`, configWK);
|
||||
props = LoadConfig(configWK[WellKnownKey] as Config);
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(`https://${homeserver}/.well-known/matrix/client not found, skipping`, e);
|
||||
}
|
||||
}
|
||||
await FetchConfig();
|
||||
|
||||
createRoot(document.getElementById("root")).render(
|
||||
<React.StrictMode>
|
||||
<AppContext.Provider value={props}>
|
||||
<AppContext.Provider value={GetConfig()}>
|
||||
<App />
|
||||
</AppContext.Provider>
|
||||
</React.StrictMode>
|
||||
|
@ -3,7 +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";
|
||||
import { FetchConfig, ClearConfig } from "../components/config";
|
||||
|
||||
const authProvider: AuthProvider = {
|
||||
// called when the user attempts to log in
|
||||
@ -82,6 +82,11 @@ const authProvider: AuthProvider = {
|
||||
storage.setItem("device_id", json.device_id);
|
||||
storage.setItem("login_type", accessToken ? "accessToken" : "credentials");
|
||||
|
||||
// when doing access token auth, config is not fetched, so we need to do it here
|
||||
if (accessToken) {
|
||||
await FetchConfig();
|
||||
}
|
||||
|
||||
return Promise.resolve({redirectTo: "/"});
|
||||
} catch(err) {
|
||||
const error = err as HttpError;
|
||||
|
Loading…
x
Reference in New Issue
Block a user