Browse Source

Add API key manager

master
Skylar Ittner 4 months ago
parent
commit
34ea14d34e
11 changed files with 183 additions and 3 deletions
  1. 24
    0
      action.php
  2. 1
    1
      app.php
  3. 2
    1
      langs/en/actions.json
  4. 10
    0
      langs/en/apikeys.json
  5. 2
    1
      langs/en/titles.json
  6. 16
    0
      langs/messages.php
  7. 17
    0
      pages.php
  8. 24
    0
      pages/addapikey.php
  9. 55
    0
      pages/apikeys.php
  10. 2
    0
      settings.template.php
  11. 30
    0
      static/js/apikeys.js

+ 24
- 0
action.php View File

@@ -241,6 +241,30 @@ switch ($VARS['action']) {
241 241
         require_once __DIR__ . "/lib/reports.php";
242 242
         generateReport($VARS['type'], $VARS['format']);
243 243
         break;
244
+    case "revokeapikey":
245
+        if (empty($VARS['key'])) {
246
+            returnToSender("invalid_parameters");
247
+        }
248
+        if ($VARS['key'] == $SETTINGS['accounthub']['key']) {
249
+            returnToSender("cannot_revoke_key_in_use");
250
+        }
251
+        $database->delete("apikeys", ['key' => $VARS['key'], "LIMIT" => 1]);
252
+        returnToSender("api_key_revoked");
253
+        break;
254
+    case "addapikey":
255
+        if (empty($VARS['key']) || empty($VARS['type'])) {
256
+            returnToSender("invalid_parameters");
257
+        }
258
+        $keytypes = ["NONE", "AUTH", "READ", "FULL"];
259
+        if (!in_array($VARS['type'], $keytypes)) {
260
+            returnToSender("invalid_parameters");
261
+        }
262
+        if ($database->has("apikeys", ["key" => $VARS['key']])) {
263
+            returnToSender("key_already_exists");
264
+        }
265
+        $database->insert("apikeys", ["key" => $VARS['key'], "notes" => $VARS['notes'], "type" => $VARS['type']]);
266
+        returnToSender("api_key_added");
267
+        break;
244 268
     case "signout":
245 269
         session_destroy();
246 270
         header('Location: index.php?logout=1');

+ 1
- 1
app.php View File

@@ -115,7 +115,7 @@ END;
115 115
 
116 116
         <?php
117 117
         // Adjust as needed
118
-        $navbar_breakpoint = "lg";
118
+        $navbar_breakpoint = "xl";
119 119
 
120 120
         // For mobile app
121 121
         echo "<script nonce=\"$SECURE_NONCE\">var navbar_breakpoint = \"$navbar_breakpoint\";</script>"

+ 2
- 1
langs/en/actions.json View File

@@ -1,5 +1,6 @@
1 1
 {
2 2
     "Edit": "Edit",
3 3
     "cancel": "Cancel",
4
-    "Choose a user": "Choose a user"
4
+    "Choose a user": "Choose a user",
5
+    "Add Key": "Add Key"
5 6
 }

+ 10
- 0
langs/en/apikeys.json View File

@@ -0,0 +1,10 @@
1
+{
2
+    "Key": "Key",
3
+    "Type": "Type",
4
+    "Notes": "Notes",
5
+    "Revoke": "Revoke",
6
+    "Cannot revoke that API key, you would lose access to ManagePanel.": "Cannot revoke that API key, you would lose access to ManagePanel.",
7
+    "API key revoked.": "API key revoked.",
8
+    "That API key already exists.": "That API key already exists.",
9
+    "API key added.": "API key added."
10
+}

+ 2
- 1
langs/en/titles.json View File

@@ -5,5 +5,6 @@
5 5
     "Security": "Security",
6 6
     "Security Log": "Security Log",
7 7
     "Managers": "Managers",
8
-    "Permissions": "Permissions"
8
+    "Permissions": "Permissions",
9
+    "API Keys": "API Keys"
9 10
 }

+ 16
- 0
langs/messages.php View File

@@ -93,4 +93,20 @@ define("MESSAGES", [
93 93
         "string" => "group already exists",
94 94
         "type" => "danger"
95 95
     ],
96
+    "cannot_revoke_key_in_use" => [
97
+        "string" => "Cannot revoke that API key, you would lose access to ManagePanel.",
98
+        "type" => "danger"
99
+    ],
100
+    "api_key_revoked" => [
101
+        "string" => "API key revoked.",
102
+        "type" => "success"
103
+    ],
104
+    "key_already_exists" => [
105
+        "string" => "That API key already exists.",
106
+        "type" => "warning"
107
+    ],
108
+    "api_key_added" => [
109
+        "string" => "API key added.",
110
+        "type" => "success"
111
+    ],
96 112
 ]);

+ 17
- 0
pages.php View File

@@ -96,6 +96,23 @@ define("PAGES", [
96 96
             "static/js/export.js"
97 97
         ]
98 98
     ],
99
+    "apikeys" => [
100
+        "title" => "API Keys",
101
+        "navbar" => true,
102
+        "icon" => "fas fa-server",
103
+        "styles" => [
104
+            "static/css/datatables.min.css",
105
+            "static/css/tables.css"
106
+        ],
107
+        "scripts" => [
108
+            "static/js/datatables.min.js",
109
+            "static/js/apikeys.js"
110
+        ],
111
+    ],
112
+    "addapikey" => [
113
+        "title" => "Add Key",
114
+        "navbar" => false
115
+    ],
99 116
     "404" => [
100 117
         "title" => "404 error"
101 118
     ]

+ 24
- 0
pages/addapikey.php View File

@@ -0,0 +1,24 @@
1
+<?php
2
+
3
+/*
4
+ * This Source Code Form is subject to the terms of the Mozilla Public
5
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
6
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7
+ */
8
+
9
+$key = hash("SHA1", random_bytes(100));
10
+
11
+$form = new FormBuilder($Strings->get("Add Key", false), "fas fa-plus");
12
+
13
+$form->addInput("key", $key, "text", true, "key", null, $Strings->get("Key", false), "fas fa-key", 12, 20);
14
+
15
+$form->addInput("type", "", "select", true, "type", ["NONE" => "NONE", "AUTH" => "AUTH", "READ" => "READ", "FULL" => "FULL"], $Strings->get("Type", false), "fas fa-list", 6);
16
+
17
+$form->addInput("notes", "", "textarea", false, "notes", null, $Strings->get("Notes", false), "fas fa-sticky-note", 6);
18
+
19
+$form->addButton($Strings->get("Add Key", false), "fas fa-save", null, "submit", null, null, "", "btn btn-success");
20
+
21
+$form->addHiddenInput("action", "addapikey");
22
+$form->addHiddenInput("source", "apikeys");
23
+
24
+$form->generate();

+ 55
- 0
pages/apikeys.php View File

@@ -0,0 +1,55 @@
1
+<?php
2
+/* This Source Code Form is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
+
6
+require_once __DIR__ . '/../required.php';
7
+
8
+redirectifnotloggedin();
9
+?>
10
+<div class="btn-group mgn-btm-10px">
11
+    <a href="app.php?page=addapikey" class="btn btn-primary"><i class="fas fa-plus"></i> <?php $Strings->get("Add Key"); ?></a>
12
+</div>
13
+<table id="apikeytable" class="table table-bordered table-hover table-sm">
14
+    <thead>
15
+        <tr>
16
+            <th data-priority="0"></th>
17
+            <th data-priority="1"><?php $Strings->get('actions'); ?></th>
18
+            <th data-priority="1"><i class="fas fa-fw fa-key d-none d-md-inline"></i> <?php $Strings->get('Key'); ?></th>
19
+            <th data-priority="1"><i class="fas fa-fw fa-list d-none d-md-inline"></i> <?php $Strings->get('Type'); ?></th>
20
+            <th data-priority="2"><i class="fas fa-fw fa-sticky-note d-none d-md-inline"></i> <?php $Strings->get('Notes'); ?></th>
21
+        </tr>
22
+    </thead>
23
+    <tbody>
24
+        <?php
25
+        $keys = $database->select("apikeys", ["key", "notes", "type"]);
26
+        foreach ($keys as $key) {
27
+            if ($SETTINGS['hide_api_key_in_use'] && $key['key'] == $SETTINGS['accounthub']['key']) {
28
+                continue;
29
+            }
30
+        ?>
31
+        <tr>
32
+            <td></td>
33
+            <td><form action="action.php" method="POST">
34
+                    <input type="hidden" name="action" value="revokeapikey" />
35
+                    <input type="hidden" name="source" value="apikeys" />
36
+                    <input type="hidden" name="key" value="<?php echo $key['key']; ?>" />
37
+                    <button type="submit" class="btn btn-danger btn-sm"><i class="fas fa-times"></i> <?php $Strings->get("Revoke"); ?></button>
38
+                </form></td>
39
+            <td><?php echo $key['key']; ?></td>
40
+            <td><?php echo $key['type']; ?></td>
41
+            <td><?php echo htmlentities($key['notes']); ?></td>
42
+        </tr>
43
+        <?php
44
+        }
45
+        ?>
46
+    </tbody>
47
+    <tfoot>
48
+        <tr>
49
+            <th data-priority="0"></th>
50
+            <th data-priority="1"><?php $Strings->get('actions'); ?></th>
51
+            <th data-priority="1"><i class="fas fa-fw fa-key d-none d-md-inline"></i> <?php $Strings->get('Key'); ?></th>
52
+            <th data-priority="1"><i class="fas fa-fw fa-list d-none d-md-inline"></i> <?php $Strings->get('Type'); ?></th>
53
+            <th data-priority="2"><i class="fas fa-fw fa-sticky-note d-none d-md-inline"></i> <?php $Strings->get('Notes'); ?></th>
54
+    </tfoot>
55
+</table>

+ 2
- 0
settings.template.php View File

@@ -50,6 +50,8 @@ $SETTINGS = [
50 50
     "permissions" => [
51 51
         "ADMIN"
52 52
     ],
53
+    // Set to true to hide the API key in use by ManagePanel from the editor.
54
+    "hide_api_key_in_use" => false,
53 55
     // For supported values, see http://php.net/manual/en/timezones.php
54 56
     "timezone" => "America/Denver",
55 57
     // Language to use for localization. See langs folder to add a language.

+ 30
- 0
static/js/apikeys.js View File

@@ -0,0 +1,30 @@
1
+/* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
+
5
+$('#apikeytable').DataTable({
6
+    responsive: {
7
+        details: {
8
+            display: $.fn.dataTable.Responsive.display.modal({
9
+                header: function (row) {
10
+                    var data = row.data();
11
+                    return "<i class=\"fas fa-list fa-fw\"></i> " + data[1];
12
+                }
13
+            }),
14
+            renderer: $.fn.dataTable.Responsive.renderer.tableAll({
15
+                tableClass: 'table'
16
+            }),
17
+            type: "column"
18
+        }
19
+    },
20
+    columnDefs: [
21
+        {
22
+            targets: 0,
23
+            className: 'control',
24
+            orderable: false
25
+        }
26
+    ],
27
+    order: [
28
+        [1, 'desc']
29
+    ],
30
+});

Loading…
Cancel
Save