instances.php 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. <?php
  2. declare(strict_types=1);
  3. require_once __DIR__ . "/../includes/auth.php";
  4. require_once __DIR__ . "/../includes/layout.php";
  5. require_once __DIR__ . "/../includes/instances.php";
  6. manageRequireLogin();
  7. $messages = [];
  8. $errors = [];
  9. // Plaintext token to display once after create/rotate. Never persisted.
  10. $newToken = null;
  11. $newTokenInstance = "";
  12. if (($_SERVER["REQUEST_METHOD"] ?? "") === "POST") {
  13. try {
  14. manageRequireCsrf();
  15. $action = (string) ($_POST["action"] ?? "");
  16. $id = trim((string) ($_POST["instance"] ?? ""));
  17. if ($action === "create") {
  18. $created = manageInstanceCreate(
  19. trim((string) ($_POST["new_instance"] ?? "")),
  20. trim((string) ($_POST["label"] ?? "")),
  21. trim((string) ($_POST["notes"] ?? "")),
  22. );
  23. $newToken = $created["token"];
  24. $newTokenInstance = $created["instance"]["id"];
  25. $messages[] = "Instanz \"" . $created["instance"]["id"] . "\" wurde angelegt.";
  26. } elseif ($action === "rotate") {
  27. $newToken = manageInstanceRotateToken($id);
  28. $newTokenInstance = $id;
  29. $messages[] = "Neues Token für \"" . $id . "\" erzeugt. Das alte Token ist ab sofort ungültig.";
  30. } elseif ($action === "toggle") {
  31. $instance = manageInstanceFind($id);
  32. if ($instance === null) {
  33. throw new RuntimeException("Instanz wurde nicht gefunden.");
  34. }
  35. manageInstanceUpdate($id, ["enabled" => !$instance["enabled"]]);
  36. $messages[] = $instance["enabled"]
  37. ? "Instanz \"" . $id . "\" wurde deaktiviert."
  38. : "Instanz \"" . $id . "\" wurde aktiviert.";
  39. } elseif ($action === "save") {
  40. manageInstanceUpdate($id, [
  41. "label" => trim((string) ($_POST["label"] ?? "")),
  42. "notes" => trim((string) ($_POST["notes"] ?? "")),
  43. ]);
  44. $messages[] = "Instanz \"" . $id . "\" wurde gespeichert.";
  45. } elseif ($action === "delete") {
  46. manageInstanceDelete($id);
  47. $messages[] = "Instanz \"" . $id . "\" wurde entfernt. Vorhandene Backups bleiben erhalten.";
  48. }
  49. } catch (Throwable $exception) {
  50. $errors[] = $exception->getMessage();
  51. }
  52. }
  53. try {
  54. $instances = manageInstanceList();
  55. } catch (Throwable $exception) {
  56. $instances = [];
  57. $errors[] = $exception->getMessage();
  58. }
  59. manageRenderHeader("Instanzen", $messages, $errors);
  60. ?>
  61. <?php if ($newToken !== null): ?>
  62. <div class="token-box">
  63. <p><strong>Token für <?php echo manageEscape($newTokenInstance); ?></strong></p>
  64. <p class="muted">Dieses Token wird nur jetzt angezeigt. Der Server speichert lediglich einen Hash davon.</p>
  65. <pre class="token-value"><?php echo manageEscape($newToken); ?></pre>
  66. <p>In die <code>config.php</code> des Clients eintragen:</p>
  67. <pre class="code-block">define("MANAGE_SERVER_URL", "<?php echo manageEscape(rtrim((string) MANAGE_PUBLIC_URL, "/")); ?>");
  68. define("MANAGE_INSTANCE", "<?php echo manageEscape($newTokenInstance); ?>");
  69. define("MANAGE_TOKEN", "<?php echo manageEscape($newToken); ?>");</pre>
  70. </div>
  71. <?php endif; ?>
  72. <h2>Neue Instanz</h2>
  73. <form method="POST" class="panel">
  74. <?php echo manageCsrfField(); ?>
  75. <input type="hidden" name="action" value="create">
  76. <div class="form-row">
  77. <div class="form-group">
  78. <label for="new_instance">Kennung</label>
  79. <input type="text" id="new_instance" name="new_instance" required
  80. pattern="[A-Za-z0-9][A-Za-z0-9._\-]*" maxlength="120" placeholder="psa-prod">
  81. <p class="hint">Buchstaben, Zahlen, Punkt, Unterstrich, Bindestrich.</p>
  82. </div>
  83. <div class="form-group">
  84. <label for="label">Bezeichnung</label>
  85. <input type="text" id="label" name="label" maxlength="200" placeholder="Stadt Freising Produktiv">
  86. </div>
  87. </div>
  88. <div class="form-group">
  89. <label for="notes">Notiz</label>
  90. <input type="text" id="notes" name="notes" maxlength="500">
  91. </div>
  92. <button type="submit" class="btn">Instanz anlegen</button>
  93. </form>
  94. <h2>Registrierte Instanzen</h2>
  95. <?php if ($instances === []): ?>
  96. <p class="empty">Noch keine Instanz registriert.</p>
  97. <?php else: ?>
  98. <?php foreach ($instances as $instance): ?>
  99. <section class="panel" id="<?php echo manageEscape($instance["id"]); ?>">
  100. <div class="panel-head">
  101. <h3><?php echo manageEscape($instance["id"]); ?></h3>
  102. <?php if ($instance["enabled"]): ?>
  103. <span class="badge badge-ok">aktiv</span>
  104. <?php else: ?>
  105. <span class="badge badge-error">deaktiviert</span>
  106. <?php endif; ?>
  107. </div>
  108. <dl class="meta-list">
  109. <div><dt>Version</dt><dd><?php echo manageEscape($instance["version"] !== "" ? $instance["version"] : "–"); ?></dd></div>
  110. <div><dt>PHP</dt><dd><?php echo manageEscape($instance["php_version"] !== "" ? $instance["php_version"] : "–"); ?></dd></div>
  111. <div><dt>Zuletzt gesehen</dt><dd><?php echo manageEscape($instance["last_seen_at"] !== "" ? $instance["last_seen_at"] : "nie"); ?></dd></div>
  112. <div><dt>Letzte IP</dt><dd><?php echo manageEscape($instance["last_ip"] !== "" ? $instance["last_ip"] : "–"); ?></dd></div>
  113. <div><dt>Letztes Backup</dt><dd><?php echo manageEscape($instance["last_backup_at"] !== "" ? $instance["last_backup_at"] : "nie"); ?></dd></div>
  114. <div><dt>Backups</dt><dd><?php echo (int) $instance["backup_count"]; ?></dd></div>
  115. <div><dt>Offene Migrationen</dt><dd><?php echo (int) $instance["pending_migrations"]; ?></dd></div>
  116. <div><dt>Token erneuert</dt><dd><?php echo manageEscape($instance["token_rotated_at"] !== "" ? $instance["token_rotated_at"] : "–"); ?></dd></div>
  117. <div><dt>Freier Speicher</dt><dd><?php echo $instance["disk_free"] > 0 ? manageEscape(manageFormatBytes($instance["disk_free"])) : "–"; ?></dd></div>
  118. </dl>
  119. <form method="POST" class="inline-form">
  120. <?php echo manageCsrfField(); ?>
  121. <input type="hidden" name="action" value="save">
  122. <input type="hidden" name="instance" value="<?php echo manageEscape($instance["id"]); ?>">
  123. <div class="form-row">
  124. <div class="form-group">
  125. <label>Bezeichnung
  126. <input type="text" name="label" maxlength="200" value="<?php echo manageEscape($instance["label"]); ?>">
  127. </label>
  128. </div>
  129. <div class="form-group">
  130. <label>Notiz
  131. <input type="text" name="notes" maxlength="500" value="<?php echo manageEscape($instance["notes"]); ?>">
  132. </label>
  133. </div>
  134. </div>
  135. <button type="submit" class="btn btn-secondary">Speichern</button>
  136. </form>
  137. <div class="button-row">
  138. <form method="POST" onsubmit="return confirm('Neues Token erzeugen? Das alte Token wird sofort ungültig.');">
  139. <?php echo manageCsrfField(); ?>
  140. <input type="hidden" name="action" value="rotate">
  141. <input type="hidden" name="instance" value="<?php echo manageEscape($instance["id"]); ?>">
  142. <button type="submit" class="btn btn-secondary">Token erneuern</button>
  143. </form>
  144. <form method="POST">
  145. <?php echo manageCsrfField(); ?>
  146. <input type="hidden" name="action" value="toggle">
  147. <input type="hidden" name="instance" value="<?php echo manageEscape($instance["id"]); ?>">
  148. <button type="submit" class="btn btn-secondary">
  149. <?php echo $instance["enabled"] ? "Deaktivieren" : "Aktivieren"; ?>
  150. </button>
  151. </form>
  152. <form method="POST" onsubmit="return confirm('Instanz wirklich entfernen? Backups bleiben erhalten.');">
  153. <?php echo manageCsrfField(); ?>
  154. <input type="hidden" name="action" value="delete">
  155. <input type="hidden" name="instance" value="<?php echo manageEscape($instance["id"]); ?>">
  156. <button type="submit" class="btn btn-danger">Entfernen</button>
  157. </form>
  158. </div>
  159. </section>
  160. <?php endforeach; ?>
  161. <?php endif; ?>
  162. <?php manageRenderFooter(); ?>