nightly checkpoint (nothing functional

master
y 2019-06-05 07:39:56 +01:00
parent f969d37804
commit 0d89c4687f
16 changed files with 674 additions and 20 deletions

127
LICENSE Normal file
View File

@ -0,0 +1,127 @@
Ideas for this mod were taken liberally from sban (MIT license, Copyright (c) 2017 shivajiva101)
and BillyS's verification mod (no listed license). Very little was explicitly copied, however.
Not sure how that affects the license here.
Otherwise:
-------------------------------------------------------------------------------
Creative Commons Legal Code
CC0 1.0 Universal
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
HEREUNDER.
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.
For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:
i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
"License"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer's
express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied,
statutory or otherwise, including without limitation warranties of
title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy, or
the present or absence of errors, whether or not discoverable, all to
the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the Work.
Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the
Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.

48
README.md Normal file
View File

@ -0,0 +1,48 @@
Verbana: Verification and banning mod for minetest
==================================================
Name
----
A portmanteau of "verification", "ban", and the herb verbena.
Motivation
----------
This mod is a response to sban, an IP-aware banning mod derived from xban,
and BillyS's verification mod for Blocky Survival. Both of these mods have
problems that I've long wanted to resolve, and it seemed the best resolution
to those problems was to create a new integrating the features of both.
Sban is a good first attempt at IP-aware bans, but it has several major flaws:
1. Multiple users may be associated with an IP, and banning one often bans
them all.
2. Banned IPs can still "hack" into existing accounts of other players by
brute-forcing weak passwords.
3. For many trolls, getting access to a new IP is far too easy, and there is no
effective way to keep them off the server.
BillyS's verification mod was created to deal with one particular troll on
the BlockySurvival server. When enabled, it requires all new players to be
verified by a player with moderator privileges before they can interact with
the server or communicate with non-moderator players.
The flaws in the verification mod are
1. Moderators are not always online to verify new players.
2. New players come from all over the world, and may not be able to communicate
with the moderator.
3. New players are of all ages, and may not be able to communicate in chat at
all.
Verbena aims to provide name-based banning, as well as ip and network based
blocking and verification.
1. IPs and Networks may be marked as "untrusted" - all new players from
untrusted IPs/networks must go through verification, while other new
players may join at will.
2. IPs and Networks may be blocked or temporarily blocked, should the need
arise.
3. There is a three tiered privilege system: Normal players, moderators,
and admins. Moderators may ban and verify players, but only admins have
the ability to mark IPs and networks as untrusted. This way, player's
personal details may be kept private. However, oderators may execute queries
to determine if a player is associated with other banned players by IP or
network.

View File

@ -1,13 +1,14 @@
if not verbana then verbana = {} end
if not verbana.ip then dofile('ipmanip.lua') end
if not verbana.modpath then verbana.modpath = '.' end
if not verbana.ip then dofile(verbana.modpath .. '/ipmanip.lua') end
if not verbana.log then function verbana.log(_, message, ...) print(message:format(...)) end end
verbana.asn_db = {}
verbana.asn = {}
local ASN_DESCRIPTION_FILE = 'data-used-autnums'
local NETWORK_ASN_FILE = 'data-raw-table'
local function load_file(filename)
local file = io.open(filename, 'r')
local file = io.open(('%s/%s'):format(verbana.modpath, filename), 'r')
if not file then
verbana.log('error', 'error opening "%s"', filename)
return
@ -31,7 +32,7 @@ local function refresh_asn_descriptions()
end
end
verbana.asn_db.description = description
verbana.asn.description = description
end
local function refresh_asn_table()
@ -77,10 +78,10 @@ local function refresh_asn_table()
end
end
verbana.asn_db.network = networks
verbana.asn.network = networks
end
function verbana.asn_db.refresh()
function verbana.asn.refresh()
local start = os.clock()
refresh_asn_descriptions()
refresh_asn_table()
@ -88,34 +89,34 @@ function verbana.asn_db.refresh()
verbana.log('action', 'refreshed ASN tables in %s seconds', os.clock() - start)
end
verbana.asn_db.refresh()
verbana.asn.refresh()
local function find(ipint)
local t = verbana.asn_db.network
local low = 0
local t = verbana.asn.network
local low = 1
local high = #t
while low <= high do
local mid = math.floor((low + high) / 2)
verbana.log('action', '%s %s %s %s %s', ipint, low, mid, high, #t)
local element = t[mid]
local start = element[1]
local end_ = element[2]
local asn = element[3]
if start <= ipint and ipint <= end_ then
return asn
return element[3]
elseif start > ipint then
low = mid + 1
else
high = mid - 1
else
low = mid + 1
end
end
end
function verbana.asn_db.lookup(ipstr)
function verbana.asn.lookup(ipstr)
local ipint = verbana.ip.ipstr_to_number(ipstr)
local asn = find(ipint)
if asn then
return asn, verbana.asn_db.description[asn]
return asn, verbana.asn.description[asn]
else
return nil, nil
end

197
commands.lua Normal file
View File

@ -0,0 +1,197 @@
local mod_priv = verbana.privs.moderator
local admin_priv = verbana.privs.admin
minetest.register_chatcommand('import_sban', {
params='<filename>',
description='import records from sban',
privs={[admin_priv]=true},
func=function(caller, params)
return false, 'TODO: implement'
end
})
minetest.register_chatcommand('get_asn', {
params='<name> | <IP>',
description='get the ASN associated with an IP or player name',
privs={[mod_priv]=true},
func = function(caller, ipstr)
if not verbana.ip.is_valid_ip(ipstr) then
-- TODO assume its a player?
return false, ('"%s" is not a valid ip'):format(ipstr)
end
local asn, description = verbana.asn.lookup(ipstr)
if not asn then
return false, ('could not find ASN for "%s"'):format(ipstr)
end
description = description or ''
return true, ('A%u %s'):format(asn, description)
end
})
minetest.register_chatcommand('verify', {
params='<name>',
description='verify a player',
privs={[mod_priv]=true},
func=function(caller, params)
return false, 'TODO: implement'
end
})
minetest.register_chatcommand('unverify', {
params='<name>',
description='unverify a player',
privs={[mod_priv]=true},
func=function(caller, params)
return false, 'TODO: implement'
end
})
minetest.override_chatcommand('kick', {
params='<name> [<reason>]',
description='kick a player',
privs={[mod_priv]=true},
func=function(caller, params)
return false, 'TODO: implement'
end
})
minetest.register_chatcommand('lock', {
params='<name> [<reason>]',
description='lock a player\'s account',
privs={[mod_priv]=true},
func=function(caller, params)
return false, 'TODO: implement'
end
})
minetest.register_chatcommand('unlock', {
params='<name> [<reason>]',
description='unlock a player\'s account',
privs={[mod_priv]=true},
func=function(caller, params)
return false, 'TODO: implement'
end
})
minetest.override_chatcommand('ban', {
params='<name> [<reason>]',
description='ban a player',
privs={[mod_priv]=true},
func=function(caller, params)
-- todo: make sure that the begining of 'reason' doesn't look like a timespan =b
return false, 'TODO: implement'
end
})
minetest.register_chatcommand('tempban', {
params='<name> <timespan> [<reason>]',
description='ban a player for a length of time',
privs={[mod_priv]=true},
func=function(caller, params)
return false, 'TODO: implement'
end
})
minetest.override_chatcommand('unban', {
params='<name> [<reason>]',
description='unban a player',
privs={[mod_priv]=true},
func=function(caller, params)
return false, 'TODO: implement'
end
})
minetest.register_chatcommand('whitelist', {
params='<name> [<reason>]',
description='whitelist a player',
privs={[admin_priv]=true},
func=function(caller, params)
return false, 'TODO: implement'
end
})
minetest.register_chatcommand('unwhitelist', {
params='<name> [<reason>]',
description='whitelist a player',
privs={[admin_priv]=true},
func=function(caller, params)
return false, 'TODO: implement'
end
})
minetest.register_chatcommand('suspect', {
params='<name> [<reason>]',
description='mark a player as suspicious',
privs={[mod_priv]=true},
func=function(caller, params)
return false, 'TODO: implement'
end
})
minetest.register_chatcommand('unsuspect', {
params='<name> [<reason>]',
description='unmark a player as suspicious',
privs={[mod_priv]=true},
func=function(caller, params)
return false, 'TODO: implement'
end
})
minetest.register_chatcommand('ban_record', {
params='<name> [<number>]',
description='shows the ban record of a player',
privs={[mod_priv]=true},
func=function(caller, params)
return false, 'TODO: implement'
end
})
minetest.register_chatcommand('login_record', {
params='<name> [<number>]',
description='shows the login record of a player',
privs={[admin_priv]=true},
func=function(caller, params)
return false, 'TODO: implement'
end
})
minetest.register_chatcommand('inspect', {
params='<name> | <IP>',
description='list data associated with a player or IP',
privs={[admin_priv]=true},
func=function(caller, params)
return false, 'TODO: implement'
end
})
minetest.register_chatcommand('inspect_asn', {
params='<asn>',
description='list player accounts and statuses associated with an ASN',
privs={[admin_priv]=true},
func=function(caller, params)
return false, 'TODO: implement'
end
})
minetest.register_chatcommand('set_ip_status', {
params='<asn> <status>',
description='set the status of an IP (default, dangerous, blocked)',
privs={[admin_priv]=true},
func=function(caller, params)
return false, 'TODO: implement'
end
})
minetest.register_chatcommand('set_asn_status', {
params='<asn> <status>',
description='set the status of an ASN (default, dangerous, blocked)',
privs={[admin_priv]=true},
func=function(caller, params)
return false, 'TODO: implement'
end
})
-- alias (for listing an account's primary, cascade status)
-- list recent bans/kicks/locks/etc
-- first_login (=b) for all players
-- asn statistics

179
data.lua Normal file
View File

@ -0,0 +1,179 @@
if not verbana then verbana = {} end
if not verbana.modpath then verbana.modpath = '.' end
if not verbana.ip then dofile(verbana.modpath .. '/ipmanip.lua') end
if not verbana.log then function verbana.log(_, message, ...) print(message:format(...)) end end
local ie = minetest.request_insecure_environment()
if not ie then
error('Verbana will not work unless it has been listed under secure.trusted_mods in minetest.conf')
end
local sql = ie.require("lsqlite3")
local db = sql.open(('%s/verbana.sqlite'):format(minetest.get_worldpath())) -- TODO get path from settings
sqlite3 = nil -- remove sqlite3 from the global (secure) namespace
minetest.register_on_shutdown(function()
db:close()
end)
local function db_exec(stmt)
local status = db:exec(stmt)
if status ~= sql.OK then
verbana.log('error', 'SQLite ERROR: %s', db:errmsg())
return false
end
return true
end
local function init_db()
db_exec([[
PRAGMA foreign_keys = OFF;
-- PLAYER
CREATE TABLE IF NOT EXISTS player_status (
id INTEGER PRIMARY KEY
, name TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS player_status_name ON player_status(name);
INSERT OR IGNORE INTO player_status
(id, name)
VALUES ( 0, 'default')
, ( 1, 'unverified')
, ( 2, 'banned')
, ( 3, 'tempbanned')
, ( 4, 'locked')
, ( 5, 'whitelisted')
, ( 6, 'suspicious');
CREATE TABLE IF NOT EXISTS player (
id INTEGER PRIMARY KEY AUTOINCREMENT
, name TEXT NOT NULL
, main_player_id INTEGER
, last_action_id INTEGER
, FOREIGN KEY (main_player_id) REFERENCES player(id)
, FOREIGN KEY (last_action_id) REFERENCES player_action_log(id)
);
CREATE UNIQUE INDEX IF NOT EXISTS player_name ON player(name);
CREATE INDEX IF NOT EXISTS player_main_player_id ON player(main_player_id);
CREATE INDEX IF NOT EXISTS player_last_action_id ON player(last_action_id);
CREATE TABLE IF NOT EXISTS player_action_log (
id INTEGER PRIMARY KEY AUTOINCREMENT
, executor_id INTEGER NOT NULL
, player_id INTEGER NOT NULL
, status_id INTEGER NOT NULL
, timestamp INTEGER NOT NULL
, reason TEXT
, expires INTEGER
, FOREIGN KEY (executor_id) REFERENCES player(id)
, FOREIGN KEY (player_id) REFERENCES player(id)
, FOREIGN KEY (status_id) REFERENCES player_status(id)
);
CREATE INDEX IF NOT EXISTS player_action_log_player_id ON player_action_log(player_id);
CREATE INDEX IF NOT EXISTS player_action_log_timestamp ON player_action_log(timestamp);
CREATE INDEX IF NOT EXISTS player_action_log_reason ON player_action_log(reason);
-- END PLAYER
-- IP
CREATE TABLE IF NOT EXISTS ip_status (
id INTEGER PRIMARY KEY
, name TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS ip_status_name ON ip_status(name);
INSERT OR IGNORE INTO ip_status
(id, name)
VALUES ( 0, 'default')
, ( 1, 'untrusted')
, ( 2, 'blocked')
, ( 3, 'tempblocked');
CREATE TABLE IF NOT EXISTS ip (
ip INTEGER PRIMARY KEY
, last_action_id INTEGER
, FOREIGN KEY (last_action_id) REFERENCES ip_action_log(id)
);
CREATE INDEX IF NOT EXISTS ip_last_action_id ON ip(last_action_id);
CREATE TABLE IF NOT EXISTS ip_action_log (
id INTEGER PRIMARY KEY AUTOINCREMENT
, executor_id INTEGER NOT NULL
, ip INTEGER NOT NULL
, status_id INTEGER NOT NULL
, timestamp INTEGER NOT NULL
, reason TEXT
, expires INTEGER
, FOREIGN KEY (executor_id) REFERENCES player(id)
, FOREIGN KEY (ip) REFERENCES ip(ip)
, FOREIGN KEY (status_id) REFERENCES ip_status(id)
);
CREATE INDEX IF NOT EXISTS ip_action_log_ip ON ip_action_log(ip);
CREATE INDEX IF NOT EXISTS ip_action_log_timestamp ON ip_action_log(timestamp);
CREATE INDEX IF NOT EXISTS ip_action_log_reason ON ip_action_log(reason);
-- END IP
-- ASN
CREATE TABLE IF NOT EXISTS asn_status (
id INTEGER PRIMARY KEY
, name TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS asn_status_name ON asn_status(name);
INSERT OR IGNORE INTO asn_status
(id, name)
VALUES ( 0, 'default')
, ( 1, 'untrusted')
, ( 2, 'blocked')
, ( 3, 'tempblocked');
CREATE TABLE IF NOT EXISTS asn (
asn INTEGER PRIMARY KEY
, last_action_id INTEGER
, FOREIGN KEY (last_action_id) REFERENCES asn_action_log(id)
);
CREATE INDEX IF NOT EXISTS asn_last_action_id ON asn(last_action_id);
CREATE TABLE IF NOT EXISTS asn_action_log (
id INTEGER PRIMARY KEY AUTOINCREMENT
, executor_id INTEGER NOT NULL
, asn INTEGER NOT NULL
, status_id INTEGER NOT NULL
, timestamp INTEGER NOT NULL
, reason TEXT
, expires INTEGER
, FOREIGN KEY (executor_id) REFERENCES player(id)
, FOREIGN KEY (asn) REFERENCES asn(asn)
, FOREIGN KEY (status_id) REFERENCES asn_status(id)
);
CREATE INDEX IF NOT EXISTS asn_action_log_asn ON asn_action_log(asn);
CREATE INDEX IF NOT EXISTS asn_action_log_timestamp ON asn_action_log(timestamp);
CREATE INDEX IF NOT EXISTS asn_action_log_reason ON asn_action_log(reason);
-- END ASN
-- OTHER
CREATE TABLE IF NOT EXISTS log (
player_id INTEGER NOT NULL
, ip INTEGER NOT NULL
, asn INTEGER NOT NULL
, timestamp INTEGER NOT NULL
, FOREIGN KEY (player_id) REFERENCES player(id)
, FOREIGN KEY (ip) REFERENCES ip(ip)
, FOREIGN KEY (asn) REFERENCES asn(asn)
);
CREATE INDEX IF NOT EXISTS log_player ON log(player_id);
CREATE INDEX IF NOT EXISTS log_ip ON log(ip);
CREATE INDEX IF NOT EXISTS log_asn ON log(asn);
CREATE INDEX IF NOT EXISTS log_timestamp ON log(timestamp);
CREATE TABLE IF NOT EXISTS assoc (
player_id INTEGER
, ip INTEGER
, asn INTEGER
, PRIMARY KEY (player_id, ip, asn)
, FOREIGN KEY (player_id) REFERENCES player(id)
, FOREIGN KEY (ip) REFERENCES ip(ip)
, FOREIGN KEY (asn) REFERENCES asn(asn)
);
CREATE INDEX IF NOT EXISTS assoc_player ON assoc(player_id);
CREATE INDEX IF NOT EXISTS assoc_ip ON assoc(ip);
CREATE INDEX IF NOT EXISTS assoc_asn ON assoc(asn);
-- END OTHER
PRAGMA foreign_keys = ON;
]])
end -- init_db()
init_db()

0
depends.txt Normal file
View File

1
description.txt Normal file
View File

@ -0,0 +1 @@
Verification and Banning mod

View File

@ -1,5 +1,22 @@
verbana = {}
local modname = minetest.get_current_modname()
verbana.modpath = minetest.get_modpath(modname)
function verbana.log(level, message)
function verbana.log(level, message, ...)
minetest.log(level, ('[%s] %s'):format(modname, message:format(...)))
end
if not minetest.request_insecure_environment() then
error('insecure environment inaccessible - make sure this mod has been added to minetest.conf!')
end
dofile(verbana.modpath .. '/settings.lua')
dofile(verbana.modpath .. '/privs.lua')
dofile(verbana.modpath .. '/ipmanip.lua')
dofile(verbana.modpath .. '/asn.lua')
dofile(verbana.modpath .. '/data.lua')
dofile(verbana.modpath .. '/commands.lua')
dofile(verbana.modpath .. '/login_handling.lua')

View File

@ -2,13 +2,19 @@ if not verbana then verbana = {} end
verbana.ip = {}
function verbana.ip.ipstr_to_number(ip)
local a, b, c, d = ip:match('^(%d+)%.(%d+)%.(%d+)%.(%d+)$')
function verbana.ip.is_valid_ip(ipstr)
local a, b, c, d = ipstr:match('^(%d+)%.(%d+)%.(%d+)%.(%d+)$')
if not a and b and c and d then return false end
a = tonumber(a)
b = tonumber(b)
c = tonumber(c)
d = tonumber(d)
return (a * 16777216) + (b * 65536) + (c * 256) + d
return 0 <= a and a < 256 and 0 <= b and b < 256 and 0 <= c and c < 256 and 0 <= d and d < 256
end
function verbana.ip.ipstr_to_number(ipstr)
local a, b, c, d = ipstr:match('^(%d+)%.(%d+)%.(%d+)%.(%d+)$')
return (tonumber(a) * 16777216) + (tonumber(b) * 65536) + (tonumber(c) * 256) + tonumber(d)
end
function verbana.ip.number_to_ipstr(number)

60
logic_notes.txt Normal file
View File

@ -0,0 +1,60 @@
TODO: turn this into proper documentation
new player logs in from a DEFAULT ip/network
status = default
new player logs in from a DANGEROUS ip/network
if player is whitelisted: status = default
else: status = unverified; alert mods
new player logs in from a BLOCKED ip/network
if player is whitelisted: let them in
else: status is not changed (we should refuse to allow them to register the account)
old player logs in from a DEFAULT ip/network
if status is banned, boot them
if status is temp banned, check expiry and conditionally boot them
if status is locked, boot them BUT ALERT MODS
if status is suspicious, let them in BUT ALERT MODS
else allow them in
old player logs in from a DANGEROUS ip/network
if player has never used that ip/network
if the player is whitelisted let them in
else refuse entry
else
if the player is whitelisted, let them in
if the player is banned/tempbanned/locked, as for default ip/net status
else let them in, but alert mods
old player logs in from a BLOCKED ip/network
if the player is whitelisted, let them in
else refuse entry
when status == default:
account can be banned
account can be temp banned
account can be locked
account can be whitelisted by admins
account can be be marked suspicious
account can be unverified (sent back to verification area)
when status == unverified
account can be verified (status -> default)
account can be banned, tempbanned, locked
account can be whitelisted by admins (also lets them out of verification area)
account can be marked suspicious (also lets them out of verification area)
when status == banned
account can be unbanned (status -> default | suspicious depending on network)
account can be tempbanned (override previous behavior)
account can be locked (override previous behavior)
when status == tempbanned
account can be unbanned (status -> default | suspicious depending on network)
account can be banned (override previous behavior)
account can be locked (override previous behavior)
when status == locked
account can be unlocked (status -> default | suspicious depending on network)
account can be banned (override previous behavior)
account can be tempbanned (override previous behavior)
when status == whitelisted
account can be locked by mods
account can be unwhitelisted by admins (status -> default)
account can be banned by admins
account can be tempbanned by admins
when status == suspicious
as for default, mutatis mutandis

7
login_handling.lua Normal file
View File

@ -0,0 +1,7 @@
minetest.register_on_prejoinplayer(function(name, ip)
end)
minetest.register_on_joinplayer(function(player)
local name = player:get_player_name()
local ip = minetest.get_player_ip(name)
end)

2
mod.conf Normal file
View File

@ -0,0 +1,2 @@
name = verbana
description = Verification and Banning mod

7
privs.lua Normal file
View File

@ -0,0 +1,7 @@
if not verbana then verbana = {} end
verbana.privs = {}
minetest.register_privilege('ban_admin', 'administrator for verification/bans')
verbana.privs.admin = 'ban_admin' -- TODO load from settings
verbana.privs.moderator = 'basic_privs' -- TODO load from settings

1
settings.lua Normal file
View File

@ -0,0 +1 @@
-- config: privs_to_whitelist: if a player has this/these privs, they are treated as whitelisted

0
settingtypes.txt Normal file
View File

1
verbana_cl.lua Normal file
View File

@ -0,0 +1 @@
-- TODO: command line interface to manipulate the DB (e.g. for emergencies)