Skip to content

Commit 5477978

Browse files
authored
Token runtime generation (#249)
* Token runtime generation * Fixing tests + clean up
1 parent aff9200 commit 5477978

File tree

4 files changed

+53
-52
lines changed

4 files changed

+53
-52
lines changed

.github/workflows/deploy.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ jobs:
3737
CAPY_PROJECT_ID: ${{ secrets.CAPY_PROJECT_ID }}
3838
CAPY_SERVER_REGION: ${{ secrets.CAPY_SERVER_REGION }}
3939
CAPY_THERAPY_SESSION_URL: ${{ secrets.CAPY_THERAPY_SESSION_URL }}
40-
CAPY_AGENT_TOKEN: ${{ secrets.CAPY_AGENT_TOKEN }}
4140
shell: bash
4241

4342
create-tag:

internal/app/therapy.go

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package app
22

33
import (
44
"bytes"
5+
"context"
56
"encoding/json"
67
"fmt"
78
"io"
@@ -12,15 +13,19 @@ import (
1213
"time"
1314

1415
"github.com/google/uuid"
16+
"google.golang.org/api/idtoken"
1517
)
1618

19+
// Allow tests to inject a custom HTTP client builder.
20+
var newTherapyHTTPClient = buildTherapyHTTPClient
21+
1722
// Internal configuration for therapy session calls
1823
type therapyConfig struct {
1924
baseURL string
20-
token string
2125
userID string
2226
sessionID string
2327
locale string
28+
ctx context.Context
2429
}
2530

2631
// Start therapy session
@@ -39,7 +44,11 @@ func callTherapySessionEndpoint(text string, session *Session) *string {
3944
return nil
4045
}
4146

42-
client := buildTherapyHTTPClient()
47+
client, err := newTherapyHTTPClient(cfg.ctx, cfg.baseURL)
48+
if err != nil {
49+
log.Printf("[TherapySession] failed to create authenticated client: %v", err)
50+
return nil
51+
}
4352

4453
if !initTherapySession(client, cfg) {
4554
return nil
@@ -58,9 +67,15 @@ func relayTherapyMessage(text string, session *Session) {
5867
}
5968
}
6069

61-
// Build an HTTP client configured for therapy session calls
62-
func buildTherapyHTTPClient() *http.Client {
63-
return &http.Client{Timeout: 120 * time.Second}
70+
// Build an HTTP client configured with ID token authentication for therapy session calls
71+
func buildTherapyHTTPClient(ctx context.Context, targetURL string) (*http.Client, error) {
72+
client, err := idtoken.NewClient(ctx, targetURL)
73+
if err != nil {
74+
return nil, fmt.Errorf("failed to create ID token client: %w", err)
75+
}
76+
// Set timeout on the client
77+
client.Timeout = 120 * time.Second
78+
return client, nil
6479
}
6580

6681
// Build configuration from environment and session; ensures a session ID exists
@@ -71,12 +86,6 @@ func buildTherapyConfig(session *Session) *therapyConfig {
7186
return nil
7287
}
7388

74-
token := os.Getenv("CAPY_AGENT_TOKEN")
75-
if token == "" {
76-
log.Printf("[TherapySession] missing CAPY_AGENT_TOKEN")
77-
return nil
78-
}
79-
8089
if session.User.TherapySessionId == nil || *session.User.TherapySessionId == "" {
8190
newID := uuid.NewString()
8291
session.User.TherapySessionId = &newID
@@ -88,10 +97,10 @@ func buildTherapyConfig(session *Session) *therapyConfig {
8897

8998
return &therapyConfig{
9099
baseURL: baseURL,
91-
token: token,
92100
userID: userID,
93101
sessionID: sessionID,
94102
locale: locale,
103+
ctx: context.Background(),
95104
}
96105
}
97106

@@ -110,7 +119,7 @@ func initTherapySession(client *http.Client, cfg *therapyConfig) bool {
110119
log.Printf("[TherapySession] init request build error: %v", err)
111120
return false
112121
}
113-
req.Header.Set("Authorization", "Bearer "+cfg.token)
122+
// ID token client automatically adds Authorization header
114123
req.Header.Set("Content-Type", "application/json")
115124

116125
resp, err := client.Do(req)
@@ -156,7 +165,6 @@ func sendTherapyMessage(client *http.Client, cfg *therapyConfig, text string) *s
156165
log.Printf("[TherapySession] run request build error: %v", err)
157166
return nil
158167
}
159-
req.Header.Set("Authorization", "Bearer "+cfg.token)
160168
req.Header.Set("Content-Type", "application/json")
161169

162170
resp, err := client.Do(req)

internal/app/therapy_test.go

Lines changed: 30 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
package app
22

33
import (
4-
"context"
5-
"net/http"
6-
"net/http/httptest"
7-
"os"
8-
"testing"
9-
"time"
4+
"context"
5+
"net/http"
6+
"net/http/httptest"
7+
"testing"
8+
"time"
109

11-
"strings"
10+
"strings"
1211

13-
"github.com/capymind/internal/database"
12+
"github.com/capymind/internal/database"
1413
)
1514

1615
func TestStartTherapySession(t *testing.T) {
@@ -56,11 +55,6 @@ func TestEndTherapySession(t *testing.T) {
5655
func TestRelayTherapyMessage(t *testing.T) {
5756
// Create a fake therapy session backend implementing both init and run endpoints
5857
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
59-
token := r.Header.Get("Authorization")
60-
if token != "Bearer test-token" {
61-
http.Error(w, "unauthorized", http.StatusUnauthorized)
62-
return
63-
}
6458
switch {
6559
case r.Method == http.MethodPost && strings.HasPrefix(r.URL.Path, "/apps/capymind_agent/users/u1/sessions/"):
6660
// Session init endpoint
@@ -79,10 +73,14 @@ func TestRelayTherapyMessage(t *testing.T) {
7973
}
8074
}))
8175
defer ts.Close()
82-
os.Setenv("CAPY_THERAPY_SESSION_URL", ts.URL)
83-
os.Setenv("CAPY_AGENT_TOKEN", "test-token")
84-
defer os.Unsetenv("CAPY_THERAPY_SESSION_URL")
85-
defer os.Unsetenv("CAPY_AGENT_TOKEN")
76+
t.Setenv("CAPY_THERAPY_SESSION_URL", ts.URL)
77+
78+
// Inject simple HTTP client without Google auth for tests
79+
originalBuilder := newTherapyHTTPClient
80+
newTherapyHTTPClient = func(ctx context.Context, targetURL string) (*http.Client, error) {
81+
return &http.Client{Timeout: 5 * time.Second}, nil
82+
}
83+
defer func() { newTherapyHTTPClient = originalBuilder }()
8684

8785
ctx := context.Background()
8886
locale := "en"
@@ -91,7 +89,7 @@ func TestRelayTherapyMessage(t *testing.T) {
9189

9290
relayTherapyMessage("hi", session)
9391

94-
if len(session.Job.Output) == 0 {
92+
if len(session.Job.Output) == 0 {
9593
t.Fatalf("expected at least one output")
9694
}
9795
if session.Job.Output[0].TextID != "Hello, I'm here for you." {
@@ -116,11 +114,6 @@ func TestHandleSession_AutoEndWhenExpired(t *testing.T) {
116114
func TestHandleSession_ForwardDuringActive(t *testing.T) {
117115
// Fake backend implementing both init and run endpoints
118116
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
119-
token := r.Header.Get("Authorization")
120-
if token != "Bearer test-token" {
121-
http.Error(w, "unauthorized", http.StatusUnauthorized)
122-
return
123-
}
124117
switch {
125118
case r.Method == http.MethodPost && strings.HasPrefix(r.URL.Path, "/apps/capymind_agent/users/u1/sessions/"):
126119
w.WriteHeader(http.StatusOK)
@@ -137,10 +130,13 @@ func TestHandleSession_ForwardDuringActive(t *testing.T) {
137130
}
138131
}))
139132
defer ts.Close()
140-
os.Setenv("CAPY_THERAPY_SESSION_URL", ts.URL)
141-
os.Setenv("CAPY_AGENT_TOKEN", "test-token")
142-
defer os.Unsetenv("CAPY_THERAPY_SESSION_URL")
143-
defer os.Unsetenv("CAPY_AGENT_TOKEN")
133+
t.Setenv("CAPY_THERAPY_SESSION_URL", ts.URL)
134+
135+
originalBuilder := newTherapyHTTPClient
136+
newTherapyHTTPClient = func(ctx context.Context, targetURL string) (*http.Client, error) {
137+
return &http.Client{Timeout: 5 * time.Second}, nil
138+
}
139+
defer func() { newTherapyHTTPClient = originalBuilder }()
144140

145141
ctx := context.Background()
146142
future := time.Now().Add(5 * time.Minute)
@@ -160,11 +156,6 @@ func TestHandleSession_ForwardDuringActive(t *testing.T) {
160156
func TestRelayTherapyMessage_ExistingSessionContinues(t *testing.T) {
161157
// Fake backend: init returns 400 Session already exists; run_sse returns a reply
162158
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
163-
token := r.Header.Get("Authorization")
164-
if token != "Bearer test-token" {
165-
http.Error(w, "unauthorized", http.StatusUnauthorized)
166-
return
167-
}
168159
switch {
169160
case r.Method == http.MethodPost && strings.HasPrefix(r.URL.Path, "/apps/capymind_agent/users/u1/sessions/"):
170161
w.WriteHeader(http.StatusBadRequest)
@@ -181,10 +172,13 @@ func TestRelayTherapyMessage_ExistingSessionContinues(t *testing.T) {
181172
}
182173
}))
183174
defer ts.Close()
184-
os.Setenv("CAPY_THERAPY_SESSION_URL", ts.URL)
185-
os.Setenv("CAPY_AGENT_TOKEN", "test-token")
186-
defer os.Unsetenv("CAPY_THERAPY_SESSION_URL")
187-
defer os.Unsetenv("CAPY_AGENT_TOKEN")
175+
t.Setenv("CAPY_THERAPY_SESSION_URL", ts.URL)
176+
177+
originalBuilder := newTherapyHTTPClient
178+
newTherapyHTTPClient = func(ctx context.Context, targetURL string) (*http.Client, error) {
179+
return &http.Client{Timeout: 5 * time.Second}, nil
180+
}
181+
defer func() { newTherapyHTTPClient = originalBuilder }()
188182

189183
ctx := context.Background()
190184
locale := "en"

scripts/deploy_functions.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ source ./scripts/get_version.sh
1717
APP_VERSION=$(get_version)
1818

1919
# Set environment variables
20-
ENV_PARAMS=("CAPY_PROJECT_ID=$CAPY_PROJECT_ID" "CAPY_SERVER_REGION=$CAPY_SERVER_REGION" "CLOUD=true" "APP_VERSION=$APP_VERSION" "CAPY_THERAPY_SESSION_URL=$CAPY_THERAPY_SESSION_URL" "CAPY_AGENT_TOKEN=$CAPY_AGENT_TOKEN")
20+
ENV_PARAMS=("CAPY_PROJECT_ID=$CAPY_PROJECT_ID" "CAPY_SERVER_REGION=$CAPY_SERVER_REGION" "CLOUD=true" "APP_VERSION=$APP_VERSION" "CAPY_THERAPY_SESSION_URL=$CAPY_THERAPY_SESSION_URL")
2121
ENV_VARS=""
2222
for PARAM in "${ENV_PARAMS[@]}"; do
2323
ENV_VARS+="$PARAM,"

0 commit comments

Comments
 (0)