(c *gin.Context)
| 372 | req.DatabaseName = strings.TrimSpace(req.DatabaseName) |
| 373 | |
| 374 | // database_name becomes the org's managed hostname label |
| 375 | // (<database_name>.<managed-suffix>) and the dbname clients connect with, |
| 376 | // so a new or CHANGED name must be a routable single DNS label — a name |
| 377 | // with spaces or dots would store fine but leave the tenant reachable by |
| 378 | // no hostname. Grandfather exception: re-provisioning an existing org with |
| 379 | // its STORED name (the deprovision→re-provision recovery loop) sends a |
| 380 | // value that predates this rule — rejecting it would orphan a flow that |
| 381 | // worked until now and write nothing new anyway. The break-glass rename |
| 382 | // lives in the admin API (PUT /api/v1/orgs/:id). |
| 383 | if existing, err := h.store.GetOrg(orgID); err == nil && existing.DatabaseName == req.DatabaseName { |
| 384 | // Existing org re-provisioning with its stored (possibly |
| 385 | // pre-validation-rule) database name: nothing changes, allow it. |
| 386 | } else if err := configstore.ValidateDatabaseName(req.DatabaseName); err != nil { |
| 387 | c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) |
| 388 | return |
| 389 | } |
| 390 | |
| 391 | if req.MetadataStore == nil { |
| 392 | c.JSON(http.StatusBadRequest, gin.H{"error": "metadata_store is required"}) |
| 393 | return |
| 394 | } |
| 395 | |
| 396 | // Resolve the transitional default_team_id alias and team_id into one |
| 397 | // effective team. Both fields keep working — the alias goes away once the |
| 398 | // PostHog backend sends team_id — but disagreement is a caller bug. |
| 399 | if req.TeamID != 0 && req.DefaultTeamID != 0 && req.TeamID != req.DefaultTeamID { |
| 400 | c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("team_id (%d) and default_team_id (%d) disagree; send one, or the same value in both", req.TeamID, req.DefaultTeamID)}) |
| 401 | return |
| 402 | } |
| 403 | effectiveTeamID := req.DefaultTeamID |
| 404 | if req.TeamID != 0 { |
| 405 | effectiveTeamID = req.TeamID |
| 406 | } |
no test coverage detected