fix(store,api): идемпотентный import (UNIQUE+ON CONFLICT) + PATCH привязки шаблона к домену

This commit is contained in:
2026-07-03 15:24:08 +07:00
parent 2aca92d070
commit ddab6e2162
9 changed files with 364 additions and 1 deletions
+76
View File
@@ -35,6 +35,8 @@ type mockTenantStore struct {
importDomains []store.Domain
importDomainsErr error
importCalled bool
setDomainTemplateErr error
}
func (m *mockTenantStore) CreateAccount(_ context.Context, projectID uuid.UUID, prov, secretEnc, comment string) (store.Account, error) {
@@ -98,6 +100,21 @@ func (m *mockTenantStore) ListDomains(context.Context, uuid.UUID) ([]store.Domai
func (m *mockTenantStore) DeleteDomain(context.Context, uuid.UUID, uuid.UUID) error { return nil }
func (m *mockTenantStore) SetDomainTemplate(_ context.Context, domainID, projectID uuid.UUID, templateID *uuid.UUID) (store.Domain, error) {
if m.setDomainTemplateErr != nil {
return store.Domain{}, m.setDomainTemplateErr
}
for i, d := range m.domains {
if d.ID == domainID {
m.domains[i].TemplateID = templateID
return m.domains[i], nil
}
}
d := store.Domain{ID: domainID, ProjectID: projectID, TemplateID: templateID}
m.domains = append(m.domains, d)
return d, nil
}
func (m *mockTenantStore) ImportDomains(_ context.Context, projectID, accountID uuid.UUID, zones []provider.Zone) ([]store.Domain, error) {
m.importCalled = true
if m.importDomainsErr != nil {
@@ -463,6 +480,65 @@ func TestCreateDomain_ValidTemplateInProject(t *testing.T) {
}
}
// --- domain template binding (import -> check loop) ---
func TestSetDomainTemplate_ValidTemplateId(t *testing.T) {
a, ts := newTenantTestAPI()
domID := uuid.New()
tplID := uuid.New()
ts.domains = []store.Domain{{ID: domID, ZoneName: "example.com", ZoneID: "z1"}}
router := NewRouter(a)
body := `{"templateId":"` + tplID.String() + `"}`
req := httptest.NewRequest(http.MethodPatch, "/api/v1/projects/"+testPID+"/domains/"+domID.String(), strings.NewReader(body))
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Fatalf("expected 200, got %d body %s", w.Code, w.Body.String())
}
var resp domainResponse
if err := json.Unmarshal(w.Body.Bytes(), &resp); err != nil {
t.Fatal(err)
}
if resp.TemplateID == nil || *resp.TemplateID != tplID.String() {
t.Fatalf("unexpected response: %+v", resp)
}
}
func TestSetDomainTemplate_BadTemplateUUID(t *testing.T) {
a, ts := newTenantTestAPI()
domID := uuid.New()
ts.domains = []store.Domain{{ID: domID}}
router := NewRouter(a)
body := `{"templateId":"not-a-uuid"}`
req := httptest.NewRequest(http.MethodPatch, "/api/v1/projects/"+testPID+"/domains/"+domID.String(), strings.NewReader(body))
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
if w.Code != http.StatusBadRequest {
t.Fatalf("expected 400, got %d body %s", w.Code, w.Body.String())
}
}
func TestSetDomainTemplate_TemplateNotFound(t *testing.T) {
a, ts := newTenantTestAPI()
domID := uuid.New()
ts.domains = []store.Domain{{ID: domID}}
ts.setDomainTemplateErr = errors.New("template not found in project")
router := NewRouter(a)
body := `{"templateId":"` + uuid.New().String() + `"}`
req := httptest.NewRequest(http.MethodPatch, "/api/v1/projects/"+testPID+"/domains/"+domID.String(), strings.NewReader(body))
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
if w.Code != http.StatusNotFound {
t.Fatalf("expected 404, got %d body %s", w.Code, w.Body.String())
}
}
func TestDeleteDomain_BadUUID(t *testing.T) {
a, _ := newTenantTestAPI()
router := NewRouter(a)