aboutsummaryrefslogtreecommitdiffstats
path: root/web
diff options
context:
space:
mode:
Diffstat (limited to 'web')
-rw-r--r--web/web.go39
-rw-r--r--web/web_test.go55
2 files changed, 94 insertions, 0 deletions
diff --git a/web/web.go b/web/web.go
index 02cbead..ca5e2a2 100644
--- a/web/web.go
+++ b/web/web.go
@@ -143,6 +143,43 @@ func serveBoxedFile(w http.ResponseWriter, r *http.Request, filename string) {
http.ServeContent(w, r, filename, fi.ModTime(), ui)
}
+func apiLoginHandler(w http.ResponseWriter, r *http.Request) {
+ username := r.FormValue("username")
+ password := r.FormValue("password")
+
+ // support JSON body as well
+ if username == "" && password == "" {
+ // try parsing json
+ /*
+ type loginReq struct {
+ Username string `json:"username"`
+ Password string `json:"password"`
+ }
+ // left as todo for now as we can use form data from fetch too
+ */
+ }
+
+ if password == config.Config.DigestPassword {
+ v, _ := bcrypt.GenerateFromPassword([]byte(password), 0)
+ c := http.Cookie{Name: AuthCookie, Value: string(v), Path: "/", MaxAge: SecondsInAYear, HttpOnly: false}
+ http.SetCookie(w, &c)
+ w.Header().Set("Content-Type", "application/json")
+ fmt.Fprintf(w, `{"status":"ok"}`)
+ } else {
+ http.Error(w, `{"status":"error", "message":"bad login"}`, 401)
+ }
+}
+
+func apiAuthStatusHandler(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ if Authenticated(r) {
+ fmt.Fprintf(w, `{"status":"ok", "authenticated":true}`)
+ } else {
+ w.WriteHeader(http.StatusUnauthorized)
+ fmt.Fprintf(w, `{"status":"error", "authenticated":false}`)
+ }
+}
+
func Serve() {
box := rice.MustFindBox("../static")
staticFileServer := http.StripPrefix("/static/", http.FileServer(box.HTTPBox()))
@@ -167,6 +204,8 @@ func Serve() {
http.HandleFunc("/login/", loginHandler)
http.HandleFunc("/logout/", logoutHandler)
+ http.HandleFunc("/api/login", apiLoginHandler)
+ http.HandleFunc("/api/auth", apiAuthStatusHandler)
http.HandleFunc("/", AuthWrap(indexHandler))
diff --git a/web/web_test.go b/web/web_test.go
index e11a98c..a73a6c9 100644
--- a/web/web_test.go
+++ b/web/web_test.go
@@ -317,6 +317,61 @@ func TestAuthWrapHandlerUnauthenticated(t *testing.T) {
}
}
+func TestApiLoginHandlerSuccess(t *testing.T) {
+ config.Config.DigestPassword = "testpass"
+ req := httptest.NewRequest("POST", "/api/login", nil)
+ req.Form = map[string][]string{"password": {"testpass"}}
+ rr := httptest.NewRecorder()
+ apiLoginHandler(rr, req)
+ if rr.Code != http.StatusOK {
+ t.Errorf("Expected 200, got %d", rr.Code)
+ }
+ body := rr.Body.String()
+ if body != `{"status":"ok"}` {
+ t.Errorf("Expected ok status, got %q", body)
+ }
+}
+
+func TestApiLoginHandlerFail(t *testing.T) {
+ config.Config.DigestPassword = "testpass"
+ req := httptest.NewRequest("POST", "/api/login", nil)
+ req.Form = map[string][]string{"password": {"wrongpass"}}
+ rr := httptest.NewRecorder()
+ apiLoginHandler(rr, req)
+ if rr.Code != http.StatusUnauthorized {
+ t.Errorf("Expected 401, got %d", rr.Code)
+ }
+}
+
+func TestApiAuthStatusHandlerAuthenticated(t *testing.T) {
+ config.Config.DigestPassword = "secret"
+ req := httptest.NewRequest("GET", "/api/auth", nil)
+ req.AddCookie(authCookie())
+ rr := httptest.NewRecorder()
+ apiAuthStatusHandler(rr, req)
+ if rr.Code != http.StatusOK {
+ t.Errorf("Expected 200, got %d", rr.Code)
+ }
+ body := rr.Body.String()
+ if body != `{"status":"ok", "authenticated":true}` {
+ t.Errorf("Expected authenticated true, got %q", body)
+ }
+}
+
+func TestApiAuthStatusHandlerUnauthenticated(t *testing.T) {
+ config.Config.DigestPassword = "secret"
+ req := httptest.NewRequest("GET", "/api/auth", nil)
+ rr := httptest.NewRecorder()
+ apiAuthStatusHandler(rr, req)
+ if rr.Code != http.StatusUnauthorized {
+ t.Errorf("Expected 401, got %d", rr.Code)
+ }
+ body := rr.Body.String()
+ if body != `{"status":"error", "authenticated":false}` {
+ t.Errorf("Expected authenticated false, got %q", body)
+ }
+}
+
func TestLoginHandlerGet(t *testing.T) {
req := httptest.NewRequest("GET", "/login/", nil)
rr := httptest.NewRecorder()