Files
Egutierrez 0e3c5f5e84 feat: scaffold matrix_admin_panel v0.1.0 (issue 0163)
Wails + React + Mantine v7 admin panel for Matrix/Synapse. Replaces the
removed synapse-admin container. MAS OIDC PKCE login (loopback :8766) +
Synapse Admin API (users/rooms/sessions).

- MAS client: XSFD2SWA394DXRVJFTREAMY6J6 (public PKCE, no auth method).
- Backend: AdminService (Go) with Login/SetAdminToken/ListUsers/
  DeactivateUser/ResetUserPassword/ListRooms/DeleteRoom/GetUserDevices.
- Vendored helpers in internal/infra/ from registry:
  mas_oidc_loopback_go_infra, keyring_token_store_go_infra,
  synapse_admin_client_go_infra.
- Frontend: AppShell + sidebar tabs (Users/Rooms/Sessions). Sessions
  placeholder pending MAS admin API.
- Build verified: Linux + Windows.
2026-05-25 01:05:43 +02:00

47 lines
1.2 KiB
Go

package main
import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"time"
)
// whoami issues GET /_matrix/client/v3/account/whoami against the homeserver with the
// provided access_token. Used to resolve the canonical user_id post-login.
func whoami(ctx context.Context, homeserver, accessToken string) (string, string, error) {
if ctx == nil {
ctx = context.Background()
}
u, err := url.JoinPath(homeserver, "/_matrix/client/v3/account/whoami")
if err != nil {
return "", "", fmt.Errorf("joinpath: %w", err)
}
req, err := http.NewRequestWithContext(ctx, http.MethodGet, u, nil)
if err != nil {
return "", "", err
}
req.Header.Set("Authorization", "Bearer "+accessToken)
cl := &http.Client{Timeout: 15 * time.Second}
resp, err := cl.Do(req)
if err != nil {
return "", "", err
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
if resp.StatusCode != 200 {
return "", "", fmt.Errorf("whoami: %s: %s", resp.Status, body)
}
var out struct {
UserID string `json:"user_id"`
DeviceID string `json:"device_id"`
}
if err := json.Unmarshal(body, &out); err != nil {
return "", "", fmt.Errorf("whoami parse: %w", err)
}
return out.UserID, out.DeviceID, nil
}