Beispiel #1
0
func registerHandler(c appengine.Context, w http.ResponseWriter, r *http.Request) {
	u := gaeuser.Current(c)
	if u != nil && u.ID != "" {
		var err error
		vendor := r.FormValue("vendor")
		if !nutp.VendorRegexp.MatchString(vendor) {
			err = fmt.Errorf("Vendor name should match %s.", nutp.VendorRegexp.String())
			WriteError(w, http.StatusBadRequest, err)
			return
		}

		v := &gonuts.Vendor{Vendor: vendor}
		user := &gonuts.User{Id: u.ID, Email: u.Email, FederatedIdentity: u.FederatedIdentity}
		gonuts.PanicIfErr(user.GenerateToken())

		err = datastore.Get(c, gonuts.VendorKey(c, vendor), v)
		if err != datastore.ErrNoSuchEntity {
			if err == nil {
				err = fmt.Errorf("Vendor name %q is already registered.", vendor)
				WriteError(w, http.StatusForbidden, err)
				return
			}

			gonuts.LogError(c, err)
			WriteError(w, http.StatusInternalServerError, err)
			return
		}

		err = datastore.Get(c, gonuts.UserKey(c, u), user)
		if err != datastore.ErrNoSuchEntity {
			gonuts.LogError(c, err)
			WriteError(w, http.StatusInternalServerError, err)
			return
		}

		c.Infof("Adding user %s (%s) to vendor %s.", user.Id, user.Identifier(), v.Vendor)
		user.AddVendor(v)
		_, err = datastore.Put(c, gonuts.VendorKey(c, vendor), v)
		gonuts.PanicIfErr(err)
		_, err = datastore.Put(c, gonuts.UserKey(c, u), user)
		gonuts.PanicIfErr(err)
	}

	http.Redirect(w, r, "/-/me", http.StatusSeeOther)
}
Beispiel #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
}