package main import ( "context" "data-terminal-cloud/internal/onboarding" "encoding/json" "errors" "fmt" "github.com/jackc/pgx/v5/pgxpool" "github.com/redis/go-redis/v9" "io" "os" "strings" "time" ) func main() { if err := run(); err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } } func secret(name string) (string, error) { if file := os.Getenv(name + "_FILE"); file != "" { b, e := os.ReadFile(file) if e != nil { return "", fmt.Errorf("read %s_FILE: %w", name, e) } return strings.TrimSpace(string(b)), nil } if v := os.Getenv(name); v != "" { return v, nil } return "", fmt.Errorf("missing %s", name) } func run() error { if len(os.Args) != 1 { return errors.New("customer-phone-account reads provisioning JSON from standard input") } var in struct { AccountKind string `json:"account_kind"` UserID string `json:"user_id"` Issuer string `json:"issuer"` Subject string `json:"subject"` Phone string `json:"phone_e164"` Password string `json:"password"` RequestID string `json:"request_id"` } raw, err := io.ReadAll(io.LimitReader(os.Stdin, 8193)) if err != nil { return err } if err = onboarding.StrictJSON(raw, &in); err != nil { return err } db, err := secret("DATABASE_URL") if err != nil { return err } master, err := secret("ONBOARDING_MASTER_KEY") if err != nil { return err } ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() pool, err := pgxpool.New(ctx, db) if err != nil { return errors.New("database configuration invalid") } defer pool.Close() r := redis.NewClient(&redis.Options{Addr: os.Getenv("REDIS_ADDR")}) defer r.Close() s, err := onboarding.NewService(pool, r, onboarding.Options{MasterKey: master, EntryURL: os.Getenv("ONBOARDING_ENTRY_URL")}) if err != nil { return err } provision := s.ProvisionCustomerPhone if in.AccountKind == "operator" { provision = s.ProvisionOperatorPhone } else if in.AccountKind != "" && in.AccountKind != "customer" { return errors.New("invalid account_kind") } created, err := provision(ctx, in.UserID, in.Issuer, in.Subject, in.Phone, in.Password, in.RequestID) if err != nil { return err } return json.NewEncoder(os.Stdout).Encode(map[string]any{"configured": true, "created": created, "user_id": in.UserID, "phone_masked": in.Phone[:len(in.Phone)-8] + "****" + in.Phone[len(in.Phone)-4:], "sms_verified": false}) }