diff --git a/http.go b/http.go index c699832..9acda18 100644 --- a/http.go +++ b/http.go @@ -13,7 +13,9 @@ import ( ) type HTTPServer struct { - store FileStore + Files FileStore + Users UserStore + Auth *AuthService config *ServerConfig Logger *zap.SugaredLogger AccessLogger *zap.SugaredLogger @@ -26,7 +28,9 @@ func NewHTTPServer(cfg *ServerConfig) *HTTPServer { Logger: zap.NewNop().Sugar(), AccessLogger: zap.NewNop().Sugar(), } - srv.store = NewMemoryFileStore() + srv.Files = NewMemoryFileStore() + srv.Users = NewMemoryUserStore() + srv.Auth = NewAuthService(srv.Users, []byte("test1235")) r := chi.NewRouter() r.Use(middleware.RealIP) @@ -35,6 +39,7 @@ func NewHTTPServer(cfg *ServerConfig) *HTTPServer { r.Get("/", srv.HandlerIndex) r.Post("/api/file", srv.HandlerAPIFilePost) r.Get("/api/file/{id}", srv.HandlerAPIFileGet) + r.Post("/api/login", srv.HandlerAPILogin) srv.Handler = r return srv @@ -57,7 +62,7 @@ func (s *HTTPServer) HandlerAPIFilePost(w http.ResponseWriter, r *http.Request) s.processMultiPartFormUpload(w, r) return } - err := s.store.Store(f) + err := s.Files.Store(f) if err != nil { w.WriteHeader(http.StatusInternalServerError) s.Logger.Warnw("Error storing file.", "req_id", reqID, "error", err, "id", f.ID, "remote_addr", r.RemoteAddr) @@ -87,7 +92,7 @@ func (s *HTTPServer) HandlerAPIFileGet(w http.ResponseWriter, r *http.Request) { return } - f, err := s.store.Get(id) + f, err := s.Files.Get(id) if err != nil { // TODO: LOG w.WriteHeader(http.StatusInternalServerError) @@ -126,7 +131,7 @@ func (s *HTTPServer) processMultiPartFormUpload(w http.ResponseWriter, r *http.R Body: ff, } - if err := s.store.Store(f); err != nil { + if err := s.Files.Store(f); err != nil { w.WriteHeader(http.StatusInternalServerError) s.Logger.Warnw("Error storing file.", "req_id", reqID, "error", err, "id", f.ID, "remote_addr", r.RemoteAddr) return @@ -143,3 +148,34 @@ func (s *HTTPServer) processMultiPartFormUpload(w http.ResponseWriter, r *http.R s.Logger.Warnw("Error encoding response to client.", "req_id", reqID, "error", err, "remote_addr", r.RemoteAddr) } } + +func (s *HTTPServer) HandlerAPILogin(w http.ResponseWriter, r *http.Request) { + reqID := middleware.GetReqID(r.Context()) + expectedRequest := struct { + Username string `json:"username"` + Password string `json:"password"` + }{} + decoder := json.NewDecoder(r.Body) + defer r.Body.Close() + if err := decoder.Decode(&expectedRequest); err != nil { + w.WriteHeader(http.StatusBadRequest) + return + } + + token, err := s.Auth.Login(expectedRequest.Username, expectedRequest.Password) + if err != nil { + w.WriteHeader(http.StatusUnauthorized) + return + } + + response := struct { + Token string `json:"token"` + }{ + Token: token, + } + + encoder := json.NewEncoder(w) + if err := encoder.Encode(&response); err != nil { + s.Logger.Infow("Error encoding json response to client.", "req_id", reqID, "error", err, "remote_addr", r.RemoteAddr) + } +} diff --git a/http_test.go b/http_test.go index cf99e23..8ecc89d 100644 --- a/http_test.go +++ b/http_test.go @@ -96,4 +96,48 @@ func TestHandlers(t *testing.T) { } }) }) + t.Run("HandlerAPILogin", func(t *testing.T) { + // TODO: Add test + username := "admin" + password := "admin" + user := &gpaste.User{Username: username} + if err := user.SetPassword(password); err != nil { + t.Fatalf("Error setting user password: %s", err) + } + if err := hs.Users.Store(user); err != nil { + t.Fatalf("Error storing user: %s", err) + } + + requestData := struct { + Username string `json:"username"` + Password string `json:"password"` + }{ + Username: username, + Password: password, + } + + body := new(bytes.Buffer) + encoder := json.NewEncoder(body) + if err := encoder.Encode(&requestData); err != nil { + t.Fatalf("Error encoding request body: %s", err) + } + + rr := httptest.NewRecorder() + req := httptest.NewRequest(http.MethodPost, "/api/login", body) + + hs.Handler.ServeHTTP(rr, req) + + responseData := struct { + Token string `json:"token"` + }{} + + decoder := json.NewDecoder(rr.Body) + if err := decoder.Decode(&responseData); err != nil { + t.Fatalf("Error decoding response: %s", err) + } + + if err := hs.Auth.ValidateToken(responseData.Token); err != nil { + t.Fatalf("Unable to validate received token: %s", err) + } + }) }