updates on the ai and agent and all thse things awith onboarding
This commit is contained in:
105
routes/routes_client_onboarding_test.go
Normal file
105
routes/routes_client_onboarding_test.go
Normal file
@@ -0,0 +1,105 @@
|
||||
package routes_test
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"doormile/config"
|
||||
"doormile/routes"
|
||||
"doormile/utils"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v2/middleware/recover"
|
||||
)
|
||||
|
||||
// Client onboarding's gate, over real HTTP. Only the configured owner login —
|
||||
// as Doormile staff with roleid 1 — reaches the handler; everyone else is
|
||||
// refused in middleware, before any database access.
|
||||
|
||||
const onboardingOwner = "admin@doormile.com"
|
||||
|
||||
var onboardingRoutes = []struct{ method, path, body string }{
|
||||
{http.MethodPost, "/api/v1/admin/clients/onboard", `{"companyname":"Acme"}`},
|
||||
{http.MethodGet, "/api/v1/admin/clients/onboarded", ""},
|
||||
{http.MethodGet, "/api/v1/admin/clients/cities", ""},
|
||||
{http.MethodPut, "/api/v1/admin/clients/5", `{"status":"Inactive"}`},
|
||||
{http.MethodDelete, "/api/v1/admin/clients/5", ""},
|
||||
}
|
||||
|
||||
func onboardingApp() *fiber.App {
|
||||
app := fiber.New()
|
||||
app.Use(recover.New())
|
||||
routes.RegisterRoutes(app, &config.Config{JWTSecret: jwtSecret, ClientOnboardingOwners: []string{onboardingOwner}})
|
||||
return app
|
||||
}
|
||||
|
||||
func consoleToken(t *testing.T, email string, roleID, tenantID int) string {
|
||||
t.Helper()
|
||||
tok, err := utils.GenerateToken(1, email, roleID, tenantID, 1, jwtSecret)
|
||||
if err != nil {
|
||||
t.Fatalf("mint token: %v", err)
|
||||
}
|
||||
return tok
|
||||
}
|
||||
|
||||
func TestClientOnboardingNeedsALogin(t *testing.T) {
|
||||
app := onboardingApp()
|
||||
for _, r := range onboardingRoutes {
|
||||
if code, _ := do(t, app, r.method, r.path, "", r.body); code != http.StatusUnauthorized {
|
||||
t.Errorf("%s %s with no token = %d, want 401", r.method, r.path, code)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientOnboardingRefusesEveryoneButTheOwner(t *testing.T) {
|
||||
app := onboardingApp()
|
||||
cases := []struct {
|
||||
name string
|
||||
token string
|
||||
}{
|
||||
{"another Doormile admin", consoleToken(t, "suriya@doormile.com", 1, 0)},
|
||||
{"owner email as a manager", consoleToken(t, onboardingOwner, 3, 0)},
|
||||
{"owner email as an executive", consoleToken(t, onboardingOwner, 4, 0)},
|
||||
{"owner email on a client tenant", consoleToken(t, onboardingOwner, 1, 7)},
|
||||
{"a client login", consoleToken(t, "ops@acme.example", 3, 7)},
|
||||
{"a miler", consoleToken(t, onboardingOwner, 5, 0)},
|
||||
{"a customer", consoleToken(t, onboardingOwner, 9, 0)},
|
||||
}
|
||||
for _, c := range cases {
|
||||
for _, r := range onboardingRoutes {
|
||||
code, body := do(t, app, r.method, r.path, c.token, r.body)
|
||||
if code != http.StatusForbidden {
|
||||
t.Errorf("%s: %s %s = %d, want 403", c.name, r.method, r.path, code)
|
||||
}
|
||||
if strings.Contains(body, onboardingOwner) {
|
||||
t.Errorf("%s: the refusal leaked the owner email: %s", c.name, body)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// With no owners configured, nobody gets in — not even admin@doormile.com.
|
||||
func TestClientOnboardingFailsClosedWithoutOwners(t *testing.T) {
|
||||
app := newApp() // config without ClientOnboardingOwners
|
||||
for _, r := range onboardingRoutes {
|
||||
if code, _ := do(t, app, r.method, r.path, consoleToken(t, onboardingOwner, 1, 0), r.body); code != http.StatusForbidden {
|
||||
t.Errorf("%s %s with no owners configured = %d, want 403", r.method, r.path, code)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The owner passes every gate. There is no database here, so the handler's
|
||||
// first query panics and recover answers 500 — proof that the route exists
|
||||
// and nothing in front of it refused. Email matching ignores case.
|
||||
func TestClientOnboardingOwnerPassesTheGate(t *testing.T) {
|
||||
app := onboardingApp()
|
||||
for _, email := range []string{onboardingOwner, "Admin@Doormile.com"} {
|
||||
tok := consoleToken(t, email, 1, 0)
|
||||
for _, r := range onboardingRoutes {
|
||||
if code, _ := do(t, app, r.method, r.path, tok, r.body); code == 401 || code == 403 || code == 404 {
|
||||
t.Errorf("owner %s %s %s = %d; a gate refused or the route is missing", email, r.method, r.path, code)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user