web iface updates, qol for operaators etcs

0aa3d5d · gmorell · 2026-06-10 22:49

38 files +660 -2

Files changed

modified README.md
+24 −0
@@ -153,6 +153,16 @@ bare note from a day count). Both commands require operator status and
153 153 reply `481` otherwise. (`/quote` sends a raw command; some clients use
154 154 `/raw` or accept `/mkinvite` directly.)
155 155
156 +**From the web UI:** operator-flagged accounts get an **Admin** link in
157 +the account menu, linking to `/admin`. From there an oper can create
158 +invites (note + optional expiry), copy each single-use signup link,
159 +revoke outstanding invites, see every registered channel network-wide
160 +(the operator counterpart to the per-user "Registered channels you can
161 +manage" page), and see everyone currently connected to the network —
162 +each tagged registered / anonymous / service, with their account, host,
163 +and node. The page is gated to opers — see
164 +[Creating an IRC operator](#creating-an-irc-operator) for the flag.
165 +
156 166 Registration mode itself is set from the `REGISTRATION_MODE` env var in
157 167 `runtime.exs` (`open` for free signup, anything else → `invite_only`).
158 168 With `:open`, the gate is off and invite tokens are unnecessary.
@@ -274,6 +284,20 @@ deploy/
274 284
275 285 See `deploy/README.md` for the apply order and operating notes.
276 286
287 +### Database migrations
288 +
289 +Prod releases **run pending migrations automatically on boot** — a
290 +synchronous migrator runs right after the Repo starts and before the IRC
291 +listeners / web endpoint come up, so clients never hit a half-migrated
292 +schema. In a cluster every node does this, but Ecto's migration lock
293 +serialises them, so only the first node actually applies each migration.
294 +
295 +This is on by default in prod; set `MIGRATE_ON_START=false` to opt out
296 +(e.g. when you run migrations from a separate Kubernetes Job or
297 +initContainer). You can still migrate manually any time with
298 +`bin/oh_my_ex_oh_ircd eval 'OhMyExOhIrcd.Release.migrate()'`. In dev/test
299 +the auto-migrator is a no-op — use `mix ecto.migrate` as usual.
300 +
277 301 ## Architecture sketch
278 302
279 303 ```
modified config/runtime.exs
+13 −0
@@ -74,6 +74,19 @@ if config_env() == :prod do
74 74 end
75 75
76 76 config :oh_my_ex_oh_ircd, :registration_mode, registration_mode
77 +
78 + # Run pending migrations automatically when the release boots. On by
79 + # default in prod; set MIGRATE_ON_START=false to opt out (e.g. if you
80 + # run migrations from a separate k8s Job / initContainer instead).
81 + config :oh_my_ex_oh_ircd,
82 + :migrate_on_start,
83 + System.get_env("MIGRATE_ON_START", "true") not in ["0", "false", "no"]
84 +
85 + # WebIRC LiveView toggle. Off by default in prod (matches config.exs);
86 + # set WEBIRC_ENABLED=true to let logged-in users open /webirc.
87 + config :oh_my_ex_oh_ircd,
88 + :webirc,
89 + enabled: System.get_env("WEBIRC_ENABLED", "false") in ~w(1 true yes on)
77 90 end
78 91
79 92 # TLS listener cert paths from env. In the :kubernetes build these point at
modified deploy/argo/neiam-ircd/app.yml
+2 −1
@@ -44,9 +44,10 @@ spec:
44 44 - { name: IRC_SERVER_NAME, value: "irc.skyjeep.club" }
45 45 - { name: IRC_NETWORK_NAME, value: "SkyjeepIRC" }
46 46 # Defaults in runtime.exs: anonymous IRC ON, web registration
47 − # invite-only. Uncomment to override:
47 + # invite-only, /webirc OFF. Uncomment to override:
48 48 # - { name: IRC_ALLOW_ANONYMOUS, value: "false" }
49 49 # - { name: REGISTRATION_MODE, value: "open" }
50 + # - { name: WEBIRC_ENABLED, value: "true" }
50 51
51 52 # TLS terminates at Traefik now (see the IngressRouteTCP at
52 53 # the bottom). Backend speaks plain IRC on 6667 only; we
modified deploy/kubernetes/60-deployment.yaml
+2 −0
@@ -44,6 +44,8 @@ spec:
44 44 - { name: IRC_SERVER_NAME, value: "irc.example.com" }
45 45 - { name: IRC_NETWORK_NAME, value: "ExampleNet" }
46 46 - { name: IRC_ALLOW_ANONYMOUS, value: "false" }
47 + # Set to "true" to expose the in-browser /webirc client.
48 + - { name: WEBIRC_ENABLED, value: "false" }
47 49 # IRC TLS — paths point at the cert-manager Secret mounted below.
48 50 - { name: IRC_TLS_ENABLED, value: "true" }
49 51 - { name: IRC_TLS_PORT, value: "6697" }
modified deploy/standalone/docker-compose.yml
+2 −0
@@ -40,6 +40,8 @@ services:
40 40 IRC_ALLOW_ANONYMOUS: "false"
41 41 IRC_TLS_ENABLED: "true"
42 42 IRC_TLS_PORT: "6697"
43 + # Set to "true" to expose the in-browser /webirc client.
44 + WEBIRC_ENABLED: "false"
43 45 # ACME (consumed by the :standalone build's runtime.exs ACME block).
44 46 ACME_DOMAINS: ${HOSTNAME}
45 47 ACME_EMAILS: ${ACME_EMAIL}
modified deploy/standalone/quadlet/ircd.container
+1 −0

Click to load diff…

modified lib/oh_my_ex_oh_ircd/accounts.ex
+13 −1

Click to load diff…

modified lib/oh_my_ex_oh_ircd/application.ex
+3 −0

Click to load diff…

modified lib/oh_my_ex_oh_ircd/channels.ex
+9 −0

Click to load diff…

modified lib/oh_my_ex_oh_ircd/irc/stats.ex
+44 −0

Click to load diff…

added lib/oh_my_ex_oh_ircd/release/migrator.ex
+44 −0

Click to load diff…

modified lib/oh_my_ex_oh_ircd_web/components/layouts.ex
+7 −0

Click to load diff…

added lib/oh_my_ex_oh_ircd_web/live/admin_live.ex
+281 −0

Click to load diff…

modified lib/oh_my_ex_oh_ircd_web/router.ex
+5 −0

Click to load diff…

modified lib/oh_my_ex_oh_ircd_web/user_auth.ex
+26 −0

Click to load diff…

added test/oh_my_ex_oh_ircd/irc/stats_users_test.exs
+49 −0

Click to load diff…

added test/oh_my_ex_oh_ircd/release/migrator_test.exs
+37 −0

Click to load diff…

added test/oh_my_ex_oh_ircd_web/live/admin_live_test.exs
+98 −0

Click to load diff…

Parents: d2edb4a