Skip to content

Commit cec93b4

Browse files
committed
Fix test data and permission checks on datapoint requests
1 parent 4eb220b commit cec93b4

13 files changed

Lines changed: 81 additions & 36 deletions

File tree

Plan/common/src/main/java/com/djrapitops/plan/delivery/rendering/json/datapoint/types/PlayersOnlineCurrent.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ public Optional<Integer> getValue(GenericFilter filter) {
6868
serverUUIDs = dbSystem.getDatabase().query(ServerQueries.fetchProxyServerUUIDs());
6969
}
7070
}
71+
if (serverUUIDs.isEmpty()) {
72+
return Optional.of(serverSensor.getOnlinePlayerCount());
73+
}
7174

7275
if (serverUUIDs.size() == 1) {
7376
ServerUUID serverUUID = serverUUIDs.get(0);

Plan/common/src/test/java/com/djrapitops/plan/delivery/export/ExportTestUtilities.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ static void savePlayerData(Database database, ServerUUID serverUUID) {
133133
}
134134

135135
static void saveServerData(Database database, ServerUUID serverUUID) {
136-
RandomData.randomDateOrderedTPS(5).forEach(tps -> database.executeTransaction(new TPSStoreTransaction(serverUUID, tps)).join());
136+
RandomData.randomDateOrderedTPS(1).forEach(tps -> database.executeTransaction(new TPSStoreTransaction(serverUUID, tps)).join());
137137
}
138138

139139
public static List<String> getEndpointsToTest(ServerUUID serverUUID) {

Plan/common/src/test/java/com/djrapitops/plan/delivery/webserver/AccessControlTest.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
import java.util.Arrays;
6262
import java.util.Collections;
6363
import java.util.concurrent.ExecutionException;
64+
import java.util.concurrent.TimeUnit;
6465
import java.util.stream.Stream;
6566

6667
import static org.junit.jupiter.api.Assertions.*;
@@ -306,9 +307,10 @@ static void setUpClass(@TempDir Path tempDir) throws Exception {
306307
TestConstants.SERVER_NAME,
307308
address,
308309
TestConstants.VERSION)));
309-
for (TPS tps : RandomData.randomTPS()) {
310-
database.executeInTransaction(DataStoreQueries.storeTPS(TestConstants.SERVER_UUID, tps));
310+
for (TPS tps : RandomData.randomDateOrderedTPS(1)) {
311+
database.executeInTransaction(DataStoreQueries.storeTPS(TestConstants.SERVER_UUID, tps)).join();
311312
}
313+
database.executeInTransaction(DataStoreQueries.storeTPS(TestConstants.SERVER_UUID, RandomData.randomTPSAtDate(System.currentTimeMillis() - TimeUnit.SECONDS.toMillis(5))));
312314

313315
Caller caller = system.getApiServices().getExtensionService().register(new ExtensionsDatabaseTest.PlayerExtension())
314316
.orElseThrow(AssertionError::new);

Plan/common/src/test/java/com/djrapitops/plan/delivery/webserver/AccessControlVisibilityTest.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import com.djrapitops.plan.settings.config.paths.DisplaySettings;
2828
import com.djrapitops.plan.settings.config.paths.WebserverSettings;
2929
import com.djrapitops.plan.storage.database.Database;
30+
import com.djrapitops.plan.storage.database.queries.DataStoreQueries;
3031
import com.djrapitops.plan.storage.database.queries.objects.ServerQueries;
3132
import com.djrapitops.plan.storage.database.transactions.StoreServerInformationTransaction;
3233
import com.djrapitops.plan.storage.database.transactions.commands.RemoveWebGroupsTransaction;
@@ -198,6 +199,13 @@ private static void storePlayer(Database database, ServerUUID serverUUID, UUID p
198199
.get();
199200
}
200201

202+
@BeforeEach
203+
void setUp(Database database, ServerUUID serverUUID) {
204+
database.executeInTransaction(
205+
DataStoreQueries.storeTPS(serverUUID,
206+
RandomData.randomTPSAtDate(System.currentTimeMillis() - TimeUnit.SECONDS.toMillis(5)))).join();
207+
}
208+
201209
@AfterEach
202210
void tearDownTest(WebDriver driver) {
203211
String address = "https://localhost:" + TEST_PORT_NUMBER + "/auth/logout";
@@ -295,10 +303,11 @@ void serverPageElementNotVisible(WebPermission permission, String element, Strin
295303
assertNoLogs(driver, address);
296304
}
297305

298-
private void registerProxy(Database database) throws ExecutionException, InterruptedException {
306+
private void registerProxy(Database database) {
299307
database.executeTransaction(new StoreServerInformationTransaction(
300308
new Server(null, TestConstants.SERVER_TWO_UUID, "Proxy", "https://localhost", true, TestConstants.VERSION)
301-
)).get();
309+
)).join();
310+
database.executeInTransaction(DataStoreQueries.storeTPS(TestConstants.SERVER_TWO_UUID, RandomData.randomTPSAtDate(System.currentTimeMillis() - 1)));
302311
Awaitility.await("Proxy was not registered")
303312
.atMost(5, TimeUnit.SECONDS)
304313
.until(() -> !database.query(ServerQueries.fetchProxyServers()).isEmpty());

Plan/common/src/testFixtures/java/utilities/RandomData.java

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,10 @@ public static List<TPS> randomTPS() {
8585
int randEntities = r.nextInt(10000);
8686
int randChunks = r.nextInt(10000);
8787
long randDisk = r.nextLong() % 100000L;
88-
test.add(new TPS(randDate, randTPS, randPlayers, randCPU, randMemory, randEntities, randChunks, randDisk));
88+
TPS tps = new TPS(randDate, randTPS, randPlayers, randCPU, randMemory, randEntities, randChunks, randDisk);
89+
tps.setMsptAverage(randTPS / 20.0);
90+
tps.setMspt95thPercentile(randTPS / 20.0);
91+
test.add(tps);
8992
}
9093
return test;
9194
}
@@ -100,16 +103,30 @@ public static List<TPS> randomDateOrderedTPS(long minimumDay) {
100103
int previousPlayers = randomInt(0, 100);
101104
for (int i = 0; i < randomInt(50, 100); i++) {
102105
int randInt = r.nextInt();
103-
double randTps = r.nextDouble() * 20;
106+
double randTps = Math.abs(r.nextDouble() * 20);
104107
long randLong = Math.abs(r.nextLong());
105-
test.add(new TPS(previousTimestamp, randTps, previousPlayers, randLong, randLong, randInt, randInt, randLong));
108+
TPS tps = new TPS(previousTimestamp, randTps, previousPlayers, randLong, randLong, randInt, randInt, randLong);
109+
tps.setMsptAverage(randTps / 20.0);
110+
tps.setMspt95thPercentile(randTps / 20.0);
111+
test.add(tps);
106112
boolean reboot = Math.random() < 0.10;
107113
previousTimestamp = previousTimestamp + (reboot ? TimeUnit.MINUTES.toMillis(1) : TimeUnit.MINUTES.toMillis(10));
108114
previousPlayers = Math.max(previousPlayers + r.nextInt(10) - 10, 0);
109115
}
110116
return test;
111117
}
112118

119+
public static TPS randomTPSAtDate(long epoch) {
120+
int randInt = r.nextInt();
121+
double randTps = Math.abs(r.nextDouble() * 20);
122+
long randLong = Math.abs(r.nextLong());
123+
int previousPlayers = randomInt(0, 100);
124+
TPS tps = new TPS(epoch, randTps, previousPlayers, randLong, randLong, randInt, randInt, randLong);
125+
tps.setMsptAverage(randTps / 20.0);
126+
tps.setMspt95thPercentile(randTps / 20.0);
127+
return tps;
128+
}
129+
113130
public static List<FinishedSession> randomSessions() {
114131
return pickMultiple(randomInt(15, 30),
115132
() -> randomSession(
@@ -251,6 +268,6 @@ public static List<JoinAddress> generateJoinAddresses(int n) {
251268
}
252269

253270
public static List<UUID> randomUUIDs(int n) {
254-
return IntStream.range(0, n).mapToObj(i -> UUID.randomUUID()).toList();
271+
return IntStream.range(0, n).mapToObj(_ -> UUID.randomUUID()).toList();
255272
}
256273
}

Plan/react/dashboard/src/components/cards/network/QuickViewGraphCard.jsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,15 @@ import {useDataRequest} from "../../../hooks/dataFetchHook.js";
88
import {fetchPlayersOnlineGraph} from "../../../service/serverService.js";
99
import {ErrorViewCard} from "../../../views/ErrorView.tsx";
1010
import {CardLoader} from "../../navigation/Loader.tsx";
11+
import {useAuth} from "../../../hooks/authenticationHook.tsx";
1112

1213
const QuickViewGraphCard = ({server}) => {
1314
const {t} = useTranslation();
15+
const {hasPermission} = useAuth();
1416
const {data, loadingError} = useDataRequest(
1517
fetchPlayersOnlineGraph,
16-
[server.serverUUID])
18+
[server.serverUUID],
19+
hasPermission('page.server.overview.players.online.graph'))
1720

1821
if (loadingError) return <ErrorViewCard error={loadingError}/>
1922
if (!data) return <CardLoader/>;

Plan/react/dashboard/src/components/cards/network/ServersTableCard.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const SortDropDown = ({sortBy, sortReversed, setSortBy}) => {
1212
const {hasPermission} = useAuth();
1313

1414
const sortOptions = Object.values(ServerSortOption)
15-
.filter(sortBy => hasPermission(calculatePermission(sortBy.data)));
15+
.filter(sortBy => hasPermission(calculatePermission(sortBy.data, {server: "true"})));
1616

1717
const getSortIcon = useCallback(() => {
1818
return sortReversed ? sortBy.iconDesc : sortBy.iconAsc;

Plan/react/dashboard/src/components/cards/server/insights/SessionInsightsCard.jsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,7 @@ const SessionInsightsCard = ({identifier}) => {
4545
dataType={DatapointType.AFK_TIME}
4646
filter={filter}
4747
valueLabel={<>(<QueryDatapointValue dataType={DatapointType.AFK_TIME_PERCENTAGE}
48-
filter={filter}
49-
permission={"afk.time"}/>)</>}
48+
filter={filter}/>)</>}
5049
/>
5150
</InsightsFor30DaysCard>
5251
)

Plan/react/dashboard/src/components/cards/server/values/ServerAsNumbersCard.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ const ServerAsNumbersCard = () => {
4646
filter={filter} bold/>
4747
<QueryDatapoint name={t('html.label.playersOnline')}
4848
color={'players-online'} icon={faUser}
49-
dataType={DatapointType.PLAYERS_ONLINE}
49+
dataType={DatapointType.PLAYERS_ONLINE} permission="players.online.current"
5050
filter={filter} bold/>
5151
<hr/>
5252
<QueryDatapoint

Plan/react/dashboard/src/components/datapoint/QueryDatapoint.tsx

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {
22
Datapoint,
33
DatapointType,
44
DatapointTypeMap,
5+
differingPermissions,
56
FormatType,
67
getDatapointUrl,
78
NumericDatapointType
@@ -10,7 +11,7 @@ import {GenericFilter} from "../../dataHooks/model/GenericFilter";
1011
import {useNavigation} from "../../hooks/navigationHook";
1112
import {useQueries, useQuery} from "@tanstack/react-query";
1213
import {queryRetry} from "../../dataHooks/queryRetry";
13-
import React, {useEffect} from "react";
14+
import React, {useEffect, useRef} from "react";
1415
import {Datapoint as DatapointComponent, DatapointProps} from "./Datapoint";
1516
import FormattedTime from "../text/FormattedTime";
1617
import {DatapointLoader} from "../navigation/Loader";
@@ -28,7 +29,6 @@ import {faQuestionCircle} from "@fortawesome/free-regular-svg-icons";
2829
type Props<K extends DatapointType> = {
2930
dataType: K;
3031
filter?: GenericFilter;
31-
permission?: string;
3232
fallbackUnavailableExplanation?: string
3333
} & Omit<DatapointProps, 'value'>;
3434

@@ -91,9 +91,9 @@ function Format<K extends DatapointType>({value, formatType}: FormatProps<K>) {
9191
}
9292
}
9393

94-
export function calculatePermission(dataType: DatapointType, permission?: string, filter?: GenericFilter) {
94+
export function calculatePermission(dataType: DatapointType, filter?: GenericFilter) {
9595
if (!dataType) return '';
96-
const asPermission = permission || dataType.toLowerCase().replaceAll('_', '.');
96+
const asPermission = differingPermissions[dataType] || dataType.toLowerCase().replaceAll('_', '.');
9797
if (filter) {
9898
if (filter.player) return 'data.player.' + asPermission;
9999
if (filter.server?.length) return 'data.server.' + asPermission;
@@ -102,14 +102,13 @@ export function calculatePermission(dataType: DatapointType, permission?: string
102102
}
103103

104104
export function QueryDatapoint<K extends DatapointType>({
105-
permission,
106105
dataType,
107106
filter,
108107
fallbackUnavailableExplanation,
109108
...props
110109
}: Props<K>) {
111110
const {hasPermission} = useAuth();
112-
const allowed = hasPermission(calculatePermission(dataType, permission, filter));
111+
const allowed = hasPermission(calculatePermission(dataType, filter));
113112
const {data, isFetching, error} = useDatapointQuery(allowed, dataType, filter);
114113

115114
if (!allowed) return null;
@@ -140,9 +139,9 @@ export function QueryDatapoint<K extends DatapointType>({
140139
/>
141140
}
142141

143-
export function QueryDatapointValue<K extends DatapointType>({permission, dataType, filter}: ValueProps<K>) {
142+
export function QueryDatapointValue<K extends DatapointType>({dataType, filter}: ValueProps<K>) {
144143
const {hasPermission} = useAuth();
145-
const allowed = hasPermission(calculatePermission(dataType, permission, filter));
144+
const allowed = hasPermission(calculatePermission(dataType, filter));
146145
const {data, isFetching, error} = useDatapointQuery(allowed, dataType, filter);
147146
const {t} = useTranslation();
148147

@@ -161,14 +160,13 @@ export function QueryDatapointValue<K extends DatapointType>({permission, dataTy
161160
type TrendProps<K extends NumericDatapointType> = { downGood?: boolean, filter2: GenericFilter } & ValueProps<K>
162161

163162
export function QueryDatapointTrend<K extends NumericDatapointType>({
164-
permission,
165163
dataType,
166164
downGood,
167165
filter,
168166
filter2
169167
}: TrendProps<K>) {
170168
const {hasPermission} = useAuth();
171-
const allowed = hasPermission(calculatePermission(dataType, permission, filter));
169+
const allowed = hasPermission(calculatePermission(dataType, filter));
172170
const {data: before, error: error1} = useDatapointQuery(allowed, dataType, filter);
173171
const {data: after, error: error2} = useDatapointQuery(allowed, dataType, filter2);
174172

@@ -194,20 +192,25 @@ export function QueryDatapointTrend<K extends NumericDatapointType>({
194192

195193
export function useDatapointQuery<K extends DatapointType>(allowed: boolean, dataType: K, filter?: GenericFilter) {
196194
const {updateRequested} = useNavigation() as { updateRequested: number };
195+
const prevUpdateRef = useRef<number | undefined>(undefined);
197196
const query = useQuery({
198197
queryKey: filter ? ['datapoint', dataType, ...Object.values(filter)] : ['datapoint', dataType],
199198
queryFn: () => getDatapoint(dataType, filter),
200199
retry: queryRetry,
201200
enabled: Boolean(allowed)
202201
});
203202
useEffect(() => {
204-
query.refetch()
205-
}, [updateRequested]);
203+
if (allowed && prevUpdateRef.current && prevUpdateRef.current <= updateRequested) {
204+
query.refetch()
205+
}
206+
prevUpdateRef.current = updateRequested;
207+
}, [updateRequested, allowed]);
206208
return query;
207209
}
208210

209211
export function useDatapointQueries<K extends DatapointType>(allowed: boolean, dataType: K, filters: GenericFilter[]) {
210212
const {updateRequested} = useNavigation() as { updateRequested: number };
213+
const prevUpdateRef = useRef<number | undefined>(undefined);
211214
const query = useQueries({
212215
queries: filters.map(filter => ({
213216
queryKey: filter ? ['datapoint', dataType, ...Object.values(filter)] : ['datapoint', dataType],
@@ -217,8 +220,11 @@ export function useDatapointQueries<K extends DatapointType>(allowed: boolean, d
217220
}))
218221
});
219222
useEffect(() => {
220-
query.forEach(q => q.refetch())
221-
}, [updateRequested]);
223+
if (allowed && prevUpdateRef.current && prevUpdateRef.current <= updateRequested) {
224+
query.forEach(q => q.refetch())
225+
}
226+
prevUpdateRef.current = updateRequested;
227+
}, [updateRequested, allowed]);
222228
return query;
223229
}
224230

0 commit comments

Comments
 (0)