Support multiple allowed users for write access

MAPTOOL_ALLOWED_GITEA_USER now accepts a comma-separated list of
Gitea usernames instead of just one, for when more than one person
needs upload/delete/move access.
This commit is contained in:
randy committed 2026-08-27 18:25:31 +02:00
1 parent e13d1a1e97
commit 260006ad65
3 files changed
+23 -16

No files matched your search

+7 -7
View File
@@ -24,13 +24,13 @@ module Maptool
# Login delegates to the Gitea instance the user already has an account # Login delegates to the Gitea instance the user already has an account
# on, rather than maintaining a local username/password — see # on, rather than maintaining a local username/password — see
# docs/architecture.adoc. Only ALLOWED_GITEA_USER may write; anyone else # docs/architecture.adoc. Only users listed in ALLOWED_GITEA_USERS may
# can authenticate against Gitea but is still refused. No defaults for # write; anyone else can authenticate against Gitea but is still
# the OAuth2 client id/secret/user: blank values just mean login (and # refused. No defaults for the OAuth2 client id/secret/user list: blank
# thus writing) doesn't work, which is fine outside production — nothing # values just mean login (and thus writing) doesn't work, which is fine
# here is eagerly validated at load time. # outside production — nothing here is eagerly validated at load time.
GITEA_URL = ENV.fetch("GITEA_URL", "https://git.priesol.net") GITEA_URL = ENV.fetch("GITEA_URL", "https://git.priesol.net")
ALLOWED_GITEA_USER = ENV.fetch("MAPTOOL_ALLOWED_GITEA_USER", "") ALLOWED_GITEA_USERS = ENV.fetch("MAPTOOL_ALLOWED_GITEA_USER", "").split(",").map(&:strip)
OAUTH_CLIENT = OAuth2::Client.new( OAUTH_CLIENT = OAuth2::Client.new(
ENV.fetch("GITEA_OAUTH_CLIENT_ID", ""), ENV.fetch("GITEA_OAUTH_CLIENT_ID", ""),
ENV.fetch("GITEA_OAUTH_CLIENT_SECRET", ""), ENV.fetch("GITEA_OAUTH_CLIENT_SECRET", ""),
@@ -67,7 +67,7 @@ module Maptool
token = OAUTH_CLIENT.auth_code.get_token(params[:code], redirect_uri: callback_url) token = OAUTH_CLIENT.auth_code.get_token(params[:code], redirect_uri: callback_url)
user = token.get("/api/v1/user").parsed user = token.get("/api/v1/user").parsed
halt 403, "not authorized" unless user["login"] == ALLOWED_GITEA_USER halt 403, "not authorized" unless ALLOWED_GITEA_USERS.include?(user["login"])
session[:user] = user["login"] session[:user] = user["login"]
redirect "/" redirect "/"
+5 -3
View File
@@ -260,9 +260,11 @@ username/password — there's already an account to reuse, and it keeps
credential storage (password hash, resets, ...) out of this app credential storage (password hash, resets, ...) out of this app
entirely. Successfully authenticating with Gitea is not by itself entirely. Successfully authenticating with Gitea is not by itself
enough to write, though — the callback also checks the returned enough to write, though — the callback also checks the returned
`login` against `MAPTOOL_ALLOWED_GITEA_USER`, so registering (or `login` against `MAPTOOL_ALLOWED_GITEA_USER` (a comma-separated
already having) any other account on that Gitea instance doesn't grant allowlist, e.g. `randy,friend1,friend2`), so registering (or already
access here. having) any other account on that Gitea instance doesn't grant access
here. It's a flat allowlist — everyone in it has equal write access,
no per-user roles or permissions.
Session state is a signed cookie (`Rack::Session::Cookie`, `secure` Session state is a signed cookie (`Rack::Session::Cookie`, `secure`
in production, `httponly`, `same_site: lax`) keyed off in production, `httponly`, `same_site: lax`) keyed off
+11 -6
View File
@@ -95,12 +95,17 @@ it every push would silently log everyone out every time `main`
changes) — generate it once (`openssl rand -hex 32`) and store that changes) — generate it once (`openssl rand -hex 32`) and store that
same value as the secret from then on, don't regenerate per-deploy. same value as the secret from then on, don't regenerate per-deploy.
Register the OAuth2 application on the Gitea side (as the Register the OAuth2 application once, under any one Gitea account
`MAPTOOL_ALLOWED_GITEA_USER` account): *Settings → Applications → (doesn't need to be an allowed user itself — any Gitea account can
Manage OAuth2 Applications → Create a new OAuth2 Application*, with authenticate through it, `MAPTOOL_ALLOWED_GITEA_USER` is what actually
redirect URI `https://map.priesol.net/auth/callback`. That gives you decides who gets write access): *Settings → Applications → Manage
the client id/secret to store as the two `GITEA_OAUTH_*` secrets OAuth2 Applications → Create a new OAuth2 Application*, with redirect
above. URI `https://map.priesol.net/auth/callback`. That gives you the client
id/secret to store as the two `OAUTH_CLIENT_*` secrets above.
`MAPTOOL_ALLOWED_GITEA_USER` itself is a comma-separated list of Gitea
usernames, e.g. `randy,friend1,friend2` — not their emails, the
`login` field from Gitea's `/api/v1/user`.
== CI deploy job == CI deploy job