Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/plan-player-analytics/Plan
Browse files Browse the repository at this point in the history
…into folia-support
  • Loading branch information
ColdeZhang committed May 18, 2024
2 parents 7cc597f + 5e0780b commit 71d3f3f
Show file tree
Hide file tree
Showing 14 changed files with 533 additions and 651 deletions.
15 changes: 8 additions & 7 deletions Plan/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,14 @@ subprojects {

commonsTextVersion = "1.12.0"
commonsCompressVersion = "1.26.1"
commonsCodecVersion = "1.16.1"
commonsCodecVersion = "1.17.0"
caffeineVersion = "3.1.8"
jettyVersion = "11.0.20"
jettyVersion = "11.0.21"
caffeineVersion = "2.9.2"
mysqlVersion = "8.3.0"
mysqlVersion = "8.4.0"
mariadbVersion = "3.3.3"
sqliteVersion = "3.42.0.1"
adventureVersion = "4.14.0"
adventureVersion = "4.17.0"
hikariVersion = "5.1.0"
slf4jVersion = "2.0.13"
geoIpVersion = "4.2.0"
Expand All @@ -106,9 +106,10 @@ subprojects {
nkPlaceholderapiVersion = "1.4-SNAPSHOT"

junitVersion = "5.10.2"
mockitoVersion = "5.11.0"
testContainersVersion = "1.19.7"
swaggerVersion = "2.2.21"
mockitoVersion = "5.12.0"
seleniumVersion = "4.21.0"
testContainersVersion = "1.19.8"
swaggerVersion = "2.2.22"
}

repositories {
Expand Down
8 changes: 4 additions & 4 deletions Plan/common/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import org.apache.tools.ant.filters.ReplaceTokens
plugins {
id "dev.vankka.dependencydownload.plugin" version "$dependencyDownloadVersion"
id "com.github.node-gradle.node" version "7.0.2"
id "io.swagger.core.v3.swagger-gradle-plugin" version "2.2.21"
id "io.swagger.core.v3.swagger-gradle-plugin" version "2.2.22"
}

configurations {
Expand Down Expand Up @@ -56,7 +56,7 @@ dependencies {
shadow project(":extensions")

shadow "net.playeranalytics:platform-abstraction-layer-api:$palVersion"
compileOnly "net.kyori:adventure-api:4.14.0"
compileOnly "net.kyori:adventure-api:$adventureVersion"
shadow("dev.vankka:dependencydownload-runtime:$dependencyDownloadVersion") {
// Effectively disables relocating
exclude module: "jar-relocator"
Expand Down Expand Up @@ -87,15 +87,15 @@ dependencies {


// Swagger annotations
implementation "jakarta.ws.rs:jakarta.ws.rs-api:3.1.0"
implementation "jakarta.ws.rs:jakarta.ws.rs-api:4.0.0"
implementation "io.swagger.core.v3:swagger-core-jakarta:$swaggerVersion"
implementation "io.swagger.core.v3:swagger-jaxrs2-jakarta:$swaggerVersion"

testImplementation project(":api")
testArtifacts project(":extensions:adventure")
testImplementation project(":extensions:adventure")
testImplementation "com.google.code.gson:gson:$gsonVersion"
testImplementation "org.seleniumhq.selenium:selenium-java:4.19.1"
testImplementation "org.seleniumhq.selenium:selenium-java:$seleniumVersion"
testImplementation "org.testcontainers:testcontainers:$testContainersVersion"
testImplementation "org.testcontainers:junit-jupiter:$testContainersVersion"
testImplementation "org.testcontainers:nginx:$testContainersVersion"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,7 @@ public class RateLimitGuard {
.expireAfterWrite(120, TimeUnit.SECONDS)
.build();

public boolean shouldPreventRequest(@Untrusted String accessor) {
Integer attempts = requests.getIfPresent(accessor);
if (attempts == null) return false;
// Too many attempts, forbid further attempts.
return attempts >= ATTEMPT_LIMIT;
}

public void increaseAttemptCount(@Untrusted String requestPath, @Untrusted String accessor) {
public boolean shouldPreventRequest(@Untrusted String requestPath, @Untrusted String accessor) {
String previous = lastRequestPath.getIfPresent(accessor);
if (!Objects.equals(previous, requestPath)) {
resetAttemptCount(accessor);
Expand All @@ -60,23 +53,23 @@ public void increaseAttemptCount(@Untrusted String requestPath, @Untrusted Strin

lastRequestPath.put(accessor, requestPath);
requests.put(accessor, attempts + 1);

// Too many attempts, forbid further attempts.
return attempts + 1 >= ATTEMPT_LIMIT;
}

public void resetAttemptCount(@Untrusted String accessor) {
// previous request changed
requests.cleanUp();
requests.invalidate(accessor);
requests.cleanUp();
}

public static class Disabled extends RateLimitGuard {
@Override
public boolean shouldPreventRequest(String accessor) {
public boolean shouldPreventRequest(@Untrusted String requestedPath, String accessor) {
return false;
}

@Override
public void increaseAttemptCount(String requestPath, String accessor) { /* Disabled */ }

@Override
public void resetAttemptCount(String accessor) { /* Disabled */ }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,14 @@ public RequestHandler(WebserverConfiguration webserverConfiguration, ResponseFac
public Response getResponse(InternalRequest internalRequest) {
@Untrusted String accessAddress = internalRequest.getAccessAddress(webserverConfiguration);
@Untrusted String requestedPath = internalRequest.getRequestedPath();
rateLimitGuard.increaseAttemptCount(requestedPath, accessAddress);

boolean blocked = false;
Response response;
@Untrusted Request request = null;
if (bruteForceGuard.shouldPreventRequest(accessAddress)) {
response = responseFactory.failedLoginAttempts403();
blocked = true;
} else if (rateLimitGuard.shouldPreventRequest(accessAddress)) {
} else if (rateLimitGuard.shouldPreventRequest(requestedPath, accessAddress)) {
response = responseFactory.failedRateLimit403();
blocked = true;
} else if (!webserverConfiguration.getAllowedIpList().isAllowed(accessAddress)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* This file is part of Player Analytics (Plan).
*
* Plan is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License v3 as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Plan is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
*/
package com.djrapitops.plan.storage.database.transactions.commands;

import com.djrapitops.plan.storage.database.sql.tables.webuser.SecurityTable;
import com.djrapitops.plan.storage.database.sql.tables.webuser.WebGroupTable;
import com.djrapitops.plan.storage.database.sql.tables.webuser.WebGroupToPermissionTable;
import com.djrapitops.plan.storage.database.sql.tables.webuser.WebUserPreferencesTable;
import com.djrapitops.plan.storage.database.transactions.Transaction;

/**
* Transaction that removes all web groups from the database.
*
* @author AuroraLS3
*/
public class RemoveWebGroupsTransaction extends Transaction {

@Override
protected void performOperations() {
clearTable(WebUserPreferencesTable.TABLE_NAME);
clearTable(SecurityTable.TABLE_NAME);
clearTable(WebGroupToPermissionTable.TABLE_NAME);
clearTable(WebGroupTable.TABLE_NAME);
}

private void clearTable(String tableName) {
execute("DELETE FROM " + tableName);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -907,7 +907,7 @@ plugin:
no: ""
today: "'今天'"
unavailable: "不可用"
unknown: "位置"
unknown: "未知"
yes: ""
yesterday: "'昨天'"
localeReloaded: "自定义 locale.yml 已被修改,因此已重新加载并且现在正在使用。"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import com.djrapitops.plan.storage.database.Database;
import com.djrapitops.plan.storage.database.queries.objects.ServerQueries;
import com.djrapitops.plan.storage.database.transactions.StoreServerInformationTransaction;
import com.djrapitops.plan.storage.database.transactions.commands.RemoveWebGroupsTransaction;
import com.djrapitops.plan.storage.database.transactions.commands.StoreWebUserTransaction;
import com.djrapitops.plan.storage.database.transactions.events.StoreServerPlayerTransaction;
import com.djrapitops.plan.storage.database.transactions.webuser.StoreWebGroupTransaction;
Expand Down Expand Up @@ -94,6 +95,8 @@ static void setUp(PlanSystem system, @TempDir Path tempDir, PlanConfig config) t

@AfterEach
void tearDownTest(WebDriver driver) {
String address = "https://localhost:" + TEST_PORT_NUMBER + "/auth/logout";
driver.get(address);
SeleniumExtension.newTab(driver);
driver.manage().deleteAllCookies();
}
Expand Down Expand Up @@ -206,6 +209,8 @@ static Stream<Arguments> pageLevelVisibleCases() {
@ParameterizedTest(name = "Access with visibility {0} can see element #{1} in /{2}")
@MethodSource("pageLevelVisibleCases")
void pageVisible(WebPermission permission, String element, String page, Database database, ServerUUID serverUUID, ChromeDriver driver) throws Exception {
// TODO Remove after fixing manage/groups making bazillion calls to /v1/permissions
database.executeTransaction(new RemoveWebGroupsTransaction()).get();
User user = registerUser(database, permission);

String address = "https://localhost:" + TEST_PORT_NUMBER + "/" + page;
Expand Down Expand Up @@ -285,7 +290,7 @@ void serverPageElementNotVisible(WebPermission permission, String element, Strin
driver.get(address);
login(driver, user);

SeleniumExtension.waitForElementToBeVisible(By.id("wrapper"), driver);
SeleniumExtension.waitForElementToBeVisible(By.className("login-username"), driver);
By id = By.id(element);
assertThrows(NoSuchElementException.class, () -> driver.findElement(id), () -> "Saw element #" + element + " at " + address + " without permission to");
assertNoLogs(driver, address);
Expand Down Expand Up @@ -327,7 +332,7 @@ void networkPageElementNotVisible(WebPermission permission, String element, Stri
driver.get(address);
login(driver, user);

SeleniumExtension.waitForElementToBeVisible(By.id("wrapper"), driver);
SeleniumExtension.waitForElementToBeVisible(By.className("login-username"), driver);
By id = By.id(element);
assertThrows(NoSuchElementException.class, () -> driver.findElement(id), () -> "Saw element #" + element + " at " + address + " without permission to");
assertNoLogs(driver, address);
Expand Down Expand Up @@ -360,7 +365,7 @@ void playerPageElementNotVisible(WebPermission permission, String element, Strin
driver.get(address);
login(driver, user);

SeleniumExtension.waitForElementToBeVisible(By.id("wrapper"), driver);
SeleniumExtension.waitForElementToBeVisible(By.className("login-username"), driver);
By id = By.id(element);
assertThrows(NoSuchElementException.class, () -> driver.findElement(id), () -> "Saw element #" + element + " at " + address + " without permission to");
assertNoLogs(driver, address);
Expand Down Expand Up @@ -406,7 +411,7 @@ void playerSelfNonVisibilityTests(Database database, ServerUUID serverUUID, Chro
driver.get(address);
login(driver, playerUser);

SeleniumExtension.waitForElementToBeVisible(By.id("wrapper"), driver);
SeleniumExtension.waitForElementToBeVisible(By.className("login-username"), driver);
By id = By.id(element);
assertThrows(NoSuchElementException.class, () -> driver.findElement(id), () -> "Saw element #" + element + " at /player/" + TestConstants.PLAYER_TWO_UUID + " without permission to");
}
Expand Down
3 changes: 2 additions & 1 deletion Plan/common/src/test/java/extension/SeleniumExtension.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ public static void waitForElementToBeVisible(By by, ChromeDriver driver) {
SeleniumExtension.waitForPageLoadForSeconds(5, driver);
Awaitility.await("waitForElementToBeVisible " + by.toString())
.atMost(5, TimeUnit.SECONDS)
.ignoreException(NoSuchElementException.class)
.ignoreExceptionsMatching(throwable -> throwable instanceof NoSuchElementException
|| throwable instanceof StaleElementReferenceException)
.until(() -> driver.findElement(by).isDisplayed());
}

Expand Down
24 changes: 12 additions & 12 deletions Plan/react/dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,36 +12,36 @@
"@fortawesome/free-brands-svg-icons": "^6.5.2",
"@fortawesome/free-regular-svg-icons": "^6.5.2",
"@fortawesome/free-solid-svg-icons": "^6.5.2",
"@fortawesome/react-fontawesome": "^0.2.0",
"@fortawesome/react-fontawesome": "^0.2.1",
"@fullcalendar/bootstrap": "^6.1.11",
"@fullcalendar/core": "^6.1.11",
"@fullcalendar/daygrid": "^6.1.11",
"@fullcalendar/interaction": "^6.1.11",
"@fullcalendar/react": "^6.1.11",
"@highcharts/map-collection": "^2.1.0",
"@testing-library/jest-dom": "^6.4.2",
"@testing-library/react": "^15.0.2",
"@testing-library/jest-dom": "^6.4.5",
"@testing-library/react": "^15.0.7",
"@testing-library/user-event": "^14.5.2",
"axios": "^1.6.8",
"bootstrap": "^5.3.3",
"export-to-csv": "^1.2.4",
"highcharts": "^10.3.3",
"i18next": "^23.11.2",
"export-to-csv": "^1.3.0",
"highcharts": "^11.4.1",
"i18next": "^23.11.4",
"i18next-chained-backend": "^4.6.2",
"i18next-http-backend": "^2.5.1",
"i18next-localstorage-backend": "^4.2.0",
"masonry-layout": "^4.2.2",
"moment": "^2.30.1",
"react": "^18.2.0",
"react": "^18.3.1",
"react-bootstrap": "^2.10.2",
"react-bootstrap-range-slider": "^3.0.8",
"react-dom": "^18.2.0",
"react-i18next": "^14.1.0",
"react-i18next": "^14.1.1",
"react-mcjsonchat": "^1.0.0",
"react-router-dom": "6",
"sass": "^1.75.0",
"react-router-dom": "^6.23.1",
"sass": "^1.77.2",
"source-map-explorer": "^2.5.2",
"swagger-ui": "^5.16.1",
"swagger-ui": "^5.17.10",
"web-vitals": "^3.0.2"
},
"scripts": {
Expand Down Expand Up @@ -69,6 +69,6 @@
},
"devDependencies": {
"@vitejs/plugin-react": "^4.2.1",
"vite": "^5.2.9"
"vite": "^5.2.11"
}
}
1 change: 1 addition & 0 deletions Plan/react/dashboard/src/components/graphs/PunchCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const PunchCard = ({series}) => {
const punchCard = {
name: t('html.label.relativeJoinActivity'),
color: nightModeEnabled ? withReducedSaturation('#222') : '#222',
type: 'scatter',
data: series
};
Accessibility(Highcharts);
Expand Down
10 changes: 5 additions & 5 deletions Plan/react/dashboard/src/components/navigation/Sidebar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const InnerItem = ({href, icon, name, nameShort, color, external, collapseSideba
if (external) {
return (
<a href={href} className="collapse-item nav-button">
<Fa icon={icon} className={color ? "col-" + color : undefined}/>
<Fa icon={icon} className={color ? "col-" + color : ""}/>
<span>{nameShort ? nameShort : name}</span>
</a>
)
Expand All @@ -41,7 +41,7 @@ const InnerItem = ({href, icon, name, nameShort, color, external, collapseSideba
return <NavLink to={href} onClick={collapseSidebar} className={({isActive}) => {
return isActive ? "collapse-item nav-button active" : "collapse-item nav-button"
}}>
<Fa icon={icon} className={color ? "col-" + color : undefined}/> <span>{nameShort ? nameShort : name}</span>
<Fa icon={icon} className={color ? "col-" + color : ""}/> <span>{nameShort ? nameShort : name}</span>
</NavLink>
}

Expand All @@ -65,7 +65,7 @@ export const Item = ({item, inner, collapseSidebar}) => {
return (
<li className={"nav-item nav-button"}>
<a href={baseAddress + href} className="nav-link">
<Fa icon={icon} className={color ? "col-" + color : undefined}/>
<Fa icon={icon} className={color ? "col-" + color : ""}/>
<span>{t(nameShort ? nameShort : name)}</span>
</a>
</li>
Expand All @@ -77,7 +77,7 @@ export const Item = ({item, inner, collapseSidebar}) => {
<NavLink to={href} onClick={collapseSidebar} className={({isActive}) => {
return isActive ? "nav-link active" : "nav-link"
}}>
<Fa icon={icon} className={color ? "col-" + color : undefined}/> <span>{t(name)}</span>
<Fa icon={icon} className={color ? "col-" + color : ""}/> <span>{t(name)}</span>
</NavLink>
</li>
);
Expand Down Expand Up @@ -142,7 +142,7 @@ const SidebarCollapse = ({item, open, setOpen, collapseSidebar}) => {
aria-expanded={open}
data-bs-toggle="collapse"
>
<Fa icon={item.icon} className={item?.color ? "col-" + item?.color : undefined}/>
<Fa icon={item.icon} className={item?.color ? "col-" + item?.color : ""}/>
<span>{t(item.name)}</span>
</button>
<Collapse in={open}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export const GroupEditContextProvider = ({groupName, children}) => {

const [allPermissions, setAllPermissions] = useState([]);
useEffect(() => {
// TODO Make this only happen once when opening groups page
fetchAvailablePermissions().then(response => {
setAllPermissions(response?.data?.permissions);
});
Expand Down
Loading

0 comments on commit 71d3f3f

Please sign in to comment.