Beispiel #1
0
func TestAuthenticateQueryParams(t *testing.T) {
	ctx := context.Background()
	db := mem.NewDB()
	logger := services.NewTestLogger(t)

	var userContext context.Context
	var authed bool
	s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		userContext, authed = routes.Authenticate(ctx, w, r, logger, db)
		if authed {
			w.WriteHeader(http.StatusOK)
		}
	}))
	defer s.Close()

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

	req, err := http.NewRequest("GET", s.URL, new(bytes.Buffer))
	if err != nil {
		t.Fatalf("http.NewRequest error: %s", err)
	}
	client.Do(req)
	if got, want := authed, false; got != want {
		t.Fatalf("authed: got %t, want %t", got, want)
	}

	req, err = http.NewRequest("GET", s.URL+"?public=username&private=password", new(bytes.Buffer))
	if err != nil {
		t.Fatalf("http.NewRequest error: %s", err)
	}
	client.Do(req)
	if got, want := authed, true; got != want {
		t.Fatalf("authed: got %t, want %t")
	}
	authedU, ok := user.FromContext(userContext)
	if got, want := ok, true; got != want {
		t.Fatalf("_, ok := user.FromContext: got %t, want %t")
	}
	if got, want := data.Equivalent(authedU, u), true; got != want {
		t.Errorf("data.Equivalent(authedU, u): got %t, want %t", got, want)
	}
}
Beispiel #2
0
func TestAuthenticatePostForm(t *testing.T) {
	ctx := context.Background()
	db := mem.NewDB()
	logger := services.NewTestLogger(t)

	var userContext context.Context
	var authed bool
	s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		userContext, authed = routes.Authenticate(ctx, w, r, logger, db)
		if authed {
			w.WriteHeader(http.StatusOK)
		}
	}))
	defer s.Close()

	u, _, err := user.Create(db, "username", "password")
	if err != nil {
		t.Fatalf("user.Create(db, \"username\", \"password\") error: %s", err)
	}
	client := new(http.Client)
	client.PostForm(s.URL, url.Values{
		"public":  []string{"username"},
		"private": []string{"password"},
	})

	if got, want := authed, true; got != want {
		t.Fatalf("authed: got %t, want %t", got, want)
	}
	authedU, ok := user.FromContext(userContext)
	if got, want := ok, true; got != want {
		t.Fatalf("_, ok := user.FromContext: got %t, want %t", got, want)
	}
	if got, want := data.Equivalent(authedU, u), true; got != want {
		t.Fatal("data.Equivalent(authedU, u): got %t ,want %t", got, want)
	}
}
Beispiel #3
0
func TestLoginPOST(t *testing.T) {
	ctx := context.Background()
	db := mem.NewDB()
	logger := services.NewTestLogger(t)
	m := http.NewServeMux()
	m.Handle("/login/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		ctx, ok := routes.Authenticate(ctx, w, r, logger, db)
		if !ok {
			t.Fatal("bad authentication")
		}
		routes.LoginPOST(ctx, w, r, db, logger)
	}))
	m.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusAccepted)
	}))
	s := httptest.NewServer(http.HandlerFunc(m.ServeHTTP))
	defer s.Close()

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

	req, err := http.NewRequest("GET", s.URL+"/login/", new(bytes.Buffer))
	if err != nil {
		t.Fatalf("http.NewRequest error: %s", err)
	}
	req.SetBasicAuth("username", "password")

	jar, err := cookiejar.New(new(cookiejar.Options))
	if err != nil {
		t.Fatalf("cookiejar.New error: %s", err)
	}
	client := &http.Client{
		Jar: jar,
	}

	resp, err := client.Do(req)

	if err != nil {
		t.Fatalf("error posting to LoginPOST: %s", err)
	}

	t.Logf("Response:\n\t%v", resp)

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

	iter, err := db.Query(models.SessionKind).Execute()
	if err != nil {
		t.Fatalf("db.Query(models.SessionKind).Execute(): %s", err)
	}

	seshes := mem.Slice(iter, func() data.Record { return new(models.Session) })

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

	uri, err := url.Parse(s.URL)
	if err != nil {
		t.Fatalf("url.Prase(s.URL) error: %s", err)
	}

	t.Logf("URL: %s", uri)

	cookies := jar.Cookies(uri)
	if got, want := len(cookies), 1; got != want {
		t.Fatalf("len(cookies): got %d, want %d", got, want)
	}

	if got, want := cookies[0].Value, seshes[0].(*models.Session).Token; got != want {
		t.Errorf("cookies[0].Value: got %s, want %s", got, want)
	}
}
Beispiel #4
0
func router(ctx context.Context, m *Middleware, s *Services) (http.Handler, context.CancelFunc) {
	mux := http.NewServeMux()
	requestBackground, cancelAll := context.WithCancel(ctx)

	mux.Handle("/app/", http.StripPrefix("/app/", http.FileServer(s.AppFileSystem)))

	mux.HandleFunc(routes.Index, logRequest(func(w http.ResponseWriter, r *http.Request) {
		switch r.Method {
		case "GET":
			w.Write([]byte("Who is John Galt?"))
		default:
			http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
			return
		}
	}, s.Logger))

	// /records/query/
	mux.HandleFunc(routes.RecordsQuery, logRequest(func(w http.ResponseWriter, r *http.Request) {
		switch r.Method {
		case "GET":
			routes.Records.QueryGET(ctx, w, r, s.WebUIClient)
		default:
			http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
			return
		}
	}, s.Logger))

	// /records/new/
	mux.HandleFunc(routes.RecordsNew, logRequest(func(w http.ResponseWriter, r *http.Request) {
		switch r.Method {
		case "GET":
			routes.Records.NewGET(ctx, w, r, s.WebUIClient)
		default:
			http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
			return
		}
	}, s.Logger))

	// /records/create/
	mux.HandleFunc(routes.RecordsCreate, logRequest(func(w http.ResponseWriter, r *http.Request) {
		switch r.Method {
		case "GET":
			routes.Records.CreateGET(ctx, w, r, s.WebUIClient)
		case "POST":
			routes.Records.CreatePOST(ctx, w, r, s.WebUIClient)
		default:
			http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
			return
		}
	}, s.Logger))

	// /records/edit/
	mux.HandleFunc(routes.RecordsEdit, logRequest(func(w http.ResponseWriter, r *http.Request) {
		switch r.Method {
		case "GET":
			routes.Records.EditGET(ctx, w, r, s.WebUIClient)
		case "POST":
			routes.Records.EditPOST(ctx, w, r, s.WebUIClient)
		default:
			http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
			return
		}
	}, s.Logger))

	// /records/view/
	mux.HandleFunc(routes.RecordsView, logRequest(func(w http.ResponseWriter, r *http.Request) {
		switch r.Method {
		case "GET":
			routes.Records.ViewGET(ctx, w, r, s.WebUIClient)
		default:
			http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
			return
		}
	}, s.Logger))

	// /records/delete/
	mux.HandleFunc(routes.RecordsDelete, logRequest(func(w http.ResponseWriter, r *http.Request) {
		switch r.Method {
		case "POST":
			routes.Records.DeletePOST(ctx, w, r, s.WebUIClient)
		default:
			http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
			return
		}
	}, s.Logger))

	// /register/
	mux.HandleFunc(routes.Register, logRequest(func(w http.ResponseWriter, r *http.Request) {
		switch r.Method {
		case "POST":
			routes.RegisterPOST(requestBackground, w, r, s.WebUIClient)
		case "GET":
			routes.RegisterGET(requestBackground, w, r, s.WebUIClient)
		default:
			http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
			return
		}
	}, s.Logger))

	// /login/
	mux.HandleFunc(routes.Login, logRequest(func(w http.ResponseWriter, r *http.Request) {
		switch r.Method {
		case "POST":
			routes.LoginPOST(ctx, w, r, s.WebUIClient)
		case "GET":
			routes.LoginGET(requestBackground, w, r, s.WebUIClient)
		default:
			http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
			return
		}
	}, s.Logger))

	// /record/
	mux.HandleFunc(routes.Record, logRequest(cors(func(w http.ResponseWriter, r *http.Request) {
		if r.Method == "OPTIONS" {
			routes.RecordOPTIONS(requestBackground, w, r)
			return
		}

		ctx, ok := routes.Authenticate(requestBackground, w, r, s.Logger, s.DB)
		if !ok {
			return
		}

		switch r.Method {
		case "GET":
			routes.RecordGET(ctx, w, r, s.Logger, s.DB)
		case "POST":
			routes.RecordPOST(ctx, w, r, s.Logger, s.DB)
		case "DELETE":
			routes.RecordDELETE(ctx, w, r, s.Logger, s.DB)
		case "OPTIONS":
			routes.RecordOPTIONS(ctx, w, r)
		default:
			http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
			return
		}
	}), s.Logger))

	// /record/query/
	mux.HandleFunc(routes.RecordQuery, logRequest(cors(func(w http.ResponseWriter, r *http.Request) {
		if r.Method == "OPTIONS" {
			routes.RecordOPTIONS(requestBackground, w, r)
			return
		}

		ctx, ok := routes.Authenticate(requestBackground, w, r, s.Logger, s.DB)
		if !ok {
			return
		}

		switch r.Method {
		case "POST":
			routes.RecordQueryPOST(ctx, w, r, s.Logger, s.DB)
		default:
			http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
			return
		}
	}), s.Logger))

	// /event/
	mux.HandleFunc(routes.Event, logRequest(cors(func(w http.ResponseWriter, r *http.Request) {
		ctx, ok := routes.Authenticate(requestBackground, w, r, s.Logger, s.DB)
		if !ok {
			return
		}

		switch r.Method {
		case "POST":
			routes.EventPOST(ctx, w, r, s.DB, s.Logger)
		default:
			http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
			return
		}
	}), s.Logger))

	// /record/changes/
	mux.HandleFunc(routes.RecordChanges, logRequest(websocket.Handler(
		routes.ContextualizeRecordChangesGET(requestBackground, s.DB, s.Logger),
	).ServeHTTP, s.Logger))

	// /command/sms/
	mux.HandleFunc(routes.CommandSMS, logRequest(func(w http.ResponseWriter, r *http.Request) {
		ctx := requestBackground

		switch r.Method {
		case "POST":
			routes.CommandSMSPOST(ctx, w, r, s.Logger, s.SMSCommandSessions)
		default:
			http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
			return
		}
	}, s.Logger))

	// /command/web/
	mux.HandleFunc(routes.CommandWeb, logRequest(websocket.Handler(
		routes.ContextualizeCommandWebGET(requestBackground, s.DB, s.Logger),
	).ServeHTTP, s.Logger))

	// /mobile/location/
	mux.HandleFunc(routes.MobileLocation, logRequest(func(w http.ResponseWriter, r *http.Request) {
		ctx, ok := routes.Authenticate(requestBackground, w, r, s.Logger, s.DB)
		if !ok {
			return
		}

		switch r.Method {
		case "POST":
			routes.MobileLocationPOST(ctx, w, r, s.Logger, s.DB)
		default:
			http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
			return
		}
	}, s.Logger))

	// /cal/week/
	mux.HandleFunc(routes.CalWeek, logRequest(func(w http.ResponseWriter, r *http.Request) {
		switch r.Method {
		case "GET":
			cal.WeekGET(ctx, w, r, s.CalWebUIClient)
		default:
			http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
			return
		}
	}, s.Logger))

	// Handle letsencrypt
	fs := http.FileServer(http.Dir("/var/www/elos/"))
	mux.Handle("/.well-known/", logRequest(func(w http.ResponseWriter, r *http.Request) {
		fs.ServeHTTP(w, r)
	}, s.Logger))

	return mux, cancelAll
}
Beispiel #5
0
// --- TestAuthenticateSession {{{
func TestAuthenticateSession(t *testing.T) {
	ctx := context.Background()
	db := mem.NewDB()
	logger := services.NewTestLogger(t)

	var userContext context.Context
	var authed bool
	s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		userContext, authed = routes.Authenticate(ctx, w, r, logger, db)
		if authed {
			w.WriteHeader(http.StatusOK)
		}
	}))
	defer s.Close()

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

	req, err := http.NewRequest("GET", s.URL, new(bytes.Buffer))
	if err != nil {
		t.Fatalf("http.NewRequest error: %s", err)
	}
	req.AddCookie(&http.Cookie{
		Name:  "elos-session-token",
		Value: "garbage",
	})
	client.Do(req)

	if got, want := authed, false; got != want {
		t.Errorf("authed: got %t, want %t", got, want)
	}

	sesh := models.NewSessionForUser(u)
	sesh.SetID(db.NewID())
	if err := db.Save(sesh); err != nil {
		t.Fatalf("db.Save(sesh) error: %s", err)
	}
	req, err = http.NewRequest("GET", s.URL, new(bytes.Buffer))
	if err != nil {
		t.Fatalf("http.NewRequest error: %s", err)
	}
	req.AddCookie(&http.Cookie{
		Name:  "elos-session-token",
		Value: sesh.Token,
	})
	client.Do(req)

	if got, want := authed, true; got != want {
		t.Fatalf("authed: got %t, want %t", got, want)
	}
	authedU, ok := user.FromContext(userContext)
	if got, want := ok, true; got != want {
		t.Fatalf("_, ok := user.FromContext: got %t, want %t", got, want)
	}
	if got, want := data.Equivalent(authedU, u), true; got != want {
		t.Errorf("data.Equivalent(authedU, u): got %t, want %t", got, want)
	}
}
Beispiel #6
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)
	}
}