You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
106 lines
2.6 KiB
106 lines
2.6 KiB
package utils
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"github.com/dustinpianalto/errors"
|
|
"github.com/dustinpianalto/quartermaster"
|
|
"github.com/dustinpianalto/quartermaster/internal/jwt"
|
|
"github.com/dustinpianalto/quartermaster/pkg/services"
|
|
"github.com/gorilla/mux"
|
|
)
|
|
|
|
func Mount(r *mux.Router, path string, handler http.Handler) {
|
|
r.PathPrefix(path).Handler(
|
|
http.StripPrefix(
|
|
strings.TrimSuffix(path, "/"),
|
|
handler,
|
|
),
|
|
)
|
|
}
|
|
|
|
type RootHandler func(*http.ResponseWriter, *http.Request) error
|
|
|
|
func (rh RootHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
err := rh(&w, r)
|
|
if err == nil {
|
|
return
|
|
}
|
|
|
|
log.Println(err)
|
|
|
|
e, ok := err.(*errors.Error)
|
|
if !ok {
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
|
|
|
if errors.Is(errors.Permission, e) {
|
|
body := getErrorBody("Permission Denied")
|
|
w.WriteHeader(http.StatusForbidden)
|
|
w.Write(body)
|
|
}
|
|
|
|
if errors.Is(errors.Incorrect, e) && strings.Contains(string(e.Method), "login") {
|
|
body := getErrorBody("Invalid Login Credentials")
|
|
w.WriteHeader(http.StatusUnauthorized)
|
|
w.Write(body)
|
|
}
|
|
|
|
if errors.Is(errors.Incorrect, e) && strings.Contains(string(e.Method), "refresh") {
|
|
body := getErrorBody("Missing or Invalid Cookie")
|
|
w.WriteHeader(http.StatusUnauthorized)
|
|
w.Write(body)
|
|
}
|
|
|
|
if errors.Is(errors.Malformed, e) {
|
|
body := getErrorBody("Bad Request")
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
w.Write(body)
|
|
}
|
|
|
|
if errors.Is(errors.Internal, e) {
|
|
body := getErrorBody("Internal Server Error")
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
w.Write(body)
|
|
}
|
|
|
|
if errors.Is(errors.Conflict, e) && strings.Contains(string(e.Method), "register") {
|
|
body := getErrorBody("User already exists")
|
|
w.WriteHeader(http.StatusConflict)
|
|
w.Write(body)
|
|
}
|
|
}
|
|
|
|
func getErrorBody(s string) []byte {
|
|
return []byte(fmt.Sprintf("{\"error\": \"%s\"}", s))
|
|
}
|
|
|
|
type authenticatedHandler func(*http.ResponseWriter, *http.Request, *quartermaster.User) error
|
|
|
|
func AuthenticationMiddleware(next authenticatedHandler) RootHandler {
|
|
const method = "utils/AuthenticationMiddleware"
|
|
return RootHandler(func(w *http.ResponseWriter, r *http.Request) error {
|
|
claims, err := jwt.AuthenticateJWTToken(r)
|
|
if err != nil {
|
|
return errors.E(method, errors.Permission, "invalid token", err)
|
|
}
|
|
|
|
u, err := services.UserService.User(claims.Username)
|
|
if err != nil {
|
|
return errors.E(method, errors.Permission, "user not found", err)
|
|
}
|
|
|
|
err = next(w, r, u)
|
|
if err != nil {
|
|
return errors.E(method, "error in handler", err)
|
|
}
|
|
return nil
|
|
})
|
|
}
|