Go app for capturing and archiving HSA-eligible receipts: OIDC/PKCE auth against Authelia, SQLite storage with dual-write (filesystem + DB blob), mobile-first upload, and DB export. Adds AI receipt classification: a config.json catalog of people and categories (seeded into the DB on startup), a prompt builder that derives name-order/initial variants from the data (with same-surname ambiguity handling), and an Anthropic tool-use client behind POST /classify. Tests run against a mock endpoint; a live integration test is env-gated to the cheapest model. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
52 lines
1.3 KiB
Go
52 lines
1.3 KiB
Go
package auth
|
|
|
|
import (
|
|
"net/url"
|
|
"strings"
|
|
"testing"
|
|
|
|
"golang.org/x/oauth2"
|
|
)
|
|
|
|
func TestAuthorizeURL(t *testing.T) {
|
|
cfg := &oauth2.Config{
|
|
ClientID: "hsa-tracker",
|
|
RedirectURL: "https://hsa.maisym.com/callback",
|
|
Scopes: []string{"openid", "profile", "email", "groups"},
|
|
Endpoint: oauth2.Endpoint{
|
|
AuthURL: "https://auth.maisym.com/api/oidc/authorization",
|
|
TokenURL: "https://auth.maisym.com/api/oidc/token",
|
|
},
|
|
}
|
|
|
|
state := "test-state-value"
|
|
verifier := "test-verifier-value"
|
|
challenge := ChallengeS256(verifier)
|
|
|
|
rawURL := AuthorizeURL(cfg, state, challenge)
|
|
|
|
u, err := url.Parse(rawURL)
|
|
if err != nil {
|
|
t.Fatalf("AuthorizeURL returned invalid URL: %v", err)
|
|
}
|
|
q := u.Query()
|
|
|
|
if q.Get("state") != state {
|
|
t.Errorf("state = %q, want %q", q.Get("state"), state)
|
|
}
|
|
if q.Get("code_challenge") != challenge {
|
|
t.Errorf("code_challenge = %q, want %q", q.Get("code_challenge"), challenge)
|
|
}
|
|
if q.Get("code_challenge_method") != "S256" {
|
|
t.Errorf("code_challenge_method = %q, want S256", q.Get("code_challenge_method"))
|
|
}
|
|
if q.Get("response_type") != "code" {
|
|
t.Errorf("response_type = %q, want code", q.Get("response_type"))
|
|
}
|
|
scopes := q.Get("scope")
|
|
for _, s := range []string{"openid", "profile", "email", "groups"} {
|
|
if !strings.Contains(scopes, s) {
|
|
t.Errorf("scope %q missing from %q", s, scopes)
|
|
}
|
|
}
|
|
}
|