mirror of https://github.com/harness/drone.git
block 'api' as root space name, minor improvements
parent
d7f0ae4b2c
commit
ff806fb492
|
@ -12,18 +12,16 @@ import (
|
|||
"github.com/harness/gitness/internal/api/render"
|
||||
"github.com/harness/gitness/internal/api/request"
|
||||
"github.com/harness/gitness/internal/auth/authz"
|
||||
"github.com/harness/gitness/internal/store"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
type Guard struct {
|
||||
authorizer authz.Authorizer
|
||||
spaces store.SpaceStore
|
||||
}
|
||||
|
||||
func New(spaces store.SpaceStore, authorizer authz.Authorizer) *Guard {
|
||||
return &Guard{authorizer: authorizer, spaces: spaces}
|
||||
func New(authorizer authz.Authorizer) *Guard {
|
||||
return &Guard{authorizer: authorizer}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -42,8 +42,8 @@ func (g *Guard) Repo(permission enum.Permission, orPublic bool, guarded http.Han
|
|||
return
|
||||
}
|
||||
|
||||
// Enforce permission
|
||||
if (!orPublic || !rep.IsPublic) && !g.EnforceRepo(w, r, permission, rep.Fqn) {
|
||||
// Enforce permission (renders error)
|
||||
if !(orPublic && rep.IsPublic) && !g.EnforceRepo(w, r, permission, rep.Fqn) {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ package guard
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/harness/gitness/internal/api/render"
|
||||
|
@ -43,10 +42,8 @@ func (g *Guard) Space(permission enum.Permission, orPublic bool, guarded http.Ha
|
|||
return
|
||||
}
|
||||
|
||||
fmt.Printf("check for space '%s'", s.Fqn)
|
||||
|
||||
// Enforce permission (renders error)
|
||||
if (!orPublic || !s.IsPublic) && !g.EnforceSpace(w, r, permission, s.Fqn) {
|
||||
if !(orPublic && s.IsPublic) && !g.EnforceSpace(w, r, permission, s.Fqn) {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ func HandleCreate(guard *guard.Guard, spaces store.SpaceStore, repos store.RepoS
|
|||
/*
|
||||
* AUTHORIZATION - has to be done on parent space!
|
||||
*/
|
||||
if !guard.EnforceSpace(w, r, enum.PermissionRepoCreate, parentFqn) {
|
||||
if !guard.EnforceRepo(w, r, enum.PermissionRepoCreate, parentFqn) {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ func HandleCreate(guard *guard.Guard, spaces store.SpaceStore) http.HandlerFunc
|
|||
ctx := r.Context()
|
||||
log := hlog.FromRequest(r)
|
||||
|
||||
// get fqn (requires parent if child space)
|
||||
// get fqn (requires parent of child space)
|
||||
sref, err := request.GetSpaceRef(r)
|
||||
if err != nil {
|
||||
render.BadRequest(w, err)
|
||||
|
@ -81,7 +81,7 @@ func HandleCreate(guard *guard.Guard, spaces store.SpaceStore) http.HandlerFunc
|
|||
}
|
||||
|
||||
// get parentId if needed
|
||||
parentId := int64(-1)
|
||||
parentId := int64(0)
|
||||
if parentFqn != "" {
|
||||
parentSpace, err := spaces.FindFqn(ctx, parentFqn)
|
||||
if err != nil {
|
||||
|
|
|
@ -32,7 +32,6 @@ func HandleDelete(guard *guard.Guard, spaces store.SpaceStore) http.HandlerFunc
|
|||
if err != nil {
|
||||
render.InternalError(w, err)
|
||||
log.Error().Err(err).
|
||||
Int64("space_id", s.ID).
|
||||
Str("space_fqn", s.Fqn).
|
||||
Msg("Failed to delete space.")
|
||||
return
|
||||
|
|
|
@ -36,7 +36,8 @@ func HandleList(guard *guard.Guard, spaces store.SpaceStore) http.HandlerFunc {
|
|||
if err != nil {
|
||||
render.InternalError(w, err)
|
||||
log.Error().Err(err).
|
||||
Msgf("Failed to retrieve count of spaces under '%s'.", s.Fqn)
|
||||
Str("space_fqn", s.Fqn).
|
||||
Msg("Failed to retrieve count of child spaces.")
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -44,7 +45,8 @@ func HandleList(guard *guard.Guard, spaces store.SpaceStore) http.HandlerFunc {
|
|||
if err != nil {
|
||||
render.InternalError(w, err)
|
||||
log.Error().Err(err).
|
||||
Msgf("Failed to retrieve list of spaces under '%s'.", s.Fqn)
|
||||
Str("space_fqn", s.Fqn).
|
||||
Msg("Failed to retrieve list of child spaces.")
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,8 @@ func HandleListRepos(guard *guard.Guard, repos store.RepoStore) http.HandlerFunc
|
|||
if err != nil {
|
||||
render.InternalError(w, err)
|
||||
log.Error().Err(err).
|
||||
Msgf("Failed to retrieve count of repos under '%s'.", s.Fqn)
|
||||
Str("space_fqn", s.Fqn).
|
||||
Msg("Failed to retrieve count of repos.")
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -44,7 +45,8 @@ func HandleListRepos(guard *guard.Guard, repos store.RepoStore) http.HandlerFunc
|
|||
if err != nil {
|
||||
render.InternalError(w, err)
|
||||
log.Error().Err(err).
|
||||
Msgf("Failed to retrieve list of repos under '%s'.", s.Fqn)
|
||||
Str("space_fqn", s.Fqn).
|
||||
Msg("Failed to retrieve list of repos.")
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -26,11 +26,15 @@ func Attempt(authenticator authn.Authenticator) func(http.Handler) http.Handler
|
|||
if err != nil {
|
||||
render.Unauthorized(w, err)
|
||||
return
|
||||
} else if user == nil {
|
||||
}
|
||||
|
||||
// if there was no auth info - continue as is
|
||||
if user == nil {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// otherwise update the logging context and inject user in context
|
||||
ctx := r.Context()
|
||||
log.Ctx(ctx).UpdateContext(func(c zerolog.Context) zerolog.Context {
|
||||
return c.Str("session_email", user.Email).Bool("session_admin", user.Admin)
|
||||
|
|
|
@ -14,7 +14,7 @@ import (
|
|||
*/
|
||||
func GitFqnBefore(h http.HandlerFunc) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
r, _ = encodeFQNWithCustomMarker(r, "", ".git", false)
|
||||
r, _ = encodeFQNWithMarker(r, "", ".git", false)
|
||||
h.ServeHTTP(w, r)
|
||||
}
|
||||
}
|
||||
|
@ -27,8 +27,9 @@ func GitFqnBefore(h http.HandlerFunc) http.HandlerFunc {
|
|||
func TerminatedFqnBefore(prefixes []string, h http.HandlerFunc) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
for _, p := range prefixes {
|
||||
// IMPORTANT: define changed separately to avoid overshadowing r
|
||||
changed := false
|
||||
if r, changed = encodeFQNWithCustomMarker(r, p, "/+", false); changed {
|
||||
if r, changed = encodeFQNWithMarker(r, p, "/+", false); changed {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
@ -44,10 +45,10 @@ func TerminatedFqnBefore(prefixes []string, h http.HandlerFunc) http.HandlerFunc
|
|||
*
|
||||
* Examples:
|
||||
* Prefix: "" Path: "/space1/space2/+" => "/space1%2Fspace2"
|
||||
* Prefix: "" Path: "/space1/space2.git" => "/space1%2Fspace2.git"
|
||||
* Prefix: "" Path: "/space1/space2.git" => "/space1%2Fspace2"
|
||||
* Prefix: "/spaces" Path: "/spaces/space1/space2/+/authToken" => "/spaces/space1%2Fspace2/authToken"
|
||||
*/
|
||||
func encodeFQNWithCustomMarker(r *http.Request, prefix string, marker string, keepMarker bool) (*http.Request, bool) {
|
||||
func encodeFQNWithMarker(r *http.Request, prefix string, marker string, keepMarker bool) (*http.Request, bool) {
|
||||
// In case path doesn't start with prefix - nothing to encode
|
||||
if len(r.URL.Path) < len(prefix) || r.URL.Path[0:len(prefix)] != prefix {
|
||||
return r, false
|
||||
|
@ -58,11 +59,12 @@ func encodeFQNWithCustomMarker(r *http.Request, prefix string, marker string, ke
|
|||
|
||||
// If we don't find a marker - nothing to encode
|
||||
if !found {
|
||||
fmt.Println("what")
|
||||
return r, false
|
||||
}
|
||||
|
||||
// if marker was found - convert to escaped version
|
||||
escapedFqn := "/" + strings.Replace(fqn[1:], "/", "%2F", -1)
|
||||
// if marker was found - convert to escaped version (skip first character in case path starts with '/')
|
||||
escapedFqn := fqn[0:1] + strings.Replace(fqn[1:], "/", "%2F", -1)
|
||||
if keepMarker {
|
||||
escapedFqn += marker
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ func WithUser(parent context.Context, v *types.User) context.Context {
|
|||
// context.
|
||||
func UserFrom(ctx context.Context) (*types.User, bool) {
|
||||
v, ok := ctx.Value(userKey).(*types.User)
|
||||
return v, ok
|
||||
return v, ok && v != nil
|
||||
}
|
||||
|
||||
// WithSpace returns a copy of parent in which the space value is set
|
||||
|
|
|
@ -87,7 +87,7 @@ func ParseUserFilter(r *http.Request) types.UserFilter {
|
|||
}
|
||||
}
|
||||
|
||||
// ParseSpaceFilter extracts the user query parameter from the url.
|
||||
// ParseSpaceFilter extracts the space query parameter from the url.
|
||||
func ParseSpaceFilter(r *http.Request) types.SpaceFilter {
|
||||
return types.SpaceFilter{
|
||||
Order: ParseOrder(r),
|
||||
|
@ -97,7 +97,7 @@ func ParseSpaceFilter(r *http.Request) types.SpaceFilter {
|
|||
}
|
||||
}
|
||||
|
||||
// ParseRepoFilter extracts the user query parameter from the url.
|
||||
// ParseRepoFilter extracts the repository query parameter from the url.
|
||||
func ParseRepoFilter(r *http.Request) types.RepoFilter {
|
||||
return types.RepoFilter{
|
||||
Order: ParseOrder(r),
|
||||
|
|
|
@ -16,9 +16,7 @@ import (
|
|||
"github.com/harness/gitness/internal/store"
|
||||
"github.com/harness/gitness/internal/token"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/hlog"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
var _ Authenticator = (*TokenAuthenticator)(nil)
|
||||
|
@ -81,10 +79,6 @@ func (a *TokenAuthenticator) Authenticate(r *http.Request) (*types.User, error)
|
|||
}
|
||||
}
|
||||
|
||||
log.Ctx(ctx).UpdateContext(func(c zerolog.Context) zerolog.Context {
|
||||
return c.Str("session_email", user.Email).Bool("session_admin", user.Admin)
|
||||
})
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ import (
|
|||
)
|
||||
|
||||
/*
|
||||
* Mounts the Rest API Router under mountPath.
|
||||
* Mounts the Rest API Router under mountPath (path has to end with ).
|
||||
* The handler is wrapped within a layer that handles encoding terminated FQNs.
|
||||
*/
|
||||
func newApiHandler(
|
||||
|
@ -40,8 +40,9 @@ func newApiHandler(
|
|||
authorizer authz.Authorizer) (http.Handler, error) {
|
||||
|
||||
config := systemStore.Config(nocontext)
|
||||
guard := guard.New(authorizer)
|
||||
|
||||
// User go-chi router for inner routing (restricted to mountPath!)
|
||||
// Use go-chi router for inner routing (restricted to mountPath!)
|
||||
r := chi.NewRouter()
|
||||
r.Route(mountPath, func(r chi.Router) {
|
||||
|
||||
|
@ -72,7 +73,7 @@ func newApiHandler(
|
|||
r.Use(middleware_authn.Attempt(authenticator))
|
||||
|
||||
r.Route("/v1", func(r chi.Router) {
|
||||
setupRoutesV1(r, systemStore, userStore, spaceStore, repoStore, authenticator, authorizer)
|
||||
setupRoutesV1(r, systemStore, userStore, spaceStore, repoStore, authenticator, guard)
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -92,10 +93,7 @@ func setupRoutesV1(
|
|||
spaceStore store.SpaceStore,
|
||||
repoStore store.RepoStore,
|
||||
authenticator authn.Authenticator,
|
||||
authorizer authz.Authorizer) {
|
||||
|
||||
// Create singleton middlewares for later usage
|
||||
guard := guard.New(spaceStore, authorizer)
|
||||
guard *guard.Guard) {
|
||||
|
||||
// SPACES
|
||||
r.Route("/spaces", func(r chi.Router) {
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
"github.com/harness/gitness/internal/auth/authn"
|
||||
"github.com/harness/gitness/internal/auth/authz"
|
||||
"github.com/harness/gitness/internal/store"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/go-chi/chi/middleware"
|
||||
|
@ -32,13 +33,12 @@ func newGitHandler(
|
|||
authenticator authn.Authenticator,
|
||||
authorizer authz.Authorizer) (http.Handler, error) {
|
||||
|
||||
// User go-chi router for inner routing (restricted to mountPath!)
|
||||
guard := guard.New(authorizer)
|
||||
|
||||
// Use go-chi router for inner routing (restricted to mountPath!)
|
||||
r := chi.NewRouter()
|
||||
r.Route(mountPath, func(r chi.Router) {
|
||||
|
||||
// Create singleton middlewares for later usage
|
||||
guard := guard.New(spaceStore, authorizer)
|
||||
|
||||
// Apply common api middleware
|
||||
r.Use(middleware.NoCache)
|
||||
r.Use(middleware.Recoverer)
|
||||
|
@ -56,15 +56,19 @@ func newGitHandler(
|
|||
// resolves the repo and stores in the context
|
||||
r.Use(repo.Required(repoStore))
|
||||
|
||||
// Operations that require auth (write)
|
||||
// Write operations (need auth)
|
||||
r.Group(func(r chi.Router) {
|
||||
r.Use(guard.EnforceAuthenticated)
|
||||
// TODO: specific permission for pushing code?
|
||||
r.Use(guard.ForRepo(enum.PermissionRepoEdit, false))
|
||||
|
||||
r.Handle("/git-upload-pack", http.HandlerFunc(stubGitHandler))
|
||||
})
|
||||
|
||||
// Operations that not always require auth (read)
|
||||
// Read operations (only need of it not public)
|
||||
r.Group(func(r chi.Router) {
|
||||
|
||||
r.Use(guard.ForRepo(enum.PermissionRepoView, true))
|
||||
|
||||
r.Post("/git-receive-pack", stubGitHandler)
|
||||
r.Get("/info/refs", stubGitHandler)
|
||||
r.Get("/HEAD", stubGitHandler)
|
||||
|
@ -88,7 +92,7 @@ func stubGitHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
w.Write([]byte(fmt.Sprintf(
|
||||
"Work in progress ... \n"+
|
||||
"Oooops, seems you hit a major construction site ... \n"+
|
||||
" Repo: '%s' (%s)\n"+
|
||||
" Method: '%s'\n"+
|
||||
" Path: '%s'\n"+
|
||||
|
|
|
@ -17,7 +17,8 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
restMount = "/api/"
|
||||
restMount = "/api"
|
||||
gitUserAgentPrefix = "git/"
|
||||
)
|
||||
|
||||
// empty context
|
||||
|
@ -39,7 +40,7 @@ func New(
|
|||
authenticator authn.Authenticator,
|
||||
authorizer authz.Authorizer,
|
||||
) (http.Handler, error) {
|
||||
api, err := newApiHandler("/api", systemStore, userStore, spaceStore, repoStore, authenticator, authorizer)
|
||||
api, err := newApiHandler(restMount, systemStore, userStore, spaceStore, repoStore, authenticator, authorizer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -68,8 +69,8 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
* This can collide with other API endpoints and thus has to be checked first.
|
||||
* To avoid any false positives, we use the user-agent header to identify git agents.
|
||||
*/
|
||||
a := req.Header.Get("user-agent")
|
||||
if strings.HasPrefix(a, "git/") {
|
||||
ua := req.Header.Get("user-agent")
|
||||
if strings.HasPrefix(ua, gitUserAgentPrefix) {
|
||||
r.git.ServeHTTP(w, req)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ func newWebHandler(
|
|||
|
||||
config := systemStore.Config(nocontext)
|
||||
|
||||
// User go-chi router for inner routing (restricted to mountPath!)
|
||||
// Use go-chi router for inner routing (restricted to mountPath!)
|
||||
r := chi.NewRouter()
|
||||
r.Route(mountPath, func(r chi.Router) {
|
||||
|
||||
|
|
|
@ -199,7 +199,7 @@ INSERT INTO repositories (
|
|||
,:repo_numPulls
|
||||
,:repo_numClosedPulls
|
||||
,:repo_numOpenPulls
|
||||
)RETURNING repo_id
|
||||
) RETURNING repo_id
|
||||
`
|
||||
|
||||
const repoUpdate = `
|
||||
|
|
|
@ -176,7 +176,7 @@ WHERE space_id = $1
|
|||
|
||||
const spaceInsert = `
|
||||
INSERT INTO spaces (
|
||||
space_name
|
||||
space_name
|
||||
,space_fqn
|
||||
,space_parentId
|
||||
,space_displayName
|
||||
|
@ -195,7 +195,7 @@ INSERT INTO spaces (
|
|||
,:space_createdBy
|
||||
,:space_created
|
||||
,:space_updated
|
||||
)RETURNING space_id
|
||||
) RETURNING space_id
|
||||
`
|
||||
|
||||
const spaceUpdate = `
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
[
|
||||
{
|
||||
"id": 1,
|
||||
"name": "repo1",
|
||||
"spaceId": 1,
|
||||
"fqn": "space1/repo1",
|
||||
"displayName": "Repository 1",
|
||||
"description": "Some repository.",
|
||||
"isPublic": true,
|
||||
"createdBy": 1,
|
||||
"created": 1662427496787,
|
||||
"updated": 1662427496787,
|
||||
"forkId": 0,
|
||||
"numForks": 0,
|
||||
"numPulls": 0,
|
||||
"numClosedPulls": 0,
|
||||
"numOpenPulls": 0
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "repo2",
|
||||
"spaceId": 2,
|
||||
"fqn": "space1/space2/repo2",
|
||||
"displayName": "Repository 2",
|
||||
"description": "Some other repository.",
|
||||
"isPublic": true,
|
||||
"createdBy": 1,
|
||||
"created": 1662427602488,
|
||||
"updated": 1662427602488,
|
||||
"forkId": 0,
|
||||
"numForks": 0,
|
||||
"numPulls": 0,
|
||||
"numClosedPulls": 0,
|
||||
"numOpenPulls": 0
|
||||
}
|
||||
]
|
|
@ -0,0 +1,26 @@
|
|||
[
|
||||
{
|
||||
"id": 1,
|
||||
"name": "space1",
|
||||
"fqn": "space1",
|
||||
"parentId": 0,
|
||||
"displayName": "Space 1",
|
||||
"description": "Some space.",
|
||||
"isPublic": true,
|
||||
"createdBy": 1,
|
||||
"created": 1662427417128,
|
||||
"updated": 1662427417128
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "space2",
|
||||
"fqn": "space1/space2",
|
||||
"parentId": 1,
|
||||
"displayName": "Space 2",
|
||||
"description": "Some subspace.",
|
||||
"isPublic": true,
|
||||
"createdBy": 1,
|
||||
"created": 1662427428536,
|
||||
"updated": 1662427428536
|
||||
}
|
||||
]
|
|
@ -1,6 +1,6 @@
|
|||
[
|
||||
{
|
||||
"id": 0,
|
||||
"id": 1,
|
||||
"email": "jane@example.com",
|
||||
"name": "jane",
|
||||
"company": "acme",
|
||||
|
@ -11,7 +11,7 @@
|
|||
"authed": 0
|
||||
},
|
||||
{
|
||||
"id": 0,
|
||||
"id": 2,
|
||||
"email": "john@example.com",
|
||||
"name": "john",
|
||||
"company": "acme",
|
||||
|
|
|
@ -5,5 +5,5 @@
|
|||
// Package mocks provides mock interfaces.
|
||||
package mocks
|
||||
|
||||
//go:generate mockgen -package=mocks -destination=mock_store.go github.com/harness/gitness/internal/store SystemStore,UserStore
|
||||
//go:generate mockgen -package=mocks -destination=mock_store.go github.com/harness/gitness/internal/store SystemStore,UserStore,SpaceStore,RepoStore
|
||||
//go:generate mockgen -package=mocks -destination=mock_client.go github.com/harness/gitness/client Client
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: github.com/harness/gitness/internal/store (interfaces: SystemStore,UserStore)
|
||||
// Source: github.com/harness/gitness/internal/store (interfaces: SystemStore,UserStore,SpaceStore,RepoStore)
|
||||
|
||||
// Package mocks is a generated GoMock package.
|
||||
package mocks
|
||||
|
@ -188,3 +188,253 @@ func (mr *MockUserStoreMockRecorder) Update(arg0, arg1 interface{}) *gomock.Call
|
|||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockUserStore)(nil).Update), arg0, arg1)
|
||||
}
|
||||
|
||||
// MockSpaceStore is a mock of SpaceStore interface.
|
||||
type MockSpaceStore struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockSpaceStoreMockRecorder
|
||||
}
|
||||
|
||||
// MockSpaceStoreMockRecorder is the mock recorder for MockSpaceStore.
|
||||
type MockSpaceStoreMockRecorder struct {
|
||||
mock *MockSpaceStore
|
||||
}
|
||||
|
||||
// NewMockSpaceStore creates a new mock instance.
|
||||
func NewMockSpaceStore(ctrl *gomock.Controller) *MockSpaceStore {
|
||||
mock := &MockSpaceStore{ctrl: ctrl}
|
||||
mock.recorder = &MockSpaceStoreMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockSpaceStore) EXPECT() *MockSpaceStoreMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// Count mocks base method.
|
||||
func (m *MockSpaceStore) Count(arg0 context.Context, arg1 int64) (int64, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Count", arg0, arg1)
|
||||
ret0, _ := ret[0].(int64)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Count indicates an expected call of Count.
|
||||
func (mr *MockSpaceStoreMockRecorder) Count(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Count", reflect.TypeOf((*MockSpaceStore)(nil).Count), arg0, arg1)
|
||||
}
|
||||
|
||||
// Create mocks base method.
|
||||
func (m *MockSpaceStore) Create(arg0 context.Context, arg1 *types.Space) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Create", arg0, arg1)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Create indicates an expected call of Create.
|
||||
func (mr *MockSpaceStoreMockRecorder) Create(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockSpaceStore)(nil).Create), arg0, arg1)
|
||||
}
|
||||
|
||||
// Delete mocks base method.
|
||||
func (m *MockSpaceStore) Delete(arg0 context.Context, arg1 int64) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Delete", arg0, arg1)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Delete indicates an expected call of Delete.
|
||||
func (mr *MockSpaceStoreMockRecorder) Delete(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockSpaceStore)(nil).Delete), arg0, arg1)
|
||||
}
|
||||
|
||||
// Find mocks base method.
|
||||
func (m *MockSpaceStore) Find(arg0 context.Context, arg1 int64) (*types.Space, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Find", arg0, arg1)
|
||||
ret0, _ := ret[0].(*types.Space)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Find indicates an expected call of Find.
|
||||
func (mr *MockSpaceStoreMockRecorder) Find(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Find", reflect.TypeOf((*MockSpaceStore)(nil).Find), arg0, arg1)
|
||||
}
|
||||
|
||||
// FindFqn mocks base method.
|
||||
func (m *MockSpaceStore) FindFqn(arg0 context.Context, arg1 string) (*types.Space, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "FindFqn", arg0, arg1)
|
||||
ret0, _ := ret[0].(*types.Space)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// FindFqn indicates an expected call of FindFqn.
|
||||
func (mr *MockSpaceStoreMockRecorder) FindFqn(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindFqn", reflect.TypeOf((*MockSpaceStore)(nil).FindFqn), arg0, arg1)
|
||||
}
|
||||
|
||||
// List mocks base method.
|
||||
func (m *MockSpaceStore) List(arg0 context.Context, arg1 int64, arg2 types.SpaceFilter) ([]*types.Space, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "List", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].([]*types.Space)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// List indicates an expected call of List.
|
||||
func (mr *MockSpaceStoreMockRecorder) List(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockSpaceStore)(nil).List), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// Update mocks base method.
|
||||
func (m *MockSpaceStore) Update(arg0 context.Context, arg1 *types.Space) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Update", arg0, arg1)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Update indicates an expected call of Update.
|
||||
func (mr *MockSpaceStoreMockRecorder) Update(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockSpaceStore)(nil).Update), arg0, arg1)
|
||||
}
|
||||
|
||||
// MockRepoStore is a mock of RepoStore interface.
|
||||
type MockRepoStore struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockRepoStoreMockRecorder
|
||||
}
|
||||
|
||||
// MockRepoStoreMockRecorder is the mock recorder for MockRepoStore.
|
||||
type MockRepoStoreMockRecorder struct {
|
||||
mock *MockRepoStore
|
||||
}
|
||||
|
||||
// NewMockRepoStore creates a new mock instance.
|
||||
func NewMockRepoStore(ctrl *gomock.Controller) *MockRepoStore {
|
||||
mock := &MockRepoStore{ctrl: ctrl}
|
||||
mock.recorder = &MockRepoStoreMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockRepoStore) EXPECT() *MockRepoStoreMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// Count mocks base method.
|
||||
func (m *MockRepoStore) Count(arg0 context.Context, arg1 int64) (int64, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Count", arg0, arg1)
|
||||
ret0, _ := ret[0].(int64)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Count indicates an expected call of Count.
|
||||
func (mr *MockRepoStoreMockRecorder) Count(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Count", reflect.TypeOf((*MockRepoStore)(nil).Count), arg0, arg1)
|
||||
}
|
||||
|
||||
// Create mocks base method.
|
||||
func (m *MockRepoStore) Create(arg0 context.Context, arg1 *types.Repository) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Create", arg0, arg1)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Create indicates an expected call of Create.
|
||||
func (mr *MockRepoStoreMockRecorder) Create(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockRepoStore)(nil).Create), arg0, arg1)
|
||||
}
|
||||
|
||||
// Delete mocks base method.
|
||||
func (m *MockRepoStore) Delete(arg0 context.Context, arg1 int64) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Delete", arg0, arg1)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Delete indicates an expected call of Delete.
|
||||
func (mr *MockRepoStoreMockRecorder) Delete(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockRepoStore)(nil).Delete), arg0, arg1)
|
||||
}
|
||||
|
||||
// Find mocks base method.
|
||||
func (m *MockRepoStore) Find(arg0 context.Context, arg1 int64) (*types.Repository, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Find", arg0, arg1)
|
||||
ret0, _ := ret[0].(*types.Repository)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Find indicates an expected call of Find.
|
||||
func (mr *MockRepoStoreMockRecorder) Find(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Find", reflect.TypeOf((*MockRepoStore)(nil).Find), arg0, arg1)
|
||||
}
|
||||
|
||||
// FindFqn mocks base method.
|
||||
func (m *MockRepoStore) FindFqn(arg0 context.Context, arg1 string) (*types.Repository, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "FindFqn", arg0, arg1)
|
||||
ret0, _ := ret[0].(*types.Repository)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// FindFqn indicates an expected call of FindFqn.
|
||||
func (mr *MockRepoStoreMockRecorder) FindFqn(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindFqn", reflect.TypeOf((*MockRepoStore)(nil).FindFqn), arg0, arg1)
|
||||
}
|
||||
|
||||
// List mocks base method.
|
||||
func (m *MockRepoStore) List(arg0 context.Context, arg1 int64, arg2 types.RepoFilter) ([]*types.Repository, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "List", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].([]*types.Repository)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// List indicates an expected call of List.
|
||||
func (mr *MockRepoStoreMockRecorder) List(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockRepoStore)(nil).List), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// Update mocks base method.
|
||||
func (m *MockRepoStore) Update(arg0 context.Context, arg1 *types.Repository) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Update", arg0, arg1)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Update indicates an expected call of Update.
|
||||
func (mr *MockRepoStoreMockRecorder) Update(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockRepoStore)(nil).Update), arg0, arg1)
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ var (
|
|||
ErrRepoNameLength = errors.New(fmt.Sprintf("Repository name has to be between %d and %d in length.", minRepoNameLength, maxRepoNameLength))
|
||||
ErrRepoNameRegex = errors.New("Repository name has start with a letter and only contain the following [a-z0-9-_].")
|
||||
|
||||
ErrRepoDisplayNameLength = errors.New(fmt.Sprintf("Repository name has to be between %d and %d in length.", minRepoDisplayNameLength, maxRepoDisplayNameLength))
|
||||
ErrRepoDisplayNameLength = errors.New(fmt.Sprintf("Repository display name has to be between %d and %d in length.", minRepoDisplayNameLength, maxRepoDisplayNameLength))
|
||||
ErrRepoDisplayNameRegex = errors.New("Repository display name has start with a letter and only contain the following [a-zA-Z0-9-_ ].")
|
||||
)
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/harness/gitness/types"
|
||||
)
|
||||
|
@ -26,8 +27,11 @@ var (
|
|||
ErrSpaceNameLength = errors.New(fmt.Sprintf("Space name has to be between %d and %d in length.", minSpaceNameLength, maxSpaceNameLength))
|
||||
ErrSpaceNameRegex = errors.New("Space name has start with a letter and only contain the following [a-z0-9-_].")
|
||||
|
||||
ErrSpaceDisplayNameLength = errors.New(fmt.Sprintf("Space name has to be between %d and %d in length.", minSpaceDisplayNameLength, maxSpaceDisplayNameLength))
|
||||
ErrSpaceDisplayNameLength = errors.New(fmt.Sprintf("Space display name has to be between %d and %d in length.", minSpaceDisplayNameLength, maxSpaceDisplayNameLength))
|
||||
ErrSpaceDisplayNameRegex = errors.New("Space display name has start with a letter and only contain the following [a-zA-Z0-9-_ ].")
|
||||
|
||||
illegalRootSpaceNames = []string{"api"}
|
||||
ErrRootSpaceNameNotAllowed = errors.New(fmt.Sprintf("The following names are not allowed for a root space: %v", illegalRootSpaceNames))
|
||||
)
|
||||
|
||||
// User returns true if the User if valid.
|
||||
|
@ -50,5 +54,14 @@ func Space(space *types.Space) (bool, error) {
|
|||
return false, ErrSpaceDisplayNameRegex
|
||||
}
|
||||
|
||||
// root space specific validations
|
||||
if space.ParentId <= 0 {
|
||||
for _, p := range illegalRootSpaceNames {
|
||||
if strings.HasPrefix(space.Name, p) {
|
||||
return false, ErrRootSpaceNameNotAllowed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue