Check that repositories can only be migrated to own user or organizations (#4366)
* Repositories can only migrated to own user or organizations * Add check for organization that user does not belong to * Allow admin to migrate repositories for other users
This commit is contained in:
		
							parent
							
								
									b46066f17c
								
							
						
					
					
						commit
						4a8ee0b5cc
					
				
					 2 changed files with 42 additions and 8 deletions
				
			
		|  | @ -235,3 +235,30 @@ func TestAPIGetRepoByIDUnauthorized(t *testing.T) { | ||||||
| 	req := NewRequestf(t, "GET", "/api/v1/repositories/2") | 	req := NewRequestf(t, "GET", "/api/v1/repositories/2") | ||||||
| 	sess.MakeRequest(t, req, http.StatusNotFound) | 	sess.MakeRequest(t, req, http.StatusNotFound) | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func TestAPIRepoMigrate(t *testing.T) { | ||||||
|  | 	testCases := []struct { | ||||||
|  | 		ctxUserID, userID  int64 | ||||||
|  | 		cloneURL, repoName string | ||||||
|  | 		expectedStatus     int | ||||||
|  | 	}{ | ||||||
|  | 		{ctxUserID: 1, userID: 2, cloneURL: "https://github.com/go-gitea/git.git", repoName: "git-admin", expectedStatus: http.StatusCreated}, | ||||||
|  | 		{ctxUserID: 2, userID: 2, cloneURL: "https://github.com/go-gitea/git.git", repoName: "git-own", expectedStatus: http.StatusCreated}, | ||||||
|  | 		{ctxUserID: 2, userID: 1, cloneURL: "https://github.com/go-gitea/git.git", repoName: "git-bad", expectedStatus: http.StatusForbidden}, | ||||||
|  | 		{ctxUserID: 2, userID: 3, cloneURL: "https://github.com/go-gitea/git.git", repoName: "git-org", expectedStatus: http.StatusCreated}, | ||||||
|  | 		{ctxUserID: 2, userID: 6, cloneURL: "https://github.com/go-gitea/git.git", repoName: "git-bad-org", expectedStatus: http.StatusForbidden}, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	prepareTestEnv(t) | ||||||
|  | 	for _, testCase := range testCases { | ||||||
|  | 		user := models.AssertExistsAndLoadBean(t, &models.User{ID: testCase.ctxUserID}).(*models.User) | ||||||
|  | 		session := loginUser(t, user.Name) | ||||||
|  | 
 | ||||||
|  | 		req := NewRequestWithJSON(t, "POST", "/api/v1/repos/migrate", &api.MigrateRepoOption{ | ||||||
|  | 			CloneAddr: testCase.cloneURL, | ||||||
|  | 			UID:       int(testCase.userID), | ||||||
|  | 			RepoName:  testCase.repoName, | ||||||
|  | 		}) | ||||||
|  | 		session.MakeRequest(t, req, testCase.expectedStatus) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -306,16 +306,23 @@ func Migrate(ctx *context.APIContext, form auth.MigrateRepoForm) { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if ctxUser.IsOrganization() && !ctx.User.IsAdmin { | 	if !ctx.User.IsAdmin { | ||||||
| 		// Check ownership of organization.
 | 		if !ctxUser.IsOrganization() && ctx.User.ID != ctxUser.ID { | ||||||
| 		isOwner, err := ctxUser.IsOwnedBy(ctx.User.ID) | 			ctx.Error(403, "", "Given user is not an organization.") | ||||||
| 		if err != nil { |  | ||||||
| 			ctx.Error(500, "IsOwnedBy", err) |  | ||||||
| 			return |  | ||||||
| 		} else if !isOwner { |  | ||||||
| 			ctx.Error(403, "", "Given user is not owner of organization.") |  | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
|  | 		if ctxUser.IsOrganization() { | ||||||
|  | 			// Check ownership of organization.
 | ||||||
|  | 			isOwner, err := ctxUser.IsOwnedBy(ctx.User.ID) | ||||||
|  | 			if err != nil { | ||||||
|  | 				ctx.Error(500, "IsOwnedBy", err) | ||||||
|  | 				return | ||||||
|  | 			} else if !isOwner { | ||||||
|  | 				ctx.Error(403, "", "Given user is not owner of organization.") | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	remoteAddr, err := form.ParseRemoteAddr(ctx.User) | 	remoteAddr, err := form.ParseRemoteAddr(ctx.User) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue