172 lines
5.1 KiB
Go
172 lines
5.1 KiB
Go
package crud
|
|
|
|
import (
|
|
"code.mrmelon54.com/melon/summer/pkg/api"
|
|
"code.mrmelon54.com/melon/summer/pkg/claims/auth"
|
|
"code.mrmelon54.com/melon/summer/pkg/utils"
|
|
"encoding/json"
|
|
"github.com/gorilla/mux"
|
|
"github.com/mrmelon54/mjwt"
|
|
"net/http"
|
|
)
|
|
|
|
type crudHandler[T any] struct {
|
|
provider Provider[T]
|
|
verify mjwt.Provider
|
|
}
|
|
|
|
type secureHandlerFunc func(rw http.ResponseWriter, req *http.Request, claims *auth.AccessTokenClaims)
|
|
|
|
func NewCrudHandler[T any](router *mux.Router, verify mjwt.Provider, provider Provider[T], findPath, itemPath string) {
|
|
z := &crudHandler[T]{provider: provider, verify: verify}
|
|
router.HandleFunc(findPath, z.claimExtractor(z.handleFind)).Methods(http.MethodGet)
|
|
router.HandleFunc(findPath, z.claimExtractor(z.handleAdd)).Methods(http.MethodPost)
|
|
router.HandleFunc(itemPath, z.claimExtractor(z.handleGet)).Methods(http.MethodGet)
|
|
router.HandleFunc(itemPath, z.claimExtractor(z.handlePut)).Methods(http.MethodPut)
|
|
router.HandleFunc(itemPath, z.claimExtractor(z.handlePatch)).Methods(http.MethodPatch)
|
|
router.HandleFunc(itemPath, z.claimExtractor(z.handleDelete)).Methods(http.MethodDelete)
|
|
}
|
|
|
|
func (c *crudHandler[T]) claimExtractor(f secureHandlerFunc) func(rw http.ResponseWriter, req *http.Request) {
|
|
return func(rw http.ResponseWriter, req *http.Request) {
|
|
token := utils.GetBearerToken(req)
|
|
if token == "" {
|
|
f(rw, req, nil)
|
|
return
|
|
}
|
|
|
|
// Verify as mfa flow token
|
|
_, b, err := mjwt.ExtractClaims[auth.AccessTokenClaims](c.verify, token)
|
|
if err != nil {
|
|
f(rw, req, nil)
|
|
return
|
|
}
|
|
|
|
f(rw, req, &b.Claims)
|
|
}
|
|
}
|
|
|
|
func (c *crudHandler[T]) handleFind(rw http.ResponseWriter, _ *http.Request, claims *auth.AccessTokenClaims) {
|
|
a, err := c.provider.Find(claims)
|
|
if HttpCatchError(rw, err) {
|
|
return
|
|
}
|
|
if api.GenericErrorMsg[T](rw, err, http.StatusInternalServerError, "Find error") {
|
|
return
|
|
}
|
|
rw.Header().Set("Content-Type", "application/json")
|
|
rw.WriteHeader(http.StatusOK)
|
|
err = json.NewEncoder(rw).Encode(a)
|
|
if api.GenericErrorMsg[T](rw, err, http.StatusInternalServerError, "Encode error") {
|
|
return
|
|
}
|
|
}
|
|
|
|
func (c *crudHandler[T]) handleAdd(rw http.ResponseWriter, req *http.Request, claims *auth.AccessTokenClaims) {
|
|
var t T
|
|
err := json.NewDecoder(req.Body).Decode(&t)
|
|
if api.GenericErrorMsg[T](rw, err, http.StatusBadRequest, "Decode error") {
|
|
return
|
|
}
|
|
t, err = c.provider.Add(claims, t)
|
|
if HttpCatchError(rw, err) {
|
|
return
|
|
}
|
|
if api.GenericErrorMsg[T](rw, err, http.StatusInternalServerError, "Add error") {
|
|
return
|
|
}
|
|
rw.Header().Set("Content-Type", "application/json")
|
|
rw.WriteHeader(http.StatusCreated)
|
|
err = json.NewEncoder(rw).Encode(&t)
|
|
if api.GenericErrorMsg[T](rw, err, http.StatusInternalServerError, "Encode error") {
|
|
return
|
|
}
|
|
}
|
|
|
|
func (c *crudHandler[T]) handleGet(rw http.ResponseWriter, req *http.Request, claims *auth.AccessTokenClaims) {
|
|
vars := mux.Vars(req)
|
|
s, ok := vars["id"]
|
|
if !ok {
|
|
api.GenericErrorMsg[T](rw, api.ErrParamMissing, http.StatusBadRequest, "Parameter error")
|
|
return
|
|
}
|
|
t, found, err := c.provider.Get(claims, s)
|
|
if HttpCatchError(rw, err) {
|
|
return
|
|
}
|
|
if api.GenericErrorMsg[T](rw, err, http.StatusInternalServerError, "Get error") {
|
|
return
|
|
}
|
|
if !found {
|
|
api.GenericErrorMsg[T](rw, err, http.StatusNotFound, "Not Found")
|
|
return
|
|
}
|
|
rw.Header().Set("Content-Type", "application/json")
|
|
rw.WriteHeader(http.StatusOK)
|
|
err = json.NewEncoder(rw).Encode(&t)
|
|
if api.GenericErrorMsg[T](rw, err, http.StatusInternalServerError, "Encode error") {
|
|
return
|
|
}
|
|
}
|
|
|
|
func (c *crudHandler[T]) handlePut(rw http.ResponseWriter, req *http.Request, claims *auth.AccessTokenClaims) {
|
|
vars := mux.Vars(req)
|
|
s, ok := vars["id"]
|
|
if !ok {
|
|
api.GenericErrorMsg[T](rw, api.ErrParamMissing, http.StatusBadRequest, "Parameter error")
|
|
return
|
|
}
|
|
var t T
|
|
err := json.NewDecoder(req.Body).Decode(&t)
|
|
if api.GenericErrorMsg[T](rw, err, http.StatusBadRequest, "Decode error") {
|
|
return
|
|
}
|
|
err = c.provider.Put(claims, s, t)
|
|
if HttpCatchError(rw, err) {
|
|
return
|
|
}
|
|
if api.GenericErrorMsg[T](rw, err, http.StatusInternalServerError, "Put error") {
|
|
return
|
|
}
|
|
rw.WriteHeader(http.StatusNoContent)
|
|
}
|
|
|
|
func (c *crudHandler[T]) handlePatch(rw http.ResponseWriter, req *http.Request, claims *auth.AccessTokenClaims) {
|
|
vars := mux.Vars(req)
|
|
s, ok := vars["id"]
|
|
if !ok {
|
|
api.GenericErrorMsg[T](rw, api.ErrParamMissing, http.StatusBadRequest, "Parameter error")
|
|
return
|
|
}
|
|
var t T
|
|
err := json.NewDecoder(req.Body).Decode(&t)
|
|
if api.GenericErrorMsg[T](rw, err, http.StatusBadRequest, "Decode error") {
|
|
return
|
|
}
|
|
err = c.provider.Patch(claims, s, t)
|
|
if HttpCatchError(rw, err) {
|
|
return
|
|
}
|
|
if api.GenericErrorMsg[T](rw, err, http.StatusInternalServerError, "Patch error") {
|
|
return
|
|
}
|
|
rw.WriteHeader(http.StatusNoContent)
|
|
}
|
|
|
|
func (c *crudHandler[T]) handleDelete(rw http.ResponseWriter, req *http.Request, claims *auth.AccessTokenClaims) {
|
|
vars := mux.Vars(req)
|
|
s, ok := vars["id"]
|
|
if !ok {
|
|
api.GenericErrorMsg[T](rw, api.ErrParamMissing, http.StatusBadRequest, "Parameter error")
|
|
return
|
|
}
|
|
err := c.provider.Delete(claims, s)
|
|
if HttpCatchError(rw, err) {
|
|
return
|
|
}
|
|
if api.GenericErrorMsg[T](rw, err, http.StatusInternalServerError, "Delete error") {
|
|
return
|
|
}
|
|
rw.WriteHeader(http.StatusNoContent)
|
|
}
|