Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ jobs:
steps:
- uses: actions/checkout@v4

- uses: actions/checkout@v4
with:
repository: BanManagement/BanManager
path: BanManager
ref: master

- name: Set up JDK 17
uses: actions/setup-java@v4
with:
Expand All @@ -50,10 +56,19 @@ jobs:
key: ${{ runner.os }}-loom-${{ hashFiles('**/libs.versions.*', '**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: ${{ runner.os }}-loom-

- name: Publish BanManager to Maven Local
working-directory: BanManager
run: ./gradlew publishToMavenLocal --build-cache

- name: Clear stale BanManager dependency caches
run: |
find ~/.gradle/caches -path "*/me.confuser.banmanager*" -exec rm -rf {} + 2>/dev/null || true
find .gradle/loom-cache -path "*/BanManager*" -exec rm -rf {} + 2>/dev/null || true

- name: Execute Gradle build
env:
STORAGE_TYPE: ${{ matrix.storageType }}
run: ./gradlew build --build-cache --info
run: ./gradlew build --build-cache --refresh-dependencies --info

- name: Build all Fabric versions
run: ./gradlew :fabric:1.20.1:remapJar :fabric:1.21.1:remapJar :fabric:1.21.4:remapJar :fabric:1.21.11:remapJar --build-cache
11 changes: 10 additions & 1 deletion .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,15 @@ jobs:
key: ${{ runner.os }}-loom-${{ hashFiles('**/libs.versions.*', '**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: ${{ runner.os }}-loom-

- name: Publish BanManager to Maven Local
working-directory: BanManager
run: ./gradlew publishToMavenLocal --build-cache

- name: Clear stale BanManager dependency caches
run: |
find ~/.gradle/caches -path "*/me.confuser.banmanager*" -exec rm -rf {} + 2>/dev/null || true
find .gradle/loom-cache -path "*/BanManager*" -exec rm -rf {} + 2>/dev/null || true

# Docker Buildx for better caching
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
Expand Down Expand Up @@ -171,7 +180,7 @@ jobs:
run: ./gradlew ${{ matrix.build_task }} --build-cache

- name: Run E2E tests
run: ./gradlew :BanManagerWebEnhancerE2E:${{ matrix.task }} --build-cache -PbanManagerPath=BanManager
run: ./gradlew :BanManagerWebEnhancerE2E:${{ matrix.task }} --build-cache --refresh-dependencies -PbanManagerPath=BanManager
timeout-minutes: 15
env:
MC_VERSION: ${{ matrix.mc_version }}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package me.confuser.banmanager.webenhancer.bukkit.listeners;

import me.confuser.banmanager.common.ormlite.stmt.DeleteBuilder;
import me.confuser.banmanager.bukkit.api.events.PlayerBannedEvent;
import me.confuser.banmanager.bukkit.api.events.PlayerReportDeletedEvent;
import me.confuser.banmanager.bukkit.api.events.PlayerReportedEvent;
import me.confuser.banmanager.bukkit.api.events.PlayerDeniedEvent;
import me.confuser.banmanager.bukkit.api.events.PluginReloadedEvent;
import me.confuser.banmanager.common.util.Message;
import me.confuser.banmanager.common.data.PlayerReportData;
import me.confuser.banmanager.webenhancer.bukkit.BukkitPlugin;
import me.confuser.banmanager.webenhancer.common.data.LogData;
Expand Down Expand Up @@ -76,6 +78,17 @@ public void onDeny(PlayerDeniedEvent event) {
listener.handlePin(event.getPlayer(), event.getMessage());
}

@EventHandler(priority = EventPriority.MONITOR)
public void onBanned(PlayerBannedEvent event) {
try {
Message kickMessage = event.getKickMessage();
if (kickMessage != null) {
listener.handlePin(event.getBan().getPlayer(), kickMessage);
}
} catch (NoSuchMethodError ignored) {
}
}

@EventHandler
public void onReload(PluginReloadedEvent event) {
plugin.getPlugin().setupConfigs();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package me.confuser.banmanager.webenhancer.bungee.listeners;

import me.confuser.banmanager.bungee.api.events.PlayerBannedEvent;
import me.confuser.banmanager.bungee.api.events.PlayerDeniedEvent;
import me.confuser.banmanager.bungee.api.events.PluginReloadedEvent;
import me.confuser.banmanager.common.util.Message;
import me.confuser.banmanager.webenhancer.bungee.BungeePlugin;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
Expand All @@ -21,6 +23,17 @@ public void onDeny(PlayerDeniedEvent event) {
listener.handlePin(event.getPlayer(), event.getMessage());
}

@EventHandler
public void onBanned(PlayerBannedEvent event) {
try {
Message kickMessage = event.getKickMessage();
if (kickMessage != null) {
listener.handlePin(event.getBan().getPlayer(), kickMessage);
}
} catch (NoSuchMethodError ignored) {
}
}

@EventHandler
public void onReload(PluginReloadedEvent event) {
plugin.getPlugin().setupConfigs();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
package me.confuser.banmanager.webenhancer.common.runnables;

import me.confuser.banmanager.common.ormlite.stmt.DeleteBuilder;
import me.confuser.banmanager.common.BanManagerPlugin;
import me.confuser.banmanager.common.runnables.BmRunnable;
import me.confuser.banmanager.common.util.DateUtils;
import me.confuser.banmanager.webenhancer.common.WebEnhancerPlugin;
import me.confuser.banmanager.webenhancer.common.data.PlayerPinData;
import me.confuser.banmanager.webenhancer.common.storage.PlayerPinStorage;

import java.sql.SQLException;

public class ExpiresSync extends BmRunnable {
public class ExpiresSync implements Runnable {
private PlayerPinStorage pinStorage;

public ExpiresSync(WebEnhancerPlugin plugin) {
super(BanManagerPlugin.getInstance(), "pinCheck");

pinStorage = plugin.getPlayerPinStorage();
}

Expand Down
4 changes: 2 additions & 2 deletions e2e/platforms/bukkit/configs/banmanager/messages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ messages:
ban:
player:
disallowed: '&6You have been banned from this server for &4[reason]&6. Your appeal pin is [pin]'
kick: '&6You have been banned permanently for &4[reason]'
kick: '&6You have been banned permanently for &4[reason]&6. Your appeal pin is [pin]'
dateTimeFormat: 'yyyy-MM-dd HH:mm:ss'
notify: '&6[player] has been permanently banned by [actor] for &4[reason]'
error:
Expand All @@ -149,7 +149,7 @@ messages:
tempban:
player:
disallowed: '&6You have been temporarily banned from this server for &4[reason] \n&6It expires in [expires]. Your appeal pin is [pin]'
kick: '&6You have been temporarily banned for &4[reason]'
kick: '&6You have been temporarily banned for &4[reason]&6. Your appeal pin is [pin]'
dateTimeFormat: 'yyyy-MM-dd HH:mm:ss'
notify: '&6[player] has been temporarily banned for [expires] by [actor] for &4[reason]'

Expand Down
4 changes: 2 additions & 2 deletions e2e/platforms/bungee/configs/banmanager/messages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ messages:
player:
disallowed: '&6You have been banned from this server for &4[reason]&6. Your
appeal pin is [pin]'
kick: '&6You have been banned permanently for &4[reason]'
kick: '&6You have been banned permanently for &4[reason]&6. Your appeal pin is [pin]'
dateTimeFormat: yyyy-MM-dd HH:mm:ss
notify: '&6[player] has been permanently banned by [actor] for &4[reason]'
error:
Expand All @@ -155,7 +155,7 @@ messages:
player:
disallowed: '&6You have been temporarily banned from this server for &4[reason]
\n&6It expires in [expires]. Your appeal pin is [pin]'
kick: '&6You have been temporarily banned for &4[reason]'
kick: '&6You have been temporarily banned for &4[reason]&6. Your appeal pin is [pin]'
dateTimeFormat: yyyy-MM-dd HH:mm:ss
notify: '&6[player] has been temporarily banned for [expires] by [actor] for &4[reason]'
tempbanall:
Expand Down
4 changes: 2 additions & 2 deletions e2e/platforms/fabric/configs/banmanager/messages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ messages:
ban:
player:
disallowed: '&6You have been banned from this server for &4[reason]&6. Your appeal pin is [pin]'
kick: '&6You have been banned permanently for &4[reason]'
kick: '&6You have been banned permanently for &4[reason]&6. Your appeal pin is [pin]'
dateTimeFormat: 'yyyy-MM-dd HH:mm:ss'
notify: '&6[player] has been permanently banned by [actor] for &4[reason]'
error:
Expand All @@ -155,7 +155,7 @@ messages:
tempban:
player:
disallowed: '&6You have been temporarily banned from this server for &4[reason] \n&6It expires in [expires]. Your appeal pin is [pin]'
kick: '&6You have been temporarily banned for &4[reason]'
kick: '&6You have been temporarily banned for &4[reason]&6. Your appeal pin is [pin]'
dateTimeFormat: 'yyyy-MM-dd HH:mm:ss'
notify: '&6[player] has been temporarily banned for [expires] by [actor] for &4[reason]'

Expand Down
4 changes: 2 additions & 2 deletions e2e/platforms/sponge/configs/banmanager/messages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ messages:
ban:
player:
disallowed: '&6You have been banned from this server for &4[reason]&6. Your appeal pin is [pin]'
kick: '&6You have been banned permanently for &4[reason]'
kick: '&6You have been banned permanently for &4[reason]&6. Your appeal pin is [pin]'
dateTimeFormat: 'yyyy-MM-dd HH:mm:ss'
notify: '&6[player] has been permanently banned by [actor] for &4[reason]'
error:
Expand All @@ -149,7 +149,7 @@ messages:
tempban:
player:
disallowed: '&6You have been temporarily banned from this server for &4[reason] \n&6It expires in [expires]. Your appeal pin is [pin]'
kick: '&6You have been temporarily banned for &4[reason]'
kick: '&6You have been temporarily banned for &4[reason]&6. Your appeal pin is [pin]'
dateTimeFormat: 'yyyy-MM-dd HH:mm:ss'
notify: '&6[player] has been temporarily banned for [expires] by [actor] for &4[reason]'

Expand Down
4 changes: 2 additions & 2 deletions e2e/platforms/sponge7/configs/banmanager/messages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ messages:
ban:
player:
disallowed: '&6You have been banned from this server for &4[reason]&6. Your appeal pin is [pin]'
kick: '&6You have been banned permanently for &4[reason]'
kick: '&6You have been banned permanently for &4[reason]&6. Your appeal pin is [pin]'
dateTimeFormat: 'yyyy-MM-dd HH:mm:ss'
notify: '&6[player] has been permanently banned by [actor] for &4[reason]'
error:
Expand All @@ -149,7 +149,7 @@ messages:
tempban:
player:
disallowed: '&6You have been temporarily banned from this server for &4[reason] \n&6It expires in [expires]. Your appeal pin is [pin]'
kick: '&6You have been temporarily banned for &4[reason]'
kick: '&6You have been temporarily banned for &4[reason]&6. Your appeal pin is [pin]'
dateTimeFormat: 'yyyy-MM-dd HH:mm:ss'
notify: '&6[player] has been temporarily banned for [expires] by [actor] for &4[reason]'

Expand Down
4 changes: 2 additions & 2 deletions e2e/platforms/velocity/configs/banmanager/messages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ messages:
player:
disallowed: '&6You have been banned from this server for &4[reason]&6. Your
appeal pin is [pin]'
kick: '&6You have been banned permanently for &4[reason]'
kick: '&6You have been banned permanently for &4[reason]&6. Your appeal pin is [pin]'
dateTimeFormat: yyyy-MM-dd HH:mm:ss
notify: '&6[player] has been permanently banned by [actor] for &4[reason]'
error:
Expand All @@ -155,7 +155,7 @@ messages:
player:
disallowed: '&6You have been temporarily banned from this server for &4[reason]
\n&6It expires in [expires]. Your appeal pin is [pin]'
kick: '&6You have been temporarily banned for &4[reason]'
kick: '&6You have been temporarily banned for &4[reason]&6. Your appeal pin is [pin]'
dateTimeFormat: yyyy-MM-dd HH:mm:ss
notify: '&6[player] has been temporarily banned for [expires] by [actor] for &4[reason]'
tempbanall:
Expand Down
96 changes: 79 additions & 17 deletions e2e/tests/src/denied-pin.test.ts
Original file line number Diff line number Diff line change
@@ -1,44 +1,44 @@
import { TestBot, createBot, sendCommand, disconnectRcon, sleep } from './helpers'

afterAll(async () => {
await disconnectRcon()
})

describe('Denied Pin Placeholder', () => {
let bannedBot: TestBot | null = null
const BANNED_USERNAME = 'DeniedPinPlayer'
const TEST_TIMEOUT_MS = 60000
const TEST_TIMEOUT_MS = 120000

const expectDeniedConnection = async (): Promise<string> => {
let lastError: Error | null = null

// Ban/tempban enforcement can be async across worker threads; retry denied connect checks.
for (let attempt = 1; attempt <= 3; attempt++) {
// Use a short connect timeout (10s) so limbo connections (neither kicked nor spawned)
// don't burn the full 30s default, leaving room for more retries.
for (let attempt = 1; attempt <= 8; attempt++) {
const bot = new TestBot(BANNED_USERNAME)
try {
bannedBot = await createBot(BANNED_USERNAME)
await bannedBot.disconnect()
bannedBot = null
await bot.connect(10000)
await bot.disconnect()
lastError = new Error(`Attempt ${attempt}: player connected while expected to be denied`)
} catch (error: unknown) {
const errorMessage = error instanceof Error ? error.message : String(error)
if (errorMessage.includes('was kicked')) {
return errorMessage
}
lastError = error instanceof Error ? error : new Error(String(error))
try { await bot.disconnect() } catch (e) {}
}

await sleep(1000)
await sleep(2000)
}

throw lastError ?? new Error('Expected denied connection but did not receive a denial kick')
}

afterEach(async () => {
try {
await sendCommand(`bmunban ${BANNED_USERNAME}`)
} catch (e) {}
await bannedBot?.disconnect()
bannedBot = null
})

afterAll(async () => {
await disconnectRcon()
try { await sendCommand(`bmunban ${BANNED_USERNAME}`) } catch (e) {}
try { await sendCommand(`bmuntempban ${BANNED_USERNAME}`) } catch (e) {}
await sleep(2000)
})

test('[pin] placeholder in ban message is replaced with actual pin', async () => {
Expand All @@ -64,7 +64,7 @@ describe('Denied Pin Placeholder', () => {
test('[pin] placeholder in tempban message is replaced with actual pin', async () => {
const tempbanResponse = await sendCommand(`bmtempban ${BANNED_USERNAME} 1h Testing tempban pin placeholder`)
console.log(`Tempban response: ${tempbanResponse}`)
await sleep(2000)
await sleep(5000)

const errorMessage = await expectDeniedConnection()
console.log(`Player was denied (tempban) as expected: ${errorMessage}`)
Expand All @@ -82,3 +82,65 @@ describe('Denied Pin Placeholder', () => {
}
}, TEST_TIMEOUT_MS)
})

describe('Online Kick Pin Placeholder', () => {
const KICK_USERNAME = 'OnlineKickPin'
const TEST_TIMEOUT_MS = 60000
let bot: TestBot | null = null

afterEach(async () => {
await bot?.disconnect()
bot = null
try { await sendCommand(`bmunban ${KICK_USERNAME}`) } catch (e) {}
try { await sendCommand(`bmuntempban ${KICK_USERNAME}`) } catch (e) {}
await sleep(2000)
})

test('[pin] placeholder in kick message is replaced when banning an online player', async () => {
bot = await createBot(KICK_USERNAME)
const kickPromise = bot.waitForKick()

await sleep(1000)
const banResponse = await sendCommand(`bmban ${KICK_USERNAME} Testing online kick pin`)
console.log(`Ban response: ${banResponse}`)

const kickReason = await kickPromise
console.log(`Online player kicked with reason: ${kickReason}`)
bot = null

expect(kickReason).not.toContain('[pin]')

const pinMatch = kickReason.match(/pin is (\d{6})/)
expect(pinMatch).not.toBeNull()

if (pinMatch != null) {
const pin = pinMatch[1]
console.log(`Extracted pin from online kick message: ${pin}`)
expect(pin).toMatch(/^\d{6}$/)
}
}, TEST_TIMEOUT_MS)

test('[pin] placeholder in kick message is replaced when tempbanning an online player', async () => {
bot = await createBot(KICK_USERNAME)
const kickPromise = bot.waitForKick()

await sleep(1000)
const tempbanResponse = await sendCommand(`bmtempban ${KICK_USERNAME} 1h Testing online tempban kick pin`)
console.log(`Tempban response: ${tempbanResponse}`)

const kickReason = await kickPromise
console.log(`Online player kicked (tempban) with reason: ${kickReason}`)
bot = null

expect(kickReason).not.toContain('[pin]')

const pinMatch = kickReason.match(/pin is (\d{6})/)
expect(pinMatch).not.toBeNull()

if (pinMatch != null) {
const pin = pinMatch[1]
console.log(`Extracted pin from online tempban kick message: ${pin}`)
expect(pin).toMatch(/^\d{6}$/)
}
}, TEST_TIMEOUT_MS)
})
Loading
Loading