From 6af8df337b92f5ac89352152793a6d2e52ab358c Mon Sep 17 00:00:00 2001 From: atefeh Date: Sat, 20 Apr 2024 02:20:35 -0700 Subject: [PATCH 01/31] added public access service, removed is-public from repo and space everywhere db and all --- app/api/auth/repo.go | 15 +- app/api/auth/space.go | 15 +- app/api/controller/check/controller.go | 30 ++-- app/api/controller/check/wire.go | 3 + app/api/controller/githook/controller.go | 4 + app/api/controller/githook/pre_receive.go | 2 +- app/api/controller/githook/wire.go | 3 + app/api/controller/pullreq/check_list.go | 2 +- app/api/controller/pullreq/comment_create.go | 2 +- app/api/controller/pullreq/comment_delete.go | 2 +- app/api/controller/pullreq/comment_status.go | 2 +- app/api/controller/pullreq/controller.go | 6 +- app/api/controller/pullreq/file_view_add.go | 2 +- .../controller/pullreq/file_view_delete.go | 2 +- app/api/controller/pullreq/merge.go | 2 +- app/api/controller/pullreq/pr_create.go | 2 +- app/api/controller/pullreq/pr_state.go | 2 +- app/api/controller/pullreq/pr_update.go | 2 +- app/api/controller/pullreq/review_submit.go | 2 +- app/api/controller/pullreq/reviewer_add.go | 4 +- app/api/controller/pullreq/wire.go | 5 +- app/api/controller/repo/controller.go | 13 +- app/api/controller/repo/create.go | 11 +- app/api/controller/repo/diff.go | 4 +- app/api/controller/repo/find.go | 2 +- app/api/controller/repo/helper.go | 4 +- app/api/controller/repo/import.go | 17 +- app/api/controller/repo/import_progress.go | 2 +- app/api/controller/repo/move.go | 2 +- app/api/controller/repo/purge.go | 2 +- app/api/controller/repo/restore.go | 2 +- app/api/controller/repo/soft_delete.go | 2 +- app/api/controller/repo/update.go | 13 +- app/api/controller/repo/visibility_update.go | 77 +++++++++ app/api/controller/repo/wire.go | 9 +- app/api/controller/reposettings/controller.go | 17 +- .../controller/reposettings/security_find.go | 2 +- app/api/controller/reposettings/wire.go | 4 +- app/api/controller/space/controller.go | 5 +- app/api/controller/space/create.go | 12 +- app/api/controller/space/events.go | 2 +- app/api/controller/space/export.go | 2 +- app/api/controller/space/export_progress.go | 2 +- app/api/controller/space/find.go | 2 +- app/api/controller/space/import.go | 15 +- .../controller/space/import_repositories.go | 15 +- app/api/controller/space/list_repositories.go | 52 ++++-- app/api/controller/space/list_spaces.go | 30 +++- app/api/controller/space/membership_add.go | 2 +- app/api/controller/space/membership_delete.go | 2 +- app/api/controller/space/membership_list.go | 2 +- app/api/controller/space/membership_update.go | 2 +- app/api/controller/space/move.go | 2 +- app/api/controller/space/purge.go | 2 +- app/api/controller/space/restore.go | 2 +- app/api/controller/space/soft_delete.go | 1 + app/api/controller/space/update.go | 15 +- app/api/controller/space/wire.go | 5 +- app/api/controller/upload/controller.go | 18 +- app/api/controller/upload/upload.go | 2 +- app/api/controller/upload/wire.go | 4 +- app/api/controller/webhook/controller.go | 6 +- app/api/controller/webhook/wire.go | 5 +- app/api/handler/repo/visibility_update.go | 52 ++++++ app/router/api.go | 1 + app/services/exporter/repository.go | 27 ++- app/services/exporter/wire.go | 15 +- app/services/importer/provider.go | 8 +- app/services/importer/repository.go | 1 + app/services/publicaccess/manager.go | 62 +++++++ app/services/publicaccess/public_access.go | 44 +++++ app/services/publicaccess/service.go | 48 ++++++ app/services/publicaccess/wire.go | 42 +++++ app/store/database.go | 7 + ...050_create_table_public_resources.down.sql | 28 +++ .../0050_create_table_public_resources.up.sql | 55 ++++++ ...050_create_table_public_resources.down.sql | 28 +++ .../0050_create_table_public_resources.up.sql | 55 ++++++ app/store/database/public_resource.go | 159 ++++++++++++++++++ app/store/database/repo.go | 7 - app/store/database/space.go | 7 - app/store/database/wire.go | 6 + cmd/gitness/wire.go | 2 + cmd/gitness/wire_gen.go | 23 ++- types/enum/membership_role.go | 2 + types/enum/permission.go | 1 + types/enum/public_resource.go | 33 ++++ types/public_resource.go | 23 +++ types/repo.go | 1 - types/space.go | 1 - 90 files changed, 1062 insertions(+), 175 deletions(-) create mode 100644 app/api/controller/repo/visibility_update.go create mode 100644 app/api/handler/repo/visibility_update.go create mode 100644 app/services/publicaccess/manager.go create mode 100644 app/services/publicaccess/public_access.go create mode 100644 app/services/publicaccess/service.go create mode 100644 app/services/publicaccess/wire.go create mode 100644 app/store/database/migrate/postgres/0050_create_table_public_resources.down.sql create mode 100644 app/store/database/migrate/postgres/0050_create_table_public_resources.up.sql create mode 100644 app/store/database/migrate/sqlite/0050_create_table_public_resources.down.sql create mode 100644 app/store/database/migrate/sqlite/0050_create_table_public_resources.up.sql create mode 100644 app/store/database/public_resource.go create mode 100644 types/enum/public_resource.go create mode 100644 types/public_resource.go diff --git a/app/api/auth/repo.go b/app/api/auth/repo.go index dd89a10536..50f0f178cb 100644 --- a/app/api/auth/repo.go +++ b/app/api/auth/repo.go @@ -21,6 +21,7 @@ import ( "github.com/harness/gitness/app/auth" "github.com/harness/gitness/app/auth/authz" "github.com/harness/gitness/app/paths" + "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/types" "github.com/harness/gitness/types/enum" @@ -37,9 +38,18 @@ func CheckRepo( session *auth.Session, repo *types.Repository, permission enum.Permission, + publicaccess *publicaccess.Service, orPublic bool, ) error { - if orPublic && repo.IsPublic { + isPublic, err := publicaccess.Get(ctx, &types.PublicResource{ + Type: enum.PublicResourceTypeRepository, + ResourceID: repo.ID, + }) + if err != nil { + return fmt.Errorf("failed to check public access: %w", err) + } + + if isPublic && orPublic { return nil } @@ -62,9 +72,10 @@ func IsRepoOwner( authorizer authz.Authorizer, session *auth.Session, repo *types.Repository, + publicaccess *publicaccess.Service, ) (bool, error) { // for now we use repoedit as permission to verify if someone is a SpaceOwner and hence a RepoOwner. - err := CheckRepo(ctx, authorizer, session, repo, enum.PermissionRepoEdit, false) + err := CheckRepo(ctx, authorizer, session, repo, enum.PermissionRepoEdit, publicaccess, false) if err != nil && !errors.Is(err, ErrNotAuthorized) { return false, fmt.Errorf("failed to check access user access: %w", err) } diff --git a/app/api/auth/space.go b/app/api/auth/space.go index 71a496bb78..e136443019 100644 --- a/app/api/auth/space.go +++ b/app/api/auth/space.go @@ -16,10 +16,12 @@ package auth import ( "context" + "fmt" "github.com/harness/gitness/app/auth" "github.com/harness/gitness/app/auth/authz" "github.com/harness/gitness/app/paths" + "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/types" "github.com/harness/gitness/types/enum" @@ -35,9 +37,18 @@ func CheckSpace( session *auth.Session, space *types.Space, permission enum.Permission, + publicaccess *publicaccess.Service, orPublic bool, ) error { - if orPublic && space.IsPublic { + isPublic, err := publicaccess.Get(ctx, &types.PublicResource{ + Type: enum.PublicResourceTypeSpace, + ResourceID: space.ID, + }) + if err != nil { + return fmt.Errorf("failed to check public access: %w", err) + } + + if isPublic && orPublic { return nil } @@ -67,7 +78,7 @@ func CheckSpaceScope( permission enum.Permission, orPublic bool, ) error { - if orPublic && space.IsPublic { + if orPublic { return nil } diff --git a/app/api/controller/check/controller.go b/app/api/controller/check/controller.go index 93224d3e78..c6b4f8b697 100644 --- a/app/api/controller/check/controller.go +++ b/app/api/controller/check/controller.go @@ -22,6 +22,7 @@ import ( "github.com/harness/gitness/app/api/usererror" "github.com/harness/gitness/app/auth" "github.com/harness/gitness/app/auth/authz" + "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/store" "github.com/harness/gitness/git" "github.com/harness/gitness/store/database/dbtx" @@ -30,12 +31,13 @@ import ( ) type Controller struct { - tx dbtx.Transactor - authorizer authz.Authorizer - repoStore store.RepoStore - checkStore store.CheckStore - git git.Interface - sanitizers map[enum.CheckPayloadKind]func(in *ReportInput, s *auth.Session) error + tx dbtx.Transactor + authorizer authz.Authorizer + repoStore store.RepoStore + checkStore store.CheckStore + git git.Interface + sanitizers map[enum.CheckPayloadKind]func(in *ReportInput, s *auth.Session) error + publicaccess *publicaccess.Service } func NewController( @@ -45,14 +47,16 @@ func NewController( checkStore store.CheckStore, git git.Interface, sanitizers map[enum.CheckPayloadKind]func(in *ReportInput, s *auth.Session) error, + publicaccess *publicaccess.Service, ) *Controller { return &Controller{ - tx: tx, - authorizer: authorizer, - repoStore: repoStore, - checkStore: checkStore, - git: git, - sanitizers: sanitizers, + tx: tx, + authorizer: authorizer, + repoStore: repoStore, + checkStore: checkStore, + git: git, + sanitizers: sanitizers, + publicaccess: publicaccess, } } @@ -68,7 +72,7 @@ func (c *Controller) getRepoCheckAccess(ctx context.Context, return nil, fmt.Errorf("failed to find repository: %w", err) } - if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, reqPermission, false); err != nil { + if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, reqPermission, c.publicaccess, false); err != nil { return nil, fmt.Errorf("access check failed: %w", err) } diff --git a/app/api/controller/check/wire.go b/app/api/controller/check/wire.go index f8e570a0fd..7b14e23e15 100644 --- a/app/api/controller/check/wire.go +++ b/app/api/controller/check/wire.go @@ -17,6 +17,7 @@ package check import ( "github.com/harness/gitness/app/auth" "github.com/harness/gitness/app/auth/authz" + "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/store" "github.com/harness/gitness/git" "github.com/harness/gitness/store/database/dbtx" @@ -38,6 +39,7 @@ func ProvideController( checkStore store.CheckStore, rpcClient git.Interface, sanitizers map[enum.CheckPayloadKind]func(in *ReportInput, s *auth.Session) error, + publicaccess *publicaccess.Service, ) *Controller { return NewController( tx, @@ -46,5 +48,6 @@ func ProvideController( checkStore, rpcClient, sanitizers, + publicaccess, ) } diff --git a/app/api/controller/githook/controller.go b/app/api/controller/githook/controller.go index 51f16d1ddb..beb585820c 100644 --- a/app/api/controller/githook/controller.go +++ b/app/api/controller/githook/controller.go @@ -25,6 +25,7 @@ import ( eventsgit "github.com/harness/gitness/app/events/git" eventsrepo "github.com/harness/gitness/app/events/repo" "github.com/harness/gitness/app/services/protection" + "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/services/settings" "github.com/harness/gitness/app/store" "github.com/harness/gitness/app/url" @@ -52,6 +53,7 @@ type Controller struct { preReceiveExtender PreReceiveExtender updateExtender UpdateExtender postReceiveExtender PostReceiveExtender + publicAccess *publicaccess.Service } func NewController( @@ -69,6 +71,7 @@ func NewController( preReceiveExtender PreReceiveExtender, updateExtender UpdateExtender, postReceiveExtender PostReceiveExtender, + publicAccess *publicaccess.Service, ) *Controller { return &Controller{ authorizer: authorizer, @@ -85,6 +88,7 @@ func NewController( preReceiveExtender: preReceiveExtender, updateExtender: updateExtender, postReceiveExtender: postReceiveExtender, + publicAccess: publicAccess, } } diff --git a/app/api/controller/githook/pre_receive.go b/app/api/controller/githook/pre_receive.go index cacceffca2..ae2d579b6d 100644 --- a/app/api/controller/githook/pre_receive.go +++ b/app/api/controller/githook/pre_receive.go @@ -117,7 +117,7 @@ func (c *Controller) checkProtectionRules( refUpdates changedRefs, output *hook.Output, ) error { - isRepoOwner, err := apiauth.IsRepoOwner(ctx, c.authorizer, session, repo) + isRepoOwner, err := apiauth.IsRepoOwner(ctx, c.authorizer, session, repo, c.publicAccess) if err != nil { return fmt.Errorf("failed to determine if user is repo owner: %w", err) } diff --git a/app/api/controller/githook/wire.go b/app/api/controller/githook/wire.go index a542021969..1bd8a60ccf 100644 --- a/app/api/controller/githook/wire.go +++ b/app/api/controller/githook/wire.go @@ -20,6 +20,7 @@ import ( eventsgit "github.com/harness/gitness/app/events/git" eventsrepo "github.com/harness/gitness/app/events/repo" "github.com/harness/gitness/app/services/protection" + "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/services/settings" "github.com/harness/gitness/app/store" "github.com/harness/gitness/app/url" @@ -56,6 +57,7 @@ func ProvideController( preReceiveExtender PreReceiveExtender, updateExtender UpdateExtender, postReceiveExtender PostReceiveExtender, + publicAccess *publicaccess.Service, ) *Controller { ctrl := NewController( authorizer, @@ -72,6 +74,7 @@ func ProvideController( preReceiveExtender, updateExtender, postReceiveExtender, + publicAccess, ) // TODO: improve wiring if possible diff --git a/app/api/controller/pullreq/check_list.go b/app/api/controller/pullreq/check_list.go index ac6c6ffd5d..04f84b7f7d 100644 --- a/app/api/controller/pullreq/check_list.go +++ b/app/api/controller/pullreq/check_list.go @@ -44,7 +44,7 @@ func (c *Controller) ListChecks( return types.PullReqChecks{}, fmt.Errorf("failed to find pull request by number: %w", err) } - isRepoOwner, err := apiauth.IsRepoOwner(ctx, c.authorizer, session, repo) + isRepoOwner, err := apiauth.IsRepoOwner(ctx, c.authorizer, session, repo, c.publicAccess) if err != nil { return types.PullReqChecks{}, fmt.Errorf("failed to determine if user is repo owner: %w", err) } diff --git a/app/api/controller/pullreq/comment_create.go b/app/api/controller/pullreq/comment_create.go index e994907c93..7c61f437e5 100644 --- a/app/api/controller/pullreq/comment_create.go +++ b/app/api/controller/pullreq/comment_create.go @@ -91,7 +91,7 @@ func (c *Controller) CommentCreate( prNum int64, in *CommentCreateInput, ) (*types.PullReqActivity, error) { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoReview) if err != nil { return nil, fmt.Errorf("failed to acquire access to repo: %w", err) } diff --git a/app/api/controller/pullreq/comment_delete.go b/app/api/controller/pullreq/comment_delete.go index 70da017ae4..169a5f0bf4 100644 --- a/app/api/controller/pullreq/comment_delete.go +++ b/app/api/controller/pullreq/comment_delete.go @@ -35,7 +35,7 @@ func (c *Controller) CommentDelete( prNum int64, commentID int64, ) error { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoReview) if err != nil { return fmt.Errorf("failed to acquire access to repo: %w", err) } diff --git a/app/api/controller/pullreq/comment_status.go b/app/api/controller/pullreq/comment_status.go index a62311cee2..5742966041 100644 --- a/app/api/controller/pullreq/comment_status.go +++ b/app/api/controller/pullreq/comment_status.go @@ -59,7 +59,7 @@ func (c *Controller) CommentStatus( commentID int64, in *CommentStatusInput, ) (*types.PullReqActivity, error) { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoReview) if err != nil { return nil, fmt.Errorf("failed to acquire access to repo: %w", err) } diff --git a/app/api/controller/pullreq/controller.go b/app/api/controller/pullreq/controller.go index 554933bd04..84274b092c 100644 --- a/app/api/controller/pullreq/controller.go +++ b/app/api/controller/pullreq/controller.go @@ -27,6 +27,7 @@ import ( "github.com/harness/gitness/app/services/codeowners" locker "github.com/harness/gitness/app/services/locker" "github.com/harness/gitness/app/services/protection" + "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/services/pullreq" "github.com/harness/gitness/app/sse" "github.com/harness/gitness/app/store" @@ -61,6 +62,7 @@ type Controller struct { sseStreamer sse.Streamer codeOwners *codeowners.Service locker *locker.Locker + publicAccess *publicaccess.Service } func NewController( @@ -85,6 +87,7 @@ func NewController( sseStreamer sse.Streamer, codeowners *codeowners.Service, locker *locker.Locker, + publicAccess *publicaccess.Service, ) *Controller { return &Controller{ tx: tx, @@ -108,6 +111,7 @@ func NewController( sseStreamer: sseStreamer, codeOwners: codeowners, locker: locker, + publicAccess: publicAccess, } } @@ -153,7 +157,7 @@ func (c *Controller) getRepoCheckAccess(ctx context.Context, return nil, usererror.BadRequest("Repository import is in progress.") } - if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, reqPermission, false); err != nil { + if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, reqPermission, c.publicAccess, false); err != nil { return nil, fmt.Errorf("access check failed: %w", err) } diff --git a/app/api/controller/pullreq/file_view_add.go b/app/api/controller/pullreq/file_view_add.go index 552e739a78..424637f209 100644 --- a/app/api/controller/pullreq/file_view_add.go +++ b/app/api/controller/pullreq/file_view_add.go @@ -62,7 +62,7 @@ func (c *Controller) FileViewAdd( return nil, err } - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoReview) if err != nil { return nil, fmt.Errorf("failed to acquire access to repo: %w", err) } diff --git a/app/api/controller/pullreq/file_view_delete.go b/app/api/controller/pullreq/file_view_delete.go index b1d5b9e520..f9db9adbe0 100644 --- a/app/api/controller/pullreq/file_view_delete.go +++ b/app/api/controller/pullreq/file_view_delete.go @@ -31,7 +31,7 @@ func (c *Controller) FileViewDelete( prNum int64, filePath string, ) error { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoReview) if err != nil { return fmt.Errorf("failed to acquire access to repo: %w", err) } diff --git a/app/api/controller/pullreq/merge.go b/app/api/controller/pullreq/merge.go index f83895448e..982831d2a7 100644 --- a/app/api/controller/pullreq/merge.go +++ b/app/api/controller/pullreq/merge.go @@ -176,7 +176,7 @@ func (c *Controller) Merge( } } - isRepoOwner, err := apiauth.IsRepoOwner(ctx, c.authorizer, session, targetRepo) + isRepoOwner, err := apiauth.IsRepoOwner(ctx, c.authorizer, session, targetRepo, c.publicAccess) if err != nil { return nil, nil, fmt.Errorf("failed to determine if user is repo owner: %w", err) } diff --git a/app/api/controller/pullreq/pr_create.go b/app/api/controller/pullreq/pr_create.go index af8f271a01..15b4fc1160 100644 --- a/app/api/controller/pullreq/pr_create.go +++ b/app/api/controller/pullreq/pr_create.go @@ -60,7 +60,7 @@ func (c *Controller) Create( sourceRepo := targetRepo if in.SourceRepoRef != "" { - sourceRepo, err = c.getRepoCheckAccess(ctx, session, in.SourceRepoRef, enum.PermissionRepoView) + sourceRepo, err = c.getRepoCheckAccess(ctx, session, in.SourceRepoRef, enum.PermissionRepoReview) if err != nil { return nil, fmt.Errorf("failed to acquire access to source repo: %w", err) } diff --git a/app/api/controller/pullreq/pr_state.go b/app/api/controller/pullreq/pr_state.go index 97f3e3be37..6ba9901c93 100644 --- a/app/api/controller/pullreq/pr_state.go +++ b/app/api/controller/pullreq/pr_state.go @@ -79,7 +79,7 @@ func (c *Controller) State(ctx context.Context, } if err = apiauth.CheckRepo(ctx, c.authorizer, session, sourceRepo, - enum.PermissionRepoView, false); err != nil { + enum.PermissionRepoReview, c.publicAccess, false); err != nil { return nil, fmt.Errorf("failed to acquire access to source repo: %w", err) } } diff --git a/app/api/controller/pullreq/pr_update.go b/app/api/controller/pullreq/pr_update.go index 06a8f44f5e..5c8a8b9ac7 100644 --- a/app/api/controller/pullreq/pr_update.go +++ b/app/api/controller/pullreq/pr_update.go @@ -74,7 +74,7 @@ func (c *Controller) Update(ctx context.Context, } if err = apiauth.CheckRepo(ctx, c.authorizer, session, sourceRepo, - enum.PermissionRepoView, false); err != nil { + enum.PermissionRepoReview, c.publicAccess, false); err != nil { return nil, fmt.Errorf("failed to acquire access to source repo: %w", err) } } diff --git a/app/api/controller/pullreq/review_submit.go b/app/api/controller/pullreq/review_submit.go index 7742c39a19..879fa5dd1e 100644 --- a/app/api/controller/pullreq/review_submit.go +++ b/app/api/controller/pullreq/review_submit.go @@ -66,7 +66,7 @@ func (c *Controller) ReviewSubmit( return nil, err } - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoReview) if err != nil { return nil, fmt.Errorf("failed to acquire access to repo: %w", err) } diff --git a/app/api/controller/pullreq/reviewer_add.go b/app/api/controller/pullreq/reviewer_add.go index cb3c0c0a41..e7de8c27ed 100644 --- a/app/api/controller/pullreq/reviewer_add.go +++ b/app/api/controller/pullreq/reviewer_add.go @@ -43,7 +43,7 @@ func (c *Controller) ReviewerAdd( prNum int64, in *ReviewerAddInput, ) (*types.PullReqReviewer, error) { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoReview) if err != nil { return nil, fmt.Errorf("failed to acquire access to repo: %w", err) } @@ -87,7 +87,7 @@ func (c *Controller) ReviewerAdd( if err = apiauth.CheckRepo(ctx, c.authorizer, &auth.Session{ Principal: *reviewerPrincipal, Metadata: nil, - }, repo, enum.PermissionRepoView, false); err != nil { + }, repo, enum.PermissionRepoReview, c.publicAccess, false); err != nil { log.Ctx(ctx).Info().Msgf("Reviewer principal: %s access error: %s", reviewerInfo.UID, err) return nil, usererror.BadRequest("The reviewer doesn't have enough permissions for the repository.") } diff --git a/app/api/controller/pullreq/wire.go b/app/api/controller/pullreq/wire.go index 5019471be9..55606b94bb 100644 --- a/app/api/controller/pullreq/wire.go +++ b/app/api/controller/pullreq/wire.go @@ -21,6 +21,7 @@ import ( "github.com/harness/gitness/app/services/codeowners" "github.com/harness/gitness/app/services/locker" "github.com/harness/gitness/app/services/protection" + "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/services/pullreq" "github.com/harness/gitness/app/sse" "github.com/harness/gitness/app/store" @@ -45,7 +46,7 @@ func ProvideController(tx dbtx.Transactor, urlProvider url.Provider, authorizer checkStore store.CheckStore, rpcClient git.Interface, eventReporter *pullreqevents.Reporter, codeCommentMigrator *codecomments.Migrator, pullreqService *pullreq.Service, ruleManager *protection.Manager, sseStreamer sse.Streamer, - codeOwners *codeowners.Service, locker *locker.Locker, + codeOwners *codeowners.Service, locker *locker.Locker, publicAccess *publicaccess.Service, ) *Controller { return NewController(tx, urlProvider, authorizer, pullReqStore, pullReqActivityStore, @@ -56,5 +57,5 @@ func ProvideController(tx dbtx.Transactor, urlProvider url.Provider, authorizer checkStore, rpcClient, eventReporter, codeCommentMigrator, - pullreqService, ruleManager, sseStreamer, codeOwners, locker) + pullreqService, ruleManager, sseStreamer, codeOwners, locker, publicAccess) } diff --git a/app/api/controller/repo/controller.go b/app/api/controller/repo/controller.go index ff67370aba..06245fa061 100644 --- a/app/api/controller/repo/controller.go +++ b/app/api/controller/repo/controller.go @@ -21,6 +21,7 @@ import ( "strings" apiauth "github.com/harness/gitness/app/api/auth" + "github.com/harness/gitness/app/api/controller/limiter" "github.com/harness/gitness/app/api/usererror" "github.com/harness/gitness/app/auth" @@ -31,6 +32,7 @@ import ( "github.com/harness/gitness/app/services/keywordsearch" "github.com/harness/gitness/app/services/locker" "github.com/harness/gitness/app/services/protection" + "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/services/settings" "github.com/harness/gitness/app/store" "github.com/harness/gitness/app/url" @@ -47,6 +49,11 @@ var ( errPublicRepoCreationDisabled = usererror.BadRequestf("Public repository creation is disabled.") ) +type Repository struct { + types.Repository + IsPublic bool `json:"is_public"` +} + type Controller struct { defaultBranch string publicResourceCreationEnabled bool @@ -73,6 +80,7 @@ type Controller struct { mtxManager lock.MutexManager identifierCheck check.RepoIdentifier repoCheck Check + publicAccess *publicaccess.Service } func NewController( @@ -99,6 +107,7 @@ func NewController( mtxManager lock.MutexManager, identifierCheck check.RepoIdentifier, repoCheck Check, + publicAccess *publicaccess.Service, ) *Controller { return &Controller{ defaultBranch: config.Git.DefaultBranch, @@ -125,6 +134,7 @@ func NewController( mtxManager: mtxManager, identifierCheck: identifierCheck, repoCheck: repoCheck, + publicAccess: publicAccess, } } @@ -156,6 +166,7 @@ func (c *Controller) getRepoCheckAccess( session, repoRef, reqPermission, + c.publicAccess, orPublic, ) } @@ -174,7 +185,7 @@ func (c *Controller) fetchRules( session *auth.Session, repo *types.Repository, ) (protection.Protection, bool, error) { - isRepoOwner, err := apiauth.IsRepoOwner(ctx, c.authorizer, session, repo) + isRepoOwner, err := apiauth.IsRepoOwner(ctx, c.authorizer, session, repo, c.publicAccess) if err != nil { return nil, false, fmt.Errorf("failed to determine if user is repo owner: %w", err) } diff --git a/app/api/controller/repo/create.go b/app/api/controller/repo/create.go index 4d72ba68bc..48537749ad 100644 --- a/app/api/controller/repo/create.go +++ b/app/api/controller/repo/create.go @@ -101,7 +101,6 @@ func (c *Controller) Create(ctx context.Context, session *auth.Session, in *Crea Identifier: in.Identifier, GitUID: gitResp.UID, Description: in.Description, - IsPublic: in.IsPublic, CreatedBy: session.Principal.ID, Created: now, Updated: now, @@ -117,6 +116,16 @@ func (c *Controller) Create(ctx context.Context, session *auth.Session, in *Crea return fmt.Errorf("failed to create repository in storage: %w", err) } + if in.IsPublic && c.publicResourceCreationEnabled { + err = c.publicAccess.Set(ctx, &types.PublicResource{ + Type: enum.PublicResourceTypeRepository, + ResourceID: repo.ID, + }, in.IsPublic) + if err != nil { + return fmt.Errorf("failed to set a public resource: %w", err) + } + } + return nil }, sql.TxOptions{Isolation: sql.LevelSerializable}) if err != nil { diff --git a/app/api/controller/repo/diff.go b/app/api/controller/repo/diff.go index 6f5344e02f..9f951226f7 100644 --- a/app/api/controller/repo/diff.go +++ b/app/api/controller/repo/diff.go @@ -104,7 +104,7 @@ func (c *Controller) DiffStats( return types.DiffStats{}, err } - if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, enum.PermissionRepoView, false); err != nil { + if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, enum.PermissionRepoView, c.publicAccess, false); err != nil { return types.DiffStats{}, err } @@ -139,7 +139,7 @@ func (c *Controller) Diff( return nil, err } - if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, enum.PermissionRepoView, false); err != nil { + if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, enum.PermissionRepoView, c.publicAccess, false); err != nil { return nil, err } diff --git a/app/api/controller/repo/find.go b/app/api/controller/repo/find.go index 21d890342b..94c5989876 100644 --- a/app/api/controller/repo/find.go +++ b/app/api/controller/repo/find.go @@ -31,7 +31,7 @@ func (c *Controller) Find(ctx context.Context, session *auth.Session, repoRef st return nil, err } - if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, enum.PermissionRepoView, true); err != nil { + if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, enum.PermissionRepoView, c.publicAccess, true); err != nil { return nil, err } diff --git a/app/api/controller/repo/helper.go b/app/api/controller/repo/helper.go index 5d941069a6..8d81d360c9 100644 --- a/app/api/controller/repo/helper.go +++ b/app/api/controller/repo/helper.go @@ -22,6 +22,7 @@ import ( "github.com/harness/gitness/app/api/usererror" "github.com/harness/gitness/app/auth" "github.com/harness/gitness/app/auth/authz" + "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/store" "github.com/harness/gitness/types" "github.com/harness/gitness/types/enum" @@ -58,6 +59,7 @@ func GetRepoCheckAccess( session *auth.Session, repoRef string, reqPermission enum.Permission, + publicAccess *publicaccess.Service, orPublic bool, ) (*types.Repository, error) { repo, err := GetRepo(ctx, repoStore, repoRef) @@ -65,7 +67,7 @@ func GetRepoCheckAccess( return nil, fmt.Errorf("failed to find repo: %w", err) } - if err = apiauth.CheckRepo(ctx, authorizer, session, repo, reqPermission, orPublic); err != nil { + if err = apiauth.CheckRepo(ctx, authorizer, session, repo, reqPermission, publicAccess, orPublic); err != nil { return nil, fmt.Errorf("access check failed: %w", err) } diff --git a/app/api/controller/repo/import.go b/app/api/controller/repo/import.go index 03c64a2145..8bfd265847 100644 --- a/app/api/controller/repo/import.go +++ b/app/api/controller/repo/import.go @@ -22,6 +22,7 @@ import ( "github.com/harness/gitness/app/auth" "github.com/harness/gitness/app/services/importer" "github.com/harness/gitness/types" + "github.com/harness/gitness/types/enum" ) type ImportInput struct { @@ -49,6 +50,7 @@ func (c *Controller) Import(ctx context.Context, session *auth.Session, in *Impo } var repo *types.Repository + var isPublic bool err = c.tx.WithTx(ctx, func(ctx context.Context) error { if err := c.resourceLimiter.RepoCount(ctx, parentSpace.ID, 1); err != nil { return fmt.Errorf("resource limit exceeded: %w", limiter.ErrMaxNumReposReached) @@ -58,12 +60,12 @@ func (c *Controller) Import(ctx context.Context, session *auth.Session, in *Impo if err != nil { return err } - repo = remoteRepository.ToRepo( + + repo, isPublic = remoteRepository.ToRepo( parentSpace.ID, in.Identifier, in.Description, &session.Principal, - c.publicResourceCreationEnabled, ) // lock the space for update during repo creation to prevent racing conditions with space soft delete. @@ -77,6 +79,17 @@ func (c *Controller) Import(ctx context.Context, session *auth.Session, in *Impo return fmt.Errorf("failed to create repository in storage: %w", err) } + // update public resources + if isPublic && c.publicResourceCreationEnabled { + err = c.publicAccess.Set(ctx, &types.PublicResource{ + Type: enum.PublicResourceTypeRepository, + ResourceID: repo.ID, + }, isPublic) + } + if err != nil { + return fmt.Errorf("failed to set a public repo: %w", err) + } + err = c.importer.Run(ctx, provider, repo, remoteRepository.CloneURL, in.Pipelines) if err != nil { return fmt.Errorf("failed to start import repository job: %w", err) diff --git a/app/api/controller/repo/import_progress.go b/app/api/controller/repo/import_progress.go index ec999f6179..a2d2c341b3 100644 --- a/app/api/controller/repo/import_progress.go +++ b/app/api/controller/repo/import_progress.go @@ -38,7 +38,7 @@ func (c *Controller) ImportProgress(ctx context.Context, return job.Progress{}, err } - if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, enum.PermissionRepoView, false); err != nil { + if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, enum.PermissionRepoView, c.publicAccess, false); err != nil { return job.Progress{}, err } diff --git a/app/api/controller/repo/move.go b/app/api/controller/repo/move.go index 099da66d8e..34031e9f7e 100644 --- a/app/api/controller/repo/move.go +++ b/app/api/controller/repo/move.go @@ -62,7 +62,7 @@ func (c *Controller) Move(ctx context.Context, return nil, usererror.BadRequest("can't move a repo that is being imported") } - if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, enum.PermissionRepoEdit, false); err != nil { + if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, enum.PermissionRepoEdit, c.publicAccess, false); err != nil { return nil, err } diff --git a/app/api/controller/repo/purge.go b/app/api/controller/repo/purge.go index 09a07e6db0..6bc2d2ecfd 100644 --- a/app/api/controller/repo/purge.go +++ b/app/api/controller/repo/purge.go @@ -43,7 +43,7 @@ func (c *Controller) Purge( return fmt.Errorf("failed to find the repo (deleted at %d): %w", deletedAt, err) } - if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, enum.PermissionRepoDelete, false); err != nil { + if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, enum.PermissionRepoDelete, c.publicAccess, false); err != nil { return err } diff --git a/app/api/controller/repo/restore.go b/app/api/controller/repo/restore.go index cc80ac5867..02145ca008 100644 --- a/app/api/controller/repo/restore.go +++ b/app/api/controller/repo/restore.go @@ -46,7 +46,7 @@ func (c *Controller) Restore( return nil, fmt.Errorf("failed to find repository: %w", err) } - if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, enum.PermissionRepoEdit, false); err != nil { + if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, enum.PermissionRepoEdit, c.publicAccess, false); err != nil { return nil, fmt.Errorf("access check failed: %w", err) } diff --git a/app/api/controller/repo/soft_delete.go b/app/api/controller/repo/soft_delete.go index 3168fba466..c9e742bd5f 100644 --- a/app/api/controller/repo/soft_delete.go +++ b/app/api/controller/repo/soft_delete.go @@ -46,7 +46,7 @@ func (c *Controller) SoftDelete( return nil, fmt.Errorf("failed to find the repo for soft delete: %w", err) } - if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, enum.PermissionRepoDelete, false); err != nil { + if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, enum.PermissionRepoDelete, c.publicAccess, false); err != nil { return nil, fmt.Errorf("access check failed: %w", err) } diff --git a/app/api/controller/repo/update.go b/app/api/controller/repo/update.go index 7e57c07d27..a90058a8f4 100644 --- a/app/api/controller/repo/update.go +++ b/app/api/controller/repo/update.go @@ -32,12 +32,10 @@ import ( // UpdateInput is used for updating a repo. type UpdateInput struct { Description *string `json:"description"` - IsPublic *bool `json:"is_public"` } func (in *UpdateInput) hasChanges(repo *types.Repository) bool { - return (in.Description != nil && *in.Description != repo.Description) || - (in.IsPublic != nil && *in.IsPublic != repo.IsPublic) + return in.Description != nil && *in.Description != repo.Description } // Update updates a repository. @@ -66,9 +64,6 @@ func (c *Controller) Update(ctx context.Context, if in.Description != nil { repo.Description = *in.Description } - if in.IsPublic != nil { - repo.IsPublic = *in.IsPublic - } return nil }) @@ -95,12 +90,6 @@ func (c *Controller) Update(ctx context.Context, } func (c *Controller) sanitizeUpdateInput(in *UpdateInput) error { - if in.IsPublic != nil { - if *in.IsPublic && !c.publicResourceCreationEnabled { - return errPublicRepoCreationDisabled - } - } - if in.Description != nil { *in.Description = strings.TrimSpace(*in.Description) if err := check.Description(*in.Description); err != nil { diff --git a/app/api/controller/repo/visibility_update.go b/app/api/controller/repo/visibility_update.go new file mode 100644 index 0000000000..d5cba04908 --- /dev/null +++ b/app/api/controller/repo/visibility_update.go @@ -0,0 +1,77 @@ +// Copyright 2023 Harness, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package repo + +import ( + "context" + "fmt" + + "github.com/harness/gitness/app/auth" + "github.com/harness/gitness/types" + "github.com/harness/gitness/types/enum" +) + +type VisibilityInput struct { + EnablePublic bool `json:"enable_public"` +} + +type VisibilityOutput struct { + IsPublic bool `json:"is_public"` +} + +func (c *Controller) VisibilityUpdate(ctx context.Context, + session *auth.Session, + repoRef string, + in *VisibilityInput, +) (*VisibilityOutput, error) { + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoEdit, false) + if err != nil { + return nil, err + } + + if err = c.sanitizeVisibilityInput(in); err != nil { + return nil, fmt.Errorf("failed to sanitize input: %w", err) + } + + err = c.publicAccess.Set( + ctx, + &types.PublicResource{ + Type: enum.PublicResourceTypeRepository, + ResourceID: repo.ID, + }, + in.EnablePublic, + ) + if err != nil { + return nil, fmt.Errorf("failed to set public access: %w", err) + } + + // TODO log for the audit service + + // backfill repo url + repo.GitURL = c.urlProvider.GenerateGITCloneURL(repo.Path) + + return &VisibilityOutput{ + in.EnablePublic, + }, nil + +} + +func (c *Controller) sanitizeVisibilityInput(in *VisibilityInput) error { + if in.EnablePublic && !c.publicResourceCreationEnabled { + return errPublicRepoCreationDisabled + } + + return nil +} diff --git a/app/api/controller/repo/wire.go b/app/api/controller/repo/wire.go index e39496c583..4190d9f229 100644 --- a/app/api/controller/repo/wire.go +++ b/app/api/controller/repo/wire.go @@ -17,12 +17,14 @@ package repo import ( "github.com/harness/gitness/app/api/controller/limiter" "github.com/harness/gitness/app/auth/authz" + repoevents "github.com/harness/gitness/app/events/repo" "github.com/harness/gitness/app/services/codeowners" "github.com/harness/gitness/app/services/importer" "github.com/harness/gitness/app/services/keywordsearch" "github.com/harness/gitness/app/services/locker" "github.com/harness/gitness/app/services/protection" + "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/services/settings" "github.com/harness/gitness/app/store" "github.com/harness/gitness/app/url" @@ -65,12 +67,13 @@ func ProvideController( mtxManager lock.MutexManager, identifierCheck check.RepoIdentifier, repoChecks Check, + publicAccess *publicaccess.Service, ) *Controller { return NewController(config, tx, urlProvider, - authorizer, repoStore, - spaceStore, pipelineStore, + authorizer, + repoStore, spaceStore, pipelineStore, principalStore, ruleStore, settings, principalInfoCache, protectionManager, rpcClient, importer, - codeOwners, reporeporter, indexer, limiter, locker, auditService, mtxManager, identifierCheck, repoChecks) + codeOwners, reporeporter, indexer, limiter, locker, auditService, mtxManager, identifierCheck, repoChecks, publicAccess) } func ProvideRepoCheck() Check { diff --git a/app/api/controller/reposettings/controller.go b/app/api/controller/reposettings/controller.go index c98e99f439..1eb29636c1 100644 --- a/app/api/controller/reposettings/controller.go +++ b/app/api/controller/reposettings/controller.go @@ -20,6 +20,7 @@ import ( "github.com/harness/gitness/app/api/controller/repo" "github.com/harness/gitness/app/auth" "github.com/harness/gitness/app/auth/authz" + "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/services/settings" "github.com/harness/gitness/app/store" "github.com/harness/gitness/types" @@ -27,20 +28,23 @@ import ( ) type Controller struct { - authorizer authz.Authorizer - repoStore store.RepoStore - settings *settings.Service + authorizer authz.Authorizer + repoStore store.RepoStore + settings *settings.Service + publicAccess *publicaccess.Service } func NewController( authorizer authz.Authorizer, repoStore store.RepoStore, settings *settings.Service, + publicAccess *publicaccess.Service, ) *Controller { return &Controller{ - authorizer: authorizer, - repoStore: repoStore, - settings: settings, + authorizer: authorizer, + repoStore: repoStore, + settings: settings, + publicAccess: publicAccess, } } @@ -60,6 +64,7 @@ func (c *Controller) getRepoCheckAccess( session, repoRef, reqPermission, + c.publicAccess, orPublic, ) } diff --git a/app/api/controller/reposettings/security_find.go b/app/api/controller/reposettings/security_find.go index f6c422f6cc..ee8d848900 100644 --- a/app/api/controller/reposettings/security_find.go +++ b/app/api/controller/reposettings/security_find.go @@ -28,7 +28,7 @@ func (c *Controller) SecurityFind( session *auth.Session, repoRef string, ) (*SecuritySettings, error) { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView, true) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoEdit, true) if err != nil { return nil, err } diff --git a/app/api/controller/reposettings/wire.go b/app/api/controller/reposettings/wire.go index 10776c9a3d..0d02cf677a 100644 --- a/app/api/controller/reposettings/wire.go +++ b/app/api/controller/reposettings/wire.go @@ -16,6 +16,7 @@ package reposettings import ( "github.com/harness/gitness/app/auth/authz" + "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/services/settings" "github.com/harness/gitness/app/store" @@ -31,6 +32,7 @@ func ProvideController( authorizer authz.Authorizer, repoStore store.RepoStore, settings *settings.Service, + publicAccess *publicaccess.Service, ) *Controller { - return NewController(authorizer, repoStore, settings) + return NewController(authorizer, repoStore, settings, publicAccess) } diff --git a/app/api/controller/space/controller.go b/app/api/controller/space/controller.go index 295f4f9251..f0c8445958 100644 --- a/app/api/controller/space/controller.go +++ b/app/api/controller/space/controller.go @@ -21,6 +21,7 @@ import ( "github.com/harness/gitness/app/auth/authz" "github.com/harness/gitness/app/services/exporter" "github.com/harness/gitness/app/services/importer" + "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/sse" "github.com/harness/gitness/app/store" "github.com/harness/gitness/app/url" @@ -57,6 +58,7 @@ type Controller struct { importer *importer.Repository exporter *exporter.Repository resourceLimiter limiter.ResourceLimiter + publicAccess *publicaccess.Service } func NewController(config *types.Config, tx dbtx.Transactor, urlProvider url.Provider, @@ -65,7 +67,7 @@ func NewController(config *types.Config, tx dbtx.Transactor, urlProvider url.Pro connectorStore store.ConnectorStore, templateStore store.TemplateStore, spaceStore store.SpaceStore, repoStore store.RepoStore, principalStore store.PrincipalStore, repoCtrl *repo.Controller, membershipStore store.MembershipStore, importer *importer.Repository, exporter *exporter.Repository, - limiter limiter.ResourceLimiter, + limiter limiter.ResourceLimiter, publicAccess *publicaccess.Service, ) *Controller { return &Controller{ nestedSpacesEnabled: config.NestedSpacesEnabled, @@ -88,5 +90,6 @@ func NewController(config *types.Config, tx dbtx.Transactor, urlProvider url.Pro importer: importer, exporter: exporter, resourceLimiter: limiter, + publicAccess: publicAccess, } } diff --git a/app/api/controller/space/create.go b/app/api/controller/space/create.go index 1b9e4fea0c..bc5a7e2d80 100644 --- a/app/api/controller/space/create.go +++ b/app/api/controller/space/create.go @@ -102,7 +102,6 @@ func (c *Controller) createSpaceInnerInTX( ParentID: parentID, Identifier: in.Identifier, Description: in.Description, - IsPublic: in.IsPublic, Path: spacePath, CreatedBy: session.Principal.ID, Created: now, @@ -147,6 +146,17 @@ func (c *Controller) createSpaceInnerInTX( } } + if in.IsPublic { + err = c.publicAccess.Set(ctx, + &types.PublicResource{ + Type: enum.PublicResourceTypeSpace, + ResourceID: space.ID, + }, in.IsPublic) + if err != nil { + return nil, fmt.Errorf("failed to insert a public resource: %w", err) + } + } + return space, nil } diff --git a/app/api/controller/space/events.go b/app/api/controller/space/events.go index 3f4083f857..04da5e930c 100644 --- a/app/api/controller/space/events.go +++ b/app/api/controller/space/events.go @@ -34,7 +34,7 @@ func (c *Controller) Events( return nil, nil, nil, fmt.Errorf("failed to find space ref: %w", err) } - if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceView, true); err != nil { + if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceView, c.publicAccess, true); err != nil { return nil, nil, nil, fmt.Errorf("failed to authorize stream: %w", err) } diff --git a/app/api/controller/space/export.go b/app/api/controller/space/export.go index f8cf5d28a9..0c52ccddd3 100644 --- a/app/api/controller/space/export.go +++ b/app/api/controller/space/export.go @@ -41,7 +41,7 @@ func (c *Controller) Export(ctx context.Context, session *auth.Session, spaceRef return err } - if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceEdit, false); err != nil { + if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceEdit, c.publicAccess, false); err != nil { return err } diff --git a/app/api/controller/space/export_progress.go b/app/api/controller/space/export_progress.go index 92df8b0c9a..9b20c6d8da 100644 --- a/app/api/controller/space/export_progress.go +++ b/app/api/controller/space/export_progress.go @@ -42,7 +42,7 @@ func (c *Controller) ExportProgress(ctx context.Context, return ExportProgressOutput{}, err } - if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceView, false); err != nil { + if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceView, c.publicAccess, false); err != nil { return ExportProgressOutput{}, err } diff --git a/app/api/controller/space/find.go b/app/api/controller/space/find.go index ed301d1dab..c4abe04c3a 100644 --- a/app/api/controller/space/find.go +++ b/app/api/controller/space/find.go @@ -32,7 +32,7 @@ func (c *Controller) Find(ctx context.Context, session *auth.Session, spaceRef s return nil, err } - if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceView, true); err != nil { + if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceView, c.publicAccess, true); err != nil { return nil, err } diff --git a/app/api/controller/space/import.go b/app/api/controller/space/import.go index 094c5f0951..23a7bd2860 100644 --- a/app/api/controller/space/import.go +++ b/app/api/controller/space/import.go @@ -23,6 +23,7 @@ import ( "github.com/harness/gitness/app/auth" "github.com/harness/gitness/app/services/importer" "github.com/harness/gitness/types" + "github.com/harness/gitness/types/enum" ) type ProviderInput struct { @@ -78,12 +79,11 @@ func (c *Controller) Import(ctx context.Context, session *auth.Session, in *Impo } for i, remoteRepository := range remoteRepositories { - repo := remoteRepository.ToRepo( + repo, isPublic := remoteRepository.ToRepo( space.ID, remoteRepository.Identifier, "", &session.Principal, - c.publicResourceCreationEnabled, ) err = c.repoStore.Create(ctx, repo) @@ -93,6 +93,17 @@ func (c *Controller) Import(ctx context.Context, session *auth.Session, in *Impo repoIDs[i] = repo.ID cloneURLs[i] = remoteRepository.CloneURL + + // update public resources + if isPublic && c.publicResourceCreationEnabled { + err = c.publicAccess.Set(ctx, &types.PublicResource{ + Type: enum.PublicResourceTypeRepository, + ResourceID: repo.ID, + }, isPublic) + } + if err != nil { + return fmt.Errorf("failed to set a public repo: %w", err) + } } jobGroupID := fmt.Sprintf("space-import-%d", space.ID) diff --git a/app/api/controller/space/import_repositories.go b/app/api/controller/space/import_repositories.go index 608c0a4700..146f36fc22 100644 --- a/app/api/controller/space/import_repositories.go +++ b/app/api/controller/space/import_repositories.go @@ -108,12 +108,11 @@ func (c *Controller) ImportRepositories( } for _, remoteRepository := range remoteRepositories { - repo := remoteRepository.ToRepo( + repo, isPublic := remoteRepository.ToRepo( space.ID, remoteRepository.Identifier, "", &session.Principal, - c.publicResourceCreationEnabled, ) err = c.repoStore.Create(ctx, repo) @@ -124,6 +123,18 @@ func (c *Controller) ImportRepositories( } else if err != nil { return fmt.Errorf("failed to create repository in storage: %w", err) } + + // update public resources + if isPublic && c.publicResourceCreationEnabled { + err = c.publicAccess.Set(ctx, &types.PublicResource{ + Type: enum.PublicResourceTypeRepository, + ResourceID: repo.ID, + }, isPublic) + } + if err != nil { + return fmt.Errorf("failed to set a public repo: %w", err) + } + repos = append(repos, repo) repoIDs = append(repoIDs, repo.ID) cloneURLs = append(cloneURLs, remoteRepository.CloneURL) diff --git a/app/api/controller/space/list_repositories.go b/app/api/controller/space/list_repositories.go index 2f928f2b0f..6e7d1b39dd 100644 --- a/app/api/controller/space/list_repositories.go +++ b/app/api/controller/space/list_repositories.go @@ -19,7 +19,9 @@ import ( "fmt" apiauth "github.com/harness/gitness/app/api/auth" + "github.com/harness/gitness/app/api/controller/repo" "github.com/harness/gitness/app/auth" + "github.com/harness/gitness/store/database/dbtx" "github.com/harness/gitness/types" "github.com/harness/gitness/types/enum" ) @@ -30,7 +32,7 @@ func (c *Controller) ListRepositories( session *auth.Session, spaceRef string, filter *types.RepoFilter, -) ([]*types.Repository, int64, error) { +) ([]*repo.Repository, int64, error) { space, err := c.spaceStore.FindByRef(ctx, spaceRef) if err != nil { return nil, 0, err @@ -56,20 +58,44 @@ func (c *Controller) ListRepositoriesNoAuth( ctx context.Context, spaceID int64, filter *types.RepoFilter, -) ([]*types.Repository, int64, error) { - count, err := c.repoStore.Count(ctx, spaceID, filter) - if err != nil { - return nil, 0, fmt.Errorf("failed to count child repos: %w", err) - } +) ([]*repo.Repository, int64, error) { + var repos []*repo.Repository + var count int64 - repos, err := c.repoStore.List(ctx, spaceID, filter) - if err != nil { - return nil, 0, fmt.Errorf("failed to list child repos: %w", err) - } + err := c.tx.WithTx(ctx, func(ctx context.Context) (err error) { + count, err = c.repoStore.Count(ctx, spaceID, filter) + if err != nil { + return fmt.Errorf("failed to count child repos: %w", err) + } + + reposBase, err := c.repoStore.List(ctx, spaceID, filter) + if err != nil { + return fmt.Errorf("failed to list child repos: %w", err) + } - // backfill URLs - for _, repo := range repos { - repo.GitURL = c.urlProvider.GenerateGITCloneURL(repo.Path) + for _, repoBase := range reposBase { + // backfill URLs + repoBase.GitURL = c.urlProvider.GenerateGITCloneURL(repoBase.Path) + + // backfill public access mode + isPublic, err := c.publicAccess.Get(ctx, + &types.PublicResource{ + Type: enum.PublicResourceTypeRepository, + ResourceID: repoBase.ID, + }) + if err != nil { + return fmt.Errorf("failed to get resource public access mode: %w", err) + } + + repos = append(repos, &repo.Repository{ + Repository: *repoBase, + IsPublic: isPublic, + }) + } + return nil + }, dbtx.TxDefaultReadOnly) + if err != nil { + return nil, 0, err } return repos, count, nil diff --git a/app/api/controller/space/list_spaces.go b/app/api/controller/space/list_spaces.go index c27d93c228..9a6d6cf80b 100644 --- a/app/api/controller/space/list_spaces.go +++ b/app/api/controller/space/list_spaces.go @@ -25,12 +25,17 @@ import ( "github.com/harness/gitness/types/enum" ) +type Space struct { + types.Space + IsPublic bool `json:"is_public"` +} + // ListSpaces lists the child spaces of a space. func (c *Controller) ListSpaces(ctx context.Context, session *auth.Session, spaceRef string, filter *types.SpaceFilter, -) ([]*types.Space, int64, error) { +) ([]*Space, int64, error) { space, err := c.spaceStore.FindByRef(ctx, spaceRef) if err != nil { return nil, 0, err @@ -47,6 +52,7 @@ func (c *Controller) ListSpaces(ctx context.Context, ); err != nil { return nil, 0, err } + return c.ListSpacesNoAuth(ctx, space.ID, filter) } @@ -55,8 +61,8 @@ func (c *Controller) ListSpacesNoAuth( ctx context.Context, spaceID int64, filter *types.SpaceFilter, -) ([]*types.Space, int64, error) { - var spaces []*types.Space +) ([]*Space, int64, error) { + var spaces []*Space var count int64 err := c.tx.WithTx(ctx, func(ctx context.Context) (err error) { @@ -65,11 +71,27 @@ func (c *Controller) ListSpacesNoAuth( return fmt.Errorf("failed to count child spaces: %w", err) } - spaces, err = c.spaceStore.List(ctx, spaceID, filter) + spacesBase, err := c.spaceStore.List(ctx, spaceID, filter) if err != nil { return fmt.Errorf("failed to list child spaces: %w", err) } + for _, spaceBase := range spacesBase { + // backfill public access mode + isPublic, err := c.publicAccess.Get(ctx, &types.PublicResource{ + Type: enum.PublicResourceTypeSpace, + ResourceID: spaceBase.ID, + }) + if err != nil { + return fmt.Errorf("failed to get resource public access mode: %w", err) + } + + spaces = append(spaces, &Space{ + Space: *spaceBase, + IsPublic: isPublic, + }) + } + return nil }, dbtx.TxDefaultReadOnly) if err != nil { diff --git a/app/api/controller/space/membership_add.go b/app/api/controller/space/membership_add.go index 1b0c63c7b9..14a5224350 100644 --- a/app/api/controller/space/membership_add.go +++ b/app/api/controller/space/membership_add.go @@ -66,7 +66,7 @@ func (c *Controller) MembershipAdd(ctx context.Context, return nil, err } - if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceEdit, false); err != nil { + if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceEdit, c.publicAccess, false); err != nil { return nil, err } diff --git a/app/api/controller/space/membership_delete.go b/app/api/controller/space/membership_delete.go index 698b895db8..8f5784639d 100644 --- a/app/api/controller/space/membership_delete.go +++ b/app/api/controller/space/membership_delete.go @@ -35,7 +35,7 @@ func (c *Controller) MembershipDelete(ctx context.Context, return err } - if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceEdit, false); err != nil { + if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceEdit, c.publicAccess, false); err != nil { return err } diff --git a/app/api/controller/space/membership_list.go b/app/api/controller/space/membership_list.go index 1f4e9f936e..c3cb2c45fc 100644 --- a/app/api/controller/space/membership_list.go +++ b/app/api/controller/space/membership_list.go @@ -36,7 +36,7 @@ func (c *Controller) MembershipList(ctx context.Context, return nil, 0, err } - if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceView, false); err != nil { + if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceView, c.publicAccess, false); err != nil { return nil, 0, err } diff --git a/app/api/controller/space/membership_update.go b/app/api/controller/space/membership_update.go index f14223a0c1..0dd079637b 100644 --- a/app/api/controller/space/membership_update.go +++ b/app/api/controller/space/membership_update.go @@ -58,7 +58,7 @@ func (c *Controller) MembershipUpdate(ctx context.Context, return nil, err } - if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceEdit, false); err != nil { + if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceEdit, c.publicAccess, false); err != nil { return nil, err } diff --git a/app/api/controller/space/move.go b/app/api/controller/space/move.go index 7ab78a875f..53bc81396d 100644 --- a/app/api/controller/space/move.go +++ b/app/api/controller/space/move.go @@ -55,7 +55,7 @@ func (c *Controller) Move( return nil, err } - if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceEdit, false); err != nil { + if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceEdit, c.publicAccess, false); err != nil { return nil, err } diff --git a/app/api/controller/space/purge.go b/app/api/controller/space/purge.go index bfa4b4c9aa..1e17fa8010 100644 --- a/app/api/controller/space/purge.go +++ b/app/api/controller/space/purge.go @@ -43,7 +43,7 @@ func (c *Controller) Purge( // authz will check the permission within the first existing parent since space was deleted. // purge top level space is limited to admin only. - err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceDelete, false) + err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceDelete, c.publicAccess, false) if err != nil { return fmt.Errorf("failed to authorize on space purge: %w", err) } diff --git a/app/api/controller/space/restore.go b/app/api/controller/space/restore.go index 7a86992080..f9892b515b 100644 --- a/app/api/controller/space/restore.go +++ b/app/api/controller/space/restore.go @@ -56,7 +56,7 @@ func (c *Controller) Restore( } // check view permission on the original ref. - err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceView, false) + err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceView, c.publicAccess, false) if err != nil { return nil, fmt.Errorf("failed to authorize on space restore: %w", err) } diff --git a/app/api/controller/space/soft_delete.go b/app/api/controller/space/soft_delete.go index 4b33b03f64..eb490d49df 100644 --- a/app/api/controller/space/soft_delete.go +++ b/app/api/controller/space/soft_delete.go @@ -47,6 +47,7 @@ func (c *Controller) SoftDelete( session, space, enum.PermissionSpaceDelete, + c.publicAccess, false, ); err != nil { return nil, fmt.Errorf("failed to check access: %w", err) diff --git a/app/api/controller/space/update.go b/app/api/controller/space/update.go index 1a057d0746..8301aff659 100644 --- a/app/api/controller/space/update.go +++ b/app/api/controller/space/update.go @@ -29,12 +29,10 @@ import ( // UpdateInput is used for updating a space. type UpdateInput struct { Description *string `json:"description"` - IsPublic *bool `json:"is_public"` } func (in *UpdateInput) hasChanges(space *types.Space) bool { - return (in.Description != nil && *in.Description != space.Description) || - (in.IsPublic != nil && *in.IsPublic != space.IsPublic) + return in.Description != nil && *in.Description != space.Description } // Update updates a space. @@ -45,7 +43,7 @@ func (c *Controller) Update(ctx context.Context, session *auth.Session, return nil, err } - if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceEdit, false); err != nil { + if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceEdit, c.publicAccess, false); err != nil { return nil, err } @@ -62,9 +60,6 @@ func (c *Controller) Update(ctx context.Context, session *auth.Session, if in.Description != nil { space.Description = *in.Description } - if in.IsPublic != nil { - space.IsPublic = *in.IsPublic - } return nil }) @@ -76,12 +71,6 @@ func (c *Controller) Update(ctx context.Context, session *auth.Session, } func (c *Controller) sanitizeUpdateInput(in *UpdateInput) error { - if in.IsPublic != nil { - if *in.IsPublic && !c.publicResourceCreationEnabled { - return errPublicSpaceCreationDisabled - } - } - if in.Description != nil { *in.Description = strings.TrimSpace(*in.Description) if err := check.Description(*in.Description); err != nil { diff --git a/app/api/controller/space/wire.go b/app/api/controller/space/wire.go index 3fe6f4e304..adcd23c236 100644 --- a/app/api/controller/space/wire.go +++ b/app/api/controller/space/wire.go @@ -20,6 +20,7 @@ import ( "github.com/harness/gitness/app/auth/authz" "github.com/harness/gitness/app/services/exporter" "github.com/harness/gitness/app/services/importer" + "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/sse" "github.com/harness/gitness/app/store" "github.com/harness/gitness/app/url" @@ -41,11 +42,11 @@ func ProvideController(config *types.Config, tx dbtx.Transactor, urlProvider url connectorStore store.ConnectorStore, templateStore store.TemplateStore, spaceStore store.SpaceStore, repoStore store.RepoStore, principalStore store.PrincipalStore, repoCtrl *repo.Controller, membershipStore store.MembershipStore, importer *importer.Repository, - exporter *exporter.Repository, limiter limiter.ResourceLimiter, + exporter *exporter.Repository, limiter limiter.ResourceLimiter, publicAccess *publicaccess.Service, ) *Controller { return NewController(config, tx, urlProvider, sseStreamer, identifierCheck, authorizer, spacePathStore, pipelineStore, secretStore, connectorStore, templateStore, spaceStore, repoStore, principalStore, - repoCtrl, membershipStore, importer, exporter, limiter) + repoCtrl, membershipStore, importer, exporter, limiter, publicAccess) } diff --git a/app/api/controller/upload/controller.go b/app/api/controller/upload/controller.go index 10532e901a..78c440e593 100644 --- a/app/api/controller/upload/controller.go +++ b/app/api/controller/upload/controller.go @@ -26,6 +26,7 @@ import ( "github.com/harness/gitness/app/api/usererror" "github.com/harness/gitness/app/auth" "github.com/harness/gitness/app/auth/authz" + "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/store" "github.com/harness/gitness/blob" "github.com/harness/gitness/types" @@ -46,19 +47,22 @@ var supportedFileTypes = map[string]struct{}{ } type Controller struct { - authorizer authz.Authorizer - repoStore store.RepoStore - blobStore blob.Store + authorizer authz.Authorizer + repoStore store.RepoStore + blobStore blob.Store + publicAccess *publicaccess.Service } func NewController(authorizer authz.Authorizer, repoStore store.RepoStore, blobStore blob.Store, + publicAccess *publicaccess.Service, ) *Controller { return &Controller{ - authorizer: authorizer, - repoStore: repoStore, - blobStore: blobStore, + authorizer: authorizer, + repoStore: repoStore, + blobStore: blobStore, + publicAccess: publicAccess, } } func (c *Controller) getRepoCheckAccess(ctx context.Context, @@ -76,7 +80,7 @@ func (c *Controller) getRepoCheckAccess(ctx context.Context, return nil, fmt.Errorf("failed to find repo: %w", err) } - if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, reqPermission, orPublic); err != nil { + if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, reqPermission, c.publicAccess, orPublic); err != nil { return nil, fmt.Errorf("failed to verify authorization: %w", err) } diff --git a/app/api/controller/upload/upload.go b/app/api/controller/upload/upload.go index 9db2c00d9f..5c6bb93e30 100644 --- a/app/api/controller/upload/upload.go +++ b/app/api/controller/upload/upload.go @@ -42,7 +42,7 @@ func (c *Controller) Upload(ctx context.Context, file io.Reader, ) (*Result, error) { // Permission check to see if the user in request has access to the repo. - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView, false) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoReview, false) if err != nil { return nil, fmt.Errorf("failed to acquire access to repo: %w", err) } diff --git a/app/api/controller/upload/wire.go b/app/api/controller/upload/wire.go index 68c6ea6e6d..bbc72dbf43 100644 --- a/app/api/controller/upload/wire.go +++ b/app/api/controller/upload/wire.go @@ -16,6 +16,7 @@ package upload import ( "github.com/harness/gitness/app/auth/authz" + "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/store" "github.com/harness/gitness/blob" @@ -31,6 +32,7 @@ func ProvideController( authorizer authz.Authorizer, repoStore store.RepoStore, blobStore blob.Store, + publicAccess *publicaccess.Service, ) *Controller { - return NewController(authorizer, repoStore, blobStore) + return NewController(authorizer, repoStore, blobStore, publicAccess) } diff --git a/app/api/controller/webhook/controller.go b/app/api/controller/webhook/controller.go index 2763ea6037..c5be7d221c 100644 --- a/app/api/controller/webhook/controller.go +++ b/app/api/controller/webhook/controller.go @@ -22,6 +22,7 @@ import ( "github.com/harness/gitness/app/api/usererror" "github.com/harness/gitness/app/auth" "github.com/harness/gitness/app/auth/authz" + "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/services/webhook" "github.com/harness/gitness/app/store" "github.com/harness/gitness/encrypt" @@ -39,6 +40,7 @@ type Controller struct { repoStore store.RepoStore webhookService *webhook.Service encrypter encrypt.Encrypter + publicAccess *publicaccess.Service } func NewController( @@ -50,6 +52,7 @@ func NewController( repoStore store.RepoStore, webhookService *webhook.Service, encrypter encrypt.Encrypter, + publicAccess *publicaccess.Service, ) *Controller { return &Controller{ allowLoopback: allowLoopback, @@ -60,6 +63,7 @@ func NewController( repoStore: repoStore, webhookService: webhookService, encrypter: encrypter, + publicAccess: publicAccess, } } @@ -74,7 +78,7 @@ func (c *Controller) getRepoCheckAccess(ctx context.Context, return nil, fmt.Errorf("failed to find repo: %w", err) } - if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, reqPermission, false); err != nil { + if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, reqPermission, c.publicAccess, false); err != nil { return nil, fmt.Errorf("failed to verify authorization: %w", err) } diff --git a/app/api/controller/webhook/wire.go b/app/api/controller/webhook/wire.go index 749f0d0f9c..c11affe710 100644 --- a/app/api/controller/webhook/wire.go +++ b/app/api/controller/webhook/wire.go @@ -16,6 +16,7 @@ package webhook import ( "github.com/harness/gitness/app/auth/authz" + "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/services/webhook" "github.com/harness/gitness/app/store" "github.com/harness/gitness/encrypt" @@ -30,10 +31,10 @@ var WireSet = wire.NewSet( func ProvideController(config webhook.Config, authorizer authz.Authorizer, webhookStore store.WebhookStore, webhookExecutionStore store.WebhookExecutionStore, - repoStore store.RepoStore, webhookService *webhook.Service, encrypter encrypt.Encrypter, + repoStore store.RepoStore, webhookService *webhook.Service, encrypter encrypt.Encrypter, publicAccess *publicaccess.Service, ) *Controller { return NewController( config.AllowLoopback, config.AllowPrivateNetwork, authorizer, webhookStore, webhookExecutionStore, - repoStore, webhookService, encrypter) + repoStore, webhookService, encrypter, publicAccess) } diff --git a/app/api/handler/repo/visibility_update.go b/app/api/handler/repo/visibility_update.go new file mode 100644 index 0000000000..db7656d0d6 --- /dev/null +++ b/app/api/handler/repo/visibility_update.go @@ -0,0 +1,52 @@ +// Copyright 2023 Harness, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package repo + +import ( + "encoding/json" + "net/http" + + "github.com/harness/gitness/app/api/controller/repo" + "github.com/harness/gitness/app/api/render" + "github.com/harness/gitness/app/api/request" +) + +func HandleVisibilityUpdate(repoCtrl *repo.Controller) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + session, _ := request.AuthSessionFrom(ctx) + + repoRef, err := request.GetRepoRefFromPath(r) + if err != nil { + render.TranslatedUserError(ctx, w, err) + return + } + + in := new(repo.VisibilityInput) + err = json.NewDecoder(r.Body).Decode(in) + if err != nil { + render.BadRequestf(ctx, w, "Invalid Request Body: %s.", err) + return + } + + repo, err := repoCtrl.VisibilityUpdate(ctx, session, repoRef, in) + if err != nil { + render.TranslatedUserError(ctx, w, err) + return + } + + render.JSON(w, http.StatusOK, repo) + } +} diff --git a/app/router/api.go b/app/router/api.go index 6dbc848d02..9ccd90a4b8 100644 --- a/app/router/api.go +++ b/app/router/api.go @@ -276,6 +276,7 @@ func setupRepos(r chi.Router, r.Delete("/", handlerrepo.HandleSoftDelete(repoCtrl)) r.Post("/purge", handlerrepo.HandlePurge(repoCtrl)) r.Post("/restore", handlerrepo.HandleRestore(repoCtrl)) + r.Patch("/visibility", handlerrepo.HandleVisibilityUpdate(repoCtrl)) r.Get("/settings/security", handlerreposettings.HandleSecurityFind(repoSettingsCtrl)) r.Patch("/settings/security", handlerreposettings.HandleSecurityUpdate(repoSettingsCtrl)) diff --git a/app/services/exporter/repository.go b/app/services/exporter/repository.go index 311ed8fea8..48c329332d 100644 --- a/app/services/exporter/repository.go +++ b/app/services/exporter/repository.go @@ -25,6 +25,7 @@ import ( "time" "github.com/harness/gitness/app/api/controller/repo" + "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/sse" "github.com/harness/gitness/app/store" gitnessurl "github.com/harness/gitness/app/url" @@ -48,12 +49,13 @@ var ( ) type Repository struct { - urlProvider gitnessurl.Provider - git git.Interface - repoStore store.RepoStore - scheduler *job.Scheduler - encrypter encrypt.Encrypter - sseStreamer sse.Streamer + urlProvider gitnessurl.Provider + git git.Interface + repoStore store.RepoStore + scheduler *job.Scheduler + encrypter encrypt.Encrypter + sseStreamer sse.Streamer + publicAccess *publicaccess.Service } type Input struct { @@ -114,11 +116,21 @@ func (r *Repository) RunManyForSpace( jobDefinitions := make([]job.Definition, len(repos)) for i, repository := range repos { + // check if repo is public + isPublic, err := r.publicAccess.Get(ctx, + &types.PublicResource{ + Type: enum.PublicResourceTypeRepository, + ResourceID: repository.ID, + }) + if err != nil { + return fmt.Errorf("failed to check repo public visibility: %w", err) + } + repoJobData := Input{ Identifier: repository.Identifier, ID: repository.ID, Description: repository.Description, - IsPublic: repository.IsPublic, + IsPublic: isPublic, HarnessCodeInfo: *harnessCodeInfo, } @@ -188,7 +200,6 @@ func (r *Repository) Handle(ctx context.Context, data string, _ job.ProgressRepo Identifier: repository.Identifier, DefaultBranch: repository.DefaultBranch, Description: repository.Description, - IsPublic: repository.IsPublic, Readme: false, License: "", GitIgnore: "", diff --git a/app/services/exporter/wire.go b/app/services/exporter/wire.go index 7085dd470e..b6e7033f2c 100644 --- a/app/services/exporter/wire.go +++ b/app/services/exporter/wire.go @@ -15,6 +15,7 @@ package exporter import ( + "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/sse" "github.com/harness/gitness/app/store" "github.com/harness/gitness/app/url" @@ -37,14 +38,16 @@ func ProvideSpaceExporter( executor *job.Executor, encrypter encrypt.Encrypter, sseStreamer sse.Streamer, + publicAccess *publicaccess.Service, ) (*Repository, error) { exporter := &Repository{ - urlProvider: urlProvider, - git: git, - repoStore: repoStore, - scheduler: scheduler, - encrypter: encrypter, - sseStreamer: sseStreamer, + urlProvider: urlProvider, + git: git, + repoStore: repoStore, + scheduler: scheduler, + encrypter: encrypter, + sseStreamer: sseStreamer, + publicAccess: publicAccess, } err := executor.Register(jobType, exporter) diff --git a/app/services/importer/provider.go b/app/services/importer/provider.go index 32ddf7f7c0..ad821de962 100644 --- a/app/services/importer/provider.go +++ b/app/services/importer/provider.go @@ -75,14 +75,13 @@ type RepositoryInfo struct { DefaultBranch string } -// ToRepo converts the RepositoryInfo into the types.Repository object marked as being imported. +// ToRepo converts the RepositoryInfo into the types.Repository object marked as being imported and is public flag. func (r *RepositoryInfo) ToRepo( spaceID int64, identifier string, description string, principal *types.Principal, - publicResourceCreationEnabled bool, -) *types.Repository { +) (*types.Repository, bool) { now := time.Now().UnixMilli() gitTempUID := fmt.Sprintf("importing-%s-%d", hash(fmt.Sprintf("%d:%s", spaceID, identifier)), now) return &types.Repository{ @@ -91,14 +90,13 @@ func (r *RepositoryInfo) ToRepo( Identifier: identifier, GitUID: gitTempUID, // the correct git UID will be set by the job handler Description: description, - IsPublic: publicResourceCreationEnabled && r.IsPublic, CreatedBy: principal.ID, Created: now, Updated: now, ForkID: 0, DefaultBranch: r.DefaultBranch, Importing: true, - } + }, r.IsPublic } func hash(s string) string { diff --git a/app/services/importer/repository.go b/app/services/importer/repository.go index 5f4ae0a3ee..55d23a82d5 100644 --- a/app/services/importer/repository.go +++ b/app/services/importer/repository.go @@ -53,6 +53,7 @@ var ( type Repository struct { defaultBranch string + isPublic bool urlProvider gitnessurl.Provider git git.Interface tx dbtx.Transactor diff --git a/app/services/publicaccess/manager.go b/app/services/publicaccess/manager.go new file mode 100644 index 0000000000..faaec8694a --- /dev/null +++ b/app/services/publicaccess/manager.go @@ -0,0 +1,62 @@ +// Copyright 2023 Harness, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package publicaccess + +import ( + "context" + "errors" + "fmt" + + "github.com/harness/gitness/app/store" + gitness_store "github.com/harness/gitness/store" + + "github.com/harness/gitness/types" +) + +type PublicAccessManager struct { + publicResourceStore store.PublicResource +} + +func NewPublicAccessManager( + publicResourceStore store.PublicResource, +) *PublicAccessManager { + return &PublicAccessManager{ + publicResourceStore: publicResourceStore, + } +} + +func (r *PublicAccessManager) Get( + ctx context.Context, + resource *types.PublicResource) (bool, error) { + _, err := r.publicResourceStore.Find(ctx, resource) + if errors.Is(err, gitness_store.ErrResourceNotFound) { + return false, nil + } + if err != nil { + return false, fmt.Errorf("failed to get public access resource: %w", err) + } + + return true, nil +} + +func (r *PublicAccessManager) Set(ctx context.Context, + resource *types.PublicResource, + enable bool) error { + if enable { + return r.publicResourceStore.Create(ctx, resource) + } else { + return r.publicResourceStore.Delete(ctx, resource) + } +} diff --git a/app/services/publicaccess/public_access.go b/app/services/publicaccess/public_access.go new file mode 100644 index 0000000000..61c58074da --- /dev/null +++ b/app/services/publicaccess/public_access.go @@ -0,0 +1,44 @@ +// Copyright 2023 Harness, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package publicaccess + +import ( + "context" + + "github.com/harness/gitness/types" +) + +// PublicAccess is an abstraction of an entity responsible for managing public access to resources. +type PublicAccess interface { + /* + * Get returns whether resource public access is enabled. + * Returns + * (true, nil) - resource public access is allowed + * (false, nil) - resource public access is not allowed + * (false, err) - an error occurred while performing the public access check. + */ + Get(ctx context.Context, + resource *types.PublicResource) (bool, error) + + /* + * Sets the resource public access mode with the provided value. + * Returns + * err - resource public access mode has been updated successfully + * nil - an error occurred while performing the public access set. + */ + Set(ctx context.Context, + resource *types.PublicResource, + enable bool) error +} diff --git a/app/services/publicaccess/service.go b/app/services/publicaccess/service.go new file mode 100644 index 0000000000..1a54795245 --- /dev/null +++ b/app/services/publicaccess/service.go @@ -0,0 +1,48 @@ +// Copyright 2023 Harness, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package publicaccess + +import ( + "context" + + "github.com/harness/gitness/types" +) + +type Service struct { + manager PublicAccess +} + +func NewService( + manager PublicAccess, +) *Service { + return &Service{ + manager: manager, + } +} + +func (s *Service) Get( + ctx context.Context, + resource *types.PublicResource, +) (bool, error) { + return s.manager.Get(ctx, resource) +} + +func (s *Service) Set( + ctx context.Context, + resource *types.PublicResource, + enable bool, +) error { + return s.manager.Set(ctx, resource, enable) +} diff --git a/app/services/publicaccess/wire.go b/app/services/publicaccess/wire.go new file mode 100644 index 0000000000..bf1e17c801 --- /dev/null +++ b/app/services/publicaccess/wire.go @@ -0,0 +1,42 @@ +// Copyright 2023 Harness, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package publicaccess + +import ( + "github.com/google/wire" + "github.com/harness/gitness/app/store" +) + +var WireSet = wire.NewSet( + ProvidePublicAccessManager, + ProvidePublicAccess, + ProvideService, +) + +func ProvideService( + manager PublicAccess, +) *Service { + return NewService(manager) +} + +func ProvidePublicAccessManager( + publicResources store.PublicResource, +) *PublicAccessManager { + return NewPublicAccessManager(publicResources) +} + +func ProvidePublicAccess(p *PublicAccessManager) PublicAccess { + return p +} diff --git a/app/store/database.go b/app/store/database.go index 2c4415c0ff..b96af02380 100644 --- a/app/store/database.go +++ b/app/store/database.go @@ -290,6 +290,13 @@ type ( ListSpaces(ctx context.Context, userID int64, filter types.MembershipSpaceFilter) ([]types.MembershipSpace, error) } + // PublicResource defines the publicly accessible resources data storage. + PublicResource interface { + Find(ctx context.Context, publicResource *types.PublicResource) (bool, error) + Create(ctx context.Context, publicResource *types.PublicResource) error + Delete(ctx context.Context, publicResource *types.PublicResource) error + } + // TokenStore defines the token data storage. TokenStore interface { // Find finds the token by id diff --git a/app/store/database/migrate/postgres/0050_create_table_public_resources.down.sql b/app/store/database/migrate/postgres/0050_create_table_public_resources.down.sql new file mode 100644 index 0000000000..b218cf6622 --- /dev/null +++ b/app/store/database/migrate/postgres/0050_create_table_public_resources.down.sql @@ -0,0 +1,28 @@ +-- copy public repositories +ALTER TABLE repositories ADD COLUMN repo_is_public; + +UPDATE repositories +WHERE repo_id IN ( + SELECT public_resource_repo_id + FROM public_resources + WHERE public_resource_type = 'repository' AND public_resource_repo_id IS NOT NULL; +) SET +repo_is_public = TRUE; + + +-- copy public spaces +ALTER TABLE spaces ADD COLUMN space_is_public; + +-- update public resources +UPDATE spaces +WHERE space_id IN ( + SELECT public_resource_space_id + FROM public_resources + WHERE public_resource_type = 'space' AND public_resource_space_id IS NOT NULL; +) SET +sapce_is_public = TRUE; + +-- clear public_resoureces +DROP INDEX public_resource_space_id_key; +DROP INDEX public_resource_repo_id_key; +DROP TABLE public_resources; \ No newline at end of file diff --git a/app/store/database/migrate/postgres/0050_create_table_public_resources.up.sql b/app/store/database/migrate/postgres/0050_create_table_public_resources.up.sql new file mode 100644 index 0000000000..bb10e924de --- /dev/null +++ b/app/store/database/migrate/postgres/0050_create_table_public_resources.up.sql @@ -0,0 +1,55 @@ +CREATE TABLE public_resources ( + public_resource_id SERIAL PRIMARY KEY +,public_resource_type TEXT NOT NULL +,public_resource_space_id INTEGER +,public_resource_repo_id INTEGER + +,CONSTRAINT fk_public_resource_space_id FOREIGN KEY (public_resource_space_id) + REFERENCES spaces (space_id) MATCH SIMPLE + ON UPDATE NO ACTION + ON DELETE CASCADE +,CONSTRAINT fk_public_resource_repo_id FOREIGN KEY (public_resource_repo_id) + REFERENCES repositories (repo_id) MATCH SIMPLE + ON UPDATE NO ACTION + ON DELETE CASCADE +); + +CREATE UNIQUE INDEX public_resource_space_id_key + ON public_resources(public_resource_space_id) + WHERE public_resource_space_id IS NOT NULL; + +CREATE UNIQUE INDEX public_resource_repo_id_key + ON public_resources(public_resource_repo_id) + WHERE public_resource_repo_id IS NOT NULL; + +-- move public repos into public_resource +INSERT INTO public_resources ( + public_resource_type + ,public_resource_space_id + ,public_resource_repo_id +) +SELECT + 'repository' + ,NULL + ,repo_id +FROM repositories +WHERE repo_is_public = TRUE; + +-- alter repo table +ALTER TABLE repositories DROP COLUMN repo_is_public; + +-- move public spaces into public_resource +INSERT INTO public_resources ( + public_resource_type + ,public_resource_space_id + ,public_resource_repo_id +) +SELECT + 'space' + ,space_id + ,NULL +FROM spaces +WHERE space_is_public = TRUE; + +-- alter space table +ALTER TABLE spaces DROP COLUMN space_is_public; diff --git a/app/store/database/migrate/sqlite/0050_create_table_public_resources.down.sql b/app/store/database/migrate/sqlite/0050_create_table_public_resources.down.sql new file mode 100644 index 0000000000..b218cf6622 --- /dev/null +++ b/app/store/database/migrate/sqlite/0050_create_table_public_resources.down.sql @@ -0,0 +1,28 @@ +-- copy public repositories +ALTER TABLE repositories ADD COLUMN repo_is_public; + +UPDATE repositories +WHERE repo_id IN ( + SELECT public_resource_repo_id + FROM public_resources + WHERE public_resource_type = 'repository' AND public_resource_repo_id IS NOT NULL; +) SET +repo_is_public = TRUE; + + +-- copy public spaces +ALTER TABLE spaces ADD COLUMN space_is_public; + +-- update public resources +UPDATE spaces +WHERE space_id IN ( + SELECT public_resource_space_id + FROM public_resources + WHERE public_resource_type = 'space' AND public_resource_space_id IS NOT NULL; +) SET +sapce_is_public = TRUE; + +-- clear public_resoureces +DROP INDEX public_resource_space_id_key; +DROP INDEX public_resource_repo_id_key; +DROP TABLE public_resources; \ No newline at end of file diff --git a/app/store/database/migrate/sqlite/0050_create_table_public_resources.up.sql b/app/store/database/migrate/sqlite/0050_create_table_public_resources.up.sql new file mode 100644 index 0000000000..07f0f51421 --- /dev/null +++ b/app/store/database/migrate/sqlite/0050_create_table_public_resources.up.sql @@ -0,0 +1,55 @@ +CREATE TABLE public_resources ( + public_resource_id SERIAL PRIMARY KEY +,public_resource_type TEXT NOT NULL +,public_resource_space_id INTEGER +,public_resource_repo_id INTEGER + +,CONSTRAINT fk_public_resource_space_id FOREIGN KEY (public_resource_space_id) + REFERENCES spaces (space_id) MATCH SIMPLE + ON UPDATE NO ACTION + ON DELETE CASCADE +,CONSTRAINT fk_public_resource_repo_id FOREIGN KEY (public_resource_repo_id) + REFERENCES repositories (repo_id) MATCH SIMPLE + ON UPDATE NO ACTION + ON DELETE CASCADE +); + +CREATE UNIQUE INDEX public_resource_space_id_key + ON public_resources(public_resource_space_id) + WHERE public_resource_space_id IS NOT NULL; + +CREATE UNIQUE INDEX public_resource_repo_id_key + ON public_resources(public_resource_repo_id) + WHERE public_resource_repo_id IS NOT NULL; + +-- move public repos into public_resource +INSERT INTO public_resources ( + public_resource_type + ,public_resource_space_id + ,public_resource_repo_id +) +SELECT + 'repository' + ,NULL + ,repo_id +FROM repositories +WHERE repo_is_public = TRUE; + +-- alter repo table +ALTER TABLE repositories DROP COLUMN repo_is_public; + +-- move public spaces into public_resource +INSERT INTO public_resources ( + public_resource_type + ,public_resource_space_id + ,public_resource_repo_id +) +SELECT + 'space' + ,space_id + ,NULL +FROM spaces +WHERE space_is_public = TRUE; + +-- alter space table +ALTER TABLE spaces DROP COLUMN space_is_public; diff --git a/app/store/database/public_resource.go b/app/store/database/public_resource.go new file mode 100644 index 0000000000..a123649a53 --- /dev/null +++ b/app/store/database/public_resource.go @@ -0,0 +1,159 @@ +// Copyright 2023 Harness, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package database + +import ( + "context" + "fmt" + + "github.com/guregu/null" + "github.com/harness/gitness/app/store" + "github.com/harness/gitness/store/database" + "github.com/harness/gitness/store/database/dbtx" + "github.com/harness/gitness/types/enum" + "github.com/jmoiron/sqlx" + + "github.com/harness/gitness/types" +) + +var _ store.PublicResource = (*PublicResourcesStore)(nil) + +// NewPublicResourcesStore returns a new PublicResourcesStore. +func NewPublicResourcesStore(db *sqlx.DB) *PublicResourcesStore { + return &PublicResourcesStore{ + db: db, + } +} + +// PublicResourcesStore implements store.SettingsStore backed by a relational database. +type PublicResourcesStore struct { + db *sqlx.DB +} + +type publicResource struct { + ID int64 `db:"public_resource_id"` + Type string `db:"public_resource_type"` + SpaceID null.Int `db:"public_resource_space_id"` + RepoID null.Int `db:"public_resource_repo_id"` +} + +const ( + publicResourceColumns = ` + public_resource_id + ,public_resource_type + ,public_resource_space_id + ,public_resource_repo_id + ` +) + +func (p *PublicResourcesStore) Find( + ctx context.Context, + publicRsc *types.PublicResource, +) (bool, error) { + stmt := database.Builder. + Select(publicResourceColumns). + From("public_resources"). + Where("public_resource_type = ?", publicRsc.Type) + + switch publicRsc.Type { + case enum.PublicResourceTypeRepository: + stmt = stmt.Where("public_resource_repo_id = ?", publicRsc.ResourceID) + case enum.PublicResourceTypeSpace: + stmt = stmt.Where("public_resource_space_id = ?", publicRsc.ResourceID) + default: + return false, fmt.Errorf("public resource type %q is not supported", publicRsc.Type) + } + + sql, args, err := stmt.ToSql() + if err != nil { + return false, fmt.Errorf("failed to convert query to sql: %w", err) + } + + db := dbtx.GetAccessor(ctx, p.db) + + dst := &publicResource{} + err = db.GetContext(ctx, dst, sql, args...) + if err != nil { + return false, database.ProcessSQLErrorf(ctx, err, "Select query failed") + } + + return true, nil +} + +func (p *PublicResourcesStore) Create( + ctx context.Context, + publicRsc *types.PublicResource) error { + stmt := database.Builder. + Insert(""). + Into("public_resources"). + Columns( + "public_resource_type", + "public_resource_space_id", + "public_resource_repo_id", + ) + + switch publicRsc.Type { + case enum.PublicResourceTypeRepository: + stmt = stmt.Values(enum.PublicResourceTypeRepository, null.Int{}, null.IntFrom(publicRsc.ResourceID)) + case enum.PublicResourceTypeSpace: + stmt = stmt.Values(enum.PublicResourceTypeSpace, null.IntFrom(publicRsc.ResourceID), null.Int{}) + default: + return fmt.Errorf("public resource type %q is not supported", publicRsc.Type) + } + + sql, args, err := stmt.ToSql() + if err != nil { + return fmt.Errorf("failed to convert query to sql: %w", err) + } + + db := dbtx.GetAccessor(ctx, p.db) + + if _, err := db.ExecContext(ctx, sql, args...); err != nil { + return database.ProcessSQLErrorf(ctx, err, "Insert query failed") + } + + return nil +} + +func (p *PublicResourcesStore) Delete( + ctx context.Context, + publicRsc *types.PublicResource) error { + stmt := database.Builder. + Delete("public_resources"). + Where("public_resource_type = ?", publicRsc.Type) + + switch publicRsc.Type { + case enum.PublicResourceTypeRepository: + stmt = stmt.Where("public_resource_repo_id = ?", publicRsc.ResourceID) + case enum.PublicResourceTypeSpace: + stmt = stmt.Where("public_resource_space_id = ?", publicRsc.ResourceID) + default: + return fmt.Errorf("public resource type %q is not supported", publicRsc.Type) + } + + sql, args, err := stmt.ToSql() + if err != nil { + return fmt.Errorf("failed to convert delete public resource query to sql: %w", err) + } + + db := dbtx.GetAccessor(ctx, p.db) + + _, err = db.ExecContext(ctx, sql, args...) + if err != nil { + return database.ProcessSQLErrorf(ctx, err, "the delete query failed") + } + + return nil +} diff --git a/app/store/database/repo.go b/app/store/database/repo.go index deb36c0ae8..f3bb7b4d2a 100644 --- a/app/store/database/repo.go +++ b/app/store/database/repo.go @@ -67,7 +67,6 @@ type repository struct { ParentID int64 `db:"repo_parent_id"` Identifier string `db:"repo_uid"` Description string `db:"repo_description"` - IsPublic bool `db:"repo_is_public"` CreatedBy int64 `db:"repo_created_by"` Created int64 `db:"repo_created"` Updated int64 `db:"repo_updated"` @@ -98,7 +97,6 @@ const ( ,repo_parent_id ,repo_uid ,repo_description - ,repo_is_public ,repo_created_by ,repo_created ,repo_updated @@ -223,7 +221,6 @@ func (s *RepoStore) Create(ctx context.Context, repo *types.Repository) error { ,repo_parent_id ,repo_uid ,repo_description - ,repo_is_public ,repo_created_by ,repo_created ,repo_updated @@ -246,7 +243,6 @@ func (s *RepoStore) Create(ctx context.Context, repo *types.Repository) error { ,:repo_parent_id ,:repo_uid ,:repo_description - ,:repo_is_public ,:repo_created_by ,:repo_created ,:repo_updated @@ -298,7 +294,6 @@ func (s *RepoStore) Update(ctx context.Context, repo *types.Repository) error { ,repo_uid = :repo_uid ,repo_git_uid = :repo_git_uid ,repo_description = :repo_description - ,repo_is_public = :repo_is_public ,repo_default_branch = :repo_default_branch ,repo_pullreq_seq = :repo_pullreq_seq ,repo_num_forks = :repo_num_forks @@ -734,7 +729,6 @@ func (s *RepoStore) mapToRepo( ParentID: in.ParentID, Identifier: in.Identifier, Description: in.Description, - IsPublic: in.IsPublic, Created: in.Created, CreatedBy: in.CreatedBy, Updated: in.Updated, @@ -818,7 +812,6 @@ func mapToInternalRepo(in *types.Repository) *repository { ParentID: in.ParentID, Identifier: in.Identifier, Description: in.Description, - IsPublic: in.IsPublic, Created: in.Created, CreatedBy: in.CreatedBy, Updated: in.Updated, diff --git a/app/store/database/space.go b/app/store/database/space.go index 01f3117632..7a71f73f4a 100644 --- a/app/store/database/space.go +++ b/app/store/database/space.go @@ -65,7 +65,6 @@ type space struct { ParentID null.Int `db:"space_parent_id"` Identifier string `db:"space_uid"` Description string `db:"space_description"` - IsPublic bool `db:"space_is_public"` CreatedBy int64 `db:"space_created_by"` Created int64 `db:"space_created"` Updated int64 `db:"space_updated"` @@ -79,7 +78,6 @@ const ( ,space_parent_id ,space_uid ,space_description - ,space_is_public ,space_created_by ,space_created ,space_updated @@ -233,7 +231,6 @@ func (s *SpaceStore) Create(ctx context.Context, space *types.Space) error { ,space_parent_id ,space_uid ,space_description - ,space_is_public ,space_created_by ,space_created ,space_updated @@ -243,7 +240,6 @@ func (s *SpaceStore) Create(ctx context.Context, space *types.Space) error { ,:space_parent_id ,:space_uid ,:space_description - ,:space_is_public ,:space_created_by ,:space_created ,:space_updated @@ -278,7 +274,6 @@ func (s *SpaceStore) Update(ctx context.Context, space *types.Space) error { ,space_parent_id = :space_parent_id ,space_uid = :space_uid ,space_description = :space_description - ,space_is_public = :space_is_public ,space_deleted = :space_deleted WHERE space_id = :space_id AND space_version = :space_version - 1` @@ -722,7 +717,6 @@ func mapToSpace( Version: in.Version, Identifier: in.Identifier, Description: in.Description, - IsPublic: in.IsPublic, Created: in.Created, CreatedBy: in.CreatedBy, Updated: in.Updated, @@ -783,7 +777,6 @@ func mapToInternalSpace(s *types.Space) *space { Version: s.Version, Identifier: s.Identifier, Description: s.Description, - IsPublic: s.IsPublic, Created: s.Created, CreatedBy: s.CreatedBy, Updated: s.Updated, diff --git a/app/store/database/wire.go b/app/store/database/wire.go index 369b46f232..2979cee90c 100644 --- a/app/store/database/wire.go +++ b/app/store/database/wire.go @@ -53,6 +53,7 @@ var WireSet = wire.NewSet( ProvideWebhookStore, ProvideWebhookExecutionStore, ProvideSettingsStore, + ProvidePublicResourcesStore, ProvideCheckStore, ProvideConnectorStore, ProvideTemplateStore, @@ -247,3 +248,8 @@ func ProvideCheckStore(db *sqlx.DB, func ProvideSettingsStore(db *sqlx.DB) store.SettingsStore { return NewSettingsStore(db) } + +// ProvidePublicResourcesStore provides a pulic resources store. +func ProvidePublicResourcesStore(db *sqlx.DB) store.PublicResource { + return NewPublicResourcesStore(db) +} diff --git a/cmd/gitness/wire.go b/cmd/gitness/wire.go index 236f92ffd2..6e8058ac9e 100644 --- a/cmd/gitness/wire.go +++ b/cmd/gitness/wire.go @@ -63,6 +63,7 @@ import ( "github.com/harness/gitness/app/services/notification" "github.com/harness/gitness/app/services/notification/mailer" "github.com/harness/gitness/app/services/protection" + "github.com/harness/gitness/app/services/publicaccess" pullreqservice "github.com/harness/gitness/app/services/pullreq" reposervice "github.com/harness/gitness/app/services/repo" "github.com/harness/gitness/app/services/settings" @@ -114,6 +115,7 @@ func initSystem(ctx context.Context, config *types.Config) (*cliserver.System, e url.WireSet, space.WireSet, limiter.WireSet, + publicaccess.WireSet, repo.WireSet, reposettings.WireSet, pullreq.WireSet, diff --git a/cmd/gitness/wire_gen.go b/cmd/gitness/wire_gen.go index e74e357bff..fef834ad07 100644 --- a/cmd/gitness/wire_gen.go +++ b/cmd/gitness/wire_gen.go @@ -62,6 +62,7 @@ import ( "github.com/harness/gitness/app/services/notification" "github.com/harness/gitness/app/services/notification/mailer" "github.com/harness/gitness/app/services/protection" + "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/services/pullreq" repo2 "github.com/harness/gitness/app/services/repo" "github.com/harness/gitness/app/services/settings" @@ -197,8 +198,12 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro auditService := audit.ProvideAuditService() repoIdentifier := check.ProvideRepoIdentifierCheck() repoCheck := repo.ProvideRepoCheck() - repoController := repo.ProvideController(config, transactor, provider, authorizer, repoStore, spaceStore, pipelineStore, principalStore, ruleStore, settingsService, principalInfoCache, protectionManager, gitInterface, repository, codeownersService, reporter, indexer, resourceLimiter, lockerLocker, auditService, mutexManager, repoIdentifier, repoCheck) - reposettingsController := reposettings.ProvideController(authorizer, repoStore, settingsService) + publicResource := database.ProvidePublicResourcesStore(db) + publicAccessManager := publicaccess.ProvidePublicAccessManager(publicResource) + publicAccess := publicaccess.ProvidePublicAccess(publicAccessManager) + publicaccessService := publicaccess.ProvideService(publicAccess) + repoController := repo.ProvideController(config, transactor, provider, authorizer, repoStore, spaceStore, pipelineStore, principalStore, ruleStore, settingsService, principalInfoCache, protectionManager, gitInterface, repository, codeownersService, reporter, indexer, resourceLimiter, lockerLocker, auditService, mutexManager, repoIdentifier, repoCheck, publicaccessService) + reposettingsController := reposettings.ProvideController(authorizer, repoStore, settingsService, publicaccessService) executionStore := database.ProvideExecutionStore(db) checkStore := database.ProvideCheckStore(db, principalInfoCache) stageStore := database.ProvideStageStore(db) @@ -221,11 +226,11 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro spaceIdentifier := check.ProvideSpaceIdentifierCheck() secretStore := database.ProvideSecretStore(db) connectorStore := database.ProvideConnectorStore(db) - exporterRepository, err := exporter.ProvideSpaceExporter(provider, gitInterface, repoStore, jobScheduler, executor, encrypter, streamer) + exporterRepository, err := exporter.ProvideSpaceExporter(provider, gitInterface, repoStore, jobScheduler, executor, encrypter, streamer, publicaccessService) if err != nil { return nil, err } - spaceController := space.ProvideController(config, transactor, provider, streamer, spaceIdentifier, authorizer, spacePathStore, pipelineStore, secretStore, connectorStore, templateStore, spaceStore, repoStore, principalStore, repoController, membershipStore, repository, exporterRepository, resourceLimiter) + spaceController := space.ProvideController(config, transactor, provider, streamer, spaceIdentifier, authorizer, spacePathStore, pipelineStore, secretStore, connectorStore, templateStore, spaceStore, repoStore, principalStore, repoController, membershipStore, repository, exporterRepository, resourceLimiter, publicaccessService) pipelineController := pipeline.ProvideController(repoStore, triggerStore, authorizer, pipelineStore) secretController := secret.ProvideController(encrypter, secretStore, authorizer, spaceStore) triggerController := trigger.ProvideController(authorizer, triggerStore, pipelineStore, repoStore) @@ -257,7 +262,7 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro if err != nil { return nil, err } - pullreqController := pullreq2.ProvideController(transactor, provider, authorizer, pullReqStore, pullReqActivityStore, codeCommentView, pullReqReviewStore, pullReqReviewerStore, repoStore, principalStore, pullReqFileViewStore, membershipStore, checkStore, gitInterface, eventsReporter, migrator, pullreqService, protectionManager, streamer, codeownersService, lockerLocker) + pullreqController := pullreq2.ProvideController(transactor, provider, authorizer, pullReqStore, pullReqActivityStore, codeCommentView, pullReqReviewStore, pullReqReviewerStore, repoStore, principalStore, pullReqFileViewStore, membershipStore, checkStore, gitInterface, eventsReporter, migrator, pullreqService, protectionManager, streamer, codeownersService, lockerLocker, publicaccessService) webhookConfig := server.ProvideWebhookConfig(config) webhookStore := database.ProvideWebhookStore(db) webhookExecutionStore := database.ProvideWebhookExecutionStore(db) @@ -265,7 +270,7 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro if err != nil { return nil, err } - webhookController := webhook2.ProvideController(webhookConfig, authorizer, webhookStore, webhookExecutionStore, repoStore, webhookService, encrypter) + webhookController := webhook2.ProvideController(webhookConfig, authorizer, webhookStore, webhookExecutionStore, repoStore, webhookService, encrypter, publicaccessService) reporter2, err := events4.ProvideReporter(eventsSystem) if err != nil { return nil, err @@ -282,11 +287,11 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro if err != nil { return nil, err } - githookController := githook.ProvideController(authorizer, principalStore, repoStore, reporter2, reporter, gitInterface, pullReqStore, provider, protectionManager, clientFactory, resourceLimiter, settingsService, preReceiveExtender, updateExtender, postReceiveExtender) + githookController := githook.ProvideController(authorizer, principalStore, repoStore, reporter2, reporter, gitInterface, pullReqStore, provider, protectionManager, clientFactory, resourceLimiter, settingsService, preReceiveExtender, updateExtender, postReceiveExtender, publicaccessService) serviceaccountController := serviceaccount.NewController(principalUID, authorizer, principalStore, spaceStore, repoStore, tokenStore) principalController := principal.ProvideController(principalStore) v := check2.ProvideCheckSanitizers() - checkController := check2.ProvideController(transactor, authorizer, repoStore, checkStore, gitInterface, v) + checkController := check2.ProvideController(transactor, authorizer, repoStore, checkStore, gitInterface, v, publicaccessService) systemController := system.NewController(principalStore, config) blobConfig, err := server.ProvideBlobStoreConfig(config) if err != nil { @@ -296,7 +301,7 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro if err != nil { return nil, err } - uploadController := upload.ProvideController(authorizer, repoStore, blobStore) + uploadController := upload.ProvideController(authorizer, repoStore, blobStore, publicaccessService) searcher := keywordsearch.ProvideSearcher(localIndexSearcher) keywordsearchController := keywordsearch2.ProvideController(authorizer, searcher, repoController, spaceController) apiHandler := router.ProvideAPIHandler(ctx, config, authenticator, repoController, reposettingsController, executionController, logsController, spaceController, pipelineController, secretController, triggerController, connectorController, templateController, pluginController, pullreqController, webhookController, githookController, gitInterface, serviceaccountController, controller, principalController, checkController, systemController, uploadController, keywordsearchController) diff --git a/types/enum/membership_role.go b/types/enum/membership_role.go index 31547de1a5..3ca27a2707 100644 --- a/types/enum/membership_role.go +++ b/types/enum/membership_role.go @@ -50,6 +50,7 @@ var membershipRoleExecutorPermissions = slices.Clip(slices.Insert(membershipRole var membershipRoleContributorPermissions = slices.Clip(slices.Insert(membershipRoleReaderPermissions, 0, PermissionRepoPush, + PermissionRepoReview, )) var membershipRoleSpaceOwnerPermissions = slices.Clip(slices.Insert(membershipRoleReaderPermissions, 0, @@ -57,6 +58,7 @@ var membershipRoleSpaceOwnerPermissions = slices.Clip(slices.Insert(membershipRo PermissionRepoDelete, PermissionRepoPush, PermissionRepoReportCommitCheck, + PermissionRepoReview, PermissionSpaceEdit, PermissionSpaceDelete, diff --git a/types/enum/permission.go b/types/enum/permission.go index 61912ef9c5..38d2185e92 100644 --- a/types/enum/permission.go +++ b/types/enum/permission.go @@ -49,6 +49,7 @@ const ( PermissionRepoEdit Permission = "repo_edit" PermissionRepoDelete Permission = "repo_delete" PermissionRepoPush Permission = "repo_push" + PermissionRepoReview Permission = "repo_review" PermissionRepoReportCommitCheck Permission = "repo_reportCommitCheck" ) diff --git a/types/enum/public_resource.go b/types/enum/public_resource.go new file mode 100644 index 0000000000..90a11150dd --- /dev/null +++ b/types/enum/public_resource.go @@ -0,0 +1,33 @@ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package enum + +// PublicResourceType defines the type of the public resource. +type PublicResourceType string + +func (PublicResourceType) Enum() []interface{} { + return toInterfaceSlice(GetAllPublicResourceTypes()) +} + +var ( + PublicResourceTypeRepository PublicResourceType = "repository" + PublicResourceTypeSpace PublicResourceType = "space" +) + +func GetAllPublicResourceTypes() []PublicResourceType { + return []PublicResourceType{ + PublicResourceTypeRepository, + PublicResourceTypeSpace, + } +} diff --git a/types/public_resource.go b/types/public_resource.go new file mode 100644 index 0000000000..673afdf436 --- /dev/null +++ b/types/public_resource.go @@ -0,0 +1,23 @@ +// Copyright 2023 Harness, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import "github.com/harness/gitness/types/enum" + +// PublicResource defines a public resource info. +type PublicResource struct { + Type enum.PublicResourceType + ResourceID int64 +} diff --git a/types/repo.go b/types/repo.go index ec1d19f5e7..fe28769047 100644 --- a/types/repo.go +++ b/types/repo.go @@ -29,7 +29,6 @@ type Repository struct { Identifier string `json:"identifier" yaml:"identifier"` Path string `json:"path" yaml:"path"` Description string `json:"description" yaml:"description"` - IsPublic bool `json:"is_public" yaml:"is_public"` CreatedBy int64 `json:"created_by" yaml:"created_by"` Created int64 `json:"created" yaml:"created"` Updated int64 `json:"updated" yaml:"updated"` diff --git a/types/space.go b/types/space.go index 6140b0b676..869f3003d0 100644 --- a/types/space.go +++ b/types/space.go @@ -39,7 +39,6 @@ type Space struct { Path string `json:"path"` Identifier string `json:"identifier"` Description string `json:"description"` - IsPublic bool `json:"is_public"` CreatedBy int64 `json:"created_by"` Created int64 `json:"created"` Updated int64 `json:"updated"` From 717a8b85f56788a25d63fe27644f743b642d8c2d Mon Sep 17 00:00:00 2001 From: atefeh Date: Mon, 22 Apr 2024 20:20:17 -0700 Subject: [PATCH 02/31] few bug fixes and added publicAccess to spaceScopeCheck --- app/api/auth/repo.go | 8 ++++---- app/api/auth/space.go | 16 +++++++++++++--- app/api/controller/check/controller.go | 8 ++++---- app/api/controller/check/wire.go | 4 ++-- app/api/controller/repo/controller.go | 1 - app/api/controller/repo/create.go | 1 + app/api/controller/space/create.go | 1 + app/api/controller/space/list_repositories.go | 1 + app/api/controller/space/list_spaces.go | 1 + app/api/controller/space/restore.go | 1 + app/api/handler/repo/visibility_update.go | 4 ++-- app/services/publicaccess/manager.go | 7 +++++-- app/services/publicaccess/wire.go | 3 ++- .../0050_create_table_public_resources.up.sql | 2 +- app/store/database/public_resource.go | 9 ++++----- 15 files changed, 42 insertions(+), 25 deletions(-) diff --git a/app/api/auth/repo.go b/app/api/auth/repo.go index 50f0f178cb..e939705e2b 100644 --- a/app/api/auth/repo.go +++ b/app/api/auth/repo.go @@ -38,10 +38,10 @@ func CheckRepo( session *auth.Session, repo *types.Repository, permission enum.Permission, - publicaccess *publicaccess.Service, + publicAccess *publicaccess.Service, orPublic bool, ) error { - isPublic, err := publicaccess.Get(ctx, &types.PublicResource{ + isPublic, err := publicAccess.Get(ctx, &types.PublicResource{ Type: enum.PublicResourceTypeRepository, ResourceID: repo.ID, }) @@ -72,10 +72,10 @@ func IsRepoOwner( authorizer authz.Authorizer, session *auth.Session, repo *types.Repository, - publicaccess *publicaccess.Service, + publicAccess *publicaccess.Service, ) (bool, error) { // for now we use repoedit as permission to verify if someone is a SpaceOwner and hence a RepoOwner. - err := CheckRepo(ctx, authorizer, session, repo, enum.PermissionRepoEdit, publicaccess, false) + err := CheckRepo(ctx, authorizer, session, repo, enum.PermissionRepoEdit, publicAccess, false) if err != nil && !errors.Is(err, ErrNotAuthorized) { return false, fmt.Errorf("failed to check access user access: %w", err) } diff --git a/app/api/auth/space.go b/app/api/auth/space.go index e136443019..e0b561672e 100644 --- a/app/api/auth/space.go +++ b/app/api/auth/space.go @@ -37,10 +37,10 @@ func CheckSpace( session *auth.Session, space *types.Space, permission enum.Permission, - publicaccess *publicaccess.Service, + publicAccess *publicaccess.Service, orPublic bool, ) error { - isPublic, err := publicaccess.Get(ctx, &types.PublicResource{ + isPublic, err := publicAccess.Get(ctx, &types.PublicResource{ Type: enum.PublicResourceTypeSpace, ResourceID: space.ID, }) @@ -76,9 +76,19 @@ func CheckSpaceScope( space *types.Space, resourceType enum.ResourceType, permission enum.Permission, + publicAccess *publicaccess.Service, orPublic bool, ) error { - if orPublic { + // TODO ATEFEH check resource id scope + isPublic, err := publicAccess.Get(ctx, &types.PublicResource{ + Type: enum.PublicResourceTypeSpace, + ResourceID: space.ParentID, + }) + if err != nil { + return fmt.Errorf("failed to check public access: %w", err) + } + + if isPublic && orPublic { return nil } diff --git a/app/api/controller/check/controller.go b/app/api/controller/check/controller.go index c6b4f8b697..59b6fbaaff 100644 --- a/app/api/controller/check/controller.go +++ b/app/api/controller/check/controller.go @@ -37,7 +37,7 @@ type Controller struct { checkStore store.CheckStore git git.Interface sanitizers map[enum.CheckPayloadKind]func(in *ReportInput, s *auth.Session) error - publicaccess *publicaccess.Service + publicAccess *publicaccess.Service } func NewController( @@ -47,7 +47,7 @@ func NewController( checkStore store.CheckStore, git git.Interface, sanitizers map[enum.CheckPayloadKind]func(in *ReportInput, s *auth.Session) error, - publicaccess *publicaccess.Service, + publicAccess *publicaccess.Service, ) *Controller { return &Controller{ tx: tx, @@ -56,7 +56,7 @@ func NewController( checkStore: checkStore, git: git, sanitizers: sanitizers, - publicaccess: publicaccess, + publicAccess: publicAccess, } } @@ -72,7 +72,7 @@ func (c *Controller) getRepoCheckAccess(ctx context.Context, return nil, fmt.Errorf("failed to find repository: %w", err) } - if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, reqPermission, c.publicaccess, false); err != nil { + if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, reqPermission, c.publicAccess, false); err != nil { return nil, fmt.Errorf("access check failed: %w", err) } diff --git a/app/api/controller/check/wire.go b/app/api/controller/check/wire.go index 7b14e23e15..c6f1ceb03f 100644 --- a/app/api/controller/check/wire.go +++ b/app/api/controller/check/wire.go @@ -39,7 +39,7 @@ func ProvideController( checkStore store.CheckStore, rpcClient git.Interface, sanitizers map[enum.CheckPayloadKind]func(in *ReportInput, s *auth.Session) error, - publicaccess *publicaccess.Service, + publicAccess *publicaccess.Service, ) *Controller { return NewController( tx, @@ -48,6 +48,6 @@ func ProvideController( checkStore, rpcClient, sanitizers, - publicaccess, + publicAccess, ) } diff --git a/app/api/controller/repo/controller.go b/app/api/controller/repo/controller.go index 06245fa061..fadf94145f 100644 --- a/app/api/controller/repo/controller.go +++ b/app/api/controller/repo/controller.go @@ -21,7 +21,6 @@ import ( "strings" apiauth "github.com/harness/gitness/app/api/auth" - "github.com/harness/gitness/app/api/controller/limiter" "github.com/harness/gitness/app/api/usererror" "github.com/harness/gitness/app/auth" diff --git a/app/api/controller/repo/create.go b/app/api/controller/repo/create.go index 48537749ad..86a3f50898 100644 --- a/app/api/controller/repo/create.go +++ b/app/api/controller/repo/create.go @@ -175,6 +175,7 @@ func (c *Controller) getSpaceCheckAuthRepoCreation( space, enum.ResourceTypeRepo, enum.PermissionRepoEdit, + c.publicAccess, false, ) if err != nil { diff --git a/app/api/controller/space/create.go b/app/api/controller/space/create.go index bc5a7e2d80..5f98e249a3 100644 --- a/app/api/controller/space/create.go +++ b/app/api/controller/space/create.go @@ -187,6 +187,7 @@ func (c *Controller) getSpaceCheckAuthSpaceCreation( parentSpace, enum.ResourceTypeSpace, enum.PermissionSpaceEdit, + c.publicAccess, false, ); err != nil { return nil, fmt.Errorf("authorization failed: %w", err) diff --git a/app/api/controller/space/list_repositories.go b/app/api/controller/space/list_repositories.go index 6e7d1b39dd..0ec35a539a 100644 --- a/app/api/controller/space/list_repositories.go +++ b/app/api/controller/space/list_repositories.go @@ -45,6 +45,7 @@ func (c *Controller) ListRepositories( space, enum.ResourceTypeRepo, enum.PermissionRepoView, + c.publicAccess, true, ); err != nil { return nil, 0, err diff --git a/app/api/controller/space/list_spaces.go b/app/api/controller/space/list_spaces.go index 9a6d6cf80b..82bdeaec03 100644 --- a/app/api/controller/space/list_spaces.go +++ b/app/api/controller/space/list_spaces.go @@ -48,6 +48,7 @@ func (c *Controller) ListSpaces(ctx context.Context, space, enum.ResourceTypeSpace, enum.PermissionSpaceView, + c.publicAccess, true, ); err != nil { return nil, 0, err diff --git a/app/api/controller/space/restore.go b/app/api/controller/space/restore.go index f9892b515b..953e6681b0 100644 --- a/app/api/controller/space/restore.go +++ b/app/api/controller/space/restore.go @@ -74,6 +74,7 @@ func (c *Controller) Restore( parentSpace, enum.ResourceTypeSpace, enum.PermissionSpaceEdit, + c.publicAccess, false, ); err != nil { return nil, fmt.Errorf("authorization failed on space restore: %w", err) diff --git a/app/api/handler/repo/visibility_update.go b/app/api/handler/repo/visibility_update.go index db7656d0d6..a20ba23eed 100644 --- a/app/api/handler/repo/visibility_update.go +++ b/app/api/handler/repo/visibility_update.go @@ -41,12 +41,12 @@ func HandleVisibilityUpdate(repoCtrl *repo.Controller) http.HandlerFunc { return } - repo, err := repoCtrl.VisibilityUpdate(ctx, session, repoRef, in) + res, err := repoCtrl.VisibilityUpdate(ctx, session, repoRef, in) if err != nil { render.TranslatedUserError(ctx, w, err) return } - render.JSON(w, http.StatusOK, repo) + render.JSON(w, http.StatusOK, res) } } diff --git a/app/services/publicaccess/manager.go b/app/services/publicaccess/manager.go index faaec8694a..4014d36ba2 100644 --- a/app/services/publicaccess/manager.go +++ b/app/services/publicaccess/manager.go @@ -21,7 +21,6 @@ import ( "github.com/harness/gitness/app/store" gitness_store "github.com/harness/gitness/store" - "github.com/harness/gitness/types" ) @@ -55,7 +54,11 @@ func (r *PublicAccessManager) Set(ctx context.Context, resource *types.PublicResource, enable bool) error { if enable { - return r.publicResourceStore.Create(ctx, resource) + err := r.publicResourceStore.Create(ctx, resource) + if errors.Is(err, gitness_store.ErrDuplicate) { + return nil + } + return err } else { return r.publicResourceStore.Delete(ctx, resource) } diff --git a/app/services/publicaccess/wire.go b/app/services/publicaccess/wire.go index bf1e17c801..cdba432da5 100644 --- a/app/services/publicaccess/wire.go +++ b/app/services/publicaccess/wire.go @@ -15,8 +15,9 @@ package publicaccess import ( - "github.com/google/wire" "github.com/harness/gitness/app/store" + + "github.com/google/wire" ) var WireSet = wire.NewSet( diff --git a/app/store/database/migrate/sqlite/0050_create_table_public_resources.up.sql b/app/store/database/migrate/sqlite/0050_create_table_public_resources.up.sql index 07f0f51421..03e564bb21 100644 --- a/app/store/database/migrate/sqlite/0050_create_table_public_resources.up.sql +++ b/app/store/database/migrate/sqlite/0050_create_table_public_resources.up.sql @@ -1,5 +1,5 @@ CREATE TABLE public_resources ( - public_resource_id SERIAL PRIMARY KEY + public_resource_id INTEGER PRIMARY KEY AUTOINCREMENT ,public_resource_type TEXT NOT NULL ,public_resource_space_id INTEGER ,public_resource_repo_id INTEGER diff --git a/app/store/database/public_resource.go b/app/store/database/public_resource.go index a123649a53..fb75194263 100644 --- a/app/store/database/public_resource.go +++ b/app/store/database/public_resource.go @@ -18,14 +18,14 @@ import ( "context" "fmt" - "github.com/guregu/null" "github.com/harness/gitness/app/store" "github.com/harness/gitness/store/database" "github.com/harness/gitness/store/database/dbtx" + "github.com/harness/gitness/types" "github.com/harness/gitness/types/enum" - "github.com/jmoiron/sqlx" - "github.com/harness/gitness/types" + "github.com/guregu/null" + "github.com/jmoiron/sqlx" ) var _ store.PublicResource = (*PublicResourcesStore)(nil) @@ -84,8 +84,7 @@ func (p *PublicResourcesStore) Find( db := dbtx.GetAccessor(ctx, p.db) dst := &publicResource{} - err = db.GetContext(ctx, dst, sql, args...) - if err != nil { + if err = db.GetContext(ctx, dst, sql, args...); err != nil { return false, database.ProcessSQLErrorf(ctx, err, "Select query failed") } From 510ca5ba4104e9f6e2b3048871070eeb046999dc Mon Sep 17 00:00:00 2001 From: atefeh Date: Tue, 23 Apr 2024 13:48:39 -0700 Subject: [PATCH 03/31] no need to store resource type in public-resources table --- app/api/controller/repo/commit.go | 3 --- app/services/publicaccess/manager.go | 2 +- app/store/database.go | 2 +- ...050_create_table_public_resources.down.sql | 4 ++-- .../0050_create_table_public_resources.up.sql | 13 ++++------- ...050_create_table_public_resources.down.sql | 4 ++-- .../0050_create_table_public_resources.up.sql | 13 ++++------- app/store/database/public_resource.go | 23 ++++++++----------- 8 files changed, 23 insertions(+), 41 deletions(-) diff --git a/app/api/controller/repo/commit.go b/app/api/controller/repo/commit.go index ec8f0632b0..99da70f01c 100644 --- a/app/api/controller/repo/commit.go +++ b/app/api/controller/repo/commit.go @@ -62,9 +62,6 @@ func (c *Controller) CommitFiles(ctx context.Context, in *CommitFilesOptions, ) (types.CommitFilesResponse, []types.RuleViolations, error) { requiredPermission := enum.PermissionRepoPush - if in.DryRunRules { - requiredPermission = enum.PermissionRepoView - } repo, err := c.getRepoCheckAccess(ctx, session, repoRef, requiredPermission, false) if err != nil { diff --git a/app/services/publicaccess/manager.go b/app/services/publicaccess/manager.go index 4014d36ba2..5e499ee25d 100644 --- a/app/services/publicaccess/manager.go +++ b/app/services/publicaccess/manager.go @@ -39,7 +39,7 @@ func NewPublicAccessManager( func (r *PublicAccessManager) Get( ctx context.Context, resource *types.PublicResource) (bool, error) { - _, err := r.publicResourceStore.Find(ctx, resource) + err := r.publicResourceStore.Find(ctx, resource) if errors.Is(err, gitness_store.ErrResourceNotFound) { return false, nil } diff --git a/app/store/database.go b/app/store/database.go index b96af02380..2bbadc3a84 100644 --- a/app/store/database.go +++ b/app/store/database.go @@ -292,7 +292,7 @@ type ( // PublicResource defines the publicly accessible resources data storage. PublicResource interface { - Find(ctx context.Context, publicResource *types.PublicResource) (bool, error) + Find(ctx context.Context, publicResource *types.PublicResource) error Create(ctx context.Context, publicResource *types.PublicResource) error Delete(ctx context.Context, publicResource *types.PublicResource) error } diff --git a/app/store/database/migrate/postgres/0050_create_table_public_resources.down.sql b/app/store/database/migrate/postgres/0050_create_table_public_resources.down.sql index b218cf6622..9c9255168e 100644 --- a/app/store/database/migrate/postgres/0050_create_table_public_resources.down.sql +++ b/app/store/database/migrate/postgres/0050_create_table_public_resources.down.sql @@ -5,7 +5,7 @@ UPDATE repositories WHERE repo_id IN ( SELECT public_resource_repo_id FROM public_resources - WHERE public_resource_type = 'repository' AND public_resource_repo_id IS NOT NULL; + WHERE public_resource_repo_id IS NOT NULL; ) SET repo_is_public = TRUE; @@ -18,7 +18,7 @@ UPDATE spaces WHERE space_id IN ( SELECT public_resource_space_id FROM public_resources - WHERE public_resource_type = 'space' AND public_resource_space_id IS NOT NULL; + WHERE public_resource_space_id IS NOT NULL; ) SET sapce_is_public = TRUE; diff --git a/app/store/database/migrate/postgres/0050_create_table_public_resources.up.sql b/app/store/database/migrate/postgres/0050_create_table_public_resources.up.sql index bb10e924de..f67a640ac7 100644 --- a/app/store/database/migrate/postgres/0050_create_table_public_resources.up.sql +++ b/app/store/database/migrate/postgres/0050_create_table_public_resources.up.sql @@ -1,6 +1,5 @@ CREATE TABLE public_resources ( public_resource_id SERIAL PRIMARY KEY -,public_resource_type TEXT NOT NULL ,public_resource_space_id INTEGER ,public_resource_repo_id INTEGER @@ -24,13 +23,11 @@ CREATE UNIQUE INDEX public_resource_repo_id_key -- move public repos into public_resource INSERT INTO public_resources ( - public_resource_type - ,public_resource_space_id + public_resource_space_id ,public_resource_repo_id ) SELECT - 'repository' - ,NULL + NULL ,repo_id FROM repositories WHERE repo_is_public = TRUE; @@ -40,13 +37,11 @@ ALTER TABLE repositories DROP COLUMN repo_is_public; -- move public spaces into public_resource INSERT INTO public_resources ( - public_resource_type - ,public_resource_space_id + public_resource_space_id ,public_resource_repo_id ) SELECT - 'space' - ,space_id + space_id ,NULL FROM spaces WHERE space_is_public = TRUE; diff --git a/app/store/database/migrate/sqlite/0050_create_table_public_resources.down.sql b/app/store/database/migrate/sqlite/0050_create_table_public_resources.down.sql index b218cf6622..9c9255168e 100644 --- a/app/store/database/migrate/sqlite/0050_create_table_public_resources.down.sql +++ b/app/store/database/migrate/sqlite/0050_create_table_public_resources.down.sql @@ -5,7 +5,7 @@ UPDATE repositories WHERE repo_id IN ( SELECT public_resource_repo_id FROM public_resources - WHERE public_resource_type = 'repository' AND public_resource_repo_id IS NOT NULL; + WHERE public_resource_repo_id IS NOT NULL; ) SET repo_is_public = TRUE; @@ -18,7 +18,7 @@ UPDATE spaces WHERE space_id IN ( SELECT public_resource_space_id FROM public_resources - WHERE public_resource_type = 'space' AND public_resource_space_id IS NOT NULL; + WHERE public_resource_space_id IS NOT NULL; ) SET sapce_is_public = TRUE; diff --git a/app/store/database/migrate/sqlite/0050_create_table_public_resources.up.sql b/app/store/database/migrate/sqlite/0050_create_table_public_resources.up.sql index 03e564bb21..e2de44389b 100644 --- a/app/store/database/migrate/sqlite/0050_create_table_public_resources.up.sql +++ b/app/store/database/migrate/sqlite/0050_create_table_public_resources.up.sql @@ -1,6 +1,5 @@ CREATE TABLE public_resources ( public_resource_id INTEGER PRIMARY KEY AUTOINCREMENT -,public_resource_type TEXT NOT NULL ,public_resource_space_id INTEGER ,public_resource_repo_id INTEGER @@ -24,13 +23,11 @@ CREATE UNIQUE INDEX public_resource_repo_id_key -- move public repos into public_resource INSERT INTO public_resources ( - public_resource_type - ,public_resource_space_id + public_resource_space_id ,public_resource_repo_id ) SELECT - 'repository' - ,NULL + NULL ,repo_id FROM repositories WHERE repo_is_public = TRUE; @@ -40,13 +37,11 @@ ALTER TABLE repositories DROP COLUMN repo_is_public; -- move public spaces into public_resource INSERT INTO public_resources ( - public_resource_type - ,public_resource_space_id + public_resource_space_id ,public_resource_repo_id ) SELECT - 'space' - ,space_id + space_id ,NULL FROM spaces WHERE space_is_public = TRUE; diff --git a/app/store/database/public_resource.go b/app/store/database/public_resource.go index fb75194263..df4f4241a4 100644 --- a/app/store/database/public_resource.go +++ b/app/store/database/public_resource.go @@ -44,7 +44,6 @@ type PublicResourcesStore struct { type publicResource struct { ID int64 `db:"public_resource_id"` - Type string `db:"public_resource_type"` SpaceID null.Int `db:"public_resource_space_id"` RepoID null.Int `db:"public_resource_repo_id"` } @@ -52,7 +51,6 @@ type publicResource struct { const ( publicResourceColumns = ` public_resource_id - ,public_resource_type ,public_resource_space_id ,public_resource_repo_id ` @@ -61,11 +59,10 @@ const ( func (p *PublicResourcesStore) Find( ctx context.Context, publicRsc *types.PublicResource, -) (bool, error) { +) error { stmt := database.Builder. Select(publicResourceColumns). - From("public_resources"). - Where("public_resource_type = ?", publicRsc.Type) + From("public_resources") switch publicRsc.Type { case enum.PublicResourceTypeRepository: @@ -73,22 +70,22 @@ func (p *PublicResourcesStore) Find( case enum.PublicResourceTypeSpace: stmt = stmt.Where("public_resource_space_id = ?", publicRsc.ResourceID) default: - return false, fmt.Errorf("public resource type %q is not supported", publicRsc.Type) + return fmt.Errorf("public resource type %q is not supported", publicRsc.Type) } sql, args, err := stmt.ToSql() if err != nil { - return false, fmt.Errorf("failed to convert query to sql: %w", err) + return fmt.Errorf("failed to convert query to sql: %w", err) } db := dbtx.GetAccessor(ctx, p.db) dst := &publicResource{} if err = db.GetContext(ctx, dst, sql, args...); err != nil { - return false, database.ProcessSQLErrorf(ctx, err, "Select query failed") + return database.ProcessSQLErrorf(ctx, err, "Select query failed") } - return true, nil + return nil } func (p *PublicResourcesStore) Create( @@ -98,16 +95,15 @@ func (p *PublicResourcesStore) Create( Insert(""). Into("public_resources"). Columns( - "public_resource_type", "public_resource_space_id", "public_resource_repo_id", ) switch publicRsc.Type { case enum.PublicResourceTypeRepository: - stmt = stmt.Values(enum.PublicResourceTypeRepository, null.Int{}, null.IntFrom(publicRsc.ResourceID)) + stmt = stmt.Values(null.Int{}, null.IntFrom(publicRsc.ResourceID)) case enum.PublicResourceTypeSpace: - stmt = stmt.Values(enum.PublicResourceTypeSpace, null.IntFrom(publicRsc.ResourceID), null.Int{}) + stmt = stmt.Values(null.IntFrom(publicRsc.ResourceID), null.Int{}) default: return fmt.Errorf("public resource type %q is not supported", publicRsc.Type) } @@ -130,8 +126,7 @@ func (p *PublicResourcesStore) Delete( ctx context.Context, publicRsc *types.PublicResource) error { stmt := database.Builder. - Delete("public_resources"). - Where("public_resource_type = ?", publicRsc.Type) + Delete("public_resources") switch publicRsc.Type { case enum.PublicResourceTypeRepository: From e4d46d8a3085d9a9fcd30068e9584167fe69a2d3 Mon Sep 17 00:00:00 2001 From: atefeh Date: Thu, 25 Apr 2024 02:18:20 -0700 Subject: [PATCH 04/31] refactor public access service, removed all orPublic argument other code cleaning --- app/api/auth/auth.go | 2 +- app/api/auth/pipeline.go | 5 +- app/api/auth/repo.go | 30 ++++--- app/api/auth/space.go | 52 +++++------ app/api/controller/check/controller.go | 30 +++---- app/api/controller/check/wire.go | 3 - app/api/controller/githook/controller.go | 4 - app/api/controller/githook/pre_receive.go | 2 +- app/api/controller/githook/wire.go | 3 - app/api/controller/pullreq/check_list.go | 2 +- app/api/controller/pullreq/controller.go | 6 +- app/api/controller/pullreq/merge.go | 2 +- app/api/controller/pullreq/pr_state.go | 2 +- app/api/controller/pullreq/pr_update.go | 2 +- app/api/controller/pullreq/reviewer_add.go | 2 +- app/api/controller/pullreq/wire.go | 5 +- app/api/controller/repo/blame.go | 2 +- app/api/controller/repo/codeowner_validate.go | 4 +- app/api/controller/repo/commit.go | 8 +- app/api/controller/repo/content_get.go | 2 +- .../controller/repo/content_paths_details.go | 2 +- app/api/controller/repo/controller.go | 15 ++-- app/api/controller/repo/create.go | 31 +++++-- app/api/controller/repo/create_branch.go | 8 +- app/api/controller/repo/create_commit_tag.go | 8 +- app/api/controller/repo/default_branch.go | 13 +-- app/api/controller/repo/delete_branch.go | 8 +- app/api/controller/repo/delete_tag.go | 8 +- app/api/controller/repo/diff.go | 8 +- app/api/controller/repo/find.go | 2 +- app/api/controller/repo/get_branch.go | 2 +- app/api/controller/repo/get_commit.go | 2 +- .../controller/repo/get_commit_divergences.go | 2 +- app/api/controller/repo/git_info_refs.go | 2 +- app/api/controller/repo/git_service_pack.go | 4 +- app/api/controller/repo/helper.go | 23 +++-- app/api/controller/repo/import.go | 17 ++-- app/api/controller/repo/import_progress.go | 2 +- app/api/controller/repo/list_branches.go | 2 +- app/api/controller/repo/list_commit_tags.go | 2 +- app/api/controller/repo/list_commits.go | 2 +- app/api/controller/repo/merge_check.go | 4 +- app/api/controller/repo/move.go | 2 +- app/api/controller/repo/pipeline_generate.go | 2 +- app/api/controller/repo/purge.go | 2 +- app/api/controller/repo/raw.go | 2 +- app/api/controller/repo/restore.go | 16 +++- app/api/controller/repo/rule_create.go | 2 +- app/api/controller/repo/rule_delete.go | 2 +- app/api/controller/repo/rule_find.go | 2 +- app/api/controller/repo/rule_list.go | 2 +- app/api/controller/repo/rule_update.go | 2 +- app/api/controller/repo/soft_delete.go | 2 +- app/api/controller/repo/update.go | 18 ++-- app/api/controller/repo/visibility_update.go | 25 +++--- app/api/controller/repo/wire.go | 3 +- app/api/controller/reposettings/controller.go | 11 +-- .../controller/reposettings/security_find.go | 2 +- .../reposettings/security_update.go | 2 +- app/api/controller/reposettings/wire.go | 2 +- app/api/controller/space/controller.go | 4 +- app/api/controller/space/create.go | 24 +++-- app/api/controller/space/events.go | 2 +- app/api/controller/space/export.go | 2 +- app/api/controller/space/export_progress.go | 2 +- app/api/controller/space/find.go | 2 +- app/api/controller/space/import.go | 11 +-- .../controller/space/import_repositories.go | 10 +-- app/api/controller/space/list_repositories.go | 8 +- app/api/controller/space/list_spaces.go | 7 +- app/api/controller/space/membership_add.go | 2 +- app/api/controller/space/membership_delete.go | 2 +- app/api/controller/space/membership_list.go | 2 +- app/api/controller/space/membership_update.go | 2 +- app/api/controller/space/move.go | 2 +- app/api/controller/space/purge.go | 2 +- app/api/controller/space/restore.go | 4 +- app/api/controller/space/soft_delete.go | 2 - app/api/controller/space/update.go | 2 +- app/api/controller/space/wire.go | 2 +- app/api/controller/upload/controller.go | 19 ++-- app/api/controller/upload/download.go | 2 +- app/api/controller/upload/upload.go | 2 +- app/api/controller/upload/wire.go | 4 +- app/api/controller/webhook/controller.go | 6 +- app/api/controller/webhook/wire.go | 2 +- app/auth/authz/membership.go | 14 ++- app/auth/authz/public.go | 43 +++++++++ app/auth/authz/wire.go | 9 +- app/services/exporter/harness_code_client.go | 5 +- app/services/exporter/repository.go | 20 +++-- app/services/exporter/wire.go | 2 +- app/services/publicaccess/manager.go | 65 -------------- app/services/publicaccess/public_access.go | 20 +++-- app/services/publicaccess/resources.go | 87 +++++++++++++++++++ app/services/publicaccess/service.go | 54 ++++++++++-- app/services/publicaccess/wire.go | 20 ++--- app/store/database.go | 6 +- app/store/database/public_resource.go | 38 ++++---- cmd/gitness/wire_gen.go | 28 +++--- types/enum/public_resource.go | 6 +- types/public_resource.go | 4 +- 102 files changed, 543 insertions(+), 441 deletions(-) create mode 100644 app/auth/authz/public.go delete mode 100644 app/services/publicaccess/manager.go create mode 100644 app/services/publicaccess/resources.go diff --git a/app/api/auth/auth.go b/app/api/auth/auth.go index 3d20fd2f88..c7a0d4bb12 100644 --- a/app/api/auth/auth.go +++ b/app/api/auth/auth.go @@ -104,7 +104,7 @@ func getScopeForParent(ctx context.Context, spaceStore store.SpaceStore, repoSto spacePath, repoName, err := paths.DisectLeaf(repo.Path) if err != nil { - return nil, errors.Wrapf(err, "Failed to disect path '%s'", repo.Path) + return nil, fmt.Errorf("failed to disect path '%s': %w", repo.Path, err) } return &types.Scope{SpacePath: spacePath, Repo: repoName}, nil diff --git a/app/api/auth/pipeline.go b/app/api/auth/pipeline.go index 73a2ab561c..6ca1754fc5 100644 --- a/app/api/auth/pipeline.go +++ b/app/api/auth/pipeline.go @@ -16,14 +16,13 @@ package auth import ( "context" + "fmt" "github.com/harness/gitness/app/auth" "github.com/harness/gitness/app/auth/authz" "github.com/harness/gitness/app/paths" "github.com/harness/gitness/types" "github.com/harness/gitness/types/enum" - - "github.com/pkg/errors" ) // CheckPipeline checks if a pipeline specific permission is granted for the current auth session @@ -34,7 +33,7 @@ func CheckPipeline(ctx context.Context, authorizer authz.Authorizer, session *au repoPath string, pipelineIdentifier string, permission enum.Permission) error { spacePath, repoName, err := paths.DisectLeaf(repoPath) if err != nil { - return errors.Wrapf(err, "Failed to disect path '%s'", repoPath) + return fmt.Errorf("failed to disect path '%s': %w", repoPath, err) } scope := &types.Scope{SpacePath: spacePath, Repo: repoName} resource := &types.Resource{ diff --git a/app/api/auth/repo.go b/app/api/auth/repo.go index e939705e2b..d666fee5b4 100644 --- a/app/api/auth/repo.go +++ b/app/api/auth/repo.go @@ -38,24 +38,29 @@ func CheckRepo( session *auth.Session, repo *types.Repository, permission enum.Permission, - publicAccess *publicaccess.Service, - orPublic bool, ) error { - isPublic, err := publicAccess.Get(ctx, &types.PublicResource{ - Type: enum.PublicResourceTypeRepository, - ResourceID: repo.ID, - }) + parentSpace, name, err := paths.DisectLeaf(repo.Path) if err != nil { - return fmt.Errorf("failed to check public access: %w", err) + return fmt.Errorf("failed to disect path '%s': %w", repo.Path, err) } - if isPublic && orPublic { - return nil + scope := &types.Scope{SpacePath: parentSpace} + resource := &types.Resource{ + Type: enum.ResourceTypeRepo, + Identifier: name, } + return Check(ctx, authorizer, session, scope, resource, permission) +} + +func CheckRepoIsPublic( + ctx context.Context, + publicAccess publicaccess.PublicAccess, + repo *types.Repository, +) (bool, error) { parentSpace, name, err := paths.DisectLeaf(repo.Path) if err != nil { - return errors.Wrapf(err, "Failed to disect path '%s'", repo.Path) + return false, fmt.Errorf("failed to disect path '%s': %w", repo.Path, err) } scope := &types.Scope{SpacePath: parentSpace} @@ -64,7 +69,7 @@ func CheckRepo( Identifier: name, } - return Check(ctx, authorizer, session, scope, resource, permission) + return publicAccess.Get(ctx, scope, resource) } func IsRepoOwner( @@ -72,10 +77,9 @@ func IsRepoOwner( authorizer authz.Authorizer, session *auth.Session, repo *types.Repository, - publicAccess *publicaccess.Service, ) (bool, error) { // for now we use repoedit as permission to verify if someone is a SpaceOwner and hence a RepoOwner. - err := CheckRepo(ctx, authorizer, session, repo, enum.PermissionRepoEdit, publicAccess, false) + err := CheckRepo(ctx, authorizer, session, repo, enum.PermissionRepoEdit) if err != nil && !errors.Is(err, ErrNotAuthorized) { return false, fmt.Errorf("failed to check access user access: %w", err) } diff --git a/app/api/auth/space.go b/app/api/auth/space.go index e0b561672e..1901f00f5f 100644 --- a/app/api/auth/space.go +++ b/app/api/auth/space.go @@ -24,8 +24,6 @@ import ( "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/types" "github.com/harness/gitness/types/enum" - - "github.com/pkg/errors" ) // CheckSpace checks if a space specific permission is granted for the current auth session @@ -37,24 +35,10 @@ func CheckSpace( session *auth.Session, space *types.Space, permission enum.Permission, - publicAccess *publicaccess.Service, - orPublic bool, ) error { - isPublic, err := publicAccess.Get(ctx, &types.PublicResource{ - Type: enum.PublicResourceTypeSpace, - ResourceID: space.ID, - }) - if err != nil { - return fmt.Errorf("failed to check public access: %w", err) - } - - if isPublic && orPublic { - return nil - } - parentSpace, name, err := paths.DisectLeaf(space.Path) if err != nil { - return errors.Wrapf(err, "Failed to disect path '%s'", space.Path) + return fmt.Errorf("failed to disect path '%s': %w", space.Path, err) } scope := &types.Scope{SpacePath: parentSpace} @@ -76,22 +60,7 @@ func CheckSpaceScope( space *types.Space, resourceType enum.ResourceType, permission enum.Permission, - publicAccess *publicaccess.Service, - orPublic bool, ) error { - // TODO ATEFEH check resource id scope - isPublic, err := publicAccess.Get(ctx, &types.PublicResource{ - Type: enum.PublicResourceTypeSpace, - ResourceID: space.ParentID, - }) - if err != nil { - return fmt.Errorf("failed to check public access: %w", err) - } - - if isPublic && orPublic { - return nil - } - scope := &types.Scope{SpacePath: space.Path} resource := &types.Resource{ Type: resourceType, @@ -100,3 +69,22 @@ func CheckSpaceScope( return Check(ctx, authorizer, session, scope, resource, permission) } + +func CheckSpaceIsPublic( + ctx context.Context, + publicAccess publicaccess.PublicAccess, + space *types.Space, +) (bool, error) { + parentSpace, name, err := paths.DisectLeaf(space.Path) + if err != nil { + return false, fmt.Errorf("failed to disect path '%s': %w", space.Path, err) + } + + scope := &types.Scope{SpacePath: parentSpace} + resource := &types.Resource{ + Type: enum.ResourceTypeSpace, + Identifier: name, + } + + return publicAccess.Get(ctx, scope, resource) +} diff --git a/app/api/controller/check/controller.go b/app/api/controller/check/controller.go index 59b6fbaaff..f13887b791 100644 --- a/app/api/controller/check/controller.go +++ b/app/api/controller/check/controller.go @@ -22,7 +22,6 @@ import ( "github.com/harness/gitness/app/api/usererror" "github.com/harness/gitness/app/auth" "github.com/harness/gitness/app/auth/authz" - "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/store" "github.com/harness/gitness/git" "github.com/harness/gitness/store/database/dbtx" @@ -31,13 +30,12 @@ import ( ) type Controller struct { - tx dbtx.Transactor - authorizer authz.Authorizer - repoStore store.RepoStore - checkStore store.CheckStore - git git.Interface - sanitizers map[enum.CheckPayloadKind]func(in *ReportInput, s *auth.Session) error - publicAccess *publicaccess.Service + tx dbtx.Transactor + authorizer authz.Authorizer + repoStore store.RepoStore + checkStore store.CheckStore + git git.Interface + sanitizers map[enum.CheckPayloadKind]func(in *ReportInput, s *auth.Session) error } func NewController( @@ -47,16 +45,14 @@ func NewController( checkStore store.CheckStore, git git.Interface, sanitizers map[enum.CheckPayloadKind]func(in *ReportInput, s *auth.Session) error, - publicAccess *publicaccess.Service, ) *Controller { return &Controller{ - tx: tx, - authorizer: authorizer, - repoStore: repoStore, - checkStore: checkStore, - git: git, - sanitizers: sanitizers, - publicAccess: publicAccess, + tx: tx, + authorizer: authorizer, + repoStore: repoStore, + checkStore: checkStore, + git: git, + sanitizers: sanitizers, } } @@ -72,7 +68,7 @@ func (c *Controller) getRepoCheckAccess(ctx context.Context, return nil, fmt.Errorf("failed to find repository: %w", err) } - if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, reqPermission, c.publicAccess, false); err != nil { + if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, reqPermission); err != nil { return nil, fmt.Errorf("access check failed: %w", err) } diff --git a/app/api/controller/check/wire.go b/app/api/controller/check/wire.go index c6f1ceb03f..f8e570a0fd 100644 --- a/app/api/controller/check/wire.go +++ b/app/api/controller/check/wire.go @@ -17,7 +17,6 @@ package check import ( "github.com/harness/gitness/app/auth" "github.com/harness/gitness/app/auth/authz" - "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/store" "github.com/harness/gitness/git" "github.com/harness/gitness/store/database/dbtx" @@ -39,7 +38,6 @@ func ProvideController( checkStore store.CheckStore, rpcClient git.Interface, sanitizers map[enum.CheckPayloadKind]func(in *ReportInput, s *auth.Session) error, - publicAccess *publicaccess.Service, ) *Controller { return NewController( tx, @@ -48,6 +46,5 @@ func ProvideController( checkStore, rpcClient, sanitizers, - publicAccess, ) } diff --git a/app/api/controller/githook/controller.go b/app/api/controller/githook/controller.go index beb585820c..51f16d1ddb 100644 --- a/app/api/controller/githook/controller.go +++ b/app/api/controller/githook/controller.go @@ -25,7 +25,6 @@ import ( eventsgit "github.com/harness/gitness/app/events/git" eventsrepo "github.com/harness/gitness/app/events/repo" "github.com/harness/gitness/app/services/protection" - "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/services/settings" "github.com/harness/gitness/app/store" "github.com/harness/gitness/app/url" @@ -53,7 +52,6 @@ type Controller struct { preReceiveExtender PreReceiveExtender updateExtender UpdateExtender postReceiveExtender PostReceiveExtender - publicAccess *publicaccess.Service } func NewController( @@ -71,7 +69,6 @@ func NewController( preReceiveExtender PreReceiveExtender, updateExtender UpdateExtender, postReceiveExtender PostReceiveExtender, - publicAccess *publicaccess.Service, ) *Controller { return &Controller{ authorizer: authorizer, @@ -88,7 +85,6 @@ func NewController( preReceiveExtender: preReceiveExtender, updateExtender: updateExtender, postReceiveExtender: postReceiveExtender, - publicAccess: publicAccess, } } diff --git a/app/api/controller/githook/pre_receive.go b/app/api/controller/githook/pre_receive.go index ae2d579b6d..cacceffca2 100644 --- a/app/api/controller/githook/pre_receive.go +++ b/app/api/controller/githook/pre_receive.go @@ -117,7 +117,7 @@ func (c *Controller) checkProtectionRules( refUpdates changedRefs, output *hook.Output, ) error { - isRepoOwner, err := apiauth.IsRepoOwner(ctx, c.authorizer, session, repo, c.publicAccess) + isRepoOwner, err := apiauth.IsRepoOwner(ctx, c.authorizer, session, repo) if err != nil { return fmt.Errorf("failed to determine if user is repo owner: %w", err) } diff --git a/app/api/controller/githook/wire.go b/app/api/controller/githook/wire.go index 1bd8a60ccf..a542021969 100644 --- a/app/api/controller/githook/wire.go +++ b/app/api/controller/githook/wire.go @@ -20,7 +20,6 @@ import ( eventsgit "github.com/harness/gitness/app/events/git" eventsrepo "github.com/harness/gitness/app/events/repo" "github.com/harness/gitness/app/services/protection" - "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/services/settings" "github.com/harness/gitness/app/store" "github.com/harness/gitness/app/url" @@ -57,7 +56,6 @@ func ProvideController( preReceiveExtender PreReceiveExtender, updateExtender UpdateExtender, postReceiveExtender PostReceiveExtender, - publicAccess *publicaccess.Service, ) *Controller { ctrl := NewController( authorizer, @@ -74,7 +72,6 @@ func ProvideController( preReceiveExtender, updateExtender, postReceiveExtender, - publicAccess, ) // TODO: improve wiring if possible diff --git a/app/api/controller/pullreq/check_list.go b/app/api/controller/pullreq/check_list.go index 04f84b7f7d..ac6c6ffd5d 100644 --- a/app/api/controller/pullreq/check_list.go +++ b/app/api/controller/pullreq/check_list.go @@ -44,7 +44,7 @@ func (c *Controller) ListChecks( return types.PullReqChecks{}, fmt.Errorf("failed to find pull request by number: %w", err) } - isRepoOwner, err := apiauth.IsRepoOwner(ctx, c.authorizer, session, repo, c.publicAccess) + isRepoOwner, err := apiauth.IsRepoOwner(ctx, c.authorizer, session, repo) if err != nil { return types.PullReqChecks{}, fmt.Errorf("failed to determine if user is repo owner: %w", err) } diff --git a/app/api/controller/pullreq/controller.go b/app/api/controller/pullreq/controller.go index 84274b092c..9a080022ad 100644 --- a/app/api/controller/pullreq/controller.go +++ b/app/api/controller/pullreq/controller.go @@ -27,7 +27,6 @@ import ( "github.com/harness/gitness/app/services/codeowners" locker "github.com/harness/gitness/app/services/locker" "github.com/harness/gitness/app/services/protection" - "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/services/pullreq" "github.com/harness/gitness/app/sse" "github.com/harness/gitness/app/store" @@ -62,7 +61,6 @@ type Controller struct { sseStreamer sse.Streamer codeOwners *codeowners.Service locker *locker.Locker - publicAccess *publicaccess.Service } func NewController( @@ -87,7 +85,6 @@ func NewController( sseStreamer sse.Streamer, codeowners *codeowners.Service, locker *locker.Locker, - publicAccess *publicaccess.Service, ) *Controller { return &Controller{ tx: tx, @@ -111,7 +108,6 @@ func NewController( sseStreamer: sseStreamer, codeOwners: codeowners, locker: locker, - publicAccess: publicAccess, } } @@ -157,7 +153,7 @@ func (c *Controller) getRepoCheckAccess(ctx context.Context, return nil, usererror.BadRequest("Repository import is in progress.") } - if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, reqPermission, c.publicAccess, false); err != nil { + if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, reqPermission); err != nil { return nil, fmt.Errorf("access check failed: %w", err) } diff --git a/app/api/controller/pullreq/merge.go b/app/api/controller/pullreq/merge.go index 982831d2a7..f83895448e 100644 --- a/app/api/controller/pullreq/merge.go +++ b/app/api/controller/pullreq/merge.go @@ -176,7 +176,7 @@ func (c *Controller) Merge( } } - isRepoOwner, err := apiauth.IsRepoOwner(ctx, c.authorizer, session, targetRepo, c.publicAccess) + isRepoOwner, err := apiauth.IsRepoOwner(ctx, c.authorizer, session, targetRepo) if err != nil { return nil, nil, fmt.Errorf("failed to determine if user is repo owner: %w", err) } diff --git a/app/api/controller/pullreq/pr_state.go b/app/api/controller/pullreq/pr_state.go index 6ba9901c93..3d380f959e 100644 --- a/app/api/controller/pullreq/pr_state.go +++ b/app/api/controller/pullreq/pr_state.go @@ -79,7 +79,7 @@ func (c *Controller) State(ctx context.Context, } if err = apiauth.CheckRepo(ctx, c.authorizer, session, sourceRepo, - enum.PermissionRepoReview, c.publicAccess, false); err != nil { + enum.PermissionRepoReview); err != nil { return nil, fmt.Errorf("failed to acquire access to source repo: %w", err) } } diff --git a/app/api/controller/pullreq/pr_update.go b/app/api/controller/pullreq/pr_update.go index 5c8a8b9ac7..3c29c2dad8 100644 --- a/app/api/controller/pullreq/pr_update.go +++ b/app/api/controller/pullreq/pr_update.go @@ -74,7 +74,7 @@ func (c *Controller) Update(ctx context.Context, } if err = apiauth.CheckRepo(ctx, c.authorizer, session, sourceRepo, - enum.PermissionRepoReview, c.publicAccess, false); err != nil { + enum.PermissionRepoReview); err != nil { return nil, fmt.Errorf("failed to acquire access to source repo: %w", err) } } diff --git a/app/api/controller/pullreq/reviewer_add.go b/app/api/controller/pullreq/reviewer_add.go index e7de8c27ed..bf8830880f 100644 --- a/app/api/controller/pullreq/reviewer_add.go +++ b/app/api/controller/pullreq/reviewer_add.go @@ -87,7 +87,7 @@ func (c *Controller) ReviewerAdd( if err = apiauth.CheckRepo(ctx, c.authorizer, &auth.Session{ Principal: *reviewerPrincipal, Metadata: nil, - }, repo, enum.PermissionRepoReview, c.publicAccess, false); err != nil { + }, repo, enum.PermissionRepoReview); err != nil { log.Ctx(ctx).Info().Msgf("Reviewer principal: %s access error: %s", reviewerInfo.UID, err) return nil, usererror.BadRequest("The reviewer doesn't have enough permissions for the repository.") } diff --git a/app/api/controller/pullreq/wire.go b/app/api/controller/pullreq/wire.go index 55606b94bb..5019471be9 100644 --- a/app/api/controller/pullreq/wire.go +++ b/app/api/controller/pullreq/wire.go @@ -21,7 +21,6 @@ import ( "github.com/harness/gitness/app/services/codeowners" "github.com/harness/gitness/app/services/locker" "github.com/harness/gitness/app/services/protection" - "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/services/pullreq" "github.com/harness/gitness/app/sse" "github.com/harness/gitness/app/store" @@ -46,7 +45,7 @@ func ProvideController(tx dbtx.Transactor, urlProvider url.Provider, authorizer checkStore store.CheckStore, rpcClient git.Interface, eventReporter *pullreqevents.Reporter, codeCommentMigrator *codecomments.Migrator, pullreqService *pullreq.Service, ruleManager *protection.Manager, sseStreamer sse.Streamer, - codeOwners *codeowners.Service, locker *locker.Locker, publicAccess *publicaccess.Service, + codeOwners *codeowners.Service, locker *locker.Locker, ) *Controller { return NewController(tx, urlProvider, authorizer, pullReqStore, pullReqActivityStore, @@ -57,5 +56,5 @@ func ProvideController(tx dbtx.Transactor, urlProvider url.Provider, authorizer checkStore, rpcClient, eventReporter, codeCommentMigrator, - pullreqService, ruleManager, sseStreamer, codeOwners, locker, publicAccess) + pullreqService, ruleManager, sseStreamer, codeOwners, locker) } diff --git a/app/api/controller/repo/blame.go b/app/api/controller/repo/blame.go index 1400dc354b..585f3ab21a 100644 --- a/app/api/controller/repo/blame.go +++ b/app/api/controller/repo/blame.go @@ -39,7 +39,7 @@ func (c *Controller) Blame(ctx context.Context, return nil, usererror.BadRequest("Line range must be valid.") } - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView, true) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView) if err != nil { return nil, err } diff --git a/app/api/controller/repo/codeowner_validate.go b/app/api/controller/repo/codeowner_validate.go index 5fc52c1a02..6f65caed75 100644 --- a/app/api/controller/repo/codeowner_validate.go +++ b/app/api/controller/repo/codeowner_validate.go @@ -28,7 +28,7 @@ func (c *Controller) CodeOwnersValidate( repoRef string, ref string, ) (*types.CodeOwnersValidation, error) { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView, true) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView) if err != nil { return nil, err } @@ -37,7 +37,7 @@ func (c *Controller) CodeOwnersValidate( ref = repo.DefaultBranch } - violations, err := c.codeOwners.Validate(ctx, repo, ref) + violations, err := c.codeOwners.Validate(ctx, &repo.Repository, ref) if err != nil { return nil, err } diff --git a/app/api/controller/repo/commit.go b/app/api/controller/repo/commit.go index 99da70f01c..0ed1e37f9e 100644 --- a/app/api/controller/repo/commit.go +++ b/app/api/controller/repo/commit.go @@ -63,12 +63,12 @@ func (c *Controller) CommitFiles(ctx context.Context, ) (types.CommitFilesResponse, []types.RuleViolations, error) { requiredPermission := enum.PermissionRepoPush - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, requiredPermission, false) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, requiredPermission) if err != nil { return types.CommitFilesResponse{}, nil, err } - rules, isRepoOwner, err := c.fetchRules(ctx, session, repo) + rules, isRepoOwner, err := c.fetchRules(ctx, session, &repo.Repository) if err != nil { return types.CommitFilesResponse{}, nil, err } @@ -87,7 +87,7 @@ func (c *Controller) CommitFiles(ctx context.Context, Actor: &session.Principal, AllowBypass: in.BypassRules, IsRepoOwner: isRepoOwner, - Repo: repo, + Repo: &repo.Repository, RefAction: refAction, RefType: protection.RefTypeBranch, RefNames: []string{branchName}, @@ -132,7 +132,7 @@ func (c *Controller) CommitFiles(ctx context.Context, } // Create internal write params. Note: This will skip the pre-commit protection rules check. - writeParams, err := controller.CreateRPCInternalWriteParams(ctx, c.urlProvider, session, repo) + writeParams, err := controller.CreateRPCInternalWriteParams(ctx, c.urlProvider, session, &repo.Repository) if err != nil { return types.CommitFilesResponse{}, nil, fmt.Errorf("failed to create RPC write params: %w", err) } diff --git a/app/api/controller/repo/content_get.go b/app/api/controller/repo/content_get.go index 2acbfc9051..576a93d4c7 100644 --- a/app/api/controller/repo/content_get.go +++ b/app/api/controller/repo/content_get.go @@ -101,7 +101,7 @@ func (c *Controller) GetContent(ctx context.Context, repoPath string, includeLatestCommit bool, ) (*GetContentOutput, error) { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView, true) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView) if err != nil { return nil, err } diff --git a/app/api/controller/repo/content_paths_details.go b/app/api/controller/repo/content_paths_details.go index 302613fcef..d75d4e6783 100644 --- a/app/api/controller/repo/content_paths_details.go +++ b/app/api/controller/repo/content_paths_details.go @@ -39,7 +39,7 @@ func (c *Controller) PathsDetails(ctx context.Context, gitRef string, input PathsDetailsInput, ) (PathsDetailsOutput, error) { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView, true) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView) if err != nil { return PathsDetailsOutput{}, err } diff --git a/app/api/controller/repo/controller.go b/app/api/controller/repo/controller.go index fadf94145f..20679edf0d 100644 --- a/app/api/controller/repo/controller.go +++ b/app/api/controller/repo/controller.go @@ -79,7 +79,7 @@ type Controller struct { mtxManager lock.MutexManager identifierCheck check.RepoIdentifier repoCheck Check - publicAccess *publicaccess.Service + publicAccess publicaccess.PublicAccess } func NewController( @@ -106,7 +106,7 @@ func NewController( mtxManager lock.MutexManager, identifierCheck check.RepoIdentifier, repoCheck Check, - publicAccess *publicaccess.Service, + publicAccess publicaccess.PublicAccess, ) *Controller { return &Controller{ defaultBranch: config.Git.DefaultBranch, @@ -141,9 +141,10 @@ func NewController( func (c *Controller) getRepo( ctx context.Context, repoRef string, -) (*types.Repository, error) { +) (*Repository, error) { return GetRepo( ctx, + c.publicAccess, c.repoStore, repoRef, ) @@ -156,17 +157,15 @@ func (c *Controller) getRepoCheckAccess( session *auth.Session, repoRef string, reqPermission enum.Permission, - orPublic bool, -) (*types.Repository, error) { +) (*Repository, error) { return GetRepoCheckAccess( ctx, c.repoStore, c.authorizer, + c.publicAccess, session, repoRef, reqPermission, - c.publicAccess, - orPublic, ) } @@ -184,7 +183,7 @@ func (c *Controller) fetchRules( session *auth.Session, repo *types.Repository, ) (protection.Protection, bool, error) { - isRepoOwner, err := apiauth.IsRepoOwner(ctx, c.authorizer, session, repo, c.publicAccess) + isRepoOwner, err := apiauth.IsRepoOwner(ctx, c.authorizer, session, repo) if err != nil { return nil, false, fmt.Errorf("failed to determine if user is repo owner: %w", err) } diff --git a/app/api/controller/repo/create.go b/app/api/controller/repo/create.go index 86a3f50898..37eb5fc388 100644 --- a/app/api/controller/repo/create.go +++ b/app/api/controller/repo/create.go @@ -35,6 +35,7 @@ import ( "github.com/harness/gitness/types" "github.com/harness/gitness/types/check" "github.com/harness/gitness/types/enum" + "github.com/pkg/errors" "github.com/rs/zerolog/log" ) @@ -62,7 +63,7 @@ type CreateInput struct { // Create creates a new repository. // //nolint:gocognit -func (c *Controller) Create(ctx context.Context, session *auth.Session, in *CreateInput) (*types.Repository, error) { +func (c *Controller) Create(ctx context.Context, session *auth.Session, in *CreateInput) (*Repository, error) { if err := c.sanitizeCreateInput(in); err != nil { return nil, fmt.Errorf("failed to sanitize input: %w", err) } @@ -117,11 +118,7 @@ func (c *Controller) Create(ctx context.Context, session *auth.Session, in *Crea } if in.IsPublic && c.publicResourceCreationEnabled { - err = c.publicAccess.Set(ctx, &types.PublicResource{ - Type: enum.PublicResourceTypeRepository, - ResourceID: repo.ID, - }, in.IsPublic) - if err != nil { + if err = c.SetPublicRepo(ctx, repo); err != nil { return fmt.Errorf("failed to set a public resource: %w", err) } } @@ -154,7 +151,10 @@ func (c *Controller) Create(ctx context.Context, session *auth.Session, in *Crea } } - return repo, nil + return &Repository{ + Repository: *repo, + IsPublic: in.IsPublic, + }, nil } func (c *Controller) getSpaceCheckAuthRepoCreation( @@ -175,8 +175,6 @@ func (c *Controller) getSpaceCheckAuthRepoCreation( space, enum.ResourceTypeRepo, enum.PermissionRepoEdit, - c.publicAccess, - false, ) if err != nil { return nil, fmt.Errorf("auth check failed: %w", err) @@ -283,6 +281,21 @@ func (c *Controller) createGitRepository(ctx context.Context, session *auth.Sess return resp, len(files) == 0, nil } +func (c *Controller) SetPublicRepo(ctx context.Context, repo *types.Repository) error { + parentSpace, name, err := paths.DisectLeaf(repo.Path) + if err != nil { + return fmt.Errorf("failed to disect path '%s': %w", repo.Path, err) + } + + scope := &types.Scope{SpacePath: parentSpace} + resource := &types.Resource{ + Type: enum.ResourceTypeRepo, + Identifier: name, + } + + return c.publicAccess.Set(ctx, scope, resource, true) +} + func createReadme(name, description string) []byte { content := bytes.Buffer{} content.WriteString("# " + name + "\n") diff --git a/app/api/controller/repo/create_branch.go b/app/api/controller/repo/create_branch.go index 19e42d1832..6a2f6c6895 100644 --- a/app/api/controller/repo/create_branch.go +++ b/app/api/controller/repo/create_branch.go @@ -43,7 +43,7 @@ func (c *Controller) CreateBranch(ctx context.Context, repoRef string, in *CreateBranchInput, ) (*Branch, []types.RuleViolations, error) { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoPush, false) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoPush) if err != nil { return nil, nil, err } @@ -53,7 +53,7 @@ func (c *Controller) CreateBranch(ctx context.Context, in.Target = repo.DefaultBranch } - rules, isRepoOwner, err := c.fetchRules(ctx, session, repo) + rules, isRepoOwner, err := c.fetchRules(ctx, session, &repo.Repository) if err != nil { return nil, nil, err } @@ -62,7 +62,7 @@ func (c *Controller) CreateBranch(ctx context.Context, Actor: &session.Principal, AllowBypass: in.BypassRules, IsRepoOwner: isRepoOwner, - Repo: repo, + Repo: &repo.Repository, RefAction: protection.RefActionCreate, RefType: protection.RefTypeBranch, RefNames: []string{in.Name}, @@ -74,7 +74,7 @@ func (c *Controller) CreateBranch(ctx context.Context, return nil, violations, nil } - writeParams, err := controller.CreateRPCInternalWriteParams(ctx, c.urlProvider, session, repo) + writeParams, err := controller.CreateRPCInternalWriteParams(ctx, c.urlProvider, session, &repo.Repository) if err != nil { return nil, nil, fmt.Errorf("failed to create RPC write params: %w", err) } diff --git a/app/api/controller/repo/create_commit_tag.go b/app/api/controller/repo/create_commit_tag.go index 672b057a74..0424d4d665 100644 --- a/app/api/controller/repo/create_commit_tag.go +++ b/app/api/controller/repo/create_commit_tag.go @@ -47,7 +47,7 @@ func (c *Controller) CreateCommitTag(ctx context.Context, repoRef string, in *CreateCommitTagInput, ) (*CommitTag, []types.RuleViolations, error) { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoPush, false) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoPush) if err != nil { return nil, nil, err } @@ -57,7 +57,7 @@ func (c *Controller) CreateCommitTag(ctx context.Context, in.Target = repo.DefaultBranch } - rules, isRepoOwner, err := c.fetchRules(ctx, session, repo) + rules, isRepoOwner, err := c.fetchRules(ctx, session, &repo.Repository) if err != nil { return nil, nil, err } @@ -66,7 +66,7 @@ func (c *Controller) CreateCommitTag(ctx context.Context, Actor: &session.Principal, AllowBypass: in.BypassRules, IsRepoOwner: isRepoOwner, - Repo: repo, + Repo: &repo.Repository, RefAction: protection.RefActionCreate, RefType: protection.RefTypeTag, RefNames: []string{in.Name}, @@ -78,7 +78,7 @@ func (c *Controller) CreateCommitTag(ctx context.Context, return nil, violations, nil } - writeParams, err := controller.CreateRPCInternalWriteParams(ctx, c.urlProvider, session, repo) + writeParams, err := controller.CreateRPCInternalWriteParams(ctx, c.urlProvider, session, &repo.Repository) if err != nil { return nil, nil, fmt.Errorf("failed to create RPC write params: %w", err) } diff --git a/app/api/controller/repo/default_branch.go b/app/api/controller/repo/default_branch.go index 74970dbd29..dc92d22c2c 100644 --- a/app/api/controller/repo/default_branch.go +++ b/app/api/controller/repo/default_branch.go @@ -43,8 +43,8 @@ func (c *Controller) UpdateDefaultBranch( session *auth.Session, repoRef string, in *UpdateDefaultBranchInput, -) (*types.Repository, error) { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoEdit, false) +) (*Repository, error) { + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoEdit) if err != nil { return nil, err } @@ -65,7 +65,7 @@ func (c *Controller) UpdateDefaultBranch( } defer unlock() - writeParams, err := controller.CreateRPCInternalWriteParams(ctx, c.urlProvider, session, repo) + writeParams, err := controller.CreateRPCInternalWriteParams(ctx, c.urlProvider, session, &repo.Repository) if err != nil { return nil, fmt.Errorf("failed to create RPC write params: %w", err) } @@ -87,7 +87,7 @@ func (c *Controller) UpdateDefaultBranch( } oldName := repo.DefaultBranch - repo, err = c.repoStore.UpdateOptLock(ctx, repo, func(r *types.Repository) error { + repoBase, err := c.repoStore.UpdateOptLock(ctx, &repo.Repository, func(r *types.Repository) error { r.DefaultBranch = in.Name return nil }) @@ -114,5 +114,8 @@ func (c *Controller) UpdateDefaultBranch( NewName: repo.DefaultBranch, }) - return repo, nil + return &Repository{ + Repository: *repoBase, + IsPublic: repo.IsPublic, + }, nil } diff --git a/app/api/controller/repo/delete_branch.go b/app/api/controller/repo/delete_branch.go index 0d7eaafb08..ca2f17a7c9 100644 --- a/app/api/controller/repo/delete_branch.go +++ b/app/api/controller/repo/delete_branch.go @@ -34,7 +34,7 @@ func (c *Controller) DeleteBranch(ctx context.Context, branchName string, bypassRules bool, ) ([]types.RuleViolations, error) { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoPush, false) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoPush) if err != nil { return nil, err } @@ -47,7 +47,7 @@ func (c *Controller) DeleteBranch(ctx context.Context, return nil, usererror.ErrDefaultBranchCantBeDeleted } - rules, isRepoOwner, err := c.fetchRules(ctx, session, repo) + rules, isRepoOwner, err := c.fetchRules(ctx, session, &repo.Repository) if err != nil { return nil, err } @@ -56,7 +56,7 @@ func (c *Controller) DeleteBranch(ctx context.Context, Actor: &session.Principal, AllowBypass: bypassRules, IsRepoOwner: isRepoOwner, - Repo: repo, + Repo: &repo.Repository, RefAction: protection.RefActionDelete, RefType: protection.RefTypeBranch, RefNames: []string{branchName}, @@ -68,7 +68,7 @@ func (c *Controller) DeleteBranch(ctx context.Context, return violations, nil } - writeParams, err := controller.CreateRPCInternalWriteParams(ctx, c.urlProvider, session, repo) + writeParams, err := controller.CreateRPCInternalWriteParams(ctx, c.urlProvider, session, &repo.Repository) if err != nil { return nil, fmt.Errorf("failed to create RPC write params: %w", err) } diff --git a/app/api/controller/repo/delete_tag.go b/app/api/controller/repo/delete_tag.go index 25dbc86a5c..776c3b5b8b 100644 --- a/app/api/controller/repo/delete_tag.go +++ b/app/api/controller/repo/delete_tag.go @@ -33,12 +33,12 @@ func (c *Controller) DeleteTag(ctx context.Context, tagName string, bypassRules bool, ) ([]types.RuleViolations, error) { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoPush, false) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoPush) if err != nil { return nil, err } - rules, isRepoOwner, err := c.fetchRules(ctx, session, repo) + rules, isRepoOwner, err := c.fetchRules(ctx, session, &repo.Repository) if err != nil { return nil, err } @@ -47,7 +47,7 @@ func (c *Controller) DeleteTag(ctx context.Context, Actor: &session.Principal, AllowBypass: bypassRules, IsRepoOwner: isRepoOwner, - Repo: repo, + Repo: &repo.Repository, RefAction: protection.RefActionDelete, RefType: protection.RefTypeTag, RefNames: []string{tagName}, @@ -59,7 +59,7 @@ func (c *Controller) DeleteTag(ctx context.Context, return violations, nil } - writeParams, err := controller.CreateRPCInternalWriteParams(ctx, c.urlProvider, session, repo) + writeParams, err := controller.CreateRPCInternalWriteParams(ctx, c.urlProvider, session, &repo.Repository) if err != nil { return nil, fmt.Errorf("failed to create RPC write params: %w", err) } diff --git a/app/api/controller/repo/diff.go b/app/api/controller/repo/diff.go index 9f951226f7..4bfb72e439 100644 --- a/app/api/controller/repo/diff.go +++ b/app/api/controller/repo/diff.go @@ -36,7 +36,7 @@ func (c *Controller) RawDiff( path string, files ...gittypes.FileDiffRequest, ) error { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView, true) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView) if err != nil { return err } @@ -61,7 +61,7 @@ func (c *Controller) CommitDiff( rev string, w io.Writer, ) error { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView, true) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView) if err != nil { return err } @@ -104,7 +104,7 @@ func (c *Controller) DiffStats( return types.DiffStats{}, err } - if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, enum.PermissionRepoView, c.publicAccess, false); err != nil { + if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, enum.PermissionRepoView); err != nil { return types.DiffStats{}, err } @@ -139,7 +139,7 @@ func (c *Controller) Diff( return nil, err } - if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, enum.PermissionRepoView, c.publicAccess, false); err != nil { + if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, enum.PermissionRepoView); err != nil { return nil, err } diff --git a/app/api/controller/repo/find.go b/app/api/controller/repo/find.go index 94c5989876..145bbba220 100644 --- a/app/api/controller/repo/find.go +++ b/app/api/controller/repo/find.go @@ -31,7 +31,7 @@ func (c *Controller) Find(ctx context.Context, session *auth.Session, repoRef st return nil, err } - if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, enum.PermissionRepoView, c.publicAccess, true); err != nil { + if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, enum.PermissionRepoView); err != nil { return nil, err } diff --git a/app/api/controller/repo/get_branch.go b/app/api/controller/repo/get_branch.go index 7b792455e9..a1a06521fb 100644 --- a/app/api/controller/repo/get_branch.go +++ b/app/api/controller/repo/get_branch.go @@ -29,7 +29,7 @@ func (c *Controller) GetBranch(ctx context.Context, repoRef string, branchName string, ) (*Branch, error) { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView, true) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView) if err != nil { return nil, err } diff --git a/app/api/controller/repo/get_commit.go b/app/api/controller/repo/get_commit.go index 9814f9b6fe..ede7f7c4a8 100644 --- a/app/api/controller/repo/get_commit.go +++ b/app/api/controller/repo/get_commit.go @@ -31,7 +31,7 @@ func (c *Controller) GetCommit(ctx context.Context, repoRef string, sha string, ) (*types.Commit, error) { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView, true) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView) if err != nil { return nil, err } diff --git a/app/api/controller/repo/get_commit_divergences.go b/app/api/controller/repo/get_commit_divergences.go index ff8d87e5f1..dad31b230e 100644 --- a/app/api/controller/repo/get_commit_divergences.go +++ b/app/api/controller/repo/get_commit_divergences.go @@ -54,7 +54,7 @@ func (c *Controller) GetCommitDivergences(ctx context.Context, repoRef string, in *GetCommitDivergencesInput, ) ([]CommitDivergence, error) { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView, true) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView) if err != nil { return nil, err } diff --git a/app/api/controller/repo/git_info_refs.go b/app/api/controller/repo/git_info_refs.go index 8d7ad2fbdc..3d9fbe09fd 100644 --- a/app/api/controller/repo/git_info_refs.go +++ b/app/api/controller/repo/git_info_refs.go @@ -33,7 +33,7 @@ func (c *Controller) GitInfoRefs( gitProtocol string, w io.Writer, ) error { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView, true) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView) if err != nil { return fmt.Errorf("failed to verify repo access: %w", err) } diff --git a/app/api/controller/repo/git_service_pack.go b/app/api/controller/repo/git_service_pack.go index 8d2988e65c..7debd35092 100644 --- a/app/api/controller/repo/git_service_pack.go +++ b/app/api/controller/repo/git_service_pack.go @@ -43,7 +43,7 @@ func (c *Controller) GitServicePack( permission = enum.PermissionRepoPush } - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, permission, !isWriteOperation) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, permission) if err != nil { return fmt.Errorf("failed to verify repo access: %w", err) } @@ -59,7 +59,7 @@ func (c *Controller) GitServicePack( // setup read/writeparams depending on whether it's a write operation if isWriteOperation { var writeParams git.WriteParams - writeParams, err = controller.CreateRPCExternalWriteParams(ctx, c.urlProvider, session, repo) + writeParams, err = controller.CreateRPCExternalWriteParams(ctx, c.urlProvider, session, &repo.Repository) if err != nil { return fmt.Errorf("failed to create RPC write params: %w", err) } diff --git a/app/api/controller/repo/helper.go b/app/api/controller/repo/helper.go index 8d81d360c9..51d406432b 100644 --- a/app/api/controller/repo/helper.go +++ b/app/api/controller/repo/helper.go @@ -24,16 +24,16 @@ import ( "github.com/harness/gitness/app/auth/authz" "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/store" - "github.com/harness/gitness/types" "github.com/harness/gitness/types/enum" ) // GetRepo fetches an active repo (not one that is currently being imported). func GetRepo( ctx context.Context, + publicAccess publicaccess.PublicAccess, repoStore store.RepoStore, repoRef string, -) (*types.Repository, error) { +) (*Repository, error) { if repoRef == "" { return nil, usererror.BadRequest("A valid repository reference must be provided.") } @@ -47,7 +47,15 @@ func GetRepo( return nil, usererror.BadRequest("Repository import is in progress.") } - return repo, nil + isPublic, err := apiauth.CheckRepoIsPublic(ctx, publicAccess, repo) + if err != nil { + return nil, fmt.Errorf("failed to check if repo is public: %w", err) + } + + return &Repository{ + Repository: *repo, + IsPublic: isPublic, + }, nil } // GetRepoCheckAccess fetches an active repo (not one that is currently being imported) @@ -56,18 +64,17 @@ func GetRepoCheckAccess( ctx context.Context, repoStore store.RepoStore, authorizer authz.Authorizer, + publicAccess publicaccess.PublicAccess, session *auth.Session, repoRef string, reqPermission enum.Permission, - publicAccess *publicaccess.Service, - orPublic bool, -) (*types.Repository, error) { - repo, err := GetRepo(ctx, repoStore, repoRef) +) (*Repository, error) { + repo, err := GetRepo(ctx, publicAccess, repoStore, repoRef) if err != nil { return nil, fmt.Errorf("failed to find repo: %w", err) } - if err = apiauth.CheckRepo(ctx, authorizer, session, repo, reqPermission, publicAccess, orPublic); err != nil { + if err = apiauth.CheckRepo(ctx, authorizer, session, &repo.Repository, reqPermission); err != nil { return nil, fmt.Errorf("access check failed: %w", err) } diff --git a/app/api/controller/repo/import.go b/app/api/controller/repo/import.go index 8bfd265847..d7f63ed941 100644 --- a/app/api/controller/repo/import.go +++ b/app/api/controller/repo/import.go @@ -22,7 +22,6 @@ import ( "github.com/harness/gitness/app/auth" "github.com/harness/gitness/app/services/importer" "github.com/harness/gitness/types" - "github.com/harness/gitness/types/enum" ) type ImportInput struct { @@ -39,7 +38,7 @@ type ImportInput struct { } // Import creates a new empty repository and starts git import to it from a remote repository. -func (c *Controller) Import(ctx context.Context, session *auth.Session, in *ImportInput) (*types.Repository, error) { +func (c *Controller) Import(ctx context.Context, session *auth.Session, in *ImportInput) (*Repository, error) { if err := c.sanitizeImportInput(in); err != nil { return nil, fmt.Errorf("failed to sanitize input: %w", err) } @@ -81,13 +80,9 @@ func (c *Controller) Import(ctx context.Context, session *auth.Session, in *Impo // update public resources if isPublic && c.publicResourceCreationEnabled { - err = c.publicAccess.Set(ctx, &types.PublicResource{ - Type: enum.PublicResourceTypeRepository, - ResourceID: repo.ID, - }, isPublic) - } - if err != nil { - return fmt.Errorf("failed to set a public repo: %w", err) + if err = c.SetPublicRepo(ctx, repo); err != nil { + return fmt.Errorf("failed to set a public repo: %w", err) + } } err = c.importer.Run(ctx, provider, repo, remoteRepository.CloneURL, in.Pipelines) @@ -103,7 +98,9 @@ func (c *Controller) Import(ctx context.Context, session *auth.Session, in *Impo repo.GitURL = c.urlProvider.GenerateGITCloneURL(repo.Path) - return repo, nil + return &Repository{ + Repository: *repo, + IsPublic: isPublic}, nil } func (c *Controller) sanitizeImportInput(in *ImportInput) error { diff --git a/app/api/controller/repo/import_progress.go b/app/api/controller/repo/import_progress.go index a2d2c341b3..4156e16fec 100644 --- a/app/api/controller/repo/import_progress.go +++ b/app/api/controller/repo/import_progress.go @@ -38,7 +38,7 @@ func (c *Controller) ImportProgress(ctx context.Context, return job.Progress{}, err } - if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, enum.PermissionRepoView, c.publicAccess, false); err != nil { + if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, enum.PermissionRepoView); err != nil { return job.Progress{}, err } diff --git a/app/api/controller/repo/list_branches.go b/app/api/controller/repo/list_branches.go index 7c369e9ba8..a464da158f 100644 --- a/app/api/controller/repo/list_branches.go +++ b/app/api/controller/repo/list_branches.go @@ -38,7 +38,7 @@ func (c *Controller) ListBranches(ctx context.Context, includeCommit bool, filter *types.BranchFilter, ) ([]Branch, error) { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView, true) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView) if err != nil { return nil, err } diff --git a/app/api/controller/repo/list_commit_tags.go b/app/api/controller/repo/list_commit_tags.go index c460c42069..a4e0320e14 100644 --- a/app/api/controller/repo/list_commit_tags.go +++ b/app/api/controller/repo/list_commit_tags.go @@ -42,7 +42,7 @@ func (c *Controller) ListCommitTags(ctx context.Context, includeCommit bool, filter *types.TagFilter, ) ([]CommitTag, error) { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView, true) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView) if err != nil { return nil, err } diff --git a/app/api/controller/repo/list_commits.go b/app/api/controller/repo/list_commits.go index 3e9ec83b81..44a5f82bdf 100644 --- a/app/api/controller/repo/list_commits.go +++ b/app/api/controller/repo/list_commits.go @@ -32,7 +32,7 @@ func (c *Controller) ListCommits(ctx context.Context, gitRef string, filter *types.CommitFilter, ) (types.ListCommitResponse, error) { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView, true) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView) if err != nil { return types.ListCommitResponse{}, err } diff --git a/app/api/controller/repo/merge_check.go b/app/api/controller/repo/merge_check.go index 7f5021b4e5..cba1af3d5b 100644 --- a/app/api/controller/repo/merge_check.go +++ b/app/api/controller/repo/merge_check.go @@ -35,7 +35,7 @@ func (c *Controller) MergeCheck( repoRef string, diffPath string, ) (MergeCheck, error) { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView, false) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView) if err != nil { return MergeCheck{}, err } @@ -45,7 +45,7 @@ func (c *Controller) MergeCheck( return MergeCheck{}, err } - writeParams, err := controller.CreateRPCInternalWriteParams(ctx, c.urlProvider, session, repo) + writeParams, err := controller.CreateRPCInternalWriteParams(ctx, c.urlProvider, session, &repo.Repository) if err != nil { return MergeCheck{}, fmt.Errorf("failed to create rpc write params: %w", err) } diff --git a/app/api/controller/repo/move.go b/app/api/controller/repo/move.go index 34031e9f7e..3360c4df86 100644 --- a/app/api/controller/repo/move.go +++ b/app/api/controller/repo/move.go @@ -62,7 +62,7 @@ func (c *Controller) Move(ctx context.Context, return nil, usererror.BadRequest("can't move a repo that is being imported") } - if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, enum.PermissionRepoEdit, c.publicAccess, false); err != nil { + if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, enum.PermissionRepoEdit); err != nil { return nil, err } diff --git a/app/api/controller/repo/pipeline_generate.go b/app/api/controller/repo/pipeline_generate.go index 97fe4c3b97..65142dad3c 100644 --- a/app/api/controller/repo/pipeline_generate.go +++ b/app/api/controller/repo/pipeline_generate.go @@ -29,7 +29,7 @@ func (c *Controller) PipelineGenerate( session *auth.Session, repoRef string, ) ([]byte, error) { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView, true) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView) if err != nil { return nil, err } diff --git a/app/api/controller/repo/purge.go b/app/api/controller/repo/purge.go index 6bc2d2ecfd..34e4f1b685 100644 --- a/app/api/controller/repo/purge.go +++ b/app/api/controller/repo/purge.go @@ -43,7 +43,7 @@ func (c *Controller) Purge( return fmt.Errorf("failed to find the repo (deleted at %d): %w", deletedAt, err) } - if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, enum.PermissionRepoDelete, c.publicAccess, false); err != nil { + if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, enum.PermissionRepoDelete); err != nil { return err } diff --git a/app/api/controller/repo/raw.go b/app/api/controller/repo/raw.go index 329f5a0869..464adead03 100644 --- a/app/api/controller/repo/raw.go +++ b/app/api/controller/repo/raw.go @@ -33,7 +33,7 @@ func (c *Controller) Raw(ctx context.Context, gitRef string, path string, ) (io.ReadCloser, int64, error) { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView, true) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView) if err != nil { return nil, 0, err } diff --git a/app/api/controller/repo/restore.go b/app/api/controller/repo/restore.go index 02145ca008..2a1296692e 100644 --- a/app/api/controller/repo/restore.go +++ b/app/api/controller/repo/restore.go @@ -40,13 +40,13 @@ func (c *Controller) Restore( repoRef string, deletedAt int64, in *RestoreInput, -) (*types.Repository, error) { +) (*Repository, error) { repo, err := c.repoStore.FindByRefAndDeletedAt(ctx, repoRef, deletedAt) if err != nil { return nil, fmt.Errorf("failed to find repository: %w", err) } - if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, enum.PermissionRepoEdit, c.publicAccess, false); err != nil { + if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, enum.PermissionRepoEdit); err != nil { return nil, fmt.Errorf("access check failed: %w", err) } @@ -75,7 +75,7 @@ func (c *Controller) RestoreNoAuth( repo *types.Repository, newIdentifier *string, newParentID int64, -) (*types.Repository, error) { +) (*Repository, error) { var err error err = c.tx.WithTx(ctx, func(ctx context.Context) error { if err := c.resourceLimiter.RepoCount(ctx, newParentID, 1); err != nil { @@ -93,5 +93,13 @@ func (c *Controller) RestoreNoAuth( return nil, fmt.Errorf("failed to restore the repo: %w", err) } - return repo, nil + isPublic, err := apiauth.CheckRepoIsPublic(ctx, c.publicAccess, repo) + if err != nil { + return nil, fmt.Errorf("failed to get resource public access mode: %w", err) + } + + return &Repository{ + Repository: *repo, + IsPublic: isPublic, + }, nil } diff --git a/app/api/controller/repo/rule_create.go b/app/api/controller/repo/rule_create.go index 86ae87f233..d7c8744584 100644 --- a/app/api/controller/repo/rule_create.go +++ b/app/api/controller/repo/rule_create.go @@ -85,7 +85,7 @@ func (c *Controller) RuleCreate(ctx context.Context, return nil, err } - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoEdit, false) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoEdit) if err != nil { return nil, err } diff --git a/app/api/controller/repo/rule_delete.go b/app/api/controller/repo/rule_delete.go index b9b7ac1427..05bc812a85 100644 --- a/app/api/controller/repo/rule_delete.go +++ b/app/api/controller/repo/rule_delete.go @@ -32,7 +32,7 @@ func (c *Controller) RuleDelete(ctx context.Context, repoRef string, identifier string, ) error { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoEdit, false) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoEdit) if err != nil { return err } diff --git a/app/api/controller/repo/rule_find.go b/app/api/controller/repo/rule_find.go index bedef7ec20..53d3949641 100644 --- a/app/api/controller/repo/rule_find.go +++ b/app/api/controller/repo/rule_find.go @@ -29,7 +29,7 @@ func (c *Controller) RuleFind(ctx context.Context, repoRef string, identifier string, ) (*types.Rule, error) { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView, true) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView) if err != nil { return nil, err } diff --git a/app/api/controller/repo/rule_list.go b/app/api/controller/repo/rule_list.go index faef00d075..36a17652b3 100644 --- a/app/api/controller/repo/rule_list.go +++ b/app/api/controller/repo/rule_list.go @@ -30,7 +30,7 @@ func (c *Controller) RuleList(ctx context.Context, repoRef string, filter *types.RuleFilter, ) ([]types.Rule, int64, error) { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView, true) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView) if err != nil { return nil, 0, err } diff --git a/app/api/controller/repo/rule_update.go b/app/api/controller/repo/rule_update.go index 6aa304788e..84e2145cac 100644 --- a/app/api/controller/repo/rule_update.go +++ b/app/api/controller/repo/rule_update.go @@ -91,7 +91,7 @@ func (c *Controller) RuleUpdate(ctx context.Context, return nil, err } - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoEdit, false) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoEdit) if err != nil { return nil, err } diff --git a/app/api/controller/repo/soft_delete.go b/app/api/controller/repo/soft_delete.go index c9e742bd5f..6a1aefdc70 100644 --- a/app/api/controller/repo/soft_delete.go +++ b/app/api/controller/repo/soft_delete.go @@ -46,7 +46,7 @@ func (c *Controller) SoftDelete( return nil, fmt.Errorf("failed to find the repo for soft delete: %w", err) } - if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, enum.PermissionRepoDelete, c.publicAccess, false); err != nil { + if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, enum.PermissionRepoDelete); err != nil { return nil, fmt.Errorf("access check failed: %w", err) } diff --git a/app/api/controller/repo/update.go b/app/api/controller/repo/update.go index a90058a8f4..92e4572461 100644 --- a/app/api/controller/repo/update.go +++ b/app/api/controller/repo/update.go @@ -19,6 +19,7 @@ import ( "fmt" "strings" + apiauth "github.com/harness/gitness/app/api/auth" "github.com/harness/gitness/app/auth" "github.com/harness/gitness/app/paths" "github.com/harness/gitness/audit" @@ -43,15 +44,15 @@ func (c *Controller) Update(ctx context.Context, session *auth.Session, repoRef string, in *UpdateInput, -) (*types.Repository, error) { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoEdit, false) +) (*Repository, error) { + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoEdit) if err != nil { return nil, err } repoClone := repo.Clone() - if !in.hasChanges(repo) { + if !in.hasChanges(&repo.Repository) { return repo, nil } @@ -59,7 +60,7 @@ func (c *Controller) Update(ctx context.Context, return nil, fmt.Errorf("failed to sanitize input: %w", err) } - repo, err = c.repoStore.UpdateOptLock(ctx, repo, func(repo *types.Repository) error { + repoBase, err := c.repoStore.UpdateOptLock(ctx, &repo.Repository, func(repo *types.Repository) error { // update values only if provided if in.Description != nil { repo.Description = *in.Description @@ -85,8 +86,15 @@ func (c *Controller) Update(ctx context.Context, // backfill repo url repo.GitURL = c.urlProvider.GenerateGITCloneURL(repo.Path) + isPublic, err := apiauth.CheckRepoIsPublic(ctx, c.publicAccess, repoBase) + if err != nil { + return nil, fmt.Errorf("failed to get resource public access mode: %w", err) + } - return repo, nil + return &Repository{ + Repository: *repoBase, + IsPublic: isPublic, + }, nil } func (c *Controller) sanitizeUpdateInput(in *UpdateInput) error { diff --git a/app/api/controller/repo/visibility_update.go b/app/api/controller/repo/visibility_update.go index d5cba04908..07bdacb044 100644 --- a/app/api/controller/repo/visibility_update.go +++ b/app/api/controller/repo/visibility_update.go @@ -19,6 +19,7 @@ import ( "fmt" "github.com/harness/gitness/app/auth" + "github.com/harness/gitness/app/paths" "github.com/harness/gitness/types" "github.com/harness/gitness/types/enum" ) @@ -36,7 +37,7 @@ func (c *Controller) VisibilityUpdate(ctx context.Context, repoRef string, in *VisibilityInput, ) (*VisibilityOutput, error) { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoEdit, false) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoEdit) if err != nil { return nil, err } @@ -45,22 +46,20 @@ func (c *Controller) VisibilityUpdate(ctx context.Context, return nil, fmt.Errorf("failed to sanitize input: %w", err) } - err = c.publicAccess.Set( - ctx, - &types.PublicResource{ - Type: enum.PublicResourceTypeRepository, - ResourceID: repo.ID, - }, - in.EnablePublic, - ) + parentSpace, name, err := paths.DisectLeaf(repo.Path) if err != nil { - return nil, fmt.Errorf("failed to set public access: %w", err) + return nil, fmt.Errorf("Failed to disect path '%s': %w", repo.Path, err) } - // TODO log for the audit service + scope := &types.Scope{SpacePath: parentSpace} + resource := &types.Resource{ + Type: enum.ResourceTypeRepo, + Identifier: name, + } - // backfill repo url - repo.GitURL = c.urlProvider.GenerateGITCloneURL(repo.Path) + if err = c.publicAccess.Set(ctx, scope, resource, in.EnablePublic); err != nil { + return nil, fmt.Errorf("failed to set public access: %w", err) + } return &VisibilityOutput{ in.EnablePublic, diff --git a/app/api/controller/repo/wire.go b/app/api/controller/repo/wire.go index 4190d9f229..4fd391b2b7 100644 --- a/app/api/controller/repo/wire.go +++ b/app/api/controller/repo/wire.go @@ -17,7 +17,6 @@ package repo import ( "github.com/harness/gitness/app/api/controller/limiter" "github.com/harness/gitness/app/auth/authz" - repoevents "github.com/harness/gitness/app/events/repo" "github.com/harness/gitness/app/services/codeowners" "github.com/harness/gitness/app/services/importer" @@ -67,7 +66,7 @@ func ProvideController( mtxManager lock.MutexManager, identifierCheck check.RepoIdentifier, repoChecks Check, - publicAccess *publicaccess.Service, + publicAccess publicaccess.PublicAccess, ) *Controller { return NewController(config, tx, urlProvider, authorizer, diff --git a/app/api/controller/reposettings/controller.go b/app/api/controller/reposettings/controller.go index 1eb29636c1..3d8bc628a7 100644 --- a/app/api/controller/reposettings/controller.go +++ b/app/api/controller/reposettings/controller.go @@ -23,7 +23,6 @@ import ( "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/services/settings" "github.com/harness/gitness/app/store" - "github.com/harness/gitness/types" "github.com/harness/gitness/types/enum" ) @@ -31,14 +30,14 @@ type Controller struct { authorizer authz.Authorizer repoStore store.RepoStore settings *settings.Service - publicAccess *publicaccess.Service + publicAccess publicaccess.PublicAccess } func NewController( authorizer authz.Authorizer, repoStore store.RepoStore, settings *settings.Service, - publicAccess *publicaccess.Service, + publicAccess publicaccess.PublicAccess, ) *Controller { return &Controller{ authorizer: authorizer, @@ -55,16 +54,14 @@ func (c *Controller) getRepoCheckAccess( session *auth.Session, repoRef string, reqPermission enum.Permission, - orPublic bool, -) (*types.Repository, error) { +) (*repo.Repository, error) { return repo.GetRepoCheckAccess( ctx, c.repoStore, c.authorizer, + c.publicAccess, session, repoRef, reqPermission, - c.publicAccess, - orPublic, ) } diff --git a/app/api/controller/reposettings/security_find.go b/app/api/controller/reposettings/security_find.go index ee8d848900..b6c675f0bc 100644 --- a/app/api/controller/reposettings/security_find.go +++ b/app/api/controller/reposettings/security_find.go @@ -28,7 +28,7 @@ func (c *Controller) SecurityFind( session *auth.Session, repoRef string, ) (*SecuritySettings, error) { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoEdit, true) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoEdit) if err != nil { return nil, err } diff --git a/app/api/controller/reposettings/security_update.go b/app/api/controller/reposettings/security_update.go index 9d9e8ccebe..d81859b01d 100644 --- a/app/api/controller/reposettings/security_update.go +++ b/app/api/controller/reposettings/security_update.go @@ -29,7 +29,7 @@ func (c *Controller) SecurityUpdate( repoRef string, in *SecuritySettings, ) (*SecuritySettings, error) { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoEdit, false) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoEdit) if err != nil { return nil, err } diff --git a/app/api/controller/reposettings/wire.go b/app/api/controller/reposettings/wire.go index 0d02cf677a..4aaa2ba85c 100644 --- a/app/api/controller/reposettings/wire.go +++ b/app/api/controller/reposettings/wire.go @@ -32,7 +32,7 @@ func ProvideController( authorizer authz.Authorizer, repoStore store.RepoStore, settings *settings.Service, - publicAccess *publicaccess.Service, + publicAccess publicaccess.PublicAccess, ) *Controller { return NewController(authorizer, repoStore, settings, publicAccess) } diff --git a/app/api/controller/space/controller.go b/app/api/controller/space/controller.go index f0c8445958..05dd2d4824 100644 --- a/app/api/controller/space/controller.go +++ b/app/api/controller/space/controller.go @@ -58,7 +58,7 @@ type Controller struct { importer *importer.Repository exporter *exporter.Repository resourceLimiter limiter.ResourceLimiter - publicAccess *publicaccess.Service + publicAccess publicaccess.PublicAccess } func NewController(config *types.Config, tx dbtx.Transactor, urlProvider url.Provider, @@ -67,7 +67,7 @@ func NewController(config *types.Config, tx dbtx.Transactor, urlProvider url.Pro connectorStore store.ConnectorStore, templateStore store.TemplateStore, spaceStore store.SpaceStore, repoStore store.RepoStore, principalStore store.PrincipalStore, repoCtrl *repo.Controller, membershipStore store.MembershipStore, importer *importer.Repository, exporter *exporter.Repository, - limiter limiter.ResourceLimiter, publicAccess *publicaccess.Service, + limiter limiter.ResourceLimiter, publicAccess publicaccess.PublicAccess, ) *Controller { return &Controller{ nestedSpacesEnabled: config.NestedSpacesEnabled, diff --git a/app/api/controller/space/create.go b/app/api/controller/space/create.go index 5f98e249a3..b979b60142 100644 --- a/app/api/controller/space/create.go +++ b/app/api/controller/space/create.go @@ -147,12 +147,7 @@ func (c *Controller) createSpaceInnerInTX( } if in.IsPublic { - err = c.publicAccess.Set(ctx, - &types.PublicResource{ - Type: enum.PublicResourceTypeSpace, - ResourceID: space.ID, - }, in.IsPublic) - if err != nil { + if err := c.setPublicSpace(ctx, space); err != nil { return nil, fmt.Errorf("failed to insert a public resource: %w", err) } } @@ -187,8 +182,6 @@ func (c *Controller) getSpaceCheckAuthSpaceCreation( parentSpace, enum.ResourceTypeSpace, enum.PermissionSpaceEdit, - c.publicAccess, - false, ); err != nil { return nil, fmt.Errorf("authorization failed: %w", err) } @@ -196,6 +189,21 @@ func (c *Controller) getSpaceCheckAuthSpaceCreation( return parentSpace, nil } +func (c *Controller) setPublicSpace(ctx context.Context, space *types.Space) error { + parentSpace, name, err := paths.DisectLeaf(space.Path) + if err != nil { + return fmt.Errorf("failed to disect path '%s': %w", space.Path, err) + } + + scope := &types.Scope{SpacePath: parentSpace} + resource := &types.Resource{ + Type: enum.ResourceTypeSpace, + Identifier: name, + } + + return c.publicAccess.Set(ctx, scope, resource, true) +} + func (c *Controller) sanitizeCreateInput(in *CreateInput) error { // TODO [CODE-1363]: remove after identifier migration. if in.Identifier == "" { diff --git a/app/api/controller/space/events.go b/app/api/controller/space/events.go index 04da5e930c..9020f39793 100644 --- a/app/api/controller/space/events.go +++ b/app/api/controller/space/events.go @@ -34,7 +34,7 @@ func (c *Controller) Events( return nil, nil, nil, fmt.Errorf("failed to find space ref: %w", err) } - if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceView, c.publicAccess, true); err != nil { + if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceView); err != nil { return nil, nil, nil, fmt.Errorf("failed to authorize stream: %w", err) } diff --git a/app/api/controller/space/export.go b/app/api/controller/space/export.go index 0c52ccddd3..0a89c7cdcc 100644 --- a/app/api/controller/space/export.go +++ b/app/api/controller/space/export.go @@ -41,7 +41,7 @@ func (c *Controller) Export(ctx context.Context, session *auth.Session, spaceRef return err } - if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceEdit, c.publicAccess, false); err != nil { + if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceEdit); err != nil { return err } diff --git a/app/api/controller/space/export_progress.go b/app/api/controller/space/export_progress.go index 9b20c6d8da..783cc43571 100644 --- a/app/api/controller/space/export_progress.go +++ b/app/api/controller/space/export_progress.go @@ -42,7 +42,7 @@ func (c *Controller) ExportProgress(ctx context.Context, return ExportProgressOutput{}, err } - if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceView, c.publicAccess, false); err != nil { + if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceView); err != nil { return ExportProgressOutput{}, err } diff --git a/app/api/controller/space/find.go b/app/api/controller/space/find.go index c4abe04c3a..9295ec47c8 100644 --- a/app/api/controller/space/find.go +++ b/app/api/controller/space/find.go @@ -32,7 +32,7 @@ func (c *Controller) Find(ctx context.Context, session *auth.Session, spaceRef s return nil, err } - if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceView, c.publicAccess, true); err != nil { + if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceView); err != nil { return nil, err } diff --git a/app/api/controller/space/import.go b/app/api/controller/space/import.go index 23a7bd2860..73c045b9d8 100644 --- a/app/api/controller/space/import.go +++ b/app/api/controller/space/import.go @@ -23,7 +23,6 @@ import ( "github.com/harness/gitness/app/auth" "github.com/harness/gitness/app/services/importer" "github.com/harness/gitness/types" - "github.com/harness/gitness/types/enum" ) type ProviderInput struct { @@ -96,13 +95,9 @@ func (c *Controller) Import(ctx context.Context, session *auth.Session, in *Impo // update public resources if isPublic && c.publicResourceCreationEnabled { - err = c.publicAccess.Set(ctx, &types.PublicResource{ - Type: enum.PublicResourceTypeRepository, - ResourceID: repo.ID, - }, isPublic) - } - if err != nil { - return fmt.Errorf("failed to set a public repo: %w", err) + if err := c.repoCtrl.SetPublicRepo(ctx, repo); err != nil { + return fmt.Errorf("failed to set a public repo: %w", err) + } } } diff --git a/app/api/controller/space/import_repositories.go b/app/api/controller/space/import_repositories.go index 146f36fc22..a05f83d663 100644 --- a/app/api/controller/space/import_repositories.go +++ b/app/api/controller/space/import_repositories.go @@ -126,13 +126,9 @@ func (c *Controller) ImportRepositories( // update public resources if isPublic && c.publicResourceCreationEnabled { - err = c.publicAccess.Set(ctx, &types.PublicResource{ - Type: enum.PublicResourceTypeRepository, - ResourceID: repo.ID, - }, isPublic) - } - if err != nil { - return fmt.Errorf("failed to set a public repo: %w", err) + if err := c.repoCtrl.SetPublicRepo(ctx, repo); err != nil { + return fmt.Errorf("failed to set a public repo: %w", err) + } } repos = append(repos, repo) diff --git a/app/api/controller/space/list_repositories.go b/app/api/controller/space/list_repositories.go index 0ec35a539a..01ae060662 100644 --- a/app/api/controller/space/list_repositories.go +++ b/app/api/controller/space/list_repositories.go @@ -45,8 +45,6 @@ func (c *Controller) ListRepositories( space, enum.ResourceTypeRepo, enum.PermissionRepoView, - c.publicAccess, - true, ); err != nil { return nil, 0, err } @@ -79,11 +77,7 @@ func (c *Controller) ListRepositoriesNoAuth( repoBase.GitURL = c.urlProvider.GenerateGITCloneURL(repoBase.Path) // backfill public access mode - isPublic, err := c.publicAccess.Get(ctx, - &types.PublicResource{ - Type: enum.PublicResourceTypeRepository, - ResourceID: repoBase.ID, - }) + isPublic, err := apiauth.CheckRepoIsPublic(ctx, c.publicAccess, repoBase) if err != nil { return fmt.Errorf("failed to get resource public access mode: %w", err) } diff --git a/app/api/controller/space/list_spaces.go b/app/api/controller/space/list_spaces.go index 82bdeaec03..41a4c32473 100644 --- a/app/api/controller/space/list_spaces.go +++ b/app/api/controller/space/list_spaces.go @@ -48,8 +48,6 @@ func (c *Controller) ListSpaces(ctx context.Context, space, enum.ResourceTypeSpace, enum.PermissionSpaceView, - c.publicAccess, - true, ); err != nil { return nil, 0, err } @@ -79,10 +77,7 @@ func (c *Controller) ListSpacesNoAuth( for _, spaceBase := range spacesBase { // backfill public access mode - isPublic, err := c.publicAccess.Get(ctx, &types.PublicResource{ - Type: enum.PublicResourceTypeSpace, - ResourceID: spaceBase.ID, - }) + isPublic, err := apiauth.CheckSpaceIsPublic(ctx, c.publicAccess, spaceBase) if err != nil { return fmt.Errorf("failed to get resource public access mode: %w", err) } diff --git a/app/api/controller/space/membership_add.go b/app/api/controller/space/membership_add.go index 14a5224350..07de38c6ab 100644 --- a/app/api/controller/space/membership_add.go +++ b/app/api/controller/space/membership_add.go @@ -66,7 +66,7 @@ func (c *Controller) MembershipAdd(ctx context.Context, return nil, err } - if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceEdit, c.publicAccess, false); err != nil { + if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceEdit); err != nil { return nil, err } diff --git a/app/api/controller/space/membership_delete.go b/app/api/controller/space/membership_delete.go index 8f5784639d..b0544cec56 100644 --- a/app/api/controller/space/membership_delete.go +++ b/app/api/controller/space/membership_delete.go @@ -35,7 +35,7 @@ func (c *Controller) MembershipDelete(ctx context.Context, return err } - if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceEdit, c.publicAccess, false); err != nil { + if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceEdit); err != nil { return err } diff --git a/app/api/controller/space/membership_list.go b/app/api/controller/space/membership_list.go index c3cb2c45fc..f35a62a633 100644 --- a/app/api/controller/space/membership_list.go +++ b/app/api/controller/space/membership_list.go @@ -36,7 +36,7 @@ func (c *Controller) MembershipList(ctx context.Context, return nil, 0, err } - if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceView, c.publicAccess, false); err != nil { + if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceView); err != nil { return nil, 0, err } diff --git a/app/api/controller/space/membership_update.go b/app/api/controller/space/membership_update.go index 0dd079637b..78ff493292 100644 --- a/app/api/controller/space/membership_update.go +++ b/app/api/controller/space/membership_update.go @@ -58,7 +58,7 @@ func (c *Controller) MembershipUpdate(ctx context.Context, return nil, err } - if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceEdit, c.publicAccess, false); err != nil { + if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceEdit); err != nil { return nil, err } diff --git a/app/api/controller/space/move.go b/app/api/controller/space/move.go index 53bc81396d..07d81af02c 100644 --- a/app/api/controller/space/move.go +++ b/app/api/controller/space/move.go @@ -55,7 +55,7 @@ func (c *Controller) Move( return nil, err } - if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceEdit, c.publicAccess, false); err != nil { + if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceEdit); err != nil { return nil, err } diff --git a/app/api/controller/space/purge.go b/app/api/controller/space/purge.go index 1e17fa8010..39f8cdd2b2 100644 --- a/app/api/controller/space/purge.go +++ b/app/api/controller/space/purge.go @@ -43,7 +43,7 @@ func (c *Controller) Purge( // authz will check the permission within the first existing parent since space was deleted. // purge top level space is limited to admin only. - err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceDelete, c.publicAccess, false) + err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceDelete) if err != nil { return fmt.Errorf("failed to authorize on space purge: %w", err) } diff --git a/app/api/controller/space/restore.go b/app/api/controller/space/restore.go index 953e6681b0..a0818cf7e9 100644 --- a/app/api/controller/space/restore.go +++ b/app/api/controller/space/restore.go @@ -56,7 +56,7 @@ func (c *Controller) Restore( } // check view permission on the original ref. - err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceView, c.publicAccess, false) + err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceView) if err != nil { return nil, fmt.Errorf("failed to authorize on space restore: %w", err) } @@ -74,8 +74,6 @@ func (c *Controller) Restore( parentSpace, enum.ResourceTypeSpace, enum.PermissionSpaceEdit, - c.publicAccess, - false, ); err != nil { return nil, fmt.Errorf("authorization failed on space restore: %w", err) } diff --git a/app/api/controller/space/soft_delete.go b/app/api/controller/space/soft_delete.go index eb490d49df..891a15a1b1 100644 --- a/app/api/controller/space/soft_delete.go +++ b/app/api/controller/space/soft_delete.go @@ -47,8 +47,6 @@ func (c *Controller) SoftDelete( session, space, enum.PermissionSpaceDelete, - c.publicAccess, - false, ); err != nil { return nil, fmt.Errorf("failed to check access: %w", err) } diff --git a/app/api/controller/space/update.go b/app/api/controller/space/update.go index 8301aff659..f7a5ba9797 100644 --- a/app/api/controller/space/update.go +++ b/app/api/controller/space/update.go @@ -43,7 +43,7 @@ func (c *Controller) Update(ctx context.Context, session *auth.Session, return nil, err } - if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceEdit, c.publicAccess, false); err != nil { + if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceEdit); err != nil { return nil, err } diff --git a/app/api/controller/space/wire.go b/app/api/controller/space/wire.go index adcd23c236..efa7ba5de5 100644 --- a/app/api/controller/space/wire.go +++ b/app/api/controller/space/wire.go @@ -42,7 +42,7 @@ func ProvideController(config *types.Config, tx dbtx.Transactor, urlProvider url connectorStore store.ConnectorStore, templateStore store.TemplateStore, spaceStore store.SpaceStore, repoStore store.RepoStore, principalStore store.PrincipalStore, repoCtrl *repo.Controller, membershipStore store.MembershipStore, importer *importer.Repository, - exporter *exporter.Repository, limiter limiter.ResourceLimiter, publicAccess *publicaccess.Service, + exporter *exporter.Repository, limiter limiter.ResourceLimiter, publicAccess publicaccess.PublicAccess, ) *Controller { return NewController(config, tx, urlProvider, sseStreamer, identifierCheck, authorizer, spacePathStore, pipelineStore, secretStore, diff --git a/app/api/controller/upload/controller.go b/app/api/controller/upload/controller.go index 78c440e593..7f3a7396a1 100644 --- a/app/api/controller/upload/controller.go +++ b/app/api/controller/upload/controller.go @@ -26,7 +26,6 @@ import ( "github.com/harness/gitness/app/api/usererror" "github.com/harness/gitness/app/auth" "github.com/harness/gitness/app/auth/authz" - "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/store" "github.com/harness/gitness/blob" "github.com/harness/gitness/types" @@ -47,29 +46,25 @@ var supportedFileTypes = map[string]struct{}{ } type Controller struct { - authorizer authz.Authorizer - repoStore store.RepoStore - blobStore blob.Store - publicAccess *publicaccess.Service + authorizer authz.Authorizer + repoStore store.RepoStore + blobStore blob.Store } func NewController(authorizer authz.Authorizer, repoStore store.RepoStore, blobStore blob.Store, - publicAccess *publicaccess.Service, ) *Controller { return &Controller{ - authorizer: authorizer, - repoStore: repoStore, - blobStore: blobStore, - publicAccess: publicAccess, + authorizer: authorizer, + repoStore: repoStore, + blobStore: blobStore, } } func (c *Controller) getRepoCheckAccess(ctx context.Context, session *auth.Session, repoRef string, reqPermission enum.Permission, - orPublic bool, ) (*types.Repository, error) { if repoRef == "" { return nil, usererror.BadRequest("A valid repository reference must be provided.") @@ -80,7 +75,7 @@ func (c *Controller) getRepoCheckAccess(ctx context.Context, return nil, fmt.Errorf("failed to find repo: %w", err) } - if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, reqPermission, c.publicAccess, orPublic); err != nil { + if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, reqPermission); err != nil { return nil, fmt.Errorf("failed to verify authorization: %w", err) } diff --git a/app/api/controller/upload/download.go b/app/api/controller/upload/download.go index 6c62449177..7730b4b302 100644 --- a/app/api/controller/upload/download.go +++ b/app/api/controller/upload/download.go @@ -31,7 +31,7 @@ func (c *Controller) Download( repoRef string, filePath string, ) (string, io.ReadCloser, error) { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView, true) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView) if err != nil { return "", nil, fmt.Errorf("failed to acquire access to repo: %w", err) } diff --git a/app/api/controller/upload/upload.go b/app/api/controller/upload/upload.go index 5c6bb93e30..f4660d0602 100644 --- a/app/api/controller/upload/upload.go +++ b/app/api/controller/upload/upload.go @@ -42,7 +42,7 @@ func (c *Controller) Upload(ctx context.Context, file io.Reader, ) (*Result, error) { // Permission check to see if the user in request has access to the repo. - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoReview, false) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoReview) if err != nil { return nil, fmt.Errorf("failed to acquire access to repo: %w", err) } diff --git a/app/api/controller/upload/wire.go b/app/api/controller/upload/wire.go index bbc72dbf43..68c6ea6e6d 100644 --- a/app/api/controller/upload/wire.go +++ b/app/api/controller/upload/wire.go @@ -16,7 +16,6 @@ package upload import ( "github.com/harness/gitness/app/auth/authz" - "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/store" "github.com/harness/gitness/blob" @@ -32,7 +31,6 @@ func ProvideController( authorizer authz.Authorizer, repoStore store.RepoStore, blobStore blob.Store, - publicAccess *publicaccess.Service, ) *Controller { - return NewController(authorizer, repoStore, blobStore, publicAccess) + return NewController(authorizer, repoStore, blobStore) } diff --git a/app/api/controller/webhook/controller.go b/app/api/controller/webhook/controller.go index c5be7d221c..410fc48c28 100644 --- a/app/api/controller/webhook/controller.go +++ b/app/api/controller/webhook/controller.go @@ -40,7 +40,7 @@ type Controller struct { repoStore store.RepoStore webhookService *webhook.Service encrypter encrypt.Encrypter - publicAccess *publicaccess.Service + publicAccess publicaccess.PublicAccess } func NewController( @@ -52,7 +52,7 @@ func NewController( repoStore store.RepoStore, webhookService *webhook.Service, encrypter encrypt.Encrypter, - publicAccess *publicaccess.Service, + publicAccess publicaccess.PublicAccess, ) *Controller { return &Controller{ allowLoopback: allowLoopback, @@ -78,7 +78,7 @@ func (c *Controller) getRepoCheckAccess(ctx context.Context, return nil, fmt.Errorf("failed to find repo: %w", err) } - if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, reqPermission, c.publicAccess, false); err != nil { + if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, reqPermission); err != nil { return nil, fmt.Errorf("failed to verify authorization: %w", err) } diff --git a/app/api/controller/webhook/wire.go b/app/api/controller/webhook/wire.go index c11affe710..c810634759 100644 --- a/app/api/controller/webhook/wire.go +++ b/app/api/controller/webhook/wire.go @@ -31,7 +31,7 @@ var WireSet = wire.NewSet( func ProvideController(config webhook.Config, authorizer authz.Authorizer, webhookStore store.WebhookStore, webhookExecutionStore store.WebhookExecutionStore, - repoStore store.RepoStore, webhookService *webhook.Service, encrypter encrypt.Encrypter, publicAccess *publicaccess.Service, + repoStore store.RepoStore, webhookService *webhook.Service, encrypter encrypt.Encrypter, publicAccess publicaccess.PublicAccess, ) *Controller { return NewController( config.AllowLoopback, config.AllowPrivateNetwork, authorizer, diff --git a/app/auth/authz/membership.go b/app/auth/authz/membership.go index 2bfb6e9180..bd8033ff0d 100644 --- a/app/auth/authz/membership.go +++ b/app/auth/authz/membership.go @@ -20,6 +20,7 @@ import ( "github.com/harness/gitness/app/auth" "github.com/harness/gitness/app/paths" + "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/store" "github.com/harness/gitness/types" "github.com/harness/gitness/types/enum" @@ -32,15 +33,18 @@ var _ Authorizer = (*MembershipAuthorizer)(nil) type MembershipAuthorizer struct { permissionCache PermissionCache spaceStore store.SpaceStore + publicAccess publicaccess.PublicAccess } func NewMembershipAuthorizer( permissionCache PermissionCache, spaceStore store.SpaceStore, + publicAccess publicaccess.PublicAccess, ) *MembershipAuthorizer { return &MembershipAuthorizer{ permissionCache: permissionCache, spaceStore: spaceStore, + publicAccess: publicAccess, } } @@ -51,7 +55,15 @@ func (a *MembershipAuthorizer) Check( resource *types.Resource, permission enum.Permission, ) (bool, error) { - // public access - not expected to come here as of now (have to refactor that part) + isPublic, err := a.CheckPublicAccess(ctx, scope, resource, permission) + if err != nil { + return false, fmt.Errorf("failed to check public access: %w", err) + } + + if isPublic { + return true, nil + } + if session == nil { log.Ctx(ctx).Warn().Msgf( "public access request for %s in scope %#v got to authorizer", diff --git a/app/auth/authz/public.go b/app/auth/authz/public.go new file mode 100644 index 0000000000..2e263df949 --- /dev/null +++ b/app/auth/authz/public.go @@ -0,0 +1,43 @@ +// Copyright 2023 Harness, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package authz + +import ( + "context" + + "github.com/harness/gitness/types" + "github.com/harness/gitness/types/enum" +) + +func (a *MembershipAuthorizer) CheckPublicAccess( + ctx context.Context, + scope *types.Scope, + resource *types.Resource, + permission enum.Permission, +) (bool, error) { + // public access only permits view. + if permission != enum.PermissionRepoView && + permission != enum.PermissionSpaceView { + return false, nil + } + + // public access is enabled on these resource types. + if resource.Type != enum.ResourceTypeRepo && + resource.Type != enum.ResourceTypeSpace { + return false, nil + } + + return a.publicAccess.Get(ctx, scope, resource) +} diff --git a/app/auth/authz/wire.go b/app/auth/authz/wire.go index 8d9aec6a93..9c7a69bf30 100644 --- a/app/auth/authz/wire.go +++ b/app/auth/authz/wire.go @@ -17,6 +17,7 @@ package authz import ( "time" + "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/store" "github.com/google/wire" @@ -28,8 +29,12 @@ var WireSet = wire.NewSet( ProvidePermissionCache, ) -func ProvideAuthorizer(pCache PermissionCache, spaceStore store.SpaceStore) Authorizer { - return NewMembershipAuthorizer(pCache, spaceStore) +func ProvideAuthorizer( + pCache PermissionCache, + spaceStore store.SpaceStore, + publicAccess publicaccess.PublicAccess, +) Authorizer { + return NewMembershipAuthorizer(pCache, spaceStore, publicAccess) } func ProvidePermissionCache( diff --git a/app/services/exporter/harness_code_client.go b/app/services/exporter/harness_code_client.go index 92f9a7bd42..43ca13fbe4 100644 --- a/app/services/exporter/harness_code_client.go +++ b/app/services/exporter/harness_code_client.go @@ -25,7 +25,6 @@ import ( "strings" "github.com/harness/gitness/app/api/controller/repo" - "github.com/harness/gitness/types" ) const ( @@ -109,7 +108,7 @@ func newHarnessCodeClient( }, nil } -func (c *harnessCodeClient) CreateRepo(ctx context.Context, input repo.CreateInput) (*types.Repository, error) { +func (c *harnessCodeClient) CreateRepo(ctx context.Context, input repo.CreateInput) (*repo.Repository, error) { path := fmt.Sprintf(pathCreateRepo, c.client.accountID, c.client.orgID, c.client.projectID) bodyBytes, err := json.Marshal(input) if err != nil { @@ -139,7 +138,7 @@ func (c *harnessCodeClient) CreateRepo(ctx context.Context, input repo.CreateInp defer func() { _ = resp.Body.Close() }() } - repository := new(types.Repository) + repository := new(repo.Repository) err = mapStatusCodeToError(resp.StatusCode) if err != nil { return nil, err diff --git a/app/services/exporter/repository.go b/app/services/exporter/repository.go index 48c329332d..c62406459b 100644 --- a/app/services/exporter/repository.go +++ b/app/services/exporter/repository.go @@ -25,6 +25,7 @@ import ( "time" "github.com/harness/gitness/app/api/controller/repo" + "github.com/harness/gitness/app/paths" "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/sse" "github.com/harness/gitness/app/store" @@ -55,7 +56,7 @@ type Repository struct { scheduler *job.Scheduler encrypter encrypt.Encrypter sseStreamer sse.Streamer - publicAccess *publicaccess.Service + publicAccess publicaccess.PublicAccess } type Input struct { @@ -117,11 +118,18 @@ func (r *Repository) RunManyForSpace( jobDefinitions := make([]job.Definition, len(repos)) for i, repository := range repos { // check if repo is public - isPublic, err := r.publicAccess.Get(ctx, - &types.PublicResource{ - Type: enum.PublicResourceTypeRepository, - ResourceID: repository.ID, - }) + parentSpace, name, err := paths.DisectLeaf(repository.Path) + if err != nil { + return fmt.Errorf("Failed to disect path '%s': %w", repository.Path, err) + } + + scope := &types.Scope{SpacePath: parentSpace} + resource := &types.Resource{ + Type: enum.ResourceTypeRepo, + Identifier: name, + } + + isPublic, err := r.publicAccess.Get(ctx, scope, resource) if err != nil { return fmt.Errorf("failed to check repo public visibility: %w", err) } diff --git a/app/services/exporter/wire.go b/app/services/exporter/wire.go index b6e7033f2c..1b25dd0228 100644 --- a/app/services/exporter/wire.go +++ b/app/services/exporter/wire.go @@ -38,7 +38,7 @@ func ProvideSpaceExporter( executor *job.Executor, encrypter encrypt.Encrypter, sseStreamer sse.Streamer, - publicAccess *publicaccess.Service, + publicAccess publicaccess.PublicAccess, ) (*Repository, error) { exporter := &Repository{ urlProvider: urlProvider, diff --git a/app/services/publicaccess/manager.go b/app/services/publicaccess/manager.go deleted file mode 100644 index 5e499ee25d..0000000000 --- a/app/services/publicaccess/manager.go +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2023 Harness, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package publicaccess - -import ( - "context" - "errors" - "fmt" - - "github.com/harness/gitness/app/store" - gitness_store "github.com/harness/gitness/store" - "github.com/harness/gitness/types" -) - -type PublicAccessManager struct { - publicResourceStore store.PublicResource -} - -func NewPublicAccessManager( - publicResourceStore store.PublicResource, -) *PublicAccessManager { - return &PublicAccessManager{ - publicResourceStore: publicResourceStore, - } -} - -func (r *PublicAccessManager) Get( - ctx context.Context, - resource *types.PublicResource) (bool, error) { - err := r.publicResourceStore.Find(ctx, resource) - if errors.Is(err, gitness_store.ErrResourceNotFound) { - return false, nil - } - if err != nil { - return false, fmt.Errorf("failed to get public access resource: %w", err) - } - - return true, nil -} - -func (r *PublicAccessManager) Set(ctx context.Context, - resource *types.PublicResource, - enable bool) error { - if enable { - err := r.publicResourceStore.Create(ctx, resource) - if errors.Is(err, gitness_store.ErrDuplicate) { - return nil - } - return err - } else { - return r.publicResourceStore.Delete(ctx, resource) - } -} diff --git a/app/services/publicaccess/public_access.go b/app/services/publicaccess/public_access.go index 61c58074da..db3b48ffbe 100644 --- a/app/services/publicaccess/public_access.go +++ b/app/services/publicaccess/public_access.go @@ -23,22 +23,28 @@ import ( // PublicAccess is an abstraction of an entity responsible for managing public access to resources. type PublicAccess interface { /* - * Get returns whether resource public access is enabled. + * Get returns whether public access is enabled on the resource. * Returns * (true, nil) - resource public access is allowed * (false, nil) - resource public access is not allowed * (false, err) - an error occurred while performing the public access check. */ - Get(ctx context.Context, - resource *types.PublicResource) (bool, error) + Get( + ctx context.Context, + scope *types.Scope, + resource *types.Resource, + ) (bool, error) /* - * Sets the resource public access mode with the provided value. + * Sets or deletes public access mode for the resource based on the value of 'enable'. * Returns * err - resource public access mode has been updated successfully * nil - an error occurred while performing the public access set. */ - Set(ctx context.Context, - resource *types.PublicResource, - enable bool) error + Set( + ctx context.Context, + scope *types.Scope, + resource *types.Resource, + enable bool, + ) error } diff --git a/app/services/publicaccess/resources.go b/app/services/publicaccess/resources.go new file mode 100644 index 0000000000..e2f8a6240f --- /dev/null +++ b/app/services/publicaccess/resources.go @@ -0,0 +1,87 @@ +// Copyright 2023 Harness, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package publicaccess + +import ( + "context" + "fmt" + + "github.com/harness/gitness/app/paths" + "github.com/harness/gitness/types" + "github.com/harness/gitness/types/enum" +) + +func (s *Service) getPublicResource( + ctx context.Context, + scope *types.Scope, + resource *types.Resource, +) (*types.PublicResource, error) { + resType := resource.Type + + // set scope type to space for checks within space scope. + if resource.Identifier == "" { + resType = enum.ResourceTypeSpace + } + var pubRes *types.PublicResource + var err error + switch resType { + case enum.ResourceTypeRepo: + pubRes, err = s.getResourceRepo(ctx, scope, resource) + case enum.ResourceTypeSpace: + pubRes, err = s.getResourceSpace(ctx, scope, resource) + default: + return nil, fmt.Errorf("invalid public resource type") + } + + if err != nil { + return nil, fmt.Errorf("failed to get public resource: %w", err) + } + + return pubRes, nil +} + +func (s *Service) getResourceRepo( + ctx context.Context, + scope *types.Scope, + resource *types.Resource, +) (*types.PublicResource, error) { + repoRef := paths.Concatenate(scope.SpacePath, resource.Identifier) + repo, err := s.repoStore.FindByRef(ctx, repoRef) + if err != nil { + return nil, fmt.Errorf("failed to find repo: %w", err) + } + + return &types.PublicResource{ + Type: enum.PublicResourceTypeRepo, + ID: repo.ID, + }, nil +} + +func (s *Service) getResourceSpace( + ctx context.Context, + scope *types.Scope, + resource *types.Resource, +) (*types.PublicResource, error) { + spaceRef := paths.Concatenate(scope.SpacePath, resource.Identifier) + space, err := s.spaceStore.FindByRef(ctx, spaceRef) + if err != nil { + return nil, fmt.Errorf("failed to find space: %w", err) + } + + return &types.PublicResource{ + Type: enum.PublicResourceTypeSpace, + ID: space.ID, + }, nil +} diff --git a/app/services/publicaccess/service.go b/app/services/publicaccess/service.go index 1a54795245..a5e5c28111 100644 --- a/app/services/publicaccess/service.go +++ b/app/services/publicaccess/service.go @@ -16,33 +16,71 @@ package publicaccess import ( "context" + "errors" + "fmt" + "github.com/harness/gitness/app/store" + gitness_store "github.com/harness/gitness/store" "github.com/harness/gitness/types" ) type Service struct { - manager PublicAccess + publicResourceStore store.PublicResource + repoStore store.RepoStore + spaceStore store.SpaceStore } func NewService( - manager PublicAccess, -) *Service { + publicResourceStore store.PublicResource, + repoStore store.RepoStore, + spaceStore store.SpaceStore, +) PublicAccess { return &Service{ - manager: manager, + publicResourceStore: publicResourceStore, + repoStore: repoStore, + spaceStore: spaceStore, } } func (s *Service) Get( ctx context.Context, - resource *types.PublicResource, + scope *types.Scope, + resource *types.Resource, ) (bool, error) { - return s.manager.Get(ctx, resource) + pubRes, err := s.getPublicResource(ctx, scope, resource) + if err != nil { + return false, err + } + + err = s.publicResourceStore.Find(ctx, pubRes) + if errors.Is(err, gitness_store.ErrResourceNotFound) { + return false, nil + } + if err != nil { + return false, fmt.Errorf("failed to get public access resource: %w", err) + } + + return true, nil } func (s *Service) Set( ctx context.Context, - resource *types.PublicResource, + scope *types.Scope, + resource *types.Resource, enable bool, ) error { - return s.manager.Set(ctx, resource, enable) + pubRes, err := s.getPublicResource(ctx, scope, resource) + if err != nil { + return err + } + + if enable { + err := s.publicResourceStore.Create(ctx, pubRes) + if errors.Is(err, gitness_store.ErrDuplicate) { + return nil + } + return err + } else { + return s.publicResourceStore.Delete(ctx, pubRes) + } } diff --git a/app/services/publicaccess/wire.go b/app/services/publicaccess/wire.go index cdba432da5..45a61ecfb5 100644 --- a/app/services/publicaccess/wire.go +++ b/app/services/publicaccess/wire.go @@ -21,23 +21,13 @@ import ( ) var WireSet = wire.NewSet( - ProvidePublicAccessManager, ProvidePublicAccess, - ProvideService, ) -func ProvideService( - manager PublicAccess, -) *Service { - return NewService(manager) -} - -func ProvidePublicAccessManager( +func ProvidePublicAccess( publicResources store.PublicResource, -) *PublicAccessManager { - return NewPublicAccessManager(publicResources) -} - -func ProvidePublicAccess(p *PublicAccessManager) PublicAccess { - return p + repoStore store.RepoStore, + spaceStore store.SpaceStore, +) PublicAccess { + return NewService(publicResources, repoStore, spaceStore) } diff --git a/app/store/database.go b/app/store/database.go index 2bbadc3a84..73a1c4f4cc 100644 --- a/app/store/database.go +++ b/app/store/database.go @@ -292,9 +292,9 @@ type ( // PublicResource defines the publicly accessible resources data storage. PublicResource interface { - Find(ctx context.Context, publicResource *types.PublicResource) error - Create(ctx context.Context, publicResource *types.PublicResource) error - Delete(ctx context.Context, publicResource *types.PublicResource) error + Find(ctx context.Context, pubRes *types.PublicResource) error + Create(ctx context.Context, pubRes *types.PublicResource) error + Delete(ctx context.Context, pubRes *types.PublicResource) error } // TokenStore defines the token data storage. diff --git a/app/store/database/public_resource.go b/app/store/database/public_resource.go index df4f4241a4..14d3fc0e90 100644 --- a/app/store/database/public_resource.go +++ b/app/store/database/public_resource.go @@ -58,19 +58,19 @@ const ( func (p *PublicResourcesStore) Find( ctx context.Context, - publicRsc *types.PublicResource, + pubRes *types.PublicResource, ) error { stmt := database.Builder. Select(publicResourceColumns). From("public_resources") - switch publicRsc.Type { - case enum.PublicResourceTypeRepository: - stmt = stmt.Where("public_resource_repo_id = ?", publicRsc.ResourceID) + switch pubRes.Type { + case enum.PublicResourceTypeRepo: + stmt = stmt.Where("public_resource_repo_id = ?", pubRes.ID) case enum.PublicResourceTypeSpace: - stmt = stmt.Where("public_resource_space_id = ?", publicRsc.ResourceID) + stmt = stmt.Where("public_resource_space_id = ?", pubRes.ID) default: - return fmt.Errorf("public resource type %q is not supported", publicRsc.Type) + return fmt.Errorf("public resource type %q is not supported", pubRes.Type) } sql, args, err := stmt.ToSql() @@ -90,7 +90,8 @@ func (p *PublicResourcesStore) Find( func (p *PublicResourcesStore) Create( ctx context.Context, - publicRsc *types.PublicResource) error { + pubRes *types.PublicResource, +) error { stmt := database.Builder. Insert(""). Into("public_resources"). @@ -99,13 +100,13 @@ func (p *PublicResourcesStore) Create( "public_resource_repo_id", ) - switch publicRsc.Type { - case enum.PublicResourceTypeRepository: - stmt = stmt.Values(null.Int{}, null.IntFrom(publicRsc.ResourceID)) + switch pubRes.Type { + case enum.PublicResourceTypeRepo: + stmt = stmt.Values(null.Int{}, null.IntFrom(pubRes.ID)) case enum.PublicResourceTypeSpace: - stmt = stmt.Values(null.IntFrom(publicRsc.ResourceID), null.Int{}) + stmt = stmt.Values(null.IntFrom(pubRes.ID), null.Int{}) default: - return fmt.Errorf("public resource type %q is not supported", publicRsc.Type) + return fmt.Errorf("public resource type %q is not supported", pubRes.Type) } sql, args, err := stmt.ToSql() @@ -124,17 +125,18 @@ func (p *PublicResourcesStore) Create( func (p *PublicResourcesStore) Delete( ctx context.Context, - publicRsc *types.PublicResource) error { + pubRes *types.PublicResource, +) error { stmt := database.Builder. Delete("public_resources") - switch publicRsc.Type { - case enum.PublicResourceTypeRepository: - stmt = stmt.Where("public_resource_repo_id = ?", publicRsc.ResourceID) + switch pubRes.Type { + case enum.PublicResourceTypeRepo: + stmt = stmt.Where("public_resource_repo_id = ?", pubRes.ID) case enum.PublicResourceTypeSpace: - stmt = stmt.Where("public_resource_space_id = ?", publicRsc.ResourceID) + stmt = stmt.Where("public_resource_space_id = ?", pubRes.ID) default: - return fmt.Errorf("public resource type %q is not supported", publicRsc.Type) + return fmt.Errorf("public resource type %q is not supported", pubRes.Type) } sql, args, err := stmt.ToSql() diff --git a/cmd/gitness/wire_gen.go b/cmd/gitness/wire_gen.go index fef834ad07..d356742af5 100644 --- a/cmd/gitness/wire_gen.go +++ b/cmd/gitness/wire_gen.go @@ -115,7 +115,10 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro principalInfoCache := cache.ProvidePrincipalInfoCache(principalInfoView) membershipStore := database.ProvideMembershipStore(db, principalInfoCache, spacePathStore, spaceStore) permissionCache := authz.ProvidePermissionCache(spaceStore, membershipStore) - authorizer := authz.ProvideAuthorizer(permissionCache, spaceStore) + publicResource := database.ProvidePublicResourcesStore(db) + repoStore := database.ProvideRepoStore(db, spacePathCache, spacePathStore, spaceStore) + publicAccess := publicaccess.ProvidePublicAccess(publicResource, repoStore, spaceStore) + authorizer := authz.ProvideAuthorizer(permissionCache, spaceStore, publicAccess) principalUIDTransformation := store.ProvidePrincipalUIDTransformation() principalStore := database.ProvidePrincipalStore(db, principalUIDTransformation) tokenStore := database.ProvideTokenStore(db) @@ -127,7 +130,6 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro if err != nil { return nil, err } - repoStore := database.ProvideRepoStore(db, spacePathCache, spacePathStore, spaceStore) pipelineStore := database.ProvidePipelineStore(db) ruleStore := database.ProvideRuleStore(db, principalInfoCache) settingsStore := database.ProvideSettingsStore(db) @@ -198,12 +200,8 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro auditService := audit.ProvideAuditService() repoIdentifier := check.ProvideRepoIdentifierCheck() repoCheck := repo.ProvideRepoCheck() - publicResource := database.ProvidePublicResourcesStore(db) - publicAccessManager := publicaccess.ProvidePublicAccessManager(publicResource) - publicAccess := publicaccess.ProvidePublicAccess(publicAccessManager) - publicaccessService := publicaccess.ProvideService(publicAccess) - repoController := repo.ProvideController(config, transactor, provider, authorizer, repoStore, spaceStore, pipelineStore, principalStore, ruleStore, settingsService, principalInfoCache, protectionManager, gitInterface, repository, codeownersService, reporter, indexer, resourceLimiter, lockerLocker, auditService, mutexManager, repoIdentifier, repoCheck, publicaccessService) - reposettingsController := reposettings.ProvideController(authorizer, repoStore, settingsService, publicaccessService) + repoController := repo.ProvideController(config, transactor, provider, authorizer, repoStore, spaceStore, pipelineStore, principalStore, ruleStore, settingsService, principalInfoCache, protectionManager, gitInterface, repository, codeownersService, reporter, indexer, resourceLimiter, lockerLocker, auditService, mutexManager, repoIdentifier, repoCheck, publicAccess) + reposettingsController := reposettings.ProvideController(authorizer, repoStore, settingsService, publicAccess) executionStore := database.ProvideExecutionStore(db) checkStore := database.ProvideCheckStore(db, principalInfoCache) stageStore := database.ProvideStageStore(db) @@ -226,11 +224,11 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro spaceIdentifier := check.ProvideSpaceIdentifierCheck() secretStore := database.ProvideSecretStore(db) connectorStore := database.ProvideConnectorStore(db) - exporterRepository, err := exporter.ProvideSpaceExporter(provider, gitInterface, repoStore, jobScheduler, executor, encrypter, streamer, publicaccessService) + exporterRepository, err := exporter.ProvideSpaceExporter(provider, gitInterface, repoStore, jobScheduler, executor, encrypter, streamer, publicAccess) if err != nil { return nil, err } - spaceController := space.ProvideController(config, transactor, provider, streamer, spaceIdentifier, authorizer, spacePathStore, pipelineStore, secretStore, connectorStore, templateStore, spaceStore, repoStore, principalStore, repoController, membershipStore, repository, exporterRepository, resourceLimiter, publicaccessService) + spaceController := space.ProvideController(config, transactor, provider, streamer, spaceIdentifier, authorizer, spacePathStore, pipelineStore, secretStore, connectorStore, templateStore, spaceStore, repoStore, principalStore, repoController, membershipStore, repository, exporterRepository, resourceLimiter, publicAccess) pipelineController := pipeline.ProvideController(repoStore, triggerStore, authorizer, pipelineStore) secretController := secret.ProvideController(encrypter, secretStore, authorizer, spaceStore) triggerController := trigger.ProvideController(authorizer, triggerStore, pipelineStore, repoStore) @@ -262,7 +260,7 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro if err != nil { return nil, err } - pullreqController := pullreq2.ProvideController(transactor, provider, authorizer, pullReqStore, pullReqActivityStore, codeCommentView, pullReqReviewStore, pullReqReviewerStore, repoStore, principalStore, pullReqFileViewStore, membershipStore, checkStore, gitInterface, eventsReporter, migrator, pullreqService, protectionManager, streamer, codeownersService, lockerLocker, publicaccessService) + pullreqController := pullreq2.ProvideController(transactor, provider, authorizer, pullReqStore, pullReqActivityStore, codeCommentView, pullReqReviewStore, pullReqReviewerStore, repoStore, principalStore, pullReqFileViewStore, membershipStore, checkStore, gitInterface, eventsReporter, migrator, pullreqService, protectionManager, streamer, codeownersService, lockerLocker) webhookConfig := server.ProvideWebhookConfig(config) webhookStore := database.ProvideWebhookStore(db) webhookExecutionStore := database.ProvideWebhookExecutionStore(db) @@ -270,7 +268,7 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro if err != nil { return nil, err } - webhookController := webhook2.ProvideController(webhookConfig, authorizer, webhookStore, webhookExecutionStore, repoStore, webhookService, encrypter, publicaccessService) + webhookController := webhook2.ProvideController(webhookConfig, authorizer, webhookStore, webhookExecutionStore, repoStore, webhookService, encrypter, publicAccess) reporter2, err := events4.ProvideReporter(eventsSystem) if err != nil { return nil, err @@ -287,11 +285,11 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro if err != nil { return nil, err } - githookController := githook.ProvideController(authorizer, principalStore, repoStore, reporter2, reporter, gitInterface, pullReqStore, provider, protectionManager, clientFactory, resourceLimiter, settingsService, preReceiveExtender, updateExtender, postReceiveExtender, publicaccessService) + githookController := githook.ProvideController(authorizer, principalStore, repoStore, reporter2, reporter, gitInterface, pullReqStore, provider, protectionManager, clientFactory, resourceLimiter, settingsService, preReceiveExtender, updateExtender, postReceiveExtender) serviceaccountController := serviceaccount.NewController(principalUID, authorizer, principalStore, spaceStore, repoStore, tokenStore) principalController := principal.ProvideController(principalStore) v := check2.ProvideCheckSanitizers() - checkController := check2.ProvideController(transactor, authorizer, repoStore, checkStore, gitInterface, v, publicaccessService) + checkController := check2.ProvideController(transactor, authorizer, repoStore, checkStore, gitInterface, v) systemController := system.NewController(principalStore, config) blobConfig, err := server.ProvideBlobStoreConfig(config) if err != nil { @@ -301,7 +299,7 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro if err != nil { return nil, err } - uploadController := upload.ProvideController(authorizer, repoStore, blobStore, publicaccessService) + uploadController := upload.ProvideController(authorizer, repoStore, blobStore) searcher := keywordsearch.ProvideSearcher(localIndexSearcher) keywordsearchController := keywordsearch2.ProvideController(authorizer, searcher, repoController, spaceController) apiHandler := router.ProvideAPIHandler(ctx, config, authenticator, repoController, reposettingsController, executionController, logsController, spaceController, pipelineController, secretController, triggerController, connectorController, templateController, pluginController, pullreqController, webhookController, githookController, gitInterface, serviceaccountController, controller, principalController, checkController, systemController, uploadController, keywordsearchController) diff --git a/types/enum/public_resource.go b/types/enum/public_resource.go index 90a11150dd..19dc89e9d0 100644 --- a/types/enum/public_resource.go +++ b/types/enum/public_resource.go @@ -21,13 +21,13 @@ func (PublicResourceType) Enum() []interface{} { } var ( - PublicResourceTypeRepository PublicResourceType = "repository" - PublicResourceTypeSpace PublicResourceType = "space" + PublicResourceTypeRepo PublicResourceType = "repository" + PublicResourceTypeSpace PublicResourceType = "space" ) func GetAllPublicResourceTypes() []PublicResourceType { return []PublicResourceType{ - PublicResourceTypeRepository, + PublicResourceTypeRepo, PublicResourceTypeSpace, } } diff --git a/types/public_resource.go b/types/public_resource.go index 673afdf436..226277b1e2 100644 --- a/types/public_resource.go +++ b/types/public_resource.go @@ -18,6 +18,6 @@ import "github.com/harness/gitness/types/enum" // PublicResource defines a public resource info. type PublicResource struct { - Type enum.PublicResourceType - ResourceID int64 + Type enum.PublicResourceType + ID int64 } From 3d5fb186c49a13d63bddfa2703e8e7986aad8e60 Mon Sep 17 00:00:00 2001 From: atefeh Date: Fri, 26 Apr 2024 18:50:00 -0700 Subject: [PATCH 05/31] update audit logs to include repo is-public --- app/api/controller/repo/controller.go | 12 ++++++ app/api/controller/repo/create.go | 19 +++++----- app/api/controller/repo/default_branch.go | 24 +++++++----- ...lity_update.go => public_access_update.go} | 37 ++++++++++++++----- app/api/controller/repo/rule_create.go | 4 +- app/api/controller/repo/rule_delete.go | 4 +- app/api/controller/repo/rule_update.go | 4 +- app/api/controller/repo/soft_delete.go | 10 ++++- app/api/controller/repo/update.go | 28 +++++++------- ...lity_update.go => public_access_update.go} | 6 +-- app/router/api.go | 2 +- types/repo.go | 11 ------ 12 files changed, 98 insertions(+), 63 deletions(-) rename app/api/controller/repo/{visibility_update.go => public_access_update.go} (61%) rename app/api/handler/repo/{visibility_update.go => public_access_update.go} (87%) diff --git a/app/api/controller/repo/controller.go b/app/api/controller/repo/controller.go index 20679edf0d..6d64f24d70 100644 --- a/app/api/controller/repo/controller.go +++ b/app/api/controller/repo/controller.go @@ -53,6 +53,18 @@ type Repository struct { IsPublic bool `json:"is_public"` } +// Clone makes deep copy of repository object. +func (r Repository) Clone() Repository { + var deleted *int64 + if r.Repository.Deleted != nil { + id := *r.Repository.Deleted + deleted = &id + } + r.Repository.Deleted = deleted + + return r +} + type Controller struct { defaultBranch string publicResourceCreationEnabled bool diff --git a/app/api/controller/repo/create.go b/app/api/controller/repo/create.go index 37eb5fc388..dc37fc8ddc 100644 --- a/app/api/controller/repo/create.go +++ b/app/api/controller/repo/create.go @@ -35,7 +35,6 @@ import ( "github.com/harness/gitness/types" "github.com/harness/gitness/types/check" "github.com/harness/gitness/types/enum" - "github.com/pkg/errors" "github.com/rs/zerolog/log" ) @@ -129,20 +128,25 @@ func (c *Controller) Create(ctx context.Context, session *auth.Session, in *Crea return nil, err } + // backfil GitURL + repo.GitURL = c.urlProvider.GenerateGITCloneURL(repo.Path) + + repoData := &Repository{ + Repository: *repo, + IsPublic: in.IsPublic, + } + err = c.auditService.Log(ctx, session.Principal, audit.NewResource(audit.ResourceTypeRepository, repo.Identifier), audit.ActionCreated, paths.Space(repo.Path), - audit.WithNewObject(repo), + audit.WithNewObject(repoData), ) if err != nil { log.Ctx(ctx).Warn().Msgf("failed to insert audit log for create repository operation: %s", err) } - // backfil GitURL - repo.GitURL = c.urlProvider.GenerateGITCloneURL(repo.Path) - // index repository if files are created if !repo.IsEmpty { err = c.indexer.Index(ctx, repo) @@ -151,10 +155,7 @@ func (c *Controller) Create(ctx context.Context, session *auth.Session, in *Crea } } - return &Repository{ - Repository: *repo, - IsPublic: in.IsPublic, - }, nil + return repoData, nil } func (c *Controller) getSpaceCheckAuthRepoCreation( diff --git a/app/api/controller/repo/default_branch.go b/app/api/controller/repo/default_branch.go index dc92d22c2c..5e8e1d1095 100644 --- a/app/api/controller/repo/default_branch.go +++ b/app/api/controller/repo/default_branch.go @@ -48,7 +48,9 @@ func (c *Controller) UpdateDefaultBranch( if err != nil { return nil, err } + repoClone := repo.Clone() + // the max time we give an update default branch to succeed const timeout = 2 * time.Minute @@ -56,7 +58,7 @@ func (c *Controller) UpdateDefaultBranch( // requests will wait for previous ones to compelete before proceed unlock, err := c.locker.LockDefaultBranch( ctx, - repo.ID, + repo.Repository.ID, in.Name, // branch name only used for logging (lock is on repo) timeout+30*time.Second, // add 30s to the lock to give enough time for updating default branch ) @@ -86,7 +88,7 @@ func (c *Controller) UpdateDefaultBranch( return nil, fmt.Errorf("failed to update the repo default branch: %w", err) } - oldName := repo.DefaultBranch + oldName := repo.Repository.DefaultBranch repoBase, err := c.repoStore.UpdateOptLock(ctx, &repo.Repository, func(r *types.Repository) error { r.DefaultBranch = in.Name return nil @@ -95,11 +97,16 @@ func (c *Controller) UpdateDefaultBranch( return nil, fmt.Errorf("failed to update the repo default branch on db:%w", err) } + repo = &Repository{ + Repository: *repoBase, + IsPublic: repo.IsPublic, + } + err = c.auditService.Log(ctx, session.Principal, - audit.NewResource(audit.ResourceTypeRepository, repo.Identifier), + audit.NewResource(audit.ResourceTypeRepository, repo.Repository.Identifier), audit.ActionUpdated, - paths.Space(repo.Path), + paths.Space(repo.Repository.Path), audit.WithOldObject(repoClone), audit.WithNewObject(repo), ) @@ -108,14 +115,11 @@ func (c *Controller) UpdateDefaultBranch( } c.eventReporter.DefaultBranchUpdated(ctx, &repoevents.DefaultBranchUpdatedPayload{ - RepoID: repo.ID, + RepoID: repoBase.ID, PrincipalID: bootstrap.NewSystemServiceSession().Principal.ID, OldName: oldName, - NewName: repo.DefaultBranch, + NewName: repoBase.DefaultBranch, }) - return &Repository{ - Repository: *repoBase, - IsPublic: repo.IsPublic, - }, nil + return repo, nil } diff --git a/app/api/controller/repo/visibility_update.go b/app/api/controller/repo/public_access_update.go similarity index 61% rename from app/api/controller/repo/visibility_update.go rename to app/api/controller/repo/public_access_update.go index 07bdacb044..5c563b01d0 100644 --- a/app/api/controller/repo/visibility_update.go +++ b/app/api/controller/repo/public_access_update.go @@ -20,35 +20,39 @@ import ( "github.com/harness/gitness/app/auth" "github.com/harness/gitness/app/paths" + "github.com/harness/gitness/audit" "github.com/harness/gitness/types" "github.com/harness/gitness/types/enum" + "github.com/rs/zerolog/log" ) -type VisibilityInput struct { +type PublicAccessUpdateInput struct { EnablePublic bool `json:"enable_public"` } -type VisibilityOutput struct { +type PublicAccessUpdateOutput struct { IsPublic bool `json:"is_public"` } -func (c *Controller) VisibilityUpdate(ctx context.Context, +func (c *Controller) PublicAccessUpdate(ctx context.Context, session *auth.Session, repoRef string, - in *VisibilityInput, -) (*VisibilityOutput, error) { + in *PublicAccessUpdateInput, +) (*PublicAccessUpdateOutput, error) { repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoEdit) if err != nil { return nil, err } + repoClone := repo.Clone() + if err = c.sanitizeVisibilityInput(in); err != nil { return nil, fmt.Errorf("failed to sanitize input: %w", err) } - parentSpace, name, err := paths.DisectLeaf(repo.Path) + parentSpace, name, err := paths.DisectLeaf(repo.Repository.Path) if err != nil { - return nil, fmt.Errorf("Failed to disect path '%s': %w", repo.Path, err) + return nil, fmt.Errorf("failed to disect path '%s': %w", repo.Repository.Path, err) } scope := &types.Scope{SpacePath: parentSpace} @@ -61,13 +65,28 @@ func (c *Controller) VisibilityUpdate(ctx context.Context, return nil, fmt.Errorf("failed to set public access: %w", err) } - return &VisibilityOutput{ + err = c.auditService.Log(ctx, + session.Principal, + audit.NewResource(audit.ResourceTypeRepository, repo.Repository.Identifier), + audit.ActionUpdated, + paths.Space(repo.Repository.Path), + audit.WithOldObject(repoClone), + audit.WithNewObject(&Repository{ + Repository: repo.Repository, + IsPublic: in.EnablePublic, + }), + ) + if err != nil { + log.Ctx(ctx).Warn().Msgf("failed to insert audit log for update repository operation: %s", err) + } + + return &PublicAccessUpdateOutput{ in.EnablePublic, }, nil } -func (c *Controller) sanitizeVisibilityInput(in *VisibilityInput) error { +func (c *Controller) sanitizeVisibilityInput(in *PublicAccessUpdateInput) error { if in.EnablePublic && !c.publicResourceCreationEnabled { return errPublicRepoCreationDisabled } diff --git a/app/api/controller/repo/rule_create.go b/app/api/controller/repo/rule_create.go index d7c8744584..fa765a8899 100644 --- a/app/api/controller/repo/rule_create.go +++ b/app/api/controller/repo/rule_create.go @@ -100,7 +100,7 @@ func (c *Controller) RuleCreate(ctx context.Context, CreatedBy: session.Principal.ID, Created: now, Updated: now, - RepoID: &repo.ID, + RepoID: &repo.Repository.ID, SpaceID: nil, Type: in.Type, State: in.State, @@ -120,7 +120,7 @@ func (c *Controller) RuleCreate(ctx context.Context, session.Principal, audit.NewResource(audit.ResourceTypeBranchRule, r.Identifier), audit.ActionCreated, - paths.Space(repo.Path), + paths.Space(repo.Repository.Path), audit.WithNewObject(r), ) if err != nil { diff --git a/app/api/controller/repo/rule_delete.go b/app/api/controller/repo/rule_delete.go index 05bc812a85..919d1bbe7b 100644 --- a/app/api/controller/repo/rule_delete.go +++ b/app/api/controller/repo/rule_delete.go @@ -37,7 +37,7 @@ func (c *Controller) RuleDelete(ctx context.Context, return err } - r, err := c.ruleStore.FindByIdentifier(ctx, nil, &repo.ID, identifier) + r, err := c.ruleStore.FindByIdentifier(ctx, nil, &repo.Repository.ID, identifier) if err != nil { return fmt.Errorf("failed to find repository-level protection rule by identifier: %w", err) } @@ -51,7 +51,7 @@ func (c *Controller) RuleDelete(ctx context.Context, session.Principal, audit.NewResource(audit.ResourceTypeBranchRule, r.Identifier), audit.ActionDeleted, - paths.Space(repo.Path), + paths.Space(repo.Repository.Path), audit.WithOldObject(r), ) if err != nil { diff --git a/app/api/controller/repo/rule_update.go b/app/api/controller/repo/rule_update.go index 84e2145cac..c7bd19584e 100644 --- a/app/api/controller/repo/rule_update.go +++ b/app/api/controller/repo/rule_update.go @@ -96,7 +96,7 @@ func (c *Controller) RuleUpdate(ctx context.Context, return nil, err } - r, err := c.ruleStore.FindByIdentifier(ctx, nil, &repo.ID, identifier) + r, err := c.ruleStore.FindByIdentifier(ctx, nil, &repo.Repository.ID, identifier) if err != nil { return nil, fmt.Errorf("failed to get a repository rule by its identifier: %w", err) } @@ -142,7 +142,7 @@ func (c *Controller) RuleUpdate(ctx context.Context, session.Principal, audit.NewResource(audit.ResourceTypeBranchRule, r.Identifier), audit.ActionUpdated, - paths.Space(repo.Path), + paths.Space(repo.Repository.Path), audit.WithOldObject(oldRule), audit.WithNewObject(r), ) diff --git a/app/api/controller/repo/soft_delete.go b/app/api/controller/repo/soft_delete.go index 6a1aefdc70..ebf8b85b82 100644 --- a/app/api/controller/repo/soft_delete.go +++ b/app/api/controller/repo/soft_delete.go @@ -64,12 +64,20 @@ func (c *Controller) SoftDelete( return nil, fmt.Errorf("failed to soft delete repo: %w", err) } + isPublic, err := apiauth.CheckRepoIsPublic(ctx, c.publicAccess, repo) + if err != nil { + log.Ctx(ctx).Warn().Msgf("failed to check repo public access for audit logs: %s", err) + } + err = c.auditService.Log(ctx, session.Principal, audit.NewResource(audit.ResourceTypeRepository, repo.Identifier), audit.ActionDeleted, paths.Space(repo.Path), - audit.WithOldObject(repo), + audit.WithOldObject(&Repository{ + Repository: *repo, + IsPublic: isPublic, + }), ) if err != nil { log.Ctx(ctx).Warn().Msgf("failed to insert audit log for delete repository operation: %s", err) diff --git a/app/api/controller/repo/update.go b/app/api/controller/repo/update.go index 92e4572461..d49ee65008 100644 --- a/app/api/controller/repo/update.go +++ b/app/api/controller/repo/update.go @@ -72,11 +72,23 @@ func (c *Controller) Update(ctx context.Context, return nil, err } + // backfill repo url + repo.Repository.GitURL = c.urlProvider.GenerateGITCloneURL(repo.Repository.Path) + isPublic, err := apiauth.CheckRepoIsPublic(ctx, c.publicAccess, repoBase) + if err != nil { + return nil, fmt.Errorf("failed to get resource public access mode: %w", err) + } + + repo = &Repository{ + Repository: *repoBase, + IsPublic: isPublic, + } + err = c.auditService.Log(ctx, session.Principal, - audit.NewResource(audit.ResourceTypeRepository, repo.Identifier), + audit.NewResource(audit.ResourceTypeRepository, repo.Repository.Identifier), audit.ActionUpdated, - paths.Space(repo.Path), + paths.Space(repo.Repository.Path), audit.WithOldObject(repoClone), audit.WithNewObject(repo), ) @@ -84,17 +96,7 @@ func (c *Controller) Update(ctx context.Context, log.Ctx(ctx).Warn().Msgf("failed to insert audit log for update repository operation: %s", err) } - // backfill repo url - repo.GitURL = c.urlProvider.GenerateGITCloneURL(repo.Path) - isPublic, err := apiauth.CheckRepoIsPublic(ctx, c.publicAccess, repoBase) - if err != nil { - return nil, fmt.Errorf("failed to get resource public access mode: %w", err) - } - - return &Repository{ - Repository: *repoBase, - IsPublic: isPublic, - }, nil + return repo, nil } func (c *Controller) sanitizeUpdateInput(in *UpdateInput) error { diff --git a/app/api/handler/repo/visibility_update.go b/app/api/handler/repo/public_access_update.go similarity index 87% rename from app/api/handler/repo/visibility_update.go rename to app/api/handler/repo/public_access_update.go index a20ba23eed..f6a6b1dbc2 100644 --- a/app/api/handler/repo/visibility_update.go +++ b/app/api/handler/repo/public_access_update.go @@ -23,7 +23,7 @@ import ( "github.com/harness/gitness/app/api/request" ) -func HandleVisibilityUpdate(repoCtrl *repo.Controller) http.HandlerFunc { +func HandlePublicAccessUpdate(repoCtrl *repo.Controller) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { ctx := r.Context() session, _ := request.AuthSessionFrom(ctx) @@ -34,14 +34,14 @@ func HandleVisibilityUpdate(repoCtrl *repo.Controller) http.HandlerFunc { return } - in := new(repo.VisibilityInput) + in := new(repo.PublicAccessUpdateInput) err = json.NewDecoder(r.Body).Decode(in) if err != nil { render.BadRequestf(ctx, w, "Invalid Request Body: %s.", err) return } - res, err := repoCtrl.VisibilityUpdate(ctx, session, repoRef, in) + res, err := repoCtrl.PublicAccessUpdate(ctx, session, repoRef, in) if err != nil { render.TranslatedUserError(ctx, w, err) return diff --git a/app/router/api.go b/app/router/api.go index 9ccd90a4b8..96b8a56696 100644 --- a/app/router/api.go +++ b/app/router/api.go @@ -276,7 +276,7 @@ func setupRepos(r chi.Router, r.Delete("/", handlerrepo.HandleSoftDelete(repoCtrl)) r.Post("/purge", handlerrepo.HandlePurge(repoCtrl)) r.Post("/restore", handlerrepo.HandleRestore(repoCtrl)) - r.Patch("/visibility", handlerrepo.HandleVisibilityUpdate(repoCtrl)) + r.Post("/public-access", handlerrepo.HandlePublicAccessUpdate(repoCtrl)) r.Get("/settings/security", handlerreposettings.HandleSecurityFind(repoSettingsCtrl)) r.Patch("/settings/security", handlerreposettings.HandleSecurityUpdate(repoSettingsCtrl)) diff --git a/types/repo.go b/types/repo.go index fe28769047..7800ec093b 100644 --- a/types/repo.go +++ b/types/repo.go @@ -55,17 +55,6 @@ type Repository struct { GitURL string `json:"git_url" yaml:"git_url"` } -// Clone makes deep copy of repository object. -func (r Repository) Clone() Repository { - var deleted *int64 - if r.Deleted != nil { - id := *r.Deleted - deleted = &id - } - r.Deleted = deleted - return r -} - // TODO [CODE-1363]: remove after identifier migration. func (r Repository) MarshalJSON() ([]byte, error) { // alias allows us to embed the original object while avoiding an infinite loop of marshaling. From 86ee2d0dd2be50d70c3946a35260f0e2d34cdb90 Mon Sep 17 00:00:00 2001 From: atefeh Date: Tue, 30 Apr 2024 13:46:16 -0700 Subject: [PATCH 06/31] update pipelien manager and executor with repoCtrl repository type. fixed permissions --- app/api/auth/auth.go | 4 -- app/api/controller/pullreq/comment_update.go | 2 +- app/api/controller/pullreq/pr_create.go | 2 +- app/api/controller/pullreq/reviewer_delete.go | 2 +- app/api/controller/repo/blame.go | 4 +- app/api/controller/repo/codeowner_validate.go | 2 +- app/api/controller/repo/content_get.go | 4 +- .../controller/repo/content_paths_details.go | 4 +- app/api/controller/repo/create_branch.go | 2 +- app/api/controller/repo/create_commit_tag.go | 2 +- app/api/controller/repo/delete_branch.go | 2 +- app/api/controller/repo/diff.go | 4 +- app/api/controller/repo/get_branch.go | 2 +- app/api/controller/repo/get_commit.go | 2 +- .../controller/repo/get_commit_divergences.go | 4 +- app/api/controller/repo/git_info_refs.go | 2 +- app/api/controller/repo/git_service_pack.go | 2 +- app/api/controller/repo/import.go | 3 +- app/api/controller/repo/list_branches.go | 2 +- app/api/controller/repo/list_commit_tags.go | 2 +- app/api/controller/repo/list_commits.go | 4 +- app/api/controller/repo/list_pipelines.go | 8 ++-- .../controller/repo/list_service_accounts.go | 4 +- app/api/controller/repo/pipeline_generate.go | 2 +- app/api/controller/repo/raw.go | 4 +- app/api/controller/repo/rule_find.go | 2 +- app/api/controller/repo/rule_list.go | 4 +- app/pipeline/converter/jsonnet/jsonnet.go | 26 +++++------ app/pipeline/converter/service.go | 9 ++-- app/pipeline/converter/starlark/args.go | 22 +++++----- app/pipeline/converter/starlark/starlark.go | 7 +-- app/pipeline/file/gitness.go | 6 +-- app/pipeline/file/service.go | 4 +- app/pipeline/manager/convert.go | 25 ++++++----- app/pipeline/manager/manager.go | 44 +++++++++++++------ app/pipeline/manager/wire.go | 7 ++- app/pipeline/triggerer/env.go | 5 ++- app/pipeline/triggerer/trigger.go | 28 +++++++++--- app/pipeline/triggerer/wire.go | 4 +- app/services/exporter/repository.go | 8 ++-- cmd/gitness/wire_gen.go | 4 +- 41 files changed, 161 insertions(+), 119 deletions(-) diff --git a/app/api/auth/auth.go b/app/api/auth/auth.go index c7a0d4bb12..8569e312a2 100644 --- a/app/api/auth/auth.go +++ b/app/api/auth/auth.go @@ -42,10 +42,6 @@ var ( func Check(ctx context.Context, authorizer authz.Authorizer, session *auth.Session, scope *types.Scope, resource *types.Resource, permission enum.Permission, ) error { - if session == nil { - return ErrNotAuthenticated - } - authorized, err := authorizer.Check( ctx, session, diff --git a/app/api/controller/pullreq/comment_update.go b/app/api/controller/pullreq/comment_update.go index 4ffd6f6320..fc8c3061f9 100644 --- a/app/api/controller/pullreq/comment_update.go +++ b/app/api/controller/pullreq/comment_update.go @@ -48,7 +48,7 @@ func (c *Controller) CommentUpdate( commentID int64, in *CommentUpdateInput, ) (*types.PullReqActivity, error) { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoReview) if err != nil { return nil, fmt.Errorf("failed to acquire access to repo: %w", err) } diff --git a/app/api/controller/pullreq/pr_create.go b/app/api/controller/pullreq/pr_create.go index 15b4fc1160..fc4fdb344c 100644 --- a/app/api/controller/pullreq/pr_create.go +++ b/app/api/controller/pullreq/pr_create.go @@ -60,7 +60,7 @@ func (c *Controller) Create( sourceRepo := targetRepo if in.SourceRepoRef != "" { - sourceRepo, err = c.getRepoCheckAccess(ctx, session, in.SourceRepoRef, enum.PermissionRepoReview) + sourceRepo, err = c.getRepoCheckAccess(ctx, session, in.SourceRepoRef, enum.PermissionRepoPush) if err != nil { return nil, fmt.Errorf("failed to acquire access to source repo: %w", err) } diff --git a/app/api/controller/pullreq/reviewer_delete.go b/app/api/controller/pullreq/reviewer_delete.go index f31173fe1e..e2c4a4760c 100644 --- a/app/api/controller/pullreq/reviewer_delete.go +++ b/app/api/controller/pullreq/reviewer_delete.go @@ -25,7 +25,7 @@ import ( // ReviewerDelete deletes reviewer from the reviewerlist for the given PR. func (c *Controller) ReviewerDelete(ctx context.Context, session *auth.Session, repoRef string, prNum, reviewerID int64) error { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoEdit) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoPush) if err != nil { return fmt.Errorf("failed to acquire access to repo: %w", err) } diff --git a/app/api/controller/repo/blame.go b/app/api/controller/repo/blame.go index 585f3ab21a..cd985f16ab 100644 --- a/app/api/controller/repo/blame.go +++ b/app/api/controller/repo/blame.go @@ -45,12 +45,12 @@ func (c *Controller) Blame(ctx context.Context, } if gitRef == "" { - gitRef = repo.DefaultBranch + gitRef = repo.Repository.DefaultBranch } reader := git.NewStreamReader( c.git.Blame(ctx, &git.BlameParams{ - ReadParams: git.CreateReadParams(repo), + ReadParams: git.CreateReadParams(&repo.Repository), GitRef: gitRef, Path: path, LineFrom: lineFrom, diff --git a/app/api/controller/repo/codeowner_validate.go b/app/api/controller/repo/codeowner_validate.go index 6f65caed75..4235b83ba3 100644 --- a/app/api/controller/repo/codeowner_validate.go +++ b/app/api/controller/repo/codeowner_validate.go @@ -34,7 +34,7 @@ func (c *Controller) CodeOwnersValidate( } if ref == "" { - ref = repo.DefaultBranch + ref = repo.Repository.DefaultBranch } violations, err := c.codeOwners.Validate(ctx, &repo.Repository, ref) diff --git a/app/api/controller/repo/content_get.go b/app/api/controller/repo/content_get.go index 576a93d4c7..6623d2b5bf 100644 --- a/app/api/controller/repo/content_get.go +++ b/app/api/controller/repo/content_get.go @@ -108,11 +108,11 @@ func (c *Controller) GetContent(ctx context.Context, // set gitRef to default branch in case an empty reference was provided if gitRef == "" { - gitRef = repo.DefaultBranch + gitRef = repo.Repository.DefaultBranch } // create read params once - readParams := git.CreateReadParams(repo) + readParams := git.CreateReadParams(&repo.Repository) treeNodeOutput, err := c.git.GetTreeNode(ctx, &git.GetTreeNodeParams{ ReadParams: readParams, diff --git a/app/api/controller/repo/content_paths_details.go b/app/api/controller/repo/content_paths_details.go index d75d4e6783..d98bf35045 100644 --- a/app/api/controller/repo/content_paths_details.go +++ b/app/api/controller/repo/content_paths_details.go @@ -56,11 +56,11 @@ func (c *Controller) PathsDetails(ctx context.Context, // set gitRef to default branch in case an empty reference was provided if gitRef == "" { - gitRef = repo.DefaultBranch + gitRef = repo.Repository.DefaultBranch } result, err := c.git.PathsDetails(ctx, git.PathsDetailsParams{ - ReadParams: git.CreateReadParams(repo), + ReadParams: git.CreateReadParams(&repo.Repository), GitREF: gitRef, Paths: input.Paths, }) diff --git a/app/api/controller/repo/create_branch.go b/app/api/controller/repo/create_branch.go index 6a2f6c6895..7c74cdce2b 100644 --- a/app/api/controller/repo/create_branch.go +++ b/app/api/controller/repo/create_branch.go @@ -50,7 +50,7 @@ func (c *Controller) CreateBranch(ctx context.Context, // set target to default branch in case no target was provided if in.Target == "" { - in.Target = repo.DefaultBranch + in.Target = repo.Repository.DefaultBranch } rules, isRepoOwner, err := c.fetchRules(ctx, session, &repo.Repository) diff --git a/app/api/controller/repo/create_commit_tag.go b/app/api/controller/repo/create_commit_tag.go index 0424d4d665..399cc57137 100644 --- a/app/api/controller/repo/create_commit_tag.go +++ b/app/api/controller/repo/create_commit_tag.go @@ -54,7 +54,7 @@ func (c *Controller) CreateCommitTag(ctx context.Context, // set target to default branch in case no branch or commit was provided if in.Target == "" { - in.Target = repo.DefaultBranch + in.Target = repo.Repository.DefaultBranch } rules, isRepoOwner, err := c.fetchRules(ctx, session, &repo.Repository) diff --git a/app/api/controller/repo/delete_branch.go b/app/api/controller/repo/delete_branch.go index ca2f17a7c9..a368d6c235 100644 --- a/app/api/controller/repo/delete_branch.go +++ b/app/api/controller/repo/delete_branch.go @@ -43,7 +43,7 @@ func (c *Controller) DeleteBranch(ctx context.Context, // ASSUMPTION: lower layer calls explicit branch api // and 'refs/heads/branch1' would fail if 'branch1' exists. // TODO: Add functional test to ensure the scenario is covered! - if branchName == repo.DefaultBranch { + if branchName == repo.Repository.DefaultBranch { return nil, usererror.ErrDefaultBranchCantBeDeleted } diff --git a/app/api/controller/repo/diff.go b/app/api/controller/repo/diff.go index 4bfb72e439..69ad745df3 100644 --- a/app/api/controller/repo/diff.go +++ b/app/api/controller/repo/diff.go @@ -47,7 +47,7 @@ func (c *Controller) RawDiff( } return c.git.RawDiff(ctx, w, &git.DiffParams{ - ReadParams: git.CreateReadParams(repo), + ReadParams: git.CreateReadParams(&repo.Repository), BaseRef: info.BaseRef, HeadRef: info.HeadRef, MergeBase: info.MergeBase, @@ -67,7 +67,7 @@ func (c *Controller) CommitDiff( } return c.git.CommitDiff(ctx, &git.GetCommitParams{ - ReadParams: git.CreateReadParams(repo), + ReadParams: git.CreateReadParams(&repo.Repository), Revision: rev, }, w) } diff --git a/app/api/controller/repo/get_branch.go b/app/api/controller/repo/get_branch.go index a1a06521fb..427c56c4c9 100644 --- a/app/api/controller/repo/get_branch.go +++ b/app/api/controller/repo/get_branch.go @@ -35,7 +35,7 @@ func (c *Controller) GetBranch(ctx context.Context, } rpcOut, err := c.git.GetBranch(ctx, &git.GetBranchParams{ - ReadParams: git.CreateReadParams(repo), + ReadParams: git.CreateReadParams(&repo.Repository), BranchName: branchName, }) if err != nil { diff --git a/app/api/controller/repo/get_commit.go b/app/api/controller/repo/get_commit.go index ede7f7c4a8..a710e65a6c 100644 --- a/app/api/controller/repo/get_commit.go +++ b/app/api/controller/repo/get_commit.go @@ -37,7 +37,7 @@ func (c *Controller) GetCommit(ctx context.Context, } rpcOut, err := c.git.GetCommit(ctx, &git.GetCommitParams{ - ReadParams: git.CreateReadParams(repo), + ReadParams: git.CreateReadParams(&repo.Repository), Revision: sha, }) if err != nil { diff --git a/app/api/controller/repo/get_commit_divergences.go b/app/api/controller/repo/get_commit_divergences.go index dad31b230e..dfc815eae3 100644 --- a/app/api/controller/repo/get_commit_divergences.go +++ b/app/api/controller/repo/get_commit_divergences.go @@ -71,7 +71,7 @@ func (c *Controller) GetCommitDivergences(ctx context.Context, // map to rpc params options := &git.GetCommitDivergencesParams{ - ReadParams: git.CreateReadParams(repo), + ReadParams: git.CreateReadParams(&repo.Repository), MaxCount: in.MaxCount, Requests: make([]git.CommitDivergenceRequest, len(in.Requests)), } @@ -80,7 +80,7 @@ func (c *Controller) GetCommitDivergences(ctx context.Context, options.Requests[i].To = in.Requests[i].To // backfil default branch if no 'to' was provided if len(options.Requests[i].To) == 0 { - options.Requests[i].To = repo.DefaultBranch + options.Requests[i].To = repo.Repository.DefaultBranch } } diff --git a/app/api/controller/repo/git_info_refs.go b/app/api/controller/repo/git_info_refs.go index 3d9fbe09fd..027f6851f0 100644 --- a/app/api/controller/repo/git_info_refs.go +++ b/app/api/controller/repo/git_info_refs.go @@ -39,7 +39,7 @@ func (c *Controller) GitInfoRefs( } if err = c.git.GetInfoRefs(ctx, w, &git.InfoRefsParams{ - ReadParams: git.CreateReadParams(repo), + ReadParams: git.CreateReadParams(&repo.Repository), // TODO: git shouldn't take a random string here, but instead have accepted enum values. Service: string(service), Options: nil, diff --git a/app/api/controller/repo/git_service_pack.go b/app/api/controller/repo/git_service_pack.go index 7debd35092..476424b97d 100644 --- a/app/api/controller/repo/git_service_pack.go +++ b/app/api/controller/repo/git_service_pack.go @@ -65,7 +65,7 @@ func (c *Controller) GitServicePack( } params.WriteParams = &writeParams } else { - readParams := git.CreateReadParams(repo) + readParams := git.CreateReadParams(&repo.Repository) params.ReadParams = &readParams } diff --git a/app/api/controller/repo/import.go b/app/api/controller/repo/import.go index d7f63ed941..3153c1be4b 100644 --- a/app/api/controller/repo/import.go +++ b/app/api/controller/repo/import.go @@ -100,7 +100,8 @@ func (c *Controller) Import(ctx context.Context, session *auth.Session, in *Impo return &Repository{ Repository: *repo, - IsPublic: isPublic}, nil + IsPublic: isPublic, + }, nil } func (c *Controller) sanitizeImportInput(in *ImportInput) error { diff --git a/app/api/controller/repo/list_branches.go b/app/api/controller/repo/list_branches.go index a464da158f..72fdce5a70 100644 --- a/app/api/controller/repo/list_branches.go +++ b/app/api/controller/repo/list_branches.go @@ -44,7 +44,7 @@ func (c *Controller) ListBranches(ctx context.Context, } rpcOut, err := c.git.ListBranches(ctx, &git.ListBranchesParams{ - ReadParams: git.CreateReadParams(repo), + ReadParams: git.CreateReadParams(&repo.Repository), IncludeCommit: includeCommit, Query: filter.Query, Sort: mapToRPCBranchSortOption(filter.Sort), diff --git a/app/api/controller/repo/list_commit_tags.go b/app/api/controller/repo/list_commit_tags.go index a4e0320e14..6c60317e30 100644 --- a/app/api/controller/repo/list_commit_tags.go +++ b/app/api/controller/repo/list_commit_tags.go @@ -48,7 +48,7 @@ func (c *Controller) ListCommitTags(ctx context.Context, } rpcOut, err := c.git.ListCommitTags(ctx, &git.ListCommitTagsParams{ - ReadParams: git.CreateReadParams(repo), + ReadParams: git.CreateReadParams(&repo.Repository), IncludeCommit: includeCommit, Query: filter.Query, Sort: mapToRPCTagSortOption(filter.Sort), diff --git a/app/api/controller/repo/list_commits.go b/app/api/controller/repo/list_commits.go index 44a5f82bdf..923aa2f7df 100644 --- a/app/api/controller/repo/list_commits.go +++ b/app/api/controller/repo/list_commits.go @@ -39,11 +39,11 @@ func (c *Controller) ListCommits(ctx context.Context, // set gitRef to default branch in case an empty reference was provided if gitRef == "" { - gitRef = repo.DefaultBranch + gitRef = repo.Repository.DefaultBranch } rpcOut, err := c.git.ListCommits(ctx, &git.ListCommitsParams{ - ReadParams: git.CreateReadParams(repo), + ReadParams: git.CreateReadParams(&repo.Repository), GitREF: gitRef, After: filter.After, Page: int32(filter.Page), diff --git a/app/api/controller/repo/list_pipelines.go b/app/api/controller/repo/list_pipelines.go index 95853668a7..8c1c2a16a0 100644 --- a/app/api/controller/repo/list_pipelines.go +++ b/app/api/controller/repo/list_pipelines.go @@ -37,7 +37,7 @@ func (c *Controller) ListPipelines( if err != nil { return nil, 0, fmt.Errorf("failed to find repo: %w", err) } - if err := apiauth.CheckPipeline(ctx, c.authorizer, session, repo.Path, "", enum.PermissionPipelineView); err != nil { + if err := apiauth.CheckPipeline(ctx, c.authorizer, session, repo.Repository.Path, "", enum.PermissionPipelineView); err != nil { return nil, 0, fmt.Errorf("access check failed: %w", err) } @@ -45,18 +45,18 @@ func (c *Controller) ListPipelines( var pipelines []*types.Pipeline err = c.tx.WithTx(ctx, func(ctx context.Context) (err error) { - count, err = c.pipelineStore.Count(ctx, repo.ID, filter) + count, err = c.pipelineStore.Count(ctx, repo.Repository.ID, filter) if err != nil { return fmt.Errorf("failed to count child executions: %w", err) } if !latest { - pipelines, err = c.pipelineStore.List(ctx, repo.ID, filter) + pipelines, err = c.pipelineStore.List(ctx, repo.Repository.ID, filter) if err != nil { return fmt.Errorf("failed to list pipelines: %w", err) } } else { - pipelines, err = c.pipelineStore.ListLatest(ctx, repo.ID, filter) + pipelines, err = c.pipelineStore.ListLatest(ctx, repo.Repository.ID, filter) if err != nil { return fmt.Errorf("failed to list latest pipelines: %w", err) } diff --git a/app/api/controller/repo/list_service_accounts.go b/app/api/controller/repo/list_service_accounts.go index 28c945741b..e21e9ccf76 100644 --- a/app/api/controller/repo/list_service_accounts.go +++ b/app/api/controller/repo/list_service_accounts.go @@ -42,12 +42,12 @@ func (c *Controller) ListServiceAccounts( c.spaceStore, c.repoStore, enum.ParentResourceTypeRepo, - repo.ID, + repo.Repository.ID, "", enum.PermissionServiceAccountView, ); err != nil { return nil, fmt.Errorf("access check failed: %w", err) } - return c.principalStore.ListServiceAccounts(ctx, enum.ParentResourceTypeRepo, repo.ID) + return c.principalStore.ListServiceAccounts(ctx, enum.ParentResourceTypeRepo, repo.Repository.ID) } diff --git a/app/api/controller/repo/pipeline_generate.go b/app/api/controller/repo/pipeline_generate.go index 65142dad3c..0c770ded73 100644 --- a/app/api/controller/repo/pipeline_generate.go +++ b/app/api/controller/repo/pipeline_generate.go @@ -35,7 +35,7 @@ func (c *Controller) PipelineGenerate( } result, err := c.git.GeneratePipeline(ctx, &git.GeneratePipelineParams{ - ReadParams: git.CreateReadParams(repo), + ReadParams: git.CreateReadParams(&repo.Repository), }) if err != nil { return nil, fmt.Errorf("failed to generate pipeline: %w", err) diff --git a/app/api/controller/repo/raw.go b/app/api/controller/repo/raw.go index 464adead03..7308764ef9 100644 --- a/app/api/controller/repo/raw.go +++ b/app/api/controller/repo/raw.go @@ -40,11 +40,11 @@ func (c *Controller) Raw(ctx context.Context, // set gitRef to default branch in case an empty reference was provided if gitRef == "" { - gitRef = repo.DefaultBranch + gitRef = repo.Repository.DefaultBranch } // create read params once - readParams := git.CreateReadParams(repo) + readParams := git.CreateReadParams(&repo.Repository) treeNodeOutput, err := c.git.GetTreeNode(ctx, &git.GetTreeNodeParams{ ReadParams: readParams, GitREF: gitRef, diff --git a/app/api/controller/repo/rule_find.go b/app/api/controller/repo/rule_find.go index 53d3949641..415bfec9ec 100644 --- a/app/api/controller/repo/rule_find.go +++ b/app/api/controller/repo/rule_find.go @@ -34,7 +34,7 @@ func (c *Controller) RuleFind(ctx context.Context, return nil, err } - r, err := c.ruleStore.FindByIdentifier(ctx, nil, &repo.ID, identifier) + r, err := c.ruleStore.FindByIdentifier(ctx, nil, &repo.Repository.ID, identifier) if err != nil { return nil, fmt.Errorf("failed to find repository-level protection rule by identifier: %w", err) } diff --git a/app/api/controller/repo/rule_list.go b/app/api/controller/repo/rule_list.go index 36a17652b3..904424ffe7 100644 --- a/app/api/controller/repo/rule_list.go +++ b/app/api/controller/repo/rule_list.go @@ -39,7 +39,7 @@ func (c *Controller) RuleList(ctx context.Context, var count int64 err = c.tx.WithTx(ctx, func(ctx context.Context) error { - list, err = c.ruleStore.List(ctx, nil, &repo.ID, filter) + list, err = c.ruleStore.List(ctx, nil, &repo.Repository.ID, filter) if err != nil { return fmt.Errorf("failed to list repository-level protection rules: %w", err) } @@ -49,7 +49,7 @@ func (c *Controller) RuleList(ctx context.Context, return nil } - count, err = c.ruleStore.Count(ctx, nil, &repo.ID, filter) + count, err = c.ruleStore.Count(ctx, nil, &repo.Repository.ID, filter) if err != nil { return fmt.Errorf("failed to count repository-level protection rules: %w", err) } diff --git a/app/pipeline/converter/jsonnet/jsonnet.go b/app/pipeline/converter/jsonnet/jsonnet.go index b0205a3eff..087babfd54 100644 --- a/app/pipeline/converter/jsonnet/jsonnet.go +++ b/app/pipeline/converter/jsonnet/jsonnet.go @@ -23,10 +23,10 @@ import ( "strconv" "strings" + "github.com/google/go-jsonnet" + repoCtrl "github.com/harness/gitness/app/api/controller/repo" "github.com/harness/gitness/app/pipeline/file" "github.com/harness/gitness/types" - - "github.com/google/go-jsonnet" ) const repo = "repo." @@ -36,7 +36,7 @@ const param = "param." var noContext = context.Background() type importer struct { - repo *types.Repository + repo *repoCtrl.Repository execution *types.Execution // jsonnet does not cache file imports and may request @@ -103,7 +103,7 @@ func (i *importer) Import(importedFrom, importedPath string) (contents jsonnet.C } func Parse( - repo *types.Repository, + repo *repoCtrl.Repository, pipeline *types.Pipeline, execution *types.Execution, file *file.File, @@ -188,22 +188,22 @@ func mapBuild(v *types.Execution, vm *jsonnet.VM) { // mapBuild populates repo level variables available to jsonnet templates. // Since we want to maintain compatibility with drone 2.x, the older format // needs to be maintained (even if the variables do not exist in gitness). -func mapRepo(v *types.Repository, p *types.Pipeline, vm *jsonnet.VM) { +func mapRepo(v *repoCtrl.Repository, p *types.Pipeline, vm *jsonnet.VM) { namespace := v.Path idx := strings.LastIndex(v.Path, "/") if idx != -1 { namespace = v.Path[:idx] } // TODO [CODE-1363]: remove after identifier migration. - vm.ExtVar(repo+"uid", v.Identifier) - vm.ExtVar(repo+"identifier", v.Identifier) - vm.ExtVar(repo+"name", v.Identifier) + vm.ExtVar(repo+"uid", v.Repository.Identifier) + vm.ExtVar(repo+"identifier", v.Repository.Identifier) + vm.ExtVar(repo+"name", v.Repository.Identifier) vm.ExtVar(repo+"namespace", namespace) - vm.ExtVar(repo+"slug", v.Path) - vm.ExtVar(repo+"git_http_url", v.GitURL) - vm.ExtVar(repo+"git_ssh_url", v.GitURL) - vm.ExtVar(repo+"link", v.GitURL) - vm.ExtVar(repo+"branch", v.DefaultBranch) + vm.ExtVar(repo+"slug", v.Repository.Path) + vm.ExtVar(repo+"git_http_url", v.Repository.GitURL) + vm.ExtVar(repo+"git_ssh_url", v.Repository.GitURL) + vm.ExtVar(repo+"link", v.Repository.GitURL) + vm.ExtVar(repo+"branch", v.Repository.DefaultBranch) vm.ExtVar(repo+"config", p.ConfigPath) vm.ExtVar(repo+"private", strconv.FormatBool(!v.IsPublic)) vm.ExtVar(repo+"visibility", "internal") diff --git a/app/pipeline/converter/service.go b/app/pipeline/converter/service.go index 7f84fb403c..6a4bcb5bae 100644 --- a/app/pipeline/converter/service.go +++ b/app/pipeline/converter/service.go @@ -17,6 +17,7 @@ package converter import ( "context" + "github.com/harness/gitness/app/api/controller/repo" "github.com/harness/gitness/app/pipeline/file" "github.com/harness/gitness/types" ) @@ -25,10 +26,10 @@ type ( // ConvertArgs represents a request to the pipeline // conversion service. ConvertArgs struct { - Repo *types.Repository `json:"repository,omitempty"` - Pipeline *types.Pipeline `json:"pipeline,omitempty"` - Execution *types.Execution `json:"execution,omitempty"` - File *file.File `json:"config,omitempty"` + Repo *repo.Repository `json:"repository,omitempty"` + Pipeline *types.Pipeline `json:"pipeline,omitempty"` + Execution *types.Execution `json:"execution,omitempty"` + File *file.File `json:"config,omitempty"` } // Service converts a file which is in starlark/jsonnet form by looking diff --git a/app/pipeline/converter/starlark/args.go b/app/pipeline/converter/starlark/args.go index c4465b875a..ec5b74872f 100644 --- a/app/pipeline/converter/starlark/args.go +++ b/app/pipeline/converter/starlark/args.go @@ -17,6 +17,7 @@ package starlark import ( "strings" + "github.com/harness/gitness/app/api/controller/repo" "github.com/harness/gitness/types" "go.starlark.net/starlark" @@ -24,7 +25,7 @@ import ( ) func createArgs( - repo *types.Repository, + repo *repo.Repository, pipeline *types.Pipeline, execution *types.Execution, ) []starlark.Value { @@ -66,23 +67,24 @@ func fromBuild(v *types.Execution) starlark.StringDict { } } -func fromRepo(v *types.Repository, p *types.Pipeline) starlark.StringDict { +func fromRepo(v *repo.Repository, p *types.Pipeline) starlark.StringDict { namespace := v.Path idx := strings.LastIndex(v.Path, "/") if idx != -1 { namespace = v.Path[:idx] } + return starlark.StringDict{ // TODO [CODE-1363]: remove after identifier migration? - "uid": starlark.String(v.Identifier), - "identifier": starlark.String(v.Identifier), - "name": starlark.String(v.Identifier), + "uid": starlark.String(v.Repository.Identifier), + "identifier": starlark.String(v.Repository.Identifier), + "name": starlark.String(v.Repository.Identifier), "namespace": starlark.String(namespace), - "slug": starlark.String(v.Path), - "git_http_url": starlark.String(v.GitURL), - "git_ssh_url": starlark.String(v.GitURL), - "link": starlark.String(v.GitURL), - "branch": starlark.String(v.DefaultBranch), + "slug": starlark.String(v.Repository.Path), + "git_http_url": starlark.String(v.Repository.GitURL), + "git_ssh_url": starlark.String(v.Repository.GitURL), + "link": starlark.String(v.Repository.GitURL), + "branch": starlark.String(v.Repository.DefaultBranch), "config": starlark.String(p.ConfigPath), "private": !starlark.Bool(v.IsPublic), "visibility": starlark.String("internal"), diff --git a/app/pipeline/converter/starlark/starlark.go b/app/pipeline/converter/starlark/starlark.go index 24c0442b9a..c49ed13034 100644 --- a/app/pipeline/converter/starlark/starlark.go +++ b/app/pipeline/converter/starlark/starlark.go @@ -18,6 +18,7 @@ import ( "bytes" "errors" + "github.com/harness/gitness/app/api/controller/repo" "github.com/harness/gitness/app/pipeline/file" "github.com/harness/gitness/types" @@ -56,7 +57,7 @@ var ( ) func Parse( - repo *types.Repository, + repo *repo.Repository, pipeline *types.Pipeline, execution *types.Execution, file *file.File, @@ -68,8 +69,8 @@ func Parse( Load: noLoad, Print: func(_ *starlark.Thread, msg string) { logrus.WithFields(logrus.Fields{ - "namespace": repo.Path, // TODO: update to just be the space - "name": repo.Identifier, + "namespace": repo.Repository.Path, // TODO: update to just be the space + "name": repo.Repository.Identifier, }).Traceln(msg) }, } diff --git a/app/pipeline/file/gitness.go b/app/pipeline/file/gitness.go index 8fa90b4c2f..5c13d8015f 100644 --- a/app/pipeline/file/gitness.go +++ b/app/pipeline/file/gitness.go @@ -19,8 +19,8 @@ import ( "fmt" "io" + "github.com/harness/gitness/app/api/controller/repo" "github.com/harness/gitness/git" - "github.com/harness/gitness/types" "github.com/rs/zerolog/log" ) @@ -35,12 +35,12 @@ func newService(git git.Interface) Service { func (f *service) Get( ctx context.Context, - repo *types.Repository, + repo *repo.Repository, path string, ref string, ) (*File, error) { readParams := git.ReadParams{ - RepoUID: repo.GitUID, + RepoUID: repo.Repository.GitUID, } treeNodeOutput, err := f.git.GetTreeNode(ctx, &git.GetTreeNodeParams{ ReadParams: readParams, diff --git a/app/pipeline/file/service.go b/app/pipeline/file/service.go index 00df8913b9..773e92f284 100644 --- a/app/pipeline/file/service.go +++ b/app/pipeline/file/service.go @@ -17,7 +17,7 @@ package file import ( "context" - "github.com/harness/gitness/types" + "github.com/harness/gitness/app/api/controller/repo" ) type ( @@ -36,6 +36,6 @@ type ( Service interface { // path is the path in the repo to read // ref is the git ref for the repository e.g. refs/heads/master - Get(ctx context.Context, repo *types.Repository, path, ref string) (*File, error) + Get(ctx context.Context, repo *repo.Repository, path, ref string) (*File, error) } ) diff --git a/app/pipeline/manager/convert.go b/app/pipeline/manager/convert.go index bf0394efac..824637c24c 100644 --- a/app/pipeline/manager/convert.go +++ b/app/pipeline/manager/convert.go @@ -17,6 +17,7 @@ package manager import ( "time" + "github.com/harness/gitness/app/api/controller/repo" "github.com/harness/gitness/app/pipeline/file" "github.com/harness/gitness/livelog" "github.com/harness/gitness/types" @@ -207,21 +208,21 @@ func ConvertToDroneBuild(execution *types.Execution) *drone.Build { } } -func ConvertToDroneRepo(repo *types.Repository) *drone.Repo { +func ConvertToDroneRepo(repo *repo.Repository) *drone.Repo { return &drone.Repo{ - ID: repo.ID, + ID: repo.Repository.ID, Trusted: true, // as builds are running on user machines, the repo is marked trusted. - UID: repo.Identifier, - UserID: repo.CreatedBy, - Namespace: repo.Path, - Name: repo.Identifier, - HTTPURL: repo.GitURL, - Link: repo.GitURL, + UID: repo.Repository.Identifier, + UserID: repo.Repository.CreatedBy, + Namespace: repo.Repository.Path, + Name: repo.Repository.Identifier, + HTTPURL: repo.Repository.GitURL, + Link: repo.Repository.GitURL, Private: !repo.IsPublic, - Created: repo.Created, - Updated: repo.Updated, - Version: repo.Version, - Branch: repo.DefaultBranch, + Created: repo.Repository.Created, + Updated: repo.Repository.Updated, + Version: repo.Repository.Version, + Branch: repo.Repository.DefaultBranch, // TODO: We can get this from configuration once we start populating it. // If this is not set drone runner cancels the build. Timeout: int64((10 * time.Hour).Seconds()), diff --git a/app/pipeline/manager/manager.go b/app/pipeline/manager/manager.go index 2dfdb2d547..089a937a45 100644 --- a/app/pipeline/manager/manager.go +++ b/app/pipeline/manager/manager.go @@ -22,11 +22,14 @@ import ( "net/url" "time" + apiauth "github.com/harness/gitness/app/api/auth" + "github.com/harness/gitness/app/api/controller/repo" "github.com/harness/gitness/app/bootstrap" "github.com/harness/gitness/app/jwt" "github.com/harness/gitness/app/pipeline/converter" "github.com/harness/gitness/app/pipeline/file" "github.com/harness/gitness/app/pipeline/scheduler" + "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/sse" "github.com/harness/gitness/app/store" urlprovider "github.com/harness/gitness/app/url" @@ -80,12 +83,12 @@ type ( // ExecutionContext represents the minimum amount of information // required by the runner to execute a build. ExecutionContext struct { - Repo *types.Repository `json:"repository"` - Execution *types.Execution `json:"build"` - Stage *types.Stage `json:"stage"` - Secrets []*types.Secret `json:"secrets"` - Config *file.File `json:"config"` - Netrc *Netrc `json:"netrc"` + Repo *repo.Repository `json:"repository"` + Execution *types.Execution `json:"build"` + Stage *types.Stage `json:"stage"` + Secrets []*types.Secret `json:"secrets"` + Config *file.File `json:"config"` + Netrc *Netrc `json:"netrc"` } // ExecutionManager encapsulates complex build operations and provides @@ -148,6 +151,8 @@ type Manager struct { // System *store.System Users store.PrincipalStore // Webhook store.WebhookSender + + publicAccess publicaccess.PublicAccess } func New( @@ -167,6 +172,7 @@ func New( stageStore store.StageStore, stepStore store.StepStore, userStore store.PrincipalStore, + publicAccess publicaccess.PublicAccess, ) *Manager { return &Manager{ Config: config, @@ -185,6 +191,7 @@ func New( Stages: stageStore, Steps: stepStore, Users: userStore, + publicAccess: publicAccess, } } @@ -295,13 +302,24 @@ func (m *Manager) Details(_ context.Context, stageID int64) (*ExecutionContext, log.Warn().Err(err).Msg("manager: cannot find pipeline") return nil, err } - repo, err := m.Repos.Find(noContext, execution.RepoID) + repoBase, err := m.Repos.Find(noContext, execution.RepoID) if err != nil { log.Warn().Err(err).Msg("manager: cannot find repo") return nil, err } + + isPublic, err := apiauth.CheckRepoIsPublic(noContext, m.publicAccess, repoBase) + if err != nil { + return nil, fmt.Errorf("failed to check if repo is public: %w", err) + } + + repo := &repo.Repository{ + Repository: *repoBase, + IsPublic: isPublic, + } + // Backfill clone URL - repo.GitURL = m.urlProvider.GenerateContainerGITCloneURL(repo.Path) + repo.Repository.GitURL = m.urlProvider.GenerateContainerGITCloneURL(repo.Repository.Path) stages, err := m.Stages.List(noContext, stage.ExecutionID) if err != nil { @@ -311,12 +329,12 @@ func (m *Manager) Details(_ context.Context, stageID int64) (*ExecutionContext, execution.Stages = stages log = log.With(). Int64("build", execution.Number). - Str("repo", repo.GetGitUID()). + Str("repo", repo.Repository.GetGitUID()). Logger() // TODO: Currently we fetch all the secrets from the same space. // This logic can be updated when needed. - secrets, err := m.Secrets.ListAll(noContext, repo.ParentID) + secrets, err := m.Secrets.ListAll(noContext, repo.Repository.ParentID) if err != nil { log.Warn().Err(err).Msg("manager: cannot list secrets") return nil, err @@ -358,11 +376,11 @@ func (m *Manager) Details(_ context.Context, stageID int64) (*ExecutionContext, }, nil } -func (m *Manager) createNetrc(repo *types.Repository) (*Netrc, error) { +func (m *Manager) createNetrc(repo *repo.Repository) (*Netrc, error) { pipelinePrincipal := bootstrap.NewPipelineServiceSession().Principal jwt, err := jwt.GenerateWithMembership( pipelinePrincipal.ID, - repo.ParentID, + repo.Repository.ParentID, pipelineJWTRole, pipelineJWTLifetime, pipelinePrincipal.Salt, @@ -371,7 +389,7 @@ func (m *Manager) createNetrc(repo *types.Repository) (*Netrc, error) { return nil, fmt.Errorf("failed to create jwt: %w", err) } - cloneURL, err := url.Parse(repo.GitURL) + cloneURL, err := url.Parse(repo.Repository.GitURL) if err != nil { return nil, fmt.Errorf("failed to parse clone url '%s': %w", cloneURL, err) } diff --git a/app/pipeline/manager/wire.go b/app/pipeline/manager/wire.go index 448deefd43..09c1e8196b 100644 --- a/app/pipeline/manager/wire.go +++ b/app/pipeline/manager/wire.go @@ -18,6 +18,7 @@ import ( "github.com/harness/gitness/app/pipeline/converter" "github.com/harness/gitness/app/pipeline/file" "github.com/harness/gitness/app/pipeline/scheduler" + "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/sse" "github.com/harness/gitness/app/store" "github.com/harness/gitness/app/url" @@ -51,9 +52,11 @@ func ProvideExecutionManager( secretStore store.SecretStore, stageStore store.StageStore, stepStore store.StepStore, - userStore store.PrincipalStore) ExecutionManager { + userStore store.PrincipalStore, + PublicAccess publicaccess.PublicAccess, +) ExecutionManager { return New(config, executionStore, pipelineStore, urlProvider, sseStreamer, fileService, converterService, - logStore, logStream, checkStore, repoStore, scheduler, secretStore, stageStore, stepStore, userStore) + logStore, logStream, checkStore, repoStore, scheduler, secretStore, stageStore, stepStore, userStore, PublicAccess) } // ProvideExecutionClient provides a client implementation to interact with the execution manager. diff --git a/app/pipeline/triggerer/env.go b/app/pipeline/triggerer/env.go index ee625c789b..4060e5eb72 100644 --- a/app/pipeline/triggerer/env.go +++ b/app/pipeline/triggerer/env.go @@ -15,6 +15,7 @@ package triggerer import ( + "github.com/harness/gitness/app/api/controller/repo" "github.com/harness/gitness/app/url" "github.com/harness/gitness/types" @@ -32,11 +33,11 @@ func combine(env ...map[string]string) map[string]string { } func Envs( - repo *types.Repository, + repo *repo.Repository, pipeline *types.Pipeline, urlProvider url.Provider, ) map[string]string { return map[string]string{ - "DRONE_BUILD_LINK": urlProvider.GenerateUIBuildURL(repo.Path, pipeline.Identifier, pipeline.Seq), + "DRONE_BUILD_LINK": urlProvider.GenerateUIBuildURL(repo.Repository.Path, pipeline.Identifier, pipeline.Seq), } } diff --git a/app/pipeline/triggerer/trigger.go b/app/pipeline/triggerer/trigger.go index 146b40f071..6cfc7d674c 100644 --- a/app/pipeline/triggerer/trigger.go +++ b/app/pipeline/triggerer/trigger.go @@ -28,12 +28,16 @@ import ( "github.com/harness/gitness/app/pipeline/resolver" "github.com/harness/gitness/app/pipeline/scheduler" "github.com/harness/gitness/app/pipeline/triggerer/dag" + "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/store" "github.com/harness/gitness/app/url" "github.com/harness/gitness/store/database/dbtx" "github.com/harness/gitness/types" "github.com/harness/gitness/types/enum" + apiauth "github.com/harness/gitness/app/api/auth" + "github.com/harness/gitness/app/api/controller/repo" + "github.com/drone-runners/drone-runner-docker/engine2/inputs" "github.com/drone-runners/drone-runner-docker/engine2/script" "github.com/drone/drone-yaml/yaml" @@ -92,6 +96,7 @@ type triggerer struct { repoStore store.RepoStore templateStore store.TemplateStore pluginStore store.PluginStore + publicAccess publicaccess.PublicAccess } func New( @@ -107,6 +112,7 @@ func New( converterService converter.Service, templateStore store.TemplateStore, pluginStore store.PluginStore, + publicAccess publicaccess.PublicAccess, ) Triggerer { return &triggerer{ executionStore: executionStore, @@ -121,6 +127,7 @@ func New( repoStore: repoStore, templateStore: templateStore, pluginStore: pluginStore, + publicAccess: publicAccess, } } @@ -148,11 +155,20 @@ func (t *triggerer) Trigger( event := string(base.Action.GetTriggerEvent()) - repo, err := t.repoStore.Find(ctx, pipeline.RepoID) + repoBase, err := t.repoStore.Find(ctx, pipeline.RepoID) if err != nil { log.Error().Err(err).Msg("could not find repo") return nil, err } + isPublic, err := apiauth.CheckRepoIsPublic(ctx, t.publicAccess, repoBase) + if err != nil { + return nil, fmt.Errorf("failed to check if repo is public: %w", err) + } + + repo := &repo.Repository{ + Repository: *repoBase, + IsPublic: isPublic, + } file, err := t.fileService.Get(ctx, repo, pipeline.ConfigPath, base.After) if err != nil { @@ -162,7 +178,7 @@ func (t *triggerer) Trigger( now := time.Now().UnixMilli() execution := &types.Execution{ - RepoID: repo.ID, + RepoID: repo.Repository.ID, PipelineID: pipeline.ID, Trigger: base.Trigger, CreatedBy: base.TriggeredBy, @@ -250,7 +266,7 @@ func (t *triggerer) Trigger( log.Info().Str("pipeline", name).Msg("trigger: skipping pipeline, does not match action") case skipRef(pipeline, base.Ref): log.Info().Str("pipeline", name).Msg("trigger: skipping pipeline, does not match ref") - case skipRepo(pipeline, repo.Path): + case skipRepo(pipeline, repo.Repository.Path): log.Info().Str("pipeline", name).Msg("trigger: skipping pipeline, does not match repo") case skipCron(pipeline, base.Cron): log.Info().Str("pipeline", name).Msg("trigger: skipping pipeline, does not match cron job") @@ -278,7 +294,7 @@ func (t *triggerer) Trigger( } stage := &types.Stage{ - RepoID: repo.ID, + RepoID: repo.Repository.ID, Number: int64(i + 1), Name: match.Name, Kind: match.Kind, @@ -391,7 +407,7 @@ func trunc(s string, i int) string { func parseV1Stages( ctx context.Context, data []byte, - repo *types.Repository, + repo *repo.Repository, execution *types.Execution, templateStore store.TemplateStore, pluginStore store.PluginStore, @@ -461,7 +477,7 @@ func parseV1Stages( status = enum.CIStatusPending } temp := &types.Stage{ - RepoID: repo.ID, + RepoID: repo.Repository.ID, Number: int64(idx + 1), Name: stage.Id, // for v1, ID is the unique identifier per stage Created: now, diff --git a/app/pipeline/triggerer/wire.go b/app/pipeline/triggerer/wire.go index 34cc0babf6..9b21fd4ff6 100644 --- a/app/pipeline/triggerer/wire.go +++ b/app/pipeline/triggerer/wire.go @@ -18,6 +18,7 @@ import ( "github.com/harness/gitness/app/pipeline/converter" "github.com/harness/gitness/app/pipeline/file" "github.com/harness/gitness/app/pipeline/scheduler" + "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/store" "github.com/harness/gitness/app/url" "github.com/harness/gitness/store/database/dbtx" @@ -44,8 +45,9 @@ func ProvideTriggerer( urlProvider url.Provider, templateStore store.TemplateStore, pluginStore store.PluginStore, + publicAccess publicaccess.PublicAccess, ) Triggerer { return New(executionStore, checkStore, stageStore, pipelineStore, tx, repoStore, urlProvider, scheduler, fileService, converterService, - templateStore, pluginStore) + templateStore, pluginStore, publicAccess) } diff --git a/app/services/exporter/repository.go b/app/services/exporter/repository.go index c62406459b..e7de8baf50 100644 --- a/app/services/exporter/repository.go +++ b/app/services/exporter/repository.go @@ -120,7 +120,7 @@ func (r *Repository) RunManyForSpace( // check if repo is public parentSpace, name, err := paths.DisectLeaf(repository.Path) if err != nil { - return fmt.Errorf("Failed to disect path '%s': %w", repository.Path, err) + return fmt.Errorf("failed to disect path '%s': %w", repository.Path, err) } scope := &types.Scope{SpacePath: parentSpace} @@ -217,7 +217,7 @@ func (r *Repository) Handle(ctx context.Context, data string, _ job.ProgressRepo return "", err } - urlWithToken, err := modifyURL(remoteRepo.GitURL, harnessCodeInfo.Token) + urlWithToken, err := modifyURL(remoteRepo.Repository.GitURL, harnessCodeInfo.Token) if err != nil { return "", err } @@ -227,9 +227,9 @@ func (r *Repository) Handle(ctx context.Context, data string, _ job.ProgressRepo RemoteURL: urlWithToken, }) if err != nil && !strings.Contains(err.Error(), "empty") { - errDelete := client.DeleteRepo(ctx, remoteRepo.Identifier) + errDelete := client.DeleteRepo(ctx, remoteRepo.Repository.Identifier) if errDelete != nil { - log.Ctx(ctx).Err(errDelete).Msgf("failed to delete repo '%s' on harness", remoteRepo.Identifier) + log.Ctx(ctx).Err(errDelete).Msgf("failed to delete repo '%s' on harness", remoteRepo.Repository.Identifier) } r.publishSSE(ctx, repository) return "", err diff --git a/cmd/gitness/wire_gen.go b/cmd/gitness/wire_gen.go index d356742af5..1b401cb433 100644 --- a/cmd/gitness/wire_gen.go +++ b/cmd/gitness/wire_gen.go @@ -216,7 +216,7 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro converterService := converter.ProvideService(fileService) templateStore := database.ProvideTemplateStore(db) pluginStore := database.ProvidePluginStore(db) - triggererTriggerer := triggerer.ProvideTriggerer(executionStore, checkStore, stageStore, transactor, pipelineStore, fileService, converterService, schedulerScheduler, repoStore, provider, templateStore, pluginStore) + triggererTriggerer := triggerer.ProvideTriggerer(executionStore, checkStore, stageStore, transactor, pipelineStore, fileService, converterService, schedulerScheduler, repoStore, provider, templateStore, pluginStore, publicAccess) executionController := execution.ProvideController(transactor, authorizer, executionStore, checkStore, cancelerCanceler, commitService, triggererTriggerer, repoStore, stageStore, pipelineStore) logStore := logs.ProvideLogStore(db, config) logStream := livelog.ProvideLogStream() @@ -308,7 +308,7 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro webHandler := router.ProvideWebHandler(config, openapiService) routerRouter := router.ProvideRouter(apiHandler, gitHandler, webHandler, provider) serverServer := server2.ProvideServer(config, routerRouter) - executionManager := manager.ProvideExecutionManager(config, executionStore, pipelineStore, provider, streamer, fileService, converterService, logStore, logStream, checkStore, repoStore, schedulerScheduler, secretStore, stageStore, stepStore, principalStore) + executionManager := manager.ProvideExecutionManager(config, executionStore, pipelineStore, provider, streamer, fileService, converterService, logStore, logStream, checkStore, repoStore, schedulerScheduler, secretStore, stageStore, stepStore, principalStore, publicAccess) client := manager.ProvideExecutionClient(executionManager, provider, config) resolverManager := resolver.ProvideResolver(config, pluginStore, templateStore, executionStore, repoStore) runtimeRunner, err := runner.ProvideExecutionRunner(config, client, resolverManager) From 4d86c39e25e2df67b87f2c898b7d5ad9c447ce22 Mon Sep 17 00:00:00 2001 From: atefeh Date: Tue, 30 Apr 2024 16:31:02 -0700 Subject: [PATCH 07/31] uopdated migration files name --- ...urces.down.sql => 0051_create_table_public_resources.down.sql} | 0 ...resources.up.sql => 0051_create_table_public_resources.up.sql} | 0 ...urces.down.sql => 0051_create_table_public_resources.down.sql} | 0 ...resources.up.sql => 0051_create_table_public_resources.up.sql} | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename app/store/database/migrate/postgres/{0050_create_table_public_resources.down.sql => 0051_create_table_public_resources.down.sql} (100%) rename app/store/database/migrate/postgres/{0050_create_table_public_resources.up.sql => 0051_create_table_public_resources.up.sql} (100%) rename app/store/database/migrate/sqlite/{0050_create_table_public_resources.down.sql => 0051_create_table_public_resources.down.sql} (100%) rename app/store/database/migrate/sqlite/{0050_create_table_public_resources.up.sql => 0051_create_table_public_resources.up.sql} (100%) diff --git a/app/store/database/migrate/postgres/0050_create_table_public_resources.down.sql b/app/store/database/migrate/postgres/0051_create_table_public_resources.down.sql similarity index 100% rename from app/store/database/migrate/postgres/0050_create_table_public_resources.down.sql rename to app/store/database/migrate/postgres/0051_create_table_public_resources.down.sql diff --git a/app/store/database/migrate/postgres/0050_create_table_public_resources.up.sql b/app/store/database/migrate/postgres/0051_create_table_public_resources.up.sql similarity index 100% rename from app/store/database/migrate/postgres/0050_create_table_public_resources.up.sql rename to app/store/database/migrate/postgres/0051_create_table_public_resources.up.sql diff --git a/app/store/database/migrate/sqlite/0050_create_table_public_resources.down.sql b/app/store/database/migrate/sqlite/0051_create_table_public_resources.down.sql similarity index 100% rename from app/store/database/migrate/sqlite/0050_create_table_public_resources.down.sql rename to app/store/database/migrate/sqlite/0051_create_table_public_resources.down.sql diff --git a/app/store/database/migrate/sqlite/0050_create_table_public_resources.up.sql b/app/store/database/migrate/sqlite/0051_create_table_public_resources.up.sql similarity index 100% rename from app/store/database/migrate/sqlite/0050_create_table_public_resources.up.sql rename to app/store/database/migrate/sqlite/0051_create_table_public_resources.up.sql From 1f792dec47b98052b8988ad0ae56135c8b2af525 Mon Sep 17 00:00:00 2001 From: atefeh Date: Tue, 30 Apr 2024 17:02:01 -0700 Subject: [PATCH 08/31] make authentication required to list principals --- app/router/api.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/router/api.go b/app/router/api.go index bbc914e344..35a59730be 100644 --- a/app/router/api.go +++ b/app/router/api.go @@ -145,7 +145,7 @@ func NewAPIHandler( r.Use(audit.Middleware()) r.Route("/v1", func(r chi.Router) { - setupRoutesV1(r, appCtx, config, repoCtrl, repoSettingsCtrl, executionCtrl, triggerCtrl, logCtrl, pipelineCtrl, + setupRoutesV1(r, appCtx, config, authenticator, repoCtrl, repoSettingsCtrl, executionCtrl, triggerCtrl, logCtrl, pipelineCtrl, connectorCtrl, templateCtrl, pluginCtrl, secretCtrl, spaceCtrl, pullreqCtrl, webhookCtrl, githookCtrl, git, saCtrl, userCtrl, principalCtrl, checkCtrl, sysCtrl, uploadCtrl, searchCtrl) @@ -172,6 +172,7 @@ func corsHandler(config *types.Config) func(http.Handler) http.Handler { func setupRoutesV1(r chi.Router, appCtx context.Context, config *types.Config, + authenticator authn.Authenticator, repoCtrl *repo.Controller, repoSettingsCtrl *reposettings.Controller, executionCtrl *execution.Controller, @@ -203,7 +204,7 @@ func setupRoutesV1(r chi.Router, setupSecrets(r, secretCtrl) setupUser(r, userCtrl) setupServiceAccounts(r, saCtrl) - setupPrincipals(r, principalCtrl) + setupPrincipals(r, authenticator, principalCtrl) setupInternal(r, githookCtrl, git) setupAdmin(r, userCtrl) setupAccount(r, userCtrl, sysCtrl, config) @@ -665,8 +666,9 @@ func setupResources(r chi.Router) { }) } -func setupPrincipals(r chi.Router, principalCtrl principal.Controller) { +func setupPrincipals(r chi.Router, authenticator authn.Authenticator, principalCtrl principal.Controller) { r.Route("/principals", func(r chi.Router) { + r.Use(middlewareauthn.Required(authenticator)) r.Get("/", handlerprincipal.HandleList(principalCtrl)) r.Get(fmt.Sprintf("/{%s}", request.PathParamPrincipalID), handlerprincipal.HandleFind(principalCtrl)) }) From 3471bf806d5426d4502b63ee544620da602209c9 Mon Sep 17 00:00:00 2001 From: atefeh Date: Wed, 1 May 2024 20:10:04 -0700 Subject: [PATCH 09/31] add anonymouse principal --- app/api/middleware/authn/authn.go | 6 ------ app/auth/anonymouse.go | 30 ++++++++++++++++++++++++++++++ app/auth/authn/authenticator.go | 9 +-------- app/auth/authn/jwt.go | 4 +++- 4 files changed, 34 insertions(+), 15 deletions(-) create mode 100644 app/auth/anonymouse.go diff --git a/app/api/middleware/authn/authn.go b/app/api/middleware/authn/authn.go index ef5305f949..e566475965 100644 --- a/app/api/middleware/authn/authn.go +++ b/app/api/middleware/authn/authn.go @@ -15,7 +15,6 @@ package authn import ( - "errors" "net/http" "github.com/harness/gitness/app/api/render" @@ -52,11 +51,6 @@ func performAuthentication( session, err := authenticator.Authenticate(r) if err != nil { - if !errors.Is(err, authn.ErrNoAuthData) { - // log error to help with investigating any auth related errors - log.Warn().Err(err).Msg("authentication failed") - } - if required { render.Unauthorized(ctx, w) return diff --git a/app/auth/anonymouse.go b/app/auth/anonymouse.go new file mode 100644 index 0000000000..1b2ef16c0f --- /dev/null +++ b/app/auth/anonymouse.go @@ -0,0 +1,30 @@ +// Copyright 2023 Harness, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package auth + +import ( + "github.com/harness/gitness/types" + "github.com/harness/gitness/types/enum" +) + +// Anonymouse is an in-memory principal for users with no auth data. +// Authorizer is in charge of handling public access. +func Anonymouse() *types.Principal { + return &types.Principal{ + ID: -1, + UID: "ALL_USERS", + Type: enum.PrincipalTypeUser, + } +} diff --git a/app/auth/authn/authenticator.go b/app/auth/authn/authenticator.go index 3f948b5b4c..d0b4b6a7d1 100644 --- a/app/auth/authn/authenticator.go +++ b/app/auth/authn/authenticator.go @@ -15,25 +15,18 @@ package authn import ( - "errors" "net/http" "github.com/harness/gitness/app/auth" ) -var ( - // ErrNoAuthData that is returned if the authorizer doesn't find any data in the request that can be used for auth. - ErrNoAuthData = errors.New("the request doesn't contain any auth data that can be used by the Authorizer") -) - // Authenticator is an abstraction of an entity that's responsible for authenticating principals // that are making calls via HTTP. type Authenticator interface { /* * Tries to authenticate the acting principal if credentials are available. * Returns: - * (session, nil) - request contains auth data and principal was verified - * (nil, ErrNoAuthData) - request doesn't contain any auth data + * (session, nil) - request contains auth data and principal was verified or is anonymouse * (nil, err) - request contains auth data but verification failed */ Authenticate(r *http.Request) (*auth.Session, error) diff --git a/app/auth/authn/jwt.go b/app/auth/authn/jwt.go index 902abb01e2..5613d3f58e 100644 --- a/app/auth/authn/jwt.go +++ b/app/auth/authn/jwt.go @@ -56,7 +56,9 @@ func (a *JWTAuthenticator) Authenticate(r *http.Request) (*auth.Session, error) str := extractToken(r, a.cookieName) if len(str) == 0 { - return nil, ErrNoAuthData + return &auth.Session{ + Principal: *auth.Anonymouse(), + }, nil } var principal *types.Principal From 89f6edc6f694c4496956f96cd0379480159ccf94 Mon Sep 17 00:00:00 2001 From: atefeh Date: Wed, 1 May 2024 22:59:19 -0700 Subject: [PATCH 10/31] fix typo --- app/auth/{anonymouse.go => anonymous.go} | 4 ++-- app/auth/authn/authenticator.go | 2 +- app/auth/authn/jwt.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) rename app/auth/{anonymouse.go => anonymous.go} (88%) diff --git a/app/auth/anonymouse.go b/app/auth/anonymous.go similarity index 88% rename from app/auth/anonymouse.go rename to app/auth/anonymous.go index 1b2ef16c0f..338ee19a22 100644 --- a/app/auth/anonymouse.go +++ b/app/auth/anonymous.go @@ -19,9 +19,9 @@ import ( "github.com/harness/gitness/types/enum" ) -// Anonymouse is an in-memory principal for users with no auth data. +// Anonymous is an in-memory principal for users with no auth data. // Authorizer is in charge of handling public access. -func Anonymouse() *types.Principal { +func Anonymous() *types.Principal { return &types.Principal{ ID: -1, UID: "ALL_USERS", diff --git a/app/auth/authn/authenticator.go b/app/auth/authn/authenticator.go index d0b4b6a7d1..c3af00ac78 100644 --- a/app/auth/authn/authenticator.go +++ b/app/auth/authn/authenticator.go @@ -26,7 +26,7 @@ type Authenticator interface { /* * Tries to authenticate the acting principal if credentials are available. * Returns: - * (session, nil) - request contains auth data and principal was verified or is anonymouse + * (session, nil) - request contains auth data and principal was verified or is anonymous * (nil, err) - request contains auth data but verification failed */ Authenticate(r *http.Request) (*auth.Session, error) diff --git a/app/auth/authn/jwt.go b/app/auth/authn/jwt.go index 5613d3f58e..edbf620d5b 100644 --- a/app/auth/authn/jwt.go +++ b/app/auth/authn/jwt.go @@ -57,7 +57,7 @@ func (a *JWTAuthenticator) Authenticate(r *http.Request) (*auth.Session, error) if len(str) == 0 { return &auth.Session{ - Principal: *auth.Anonymouse(), + Principal: *auth.Anonymous(), }, nil } From 424a2f19648fe16a162fd87241195f7ab3cc37ce Mon Sep 17 00:00:00 2001 From: atefeh Date: Thu, 2 May 2024 01:53:08 -0700 Subject: [PATCH 11/31] self review --- app/auth/authz/{public.go => public_access.go} | 0 app/services/exporter/repository.go | 15 +-------------- 2 files changed, 1 insertion(+), 14 deletions(-) rename app/auth/authz/{public.go => public_access.go} (100%) diff --git a/app/auth/authz/public.go b/app/auth/authz/public_access.go similarity index 100% rename from app/auth/authz/public.go rename to app/auth/authz/public_access.go diff --git a/app/services/exporter/repository.go b/app/services/exporter/repository.go index ac9ed722ec..7c0cf3d4c9 100644 --- a/app/services/exporter/repository.go +++ b/app/services/exporter/repository.go @@ -25,7 +25,6 @@ import ( "time" "github.com/harness/gitness/app/api/controller/repo" - "github.com/harness/gitness/app/paths" "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/sse" "github.com/harness/gitness/app/store" @@ -118,19 +117,7 @@ func (r *Repository) RunManyForSpace( jobDefinitions := make([]job.Definition, len(repos)) for i, repository := range repos { - // check if repo is public - parentSpace, name, err := paths.DisectLeaf(repository.Path) - if err != nil { - return fmt.Errorf("failed to disect path '%s': %w", repository.Path, err) - } - - scope := &types.Scope{SpacePath: parentSpace} - resource := &types.Resource{ - Type: enum.ResourceTypeRepo, - Identifier: name, - } - - isPublic, err := r.publicAccess.Get(ctx, scope, resource) + isPublic, err := apiauth.CheckRepoIsPublic(ctx, r.publicAccess, repository) if err != nil { return fmt.Errorf("failed to check repo public visibility: %w", err) } From 4a825ad4b7f873d94082dce189f14a51a1693a6e Mon Sep 17 00:00:00 2001 From: atefeh Date: Thu, 2 May 2024 15:41:43 -0700 Subject: [PATCH 12/31] disable public resource on repo purge --- app/api/controller/repo/create.go | 26 +++++++++++++++----------- app/api/controller/repo/purge.go | 27 +++++++++++++++++++++++++++ app/api/controller/repo/update.go | 5 +++-- 3 files changed, 45 insertions(+), 13 deletions(-) diff --git a/app/api/controller/repo/create.go b/app/api/controller/repo/create.go index 3261b9d32e..19358b4341 100644 --- a/app/api/controller/repo/create.go +++ b/app/api/controller/repo/create.go @@ -77,6 +77,11 @@ func (c *Controller) Create(ctx context.Context, session *auth.Session, in *Crea return nil, err } + gitResp, isEmpty, err := c.createGitRepository(ctx, session, in) + if err != nil { + return nil, fmt.Errorf("error creating repository on git: %w", err) + } + var repo *types.Repository err = c.tx.WithTx(ctx, func(ctx context.Context) error { if err := c.resourceLimiter.RepoCount(ctx, parentSpace.ID, 1); err != nil { @@ -89,11 +94,6 @@ func (c *Controller) Create(ctx context.Context, session *auth.Session, in *Crea return fmt.Errorf("failed to find the parent space: %w", err) } - gitResp, isEmpty, err := c.createGitRepository(ctx, session, in) - if err != nil { - return fmt.Errorf("error creating repository on git: %w", err) - } - now := time.Now().UnixMilli() repo = &types.Repository{ Version: 0, @@ -108,6 +108,7 @@ func (c *Controller) Create(ctx context.Context, session *auth.Session, in *Crea DefaultBranch: in.DefaultBranch, IsEmpty: isEmpty, } + err = c.repoStore.Create(ctx, repo) if err != nil { if dErr := c.DeleteGitRepository(ctx, session, repo); dErr != nil { @@ -116,18 +117,21 @@ func (c *Controller) Create(ctx context.Context, session *auth.Session, in *Crea return fmt.Errorf("failed to create repository in storage: %w", err) } - if in.IsPublic && c.publicResourceCreationEnabled { - if err = c.SetPublicRepo(ctx, repo); err != nil { - return fmt.Errorf("failed to set a public resource: %w", err) - } - } - return nil }, sql.TxOptions{Isolation: sql.LevelSerializable}) if err != nil { return nil, err } + if in.IsPublic && c.publicResourceCreationEnabled { + if err = c.SetPublicRepo(ctx, repo); err != nil { + if dErr := c.PurgeNoAuth(ctx, session, repo); dErr != nil { + log.Ctx(ctx).Warn().Err(dErr).Msg("failed to purge repo for cleanup") + } + return nil, fmt.Errorf("failed to set a public resource: %w", err) + } + } + // backfil GitURL repo.GitURL = c.urlProvider.GenerateGITCloneURL(repo.Path) diff --git a/app/api/controller/repo/purge.go b/app/api/controller/repo/purge.go index 34e4f1b685..ce65f2322d 100644 --- a/app/api/controller/repo/purge.go +++ b/app/api/controller/repo/purge.go @@ -23,6 +23,7 @@ import ( "github.com/harness/gitness/app/api/usererror" "github.com/harness/gitness/app/auth" repoevents "github.com/harness/gitness/app/events/repo" + "github.com/harness/gitness/app/paths" "github.com/harness/gitness/errors" "github.com/harness/gitness/git" "github.com/harness/gitness/types" @@ -72,6 +73,17 @@ func (c *Controller) PurgeNoAuth( } } + isPublic, err := apiauth.CheckRepoIsPublic(ctx, c.publicAccess, repo) + if err != nil { + log.Ctx(ctx).Err(err).Msg("failed to check repo public access") + } + + if isPublic { + if err := c.disablePublicRepo(ctx, repo); err != nil { + log.Ctx(ctx).Err(err).Msg("failed to disable repo public access") + } + } + if err := c.repoStore.Purge(ctx, repo.ID, repo.Deleted); err != nil { return fmt.Errorf("failed to delete repo from db: %w", err) } @@ -112,3 +124,18 @@ func (c *Controller) DeleteGitRepository( } return nil } + +func (c *Controller) disablePublicRepo(ctx context.Context, repo *types.Repository) error { + parentSpace, name, err := paths.DisectLeaf(repo.Path) + if err != nil { + return fmt.Errorf("failed to disect path '%s': %w", repo.Path, err) + } + + scope := &types.Scope{SpacePath: parentSpace} + resource := &types.Resource{ + Type: enum.ResourceTypeRepo, + Identifier: name, + } + + return c.publicAccess.Set(ctx, scope, resource, false) +} diff --git a/app/api/controller/repo/update.go b/app/api/controller/repo/update.go index 400ee09a9b..2f11f1e8f5 100644 --- a/app/api/controller/repo/update.go +++ b/app/api/controller/repo/update.go @@ -72,8 +72,6 @@ func (c *Controller) Update(ctx context.Context, return nil, err } - // backfill repo url - repo.Repository.GitURL = c.urlProvider.GenerateGITCloneURL(repo.Repository.Path) isPublic, err := apiauth.CheckRepoIsPublic(ctx, c.publicAccess, repoBase) if err != nil { return nil, fmt.Errorf("failed to get resource public access mode: %w", err) @@ -96,6 +94,9 @@ func (c *Controller) Update(ctx context.Context, log.Ctx(ctx).Warn().Msgf("failed to insert audit log for update repository operation: %s", err) } + // backfill repo url + repo.Repository.GitURL = c.urlProvider.GenerateGITCloneURL(repo.Repository.Path) + return repo, nil } From 1f410581afd44a807d91502c9db78b1045413221 Mon Sep 17 00:00:00 2001 From: atefeh Date: Thu, 2 May 2024 18:19:30 -0700 Subject: [PATCH 13/31] self review --- app/api/controller/pullreq/reviewer_add.go | 2 +- app/api/controller/repo/commit.go | 4 +--- app/api/controller/repo/controller.go | 4 ++-- app/api/controller/repo/create.go | 3 ++- app/api/controller/repo/default_branch.go | 1 - .../controller/repo/public_access_update.go | 3 ++- .../controller/reposettings/security_find.go | 2 +- app/api/controller/space/controller.go | 5 +++++ app/api/controller/space/list_spaces.go | 5 ----- app/api/controller/space/update.go | 19 ++++++++++++++++--- app/pipeline/converter/jsonnet/jsonnet.go | 3 ++- app/pipeline/triggerer/trigger.go | 5 ++--- app/services/importer/provider.go | 2 +- app/services/publicaccess/public_access.go | 8 ++++---- 14 files changed, 39 insertions(+), 27 deletions(-) diff --git a/app/api/controller/pullreq/reviewer_add.go b/app/api/controller/pullreq/reviewer_add.go index bf8830880f..1c12303d9a 100644 --- a/app/api/controller/pullreq/reviewer_add.go +++ b/app/api/controller/pullreq/reviewer_add.go @@ -43,7 +43,7 @@ func (c *Controller) ReviewerAdd( prNum int64, in *ReviewerAddInput, ) (*types.PullReqReviewer, error) { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoReview) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoPush) if err != nil { return nil, fmt.Errorf("failed to acquire access to repo: %w", err) } diff --git a/app/api/controller/repo/commit.go b/app/api/controller/repo/commit.go index f6835ae7e8..6edf9ec1d8 100644 --- a/app/api/controller/repo/commit.go +++ b/app/api/controller/repo/commit.go @@ -62,9 +62,7 @@ func (c *Controller) CommitFiles(ctx context.Context, repoRef string, in *CommitFilesOptions, ) (types.CommitFilesResponse, []types.RuleViolations, error) { - requiredPermission := enum.PermissionRepoPush - - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, requiredPermission) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoPush) if err != nil { return types.CommitFilesResponse{}, nil, err } diff --git a/app/api/controller/repo/controller.go b/app/api/controller/repo/controller.go index 6d64f24d70..9f99774e43 100644 --- a/app/api/controller/repo/controller.go +++ b/app/api/controller/repo/controller.go @@ -50,7 +50,7 @@ var ( type Repository struct { types.Repository - IsPublic bool `json:"is_public"` + IsPublic bool `json:"is_public" yaml:"is_public"` } // Clone makes deep copy of repository object. @@ -61,7 +61,7 @@ func (r Repository) Clone() Repository { deleted = &id } r.Repository.Deleted = deleted - + return r } diff --git a/app/api/controller/repo/create.go b/app/api/controller/repo/create.go index 19358b4341..8ff0555b3e 100644 --- a/app/api/controller/repo/create.go +++ b/app/api/controller/repo/create.go @@ -124,7 +124,8 @@ func (c *Controller) Create(ctx context.Context, session *auth.Session, in *Crea } if in.IsPublic && c.publicResourceCreationEnabled { - if err = c.SetPublicRepo(ctx, repo); err != nil { + err = c.SetPublicRepo(ctx, repo) + if err != nil { if dErr := c.PurgeNoAuth(ctx, session, repo); dErr != nil { log.Ctx(ctx).Warn().Err(dErr).Msg("failed to purge repo for cleanup") } diff --git a/app/api/controller/repo/default_branch.go b/app/api/controller/repo/default_branch.go index f130864dcb..5ccac5af09 100644 --- a/app/api/controller/repo/default_branch.go +++ b/app/api/controller/repo/default_branch.go @@ -50,7 +50,6 @@ func (c *Controller) UpdateDefaultBranch( } repoClone := repo.Clone() - // the max time we give an update default branch to succeed const timeout = 2 * time.Minute diff --git a/app/api/controller/repo/public_access_update.go b/app/api/controller/repo/public_access_update.go index df078301b1..fc786456c9 100644 --- a/app/api/controller/repo/public_access_update.go +++ b/app/api/controller/repo/public_access_update.go @@ -23,6 +23,7 @@ import ( "github.com/harness/gitness/audit" "github.com/harness/gitness/types" "github.com/harness/gitness/types/enum" + "github.com/rs/zerolog/log" ) @@ -62,7 +63,7 @@ func (c *Controller) PublicAccessUpdate(ctx context.Context, } if err = c.publicAccess.Set(ctx, scope, resource, in.EnablePublic); err != nil { - return nil, fmt.Errorf("failed to set public access: %w", err) + return nil, fmt.Errorf("failed to update repo public access: %w", err) } err = c.auditService.Log(ctx, diff --git a/app/api/controller/reposettings/security_find.go b/app/api/controller/reposettings/security_find.go index b6c675f0bc..fc57a9c473 100644 --- a/app/api/controller/reposettings/security_find.go +++ b/app/api/controller/reposettings/security_find.go @@ -28,7 +28,7 @@ func (c *Controller) SecurityFind( session *auth.Session, repoRef string, ) (*SecuritySettings, error) { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoEdit) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView) if err != nil { return nil, err } diff --git a/app/api/controller/space/controller.go b/app/api/controller/space/controller.go index 03782a3808..e2f7d237ad 100644 --- a/app/api/controller/space/controller.go +++ b/app/api/controller/space/controller.go @@ -37,6 +37,11 @@ var ( errPublicSpaceCreationDisabled = usererror.BadRequestf("Public space creation is disabled.") ) +type Space struct { + types.Space + IsPublic bool `json:"is_public" yaml:"is_public"` +} + type Controller struct { nestedSpacesEnabled bool publicResourceCreationEnabled bool diff --git a/app/api/controller/space/list_spaces.go b/app/api/controller/space/list_spaces.go index 41a4c32473..6b8154a4c2 100644 --- a/app/api/controller/space/list_spaces.go +++ b/app/api/controller/space/list_spaces.go @@ -25,11 +25,6 @@ import ( "github.com/harness/gitness/types/enum" ) -type Space struct { - types.Space - IsPublic bool `json:"is_public"` -} - // ListSpaces lists the child spaces of a space. func (c *Controller) ListSpaces(ctx context.Context, session *auth.Session, diff --git a/app/api/controller/space/update.go b/app/api/controller/space/update.go index f7a5ba9797..89cc1d5279 100644 --- a/app/api/controller/space/update.go +++ b/app/api/controller/space/update.go @@ -37,7 +37,7 @@ func (in *UpdateInput) hasChanges(space *types.Space) bool { // Update updates a space. func (c *Controller) Update(ctx context.Context, session *auth.Session, - spaceRef string, in *UpdateInput) (*types.Space, error) { + spaceRef string, in *UpdateInput) (*Space, error) { space, err := c.spaceStore.FindByRef(ctx, spaceRef) if err != nil { return nil, err @@ -47,8 +47,18 @@ func (c *Controller) Update(ctx context.Context, session *auth.Session, return nil, err } + isPublic, err := apiauth.CheckSpaceIsPublic(ctx, c.publicAccess, space) + if err != nil { + return nil, fmt.Errorf("failed to get resource public access mode: %w", err) + } + + spaceData := &Space{ + Space: *space, + IsPublic: isPublic, + } + if !in.hasChanges(space) { - return space, nil + return spaceData, nil } if err = c.sanitizeUpdateInput(in); err != nil { @@ -67,7 +77,10 @@ func (c *Controller) Update(ctx context.Context, session *auth.Session, return nil, err } - return space, nil + return &Space{ + Space: *space, + IsPublic: isPublic, + }, nil } func (c *Controller) sanitizeUpdateInput(in *UpdateInput) error { diff --git a/app/pipeline/converter/jsonnet/jsonnet.go b/app/pipeline/converter/jsonnet/jsonnet.go index 087babfd54..a3b90a950b 100644 --- a/app/pipeline/converter/jsonnet/jsonnet.go +++ b/app/pipeline/converter/jsonnet/jsonnet.go @@ -23,10 +23,11 @@ import ( "strconv" "strings" - "github.com/google/go-jsonnet" repoCtrl "github.com/harness/gitness/app/api/controller/repo" "github.com/harness/gitness/app/pipeline/file" "github.com/harness/gitness/types" + + "github.com/google/go-jsonnet" ) const repo = "repo." diff --git a/app/pipeline/triggerer/trigger.go b/app/pipeline/triggerer/trigger.go index 6cfc7d674c..bb060d8503 100644 --- a/app/pipeline/triggerer/trigger.go +++ b/app/pipeline/triggerer/trigger.go @@ -21,6 +21,8 @@ import ( "runtime/debug" "time" + apiauth "github.com/harness/gitness/app/api/auth" + "github.com/harness/gitness/app/api/controller/repo" "github.com/harness/gitness/app/pipeline/checks" "github.com/harness/gitness/app/pipeline/converter" "github.com/harness/gitness/app/pipeline/file" @@ -35,9 +37,6 @@ import ( "github.com/harness/gitness/types" "github.com/harness/gitness/types/enum" - apiauth "github.com/harness/gitness/app/api/auth" - "github.com/harness/gitness/app/api/controller/repo" - "github.com/drone-runners/drone-runner-docker/engine2/inputs" "github.com/drone-runners/drone-runner-docker/engine2/script" "github.com/drone/drone-yaml/yaml" diff --git a/app/services/importer/provider.go b/app/services/importer/provider.go index ad821de962..661d51f313 100644 --- a/app/services/importer/provider.go +++ b/app/services/importer/provider.go @@ -75,7 +75,7 @@ type RepositoryInfo struct { DefaultBranch string } -// ToRepo converts the RepositoryInfo into the types.Repository object marked as being imported and is public flag. +// ToRepo converts the RepositoryInfo into the types.Repository object marked as being imported and is-public flag. func (r *RepositoryInfo) ToRepo( spaceID int64, identifier string, diff --git a/app/services/publicaccess/public_access.go b/app/services/publicaccess/public_access.go index db3b48ffbe..9d3fad2972 100644 --- a/app/services/publicaccess/public_access.go +++ b/app/services/publicaccess/public_access.go @@ -25,9 +25,9 @@ type PublicAccess interface { /* * Get returns whether public access is enabled on the resource. * Returns - * (true, nil) - resource public access is allowed - * (false, nil) - resource public access is not allowed - * (false, err) - an error occurred while performing the public access check. + * (true, nil) - public access to the resource is allowed + * (false, nil) - public access to the resource is not allowed + * (false, err) - an error occurred while performing public access check. */ Get( ctx context.Context, @@ -39,7 +39,7 @@ type PublicAccess interface { * Sets or deletes public access mode for the resource based on the value of 'enable'. * Returns * err - resource public access mode has been updated successfully - * nil - an error occurred while performing the public access set. + * nil - an error occurred while performing public access set. */ Set( ctx context.Context, From 0ff77052f70f67ab4e5b13c8ab5b256825efbebb Mon Sep 17 00:00:00 2001 From: atefeh Date: Tue, 7 May 2024 00:06:26 -0700 Subject: [PATCH 14/31] code cleaning, address pr comments --- app/api/auth/repo.go | 13 +-- app/api/auth/space.go | 13 +-- app/api/controller/pullreq/reviewer_add.go | 2 +- app/api/controller/pullreq/reviewer_delete.go | 2 +- app/api/controller/repo/archive.go | 2 +- app/api/controller/repo/blame.go | 4 +- app/api/controller/repo/codeowner_validate.go | 4 +- app/api/controller/repo/commit.go | 6 +- app/api/controller/repo/content_get.go | 4 +- .../controller/repo/content_paths_details.go | 4 +- app/api/controller/repo/controller.go | 18 +--- app/api/controller/repo/create.go | 44 ++++------ app/api/controller/repo/create_branch.go | 8 +- app/api/controller/repo/create_commit_tag.go | 8 +- app/api/controller/repo/default_branch.go | 23 ++---- app/api/controller/repo/delete_branch.go | 8 +- app/api/controller/repo/delete_tag.go | 6 +- app/api/controller/repo/diff.go | 4 +- app/api/controller/repo/get_branch.go | 2 +- app/api/controller/repo/get_commit.go | 2 +- .../controller/repo/get_commit_divergences.go | 4 +- app/api/controller/repo/git_info_refs.go | 2 +- app/api/controller/repo/git_service_pack.go | 4 +- app/api/controller/repo/helper.go | 37 +++++---- app/api/controller/repo/import.go | 7 +- app/api/controller/repo/list_branches.go | 2 +- app/api/controller/repo/list_commit_tags.go | 2 +- app/api/controller/repo/list_commits.go | 4 +- app/api/controller/repo/list_paths.go | 4 +- app/api/controller/repo/list_pipelines.go | 8 +- .../controller/repo/list_service_accounts.go | 4 +- app/api/controller/repo/merge_check.go | 2 +- app/api/controller/repo/pipeline_generate.go | 2 +- .../controller/repo/public_access_update.go | 41 +++++----- app/api/controller/repo/purge.go | 18 +--- app/api/controller/repo/raw.go | 4 +- app/api/controller/repo/rule_create.go | 4 +- app/api/controller/repo/rule_delete.go | 4 +- app/api/controller/repo/rule_find.go | 2 +- app/api/controller/repo/rule_list.go | 4 +- app/api/controller/repo/rule_update.go | 4 +- app/api/controller/repo/update.go | 25 ++---- app/api/controller/reposettings/controller.go | 8 +- .../controller/reposettings/general_find.go | 2 +- .../controller/reposettings/general_update.go | 10 +-- app/api/controller/reposettings/wire.go | 4 +- app/api/controller/space/create.go | 25 +++--- .../api/controller/space/helper.go | 29 +++++-- app/api/controller/space/import.go | 8 +- .../controller/space/import_repositories.go | 7 +- app/api/controller/space/update.go | 17 +--- app/api/controller/webhook/controller.go | 4 - app/api/controller/webhook/wire.go | 5 +- app/auth/{anonymous.go => anonymouse.go} | 14 ++-- app/auth/authn/jwt.go | 2 +- app/auth/authz/membership.go | 4 +- app/auth/authz/public_access.go | 19 +++-- app/pipeline/converter/converter.go | 15 +++- app/pipeline/converter/jsonnet/jsonnet.go | 28 +++---- app/pipeline/converter/service.go | 10 +-- app/pipeline/converter/starlark/args.go | 26 +++--- app/pipeline/converter/starlark/starlark.go | 10 +-- app/pipeline/file/gitness.go | 6 +- app/pipeline/file/service.go | 4 +- app/pipeline/manager/client.go | 2 +- app/pipeline/manager/convert.go | 27 +++--- app/pipeline/manager/manager.go | 67 ++++++++------- app/pipeline/triggerer/env.go | 5 +- app/pipeline/triggerer/trigger.go | 43 +++++----- app/services/exporter/repository.go | 15 +--- app/services/publicaccess/public_access.go | 10 +-- app/services/publicaccess/resources.go | 62 +++++--------- app/services/publicaccess/service.go | 34 ++++---- app/services/publicaccess/wire.go | 4 +- app/store/database.go | 10 +-- ...051_create_table_public_resources.down.sql | 28 +++---- .../0051_create_table_public_resources.up.sql | 42 +++++----- ...051_create_table_public_resources.down.sql | 28 +++---- .../0051_create_table_public_resources.up.sql | 42 +++++----- .../{public_resource.go => public_access.go} | 82 ++++++++++--------- app/store/database/wire.go | 8 +- cmd/gitness/wire_gen.go | 8 +- types/enum/public_resource.go | 2 +- types/repo.go | 12 +++ 84 files changed, 526 insertions(+), 627 deletions(-) rename types/public_resource.go => app/api/controller/space/helper.go (52%) rename app/auth/{anonymous.go => anonymouse.go} (73%) rename app/store/database/{public_resource.go => public_access.go} (62%) diff --git a/app/api/auth/repo.go b/app/api/auth/repo.go index d666fee5b4..98d59f813e 100644 --- a/app/api/auth/repo.go +++ b/app/api/auth/repo.go @@ -58,18 +58,7 @@ func CheckRepoIsPublic( publicAccess publicaccess.PublicAccess, repo *types.Repository, ) (bool, error) { - parentSpace, name, err := paths.DisectLeaf(repo.Path) - if err != nil { - return false, fmt.Errorf("failed to disect path '%s': %w", repo.Path, err) - } - - scope := &types.Scope{SpacePath: parentSpace} - resource := &types.Resource{ - Type: enum.ResourceTypeRepo, - Identifier: name, - } - - return publicAccess.Get(ctx, scope, resource) + return publicAccess.Get(ctx, enum.PublicResourceTypeRepo, repo.Path) } func IsRepoOwner( diff --git a/app/api/auth/space.go b/app/api/auth/space.go index 1901f00f5f..dd95082f91 100644 --- a/app/api/auth/space.go +++ b/app/api/auth/space.go @@ -75,16 +75,5 @@ func CheckSpaceIsPublic( publicAccess publicaccess.PublicAccess, space *types.Space, ) (bool, error) { - parentSpace, name, err := paths.DisectLeaf(space.Path) - if err != nil { - return false, fmt.Errorf("failed to disect path '%s': %w", space.Path, err) - } - - scope := &types.Scope{SpacePath: parentSpace} - resource := &types.Resource{ - Type: enum.ResourceTypeSpace, - Identifier: name, - } - - return publicAccess.Get(ctx, scope, resource) + return publicAccess.Get(ctx, enum.PublicResourceTypeSpace, space.Path) } diff --git a/app/api/controller/pullreq/reviewer_add.go b/app/api/controller/pullreq/reviewer_add.go index 1c12303d9a..bf8830880f 100644 --- a/app/api/controller/pullreq/reviewer_add.go +++ b/app/api/controller/pullreq/reviewer_add.go @@ -43,7 +43,7 @@ func (c *Controller) ReviewerAdd( prNum int64, in *ReviewerAddInput, ) (*types.PullReqReviewer, error) { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoPush) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoReview) if err != nil { return nil, fmt.Errorf("failed to acquire access to repo: %w", err) } diff --git a/app/api/controller/pullreq/reviewer_delete.go b/app/api/controller/pullreq/reviewer_delete.go index e2c4a4760c..4ae9c95e6e 100644 --- a/app/api/controller/pullreq/reviewer_delete.go +++ b/app/api/controller/pullreq/reviewer_delete.go @@ -25,7 +25,7 @@ import ( // ReviewerDelete deletes reviewer from the reviewerlist for the given PR. func (c *Controller) ReviewerDelete(ctx context.Context, session *auth.Session, repoRef string, prNum, reviewerID int64) error { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoPush) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoReview) if err != nil { return fmt.Errorf("failed to acquire access to repo: %w", err) } diff --git a/app/api/controller/repo/archive.go b/app/api/controller/repo/archive.go index ffcd87763e..256ae8927f 100644 --- a/app/api/controller/repo/archive.go +++ b/app/api/controller/repo/archive.go @@ -37,7 +37,7 @@ func (c *Controller) Archive( } return c.git.Archive(ctx, git.ArchiveParams{ - ReadParams: git.CreateReadParams(repo.Repository), + ReadParams: git.CreateReadParams(repo), ArchiveParams: params, }, w) } diff --git a/app/api/controller/repo/blame.go b/app/api/controller/repo/blame.go index 97c1857d01..585f3ab21a 100644 --- a/app/api/controller/repo/blame.go +++ b/app/api/controller/repo/blame.go @@ -45,12 +45,12 @@ func (c *Controller) Blame(ctx context.Context, } if gitRef == "" { - gitRef = repo.Repository.DefaultBranch + gitRef = repo.DefaultBranch } reader := git.NewStreamReader( c.git.Blame(ctx, &git.BlameParams{ - ReadParams: git.CreateReadParams(repo.Repository), + ReadParams: git.CreateReadParams(repo), GitRef: gitRef, Path: path, LineFrom: lineFrom, diff --git a/app/api/controller/repo/codeowner_validate.go b/app/api/controller/repo/codeowner_validate.go index 4235b83ba3..8028f44136 100644 --- a/app/api/controller/repo/codeowner_validate.go +++ b/app/api/controller/repo/codeowner_validate.go @@ -34,10 +34,10 @@ func (c *Controller) CodeOwnersValidate( } if ref == "" { - ref = repo.Repository.DefaultBranch + ref = repo.DefaultBranch } - violations, err := c.codeOwners.Validate(ctx, &repo.Repository, ref) + violations, err := c.codeOwners.Validate(ctx, repo, ref) if err != nil { return nil, err } diff --git a/app/api/controller/repo/commit.go b/app/api/controller/repo/commit.go index 6edf9ec1d8..102c1bf3f4 100644 --- a/app/api/controller/repo/commit.go +++ b/app/api/controller/repo/commit.go @@ -67,7 +67,7 @@ func (c *Controller) CommitFiles(ctx context.Context, return types.CommitFilesResponse{}, nil, err } - rules, isRepoOwner, err := c.fetchRules(ctx, session, &repo.Repository) + rules, isRepoOwner, err := c.fetchRules(ctx, session, repo) if err != nil { return types.CommitFilesResponse{}, nil, err } @@ -86,7 +86,7 @@ func (c *Controller) CommitFiles(ctx context.Context, Actor: &session.Principal, AllowBypass: in.BypassRules, IsRepoOwner: isRepoOwner, - Repo: &repo.Repository, + Repo: repo, RefAction: refAction, RefType: protection.RefTypeBranch, RefNames: []string{branchName}, @@ -131,7 +131,7 @@ func (c *Controller) CommitFiles(ctx context.Context, } // Create internal write params. Note: This will skip the pre-commit protection rules check. - writeParams, err := controller.CreateRPCInternalWriteParams(ctx, c.urlProvider, session, &repo.Repository) + writeParams, err := controller.CreateRPCInternalWriteParams(ctx, c.urlProvider, session, repo) if err != nil { return types.CommitFilesResponse{}, nil, fmt.Errorf("failed to create RPC write params: %w", err) } diff --git a/app/api/controller/repo/content_get.go b/app/api/controller/repo/content_get.go index 090192562f..576a93d4c7 100644 --- a/app/api/controller/repo/content_get.go +++ b/app/api/controller/repo/content_get.go @@ -108,11 +108,11 @@ func (c *Controller) GetContent(ctx context.Context, // set gitRef to default branch in case an empty reference was provided if gitRef == "" { - gitRef = repo.Repository.DefaultBranch + gitRef = repo.DefaultBranch } // create read params once - readParams := git.CreateReadParams(repo.Repository) + readParams := git.CreateReadParams(repo) treeNodeOutput, err := c.git.GetTreeNode(ctx, &git.GetTreeNodeParams{ ReadParams: readParams, diff --git a/app/api/controller/repo/content_paths_details.go b/app/api/controller/repo/content_paths_details.go index 6cbb9b2a1a..d75d4e6783 100644 --- a/app/api/controller/repo/content_paths_details.go +++ b/app/api/controller/repo/content_paths_details.go @@ -56,11 +56,11 @@ func (c *Controller) PathsDetails(ctx context.Context, // set gitRef to default branch in case an empty reference was provided if gitRef == "" { - gitRef = repo.Repository.DefaultBranch + gitRef = repo.DefaultBranch } result, err := c.git.PathsDetails(ctx, git.PathsDetailsParams{ - ReadParams: git.CreateReadParams(repo.Repository), + ReadParams: git.CreateReadParams(repo), GitREF: gitRef, Paths: input.Paths, }) diff --git a/app/api/controller/repo/controller.go b/app/api/controller/repo/controller.go index 9f99774e43..14a2b2e5c9 100644 --- a/app/api/controller/repo/controller.go +++ b/app/api/controller/repo/controller.go @@ -53,18 +53,6 @@ type Repository struct { IsPublic bool `json:"is_public" yaml:"is_public"` } -// Clone makes deep copy of repository object. -func (r Repository) Clone() Repository { - var deleted *int64 - if r.Repository.Deleted != nil { - id := *r.Repository.Deleted - deleted = &id - } - r.Repository.Deleted = deleted - - return r -} - type Controller struct { defaultBranch string publicResourceCreationEnabled bool @@ -153,10 +141,9 @@ func NewController( func (c *Controller) getRepo( ctx context.Context, repoRef string, -) (*Repository, error) { +) (*types.Repository, error) { return GetRepo( ctx, - c.publicAccess, c.repoStore, repoRef, ) @@ -169,12 +156,11 @@ func (c *Controller) getRepoCheckAccess( session *auth.Session, repoRef string, reqPermission enum.Permission, -) (*Repository, error) { +) (*types.Repository, error) { return GetRepoCheckAccess( ctx, c.repoStore, c.authorizer, - c.publicAccess, session, repoRef, reqPermission, diff --git a/app/api/controller/repo/create.go b/app/api/controller/repo/create.go index 8ff0555b3e..954e744e48 100644 --- a/app/api/controller/repo/create.go +++ b/app/api/controller/repo/create.go @@ -109,28 +109,21 @@ func (c *Controller) Create(ctx context.Context, session *auth.Session, in *Crea IsEmpty: isEmpty, } - err = c.repoStore.Create(ctx, repo) - if err != nil { - if dErr := c.DeleteGitRepository(ctx, session, repo); dErr != nil { - log.Ctx(ctx).Warn().Err(dErr).Msg("failed to delete repo for cleanup") - } - return fmt.Errorf("failed to create repository in storage: %w", err) - } - - return nil + return c.repoStore.Create(ctx, repo) }, sql.TxOptions{Isolation: sql.LevelSerializable}) if err != nil { + // best effort cleanup + if dErr := c.DeleteGitRepository(ctx, session, repo); dErr != nil { + log.Ctx(ctx).Warn().Err(dErr).Msg("failed to delete repo for cleanup") + } return nil, err } - if in.IsPublic && c.publicResourceCreationEnabled { - err = c.SetPublicRepo(ctx, repo) - if err != nil { - if dErr := c.PurgeNoAuth(ctx, session, repo); dErr != nil { - log.Ctx(ctx).Warn().Err(dErr).Msg("failed to purge repo for cleanup") - } - return nil, fmt.Errorf("failed to set a public resource: %w", err) + if err = c.SetRepoPublicAccess(ctx, repo, in.IsPublic); err != nil { + if dErr := c.PurgeNoAuth(ctx, session, repo); dErr != nil { + log.Ctx(ctx).Warn().Err(dErr).Msg("failed to purge repo for cleanup") } + return nil, fmt.Errorf("failed to set repo public access: %w", err) } // backfil GitURL @@ -287,19 +280,16 @@ func (c *Controller) createGitRepository(ctx context.Context, session *auth.Sess return resp, len(files) == 0, nil } -func (c *Controller) SetPublicRepo(ctx context.Context, repo *types.Repository) error { - parentSpace, name, err := paths.DisectLeaf(repo.Path) - if err != nil { - return fmt.Errorf("failed to disect path '%s': %w", repo.Path, err) - } - - scope := &types.Scope{SpacePath: parentSpace} - resource := &types.Resource{ - Type: enum.ResourceTypeRepo, - Identifier: name, +func (c *Controller) SetRepoPublicAccess( + ctx context.Context, + repo *types.Repository, + isPublic bool, +) error { + if isPublic && !c.publicResourceCreationEnabled { + return errPublicRepoCreationDisabled } - return c.publicAccess.Set(ctx, scope, resource, true) + return c.publicAccess.Set(ctx, enum.PublicResourceTypeRepo, repo.Path, isPublic) } func createReadme(name, description string) []byte { diff --git a/app/api/controller/repo/create_branch.go b/app/api/controller/repo/create_branch.go index 7c74cdce2b..d1581de45c 100644 --- a/app/api/controller/repo/create_branch.go +++ b/app/api/controller/repo/create_branch.go @@ -50,10 +50,10 @@ func (c *Controller) CreateBranch(ctx context.Context, // set target to default branch in case no target was provided if in.Target == "" { - in.Target = repo.Repository.DefaultBranch + in.Target = repo.DefaultBranch } - rules, isRepoOwner, err := c.fetchRules(ctx, session, &repo.Repository) + rules, isRepoOwner, err := c.fetchRules(ctx, session, repo) if err != nil { return nil, nil, err } @@ -62,7 +62,7 @@ func (c *Controller) CreateBranch(ctx context.Context, Actor: &session.Principal, AllowBypass: in.BypassRules, IsRepoOwner: isRepoOwner, - Repo: &repo.Repository, + Repo: repo, RefAction: protection.RefActionCreate, RefType: protection.RefTypeBranch, RefNames: []string{in.Name}, @@ -74,7 +74,7 @@ func (c *Controller) CreateBranch(ctx context.Context, return nil, violations, nil } - writeParams, err := controller.CreateRPCInternalWriteParams(ctx, c.urlProvider, session, &repo.Repository) + writeParams, err := controller.CreateRPCInternalWriteParams(ctx, c.urlProvider, session, repo) if err != nil { return nil, nil, fmt.Errorf("failed to create RPC write params: %w", err) } diff --git a/app/api/controller/repo/create_commit_tag.go b/app/api/controller/repo/create_commit_tag.go index 399cc57137..c0584e59c8 100644 --- a/app/api/controller/repo/create_commit_tag.go +++ b/app/api/controller/repo/create_commit_tag.go @@ -54,10 +54,10 @@ func (c *Controller) CreateCommitTag(ctx context.Context, // set target to default branch in case no branch or commit was provided if in.Target == "" { - in.Target = repo.Repository.DefaultBranch + in.Target = repo.DefaultBranch } - rules, isRepoOwner, err := c.fetchRules(ctx, session, &repo.Repository) + rules, isRepoOwner, err := c.fetchRules(ctx, session, repo) if err != nil { return nil, nil, err } @@ -66,7 +66,7 @@ func (c *Controller) CreateCommitTag(ctx context.Context, Actor: &session.Principal, AllowBypass: in.BypassRules, IsRepoOwner: isRepoOwner, - Repo: &repo.Repository, + Repo: repo, RefAction: protection.RefActionCreate, RefType: protection.RefTypeTag, RefNames: []string{in.Name}, @@ -78,7 +78,7 @@ func (c *Controller) CreateCommitTag(ctx context.Context, return nil, violations, nil } - writeParams, err := controller.CreateRPCInternalWriteParams(ctx, c.urlProvider, session, &repo.Repository) + writeParams, err := controller.CreateRPCInternalWriteParams(ctx, c.urlProvider, session, repo) if err != nil { return nil, nil, fmt.Errorf("failed to create RPC write params: %w", err) } diff --git a/app/api/controller/repo/default_branch.go b/app/api/controller/repo/default_branch.go index 5ccac5af09..35e6e7cf7e 100644 --- a/app/api/controller/repo/default_branch.go +++ b/app/api/controller/repo/default_branch.go @@ -57,7 +57,7 @@ func (c *Controller) UpdateDefaultBranch( // requests will wait for previous ones to compelete before proceed unlock, err := c.locker.LockDefaultBranch( ctx, - repo.Repository.ID, + repo.ID, in.Name, // branch name only used for logging (lock is on repo) timeout+30*time.Second, // add 30s to the lock to give enough time for updating default branch ) @@ -66,7 +66,7 @@ func (c *Controller) UpdateDefaultBranch( } defer unlock() - writeParams, err := controller.CreateRPCInternalWriteParams(ctx, c.urlProvider, session, &repo.Repository) + writeParams, err := controller.CreateRPCInternalWriteParams(ctx, c.urlProvider, session, repo) if err != nil { return nil, fmt.Errorf("failed to create RPC write params: %w", err) } @@ -87,8 +87,8 @@ func (c *Controller) UpdateDefaultBranch( return nil, fmt.Errorf("failed to update the repo default branch: %w", err) } - oldName := repo.Repository.DefaultBranch - repoBase, err := c.repoStore.UpdateOptLock(ctx, &repo.Repository, func(r *types.Repository) error { + oldName := repo.DefaultBranch + repo, err = c.repoStore.UpdateOptLock(ctx, repo, func(r *types.Repository) error { r.DefaultBranch = in.Name return nil }) @@ -96,16 +96,11 @@ func (c *Controller) UpdateDefaultBranch( return nil, fmt.Errorf("failed to update the repo default branch on db:%w", err) } - repo = &Repository{ - Repository: *repoBase, - IsPublic: repo.IsPublic, - } - err = c.auditService.Log(ctx, session.Principal, - audit.NewResource(audit.ResourceTypeRepository, repo.Repository.Identifier), + audit.NewResource(audit.ResourceTypeRepository, repo.Identifier), audit.ActionUpdated, - paths.Parent(repo.Repository.Path), + paths.Parent(repo.Path), audit.WithOldObject(repoClone), audit.WithNewObject(repo), ) @@ -114,11 +109,11 @@ func (c *Controller) UpdateDefaultBranch( } c.eventReporter.DefaultBranchUpdated(ctx, &repoevents.DefaultBranchUpdatedPayload{ - RepoID: repoBase.ID, + RepoID: repo.ID, PrincipalID: bootstrap.NewSystemServiceSession().Principal.ID, OldName: oldName, - NewName: repoBase.DefaultBranch, + NewName: repo.DefaultBranch, }) - return repo, nil + return GetRepoOutput(ctx, c.publicAccess, repo) } diff --git a/app/api/controller/repo/delete_branch.go b/app/api/controller/repo/delete_branch.go index a368d6c235..3f064f9540 100644 --- a/app/api/controller/repo/delete_branch.go +++ b/app/api/controller/repo/delete_branch.go @@ -43,11 +43,11 @@ func (c *Controller) DeleteBranch(ctx context.Context, // ASSUMPTION: lower layer calls explicit branch api // and 'refs/heads/branch1' would fail if 'branch1' exists. // TODO: Add functional test to ensure the scenario is covered! - if branchName == repo.Repository.DefaultBranch { + if branchName == repo.DefaultBranch { return nil, usererror.ErrDefaultBranchCantBeDeleted } - rules, isRepoOwner, err := c.fetchRules(ctx, session, &repo.Repository) + rules, isRepoOwner, err := c.fetchRules(ctx, session, repo) if err != nil { return nil, err } @@ -56,7 +56,7 @@ func (c *Controller) DeleteBranch(ctx context.Context, Actor: &session.Principal, AllowBypass: bypassRules, IsRepoOwner: isRepoOwner, - Repo: &repo.Repository, + Repo: repo, RefAction: protection.RefActionDelete, RefType: protection.RefTypeBranch, RefNames: []string{branchName}, @@ -68,7 +68,7 @@ func (c *Controller) DeleteBranch(ctx context.Context, return violations, nil } - writeParams, err := controller.CreateRPCInternalWriteParams(ctx, c.urlProvider, session, &repo.Repository) + writeParams, err := controller.CreateRPCInternalWriteParams(ctx, c.urlProvider, session, repo) if err != nil { return nil, fmt.Errorf("failed to create RPC write params: %w", err) } diff --git a/app/api/controller/repo/delete_tag.go b/app/api/controller/repo/delete_tag.go index 776c3b5b8b..9912e64085 100644 --- a/app/api/controller/repo/delete_tag.go +++ b/app/api/controller/repo/delete_tag.go @@ -38,7 +38,7 @@ func (c *Controller) DeleteTag(ctx context.Context, return nil, err } - rules, isRepoOwner, err := c.fetchRules(ctx, session, &repo.Repository) + rules, isRepoOwner, err := c.fetchRules(ctx, session, repo) if err != nil { return nil, err } @@ -47,7 +47,7 @@ func (c *Controller) DeleteTag(ctx context.Context, Actor: &session.Principal, AllowBypass: bypassRules, IsRepoOwner: isRepoOwner, - Repo: &repo.Repository, + Repo: repo, RefAction: protection.RefActionDelete, RefType: protection.RefTypeTag, RefNames: []string{tagName}, @@ -59,7 +59,7 @@ func (c *Controller) DeleteTag(ctx context.Context, return violations, nil } - writeParams, err := controller.CreateRPCInternalWriteParams(ctx, c.urlProvider, session, &repo.Repository) + writeParams, err := controller.CreateRPCInternalWriteParams(ctx, c.urlProvider, session, repo) if err != nil { return nil, fmt.Errorf("failed to create RPC write params: %w", err) } diff --git a/app/api/controller/repo/diff.go b/app/api/controller/repo/diff.go index 69ad745df3..4bfb72e439 100644 --- a/app/api/controller/repo/diff.go +++ b/app/api/controller/repo/diff.go @@ -47,7 +47,7 @@ func (c *Controller) RawDiff( } return c.git.RawDiff(ctx, w, &git.DiffParams{ - ReadParams: git.CreateReadParams(&repo.Repository), + ReadParams: git.CreateReadParams(repo), BaseRef: info.BaseRef, HeadRef: info.HeadRef, MergeBase: info.MergeBase, @@ -67,7 +67,7 @@ func (c *Controller) CommitDiff( } return c.git.CommitDiff(ctx, &git.GetCommitParams{ - ReadParams: git.CreateReadParams(&repo.Repository), + ReadParams: git.CreateReadParams(repo), Revision: rev, }, w) } diff --git a/app/api/controller/repo/get_branch.go b/app/api/controller/repo/get_branch.go index b4578fc0f3..a1a06521fb 100644 --- a/app/api/controller/repo/get_branch.go +++ b/app/api/controller/repo/get_branch.go @@ -35,7 +35,7 @@ func (c *Controller) GetBranch(ctx context.Context, } rpcOut, err := c.git.GetBranch(ctx, &git.GetBranchParams{ - ReadParams: git.CreateReadParams(repo.Repository), + ReadParams: git.CreateReadParams(repo), BranchName: branchName, }) if err != nil { diff --git a/app/api/controller/repo/get_commit.go b/app/api/controller/repo/get_commit.go index 149e2451c7..ede7f7c4a8 100644 --- a/app/api/controller/repo/get_commit.go +++ b/app/api/controller/repo/get_commit.go @@ -37,7 +37,7 @@ func (c *Controller) GetCommit(ctx context.Context, } rpcOut, err := c.git.GetCommit(ctx, &git.GetCommitParams{ - ReadParams: git.CreateReadParams(repo.Repository), + ReadParams: git.CreateReadParams(repo), Revision: sha, }) if err != nil { diff --git a/app/api/controller/repo/get_commit_divergences.go b/app/api/controller/repo/get_commit_divergences.go index 90284257a1..dad31b230e 100644 --- a/app/api/controller/repo/get_commit_divergences.go +++ b/app/api/controller/repo/get_commit_divergences.go @@ -71,7 +71,7 @@ func (c *Controller) GetCommitDivergences(ctx context.Context, // map to rpc params options := &git.GetCommitDivergencesParams{ - ReadParams: git.CreateReadParams(repo.Repository), + ReadParams: git.CreateReadParams(repo), MaxCount: in.MaxCount, Requests: make([]git.CommitDivergenceRequest, len(in.Requests)), } @@ -80,7 +80,7 @@ func (c *Controller) GetCommitDivergences(ctx context.Context, options.Requests[i].To = in.Requests[i].To // backfil default branch if no 'to' was provided if len(options.Requests[i].To) == 0 { - options.Requests[i].To = repo.Repository.DefaultBranch + options.Requests[i].To = repo.DefaultBranch } } diff --git a/app/api/controller/repo/git_info_refs.go b/app/api/controller/repo/git_info_refs.go index 16ed15e280..3d9fbe09fd 100644 --- a/app/api/controller/repo/git_info_refs.go +++ b/app/api/controller/repo/git_info_refs.go @@ -39,7 +39,7 @@ func (c *Controller) GitInfoRefs( } if err = c.git.GetInfoRefs(ctx, w, &git.InfoRefsParams{ - ReadParams: git.CreateReadParams(repo.Repository), + ReadParams: git.CreateReadParams(repo), // TODO: git shouldn't take a random string here, but instead have accepted enum values. Service: string(service), Options: nil, diff --git a/app/api/controller/repo/git_service_pack.go b/app/api/controller/repo/git_service_pack.go index 84b84390d1..f4a436c480 100644 --- a/app/api/controller/repo/git_service_pack.go +++ b/app/api/controller/repo/git_service_pack.go @@ -59,13 +59,13 @@ func (c *Controller) GitServicePack( // setup read/writeparams depending on whether it's a write operation if isWriteOperation { var writeParams git.WriteParams - writeParams, err = controller.CreateRPCExternalWriteParams(ctx, c.urlProvider, session, &repo.Repository) + writeParams, err = controller.CreateRPCExternalWriteParams(ctx, c.urlProvider, session, repo) if err != nil { return fmt.Errorf("failed to create RPC write params: %w", err) } params.WriteParams = &writeParams } else { - readParams := git.CreateReadParams(repo.Repository) + readParams := git.CreateReadParams(repo) params.ReadParams = &readParams } diff --git a/app/api/controller/repo/helper.go b/app/api/controller/repo/helper.go index 51d406432b..8a698e2e81 100644 --- a/app/api/controller/repo/helper.go +++ b/app/api/controller/repo/helper.go @@ -24,16 +24,16 @@ import ( "github.com/harness/gitness/app/auth/authz" "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/store" + "github.com/harness/gitness/types" "github.com/harness/gitness/types/enum" ) // GetRepo fetches an active repo (not one that is currently being imported). func GetRepo( ctx context.Context, - publicAccess publicaccess.PublicAccess, repoStore store.RepoStore, repoRef string, -) (*Repository, error) { +) (*types.Repository, error) { if repoRef == "" { return nil, usererror.BadRequest("A valid repository reference must be provided.") } @@ -47,15 +47,7 @@ func GetRepo( return nil, usererror.BadRequest("Repository import is in progress.") } - isPublic, err := apiauth.CheckRepoIsPublic(ctx, publicAccess, repo) - if err != nil { - return nil, fmt.Errorf("failed to check if repo is public: %w", err) - } - - return &Repository{ - Repository: *repo, - IsPublic: isPublic, - }, nil + return repo, nil } // GetRepoCheckAccess fetches an active repo (not one that is currently being imported) @@ -64,19 +56,34 @@ func GetRepoCheckAccess( ctx context.Context, repoStore store.RepoStore, authorizer authz.Authorizer, - publicAccess publicaccess.PublicAccess, session *auth.Session, repoRef string, reqPermission enum.Permission, -) (*Repository, error) { - repo, err := GetRepo(ctx, publicAccess, repoStore, repoRef) +) (*types.Repository, error) { + repo, err := GetRepo(ctx, repoStore, repoRef) if err != nil { return nil, fmt.Errorf("failed to find repo: %w", err) } - if err = apiauth.CheckRepo(ctx, authorizer, session, &repo.Repository, reqPermission); err != nil { + if err = apiauth.CheckRepo(ctx, authorizer, session, repo, reqPermission); err != nil { return nil, fmt.Errorf("access check failed: %w", err) } return repo, nil } + +func GetRepoOutput( + ctx context.Context, + publicAccess publicaccess.PublicAccess, + repo *types.Repository, +) (*Repository, error) { + isPublic, err := apiauth.CheckRepoIsPublic(ctx, publicAccess, repo) + if err != nil { + return nil, fmt.Errorf("failed to check if repo is public: %w", err) + } + + return &Repository{ + Repository: *repo, + IsPublic: isPublic, + }, nil +} diff --git a/app/api/controller/repo/import.go b/app/api/controller/repo/import.go index 4f8a07418b..bb279bf672 100644 --- a/app/api/controller/repo/import.go +++ b/app/api/controller/repo/import.go @@ -82,11 +82,8 @@ func (c *Controller) Import(ctx context.Context, session *auth.Session, in *Impo return fmt.Errorf("failed to create repository in storage: %w", err) } - // update public resources - if isPublic && c.publicResourceCreationEnabled { - if err = c.SetPublicRepo(ctx, repo); err != nil { - return fmt.Errorf("failed to set a public repo: %w", err) - } + if err = c.SetRepoPublicAccess(ctx, repo, isPublic); err != nil { + return fmt.Errorf("failed to set repo public access: %w", err) } err = c.importer.Run(ctx, diff --git a/app/api/controller/repo/list_branches.go b/app/api/controller/repo/list_branches.go index 6d75f07d5e..a464da158f 100644 --- a/app/api/controller/repo/list_branches.go +++ b/app/api/controller/repo/list_branches.go @@ -44,7 +44,7 @@ func (c *Controller) ListBranches(ctx context.Context, } rpcOut, err := c.git.ListBranches(ctx, &git.ListBranchesParams{ - ReadParams: git.CreateReadParams(repo.Repository), + ReadParams: git.CreateReadParams(repo), IncludeCommit: includeCommit, Query: filter.Query, Sort: mapToRPCBranchSortOption(filter.Sort), diff --git a/app/api/controller/repo/list_commit_tags.go b/app/api/controller/repo/list_commit_tags.go index e0b41458b0..a4e0320e14 100644 --- a/app/api/controller/repo/list_commit_tags.go +++ b/app/api/controller/repo/list_commit_tags.go @@ -48,7 +48,7 @@ func (c *Controller) ListCommitTags(ctx context.Context, } rpcOut, err := c.git.ListCommitTags(ctx, &git.ListCommitTagsParams{ - ReadParams: git.CreateReadParams(repo.Repository), + ReadParams: git.CreateReadParams(repo), IncludeCommit: includeCommit, Query: filter.Query, Sort: mapToRPCTagSortOption(filter.Sort), diff --git a/app/api/controller/repo/list_commits.go b/app/api/controller/repo/list_commits.go index ae3e58ee32..44a5f82bdf 100644 --- a/app/api/controller/repo/list_commits.go +++ b/app/api/controller/repo/list_commits.go @@ -39,11 +39,11 @@ func (c *Controller) ListCommits(ctx context.Context, // set gitRef to default branch in case an empty reference was provided if gitRef == "" { - gitRef = repo.Repository.DefaultBranch + gitRef = repo.DefaultBranch } rpcOut, err := c.git.ListCommits(ctx, &git.ListCommitsParams{ - ReadParams: git.CreateReadParams(repo.Repository), + ReadParams: git.CreateReadParams(repo), GitREF: gitRef, After: filter.After, Page: int32(filter.Page), diff --git a/app/api/controller/repo/list_paths.go b/app/api/controller/repo/list_paths.go index 9549d61069..35cd827c41 100644 --- a/app/api/controller/repo/list_paths.go +++ b/app/api/controller/repo/list_paths.go @@ -42,11 +42,11 @@ func (c *Controller) ListPaths(ctx context.Context, // set gitRef to default branch in case an empty reference was provided if gitRef == "" { - gitRef = repo.Repository.DefaultBranch + gitRef = repo.DefaultBranch } rpcOut, err := c.git.ListPaths(ctx, &git.ListPathsParams{ - ReadParams: git.CreateReadParams(repo.Repository), + ReadParams: git.CreateReadParams(repo), GitREF: gitRef, IncludeDirectories: includeDirectories, }) diff --git a/app/api/controller/repo/list_pipelines.go b/app/api/controller/repo/list_pipelines.go index 8c1c2a16a0..95853668a7 100644 --- a/app/api/controller/repo/list_pipelines.go +++ b/app/api/controller/repo/list_pipelines.go @@ -37,7 +37,7 @@ func (c *Controller) ListPipelines( if err != nil { return nil, 0, fmt.Errorf("failed to find repo: %w", err) } - if err := apiauth.CheckPipeline(ctx, c.authorizer, session, repo.Repository.Path, "", enum.PermissionPipelineView); err != nil { + if err := apiauth.CheckPipeline(ctx, c.authorizer, session, repo.Path, "", enum.PermissionPipelineView); err != nil { return nil, 0, fmt.Errorf("access check failed: %w", err) } @@ -45,18 +45,18 @@ func (c *Controller) ListPipelines( var pipelines []*types.Pipeline err = c.tx.WithTx(ctx, func(ctx context.Context) (err error) { - count, err = c.pipelineStore.Count(ctx, repo.Repository.ID, filter) + count, err = c.pipelineStore.Count(ctx, repo.ID, filter) if err != nil { return fmt.Errorf("failed to count child executions: %w", err) } if !latest { - pipelines, err = c.pipelineStore.List(ctx, repo.Repository.ID, filter) + pipelines, err = c.pipelineStore.List(ctx, repo.ID, filter) if err != nil { return fmt.Errorf("failed to list pipelines: %w", err) } } else { - pipelines, err = c.pipelineStore.ListLatest(ctx, repo.Repository.ID, filter) + pipelines, err = c.pipelineStore.ListLatest(ctx, repo.ID, filter) if err != nil { return fmt.Errorf("failed to list latest pipelines: %w", err) } diff --git a/app/api/controller/repo/list_service_accounts.go b/app/api/controller/repo/list_service_accounts.go index e21e9ccf76..28c945741b 100644 --- a/app/api/controller/repo/list_service_accounts.go +++ b/app/api/controller/repo/list_service_accounts.go @@ -42,12 +42,12 @@ func (c *Controller) ListServiceAccounts( c.spaceStore, c.repoStore, enum.ParentResourceTypeRepo, - repo.Repository.ID, + repo.ID, "", enum.PermissionServiceAccountView, ); err != nil { return nil, fmt.Errorf("access check failed: %w", err) } - return c.principalStore.ListServiceAccounts(ctx, enum.ParentResourceTypeRepo, repo.Repository.ID) + return c.principalStore.ListServiceAccounts(ctx, enum.ParentResourceTypeRepo, repo.ID) } diff --git a/app/api/controller/repo/merge_check.go b/app/api/controller/repo/merge_check.go index cba1af3d5b..2cd18d4962 100644 --- a/app/api/controller/repo/merge_check.go +++ b/app/api/controller/repo/merge_check.go @@ -45,7 +45,7 @@ func (c *Controller) MergeCheck( return MergeCheck{}, err } - writeParams, err := controller.CreateRPCInternalWriteParams(ctx, c.urlProvider, session, &repo.Repository) + writeParams, err := controller.CreateRPCInternalWriteParams(ctx, c.urlProvider, session, repo) if err != nil { return MergeCheck{}, fmt.Errorf("failed to create rpc write params: %w", err) } diff --git a/app/api/controller/repo/pipeline_generate.go b/app/api/controller/repo/pipeline_generate.go index 5335309425..65142dad3c 100644 --- a/app/api/controller/repo/pipeline_generate.go +++ b/app/api/controller/repo/pipeline_generate.go @@ -35,7 +35,7 @@ func (c *Controller) PipelineGenerate( } result, err := c.git.GeneratePipeline(ctx, &git.GeneratePipelineParams{ - ReadParams: git.CreateReadParams(repo.Repository), + ReadParams: git.CreateReadParams(repo), }) if err != nil { return nil, fmt.Errorf("failed to generate pipeline: %w", err) diff --git a/app/api/controller/repo/public_access_update.go b/app/api/controller/repo/public_access_update.go index fc786456c9..048cebaa7c 100644 --- a/app/api/controller/repo/public_access_update.go +++ b/app/api/controller/repo/public_access_update.go @@ -18,10 +18,10 @@ import ( "context" "fmt" + apiauth "github.com/harness/gitness/app/api/auth" "github.com/harness/gitness/app/auth" "github.com/harness/gitness/app/paths" "github.com/harness/gitness/audit" - "github.com/harness/gitness/types" "github.com/harness/gitness/types/enum" "github.com/rs/zerolog/log" @@ -31,49 +31,48 @@ type PublicAccessUpdateInput struct { EnablePublic bool `json:"enable_public"` } -type PublicAccessUpdateOutput struct { - IsPublic bool `json:"is_public"` -} - func (c *Controller) PublicAccessUpdate(ctx context.Context, session *auth.Session, repoRef string, in *PublicAccessUpdateInput, -) (*PublicAccessUpdateOutput, error) { +) (*Repository, error) { repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoEdit) if err != nil { return nil, err } - repoClone := repo.Clone() - if err = c.sanitizeVisibilityInput(in); err != nil { return nil, fmt.Errorf("failed to sanitize input: %w", err) } - parentSpace, name, err := paths.DisectLeaf(repo.Repository.Path) + repoClone := repo.Clone() + + // get current public access vale for audit + isPublic, err := apiauth.CheckRepoIsPublic(ctx, c.publicAccess, repo) if err != nil { - return nil, fmt.Errorf("failed to disect path '%s': %w", repo.Repository.Path, err) + return nil, fmt.Errorf("failed to check current public access status: %w", err) } - scope := &types.Scope{SpacePath: parentSpace} - resource := &types.Resource{ - Type: enum.ResourceTypeRepo, - Identifier: name, + // no op + if isPublic == in.EnablePublic { + return GetRepoOutput(ctx, c.publicAccess, repo) } - if err = c.publicAccess.Set(ctx, scope, resource, in.EnablePublic); err != nil { + if err = c.publicAccess.Set(ctx, enum.PublicResourceTypeRepo, repo.Path, in.EnablePublic); err != nil { return nil, fmt.Errorf("failed to update repo public access: %w", err) } err = c.auditService.Log(ctx, session.Principal, - audit.NewResource(audit.ResourceTypeRepository, repo.Repository.Identifier), + audit.NewResource(audit.ResourceTypeRepository, repo.Identifier), audit.ActionUpdated, - paths.Parent(repo.Repository.Path), - audit.WithOldObject(repoClone), + paths.Parent(repo.Path), + audit.WithOldObject(&Repository{ + Repository: repoClone, + IsPublic: isPublic, + }), audit.WithNewObject(&Repository{ - Repository: repo.Repository, + Repository: *repo, IsPublic: in.EnablePublic, }), ) @@ -81,9 +80,7 @@ func (c *Controller) PublicAccessUpdate(ctx context.Context, log.Ctx(ctx).Warn().Msgf("failed to insert audit log for update repository operation: %s", err) } - return &PublicAccessUpdateOutput{ - in.EnablePublic, - }, nil + return GetRepoOutput(ctx, c.publicAccess, repo) } diff --git a/app/api/controller/repo/purge.go b/app/api/controller/repo/purge.go index ce65f2322d..eb93ad09ff 100644 --- a/app/api/controller/repo/purge.go +++ b/app/api/controller/repo/purge.go @@ -23,7 +23,6 @@ import ( "github.com/harness/gitness/app/api/usererror" "github.com/harness/gitness/app/auth" repoevents "github.com/harness/gitness/app/events/repo" - "github.com/harness/gitness/app/paths" "github.com/harness/gitness/errors" "github.com/harness/gitness/git" "github.com/harness/gitness/types" @@ -79,7 +78,7 @@ func (c *Controller) PurgeNoAuth( } if isPublic { - if err := c.disablePublicRepo(ctx, repo); err != nil { + if err := c.SetRepoPublicAccess(ctx, repo, false); err != nil { log.Ctx(ctx).Err(err).Msg("failed to disable repo public access") } } @@ -124,18 +123,3 @@ func (c *Controller) DeleteGitRepository( } return nil } - -func (c *Controller) disablePublicRepo(ctx context.Context, repo *types.Repository) error { - parentSpace, name, err := paths.DisectLeaf(repo.Path) - if err != nil { - return fmt.Errorf("failed to disect path '%s': %w", repo.Path, err) - } - - scope := &types.Scope{SpacePath: parentSpace} - resource := &types.Resource{ - Type: enum.ResourceTypeRepo, - Identifier: name, - } - - return c.publicAccess.Set(ctx, scope, resource, false) -} diff --git a/app/api/controller/repo/raw.go b/app/api/controller/repo/raw.go index 96dc960e10..464adead03 100644 --- a/app/api/controller/repo/raw.go +++ b/app/api/controller/repo/raw.go @@ -40,11 +40,11 @@ func (c *Controller) Raw(ctx context.Context, // set gitRef to default branch in case an empty reference was provided if gitRef == "" { - gitRef = repo.Repository.DefaultBranch + gitRef = repo.DefaultBranch } // create read params once - readParams := git.CreateReadParams(repo.Repository) + readParams := git.CreateReadParams(repo) treeNodeOutput, err := c.git.GetTreeNode(ctx, &git.GetTreeNodeParams{ ReadParams: readParams, GitREF: gitRef, diff --git a/app/api/controller/repo/rule_create.go b/app/api/controller/repo/rule_create.go index bc7edcfec9..0330eda908 100644 --- a/app/api/controller/repo/rule_create.go +++ b/app/api/controller/repo/rule_create.go @@ -100,7 +100,7 @@ func (c *Controller) RuleCreate(ctx context.Context, CreatedBy: session.Principal.ID, Created: now, Updated: now, - RepoID: &repo.Repository.ID, + RepoID: &repo.ID, SpaceID: nil, Type: in.Type, State: in.State, @@ -120,7 +120,7 @@ func (c *Controller) RuleCreate(ctx context.Context, session.Principal, audit.NewResource(audit.ResourceTypeBranchRule, r.Identifier), audit.ActionCreated, - paths.Parent(repo.Repository.Path), + paths.Parent(repo.Path), audit.WithNewObject(r), ) if err != nil { diff --git a/app/api/controller/repo/rule_delete.go b/app/api/controller/repo/rule_delete.go index 124820e88a..2d839c5775 100644 --- a/app/api/controller/repo/rule_delete.go +++ b/app/api/controller/repo/rule_delete.go @@ -37,7 +37,7 @@ func (c *Controller) RuleDelete(ctx context.Context, return err } - r, err := c.ruleStore.FindByIdentifier(ctx, nil, &repo.Repository.ID, identifier) + r, err := c.ruleStore.FindByIdentifier(ctx, nil, &repo.ID, identifier) if err != nil { return fmt.Errorf("failed to find repository-level protection rule by identifier: %w", err) } @@ -51,7 +51,7 @@ func (c *Controller) RuleDelete(ctx context.Context, session.Principal, audit.NewResource(audit.ResourceTypeBranchRule, r.Identifier), audit.ActionDeleted, - paths.Parent(repo.Repository.Path), + paths.Parent(repo.Path), audit.WithOldObject(r), ) if err != nil { diff --git a/app/api/controller/repo/rule_find.go b/app/api/controller/repo/rule_find.go index 415bfec9ec..53d3949641 100644 --- a/app/api/controller/repo/rule_find.go +++ b/app/api/controller/repo/rule_find.go @@ -34,7 +34,7 @@ func (c *Controller) RuleFind(ctx context.Context, return nil, err } - r, err := c.ruleStore.FindByIdentifier(ctx, nil, &repo.Repository.ID, identifier) + r, err := c.ruleStore.FindByIdentifier(ctx, nil, &repo.ID, identifier) if err != nil { return nil, fmt.Errorf("failed to find repository-level protection rule by identifier: %w", err) } diff --git a/app/api/controller/repo/rule_list.go b/app/api/controller/repo/rule_list.go index 904424ffe7..36a17652b3 100644 --- a/app/api/controller/repo/rule_list.go +++ b/app/api/controller/repo/rule_list.go @@ -39,7 +39,7 @@ func (c *Controller) RuleList(ctx context.Context, var count int64 err = c.tx.WithTx(ctx, func(ctx context.Context) error { - list, err = c.ruleStore.List(ctx, nil, &repo.Repository.ID, filter) + list, err = c.ruleStore.List(ctx, nil, &repo.ID, filter) if err != nil { return fmt.Errorf("failed to list repository-level protection rules: %w", err) } @@ -49,7 +49,7 @@ func (c *Controller) RuleList(ctx context.Context, return nil } - count, err = c.ruleStore.Count(ctx, nil, &repo.Repository.ID, filter) + count, err = c.ruleStore.Count(ctx, nil, &repo.ID, filter) if err != nil { return fmt.Errorf("failed to count repository-level protection rules: %w", err) } diff --git a/app/api/controller/repo/rule_update.go b/app/api/controller/repo/rule_update.go index a7682c8d83..18632a262b 100644 --- a/app/api/controller/repo/rule_update.go +++ b/app/api/controller/repo/rule_update.go @@ -96,7 +96,7 @@ func (c *Controller) RuleUpdate(ctx context.Context, return nil, err } - r, err := c.ruleStore.FindByIdentifier(ctx, nil, &repo.Repository.ID, identifier) + r, err := c.ruleStore.FindByIdentifier(ctx, nil, &repo.ID, identifier) if err != nil { return nil, fmt.Errorf("failed to get a repository rule by its identifier: %w", err) } @@ -142,7 +142,7 @@ func (c *Controller) RuleUpdate(ctx context.Context, session.Principal, audit.NewResource(audit.ResourceTypeBranchRule, r.Identifier), audit.ActionUpdated, - paths.Parent(repo.Repository.Path), + paths.Parent(repo.Path), audit.WithOldObject(oldRule), audit.WithNewObject(r), ) diff --git a/app/api/controller/repo/update.go b/app/api/controller/repo/update.go index 2f11f1e8f5..e178c5450d 100644 --- a/app/api/controller/repo/update.go +++ b/app/api/controller/repo/update.go @@ -19,7 +19,6 @@ import ( "fmt" "strings" - apiauth "github.com/harness/gitness/app/api/auth" "github.com/harness/gitness/app/auth" "github.com/harness/gitness/app/paths" "github.com/harness/gitness/audit" @@ -52,15 +51,15 @@ func (c *Controller) Update(ctx context.Context, repoClone := repo.Clone() - if !in.hasChanges(&repo.Repository) { - return repo, nil + if !in.hasChanges(repo) { + return GetRepoOutput(ctx, c.publicAccess, repo) } if err = c.sanitizeUpdateInput(in); err != nil { return nil, fmt.Errorf("failed to sanitize input: %w", err) } - repoBase, err := c.repoStore.UpdateOptLock(ctx, &repo.Repository, func(repo *types.Repository) error { + repo, err = c.repoStore.UpdateOptLock(ctx, repo, func(repo *types.Repository) error { // update values only if provided if in.Description != nil { repo.Description = *in.Description @@ -72,21 +71,11 @@ func (c *Controller) Update(ctx context.Context, return nil, err } - isPublic, err := apiauth.CheckRepoIsPublic(ctx, c.publicAccess, repoBase) - if err != nil { - return nil, fmt.Errorf("failed to get resource public access mode: %w", err) - } - - repo = &Repository{ - Repository: *repoBase, - IsPublic: isPublic, - } - err = c.auditService.Log(ctx, session.Principal, - audit.NewResource(audit.ResourceTypeRepository, repo.Repository.Identifier), + audit.NewResource(audit.ResourceTypeRepository, repo.Identifier), audit.ActionUpdated, - paths.Parent(repo.Repository.Path), + paths.Parent(repo.Path), audit.WithOldObject(repoClone), audit.WithNewObject(repo), ) @@ -95,9 +84,9 @@ func (c *Controller) Update(ctx context.Context, } // backfill repo url - repo.Repository.GitURL = c.urlProvider.GenerateGITCloneURL(repo.Repository.Path) + repo.GitURL = c.urlProvider.GenerateGITCloneURL(repo.Path) - return repo, nil + return GetRepoOutput(ctx, c.publicAccess, repo) } func (c *Controller) sanitizeUpdateInput(in *UpdateInput) error { diff --git a/app/api/controller/reposettings/controller.go b/app/api/controller/reposettings/controller.go index 3a40594290..f59a875735 100644 --- a/app/api/controller/reposettings/controller.go +++ b/app/api/controller/reposettings/controller.go @@ -20,10 +20,10 @@ import ( "github.com/harness/gitness/app/api/controller/repo" "github.com/harness/gitness/app/auth" "github.com/harness/gitness/app/auth/authz" - "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/services/settings" "github.com/harness/gitness/app/store" "github.com/harness/gitness/audit" + "github.com/harness/gitness/types" "github.com/harness/gitness/types/enum" ) @@ -31,7 +31,6 @@ type Controller struct { authorizer authz.Authorizer repoStore store.RepoStore settings *settings.Service - publicAccess publicaccess.PublicAccess auditService audit.Service } @@ -39,14 +38,12 @@ func NewController( authorizer authz.Authorizer, repoStore store.RepoStore, settings *settings.Service, - publicAccess publicaccess.PublicAccess, auditService audit.Service, ) *Controller { return &Controller{ authorizer: authorizer, repoStore: repoStore, settings: settings, - publicAccess: publicAccess, auditService: auditService, } } @@ -58,12 +55,11 @@ func (c *Controller) getRepoCheckAccess( session *auth.Session, repoRef string, reqPermission enum.Permission, -) (*repo.Repository, error) { +) (*types.Repository, error) { return repo.GetRepoCheckAccess( ctx, c.repoStore, c.authorizer, - c.publicAccess, session, repoRef, reqPermission, diff --git a/app/api/controller/reposettings/general_find.go b/app/api/controller/reposettings/general_find.go index c6aded4026..d83bbaf817 100644 --- a/app/api/controller/reposettings/general_find.go +++ b/app/api/controller/reposettings/general_find.go @@ -35,7 +35,7 @@ func (c *Controller) GeneralFind( out := GetDefaultGeneralSettings() mappings := GetGeneralSettingsMappings(out) - err = c.settings.RepoMap(ctx, repo.Repository.ID, mappings...) + err = c.settings.RepoMap(ctx, repo.ID, mappings...) if err != nil { return nil, fmt.Errorf("failed to map settings: %w", err) } diff --git a/app/api/controller/reposettings/general_update.go b/app/api/controller/reposettings/general_update.go index 6809d2d0b6..cd9d704a52 100644 --- a/app/api/controller/reposettings/general_update.go +++ b/app/api/controller/reposettings/general_update.go @@ -41,12 +41,12 @@ func (c *Controller) GeneralUpdate( // read old settings values old := GetDefaultGeneralSettings() oldMappings := GetGeneralSettingsMappings(old) - err = c.settings.RepoMap(ctx, repo.Repository.ID, oldMappings...) + err = c.settings.RepoMap(ctx, repo.ID, oldMappings...) if err != nil { return nil, fmt.Errorf("failed to map settings (old): %w", err) } - err = c.settings.RepoSetMany(ctx, repo.Repository.ID, GetGeneralSettingsAsKeyValues(in)...) + err = c.settings.RepoSetMany(ctx, repo.ID, GetGeneralSettingsAsKeyValues(in)...) if err != nil { return nil, fmt.Errorf("failed to set settings: %w", err) } @@ -54,16 +54,16 @@ func (c *Controller) GeneralUpdate( // read all settings and return complete config out := GetDefaultGeneralSettings() mappings := GetGeneralSettingsMappings(out) - err = c.settings.RepoMap(ctx, repo.Repository.ID, mappings...) + err = c.settings.RepoMap(ctx, repo.ID, mappings...) if err != nil { return nil, fmt.Errorf("failed to map settings: %w", err) } err = c.auditService.Log(ctx, session.Principal, - audit.NewResource(audit.ResourceTypeRepositorySettings, repo.Repository.Identifier), + audit.NewResource(audit.ResourceTypeRepositorySettings, repo.Identifier), audit.ActionUpdated, - paths.Parent(repo.Repository.Path), + paths.Parent(repo.Path), audit.WithOldObject(old), audit.WithNewObject(out), ) diff --git a/app/api/controller/reposettings/wire.go b/app/api/controller/reposettings/wire.go index d269cb02c5..22c57be2f4 100644 --- a/app/api/controller/reposettings/wire.go +++ b/app/api/controller/reposettings/wire.go @@ -16,7 +16,6 @@ package reposettings import ( "github.com/harness/gitness/app/auth/authz" - "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/services/settings" "github.com/harness/gitness/app/store" "github.com/harness/gitness/audit" @@ -33,8 +32,7 @@ func ProvideController( authorizer authz.Authorizer, repoStore store.RepoStore, settings *settings.Service, - publicAccess publicaccess.PublicAccess, auditService audit.Service, ) *Controller { - return NewController(authorizer, repoStore, settings, publicAccess, auditService) + return NewController(authorizer, repoStore, settings, auditService) } diff --git a/app/api/controller/space/create.go b/app/api/controller/space/create.go index b979b60142..bd26afe41f 100644 --- a/app/api/controller/space/create.go +++ b/app/api/controller/space/create.go @@ -146,10 +146,8 @@ func (c *Controller) createSpaceInnerInTX( } } - if in.IsPublic { - if err := c.setPublicSpace(ctx, space); err != nil { - return nil, fmt.Errorf("failed to insert a public resource: %w", err) - } + if err := c.setSpacePublicAccess(ctx, space, in.IsPublic); err != nil { + return nil, fmt.Errorf("failed to set a space public: %w", err) } return space, nil @@ -189,19 +187,16 @@ func (c *Controller) getSpaceCheckAuthSpaceCreation( return parentSpace, nil } -func (c *Controller) setPublicSpace(ctx context.Context, space *types.Space) error { - parentSpace, name, err := paths.DisectLeaf(space.Path) - if err != nil { - return fmt.Errorf("failed to disect path '%s': %w", space.Path, err) - } - - scope := &types.Scope{SpacePath: parentSpace} - resource := &types.Resource{ - Type: enum.ResourceTypeSpace, - Identifier: name, +func (c *Controller) setSpacePublicAccess( + ctx context.Context, + space *types.Space, + isPublic bool, +) error { + if isPublic && !c.publicResourceCreationEnabled { + return errPublicSpaceCreationDisabled } - return c.publicAccess.Set(ctx, scope, resource, true) + return c.publicAccess.Set(ctx, enum.PublicResourceTypeSpace, space.Path, isPublic) } func (c *Controller) sanitizeCreateInput(in *CreateInput) error { diff --git a/types/public_resource.go b/app/api/controller/space/helper.go similarity index 52% rename from types/public_resource.go rename to app/api/controller/space/helper.go index 226277b1e2..bf32e2c5f7 100644 --- a/types/public_resource.go +++ b/app/api/controller/space/helper.go @@ -12,12 +12,29 @@ // See the License for the specific language governing permissions and // limitations under the License. -package types +package space -import "github.com/harness/gitness/types/enum" +import ( + "context" + "fmt" -// PublicResource defines a public resource info. -type PublicResource struct { - Type enum.PublicResourceType - ID int64 + apiauth "github.com/harness/gitness/app/api/auth" + "github.com/harness/gitness/app/services/publicaccess" + "github.com/harness/gitness/types" +) + +func GetSpaceOutput( + ctx context.Context, + publicAccess publicaccess.PublicAccess, + space *types.Space, +) (*Space, error) { + isPublic, err := apiauth.CheckSpaceIsPublic(ctx, publicAccess, space) + if err != nil { + return nil, fmt.Errorf("failed to get resource public access mode: %w", err) + } + + return &Space{ + Space: *space, + IsPublic: isPublic, + }, nil } diff --git a/app/api/controller/space/import.go b/app/api/controller/space/import.go index 299af9e2f9..b7b778b70c 100644 --- a/app/api/controller/space/import.go +++ b/app/api/controller/space/import.go @@ -98,12 +98,10 @@ func (c *Controller) Import(ctx context.Context, session *auth.Session, in *Impo repoIDs[i] = repo.ID cloneURLs[i] = remoteRepository.CloneURL - // update public resources - if isPublic && c.publicResourceCreationEnabled { - if err := c.repoCtrl.SetPublicRepo(ctx, repo); err != nil { - return fmt.Errorf("failed to set a public repo: %w", err) - } + if err := c.repoCtrl.SetRepoPublicAccess(ctx, repo, isPublic); err != nil { + return fmt.Errorf("failed to set repo public access: %w", err) } + } jobGroupID := fmt.Sprintf("space-import-%d", space.ID) diff --git a/app/api/controller/space/import_repositories.go b/app/api/controller/space/import_repositories.go index 764666245d..0924fcb7b6 100644 --- a/app/api/controller/space/import_repositories.go +++ b/app/api/controller/space/import_repositories.go @@ -126,11 +126,8 @@ func (c *Controller) ImportRepositories( return fmt.Errorf("failed to create repository in storage: %w", err) } - // update public resources - if isPublic && c.publicResourceCreationEnabled { - if err := c.repoCtrl.SetPublicRepo(ctx, repo); err != nil { - return fmt.Errorf("failed to set a public repo: %w", err) - } + if err := c.repoCtrl.SetRepoPublicAccess(ctx, repo, isPublic); err != nil { + return fmt.Errorf("failed to set repo public access: %w", err) } repos = append(repos, repo) diff --git a/app/api/controller/space/update.go b/app/api/controller/space/update.go index 89cc1d5279..b9f5e013a7 100644 --- a/app/api/controller/space/update.go +++ b/app/api/controller/space/update.go @@ -47,18 +47,8 @@ func (c *Controller) Update(ctx context.Context, session *auth.Session, return nil, err } - isPublic, err := apiauth.CheckSpaceIsPublic(ctx, c.publicAccess, space) - if err != nil { - return nil, fmt.Errorf("failed to get resource public access mode: %w", err) - } - - spaceData := &Space{ - Space: *space, - IsPublic: isPublic, - } - if !in.hasChanges(space) { - return spaceData, nil + return GetSpaceOutput(ctx, c.publicAccess, space) } if err = c.sanitizeUpdateInput(in); err != nil { @@ -77,10 +67,7 @@ func (c *Controller) Update(ctx context.Context, session *auth.Session, return nil, err } - return &Space{ - Space: *space, - IsPublic: isPublic, - }, nil + return GetSpaceOutput(ctx, c.publicAccess, space) } func (c *Controller) sanitizeUpdateInput(in *UpdateInput) error { diff --git a/app/api/controller/webhook/controller.go b/app/api/controller/webhook/controller.go index 410fc48c28..1b6628535d 100644 --- a/app/api/controller/webhook/controller.go +++ b/app/api/controller/webhook/controller.go @@ -22,7 +22,6 @@ import ( "github.com/harness/gitness/app/api/usererror" "github.com/harness/gitness/app/auth" "github.com/harness/gitness/app/auth/authz" - "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/services/webhook" "github.com/harness/gitness/app/store" "github.com/harness/gitness/encrypt" @@ -40,7 +39,6 @@ type Controller struct { repoStore store.RepoStore webhookService *webhook.Service encrypter encrypt.Encrypter - publicAccess publicaccess.PublicAccess } func NewController( @@ -52,7 +50,6 @@ func NewController( repoStore store.RepoStore, webhookService *webhook.Service, encrypter encrypt.Encrypter, - publicAccess publicaccess.PublicAccess, ) *Controller { return &Controller{ allowLoopback: allowLoopback, @@ -63,7 +60,6 @@ func NewController( repoStore: repoStore, webhookService: webhookService, encrypter: encrypter, - publicAccess: publicAccess, } } diff --git a/app/api/controller/webhook/wire.go b/app/api/controller/webhook/wire.go index c810634759..749f0d0f9c 100644 --- a/app/api/controller/webhook/wire.go +++ b/app/api/controller/webhook/wire.go @@ -16,7 +16,6 @@ package webhook import ( "github.com/harness/gitness/app/auth/authz" - "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/services/webhook" "github.com/harness/gitness/app/store" "github.com/harness/gitness/encrypt" @@ -31,10 +30,10 @@ var WireSet = wire.NewSet( func ProvideController(config webhook.Config, authorizer authz.Authorizer, webhookStore store.WebhookStore, webhookExecutionStore store.WebhookExecutionStore, - repoStore store.RepoStore, webhookService *webhook.Service, encrypter encrypt.Encrypter, publicAccess publicaccess.PublicAccess, + repoStore store.RepoStore, webhookService *webhook.Service, encrypter encrypt.Encrypter, ) *Controller { return NewController( config.AllowLoopback, config.AllowPrivateNetwork, authorizer, webhookStore, webhookExecutionStore, - repoStore, webhookService, encrypter, publicAccess) + repoStore, webhookService, encrypter) } diff --git a/app/auth/anonymous.go b/app/auth/anonymouse.go similarity index 73% rename from app/auth/anonymous.go rename to app/auth/anonymouse.go index 338ee19a22..ad8e97fa42 100644 --- a/app/auth/anonymous.go +++ b/app/auth/anonymouse.go @@ -19,12 +19,10 @@ import ( "github.com/harness/gitness/types/enum" ) -// Anonymous is an in-memory principal for users with no auth data. -// Authorizer is in charge of handling public access. -func Anonymous() *types.Principal { - return &types.Principal{ - ID: -1, - UID: "ALL_USERS", - Type: enum.PrincipalTypeUser, - } +// anonymousPrincipal is an in-memory principal for users with no auth data. +// Authorizer is in charge of handling anonymouse access. +var AnonymousPrincipal = types.Principal{ + ID: -1, + UID: "anonymous", + Type: enum.PrincipalTypeUser, } diff --git a/app/auth/authn/jwt.go b/app/auth/authn/jwt.go index edbf620d5b..1cf58318c6 100644 --- a/app/auth/authn/jwt.go +++ b/app/auth/authn/jwt.go @@ -57,7 +57,7 @@ func (a *JWTAuthenticator) Authenticate(r *http.Request) (*auth.Session, error) if len(str) == 0 { return &auth.Session{ - Principal: *auth.Anonymous(), + Principal: auth.AnonymousPrincipal, }, nil } diff --git a/app/auth/authz/membership.go b/app/auth/authz/membership.go index bd8033ff0d..6abea8606f 100644 --- a/app/auth/authz/membership.go +++ b/app/auth/authz/membership.go @@ -55,12 +55,12 @@ func (a *MembershipAuthorizer) Check( resource *types.Resource, permission enum.Permission, ) (bool, error) { - isPublic, err := a.CheckPublicAccess(ctx, scope, resource, permission) + publicAccessAllowed, err := a.CheckPublicAccess(ctx, scope, resource, permission) if err != nil { return false, fmt.Errorf("failed to check public access: %w", err) } - if isPublic { + if publicAccessAllowed { return true, nil } diff --git a/app/auth/authz/public_access.go b/app/auth/authz/public_access.go index 2e263df949..2ff226439f 100644 --- a/app/auth/authz/public_access.go +++ b/app/auth/authz/public_access.go @@ -17,6 +17,7 @@ package authz import ( "context" + "github.com/harness/gitness/app/paths" "github.com/harness/gitness/types" "github.com/harness/gitness/types/enum" ) @@ -33,11 +34,19 @@ func (a *MembershipAuthorizer) CheckPublicAccess( return false, nil } - // public access is enabled on these resource types. - if resource.Type != enum.ResourceTypeRepo && - resource.Type != enum.ResourceTypeSpace { - return false, nil + pubResType, pubResPath := mapResource(scope, resource) + + return a.publicAccess.Get(ctx, pubResType, pubResPath) +} + +func mapResource(scope *types.Scope, resource *types.Resource, +) (enum.PublicResourceType, string) { + pubResType := enum.PublicResourceTypeSpace + + if resource.Type == enum.ResourceTypeRepo && + resource.Identifier != "" { + pubResType = enum.PublicResourceTypeRepo } - return a.publicAccess.Get(ctx, scope, resource) + return pubResType, paths.Concatenate(scope.SpacePath, resource.Identifier) } diff --git a/app/pipeline/converter/converter.go b/app/pipeline/converter/converter.go index 87a61d1143..bbd673db1a 100644 --- a/app/pipeline/converter/converter.go +++ b/app/pipeline/converter/converter.go @@ -21,6 +21,8 @@ import ( "github.com/harness/gitness/app/pipeline/converter/jsonnet" "github.com/harness/gitness/app/pipeline/converter/starlark" "github.com/harness/gitness/app/pipeline/file" + "github.com/harness/gitness/app/services/publicaccess" + "github.com/harness/gitness/types/enum" ) const ( @@ -30,7 +32,8 @@ const ( ) type converter struct { - fileService file.Service + fileService file.Service + publicaccess publicaccess.PublicAccess } func newConverter(fileService file.Service) Service { @@ -40,14 +43,20 @@ func newConverter(fileService file.Service) Service { func (c *converter) Convert(_ context.Context, args *ConvertArgs) (*file.File, error) { path := args.Pipeline.ConfigPath + // get public access visibility of the repo + repoIsPublic, err := c.publicaccess.Get(context.Background(), enum.PublicResourceTypeRepo, args.Repo.Path) + if err != nil { + return nil, err + } + if isJSONNet(path) { - str, err := jsonnet.Parse(args.Repo, args.Pipeline, args.Execution, args.File, c.fileService, jsonnetImportLimit) + str, err := jsonnet.Parse(args.Repo, repoIsPublic, args.Pipeline, args.Execution, args.File, c.fileService, jsonnetImportLimit) if err != nil { return nil, err } return &file.File{Data: []byte(str)}, nil } else if isStarlark(path) { - str, err := starlark.Parse(args.Repo, args.Pipeline, args.Execution, args.File, starlarkStepLimit, starlarkSizeLimit) + str, err := starlark.Parse(args.Repo, repoIsPublic, args.Pipeline, args.Execution, args.File, starlarkStepLimit, starlarkSizeLimit) if err != nil { return nil, err } diff --git a/app/pipeline/converter/jsonnet/jsonnet.go b/app/pipeline/converter/jsonnet/jsonnet.go index a3b90a950b..f1e6f485c5 100644 --- a/app/pipeline/converter/jsonnet/jsonnet.go +++ b/app/pipeline/converter/jsonnet/jsonnet.go @@ -23,7 +23,6 @@ import ( "strconv" "strings" - repoCtrl "github.com/harness/gitness/app/api/controller/repo" "github.com/harness/gitness/app/pipeline/file" "github.com/harness/gitness/types" @@ -37,7 +36,7 @@ const param = "param." var noContext = context.Background() type importer struct { - repo *repoCtrl.Repository + repo *types.Repository execution *types.Execution // jsonnet does not cache file imports and may request @@ -104,7 +103,8 @@ func (i *importer) Import(importedFrom, importedPath string) (contents jsonnet.C } func Parse( - repo *repoCtrl.Repository, + repo *types.Repository, + repoIsPublic bool, pipeline *types.Pipeline, execution *types.Execution, file *file.File, @@ -131,7 +131,7 @@ func Parse( mapBuild(execution, vm) } if repo != nil { - mapRepo(repo, pipeline, vm) + mapRepo(repo, pipeline, vm, repoIsPublic) } jsonnetFile := file @@ -189,24 +189,24 @@ func mapBuild(v *types.Execution, vm *jsonnet.VM) { // mapBuild populates repo level variables available to jsonnet templates. // Since we want to maintain compatibility with drone 2.x, the older format // needs to be maintained (even if the variables do not exist in gitness). -func mapRepo(v *repoCtrl.Repository, p *types.Pipeline, vm *jsonnet.VM) { +func mapRepo(v *types.Repository, p *types.Pipeline, vm *jsonnet.VM, publicRepo bool) { namespace := v.Path idx := strings.LastIndex(v.Path, "/") if idx != -1 { namespace = v.Path[:idx] } // TODO [CODE-1363]: remove after identifier migration. - vm.ExtVar(repo+"uid", v.Repository.Identifier) - vm.ExtVar(repo+"identifier", v.Repository.Identifier) - vm.ExtVar(repo+"name", v.Repository.Identifier) + vm.ExtVar(repo+"uid", v.Identifier) + vm.ExtVar(repo+"identifier", v.Identifier) + vm.ExtVar(repo+"name", v.Identifier) vm.ExtVar(repo+"namespace", namespace) - vm.ExtVar(repo+"slug", v.Repository.Path) - vm.ExtVar(repo+"git_http_url", v.Repository.GitURL) - vm.ExtVar(repo+"git_ssh_url", v.Repository.GitURL) - vm.ExtVar(repo+"link", v.Repository.GitURL) - vm.ExtVar(repo+"branch", v.Repository.DefaultBranch) + vm.ExtVar(repo+"slug", v.Path) + vm.ExtVar(repo+"git_http_url", v.GitURL) + vm.ExtVar(repo+"git_ssh_url", v.GitURL) + vm.ExtVar(repo+"link", v.GitURL) + vm.ExtVar(repo+"branch", v.DefaultBranch) vm.ExtVar(repo+"config", p.ConfigPath) - vm.ExtVar(repo+"private", strconv.FormatBool(!v.IsPublic)) + vm.ExtVar(repo+"private", strconv.FormatBool(!publicRepo)) vm.ExtVar(repo+"visibility", "internal") vm.ExtVar(repo+"active", strconv.FormatBool(true)) vm.ExtVar(repo+"trusted", strconv.FormatBool(true)) diff --git a/app/pipeline/converter/service.go b/app/pipeline/converter/service.go index 6a4bcb5bae..89c76f18a6 100644 --- a/app/pipeline/converter/service.go +++ b/app/pipeline/converter/service.go @@ -17,7 +17,6 @@ package converter import ( "context" - "github.com/harness/gitness/app/api/controller/repo" "github.com/harness/gitness/app/pipeline/file" "github.com/harness/gitness/types" ) @@ -26,10 +25,11 @@ type ( // ConvertArgs represents a request to the pipeline // conversion service. ConvertArgs struct { - Repo *repo.Repository `json:"repository,omitempty"` - Pipeline *types.Pipeline `json:"pipeline,omitempty"` - Execution *types.Execution `json:"execution,omitempty"` - File *file.File `json:"config,omitempty"` + Repo *types.Repository `json:"repository,omitempty"` + Pipeline *types.Pipeline `json:"pipeline,omitempty"` + Execution *types.Execution `json:"execution,omitempty"` + File *file.File `json:"config,omitempty"` + RepoIsPublic bool `json:"repo_is_public,omitempty"` } // Service converts a file which is in starlark/jsonnet form by looking diff --git a/app/pipeline/converter/starlark/args.go b/app/pipeline/converter/starlark/args.go index ec5b74872f..ff2f96d2ac 100644 --- a/app/pipeline/converter/starlark/args.go +++ b/app/pipeline/converter/starlark/args.go @@ -17,7 +17,6 @@ package starlark import ( "strings" - "github.com/harness/gitness/app/api/controller/repo" "github.com/harness/gitness/types" "go.starlark.net/starlark" @@ -25,15 +24,16 @@ import ( ) func createArgs( - repo *repo.Repository, + repo *types.Repository, pipeline *types.Pipeline, execution *types.Execution, + repoIsPublic bool, ) []starlark.Value { args := []starlark.Value{ starlarkstruct.FromStringDict( starlark.String("context"), starlark.StringDict{ - "repo": starlarkstruct.FromStringDict(starlark.String("repo"), fromRepo(repo, pipeline)), + "repo": starlarkstruct.FromStringDict(starlark.String("repo"), fromRepo(repo, pipeline, repoIsPublic)), "build": starlarkstruct.FromStringDict(starlark.String("build"), fromBuild(execution)), }, ), @@ -67,7 +67,7 @@ func fromBuild(v *types.Execution) starlark.StringDict { } } -func fromRepo(v *repo.Repository, p *types.Pipeline) starlark.StringDict { +func fromRepo(v *types.Repository, p *types.Pipeline, publicRepo bool) starlark.StringDict { namespace := v.Path idx := strings.LastIndex(v.Path, "/") if idx != -1 { @@ -76,17 +76,17 @@ func fromRepo(v *repo.Repository, p *types.Pipeline) starlark.StringDict { return starlark.StringDict{ // TODO [CODE-1363]: remove after identifier migration? - "uid": starlark.String(v.Repository.Identifier), - "identifier": starlark.String(v.Repository.Identifier), - "name": starlark.String(v.Repository.Identifier), + "uid": starlark.String(v.Identifier), + "identifier": starlark.String(v.Identifier), + "name": starlark.String(v.Identifier), "namespace": starlark.String(namespace), - "slug": starlark.String(v.Repository.Path), - "git_http_url": starlark.String(v.Repository.GitURL), - "git_ssh_url": starlark.String(v.Repository.GitURL), - "link": starlark.String(v.Repository.GitURL), - "branch": starlark.String(v.Repository.DefaultBranch), + "slug": starlark.String(v.Path), + "git_http_url": starlark.String(v.GitURL), + "git_ssh_url": starlark.String(v.GitURL), + "link": starlark.String(v.GitURL), + "branch": starlark.String(v.DefaultBranch), "config": starlark.String(p.ConfigPath), - "private": !starlark.Bool(v.IsPublic), + "private": !starlark.Bool(publicRepo), "visibility": starlark.String("internal"), "active": starlark.Bool(true), "trusted": starlark.Bool(true), diff --git a/app/pipeline/converter/starlark/starlark.go b/app/pipeline/converter/starlark/starlark.go index c49ed13034..8807108308 100644 --- a/app/pipeline/converter/starlark/starlark.go +++ b/app/pipeline/converter/starlark/starlark.go @@ -18,7 +18,6 @@ import ( "bytes" "errors" - "github.com/harness/gitness/app/api/controller/repo" "github.com/harness/gitness/app/pipeline/file" "github.com/harness/gitness/types" @@ -57,7 +56,8 @@ var ( ) func Parse( - repo *repo.Repository, + repo *types.Repository, + repoIsPublic bool, pipeline *types.Pipeline, execution *types.Execution, file *file.File, @@ -69,8 +69,8 @@ func Parse( Load: noLoad, Print: func(_ *starlark.Thread, msg string) { logrus.WithFields(logrus.Fields{ - "namespace": repo.Repository.Path, // TODO: update to just be the space - "name": repo.Repository.Identifier, + "namespace": repo.Path, // TODO: update to just be the space + "name": repo.Identifier, }).Traceln(msg) }, } @@ -96,7 +96,7 @@ func Parse( // create the input args and invoke the main method // using the input args. - args := createArgs(repo, pipeline, execution) + args := createArgs(repo, pipeline, execution, repoIsPublic) // set the maximum number of operations in the script. this // mitigates long running scripts. diff --git a/app/pipeline/file/gitness.go b/app/pipeline/file/gitness.go index 5c13d8015f..8fa90b4c2f 100644 --- a/app/pipeline/file/gitness.go +++ b/app/pipeline/file/gitness.go @@ -19,8 +19,8 @@ import ( "fmt" "io" - "github.com/harness/gitness/app/api/controller/repo" "github.com/harness/gitness/git" + "github.com/harness/gitness/types" "github.com/rs/zerolog/log" ) @@ -35,12 +35,12 @@ func newService(git git.Interface) Service { func (f *service) Get( ctx context.Context, - repo *repo.Repository, + repo *types.Repository, path string, ref string, ) (*File, error) { readParams := git.ReadParams{ - RepoUID: repo.Repository.GitUID, + RepoUID: repo.GitUID, } treeNodeOutput, err := f.git.GetTreeNode(ctx, &git.GetTreeNodeParams{ ReadParams: readParams, diff --git a/app/pipeline/file/service.go b/app/pipeline/file/service.go index 773e92f284..00df8913b9 100644 --- a/app/pipeline/file/service.go +++ b/app/pipeline/file/service.go @@ -17,7 +17,7 @@ package file import ( "context" - "github.com/harness/gitness/app/api/controller/repo" + "github.com/harness/gitness/types" ) type ( @@ -36,6 +36,6 @@ type ( Service interface { // path is the path in the repo to read // ref is the git ref for the repository e.g. refs/heads/master - Get(ctx context.Context, repo *repo.Repository, path, ref string) (*File, error) + Get(ctx context.Context, repo *types.Repository, path, ref string) (*File, error) } ) diff --git a/app/pipeline/manager/client.go b/app/pipeline/manager/client.go index e79ed2c8bf..68f01ce1ee 100644 --- a/app/pipeline/manager/client.go +++ b/app/pipeline/manager/client.go @@ -103,7 +103,7 @@ func (e *embedded) Detail(ctx context.Context, stage *drone.Stage) (*client.Cont return &client.Context{ Build: ConvertToDroneBuild(details.Execution), - Repo: ConvertToDroneRepo(details.Repo), + Repo: ConvertToDroneRepo(details.Repo, details.RepoIsPublic), Stage: ConvertToDroneStage(details.Stage), Secrets: ConvertToDroneSecrets(details.Secrets), Config: ConvertToDroneFile(details.Config), diff --git a/app/pipeline/manager/convert.go b/app/pipeline/manager/convert.go index 824637c24c..8c9bbd0904 100644 --- a/app/pipeline/manager/convert.go +++ b/app/pipeline/manager/convert.go @@ -17,7 +17,6 @@ package manager import ( "time" - "github.com/harness/gitness/app/api/controller/repo" "github.com/harness/gitness/app/pipeline/file" "github.com/harness/gitness/livelog" "github.com/harness/gitness/types" @@ -208,21 +207,21 @@ func ConvertToDroneBuild(execution *types.Execution) *drone.Build { } } -func ConvertToDroneRepo(repo *repo.Repository) *drone.Repo { +func ConvertToDroneRepo(repo *types.Repository, repoIsPublic bool) *drone.Repo { return &drone.Repo{ - ID: repo.Repository.ID, + ID: repo.ID, Trusted: true, // as builds are running on user machines, the repo is marked trusted. - UID: repo.Repository.Identifier, - UserID: repo.Repository.CreatedBy, - Namespace: repo.Repository.Path, - Name: repo.Repository.Identifier, - HTTPURL: repo.Repository.GitURL, - Link: repo.Repository.GitURL, - Private: !repo.IsPublic, - Created: repo.Repository.Created, - Updated: repo.Repository.Updated, - Version: repo.Repository.Version, - Branch: repo.Repository.DefaultBranch, + UID: repo.Identifier, + UserID: repo.CreatedBy, + Namespace: repo.Path, + Name: repo.Identifier, + HTTPURL: repo.GitURL, + Link: repo.GitURL, + Private: !repoIsPublic, + Created: repo.Created, + Updated: repo.Updated, + Version: repo.Version, + Branch: repo.DefaultBranch, // TODO: We can get this from configuration once we start populating it. // If this is not set drone runner cancels the build. Timeout: int64((10 * time.Hour).Seconds()), diff --git a/app/pipeline/manager/manager.go b/app/pipeline/manager/manager.go index 089a937a45..a16d1e25af 100644 --- a/app/pipeline/manager/manager.go +++ b/app/pipeline/manager/manager.go @@ -23,7 +23,6 @@ import ( "time" apiauth "github.com/harness/gitness/app/api/auth" - "github.com/harness/gitness/app/api/controller/repo" "github.com/harness/gitness/app/bootstrap" "github.com/harness/gitness/app/jwt" "github.com/harness/gitness/app/pipeline/converter" @@ -83,12 +82,13 @@ type ( // ExecutionContext represents the minimum amount of information // required by the runner to execute a build. ExecutionContext struct { - Repo *repo.Repository `json:"repository"` - Execution *types.Execution `json:"build"` - Stage *types.Stage `json:"stage"` - Secrets []*types.Secret `json:"secrets"` - Config *file.File `json:"config"` - Netrc *Netrc `json:"netrc"` + Repo *types.Repository `json:"repository"` + RepoIsPublic bool `json:"repository_is_public,omitempty"` + Execution *types.Execution `json:"build"` + Stage *types.Stage `json:"stage"` + Secrets []*types.Secret `json:"secrets"` + Config *file.File `json:"config"` + Netrc *Netrc `json:"netrc"` } // ExecutionManager encapsulates complex build operations and provides @@ -302,24 +302,14 @@ func (m *Manager) Details(_ context.Context, stageID int64) (*ExecutionContext, log.Warn().Err(err).Msg("manager: cannot find pipeline") return nil, err } - repoBase, err := m.Repos.Find(noContext, execution.RepoID) + repo, err := m.Repos.Find(noContext, execution.RepoID) if err != nil { log.Warn().Err(err).Msg("manager: cannot find repo") return nil, err } - isPublic, err := apiauth.CheckRepoIsPublic(noContext, m.publicAccess, repoBase) - if err != nil { - return nil, fmt.Errorf("failed to check if repo is public: %w", err) - } - - repo := &repo.Repository{ - Repository: *repoBase, - IsPublic: isPublic, - } - // Backfill clone URL - repo.Repository.GitURL = m.urlProvider.GenerateContainerGITCloneURL(repo.Repository.Path) + repo.GitURL = m.urlProvider.GenerateContainerGITCloneURL(repo.Path) stages, err := m.Stages.List(noContext, stage.ExecutionID) if err != nil { @@ -329,12 +319,12 @@ func (m *Manager) Details(_ context.Context, stageID int64) (*ExecutionContext, execution.Stages = stages log = log.With(). Int64("build", execution.Number). - Str("repo", repo.Repository.GetGitUID()). + Str("repo", repo.GetGitUID()). Logger() // TODO: Currently we fetch all the secrets from the same space. // This logic can be updated when needed. - secrets, err := m.Secrets.ListAll(noContext, repo.Repository.ParentID) + secrets, err := m.Secrets.ListAll(noContext, repo.ParentID) if err != nil { log.Warn().Err(err).Msg("manager: cannot list secrets") return nil, err @@ -347,12 +337,20 @@ func (m *Manager) Details(_ context.Context, stageID int64) (*ExecutionContext, return nil, err } + // Get public access settings of the repo + repoIsPublic, err := apiauth.CheckRepoIsPublic(noContext, m.publicAccess, repo) + if err != nil { + log.Warn().Err(err).Msg("manager: cannot check if repo is public") + return nil, err + } + // Convert file contents in case templates are being used. args := &converter.ConvertArgs{ - Repo: repo, - Pipeline: pipeline, - Execution: execution, - File: file, + Repo: repo, + Pipeline: pipeline, + Execution: execution, + File: file, + RepoIsPublic: repoIsPublic, } file, err = m.ConverterService.Convert(noContext, args) if err != nil { @@ -367,20 +365,21 @@ func (m *Manager) Details(_ context.Context, stageID int64) (*ExecutionContext, } return &ExecutionContext{ - Repo: repo, - Execution: execution, - Stage: stage, - Secrets: secrets, - Config: file, - Netrc: netrc, + Repo: repo, + RepoIsPublic: repoIsPublic, + Execution: execution, + Stage: stage, + Secrets: secrets, + Config: file, + Netrc: netrc, }, nil } -func (m *Manager) createNetrc(repo *repo.Repository) (*Netrc, error) { +func (m *Manager) createNetrc(repo *types.Repository) (*Netrc, error) { pipelinePrincipal := bootstrap.NewPipelineServiceSession().Principal jwt, err := jwt.GenerateWithMembership( pipelinePrincipal.ID, - repo.Repository.ParentID, + repo.ParentID, pipelineJWTRole, pipelineJWTLifetime, pipelinePrincipal.Salt, @@ -389,7 +388,7 @@ func (m *Manager) createNetrc(repo *repo.Repository) (*Netrc, error) { return nil, fmt.Errorf("failed to create jwt: %w", err) } - cloneURL, err := url.Parse(repo.Repository.GitURL) + cloneURL, err := url.Parse(repo.GitURL) if err != nil { return nil, fmt.Errorf("failed to parse clone url '%s': %w", cloneURL, err) } diff --git a/app/pipeline/triggerer/env.go b/app/pipeline/triggerer/env.go index 4060e5eb72..ee625c789b 100644 --- a/app/pipeline/triggerer/env.go +++ b/app/pipeline/triggerer/env.go @@ -15,7 +15,6 @@ package triggerer import ( - "github.com/harness/gitness/app/api/controller/repo" "github.com/harness/gitness/app/url" "github.com/harness/gitness/types" @@ -33,11 +32,11 @@ func combine(env ...map[string]string) map[string]string { } func Envs( - repo *repo.Repository, + repo *types.Repository, pipeline *types.Pipeline, urlProvider url.Provider, ) map[string]string { return map[string]string{ - "DRONE_BUILD_LINK": urlProvider.GenerateUIBuildURL(repo.Repository.Path, pipeline.Identifier, pipeline.Seq), + "DRONE_BUILD_LINK": urlProvider.GenerateUIBuildURL(repo.Path, pipeline.Identifier, pipeline.Seq), } } diff --git a/app/pipeline/triggerer/trigger.go b/app/pipeline/triggerer/trigger.go index bb060d8503..5da6be225e 100644 --- a/app/pipeline/triggerer/trigger.go +++ b/app/pipeline/triggerer/trigger.go @@ -22,7 +22,6 @@ import ( "time" apiauth "github.com/harness/gitness/app/api/auth" - "github.com/harness/gitness/app/api/controller/repo" "github.com/harness/gitness/app/pipeline/checks" "github.com/harness/gitness/app/pipeline/converter" "github.com/harness/gitness/app/pipeline/file" @@ -154,19 +153,15 @@ func (t *triggerer) Trigger( event := string(base.Action.GetTriggerEvent()) - repoBase, err := t.repoStore.Find(ctx, pipeline.RepoID) + repo, err := t.repoStore.Find(ctx, pipeline.RepoID) if err != nil { log.Error().Err(err).Msg("could not find repo") return nil, err } - isPublic, err := apiauth.CheckRepoIsPublic(ctx, t.publicAccess, repoBase) - if err != nil { - return nil, fmt.Errorf("failed to check if repo is public: %w", err) - } - repo := &repo.Repository{ - Repository: *repoBase, - IsPublic: isPublic, + repoIsPublic, err := apiauth.CheckRepoIsPublic(ctx, t.publicAccess, repo) + if err != nil { + return nil, fmt.Errorf("could not check if repo is public: %w", err) } file, err := t.fileService.Get(ctx, repo, pipeline.ConfigPath, base.After) @@ -177,7 +172,7 @@ func (t *triggerer) Trigger( now := time.Now().UnixMilli() execution := &types.Execution{ - RepoID: repo.Repository.ID, + RepoID: repo.ID, PipelineID: pipeline.ID, Trigger: base.Trigger, CreatedBy: base.TriggeredBy, @@ -215,10 +210,11 @@ func (t *triggerer) Trigger( if !isV1Yaml(file.Data) { // Convert from jsonnet/starlark to drone yaml args := &converter.ConvertArgs{ - Repo: repo, - Pipeline: pipeline, - Execution: execution, - File: file, + Repo: repo, + Pipeline: pipeline, + Execution: execution, + File: file, + RepoIsPublic: repoIsPublic, } file, err = t.converterService.Convert(ctx, args) if err != nil { @@ -265,7 +261,7 @@ func (t *triggerer) Trigger( log.Info().Str("pipeline", name).Msg("trigger: skipping pipeline, does not match action") case skipRef(pipeline, base.Ref): log.Info().Str("pipeline", name).Msg("trigger: skipping pipeline, does not match ref") - case skipRepo(pipeline, repo.Repository.Path): + case skipRepo(pipeline, repo.Path): log.Info().Str("pipeline", name).Msg("trigger: skipping pipeline, does not match repo") case skipCron(pipeline, base.Cron): log.Info().Str("pipeline", name).Msg("trigger: skipping pipeline, does not match cron job") @@ -293,7 +289,7 @@ func (t *triggerer) Trigger( } stage := &types.Stage{ - RepoID: repo.Repository.ID, + RepoID: repo.ID, Number: int64(i + 1), Name: match.Name, Kind: match.Kind, @@ -346,7 +342,7 @@ func (t *triggerer) Trigger( } } else { stages, err = parseV1Stages( - ctx, file.Data, repo, execution, t.templateStore, t.pluginStore) + ctx, file.Data, repo, execution, t.templateStore, t.pluginStore, t.publicAccess) if err != nil { return nil, fmt.Errorf("could not parse v1 YAML into stages: %w", err) } @@ -406,10 +402,11 @@ func trunc(s string, i int) string { func parseV1Stages( ctx context.Context, data []byte, - repo *repo.Repository, + repo *types.Repository, execution *types.Execution, templateStore store.TemplateStore, pluginStore store.PluginStore, + publicaccess publicaccess.PublicAccess, ) ([]*types.Stage, error) { stages := []*types.Stage{} // For V1 YAML, just go through the YAML and create stages serially for now @@ -428,8 +425,14 @@ func parseV1Stages( return nil, fmt.Errorf("cannot support non-pipeline kinds in v1 at the moment: %w", err) } + // get repo public access + repoIsPublic, err := publicaccess.Get(ctx, enum.PublicResourceTypeRepo, repo.Path) + if err != nil { + return nil, fmt.Errorf("could not check repo public access: %w", err) + } + inputParams := map[string]interface{}{} - inputParams["repo"] = inputs.Repo(manager.ConvertToDroneRepo(repo)) + inputParams["repo"] = inputs.Repo(manager.ConvertToDroneRepo(repo, repoIsPublic)) inputParams["build"] = inputs.Build(manager.ConvertToDroneBuild(execution)) var prevStage string @@ -476,7 +479,7 @@ func parseV1Stages( status = enum.CIStatusPending } temp := &types.Stage{ - RepoID: repo.Repository.ID, + RepoID: repo.ID, Number: int64(idx + 1), Name: stage.Id, // for v1, ID is the unique identifier per stage Created: now, diff --git a/app/services/exporter/repository.go b/app/services/exporter/repository.go index 7c0cf3d4c9..c7eb3bcf2e 100644 --- a/app/services/exporter/repository.go +++ b/app/services/exporter/repository.go @@ -35,7 +35,6 @@ import ( "github.com/harness/gitness/types" "github.com/harness/gitness/types/enum" - apiauth "github.com/harness/gitness/app/api/auth" "github.com/rs/zerolog/log" ) @@ -117,16 +116,11 @@ func (r *Repository) RunManyForSpace( jobDefinitions := make([]job.Definition, len(repos)) for i, repository := range repos { - isPublic, err := apiauth.CheckRepoIsPublic(ctx, r.publicAccess, repository) - if err != nil { - return fmt.Errorf("failed to check repo public visibility: %w", err) - } - repoJobData := Input{ Identifier: repository.Identifier, ID: repository.ID, Description: repository.Description, - IsPublic: isPublic, + IsPublic: false, // todo: use repository.IsPublic once public is available. HarnessCodeInfo: *harnessCodeInfo, } @@ -193,16 +187,11 @@ func (r *Repository) Handle(ctx context.Context, data string, _ job.ProgressRepo return "", err } - isPublic, err := apiauth.CheckRepoIsPublic(ctx, r.publicAccess, repository) - if err != nil { - return "", fmt.Errorf("failed to check if repo is public: %w", err) - } - remoteRepo, err := client.CreateRepo(ctx, repo.CreateInput{ Identifier: repository.Identifier, DefaultBranch: repository.DefaultBranch, Description: repository.Description, - IsPublic: isPublic, + IsPublic: false, // TODO: use apiauth.CheckRepoIsPublic once public access is deployed on HC. Readme: false, License: "", GitIgnore: "", diff --git a/app/services/publicaccess/public_access.go b/app/services/publicaccess/public_access.go index 9d3fad2972..4a789c8c22 100644 --- a/app/services/publicaccess/public_access.go +++ b/app/services/publicaccess/public_access.go @@ -17,7 +17,7 @@ package publicaccess import ( "context" - "github.com/harness/gitness/types" + "github.com/harness/gitness/types/enum" ) // PublicAccess is an abstraction of an entity responsible for managing public access to resources. @@ -31,8 +31,8 @@ type PublicAccess interface { */ Get( ctx context.Context, - scope *types.Scope, - resource *types.Resource, + resourceType enum.PublicResourceType, + resourcePath string, ) (bool, error) /* @@ -43,8 +43,8 @@ type PublicAccess interface { */ Set( ctx context.Context, - scope *types.Scope, - resource *types.Resource, + resourceType enum.PublicResourceType, + resourcePath string, enable bool, ) error } diff --git a/app/services/publicaccess/resources.go b/app/services/publicaccess/resources.go index e2f8a6240f..e2009be118 100644 --- a/app/services/publicaccess/resources.go +++ b/app/services/publicaccess/resources.go @@ -18,70 +18,52 @@ import ( "context" "fmt" - "github.com/harness/gitness/app/paths" - "github.com/harness/gitness/types" "github.com/harness/gitness/types/enum" ) func (s *Service) getPublicResource( ctx context.Context, - scope *types.Scope, - resource *types.Resource, -) (*types.PublicResource, error) { - resType := resource.Type - - // set scope type to space for checks within space scope. - if resource.Identifier == "" { - resType = enum.ResourceTypeSpace - } - var pubRes *types.PublicResource + resourceType enum.PublicResourceType, + resourcePath string, +) (int64, error) { + var id int64 var err error - switch resType { - case enum.ResourceTypeRepo: - pubRes, err = s.getResourceRepo(ctx, scope, resource) - case enum.ResourceTypeSpace: - pubRes, err = s.getResourceSpace(ctx, scope, resource) + switch resourceType { + case enum.PublicResourceTypeRepo: + id, err = s.getResourceRepo(ctx, resourcePath) + case enum.PublicResourceTypeSpace: + id, err = s.getResourceSpace(ctx, resourcePath) default: - return nil, fmt.Errorf("invalid public resource type") + return 0, fmt.Errorf("invalid public resource type") } if err != nil { - return nil, fmt.Errorf("failed to get public resource: %w", err) + return 0, fmt.Errorf("failed to get public resource: %w", err) } - return pubRes, nil + return id, nil } func (s *Service) getResourceRepo( ctx context.Context, - scope *types.Scope, - resource *types.Resource, -) (*types.PublicResource, error) { - repoRef := paths.Concatenate(scope.SpacePath, resource.Identifier) - repo, err := s.repoStore.FindByRef(ctx, repoRef) + path string, +) (int64, error) { + repo, err := s.repoStore.FindByRef(ctx, path) if err != nil { - return nil, fmt.Errorf("failed to find repo: %w", err) + return 0, fmt.Errorf("failed to find repo: %w", err) } - return &types.PublicResource{ - Type: enum.PublicResourceTypeRepo, - ID: repo.ID, - }, nil + return repo.ID, nil } func (s *Service) getResourceSpace( ctx context.Context, - scope *types.Scope, - resource *types.Resource, -) (*types.PublicResource, error) { - spaceRef := paths.Concatenate(scope.SpacePath, resource.Identifier) - space, err := s.spaceStore.FindByRef(ctx, spaceRef) + path string, +) (int64, error) { + space, err := s.spaceStore.FindByRef(ctx, path) if err != nil { - return nil, fmt.Errorf("failed to find space: %w", err) + return 0, fmt.Errorf("failed to find space: %w", err) } - return &types.PublicResource{ - Type: enum.PublicResourceTypeSpace, - ID: space.ID, - }, nil + return space.ID, nil } diff --git a/app/services/publicaccess/service.go b/app/services/publicaccess/service.go index a5e5c28111..690c00807d 100644 --- a/app/services/publicaccess/service.go +++ b/app/services/publicaccess/service.go @@ -21,38 +21,38 @@ import ( "github.com/harness/gitness/app/store" gitness_store "github.com/harness/gitness/store" - "github.com/harness/gitness/types" + "github.com/harness/gitness/types/enum" ) type Service struct { - publicResourceStore store.PublicResource - repoStore store.RepoStore - spaceStore store.SpaceStore + publicAccessStore store.PublicAccessStore + repoStore store.RepoStore + spaceStore store.SpaceStore } func NewService( - publicResourceStore store.PublicResource, + publicAccessStore store.PublicAccessStore, repoStore store.RepoStore, spaceStore store.SpaceStore, ) PublicAccess { return &Service{ - publicResourceStore: publicResourceStore, - repoStore: repoStore, - spaceStore: spaceStore, + publicAccessStore: publicAccessStore, + repoStore: repoStore, + spaceStore: spaceStore, } } func (s *Service) Get( ctx context.Context, - scope *types.Scope, - resource *types.Resource, + resourceType enum.PublicResourceType, + resourcePath string, ) (bool, error) { - pubRes, err := s.getPublicResource(ctx, scope, resource) + pubResID, err := s.getPublicResource(ctx, resourceType, resourcePath) if err != nil { return false, err } - err = s.publicResourceStore.Find(ctx, pubRes) + err = s.publicAccessStore.Find(ctx, resourceType, pubResID) if errors.Is(err, gitness_store.ErrResourceNotFound) { return false, nil } @@ -65,22 +65,22 @@ func (s *Service) Get( func (s *Service) Set( ctx context.Context, - scope *types.Scope, - resource *types.Resource, + resourceType enum.PublicResourceType, + resourcePath string, enable bool, ) error { - pubRes, err := s.getPublicResource(ctx, scope, resource) + pubResID, err := s.getPublicResource(ctx, resourceType, resourcePath) if err != nil { return err } if enable { - err := s.publicResourceStore.Create(ctx, pubRes) + err := s.publicAccessStore.Create(ctx, resourceType, pubResID) if errors.Is(err, gitness_store.ErrDuplicate) { return nil } return err } else { - return s.publicResourceStore.Delete(ctx, pubRes) + return s.publicAccessStore.Delete(ctx, resourceType, pubResID) } } diff --git a/app/services/publicaccess/wire.go b/app/services/publicaccess/wire.go index 45a61ecfb5..a470dca374 100644 --- a/app/services/publicaccess/wire.go +++ b/app/services/publicaccess/wire.go @@ -25,9 +25,9 @@ var WireSet = wire.NewSet( ) func ProvidePublicAccess( - publicResources store.PublicResource, + publicAccessStore store.PublicAccessStore, repoStore store.RepoStore, spaceStore store.SpaceStore, ) PublicAccess { - return NewService(publicResources, repoStore, spaceStore) + return NewService(publicAccessStore, repoStore, spaceStore) } diff --git a/app/store/database.go b/app/store/database.go index 385d640c0a..17a4378da6 100644 --- a/app/store/database.go +++ b/app/store/database.go @@ -290,11 +290,11 @@ type ( ListSpaces(ctx context.Context, userID int64, filter types.MembershipSpaceFilter) ([]types.MembershipSpace, error) } - // PublicResource defines the publicly accessible resources data storage. - PublicResource interface { - Find(ctx context.Context, pubRes *types.PublicResource) error - Create(ctx context.Context, pubRes *types.PublicResource) error - Delete(ctx context.Context, pubRes *types.PublicResource) error + // PublicAccessStore defines the publicly accessible resources data storage. + PublicAccessStore interface { + Find(ctx context.Context, typ enum.PublicResourceType, id int64) error + Create(ctx context.Context, typ enum.PublicResourceType, id int64) error + Delete(ctx context.Context, typ enum.PublicResourceType, id int64) error } // TokenStore defines the token data storage. diff --git a/app/store/database/migrate/postgres/0051_create_table_public_resources.down.sql b/app/store/database/migrate/postgres/0051_create_table_public_resources.down.sql index 9c9255168e..e2faa6bdb2 100644 --- a/app/store/database/migrate/postgres/0051_create_table_public_resources.down.sql +++ b/app/store/database/migrate/postgres/0051_create_table_public_resources.down.sql @@ -1,28 +1,28 @@ -- copy public repositories -ALTER TABLE repositories ADD COLUMN repo_is_public; +ALTER TABLE repositories ADD COLUMN repo_is_public BOOLEAN; UPDATE repositories WHERE repo_id IN ( - SELECT public_resource_repo_id - FROM public_resources - WHERE public_resource_repo_id IS NOT NULL; + SELECT public_access_repo_id + FROM public_access + WHERE public_access_repo_id IS NOT NULL; ) SET repo_is_public = TRUE; -- copy public spaces -ALTER TABLE spaces ADD COLUMN space_is_public; +ALTER TABLE spaces ADD COLUMN space_is_public BOOLEAN; --- update public resources +-- update public access UPDATE spaces WHERE space_id IN ( - SELECT public_resource_space_id - FROM public_resources - WHERE public_resource_space_id IS NOT NULL; + SELECT public_access_space_id + FROM public_access + WHERE public_access_space_id IS NOT NULL; ) SET -sapce_is_public = TRUE; +space_is_public = TRUE; --- clear public_resoureces -DROP INDEX public_resource_space_id_key; -DROP INDEX public_resource_repo_id_key; -DROP TABLE public_resources; \ No newline at end of file +-- clear public access +DROP INDEX public_access_space_id_key; +DROP INDEX public_access_repo_id_key; +DROP TABLE public_access; \ No newline at end of file diff --git a/app/store/database/migrate/postgres/0051_create_table_public_resources.up.sql b/app/store/database/migrate/postgres/0051_create_table_public_resources.up.sql index f67a640ac7..875c6bdc6e 100644 --- a/app/store/database/migrate/postgres/0051_create_table_public_resources.up.sql +++ b/app/store/database/migrate/postgres/0051_create_table_public_resources.up.sql @@ -1,48 +1,44 @@ -CREATE TABLE public_resources ( - public_resource_id SERIAL PRIMARY KEY -,public_resource_space_id INTEGER -,public_resource_repo_id INTEGER +CREATE TABLE public_access ( + public_access_id SERIAL PRIMARY KEY +,public_access_space_id INTEGER +,public_access_repo_id INTEGER -,CONSTRAINT fk_public_resource_space_id FOREIGN KEY (public_resource_space_id) +,CONSTRAINT fk_public_access_space_id FOREIGN KEY (public_access_space_id) REFERENCES spaces (space_id) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE CASCADE -,CONSTRAINT fk_public_resource_repo_id FOREIGN KEY (public_resource_repo_id) +,CONSTRAINT fk_public_access_repo_id FOREIGN KEY (public_access_repo_id) REFERENCES repositories (repo_id) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE CASCADE ); -CREATE UNIQUE INDEX public_resource_space_id_key - ON public_resources(public_resource_space_id) - WHERE public_resource_space_id IS NOT NULL; +CREATE UNIQUE INDEX public_access_space_id_key + ON public_access(public_access_space_id) + WHERE public_access_space_id IS NOT NULL; -CREATE UNIQUE INDEX public_resource_repo_id_key - ON public_resources(public_resource_repo_id) - WHERE public_resource_repo_id IS NOT NULL; +CREATE UNIQUE INDEX public_access_repo_id_key + ON public_access(public_access_repo_id) + WHERE public_access_repo_id IS NOT NULL; --- move public repos into public_resource -INSERT INTO public_resources ( - public_resource_space_id - ,public_resource_repo_id +-- move public repos into public_access +INSERT INTO public_access ( + public_access_repo_id ) SELECT - NULL - ,repo_id + repo_id FROM repositories WHERE repo_is_public = TRUE; -- alter repo table ALTER TABLE repositories DROP COLUMN repo_is_public; --- move public spaces into public_resource -INSERT INTO public_resources ( - public_resource_space_id - ,public_resource_repo_id +-- move public spaces into public_access +INSERT INTO public_access ( + public_access_space_id ) SELECT space_id - ,NULL FROM spaces WHERE space_is_public = TRUE; diff --git a/app/store/database/migrate/sqlite/0051_create_table_public_resources.down.sql b/app/store/database/migrate/sqlite/0051_create_table_public_resources.down.sql index 9c9255168e..c7b02dfe03 100644 --- a/app/store/database/migrate/sqlite/0051_create_table_public_resources.down.sql +++ b/app/store/database/migrate/sqlite/0051_create_table_public_resources.down.sql @@ -1,28 +1,28 @@ -- copy public repositories -ALTER TABLE repositories ADD COLUMN repo_is_public; +ALTER TABLE repositories ADD COLUMN repo_is_public BOOLEAN; UPDATE repositories WHERE repo_id IN ( - SELECT public_resource_repo_id - FROM public_resources - WHERE public_resource_repo_id IS NOT NULL; + SELECT public_access_repo_id + FROM public_access + WHERE public_access_repo_id IS NOT NULL; ) SET repo_is_public = TRUE; -- copy public spaces -ALTER TABLE spaces ADD COLUMN space_is_public; +ALTER TABLE spaces ADD COLUMN space_is_public BOOLEAN; --- update public resources +-- update public access UPDATE spaces WHERE space_id IN ( - SELECT public_resource_space_id - FROM public_resources - WHERE public_resource_space_id IS NOT NULL; + SELECT public_access_space_id + FROM public_access + WHERE public_access_space_id IS NOT NULL; ) SET -sapce_is_public = TRUE; +space_is_public = TRUE; --- clear public_resoureces -DROP INDEX public_resource_space_id_key; -DROP INDEX public_resource_repo_id_key; -DROP TABLE public_resources; \ No newline at end of file +-- clear public_access +DROP INDEX public_access_space_id_key; +DROP INDEX public_access_repo_id_key; +DROP TABLE public_access; \ No newline at end of file diff --git a/app/store/database/migrate/sqlite/0051_create_table_public_resources.up.sql b/app/store/database/migrate/sqlite/0051_create_table_public_resources.up.sql index e2de44389b..9031fa714e 100644 --- a/app/store/database/migrate/sqlite/0051_create_table_public_resources.up.sql +++ b/app/store/database/migrate/sqlite/0051_create_table_public_resources.up.sql @@ -1,48 +1,44 @@ -CREATE TABLE public_resources ( - public_resource_id INTEGER PRIMARY KEY AUTOINCREMENT -,public_resource_space_id INTEGER -,public_resource_repo_id INTEGER +CREATE TABLE public_access ( + public_access_id INTEGER PRIMARY KEY AUTOINCREMENT +,public_access_space_id INTEGER +,public_access_repo_id INTEGER -,CONSTRAINT fk_public_resource_space_id FOREIGN KEY (public_resource_space_id) +,CONSTRAINT fk_public_access_space_id FOREIGN KEY (public_access_space_id) REFERENCES spaces (space_id) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE CASCADE -,CONSTRAINT fk_public_resource_repo_id FOREIGN KEY (public_resource_repo_id) +,CONSTRAINT fk_public_access_repo_id FOREIGN KEY (public_access_repo_id) REFERENCES repositories (repo_id) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE CASCADE ); -CREATE UNIQUE INDEX public_resource_space_id_key - ON public_resources(public_resource_space_id) - WHERE public_resource_space_id IS NOT NULL; +CREATE UNIQUE INDEX public_access_space_id_key + ON public_access(public_access_space_id) + WHERE public_access_space_id IS NOT NULL; -CREATE UNIQUE INDEX public_resource_repo_id_key - ON public_resources(public_resource_repo_id) - WHERE public_resource_repo_id IS NOT NULL; +CREATE UNIQUE INDEX public_access_repo_id_key + ON public_access(public_access_repo_id) + WHERE public_access_repo_id IS NOT NULL; --- move public repos into public_resource -INSERT INTO public_resources ( - public_resource_space_id - ,public_resource_repo_id +-- move public repos into public_access +INSERT INTO public_access ( + public_access_repo_id ) SELECT - NULL - ,repo_id + repo_id FROM repositories WHERE repo_is_public = TRUE; -- alter repo table ALTER TABLE repositories DROP COLUMN repo_is_public; --- move public spaces into public_resource -INSERT INTO public_resources ( - public_resource_space_id - ,public_resource_repo_id +-- move public spaces into public_access +INSERT INTO public_access ( + public_access_space_id ) SELECT space_id - ,NULL FROM spaces WHERE space_is_public = TRUE; diff --git a/app/store/database/public_resource.go b/app/store/database/public_access.go similarity index 62% rename from app/store/database/public_resource.go rename to app/store/database/public_access.go index 14d3fc0e90..b60772b522 100644 --- a/app/store/database/public_resource.go +++ b/app/store/database/public_access.go @@ -21,56 +21,56 @@ import ( "github.com/harness/gitness/app/store" "github.com/harness/gitness/store/database" "github.com/harness/gitness/store/database/dbtx" - "github.com/harness/gitness/types" "github.com/harness/gitness/types/enum" "github.com/guregu/null" "github.com/jmoiron/sqlx" ) -var _ store.PublicResource = (*PublicResourcesStore)(nil) +var _ store.PublicAccessStore = (*PublicAccessStore)(nil) -// NewPublicResourcesStore returns a new PublicResourcesStore. -func NewPublicResourcesStore(db *sqlx.DB) *PublicResourcesStore { - return &PublicResourcesStore{ +// NewPublicAccessStore returns a new PublicAccessStore. +func NewPublicAccessStore(db *sqlx.DB) *PublicAccessStore { + return &PublicAccessStore{ db: db, } } -// PublicResourcesStore implements store.SettingsStore backed by a relational database. -type PublicResourcesStore struct { +// PublicAccessStore implements store.PublicAccessStore backed by a relational database. +type PublicAccessStore struct { db *sqlx.DB } -type publicResource struct { - ID int64 `db:"public_resource_id"` - SpaceID null.Int `db:"public_resource_space_id"` - RepoID null.Int `db:"public_resource_repo_id"` +type publicAccess struct { + ID int64 `db:"public_access_id"` + SpaceID null.Int `db:"public_access_space_id"` + RepoID null.Int `db:"public_access_repo_id"` } const ( - publicResourceColumns = ` - public_resource_id - ,public_resource_space_id - ,public_resource_repo_id + publicAccessColumns = ` + public_access_id + ,public_access_space_id + ,public_access_repo_id ` ) -func (p *PublicResourcesStore) Find( +func (p *PublicAccessStore) Find( ctx context.Context, - pubRes *types.PublicResource, + typ enum.PublicResourceType, + id int64, ) error { stmt := database.Builder. - Select(publicResourceColumns). - From("public_resources") + Select(publicAccessColumns). + From("public_access") - switch pubRes.Type { + switch typ { case enum.PublicResourceTypeRepo: - stmt = stmt.Where("public_resource_repo_id = ?", pubRes.ID) + stmt = stmt.Where("public_access_repo_id = ?", id) case enum.PublicResourceTypeSpace: - stmt = stmt.Where("public_resource_space_id = ?", pubRes.ID) + stmt = stmt.Where("public_access_space_id = ?", id) default: - return fmt.Errorf("public resource type %q is not supported", pubRes.Type) + return fmt.Errorf("public resource type %q is not supported", typ) } sql, args, err := stmt.ToSql() @@ -80,7 +80,7 @@ func (p *PublicResourcesStore) Find( db := dbtx.GetAccessor(ctx, p.db) - dst := &publicResource{} + dst := &publicAccess{} if err = db.GetContext(ctx, dst, sql, args...); err != nil { return database.ProcessSQLErrorf(ctx, err, "Select query failed") } @@ -88,25 +88,26 @@ func (p *PublicResourcesStore) Find( return nil } -func (p *PublicResourcesStore) Create( +func (p *PublicAccessStore) Create( ctx context.Context, - pubRes *types.PublicResource, + typ enum.PublicResourceType, + id int64, ) error { stmt := database.Builder. Insert(""). - Into("public_resources"). + Into("public_access"). Columns( - "public_resource_space_id", - "public_resource_repo_id", + "public_access_space_id", + "public_access_repo_id", ) - switch pubRes.Type { + switch typ { case enum.PublicResourceTypeRepo: - stmt = stmt.Values(null.Int{}, null.IntFrom(pubRes.ID)) + stmt = stmt.Values(null.Int{}, null.IntFrom(id)) case enum.PublicResourceTypeSpace: - stmt = stmt.Values(null.IntFrom(pubRes.ID), null.Int{}) + stmt = stmt.Values(null.IntFrom(id), null.Int{}) default: - return fmt.Errorf("public resource type %q is not supported", pubRes.Type) + return fmt.Errorf("public resource type %q is not supported", typ) } sql, args, err := stmt.ToSql() @@ -123,20 +124,21 @@ func (p *PublicResourcesStore) Create( return nil } -func (p *PublicResourcesStore) Delete( +func (p *PublicAccessStore) Delete( ctx context.Context, - pubRes *types.PublicResource, + typ enum.PublicResourceType, + id int64, ) error { stmt := database.Builder. - Delete("public_resources") + Delete("public_access") - switch pubRes.Type { + switch typ { case enum.PublicResourceTypeRepo: - stmt = stmt.Where("public_resource_repo_id = ?", pubRes.ID) + stmt = stmt.Where("public_access_repo_id = ?", id) case enum.PublicResourceTypeSpace: - stmt = stmt.Where("public_resource_space_id = ?", pubRes.ID) + stmt = stmt.Where("public_access_space_id = ?", id) default: - return fmt.Errorf("public resource type %q is not supported", pubRes.Type) + return fmt.Errorf("public resource type %q is not supported", typ) } sql, args, err := stmt.ToSql() diff --git a/app/store/database/wire.go b/app/store/database/wire.go index 2979cee90c..1b35b244c7 100644 --- a/app/store/database/wire.go +++ b/app/store/database/wire.go @@ -53,7 +53,7 @@ var WireSet = wire.NewSet( ProvideWebhookStore, ProvideWebhookExecutionStore, ProvideSettingsStore, - ProvidePublicResourcesStore, + ProvidePublicPublicAccessStore, ProvideCheckStore, ProvideConnectorStore, ProvideTemplateStore, @@ -249,7 +249,7 @@ func ProvideSettingsStore(db *sqlx.DB) store.SettingsStore { return NewSettingsStore(db) } -// ProvidePublicResourcesStore provides a pulic resources store. -func ProvidePublicResourcesStore(db *sqlx.DB) store.PublicResource { - return NewPublicResourcesStore(db) +// ProvidePublicPublicAccessStore provides a pulic access store. +func ProvidePublicPublicAccessStore(db *sqlx.DB) store.PublicAccessStore { + return NewPublicAccessStore(db) } diff --git a/cmd/gitness/wire_gen.go b/cmd/gitness/wire_gen.go index ad2e86ba86..a672d4c13c 100644 --- a/cmd/gitness/wire_gen.go +++ b/cmd/gitness/wire_gen.go @@ -115,9 +115,9 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro principalInfoCache := cache.ProvidePrincipalInfoCache(principalInfoView) membershipStore := database.ProvideMembershipStore(db, principalInfoCache, spacePathStore, spaceStore) permissionCache := authz.ProvidePermissionCache(spaceStore, membershipStore) - publicResource := database.ProvidePublicResourcesStore(db) + publicAccessStore := database.ProvidePublicPublicAccessStore(db) repoStore := database.ProvideRepoStore(db, spacePathCache, spacePathStore, spaceStore) - publicAccess := publicaccess.ProvidePublicAccess(publicResource, repoStore, spaceStore) + publicAccess := publicaccess.ProvidePublicAccess(publicAccessStore, repoStore, spaceStore) authorizer := authz.ProvideAuthorizer(permissionCache, spaceStore, publicAccess) principalUIDTransformation := store.ProvidePrincipalUIDTransformation() principalStore := database.ProvidePrincipalStore(db, principalUIDTransformation) @@ -201,7 +201,7 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro repoIdentifier := check.ProvideRepoIdentifierCheck() repoCheck := repo.ProvideRepoCheck() repoController := repo.ProvideController(config, transactor, provider, authorizer, repoStore, spaceStore, pipelineStore, principalStore, ruleStore, settingsService, principalInfoCache, protectionManager, gitInterface, repository, codeownersService, reporter, indexer, resourceLimiter, lockerLocker, auditService, mutexManager, repoIdentifier, repoCheck, publicAccess) - reposettingsController := reposettings.ProvideController(authorizer, repoStore, settingsService, publicAccess, auditService) + reposettingsController := reposettings.ProvideController(authorizer, repoStore, settingsService, auditService) executionStore := database.ProvideExecutionStore(db) checkStore := database.ProvideCheckStore(db, principalInfoCache) stageStore := database.ProvideStageStore(db) @@ -268,7 +268,7 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro if err != nil { return nil, err } - webhookController := webhook2.ProvideController(webhookConfig, authorizer, webhookStore, webhookExecutionStore, repoStore, webhookService, encrypter, publicAccess) + webhookController := webhook2.ProvideController(webhookConfig, authorizer, webhookStore, webhookExecutionStore, repoStore, webhookService, encrypter) reporter2, err := events4.ProvideReporter(eventsSystem) if err != nil { return nil, err diff --git a/types/enum/public_resource.go b/types/enum/public_resource.go index 19dc89e9d0..50b2e048e6 100644 --- a/types/enum/public_resource.go +++ b/types/enum/public_resource.go @@ -20,7 +20,7 @@ func (PublicResourceType) Enum() []interface{} { return toInterfaceSlice(GetAllPublicResourceTypes()) } -var ( +const ( PublicResourceTypeRepo PublicResourceType = "repository" PublicResourceTypeSpace PublicResourceType = "space" ) diff --git a/types/repo.go b/types/repo.go index 43e84179f8..3ae3704d9c 100644 --- a/types/repo.go +++ b/types/repo.go @@ -70,6 +70,18 @@ func (r Repository) MarshalJSON() ([]byte, error) { }) } +// Clone makes deep copy of repository object. +func (r Repository) Clone() Repository { + var deleted *int64 + if r.Deleted != nil { + id := *r.Deleted + deleted = &id + } + r.Deleted = deleted + + return r +} + type RepositorySizeInfo struct { ID int64 `json:"id"` GitUID string `json:"git_uid"` From 71ea1947b2c8a229376f162b9163e6c99806a928 Mon Sep 17 00:00:00 2001 From: atefeh Date: Tue, 7 May 2024 00:29:55 -0700 Subject: [PATCH 15/31] put anonymous into illegal principal uids --- types/check/common.go | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/types/check/common.go b/types/check/common.go index e2c0ac2e15..c6813503bf 100644 --- a/types/check/common.go +++ b/types/check/common.go @@ -39,6 +39,10 @@ var ( // illegalRootSpaceIdentifiers is the list of space identifier we are blocking for root spaces // as they might cause issues with routing. illegalRootSpaceIdentifiers = []string{"api", "git"} + + // illegalPrincipalUID is the UID we are blocking for principals + // as they might cause issues with system generated values. + illegalPrincipalUID = "anonymous" ) var ( @@ -74,6 +78,10 @@ var ( ErrIllegalRepoSpaceIdentifierSuffix = &ValidationError{ fmt.Sprintf("Space and repository identifiers cannot end with %q.", illegalRepoSpaceIdentifierSuffix), } + + ErrIllegalPrincipalUID = &ValidationError{ + fmt.Sprintf("Principal UID is not allowed to be %q.", illegalPrincipalUID), + } ) // DisplayName checks the provided display name and returns an error if it isn't valid. @@ -143,7 +151,15 @@ type PrincipalUID func(uid string) error // PrincipalUIDDefault performs the default Principal UID check. func PrincipalUIDDefault(uid string) error { - return Identifier(uid) + if err := Identifier(uid); err != nil { + return err + } + + if uid == illegalPrincipalUID { + return ErrIllegalPrincipalUID + } + + return nil } // SpaceIdentifier is an abstraction of a validation method that returns true From 1ef317fb3b412cea5ba4a60b8e20d34d1a4dd416 Mon Sep 17 00:00:00 2001 From: atefeh Date: Tue, 7 May 2024 09:03:25 -0700 Subject: [PATCH 16/31] delete public acccess on softdelete. restore repo will always be private --- app/api/controller/repo/purge.go | 11 ----------- app/api/controller/repo/restore.go | 8 ++------ app/api/controller/repo/soft_delete.go | 22 ++++++++++++---------- 3 files changed, 14 insertions(+), 27 deletions(-) diff --git a/app/api/controller/repo/purge.go b/app/api/controller/repo/purge.go index eb93ad09ff..34e4f1b685 100644 --- a/app/api/controller/repo/purge.go +++ b/app/api/controller/repo/purge.go @@ -72,17 +72,6 @@ func (c *Controller) PurgeNoAuth( } } - isPublic, err := apiauth.CheckRepoIsPublic(ctx, c.publicAccess, repo) - if err != nil { - log.Ctx(ctx).Err(err).Msg("failed to check repo public access") - } - - if isPublic { - if err := c.SetRepoPublicAccess(ctx, repo, false); err != nil { - log.Ctx(ctx).Err(err).Msg("failed to disable repo public access") - } - } - if err := c.repoStore.Purge(ctx, repo.ID, repo.Deleted); err != nil { return fmt.Errorf("failed to delete repo from db: %w", err) } diff --git a/app/api/controller/repo/restore.go b/app/api/controller/repo/restore.go index 2a1296692e..8610d3d2d6 100644 --- a/app/api/controller/repo/restore.go +++ b/app/api/controller/repo/restore.go @@ -93,13 +93,9 @@ func (c *Controller) RestoreNoAuth( return nil, fmt.Errorf("failed to restore the repo: %w", err) } - isPublic, err := apiauth.CheckRepoIsPublic(ctx, c.publicAccess, repo) - if err != nil { - return nil, fmt.Errorf("failed to get resource public access mode: %w", err) - } - + // Repos restored as private since public access data is deleted upon deletion. return &Repository{ Repository: *repo, - IsPublic: isPublic, + IsPublic: false, }, nil } diff --git a/app/api/controller/repo/soft_delete.go b/app/api/controller/repo/soft_delete.go index 56ff885689..84d1704c61 100644 --- a/app/api/controller/repo/soft_delete.go +++ b/app/api/controller/repo/soft_delete.go @@ -64,20 +64,12 @@ func (c *Controller) SoftDelete( return nil, fmt.Errorf("failed to soft delete repo: %w", err) } - isPublic, err := apiauth.CheckRepoIsPublic(ctx, c.publicAccess, repo) - if err != nil { - log.Ctx(ctx).Warn().Msgf("failed to check repo public access for audit logs: %s", err) - } - err = c.auditService.Log(ctx, session.Principal, audit.NewResource(audit.ResourceTypeRepository, repo.Identifier), audit.ActionDeleted, paths.Parent(repo.Path), - audit.WithOldObject(&Repository{ - Repository: *repo, - IsPublic: isPublic, - }), + audit.WithOldObject(repo), ) if err != nil { log.Ctx(ctx).Warn().Msgf("failed to insert audit log for delete repository operation: %s", err) @@ -96,8 +88,18 @@ func (c *Controller) SoftDeleteNoAuth( return c.PurgeNoAuth(ctx, session, repo) } - err := c.repoStore.SoftDelete(ctx, repo, deletedAt) + isPublic, err := apiauth.CheckRepoIsPublic(ctx, c.publicAccess, repo) if err != nil { + return fmt.Errorf("failed to check repo public access: %w", err) + } + + if isPublic { + if err := c.SetRepoPublicAccess(ctx, repo, false); err != nil { + return fmt.Errorf("failed to disable repo public access: %w", err) + } + } + + if err := c.repoStore.SoftDelete(ctx, repo, deletedAt); err != nil { return fmt.Errorf("failed to soft delete repo from db: %w", err) } From f600e7305992d51ce512ec5c01ae749e02629de7 Mon Sep 17 00:00:00 2001 From: atefeh Date: Tue, 7 May 2024 11:26:01 -0700 Subject: [PATCH 17/31] self review --- app/api/controller/space/list_repositories.go | 17 ++++++------- app/api/controller/space/list_spaces.go | 14 +++++------ app/auth/anonymouse.go | 2 +- app/services/exporter/repository.go | 8 ++++++- app/services/publicaccess/service.go | 2 ++ types/repo.go | 24 +++++++++---------- 6 files changed, 38 insertions(+), 29 deletions(-) diff --git a/app/api/controller/space/list_repositories.go b/app/api/controller/space/list_repositories.go index 01ae060662..7f613e9bcc 100644 --- a/app/api/controller/space/list_repositories.go +++ b/app/api/controller/space/list_repositories.go @@ -20,6 +20,7 @@ import ( apiauth "github.com/harness/gitness/app/api/auth" "github.com/harness/gitness/app/api/controller/repo" + repoCtrl "github.com/harness/gitness/app/api/controller/repo" "github.com/harness/gitness/app/auth" "github.com/harness/gitness/store/database/dbtx" "github.com/harness/gitness/types" @@ -58,7 +59,7 @@ func (c *Controller) ListRepositoriesNoAuth( spaceID int64, filter *types.RepoFilter, ) ([]*repo.Repository, int64, error) { - var repos []*repo.Repository + var reposOutput []*repo.Repository var count int64 err := c.tx.WithTx(ctx, func(ctx context.Context) (err error) { @@ -67,23 +68,23 @@ func (c *Controller) ListRepositoriesNoAuth( return fmt.Errorf("failed to count child repos: %w", err) } - reposBase, err := c.repoStore.List(ctx, spaceID, filter) + repos, err := c.repoStore.List(ctx, spaceID, filter) if err != nil { return fmt.Errorf("failed to list child repos: %w", err) } - for _, repoBase := range reposBase { + for _, repo := range repos { // backfill URLs - repoBase.GitURL = c.urlProvider.GenerateGITCloneURL(repoBase.Path) + repo.GitURL = c.urlProvider.GenerateGITCloneURL(repo.Path) // backfill public access mode - isPublic, err := apiauth.CheckRepoIsPublic(ctx, c.publicAccess, repoBase) + isPublic, err := apiauth.CheckRepoIsPublic(ctx, c.publicAccess, repo) if err != nil { return fmt.Errorf("failed to get resource public access mode: %w", err) } - repos = append(repos, &repo.Repository{ - Repository: *repoBase, + reposOutput = append(reposOutput, &repoCtrl.Repository{ + Repository: *repo, IsPublic: isPublic, }) } @@ -93,5 +94,5 @@ func (c *Controller) ListRepositoriesNoAuth( return nil, 0, err } - return repos, count, nil + return reposOutput, count, nil } diff --git a/app/api/controller/space/list_spaces.go b/app/api/controller/space/list_spaces.go index 6b8154a4c2..e409edfe6d 100644 --- a/app/api/controller/space/list_spaces.go +++ b/app/api/controller/space/list_spaces.go @@ -56,7 +56,7 @@ func (c *Controller) ListSpacesNoAuth( spaceID int64, filter *types.SpaceFilter, ) ([]*Space, int64, error) { - var spaces []*Space + var spacesOutput []*Space var count int64 err := c.tx.WithTx(ctx, func(ctx context.Context) (err error) { @@ -65,20 +65,20 @@ func (c *Controller) ListSpacesNoAuth( return fmt.Errorf("failed to count child spaces: %w", err) } - spacesBase, err := c.spaceStore.List(ctx, spaceID, filter) + spaces, err := c.spaceStore.List(ctx, spaceID, filter) if err != nil { return fmt.Errorf("failed to list child spaces: %w", err) } - for _, spaceBase := range spacesBase { + for _, space := range spaces { // backfill public access mode - isPublic, err := apiauth.CheckSpaceIsPublic(ctx, c.publicAccess, spaceBase) + isPublic, err := apiauth.CheckSpaceIsPublic(ctx, c.publicAccess, space) if err != nil { return fmt.Errorf("failed to get resource public access mode: %w", err) } - spaces = append(spaces, &Space{ - Space: *spaceBase, + spacesOutput = append(spacesOutput, &Space{ + Space: *space, IsPublic: isPublic, }) } @@ -89,5 +89,5 @@ func (c *Controller) ListSpacesNoAuth( return nil, 0, err } - return spaces, count, nil + return spacesOutput, count, nil } diff --git a/app/auth/anonymouse.go b/app/auth/anonymouse.go index ad8e97fa42..f46f3ffc1b 100644 --- a/app/auth/anonymouse.go +++ b/app/auth/anonymouse.go @@ -19,7 +19,7 @@ import ( "github.com/harness/gitness/types/enum" ) -// anonymousPrincipal is an in-memory principal for users with no auth data. +// AnonymousPrincipal is an in-memory principal for users with no auth data. // Authorizer is in charge of handling anonymouse access. var AnonymousPrincipal = types.Principal{ ID: -1, diff --git a/app/services/exporter/repository.go b/app/services/exporter/repository.go index c7eb3bcf2e..9488f2cd9c 100644 --- a/app/services/exporter/repository.go +++ b/app/services/exporter/repository.go @@ -24,6 +24,7 @@ import ( "strings" "time" + "github.com/harness/gitness/app/api/auth" "github.com/harness/gitness/app/api/controller/repo" "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/sse" @@ -116,11 +117,16 @@ func (r *Repository) RunManyForSpace( jobDefinitions := make([]job.Definition, len(repos)) for i, repository := range repos { + isPublic, err := auth.CheckRepoIsPublic(ctx, r.publicAccess, repository) + if err != nil { + return fmt.Errorf("failed to check repo public access: %w", err) + } + repoJobData := Input{ Identifier: repository.Identifier, ID: repository.ID, Description: repository.Description, - IsPublic: false, // todo: use repository.IsPublic once public is available. + IsPublic: isPublic, HarnessCodeInfo: *harnessCodeInfo, } diff --git a/app/services/publicaccess/service.go b/app/services/publicaccess/service.go index 690c00807d..c627ba8bf7 100644 --- a/app/services/publicaccess/service.go +++ b/app/services/publicaccess/service.go @@ -22,6 +22,7 @@ import ( "github.com/harness/gitness/app/store" gitness_store "github.com/harness/gitness/store" "github.com/harness/gitness/types/enum" + "github.com/rs/zerolog/log" ) type Service struct { @@ -77,6 +78,7 @@ func (s *Service) Set( if enable { err := s.publicAccessStore.Create(ctx, resourceType, pubResID) if errors.Is(err, gitness_store.ErrDuplicate) { + log.Ctx(ctx).Warn().Msgf("repo %d is already set for public access", pubResID) return nil } return err diff --git a/types/repo.go b/types/repo.go index 3ae3704d9c..d61fe1dde0 100644 --- a/types/repo.go +++ b/types/repo.go @@ -57,6 +57,18 @@ type Repository struct { GitURL string `json:"git_url" yaml:"git_url"` } +// Clone makes deep copy of repository object. +func (r Repository) Clone() Repository { + var deleted *int64 + if r.Deleted != nil { + id := *r.Deleted + deleted = &id + } + r.Deleted = deleted + + return r +} + // TODO [CODE-1363]: remove after identifier migration. func (r Repository) MarshalJSON() ([]byte, error) { // alias allows us to embed the original object while avoiding an infinite loop of marshaling. @@ -70,18 +82,6 @@ func (r Repository) MarshalJSON() ([]byte, error) { }) } -// Clone makes deep copy of repository object. -func (r Repository) Clone() Repository { - var deleted *int64 - if r.Deleted != nil { - id := *r.Deleted - deleted = &id - } - r.Deleted = deleted - - return r -} - type RepositorySizeInfo struct { ID int64 `json:"id"` GitUID string `json:"git_uid"` From 507e4c88694750442588d4d53517960720c8ea43 Mon Sep 17 00:00:00 2001 From: atefeh Date: Tue, 7 May 2024 11:55:13 -0700 Subject: [PATCH 18/31] updated openapis and consistency among ctrl on repo/space --- app/api/controller/repo/find.go | 5 ++--- app/api/controller/repo/move.go | 6 +++--- app/api/controller/space/create.go | 6 +++--- app/api/controller/space/find.go | 5 ++--- app/api/controller/space/import.go | 4 ++-- app/api/controller/space/move.go | 6 +++--- app/api/controller/space/restore.go | 4 ++-- app/api/openapi/repo.go | 32 +++++++++++++++++++++++------ app/api/openapi/space.go | 14 ++++++------- 9 files changed, 50 insertions(+), 32 deletions(-) diff --git a/app/api/controller/repo/find.go b/app/api/controller/repo/find.go index 145bbba220..6ba7f3b81b 100644 --- a/app/api/controller/repo/find.go +++ b/app/api/controller/repo/find.go @@ -19,12 +19,11 @@ import ( apiauth "github.com/harness/gitness/app/api/auth" "github.com/harness/gitness/app/auth" - "github.com/harness/gitness/types" "github.com/harness/gitness/types/enum" ) // Find finds a repo. -func (c *Controller) Find(ctx context.Context, session *auth.Session, repoRef string) (*types.Repository, error) { +func (c *Controller) Find(ctx context.Context, session *auth.Session, repoRef string) (*Repository, error) { // note: can't use c.getRepoCheckAccess because even repositories that are currently being imported can be fetched. repo, err := c.repoStore.FindByRef(ctx, repoRef) if err != nil { @@ -38,5 +37,5 @@ func (c *Controller) Find(ctx context.Context, session *auth.Session, repoRef st // backfill clone url repo.GitURL = c.urlProvider.GenerateGITCloneURL(repo.Path) - return repo, nil + return GetRepoOutput(ctx, c.publicAccess, repo) } diff --git a/app/api/controller/repo/move.go b/app/api/controller/repo/move.go index 3360c4df86..05f2eb071f 100644 --- a/app/api/controller/repo/move.go +++ b/app/api/controller/repo/move.go @@ -48,7 +48,7 @@ func (c *Controller) Move(ctx context.Context, session *auth.Session, repoRef string, in *MoveInput, -) (*types.Repository, error) { +) (*Repository, error) { if err := c.sanitizeMoveInput(in); err != nil { return nil, fmt.Errorf("failed to sanitize input: %w", err) } @@ -67,7 +67,7 @@ func (c *Controller) Move(ctx context.Context, } if !in.hasChanges(repo) { - return repo, nil + return GetRepoOutput(ctx, c.publicAccess, repo) } repo, err = c.repoStore.UpdateOptLock(ctx, repo, func(r *types.Repository) error { @@ -82,7 +82,7 @@ func (c *Controller) Move(ctx context.Context, repo.GitURL = c.urlProvider.GenerateGITCloneURL(repo.Path) - return repo, nil + return GetRepoOutput(ctx, c.publicAccess, repo) } func (c *Controller) sanitizeMoveInput(in *MoveInput) error { diff --git a/app/api/controller/space/create.go b/app/api/controller/space/create.go index bd26afe41f..96b39684ee 100644 --- a/app/api/controller/space/create.go +++ b/app/api/controller/space/create.go @@ -157,7 +157,7 @@ func (c *Controller) getSpaceCheckAuthSpaceCreation( ctx context.Context, session *auth.Session, parentRef string, -) (*types.Space, error) { +) (*Space, error) { parentRefAsID, err := strconv.ParseInt(parentRef, 10, 64) if (parentRefAsID <= 0 && err == nil) || (len(strings.TrimSpace(parentRef)) == 0) { // TODO: Restrict top level space creation - should be move to authorizer? @@ -165,7 +165,7 @@ func (c *Controller) getSpaceCheckAuthSpaceCreation( return nil, fmt.Errorf("anonymous user not allowed to create top level spaces: %w", usererror.ErrUnauthorized) } - return &types.Space{}, nil + return &Space{}, nil } parentSpace, err := c.spaceStore.FindByRef(ctx, parentRef) @@ -184,7 +184,7 @@ func (c *Controller) getSpaceCheckAuthSpaceCreation( return nil, fmt.Errorf("authorization failed: %w", err) } - return parentSpace, nil + return GetSpaceOutput(ctx, c.publicAccess, parentSpace) } func (c *Controller) setSpacePublicAccess( diff --git a/app/api/controller/space/find.go b/app/api/controller/space/find.go index 9295ec47c8..ae3786aec7 100644 --- a/app/api/controller/space/find.go +++ b/app/api/controller/space/find.go @@ -19,14 +19,13 @@ import ( apiauth "github.com/harness/gitness/app/api/auth" "github.com/harness/gitness/app/auth" - "github.com/harness/gitness/types" "github.com/harness/gitness/types/enum" ) /* * Find finds a space. */ -func (c *Controller) Find(ctx context.Context, session *auth.Session, spaceRef string) (*types.Space, error) { +func (c *Controller) Find(ctx context.Context, session *auth.Session, spaceRef string) (*Space, error) { space, err := c.spaceStore.FindByRef(ctx, spaceRef) if err != nil { return nil, err @@ -36,5 +35,5 @@ func (c *Controller) Find(ctx context.Context, session *auth.Session, spaceRef s return nil, err } - return space, nil + return GetSpaceOutput(ctx, c.publicAccess, space) } diff --git a/app/api/controller/space/import.go b/app/api/controller/space/import.go index b7b778b70c..fc03576f9c 100644 --- a/app/api/controller/space/import.go +++ b/app/api/controller/space/import.go @@ -41,7 +41,7 @@ type ImportInput struct { } // Import creates new space and starts import of all repositories from the remote provider's space into it. -func (c *Controller) Import(ctx context.Context, session *auth.Session, in *ImportInput) (*types.Space, error) { +func (c *Controller) Import(ctx context.Context, session *auth.Session, in *ImportInput) (*Space, error) { parentSpace, err := c.getSpaceCheckAuthSpaceCreation(ctx, session, in.ParentRef) if err != nil { return nil, err @@ -135,7 +135,7 @@ func (c *Controller) Import(ctx context.Context, session *auth.Session, in *Impo } } - return space, nil + return GetSpaceOutput(ctx, c.publicAccess, space) } func (c *Controller) sanitizeImportInput(in *ImportInput) error { diff --git a/app/api/controller/space/move.go b/app/api/controller/space/move.go index 07d81af02c..ccb1b58c95 100644 --- a/app/api/controller/space/move.go +++ b/app/api/controller/space/move.go @@ -49,7 +49,7 @@ func (c *Controller) Move( session *auth.Session, spaceRef string, in *MoveInput, -) (*types.Space, error) { +) (*Space, error) { space, err := c.spaceStore.FindByRef(ctx, spaceRef) if err != nil { return nil, err @@ -65,7 +65,7 @@ func (c *Controller) Move( // exit early if there are no changes if !in.hasChanges(space) { - return space, nil + return GetSpaceOutput(ctx, c.publicAccess, space) } if err = c.moveInner( @@ -77,7 +77,7 @@ func (c *Controller) Move( return nil, err } - return space, nil + return GetSpaceOutput(ctx, c.publicAccess, space) } func (c *Controller) sanitizeMoveInput(in *MoveInput, isRoot bool) error { diff --git a/app/api/controller/space/restore.go b/app/api/controller/space/restore.go index a0818cf7e9..3e5e0d9922 100644 --- a/app/api/controller/space/restore.go +++ b/app/api/controller/space/restore.go @@ -45,7 +45,7 @@ func (c *Controller) Restore( spaceRef string, deletedAt int64, in *RestoreInput, -) (*types.Space, error) { +) (*Space, error) { if err := c.sanitizeRestoreInput(in); err != nil { return nil, fmt.Errorf("failed to sanitize restore input: %w", err) } @@ -97,7 +97,7 @@ func (c *Controller) Restore( return nil, fmt.Errorf("failed to restore space in a tnx: %w", err) } - return space, nil + return GetSpaceOutput(ctx, c.publicAccess, space) } func (c *Controller) restoreSpaceInnerInTx( diff --git a/app/api/openapi/repo.go b/app/api/openapi/repo.go index c623ac65bc..6b8c71afc2 100644 --- a/app/api/openapi/repo.go +++ b/app/api/openapi/repo.go @@ -200,6 +200,11 @@ type restoreRequest struct { repo.RestoreInput } +type UpdatePublicAccessRequest struct { + repoRequest + repo.PublicAccessUpdateInput +} + type securitySettingsRequest struct { repoRequest reposettings.SecuritySettings @@ -605,7 +610,7 @@ func repoOperations(reflector *openapi3.Reflector) { createRepository.WithMapOfAnything(map[string]interface{}{"operationId": "createRepository"}) createRepository.WithParameters(queryParameterSpacePath) _ = reflector.SetRequest(&createRepository, new(createRepositoryRequest), http.MethodPost) - _ = reflector.SetJSONResponse(&createRepository, new(types.Repository), http.StatusCreated) + _ = reflector.SetJSONResponse(&createRepository, new(repo.Repository), http.StatusCreated) _ = reflector.SetJSONResponse(&createRepository, new(usererror.Error), http.StatusBadRequest) _ = reflector.SetJSONResponse(&createRepository, new(usererror.Error), http.StatusInternalServerError) _ = reflector.SetJSONResponse(&createRepository, new(usererror.Error), http.StatusUnauthorized) @@ -617,7 +622,7 @@ func repoOperations(reflector *openapi3.Reflector) { importRepository.WithMapOfAnything(map[string]interface{}{"operationId": "importRepository"}) importRepository.WithParameters(queryParameterSpacePath) _ = reflector.SetRequest(&importRepository, &struct{ repo.ImportInput }{}, http.MethodPost) - _ = reflector.SetJSONResponse(&importRepository, new(types.Repository), http.StatusCreated) + _ = reflector.SetJSONResponse(&importRepository, new(repo.Repository), http.StatusCreated) _ = reflector.SetJSONResponse(&importRepository, new(usererror.Error), http.StatusBadRequest) _ = reflector.SetJSONResponse(&importRepository, new(usererror.Error), http.StatusInternalServerError) _ = reflector.SetJSONResponse(&importRepository, new(usererror.Error), http.StatusUnauthorized) @@ -628,7 +633,7 @@ func repoOperations(reflector *openapi3.Reflector) { opFind.WithTags("repository") opFind.WithMapOfAnything(map[string]interface{}{"operationId": "findRepository"}) _ = reflector.SetRequest(&opFind, new(repoRequest), http.MethodGet) - _ = reflector.SetJSONResponse(&opFind, new(types.Repository), http.StatusOK) + _ = reflector.SetJSONResponse(&opFind, new(repo.Repository), http.StatusOK) _ = reflector.SetJSONResponse(&opFind, new(usererror.Error), http.StatusInternalServerError) _ = reflector.SetJSONResponse(&opFind, new(usererror.Error), http.StatusUnauthorized) _ = reflector.SetJSONResponse(&opFind, new(usererror.Error), http.StatusForbidden) @@ -639,7 +644,7 @@ func repoOperations(reflector *openapi3.Reflector) { opUpdate.WithTags("repository") opUpdate.WithMapOfAnything(map[string]interface{}{"operationId": "updateRepository"}) _ = reflector.SetRequest(&opUpdate, new(updateRepoRequest), http.MethodPatch) - _ = reflector.SetJSONResponse(&opUpdate, new(types.Repository), http.StatusOK) + _ = reflector.SetJSONResponse(&opUpdate, new(repo.Repository), http.StatusOK) _ = reflector.SetJSONResponse(&opUpdate, new(usererror.Error), http.StatusBadRequest) _ = reflector.SetJSONResponse(&opUpdate, new(usererror.Error), http.StatusInternalServerError) _ = reflector.SetJSONResponse(&opUpdate, new(usererror.Error), http.StatusUnauthorized) @@ -675,7 +680,7 @@ func repoOperations(reflector *openapi3.Reflector) { opRestore.WithMapOfAnything(map[string]interface{}{"operationId": "restoreRepository"}) opRestore.WithParameters(queryParameterDeletedAt) _ = reflector.SetRequest(&opRestore, new(restoreRequest), http.MethodPost) - _ = reflector.SetJSONResponse(&opRestore, new(types.Repository), http.StatusOK) + _ = reflector.SetJSONResponse(&opRestore, new(repo.Repository), http.StatusOK) _ = reflector.SetJSONResponse(&opRestore, new(usererror.Error), http.StatusBadRequest) _ = reflector.SetJSONResponse(&opRestore, new(usererror.Error), http.StatusInternalServerError) _ = reflector.SetJSONResponse(&opRestore, new(usererror.Error), http.StatusUnauthorized) @@ -687,13 +692,28 @@ func repoOperations(reflector *openapi3.Reflector) { opMove.WithTags("repository") opMove.WithMapOfAnything(map[string]interface{}{"operationId": "moveRepository"}) _ = reflector.SetRequest(&opMove, new(moveRepoRequest), http.MethodPost) - _ = reflector.SetJSONResponse(&opMove, new(types.Repository), http.StatusOK) + _ = reflector.SetJSONResponse(&opMove, new(repo.Repository), http.StatusOK) _ = reflector.SetJSONResponse(&opMove, new(usererror.Error), http.StatusBadRequest) _ = reflector.SetJSONResponse(&opMove, new(usererror.Error), http.StatusInternalServerError) _ = reflector.SetJSONResponse(&opMove, new(usererror.Error), http.StatusUnauthorized) _ = reflector.SetJSONResponse(&opMove, new(usererror.Error), http.StatusForbidden) _ = reflector.Spec.AddOperation(http.MethodPost, "/repos/{repo_ref}/move", opMove) + opUpdatePublicAccess := openapi3.Operation{} + opUpdatePublicAccess.WithTags("repository") + opUpdatePublicAccess.WithMapOfAnything( + map[string]interface{}{"operationId": "updatePublicAccess"}) + _ = reflector.SetRequest( + &opUpdatePublicAccess, new(UpdatePublicAccessRequest), http.MethodPost) + _ = reflector.SetJSONResponse(&opUpdatePublicAccess, new(repo.Repository), http.StatusOK) + _ = reflector.SetJSONResponse(&opUpdatePublicAccess, new(usererror.Error), http.StatusBadRequest) + _ = reflector.SetJSONResponse(&opUpdatePublicAccess, new(usererror.Error), http.StatusInternalServerError) + _ = reflector.SetJSONResponse(&opUpdatePublicAccess, new(usererror.Error), http.StatusUnauthorized) + _ = reflector.SetJSONResponse(&opUpdatePublicAccess, new(usererror.Error), http.StatusForbidden) + _ = reflector.SetJSONResponse(&opUpdatePublicAccess, new(usererror.Error), http.StatusNotFound) + _ = reflector.Spec.AddOperation( + http.MethodPatch, "/repos/{repo_ref}/public-access", opUpdatePublicAccess) + opServiceAccounts := openapi3.Operation{} opServiceAccounts.WithTags("repository") opServiceAccounts.WithMapOfAnything(map[string]interface{}{"operationId": "listRepositoryServiceAccounts"}) diff --git a/app/api/openapi/space.go b/app/api/openapi/space.go index bd52e72d84..33d4d05033 100644 --- a/app/api/openapi/space.go +++ b/app/api/openapi/space.go @@ -173,7 +173,7 @@ func spaceOperations(reflector *openapi3.Reflector) { opCreate.WithTags("space") opCreate.WithMapOfAnything(map[string]interface{}{"operationId": "createSpace"}) _ = reflector.SetRequest(&opCreate, new(createSpaceRequest), http.MethodPost) - _ = reflector.SetJSONResponse(&opCreate, new(types.Space), http.StatusCreated) + _ = reflector.SetJSONResponse(&opCreate, new(space.Space), http.StatusCreated) _ = reflector.SetJSONResponse(&opCreate, new(usererror.Error), http.StatusBadRequest) _ = reflector.SetJSONResponse(&opCreate, new(usererror.Error), http.StatusInternalServerError) _ = reflector.SetJSONResponse(&opCreate, new(usererror.Error), http.StatusUnauthorized) @@ -184,7 +184,7 @@ func spaceOperations(reflector *openapi3.Reflector) { opImport.WithTags("space") opImport.WithMapOfAnything(map[string]interface{}{"operationId": "importSpace"}) _ = reflector.SetRequest(&opImport, &struct{ space.ImportInput }{}, http.MethodPost) - _ = reflector.SetJSONResponse(&opImport, new(types.Space), http.StatusCreated) + _ = reflector.SetJSONResponse(&opImport, new(space.Space), http.StatusCreated) _ = reflector.SetJSONResponse(&opImport, new(usererror.Error), http.StatusBadRequest) _ = reflector.SetJSONResponse(&opImport, new(usererror.Error), http.StatusInternalServerError) _ = reflector.SetJSONResponse(&opImport, new(usererror.Error), http.StatusUnauthorized) @@ -228,7 +228,7 @@ func spaceOperations(reflector *openapi3.Reflector) { opGet.WithTags("space") opGet.WithMapOfAnything(map[string]interface{}{"operationId": "getSpace"}) _ = reflector.SetRequest(&opGet, new(spaceRequest), http.MethodGet) - _ = reflector.SetJSONResponse(&opGet, new(types.Space), http.StatusOK) + _ = reflector.SetJSONResponse(&opGet, new(space.Space), http.StatusOK) _ = reflector.SetJSONResponse(&opGet, new(usererror.Error), http.StatusInternalServerError) _ = reflector.SetJSONResponse(&opGet, new(usererror.Error), http.StatusUnauthorized) _ = reflector.SetJSONResponse(&opGet, new(usererror.Error), http.StatusForbidden) @@ -239,7 +239,7 @@ func spaceOperations(reflector *openapi3.Reflector) { opUpdate.WithTags("space") opUpdate.WithMapOfAnything(map[string]interface{}{"operationId": "updateSpace"}) _ = reflector.SetRequest(&opUpdate, new(updateSpaceRequest), http.MethodPatch) - _ = reflector.SetJSONResponse(&opUpdate, new(types.Space), http.StatusOK) + _ = reflector.SetJSONResponse(&opUpdate, new(space.Space), http.StatusOK) _ = reflector.SetJSONResponse(&opUpdate, new(usererror.Error), http.StatusBadRequest) _ = reflector.SetJSONResponse(&opUpdate, new(usererror.Error), http.StatusInternalServerError) _ = reflector.SetJSONResponse(&opUpdate, new(usererror.Error), http.StatusUnauthorized) @@ -275,7 +275,7 @@ func spaceOperations(reflector *openapi3.Reflector) { opRestore.WithMapOfAnything(map[string]interface{}{"operationId": "restoreSpace"}) opRestore.WithParameters(queryParameterDeletedAt) _ = reflector.SetRequest(&opRestore, new(restoreSpaceRequest), http.MethodPost) - _ = reflector.SetJSONResponse(&opRestore, new(types.Space), http.StatusOK) + _ = reflector.SetJSONResponse(&opRestore, new(space.Space), http.StatusOK) _ = reflector.SetJSONResponse(&opRestore, new(usererror.Error), http.StatusBadRequest) _ = reflector.SetJSONResponse(&opRestore, new(usererror.Error), http.StatusInternalServerError) _ = reflector.SetJSONResponse(&opRestore, new(usererror.Error), http.StatusUnauthorized) @@ -287,7 +287,7 @@ func spaceOperations(reflector *openapi3.Reflector) { opMove.WithTags("space") opMove.WithMapOfAnything(map[string]interface{}{"operationId": "moveSpace"}) _ = reflector.SetRequest(&opMove, new(moveSpaceRequest), http.MethodPost) - _ = reflector.SetJSONResponse(&opMove, new(types.Space), http.StatusOK) + _ = reflector.SetJSONResponse(&opMove, new(space.Space), http.StatusOK) _ = reflector.SetJSONResponse(&opMove, new(usererror.Error), http.StatusBadRequest) _ = reflector.SetJSONResponse(&opMove, new(usererror.Error), http.StatusInternalServerError) _ = reflector.SetJSONResponse(&opMove, new(usererror.Error), http.StatusUnauthorized) @@ -301,7 +301,7 @@ func spaceOperations(reflector *openapi3.Reflector) { opSpaces.WithParameters(queryParameterQuerySpace, queryParameterSortSpace, queryParameterOrder, queryParameterPage, queryParameterLimit) _ = reflector.SetRequest(&opSpaces, new(spaceRequest), http.MethodGet) - _ = reflector.SetJSONResponse(&opSpaces, []types.Space{}, http.StatusOK) + _ = reflector.SetJSONResponse(&opSpaces, []space.Space{}, http.StatusOK) _ = reflector.SetJSONResponse(&opSpaces, new(usererror.Error), http.StatusInternalServerError) _ = reflector.SetJSONResponse(&opSpaces, new(usererror.Error), http.StatusUnauthorized) _ = reflector.SetJSONResponse(&opSpaces, new(usererror.Error), http.StatusForbidden) From b775459168db3a79ccb727124fc64fb41329c95c Mon Sep 17 00:00:00 2001 From: atefeh Date: Tue, 7 May 2024 14:27:48 -0700 Subject: [PATCH 19/31] added update space public access and code cleaning --- ...cess_update.go => update_public_access.go} | 10 +-- .../controller/space/update_public_access.go | 61 +++++++++++++++++++ ...cess_update.go => update_public_access.go} | 6 +- app/api/handler/space/update_public_access.go | 52 ++++++++++++++++ app/api/openapi/repo.go | 6 +- app/api/openapi/space.go | 19 ++++++ app/router/api.go | 3 +- 7 files changed, 145 insertions(+), 12 deletions(-) rename app/api/controller/repo/{public_access_update.go => update_public_access.go} (89%) create mode 100644 app/api/controller/space/update_public_access.go rename app/api/handler/repo/{public_access_update.go => update_public_access.go} (88%) create mode 100644 app/api/handler/space/update_public_access.go diff --git a/app/api/controller/repo/public_access_update.go b/app/api/controller/repo/update_public_access.go similarity index 89% rename from app/api/controller/repo/public_access_update.go rename to app/api/controller/repo/update_public_access.go index 048cebaa7c..400a5b53f3 100644 --- a/app/api/controller/repo/public_access_update.go +++ b/app/api/controller/repo/update_public_access.go @@ -27,21 +27,21 @@ import ( "github.com/rs/zerolog/log" ) -type PublicAccessUpdateInput struct { +type UpdatePublicAccessInput struct { EnablePublic bool `json:"enable_public"` } -func (c *Controller) PublicAccessUpdate(ctx context.Context, +func (c *Controller) UpdatePublicAccess(ctx context.Context, session *auth.Session, repoRef string, - in *PublicAccessUpdateInput, + in *UpdatePublicAccessInput, ) (*Repository, error) { repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoEdit) if err != nil { return nil, err } - if err = c.sanitizeVisibilityInput(in); err != nil { + if err = c.sanitizeUpdatePublicAccessInput(in); err != nil { return nil, fmt.Errorf("failed to sanitize input: %w", err) } @@ -84,7 +84,7 @@ func (c *Controller) PublicAccessUpdate(ctx context.Context, } -func (c *Controller) sanitizeVisibilityInput(in *PublicAccessUpdateInput) error { +func (c *Controller) sanitizeUpdatePublicAccessInput(in *UpdatePublicAccessInput) error { if in.EnablePublic && !c.publicResourceCreationEnabled { return errPublicRepoCreationDisabled } diff --git a/app/api/controller/space/update_public_access.go b/app/api/controller/space/update_public_access.go new file mode 100644 index 0000000000..5afdba9ffa --- /dev/null +++ b/app/api/controller/space/update_public_access.go @@ -0,0 +1,61 @@ +// Copyright 2023 Harness, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package space + +import ( + "context" + "fmt" + + apiauth "github.com/harness/gitness/app/api/auth" + "github.com/harness/gitness/app/auth" + "github.com/harness/gitness/types/enum" +) + +type UpdatePublicAccessInput struct { + EnablePublic bool `json:"enable_public"` +} + +func (c *Controller) UpdatePublicAccess(ctx context.Context, + session *auth.Session, + spaceRef string, + in *UpdatePublicAccessInput, +) (*Space, error) { + space, err := c.spaceStore.FindByRef(ctx, spaceRef) + if err != nil { + return nil, err + } + + if err = apiauth.CheckSpace(ctx, c.authorizer, session, space, enum.PermissionSpaceEdit); err != nil { + return nil, err + } + + if err = c.sanitizeUpdatePublicAccessInput(in); err != nil { + return nil, fmt.Errorf("failed to sanitize input: %w", err) + } + + if err = c.publicAccess.Set(ctx, enum.PublicResourceTypeSpace, space.Path, in.EnablePublic); err != nil { + return nil, fmt.Errorf("failed to update space public access: %w", err) + } + + return GetSpaceOutput(ctx, c.publicAccess, space) +} + +func (c *Controller) sanitizeUpdatePublicAccessInput(in *UpdatePublicAccessInput) error { + if in.EnablePublic && !c.publicResourceCreationEnabled { + return errPublicSpaceCreationDisabled + } + + return nil +} diff --git a/app/api/handler/repo/public_access_update.go b/app/api/handler/repo/update_public_access.go similarity index 88% rename from app/api/handler/repo/public_access_update.go rename to app/api/handler/repo/update_public_access.go index f6a6b1dbc2..e1b2d63844 100644 --- a/app/api/handler/repo/public_access_update.go +++ b/app/api/handler/repo/update_public_access.go @@ -23,7 +23,7 @@ import ( "github.com/harness/gitness/app/api/request" ) -func HandlePublicAccessUpdate(repoCtrl *repo.Controller) http.HandlerFunc { +func HandleUpdatePublicAccess(repoCtrl *repo.Controller) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { ctx := r.Context() session, _ := request.AuthSessionFrom(ctx) @@ -34,14 +34,14 @@ func HandlePublicAccessUpdate(repoCtrl *repo.Controller) http.HandlerFunc { return } - in := new(repo.PublicAccessUpdateInput) + in := new(repo.UpdatePublicAccessInput) err = json.NewDecoder(r.Body).Decode(in) if err != nil { render.BadRequestf(ctx, w, "Invalid Request Body: %s.", err) return } - res, err := repoCtrl.PublicAccessUpdate(ctx, session, repoRef, in) + res, err := repoCtrl.UpdatePublicAccess(ctx, session, repoRef, in) if err != nil { render.TranslatedUserError(ctx, w, err) return diff --git a/app/api/handler/space/update_public_access.go b/app/api/handler/space/update_public_access.go new file mode 100644 index 0000000000..d7ccbfd140 --- /dev/null +++ b/app/api/handler/space/update_public_access.go @@ -0,0 +1,52 @@ +// Copyright 2023 Harness, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package space + +import ( + "encoding/json" + "net/http" + + "github.com/harness/gitness/app/api/controller/space" + "github.com/harness/gitness/app/api/render" + "github.com/harness/gitness/app/api/request" +) + +// HandleUpdatePublicAccess updates public access mode of an existing space. +func HandleUpdatePublicAccess(spaceCtrl *space.Controller) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + session, _ := request.AuthSessionFrom(ctx) + spaceRef, err := request.GetSpaceRefFromPath(r) + if err != nil { + render.TranslatedUserError(ctx, w, err) + return + } + + in := new(space.UpdatePublicAccessInput) + err = json.NewDecoder(r.Body).Decode(in) + if err != nil { + render.BadRequestf(ctx, w, "Invalid request body: %s.", err) + return + } + + space, err := spaceCtrl.UpdatePublicAccess(ctx, session, spaceRef, in) + if err != nil { + render.TranslatedUserError(ctx, w, err) + return + } + + render.JSON(w, http.StatusOK, space) + } +} diff --git a/app/api/openapi/repo.go b/app/api/openapi/repo.go index 6b8c71afc2..328a5c1a9d 100644 --- a/app/api/openapi/repo.go +++ b/app/api/openapi/repo.go @@ -200,9 +200,9 @@ type restoreRequest struct { repo.RestoreInput } -type UpdatePublicAccessRequest struct { +type updateRepoPublicAccessRequest struct { repoRequest - repo.PublicAccessUpdateInput + repo.UpdatePublicAccessInput } type securitySettingsRequest struct { @@ -704,7 +704,7 @@ func repoOperations(reflector *openapi3.Reflector) { opUpdatePublicAccess.WithMapOfAnything( map[string]interface{}{"operationId": "updatePublicAccess"}) _ = reflector.SetRequest( - &opUpdatePublicAccess, new(UpdatePublicAccessRequest), http.MethodPost) + &opUpdatePublicAccess, new(updateRepoPublicAccessRequest), http.MethodPost) _ = reflector.SetJSONResponse(&opUpdatePublicAccess, new(repo.Repository), http.StatusOK) _ = reflector.SetJSONResponse(&opUpdatePublicAccess, new(usererror.Error), http.StatusBadRequest) _ = reflector.SetJSONResponse(&opUpdatePublicAccess, new(usererror.Error), http.StatusInternalServerError) diff --git a/app/api/openapi/space.go b/app/api/openapi/space.go index 33d4d05033..8011e0e3d7 100644 --- a/app/api/openapi/space.go +++ b/app/api/openapi/space.go @@ -40,6 +40,10 @@ type updateSpaceRequest struct { space.UpdateInput } +type updateSpacePublicAccessRequest struct { + spaceRequest + space.UpdatePublicAccessInput +} type moveSpaceRequest struct { spaceRequest space.MoveInput @@ -247,6 +251,21 @@ func spaceOperations(reflector *openapi3.Reflector) { _ = reflector.SetJSONResponse(&opUpdate, new(usererror.Error), http.StatusNotFound) _ = reflector.Spec.AddOperation(http.MethodPatch, "/spaces/{space_ref}", opUpdate) + opUpdatePublicAccess := openapi3.Operation{} + opUpdatePublicAccess.WithTags("space") + opUpdatePublicAccess.WithMapOfAnything( + map[string]interface{}{"operationId": "updatePublicAccess"}) + _ = reflector.SetRequest( + &opUpdatePublicAccess, new(updateSpacePublicAccessRequest), http.MethodPost) + _ = reflector.SetJSONResponse(&opUpdatePublicAccess, new(space.Space), http.StatusOK) + _ = reflector.SetJSONResponse(&opUpdatePublicAccess, new(usererror.Error), http.StatusBadRequest) + _ = reflector.SetJSONResponse(&opUpdatePublicAccess, new(usererror.Error), http.StatusInternalServerError) + _ = reflector.SetJSONResponse(&opUpdatePublicAccess, new(usererror.Error), http.StatusUnauthorized) + _ = reflector.SetJSONResponse(&opUpdatePublicAccess, new(usererror.Error), http.StatusForbidden) + _ = reflector.SetJSONResponse(&opUpdatePublicAccess, new(usererror.Error), http.StatusNotFound) + _ = reflector.Spec.AddOperation( + http.MethodPatch, "/spaces/{space_ref}/public-access", opUpdatePublicAccess) + opDelete := openapi3.Operation{} opDelete.WithTags("space") opDelete.WithMapOfAnything(map[string]interface{}{"operationId": "deleteSpace"}) diff --git a/app/router/api.go b/app/router/api.go index 35a59730be..4831990be5 100644 --- a/app/router/api.go +++ b/app/router/api.go @@ -241,6 +241,7 @@ func setupSpaces(r chi.Router, appCtx context.Context, spaceCtrl *space.Controll r.Get("/templates", handlerspace.HandleListTemplates(spaceCtrl)) r.Post("/export", handlerspace.HandleExport(spaceCtrl)) r.Get("/export-progress", handlerspace.HandleExportProgress(spaceCtrl)) + r.Post("/public-access", handlerspace.HandleUpdatePublicAccess(spaceCtrl)) r.Route("/members", func(r chi.Router) { r.Get("/", handlerspace.HandleMembershipList(spaceCtrl)) @@ -277,7 +278,7 @@ func setupRepos(r chi.Router, r.Delete("/", handlerrepo.HandleSoftDelete(repoCtrl)) r.Post("/purge", handlerrepo.HandlePurge(repoCtrl)) r.Post("/restore", handlerrepo.HandleRestore(repoCtrl)) - r.Post("/public-access", handlerrepo.HandlePublicAccessUpdate(repoCtrl)) + r.Post("/public-access", handlerrepo.HandleUpdatePublicAccess(repoCtrl)) r.Route("/settings", func(r chi.Router) { r.Get("/security", handlerreposettings.HandleSecurityFind(repoSettingsCtrl)) From deb003f08918e2e17597f9e64a84aad318898273 Mon Sep 17 00:00:00 2001 From: Ritik Kapoor Date: Tue, 7 May 2024 17:30:45 +0530 Subject: [PATCH 20/31] fix: [ritik/code-1773] Added Repository Setting for Public/Private Access --- web/src/App.tsx | 6 +- web/src/AppContext.tsx | 3 +- web/src/AppProps.ts | 1 + web/src/bootstrap.tsx | 1 + web/src/framework/strings/stringTypes.ts | 2 + web/src/i18n/strings.en.yaml | 4 +- .../GeneralSettingsContent.tsx | 115 +++++++++++------- .../RepositorySettings.module.scss | 1 - 8 files changed, 84 insertions(+), 49 deletions(-) diff --git a/web/src/App.tsx b/web/src/App.tsx index effac21cb7..098b8ab2d3 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -48,7 +48,8 @@ const App: React.FC = React.memo(function App({ hooks, customComponents, currentUserProfileURL = '', - defaultSettingsURL = '' + defaultSettingsURL = '', + isPublicAccessEnabledOnResources = false }: AppProps) { const [strings, setStrings] = useState() const getRequestOptions = useCallback( @@ -90,7 +91,8 @@ const App: React.FC = React.memo(function App({ currentUser: defaultCurrentUser, customComponents, currentUserProfileURL, - defaultSettingsURL + defaultSettingsURL, + isPublicAccessEnabledOnResources }}> ({ }, currentUserProfileURL: '', routingId: '', - defaultSettingsURL: '' + defaultSettingsURL: '', + isPublicAccessEnabledOnResources: false }) export const AppContextProvider: React.FC<{ value: AppProps }> = React.memo(function AppContextProvider({ diff --git a/web/src/AppProps.ts b/web/src/AppProps.ts index c4ae2d687a..905f6c83dc 100644 --- a/web/src/AppProps.ts +++ b/web/src/AppProps.ts @@ -78,4 +78,5 @@ export interface AppProps { currentUserProfileURL: string defaultSettingsURL: string + isPublicAccessEnabledOnResources: boolean } diff --git a/web/src/bootstrap.tsx b/web/src/bootstrap.tsx index a712f307c2..3ed96d8c9d 100644 --- a/web/src/bootstrap.tsx +++ b/web/src/bootstrap.tsx @@ -50,6 +50,7 @@ ReactDOM.render( currentUserProfileURL="" routingId="" defaultSettingsURL="" + isPublicAccessEnabledOnResources />, document.getElementById('react-root') ) diff --git a/web/src/framework/strings/stringTypes.ts b/web/src/framework/strings/stringTypes.ts index 4b114ff301..38ea9c6494 100644 --- a/web/src/framework/strings/stringTypes.ts +++ b/web/src/framework/strings/stringTypes.ts @@ -179,6 +179,7 @@ export interface StringsMap { confirmNewPassword: string confirmPassRequired: string confirmPassword: string + confirmRepoVisButton: string confirmation: string content: string contents: string @@ -206,6 +207,7 @@ export interface StringsMap { 'createRepoModal.branchLabel': string 'createRepoModal.privateLabel': string 'createRepoModal.publicLabel': string + 'createRepoModal.publicWarning': string createRepoPerms: string createSpace: string createTag: string diff --git a/web/src/i18n/strings.en.yaml b/web/src/i18n/strings.en.yaml index d9bd67c9a7..ae03fe347a 100644 --- a/web/src/i18n/strings.en.yaml +++ b/web/src/i18n/strings.en.yaml @@ -122,6 +122,7 @@ createRepoModal: branch: ' branch.' publicLabel: Anyone with access to the Gitness environment can clone this repo. privateLabel: You choose who can see and commit to this repository. + publicWarning: Please note that anyone with access to the Gitness environment can clone this repo. validation: repoNamePatternIsNotValid: "Name can only contain alphanumerics, '-', '_', '.', and '$'" gitBranchNameInvalid: Branch name is invalid. @@ -893,7 +894,8 @@ enterGitlabPlaceholder: https://gitlab.com/ enterGithubPlaceholder: https://api.github.com/ enterBitbucketPlaceholder: https://bitbucket.org/ changeRepoVis: Change repository visibility -changeRepoVisContent: Are you sure you want to make this repository {repoVis}? {repoText} +changeRepoVisContent: Are you sure you want to make this repository {repoVis}? +confirmRepoVisButton: Yes, make the Repository {repoVis} repoVisibility: Repository visibility visibility: Visibility attachText: Attach images & videos by dragging & dropping, selecting or pasting them. diff --git a/web/src/pages/RepositorySettings/GeneralSettingsContent/GeneralSettingsContent.tsx b/web/src/pages/RepositorySettings/GeneralSettingsContent/GeneralSettingsContent.tsx index 1b149ba080..fa0e03f849 100644 --- a/web/src/pages/RepositorySettings/GeneralSettingsContent/GeneralSettingsContent.tsx +++ b/web/src/pages/RepositorySettings/GeneralSettingsContent/GeneralSettingsContent.tsx @@ -65,8 +65,7 @@ const GeneralSettingsContent = (props: GeneralSettingsProps) => { const { showError, showSuccess } = useToaster() const space = useGetSpaceParam() - const { standalone } = useAppContext() - const { hooks } = useAppContext() + const { standalone, hooks, isPublicAccessEnabledOnResources } = useAppContext() const { getString } = useStrings() const currRepoVisibility = repoMetadata?.is_public === true ? RepoVisibility.PUBLIC : RepoVisibility.PRIVATE @@ -77,6 +76,11 @@ const GeneralSettingsContent = (props: GeneralSettingsProps) => { path: `/api/v1/repos/${repoMetadata?.path}/+/` }) + const { mutate: changeVisibility } = useMutate({ + verb: 'POST', + path: `/api/v1/repos/${repoMetadata?.path}/+/public-access` + }) + const permEditResult = hooks?.usePermissionTranslate?.( { resource: { @@ -109,50 +113,71 @@ const GeneralSettingsContent = (props: GeneralSettingsProps) => { return ( {getString('changeRepoVis')}} isOpen onClose={hideModal}> - - {repoVis}, - repoText: - repoVis === RepoVisibility.PUBLIC - ? getString('createRepoModal.publicLabel') - : getString('createRepoModal.privateLabel') - }} - /> - -
- -
) } @@ -315,7 +340,7 @@ const GeneralSettingsContent = (props: GeneralSettingsProps) => { - + @@ -330,6 +355,7 @@ const GeneralSettingsContent = (props: GeneralSettingsProps) => { onChange={evt => { setRepoVis((evt.target as HTMLInputElement).value as RepoVisibility) }} + {...permissionProps(permEditResult, standalone)} className={css.radioContainer} items={[ { @@ -391,6 +417,7 @@ const GeneralSettingsContent = (props: GeneralSettingsProps) => { setRepoVis(formik.values.isPublic) openModal() }} + {...permissionProps(permEditResult, standalone)} /> ) : null} diff --git a/web/src/pages/RepositorySettings/RepositorySettings.module.scss b/web/src/pages/RepositorySettings/RepositorySettings.module.scss index 4b25b2eab6..640880926a 100644 --- a/web/src/pages/RepositorySettings/RepositorySettings.module.scss +++ b/web/src/pages/RepositorySettings/RepositorySettings.module.scss @@ -122,7 +122,6 @@ } .dialogContainer { - padding-bottom: 27px !important; :global(.bp3-dialog-header) { margin-bottom: var(--spacing-medium) !important; From 8d827bd1277d034473fce18ac20f373b1e1ca4be Mon Sep 17 00:00:00 2001 From: Ritik Kapoor Date: Tue, 7 May 2024 23:20:02 +0530 Subject: [PATCH 21/31] feat: [ritik/code-1773] Added global variable for hiding semantic search in public view --- web/src/App.tsx | 6 ++++-- web/src/AppContext.tsx | 3 ++- web/src/AppProps.ts | 1 + web/src/bootstrap.tsx | 1 + web/src/components/CodeSearchBar/CodeSearchBar.tsx | 6 ++++-- 5 files changed, 12 insertions(+), 5 deletions(-) diff --git a/web/src/App.tsx b/web/src/App.tsx index 098b8ab2d3..8c6e72e478 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -49,7 +49,8 @@ const App: React.FC = React.memo(function App({ customComponents, currentUserProfileURL = '', defaultSettingsURL = '', - isPublicAccessEnabledOnResources = false + isPublicAccessEnabledOnResources = false, + isCurrentSessionPublic = false }: AppProps) { const [strings, setStrings] = useState() const getRequestOptions = useCallback( @@ -92,7 +93,8 @@ const App: React.FC = React.memo(function App({ customComponents, currentUserProfileURL, defaultSettingsURL, - isPublicAccessEnabledOnResources + isPublicAccessEnabledOnResources, + isCurrentSessionPublic }}> ({ currentUserProfileURL: '', routingId: '', defaultSettingsURL: '', - isPublicAccessEnabledOnResources: false + isPublicAccessEnabledOnResources: false, + isCurrentSessionPublic: false }) export const AppContextProvider: React.FC<{ value: AppProps }> = React.memo(function AppContextProvider({ diff --git a/web/src/AppProps.ts b/web/src/AppProps.ts index 905f6c83dc..ecd93f7f9e 100644 --- a/web/src/AppProps.ts +++ b/web/src/AppProps.ts @@ -79,4 +79,5 @@ export interface AppProps { currentUserProfileURL: string defaultSettingsURL: string isPublicAccessEnabledOnResources: boolean + isCurrentSessionPublic: boolean } diff --git a/web/src/bootstrap.tsx b/web/src/bootstrap.tsx index 3ed96d8c9d..8b25b7c42c 100644 --- a/web/src/bootstrap.tsx +++ b/web/src/bootstrap.tsx @@ -51,6 +51,7 @@ ReactDOM.render( routingId="" defaultSettingsURL="" isPublicAccessEnabledOnResources + isCurrentSessionPublic={false} />, document.getElementById('react-root') ) diff --git a/web/src/components/CodeSearchBar/CodeSearchBar.tsx b/web/src/components/CodeSearchBar/CodeSearchBar.tsx index 599e68ac4f..4411345b8c 100644 --- a/web/src/components/CodeSearchBar/CodeSearchBar.tsx +++ b/web/src/components/CodeSearchBar/CodeSearchBar.tsx @@ -42,7 +42,7 @@ const KEYWORD_REGEX = /((?:(?:-{0,1})(?:repo|lang|file|case|count)):\S*|(?: or|a const CodeSearchBar: FC = ({ value, onChange, onSearch, onKeyDown, searchMode, setSearchMode }) => { const { getString } = useStrings() - const { hooks, routingId, defaultSettingsURL } = useAppContext() + const { hooks, routingId, defaultSettingsURL, isCurrentSessionPublic } = useAppContext() const { SEMANTIC_SEARCH_ENABLED: isSemanticSearchFFEnabled } = hooks?.useFeatureFlags() const { orgIdentifier, projectIdentifier } = useParams() const { data: aidaSettingResponse, loading: isAidaSettingLoading } = hooks?.useGetSettingValue({ @@ -51,7 +51,9 @@ const CodeSearchBar: FC = ({ value, onChange, onSearch, onKe }) const [enableSemanticSearch, setEnableSemanticSearch] = useState(false) useEffect(() => { - setEnableSemanticSearch(isSemanticSearchFFEnabled && aidaSettingResponse?.data?.value == 'true') + setEnableSemanticSearch( + isSemanticSearchFFEnabled && aidaSettingResponse?.data?.value == 'true' && !isCurrentSessionPublic + ) }, [isAidaSettingLoading, isSemanticSearchFFEnabled]) const isSemanticMode = enableSemanticSearch && searchMode === SEARCH_MODE.SEMANTIC return ( From 94fde0b33eb6c1f3ee9a9fe92c435d1eb27bea64 Mon Sep 17 00:00:00 2001 From: Ritik Kapoor Date: Wed, 8 May 2024 16:10:08 +0530 Subject: [PATCH 22/31] feat: [ritik/code-1773] hidden search bar for public session --- .../RepositoryPageHeader/RepositoryPageHeader.module.scss | 4 ++++ .../RepositoryPageHeader.module.scss.d.ts | 1 + .../RepositoryPageHeader/RepositoryPageHeader.tsx | 7 +++++-- .../RepositoryContent/ContentHeader/ContentHeader.tsx | 6 ++++-- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/web/src/components/RepositoryPageHeader/RepositoryPageHeader.module.scss b/web/src/components/RepositoryPageHeader/RepositoryPageHeader.module.scss index d5194f3a0a..cc6ea5b837 100644 --- a/web/src/components/RepositoryPageHeader/RepositoryPageHeader.module.scss +++ b/web/src/components/RepositoryPageHeader/RepositoryPageHeader.module.scss @@ -26,3 +26,7 @@ .breadcrumb { align-items: center; } + +.hideBreadcrumbs { + display: none !important; +} diff --git a/web/src/components/RepositoryPageHeader/RepositoryPageHeader.module.scss.d.ts b/web/src/components/RepositoryPageHeader/RepositoryPageHeader.module.scss.d.ts index 71430f2e2e..3952f14a78 100644 --- a/web/src/components/RepositoryPageHeader/RepositoryPageHeader.module.scss.d.ts +++ b/web/src/components/RepositoryPageHeader/RepositoryPageHeader.module.scss.d.ts @@ -18,3 +18,4 @@ // This is an auto-generated file export declare const breadcrumb: string export declare const header: string +export declare const hideBreadcrumbs: string diff --git a/web/src/components/RepositoryPageHeader/RepositoryPageHeader.tsx b/web/src/components/RepositoryPageHeader/RepositoryPageHeader.tsx index bc6b62e7a0..ade5451d25 100644 --- a/web/src/components/RepositoryPageHeader/RepositoryPageHeader.tsx +++ b/web/src/components/RepositoryPageHeader/RepositoryPageHeader.tsx @@ -15,6 +15,7 @@ */ import React, { Fragment } from 'react' +import cx from 'classnames' import { Container, Layout, Text, PageHeader, PageHeaderProps } from '@harnessio/uicore' import { Icon } from '@harnessio/icons' import { Color, FontVariation } from '@harnessio/design-system' @@ -50,7 +51,7 @@ export function RepositoryPageHeader({ const { gitRef } = useParams() const { getString } = useStrings() const space = useGetSpaceParam() - const { routes } = useAppContext() + const { routes, isCurrentSessionPublic } = useAppContext() return ( - + {getString('repositories')} diff --git a/web/src/pages/Repository/RepositoryContent/ContentHeader/ContentHeader.tsx b/web/src/pages/Repository/RepositoryContent/ContentHeader/ContentHeader.tsx index bba6f051ef..a90f34cd4e 100644 --- a/web/src/pages/Repository/RepositoryContent/ContentHeader/ContentHeader.tsx +++ b/web/src/pages/Repository/RepositoryContent/ContentHeader/ContentHeader.tsx @@ -43,7 +43,7 @@ export function ContentHeader({ resourceContent }: Pick) { const { getString } = useStrings() - const { routes, standalone, hooks } = useAppContext() + const { routes, standalone, hooks, isCurrentSessionPublic } = useAppContext() const history = useHistory() const _isDir = isDir(resourceContent) const space = useGetSpaceParam() @@ -164,7 +164,9 @@ export function ContentHeader({ )} -
{!standalone ? : null}
+
+ {!standalone && !isCurrentSessionPublic ? : null} +
) } From 8a08b3239c14f67d8c0451308ddefeb7bf5feb01 Mon Sep 17 00:00:00 2001 From: Ritik Kapoor Date: Wed, 8 May 2024 16:11:20 +0530 Subject: [PATCH 23/31] feat: [ritik/code-1773] checks --- web/src/pages/RepositorySettings/RepositorySettings.module.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/web/src/pages/RepositorySettings/RepositorySettings.module.scss b/web/src/pages/RepositorySettings/RepositorySettings.module.scss index 640880926a..ad3329136f 100644 --- a/web/src/pages/RepositorySettings/RepositorySettings.module.scss +++ b/web/src/pages/RepositorySettings/RepositorySettings.module.scss @@ -122,7 +122,6 @@ } .dialogContainer { - :global(.bp3-dialog-header) { margin-bottom: var(--spacing-medium) !important; } From 5da9d57fab0c0bfc52d8ddc49997da93f026757b Mon Sep 17 00:00:00 2001 From: Ritik Kapoor Date: Thu, 9 May 2024 13:05:58 +0530 Subject: [PATCH 24/31] feat: [ritik/code-1773] updated api payload --- .../GeneralSettingsContent/GeneralSettingsContent.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/pages/RepositorySettings/GeneralSettingsContent/GeneralSettingsContent.tsx b/web/src/pages/RepositorySettings/GeneralSettingsContent/GeneralSettingsContent.tsx index fa0e03f849..b9c92996ac 100644 --- a/web/src/pages/RepositorySettings/GeneralSettingsContent/GeneralSettingsContent.tsx +++ b/web/src/pages/RepositorySettings/GeneralSettingsContent/GeneralSettingsContent.tsx @@ -157,7 +157,7 @@ const GeneralSettingsContent = (props: GeneralSettingsProps) => { } variation={ButtonVariation.PRIMARY} onClick={() => { - changeVisibility({ enable: repoVis === RepoVisibility.PUBLIC ? true : false }) + changeVisibility({ enable_public: repoVis === RepoVisibility.PUBLIC ? true : false }) .then(() => { showSuccess(getString('repoUpdate')) hideModal() From afe58fc6cd37acd9ba6105644cf37db0cf0dcc96 Mon Sep 17 00:00:00 2001 From: atefeh Date: Thu, 9 May 2024 02:31:51 -0700 Subject: [PATCH 25/31] pr comments --- app/api/auth/repo.go | 9 ---- app/api/auth/space.go | 9 ---- app/api/controller/principal/controller.go | 5 ++- app/api/controller/principal/find.go | 3 +- app/api/controller/principal/wire.go | 5 ++- app/api/controller/repo/controller.go | 15 +++---- app/api/controller/repo/default_branch.go | 2 +- app/api/controller/repo/find.go | 2 +- app/api/controller/repo/helper.go | 8 ++-- app/api/controller/repo/import.go | 4 +- app/api/controller/repo/move.go | 2 +- app/api/controller/repo/restore.go | 6 +-- app/api/controller/repo/soft_delete.go | 12 ++---- app/api/controller/repo/update.go | 2 +- .../controller/repo/update_public_access.go | 30 ++++--------- app/api/controller/repo/wire.go | 2 +- app/api/controller/space/controller.go | 6 +-- app/api/controller/space/create.go | 14 +++---- app/api/controller/space/find.go | 2 +- app/api/controller/space/helper.go | 10 ++--- app/api/controller/space/import.go | 2 +- app/api/controller/space/list_repositories.go | 42 ++++++++++--------- app/api/controller/space/list_spaces.go | 37 ++++++++-------- app/api/controller/space/move.go | 2 +- app/api/controller/space/restore.go | 2 +- app/api/controller/space/update.go | 8 +++- .../controller/space/update_public_access.go | 18 ++------ app/api/controller/space/wire.go | 2 +- app/api/handler/principal/find.go | 4 +- app/api/openapi/repo.go | 14 +++---- app/api/openapi/space.go | 16 +++---- app/auth/{anonymouse.go => anonymous.go} | 2 +- app/auth/authz/membership.go | 4 +- app/auth/authz/wire.go | 2 +- app/pipeline/converter/converter.go | 4 +- app/pipeline/converter/service.go | 2 +- app/pipeline/manager/manager.go | 7 ++-- app/pipeline/manager/wire.go | 2 +- app/pipeline/triggerer/trigger.go | 11 +++-- app/pipeline/triggerer/wire.go | 2 +- app/services/exporter/harness_code_client.go | 5 ++- app/services/exporter/repository.go | 13 +++--- app/services/exporter/wire.go | 15 +++---- app/services/publicaccess/public_access.go | 8 ++-- app/services/publicaccess/resources.go | 6 +-- app/services/publicaccess/service.go | 32 +++++++++----- app/services/publicaccess/wire.go | 6 ++- app/store/database/wire.go | 6 +-- cmd/gitness/wire_gen.go | 18 ++++---- types/check/common.go | 10 ++--- types/principal.go | 3 ++ 51 files changed, 207 insertions(+), 246 deletions(-) rename app/auth/{anonymouse.go => anonymous.go} (96%) diff --git a/app/api/auth/repo.go b/app/api/auth/repo.go index 98d59f813e..bca4cdbfb3 100644 --- a/app/api/auth/repo.go +++ b/app/api/auth/repo.go @@ -21,7 +21,6 @@ import ( "github.com/harness/gitness/app/auth" "github.com/harness/gitness/app/auth/authz" "github.com/harness/gitness/app/paths" - "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/types" "github.com/harness/gitness/types/enum" @@ -53,14 +52,6 @@ func CheckRepo( return Check(ctx, authorizer, session, scope, resource, permission) } -func CheckRepoIsPublic( - ctx context.Context, - publicAccess publicaccess.PublicAccess, - repo *types.Repository, -) (bool, error) { - return publicAccess.Get(ctx, enum.PublicResourceTypeRepo, repo.Path) -} - func IsRepoOwner( ctx context.Context, authorizer authz.Authorizer, diff --git a/app/api/auth/space.go b/app/api/auth/space.go index dd95082f91..398676d728 100644 --- a/app/api/auth/space.go +++ b/app/api/auth/space.go @@ -21,7 +21,6 @@ import ( "github.com/harness/gitness/app/auth" "github.com/harness/gitness/app/auth/authz" "github.com/harness/gitness/app/paths" - "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/types" "github.com/harness/gitness/types/enum" ) @@ -69,11 +68,3 @@ func CheckSpaceScope( return Check(ctx, authorizer, session, scope, resource, permission) } - -func CheckSpaceIsPublic( - ctx context.Context, - publicAccess publicaccess.PublicAccess, - space *types.Space, -) (bool, error) { - return publicAccess.Get(ctx, enum.PublicResourceTypeSpace, space.Path) -} diff --git a/app/api/controller/principal/controller.go b/app/api/controller/principal/controller.go index 0b351bed3d..2ad655f8cf 100644 --- a/app/api/controller/principal/controller.go +++ b/app/api/controller/principal/controller.go @@ -15,15 +15,18 @@ package principal import ( + "github.com/harness/gitness/app/auth/authz" "github.com/harness/gitness/app/store" ) type controller struct { principalStore store.PrincipalStore + authorizer authz.Authorizer } -func newController(principalStore store.PrincipalStore) *controller { +func newController(principalStore store.PrincipalStore, authorizer authz.Authorizer) *controller { return &controller{ principalStore: principalStore, + authorizer: authorizer, } } diff --git a/app/api/controller/principal/find.go b/app/api/controller/principal/find.go index 301bdde288..8aae2cfe6f 100644 --- a/app/api/controller/principal/find.go +++ b/app/api/controller/principal/find.go @@ -17,10 +17,11 @@ package principal import ( "context" + "github.com/harness/gitness/app/auth" "github.com/harness/gitness/types" ) -func (c controller) Find(ctx context.Context, principalID int64) (*types.PrincipalInfo, error) { +func (c controller) Find(ctx context.Context, session *auth.Session, principalID int64) (*types.PrincipalInfo, error) { principal, err := c.principalStore.Find(ctx, principalID) if err != nil { return nil, err diff --git a/app/api/controller/principal/wire.go b/app/api/controller/principal/wire.go index 15d8f4dbd6..1c91706995 100644 --- a/app/api/controller/principal/wire.go +++ b/app/api/controller/principal/wire.go @@ -15,6 +15,7 @@ package principal import ( + "github.com/harness/gitness/app/auth/authz" "github.com/harness/gitness/app/store" "github.com/google/wire" @@ -25,6 +26,6 @@ var WireSet = wire.NewSet( ProvideController, ) -func ProvideController(principalStore store.PrincipalStore) Controller { - return newController(principalStore) +func ProvideController(principalStore store.PrincipalStore, authorizer authz.Authorizer) Controller { + return newController(principalStore, authorizer) } diff --git a/app/api/controller/repo/controller.go b/app/api/controller/repo/controller.go index 14a2b2e5c9..0fde863072 100644 --- a/app/api/controller/repo/controller.go +++ b/app/api/controller/repo/controller.go @@ -22,7 +22,6 @@ import ( apiauth "github.com/harness/gitness/app/api/auth" "github.com/harness/gitness/app/api/controller/limiter" - "github.com/harness/gitness/app/api/usererror" "github.com/harness/gitness/app/auth" "github.com/harness/gitness/app/auth/authz" repoevents "github.com/harness/gitness/app/events/repo" @@ -44,13 +43,9 @@ import ( "github.com/harness/gitness/types/enum" ) -var ( - errPublicRepoCreationDisabled = usererror.BadRequestf("Public repository creation is disabled.") -) - -type Repository struct { - types.Repository - IsPublic bool `json:"is_public" yaml:"is_public"` +type RepositoryOutput struct { + types.Repository `json:",inline"` + IsPublic bool `json:"is_public" yaml:"is_public"` } type Controller struct { @@ -79,7 +74,7 @@ type Controller struct { mtxManager lock.MutexManager identifierCheck check.RepoIdentifier repoCheck Check - publicAccess publicaccess.PublicAccess + publicAccess publicaccess.Service } func NewController( @@ -106,7 +101,7 @@ func NewController( mtxManager lock.MutexManager, identifierCheck check.RepoIdentifier, repoCheck Check, - publicAccess publicaccess.PublicAccess, + publicAccess publicaccess.Service, ) *Controller { return &Controller{ defaultBranch: config.Git.DefaultBranch, diff --git a/app/api/controller/repo/default_branch.go b/app/api/controller/repo/default_branch.go index 35e6e7cf7e..ed0cbd7b3b 100644 --- a/app/api/controller/repo/default_branch.go +++ b/app/api/controller/repo/default_branch.go @@ -43,7 +43,7 @@ func (c *Controller) UpdateDefaultBranch( session *auth.Session, repoRef string, in *UpdateDefaultBranchInput, -) (*Repository, error) { +) (*RepositoryOutput, error) { repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoEdit) if err != nil { return nil, err diff --git a/app/api/controller/repo/find.go b/app/api/controller/repo/find.go index 6ba7f3b81b..6a08a93461 100644 --- a/app/api/controller/repo/find.go +++ b/app/api/controller/repo/find.go @@ -23,7 +23,7 @@ import ( ) // Find finds a repo. -func (c *Controller) Find(ctx context.Context, session *auth.Session, repoRef string) (*Repository, error) { +func (c *Controller) Find(ctx context.Context, session *auth.Session, repoRef string) (*RepositoryOutput, error) { // note: can't use c.getRepoCheckAccess because even repositories that are currently being imported can be fetched. repo, err := c.repoStore.FindByRef(ctx, repoRef) if err != nil { diff --git a/app/api/controller/repo/helper.go b/app/api/controller/repo/helper.go index 8a698e2e81..97cce0e484 100644 --- a/app/api/controller/repo/helper.go +++ b/app/api/controller/repo/helper.go @@ -74,15 +74,15 @@ func GetRepoCheckAccess( func GetRepoOutput( ctx context.Context, - publicAccess publicaccess.PublicAccess, + publicAccess publicaccess.Service, repo *types.Repository, -) (*Repository, error) { - isPublic, err := apiauth.CheckRepoIsPublic(ctx, publicAccess, repo) +) (*RepositoryOutput, error) { + isPublic, err := publicAccess.Get(ctx, enum.PublicResourceTypeRepo, repo.Path) if err != nil { return nil, fmt.Errorf("failed to check if repo is public: %w", err) } - return &Repository{ + return &RepositoryOutput{ Repository: *repo, IsPublic: isPublic, }, nil diff --git a/app/api/controller/repo/import.go b/app/api/controller/repo/import.go index bb279bf672..a4ec9fb6d6 100644 --- a/app/api/controller/repo/import.go +++ b/app/api/controller/repo/import.go @@ -42,7 +42,7 @@ type ImportInput struct { } // Import creates a new empty repository and starts git import to it from a remote repository. -func (c *Controller) Import(ctx context.Context, session *auth.Session, in *ImportInput) (*Repository, error) { +func (c *Controller) Import(ctx context.Context, session *auth.Session, in *ImportInput) (*RepositoryOutput, error) { if err := c.sanitizeImportInput(in); err != nil { return nil, fmt.Errorf("failed to sanitize input: %w", err) } @@ -104,7 +104,7 @@ func (c *Controller) Import(ctx context.Context, session *auth.Session, in *Impo repo.GitURL = c.urlProvider.GenerateGITCloneURL(repo.Path) - repoData := &Repository{ + repoData := &RepositoryOutput{ Repository: *repo, IsPublic: isPublic && c.publicResourceCreationEnabled, } diff --git a/app/api/controller/repo/move.go b/app/api/controller/repo/move.go index 05f2eb071f..12958ae052 100644 --- a/app/api/controller/repo/move.go +++ b/app/api/controller/repo/move.go @@ -48,7 +48,7 @@ func (c *Controller) Move(ctx context.Context, session *auth.Session, repoRef string, in *MoveInput, -) (*Repository, error) { +) (*RepositoryOutput, error) { if err := c.sanitizeMoveInput(in); err != nil { return nil, fmt.Errorf("failed to sanitize input: %w", err) } diff --git a/app/api/controller/repo/restore.go b/app/api/controller/repo/restore.go index 8610d3d2d6..38317b6564 100644 --- a/app/api/controller/repo/restore.go +++ b/app/api/controller/repo/restore.go @@ -40,7 +40,7 @@ func (c *Controller) Restore( repoRef string, deletedAt int64, in *RestoreInput, -) (*Repository, error) { +) (*RepositoryOutput, error) { repo, err := c.repoStore.FindByRefAndDeletedAt(ctx, repoRef, deletedAt) if err != nil { return nil, fmt.Errorf("failed to find repository: %w", err) @@ -75,7 +75,7 @@ func (c *Controller) RestoreNoAuth( repo *types.Repository, newIdentifier *string, newParentID int64, -) (*Repository, error) { +) (*RepositoryOutput, error) { var err error err = c.tx.WithTx(ctx, func(ctx context.Context) error { if err := c.resourceLimiter.RepoCount(ctx, newParentID, 1); err != nil { @@ -94,7 +94,7 @@ func (c *Controller) RestoreNoAuth( } // Repos restored as private since public access data is deleted upon deletion. - return &Repository{ + return &RepositoryOutput{ Repository: *repo, IsPublic: false, }, nil diff --git a/app/api/controller/repo/soft_delete.go b/app/api/controller/repo/soft_delete.go index 84d1704c61..a16850ad10 100644 --- a/app/api/controller/repo/soft_delete.go +++ b/app/api/controller/repo/soft_delete.go @@ -88,15 +88,9 @@ func (c *Controller) SoftDeleteNoAuth( return c.PurgeNoAuth(ctx, session, repo) } - isPublic, err := apiauth.CheckRepoIsPublic(ctx, c.publicAccess, repo) - if err != nil { - return fmt.Errorf("failed to check repo public access: %w", err) - } - - if isPublic { - if err := c.SetRepoPublicAccess(ctx, repo, false); err != nil { - return fmt.Errorf("failed to disable repo public access: %w", err) - } + // unset repo public access regardless if it's public/private + if err := c.SetRepoPublicAccess(ctx, repo, false); err != nil { + return fmt.Errorf("failed to disable repo public access: %w", err) } if err := c.repoStore.SoftDelete(ctx, repo, deletedAt); err != nil { diff --git a/app/api/controller/repo/update.go b/app/api/controller/repo/update.go index e178c5450d..c18b066916 100644 --- a/app/api/controller/repo/update.go +++ b/app/api/controller/repo/update.go @@ -43,7 +43,7 @@ func (c *Controller) Update(ctx context.Context, session *auth.Session, repoRef string, in *UpdateInput, -) (*Repository, error) { +) (*RepositoryOutput, error) { repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoEdit) if err != nil { return nil, err diff --git a/app/api/controller/repo/update_public_access.go b/app/api/controller/repo/update_public_access.go index 400a5b53f3..553984ab19 100644 --- a/app/api/controller/repo/update_public_access.go +++ b/app/api/controller/repo/update_public_access.go @@ -18,7 +18,6 @@ import ( "context" "fmt" - apiauth "github.com/harness/gitness/app/api/auth" "github.com/harness/gitness/app/auth" "github.com/harness/gitness/app/paths" "github.com/harness/gitness/audit" @@ -28,37 +27,33 @@ import ( ) type UpdatePublicAccessInput struct { - EnablePublic bool `json:"enable_public"` + IsPublic bool `json:"is_public"` } func (c *Controller) UpdatePublicAccess(ctx context.Context, session *auth.Session, repoRef string, in *UpdatePublicAccessInput, -) (*Repository, error) { +) (*RepositoryOutput, error) { repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoEdit) if err != nil { return nil, err } - if err = c.sanitizeUpdatePublicAccessInput(in); err != nil { - return nil, fmt.Errorf("failed to sanitize input: %w", err) - } - repoClone := repo.Clone() // get current public access vale for audit - isPublic, err := apiauth.CheckRepoIsPublic(ctx, c.publicAccess, repo) + isPublic, err := c.publicAccess.Get(ctx, enum.PublicResourceTypeRepo, repo.Path) if err != nil { return nil, fmt.Errorf("failed to check current public access status: %w", err) } // no op - if isPublic == in.EnablePublic { + if isPublic == in.IsPublic { return GetRepoOutput(ctx, c.publicAccess, repo) } - if err = c.publicAccess.Set(ctx, enum.PublicResourceTypeRepo, repo.Path, in.EnablePublic); err != nil { + if err = c.publicAccess.Set(ctx, enum.PublicResourceTypeRepo, repo.Path, in.IsPublic); err != nil { return nil, fmt.Errorf("failed to update repo public access: %w", err) } @@ -67,13 +62,13 @@ func (c *Controller) UpdatePublicAccess(ctx context.Context, audit.NewResource(audit.ResourceTypeRepository, repo.Identifier), audit.ActionUpdated, paths.Parent(repo.Path), - audit.WithOldObject(&Repository{ + audit.WithOldObject(&RepositoryOutput{ Repository: repoClone, IsPublic: isPublic, }), - audit.WithNewObject(&Repository{ + audit.WithNewObject(&RepositoryOutput{ Repository: *repo, - IsPublic: in.EnablePublic, + IsPublic: in.IsPublic, }), ) if err != nil { @@ -81,13 +76,4 @@ func (c *Controller) UpdatePublicAccess(ctx context.Context, } return GetRepoOutput(ctx, c.publicAccess, repo) - -} - -func (c *Controller) sanitizeUpdatePublicAccessInput(in *UpdatePublicAccessInput) error { - if in.EnablePublic && !c.publicResourceCreationEnabled { - return errPublicRepoCreationDisabled - } - - return nil } diff --git a/app/api/controller/repo/wire.go b/app/api/controller/repo/wire.go index 4fd391b2b7..6e893015ea 100644 --- a/app/api/controller/repo/wire.go +++ b/app/api/controller/repo/wire.go @@ -66,7 +66,7 @@ func ProvideController( mtxManager lock.MutexManager, identifierCheck check.RepoIdentifier, repoChecks Check, - publicAccess publicaccess.PublicAccess, + publicAccess publicaccess.Service, ) *Controller { return NewController(config, tx, urlProvider, authorizer, diff --git a/app/api/controller/space/controller.go b/app/api/controller/space/controller.go index e2f7d237ad..56286fdbd1 100644 --- a/app/api/controller/space/controller.go +++ b/app/api/controller/space/controller.go @@ -37,7 +37,7 @@ var ( errPublicSpaceCreationDisabled = usererror.BadRequestf("Public space creation is disabled.") ) -type Space struct { +type SpaceOutput struct { types.Space IsPublic bool `json:"is_public" yaml:"is_public"` } @@ -64,7 +64,7 @@ type Controller struct { importer *importer.Repository exporter *exporter.Repository resourceLimiter limiter.ResourceLimiter - publicAccess publicaccess.PublicAccess + publicAccess publicaccess.Service auditService audit.Service } @@ -74,7 +74,7 @@ func NewController(config *types.Config, tx dbtx.Transactor, urlProvider url.Pro connectorStore store.ConnectorStore, templateStore store.TemplateStore, spaceStore store.SpaceStore, repoStore store.RepoStore, principalStore store.PrincipalStore, repoCtrl *repo.Controller, membershipStore store.MembershipStore, importer *importer.Repository, exporter *exporter.Repository, - limiter limiter.ResourceLimiter, publicAccess publicaccess.PublicAccess, auditService audit.Service, + limiter limiter.ResourceLimiter, publicAccess publicaccess.Service, auditService audit.Service, ) *Controller { return &Controller{ nestedSpacesEnabled: config.NestedSpacesEnabled, diff --git a/app/api/controller/space/create.go b/app/api/controller/space/create.go index 96b39684ee..7e44f25680 100644 --- a/app/api/controller/space/create.go +++ b/app/api/controller/space/create.go @@ -52,7 +52,7 @@ func (c *Controller) Create( ctx context.Context, session *auth.Session, in *CreateInput, -) (*types.Space, error) { +) (*SpaceOutput, error) { if err := c.sanitizeCreateInput(in); err != nil { return nil, fmt.Errorf("failed to sanitize input: %w", err) } @@ -71,7 +71,7 @@ func (c *Controller) Create( return nil, err } - return space, nil + return GetSpaceOutput(ctx, c.publicAccess, space) } func (c *Controller) createSpaceInnerInTX( @@ -157,7 +157,7 @@ func (c *Controller) getSpaceCheckAuthSpaceCreation( ctx context.Context, session *auth.Session, parentRef string, -) (*Space, error) { +) (*types.Space, error) { parentRefAsID, err := strconv.ParseInt(parentRef, 10, 64) if (parentRefAsID <= 0 && err == nil) || (len(strings.TrimSpace(parentRef)) == 0) { // TODO: Restrict top level space creation - should be move to authorizer? @@ -165,7 +165,7 @@ func (c *Controller) getSpaceCheckAuthSpaceCreation( return nil, fmt.Errorf("anonymous user not allowed to create top level spaces: %w", usererror.ErrUnauthorized) } - return &Space{}, nil + return &types.Space{}, nil } parentSpace, err := c.spaceStore.FindByRef(ctx, parentRef) @@ -184,7 +184,7 @@ func (c *Controller) getSpaceCheckAuthSpaceCreation( return nil, fmt.Errorf("authorization failed: %w", err) } - return GetSpaceOutput(ctx, c.publicAccess, parentSpace) + return parentSpace, nil } func (c *Controller) setSpacePublicAccess( @@ -192,10 +192,6 @@ func (c *Controller) setSpacePublicAccess( space *types.Space, isPublic bool, ) error { - if isPublic && !c.publicResourceCreationEnabled { - return errPublicSpaceCreationDisabled - } - return c.publicAccess.Set(ctx, enum.PublicResourceTypeSpace, space.Path, isPublic) } diff --git a/app/api/controller/space/find.go b/app/api/controller/space/find.go index ae3786aec7..dd8569c6bf 100644 --- a/app/api/controller/space/find.go +++ b/app/api/controller/space/find.go @@ -25,7 +25,7 @@ import ( /* * Find finds a space. */ -func (c *Controller) Find(ctx context.Context, session *auth.Session, spaceRef string) (*Space, error) { +func (c *Controller) Find(ctx context.Context, session *auth.Session, spaceRef string) (*SpaceOutput, error) { space, err := c.spaceStore.FindByRef(ctx, spaceRef) if err != nil { return nil, err diff --git a/app/api/controller/space/helper.go b/app/api/controller/space/helper.go index bf32e2c5f7..9d1eb1292f 100644 --- a/app/api/controller/space/helper.go +++ b/app/api/controller/space/helper.go @@ -18,22 +18,22 @@ import ( "context" "fmt" - apiauth "github.com/harness/gitness/app/api/auth" "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/types" + "github.com/harness/gitness/types/enum" ) func GetSpaceOutput( ctx context.Context, - publicAccess publicaccess.PublicAccess, + publicAccess publicaccess.Service, space *types.Space, -) (*Space, error) { - isPublic, err := apiauth.CheckSpaceIsPublic(ctx, publicAccess, space) +) (*SpaceOutput, error) { + isPublic, err := publicAccess.Get(ctx, enum.PublicResourceTypeSpace, space.Path) if err != nil { return nil, fmt.Errorf("failed to get resource public access mode: %w", err) } - return &Space{ + return &SpaceOutput{ Space: *space, IsPublic: isPublic, }, nil diff --git a/app/api/controller/space/import.go b/app/api/controller/space/import.go index fc03576f9c..2696dd9484 100644 --- a/app/api/controller/space/import.go +++ b/app/api/controller/space/import.go @@ -41,7 +41,7 @@ type ImportInput struct { } // Import creates new space and starts import of all repositories from the remote provider's space into it. -func (c *Controller) Import(ctx context.Context, session *auth.Session, in *ImportInput) (*Space, error) { +func (c *Controller) Import(ctx context.Context, session *auth.Session, in *ImportInput) (*SpaceOutput, error) { parentSpace, err := c.getSpaceCheckAuthSpaceCreation(ctx, session, in.ParentRef) if err != nil { return nil, err diff --git a/app/api/controller/space/list_repositories.go b/app/api/controller/space/list_repositories.go index 7f613e9bcc..2514acbf64 100644 --- a/app/api/controller/space/list_repositories.go +++ b/app/api/controller/space/list_repositories.go @@ -33,7 +33,7 @@ func (c *Controller) ListRepositories( session *auth.Session, spaceRef string, filter *types.RepoFilter, -) ([]*repo.Repository, int64, error) { +) ([]*repo.RepositoryOutput, int64, error) { space, err := c.spaceStore.FindByRef(ctx, spaceRef) if err != nil { return nil, 0, err @@ -58,8 +58,8 @@ func (c *Controller) ListRepositoriesNoAuth( ctx context.Context, spaceID int64, filter *types.RepoFilter, -) ([]*repo.Repository, int64, error) { - var reposOutput []*repo.Repository +) ([]*repo.RepositoryOutput, int64, error) { + var repos []*types.Repository var count int64 err := c.tx.WithTx(ctx, func(ctx context.Context) (err error) { @@ -68,31 +68,33 @@ func (c *Controller) ListRepositoriesNoAuth( return fmt.Errorf("failed to count child repos: %w", err) } - repos, err := c.repoStore.List(ctx, spaceID, filter) + repos, err = c.repoStore.List(ctx, spaceID, filter) if err != nil { return fmt.Errorf("failed to list child repos: %w", err) } - for _, repo := range repos { - // backfill URLs - repo.GitURL = c.urlProvider.GenerateGITCloneURL(repo.Path) - - // backfill public access mode - isPublic, err := apiauth.CheckRepoIsPublic(ctx, c.publicAccess, repo) - if err != nil { - return fmt.Errorf("failed to get resource public access mode: %w", err) - } - - reposOutput = append(reposOutput, &repoCtrl.Repository{ - Repository: *repo, - IsPublic: isPublic, - }) - } return nil }, dbtx.TxDefaultReadOnly) if err != nil { return nil, 0, err } - return reposOutput, count, nil + var reposOut []*repo.RepositoryOutput + for _, repo := range repos { + // backfill URLs + repo.GitURL = c.urlProvider.GenerateGITCloneURL(repo.Path) + + // backfill public access mode + isPublic, err := c.publicAccess.Get(ctx, enum.PublicResourceTypeRepo, repo.Path) + if err != nil { + return nil, 0, fmt.Errorf("failed to get resource public access mode: %w", err) + } + + reposOut = append(reposOut, &repoCtrl.RepositoryOutput{ + Repository: *repo, + IsPublic: isPublic, + }) + } + + return reposOut, count, nil } diff --git a/app/api/controller/space/list_spaces.go b/app/api/controller/space/list_spaces.go index e409edfe6d..d72e5fa146 100644 --- a/app/api/controller/space/list_spaces.go +++ b/app/api/controller/space/list_spaces.go @@ -30,7 +30,7 @@ func (c *Controller) ListSpaces(ctx context.Context, session *auth.Session, spaceRef string, filter *types.SpaceFilter, -) ([]*Space, int64, error) { +) ([]*SpaceOutput, int64, error) { space, err := c.spaceStore.FindByRef(ctx, spaceRef) if err != nil { return nil, 0, err @@ -55,8 +55,8 @@ func (c *Controller) ListSpacesNoAuth( ctx context.Context, spaceID int64, filter *types.SpaceFilter, -) ([]*Space, int64, error) { - var spacesOutput []*Space +) ([]*SpaceOutput, int64, error) { + var spaces []*types.Space var count int64 err := c.tx.WithTx(ctx, func(ctx context.Context) (err error) { @@ -65,29 +65,30 @@ func (c *Controller) ListSpacesNoAuth( return fmt.Errorf("failed to count child spaces: %w", err) } - spaces, err := c.spaceStore.List(ctx, spaceID, filter) + spaces, err = c.spaceStore.List(ctx, spaceID, filter) if err != nil { return fmt.Errorf("failed to list child spaces: %w", err) } - for _, space := range spaces { - // backfill public access mode - isPublic, err := apiauth.CheckSpaceIsPublic(ctx, c.publicAccess, space) - if err != nil { - return fmt.Errorf("failed to get resource public access mode: %w", err) - } - - spacesOutput = append(spacesOutput, &Space{ - Space: *space, - IsPublic: isPublic, - }) - } - return nil }, dbtx.TxDefaultReadOnly) if err != nil { return nil, 0, err } - return spacesOutput, count, nil + // backfill public access mode + var spacesOut []*SpaceOutput + for _, space := range spaces { + isPublic, err := c.publicAccess.Get(ctx, enum.PublicResourceTypeSpace, space.Path) + if err != nil { + return nil, 0, fmt.Errorf("failed to get space public access mode: %w", err) + } + + spacesOut = append(spacesOut, &SpaceOutput{ + Space: *space, + IsPublic: isPublic, + }) + } + + return spacesOut, count, nil } diff --git a/app/api/controller/space/move.go b/app/api/controller/space/move.go index ccb1b58c95..b113770806 100644 --- a/app/api/controller/space/move.go +++ b/app/api/controller/space/move.go @@ -49,7 +49,7 @@ func (c *Controller) Move( session *auth.Session, spaceRef string, in *MoveInput, -) (*Space, error) { +) (*SpaceOutput, error) { space, err := c.spaceStore.FindByRef(ctx, spaceRef) if err != nil { return nil, err diff --git a/app/api/controller/space/restore.go b/app/api/controller/space/restore.go index 3e5e0d9922..152b16acd3 100644 --- a/app/api/controller/space/restore.go +++ b/app/api/controller/space/restore.go @@ -45,7 +45,7 @@ func (c *Controller) Restore( spaceRef string, deletedAt int64, in *RestoreInput, -) (*Space, error) { +) (*SpaceOutput, error) { if err := c.sanitizeRestoreInput(in); err != nil { return nil, fmt.Errorf("failed to sanitize restore input: %w", err) } diff --git a/app/api/controller/space/update.go b/app/api/controller/space/update.go index b9f5e013a7..77813543d9 100644 --- a/app/api/controller/space/update.go +++ b/app/api/controller/space/update.go @@ -36,8 +36,12 @@ func (in *UpdateInput) hasChanges(space *types.Space) bool { } // Update updates a space. -func (c *Controller) Update(ctx context.Context, session *auth.Session, - spaceRef string, in *UpdateInput) (*Space, error) { +func (c *Controller) Update( + ctx context.Context, + session *auth.Session, + spaceRef string, + in *UpdateInput, +) (*SpaceOutput, error) { space, err := c.spaceStore.FindByRef(ctx, spaceRef) if err != nil { return nil, err diff --git a/app/api/controller/space/update_public_access.go b/app/api/controller/space/update_public_access.go index 5afdba9ffa..ef8ff2abad 100644 --- a/app/api/controller/space/update_public_access.go +++ b/app/api/controller/space/update_public_access.go @@ -24,14 +24,14 @@ import ( ) type UpdatePublicAccessInput struct { - EnablePublic bool `json:"enable_public"` + IsPublic bool `json:"is_public"` } func (c *Controller) UpdatePublicAccess(ctx context.Context, session *auth.Session, spaceRef string, in *UpdatePublicAccessInput, -) (*Space, error) { +) (*SpaceOutput, error) { space, err := c.spaceStore.FindByRef(ctx, spaceRef) if err != nil { return nil, err @@ -41,21 +41,9 @@ func (c *Controller) UpdatePublicAccess(ctx context.Context, return nil, err } - if err = c.sanitizeUpdatePublicAccessInput(in); err != nil { - return nil, fmt.Errorf("failed to sanitize input: %w", err) - } - - if err = c.publicAccess.Set(ctx, enum.PublicResourceTypeSpace, space.Path, in.EnablePublic); err != nil { + if err = c.publicAccess.Set(ctx, enum.PublicResourceTypeSpace, space.Path, in.IsPublic); err != nil { return nil, fmt.Errorf("failed to update space public access: %w", err) } return GetSpaceOutput(ctx, c.publicAccess, space) } - -func (c *Controller) sanitizeUpdatePublicAccessInput(in *UpdatePublicAccessInput) error { - if in.EnablePublic && !c.publicResourceCreationEnabled { - return errPublicSpaceCreationDisabled - } - - return nil -} diff --git a/app/api/controller/space/wire.go b/app/api/controller/space/wire.go index 7da580611f..ee59db6927 100644 --- a/app/api/controller/space/wire.go +++ b/app/api/controller/space/wire.go @@ -43,7 +43,7 @@ func ProvideController(config *types.Config, tx dbtx.Transactor, urlProvider url connectorStore store.ConnectorStore, templateStore store.TemplateStore, spaceStore store.SpaceStore, repoStore store.RepoStore, principalStore store.PrincipalStore, repoCtrl *repo.Controller, membershipStore store.MembershipStore, importer *importer.Repository, - exporter *exporter.Repository, limiter limiter.ResourceLimiter, publicAccess publicaccess.PublicAccess, auditService audit.Service, + exporter *exporter.Repository, limiter limiter.ResourceLimiter, publicAccess publicaccess.Service, auditService audit.Service, ) *Controller { return NewController(config, tx, urlProvider, sseStreamer, identifierCheck, authorizer, spacePathStore, pipelineStore, secretStore, diff --git a/app/api/handler/principal/find.go b/app/api/handler/principal/find.go index ca74463a97..2f4705353d 100644 --- a/app/api/handler/principal/find.go +++ b/app/api/handler/principal/find.go @@ -25,14 +25,14 @@ import ( func HandleFind(principalCtrl principal.Controller) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - + session, _ := request.AuthSessionFrom(ctx) principalID, err := request.GetPrincipalIDFromPath(r) if err != nil { render.TranslatedUserError(ctx, w, err) return } - principalInfo, err := principalCtrl.Find(ctx, principalID) + principalInfo, err := principalCtrl.Find(ctx, session, principalID) if err != nil { render.TranslatedUserError(ctx, w, err) return diff --git a/app/api/openapi/repo.go b/app/api/openapi/repo.go index 328a5c1a9d..87a2bd046c 100644 --- a/app/api/openapi/repo.go +++ b/app/api/openapi/repo.go @@ -610,7 +610,7 @@ func repoOperations(reflector *openapi3.Reflector) { createRepository.WithMapOfAnything(map[string]interface{}{"operationId": "createRepository"}) createRepository.WithParameters(queryParameterSpacePath) _ = reflector.SetRequest(&createRepository, new(createRepositoryRequest), http.MethodPost) - _ = reflector.SetJSONResponse(&createRepository, new(repo.Repository), http.StatusCreated) + _ = reflector.SetJSONResponse(&createRepository, new(repo.RepositoryOutput), http.StatusCreated) _ = reflector.SetJSONResponse(&createRepository, new(usererror.Error), http.StatusBadRequest) _ = reflector.SetJSONResponse(&createRepository, new(usererror.Error), http.StatusInternalServerError) _ = reflector.SetJSONResponse(&createRepository, new(usererror.Error), http.StatusUnauthorized) @@ -622,7 +622,7 @@ func repoOperations(reflector *openapi3.Reflector) { importRepository.WithMapOfAnything(map[string]interface{}{"operationId": "importRepository"}) importRepository.WithParameters(queryParameterSpacePath) _ = reflector.SetRequest(&importRepository, &struct{ repo.ImportInput }{}, http.MethodPost) - _ = reflector.SetJSONResponse(&importRepository, new(repo.Repository), http.StatusCreated) + _ = reflector.SetJSONResponse(&importRepository, new(repo.RepositoryOutput), http.StatusCreated) _ = reflector.SetJSONResponse(&importRepository, new(usererror.Error), http.StatusBadRequest) _ = reflector.SetJSONResponse(&importRepository, new(usererror.Error), http.StatusInternalServerError) _ = reflector.SetJSONResponse(&importRepository, new(usererror.Error), http.StatusUnauthorized) @@ -633,7 +633,7 @@ func repoOperations(reflector *openapi3.Reflector) { opFind.WithTags("repository") opFind.WithMapOfAnything(map[string]interface{}{"operationId": "findRepository"}) _ = reflector.SetRequest(&opFind, new(repoRequest), http.MethodGet) - _ = reflector.SetJSONResponse(&opFind, new(repo.Repository), http.StatusOK) + _ = reflector.SetJSONResponse(&opFind, new(repo.RepositoryOutput), http.StatusOK) _ = reflector.SetJSONResponse(&opFind, new(usererror.Error), http.StatusInternalServerError) _ = reflector.SetJSONResponse(&opFind, new(usererror.Error), http.StatusUnauthorized) _ = reflector.SetJSONResponse(&opFind, new(usererror.Error), http.StatusForbidden) @@ -644,7 +644,7 @@ func repoOperations(reflector *openapi3.Reflector) { opUpdate.WithTags("repository") opUpdate.WithMapOfAnything(map[string]interface{}{"operationId": "updateRepository"}) _ = reflector.SetRequest(&opUpdate, new(updateRepoRequest), http.MethodPatch) - _ = reflector.SetJSONResponse(&opUpdate, new(repo.Repository), http.StatusOK) + _ = reflector.SetJSONResponse(&opUpdate, new(repo.RepositoryOutput), http.StatusOK) _ = reflector.SetJSONResponse(&opUpdate, new(usererror.Error), http.StatusBadRequest) _ = reflector.SetJSONResponse(&opUpdate, new(usererror.Error), http.StatusInternalServerError) _ = reflector.SetJSONResponse(&opUpdate, new(usererror.Error), http.StatusUnauthorized) @@ -680,7 +680,7 @@ func repoOperations(reflector *openapi3.Reflector) { opRestore.WithMapOfAnything(map[string]interface{}{"operationId": "restoreRepository"}) opRestore.WithParameters(queryParameterDeletedAt) _ = reflector.SetRequest(&opRestore, new(restoreRequest), http.MethodPost) - _ = reflector.SetJSONResponse(&opRestore, new(repo.Repository), http.StatusOK) + _ = reflector.SetJSONResponse(&opRestore, new(repo.RepositoryOutput), http.StatusOK) _ = reflector.SetJSONResponse(&opRestore, new(usererror.Error), http.StatusBadRequest) _ = reflector.SetJSONResponse(&opRestore, new(usererror.Error), http.StatusInternalServerError) _ = reflector.SetJSONResponse(&opRestore, new(usererror.Error), http.StatusUnauthorized) @@ -692,7 +692,7 @@ func repoOperations(reflector *openapi3.Reflector) { opMove.WithTags("repository") opMove.WithMapOfAnything(map[string]interface{}{"operationId": "moveRepository"}) _ = reflector.SetRequest(&opMove, new(moveRepoRequest), http.MethodPost) - _ = reflector.SetJSONResponse(&opMove, new(repo.Repository), http.StatusOK) + _ = reflector.SetJSONResponse(&opMove, new(repo.RepositoryOutput), http.StatusOK) _ = reflector.SetJSONResponse(&opMove, new(usererror.Error), http.StatusBadRequest) _ = reflector.SetJSONResponse(&opMove, new(usererror.Error), http.StatusInternalServerError) _ = reflector.SetJSONResponse(&opMove, new(usererror.Error), http.StatusUnauthorized) @@ -705,7 +705,7 @@ func repoOperations(reflector *openapi3.Reflector) { map[string]interface{}{"operationId": "updatePublicAccess"}) _ = reflector.SetRequest( &opUpdatePublicAccess, new(updateRepoPublicAccessRequest), http.MethodPost) - _ = reflector.SetJSONResponse(&opUpdatePublicAccess, new(repo.Repository), http.StatusOK) + _ = reflector.SetJSONResponse(&opUpdatePublicAccess, new(repo.RepositoryOutput), http.StatusOK) _ = reflector.SetJSONResponse(&opUpdatePublicAccess, new(usererror.Error), http.StatusBadRequest) _ = reflector.SetJSONResponse(&opUpdatePublicAccess, new(usererror.Error), http.StatusInternalServerError) _ = reflector.SetJSONResponse(&opUpdatePublicAccess, new(usererror.Error), http.StatusUnauthorized) diff --git a/app/api/openapi/space.go b/app/api/openapi/space.go index 8011e0e3d7..992fe4da75 100644 --- a/app/api/openapi/space.go +++ b/app/api/openapi/space.go @@ -177,7 +177,7 @@ func spaceOperations(reflector *openapi3.Reflector) { opCreate.WithTags("space") opCreate.WithMapOfAnything(map[string]interface{}{"operationId": "createSpace"}) _ = reflector.SetRequest(&opCreate, new(createSpaceRequest), http.MethodPost) - _ = reflector.SetJSONResponse(&opCreate, new(space.Space), http.StatusCreated) + _ = reflector.SetJSONResponse(&opCreate, new(space.SpaceOutput), http.StatusCreated) _ = reflector.SetJSONResponse(&opCreate, new(usererror.Error), http.StatusBadRequest) _ = reflector.SetJSONResponse(&opCreate, new(usererror.Error), http.StatusInternalServerError) _ = reflector.SetJSONResponse(&opCreate, new(usererror.Error), http.StatusUnauthorized) @@ -188,7 +188,7 @@ func spaceOperations(reflector *openapi3.Reflector) { opImport.WithTags("space") opImport.WithMapOfAnything(map[string]interface{}{"operationId": "importSpace"}) _ = reflector.SetRequest(&opImport, &struct{ space.ImportInput }{}, http.MethodPost) - _ = reflector.SetJSONResponse(&opImport, new(space.Space), http.StatusCreated) + _ = reflector.SetJSONResponse(&opImport, new(space.SpaceOutput), http.StatusCreated) _ = reflector.SetJSONResponse(&opImport, new(usererror.Error), http.StatusBadRequest) _ = reflector.SetJSONResponse(&opImport, new(usererror.Error), http.StatusInternalServerError) _ = reflector.SetJSONResponse(&opImport, new(usererror.Error), http.StatusUnauthorized) @@ -232,7 +232,7 @@ func spaceOperations(reflector *openapi3.Reflector) { opGet.WithTags("space") opGet.WithMapOfAnything(map[string]interface{}{"operationId": "getSpace"}) _ = reflector.SetRequest(&opGet, new(spaceRequest), http.MethodGet) - _ = reflector.SetJSONResponse(&opGet, new(space.Space), http.StatusOK) + _ = reflector.SetJSONResponse(&opGet, new(space.SpaceOutput), http.StatusOK) _ = reflector.SetJSONResponse(&opGet, new(usererror.Error), http.StatusInternalServerError) _ = reflector.SetJSONResponse(&opGet, new(usererror.Error), http.StatusUnauthorized) _ = reflector.SetJSONResponse(&opGet, new(usererror.Error), http.StatusForbidden) @@ -243,7 +243,7 @@ func spaceOperations(reflector *openapi3.Reflector) { opUpdate.WithTags("space") opUpdate.WithMapOfAnything(map[string]interface{}{"operationId": "updateSpace"}) _ = reflector.SetRequest(&opUpdate, new(updateSpaceRequest), http.MethodPatch) - _ = reflector.SetJSONResponse(&opUpdate, new(space.Space), http.StatusOK) + _ = reflector.SetJSONResponse(&opUpdate, new(space.SpaceOutput), http.StatusOK) _ = reflector.SetJSONResponse(&opUpdate, new(usererror.Error), http.StatusBadRequest) _ = reflector.SetJSONResponse(&opUpdate, new(usererror.Error), http.StatusInternalServerError) _ = reflector.SetJSONResponse(&opUpdate, new(usererror.Error), http.StatusUnauthorized) @@ -257,7 +257,7 @@ func spaceOperations(reflector *openapi3.Reflector) { map[string]interface{}{"operationId": "updatePublicAccess"}) _ = reflector.SetRequest( &opUpdatePublicAccess, new(updateSpacePublicAccessRequest), http.MethodPost) - _ = reflector.SetJSONResponse(&opUpdatePublicAccess, new(space.Space), http.StatusOK) + _ = reflector.SetJSONResponse(&opUpdatePublicAccess, new(space.SpaceOutput), http.StatusOK) _ = reflector.SetJSONResponse(&opUpdatePublicAccess, new(usererror.Error), http.StatusBadRequest) _ = reflector.SetJSONResponse(&opUpdatePublicAccess, new(usererror.Error), http.StatusInternalServerError) _ = reflector.SetJSONResponse(&opUpdatePublicAccess, new(usererror.Error), http.StatusUnauthorized) @@ -294,7 +294,7 @@ func spaceOperations(reflector *openapi3.Reflector) { opRestore.WithMapOfAnything(map[string]interface{}{"operationId": "restoreSpace"}) opRestore.WithParameters(queryParameterDeletedAt) _ = reflector.SetRequest(&opRestore, new(restoreSpaceRequest), http.MethodPost) - _ = reflector.SetJSONResponse(&opRestore, new(space.Space), http.StatusOK) + _ = reflector.SetJSONResponse(&opRestore, new(space.SpaceOutput), http.StatusOK) _ = reflector.SetJSONResponse(&opRestore, new(usererror.Error), http.StatusBadRequest) _ = reflector.SetJSONResponse(&opRestore, new(usererror.Error), http.StatusInternalServerError) _ = reflector.SetJSONResponse(&opRestore, new(usererror.Error), http.StatusUnauthorized) @@ -306,7 +306,7 @@ func spaceOperations(reflector *openapi3.Reflector) { opMove.WithTags("space") opMove.WithMapOfAnything(map[string]interface{}{"operationId": "moveSpace"}) _ = reflector.SetRequest(&opMove, new(moveSpaceRequest), http.MethodPost) - _ = reflector.SetJSONResponse(&opMove, new(space.Space), http.StatusOK) + _ = reflector.SetJSONResponse(&opMove, new(space.SpaceOutput), http.StatusOK) _ = reflector.SetJSONResponse(&opMove, new(usererror.Error), http.StatusBadRequest) _ = reflector.SetJSONResponse(&opMove, new(usererror.Error), http.StatusInternalServerError) _ = reflector.SetJSONResponse(&opMove, new(usererror.Error), http.StatusUnauthorized) @@ -320,7 +320,7 @@ func spaceOperations(reflector *openapi3.Reflector) { opSpaces.WithParameters(queryParameterQuerySpace, queryParameterSortSpace, queryParameterOrder, queryParameterPage, queryParameterLimit) _ = reflector.SetRequest(&opSpaces, new(spaceRequest), http.MethodGet) - _ = reflector.SetJSONResponse(&opSpaces, []space.Space{}, http.StatusOK) + _ = reflector.SetJSONResponse(&opSpaces, []space.SpaceOutput{}, http.StatusOK) _ = reflector.SetJSONResponse(&opSpaces, new(usererror.Error), http.StatusInternalServerError) _ = reflector.SetJSONResponse(&opSpaces, new(usererror.Error), http.StatusUnauthorized) _ = reflector.SetJSONResponse(&opSpaces, new(usererror.Error), http.StatusForbidden) diff --git a/app/auth/anonymouse.go b/app/auth/anonymous.go similarity index 96% rename from app/auth/anonymouse.go rename to app/auth/anonymous.go index f46f3ffc1b..14587741fe 100644 --- a/app/auth/anonymouse.go +++ b/app/auth/anonymous.go @@ -23,6 +23,6 @@ import ( // Authorizer is in charge of handling anonymouse access. var AnonymousPrincipal = types.Principal{ ID: -1, - UID: "anonymous", + UID: types.AnonymousPrincipalUID, Type: enum.PrincipalTypeUser, } diff --git a/app/auth/authz/membership.go b/app/auth/authz/membership.go index 6abea8606f..649ce1b97e 100644 --- a/app/auth/authz/membership.go +++ b/app/auth/authz/membership.go @@ -33,13 +33,13 @@ var _ Authorizer = (*MembershipAuthorizer)(nil) type MembershipAuthorizer struct { permissionCache PermissionCache spaceStore store.SpaceStore - publicAccess publicaccess.PublicAccess + publicAccess publicaccess.Service } func NewMembershipAuthorizer( permissionCache PermissionCache, spaceStore store.SpaceStore, - publicAccess publicaccess.PublicAccess, + publicAccess publicaccess.Service, ) *MembershipAuthorizer { return &MembershipAuthorizer{ permissionCache: permissionCache, diff --git a/app/auth/authz/wire.go b/app/auth/authz/wire.go index 9c7a69bf30..9b500240d9 100644 --- a/app/auth/authz/wire.go +++ b/app/auth/authz/wire.go @@ -32,7 +32,7 @@ var WireSet = wire.NewSet( func ProvideAuthorizer( pCache PermissionCache, spaceStore store.SpaceStore, - publicAccess publicaccess.PublicAccess, + publicAccess publicaccess.Service, ) Authorizer { return NewMembershipAuthorizer(pCache, spaceStore, publicAccess) } diff --git a/app/pipeline/converter/converter.go b/app/pipeline/converter/converter.go index bbd673db1a..06b01cc05c 100644 --- a/app/pipeline/converter/converter.go +++ b/app/pipeline/converter/converter.go @@ -33,7 +33,7 @@ const ( type converter struct { fileService file.Service - publicaccess publicaccess.PublicAccess + publicAccess publicaccess.Service } func newConverter(fileService file.Service) Service { @@ -44,7 +44,7 @@ func (c *converter) Convert(_ context.Context, args *ConvertArgs) (*file.File, e path := args.Pipeline.ConfigPath // get public access visibility of the repo - repoIsPublic, err := c.publicaccess.Get(context.Background(), enum.PublicResourceTypeRepo, args.Repo.Path) + repoIsPublic, err := c.publicAccess.Get(context.Background(), enum.PublicResourceTypeRepo, args.Repo.Path) if err != nil { return nil, err } diff --git a/app/pipeline/converter/service.go b/app/pipeline/converter/service.go index 89c76f18a6..e2bbceb1ef 100644 --- a/app/pipeline/converter/service.go +++ b/app/pipeline/converter/service.go @@ -26,10 +26,10 @@ type ( // conversion service. ConvertArgs struct { Repo *types.Repository `json:"repository,omitempty"` + RepoIsPublic bool `json:"repo_is_public,omitempty"` Pipeline *types.Pipeline `json:"pipeline,omitempty"` Execution *types.Execution `json:"execution,omitempty"` File *file.File `json:"config,omitempty"` - RepoIsPublic bool `json:"repo_is_public,omitempty"` } // Service converts a file which is in starlark/jsonnet form by looking diff --git a/app/pipeline/manager/manager.go b/app/pipeline/manager/manager.go index a16d1e25af..1f968eba30 100644 --- a/app/pipeline/manager/manager.go +++ b/app/pipeline/manager/manager.go @@ -22,7 +22,6 @@ import ( "net/url" "time" - apiauth "github.com/harness/gitness/app/api/auth" "github.com/harness/gitness/app/bootstrap" "github.com/harness/gitness/app/jwt" "github.com/harness/gitness/app/pipeline/converter" @@ -152,7 +151,7 @@ type Manager struct { Users store.PrincipalStore // Webhook store.WebhookSender - publicAccess publicaccess.PublicAccess + publicAccess publicaccess.Service } func New( @@ -172,7 +171,7 @@ func New( stageStore store.StageStore, stepStore store.StepStore, userStore store.PrincipalStore, - publicAccess publicaccess.PublicAccess, + publicAccess publicaccess.Service, ) *Manager { return &Manager{ Config: config, @@ -338,7 +337,7 @@ func (m *Manager) Details(_ context.Context, stageID int64) (*ExecutionContext, } // Get public access settings of the repo - repoIsPublic, err := apiauth.CheckRepoIsPublic(noContext, m.publicAccess, repo) + repoIsPublic, err := m.publicAccess.Get(noContext, enum.PublicResourceTypeRepo, repo.Path) if err != nil { log.Warn().Err(err).Msg("manager: cannot check if repo is public") return nil, err diff --git a/app/pipeline/manager/wire.go b/app/pipeline/manager/wire.go index 09c1e8196b..74a74a65b5 100644 --- a/app/pipeline/manager/wire.go +++ b/app/pipeline/manager/wire.go @@ -53,7 +53,7 @@ func ProvideExecutionManager( stageStore store.StageStore, stepStore store.StepStore, userStore store.PrincipalStore, - PublicAccess publicaccess.PublicAccess, + PublicAccess publicaccess.Service, ) ExecutionManager { return New(config, executionStore, pipelineStore, urlProvider, sseStreamer, fileService, converterService, logStore, logStream, checkStore, repoStore, scheduler, secretStore, stageStore, stepStore, userStore, PublicAccess) diff --git a/app/pipeline/triggerer/trigger.go b/app/pipeline/triggerer/trigger.go index 5da6be225e..e44a80c52d 100644 --- a/app/pipeline/triggerer/trigger.go +++ b/app/pipeline/triggerer/trigger.go @@ -21,7 +21,6 @@ import ( "runtime/debug" "time" - apiauth "github.com/harness/gitness/app/api/auth" "github.com/harness/gitness/app/pipeline/checks" "github.com/harness/gitness/app/pipeline/converter" "github.com/harness/gitness/app/pipeline/file" @@ -94,7 +93,7 @@ type triggerer struct { repoStore store.RepoStore templateStore store.TemplateStore pluginStore store.PluginStore - publicAccess publicaccess.PublicAccess + publicAccess publicaccess.Service } func New( @@ -110,7 +109,7 @@ func New( converterService converter.Service, templateStore store.TemplateStore, pluginStore store.PluginStore, - publicAccess publicaccess.PublicAccess, + publicAccess publicaccess.Service, ) Triggerer { return &triggerer{ executionStore: executionStore, @@ -159,7 +158,7 @@ func (t *triggerer) Trigger( return nil, err } - repoIsPublic, err := apiauth.CheckRepoIsPublic(ctx, t.publicAccess, repo) + repoIsPublic, err := t.publicAccess.Get(ctx, enum.PublicResourceTypeRepo, repo.Path) if err != nil { return nil, fmt.Errorf("could not check if repo is public: %w", err) } @@ -406,7 +405,7 @@ func parseV1Stages( execution *types.Execution, templateStore store.TemplateStore, pluginStore store.PluginStore, - publicaccess publicaccess.PublicAccess, + publicAccess publicaccess.Service, ) ([]*types.Stage, error) { stages := []*types.Stage{} // For V1 YAML, just go through the YAML and create stages serially for now @@ -426,7 +425,7 @@ func parseV1Stages( } // get repo public access - repoIsPublic, err := publicaccess.Get(ctx, enum.PublicResourceTypeRepo, repo.Path) + repoIsPublic, err := publicAccess.Get(ctx, enum.PublicResourceTypeRepo, repo.Path) if err != nil { return nil, fmt.Errorf("could not check repo public access: %w", err) } diff --git a/app/pipeline/triggerer/wire.go b/app/pipeline/triggerer/wire.go index 9b21fd4ff6..41652795de 100644 --- a/app/pipeline/triggerer/wire.go +++ b/app/pipeline/triggerer/wire.go @@ -45,7 +45,7 @@ func ProvideTriggerer( urlProvider url.Provider, templateStore store.TemplateStore, pluginStore store.PluginStore, - publicAccess publicaccess.PublicAccess, + publicAccess publicaccess.Service, ) Triggerer { return New(executionStore, checkStore, stageStore, pipelineStore, tx, repoStore, urlProvider, scheduler, fileService, converterService, diff --git a/app/services/exporter/harness_code_client.go b/app/services/exporter/harness_code_client.go index 43ca13fbe4..92f9a7bd42 100644 --- a/app/services/exporter/harness_code_client.go +++ b/app/services/exporter/harness_code_client.go @@ -25,6 +25,7 @@ import ( "strings" "github.com/harness/gitness/app/api/controller/repo" + "github.com/harness/gitness/types" ) const ( @@ -108,7 +109,7 @@ func newHarnessCodeClient( }, nil } -func (c *harnessCodeClient) CreateRepo(ctx context.Context, input repo.CreateInput) (*repo.Repository, error) { +func (c *harnessCodeClient) CreateRepo(ctx context.Context, input repo.CreateInput) (*types.Repository, error) { path := fmt.Sprintf(pathCreateRepo, c.client.accountID, c.client.orgID, c.client.projectID) bodyBytes, err := json.Marshal(input) if err != nil { @@ -138,7 +139,7 @@ func (c *harnessCodeClient) CreateRepo(ctx context.Context, input repo.CreateInp defer func() { _ = resp.Body.Close() }() } - repository := new(repo.Repository) + repository := new(types.Repository) err = mapStatusCodeToError(resp.StatusCode) if err != nil { return nil, err diff --git a/app/services/exporter/repository.go b/app/services/exporter/repository.go index 9488f2cd9c..c7ce1da2a9 100644 --- a/app/services/exporter/repository.go +++ b/app/services/exporter/repository.go @@ -24,7 +24,6 @@ import ( "strings" "time" - "github.com/harness/gitness/app/api/auth" "github.com/harness/gitness/app/api/controller/repo" "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/sse" @@ -56,7 +55,7 @@ type Repository struct { scheduler *job.Scheduler encrypter encrypt.Encrypter sseStreamer sse.Streamer - publicAccess publicaccess.PublicAccess + publicAccess publicaccess.Service } type Input struct { @@ -117,7 +116,7 @@ func (r *Repository) RunManyForSpace( jobDefinitions := make([]job.Definition, len(repos)) for i, repository := range repos { - isPublic, err := auth.CheckRepoIsPublic(ctx, r.publicAccess, repository) + isPublic, err := r.publicAccess.Get(ctx, enum.PublicResourceTypeRepo, repository.Path) if err != nil { return fmt.Errorf("failed to check repo public access: %w", err) } @@ -197,7 +196,7 @@ func (r *Repository) Handle(ctx context.Context, data string, _ job.ProgressRepo Identifier: repository.Identifier, DefaultBranch: repository.DefaultBranch, Description: repository.Description, - IsPublic: false, // TODO: use apiauth.CheckRepoIsPublic once public access is deployed on HC. + IsPublic: false, // TODO: replace with publicaccess service response once deployed on HC. Readme: false, License: "", GitIgnore: "", @@ -207,7 +206,7 @@ func (r *Repository) Handle(ctx context.Context, data string, _ job.ProgressRepo return "", err } - urlWithToken, err := modifyURL(remoteRepo.Repository.GitURL, harnessCodeInfo.Token) + urlWithToken, err := modifyURL(remoteRepo.GitURL, harnessCodeInfo.Token) if err != nil { return "", err } @@ -217,9 +216,9 @@ func (r *Repository) Handle(ctx context.Context, data string, _ job.ProgressRepo RemoteURL: urlWithToken, }) if err != nil && !strings.Contains(err.Error(), "empty") { - errDelete := client.DeleteRepo(ctx, remoteRepo.Repository.Identifier) + errDelete := client.DeleteRepo(ctx, remoteRepo.Identifier) if errDelete != nil { - log.Ctx(ctx).Err(errDelete).Msgf("failed to delete repo '%s' on harness", remoteRepo.Repository.Identifier) + log.Ctx(ctx).Err(errDelete).Msgf("failed to delete repo '%s' on harness", remoteRepo.Identifier) } r.publishSSE(ctx, repository) return "", err diff --git a/app/services/exporter/wire.go b/app/services/exporter/wire.go index 1b25dd0228..7085dd470e 100644 --- a/app/services/exporter/wire.go +++ b/app/services/exporter/wire.go @@ -15,7 +15,6 @@ package exporter import ( - "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/sse" "github.com/harness/gitness/app/store" "github.com/harness/gitness/app/url" @@ -38,16 +37,14 @@ func ProvideSpaceExporter( executor *job.Executor, encrypter encrypt.Encrypter, sseStreamer sse.Streamer, - publicAccess publicaccess.PublicAccess, ) (*Repository, error) { exporter := &Repository{ - urlProvider: urlProvider, - git: git, - repoStore: repoStore, - scheduler: scheduler, - encrypter: encrypter, - sseStreamer: sseStreamer, - publicAccess: publicAccess, + urlProvider: urlProvider, + git: git, + repoStore: repoStore, + scheduler: scheduler, + encrypter: encrypter, + sseStreamer: sseStreamer, } err := executor.Register(jobType, exporter) diff --git a/app/services/publicaccess/public_access.go b/app/services/publicaccess/public_access.go index 4a789c8c22..3bf7590e31 100644 --- a/app/services/publicaccess/public_access.go +++ b/app/services/publicaccess/public_access.go @@ -20,8 +20,8 @@ import ( "github.com/harness/gitness/types/enum" ) -// PublicAccess is an abstraction of an entity responsible for managing public access to resources. -type PublicAccess interface { +// Service is an abstraction of an entity responsible for managing public access to resources. +type Service interface { /* * Get returns whether public access is enabled on the resource. * Returns @@ -38,8 +38,8 @@ type PublicAccess interface { /* * Sets or deletes public access mode for the resource based on the value of 'enable'. * Returns - * err - resource public access mode has been updated successfully - * nil - an error occurred while performing public access set. + * nil - resource public access mode has been updated successfully + * err - an error occurred while performing public access set. */ Set( ctx context.Context, diff --git a/app/services/publicaccess/resources.go b/app/services/publicaccess/resources.go index e2009be118..f3490b0992 100644 --- a/app/services/publicaccess/resources.go +++ b/app/services/publicaccess/resources.go @@ -21,7 +21,7 @@ import ( "github.com/harness/gitness/types/enum" ) -func (s *Service) getPublicResource( +func (s *service) getPublicResource( ctx context.Context, resourceType enum.PublicResourceType, resourcePath string, @@ -44,7 +44,7 @@ func (s *Service) getPublicResource( return id, nil } -func (s *Service) getResourceRepo( +func (s *service) getResourceRepo( ctx context.Context, path string, ) (int64, error) { @@ -56,7 +56,7 @@ func (s *Service) getResourceRepo( return repo.ID, nil } -func (s *Service) getResourceSpace( +func (s *service) getResourceSpace( ctx context.Context, path string, ) (int64, error) { diff --git a/app/services/publicaccess/service.go b/app/services/publicaccess/service.go index c627ba8bf7..0f6a94a845 100644 --- a/app/services/publicaccess/service.go +++ b/app/services/publicaccess/service.go @@ -21,29 +21,35 @@ import ( "github.com/harness/gitness/app/store" gitness_store "github.com/harness/gitness/store" + "github.com/harness/gitness/types" "github.com/harness/gitness/types/enum" "github.com/rs/zerolog/log" ) -type Service struct { - publicAccessStore store.PublicAccessStore - repoStore store.RepoStore - spaceStore store.SpaceStore +var errPublicResourceCreationDisabled = errors.New("public resource creation is disabled") + +type service struct { + publicResourceCreationEnabled bool + publicAccessStore store.PublicAccessStore + repoStore store.RepoStore + spaceStore store.SpaceStore } func NewService( + config *types.Config, publicAccessStore store.PublicAccessStore, repoStore store.RepoStore, spaceStore store.SpaceStore, -) PublicAccess { - return &Service{ - publicAccessStore: publicAccessStore, - repoStore: repoStore, - spaceStore: spaceStore, +) Service { + return &service{ + publicResourceCreationEnabled: config.PublicResourceCreationEnabled, + publicAccessStore: publicAccessStore, + repoStore: repoStore, + spaceStore: spaceStore, } } -func (s *Service) Get( +func (s *service) Get( ctx context.Context, resourceType enum.PublicResourceType, resourcePath string, @@ -64,12 +70,16 @@ func (s *Service) Get( return true, nil } -func (s *Service) Set( +func (s *service) Set( ctx context.Context, resourceType enum.PublicResourceType, resourcePath string, enable bool, ) error { + if enable && !s.publicResourceCreationEnabled { + return errPublicResourceCreationDisabled + } + pubResID, err := s.getPublicResource(ctx, resourceType, resourcePath) if err != nil { return err diff --git a/app/services/publicaccess/wire.go b/app/services/publicaccess/wire.go index a470dca374..5dfbbaea4d 100644 --- a/app/services/publicaccess/wire.go +++ b/app/services/publicaccess/wire.go @@ -16,6 +16,7 @@ package publicaccess import ( "github.com/harness/gitness/app/store" + "github.com/harness/gitness/types" "github.com/google/wire" ) @@ -25,9 +26,10 @@ var WireSet = wire.NewSet( ) func ProvidePublicAccess( + config *types.Config, publicAccessStore store.PublicAccessStore, repoStore store.RepoStore, spaceStore store.SpaceStore, -) PublicAccess { - return NewService(publicAccessStore, repoStore, spaceStore) +) Service { + return NewService(config, publicAccessStore, repoStore, spaceStore) } diff --git a/app/store/database/wire.go b/app/store/database/wire.go index 1b35b244c7..4078195a25 100644 --- a/app/store/database/wire.go +++ b/app/store/database/wire.go @@ -53,7 +53,7 @@ var WireSet = wire.NewSet( ProvideWebhookStore, ProvideWebhookExecutionStore, ProvideSettingsStore, - ProvidePublicPublicAccessStore, + ProvidePublicAccessStore, ProvideCheckStore, ProvideConnectorStore, ProvideTemplateStore, @@ -249,7 +249,7 @@ func ProvideSettingsStore(db *sqlx.DB) store.SettingsStore { return NewSettingsStore(db) } -// ProvidePublicPublicAccessStore provides a pulic access store. -func ProvidePublicPublicAccessStore(db *sqlx.DB) store.PublicAccessStore { +// ProvidePublicAccessStore provides a pulic access store. +func ProvidePublicAccessStore(db *sqlx.DB) store.PublicAccessStore { return NewPublicAccessStore(db) } diff --git a/cmd/gitness/wire_gen.go b/cmd/gitness/wire_gen.go index a672d4c13c..f35725c3cb 100644 --- a/cmd/gitness/wire_gen.go +++ b/cmd/gitness/wire_gen.go @@ -115,10 +115,10 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro principalInfoCache := cache.ProvidePrincipalInfoCache(principalInfoView) membershipStore := database.ProvideMembershipStore(db, principalInfoCache, spacePathStore, spaceStore) permissionCache := authz.ProvidePermissionCache(spaceStore, membershipStore) - publicAccessStore := database.ProvidePublicPublicAccessStore(db) + publicAccessStore := database.ProvidePublicAccessStore(db) repoStore := database.ProvideRepoStore(db, spacePathCache, spacePathStore, spaceStore) - publicAccess := publicaccess.ProvidePublicAccess(publicAccessStore, repoStore, spaceStore) - authorizer := authz.ProvideAuthorizer(permissionCache, spaceStore, publicAccess) + publicaccessService := publicaccess.ProvidePublicAccess(config, publicAccessStore, repoStore, spaceStore) + authorizer := authz.ProvideAuthorizer(permissionCache, spaceStore, publicaccessService) principalUIDTransformation := store.ProvidePrincipalUIDTransformation() principalStore := database.ProvidePrincipalStore(db, principalUIDTransformation) tokenStore := database.ProvideTokenStore(db) @@ -200,7 +200,7 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro auditService := audit.ProvideAuditService() repoIdentifier := check.ProvideRepoIdentifierCheck() repoCheck := repo.ProvideRepoCheck() - repoController := repo.ProvideController(config, transactor, provider, authorizer, repoStore, spaceStore, pipelineStore, principalStore, ruleStore, settingsService, principalInfoCache, protectionManager, gitInterface, repository, codeownersService, reporter, indexer, resourceLimiter, lockerLocker, auditService, mutexManager, repoIdentifier, repoCheck, publicAccess) + repoController := repo.ProvideController(config, transactor, provider, authorizer, repoStore, spaceStore, pipelineStore, principalStore, ruleStore, settingsService, principalInfoCache, protectionManager, gitInterface, repository, codeownersService, reporter, indexer, resourceLimiter, lockerLocker, auditService, mutexManager, repoIdentifier, repoCheck, publicaccessService) reposettingsController := reposettings.ProvideController(authorizer, repoStore, settingsService, auditService) executionStore := database.ProvideExecutionStore(db) checkStore := database.ProvideCheckStore(db, principalInfoCache) @@ -216,7 +216,7 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro converterService := converter.ProvideService(fileService) templateStore := database.ProvideTemplateStore(db) pluginStore := database.ProvidePluginStore(db) - triggererTriggerer := triggerer.ProvideTriggerer(executionStore, checkStore, stageStore, transactor, pipelineStore, fileService, converterService, schedulerScheduler, repoStore, provider, templateStore, pluginStore, publicAccess) + triggererTriggerer := triggerer.ProvideTriggerer(executionStore, checkStore, stageStore, transactor, pipelineStore, fileService, converterService, schedulerScheduler, repoStore, provider, templateStore, pluginStore, publicaccessService) executionController := execution.ProvideController(transactor, authorizer, executionStore, checkStore, cancelerCanceler, commitService, triggererTriggerer, repoStore, stageStore, pipelineStore) logStore := logs.ProvideLogStore(db, config) logStream := livelog.ProvideLogStream() @@ -224,11 +224,11 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro spaceIdentifier := check.ProvideSpaceIdentifierCheck() secretStore := database.ProvideSecretStore(db) connectorStore := database.ProvideConnectorStore(db) - exporterRepository, err := exporter.ProvideSpaceExporter(provider, gitInterface, repoStore, jobScheduler, executor, encrypter, streamer, publicAccess) + exporterRepository, err := exporter.ProvideSpaceExporter(provider, gitInterface, repoStore, jobScheduler, executor, encrypter, streamer) if err != nil { return nil, err } - spaceController := space.ProvideController(config, transactor, provider, streamer, spaceIdentifier, authorizer, spacePathStore, pipelineStore, secretStore, connectorStore, templateStore, spaceStore, repoStore, principalStore, repoController, membershipStore, repository, exporterRepository, resourceLimiter, publicAccess, auditService) + spaceController := space.ProvideController(config, transactor, provider, streamer, spaceIdentifier, authorizer, spacePathStore, pipelineStore, secretStore, connectorStore, templateStore, spaceStore, repoStore, principalStore, repoController, membershipStore, repository, exporterRepository, resourceLimiter, publicaccessService, auditService) pipelineController := pipeline.ProvideController(repoStore, triggerStore, authorizer, pipelineStore) secretController := secret.ProvideController(encrypter, secretStore, authorizer, spaceStore) triggerController := trigger.ProvideController(authorizer, triggerStore, pipelineStore, repoStore) @@ -287,7 +287,7 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro } githookController := githook.ProvideController(authorizer, principalStore, repoStore, reporter2, reporter, gitInterface, pullReqStore, provider, protectionManager, clientFactory, resourceLimiter, settingsService, preReceiveExtender, updateExtender, postReceiveExtender) serviceaccountController := serviceaccount.NewController(principalUID, authorizer, principalStore, spaceStore, repoStore, tokenStore) - principalController := principal.ProvideController(principalStore) + principalController := principal.ProvideController(principalStore, authorizer) v := check2.ProvideCheckSanitizers() checkController := check2.ProvideController(transactor, authorizer, repoStore, checkStore, gitInterface, v) systemController := system.NewController(principalStore, config) @@ -308,7 +308,7 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro webHandler := router.ProvideWebHandler(config, openapiService) routerRouter := router.ProvideRouter(apiHandler, gitHandler, webHandler, provider) serverServer := server2.ProvideServer(config, routerRouter) - executionManager := manager.ProvideExecutionManager(config, executionStore, pipelineStore, provider, streamer, fileService, converterService, logStore, logStream, checkStore, repoStore, schedulerScheduler, secretStore, stageStore, stepStore, principalStore, publicAccess) + executionManager := manager.ProvideExecutionManager(config, executionStore, pipelineStore, provider, streamer, fileService, converterService, logStore, logStream, checkStore, repoStore, schedulerScheduler, secretStore, stageStore, stepStore, principalStore, publicaccessService) client := manager.ProvideExecutionClient(executionManager, provider, config) resolverManager := resolver.ProvideResolver(config, pluginStore, templateStore, executionStore, repoStore) runtimeRunner, err := runner.ProvideExecutionRunner(config, client, resolverManager) diff --git a/types/check/common.go b/types/check/common.go index c6813503bf..640581fc8f 100644 --- a/types/check/common.go +++ b/types/check/common.go @@ -18,6 +18,8 @@ import ( "fmt" "regexp" "strings" + + "github.com/harness/gitness/types" ) const ( @@ -39,10 +41,6 @@ var ( // illegalRootSpaceIdentifiers is the list of space identifier we are blocking for root spaces // as they might cause issues with routing. illegalRootSpaceIdentifiers = []string{"api", "git"} - - // illegalPrincipalUID is the UID we are blocking for principals - // as they might cause issues with system generated values. - illegalPrincipalUID = "anonymous" ) var ( @@ -80,7 +78,7 @@ var ( } ErrIllegalPrincipalUID = &ValidationError{ - fmt.Sprintf("Principal UID is not allowed to be %q.", illegalPrincipalUID), + fmt.Sprintf("Principal UID is not allowed to be %q.", types.AnonymousPrincipalUID), } ) @@ -155,7 +153,7 @@ func PrincipalUIDDefault(uid string) error { return err } - if uid == illegalPrincipalUID { + if uid == types.AnonymousPrincipalUID { return ErrIllegalPrincipalUID } diff --git a/types/principal.go b/types/principal.go index 52159e8914..ef6b2e3c8e 100644 --- a/types/principal.go +++ b/types/principal.go @@ -19,6 +19,9 @@ import ( "github.com/harness/gitness/types/enum" ) +// AnonymousPrincipalUID is an internal UID for anonymous principals. +const AnonymousPrincipalUID = "anonymous" + // Principal represents the identity of an acting entity (User, ServiceAccount, Service). type Principal struct { // TODO: int64 ID doesn't match DB From d404f3f9e93302441521be1bbb1cc3429b0bdbfc Mon Sep 17 00:00:00 2001 From: atefeh Date: Fri, 10 May 2024 00:48:35 -0700 Subject: [PATCH 26/31] fix a few bugs and addressed pr comments --- app/api/controller/principal/find.go | 15 +++++++++ app/api/controller/principal/interface.go | 5 +-- app/api/controller/principal/search.go | 18 +++++++++- app/api/controller/pullreq/pr_update.go | 2 +- app/api/controller/repo/controller.go | 18 ++++++++-- app/api/controller/repo/create.go | 23 +++---------- app/api/controller/repo/import.go | 6 ++-- app/api/controller/repo/soft_delete.go | 5 +-- app/api/controller/space/create.go | 21 +++++------- app/api/controller/space/import.go | 9 +++-- .../controller/space/import_repositories.go | 8 ++--- app/api/controller/space/purge.go | 9 +++-- app/api/handler/principal/search.go | 3 +- app/api/middleware/authn/authn.go | 6 ---- app/auth/authz/membership.go | 9 +++-- app/auth/authz/public_access.go | 33 ++++++++++--------- app/router/api.go | 5 ++- app/services/importer/provider.go | 3 +- app/services/importer/wire.go | 3 ++ ...50_create_table_public_resources.down.sql} | 16 ++++----- ...0050_create_table_public_resources.up.sql} | 0 ...50_create_table_public_resources.down.sql} | 16 ++++----- ...0050_create_table_public_resources.up.sql} | 0 app/store/database/public_access.go | 10 ++---- cmd/gitness/wire_gen.go | 2 +- types/repo.go | 15 --------- 26 files changed, 136 insertions(+), 124 deletions(-) rename app/store/database/migrate/postgres/{0051_create_table_public_resources.down.sql => 0050_create_table_public_resources.down.sql} (66%) rename app/store/database/migrate/postgres/{0051_create_table_public_resources.up.sql => 0050_create_table_public_resources.up.sql} (100%) rename app/store/database/migrate/sqlite/{0051_create_table_public_resources.down.sql => 0050_create_table_public_resources.down.sql} (66%) rename app/store/database/migrate/sqlite/{0051_create_table_public_resources.up.sql => 0050_create_table_public_resources.up.sql} (100%) diff --git a/app/api/controller/principal/find.go b/app/api/controller/principal/find.go index 8aae2cfe6f..8c9443efee 100644 --- a/app/api/controller/principal/find.go +++ b/app/api/controller/principal/find.go @@ -17,11 +17,26 @@ package principal import ( "context" + apiauth "github.com/harness/gitness/app/api/auth" "github.com/harness/gitness/app/auth" "github.com/harness/gitness/types" + "github.com/harness/gitness/types/enum" ) func (c controller) Find(ctx context.Context, session *auth.Session, principalID int64) (*types.PrincipalInfo, error) { + if err := apiauth.Check( + ctx, + c.authorizer, + session, + &types.Scope{}, + &types.Resource{ + Type: enum.ResourceTypeUser, + }, + enum.PermissionUserView, + ); err != nil { + return nil, err + } + principal, err := c.principalStore.Find(ctx, principalID) if err != nil { return nil, err diff --git a/app/api/controller/principal/interface.go b/app/api/controller/principal/interface.go index 3a9404f1cb..67aae796b0 100644 --- a/app/api/controller/principal/interface.go +++ b/app/api/controller/principal/interface.go @@ -17,6 +17,7 @@ package principal import ( "context" + "github.com/harness/gitness/app/auth" "github.com/harness/gitness/types" ) @@ -24,6 +25,6 @@ import ( // principal related information. type Controller interface { // List lists the principals based on the provided filter. - List(ctx context.Context, opts *types.PrincipalFilter) ([]*types.PrincipalInfo, error) - Find(ctx context.Context, principalID int64) (*types.PrincipalInfo, error) + List(ctx context.Context, session *auth.Session, opts *types.PrincipalFilter) ([]*types.PrincipalInfo, error) + Find(ctx context.Context, session *auth.Session, principalID int64) (*types.PrincipalInfo, error) } diff --git a/app/api/controller/principal/search.go b/app/api/controller/principal/search.go index 48ed8dd976..6c20a04caa 100644 --- a/app/api/controller/principal/search.go +++ b/app/api/controller/principal/search.go @@ -17,11 +17,27 @@ package principal import ( "context" + apiauth "github.com/harness/gitness/app/api/auth" + "github.com/harness/gitness/app/auth" "github.com/harness/gitness/types" + "github.com/harness/gitness/types/enum" ) -func (c controller) List(ctx context.Context, opts *types.PrincipalFilter) ( +func (c controller) List(ctx context.Context, session *auth.Session, opts *types.PrincipalFilter) ( []*types.PrincipalInfo, error) { + if err := apiauth.Check( + ctx, + c.authorizer, + session, + &types.Scope{}, + &types.Resource{ + Type: enum.ResourceTypeUser, + }, + enum.PermissionUserView, + ); err != nil { + return nil, err + } + principals, err := c.principalStore.List(ctx, opts) if err != nil { return nil, err diff --git a/app/api/controller/pullreq/pr_update.go b/app/api/controller/pullreq/pr_update.go index 3c29c2dad8..1f16fb2cdf 100644 --- a/app/api/controller/pullreq/pr_update.go +++ b/app/api/controller/pullreq/pr_update.go @@ -74,7 +74,7 @@ func (c *Controller) Update(ctx context.Context, } if err = apiauth.CheckRepo(ctx, c.authorizer, session, sourceRepo, - enum.PermissionRepoReview); err != nil { + enum.PermissionRepoView); err != nil { return nil, fmt.Errorf("failed to acquire access to source repo: %w", err) } } diff --git a/app/api/controller/repo/controller.go b/app/api/controller/repo/controller.go index 0fde863072..0aa90dcccf 100644 --- a/app/api/controller/repo/controller.go +++ b/app/api/controller/repo/controller.go @@ -16,6 +16,7 @@ package repo import ( "context" + "encoding/json" "fmt" "strconv" "strings" @@ -44,8 +45,21 @@ import ( ) type RepositoryOutput struct { - types.Repository `json:",inline"` - IsPublic bool `json:"is_public" yaml:"is_public"` + types.Repository + IsPublic bool `json:"is_public" yaml:"is_public"` +} + +// TODO [CODE-1363]: remove after identifier migration. +func (r RepositoryOutput) MarshalJSON() ([]byte, error) { + // alias allows us to embed the original object while avoiding an infinite loop of marshaling. + type alias RepositoryOutput + return json.Marshal(&struct { + alias + UID string `json:"uid"` + }{ + alias: (alias)(r), + UID: r.Identifier, + }) } type Controller struct { diff --git a/app/api/controller/repo/create.go b/app/api/controller/repo/create.go index 954e744e48..89c7fba74f 100644 --- a/app/api/controller/repo/create.go +++ b/app/api/controller/repo/create.go @@ -62,7 +62,7 @@ type CreateInput struct { // Create creates a new repository. // //nolint:gocognit -func (c *Controller) Create(ctx context.Context, session *auth.Session, in *CreateInput) (*Repository, error) { +func (c *Controller) Create(ctx context.Context, session *auth.Session, in *CreateInput) (*RepositoryOutput, error) { if err := c.sanitizeCreateInput(in); err != nil { return nil, fmt.Errorf("failed to sanitize input: %w", err) } @@ -119,7 +119,8 @@ func (c *Controller) Create(ctx context.Context, session *auth.Session, in *Crea return nil, err } - if err = c.SetRepoPublicAccess(ctx, repo, in.IsPublic); err != nil { + err = c.publicAccess.Set(ctx, enum.PublicResourceTypeRepo, repo.Path, in.IsPublic) + if err != nil { if dErr := c.PurgeNoAuth(ctx, session, repo); dErr != nil { log.Ctx(ctx).Warn().Err(dErr).Msg("failed to purge repo for cleanup") } @@ -129,7 +130,7 @@ func (c *Controller) Create(ctx context.Context, session *auth.Session, in *Crea // backfil GitURL repo.GitURL = c.urlProvider.GenerateGITCloneURL(repo.Path) - repoData := &Repository{ + repoData := &RepositoryOutput{ Repository: *repo, IsPublic: in.IsPublic, } @@ -188,10 +189,6 @@ func (c *Controller) sanitizeCreateInput(in *CreateInput) error { in.Identifier = in.UID } - if in.IsPublic && !c.publicResourceCreationEnabled { - return errPublicRepoCreationDisabled - } - if err := c.validateParentRef(in.ParentRef); err != nil { return err } @@ -280,18 +277,6 @@ func (c *Controller) createGitRepository(ctx context.Context, session *auth.Sess return resp, len(files) == 0, nil } -func (c *Controller) SetRepoPublicAccess( - ctx context.Context, - repo *types.Repository, - isPublic bool, -) error { - if isPublic && !c.publicResourceCreationEnabled { - return errPublicRepoCreationDisabled - } - - return c.publicAccess.Set(ctx, enum.PublicResourceTypeRepo, repo.Path, isPublic) -} - func createReadme(name, description string) []byte { content := bytes.Buffer{} content.WriteString("# " + name + "\n") diff --git a/app/api/controller/repo/import.go b/app/api/controller/repo/import.go index a4ec9fb6d6..46c563cc31 100644 --- a/app/api/controller/repo/import.go +++ b/app/api/controller/repo/import.go @@ -69,6 +69,7 @@ func (c *Controller) Import(ctx context.Context, session *auth.Session, in *Impo in.Identifier, in.Description, &session.Principal, + c.publicResourceCreationEnabled, ) // lock the space for update during repo creation to prevent racing conditions with space soft delete. @@ -82,14 +83,11 @@ func (c *Controller) Import(ctx context.Context, session *auth.Session, in *Impo return fmt.Errorf("failed to create repository in storage: %w", err) } - if err = c.SetRepoPublicAccess(ctx, repo, isPublic); err != nil { - return fmt.Errorf("failed to set repo public access: %w", err) - } - err = c.importer.Run(ctx, provider, repo, remoteRepository.CloneURL, + isPublic, in.Pipelines, ) if err != nil { diff --git a/app/api/controller/repo/soft_delete.go b/app/api/controller/repo/soft_delete.go index a16850ad10..51673a2716 100644 --- a/app/api/controller/repo/soft_delete.go +++ b/app/api/controller/repo/soft_delete.go @@ -88,8 +88,9 @@ func (c *Controller) SoftDeleteNoAuth( return c.PurgeNoAuth(ctx, session, repo) } - // unset repo public access regardless if it's public/private - if err := c.SetRepoPublicAccess(ctx, repo, false); err != nil { + // unset repo public access regardless if it's public/private for simplicity. + err := c.publicAccess.Set(ctx, enum.PublicResourceTypeRepo, repo.Path, false) + if err != nil { return fmt.Errorf("failed to disable repo public access: %w", err) } diff --git a/app/api/controller/space/create.go b/app/api/controller/space/create.go index 7e44f25680..ca25b1c407 100644 --- a/app/api/controller/space/create.go +++ b/app/api/controller/space/create.go @@ -29,6 +29,7 @@ import ( "github.com/harness/gitness/types" "github.com/harness/gitness/types/check" "github.com/harness/gitness/types/enum" + "github.com/rs/zerolog/log" ) var ( @@ -71,6 +72,14 @@ func (c *Controller) Create( return nil, err } + err = c.publicAccess.Set(ctx, enum.PublicResourceTypeSpace, space.Path, in.IsPublic) + if err != nil { + if dErr := c.PurgeNoAuth(ctx, session, space); dErr != nil { + log.Ctx(ctx).Warn().Err(dErr).Msg("failed to set a space public") + } + return nil, fmt.Errorf("failed to set space public access: %w", err) + } + return GetSpaceOutput(ctx, c.publicAccess, space) } @@ -146,10 +155,6 @@ func (c *Controller) createSpaceInnerInTX( } } - if err := c.setSpacePublicAccess(ctx, space, in.IsPublic); err != nil { - return nil, fmt.Errorf("failed to set a space public: %w", err) - } - return space, nil } @@ -187,14 +192,6 @@ func (c *Controller) getSpaceCheckAuthSpaceCreation( return parentSpace, nil } -func (c *Controller) setSpacePublicAccess( - ctx context.Context, - space *types.Space, - isPublic bool, -) error { - return c.publicAccess.Set(ctx, enum.PublicResourceTypeSpace, space.Path, isPublic) -} - func (c *Controller) sanitizeCreateInput(in *CreateInput) error { // TODO [CODE-1363]: remove after identifier migration. if in.Identifier == "" { diff --git a/app/api/controller/space/import.go b/app/api/controller/space/import.go index 2696dd9484..ce54fa5569 100644 --- a/app/api/controller/space/import.go +++ b/app/api/controller/space/import.go @@ -67,6 +67,7 @@ func (c *Controller) Import(ctx context.Context, session *auth.Session, in *Impo } repoIDs := make([]int64, len(remoteRepositories)) + repoIsPublicVals := make([]bool, len(remoteRepositories)) cloneURLs := make([]string, len(remoteRepositories)) repos := make([]*types.Repository, 0, len(remoteRepositories)) @@ -88,6 +89,7 @@ func (c *Controller) Import(ctx context.Context, session *auth.Session, in *Impo remoteRepository.Identifier, "", &session.Principal, + c.publicResourceCreationEnabled, ) err = c.repoStore.Create(ctx, repo) @@ -97,11 +99,7 @@ func (c *Controller) Import(ctx context.Context, session *auth.Session, in *Impo repos = append(repos, repo) repoIDs[i] = repo.ID cloneURLs[i] = remoteRepository.CloneURL - - if err := c.repoCtrl.SetRepoPublicAccess(ctx, repo, isPublic); err != nil { - return fmt.Errorf("failed to set repo public access: %w", err) - } - + repoIsPublicVals[i] = isPublic } jobGroupID := fmt.Sprintf("space-import-%d", space.ID) @@ -109,6 +107,7 @@ func (c *Controller) Import(ctx context.Context, session *auth.Session, in *Impo jobGroupID, provider, repoIDs, + repoIsPublicVals, cloneURLs, in.Pipelines, ) diff --git a/app/api/controller/space/import_repositories.go b/app/api/controller/space/import_repositories.go index 0924fcb7b6..462bb014eb 100644 --- a/app/api/controller/space/import_repositories.go +++ b/app/api/controller/space/import_repositories.go @@ -93,6 +93,7 @@ func (c *Controller) ImportRepositories( } repoIDs := make([]int64, 0, len(remoteRepositories)) + repoIsPublicVals := make([]bool, 0, len(remoteRepositories)) cloneURLs := make([]string, 0, len(remoteRepositories)) repos := make([]*types.Repository, 0, len(remoteRepositories)) duplicateRepos := make([]*types.Repository, 0, len(remoteRepositories)) @@ -115,6 +116,7 @@ func (c *Controller) ImportRepositories( remoteRepository.Identifier, "", &session.Principal, + c.publicResourceCreationEnabled, ) err = c.repoStore.Create(ctx, repo) @@ -126,13 +128,10 @@ func (c *Controller) ImportRepositories( return fmt.Errorf("failed to create repository in storage: %w", err) } - if err := c.repoCtrl.SetRepoPublicAccess(ctx, repo, isPublic); err != nil { - return fmt.Errorf("failed to set repo public access: %w", err) - } - repos = append(repos, repo) repoIDs = append(repoIDs, repo.ID) cloneURLs = append(cloneURLs, remoteRepository.CloneURL) + repoIsPublicVals = append(repoIsPublicVals, isPublic) } if len(repoIDs) == 0 { return nil @@ -143,6 +142,7 @@ func (c *Controller) ImportRepositories( jobGroupID, provider, repoIDs, + repoIsPublicVals, cloneURLs, in.Pipelines, ) diff --git a/app/api/controller/space/purge.go b/app/api/controller/space/purge.go index 39f8cdd2b2..8e3d609378 100644 --- a/app/api/controller/space/purge.go +++ b/app/api/controller/space/purge.go @@ -48,7 +48,7 @@ func (c *Controller) Purge( return fmt.Errorf("failed to authorize on space purge: %w", err) } - return c.PurgeNoAuth(ctx, session, space.ID, deletedAt) + return c.PurgeNoAuth(ctx, session, space) } // PurgeNoAuth purges the space - no authorization is verified. @@ -56,8 +56,7 @@ func (c *Controller) Purge( func (c *Controller) PurgeNoAuth( ctx context.Context, session *auth.Session, - spaceID int64, - deletedAt int64, + space *types.Space, ) error { // the max time we give a purge space to succeed const timeout = 15 * time.Minute @@ -71,11 +70,11 @@ func (c *Controller) PurgeNoAuth( var toBeDeletedRepos []*types.Repository var err error err = c.tx.WithTx(ctx, func(ctx context.Context) error { - toBeDeletedRepos, err = c.purgeSpaceInnerInTx(ctx, spaceID, deletedAt) + toBeDeletedRepos, err = c.purgeSpaceInnerInTx(ctx, space.ID, *space.Deleted) return err }) if err != nil { - return fmt.Errorf("failed to purge space %d in a tnx: %w", spaceID, err) + return fmt.Errorf("failed to purge space %d in a tnx: %w", space.ID, err) } // permanently purge all repositories in the space and its subspaces after successful space purge tnx. diff --git a/app/api/handler/principal/search.go b/app/api/handler/principal/search.go index d1a5df6925..c3b5fe9f17 100644 --- a/app/api/handler/principal/search.go +++ b/app/api/handler/principal/search.go @@ -26,8 +26,9 @@ func HandleList(principalCtrl principal.Controller) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { ctx := r.Context() + session, _ := request.AuthSessionFrom(ctx) principalFilter := request.ParsePrincipalFilter(r) - principalInfos, err := principalCtrl.List(ctx, principalFilter) + principalInfos, err := principalCtrl.List(ctx, session, principalFilter) if err != nil { render.TranslatedUserError(ctx, w, err) return diff --git a/app/api/middleware/authn/authn.go b/app/api/middleware/authn/authn.go index e566475965..4d81faabfa 100644 --- a/app/api/middleware/authn/authn.go +++ b/app/api/middleware/authn/authn.go @@ -31,12 +31,6 @@ func Attempt(authenticator authn.Authenticator) func(http.Handler) http.Handler return performAuthentication(authenticator, false) } -// Required returns an http.HandlerFunc middleware that authenticates -// the http.Request and fails the request if no auth data was available. -func Required(authenticator authn.Authenticator) func(http.Handler) http.Handler { - return performAuthentication(authenticator, true) -} - // performAuthentication returns an http.HandlerFunc middleware that authenticates // the http.Request if authentication payload is available. // Depending on whether it is required or not, the request will be failed. diff --git a/app/auth/authz/membership.go b/app/auth/authz/membership.go index 649ce1b97e..44a18f9651 100644 --- a/app/auth/authz/membership.go +++ b/app/auth/authz/membership.go @@ -114,9 +114,14 @@ func (a *MembershipAuthorizer) Check( spacePath = scope.SpacePath case enum.ResourceTypeUser: - // a user is allowed to view / edit themselves + // a user is allowed to edit themselves if resource.Identifier == session.Principal.UID && - (permission == enum.PermissionUserView || permission == enum.PermissionUserEdit) { + permission == enum.PermissionUserEdit { + return true, nil + } + + // user can see all other users in the system. + if permission == enum.PermissionUserView { return true, nil } diff --git a/app/auth/authz/public_access.go b/app/auth/authz/public_access.go index 2ff226439f..75795a5f9d 100644 --- a/app/auth/authz/public_access.go +++ b/app/auth/authz/public_access.go @@ -28,25 +28,28 @@ func (a *MembershipAuthorizer) CheckPublicAccess( resource *types.Resource, permission enum.Permission, ) (bool, error) { - // public access only permits view. - if permission != enum.PermissionRepoView && - permission != enum.PermissionSpaceView { - return false, nil - } - - pubResType, pubResPath := mapResource(scope, resource) + var pubResType enum.PublicResourceType - return a.publicAccess.Get(ctx, pubResType, pubResPath) -} + //nolint:exhaustive + switch resource.Type { + case enum.ResourceTypeSpace: + pubResType = enum.PublicResourceTypeSpace -func mapResource(scope *types.Scope, resource *types.Resource, -) (enum.PublicResourceType, string) { - pubResType := enum.PublicResourceTypeSpace + case enum.ResourceTypeRepo: + if resource.Identifier != "" { + pubResType = enum.PublicResourceTypeRepo + } else { // for spaceScope checks + pubResType = enum.PublicResourceTypeSpace + } - if resource.Type == enum.ResourceTypeRepo && - resource.Identifier != "" { + case enum.ResourceTypePipeline: pubResType = enum.PublicResourceTypeRepo + + default: + return false, nil } - return pubResType, paths.Concatenate(scope.SpacePath, resource.Identifier) + pubResPath := paths.Concatenate(scope.SpacePath, resource.Identifier) + + return a.publicAccess.Get(ctx, pubResType, pubResPath) } diff --git a/app/router/api.go b/app/router/api.go index 0d139f4e16..5e098ed7b5 100644 --- a/app/router/api.go +++ b/app/router/api.go @@ -205,7 +205,7 @@ func setupRoutesV1(r chi.Router, setupSecrets(r, secretCtrl) setupUser(r, userCtrl) setupServiceAccounts(r, saCtrl) - setupPrincipals(r, authenticator, principalCtrl) + setupPrincipals(r, principalCtrl) setupInternal(r, githookCtrl, git) setupAdmin(r, userCtrl) setupAccount(r, userCtrl, sysCtrl, config) @@ -668,9 +668,8 @@ func setupResources(r chi.Router) { }) } -func setupPrincipals(r chi.Router, authenticator authn.Authenticator, principalCtrl principal.Controller) { +func setupPrincipals(r chi.Router, principalCtrl principal.Controller) { r.Route("/principals", func(r chi.Router) { - r.Use(middlewareauthn.Required(authenticator)) r.Get("/", handlerprincipal.HandleList(principalCtrl)) r.Get(fmt.Sprintf("/{%s}", request.PathParamPrincipalID), handlerprincipal.HandleFind(principalCtrl)) }) diff --git a/app/services/importer/provider.go b/app/services/importer/provider.go index 661d51f313..9277fd2d4d 100644 --- a/app/services/importer/provider.go +++ b/app/services/importer/provider.go @@ -81,6 +81,7 @@ func (r *RepositoryInfo) ToRepo( identifier string, description string, principal *types.Principal, + publicResourceCreationEnabled bool, ) (*types.Repository, bool) { now := time.Now().UnixMilli() gitTempUID := fmt.Sprintf("importing-%s-%d", hash(fmt.Sprintf("%d:%s", spaceID, identifier)), now) @@ -96,7 +97,7 @@ func (r *RepositoryInfo) ToRepo( ForkID: 0, DefaultBranch: r.DefaultBranch, Importing: true, - }, r.IsPublic + }, (r.IsPublic && publicResourceCreationEnabled) } func hash(s string) string { diff --git a/app/services/importer/wire.go b/app/services/importer/wire.go index c5dac7f77f..012c058368 100644 --- a/app/services/importer/wire.go +++ b/app/services/importer/wire.go @@ -16,6 +16,7 @@ package importer import ( "github.com/harness/gitness/app/services/keywordsearch" + "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/sse" "github.com/harness/gitness/app/store" "github.com/harness/gitness/app/url" @@ -45,6 +46,7 @@ func ProvideRepoImporter( executor *job.Executor, sseStreamer sse.Streamer, indexer keywordsearch.Indexer, + publicAccess publicaccess.Service, ) (*Repository, error) { importer := &Repository{ defaultBranch: config.Git.DefaultBranch, @@ -58,6 +60,7 @@ func ProvideRepoImporter( scheduler: scheduler, sseStreamer: sseStreamer, indexer: indexer, + publicAccess: publicAccess, } err := executor.Register(jobType, importer) diff --git a/app/store/database/migrate/postgres/0051_create_table_public_resources.down.sql b/app/store/database/migrate/postgres/0050_create_table_public_resources.down.sql similarity index 66% rename from app/store/database/migrate/postgres/0051_create_table_public_resources.down.sql rename to app/store/database/migrate/postgres/0050_create_table_public_resources.down.sql index e2faa6bdb2..8abdb9bf8b 100644 --- a/app/store/database/migrate/postgres/0051_create_table_public_resources.down.sql +++ b/app/store/database/migrate/postgres/0050_create_table_public_resources.down.sql @@ -1,26 +1,26 @@ -- copy public repositories ALTER TABLE repositories ADD COLUMN repo_is_public BOOLEAN; +-- update repo public access UPDATE repositories +SET repo_is_public = TRUE WHERE repo_id IN ( SELECT public_access_repo_id FROM public_access - WHERE public_access_repo_id IS NOT NULL; -) SET -repo_is_public = TRUE; - + WHERE public_access_repo_id IS NOT NULL +); -- copy public spaces ALTER TABLE spaces ADD COLUMN space_is_public BOOLEAN; --- update public access +-- update space public access UPDATE spaces +SET space_is_public = TRUE WHERE space_id IN ( SELECT public_access_space_id FROM public_access - WHERE public_access_space_id IS NOT NULL; -) SET -space_is_public = TRUE; + WHERE public_access_space_id IS NOT NULL +); -- clear public access DROP INDEX public_access_space_id_key; diff --git a/app/store/database/migrate/postgres/0051_create_table_public_resources.up.sql b/app/store/database/migrate/postgres/0050_create_table_public_resources.up.sql similarity index 100% rename from app/store/database/migrate/postgres/0051_create_table_public_resources.up.sql rename to app/store/database/migrate/postgres/0050_create_table_public_resources.up.sql diff --git a/app/store/database/migrate/sqlite/0051_create_table_public_resources.down.sql b/app/store/database/migrate/sqlite/0050_create_table_public_resources.down.sql similarity index 66% rename from app/store/database/migrate/sqlite/0051_create_table_public_resources.down.sql rename to app/store/database/migrate/sqlite/0050_create_table_public_resources.down.sql index c7b02dfe03..ed6ffdca98 100644 --- a/app/store/database/migrate/sqlite/0051_create_table_public_resources.down.sql +++ b/app/store/database/migrate/sqlite/0050_create_table_public_resources.down.sql @@ -1,26 +1,26 @@ -- copy public repositories ALTER TABLE repositories ADD COLUMN repo_is_public BOOLEAN; +-- update repo public access UPDATE repositories +SET repo_is_public = TRUE WHERE repo_id IN ( SELECT public_access_repo_id FROM public_access - WHERE public_access_repo_id IS NOT NULL; -) SET -repo_is_public = TRUE; - + WHERE public_access_repo_id IS NOT NULL +); -- copy public spaces ALTER TABLE spaces ADD COLUMN space_is_public BOOLEAN; --- update public access +-- update space public access UPDATE spaces +SET space_is_public = TRUE WHERE space_id IN ( SELECT public_access_space_id FROM public_access - WHERE public_access_space_id IS NOT NULL; -) SET -space_is_public = TRUE; + WHERE public_access_space_id IS NOT NULL +); -- clear public_access DROP INDEX public_access_space_id_key; diff --git a/app/store/database/migrate/sqlite/0051_create_table_public_resources.up.sql b/app/store/database/migrate/sqlite/0050_create_table_public_resources.up.sql similarity index 100% rename from app/store/database/migrate/sqlite/0051_create_table_public_resources.up.sql rename to app/store/database/migrate/sqlite/0050_create_table_public_resources.up.sql diff --git a/app/store/database/public_access.go b/app/store/database/public_access.go index b60772b522..400c89819c 100644 --- a/app/store/database/public_access.go +++ b/app/store/database/public_access.go @@ -95,17 +95,13 @@ func (p *PublicAccessStore) Create( ) error { stmt := database.Builder. Insert(""). - Into("public_access"). - Columns( - "public_access_space_id", - "public_access_repo_id", - ) + Into("public_access") switch typ { case enum.PublicResourceTypeRepo: - stmt = stmt.Values(null.Int{}, null.IntFrom(id)) + stmt = stmt.Columns("public_access_repo_id").Values(null.IntFrom(id)) case enum.PublicResourceTypeSpace: - stmt = stmt.Values(null.IntFrom(id), null.Int{}) + stmt = stmt.Columns("public_access_space_id").Values(null.IntFrom(id)) default: return fmt.Errorf("public resource type %q is not supported", typ) } diff --git a/cmd/gitness/wire_gen.go b/cmd/gitness/wire_gen.go index f35725c3cb..149fac5673 100644 --- a/cmd/gitness/wire_gen.go +++ b/cmd/gitness/wire_gen.go @@ -176,7 +176,7 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro streamer := sse.ProvideEventsStreaming(pubSub) localIndexSearcher := keywordsearch.ProvideLocalIndexSearcher() indexer := keywordsearch.ProvideIndexer(localIndexSearcher) - repository, err := importer.ProvideRepoImporter(config, provider, gitInterface, transactor, repoStore, pipelineStore, triggerStore, encrypter, jobScheduler, executor, streamer, indexer) + repository, err := importer.ProvideRepoImporter(config, provider, gitInterface, transactor, repoStore, pipelineStore, triggerStore, encrypter, jobScheduler, executor, streamer, indexer, publicaccessService) if err != nil { return nil, err } diff --git a/types/repo.go b/types/repo.go index d61fe1dde0..497f14e24c 100644 --- a/types/repo.go +++ b/types/repo.go @@ -15,8 +15,6 @@ package types import ( - "encoding/json" - "github.com/harness/gitness/types/enum" ) @@ -69,19 +67,6 @@ func (r Repository) Clone() Repository { return r } -// TODO [CODE-1363]: remove after identifier migration. -func (r Repository) MarshalJSON() ([]byte, error) { - // alias allows us to embed the original object while avoiding an infinite loop of marshaling. - type alias Repository - return json.Marshal(&struct { - alias - UID string `json:"uid"` - }{ - alias: (alias)(r), - UID: r.Identifier, - }) -} - type RepositorySizeInfo struct { ID int64 `json:"id"` GitUID string `json:"git_uid"` From 30db3fd32694feb34a0588cc1635d01bf1377271 Mon Sep 17 00:00:00 2001 From: atefeh Date: Fri, 10 May 2024 15:48:26 -0700 Subject: [PATCH 27/31] return anonymouse princial for user find publci access --- app/api/controller/user/find.go | 5 +++++ app/router/api.go | 3 +-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/api/controller/user/find.go b/app/api/controller/user/find.go index d2097a74fb..ff7dafb756 100644 --- a/app/api/controller/user/find.go +++ b/app/api/controller/user/find.go @@ -28,6 +28,11 @@ import ( */ func (c *Controller) Find(ctx context.Context, session *auth.Session, userUID string) (*types.User, error) { + if session.Principal.UID == auth.AnonymousPrincipal.UID { + return &types.User{ + UID: auth.AnonymousPrincipal.UID, + }, nil + } user, err := c.FindNoAuth(ctx, userUID) if err != nil { return nil, err diff --git a/app/router/api.go b/app/router/api.go index 5e098ed7b5..7237cfc906 100644 --- a/app/router/api.go +++ b/app/router/api.go @@ -146,7 +146,7 @@ func NewAPIHandler( r.Use(audit.Middleware()) r.Route("/v1", func(r chi.Router) { - setupRoutesV1(r, appCtx, config, authenticator, repoCtrl, repoSettingsCtrl, executionCtrl, triggerCtrl, logCtrl, pipelineCtrl, + setupRoutesV1(r, appCtx, config, repoCtrl, repoSettingsCtrl, executionCtrl, triggerCtrl, logCtrl, pipelineCtrl, connectorCtrl, templateCtrl, pluginCtrl, secretCtrl, spaceCtrl, pullreqCtrl, webhookCtrl, githookCtrl, git, saCtrl, userCtrl, principalCtrl, checkCtrl, sysCtrl, uploadCtrl, searchCtrl) @@ -173,7 +173,6 @@ func corsHandler(config *types.Config) func(http.Handler) http.Handler { func setupRoutesV1(r chi.Router, appCtx context.Context, config *types.Config, - authenticator authn.Authenticator, repoCtrl *repo.Controller, repoSettingsCtrl *reposettings.Controller, executionCtrl *execution.Controller, From abdd0add29c2275a85b409b6af61f420ce11a235 Mon Sep 17 00:00:00 2001 From: atefeh Date: Fri, 10 May 2024 15:53:55 -0700 Subject: [PATCH 28/31] WIP import public access set on job handler --- app/api/controller/repo/import.go | 5 +++ app/services/importer/repository.go | 48 +++++++++++++++++++---------- 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/app/api/controller/repo/import.go b/app/api/controller/repo/import.go index 46c563cc31..252176d474 100644 --- a/app/api/controller/repo/import.go +++ b/app/api/controller/repo/import.go @@ -52,6 +52,11 @@ func (c *Controller) Import(ctx context.Context, session *auth.Session, in *Impo return nil, err } + // cleanUpPublicAccess := func() { + // for ...c + // cleanup + // } + var repo *types.Repository var isPublic bool err = c.tx.WithTx(ctx, func(ctx context.Context) error { diff --git a/app/services/importer/repository.go b/app/services/importer/repository.go index 55d23a82d5..7407a2f1cb 100644 --- a/app/services/importer/repository.go +++ b/app/services/importer/repository.go @@ -27,6 +27,7 @@ import ( "github.com/harness/gitness/app/bootstrap" "github.com/harness/gitness/app/githook" "github.com/harness/gitness/app/services/keywordsearch" + "github.com/harness/gitness/app/services/publicaccess" "github.com/harness/gitness/app/sse" "github.com/harness/gitness/app/store" gitnessurl "github.com/harness/gitness/app/url" @@ -53,7 +54,6 @@ var ( type Repository struct { defaultBranch string - isPublic bool urlProvider gitnessurl.Provider git git.Interface tx dbtx.Transactor @@ -64,6 +64,7 @@ type Repository struct { scheduler *job.Scheduler sseStreamer sse.Streamer indexer keywordsearch.Indexer + publicAccess publicaccess.Service } var _ job.Handler = (*Repository)(nil) @@ -81,11 +82,12 @@ const ( ) type Input struct { - RepoID int64 `json:"repo_id"` - GitUser string `json:"git_user"` - GitPass string `json:"git_pass"` - CloneURL string `json:"clone_url"` - Pipelines PipelineOption `json:"pipelines"` + RepoID int64 `json:"repo_id"` + RepoIsPublic bool `json:"is_public"` + GitUser string `json:"git_user"` + GitPass string `json:"git_pass"` + CloneURL string `json:"clone_url"` + Pipelines PipelineOption `json:"pipelines"` } const jobType = "repository_import" @@ -100,14 +102,16 @@ func (r *Repository) Run( provider Provider, repo *types.Repository, cloneURL string, + isPublic bool, pipelines PipelineOption, ) error { jobDef, err := r.getJobDef(JobIDFromRepoID(repo.ID), Input{ - RepoID: repo.ID, - GitUser: provider.Username, - GitPass: provider.Password, - CloneURL: cloneURL, - Pipelines: pipelines, + RepoID: repo.ID, + RepoIsPublic: isPublic, + GitUser: provider.Username, + GitPass: provider.Password, + CloneURL: cloneURL, + Pipelines: pipelines, }) if err != nil { return err @@ -121,6 +125,7 @@ func (r *Repository) RunMany(ctx context.Context, groupID string, provider Provider, repoIDs []int64, + repoIsPublicVals []bool, cloneURLs []string, pipelines PipelineOption, ) error { @@ -135,13 +140,15 @@ func (r *Repository) RunMany(ctx context.Context, for k := 0; k < n; k++ { repoID := repoIDs[k] cloneURL := cloneURLs[k] + isPublic := repoIsPublicVals[k] jobDef, err := r.getJobDef(JobIDFromRepoID(repoID), Input{ - RepoID: repoID, - GitUser: provider.Username, - GitPass: provider.Password, - CloneURL: cloneURL, - Pipelines: pipelines, + RepoID: repoID, + RepoIsPublic: isPublic, + GitUser: provider.Username, + GitPass: provider.Password, + CloneURL: cloneURL, + Pipelines: pipelines, }) if err != nil { return err @@ -259,6 +266,15 @@ func (r *Repository) Handle(ctx context.Context, data string, _ job.ProgressRepo return fmt.Errorf("failed to update repository prior to the import: %w", err) } + log.Info().Msg("setting repository public access") + // setup public access + // Note: if a repository with the same reference had its public access not cleaned up + // it might retain its public status until this job sets the actual is-public value for the importing repo. + err = r.publicAccess.Set(ctx, enum.PublicResourceTypeRepo, repo.Path, input.RepoIsPublic) + if err != nil { + return fmt.Errorf("failed to set repo public access: %w", err) + } + log.Info().Msg("sync repository") defaultBranch, err := r.syncGitRepository(ctx, &systemPrincipal, repo, cloneURLWithAuth) From 30bc114210834f9deaac193e1f3381e58de27d30 Mon Sep 17 00:00:00 2001 From: atefeh Date: Fri, 10 May 2024 18:02:56 -0700 Subject: [PATCH 29/31] revereted enforcing review permission--will be added in a following pr --- app/api/controller/pullreq/comment_create.go | 2 +- app/api/controller/pullreq/comment_delete.go | 2 +- app/api/controller/pullreq/comment_status.go | 2 +- app/api/controller/pullreq/comment_update.go | 2 +- app/api/controller/pullreq/file_view_add.go | 2 +- app/api/controller/pullreq/file_view_delete.go | 2 +- app/api/controller/pullreq/pr_state.go | 2 +- app/api/controller/pullreq/review_submit.go | 2 +- app/api/controller/pullreq/reviewer_add.go | 4 ++-- app/api/controller/pullreq/reviewer_delete.go | 2 +- app/api/controller/upload/upload.go | 2 +- 11 files changed, 12 insertions(+), 12 deletions(-) diff --git a/app/api/controller/pullreq/comment_create.go b/app/api/controller/pullreq/comment_create.go index 0822e65e00..20e1542003 100644 --- a/app/api/controller/pullreq/comment_create.go +++ b/app/api/controller/pullreq/comment_create.go @@ -91,7 +91,7 @@ func (c *Controller) CommentCreate( prNum int64, in *CommentCreateInput, ) (*types.PullReqActivity, error) { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoReview) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView) if err != nil { return nil, fmt.Errorf("failed to acquire access to repo: %w", err) } diff --git a/app/api/controller/pullreq/comment_delete.go b/app/api/controller/pullreq/comment_delete.go index 169a5f0bf4..70da017ae4 100644 --- a/app/api/controller/pullreq/comment_delete.go +++ b/app/api/controller/pullreq/comment_delete.go @@ -35,7 +35,7 @@ func (c *Controller) CommentDelete( prNum int64, commentID int64, ) error { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoReview) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView) if err != nil { return fmt.Errorf("failed to acquire access to repo: %w", err) } diff --git a/app/api/controller/pullreq/comment_status.go b/app/api/controller/pullreq/comment_status.go index 5742966041..a62311cee2 100644 --- a/app/api/controller/pullreq/comment_status.go +++ b/app/api/controller/pullreq/comment_status.go @@ -59,7 +59,7 @@ func (c *Controller) CommentStatus( commentID int64, in *CommentStatusInput, ) (*types.PullReqActivity, error) { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoReview) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView) if err != nil { return nil, fmt.Errorf("failed to acquire access to repo: %w", err) } diff --git a/app/api/controller/pullreq/comment_update.go b/app/api/controller/pullreq/comment_update.go index 45a61d16b4..962577e2d7 100644 --- a/app/api/controller/pullreq/comment_update.go +++ b/app/api/controller/pullreq/comment_update.go @@ -48,7 +48,7 @@ func (c *Controller) CommentUpdate( commentID int64, in *CommentUpdateInput, ) (*types.PullReqActivity, error) { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoReview) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView) if err != nil { return nil, fmt.Errorf("failed to acquire access to repo: %w", err) } diff --git a/app/api/controller/pullreq/file_view_add.go b/app/api/controller/pullreq/file_view_add.go index 424637f209..552e739a78 100644 --- a/app/api/controller/pullreq/file_view_add.go +++ b/app/api/controller/pullreq/file_view_add.go @@ -62,7 +62,7 @@ func (c *Controller) FileViewAdd( return nil, err } - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoReview) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView) if err != nil { return nil, fmt.Errorf("failed to acquire access to repo: %w", err) } diff --git a/app/api/controller/pullreq/file_view_delete.go b/app/api/controller/pullreq/file_view_delete.go index f9db9adbe0..b1d5b9e520 100644 --- a/app/api/controller/pullreq/file_view_delete.go +++ b/app/api/controller/pullreq/file_view_delete.go @@ -31,7 +31,7 @@ func (c *Controller) FileViewDelete( prNum int64, filePath string, ) error { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoReview) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView) if err != nil { return fmt.Errorf("failed to acquire access to repo: %w", err) } diff --git a/app/api/controller/pullreq/pr_state.go b/app/api/controller/pullreq/pr_state.go index a302379a36..46b4ae1a78 100644 --- a/app/api/controller/pullreq/pr_state.go +++ b/app/api/controller/pullreq/pr_state.go @@ -79,7 +79,7 @@ func (c *Controller) State(ctx context.Context, } if err = apiauth.CheckRepo(ctx, c.authorizer, session, sourceRepo, - enum.PermissionRepoReview); err != nil { + enum.PermissionRepoView); err != nil { return nil, fmt.Errorf("failed to acquire access to source repo: %w", err) } } diff --git a/app/api/controller/pullreq/review_submit.go b/app/api/controller/pullreq/review_submit.go index 879fa5dd1e..7742c39a19 100644 --- a/app/api/controller/pullreq/review_submit.go +++ b/app/api/controller/pullreq/review_submit.go @@ -66,7 +66,7 @@ func (c *Controller) ReviewSubmit( return nil, err } - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoReview) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView) if err != nil { return nil, fmt.Errorf("failed to acquire access to repo: %w", err) } diff --git a/app/api/controller/pullreq/reviewer_add.go b/app/api/controller/pullreq/reviewer_add.go index bf8830880f..bcd93c74d2 100644 --- a/app/api/controller/pullreq/reviewer_add.go +++ b/app/api/controller/pullreq/reviewer_add.go @@ -43,7 +43,7 @@ func (c *Controller) ReviewerAdd( prNum int64, in *ReviewerAddInput, ) (*types.PullReqReviewer, error) { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoReview) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView) if err != nil { return nil, fmt.Errorf("failed to acquire access to repo: %w", err) } @@ -87,7 +87,7 @@ func (c *Controller) ReviewerAdd( if err = apiauth.CheckRepo(ctx, c.authorizer, &auth.Session{ Principal: *reviewerPrincipal, Metadata: nil, - }, repo, enum.PermissionRepoReview); err != nil { + }, repo, enum.PermissionRepoView); err != nil { log.Ctx(ctx).Info().Msgf("Reviewer principal: %s access error: %s", reviewerInfo.UID, err) return nil, usererror.BadRequest("The reviewer doesn't have enough permissions for the repository.") } diff --git a/app/api/controller/pullreq/reviewer_delete.go b/app/api/controller/pullreq/reviewer_delete.go index 4ae9c95e6e..105a8eb1af 100644 --- a/app/api/controller/pullreq/reviewer_delete.go +++ b/app/api/controller/pullreq/reviewer_delete.go @@ -25,7 +25,7 @@ import ( // ReviewerDelete deletes reviewer from the reviewerlist for the given PR. func (c *Controller) ReviewerDelete(ctx context.Context, session *auth.Session, repoRef string, prNum, reviewerID int64) error { - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoReview) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView) if err != nil { return fmt.Errorf("failed to acquire access to repo: %w", err) } diff --git a/app/api/controller/upload/upload.go b/app/api/controller/upload/upload.go index f4660d0602..2fa1d2122a 100644 --- a/app/api/controller/upload/upload.go +++ b/app/api/controller/upload/upload.go @@ -42,7 +42,7 @@ func (c *Controller) Upload(ctx context.Context, file io.Reader, ) (*Result, error) { // Permission check to see if the user in request has access to the repo. - repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoReview) + repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView) if err != nil { return nil, fmt.Errorf("failed to acquire access to repo: %w", err) } From 0cabe0516fe10a2c57cdfb6f5eff835202e2c16d Mon Sep 17 00:00:00 2001 From: atefeh Date: Fri, 10 May 2024 23:35:49 -0700 Subject: [PATCH 30/31] set repo public access before create repo on import --- app/api/controller/repo/import.go | 47 ++++++++++++++++++------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/app/api/controller/repo/import.go b/app/api/controller/repo/import.go index 252176d474..f5a6541409 100644 --- a/app/api/controller/repo/import.go +++ b/app/api/controller/repo/import.go @@ -23,7 +23,7 @@ import ( "github.com/harness/gitness/app/paths" "github.com/harness/gitness/app/services/importer" "github.com/harness/gitness/audit" - "github.com/harness/gitness/types" + "github.com/harness/gitness/types/enum" "github.com/rs/zerolog/log" ) @@ -52,30 +52,36 @@ func (c *Controller) Import(ctx context.Context, session *auth.Session, in *Impo return nil, err } - // cleanUpPublicAccess := func() { - // for ...c - // cleanup - // } + remoteRepository, provider, err := importer.LoadRepositoryFromProvider(ctx, in.Provider, in.ProviderRepo) + if err != nil { + return nil, err + } - var repo *types.Repository - var isPublic bool - err = c.tx.WithTx(ctx, func(ctx context.Context) error { - if err := c.resourceLimiter.RepoCount(ctx, parentSpace.ID, 1); err != nil { - return fmt.Errorf("resource limit exceeded: %w", limiter.ErrMaxNumReposReached) - } + repo, isPublic := remoteRepository.ToRepo( + parentSpace.ID, + in.Identifier, + in.Description, + &session.Principal, + c.publicResourceCreationEnabled, + ) - remoteRepository, provider, err := importer.LoadRepositoryFromProvider(ctx, in.Provider, in.ProviderRepo) + cleanUpPublicAccess := func() { + err := c.publicAccess.Set(ctx, enum.PublicResourceTypeRepo, repo.Path, false) if err != nil { - return err + log.Ctx(ctx).Warn().Err(err).Msg("failed to cleanup repo public access") } + } - repo, isPublic = remoteRepository.ToRepo( - parentSpace.ID, - in.Identifier, - in.Description, - &session.Principal, - c.publicResourceCreationEnabled, - ) + err = c.publicAccess.Set(ctx, enum.PublicResourceTypeRepo, repo.Path, isPublic) + if err != nil { + cleanUpPublicAccess() + return nil, fmt.Errorf("failed to set repo public access: %w", err) + } + + err = c.tx.WithTx(ctx, func(ctx context.Context) error { + if err := c.resourceLimiter.RepoCount(ctx, parentSpace.ID, 1); err != nil { + return fmt.Errorf("resource limit exceeded: %w", limiter.ErrMaxNumReposReached) + } // lock the space for update during repo creation to prevent racing conditions with space soft delete. parentSpace, err = c.spaceStore.FindForUpdate(ctx, parentSpace.ID) @@ -102,6 +108,7 @@ func (c *Controller) Import(ctx context.Context, session *auth.Session, in *Impo return nil }) if err != nil { + cleanUpPublicAccess() return nil, err } From bd9a94a1254eb5eeb7fcdf841ac1192c106de697 Mon Sep 17 00:00:00 2001 From: Ritik Kapoor Date: Sun, 12 May 2024 20:12:31 +0530 Subject: [PATCH 31/31] fix: [ritik/code-1773] api payload update --- .../GeneralSettingsContent/GeneralSettingsContent.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/pages/RepositorySettings/GeneralSettingsContent/GeneralSettingsContent.tsx b/web/src/pages/RepositorySettings/GeneralSettingsContent/GeneralSettingsContent.tsx index b9c92996ac..6dff3e5528 100644 --- a/web/src/pages/RepositorySettings/GeneralSettingsContent/GeneralSettingsContent.tsx +++ b/web/src/pages/RepositorySettings/GeneralSettingsContent/GeneralSettingsContent.tsx @@ -157,7 +157,7 @@ const GeneralSettingsContent = (props: GeneralSettingsProps) => { } variation={ButtonVariation.PRIMARY} onClick={() => { - changeVisibility({ enable_public: repoVis === RepoVisibility.PUBLIC ? true : false }) + changeVisibility({ is_public: repoVis === RepoVisibility.PUBLIC ? true : false }) .then(() => { showSuccess(getString('repoUpdate')) hideModal()