Beispiel #1
0
func locationUpdate(db data.DB, u *models.User, e *models.Event) {
	loc, _ := e.Location(db)
	p, err := user.Profile(db, u)
	if err == data.ErrNotFound {
		p = models.NewProfile()
		p.CreatedAt = time.Now()
		p.UpdatedAt = p.CreatedAt
		p.SetID(db.NewID())
		p.SetOwner(u)
	}
	p.SetLocation(loc)
	db.Save(p)
}
Beispiel #2
0
// EventPOST implements gaia's response to a POST request to the '/event/' endpoint.
//
// Assumptions: The user has been authenticated.
//
// Proceedings: Parses the url parameters.
func EventPOST(ctx context.Context, w http.ResponseWriter, r *http.Request, db data.DB, logger services.Logger) {
	l := logger.WithPrefix("EventPOST: ")

	// Parse the form
	if err := r.ParseForm(); err != nil {
		l.Printf("error parsing form: %s", err)
		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		return
	}

	// Retrieve the tags parameter
	tagNames, ok := r.Form[tagsParam]
	if !ok {
		l.Print("no tags param")
		tagNames = []string{}
	}
	// if any tag names have commas, split those
	tagNames = flatten(mapSplit(tagNames, ","))

	// Retrieve our user
	u, ok := user.FromContext(ctx)
	if !ok {
		l.Print("failed to retrieve user from context")
		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		return
	}

	e := new(models.Event)

	tags := make([]*models.Tag, len(tagNames))
	for i, n := range tagNames {
		t, err := tag.ForName(db, u, tag.Name(n))
		if err != nil {
			l.Printf("tag.ForName(%q) error: %s", n, err)
			http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
			return
		}
		tags[i] = t
	}

	defer r.Body.Close()
	if requestBody, err := ioutil.ReadAll(r.Body); err != nil {
		l.Printf("ioutil.ReadAll(r.Body) error: %s", err)
		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		return
	} else if err := json.Unmarshal(requestBody, e); err != nil {
		l.Printf("info: request body:\n%s", string(requestBody))
		l.Printf("error: while unmarshalling request body, %s", err)
		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		return
	}

	if e.CreatedAt.IsZero() {
		e.CreatedAt = time.Now()
	}
	e.UpdatedAt = time.Now()
	e.SetOwner(u)

	for _, t := range tags {
		e.IncludeTag(t)
	}

	if allowed, err := access.CanCreate(db, u, e); err != nil {
		l.Printf("access.CanCreate(db, u, e) error: %s", err)
		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		return
	} else if !allowed {
		l.Print("access.CanCreate(db, u, e) rejected authorization")
		http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
		return
	}

	if err := db.Save(u); err != nil {
		l.Printf("error saving record: %s", err)
		switch err {
		case data.ErrAccessDenial:
			http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
		// These are all equally distressing
		case data.ErrNotFound: // TODO shouldn't a not found not be fing impossible for a Save?
			fallthrough
		case data.ErrNoConnection:
			fallthrough
		case data.ErrInvalidID:
		default:
			http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		}
		return
	}

	// Now we shall write our response
	b, err := json.MarshalIndent(e, "", "    ")
	if err != nil {
		l.Printf("json.MarshalIndent(m, \"\", \"   \") error: %s", err)
		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		return
	}

	w.WriteHeader(http.StatusCreated)
	w.Header().Set("Content-Type", "application/json")
	w.Write(b)
}
Beispiel #3
0
func TestRecordsEditGET(t *testing.T) {
	ctx := context.Background()
	db := mem.NewDB()
	logger := services.NewTestLogger(t)
	s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		ctx, ok := Authenticate(ctx, w, r, logger, db)
		if !ok {
			t.Fatal("authentication failed")
		}

		Records.EditGET(ctx, w, r, db, logger)
	}))
	defer s.Close()

	u, _, err := user.Create(db, "username", "password")
	if err != nil {
		t.Fatal(err)
	}

	e := new(models.Event)
	e.SetID(db.NewID())
	e.SetOwner(u)
	e.Name = "eventname"
	if err := db.Save(e); err != nil {
		t.Fatal("db.Save(e) error: %s", err)
	}

	c := new(http.Client)
	req, err := http.NewRequest("GET", s.URL+"?"+url.Values{
		"kind": []string{string(models.EventKind)},
		"id":   []string{e.Id},
	}.Encode(), nil)
	if err != nil {
		t.Fatal(err)
	}
	req.SetBasicAuth("username", "password")

	resp, err := c.Do(req)
	if err != nil {
		t.Fatal(err)
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		t.Fatal(err)
	}

	t.Logf("Body:\n%s", body)
	doc := string(body)

	contains := map[string]bool{
		"eventname": true,
		"name":      true,
	}

	for c, want := range contains {
		if got := strings.Contains(doc, c); got != want {
			t.Fatalf("strings.Contains(%q): got %t, want %t", c, got, want)
		}
	}
}
Beispiel #4
0
// TestEventPOST tests a POST request to the '/event/' endpoint.
// in the happy case (i.e., all parameters present).
// We verify:
//   * The event's name
//   * The event's data
//   * The event's tags
func TestEventPOST(t *testing.T) {
	ctx := context.Background()
	db := mem.NewDB()
	logger := services.NewTestLogger(t)
	s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		ctx, ok := routes.Authenticate(ctx, w, r, logger, db)
		if !ok {
			t.Error("routes.Authenticate failed")
		}
		routes.EventPOST(ctx, w, r, db, logger)
	}))
	defer s.Close()

	_, _, err := user.Create(db, "username", "password")
	if err != nil {
		t.Fatalf("user.Create(db, \"username\", \"password\") error: %s", err)
	}

	u := s.URL + "?" + url.Values{
		"tags": []string{"tag1", "tag2"},
	}.Encode()

	body := map[string]interface{}{
		"name": "event name",
		"time": time.Now(),
		"data": map[string]interface{}{
			"arbitrary": []string{"data"},
			"here":      1.0,
			"foo": map[string]interface{}{
				"bar": "there",
			},
		},
	}

	b, err := json.Marshal(body)
	if err != nil {
		t.Fatal("json.Marshal(body) error: %s", err)
	}

	req, err := http.NewRequest("POST", u, bytes.NewBuffer(b))
	req.SetBasicAuth("username", "password")

	client := new(http.Client)
	resp, err := client.Do(req)
	if err != nil {
		t.Fatalf("client.Do(req) error: %s", err)
	}
	defer resp.Body.Close()

	if got, want := resp.StatusCode, http.StatusCreated; got != want {
		t.Fatalf("resp.StatusCode: got %d, want %d", got, want)
	}

	b, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		t.Fatalf("ioutil.ReadAll(resp.Body) error: %s", err)
	}

	e := new(models.Event)
	if err := json.Unmarshal(b, e); err != nil {
		t.Fatalf("json.Unmarshal(b, e) error: %s", err)
	}

	t.Logf("Event:\n\t%v", e)

	if got, want := e.Name, "event name"; got != want {
		t.Errorf("e.Name: got %q, want %q", got, want)
	}

	if got, want := e.Data["foo"].(map[string]interface{})["bar"], "there"; got != want {
		t.Errorf("e.Data[\"foo\"][\"bar\"]: got %q, want %q", got, want)
	}

	if got, want := len(e.TagsIds), 2; got != want {
		t.Fatalf("len(e.TagsIds): got %d, want %d", got, want)
	}

	tags, err := e.Tags(db)
	if err != nil {
		t.Fatalf("e.Tags(db) error: %s", err)
	}

	if got, want := len(tags), 2; got != want {
		t.Fatalf("len(tags): got %d, want %d", got, want)
	}

	if got, want := tags[0].Name, "tag1"; got != want {
		t.Errorf("tags[0].Name: got %q, want %q", got, want)
	}

	if got, want := tags[1].Name, "tag2"; got != want {
		t.Errorf("tags[1].Name: got %q, want %q", got, want)
	}
}