Gonçalo Rodrigues 91796c9fb9 test(finance): expand unit test coverage from ~55% to 64.7% (#34)
* infra(terraform): manage finance session secret via random_password

Replace the hand-rolled variable (with insecure hardcoded default) with a
random_password resource so Terraform auto-generates a 48-char secret and
owns the finance-api-secrets k8s Secret lifecycle.

To rotate: terraform taint random_password.finance_session_secret && terraform apply

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(finance): active sessions panel + account deletion with full data purge

Sessions panel (/account):
- AuthSession now stores IPAddress and Device (browser + OS hint)
  populated from X-Forwarded-For / User-Agent on every login
- Lists all active sessions with device icon, IP, sign-in time
- Current session badge ("This device") — cannot be self-revoked
- DELETE /sessions/:id revokes any other session (user-scoped)

Account deletion (POST /account/delete):
- Password accounts require password confirmation
- OAuth accounts require typing email address to confirm
- deleteAllUserData purges all 12 finance collections + user record
  in a single call: accounts, categories, transactions, trades,
  ticker_mappings, goals, import_schedules, properties, loans,
  permissions, households, sessions → then the user itself
- Clears session cookie and redirects to login with success message

Infrastructure:
- findAuthUserByID added to store + storeIface
- getSessionsByUserID, deleteSessionForUser added to store + storeIface
- contains() added to template FuncMap
- accountTmpl registered; GET /account, POST /account/delete,
  DELETE /sessions/:id routes wired
- 🔐 nav icon links to /account page
- Full EN + PT i18n coverage for all new strings

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test(finance): expand unit test coverage from ~55% to 64.7%

- Add handler_coverage_test.go (~3300 lines) covering auth flows,
  org request lifecycle, CSV bank import, property/loan views,
  fiscal year operations, session management, and cross-handler
  consistency (values shown on one page match actions on others)
- Add handler_org_test.go (~1800 lines) covering the full org
  handler surface: teams, members, invites, events, budget lines,
  tx requests (all status transitions), ledger, analysis, and reports
- Extend handler_test.go mockStore with: properties/loans slice fields,
  authUsers map with session-aware lookup, household field, org maps,
  and updateFiscalYearStatusErr for error-path testing
- Fix nav bar: Business and Account links now show active state and
  use i18n keys (removes hardcoded emoji); add account key to en/pt locales

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Gonçalo Rodrigues <guga@Goncalos-MacBook-Pro.local>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 15:07:29 +01:00

33 lines
1.0 KiB
HCL

# Session secret is auto-generated and stored in Terraform state (gitignored).
# To rotate: terraform taint random_password.finance_session_secret && terraform apply
resource "random_password" "finance_session_secret" {
length = 48
special = false # alphanumeric only — safe as an env var value
}
variable "finance_google_client_id" {
description = "Google OAuth client ID for finance-api (optional)"
type = string
default = ""
sensitive = false
}
variable "finance_google_client_secret" {
description = "Google OAuth client secret for finance-api (optional)"
type = string
default = ""
sensitive = true
}
resource "kubernetes_secret" "finance_api" {
metadata {
name = "finance-api-secrets"
namespace = kubernetes_namespace.domains["finance"].metadata[0].name
}
data = {
SESSION_SECRET = random_password.finance_session_secret.result
GOOGLE_CLIENT_ID = var.finance_google_client_id
GOOGLE_CLIENT_SECRET = var.finance_google_client_secret
}
}