aboutsummaryrefslogtreecommitdiff
path: root/clients/screens_audit.c
diff options
context:
space:
mode:
Diffstat (limited to 'clients/screens_audit.c')
-rw-r--r--clients/screens_audit.c132
1 files changed, 132 insertions, 0 deletions
diff --git a/clients/screens_audit.c b/clients/screens_audit.c
new file mode 100644
index 0000000..8f54dd5
--- /dev/null
+++ b/clients/screens_audit.c
@@ -0,0 +1,132 @@
+#include <dirent.h>
+#include <errno.h>
+#include <locale.h>
+#include <math.h>
+#include <ncursesw/ncurses.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "client.h"
+#include "tui.h"
+#include "formula.h"
+#include "util.h"
+#include "version.h"
+#include "yyjson.h"
+#include "ui.h"
+
+static void audit_verify_run(struct app *a, int full)
+{
+ char *resp = client_rpc(&a->conn, "audit.verify", a->session, a->org,
+ full ? "{\"full\":true}" : "{}");
+ if (!resp || !client_ok(resp)) {
+ show_error("Revision", resp);
+ free(resp);
+ return;
+ }
+ int64_t checked = jint_val(resp, "result.checked", 0);
+ int64_t vouchers = jint_val(resp, "result.vouchers_checked", 0);
+ int is_ok = jbool_val(resp, "result.ok", 0);
+ if (is_ok) {
+ if (full)
+ tui_message("Hashkedjor",
+ "Kedjorna är intakta.\n%lld verifikat och %lld "
+ "händelser kontrollerade.\n%lld underlag "
+ "hash-kontrollerade.",
+ (long long)vouchers, (long long)checked,
+ (long long)jint_val(resp, "result.attachments_checked",
+ 0));
+ else
+ tui_message("Hashkedjor",
+ "Kedjorna är intakta.\n%lld verifikat och %lld "
+ "händelser kontrollerade.",
+ (long long)vouchers, (long long)checked);
+ } else {
+ int64_t bad_v = jint_val(resp, "result.first_bad_voucher_id", 0);
+ int64_t bad_a = jint_val(resp, "result.first_bad_seq", 0);
+ int64_t unbal = jint_val(resp, "result.first_unbalanced_voucher_id", 0);
+ int64_t bad_att =
+ jint_val(resp, "result.first_bad_attachment_id", 0);
+ char detail[320] = "";
+ if (bad_v)
+ snprintf(detail + strlen(detail), sizeof detail - strlen(detail),
+ "Första trasiga verifikat: %lld\n", (long long)bad_v);
+ if (bad_a)
+ snprintf(detail + strlen(detail), sizeof detail - strlen(detail),
+ "Första trasiga händelse: %lld\n", (long long)bad_a);
+ if (unbal)
+ snprintf(detail + strlen(detail), sizeof detail - strlen(detail),
+ "Första obalanserade verifikat: %lld\n",
+ (long long)unbal);
+ if (bad_att)
+ snprintf(detail + strlen(detail), sizeof detail - strlen(detail),
+ "Första trasiga underlag: %lld\n", (long long)bad_att);
+ tui_message("Hashkedjor", "KEDJORNA ÄR BRUTNA!\n%s", detail);
+ }
+ free(resp);
+}
+
+void audit_screen(struct app *a)
+{
+ static const char *const audit_items[] = { "Verifiera hashkedjan",
+ "Verifiera allt (inkl. underlag)",
+ "Senaste händelser" };
+ static int last_sel = 0;
+ for (;;) {
+ if (g_quit)
+ return;
+ int sel = tui_menu("Revision", audit_items, 3, 0, &last_sel);
+ if (sel < 0)
+ return;
+ if (sel == 0) {
+ audit_verify_run(a, 0);
+ } else if (sel == 1) {
+ audit_verify_run(a, 1);
+ } else {
+ for (;;) {
+ char *resp = client_rpc(&a->conn, "audit.list", a->session,
+ a->org, "{\"limit\":200}");
+ if (!resp || !client_ok(resp)) {
+ show_error("Revision", resp);
+ free(resp);
+ break;
+ }
+ struct buf text;
+ buf_init(&text);
+ size_t n = jarr_size(resp, "result.items");
+ for (size_t i = 0; i < n; i++) {
+ char path[64], line[512];
+ snprintf(path, sizeof path, "result.items.%zu.at", i);
+ char *at = jstr_dup(resp, path);
+ snprintf(path, sizeof path, "result.items.%zu.action", i);
+ char *action = jstr_dup(resp, path);
+ snprintf(path, sizeof path,
+ "result.items.%zu.result_code", i);
+ char *code = jstr_dup(resp, path);
+ snprintf(path, sizeof path,
+ "result.items.%zu.actor_user_id", i);
+ int64_t actor = jint_val(resp, path, 0);
+ snprintf(line, sizeof line, "%s anv %lld %-22s %s\n",
+ at ? at : "", (long long)actor,
+ action ? action : "", code ? code : "");
+ buf_append(&text, line, strlen(line));
+ free(at);
+ free(action);
+ free(code);
+ }
+ buf_append(&text, "\0", 1);
+ int again = tui_pager("Behandlingshistorik", (char *)text.p, NULL);
+ buf_free(&text);
+ free(resp);
+ if (!again)
+ break;
+ }
+ }
+ }
+}