nandi/frqpublic Fork 0
5b5e90e85af0416f173c7c6e7310f01ec8328ba5
Commits
Clone
git clone https://git.rickub.com/nandi/frq.git
git clone ssh://git@rickub.com/nandi/frq.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

Remember which rooms this client has been in 1d062fd · on 5b5e90e85af0416f173c7c6e7310f01ec8328ba5 · nandi · 20d ago
store.jolt · 73 lines · 2.4 KBGDScript3 Blame HistoryRaw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
(ns frq.store
  "The one thing worth keeping between runs: the durable broker token.

  It is a credential  anyone holding it can mint session tokens for the
  account  so it lives in the user's config directory with the permissions of
  an ssh key, and never anywhere else. The web-token beside it is single-use
  and deliberately not saved."
  (:require [clojure.edn :as edn]
            [clojure.string :as str]
            [jolt.host :as host]))

(defn config-dir []
  (let [xdg (host/getenv "XDG_CONFIG_HOME")
        home (host/getenv "HOME")]
    (str (if (seq xdg) xdg (str home "/.config")) "/frq")))

(defn session-file [] (str (config-dir) "/session.edn"))

(defn load-session
  "The saved session, or nil. A file that will not parse is treated as absent —
  a stale credential is not worth an error at startup."
  []
  (let [path (session-file)]
    (when (host/file-exists? path)
      (try
        (let [m (edn/read-string (slurp path))]
          (when (and (map? m) (seq (:broker-token m))) m))
        (catch Exception _ nil)))))

(defn save-session!
  "Write {:broker-token :handle :did :nick}, readable by nobody else."
  [session]
  (let [dir (config-dir)
        path (session-file)]
    (try
      (host/mkdirs! dir)
      ;; Created before it is written, so the token is never on disk
      ;; world-readable even for an instant.
      (host/sh (str "install -m 600 /dev/null '" path "'"))
      (spit path (pr-str (select-keys session [:broker-token :handle :did :nick])))
      (host/sh (str "chmod 600 '" path "'"))
      true
      (catch Exception _ false))))

(defn channels-file [] (str (config-dir) "/channels.edn"))

(defn load-channels
  "The channels this client has opened, in the order it last used them. Unlike
  the session beside it this is not a credential  just names  so it is an
  ordinary file."
  []
  (let [path (channels-file)]
    (when (host/file-exists? path)
      (try
        (let [v (edn/read-string (slurp path))]
          (when (vector? v) (filterv string? v)))
        (catch Exception _ nil)))))

(defn save-channels!
  "Write the channel names, most recently used first."
  [names]
  (try
    (host/mkdirs! (config-dir))
    (spit (channels-file) (pr-str (vec names)))
    true
    (catch Exception _ false)))

(defn clear-session! []
  (try
    (when (host/file-exists? (session-file))
      (host/delete-file! (session-file)))
    true
    (catch Exception _ false)))