ask for the URL first, and offer what tea already knows
The form asked for a URL and a token together, on a fresh instance, while the machine in front of it often had both on disk already — somebody had run `tea login` by hand. Two changes. One thing at a time: until the platform knows where Gitea is, a token cannot be checked, because there is nothing to check it against. So the owner names the instance first, and only then does the page ask for — or discover — a token. That step now probes /api/v1/version unauthenticated, since demanding a token to validate a URL refuses a good URL for the wrong reason and sends whoever typed it looking for a credential problem. And it reads tea's own config when the platform has no instance yet, offering the URL it finds. A machine that already has a working login should not be asked to retype what it can see. Members skip the first step entirely — the instance is the owner's.
This commit is contained in:
+15
-4
@@ -16,9 +16,10 @@ import {
|
||||
invalidateAllGiteaConfigs,
|
||||
normalizeBase,
|
||||
probe,
|
||||
reachable,
|
||||
UnreadableCredentials,
|
||||
} from './upstream';
|
||||
import { readTeaLogin, writeTeaLogin, osUserFor, testTeaLogin } from './tea-config';
|
||||
import { readTeaLogin, readAnyTeaLogin, writeTeaLogin, osUserFor, testTeaLogin } from './tea-config';
|
||||
import { API_URL } from '@@/officer-url.mjs';
|
||||
|
||||
// The officer-gitea sidecar. Owns the whole Gitea contract: the instance URL and the personal access
|
||||
@@ -136,7 +137,10 @@ async function connectionState(userId: number): Promise<Response> {
|
||||
//
|
||||
// Read rather than asked for: on a machine where the owner and their members already ran `tea login`
|
||||
// by hand, the settings page should say "connected" instead of demanding something they have.
|
||||
const tea = instanceUrl ? await readTeaLogin(userId, instanceUrl) : null;
|
||||
// With an instance known, ask about THAT one. Without, offer whatever tea already has — a machine
|
||||
// where somebody ran `tea login` by hand knows the URL and holds a working token, and asking them to
|
||||
// retype it is asking for something the box can already see.
|
||||
const tea = instanceUrl ? await readTeaLogin(userId, instanceUrl) : await readAnyTeaLogin(userId);
|
||||
const osUser = await osUserFor(userId);
|
||||
|
||||
return Response.json({
|
||||
@@ -146,7 +150,8 @@ async function connectionState(userId: number): Promise<Response> {
|
||||
instanceConfigured: !!instanceUrl,
|
||||
isOwner: await isOwner(userId),
|
||||
// What tea already knows, so the page can say who you are without a round trip to Gitea.
|
||||
tea: tea ? { name: tea.name, user: tea.user, hasToken: tea.hasToken } : null,
|
||||
// `url` included so the form can offer it when the platform has no instance yet.
|
||||
tea: tea ? { name: tea.name, url: tea.url, user: tea.user, hasToken: tea.hasToken } : null,
|
||||
// Null means never provisioned an OS account, so there is nowhere to write a config. The page says
|
||||
// so rather than failing on save.
|
||||
canStoreToken: !!osUser || (await isOwner(userId)),
|
||||
@@ -199,8 +204,14 @@ async function handleConfig(req: Request, userId: number): Promise<Response> {
|
||||
// fails with the reason. Storing first and discovering later makes every downstream screen fail
|
||||
// mysteriously instead. For a member this also proves their token is valid against the shared
|
||||
// instance, which is the only thing that can be wrong on their side.
|
||||
// Setting the INSTANCE is its own step, and it must not demand a token: the owner names where Gitea
|
||||
// is first, and only then does the page ask for — or discover — a token for it. Probing with one
|
||||
// when there is none would refuse a perfectly good URL for the wrong reason.
|
||||
const current = token ? null : await getGiteaConfig(userId);
|
||||
const result = await probe({ id: existing?.id ?? 0, base, token: token ?? current?.token ?? null });
|
||||
const candidate = token ?? current?.token ?? null;
|
||||
const result = candidate
|
||||
? await probe({ id: existing?.id ?? 0, base, token: candidate })
|
||||
: await reachable(base);
|
||||
if (!result.ok) return bad(result.error ?? 'could not reach the instance');
|
||||
|
||||
// THE TOKEN GOES TO `tea`, NOT THE DATABASE.
|
||||
|
||||
Reference in New Issue
Block a user