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

Wip: SS Central - whitelist, discord link #946

Open
wants to merge 40 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
a512e53
wip ss central: wl and discord link
Furrior Dec 31, 2024
8713643
sshttp "improvement"
Furrior Jan 1, 2025
c537115
wip wl
Furrior Jan 1, 2025
c9191b7
typos
Furrior Jan 1, 2025
73b26b3
giving wl from interview
Furrior Jan 1, 2025
9bd06bd
nuke the old system
Furrior Jan 1, 2025
a50221f
Update modular_bandastation/tts/code/SSHttp.dm
Furrior Jan 1, 2025
91ef632
fixes
Furrior Jan 1, 2025
63508e8
Merge remote-tracking branch 'fur/sscentral' into sscentral
Furrior Jan 1, 2025
e211807
comments in config
Furrior Jan 1, 2025
0c05486
missed log
Furrior Jan 1, 2025
d3c84a6
typo
Furrior Jan 1, 2025
a6c86b4
or
Furrior Jan 1, 2025
06a1f85
Update modular_bandastation/metaserver/code/admin.dm
Furrior Jan 1, 2025
f98a847
various fixes
Furrior Jan 3, 2025
15afadf
atually include admin.dm
Furrior Jan 4, 2025
bc2bc96
rename discord link verb
Furrior Jan 4, 2025
c4bb628
admin.dm fixes
Furrior Jan 4, 2025
73411b9
better check for duration days
Furrior Jan 4, 2025
0188fe9
status code bandaid
Furrior Jan 4, 2025
bfba3c1
ah yes
Furrior Jan 4, 2025
be20bbc
update?
Furrior Feb 1, 2025
304f0fe
Merge remote-tracking branch 'origin/master' into sscentral
Furrior Feb 1, 2025
df71569
typo
Furrior Feb 1, 2025
b342c7e
fuck it
Furrior Feb 1, 2025
b31657e
fix tests
Furrior Feb 6, 2025
4589bab
its working I guess
Furrior Feb 7, 2025
a5e9cb6
config
Furrior Feb 7, 2025
cb5293a
bb
Furrior Feb 7, 2025
33ea3a7
central update
Furrior Feb 10, 2025
5a9575b
Update modular_bandastation/tts/code/SSHttp.dm
Furrior Feb 10, 2025
1b84f1c
req rename
Furrior Feb 10, 2025
255fe2f
admins need wl too
Furrior Feb 11, 2025
82dc99b
fiiiiiine
Furrior Feb 11, 2025
a37d5a7
wl double check
Furrior Feb 11, 2025
44af0ea
translations
Furrior Feb 11, 2025
d9d5d58
fixes
Furrior Feb 11, 2025
8dc5d27
stat entry
Furrior Feb 11, 2025
9ab24bc
typo
Furrior Feb 11, 2025
a24946b
translate no wl message
Furrior Feb 11, 2025
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
4 changes: 4 additions & 0 deletions code/modules/admin/whitelist.dm
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,8 @@ GLOBAL_LIST(whitelist)
return FALSE
. = (ckey in GLOB.whitelist)

// SS220 ADDITION - SS Central
if (!. && SScentral.initialized)
. = SScentral.is_player_whitelisted(ckey)

#undef WHITELISTFILE
10 changes: 8 additions & 2 deletions config/bandastation/bandastation_config.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,19 @@
#TTS_CACHE_ENABLED
#TTS_API_URL_SILERO

#WHITELIST220
## SS Central
Furrior marked this conversation as resolved.
Show resolved Hide resolved
SS_CENTRAL_URL http://127.0.0.1:8000
SS_CENTRAL_TOKEN 12345678
Furrior marked this conversation as resolved.
Show resolved Hide resolved
Furrior marked this conversation as resolved.
Show resolved Hide resolved
WHITELIST_TYPE default
## Entry from the general config.txt
#USEWHITELIST

## A minimum amount of security required on roundstart
## If there is less security than this value, a percent of roundstart threat will be pushed to midround
## Example: with value of 5, if there is 2 security members out of 5, then 3/5 of roundstart threat will be moved to midround
#ROUNDSTART_SECURITY_FOR_THREAT 5

## Webhooks
#TRANSLATE_SUGGEST_WEBHOOK_URL

#INTERVIEW_WEBHOOK_URL
Expand All @@ -32,4 +38,4 @@ ROUNDSTART_RACES vulpkanin
## If players are able to create crew transfer vote
#ALLOW_CREW_TRANSFER_VOTE
## If automatic crew transfer is enabled
#ENABLE_AUTOMATIC_CREW_TRANSFER
#ENABLE_AUTOMATIC_CREW_TRANSFER
4 changes: 2 additions & 2 deletions modular_bandastation/discord/_discord.dm
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/datum/modpack/links_change
name = "Привязка Дискорда."
desc = "Добавление привязки Дискорда."
name = "Дискорд."
desc = "Ссылка на дискорд."
author = "KOJIT2009"
40 changes: 0 additions & 40 deletions modular_bandastation/discord/code/discord.dm
Original file line number Diff line number Diff line change
@@ -1,46 +1,6 @@
/datum/config_entry/string/discordurl
default = "https://discord.gg/SS220"

/client/New()
. = ..()
prefs.discord_id = SSdiscord.lookup_id(ckey)

/datum/preferences
var/discord_id

// IF you have linked your account, this will trigger a verify of the user
/client/verify_in_discord()
// Safety checks
if(!CONFIG_GET(flag/sql_enabled))
to_chat(src, span_warning("This feature requires the SQL backend to be running."))
return

// Why this would ever be unset, who knows
var/prefix = CONFIG_GET(string/discordbotcommandprefix)
if(!prefix)
to_chat(src, span_warning("Нет префикса для discord verification"))

if(!SSdiscord || !SSdiscord.reverify_cache)
to_chat(src, span_warning("Wait for the Discord subsystem to finish initialising"))
return
var/message = ""
// Simple sanity check to prevent a user doing this too often
var/cached_one_time_token = SSdiscord.reverify_cache[usr.ckey]
if(cached_one_time_token && cached_one_time_token != "")
message = "Вы уже сгенерировали токен <br/> [cached_one_time_token] <br/> В канале дом-бота используйте команду <br/> <span class='warning'>[prefix]привязать</span>"


else
// Will generate one if an expired one doesn't exist already, otherwise will grab existing token
var/one_time_token = SSdiscord.get_or_generate_one_time_token_for_ckey(ckey)
SSdiscord.reverify_cache[usr.ckey] = one_time_token
message = "В канале дом-бота используйте команду <br/> <span class='warning'>[prefix]привязать</span> и введите туда свой токен <br/> [one_time_token]"

//Now give them a browse window so they can't miss whatever we told them
var/datum/browser/window = new/datum/browser(usr, "discordverification", "Discord verification")
window.set_content("<span>[message]</span>")
window.open()

//Please use mob or src (not usr) in these procs. This way they can be called in the same fashion as procs.
/client/verb/discord()
set name = "discord"
Expand Down
4 changes: 4 additions & 0 deletions modular_bandastation/metaserver/_metaserver.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/datum/modpack/metaserver
name = "Metaserver"
desc = "Использование вайтлиста через БД"
author = "furior, larentoun"
5 changes: 5 additions & 0 deletions modular_bandastation/metaserver/_metaserver.dme
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#include "_metaserver.dm"

#include "code/discord_link.dm"
#include "code/interview.dm"
#include "code/ss_central.dm"
16 changes: 16 additions & 0 deletions modular_bandastation/metaserver/code/admin.dm
Gaxeer marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
ADMIN_VERB(wl_ban, R_BAN, "WL Ban", "Ban a player from the whitelist.", ADMIN_CATEGORY_MAIN)
var/banned_ckey = input(user, "Please specify the cckey of the player you want to ban from the whitelist.", "WL Ban", "") as string|null
Furrior marked this conversation as resolved.
Show resolved Hide resolved
banned_ckey = ckey(ckey)
if(!input)
return
var/duration_days = input(user, "Please specify the duration of the ban in days.", "Duration", "") as num|null
if(!duration_days or duration_days < 0)
return

var/reason = input(user, "Please specify the reason for the ban.", "Reason", "") as text|null

SScentral.whitelist_ban_player(banned_ckey, admin_ckey, duration_days, reason)

log_admin("[key_name(user)] banned [banned_ckey] from whitelist for [duration_days] days for reason: [reason]")
message_admins("[key_name_admin(user)] banned [banned_ckey] from whitelist for [duration_days] days for reason: [reason]")
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("WL Ban", "Ckey: [banned_ckey], Duration: [duration_days], Reason: [reason]"))
34 changes: 34 additions & 0 deletions modular_bandastation/metaserver/code/discord_link.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/datum/preferences
var/discord_id

/client/New()
. = ..()
SScentral.get_player_discord_async(src)

/client/verify_in_discord()
if(!SScentral.initialized)
to_chat(src, span_warning("Привязка Discord сейчас недоступна."))

if(SScentral.discord_links[src.ckey])
to_chat(src, span_warning("Вы уже привязали свою учетную запись Discord."))

to_chat(src, span_notice("Пытаемся получить токен для входа в Discord..."))
SScentral.verify_in_discord(src)

/datum/controller/subsystem/central/proc/verify_in_discord(client/player)
var/endpoint = "[CONFIG_GET(string/ss_central_url)]/player/token/[player.ckey]"
var/list/headers = list(
"Authorization" = "Bearer [CONFIG_GET(string/ss_central_token)]"
)
SShttp.create_async_request(RUSTG_HTTP_METHOD_POST, endpoint, "", headers, CALLBACK(SScentral, PROC_REF(verify_in_discord_callback), player))

/datum/controller/subsystem/central/proc/verify_in_discord_callback(client/player, datum/http_response/response)
if(response.errored || response.status_code != 201)
stack_trace("Failed to get discord verification token: HTTP status code " + response.status_code)
return

var/list/data = json_decode(response.body)
var/login_endpoint = "[CONFIG_GET(string/ss_central_url)]/player/login?token=[data]"

to_chat(player, span_big("Авторизуйтесь в открывшемся окне. Если окно не открывается, можете открыть сами ссылку <a href='[login_endpoint]'>[login_endpoint]</a> в браузере."))
player << link(login_endpoint)
52 changes: 52 additions & 0 deletions modular_bandastation/metaserver/code/interview.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/// Doesnt need the panic bunker to work
/mob/dead/new_player/proc/check_whitelist_or_make_interviewee()
if(!CONFIG_GET(flag/panic_bunker_interview))
return
if(SScentral.is_player_whitelisted(ckey))
client.interviewee = FALSE
return
client.interviewee = TRUE

/datum/config_entry/string/interview_webhook_url

/datum/interview/approve(client/approved_by)
. = ..()
add_owner_to_whitelist(approved_by)
send_interview_webhook(src, "[approved_by.ckey] approved:")

/datum/interview_manager/enqueue(datum/interview/to_queue)
. = ..()
send_interview_webhook(to_queue, "New interview enqueued:")

/datum/interview/deny(client/denied_by)
. = ..()
send_interview_webhook(src, "[denied_by.ckey] denied:")

/datum/interview/proc/serialize_embed()
. = list(
"fields" = list(),
"author" = list(
"name" = owner_ckey
)
)
for(var/question_id in 1 to length(questions))
var/list/question_data = list(
"name" = "[questions[question_id]]",
"value" = "[isnull(responses[question_id]) ? "N/A" : responses[question_id]]"
)
.["fields"] += list(question_data)
return .

/proc/send_interview_webhook(datum/interview/interview, additional_msg)
var/webhook = CONFIG_GET(string/interview_webhook_url)
if(!webhook || !interview)
return
var/list/webhook_info = list()
webhook_info["content"] = additional_msg
webhook_info["embeds"] = list(interview.serialize_embed())
var/list/headers = list()
headers["Content-Type"] = "application/json"
SShttp.create_async_request(RUSTG_HTTP_METHOD_POST, webhook, json_encode(webhook_info), headers)

/datum/interview/proc/add_owner_to_whitelist(client/added_by)
SScentral.add_to_whitelist(owner_ckey, added_by.ckey, 365)
124 changes: 124 additions & 0 deletions modular_bandastation/metaserver/code/ss_central.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/datum/config_entry/string/ss_central_url
default = ""
protection = CONFIG_ENTRY_LOCKED

/datum/config_entry/string/ss_central_token
default = ""
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN

/datum/config_entry/string/whitelist_type
default = "default"

SUBSYSTEM_DEF(central)
var/list/discord_links = list()
flags = SS_NO_FIRE

/datum/controller/subsystem/central/Initialize()
if(!(CONFIG_GET(string/ss_central_url) && CONFIG_GET(string/ss_central_token)))
return SS_INIT_FAILURE
load_whitelist()

/datum/controller/subsystem/central/proc/load_whitelist()
var/endpoint = "[CONFIG_GET(string/ss_central_url)]/whitelist/simple/active_whitelists/ckey?wl_type=[CONFIG_GET(string/whitelist_type)]"

SShttp.create_async_request(RUSTG_HTTP_METHOD_GET, endpoint, "", list(), CALLBACK(src, PROC_REF(load_whitelist_callback)))

/datum/controller/subsystem/central/proc/load_whitelist_callback(datum/http_response/response)
if(response.errored || response.status_code != 200)
stack_trace("Failed to load whitelist: HTTP status code [response.status_code]")
return

var/list/ckeys = json_decode(response.body)
GLOB.whitelist = ckeys

/datum/controller/subsystem/central/proc/get_player_discord_async(client/player)
var/endpoint = "[CONFIG_GET(string/ss_central_url)]/player/ckey/[player.ckey]"

SShttp.create_async_request(RUSTG_HTTP_METHOD_GET, endpoint, "", list(), CALLBACK(src, PROC_REF(get_player_discord_callback), player))

/datum/controller/subsystem/central/proc/get_player_discord_callback(client/player, datum/http_response/response)
if(response.errored || response.status_code != 200)
stack_trace("Failed to get player discord: HTTP status code [response.status_code]")
return

var/list/data = json_decode(response.body)
var/discord_id = data["discord_id"]
var/ckey = data["ckey"]
discord_links[ckey] = discord_id

player.prefs.discord_id = discord_id

/datum/controller/subsystem/central/proc/is_player_discord_linked(client/player)
if(!player)
return FALSE

if(player.prefs.discord_id)
return TRUE

// If player somehow losed its id. Not sure if needed
if(SScentral.discord_links[player.ckey])
player.prefs.discord_id = SScentral.discord_links[player.ckey]
return TRUE

// Update the info just in case
SScentral.get_player_discord_async(src)

return FALSE

/// WARNING: only semi async - UNTIL based
/datum/controller/subsystem/central/proc/is_player_whitelisted(ckey)
. = (ckey in GLOB.whitelist)
Copy link
Collaborator

@Gaxeer Gaxeer Feb 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

не совсем понял зачем это, если ты всё равно делаешь запрос в любом случае, и если запрос зафейлен, то возвращаешь FALSE.


var/endpoint = "[CONFIG_GET(string/ss_central_url)]/whitelist/simple/is_whitelisted/ckey/[ckey]?wl_type=[CONFIG_GET(string/whitelist_type)]"
var/datum/http_response/response = SShttp.make_blocking_request(RUSTG_HTTP_METHOD_GET, endpoint, "", list())
if(response.errored || response.status_code != 200)
return FALSE

return json_decode(response.body)

/datum/controller/subsystem/central/proc/add_to_whitelist(ckey, added_by, duration_days = 0)
var/endpoint = "[CONFIG_GET(string/ss_central_url)]/whitelist/ckey"

var/list/headers = list()
headers["Authorization"] = "Bearer [CONFIG_GET(string/ss_central_token)]"
var/list/body = list()
body["player_ckey"] = ckey
body["admin_ckey"] = added_by
body["wl_type"] = CONFIG_GET(string/whitelist_type)
body["duration_days"] = duration_days

SShttp.create_async_request(RUSTG_HTTP_METHOD_POST, endpoint, json_encode(body), headers, CALLBACK(src, PROC_REF(add_to_whitelist_callback)))

/datum/controller/subsystem/central/proc/add_to_whitelist_callback(datum/http_response/response)
if(response.errored || response.status_code != 200)
stack_trace("Failed to add to whitelist: HTTP status code [response.status_code]")
return

var/list/data = json_decode(response.body)
var/ckey = data["ckey"]

GLOB.whitelist |= ckey

/datum/controller/subsystem/central/proc/whitelist_ban_player(player_ckey, admin_ckey, duration_days, reason)
var/endpoint = "[CONFIG_GET(string/ss_central_url)]/whitelist/ban/ckey"

var/list/headers = list()
headers["Authorization"] = "Bearer [CONFIG_GET(string/ss_central_token)]"
var/list/body = list()
body["player_ckey"] = player_ckey
body["admin_ckey"] = admin_ckey
body["wl_type"] = CONFIG_GET(string/whitelist_type)
body["duration_days"] = duration_days
body["reason"] = reason

SShttp.create_async_request(RUSTG_HTTP_METHOD_POST, endpoint, json_encode(body), headers, CALLBACK(src, PROC_REF(whitelist_ban_player_callback)))

/datum/controller/subsystem/central/proc/whitelist_ban_player_callback(datum/http_response/response)
if(response.errored || response.status_code != 200)
stack_trace("Failed to ban player: HTTP status code [response.status_code]")
return

var/list/data = json_decode(response.body)
var/ckey = data["ckey"]

GLOB.whitelist -= ckey
2 changes: 1 addition & 1 deletion modular_bandastation/modular_bandastation.dme
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
#include "species/_species.dme"
#include "translations/_translations.dme"
#include "tts/_tts.dme"
#include "whitelist220/_whitelist220.dme"
#include "metaserver/_metaserver.dme"
#include "world_topics/_world_topics.dme"
#include "preferences/_preferences.dme"
#include "jukebox/_jukebox.dme"
Expand Down
Loading
Loading