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.
quartermaster/internal/utils/utils.go

114 lines
2.8 KiB

package utils
import (
"fmt"
"log"
"net/http"
"os"
"strings"
"github.com/dustinpianalto/errors"
"github.com/dustinpianalto/quartermaster"
"github.com/golang-jwt/jwt"
"github.com/gorilla/mux"
)
var jwtKey = []byte(os.Getenv("JWT_KEY"))
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))
}
func IsAuthenticated(r *http.Request) (*jwt.Token, error) {
const method errors.Method = "utils/IsAuthenticated"
c, err := r.Cookie("token")
if err != nil {
if err == http.ErrNoCookie {
return nil, errors.E(method, errors.Incorrect, "cookie not found", err)
}
return nil, errors.E(method, errors.Malformed, "failed to get cookie data", err)
}
tknStr := c.Value
claims := &quartermaster.Claims{}
tkn, err := jwt.ParseWithClaims(tknStr, claims, func(token *jwt.Token) (interface{}, error) {
return jwtKey, nil
})
if err != nil {
if err == jwt.ErrSignatureInvalid {
return nil, errors.E(method, errors.Incorrect, "cookie is invalid", err)
}
e, _ := err.(*jwt.ValidationError)
if e.Inner == jwt.ErrInvalidKeyType {
return nil, errors.E(method, errors.Internal, err)
} else if e.Inner == jwt.ErrHashUnavailable {
return nil, errors.E(method, errors.Internal, err)
}
return nil, errors.E(method, errors.Malformed, "failed to parse cookie", err)
}
return tkn, nil
}