Fix page breaking after login

Navigation button broke the page due to requiring network metadata,
which was fetched when login page was loaded. Unfortunately
the endpoint required permissions so nothing was actually loaded.

- Load metadata after login
- Remove auth requirement from networkMetadata and serverIdentity endpoints
This commit is contained in:
Aurora Lahtela 2023-03-04 10:10:20 +02:00
parent 13cc314238
commit e9496e924f
6 changed files with 27 additions and 24 deletions

View File

@ -17,10 +17,9 @@
package com.djrapitops.plan.delivery.webserver.resolver.json; package com.djrapitops.plan.delivery.webserver.resolver.json;
import com.djrapitops.plan.delivery.domain.datatransfer.ServerDto; import com.djrapitops.plan.delivery.domain.datatransfer.ServerDto;
import com.djrapitops.plan.delivery.web.resolver.Resolver; import com.djrapitops.plan.delivery.web.resolver.NoAuthResolver;
import com.djrapitops.plan.delivery.web.resolver.Response; import com.djrapitops.plan.delivery.web.resolver.Response;
import com.djrapitops.plan.delivery.web.resolver.request.Request; import com.djrapitops.plan.delivery.web.resolver.request.Request;
import com.djrapitops.plan.delivery.web.resolver.request.WebUser;
import com.djrapitops.plan.identification.ServerInfo; import com.djrapitops.plan.identification.ServerInfo;
import com.djrapitops.plan.storage.database.DBSystem; import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.queries.objects.ServerQueries; import com.djrapitops.plan.storage.database.queries.objects.ServerQueries;
@ -42,7 +41,7 @@ import java.util.stream.Collectors;
*/ */
@Singleton @Singleton
@Path("/v1/networkMetadata") @Path("/v1/networkMetadata")
public class NetworkMetadataJSONResolver implements Resolver { public class NetworkMetadataJSONResolver implements NoAuthResolver {
private final ServerInfo serverInfo; private final ServerInfo serverInfo;
private final DBSystem dbSystem; private final DBSystem dbSystem;
@ -53,11 +52,6 @@ public class NetworkMetadataJSONResolver implements Resolver {
this.dbSystem = dbSystem; this.dbSystem = dbSystem;
} }
@Override
public boolean canAccess(Request request) {
return request.getUser().orElse(new WebUser("")).hasPermission("page.network");
}
@GET @GET
@Operation( @Operation(
description = "Get metadata about the network such as list of servers.", description = "Get metadata about the network such as list of servers.",

View File

@ -19,7 +19,7 @@ package com.djrapitops.plan.delivery.webserver.resolver.json;
import com.djrapitops.plan.delivery.domain.datatransfer.ServerDto; import com.djrapitops.plan.delivery.domain.datatransfer.ServerDto;
import com.djrapitops.plan.delivery.rendering.json.JSONFactory; import com.djrapitops.plan.delivery.rendering.json.JSONFactory;
import com.djrapitops.plan.delivery.web.resolver.MimeType; import com.djrapitops.plan.delivery.web.resolver.MimeType;
import com.djrapitops.plan.delivery.web.resolver.Resolver; import com.djrapitops.plan.delivery.web.resolver.NoAuthResolver;
import com.djrapitops.plan.delivery.web.resolver.Response; import com.djrapitops.plan.delivery.web.resolver.Response;
import com.djrapitops.plan.delivery.web.resolver.exception.BadRequestException; import com.djrapitops.plan.delivery.web.resolver.exception.BadRequestException;
import com.djrapitops.plan.delivery.web.resolver.exception.NotFoundException; import com.djrapitops.plan.delivery.web.resolver.exception.NotFoundException;
@ -43,7 +43,7 @@ import java.util.Optional;
* @author AuroraLS3 * @author AuroraLS3
*/ */
@Singleton @Singleton
public class ServerIdentityJSONResolver implements Resolver { public class ServerIdentityJSONResolver implements NoAuthResolver {
private final JSONFactory jsonFactory; private final JSONFactory jsonFactory;
@ -52,13 +52,6 @@ public class ServerIdentityJSONResolver implements Resolver {
this.jsonFactory = jsonFactory; this.jsonFactory = jsonFactory;
} }
@Override
public boolean canAccess(Request request) {
return request.getUser()
.map(user -> user.hasPermission("page.server"))
.orElse(false);
}
@GET @GET
@Operation( @Operation(
description = "Get server identity for an identifier", description = "Get server identity for an identifier",

View File

@ -214,6 +214,8 @@ class AccessControlTest {
"/v1/version,200", "/v1/version,200",
"/v1/whoami,200", "/v1/whoami,200",
"/v1/metadata,200", "/v1/metadata,200",
"/v1/networkMetadata,200",
"/v1/serverIdentity?server=" + TestConstants.SERVER_UUID_STRING + ",200",
"/v1/locale,200", "/v1/locale,200",
"/v1/locale/EN,200", "/v1/locale/EN,200",
"/v1/locale/NonexistingLanguage,404", "/v1/locale/NonexistingLanguage,404",
@ -289,6 +291,8 @@ class AccessControlTest {
"/v1/version,200", "/v1/version,200",
"/v1/whoami,200", "/v1/whoami,200",
"/v1/metadata,200", "/v1/metadata,200",
"/v1/networkMetadata,200",
"/v1/serverIdentity?server=" + TestConstants.SERVER_UUID_STRING + ",200",
"/v1/locale,200", "/v1/locale,200",
"/v1/locale/EN,200", "/v1/locale/EN,200",
"/v1/locale/NonexistingLanguage,404", "/v1/locale/NonexistingLanguage,404",
@ -364,6 +368,8 @@ class AccessControlTest {
"/v1/version,200", "/v1/version,200",
"/v1/whoami,200", "/v1/whoami,200",
"/v1/metadata,200", "/v1/metadata,200",
"/v1/networkMetadata,200",
"/v1/serverIdentity?server=" + TestConstants.SERVER_UUID_STRING + ",200",
"/v1/locale,200", "/v1/locale,200",
"/v1/locale/EN,200", "/v1/locale/EN,200",
"/v1/locale/NonexistingLanguage,404", "/v1/locale/NonexistingLanguage,404",
@ -437,6 +443,8 @@ class AccessControlTest {
"/v1/version,200", "/v1/version,200",
"/v1/whoami,200", "/v1/whoami,200",
"/v1/metadata,200", "/v1/metadata,200",
"/v1/networkMetadata,200",
"/v1/serverIdentity?server=" + TestConstants.SERVER_UUID_STRING + ",200",
"/v1/locale,200", "/v1/locale,200",
"/v1/locale/EN,200", "/v1/locale/EN,200",
"/v1/locale/NonexistingLanguage,404", "/v1/locale/NonexistingLanguage,404",

View File

@ -3,7 +3,7 @@
"name": "dashboard", "name": "dashboard",
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"proxy": "http://localhost:8800", "proxy": "https://localhost:8804",
"dependencies": { "dependencies": {
"@fortawesome/fontawesome-free": "^6.3.0", "@fortawesome/fontawesome-free": "^6.3.0",
"@fortawesome/fontawesome-svg-core": "^6.3.0", "@fortawesome/fontawesome-svg-core": "^6.3.0",

View File

@ -12,12 +12,13 @@ const PageNavigationItem = ({page}) => {
const navigate = useNavigate(); const navigate = useNavigate();
const location = useLocation(); const location = useLocation();
const {authRequired, loggedIn, user} = useAuth(); const {authRequired, loggedIn, user} = useAuth();
const {networkMetadata} = useMetadata(); const metadata = useMetadata();
const [currentPage, setCurrentPage] = useState(undefined); const [currentPage, setCurrentPage] = useState(undefined);
const [items, setItems] = useState([]); const [items, setItems] = useState([]);
useEffect(() => { useEffect(() => {
if (networkMetadata) { const networkMetadata = metadata?.networkMetadata;
if (networkMetadata && networkMetadata.servers) {
const hasProxy = networkMetadata.servers.filter(server => server.proxy).length const hasProxy = networkMetadata.servers.filter(server => server.proxy).length
let newItems = [ let newItems = [
@ -57,7 +58,7 @@ const PageNavigationItem = ({page}) => {
setItems(newItems); setItems(newItems);
setCurrentPage(newItems.find(item => location.pathname.startsWith(item.href))?.id); setCurrentPage(newItems.find(item => location.pathname.startsWith(item.href))?.id);
} }
}, [t, networkMetadata, location, authRequired, loggedIn, user, page]); }, [t, metadata, location, authRequired, loggedIn, user, page]);
const onSelect = ({target}) => { const onSelect = ({target}) => {
const selected = target.value; const selected = target.value;

View File

@ -1,15 +1,19 @@
import {createContext, useCallback, useContext, useEffect, useState} from "react"; import {createContext, useCallback, useContext, useEffect, useMemo, useState} from "react";
import {fetchNetworkMetadata, fetchPlanMetadata} from "../service/metadataService"; import {fetchNetworkMetadata, fetchPlanMetadata} from "../service/metadataService";
import terminal from '../Terminal-icon.png' import terminal from '../Terminal-icon.png'
import {useAuth} from "./authenticationHook";
const MetadataContext = createContext({}); const MetadataContext = createContext({});
export const MetadataContextProvider = ({children}) => { export const MetadataContextProvider = ({children}) => {
const [datastore] = useState({}); const [datastore] = useState({});
const [metadata, setMetadata] = useState({}); const [metadata, setMetadata] = useState({});
const {authRequired, authLoaded, loggedIn} = useAuth();
const updateMetadata = useCallback(async () => { const updateMetadata = useCallback(async () => {
if (authRequired && (!authLoaded || !loggedIn)) return;
const {data, error} = await fetchPlanMetadata(); const {data, error} = await fetchPlanMetadata();
if (data) { if (data) {
setMetadata(data); setMetadata(data);
@ -37,9 +41,12 @@ export const MetadataContextProvider = ({children}) => {
useEffect(() => { useEffect(() => {
updateMetadata(); updateMetadata();
}, [updateMetadata]); }, [updateMetadata, authLoaded, loggedIn]);
const sharedState = {...metadata, getPlayerHeadImageUrl, datastore} const sharedState = useMemo(() => {
return {...metadata, getPlayerHeadImageUrl, datastore}
},
[metadata, getPlayerHeadImageUrl, datastore]);
return (<MetadataContext.Provider value={sharedState}> return (<MetadataContext.Provider value={sharedState}>
{children} {children}
</MetadataContext.Provider> </MetadataContext.Provider>