switch to zero log

This commit is contained in:
Hayden 2022-09-03 10:38:35 -08:00
parent 9351b3fd42
commit 68204a4f22
26 changed files with 122 additions and 1335 deletions

View file

@ -2,11 +2,9 @@ package v1
import (
"github.com/hay-kot/content/backend/internal/services"
"github.com/hay-kot/content/backend/pkgs/logger"
)
type V1Controller struct {
log *logger.Logger
svc *services.AllServices
}
@ -19,9 +17,8 @@ func BaseUrlFunc(prefix string) func(s string) string {
return prefixFunc
}
func NewControllerV1(log *logger.Logger, svc *services.AllServices) *V1Controller {
func NewControllerV1(svc *services.AllServices) *V1Controller {
ctrl := &V1Controller{
log: log,
svc: svc,
}

View file

@ -9,12 +9,10 @@ import (
func Test_NewHandlerV1(t *testing.T) {
v1Base := BaseUrlFunc("/testing/v1")
ctrl := NewControllerV1(mockHandler.log, mockHandler.svc)
ctrl := NewControllerV1(mockHandler.svc)
assert.NotNil(t, ctrl)
assert.Equal(t, ctrl.log, mockHandler.log)
assert.Equal(t, "/testing/v1/v1/abc123", v1Base("/abc123"))
assert.Equal(t, "/testing/v1/v1/abc123", v1Base("/abc123"))
}

View file

@ -39,7 +39,6 @@ func userPool() func() {
func TestMain(m *testing.M) {
// Set Handler Vars
mockHandler.log = mocks.GetStructLogger()
repos, closeDb := mocks.GetEntRepos()
mockHandler.svc = mocks.GetMockServices(repos)

View file

@ -7,8 +7,8 @@ import (
"github.com/google/uuid"
"github.com/hay-kot/content/backend/internal/services"
"github.com/hay-kot/content/backend/internal/types"
"github.com/hay-kot/content/backend/pkgs/logger"
"github.com/hay-kot/content/backend/pkgs/server"
"github.com/rs/zerolog/log"
)
/*
@ -24,9 +24,7 @@ and makes it a little more consistent when error handling and logging.
func (ctrl *V1Controller) partialParseIdAndUser(w http.ResponseWriter, r *http.Request) (uuid.UUID, *types.UserOut, error) {
uid, err := uuid.Parse(chi.URLParam(r, "id"))
if err != nil {
ctrl.log.Debug(err.Error(), logger.Props{
"details": "failed to convert id to valid UUID",
})
log.Err(err).Msg("failed to parse id")
server.RespondError(w, http.StatusBadRequest, err)
return uuid.Nil, nil, err
}

View file

@ -1,207 +0,0 @@
package v1
import (
"errors"
"net/http"
"github.com/go-chi/chi/v5"
"github.com/google/uuid"
"github.com/hay-kot/content/backend/internal/services"
"github.com/hay-kot/content/backend/internal/types"
"github.com/hay-kot/content/backend/pkgs/hasher"
"github.com/hay-kot/content/backend/pkgs/logger"
"github.com/hay-kot/content/backend/pkgs/server"
)
// HandleAdminUserGetAll godoc
// @Summary Gets all users from the database
// @Tags Admin: Users
// @Produce json
// @Success 200 {object} server.Result{item=[]ent.User}
// @Router /v1/admin/users [get]
// @Security Bearer
func (ctrl *V1Controller) HandleAdminUserGetAll() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
users, err := ctrl.svc.Admin.GetAll(r.Context())
if err != nil {
server.RespondError(w, http.StatusInternalServerError, err)
return
}
server.Respond(w, http.StatusOK, server.Wrap(users))
}
}
// HandleAdminUserGet godoc
// @Summary Get a user from the database
// @Tags Admin: Users
// @Produce json
// @Param id path string true "User ID"
// @Success 200 {object} server.Result{item=ent.User}
// @Router /v1/admin/users/{id} [get]
// @Security Bearer
func (ctrl *V1Controller) HandleAdminUserGet() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
uid, err := uuid.Parse(chi.URLParam(r, "id"))
if err != nil {
ctrl.log.Debug(err.Error(), logger.Props{
"scope": "admin",
"details": "failed to convert id to valid UUID",
})
server.RespondError(w, http.StatusBadRequest, err)
return
}
user, err := ctrl.svc.Admin.GetByID(r.Context(), uid)
if err != nil {
ctrl.log.Error(err, nil)
server.RespondError(w, http.StatusInternalServerError, err)
return
}
server.Respond(w, http.StatusOK, server.Wrap(user))
}
}
// HandleAdminUserCreate godoc
// @Summary Create a new user
// @Tags Admin: Users
// @Produce json
// @Param payload body types.UserCreate true "User Data"
// @Success 200 {object} server.Result{item=ent.User}
// @Router /v1/admin/users [POST]
// @Security Bearer
func (ctrl *V1Controller) HandleAdminUserCreate() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
createData := types.UserCreate{}
if err := server.Decode(r, &createData); err != nil {
ctrl.log.Error(err, logger.Props{
"scope": "admin",
"details": "failed to decode user create data",
})
server.RespondError(w, http.StatusBadRequest, err)
return
}
err := createData.Validate()
if err != nil {
server.RespondError(w, http.StatusUnprocessableEntity, err)
return
}
hashedPw, err := hasher.HashPassword(createData.Password)
if err != nil {
ctrl.log.Error(err, logger.Props{
"scope": "admin",
"details": "failed to hash password",
})
server.RespondError(w, http.StatusInternalServerError, err)
return
}
createData.Password = hashedPw
userOut, err := ctrl.svc.Admin.Create(r.Context(), createData)
if err != nil {
ctrl.log.Error(err, logger.Props{
"scope": "admin",
"details": "failed to create user",
})
server.RespondError(w, http.StatusInternalServerError, err)
return
}
server.Respond(w, http.StatusCreated, server.Wrap(userOut))
}
}
// HandleAdminUserUpdate godoc
// @Summary Update a User
// @Tags Admin: Users
// @Param id path string true "User ID"
// @Param payload body types.UserUpdate true "User Data"
// @Produce json
// @Success 200 {object} server.Result{item=ent.User}
// @Router /v1/admin/users/{id} [PUT]
// @Security Bearer
func (ctrl *V1Controller) HandleAdminUserUpdate() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
uid, err := uuid.Parse(chi.URLParam(r, "id"))
if err != nil {
ctrl.log.Debug(err.Error(), logger.Props{
"scope": "admin",
"details": "failed to convert id to valid UUID",
})
}
updateData := types.UserUpdate{}
if err := server.Decode(r, &updateData); err != nil {
ctrl.log.Error(err, logger.Props{
"scope": "admin",
"details": "failed to decode user update data",
})
server.RespondError(w, http.StatusBadRequest, err)
return
}
newData, err := ctrl.svc.Admin.UpdateProperties(r.Context(), uid, updateData)
if err != nil {
ctrl.log.Error(err, logger.Props{
"scope": "admin",
"details": "failed to update user",
})
server.RespondError(w, http.StatusInternalServerError, err)
return
}
server.Respond(w, http.StatusOK, server.Wrap(newData))
}
}
// HandleAdminUserDelete godoc
// @Summary Delete a User
// @Tags Admin: Users
// @Param id path string true "User ID"
// @Produce json
// @Success 204
// @Router /v1/admin/users/{id} [DELETE]
// @Security Bearer
func (ctrl *V1Controller) HandleAdminUserDelete() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
uid, err := uuid.Parse(chi.URLParam(r, "id"))
if err != nil {
ctrl.log.Debug(err.Error(), logger.Props{
"scope": "admin",
"details": "failed to convert id to valid UUID",
})
}
actor := services.UseUserCtx(r.Context())
if actor.ID == uid {
server.RespondError(w, http.StatusBadRequest, errors.New("cannot delete yourself"))
return
}
err = ctrl.svc.Admin.Delete(r.Context(), uid)
if err != nil {
ctrl.log.Error(err, logger.Props{
"scope": "admin",
"details": "failed to delete user",
})
server.RespondError(w, http.StatusInternalServerError, err)
return
}
}
}

View file

@ -1,109 +0,0 @@
package v1
import (
"bytes"
"context"
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"testing"
"github.com/hay-kot/content/backend/ent"
"github.com/hay-kot/content/backend/internal/mocks/chimocker"
"github.com/hay-kot/content/backend/internal/mocks/factories"
"github.com/hay-kot/content/backend/pkgs/server"
"github.com/stretchr/testify/assert"
)
const (
UrlUser = "/api/v1/admin/users"
UrlUserId = "/api/v1/admin/users/%v"
UrlUserIdChi = "/api/v1/admin/users/{id}"
)
type usersResponse struct {
Users []*ent.User `json:"item"`
}
type userResponse struct {
User *ent.User `json:"item"`
}
func Test_HandleAdminUserGetAll_Success(t *testing.T) {
r := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, UrlUser, nil)
mockHandler.HandleAdminUserGetAll()(r, req)
response := usersResponse{
Users: []*ent.User{},
}
_ = json.Unmarshal(r.Body.Bytes(), &response)
assert.Equal(t, http.StatusOK, r.Code)
assert.Equal(t, len(users), len(response.Users))
knowEmail := []string{
users[0].Email,
users[1].Email,
users[2].Email,
users[3].Email,
}
for _, user := range users {
assert.Contains(t, knowEmail, user.Email)
}
}
func Test_HandleAdminUserGet_Success(t *testing.T) {
targetUser := users[2]
res := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, fmt.Sprintf(UrlUserId, targetUser.ID), nil)
req = chimocker.WithUrlParam(req, "id", fmt.Sprintf("%v", targetUser.ID))
mockHandler.HandleAdminUserGet()(res, req)
assert.Equal(t, http.StatusOK, res.Code)
response := userResponse{
User: &ent.User{},
}
_ = json.Unmarshal(res.Body.Bytes(), &response)
assert.Equal(t, targetUser.ID, response.User.ID)
}
func Test_HandleAdminUserCreate_Success(t *testing.T) {
payload := factories.UserFactory()
r := httptest.NewRecorder()
body, err := json.Marshal(payload)
assert.NoError(t, err)
req := httptest.NewRequest(http.MethodGet, UrlUser, bytes.NewBuffer(body))
req.Header.Set(server.ContentType, server.ContentJSON)
mockHandler.HandleAdminUserCreate()(r, req)
assert.Equal(t, http.StatusCreated, r.Code)
usr, err := mockHandler.svc.Admin.GetByEmail(context.Background(), payload.Email)
assert.NoError(t, err)
assert.Equal(t, payload.Email, usr.Email)
assert.Equal(t, payload.Name, usr.Name)
assert.NotEqual(t, payload.Password, usr.Password) // smoke test - check password is hashed
_ = mockHandler.svc.Admin.Delete(context.Background(), usr.ID)
}
func Test_HandleAdminUserUpdate_Success(t *testing.T) {
t.Skip()
}
func Test_HandleAdminUserUpdate_Delete(t *testing.T) {
t.Skip()
}

View file

@ -6,8 +6,8 @@ import (
"github.com/hay-kot/content/backend/internal/services"
"github.com/hay-kot/content/backend/internal/types"
"github.com/hay-kot/content/backend/pkgs/logger"
"github.com/hay-kot/content/backend/pkgs/server"
"github.com/rs/zerolog/log"
)
// HandleAuthLogin godoc
@ -28,7 +28,7 @@ func (ctrl *V1Controller) HandleAuthLogin() http.HandlerFunc {
err := r.ParseForm()
if err != nil {
server.Respond(w, http.StatusBadRequest, server.Wrap(err))
ctrl.log.Error(errors.New("failed to decode login form (FORM)"), logger.Props{"error": err.Error()})
log.Error().Err(err).Msg("failed to parse form")
return
}
@ -38,9 +38,7 @@ func (ctrl *V1Controller) HandleAuthLogin() http.HandlerFunc {
err := server.Decode(r, loginForm)
if err != nil {
ctrl.log.Error(errors.New("failed to decode login form (JSON)"), logger.Props{
"error": err.Error(),
})
log.Err(err).Msg("failed to decode login form")
server.Respond(w, http.StatusBadRequest, server.Wrap(err))
return
}

View file

@ -6,6 +6,7 @@ import (
"github.com/hay-kot/content/backend/internal/services"
"github.com/hay-kot/content/backend/internal/types"
"github.com/hay-kot/content/backend/pkgs/server"
"github.com/rs/zerolog/log"
)
// HandleItemsGetAll godoc
@ -20,7 +21,7 @@ func (ctrl *V1Controller) HandleItemsGetAll() http.HandlerFunc {
user := services.UseUserCtx(r.Context())
items, err := ctrl.svc.Items.GetAll(r.Context(), user.GroupID)
if err != nil {
ctrl.log.Error(err, nil)
log.Err(err).Msg("failed to get items")
server.RespondServerError(w)
return
}
@ -40,7 +41,7 @@ func (ctrl *V1Controller) HandleItemsCreate() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
createData := types.ItemCreate{}
if err := server.Decode(r, &createData); err != nil {
ctrl.log.Error(err, nil)
log.Err(err).Msg("failed to decode request body")
server.RespondError(w, http.StatusInternalServerError, err)
return
}
@ -48,7 +49,7 @@ func (ctrl *V1Controller) HandleItemsCreate() http.HandlerFunc {
user := services.UseUserCtx(r.Context())
item, err := ctrl.svc.Items.Create(r.Context(), user.GroupID, createData)
if err != nil {
ctrl.log.Error(err, nil)
log.Err(err).Msg("failed to create item")
server.RespondServerError(w)
return
}
@ -75,7 +76,7 @@ func (ctrl *V1Controller) HandleItemDelete() http.HandlerFunc {
err = ctrl.svc.Items.Delete(r.Context(), user.GroupID, uid)
if err != nil {
ctrl.log.Error(err, nil)
log.Err(err).Msg("failed to delete item")
server.RespondServerError(w)
return
}
@ -100,7 +101,7 @@ func (ctrl *V1Controller) HandleItemGet() http.HandlerFunc {
items, err := ctrl.svc.Items.GetOne(r.Context(), user.GroupID, uid)
if err != nil {
ctrl.log.Error(err, nil)
log.Err(err).Msg("failed to get item")
server.RespondServerError(w)
return
}
@ -120,7 +121,7 @@ func (ctrl *V1Controller) HandleItemUpdate() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
body := types.ItemUpdate{}
if err := server.Decode(r, &body); err != nil {
ctrl.log.Error(err, nil)
log.Err(err).Msg("failed to decode request body")
server.RespondError(w, http.StatusInternalServerError, err)
return
}
@ -132,7 +133,7 @@ func (ctrl *V1Controller) HandleItemUpdate() http.HandlerFunc {
body.ID = uid
result, err := ctrl.svc.Items.Update(r.Context(), user.GroupID, body)
if err != nil {
ctrl.log.Error(err, nil)
log.Err(err).Msg("failed to update item")
server.RespondServerError(w)
return
}

View file

@ -6,6 +6,7 @@ import (
"github.com/hay-kot/content/backend/internal/services"
"github.com/hay-kot/content/backend/internal/types"
"github.com/hay-kot/content/backend/pkgs/server"
"github.com/rs/zerolog/log"
)
// HandleLabelsGetAll godoc
@ -20,7 +21,7 @@ func (ctrl *V1Controller) HandleLabelsGetAll() http.HandlerFunc {
user := services.UseUserCtx(r.Context())
labels, err := ctrl.svc.Labels.GetAll(r.Context(), user.GroupID)
if err != nil {
ctrl.log.Error(err, nil)
log.Err(err).Msg("error getting labels")
server.RespondServerError(w)
return
}
@ -40,7 +41,7 @@ func (ctrl *V1Controller) HandleLabelsCreate() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
createData := types.LabelCreate{}
if err := server.Decode(r, &createData); err != nil {
ctrl.log.Error(err, nil)
log.Err(err).Msg("error decoding label create data")
server.RespondError(w, http.StatusInternalServerError, err)
return
}
@ -48,7 +49,7 @@ func (ctrl *V1Controller) HandleLabelsCreate() http.HandlerFunc {
user := services.UseUserCtx(r.Context())
label, err := ctrl.svc.Labels.Create(r.Context(), user.GroupID, createData)
if err != nil {
ctrl.log.Error(err, nil)
log.Err(err).Msg("error creating label")
server.RespondServerError(w)
return
}
@ -75,7 +76,7 @@ func (ctrl *V1Controller) HandleLabelDelete() http.HandlerFunc {
err = ctrl.svc.Labels.Delete(r.Context(), user.GroupID, uid)
if err != nil {
ctrl.log.Error(err, nil)
log.Err(err).Msg("error deleting label")
server.RespondServerError(w)
return
}
@ -100,7 +101,7 @@ func (ctrl *V1Controller) HandleLabelGet() http.HandlerFunc {
labels, err := ctrl.svc.Labels.Get(r.Context(), user.GroupID, uid)
if err != nil {
ctrl.log.Error(err, nil)
log.Err(err).Msg("error getting label")
server.RespondServerError(w)
return
}
@ -120,7 +121,7 @@ func (ctrl *V1Controller) HandleLabelUpdate() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
body := types.LabelUpdate{}
if err := server.Decode(r, &body); err != nil {
ctrl.log.Error(err, nil)
log.Err(err).Msg("error decoding label update data")
server.RespondError(w, http.StatusInternalServerError, err)
return
}
@ -132,7 +133,7 @@ func (ctrl *V1Controller) HandleLabelUpdate() http.HandlerFunc {
body.ID = uid
result, err := ctrl.svc.Labels.Update(r.Context(), user.GroupID, body)
if err != nil {
ctrl.log.Error(err, nil)
log.Err(err).Msg("error updating label")
server.RespondServerError(w)
return
}

View file

@ -6,6 +6,7 @@ import (
"github.com/hay-kot/content/backend/internal/services"
"github.com/hay-kot/content/backend/internal/types"
"github.com/hay-kot/content/backend/pkgs/server"
"github.com/rs/zerolog/log"
)
// HandleLocationGetAll godoc
@ -20,7 +21,7 @@ func (ctrl *V1Controller) HandleLocationGetAll() http.HandlerFunc {
user := services.UseUserCtx(r.Context())
locations, err := ctrl.svc.Location.GetAll(r.Context(), user.GroupID)
if err != nil {
ctrl.log.Error(err, nil)
log.Err(err).Msg("failed to get locations")
server.RespondServerError(w)
return
}
@ -41,7 +42,7 @@ func (ctrl *V1Controller) HandleLocationCreate() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
createData := types.LocationCreate{}
if err := server.Decode(r, &createData); err != nil {
ctrl.log.Error(err, nil)
log.Err(err).Msg("failed to decode location create data")
server.RespondError(w, http.StatusInternalServerError, err)
return
}
@ -49,7 +50,7 @@ func (ctrl *V1Controller) HandleLocationCreate() http.HandlerFunc {
user := services.UseUserCtx(r.Context())
location, err := ctrl.svc.Location.Create(r.Context(), user.GroupID, createData)
if err != nil {
ctrl.log.Error(err, nil)
log.Err(err).Msg("failed to create location")
server.RespondServerError(w)
return
}
@ -75,7 +76,7 @@ func (ctrl *V1Controller) HandleLocationDelete() http.HandlerFunc {
err = ctrl.svc.Location.Delete(r.Context(), user.GroupID, uid)
if err != nil {
ctrl.log.Error(err, nil)
log.Err(err).Msg("failed to delete location")
server.RespondServerError(w)
return
}
@ -100,7 +101,7 @@ func (ctrl *V1Controller) HandleLocationGet() http.HandlerFunc {
location, err := ctrl.svc.Location.GetOne(r.Context(), user.GroupID, uid)
if err != nil {
ctrl.log.Error(err, nil)
log.Err(err).Msg("failed to get location")
server.RespondServerError(w)
return
}
@ -120,7 +121,7 @@ func (ctrl *V1Controller) HandleLocationUpdate() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
body := types.LocationUpdate{}
if err := server.Decode(r, &body); err != nil {
ctrl.log.Error(err, nil)
log.Err(err).Msg("failed to decode location update data")
server.RespondError(w, http.StatusInternalServerError, err)
return
}
@ -134,7 +135,7 @@ func (ctrl *V1Controller) HandleLocationUpdate() http.HandlerFunc {
result, err := ctrl.svc.Location.Update(r.Context(), user.GroupID, body)
if err != nil {
ctrl.log.Error(err, nil)
log.Err(err).Msg("failed to update location")
server.RespondServerError(w)
return
}

View file

@ -1,14 +1,13 @@
package v1
import (
"errors"
"net/http"
"github.com/google/uuid"
"github.com/hay-kot/content/backend/internal/services"
"github.com/hay-kot/content/backend/internal/types"
"github.com/hay-kot/content/backend/pkgs/logger"
"github.com/hay-kot/content/backend/pkgs/server"
"github.com/rs/zerolog/log"
)
// HandleUserSelf godoc
@ -23,14 +22,13 @@ func (ctrl *V1Controller) HandleUserRegistration() http.HandlerFunc {
regData := types.UserRegistration{}
if err := server.Decode(r, &regData); err != nil {
ctrl.log.Error(err, nil)
log.Err(err).Msg("failed to decode user registration data")
server.RespondError(w, http.StatusInternalServerError, err)
return
}
_, err := ctrl.svc.User.RegisterUser(r.Context(), regData)
if err != nil {
ctrl.log.Error(err, nil)
server.RespondError(w, http.StatusInternalServerError, err)
return
}
@ -51,7 +49,7 @@ func (ctrl *V1Controller) HandleUserSelf() http.HandlerFunc {
token := services.UseTokenCtx(r.Context())
usr, err := ctrl.svc.User.GetSelf(r.Context(), token)
if usr.ID == uuid.Nil || err != nil {
ctrl.log.Error(errors.New("no user within request context"), nil)
log.Err(err).Msg("failed to get user")
server.RespondServerError(w)
return
}
@ -72,10 +70,7 @@ func (ctrl *V1Controller) HandleUserUpdate() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
updateData := types.UserUpdate{}
if err := server.Decode(r, &updateData); err != nil {
ctrl.log.Error(err, logger.Props{
"scope": "user",
"details": "failed to decode user update data",
})
log.Err(err).Msg("failed to decode user update data")
server.RespondError(w, http.StatusBadRequest, err)
return
}
@ -84,10 +79,7 @@ func (ctrl *V1Controller) HandleUserUpdate() http.HandlerFunc {
newData, err := ctrl.svc.User.UpdateSelf(r.Context(), actor.ID, updateData)
if err != nil {
ctrl.log.Error(err, logger.Props{
"scope": "user",
"details": "failed to update user",
})
server.RespondError(w, http.StatusInternalServerError, err)
return
}