mirror of https://github.com/harness/drone.git
update audit logs to include repo is-public
parent
e4d46d8a30
commit
3d5fb186c4
|
@ -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
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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),
|
||||
)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
|
@ -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))
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue