Feature: Auth (#4)

* feat(api): add auth

* feat(web): add auth and refactor

* refactor(web): baseurl

* feat: add autobrrctl cli for user creation

* build: move static assets

* refactor(web): auth guard and routing

* refactor: rename var

* fix: remove subrouter

* build: update default config
This commit is contained in:
Ludvig Lundgren 2021-08-14 14:19:21 +02:00 committed by GitHub
parent 2e8d0950c1
commit 40b855bf39
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
56 changed files with 1208 additions and 257 deletions

86
internal/http/auth.go Normal file
View file

@ -0,0 +1,86 @@
package http
import (
"encoding/json"
"net/http"
"github.com/go-chi/chi"
"github.com/gorilla/sessions"
"github.com/autobrr/autobrr/internal/config"
"github.com/autobrr/autobrr/internal/domain"
)
type authService interface {
Login(username, password string) (*domain.User, error)
}
type authHandler struct {
encoder encoder
authService authService
}
var (
// key will only be valid as long as it's running.
key = []byte(config.Config.SessionSecret)
store = sessions.NewCookieStore(key)
)
func (h authHandler) Routes(r chi.Router) {
r.Post("/login", h.login)
r.Post("/logout", h.logout)
r.Get("/test", h.test)
}
func (h authHandler) login(w http.ResponseWriter, r *http.Request) {
var (
ctx = r.Context()
data domain.User
)
if err := json.NewDecoder(r.Body).Decode(&data); err != nil {
// encode error
h.encoder.StatusResponse(ctx, w, nil, http.StatusBadRequest)
return
}
session, _ := store.Get(r, "user_session")
_, err := h.authService.Login(data.Username, data.Password)
if err != nil {
h.encoder.StatusResponse(ctx, w, nil, http.StatusUnauthorized)
return
}
// Set user as authenticated
session.Values["authenticated"] = true
session.Save(r, w)
h.encoder.StatusResponse(ctx, w, nil, http.StatusNoContent)
}
func (h authHandler) logout(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
session, _ := store.Get(r, "user_session")
// Revoke users authentication
session.Values["authenticated"] = false
session.Save(r, w)
h.encoder.StatusResponse(ctx, w, nil, http.StatusNoContent)
}
func (h authHandler) test(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
session, _ := store.Get(r, "user_session")
// Check if user is authenticated
if auth, ok := session.Values["authenticated"].(bool); !ok || !auth {
http.Error(w, "Forbidden", http.StatusForbidden)
return
}
// send empty response as ok
h.encoder.StatusResponse(ctx, w, nil, http.StatusNoContent)
}