Merge branch 'master' into nalc

This commit is contained in:
sys4-fr 2019-01-19 20:34:30 +01:00
commit af26ae75bd
7 changed files with 193 additions and 19 deletions

7
.luacheckrc Normal file
View File

@ -0,0 +1,7 @@
unused_args = false
allow_defined_top = true
read_globals = {
"minetest",
}

106
README.md Normal file
View File

@ -0,0 +1,106 @@
# Extended Ban Mod for Minetest
This mod attempts to be an improvement to Minetest's ban system.
* It supports normal bans and temporary bans (from 60 seconds up to the end of
time, with 1 second granularity).
* Records and joins all accounts using the same IP address and several IP
addresses using the same name into a single record, and can ban/unban them as
a single user.
* Can ban offline players if you know their IP or username.
* Holds a record of bans for each user, so moderators and administrators can
consult it to know if a player is a repeat offender.
* Does not modify the default ban database in any way (`ipban.txt').
* Has an API to ban and check the ban database to allows other mods to manage
users (for example, anticheat mods).
## Chat commands
The mod provides the following chat commands. All commands require the `ban`
privilege.
### `xban`
Bans a player permanently.
**Usage:** `/xban <player_or_ip> <reason>`
**Example:** `/xban 127.0.0.1 Some reason.`
### `xtempban`
Bans a player temporarily.
**Usage:** `/xtempban <player_or_ip> <time> <reason>`
The `time` parameter is a string in the format `<count><unit>` where `<unit>`
is one of `s` for seconds, `m` for minutes, `h` for hours, `D` for days, `W`
for weeks, `M` for months, or `Y` for years. If the unit is omitted, it is
assumed to mean seconds. For example, `42s` means 42 seconds, `1337m` 1337
minutes, and so on. You can chain more than one such group and they will add
up. For example, `1Y3M3D7h` will ban for 1 year, 3 months, 3 days and 7 hours.
**Example:** `/xtempban Joe 3600 Some reason.`
### `xunban`
Unbans a player.
**Usage:** `/xunban <player_or_ip>`
**Example:** `/xunban Joe`
### `xban_record`
Shows the ban record on chat.
**Usage:** `/xban_record <player_or_ip>`
This prints one ban entry per line, with the time the ban came into effect,
the expiration time (if applicable), the reason, and the source of the ban.
The record is printed to chat with one entry per line.
**Example:** `/xban_record Joe`
### `xban_wl`
Manages the whitelist.
**Usage:** `/xban_wl (add|del|get) <player_or_ip>`
Whitelisted players are allowed on the server even if it's otherwise marked
as banned. This is useful to only allow certain users from shared computers,
for example.
The `add` subcommand adds the player to the whitelist. The `del` subcommand
removes the player from the whitelist. The `get` subcommand checks if the
player is in the whitelist, and prints the status to chat.
**Example:** `/xban_record add Jane`
### `xban_gui`
Shows a form to consult the database interactively.
**Usage:** `/xban_gui`
## Administrator commands
The following commands require the `server` privilege, so they are only
available to server administrators.
### `xban_dbi`
Imports ban entries from other database formats.
**Usage:** `/xban_dbi <importer>`
The `importer` argument specifies from which database to import. These are
the supported import plugins at the time of writing:
* `minetest`: Import entries from Minetest's ban list (`ipban.txt`).
* `v1`: Old format used by xban (`players.iplist`).
* `v2`: Old format used by xban (`players.iplist.v2`).
**Example:** `/xban_dbi minetest`

View File

@ -11,13 +11,13 @@ minetest.register_chatcommand("xban_dbi", {
privs = { server=true },
func = function(name, params)
if params == "--list" then
local names = { }
for name in pairs(xban.importers) do
table.insert(names, name)
local importers = { }
for importer in pairs(xban.importers) do
table.insert(importers, importer)
end
minetest.chat_send_player(name,
("[xban] Known importers: %s"):format(
table.concat(names, ", ")))
table.concat(importers, ", ")))
return
elseif not xban.importers[params] then
minetest.chat_send_player(name,

View File

@ -102,6 +102,11 @@ end
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= FORMNAME then return end
local name = player:get_player_name()
if not minetest.check_player_privs(name, { ban=true }) then
minetest.log("warning",
"[xban2] Received fields from unauthorized user: "..name)
return
end
local state = get_state(name)
if fields.player then
local t = minetest.explode_textlist_event(fields.player)
@ -130,6 +135,7 @@ end)
minetest.register_chatcommand("xban_gui", {
description = "Show XBan GUI",
params = "",
privs = { ban=true, },
func = function(name, params)
minetest.show_formspec(name, FORMNAME, make_fs(name))
end,

View File

@ -8,19 +8,19 @@ function xban.importers.v2()
local text = f:read("*a")
f:close()
local db = minetest.deserialize(text)
for _, e in ipairs(db) do
for name in pairs(e.names) do
for _, ent in ipairs(db) do
for name in pairs(ent.names) do
local entry = xban.find_entry(name, true)
if entry.source ~= "xban:importer_v2" then
for nm in pairs(e.names) do
entry.names[nm] = true
end
if e.banned then
if ent.banned then
entry.banned = true
entry.reason = e.banned
entry.source = "xban:importer_v2"
entry.time = e.time
entry.expires = e.expires
entry.time = ent.time
entry.expires = ent.expires
table.insert(entry.record, {
source = entry.source,
reason = entry.reason,

View File

@ -9,9 +9,9 @@ local tempbans = { }
local DEF_SAVE_INTERVAL = 300 -- 5 minutes
local DEF_DB_FILENAME = minetest.get_worldpath().."/xban.db"
local DB_FILENAME = minetest.setting_get("xban.db_filename")
local DB_FILENAME = minetest.settings:get("xban.db_filename")
local SAVE_INTERVAL = tonumber(
minetest.setting_get("xban.db_save_interval")) or DEF_SAVE_INTERVAL
minetest.settings:get("xban.db_save_interval")) or DEF_SAVE_INTERVAL
if (not DB_FILENAME) or (DB_FILENAME == "") then
DB_FILENAME = DEF_DB_FILENAME
@ -24,9 +24,7 @@ local function make_logger(level)
end
local ACTION = make_logger("action")
local INFO = make_logger("info")
local WARNING = make_logger("warning")
local ERROR = make_logger("error")
local unit_to_secs = {
s = 1, m = 60, h = 3600,
@ -72,7 +70,13 @@ function xban.get_info(player) --> ip_name_list, banned, last_record
end
function xban.ban_player(player, source, expires, reason) --> bool, err
if xban.get_whitelist(player) then
return nil, "Player is whitelisted; remove from whitelist first"
end
local e = xban.find_entry(player, true)
if e.banned then
return nil, "Already banned"
end
local rec = {
source = source,
time = os.time(),
@ -131,6 +135,28 @@ function xban.unban_player(player, source) --> bool, err
return true
end
function xban.get_whitelist(name_or_ip)
return db.whitelist and db.whitelist[name_or_ip]
end
function xban.remove_whitelist(name_or_ip)
if db.whitelist then
db.whitelist[name_or_ip] = nil
end
end
function xban.add_whitelist(name_or_ip, source)
local wl = db.whitelist
if not wl then
wl = { }
db.whitelist = wl
end
wl[name_or_ip] = {
source=source,
}
return true
end
function xban.get_record(player)
local e = xban.find_entry(player)
if not e then
@ -158,6 +184,8 @@ function xban.get_record(player)
end
minetest.register_on_prejoinplayer(function(name, ip)
local wl = db.whitelist or { }
if wl[name] or wl[ip] then return end
local e = xban.find_entry(name) or xban.find_entry(ip)
if not e then return end
if e.banned then
@ -195,8 +223,8 @@ minetest.register_chatcommand("xban", {
if not (plname and reason) then
return false, "Usage: /xban <player> <reason>"
end
xban.ban_player(plname, name, nil, reason)
return true, ("Banned %s."):format(plname)
local ok, e = xban.ban_player(plname, name, nil, reason)
return ok, ok and ("Banned %s."):format(plname) or e
end,
})
@ -214,8 +242,9 @@ minetest.register_chatcommand("xtempban", {
return false, "You must ban for at least 60 seconds."
end
local expires = os.time() + time
xban.ban_player(plname, name, expires, reason)
return true, ("Banned %s until %s."):format(plname, os.date("%c", expires))
local ok, e = xban.ban_player(plname, name, expires, reason)
return ok, (ok and ("Banned %s until %s."):format(
plname, os.date("%c", expires)) or e)
end,
})
@ -260,6 +289,31 @@ minetest.register_chatcommand("xban_record", {
end,
})
minetest.register_chatcommand("xban_wl", {
description = "Manages the whitelist",
params = "(add|del|get) <name_or_ip>",
privs = { ban=true },
func = function(name, params)
local cmd, plname = params:match("%s*(%S+)%s*(%S+)")
if cmd == "add" then
xban.add_whitelist(plname, name)
ACTION("%s adds %s to whitelist", name, plname)
return true, "Added to whitelist: "..plname
elseif cmd == "del" then
xban.remove_whitelist(plname)
ACTION("%s removes %s to whitelist", name, plname)
return true, "Removed from whitelist: "..plname
elseif cmd == "get" then
local e = xban.get_whitelist(plname)
if e then
return true, "Source: "..(e.source or "Unknown")
else
return true, "No whitelist for: "..plname
end
end
end,
})
local function check_temp_bans()
minetest.after(60, check_temp_bans)
local to_rm = { }
@ -305,10 +359,10 @@ local function load_db()
WARNING("Unable to load database: %s", "Read failed")
return
end
local t = minetest.deserialize(cont)
local t, e2 = minetest.deserialize(cont)
if not t then
WARNING("Unable to load database: %s",
"Deserialization failed")
"Deserialization failed: "..(e2 or "unknown error"))
return
end
db = t

1
mod.conf Normal file
View File

@ -0,0 +1 @@
name = xban2