Changes
6 changed files (+322/-0)
-
-
@@ -498,6 +498,85 @@ func TestAPIRepoTransfer(t *testing.T) {_ = models.DeleteRepository(user, repo.OwnerID, repo.ID) } func transfer(t *testing.T) *repo_model.Repository { //create repo to move user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}).(*user_model.User) session := loginUser(t, user.Name) token := getTokenForLoggedInUser(t, session) repoName := "moveME" apiRepo := new(api.Repository) req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/user/repos?token=%s", token), &api.CreateRepoOption{ Name: repoName, Description: "repo move around", Private: false, Readme: "Default", AutoInit: true, }) resp := session.MakeRequest(t, req, http.StatusCreated) DecodeJSON(t, resp, apiRepo) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: apiRepo.ID}).(*repo_model.Repository) req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/transfer?token=%s", repo.OwnerName, repo.Name, token), &api.TransferRepoOption{ NewOwner: "user4", }) session.MakeRequest(t, req, http.StatusCreated) return repo } func TestAPIAcceptTransfer(t *testing.T) { defer prepareTestEnv(t)() repo := transfer(t) // try to accept with not authorized user session := loginUser(t, "user2") token := getTokenForLoggedInUser(t, session) req := NewRequest(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/transfer/reject?token=%s", repo.OwnerName, repo.Name, token)) session.MakeRequest(t, req, http.StatusForbidden) // try to accept repo that's not marked as transferred req = NewRequest(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/transfer/accept?token=%s", "user2", "repo1", token)) session.MakeRequest(t, req, http.StatusNotFound) // accept transfer session = loginUser(t, "user4") token = getTokenForLoggedInUser(t, session) req = NewRequest(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/transfer/accept?token=%s", repo.OwnerName, repo.Name, token)) resp := session.MakeRequest(t, req, http.StatusAccepted) apiRepo := new(api.Repository) DecodeJSON(t, resp, apiRepo) assert.Equal(t, "user4", apiRepo.Owner.UserName) } func TestAPIRejectTransfer(t *testing.T) { defer prepareTestEnv(t)() repo := transfer(t) // try to reject with not authorized user session := loginUser(t, "user2") token := getTokenForLoggedInUser(t, session) req := NewRequest(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/transfer/reject?token=%s", repo.OwnerName, repo.Name, token)) session.MakeRequest(t, req, http.StatusForbidden) // try to reject repo that's not marked as transferred req = NewRequest(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/transfer/reject?token=%s", "user2", "repo1", token)) session.MakeRequest(t, req, http.StatusNotFound) // reject transfer session = loginUser(t, "user4") token = getTokenForLoggedInUser(t, session) req = NewRequest(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/transfer/reject?token=%s", repo.OwnerName, repo.Name, token)) resp := session.MakeRequest(t, req, http.StatusOK) apiRepo := new(api.Repository) DecodeJSON(t, resp, apiRepo) assert.Equal(t, "user2", apiRepo.Owner.UserName) } func TestAPIGenerateRepo(t *testing.T) { defer prepareTestEnv(t)()
-
-
-
@@ -10,6 +10,7 @@ import ("code.gitea.io/gitea/models/perm" repo_model "code.gitea.io/gitea/models/repo" unit_model "code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/modules/log" api "code.gitea.io/gitea/modules/structs" )
-
@@ -106,6 +107,20 @@ func innerToRepo(repo *repo_model.Repository, mode perm.AccessMode, isParent boo} } var transfer *api.RepoTransfer if repo.Status == repo_model.RepositoryPendingTransfer { t, err := models.GetPendingRepositoryTransfer(repo) if err != nil && !models.IsErrNoPendingTransfer(err) { log.Warn("GetPendingRepositoryTransfer: %v", err) } else { if err := t.LoadAttributes(); err != nil { log.Warn("LoadAttributes of RepoTransfer: %v", err) } else { transfer = ToRepoTransfer(t) } } } return &api.Repository{ ID: repo.ID, Owner: ToUserWithAccessMode(repo.Owner, mode),
-
@@ -151,5 +166,20 @@ func innerToRepo(repo *repo_model.Repository, mode perm.AccessMode, isParent booAvatarURL: repo.AvatarLink(), Internal: !repo.IsPrivate && repo.Owner.Visibility == api.VisibleTypePrivate, MirrorInterval: mirrorInterval, RepoTransfer: transfer, } } // ToRepoTransfer convert a models.RepoTransfer to a structs.RepeTransfer func ToRepoTransfer(t *models.RepoTransfer) *api.RepoTransfer { var teams []*api.Team for _, v := range t.Teams { teams = append(teams, ToTeam(v)) } return &api.RepoTransfer{ Doer: ToUser(t.Doer, nil), Recipient: ToUser(t.Recipient, nil), Teams: teams, } }
-
-
-
@@ -93,6 +93,7 @@ type Repository struct {AvatarURL string `json:"avatar_url"` Internal bool `json:"internal"` MirrorInterval string `json:"mirror_interval"` RepoTransfer *RepoTransfer `json:"repo_transfer"` } // CreateRepoOption options when creating repository
-
@@ -336,3 +337,10 @@ var (CodebaseService, } ) // RepoTransfer represents a pending repo transfer type RepoTransfer struct { Doer *User `json:"doer"` Recipient *User `json:"recipient"` Teams []*Team `json:"teams"` }
-
-
-
@@ -736,6 +736,8 @@ func Routes(sessioner func(http.Handler) http.Handler) *web.Route {Patch(reqToken(), reqAdmin(), bind(api.EditRepoOption{}), repo.Edit) m.Post("/generate", reqToken(), reqRepoReader(unit.TypeCode), bind(api.GenerateRepoOption{}), repo.Generate) m.Post("/transfer", reqOwner(), bind(api.TransferRepoOption{}), repo.Transfer) m.Post("/transfer/accept", reqToken(), repo.AcceptTransfer) m.Post("/transfer/reject", reqToken(), repo.RejectTransfer) m.Combo("/notifications"). Get(reqToken(), notify.ListRepoNotifications). Put(reqToken(), notify.ReadRepoNotifications)
-
-
-
@@ -127,3 +127,105 @@ func Transfer(ctx *context.APIContext) {log.Trace("Repository transferred: %s -> %s", ctx.Repo.Repository.FullName(), newOwner.Name) ctx.JSON(http.StatusAccepted, convert.ToRepo(ctx.Repo.Repository, perm.AccessModeAdmin)) } // AcceptTransfer accept a repo transfer func AcceptTransfer(ctx *context.APIContext) { // swagger:operation POST /repos/{owner}/{repo}/transfer/accept repository acceptRepoTransfer // --- // summary: Accept a repo transfer // produces: // - application/json // parameters: // - name: owner // in: path // description: owner of the repo to transfer // type: string // required: true // - name: repo // in: path // description: name of the repo to transfer // type: string // required: true // responses: // "202": // "$ref": "#/responses/Repository" // "403": // "$ref": "#/responses/forbidden" // "404": // "$ref": "#/responses/notFound" err := acceptOrRejectRepoTransfer(ctx, true) if ctx.Written() { return } if err != nil { ctx.Error(http.StatusInternalServerError, "acceptOrRejectRepoTransfer", err) return } ctx.JSON(http.StatusAccepted, convert.ToRepo(ctx.Repo.Repository, ctx.Repo.AccessMode)) } // RejectTransfer reject a repo transfer func RejectTransfer(ctx *context.APIContext) { // swagger:operation POST /repos/{owner}/{repo}/transfer/reject repository rejectRepoTransfer // --- // summary: Reject a repo transfer // produces: // - application/json // parameters: // - name: owner // in: path // description: owner of the repo to transfer // type: string // required: true // - name: repo // in: path // description: name of the repo to transfer // type: string // required: true // responses: // "200": // "$ref": "#/responses/Repository" // "403": // "$ref": "#/responses/forbidden" // "404": // "$ref": "#/responses/notFound" err := acceptOrRejectRepoTransfer(ctx, false) if ctx.Written() { return } if err != nil { ctx.Error(http.StatusInternalServerError, "acceptOrRejectRepoTransfer", err) return } ctx.JSON(http.StatusOK, convert.ToRepo(ctx.Repo.Repository, ctx.Repo.AccessMode)) } func acceptOrRejectRepoTransfer(ctx *context.APIContext, accept bool) error { repoTransfer, err := models.GetPendingRepositoryTransfer(ctx.Repo.Repository) if err != nil { if models.IsErrNoPendingTransfer(err) { ctx.NotFound() return nil } return err } if err := repoTransfer.LoadAttributes(); err != nil { return err } if !repoTransfer.CanUserAcceptTransfer(ctx.User) { ctx.Error(http.StatusForbidden, "CanUserAcceptTransfer", nil) return fmt.Errorf("user does not have permissions to do this") } if accept { return repo_service.TransferOwnership(repoTransfer.Doer, repoTransfer.Recipient, ctx.Repo.Repository, repoTransfer.Teams) } return models.CancelRepositoryTransfer(ctx.Repo.Repository) }
-
-
-
@@ -9895,6 +9895,84 @@} } }, "/repos/{owner}/{repo}/transfer/accept": { "post": { "produces": [ "application/json" ], "tags": [ "repository" ], "summary": "Accept a repo transfer", "operationId": "acceptRepoTransfer", "parameters": [ { "type": "string", "description": "owner of the repo to transfer", "name": "owner", "in": "path", "required": true }, { "type": "string", "description": "name of the repo to transfer", "name": "repo", "in": "path", "required": true } ], "responses": { "202": { "$ref": "#/responses/Repository" }, "403": { "$ref": "#/responses/forbidden" }, "404": { "$ref": "#/responses/notFound" } } } }, "/repos/{owner}/{repo}/transfer/reject": { "post": { "produces": [ "application/json" ], "tags": [ "repository" ], "summary": "Reject a repo transfer", "operationId": "rejectRepoTransfer", "parameters": [ { "type": "string", "description": "owner of the repo to transfer", "name": "owner", "in": "path", "required": true }, { "type": "string", "description": "name of the repo to transfer", "name": "repo", "in": "path", "required": true } ], "responses": { "200": { "$ref": "#/responses/Repository" }, "403": { "$ref": "#/responses/forbidden" }, "404": { "$ref": "#/responses/notFound" } } } }, "/repos/{owner}/{repo}/wiki/new": { "post": { "consumes": [
-
@@ -16890,6 +16968,26 @@}, "x-go-package": "code.gitea.io/gitea/modules/structs" }, "RepoTransfer": { "description": "RepoTransfer represents a pending repo transfer", "type": "object", "properties": { "doer": { "$ref": "#/definitions/User" }, "recipient": { "$ref": "#/definitions/User" }, "teams": { "type": "array", "items": { "$ref": "#/definitions/Team" }, "x-go-name": "Teams" } }, "x-go-package": "code.gitea.io/gitea/modules/structs" }, "Repository": { "description": "Repository represents a repository", "type": "object",
-
@@ -17042,6 +17140,9 @@"format": "int64", "x-go-name": "Releases" }, "repo_transfer": { "$ref": "#/definitions/RepoTransfer" }, "size": { "type": "integer", "format": "int64",
-