Skip to content

Commit

Permalink
✅ Add namespace update ut (#287)
Browse files Browse the repository at this point in the history
  • Loading branch information
tosone authored Jan 29, 2024
1 parent 4c75b09 commit ea0c9f5
Show file tree
Hide file tree
Showing 34 changed files with 734 additions and 397 deletions.
14 changes: 11 additions & 3 deletions pkg/auth/artifact.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,29 @@
package auth

import (
"errors"
"fmt"

"github.com/labstack/echo/v4"
"github.com/rs/zerolog/log"
"gorm.io/gorm"

"github.com/go-sigma/sigma/pkg/types/enums"
)

// Tag ...
func (s service) Artifact(c echo.Context, artifactID int64, auth enums.Auth) bool {
func (s service) Artifact(c echo.Context, artifactID int64, auth enums.Auth) (bool, error) {
ctx := log.Logger.WithContext(c.Request().Context())

artifactService := s.artifactServiceFactory.New()
artifactObj, err := artifactService.Get(ctx, artifactID)
if err != nil {
log.Error().Err(err).Msg("Get artifact by id failed")
return false
if !errors.Is(err, gorm.ErrRecordNotFound) {
log.Error().Err(err).Int64("artifactID", artifactID).Msg("Get artifact by id failed")
return false, errors.Join(err, fmt.Errorf("Get artifact by id(%d) failed", artifactID))
}
log.Error().Err(err).Int64("artifactID", artifactID).Msg("Get artifact by id not found")
return false, errors.Join(err, fmt.Errorf("Get artifact by id(%d) not found", artifactID))
}
return s.Repository(c, artifactObj.RepositoryID, auth)
}
8 changes: 4 additions & 4 deletions pkg/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ import (
// Service is the interface for the auth service
type Service interface {
// Namespace ...
Namespace(c echo.Context, namespaceID int64, auth enums.Auth) bool
Namespace(c echo.Context, namespaceID int64, auth enums.Auth) (bool, error)
// Repository ...
Repository(c echo.Context, repositoryID int64, auth enums.Auth) bool
Repository(c echo.Context, repositoryID int64, auth enums.Auth) (bool, error)
// Tag ...
Tag(c echo.Context, tagID int64, auth enums.Auth) bool
Tag(c echo.Context, tagID int64, auth enums.Auth) (bool, error)
// Artifact ...
Artifact(c echo.Context, artifactID int64, auth enums.Auth) bool
Artifact(c echo.Context, artifactID int64, auth enums.Auth) (bool, error)
}

// ServiceFactory is the interface that provides the artifact service factory methods.
Expand Down
20 changes: 12 additions & 8 deletions pkg/auth/mocks/service.go

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

33 changes: 19 additions & 14 deletions pkg/auth/namespace.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package auth

import (
"errors"
"fmt"

"github.com/labstack/echo/v4"
"github.com/rs/zerolog/log"
Expand All @@ -27,53 +28,57 @@ import (
)

// Namespace ...
func (s service) Namespace(c echo.Context, namespaceID int64, auth enums.Auth) bool {
func (s service) Namespace(c echo.Context, namespaceID int64, auth enums.Auth) (bool, error) {
ctx := log.Logger.WithContext(c.Request().Context())

iuser := c.Get(consts.ContextUser)
if iuser == nil {
log.Error().Msg("Get user from header failed")
return false
return false, nil
}
user, ok := iuser.(*models.User)
if !ok {
log.Error().Msg("Convert user from header failed")
return false
return false, nil
}

// 1. check user is admin or not
if user.Role == enums.UserRoleAdmin || user.Role == enums.UserRoleRoot {
return true
return true, nil
}

// 2. check namespace visibility
namespaceService := s.namespaceServiceFactory.New()
namespaceObj, err := namespaceService.Get(ctx, namespaceID)
if err != nil {
log.Error().Err(err).Msg("Get namespace by id failed")
return false
if !errors.Is(err, gorm.ErrRecordNotFound) {
log.Error().Err(err).Msg("Get namespace by id failed")
return false, errors.Join(err, fmt.Errorf("Get namespace by id(%d) failed", namespaceID))
}
log.Error().Err(err).Msg("Get namespace by id not found")
return false, errors.Join(err, fmt.Errorf("Get namespace by id(%d) not found", namespaceID))
}
if namespaceObj.Visibility == enums.VisibilityPublic && auth == enums.AuthRead {
return true
return true, nil
}

// 3. check user is member of the namespace
roleService := s.roleServiceFactory.New()
namespaceMemberObj, err := roleService.GetNamespaceMember(ctx, namespaceID, user.ID)
if err != nil {
if !errors.Is(err, gorm.ErrRecordNotFound) {
log.Error().Err(err).Msg("Get namespace member failed")
if !errors.Is(err, gorm.ErrRecordNotFound) { // check user's role in this namespace
log.Error().Err(err).Msg("Get namespace member by namespace id and user id failed")
}
return false
return false, err
}
if namespaceMemberObj.Role == enums.NamespaceRoleReader && auth == enums.AuthRead {
return true
return true, nil
}
if namespaceMemberObj.Role == enums.NamespaceRoleManager && (auth == enums.AuthManage || auth == enums.AuthRead) {
return true
return true, nil
}
if namespaceMemberObj.Role == enums.NamespaceRoleAdmin && (auth == enums.AuthAdmin || auth == enums.AuthManage || auth == enums.AuthRead) {
return true
return true, nil
}
return false
return false, nil
}
14 changes: 11 additions & 3 deletions pkg/auth/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,28 @@
package auth

import (
"errors"
"fmt"

"github.com/labstack/echo/v4"
"github.com/rs/zerolog/log"
"gorm.io/gorm"

"github.com/go-sigma/sigma/pkg/types/enums"
)

// Repository ...
func (s service) Repository(c echo.Context, repositoryID int64, auth enums.Auth) bool {
func (s service) Repository(c echo.Context, repositoryID int64, auth enums.Auth) (bool, error) {
ctx := log.Logger.WithContext(c.Request().Context())
repositoryService := s.repositoryServiceFactory.New()
repositoryObj, err := repositoryService.Get(ctx, repositoryID)
if err != nil {
log.Error().Err(err).Msg("Get repository by id failed")
return false
if !errors.Is(err, gorm.ErrRecordNotFound) {
log.Error().Err(err).Int64("repositoryID", repositoryID).Msg("Get repository by id failed")
return false, errors.Join(err, fmt.Errorf("Get repository by id(%d) failed", repositoryID))
}
log.Error().Err(err).Int64("repositoryID", repositoryID).Msg("Get repository by id not found")
return false, errors.Join(err, fmt.Errorf("Get repository by id(%d) not found", repositoryID))
}
return s.Namespace(c, repositoryObj.NamespaceID, auth)
}
14 changes: 11 additions & 3 deletions pkg/auth/tag.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,29 @@
package auth

import (
"errors"
"fmt"

"github.com/labstack/echo/v4"
"github.com/rs/zerolog/log"
"gorm.io/gorm"

"github.com/go-sigma/sigma/pkg/types/enums"
)

// Tag ...
func (s service) Tag(c echo.Context, tagID int64, auth enums.Auth) bool {
func (s service) Tag(c echo.Context, tagID int64, auth enums.Auth) (bool, error) {
ctx := log.Logger.WithContext(c.Request().Context())

tagService := s.tagServiceFactory.New()
tagObj, err := tagService.GetByID(ctx, tagID)
if err != nil {
log.Error().Err(err).Msg("Get tag by id failed")
return false
if !errors.Is(err, gorm.ErrRecordNotFound) {
log.Error().Err(err).Int64("tagID", tagID).Msg("Get tag by id failed")
return false, errors.Join(err, fmt.Errorf("Get tag by id(%d) failed", tagID))
}
log.Error().Err(err).Int64("tagID", tagID).Msg("Get tag by id not found")
return false, errors.Join(err, fmt.Errorf("Get tag by id(%d) not found", tagID))
}
return s.Repository(c, tagObj.RepositoryID, auth)
}
17 changes: 13 additions & 4 deletions pkg/handlers/distribution/base/tags_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
"github.com/go-sigma/sigma/pkg/consts"
"github.com/go-sigma/sigma/pkg/dal/models"
"github.com/go-sigma/sigma/pkg/types/enums"
"github.com/go-sigma/sigma/pkg/utils"
"github.com/go-sigma/sigma/pkg/xerrors"
)

Expand Down Expand Up @@ -79,12 +80,20 @@ func (h *handler) ListTags(c echo.Context) error {
return xerrors.NewDSError(c, xerrors.DSErrCodeUnknown)
}

if !h.authServiceFactory.New().Repository(c, repositoryObj.ID, enums.AuthRead) {
log.Error().Int64("UserID", user.ID).Int64("NamespaceID", repositoryObj.ID).Msg("Auth check failed")
return xerrors.NewHTTPError(c, xerrors.HTTPErrCodeUnauthorized, "No permission with this api")
authChecked, err := h.authServiceFactory.New().Repository(c, repositoryObj.ID, enums.AuthRead)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
log.Error().Err(errors.New(utils.UnwrapJoinedErrors(err))).Msg("Resource not found")
return xerrors.GenDSErrCodeResourceNotFound(err)
}
return xerrors.NewDSError(c, xerrors.DSErrCodeUnknown)
}
if !authChecked {
log.Error().Int64("UserID", user.ID).Int64("RepositoryID", repositoryObj.ID).Msg("Auth check failed")
return xerrors.NewDSError(c, xerrors.DSErrCodeUnauthorized)
}

lastFound := false
var lastFound bool
var lastID int64 = 0

tagService := h.tagServiceFactory.New()
Expand Down
14 changes: 12 additions & 2 deletions pkg/handlers/distribution/blob/blob_delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"github.com/go-sigma/sigma/pkg/consts"
"github.com/go-sigma/sigma/pkg/dal/models"
"github.com/go-sigma/sigma/pkg/types/enums"
"github.com/go-sigma/sigma/pkg/utils"
"github.com/go-sigma/sigma/pkg/utils/imagerefs"
"github.com/go-sigma/sigma/pkg/validators"
"github.com/go-sigma/sigma/pkg/xerrors"
Expand Down Expand Up @@ -65,9 +66,18 @@ func (h *handler) DeleteBlob(c echo.Context) error {
log.Error().Err(err).Str("Name", repository).Msg("Get repository by name failed")
return xerrors.NewDSError(c, xerrors.DSErrCodeBlobUnknown)
}
if !h.authServiceFactory.New().Repository(c, namespaceObj.ID, enums.AuthManage) {

authChecked, err := h.authServiceFactory.New().Repository(c, namespaceObj.ID, enums.AuthManage)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
log.Error().Err(errors.New(utils.UnwrapJoinedErrors(err))).Msg("Resource not found")
return xerrors.GenDSErrCodeResourceNotFound(err)
}
return xerrors.NewDSError(c, xerrors.DSErrCodeUnknown)
}
if !authChecked {
log.Error().Int64("UserID", user.ID).Int64("NamespaceID", namespaceObj.ID).Msg("Auth check failed")
return xerrors.NewHTTPError(c, xerrors.HTTPErrCodeUnauthorized, "No permission with this api")
return xerrors.NewDSError(c, xerrors.DSErrCodeUnauthorized)
}

dgest, err := digest.Parse(strings.TrimPrefix(uri[strings.LastIndex(uri, "/"):], "/"))
Expand Down
13 changes: 11 additions & 2 deletions pkg/handlers/distribution/blob/blob_get.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,18 @@ func (h *handler) GetBlob(c echo.Context) error {
log.Error().Err(err).Str("Name", repository).Msg("Get repository by name failed")
return xerrors.NewDSError(c, xerrors.DSErrCodeBlobUnknown)
}
if !h.authServiceFactory.New().Namespace(c, namespaceObj.ID, enums.AuthRead) {

authChecked, err := h.authServiceFactory.New().Namespace(c, namespaceObj.ID, enums.AuthRead)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
log.Error().Err(errors.New(utils.UnwrapJoinedErrors(err))).Msg("Resource not found")
return xerrors.GenDSErrCodeResourceNotFound(err)
}
return xerrors.NewDSError(c, xerrors.DSErrCodeUnknown)
}
if !authChecked {
log.Error().Int64("UserID", user.ID).Int64("NamespaceID", namespaceObj.ID).Msg("Auth check failed")
return xerrors.NewHTTPError(c, xerrors.HTTPErrCodeUnauthorized, "No permission with this api")
return xerrors.NewDSError(c, xerrors.DSErrCodeUnauthorized)
}

dgest, err := digest.Parse(strings.TrimPrefix(uri[strings.LastIndex(uri, "/"):], "/"))
Expand Down
14 changes: 12 additions & 2 deletions pkg/handlers/distribution/blob/blob_head.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/go-sigma/sigma/pkg/handlers/distribution/clients"
"github.com/go-sigma/sigma/pkg/modules/cacher"
"github.com/go-sigma/sigma/pkg/types/enums"
"github.com/go-sigma/sigma/pkg/utils"
"github.com/go-sigma/sigma/pkg/utils/imagerefs"
"github.com/go-sigma/sigma/pkg/utils/ptr"
"github.com/go-sigma/sigma/pkg/validators"
Expand Down Expand Up @@ -69,9 +70,18 @@ func (h *handler) HeadBlob(c echo.Context) error {
log.Error().Err(err).Str("Name", repository).Msg("Get repository by name failed")
return xerrors.NewDSError(c, xerrors.DSErrCodeBlobUnknown)
}
if !h.authServiceFactory.New().Namespace(c, namespaceObj.ID, enums.AuthRead) {

authChecked, err := h.authServiceFactory.New().Namespace(c, namespaceObj.ID, enums.AuthRead)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
log.Error().Err(errors.New(utils.UnwrapJoinedErrors(err))).Msg("Resource not found")
return xerrors.GenDSErrCodeResourceNotFound(err)
}
return xerrors.NewDSError(c, xerrors.DSErrCodeUnknown)
}
if !authChecked {
log.Error().Int64("UserID", user.ID).Int64("NamespaceID", namespaceObj.ID).Msg("Auth check failed")
return xerrors.NewHTTPError(c, xerrors.HTTPErrCodeUnauthorized, "No permission with this api")
return xerrors.NewDSError(c, xerrors.DSErrCodeUnauthorized)
}

dgest, err := digest.Parse(strings.TrimPrefix(uri[strings.LastIndex(uri, "/"):], "/"))
Expand Down
14 changes: 12 additions & 2 deletions pkg/handlers/distribution/manifest/manifest_delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/go-sigma/sigma/pkg/dal/models"
"github.com/go-sigma/sigma/pkg/dal/query"
"github.com/go-sigma/sigma/pkg/types/enums"
"github.com/go-sigma/sigma/pkg/utils"
"github.com/go-sigma/sigma/pkg/utils/imagerefs"
"github.com/go-sigma/sigma/pkg/validators"
"github.com/go-sigma/sigma/pkg/xerrors"
Expand Down Expand Up @@ -67,9 +68,18 @@ func (h *handler) DeleteManifest(c echo.Context) error {
log.Error().Err(err).Str("Name", repository).Msg("Get repository by name failed")
return xerrors.NewDSError(c, xerrors.DSErrCodeBlobUnknown)
}
if !h.authServiceFactory.New().Namespace(c, namespaceObj.ID, enums.AuthManage) {

authChecked, err := h.authServiceFactory.New().Namespace(c, namespaceObj.ID, enums.AuthManage)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
log.Error().Err(errors.New(utils.UnwrapJoinedErrors(err))).Msg("Resource not found")
return xerrors.GenDSErrCodeResourceNotFound(err)
}
return xerrors.NewDSError(c, xerrors.DSErrCodeUnknown)
}
if !authChecked {
log.Error().Int64("UserID", user.ID).Int64("NamespaceID", namespaceObj.ID).Msg("Auth check failed")
return xerrors.NewHTTPError(c, xerrors.HTTPErrCodeUnauthorized, "No permission with this api")
return xerrors.NewDSError(c, xerrors.DSErrCodeUnauthorized)
}

ref := strings.TrimPrefix(uri[strings.LastIndex(uri, "/"):], "/")
Expand Down
Loading

0 comments on commit ea0c9f5

Please sign in to comment.