Ejemplo n.º 1
0
func ahCronSearchHandler(c appengine.Context, w http.ResponseWriter, r *http.Request) {
	start := time.Now()
	d := make(ContentData)

	var nut gonuts.Nut
	for i := datastore.NewQuery("Nut").Run(c); ; {
		_, err := i.Next(&nut)
		if err == datastore.Done {
			break
		}
		if err == nil {
			err = gonuts.AddToSearchIndex(c, &nut)
		}
		if err != nil {
			gonuts.LogError(c, err)
			ServeJSONError(w, http.StatusInternalServerError, err, d)
			return
		}
	}

	m := fmt.Sprintf("Search index updated in %d seconds.", time.Since(start)/time.Second)
	c.Infof("%s", m)
	d["Message"] = m
	ServeJSON(w, http.StatusOK, d)
	return
}
Ejemplo n.º 2
0
func nutCreateHandler(c appengine.Context, w http.ResponseWriter, r *http.Request) {
	d := make(ContentData)
	ct := r.Header.Get("Content-Type")
	putNut := ct == "application/zip"

	if !putNut {
		err := fmt.Errorf(`Unexpected Content-Type %q, should be "application/zip".`, ct)
		ServeJSONError(w, http.StatusNotAcceptable, err, d)
		return
	}

	vendor := r.URL.Query().Get(":vendor")
	name := r.URL.Query().Get(":name")
	ver := r.URL.Query().Get(":version")

	if vendor == "" || !nutp.VendorRegexp.MatchString(vendor) || name == "" || (ver != "" && !nutp.VersionRegexp.MatchString(ver)) {
		err := fmt.Errorf("Invalid vendor %q, name %q or version %q.", vendor, name, ver)
		ServeJSONError(w, http.StatusBadRequest, err, d)
		return
	}

	// extract token from request
	token := r.URL.Query().Get("token")
	if token == "" {
		ServeJSONError(w, http.StatusForbidden, fmt.Errorf("Can't find 'token' in get parameters."), d)
		return
	}

	// find user by token
	q := datastore.NewQuery("User").KeysOnly().Filter("Token=", token)
	userKeys, err := q.Limit(2).GetAll(c, nil)
	if err != nil || len(userKeys) != 1 {
		if err == nil || err == datastore.ErrNoSuchEntity {
			err = fmt.Errorf("Can't find user with token %q.", token)
		}
		ServeJSONError(w, http.StatusForbidden, err, d)
		return
	}
	userID := userKeys[0].StringID()

	// user should belong to vendor
	v := gonuts.Vendor{}
	err = datastore.Get(c, gonuts.VendorKey(c, vendor), &v)
	if err == datastore.ErrNoSuchEntity {
		err = fmt.Errorf("Can't find vendor %q.", vendor)
		ServeJSONError(w, http.StatusNotFound, err, d)
		return
	}
	if err != nil {
		ServeJSONError(w, http.StatusInternalServerError, err, d)
		return
	}
	found := false
	for _, id := range v.UserStringID {
		if id == userID {
			found = true
			break
		}
	}
	if !found {
		err = fmt.Errorf("You don't have publish access to vendor %q.", vendor)
		ServeJSONError(w, http.StatusForbidden, err, d)
		return
	}

	// nut version should not exist
	nutKey := gonuts.NutKey(c, vendor, name)
	nut := gonuts.Nut{Vendor: vendor, Name: name}
	versionKey := gonuts.VersionKey(c, vendor, name, ver)
	version := gonuts.Version{Vendor: vendor, Name: name, Version: ver, CreatedAt: time.Now()}
	err = datastore.Get(c, versionKey, &version)
	if err != nil && err != datastore.ErrNoSuchEntity {
		ServeJSONError(w, http.StatusInternalServerError, err, d)
		return
	}
	if err == nil {
		ServeJSONError(w, http.StatusConflict, fmt.Errorf("Nut %s/%s version %s already exists.", vendor, name, ver), d)
		return
	}

	// read nut from request body
	nf := new(nutp.NutFile)
	b, err := ioutil.ReadAll(r.Body)
	if err == nil {
		_, err = nf.ReadFrom(bytes.NewReader(b))
	}
	if err != nil {
		ServeJSONError(w, http.StatusBadRequest, err, d)
		return
	}
	nut.Doc = nf.Doc
	version.Doc = nf.Doc
	version.Homepage = nf.Homepage
	version.VersionNum = nf.Version.Major*1000000 + nf.Version.Minor*1000 + nf.Version.Patch // for sorting

	// check vendor, name and version match
	if nf.Vendor != vendor || nf.Name != name || nf.Version.String() != ver {
		err = fmt.Errorf("Nut vendor %q, name %q and version %q from URL don't match found in body: %q %q %q.",
			vendor, name, ver, nf.Vendor, nf.Name, nf.Version.String())
		ServeJSONError(w, http.StatusBadRequest, err, d)
		return
	}

	// check nut
	errors := nf.Check()
	if len(errors) != 0 {
		err = fmt.Errorf("%s", strings.Join(errors, "\n"))
		ServeJSONError(w, http.StatusBadRequest, err, d)
		return
	}

	// store nut blob
	bw, err := blobstore.Create(c, ct)
	if err == nil {
		_, err = bw.Write(b)
		if err == nil {
			err = bw.Close()
		}
	}
	if err != nil {
		ServeJSONError(w, http.StatusInternalServerError, err, d)
		return
	}

	// store nut version
	blobKey, err := bw.Key()
	if err == nil {
		version.BlobKey = blobKey
		_, err = datastore.Put(c, versionKey, &version)
	}
	if err != nil {
		ServeJSONError(w, http.StatusInternalServerError, err, d)
		return
	}

	// store nut with new doc
	_, err = datastore.Put(c, nutKey, &nut)
	if err != nil {
		ServeJSONError(w, http.StatusInternalServerError, err, d)
		return
	}

	// update search index
	err = gonuts.AddToSearchIndex(c, &nut)
	gonuts.LogError(c, err)

	// done!
	d["Message"] = fmt.Sprintf("Nut %s/%s version %s published.", vendor, name, ver)
	ServeJSON(w, http.StatusCreated, d)
	return
}