func (h *DomainHandler) Put(w http.ResponseWriter, r *http.Request) { // We need to set the FQDN in the domain request object because it is sent only in the // URI and not in the domain request body to avoid information redudancy h.Request.FQDN = h.GetFQDN() var err error if h.domain, err = protocol.Merge(h.domain, h.Request); err != nil { messageId := "" switch err { case model.ErrInvalidFQDN: messageId = "invalid-fqdn" case protocol.ErrInvalidDNSKEY: messageId = "invalid-dnskey" case protocol.ErrInvalidDSAlgorithm: messageId = "invalid-ds-algorithm" case protocol.ErrInvalidDSDigestType: messageId = "invalid-ds-digest-type" case protocol.ErrInvalidIP: messageId = "invalid-ip" case protocol.ErrInvalidLanguage: messageId = "invalid-language" } if len(messageId) == 0 { log.Println("Error while merging domain objects for create or "+ "update operation. Details:", err) w.WriteHeader(http.StatusInternalServerError) } else { if err := h.MessageResponse(messageId, r.URL.RequestURI()); err == nil { w.WriteHeader(http.StatusBadRequest) } else { log.Println("Error while writing response. Details:", err) w.WriteHeader(http.StatusInternalServerError) } } return } domainDAO := dao.DomainDAO{ Database: h.GetDatabase(), } if err := domainDAO.Save(&h.domain); err != nil { if strings.Index(err.Error(), "duplicate key error index") != -1 { if err := h.MessageResponse("conflict", r.URL.RequestURI()); err == nil { w.WriteHeader(http.StatusConflict) } else { log.Println("Error while writing response. Details:", err) w.WriteHeader(http.StatusInternalServerError) } } else { log.Println("Error while saving domain object for create or "+ "update operation. Details:", err) w.WriteHeader(http.StatusInternalServerError) } return } w.Header().Add("ETag", h.GetETag()) w.Header().Add("Last-Modified", h.GetLastModifiedAt().Format(time.RFC1123)) if h.domain.Revision == 1 { w.Header().Add("Location", "/domain/"+h.domain.FQDN) w.WriteHeader(http.StatusCreated) } else { w.WriteHeader(http.StatusNoContent) } }
// Put is responsable for checking a domain object on-the-fly without persisting in // database, useful for pre-registration validations in the registry func (h *DomainVerificationHandler) Put(w http.ResponseWriter, r *http.Request) { // We need to set the FQDN in the domain request object because it is sent only in the // URI and not in the domain request body to avoid information redudancy h.Request.FQDN = h.GetFQDN() var domain model.Domain var err error if domain, err = protocol.Merge(domain, h.Request); err != nil { messageId := "" switch err { case protocol.ErrInvalidDNSKEY: messageId = "invalid-dnskey" case protocol.ErrInvalidDSAlgorithm: messageId = "invalid-ds-algorithm" case protocol.ErrInvalidDSDigestType: messageId = "invalid-ds-digest-type" case protocol.ErrInvalidIP: messageId = "invalid-ip" case protocol.ErrInvalidLanguage: messageId = "invalid-language" } if len(messageId) == 0 { log.Println("Error while merging domain objects for domain verification "+ "operation. Details:", err) w.WriteHeader(http.StatusInternalServerError) } else { if err := h.MessageResponse(messageId, r.URL.RequestURI()); err == nil { w.WriteHeader(http.StatusBadRequest) } else { log.Println("Error while writing response. Details:", err) w.WriteHeader(http.StatusInternalServerError) } } return } scan.ScanDomain(&domain) // As we alredy did the scan, if the domain is registered in the system, we update it for this // results. This also gives a more intuitive design for when the user wants to force a check a // specific domain in the Shelter system domainDAO := dao.DomainDAO{ Database: h.GetDatabase(), } if dbDomain, err := domainDAO.FindByFQDN(domain.FQDN); err == nil { update := true // Check if we have the same nameservers, and if so update the last status if len(dbDomain.Nameservers) == len(domain.Nameservers) { for i := range dbDomain.Nameservers { dbNameserver := dbDomain.Nameservers[i] nameserver := domain.Nameservers[i] if dbNameserver.Host == nameserver.Host && dbNameserver.IPv4.Equal(nameserver.IPv4) && dbNameserver.IPv6.Equal(nameserver.IPv6) { dbDomain.Nameservers[i].ChangeStatus(nameserver.LastStatus) } else { update = false break } } } else { update = false } // Check if we have the same DS set, and if so update the last status if len(dbDomain.DSSet) == len(domain.DSSet) { for i := range dbDomain.DSSet { dbDS := dbDomain.DSSet[i] ds := domain.DSSet[i] if dbDS.Keytag == ds.Keytag && dbDS.Algorithm == ds.Algorithm && dbDS.DigestType == ds.DigestType && dbDS.Digest == ds.Digest { dbDomain.DSSet[i].ChangeStatus(ds.LastStatus) } else { update = false break } } } else { update = false } if update { // We don't care about errors resulted here, because the main idea of this service is to scan // a domaion, not persist the results domainDAO.Save(&dbDomain) } } w.WriteHeader(http.StatusOK) domainResponse := protocol.ToDomainResponse(domain, false) h.Response = &domainResponse }