]> jfr.im git - irc/unrealircd/unrealircd-webpanel.git/commitdiff
Rather large update, please see commit notes
authorValerie Pond <redacted>
Mon, 23 Jan 2023 23:54:48 +0000 (23:54 +0000)
committerValerie Pond <redacted>
Mon, 23 Jan 2023 23:54:48 +0000 (23:54 +0000)
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.

13 files changed:
Classes/class-hook.php
README.md
cfg/defines.php [new file with mode: 0644]
common.php
header.php
index.php
misc/strings.php
plugins/sql_auth/SQL/user.php
plugins/sql_auth/login.php
plugins/sql_auth/sql_auth.php
server-bans/ban-exceptions.php [new file with mode: 0644]
server-bans/index.php [moved from server_bans.php with 98% similarity]
server-bans/name-bans.php [new file with mode: 0644]

index 03effea6cf9081498d13b9ad3abe1a0a8e15fdaa..30912a2149cd186d12231874d909522e36d9437a 100644 (file)
@@ -1,10 +1,10 @@
 <?php
 
 /* Hook Definitions
- 
- * Hooks let you do things in your plugin, like add nav items for your
- * own pages, add extra cards to the overview and more (to come)
- */
+* 
+* Hooks let you do things in your plugin, like add nav items for your
+* own pages, add extra cards to the overview and more (to come)
+*/
 /** HOOKTYPE_NAVBAR
  * 
  * @param array $pages
@@ -44,8 +44,8 @@ define('HOOKTYPE_PRE_HEADER', 101);
  * See "index.php" to see how it's used.
  * 
  */
-
 define('HOOKTYPE_PRE_OVERVIEW_CARD', 102);
+
 /** HOOKTYPE_OVERVIEW_CARD
  * 
  * @param object $stats
@@ -57,11 +57,45 @@ define('HOOKTYPE_PRE_OVERVIEW_CARD', 102);
  * The parameter is an object containing stats used in the overview.
  * See "index.php" to see how it's used.
  * 
- */
+*/
+define('HOOKTYPE_OVERVIEW_CARD', 103);
 
+/** HOOKTYPE_NOTIFICATION
+ * 
+ * @param array $notification
+ * The array should contain:
+ *
+ * "name" - The name of the recipient
+ * "message" - The notification message
+ *
+ * This does not do anything special by itself. It simply allows plugins
+ * to be able to use it with regards to notification sending.
+ * This is not run at any place, but should be run from your plugin.
+ *
+ * This hook is simple in design and only contains two elements in attempt
+ * to make it work cross-plugin. That is, if you have implemented your own
+ * notificiation system, you will be able to do whatever you like such as
+ * display a navbar list of notifications or send important emails by running
+ * this hook.
+ * 
+*/
+define('HOOKTYPE_NOTIFICATION', 104);
 
-define('HOOKTYPE_OVERVIEW_CARD', 103);
 
+/** HOOKTYPE_PRE_FOOTER
+ * $param array $empty - Doesn't do anything
+ * 
+ * This runs inside the footer body before anything else.
+ */
+define('HOOKTYPE_PRE_FOOTER', 105);
+
+/** HOOKTYPE_FOOTER
+ * $param array $empty - Doesn't do anything
+ * 
+ * This runs inside the footer body after everything else.
+ */
+define('HOOKTYPE_FOOTER', 106);
 /** 
  *  Class for "Hook"
  * This is the main function which gets called whenever you want to use a Hook.
index 58c86f7a4be69a2565da53ab99606625b74c6028..05925773abb09a4e7d11673ed4a6b450df9f5bb0 100644 (file)
--- a/README.md
+++ b/README.md
@@ -15,9 +15,12 @@ Additionally, the UnrealIRCd Web Panel is a great tool for keeping track of your
 
 Overall, the UnrealIRCd Web Panel is a must-have tool for any administrator managing an IRC network. Its user-friendly interface and powerful management capabilities make it easy to keep track of your network and ensure that everything is running smoothly. So why not give it a try and see how it can improve your IRC network management experience?
 
-## Example Overview
+## Example Overview from Desktop
  <img src="https://i.ibb.co/7SdFZnk/Screenshot-from-2023-01-14-07-26-21.png">
 
+## Example Overview from Mobile
+<img src="https://i.ibb.co/KGLdB43/Screenshot-20230123-233804-Chrome.jpg">
+
 ## Prerequisites ##
 - PHP 8 or later
 - A webserver
diff --git a/cfg/defines.php b/cfg/defines.php
new file mode 100644 (file)
index 0000000..f4a948a
--- /dev/null
@@ -0,0 +1,3 @@
+<?php
+
+define('WEBPANEL_VERSION', "1.0-git");
\ No newline at end of file
index e177802f30754053873e85851906b7ff4ef005e9..948e35aee3bbb7f1a05d676de0cceac7af8e217c 100644 (file)
@@ -6,6 +6,7 @@ require_once "Classes/class-hook.php";
 if (!is_dir(UPATH . "/vendor"))
        die("The vendor/ directory is missing. Most likely the admin forgot to run 'composer install'\n");
 require_once UPATH . '/vendor/autoload.php';
+require_once "cfg/defines.php";
 require_once "connection.php";
 require_once "misc/strings.php";
 require_once "misc/user-lookup-misc.php";
@@ -16,20 +17,16 @@ require_once "Classes/class-message.php";
 require_once "Classes/class-rpc.php";
 require_once "plugins.php";
 
-function show_nick_only($str)
-{
-       $x = strpos($str, "!");
-       if ($x !== false)
-               $str = substr($str, 0, $x);
-       return $str;
-}
-
 $pages = Array(
        "Overview"     => "",
        "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",
 );
index 30fa5a5c85f2c5254520e55e5cc7cbf3af566f8a..0efd8eb5aa38b001bcbfeeeb3d25238fe39e4179 100644 (file)
@@ -4,10 +4,9 @@
 <div class="media">
 <div class="media-body">
 
-               <!-- This will make it so that it "works" on mobile device. Not sure it's a good idea yet though
-<meta name="viewport" content="width=device-width, initial-scale=1">
-<meta name="HandheldFriendly" content="true">
--->
+       <meta name="viewport" content="width=device-width, initial-scale=1">
+       <meta name="HandheldFriendly" content="true">
+
 
  <!-- Latest compiled and minified CSS -->
 <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css">
        
        <!-- Fixed navbar -->
        <nav class="navbar navbar-expand-sm navbar-dark bg-dark fixed-top z-index padding-top">
-               <ul class="nav navbar-nav">
-                       <a class="navbar-brand" href="<?php echo BASE_URL; ?>"><img src="<?php echo BASE_URL; ?>img/favicon.ico" height="25" width="25"> UnrealIRCd Admin Panel</a>
+               <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#collapsibleNavbar">
+                       <span class="navbar-toggler-icon"></span>
+               </button>
+               <div class="collapse navbar-collapse" id="collapsibleNavbar">
+                       <ul class="navbar-nav mr-auto">
+                               <a class="navbar-brand" href="<?php echo BASE_URL; ?>"><img src="<?php echo BASE_URL; ?>img/favicon.ico" height="25" width="25"> UnrealIRCd Admin Panel</a>
 <?php
 
 $active_page = NULL;
@@ -44,7 +47,9 @@ foreach ($pages as $name => $page)
 {
        $script = $_SERVER['SCRIPT_FILENAME'];
        $tok = split($script, "/");
-       if (strlen($page) == 0) {
+       if (is_array($page))
+               continue;
+       if (is_string($page) && strlen($page) == 0) {
                $active_page = "";
        }
        else if (str_ends_with($script, BASE_URL . "index.php") && BASE_URL != "/" && !strlen($tok[0]))
@@ -69,11 +74,38 @@ foreach($pages as $name=>$page)
        if (is_string($active_page) && $page == $active_page)
                $class = str_replace("\"nav-item\"", "\"nav-item active\"", $class);
        
-       echo "                  <li $class><a class=\"nav-link\" href=\"".BASE_URL.$page."\">$name</a></li> \n";
+       if (is_string($page))
+               echo "<li $class><a class=\"nav-link\" href=\"".BASE_URL.$page."\">$name</a></li>\n";
+
+       elseif (is_array($page))
+       {
+               foreach ($page as $k => $v)
+               {
+                       $first_page = $v;
+                       break;
+               }
+               ?>
+               <li class="nav-item dropdown">
+        <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+          <?php echo $name; ?>
+        </a>
+        <div class="dropdown-menu" aria-labelledby="navbarDropdown">
+                       <?php foreach($page as $k => $p)
+                       {
+                               ?>
+                                       <a class="dropdown-item" href="<?php echo BASE_URL.$p;?>"><?php echo $k; ?></a>
+                               <?php
+                       } ?>
+        </div>
+      </li>
+         <?php
+               
+       }
+
 }
 ?>
        
-               </ul>
+               </ul></div>
        </nav><br>
 </div>
 
index 4db5cb075c2e0790bf44d6d7decdad51a5aef433..173a84da9b9a94cf77380694c437f5f226583f92 100644 (file)
--- a/index.php
+++ b/index.php
@@ -20,11 +20,10 @@ $stats = (object) $array_of_stats;
 
 
 ?>
+<div class="container">
 
-<div class="container mt-5">
-
-       <div class="row">
-               <div class="col-sm">
+       <div class="row mt-3" style="margin-left:0px;">
+               <div class="col-sm mb-3">
                        <div class="card text-center">
                                <div class="card-header bg-success text-white">
                                        <div class="row">
@@ -50,7 +49,7 @@ $stats = (object) $array_of_stats;
                        
 
                </div>
-               <div class="col-sm">
+               <div class="col-sm mb-3">
                        <div class="card text-center">
                                <div class="card-header bg-primary text-white">
                                        <div class="row">
@@ -72,7 +71,7 @@ $stats = (object) $array_of_stats;
                                </div>
                        </div>
                </div>
-               <div class="col-sm">
+               <div class="col-sm mb-3">
                        <div class="card text-center">
                                <div class="card-header bg-warning">
                                        <div class="row">
@@ -95,7 +94,7 @@ $stats = (object) $array_of_stats;
                        </div>
                </div>
 
-               <div class="col-sm">
+               <div class="col-sm mb-3">
                        <div class="card text-center">
                                <div class="card-header bg-secondary text-white">
                                        <div class="row">
@@ -122,7 +121,7 @@ $stats = (object) $array_of_stats;
 <div class="container mt-3">
 
        <div class="row">
-               <div class="col-sm">
+               <div class="col-sm mb-3">
                        <div class="card text-center">
                                <div class="card-header bg-danger text-white">
                                        <div class="row">
@@ -144,7 +143,7 @@ $stats = (object) $array_of_stats;
                                </div>
                        </div>
                </div>
-               <div class="col-sm">
+               <div class="col-sm mb-3">
                        <div class="card text-center">
                                <div class="card-header bg-secondary text-white">
                                        <div class="row">
@@ -166,7 +165,7 @@ $stats = (object) $array_of_stats;
                                </div>
                        </div>
                </div>
-               <div class="col-sm">
+               <div class="col-sm mb-3">
                        <div class="card text-center">
                                <div class="card-header bg-primary text-white">
                                        <div class="row">
@@ -202,7 +201,7 @@ $stats = (object) $array_of_stats;
                else
                        $bg = "bg-warning";
                ?> 
-               <div class="col-sm">
+               <div class="col-sm mb-3">
                        <div class="card text-center">
                                <div class="card-header <?php echo $bg; ?> text-white">
                                        <div class="row">
index 4a1fc905328f9e38ef56f2591b1a4f97692b12a1..199c0f15fe8db5289697f4702d92c4450633e257 100644 (file)
@@ -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;
+}
index 511385f7e96d0ced010628e2e1023ae1a6bc0595..a05abb7b0cbf1c0332ed95244387bc423d8f046f 100644 (file)
@@ -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())
index d2b598b94495869d92f110dfcb48ccfb3fdc8661..830b3e0126532f7ea7b929e84f04233310ef7d6b 100644 (file)
@@ -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
index 5822fda11376afbcfc8c9628bf2e2368fe928682..fdfeb566177842bc191ced91037807faf4cd6a26 100644 (file)
@@ -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 "<code>Admin Panel v" . WEBPANEL_VERSION . "</code>";
+               }
+       }
+
        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 (file)
index 0000000..7b90116
--- /dev/null
@@ -0,0 +1,144 @@
+<?php
+require_once "../common.php";
+
+require_once "../header.php";
+
+
+$ban_exceptions = $rpc->serverbanexception()->getAll();
+
+?>
+<h4>Ban Exceptions Overview</h4>
+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.<br>
+<br>
+
+<p><button type="button" class="btn btn-primary" data-toggle="modal" data-target="#myModal">
+                       Add entry
+       </button></p></table>
+       <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="confirmModalCenterTitle" aria-hidden="true">
+       <div class="modal-dialog modal-dialog-centered" role="document">
+               <div class="modal-content">
+               <div class="modal-header">
+                       <h5 class="modal-title" id="myModalLabel">Add new Name Ban</h5>
+                       <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                       <span aria-hidden="true">&times;</span>
+                       </button>
+               </div>
+               <div class="modal-body">
+               
+               <form  method="post">
+                       <div class="align_label">Nick / Channel</div> <input class="curvy" type="text" id="tkl_add" name="tkl_add"><br>
+                       
+                       <div class="align_label"><label for="banlen_w">Duration: </label></div>
+                                       <select class="curvy" name="banlen_w" id="banlen_w">
+                                                       <?php
+                                                       for ($i = 0; $i <= 56; $i++)
+                                                       {
+                                                               if (!$i)
+                                                                       echo "<option value=\"0w\"></option>";
+                                                               else
+                                                               {
+                                                                       $w = ($i == 1) ? "week" : "weeks";
+                                                                       echo "<option value=\"$i" . "w\">$i $w" . "</option>";
+                                                               }
+                                                       }
+                                                       ?>
+                                       </select>
+                                       <select class="curvy" name="banlen_d" id="banlen_d">
+                                                       <?php
+                                                       for ($i = 0; $i <= 31; $i++)
+                                                       {
+                                                               if (!$i)
+                                                                       echo "<option value=\"0d\"></option>";
+                                                               else
+                                                               {
+                                                                       $d = ($i == 1) ? "day" : "days";
+                                                                       echo "<option value=\"$i" . "d\">$i $d" . "</option>";
+                                                               }
+                                                       }
+                                                       ?>
+                                       </select>
+                                       <select class="curvy" name="banlen_h" id="banlen_h">
+                                                       <?php
+                                                       for ($i = 0; $i <= 24; $i++)
+                                                       {
+                                                               if (!$i)
+                                                                       echo "<option value=\"0d\"></option>";
+                                                               else
+                                                               {
+                                                                       $h = ($i == 1) ? "hour" : "hours";
+                                                                       echo "<option value=\"$i" . "h\">$i $h" . "</option>";
+                                                               }
+                                                       }
+                                                       ?>
+                                       </select>
+                                       <br><div class="align_label"><label for="ban_reason">Reason: </label></div>
+                                       <input class="curvy input_text" type="text" id="ban_reason" name="ban_reason"><br>
+                                       <input class="curvy input_text" type="checkbox" id="soft" name="soft">Don't affect logged-in users (soft)
+                               
+                       </div>
+                       
+               <div class="modal-footer">
+                       <button id="CloseButton" type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
+                       <button type="submit" action="post" class="btn btn-danger">Add Ban</button>
+                       </form>
+               </div>
+               </div>
+       </div>
+       </div>
+
+       <table class="container-xxl table table-sm table-responsive caption-top table-striped">
+       <thead class="table-primary">
+       <form method="post">
+       <th scope="col"><input type="checkbox" label='selectall' onClick="toggle_tkl(this)" /></th>
+       <th scope="col">Mask</th>
+       <th scope="col">Duration</th>
+       <th scope="col">Reason</th>
+       <th scope="col">Set By</th>
+       <th scope="col">Set On</th>
+       <th scope="col">Expires</th>
+       </thead>
+       <tbody>
+       <?php
+               foreach($ban_exceptions as $ban_exceptions)
+               {
+                       $set_in_config = ((isset($ban_exceptions->set_in_config) && $ban_exceptions->set_in_config) || ($ban_exceptions->set_by == "-config-")) ? true : false;
+                       echo "<tr scope='col'>";
+                       if ($set_in_config)
+                               echo "<td scope=\"col\"></td>";
+                       else
+                               echo "<td scope=\"col\"><input type=\"checkbox\" value='" . base64_encode($ban_exceptions->name).",".base64_encode($ban_exceptions->type) . "' name=\"tklch[]\"></td>";
+                       echo "<td scope=\"col\">".$ban_exceptions->name."</td>";
+                       echo "<td scope=\"col\">".$ban_exceptions->duration_string."</td>";
+                       echo "<td scope=\"col\">".$ban_exceptions->reason."</td>";
+                       $set_by = $set_in_config ? "<span class=\"badge rounded-pill badge-secondary\">Config</span>" : show_nick_only($ban_exceptions->set_by);
+                       echo "<td scope=\"col\">".$set_by."</td>";
+                       echo "<td scope=\"col\">".$ban_exceptions->set_at_string."</td>";
+                       echo "<td scope=\"col\">".$ban_exceptions->expire_at_string."</td>";
+                       echo "</tr>";
+               }
+       ?></tbody></table><p><button type="button" class="btn btn-danger" data-toggle="modal" data-target="#myModal2">
+       Delete selected
+       </button></p>
+       <div class="modal fade" id="myModal2" tabindex="-1" role="dialog" aria-labelledby="confirmModalCenterTitle" aria-hidden="true">
+       <div class="modal-dialog modal-dialog-centered" role="document">
+               <div class="modal-content">
+               <div class="modal-header">
+                       <h5 class="modal-title" id="myModalLabel">Confirm deletion</h5>
+                       <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                       <span aria-hidden="true">&times;</span>
+                       </button>
+               </div>
+               <div class="modal-body">
+                       Are you sure you want to do this?<br>
+                       This cannot be undone.                  
+               </div>
+               <div class="modal-footer">
+                       <button id="CloseButton" type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
+                       <button type="submit" action="post" class="btn btn-danger">Delete</button>
+                       
+               </div>
+               </div>
+       </div>
+       </div></form></div></div>
+
+<?php require_once 'footer.php'; ?>
similarity index 98%
rename from server_bans.php
rename to server-bans/index.php
index 97ec2fa8c6369cd16ee483ec4ac67bcdbf5e13ad..f379571adcf5276d6dd6df1413f5820f96442835 100644 (file)
@@ -1,7 +1,7 @@
 <?php
-require_once "common.php";
+require_once "../common.php";
 
-require_once "header.php";
+require_once "../header.php";
 
 if (!empty($_POST))
 {
@@ -94,12 +94,11 @@ if (!empty($_POST))
 }
 
 $tkl = $rpc->serverban()->getAll();
-foreach ($rpc->nameban()->getAll() as $v)
-       $tkl[] = $v;
 foreach ($rpc->serverbanexception()->getAll() as $v)
        $tkl[] = $v;
 ?>
-<h4>Server Bans Overview</h4><br>
+<h4>Server Bans Overview</h4>
+Here are all your network bans, from K-Lines to G-Lines, it's all here.<br><br>
 <p><button type="button" class="btn btn-primary" data-toggle="modal" data-target="#myModal">
                        Add entry
        </button></p></table>
diff --git a/server-bans/name-bans.php b/server-bans/name-bans.php
new file mode 100644 (file)
index 0000000..b7d4afb
--- /dev/null
@@ -0,0 +1,198 @@
+<?php
+require_once "../common.php";
+
+require_once "../header.php";
+
+if (!empty($_POST))
+{
+
+       do_log($_POST);
+
+       if (isset($_POST['tklch']) && !empty($_POST['tklch'])) // User has asked to delete these tkls
+       {
+               foreach ($_POST['tklch'] as $key => $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();
+
+?>
+<h4>Name Bans Overview</h4>
+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.<br>
+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.<br>
+<br>
+<p><button type="button" class="btn btn-primary" data-toggle="modal" data-target="#myModal">
+                       Add entry
+       </button></p></table>
+       <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="confirmModalCenterTitle" aria-hidden="true">
+       <div class="modal-dialog modal-dialog-centered" role="document">
+               <div class="modal-content">
+               <div class="modal-header">
+                       <h5 class="modal-title" id="myModalLabel">Add new Name Ban</h5>
+                       <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                       <span aria-hidden="true">&times;</span>
+                       </button>
+               </div>
+               <div class="modal-body">
+               
+               <form  method="post">
+                       <div class="align_label">Nick / Channel</div> <input class="curvy" type="text" id="tkl_add" name="tkl_add"><br>
+                       
+                       <div class="align_label"><label for="banlen_w">Duration: </label></div>
+                                       <select class="curvy" name="banlen_w" id="banlen_w">
+                                                       <?php
+                                                       for ($i = 0; $i <= 56; $i++)
+                                                       {
+                                                               if (!$i)
+                                                                       echo "<option value=\"0w\"></option>";
+                                                               else
+                                                               {
+                                                                       $w = ($i == 1) ? "week" : "weeks";
+                                                                       echo "<option value=\"$i" . "w\">$i $w" . "</option>";
+                                                               }
+                                                       }
+                                                       ?>
+                                       </select>
+                                       <select class="curvy" name="banlen_d" id="banlen_d">
+                                                       <?php
+                                                       for ($i = 0; $i <= 31; $i++)
+                                                       {
+                                                               if (!$i)
+                                                                       echo "<option value=\"0d\"></option>";
+                                                               else
+                                                               {
+                                                                       $d = ($i == 1) ? "day" : "days";
+                                                                       echo "<option value=\"$i" . "d\">$i $d" . "</option>";
+                                                               }
+                                                       }
+                                                       ?>
+                                       </select>
+                                       <select class="curvy" name="banlen_h" id="banlen_h">
+                                                       <?php
+                                                       for ($i = 0; $i <= 24; $i++)
+                                                       {
+                                                               if (!$i)
+                                                                       echo "<option value=\"0d\"></option>";
+                                                               else
+                                                               {
+                                                                       $h = ($i == 1) ? "hour" : "hours";
+                                                                       echo "<option value=\"$i" . "h\">$i $h" . "</option>";
+                                                               }
+                                                       }
+                                                       ?>
+                                       </select>
+                                       <br><div class="align_label"><label for="ban_reason">Reason: </label></div>
+                                       <input class="curvy input_text" type="text" id="ban_reason" name="ban_reason"><br>
+                               
+                       </div>
+                       
+               <div class="modal-footer">
+                       <button id="CloseButton" type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
+                       <button type="submit" action="post" class="btn btn-danger">Add Ban</button>
+                       </form>
+               </div>
+               </div>
+       </div>
+       </div>
+
+       <table class="container-xxl table table-sm table-responsive caption-top table-striped">
+       <thead class="table-primary">
+       <form method="post" action="name-bans.php">
+       <th scope="col"><input type="checkbox" label='selectall' onClick="toggle_tkl(this)" /></th>
+       <th scope="col">Mask</th>
+       <th scope="col">Duration</th>
+       <th scope="col">Reason</th>
+       <th scope="col">Set By</th>
+       <th scope="col">Set On</th>
+       <th scope="col">Expires</th>
+       </thead>
+       <tbody>
+       <?php
+               foreach($name_bans as $name_bans)
+               {
+                       $set_in_config = ((isset($name_bans->set_in_config) && $name_bans->set_in_config) || ($name_bans->set_by == "-config-")) ? true : false;
+                       echo "<tr scope='col'>";
+                       if ($set_in_config)
+                               echo "<td scope=\"col\"></td>";
+                       else
+                               echo "<td scope=\"col\"><input type=\"checkbox\" value='" . base64_encode($name_bans->name)."' name=\"tklch[]\"></td>";
+                       echo "<td scope=\"col\">".$name_bans->name."</td>";
+                       echo "<td scope=\"col\">".$name_bans->duration_string."</td>";
+                       echo "<td scope=\"col\">".$name_bans->reason."</td>";
+                       $set_by = $set_in_config ? "<span class=\"badge rounded-pill badge-secondary\">Config</span>" : show_nick_only($name_bans->set_by);
+                       echo "<td scope=\"col\">".$set_by."</td>";
+                       echo "<td scope=\"col\">".$name_bans->set_at_string."</td>";
+                       echo "<td scope=\"col\">".$name_bans->expire_at_string."</td>";
+                       echo "</tr>";
+               }
+       ?></tbody></table><p><button type="button" class="btn btn-danger" data-toggle="modal" data-target="#myModal2">
+       Delete selected
+       </button></p>
+       <div class="modal fade" id="myModal2" tabindex="-1" role="dialog" aria-labelledby="confirmModalCenterTitle" aria-hidden="true">
+       <div class="modal-dialog modal-dialog-centered" role="document">
+               <div class="modal-content">
+               <div class="modal-header">
+                       <h5 class="modal-title" id="myModalLabel">Confirm deletion</h5>
+                       <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                       <span aria-hidden="true">&times;</span>
+                       </button>
+               </div>
+               <div class="modal-body">
+                       Are you sure you want to do this?<br>
+                       This cannot be undone.                  
+               </div>
+               <div class="modal-footer">
+                       <button id="CloseButton" type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
+                       <button type="submit" action="post" class="btn btn-danger">Delete</button>
+                       
+               </div>
+               </div>
+       </div>
+       </div></form></div></div>
+
+<?php require_once 'footer.php'; ?>