From e68b9d00a6e05b3a941f63ffb696f91e554ac5ec Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 18 Oct 2024 20:33:49 +0200 Subject: Adding upstream version 9.0.3. Signed-off-by: Daniel Baumann --- services/org/org.go | 76 +++++++++++++++++++++++++++++++++++++++++++++ services/org/org_test.go | 39 +++++++++++++++++++++++ services/org/repo.go | 27 ++++++++++++++++ services/org/repo_test.go | 34 ++++++++++++++++++++ services/org/team_invite.go | 22 +++++++++++++ 5 files changed, 198 insertions(+) create mode 100644 services/org/org.go create mode 100644 services/org/org_test.go create mode 100644 services/org/repo.go create mode 100644 services/org/repo_test.go create mode 100644 services/org/team_invite.go (limited to 'services/org') diff --git a/services/org/org.go b/services/org/org.go new file mode 100644 index 0000000..dca7794 --- /dev/null +++ b/services/org/org.go @@ -0,0 +1,76 @@ +// Copyright 2021 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package org + +import ( + "context" + "fmt" + + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/models/db" + org_model "code.gitea.io/gitea/models/organization" + packages_model "code.gitea.io/gitea/models/packages" + repo_model "code.gitea.io/gitea/models/repo" + user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/storage" + "code.gitea.io/gitea/modules/util" + repo_service "code.gitea.io/gitea/services/repository" +) + +// DeleteOrganization completely and permanently deletes everything of organization. +func DeleteOrganization(ctx context.Context, org *org_model.Organization, purge bool) error { + ctx, commiter, err := db.TxContext(ctx) + if err != nil { + return err + } + defer commiter.Close() + + if purge { + err := repo_service.DeleteOwnerRepositoriesDirectly(ctx, org.AsUser()) + if err != nil { + return err + } + } + + // Check ownership of repository. + count, err := repo_model.CountRepositories(ctx, repo_model.CountRepositoryOptions{OwnerID: org.ID}) + if err != nil { + return fmt.Errorf("GetRepositoryCount: %w", err) + } else if count > 0 { + return models.ErrUserOwnRepos{UID: org.ID} + } + + // Check ownership of packages. + if ownsPackages, err := packages_model.HasOwnerPackages(ctx, org.ID); err != nil { + return fmt.Errorf("HasOwnerPackages: %w", err) + } else if ownsPackages { + return models.ErrUserOwnPackages{UID: org.ID} + } + + if err := org_model.DeleteOrganization(ctx, org); err != nil { + return fmt.Errorf("DeleteOrganization: %w", err) + } + + if err := commiter.Commit(); err != nil { + return err + } + + // FIXME: system notice + // Note: There are something just cannot be roll back, + // so just keep error logs of those operations. + path := user_model.UserPath(org.Name) + + if err := util.RemoveAll(path); err != nil { + return fmt.Errorf("failed to RemoveAll %s: %w", path, err) + } + + if len(org.Avatar) > 0 { + avatarPath := org.CustomAvatarRelativePath() + if err := storage.Avatars.Delete(avatarPath); err != nil { + return fmt.Errorf("failed to remove %s: %w", avatarPath, err) + } + } + + return nil +} diff --git a/services/org/org_test.go b/services/org/org_test.go new file mode 100644 index 0000000..0735843 --- /dev/null +++ b/services/org/org_test.go @@ -0,0 +1,39 @@ +// Copyright 2021 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package org + +import ( + "testing" + + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/models/db" + "code.gitea.io/gitea/models/organization" + "code.gitea.io/gitea/models/unittest" + user_model "code.gitea.io/gitea/models/user" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestMain(m *testing.M) { + unittest.MainTest(m) +} + +func TestDeleteOrganization(t *testing.T) { + require.NoError(t, unittest.PrepareTestDatabase()) + org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 6}) + require.NoError(t, DeleteOrganization(db.DefaultContext, org, false)) + unittest.AssertNotExistsBean(t, &organization.Organization{ID: 6}) + unittest.AssertNotExistsBean(t, &organization.OrgUser{OrgID: 6}) + unittest.AssertNotExistsBean(t, &organization.Team{OrgID: 6}) + + org = unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3}) + err := DeleteOrganization(db.DefaultContext, org, false) + require.Error(t, err) + assert.True(t, models.IsErrUserOwnRepos(err)) + + user := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 5}) + require.Error(t, DeleteOrganization(db.DefaultContext, user, false)) + unittest.CheckConsistencyFor(t, &user_model.User{}, &organization.Team{}) +} diff --git a/services/org/repo.go b/services/org/repo.go new file mode 100644 index 0000000..78a829e --- /dev/null +++ b/services/org/repo.go @@ -0,0 +1,27 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package org + +import ( + "context" + "errors" + + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/models/db" + "code.gitea.io/gitea/models/organization" + repo_model "code.gitea.io/gitea/models/repo" +) + +// TeamAddRepository adds new repository to team of organization. +func TeamAddRepository(ctx context.Context, t *organization.Team, repo *repo_model.Repository) (err error) { + if repo.OwnerID != t.OrgID { + return errors.New("repository does not belong to organization") + } else if organization.HasTeamRepo(ctx, t.OrgID, t.ID, repo.ID) { + return nil + } + + return db.WithTx(ctx, func(ctx context.Context) error { + return models.AddRepository(ctx, t, repo) + }) +} diff --git a/services/org/repo_test.go b/services/org/repo_test.go new file mode 100644 index 0000000..2ddb8f9 --- /dev/null +++ b/services/org/repo_test.go @@ -0,0 +1,34 @@ +// Copyright 2021 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package org + +import ( + "testing" + + "code.gitea.io/gitea/models/db" + "code.gitea.io/gitea/models/organization" + repo_model "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/models/unittest" + + "github.com/stretchr/testify/require" +) + +func TestTeam_AddRepository(t *testing.T) { + require.NoError(t, unittest.PrepareTestDatabase()) + + testSuccess := func(teamID, repoID int64) { + team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: teamID}) + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repoID}) + require.NoError(t, TeamAddRepository(db.DefaultContext, team, repo)) + unittest.AssertExistsAndLoadBean(t, &organization.TeamRepo{TeamID: teamID, RepoID: repoID}) + unittest.CheckConsistencyFor(t, &organization.Team{ID: teamID}, &repo_model.Repository{ID: repoID}) + } + testSuccess(2, 3) + testSuccess(2, 5) + + team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 1}) + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) + require.Error(t, TeamAddRepository(db.DefaultContext, team, repo)) + unittest.CheckConsistencyFor(t, &organization.Team{ID: 1}, &repo_model.Repository{ID: 1}) +} diff --git a/services/org/team_invite.go b/services/org/team_invite.go new file mode 100644 index 0000000..3f28044 --- /dev/null +++ b/services/org/team_invite.go @@ -0,0 +1,22 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package org + +import ( + "context" + + org_model "code.gitea.io/gitea/models/organization" + user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/services/mailer" +) + +// CreateTeamInvite make a persistent invite in db and mail it +func CreateTeamInvite(ctx context.Context, inviter *user_model.User, team *org_model.Team, uname string) error { + invite, err := org_model.CreateTeamInvite(ctx, inviter, team, uname) + if err != nil { + return err + } + + return mailer.MailTeamInvite(ctx, inviter, team, invite) +} -- cgit v1.2.3