From: Valerie Pond Date: Mon, 23 Jan 2023 23:54:48 +0000 (+0000) Subject: Rather large update, please see commit notes X-Git-Tag: 0.9~380 X-Git-Url: https://jfr.im/git/irc/unrealircd/unrealircd-webpanel.git/commitdiff_plain/33f512fa30c06fa488c42e68f9bc9f401300a5ab?ds=sidebyside;hp=e0c259fc7c93c77aa87d52f32a8c0ec7071843c2 Rather large update, please see commit notes With this update: - WebPanel version shows in the footer for logged-in users (sql_auth) - Made things look much better on mobiles; before, the navigation bar covered most of the mobile screen and was generally not visually appealing. So now when the screen is a mobile, the navigation bar will collapse into a collapsible menu. - Separated `Name Bans` and `Server Ban Exceptions` into their own sub-menu pages. TODO: There is some weird overlap with the list background highlight. -Started on user_meta: as in, when they last logged in, what IP they are using or used, recent actions taken, and most importantly, permissions. - Added a few hooks which allow plugins to do more: - `HOOKTYPE_PRE_HEADER` - `HOOKTYPE_HEADER` - `HOOKTYPE_PRE_FOOTER` - `HOOKTYPE_FOOTER` These hooks are relatively self-explanatory. There is however another hook of a different nature. - `HOOKTYPE_NOTIFICATION` You will need to run this from your plugin as well as catch functions from it. This won't be run many places in the source so it's up to you to send notifications. Maybe some other plugin wants to show notifications somewhere else or do something different, while still being able to load your plugin and receive notifications for it, and vice versa. --- diff --git a/Classes/class-hook.php b/Classes/class-hook.php index 03effea..30912a2 100644 --- a/Classes/class-hook.php +++ b/Classes/class-hook.php @@ -1,10 +1,10 @@ +## Example Overview from Mobile + + ## Prerequisites ## - PHP 8 or later - A webserver diff --git a/cfg/defines.php b/cfg/defines.php new file mode 100644 index 0000000..f4a948a --- /dev/null +++ b/cfg/defines.php @@ -0,0 +1,3 @@ + "", "Users" => "users", "Channels" => "channels", "Servers" => "servers", - "Server Bans" => "server_bans.php", + "Server Bans" => [ + "Server Bans" => "server-bans", + "Name Bans" => "server-bans/name-bans.php", + "Ban Exceptions" => "server-bans/ban-exceptions.php" + ], "Spamfilter" => "spamfilter.php", "News" => "news.php", ); diff --git a/header.php b/header.php index 30fa5a5..0efd8eb 100644 --- a/header.php +++ b/header.php @@ -4,10 +4,9 @@
- + + + @@ -34,8 +33,12 @@

diff --git a/index.php b/index.php index 4db5cb0..173a84d 100644 --- a/index.php +++ b/index.php @@ -20,11 +20,10 @@ $stats = (object) $array_of_stats; ?> +
-
- -
-
+
+
@@ -50,7 +49,7 @@ $stats = (object) $array_of_stats;
-
+
@@ -72,7 +71,7 @@ $stats = (object) $array_of_stats;
-
+
@@ -95,7 +94,7 @@ $stats = (object) $array_of_stats;
-
+
@@ -122,7 +121,7 @@ $stats = (object) $array_of_stats;
-
+
@@ -144,7 +143,7 @@ $stats = (object) $array_of_stats;
-
+
@@ -166,7 +165,7 @@ $stats = (object) $array_of_stats;
-
+
@@ -202,7 +201,7 @@ $stats = (object) $array_of_stats; else $bg = "bg-warning"; ?> -
+
diff --git a/misc/strings.php b/misc/strings.php index 4a1fc90..199c0f1 100644 --- a/misc/strings.php +++ b/misc/strings.php @@ -14,6 +14,12 @@ function split($str, $delimiter = " ") : Array return explode($delimiter,$str); } +/** + * + * @param mixed $array + * @param mixed $delimiter + * @return string + */ function glue($array, $delimiter = " ") { $string = ""; @@ -26,6 +32,11 @@ function glue($array, $delimiter = " ") return trim($string,$delimiter); } +/** + * Gets the relative path of the filename + * @param mixed $filename + * @return string + */ function get_relative_path($filename) { $relativepath = split($filename, "/"); @@ -39,3 +50,17 @@ function get_relative_path($filename) $relativepath = glue($relativepath,"/"); return $relativepath; } + +/** + * Returns a `nick` if the string was in the syntax: + * nick!ident@host + * @param mixed $str + * @return mixed + */ +function show_nick_only($str) +{ + $x = strpos($str, "!"); + if ($x !== false) + $str = substr($str, 0, $x); + return $str; +} diff --git a/plugins/sql_auth/SQL/user.php b/plugins/sql_auth/SQL/user.php index 511385f..a05abb7 100644 --- a/plugins/sql_auth/SQL/user.php +++ b/plugins/sql_auth/SQL/user.php @@ -80,34 +80,49 @@ class SQLA_User ]; $conn = sqlnew(); - $query = "INSERT INTO " . SQL_PREFIX . "user_meta (user_id, meta_key, meta_value) VALUES (:id, :key, :value)"; + + /* check if it exists first, update it if it does */ + $query = "SELECT * FROM " . SQL_PREFIX . "user_meta WHERE user_id = :id AND meta_key = :key"; $stmt = $conn->prepare($query); - $stmt->execute($meta); - if ($stmt->rowCount()) - return true; - return false; + $stmt->execute(["id" => $this->id, "key" => $key]); + if ($stmt->rowCount()) // it exists, update instead of insert + { + $query = "UPDATE " . SQL_PREFIX . "user_meta SET meta_value = :value WHERE user_id = :id AND meta_key = :key"; + $stmt = $conn->prepare($query); + $stmt->execute($meta); + if ($stmt->rowCount()) + return true; + return false; + } + else + { + $query = "INSERT INTO " . SQL_PREFIX . "user_meta (user_id, meta_key, meta_value) VALUES (:id, :key, :value)"; + $stmt = $conn->prepare($query); + $stmt->execute($meta); + if ($stmt->rowCount()) + return true; + return false; + } } /** - * Delete user meta data + * Delete user meta data by key * @param string $key - * @param string $value * @return bool */ - function delete_meta(string $key, string $value) + function delete_meta(string $key) { - if (!$key || !$value) + if (!$key ) return false; $meta = [ "id" => $this->id, "key" => $key, - "value" => $value ]; $conn = sqlnew(); - $query = "INSERT INTO " . SQL_PREFIX . "user_meta (user_id, meta_key, meta_value) VALUES (:id, :key, :value)"; + $query = "DELETE FROM " . SQL_PREFIX . "user_meta WHERE user_id = :id AND meta_key = :key"; $stmt = $conn->prepare($query); $stmt->execute($meta); if ($stmt->rowCount()) diff --git a/plugins/sql_auth/login.php b/plugins/sql_auth/login.php index d2b598b..830b3e0 100644 --- a/plugins/sql_auth/login.php +++ b/plugins/sql_auth/login.php @@ -16,26 +16,27 @@ if (!empty($_GET['logout'])) if (!empty($_POST)) { if ($_POST['username'] && $_POST['password']) - { - - /* securitah */ - security_check(); - $user = new SQLA_User($_POST['username']); - - /* not being too informative with the login error in case of attackers */ - if (!$user->id) - { - $failmsg = "Incorrect login"; - } - else if ($user->password_verify($_POST['password'])) - { - $_SESSION['id'] = $user->id; - header('Location: ' . BASE_URL); - } - else - { - $failmsg = "Incorrect login"; - } +{ + + /* securitah */ + security_check(); + $user = new SQLA_User($_POST['username']); + + /* not being too informative with the login error in case of attackers */ + if (!$user->id) + { + $failmsg = "Incorrect login"; + } + else if ($user->password_verify($_POST['password'])) + { + $_SESSION['id'] = $user->id; + header('Location: ' . BASE_URL); + $user->add_meta("last_login", date("Y-m-d m:i:s")); + } + else + { + $failmsg = "Incorrect login"; + } } else diff --git a/plugins/sql_auth/sql_auth.php b/plugins/sql_auth/sql_auth.php index 5822fda..fdfeb56 100644 --- a/plugins/sql_auth/sql_auth.php +++ b/plugins/sql_auth/sql_auth.php @@ -17,6 +17,7 @@ class sql_auth Hook::func(HOOKTYPE_NAVBAR, 'sql_auth::add_navbar'); Hook::func(HOOKTYPE_PRE_HEADER, 'sql_auth::session_start'); Hook::func(HOOKTYPE_OVERVIEW_CARD, 'sql_auth::add_overview_card'); + Hook::func(HOOKTYPE_FOOTER, 'sql_auth::add_footer_info'); if (defined('SQL_DEFAULT_USER')) // we've got a default account { @@ -43,6 +44,16 @@ class sql_auth } } + public static function add_footer_info($empty) + { + if (!($user = unreal_get_current_user())) + return; + + else { + echo "Admin Panel v" . WEBPANEL_VERSION . ""; + } + } + public static function session_start($n) { do_log($_SESSION); @@ -102,6 +113,12 @@ class sql_auth setting_value VARCHAR(255), PRIMARY KEY (id) )"); + $conn->query("CREATE TABLE IF NOT EXISTS " . SQL_PREFIX . "fail2ban ( + id int AUTO_INCREMENT NOT NULL, + ip VARCHAR(255) NOT NULL, + count VARCHAR(255), + PRIMARY KEY (id) + )"); new AuthSettings(); } @@ -205,4 +222,6 @@ function dnsbl_check($ip) } function fail2ban_check($ip) -{} \ No newline at end of file +{ + +} \ No newline at end of file diff --git a/server-bans/ban-exceptions.php b/server-bans/ban-exceptions.php new file mode 100644 index 0000000..7b90116 --- /dev/null +++ b/server-bans/ban-exceptions.php @@ -0,0 +1,144 @@ +serverbanexception()->getAll(); + +?> +

Ban Exceptions Overview

+Here is where you can make an exception to bans, that is, to make it so that the target mask is exempt from the ban types you specify.
+
+ +

+ + + + + + + + + + + + + + + set_in_config) && $ban_exceptions->set_in_config) || ($ban_exceptions->set_by == "-config-")) ? true : false; + echo ""; + if ($set_in_config) + echo ""; + else + echo ""; + echo ""; + echo ""; + echo ""; + $set_by = $set_in_config ? "Config" : show_nick_only($ban_exceptions->set_by); + echo ""; + echo ""; + echo ""; + echo ""; + } + ?>
MaskDurationReasonSet BySet OnExpires
".$ban_exceptions->name."".$ban_exceptions->duration_string."".$ban_exceptions->reason."".$set_by."".$ban_exceptions->set_at_string."".$ban_exceptions->expire_at_string."

+
+ + diff --git a/server_bans.php b/server-bans/index.php similarity index 98% rename from server_bans.php rename to server-bans/index.php index 97ec2fa..f379571 100644 --- a/server_bans.php +++ b/server-bans/index.php @@ -1,7 +1,7 @@ serverban()->getAll(); -foreach ($rpc->nameban()->getAll() as $v) - $tkl[] = $v; foreach ($rpc->serverbanexception()->getAll() as $v) $tkl[] = $v; ?> -

Server Bans Overview


+

Server Bans Overview

+Here are all your network bans, from K-Lines to G-Lines, it's all here.

diff --git a/server-bans/name-bans.php b/server-bans/name-bans.php new file mode 100644 index 0000000..b7d4afb --- /dev/null +++ b/server-bans/name-bans.php @@ -0,0 +1,198 @@ + $value) + { + $tok = base64_decode($value); + $success = false; + $success = $rpc->nameban()->delete($tok); + + + if ($success) + Message::Success("Name Ban has been removed for $tok"); + else + Message::Fail("Unable to remove Name Ban on $tok: $rpc->error"); + } + } + elseif (isset($_POST['tkl_add']) && !empty($_POST['tkl_add'])) + { + if (!($iphost = $_POST['tkl_add'])) + Message::Fail("No mask was specified"); + + /* duplicate code for now [= */ + $banlen_w = (isset($_POST['banlen_w'])) ? $_POST['banlen_w'] : NULL; + $banlen_d = (isset($_POST['banlen_d'])) ? $_POST['banlen_d'] : NULL; + $banlen_h = (isset($_POST['banlen_h'])) ? $_POST['banlen_h'] : NULL; + $duration = ""; + if (!$banlen_d && !$banlen_h && !$banlen_w) + $duration .= "0"; + else { + if ($banlen_w) + $duration .= $banlen_w; + if ($banlen_d) + $duration .= $banlen_d; + if ($banlen_h) + $duration .= $banlen_h; + } + $msg_msg = ($duration == "0" || $duration == "0w0d0h") ? "permanently" : "for " . rpc_convert_duration_string($duration); + $reason = (isset($_POST['ban_reason'])) ? $_POST['ban_reason'] : "No reason"; + + if ($rpc->nameban()->add($iphost, $reason, $duration)) + Message::Success("Name Ban set against \"$iphost\": $reason"); + else + Message::Fail("Name Ban could not be set against \"$iphost\": $rpc->error"); + + } + elseif (isset($_POST['search_types']) && !empty($_POST['search_types'])) + { + + } +} + + +$name_bans = $rpc->nameban()->getAll(); + +?> +

Name Bans Overview

+Here you can essentially forbid the use of a nick or channel name. This is useful to reserve services nicks so they cannot be used by normal users.
+You can also forbid the use of channel names. This is useful in such cases where an admin might need to close a channel for reasons relating to their own policy.
+
+

+ + + + + + + + + + + + + + + set_in_config) && $name_bans->set_in_config) || ($name_bans->set_by == "-config-")) ? true : false; + echo ""; + if ($set_in_config) + echo ""; + else + echo ""; + echo ""; + echo ""; + echo ""; + $set_by = $set_in_config ? "Config" : show_nick_only($name_bans->set_by); + echo ""; + echo ""; + echo ""; + echo ""; + } + ?>
MaskDurationReasonSet BySet OnExpires
".$name_bans->name."".$name_bans->duration_string."".$name_bans->reason."".$set_by."".$name_bans->set_at_string."".$name_bans->expire_at_string."

+
+ +