Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

handle permanent and sticky bans in database #5628

Merged
merged 45 commits into from
Feb 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
60b70c4
sticky n perm
harryob Sep 17, 2023
c01e454
oh finally
harryob Sep 19, 2023
d712d26
perma
harryob Sep 21, 2023
0684ac1
no more default ban pager
harryob Oct 12, 2023
3112d07
Merge remote-tracking branch 'upstream/master' into sticky-n-perma
harryob Jan 31, 2024
6fdfc0a
improvmens
harryob Feb 1, 2024
5695927
done ?
harryob Feb 1, 2024
7ff6042
player panel modifications
harryob Feb 1, 2024
d5add37
tidyup
harryob Feb 1, 2024
1a4792a
tidyup and sanity
harryob Feb 1, 2024
02ddbb0
remove the CI define
harryob Feb 1, 2024
31b15ee
who made and merged this insuffferable lint
harryob Feb 1, 2024
a81027f
lets not lie
harryob Feb 2, 2024
a0bb7c5
minor whoopsie
harryob Feb 2, 2024
4e66c43
don't make duplicate matches
harryob Feb 2, 2024
9135f03
final touches maybe
harryob Feb 2, 2024
a8409a9
improvements
harryob Feb 2, 2024
13687c1
improvements
harryob Feb 2, 2024
60d673a
documentation
harryob Feb 2, 2024
f450b71
important logs
harryob Feb 2, 2024
7ffd58f
fixes permaban runtime
harryob Feb 2, 2024
5e7cec3
tidyup
harryob Feb 2, 2024
e30493b
telemetry needs to stop causing duplicate connection warnings/logs
harryob Feb 3, 2024
d2aa0b8
pulls the logic out a bit, extra documentation
harryob Feb 3, 2024
9936a0d
additional documentation
harryob Feb 3, 2024
6dfa1fe
correctly `ckey()`s before we refer to it in `add_matched_ckey()`
harryob Feb 3, 2024
3e333e1
frontload stickyban dialogues, revert changes to `world.dm` and give …
harryob Feb 3, 2024
1574a5a
weird button scss rule removed
harryob Feb 3, 2024
23f2402
tgs logging improvements
harryob Feb 3, 2024
9a78c66
drathek improvement
harryob Feb 3, 2024
c0c69a8
this uses... british?
harryob Feb 3, 2024
9cdc599
ensures all keys being entered into legacy import are `ckey()`d
harryob Feb 4, 2024
242b071
i missed a ' it's over
harryob Feb 4, 2024
8228428
whoops!
harryob Feb 4, 2024
b904da9
sticky sanity
harryob Feb 4, 2024
86aa303
prevents permabans going through multiple times
harryob Feb 4, 2024
daf0539
all changes to logging
harryob Feb 5, 2024
36c53d1
silly mistake
harryob Feb 5, 2024
adbae76
pass the message through correctly
harryob Feb 5, 2024
f00d0f5
question order consistency
harryob Feb 5, 2024
d5779fe
code cleanup + additional stickyban panel tool to find matching stick…
harryob Feb 5, 2024
e062b2d
we should, like... probably stop here if this dialogue is cancelled
harryob Feb 5, 2024
c289596
removes `log_and_message_admins()` because `message_admins()` already…
harryob Feb 10, 2024
9794fee
eek, sdmm didn't pick this up (though it's obvious)
harryob Feb 10, 2024
59626c3
does this properly
harryob Feb 12, 2024
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
5 changes: 3 additions & 2 deletions code/__DEFINES/subsystems.dm
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,9 @@
#define SS_INIT_DATABASE -27
#define SS_INIT_ENTITYMANAGER -28
#define SS_INIT_PLAYTIME -29
#define SS_INIT_PREDSHIPS -30
#define SS_INIT_OBJECTIVES -31
#define SS_INIT_STICKY -30
#define SS_INIT_PREDSHIPS -31
#define SS_INIT_OBJECTIVES -32
#define SS_INIT_MINIMAP -34
#define SS_INIT_STATPANELS -98
#define SS_INIT_CHAT -100 //Should be last to ensure chat remains smooth during init.
Expand Down
2 changes: 2 additions & 0 deletions code/controllers/configuration/entries/general.dm
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,8 @@ This maintains a list of ip addresses that are able to bypass topic filtering.

/datum/config_entry/string/round_results_webhook_url

/datum/config_entry/string/important_log_channel

/// InfluxDB v2 Host to connect to for sending statistics (over HTTP API)
/datum/config_entry/string/influxdb_host
/// InfluxDB v2 Bucket to send staistics to
Expand Down
284 changes: 284 additions & 0 deletions code/controllers/subsystem/stickyban.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,284 @@
SUBSYSTEM_DEF(stickyban)
name = "Sticky Ban"
init_order = SS_INIT_STICKY
flags = SS_NO_FIRE

/datum/controller/subsystem/stickyban/Initialize()
var/list/all_bans = world.GetConfig("ban")

for(var/existing_ban in all_bans)
var/list/ban_data = params2list(world.GetConfig("ban", existing_ban))
INVOKE_ASYNC(src, PROC_REF(import_sticky), existing_ban, ban_data)

return SS_INIT_SUCCESS

/**
* Returns a list of [/datum/view_record/stickyban]s, or null, if no stickybans are found. All arguments are optional, but you should pass at least one if you want any results.
*/
/datum/controller/subsystem/stickyban/proc/check_for_sticky_ban(ckey, address, computer_id)
var/list/stickyban_ids = list()

for(var/datum/view_record/stickyban_matched_ckey/matched_ckey as anything in get_impacted_ckey_records(ckey))
stickyban_ids += matched_ckey.linked_stickyban

for(var/datum/view_record/stickyban_matched_cid/matched_cid as anything in get_impacted_cid_records(computer_id))
stickyban_ids += matched_cid.linked_stickyban

for(var/datum/view_record/stickyban_matched_ip/matched_ip as anything in get_impacted_ip_records(address))
stickyban_ids += matched_ip.linked_stickyban

if(!length(stickyban_ids))
return FALSE

var/list/datum/view_record/stickyban/stickies = DB_VIEW(/datum/view_record/stickyban,
DB_AND(
DB_COMP("id", DB_IN, stickyban_ids),
DB_COMP("active", DB_EQUALS, TRUE)
)
)

for(var/datum/view_record/stickyban/current_sticky in stickies)
if(length(get_whitelisted_ckey_records(current_sticky.id, ckey)))
stickies -= current_sticky

if(!length(stickies))
return FALSE

return stickies

/**
* Associates an existing stickyban with a new match, either of a ckey, address, or computer_id. Or all three.
*
* Arguments:
* - existing_ban_id, int, required
* - ckey, string, optional
* - address, string, optional
* - computer_id, string, optional
*/
/datum/controller/subsystem/stickyban/proc/match_sticky(existing_ban_id, ckey, address, computer_id)
if(!existing_ban_id)
return

if(ckey)
add_matched_ckey(existing_ban_id, ckey)

if(address)
add_matched_ip(existing_ban_id, address)

if(computer_id)
add_matched_cid(existing_ban_id, computer_id)

/**
* Adds a new tracked stickyban, and returns a [/datum/entity/stickyban] if it was successful. Blocking, sleeps.
*/
/datum/controller/subsystem/stickyban/proc/add_stickyban(identifier, reason, message, datum/entity/player/banning_admin, override_date)
var/datum/entity/stickyban/new_sticky = DB_ENTITY(/datum/entity/stickyban)
new_sticky.identifier = identifier
new_sticky.reason = reason
new_sticky.message = message

if(banning_admin)
new_sticky.adminid = banning_admin.id

new_sticky.date = override_date ? override_date : "[time2text(world.realtime, "YYYY-MM-DD hh:mm:ss")]"
new_sticky.save()
new_sticky.sync()

return new_sticky

/// Adds a ckey match to the specified sticky ban.
/datum/controller/subsystem/stickyban/proc/add_matched_ckey(existing_ban_id, key)
key = ckey(key)

if(length(DB_VIEW(/datum/view_record/stickyban_matched_ckey,
DB_AND(
DB_COMP("linked_stickyban", DB_EQUALS, existing_ban_id),
DB_COMP("ckey", DB_EQUALS, key)
)
)))
return

var/datum/entity/stickyban_matched_ckey/matched_ckey = DB_ENTITY(/datum/entity/stickyban_matched_ckey)

matched_ckey.ckey = key
matched_ckey.linked_stickyban = existing_ban_id

matched_ckey.save()

/// Adds an IP match to the specified stickyban.
/datum/controller/subsystem/stickyban/proc/add_matched_ip(existing_ban_id, ip)
if(length(DB_VIEW(/datum/view_record/stickyban_matched_ip,
DB_AND(
DB_COMP("linked_stickyban", DB_EQUALS, existing_ban_id),
DB_COMP("ip", DB_EQUALS, ip)
)
)))
return

var/datum/entity/stickyban_matched_ip/matched_ip = DB_ENTITY(/datum/entity/stickyban_matched_ip)

matched_ip.ip = ip
matched_ip.linked_stickyban = existing_ban_id

matched_ip.save()

/// Adds a CID match to the specified stickyban.
/datum/controller/subsystem/stickyban/proc/add_matched_cid(existing_ban_id, cid)
if(length(DB_VIEW(/datum/view_record/stickyban_matched_cid,
DB_AND(
DB_COMP("linked_stickyban", DB_EQUALS, existing_ban_id),
DB_COMP("cid", DB_EQUALS, cid)
)
)))
return


var/datum/entity/stickyban_matched_cid/matched_cid = DB_ENTITY(/datum/entity/stickyban_matched_cid)

matched_cid.cid = cid
matched_cid.linked_stickyban = existing_ban_id

matched_cid.save()

/// Whitelists a specific CKEY to the specified stickyban, which will allow connection, even with matching CIDs and IPs.
/datum/controller/subsystem/stickyban/proc/whitelist_ckey(existing_ban_id, key)
key = ckey(key)

if(!key)
return

var/id_to_select

var/list/datum/view_record/stickyban_matched_ckey/existing_matches = DB_VIEW(/datum/view_record/stickyban_matched_ckey,
DB_AND(
DB_COMP("linked_stickyban", DB_EQUALS, existing_ban_id),
DB_COMP("ckey", DB_EQUALS, key)
)
)

if(length(existing_matches))
var/datum/view_record/stickyban_matched_ckey/match = existing_matches[1]
id_to_select = match.id

var/datum/entity/stickyban_matched_ckey/whitelisted_ckey = DB_ENTITY(/datum/entity/stickyban_matched_ckey, id_to_select)

whitelisted_ckey.ckey = key
whitelisted_ckey.linked_stickyban = existing_ban_id
whitelisted_ckey.whitelisted = TRUE

whitelisted_ckey.save()

/**
* Returns a [/list] of [/datum/view_record/stickyban_matched_ckey] where the ckey provided has not been
* whitelisted from the stickyban, and would be prevented from joining - provided that the stickyban itself
* remains active.
*/
/datum/controller/subsystem/stickyban/proc/get_impacted_ckey_records(key)
key = ckey(key)

return DB_VIEW(/datum/view_record/stickyban_matched_ckey,
DB_AND(
DB_COMP("ckey", DB_EQUALS, key),
DB_COMP("whitelisted", DB_EQUALS, FALSE)
)
)

/**
* Returns a [/list] of [/datum/view_record/stickyban_matched_ckey] which have been manually whitelisted by an admin and matches the provided existing_ban_id and key.
*/
/datum/controller/subsystem/stickyban/proc/get_whitelisted_ckey_records(existing_ban_id, key)
key = ckey(key)

return DB_VIEW(/datum/view_record/stickyban_matched_ckey,
DB_AND(
DB_COMP("linked_stickyban", DB_EQUALS, existing_ban_id),
DB_COMP("ckey", DB_EQUALS, key),
DB_COMP("whitelisted", DB_EQUALS, TRUE),
)
)

/**
* Returns a [/list] of [/datum/view_record/stickyban_matched_cid] where the impacted CID matches the CID provided.
* Connections matching this CID will be blocked - provided the linked stickyban is active.
*/
/datum/controller/subsystem/stickyban/proc/get_impacted_cid_records(cid)
return DB_VIEW(/datum/view_record/stickyban_matched_cid,
DB_COMP("cid", DB_EQUALS, cid)
)

/**
* Returns a [/list] of [/datum/view_record/stickyban_matched_ip] where the impacted IP matches the IP provided.
* Connections matchin this IP will be blocked - provided the linked stickyban is active.
*/
/datum/controller/subsystem/stickyban/proc/get_impacted_ip_records(ip)
return DB_VIEW(/datum/view_record/stickyban_matched_ip,
DB_COMP("ip", DB_EQUALS, ip)
)

/// Legacy import from pager bans to database bans.
/datum/controller/subsystem/stickyban/proc/import_sticky(identifier, list/ban_data)
WAIT_DB_READY

if(ban_data["type"] != "sticky")
handle_old_perma(identifier, ban_data)
return

if(!ban_data["message"])
ban_data["message"] = "Evasion"

add_stickyban(identifier, ban_data["reason"], ban_data["message"], override_date = "LEGACY")

/**
* We abuse the on_insert from ndatabase here to ensure we have the synced ID of the new stickyban when applying a *lot* of associated bans. If we don't have a matching pager ban with the new sticky's identifier, we stop.
*/
/datum/entity_meta/stickyban/on_insert(datum/entity/stickyban/new_sticky)
var/list/ban_data = params2list(world.GetConfig("ban", new_sticky.identifier))

if(!length(ban_data))
return

var/list/whitelisted = list()
if(ban_data["whitelist"])
whitelisted = splittext(ban_data["whitelist"], ",")
for(var/key in whitelisted)
SSstickyban.whitelist_ckey(new_sticky.id, key)

if(ban_data["keys"])
var/list/keys = splittext(ban_data["keys"], ",")
keys -= whitelisted
for(var/key in keys)
SSstickyban.add_matched_ckey(new_sticky.id, key)

if(ban_data["computer_id"])
var/list/cids = splittext(ban_data["computer_id"], ",")
for(var/cid in cids)
SSstickyban.add_matched_cid(new_sticky.id, cid)

if(ban_data["IP"])
var/list/ips = splittext(ban_data["IP"], ",")
for(var/ip in ips)
SSstickyban.add_matched_ip(new_sticky.id, ip)

world.SetConfig("ban", new_sticky.identifier, null)

/// Imports permabans from the old ban.txt, and does *not* ban people that have been whitelisted.
/datum/controller/subsystem/stickyban/proc/handle_old_perma(identifier, list/ban_data)
var/list/keys_to_ban = list()

keys_to_ban += splittext(ban_data["keys"], ",")

for(var/x in 1 to length(keys_to_ban))
keys_to_ban[x] = ckey(keys_to_ban[x])

var/list/keys = splittext(ban_data["whitelist"], ",")
for(var/key in keys)
keys_to_ban -= ckey(key)

for(var/key in keys_to_ban)
var/datum/entity/player/player_entity = get_player_from_key(key)
if(!player_entity)
continue

INVOKE_ASYNC(player_entity, TYPE_PROC_REF(/datum/entity/player, add_perma_ban), ban_data["message"])

world.SetConfig("ban", identifier, null)
Loading
Loading