anon-ghost mode, and ghosts can't sign up for accounts

This commit is contained in:
Shish 2019-11-28 21:32:18 +00:00
parent 26e24c8988
commit 30b85f58db
6 changed files with 92 additions and 72 deletions

8
composer.lock generated
View file

@ -388,12 +388,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/shish/microcrud.git", "url": "https://github.com/shish/microcrud.git",
"reference": "6471a4c7445e872282f12d1de3730db55d5c06e2" "reference": "7c917baa46f137c5e0f6bd4d9874b1c61014797e"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/shish/microcrud/zipball/6471a4c7445e872282f12d1de3730db55d5c06e2", "url": "https://api.github.com/repos/shish/microcrud/zipball/7c917baa46f137c5e0f6bd4d9874b1c61014797e",
"reference": "6471a4c7445e872282f12d1de3730db55d5c06e2", "reference": "7c917baa46f137c5e0f6bd4d9874b1c61014797e",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -429,7 +429,7 @@
"crud", "crud",
"generator" "generator"
], ],
"time": "2019-11-28T15:53:53+00:00" "time": "2019-11-28T21:02:52+00:00"
}, },
{ {
"name": "shish/microhtml", "name": "shish/microhtml",

View file

@ -13,6 +13,7 @@ abstract class Permissions
public const VIEW_IP = "view_ip"; # view IP addresses associated with things public const VIEW_IP = "view_ip"; # view IP addresses associated with things
public const BAN_IP = "ban_ip"; public const BAN_IP = "ban_ip";
public const CREATE_USER = "create_user";
public const EDIT_USER_NAME = "edit_user_name"; public const EDIT_USER_NAME = "edit_user_name";
public const EDIT_USER_PASSWORD = "edit_user_password"; public const EDIT_USER_PASSWORD = "edit_user_password";
public const EDIT_USER_INFO = "edit_user_info"; # email address, etc public const EDIT_USER_INFO = "edit_user_info"; # email address, etc

View file

@ -83,6 +83,7 @@ new UserClass("base", null, [
Permissions::VIEW_IP => false, # view IP addresses associated with things Permissions::VIEW_IP => false, # view IP addresses associated with things
Permissions::BAN_IP => false, Permissions::BAN_IP => false,
Permissions::CREATE_USER => false,
Permissions::EDIT_USER_NAME => false, Permissions::EDIT_USER_NAME => false,
Permissions::EDIT_USER_PASSWORD => false, Permissions::EDIT_USER_PASSWORD => false,
Permissions::EDIT_USER_INFO => false, # email address, etc Permissions::EDIT_USER_INFO => false, # email address, etc
@ -163,6 +164,7 @@ new UserClass("ghost", "base", [
// Anonymous users can't do anything by default, but // Anonymous users can't do anything by default, but
// the admin might grant them some permissions // the admin might grant them some permissions
new UserClass("anonymous", "base", [ new UserClass("anonymous", "base", [
Permissions::CREATE_USER => true,
]); ]);
new UserClass("user", "base", [ new UserClass("user", "base", [

View file

@ -21,10 +21,16 @@ class IPBanTable extends Table
) AS tbl1 ) AS tbl1
"; ";
$this->size = 10; $this->size = 100;
$this->limit = 1000000;
$this->columns = [ $this->columns = [
new InetColumn("ip", "IP"), new InetColumn("ip", "IP"),
new EnumColumn("mode", "Mode", ["Block"=>"block", "Firewall"=>"firewall", "Ghost"=>"ghost"]), new EnumColumn("mode", "Mode", [
"Block"=>"block",
"Firewall"=>"firewall",
"Ghost"=>"ghost",
"Anon Ghost"=>"anon-ghost"
]),
new TextColumn("reason", "Reason"), new TextColumn("reason", "Reason"),
new StringColumn("banner", "Banner"), new StringColumn("banner", "Banner"),
new DateColumn("added", "Added"), new DateColumn("added", "Added"),
@ -37,7 +43,7 @@ class IPBanTable extends Table
$this->create_url = make_link("ip_ban/create"); $this->create_url = make_link("ip_ban/create");
$this->delete_url = make_link("ip_ban/delete"); $this->delete_url = make_link("ip_ban/delete");
$this->table_attrs = ["class" => "sortable zebra"]; $this->table_attrs = ["class" => "zebra"];
} }
} }
@ -90,95 +96,101 @@ class IPBan extends Extension
{ {
global $cache, $config, $database, $page, $user, $_shm_user_classes; global $cache, $config, $database, $page, $user, $_shm_user_classes;
// Get lists of banned IPs and banned networks // Get lists of banned IPs and banned networks
$ips = $cache->get("ip_bans"); $ips = $cache->get("ip_bans");
$networks = $cache->get("network_bans"); $networks = $cache->get("network_bans");
if ($ips === false || $networks === false) { if ($ips === false || $networks === false) {
$rows = $database->get_pairs(" $rows = $database->get_pairs("
SELECT ip, id SELECT ip, id
FROM bans FROM bans
WHERE ((expires > CURRENT_TIMESTAMP) OR (expires IS NULL)) WHERE ((expires > CURRENT_TIMESTAMP) OR (expires IS NULL))
"); ");
$ips = []; # "0.0.0.0" => 123; $ips = []; # "0.0.0.0" => 123;
$networks = []; # "0.0.0.0/32" => 456; $networks = []; # "0.0.0.0/32" => 456;
foreach ($rows as $ip => $id) { foreach ($rows as $ip => $id) {
if (strstr($ip, '/')) { if (strstr($ip, '/')) {
$networks[$ip] = $id; $networks[$ip] = $id;
} else { } else {
$ips[$ip] = $id; $ips[$ip] = $id;
} }
} }
$cache->set("ip_bans", $ips, 600); $cache->set("ip_bans", $ips, 600);
$cache->set("network_bans", $networks, 600); $cache->set("network_bans", $networks, 600);
} }
// Check if our current IP is in either of the ban lists // Check if our current IP is in either of the ban lists
$remote = $_SERVER['REMOTE_ADDR']; $remote = $_SERVER['REMOTE_ADDR'];
$active_ban_id = null; $active_ban_id = null;
if (isset($ips[$remote])) { if (isset($ips[$remote])) {
$active_ban_id = $ips[$remote]; $active_ban_id = $ips[$remote];
} else {
foreach ($networks as $range => $ban_id) {
if (ip_in_range($remote, $range)) {
$active_ban_id = $ban_id;
}
}
} }
else {
foreach ($networks as $range => $ban_id) {
if (ip_in_range($remote, $range)) {
$active_ban_id = $ban_id;
}
}
}
// If an active ban is found, act on it // If an active ban is found, act on it
if(!is_null($active_ban_id)) { if (!is_null($active_ban_id)) {
$row = $database->get_row("SELECT * FROM bans WHERE id=:id", ["id"=>$active_ban_id]); $row = $database->get_row("SELECT * FROM bans WHERE id=:id", ["id"=>$active_ban_id]);
$msg = $config->get_string("ipban_message"); $msg = $config->get_string("ipban_message");
$msg = str_replace('$IP', $row["ip"], $msg); $msg = str_replace('$IP', $row["ip"], $msg);
$msg = str_replace('$DATE', $row['expires'], $msg); $msg = str_replace('$DATE', $row['expires'], $msg);
$msg = str_replace('$ADMIN', User::by_id($row['banner_id'])->name, $msg); $msg = str_replace('$ADMIN', User::by_id($row['banner_id'])->name, $msg);
$msg = str_replace('$REASON', $row['reason'], $msg); $msg = str_replace('$REASON', $row['reason'], $msg);
$contact_link = contact_link(); $contact_link = contact_link();
if (!empty($contact_link)) { if (!empty($contact_link)) {
$msg = str_replace('$CONTACT', "<a href='$contact_link'>Contact the staff (be sure to include this message)</a>", $msg); $msg = str_replace('$CONTACT', "<a href='$contact_link'>Contact the staff (be sure to include this message)</a>", $msg);
} else { } else {
$msg = str_replace('$CONTACT', "", $msg); $msg = str_replace('$CONTACT', "", $msg);
} }
if($row["mode"] == "ghost") { if ($row["mode"] == "ghost") {
$b = new Block(null, $msg, "main", 0); $b = new Block(null, $msg, "main", 0);
$b->is_content = false; $b->is_content = false;
$page->add_block($b); $page->add_block($b);
$event->user->class = $_shm_user_classes["ghost"]; $event->user->class = $_shm_user_classes["ghost"];
} else { } elseif ($row["mode"] == "anon-ghost") {
header("HTTP/1.0 403 Forbidden"); if ($event->user->is_anonymous()) {
print "$msg"; $b = new Block(null, $msg, "main", 0);
exit; $b->is_content = false;
} $page->add_block($b);
} $event->user->class = $_shm_user_classes["ghost"];
}
} else {
header("HTTP/1.0 403 Forbidden");
print "$msg";
exit;
}
}
} }
public function onPageRequest(PageRequestEvent $event) public function onPageRequest(PageRequestEvent $event)
{ {
if ($event->page_matches("ip_ban")) { if ($event->page_matches("ip_ban")) {
global $database, $page, $user; global $database, $page, $user;
if ($user->can(Permissions::BAN_IP)) { if ($user->can(Permissions::BAN_IP)) {
if ($event->get_arg(0) == "create") { if ($event->get_arg(0) == "create") {
$user->ensure_authed(); $user->ensure_authed();
$input = validate_input(["c_ip"=>"string", "c_mode"=>"string", "c_reason"=>"string", "c_expires"=>"optional,date"]); $input = validate_input(["c_ip"=>"string", "c_mode"=>"string", "c_reason"=>"string", "c_expires"=>"optional,date"]);
send_event(new AddIPBanEvent($input['c_ip'], $input['c_mode'], $input['c_reason'], $input['c_expires'])); send_event(new AddIPBanEvent($input['c_ip'], $input['c_mode'], $input['c_reason'], $input['c_expires']));
flash_message("Ban for {$input['c_ip']} added"); flash_message("Ban for {$input['c_ip']} added");
$page->set_mode(PageMode::REDIRECT); $page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("ip_ban/list")); $page->set_redirect(make_link("ip_ban/list"));
} elseif ($event->get_arg(0) == "delete") { } elseif ($event->get_arg(0) == "delete") {
$user->ensure_authed(); $user->ensure_authed();
$input = validate_input(["d_id"=>"int"]); $input = validate_input(["d_id"=>"int"]);
send_event(new RemoveIPBanEvent($input['d_id'])); send_event(new RemoveIPBanEvent($input['d_id']));
flash_message("Ban removed"); flash_message("Ban removed");
$page->set_mode(PageMode::REDIRECT); $page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("ip_ban/list")); $page->set_redirect(make_link("ip_ban/list"));
} elseif ($event->get_arg(0) == "list") { } elseif ($event->get_arg(0) == "list") {
$_GET['c_banner'] = $user->name; $_GET['c_banner'] = $user->name;
$_GET['c_added'] = date('Y-m-d'); $_GET['c_added'] = date('Y-m-d');
$t = new IPBanTable($database->raw_db()); $t = new IPBanTable($database->raw_db());
$t->token = $user->get_auth_token(); $t->token = $user->get_auth_token();
$t->inputs = $_GET; $t->inputs = $_GET;

View file

@ -397,7 +397,12 @@ class UserPage extends Extension
private function page_create() private function page_create()
{ {
global $config, $page; global $config, $page, $user;
if ($user->can(Permissions::CREATE_USER)) {
$this->theme->display_error(403, "Account creation blocked", "Account creation is currently disabled");
return;
}
if (!$config->get_bool("login_signup_enabled")) { if (!$config->get_bool("login_signup_enabled")) {
$this->theme->display_signups_disabled($page); $this->theme->display_signups_disabled($page);
} elseif (!isset($_POST['name'])) { } elseif (!isset($_POST['name'])) {

View file

@ -167,7 +167,7 @@ class UserPageTheme extends Themelet
public function display_login_block(Page $page) public function display_login_block(Page $page)
{ {
global $config; global $config, $user;
$html = ' $html = '
'.make_form(make_link("user_admin/login"))." '.make_form(make_link("user_admin/login"))."
<table style='width: 100%;' class='form'> <table style='width: 100%;' class='form'>
@ -187,7 +187,7 @@ class UserPageTheme extends Themelet
</table> </table>
</form> </form>
"; ";
if ($config->get_bool("login_signup_enabled")) { if ($config->get_bool("login_signup_enabled") && $user->can(Permissions::CREATE_USER)) {
$html .= "<small><a href='".make_link("user_admin/create")."'>Create Account</a></small>"; $html .= "<small><a href='".make_link("user_admin/create")."'>Create Account</a></small>";
} }
$page->add_block(new Block("Login", $html, "left", 90)); $page->add_block(new Block("Login", $html, "left", 90));