0
0
mirror of https://github.com/go-gitea/gitea.git synced 2026-05-15 17:11:10 +02:00

added system notice

This commit is contained in:
karthikbhandary2 2026-03-06 16:37:11 +05:30
parent 9f31e6cac1
commit a5092e5aa7
3 changed files with 102 additions and 1 deletions

View File

@ -5,6 +5,7 @@
package org
import (
"fmt"
"net/http"
activities_model "code.gitea.io/gitea/models/activities"
@ -12,6 +13,7 @@ import (
"code.gitea.io/gitea/models/organization"
"code.gitea.io/gitea/models/perm"
repo_model "code.gitea.io/gitea/models/repo"
system_model "code.gitea.io/gitea/models/system"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/log"
@ -513,6 +515,8 @@ func DeleteOrgRepos(ctx *context.APIContext) {
// responses:
// "202":
// description: Deletion started
// "204":
// description: No repositories to delete
// "403":
// "$ref": "#/responses/forbidden"
// "404":
@ -524,6 +528,11 @@ func DeleteOrgRepos(ctx *context.APIContext) {
return
}
if len(repos) == 0 {
ctx.Status(http.StatusNoContent)
return
}
doer := ctx.Doer
// Start deletion in background with detached context
@ -539,7 +548,10 @@ func DeleteOrgRepos(ctx *context.APIContext) {
for _, repo := range repos {
if err := repo_service.DeleteRepository(bgCtx, doer, repo, true); err != nil {
log.Error("Failed to delete repository %s (ID: %d) in org %s: %v", repo.Name, repo.ID, org.Name, err)
desc := fmt.Sprintf("Failed to delete repository %s (ID: %d) in org %s: %v", repo.Name, repo.ID, org.Name, err)
if noticeErr := system_model.CreateNotice(bgCtx, system_model.NoticeRepository, desc); noticeErr != nil {
log.Error("Failed to create notice for repo deletion failure: %v", noticeErr)
}
} else {
log.Info("Successfully deleted repository %s (ID: %d) in org %s", repo.Name, repo.ID, org.Name)
}

View File

@ -3551,6 +3551,9 @@
"202": {
"description": "Deletion started"
},
"204": {
"description": "No repositories to delete"
},
"403": {
"$ref": "#/responses/forbidden"
},

View File

@ -8,16 +8,20 @@ import (
"net/http"
"strings"
"testing"
"time"
auth_model "code.gitea.io/gitea/models/auth"
org_model "code.gitea.io/gitea/models/organization"
"code.gitea.io/gitea/models/perm"
repo_model "code.gitea.io/gitea/models/repo"
system_model "code.gitea.io/gitea/models/system"
unit_model "code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/test"
repo_service "code.gitea.io/gitea/services/repository"
"code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert"
@ -326,4 +330,86 @@ func TestAPIDeleteOrgRepos(t *testing.T) {
req = NewRequest(t, "DELETE", "/api/v1/orgs/org3/repos").AddTokenAuth(nonOwnerToken)
MakeRequest(t, req, http.StatusForbidden)
})
t.Run("No system notice created on successful deletion", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
session := loginUser(t, "user1")
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteOrganization, auth_model.AccessTokenScopeWriteRepository)
orgName := "test_notice_org"
req := NewRequestWithJSON(t, "POST", "/api/v1/orgs", &api.CreateOrgOption{
UserName: orgName,
}).AddTokenAuth(token)
MakeRequest(t, req, http.StatusCreated)
// Create a repo
req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/org/%s/repos", orgName), &api.CreateRepoOption{
Name: "test_repo",
}).AddTokenAuth(token)
MakeRequest(t, req, http.StatusCreated)
// Get initial notice count
initialNotices := unittest.GetCount(t, &system_model.Notice{Type: system_model.NoticeRepository})
// Delete repos
req = NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/orgs/%s/repos", orgName)).AddTokenAuth(token)
MakeRequest(t, req, http.StatusAccepted)
// Wait for background deletion to complete
time.Sleep(2 * time.Second)
// Check if notices were created (should be 0 for successful deletions)
finalNotices := unittest.GetCount(t, &system_model.Notice{Type: system_model.NoticeRepository})
assert.Equal(t, initialNotices, finalNotices, "No notices should be created for successful deletions")
})
t.Run("Returns 204 when repos already deleted", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
session := loginUser(t, "user1")
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteOrganization, auth_model.AccessTokenScopeWriteRepository)
orgName := "test_fail_notice"
req := NewRequestWithJSON(t, "POST", "/api/v1/orgs", &api.CreateOrgOption{
UserName: orgName,
}).AddTokenAuth(token)
MakeRequest(t, req, http.StatusCreated)
// Create a repo
repoName := "test_fail_repo"
req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/org/%s/repos", orgName), &api.CreateRepoOption{
Name: repoName,
}).AddTokenAuth(token)
MakeRequest(t, req, http.StatusCreated)
// Delete the repo directly to cause the bulk delete to fail
org := unittest.AssertExistsAndLoadBean(t, &org_model.Organization{Name: orgName})
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{Name: repoName, OwnerID: org.ID})
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "user1"})
err := repo_service.DeleteRepository(t.Context(), user, repo, true)
assert.NoError(t, err)
// Now try to delete all org repos - should return 204 since no repos exist
req = NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/orgs/%s/repos", orgName)).AddTokenAuth(token)
MakeRequest(t, req, http.StatusNoContent)
})
t.Run("Returns 204 when no repos exist", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
session := loginUser(t, "user1")
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteOrganization, auth_model.AccessTokenScopeWriteRepository)
orgName := "test_empty_org"
req := NewRequestWithJSON(t, "POST", "/api/v1/orgs", &api.CreateOrgOption{
UserName: orgName,
}).AddTokenAuth(token)
MakeRequest(t, req, http.StatusCreated)
// Delete repos when org has no repos - should return 204
req = NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/orgs/%s/repos", orgName)).AddTokenAuth(token)
MakeRequest(t, req, http.StatusNoContent)
})
}