package api import ( "github.com/vasyakrg/dns-autoresolver/internal/diff" "github.com/vasyakrg/dns-autoresolver/internal/store" ) type registerRequest struct { Email string `json:"email"` Password string `json:"password"` } type loginRequest struct { Email string `json:"email"` Password string `json:"password"` } // userResponse and projectResponse deliberately expose only id/email and // id/name — password_hash must never reach a client response. type userResponse struct { ID string `json:"id"` Email string `json:"email"` } type projectResponse struct { ID string `json:"id"` Name string `json:"name"` } type authResponse struct { User userResponse `json:"user"` Project projectResponse `json:"project"` } func toAuthResponse(u store.User, p store.Project) authResponse { return authResponse{ User: userResponse{ID: u.ID.String(), Email: u.Email}, Project: projectResponse{ID: p.ID.String(), Name: p.Name}, } } type applyRequest struct { Updates []string `json:"updates"` Prunes []string `json:"prunes"` } type recordView struct { Key string `json:"key"` Kind string `json:"kind"` Type string `json:"type"` Name string `json:"name"` Desired []string `json:"desired,omitempty"` Actual []string `json:"actual,omitempty"` ReadOnly bool `json:"readOnly"` } type changesetResponse struct { Updates []recordView `json:"updates"` Prunes []recordView `json:"prunes"` ReadOnly []recordView `json:"readOnly"` InSync int `json:"inSyncCount"` } func toRecordView(d diff.RecordDiff) recordView { rv := recordView{Key: d.Key(), Kind: string(d.Kind), Type: string(d.Type), Name: d.Name, ReadOnly: d.ReadOnly} if d.Desired != nil { rv.Desired = d.Desired.Values } if d.Actual != nil { rv.Actual = d.Actual.Values } return rv } func toChangesetResponse(cs diff.Changeset) changesetResponse { // Initialise the slices so an empty changeset (e.g. a zone that exactly // matches its template right after a snapshot) marshals to [] rather than // null — a nil slice becomes JSON null, which crashes clients that call // .length/.map on the field. resp := changesetResponse{ Updates: []recordView{}, Prunes: []recordView{}, ReadOnly: []recordView{}, } for _, d := range cs.Updates() { resp.Updates = append(resp.Updates, toRecordView(d)) } for _, d := range cs.Prunes() { resp.Prunes = append(resp.Prunes, toRecordView(d)) } for _, d := range cs.Diffs { if d.ReadOnly { resp.ReadOnly = append(resp.ReadOnly, toRecordView(d)) } if d.Kind == diff.InSync { resp.InSync++ } } return resp }