refactor(renderer)!: drop the API token from the internal renderer

The renderer now runs only on the compose network with no published port
or domain, so a shared bearer token adds nothing. The renderer no longer
checks Authorization or requires API_TOKEN in production, and the bot no
longer sends a token.

BREAKING CHANGE: WHEELOFNAMES_API_TOKEN and the renderer's API_TOKEN are
removed. Never publish the renderer's port: its API is unauthenticated.
This commit is contained in:
tiennm99 committed 2026-10-03 11:45:26 +07:00
1 parent 3130f5ec36
commit 2ec4a2b371
19 files changed
+30 -154

No files matched your search

@@ -67,7 +67,6 @@ func TestGacha_UsesRemoteAPIWhenConfigured(t *testing.T) {
}))
defer server.Close()
t.Setenv(wheelOfNamesAPIURLEnv, server.URL+"/api/gif")
t.Setenv(wheelOfNamesAPITokenEnv, "remote-token")
rb := installRandom(t, 999)
rb.Bot.ProcessUpdate(context.Background(), testutil.NewPrivateMessage(7, "/gacha 4* Pho"))
@@ -75,8 +74,8 @@ func TestGacha_UsesRemoteAPIWhenConfigured(t *testing.T) {
if gotPath != "/api/gacha" {
t.Fatalf("path = %q, want /api/gacha", gotPath)
}
if gotAuthorization != "Bearer remote-token" {
t.Fatalf("Authorization = %q, want bearer token", gotAuthorization)
if gotAuthorization != "" {
t.Fatalf("Authorization = %q, want none", gotAuthorization)
}
want := gachaAPIRequest{Label: "Pho", Rarity: 4, FPS: gachaRemoteFPS, Width: gachaRemoteWidth}
if got != want {
+2 -4
View File
@@ -132,7 +132,6 @@ func TestWheelOfNames_UsesRemoteAPIWhenConfigured(t *testing.T) {
}))
defer server.Close()
t.Setenv(wheelOfNamesAPIURLEnv, server.URL+"/api/gif")
t.Setenv(wheelOfNamesAPITokenEnv, "remote-token")
rb := installRandom(t, 999)
rb.Bot.ProcessUpdate(context.Background(), testutil.NewPrivateMessage(7, "/wheelofnames Alice, Bob, Carol"))
@@ -140,8 +139,8 @@ func TestWheelOfNames_UsesRemoteAPIWhenConfigured(t *testing.T) {
if calls != 1 {
t.Fatalf("remote calls = %d, want 1", calls)
}
if gotAuthorization != "Bearer remote-token" {
t.Fatalf("Authorization = %q, want bearer token", gotAuthorization)
if gotAuthorization != "" {
t.Fatalf("Authorization = %q, want none", gotAuthorization)
}
if !slices.Equal(got.Options, []string{"Alice", "Bob", "Carol"}) {
t.Fatalf("options = %#v, want parsed options", got.Options)
@@ -193,7 +192,6 @@ func TestWheelOfNames_RemoteFailureFallsBackToRandomReply(t *testing.T) {
}))
defer server.Close()
t.Setenv(wheelOfNamesAPIURLEnv, server.URL+"/api/gif")
t.Setenv(wheelOfNamesAPITokenEnv, "remote-token")
rb := installRandom(t, 999)
rb.Bot.ProcessUpdate(context.Background(), testutil.NewPrivateMessage(7, "/wheelofnames Alice"))
@@ -17,10 +17,10 @@ import (
const (
// The standard renderer is the renderer/ service in this repository, wired
// in by compose.yml. Operators may point this to any service that
// in by compose.yml and reachable only on the compose network, so requests
// carry no credentials. Operators may point this to any service that
// implements the same /api/gif contract.
wheelOfNamesAPIURLEnv = "WHEELOFNAMES_API_URL"
wheelOfNamesAPITokenEnv = "WHEELOFNAMES_API_TOKEN"
wheelOfNamesAPIURLEnv = "WHEELOFNAMES_API_URL"
wheelRemoteDurationMs = 6000
wheelRemoteHoldMs = 1000
@@ -35,9 +35,8 @@ const (
var errWheelAPINotConfigured = errors.New("wheelofnames api not configured")
type wheelAPIClient struct {
HTTP *http.Client
URL string
Token string
HTTP *http.Client
URL string
}
type wheelAPIRequest struct {
@@ -59,8 +58,7 @@ type wheelAnimation struct {
func newWheelAPIClientFromEnv() wheelAPIClient {
return wheelAPIClient{
URL: strings.TrimSpace(os.Getenv(wheelOfNamesAPIURLEnv)),
Token: strings.TrimSpace(os.Getenv(wheelOfNamesAPITokenEnv)),
URL: strings.TrimSpace(os.Getenv(wheelOfNamesAPIURLEnv)),
}
}
@@ -102,9 +100,6 @@ func (c wheelAPIClient) post(ctx context.Context, endpoint *url.URL, body []byte
}
req.Header.Set("Accept", mediaType)
req.Header.Set("Content-Type", "application/json")
if c.Token != "" {
req.Header.Set("Authorization", "Bearer "+c.Token)
}
resp, err := c.httpClient().Do(req)
if err != nil {
@@ -14,7 +14,6 @@ import (
func TestWheelAPIClient_RenderValidRequest(t *testing.T) {
var got wheelAPIRequest
var gotAccept string
var gotAuthorization string
var gotContentType string
var gotMethod string
var gotPath string
@@ -22,7 +21,6 @@ func TestWheelAPIClient_RenderValidRequest(t *testing.T) {
gotMethod = r.Method
gotPath = r.URL.Path
gotAccept = r.Header.Get("Accept")
gotAuthorization = r.Header.Get("Authorization")
gotContentType = r.Header.Get("Content-Type")
if err := json.NewDecoder(r.Body).Decode(&got); err != nil {
t.Errorf("Decode request body: %v", err)
@@ -33,9 +31,8 @@ func TestWheelAPIClient_RenderValidRequest(t *testing.T) {
defer server.Close()
client := wheelAPIClient{
HTTP: server.Client(),
URL: server.URL + "/api/gif",
Token: "secret-token",
HTTP: server.Client(),
URL: server.URL + "/api/gif",
}
data, err := client.Render(context.Background(), []string{"alice", "bob", "carol"}, 1)
if err != nil {
@@ -56,9 +53,6 @@ func TestWheelAPIClient_RenderValidRequest(t *testing.T) {
if gotContentType != "application/json" {
t.Fatalf("Content-Type = %q, want application/json", gotContentType)
}
if gotAuthorization != "Bearer secret-token" {
t.Fatalf("Authorization = %q, want bearer token", gotAuthorization)
}
if !slices.Equal(got.Options, []string{"alice", "bob", "carol"}) {
t.Fatalf("options = %#v, want original options", got.Options)
}
@@ -68,7 +62,8 @@ func TestWheelAPIClient_RenderValidRequest(t *testing.T) {
assertWheelRemoteDefaults(t, got)
}
func TestWheelAPIClient_RenderWithoutTokenOmitsAuthorization(t *testing.T) {
// The renderer is internal to the compose network; the bot sends no credentials.
func TestWheelAPIClient_RenderSendsNoAuthorization(t *testing.T) {
var gotAuthorization string
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
gotAuthorization = r.Header.Get("Authorization")