Skip to content

Commit

Permalink
Merge pull request #21 from alexferl/cleanup_models
Browse files Browse the repository at this point in the history
cleaned up models and added more tests
  • Loading branch information
alexferl authored Mar 15, 2024
2 parents 4a39e29 + 20d62f2 commit 9466eca
Show file tree
Hide file tree
Showing 37 changed files with 553 additions and 440 deletions.
10 changes: 5 additions & 5 deletions casbin/policy.csv
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ p, user, /me/personal_access_tokens/:id, (GET)|(DELETE)
p, user, /tasks, (GET)|(POST)
p, user, /tasks/:id, (GET)|(PATCH)|(DELETE)
p, user, /tasks/:id/transition, PUT
p, user, /users/:id_or_username, GET
p, user, /users/:username, GET

p, admin, /users, GET
p, admin, /users/:id_or_username, PATCH
p, admin, /users/:id_or_username/ban, (PUT)|(DELETE)
p, admin, /users/:id_or_username/lock, (PUT)|(DELETE)
p, admin, /users/:id_or_username/roles/:role, (PUT)|(DELETE)
p, admin, /users/:username, PATCH
p, admin, /users/:username/ban, (PUT)|(DELETE)
p, admin, /users/:username/lock, (PUT)|(DELETE)
p, admin, /users/:username/roles/:role, (PUT)|(DELETE)

g, *, any
g, user, any
Expand Down
29 changes: 15 additions & 14 deletions handlers/mock_PersonalAccessTokenService.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 8 additions & 6 deletions handlers/personal_access_token.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (

type PersonalAccessTokenService interface {
Create(ctx context.Context, model *models.PersonalAccessToken) (*models.PersonalAccessToken, error)
Read(ctx context.Context, id string) (*models.PersonalAccessToken, error)
Read(ctx context.Context, userId string, id string) (*models.PersonalAccessToken, error)
Find(ctx context.Context, userId string) (models.PersonalAccessTokens, error)
FindOne(ctx context.Context, userId string, name string) (*models.PersonalAccessToken, error)
Revoke(ctx context.Context, model *models.PersonalAccessToken) error
Expand All @@ -43,8 +43,8 @@ func NewPersonalAccessTokenHandler(openapi *openapi.Handler, svc PersonalAccessT
}

type CreatePersonalAccessTokenRequest struct {
Name string `json:"name" bson:"name"`
ExpiresAt string `json:"expires_at" bson:"expires_at"`
Name string `json:"name"`
ExpiresAt string `json:"expires_at"`
}

func (h *PersonalAccessTokenHandler) create(c echo.Context) error {
Expand Down Expand Up @@ -99,7 +99,7 @@ func (h *PersonalAccessTokenHandler) create(c echo.Context) error {

pat.Token = decodedToken

return h.Validate(c, http.StatusOK, pat.Response())
return h.Validate(c, http.StatusOK, pat.CreateResponse())
}

func (h *PersonalAccessTokenHandler) list(c echo.Context) error {
Expand All @@ -119,11 +119,12 @@ func (h *PersonalAccessTokenHandler) list(c echo.Context) error {

func (h *PersonalAccessTokenHandler) get(c echo.Context) error {
id := c.Param("id")
currentUser := c.Get("user").(*models.User)

ctx, cancel := context.WithTimeout(c.Request().Context(), time.Second*10)
defer cancel()

pat, err := h.svc.Read(ctx, id)
pat, err := h.svc.Read(ctx, currentUser.Id, id)
if err != nil {
var se *services.Error
if errors.As(err, &se) {
Expand All @@ -140,11 +141,12 @@ func (h *PersonalAccessTokenHandler) get(c echo.Context) error {

func (h *PersonalAccessTokenHandler) revoke(c echo.Context) error {
id := c.Param("id")
currentUser := c.Get("user").(*models.User)

ctx, cancel := context.WithTimeout(c.Request().Context(), time.Second*10)
defer cancel()

pat, err := h.svc.Read(ctx, id)
pat, err := h.svc.Read(ctx, currentUser.Id, id)
if err != nil {
var se *services.Error
if errors.As(err, &se) {
Expand Down
10 changes: 5 additions & 5 deletions handlers/personal_access_token_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ func (s *PersonalAccessTokenHandlerTestSuite) TestPersonalAccessTokenHandler_Get
Return(s.user, nil).Once()

s.svc.EXPECT().
Read(mock.Anything, mock.Anything).
Read(mock.Anything, mock.Anything, mock.Anything).
Return(newPAT, nil)

s.server.ServeHTTP(resp, req)
Expand All @@ -265,7 +265,7 @@ func (s *PersonalAccessTokenHandlerTestSuite) TestPersonalAccessTokenHandler_Get
Return(s.user, nil).Once()

s.svc.EXPECT().
Read(mock.Anything, mock.Anything).
Read(mock.Anything, mock.Anything, mock.Anything).
Return(nil, &services.Error{
Kind: services.NotExist,
Message: services.ErrPersonalAccessTokenNotFound.Error(),
Expand Down Expand Up @@ -298,7 +298,7 @@ func (s *PersonalAccessTokenHandlerTestSuite) TestPersonalAccessTokenHandler_Rev
Return(s.user, nil).Once()

s.svc.EXPECT().
Read(mock.Anything, mock.Anything).
Read(mock.Anything, mock.Anything, mock.Anything).
Return(newPAT, nil)

s.svc.EXPECT().
Expand Down Expand Up @@ -332,7 +332,7 @@ func (s *PersonalAccessTokenHandlerTestSuite) TestPersonalAccessTokenHandler_Rev
Return(s.user, nil).Once()

s.svc.EXPECT().
Read(mock.Anything, mock.Anything).
Read(mock.Anything, mock.Anything, mock.Anything).
Return(nil, &services.Error{
Kind: services.NotExist,
Message: services.ErrPersonalAccessTokenNotFound.Error(),
Expand Down Expand Up @@ -366,7 +366,7 @@ func (s *PersonalAccessTokenHandlerTestSuite) TestPersonalAccessTokenHandler_Rev
Return(s.user, nil).Once()

s.svc.EXPECT().
Read(mock.Anything, mock.Anything).
Read(mock.Anything, mock.Anything, mock.Anything).
Return(newPAT, nil)

s.server.ServeHTTP(resp, req)
Expand Down
41 changes: 23 additions & 18 deletions handlers/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,14 @@ func NewUserHandler(openapi *openapi.Handler, svc UserService) *UserHandler {
func (h *UserHandler) Register(s *server.Server) {
s.Add(http.MethodGet, "/me", h.getCurrentUser)
s.Add(http.MethodPatch, "/me", h.updateCurrentUser)
s.Add(http.MethodGet, "/users/:id_or_username", h.get)
s.Add(http.MethodPatch, "/users/:id_or_username", h.update)
s.Add(http.MethodPut, "/users/:id_or_username/ban", h.ban)
s.Add(http.MethodDelete, "/users/:id_or_username/ban", h.unban)
s.Add(http.MethodPut, "/users/:id_or_username/lock", h.lock)
s.Add(http.MethodDelete, "/users/:id_or_username/lock", h.unlock)
s.Add(http.MethodPut, "/users/:id_or_username/roles/:role", h.addRole)
s.Add(http.MethodDelete, "/users/:id_or_username/roles/:role", h.removeRole)
s.Add(http.MethodGet, "/users/:username", h.get)
s.Add(http.MethodPatch, "/users/:username", h.update)
s.Add(http.MethodPut, "/users/:username/ban", h.ban)
s.Add(http.MethodDelete, "/users/:username/ban", h.unban)
s.Add(http.MethodPut, "/users/:username/lock", h.lock)
s.Add(http.MethodDelete, "/users/:username/lock", h.unlock)
s.Add(http.MethodPut, "/users/:username/roles/:role", h.addRole)
s.Add(http.MethodDelete, "/users/:username/roles/:role", h.removeRole)
s.Add(http.MethodGet, "/users", h.list)
}

Expand Down Expand Up @@ -107,7 +107,8 @@ func (h *UserHandler) updateCurrentUser(c echo.Context) error {
}

func (h *UserHandler) get(c echo.Context) error {
id := c.Param("id_or_username")
id := c.Param("username")
currentUser := c.Get("user").(*models.User)

ctx, cancel := context.WithTimeout(c.Request().Context(), time.Second*10)
defer cancel()
Expand All @@ -120,6 +121,10 @@ func (h *UserHandler) get(c echo.Context) error {
}
}

if currentUser.HasRoleOrHigher(models.AdminRole) {
return h.Validate(c, http.StatusOK, user.AdminResponse())
}

return h.Validate(c, http.StatusOK, user.Response())
}

Expand All @@ -129,7 +134,7 @@ type UpdateUserRequest struct {
}

func (h *UserHandler) update(c echo.Context) error {
id := c.Param("id_or_username")
id := c.Param("username")
currentUser := c.Get("user").(*models.User)

body := &UpdateUserRequest{}
Expand Down Expand Up @@ -163,11 +168,11 @@ func (h *UserHandler) update(c echo.Context) error {
return err
}

return h.Validate(c, http.StatusOK, res.Response())
return h.Validate(c, http.StatusOK, res.AdminResponse())
}

func (h *UserHandler) ban(c echo.Context) error {
id := c.Param("id_or_username")
id := c.Param("username")
currentUser := c.Get("user").(*models.User)

ctx, cancel := context.WithTimeout(c.Request().Context(), time.Second*10)
Expand Down Expand Up @@ -199,7 +204,7 @@ func (h *UserHandler) ban(c echo.Context) error {
}

func (h *UserHandler) unban(c echo.Context) error {
id := c.Param("id_or_username")
id := c.Param("username")
currentUser := c.Get("user").(*models.User)

ctx, cancel := context.WithTimeout(c.Request().Context(), time.Second*10)
Expand Down Expand Up @@ -231,7 +236,7 @@ func (h *UserHandler) unban(c echo.Context) error {
}

func (h *UserHandler) lock(c echo.Context) error {
id := c.Param("id_or_username")
id := c.Param("username")
currentUser := c.Get("user").(*models.User)

ctx, cancel := context.WithTimeout(c.Request().Context(), time.Second*10)
Expand Down Expand Up @@ -263,7 +268,7 @@ func (h *UserHandler) lock(c echo.Context) error {
}

func (h *UserHandler) unlock(c echo.Context) error {
id := c.Param("id_or_username")
id := c.Param("username")
currentUser := c.Get("user").(*models.User)

ctx, cancel := context.WithTimeout(c.Request().Context(), time.Second*10)
Expand Down Expand Up @@ -295,7 +300,7 @@ func (h *UserHandler) unlock(c echo.Context) error {
}

func (h *UserHandler) addRole(c echo.Context) error {
id := c.Param("id_or_username")
id := c.Param("username")
role := c.Param("role")
currentUser := c.Get("user").(*models.User)

Expand Down Expand Up @@ -328,7 +333,7 @@ func (h *UserHandler) addRole(c echo.Context) error {
}

func (h *UserHandler) removeRole(c echo.Context) error {
id := c.Param("id_or_username")
id := c.Param("username")
role := c.Param("role")
currentUser := c.Get("user").(*models.User)

Expand Down Expand Up @@ -378,7 +383,7 @@ func (h *UserHandler) list(c echo.Context) error {

pagination.SetHeaders(c.Request(), c.Response().Header(), int(count), page, perPage)

return h.Validate(c, http.StatusOK, users.Public())
return h.Validate(c, http.StatusOK, users.AdminResponse())
}

func (h *UserHandler) readUser(c echo.Context, err error) func() error {
Expand Down
28 changes: 26 additions & 2 deletions handlers/user_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,30 @@ func (s *UserHandlerTestSuite) TestUserHandler_Get_200() {
s.Assert().Equal(s.user.Id, result.Id)
}

func (s *UserHandlerTestSuite) TestUserHandler_Get_200_Admin() {
req := httptest.NewRequest(http.MethodGet, "/users/1", nil)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", s.adminAccessToken))
resp := httptest.NewRecorder()

// middleware
s.svc.EXPECT().
Read(mock.Anything, mock.Anything).
Return(s.admin, nil).Once()

s.svc.EXPECT().
Read(mock.Anything, mock.Anything).
Return(s.user, nil).Once()

s.server.ServeHTTP(resp, req)

var result models.UserAdminResponse
_ = json.Unmarshal(resp.Body.Bytes(), &result)

s.Assert().Equal(http.StatusOK, resp.Code)
s.Assert().Equal(s.user.Id, result.Id)
}

func (s *UserHandlerTestSuite) TestUserHandler_Update_200() {
updatedUser := s.user
updatedUser.Name = "updated name"
Expand Down Expand Up @@ -185,7 +209,7 @@ func (s *UserHandlerTestSuite) TestUserHandler_Update_200() {

s.server.ServeHTTP(resp, req)

var result models.UserResponse
var result models.UserAdminResponse
_ = json.Unmarshal(resp.Body.Bytes(), &result)

s.Assert().Equal(http.StatusOK, resp.Code)
Expand Down Expand Up @@ -562,7 +586,7 @@ func (s *UserHandlerTestSuite) TestUserHandler_List_200() {

s.server.ServeHTTP(resp, req)

var result models.PublicUsersResponse
var result models.UsersAdminResponse
_ = json.Unmarshal(resp.Body.Bytes(), &result)

h := resp.Header()
Expand Down
24 changes: 12 additions & 12 deletions models/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,24 @@ import (
// Model is the base model for all models.
// NewModel should be used unless you know what you're doing.
type Model struct {
Id string `json:"id" bson:"id"`
CreatedAt *time.Time `json:"created_at" bson:"created_at"`
CreatedBy any `json:"created_by" bson:"created_by"`
DeletedAt *time.Time `json:"deleted_at" bson:"deleted_at"`
DeletedBy any `json:"deleted_by" bson:"deleted_by"`
UpdatedAt *time.Time `json:"updated_at" bson:"updated_at"`
UpdatedBy any `json:"updated_by" bson:"updated_by"`
Id string `bson:"id"`
CreatedAt *time.Time `bson:"created_at"`
CreatedBy any `bson:"created_by"`
DeletedAt *time.Time `bson:"deleted_at"`
DeletedBy any `bson:"deleted_by"`
UpdatedAt *time.Time `bson:"updated_at"`
UpdatedBy any `bson:"updated_by"`
}

// Ref is a reference to another document
// Ref is a reference to another document.
type Ref struct {
Id string `json:"id" bson:"id"`
}

func NewModel() *Model {
return &Model{Id: xid.New().String()}
}

func (m *Model) Create(id string) {
t := time.Now()
m.CreatedAt = &t
Expand All @@ -40,7 +44,3 @@ func (m *Model) Update(id string) {
m.UpdatedAt = &t
m.UpdatedBy = &Ref{Id: id}
}

func NewModel() *Model {
return &Model{Id: xid.New().String()}
}
Loading

0 comments on commit 9466eca

Please sign in to comment.