You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

479 lines
18 KiB

Template Repositories (#8768) * Start work on templates Signed-off-by: jolheiser <john.olheiser@gmail.com> * Continue work Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix IsTemplate vs IsGenerated Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix tabs vs spaces * Tabs vs Spaces * Add templates to API & start adding tests Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix integration tests Signed-off-by: jolheiser <john.olheiser@gmail.com> * Remove unused User Signed-off-by: jolheiser <john.olheiser@gmail.com> * Move template tests to existing repos Signed-off-by: jolheiser <john.olheiser@gmail.com> * Minor re-check updates and cleanup Signed-off-by: jolheiser <john.olheiser@gmail.com> * make fmt Signed-off-by: jolheiser <john.olheiser@gmail.com> * Test cleanup Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix optionalbool Signed-off-by: jolheiser <john.olheiser@gmail.com> * make fmt Signed-off-by: jolheiser <john.olheiser@gmail.com> * Test fixes and icon change Signed-off-by: jolheiser <john.olheiser@gmail.com> * Add new user and repo for tests Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix tests (finally) Signed-off-by: jolheiser <john.olheiser@gmail.com> * Update meta repo with env variables Signed-off-by: jolheiser <john.olheiser@gmail.com> * Move generation to create page Combine with repo create template Modify API search to prioritize owner for repo Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix tests and coverage Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix swagger and JS lint Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix API searching for own private repos Signed-off-by: jolheiser <john.olheiser@gmail.com> * Change wording Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix repo search test. User had a private repo that didn't show up Signed-off-by: jolheiser <john.olheiser@gmail.com> * Another search test fix Signed-off-by: jolheiser <john.olheiser@gmail.com> * Clarify git content Co-Authored-By: guillep2k <18600385+guillep2k@users.noreply.github.com> * Feedback updates Signed-off-by: jolheiser <john.olheiser@gmail.com> * Add topics WIP Signed-off-by: jolheiser <john.olheiser@gmail.com> * Finish adding topics Signed-off-by: jolheiser <john.olheiser@gmail.com> * Update locale Signed-off-by: jolheiser <john.olheiser@gmail.com>
4 years ago
Template Repositories (#8768) * Start work on templates Signed-off-by: jolheiser <john.olheiser@gmail.com> * Continue work Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix IsTemplate vs IsGenerated Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix tabs vs spaces * Tabs vs Spaces * Add templates to API & start adding tests Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix integration tests Signed-off-by: jolheiser <john.olheiser@gmail.com> * Remove unused User Signed-off-by: jolheiser <john.olheiser@gmail.com> * Move template tests to existing repos Signed-off-by: jolheiser <john.olheiser@gmail.com> * Minor re-check updates and cleanup Signed-off-by: jolheiser <john.olheiser@gmail.com> * make fmt Signed-off-by: jolheiser <john.olheiser@gmail.com> * Test cleanup Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix optionalbool Signed-off-by: jolheiser <john.olheiser@gmail.com> * make fmt Signed-off-by: jolheiser <john.olheiser@gmail.com> * Test fixes and icon change Signed-off-by: jolheiser <john.olheiser@gmail.com> * Add new user and repo for tests Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix tests (finally) Signed-off-by: jolheiser <john.olheiser@gmail.com> * Update meta repo with env variables Signed-off-by: jolheiser <john.olheiser@gmail.com> * Move generation to create page Combine with repo create template Modify API search to prioritize owner for repo Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix tests and coverage Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix swagger and JS lint Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix API searching for own private repos Signed-off-by: jolheiser <john.olheiser@gmail.com> * Change wording Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix repo search test. User had a private repo that didn't show up Signed-off-by: jolheiser <john.olheiser@gmail.com> * Another search test fix Signed-off-by: jolheiser <john.olheiser@gmail.com> * Clarify git content Co-Authored-By: guillep2k <18600385+guillep2k@users.noreply.github.com> * Feedback updates Signed-off-by: jolheiser <john.olheiser@gmail.com> * Add topics WIP Signed-off-by: jolheiser <john.olheiser@gmail.com> * Finish adding topics Signed-off-by: jolheiser <john.olheiser@gmail.com> * Update locale Signed-off-by: jolheiser <john.olheiser@gmail.com>
4 years ago
  1. // Copyright 2017 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package integrations
  5. import (
  6. "fmt"
  7. "io/ioutil"
  8. "net/http"
  9. "net/url"
  10. "testing"
  11. "code.gitea.io/gitea/models"
  12. "code.gitea.io/gitea/modules/setting"
  13. api "code.gitea.io/gitea/modules/structs"
  14. "code.gitea.io/gitea/modules/util"
  15. "github.com/stretchr/testify/assert"
  16. )
  17. func TestAPIUserReposNotLogin(t *testing.T) {
  18. defer prepareTestEnv(t)()
  19. user := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User)
  20. req := NewRequestf(t, "GET", "/api/v1/users/%s/repos", user.Name)
  21. resp := MakeRequest(t, req, http.StatusOK)
  22. var apiRepos []api.Repository
  23. DecodeJSON(t, resp, &apiRepos)
  24. expectedLen := models.GetCount(t, models.Repository{OwnerID: user.ID},
  25. models.Cond("is_private = ?", false))
  26. assert.Len(t, apiRepos, expectedLen)
  27. for _, repo := range apiRepos {
  28. assert.EqualValues(t, user.ID, repo.Owner.ID)
  29. assert.False(t, repo.Private)
  30. }
  31. }
  32. func TestAPISearchRepo(t *testing.T) {
  33. defer prepareTestEnv(t)()
  34. const keyword = "test"
  35. req := NewRequestf(t, "GET", "/api/v1/repos/search?q=%s", keyword)
  36. resp := MakeRequest(t, req, http.StatusOK)
  37. var body api.SearchResults
  38. DecodeJSON(t, resp, &body)
  39. assert.NotEmpty(t, body.Data)
  40. for _, repo := range body.Data {
  41. assert.Contains(t, repo.Name, keyword)
  42. assert.False(t, repo.Private)
  43. }
  44. user := models.AssertExistsAndLoadBean(t, &models.User{ID: 15}).(*models.User)
  45. user2 := models.AssertExistsAndLoadBean(t, &models.User{ID: 16}).(*models.User)
  46. user3 := models.AssertExistsAndLoadBean(t, &models.User{ID: 18}).(*models.User)
  47. user4 := models.AssertExistsAndLoadBean(t, &models.User{ID: 20}).(*models.User)
  48. orgUser := models.AssertExistsAndLoadBean(t, &models.User{ID: 17}).(*models.User)
  49. oldAPIDefaultNum := setting.API.DefaultPagingNum
  50. defer func() {
  51. setting.API.DefaultPagingNum = oldAPIDefaultNum
  52. }()
  53. setting.API.DefaultPagingNum = 10
  54. // Map of expected results, where key is user for login
  55. type expectedResults map[*models.User]struct {
  56. count int
  57. repoOwnerID int64
  58. repoName string
  59. includesPrivate bool
  60. }
  61. testCases := []struct {
  62. name, requestURL string
  63. expectedResults
  64. }{
  65. {name: "RepositoriesMax50", requestURL: "/api/v1/repos/search?limit=50&private=false", expectedResults: expectedResults{
  66. nil: {count: 27},
  67. user: {count: 27},
  68. user2: {count: 27}},
  69. },
  70. {name: "RepositoriesMax10", requestURL: "/api/v1/repos/search?limit=10&private=false", expectedResults: expectedResults{
  71. nil: {count: 10},
  72. user: {count: 10},
  73. user2: {count: 10}},
  74. },
  75. {name: "RepositoriesDefault", requestURL: "/api/v1/repos/search?default&private=false", expectedResults: expectedResults{
  76. nil: {count: 10},
  77. user: {count: 10},
  78. user2: {count: 10}},
  79. },
  80. {name: "RepositoriesByName", requestURL: fmt.Sprintf("/api/v1/repos/search?q=%s&private=false", "big_test_"), expectedResults: expectedResults{
  81. nil: {count: 7, repoName: "big_test_"},
  82. user: {count: 7, repoName: "big_test_"},
  83. user2: {count: 7, repoName: "big_test_"}},
  84. },
  85. {name: "RepositoriesAccessibleAndRelatedToUser", requestURL: fmt.Sprintf("/api/v1/repos/search?uid=%d", user.ID), expectedResults: expectedResults{
  86. nil: {count: 5},
  87. user: {count: 9, includesPrivate: true},
  88. user2: {count: 6, includesPrivate: true}},
  89. },
  90. {name: "RepositoriesAccessibleAndRelatedToUser2", requestURL: fmt.Sprintf("/api/v1/repos/search?uid=%d", user2.ID), expectedResults: expectedResults{
  91. nil: {count: 1},
  92. user: {count: 2, includesPrivate: true},
  93. user2: {count: 2, includesPrivate: true},
  94. user4: {count: 1}},
  95. },
  96. {name: "RepositoriesAccessibleAndRelatedToUser3", requestURL: fmt.Sprintf("/api/v1/repos/search?uid=%d", user3.ID), expectedResults: expectedResults{
  97. nil: {count: 1},
  98. user: {count: 4, includesPrivate: true},
  99. user2: {count: 3, includesPrivate: true},
  100. user3: {count: 4, includesPrivate: true}},
  101. },
  102. {name: "RepositoriesOwnedByOrganization", requestURL: fmt.Sprintf("/api/v1/repos/search?uid=%d", orgUser.ID), expectedResults: expectedResults{
  103. nil: {count: 1, repoOwnerID: orgUser.ID},
  104. user: {count: 2, repoOwnerID: orgUser.ID, includesPrivate: true},
  105. user2: {count: 1, repoOwnerID: orgUser.ID}},
  106. },
  107. {name: "RepositoriesAccessibleAndRelatedToUser4", requestURL: fmt.Sprintf("/api/v1/repos/search?uid=%d", user4.ID), expectedResults: expectedResults{
  108. nil: {count: 3},
  109. user: {count: 4, includesPrivate: true},
  110. user4: {count: 7, includesPrivate: true}}},
  111. {name: "RepositoriesAccessibleAndRelatedToUser4/SearchModeSource", requestURL: fmt.Sprintf("/api/v1/repos/search?uid=%d&mode=%s", user4.ID, "source"), expectedResults: expectedResults{
  112. nil: {count: 0},
  113. user: {count: 1, includesPrivate: true},
  114. user4: {count: 1, includesPrivate: true}}},
  115. {name: "RepositoriesAccessibleAndRelatedToUser4/SearchModeFork", requestURL: fmt.Sprintf("/api/v1/repos/search?uid=%d&mode=%s", user4.ID, "fork"), expectedResults: expectedResults{
  116. nil: {count: 1},
  117. user: {count: 1},
  118. user4: {count: 2, includesPrivate: true}}},
  119. {name: "RepositoriesAccessibleAndRelatedToUser4/SearchModeFork/Exclusive", requestURL: fmt.Sprintf("/api/v1/repos/search?uid=%d&mode=%s&exclusive=1", user4.ID, "fork"), expectedResults: expectedResults{
  120. nil: {count: 1},
  121. user: {count: 1},
  122. user4: {count: 2, includesPrivate: true}}},
  123. {name: "RepositoriesAccessibleAndRelatedToUser4/SearchModeMirror", requestURL: fmt.Sprintf("/api/v1/repos/search?uid=%d&mode=%s", user4.ID, "mirror"), expectedResults: expectedResults{
  124. nil: {count: 2},
  125. user: {count: 2},
  126. user4: {count: 4, includesPrivate: true}}},
  127. {name: "RepositoriesAccessibleAndRelatedToUser4/SearchModeMirror/Exclusive", requestURL: fmt.Sprintf("/api/v1/repos/search?uid=%d&mode=%s&exclusive=1", user4.ID, "mirror"), expectedResults: expectedResults{
  128. nil: {count: 1},
  129. user: {count: 1},
  130. user4: {count: 2, includesPrivate: true}}},
  131. {name: "RepositoriesAccessibleAndRelatedToUser4/SearchModeCollaborative", requestURL: fmt.Sprintf("/api/v1/repos/search?uid=%d&mode=%s", user4.ID, "collaborative"), expectedResults: expectedResults{
  132. nil: {count: 0},
  133. user: {count: 1, includesPrivate: true},
  134. user4: {count: 1, includesPrivate: true}}},
  135. }
  136. for _, testCase := range testCases {
  137. t.Run(testCase.name, func(t *testing.T) {
  138. for userToLogin, expected := range testCase.expectedResults {
  139. var session *TestSession
  140. var testName string
  141. var userID int64
  142. var token string
  143. if userToLogin != nil && userToLogin.ID > 0 {
  144. testName = fmt.Sprintf("LoggedUser%d", userToLogin.ID)
  145. session = loginUser(t, userToLogin.Name)
  146. token = getTokenForLoggedInUser(t, session)
  147. userID = userToLogin.ID
  148. } else {
  149. testName = "AnonymousUser"
  150. session = emptyTestSession(t)
  151. }
  152. t.Run(testName, func(t *testing.T) {
  153. request := NewRequest(t, "GET", testCase.requestURL+"&token="+token)
  154. response := session.MakeRequest(t, request, http.StatusOK)
  155. var body api.SearchResults
  156. DecodeJSON(t, response, &body)
  157. repoNames := make([]string, 0, len(body.Data))
  158. for _, repo := range body.Data {
  159. repoNames = append(repoNames, fmt.Sprintf("%d:%s:%t", repo.ID, repo.FullName, repo.Private))
  160. }
  161. assert.Len(t, repoNames, expected.count)
  162. for _, repo := range body.Data {
  163. r := getRepo(t, repo.ID)
  164. hasAccess, err := models.HasAccess(userID, r)
  165. assert.NoError(t, err, "Error when checking if User: %d has access to %s: %v", userID, repo.FullName, err)
  166. assert.True(t, hasAccess, "User: %d does not have access to %s", userID, repo.FullName)
  167. assert.NotEmpty(t, repo.Name)
  168. assert.Equal(t, repo.Name, r.Name)
  169. if len(expected.repoName) > 0 {
  170. assert.Contains(t, repo.Name, expected.repoName)
  171. }
  172. if expected.repoOwnerID > 0 {
  173. assert.Equal(t, expected.repoOwnerID, repo.Owner.ID)
  174. }
  175. if !expected.includesPrivate {
  176. assert.False(t, repo.Private, "User: %d not expecting private repository: %s", userID, repo.FullName)
  177. }
  178. }
  179. })
  180. }
  181. })
  182. }
  183. }
  184. var repoCache = make(map[int64]*models.Repository)
  185. func getRepo(t *testing.T, repoID int64) *models.Repository {
  186. if _, ok := repoCache[repoID]; !ok {
  187. repoCache[repoID] = models.AssertExistsAndLoadBean(t, &models.Repository{ID: repoID}).(*models.Repository)
  188. }
  189. return repoCache[repoID]
  190. }
  191. func TestAPIViewRepo(t *testing.T) {
  192. defer prepareTestEnv(t)()
  193. var repo api.Repository
  194. req := NewRequest(t, "GET", "/api/v1/repos/user2/repo1")
  195. resp := MakeRequest(t, req, http.StatusOK)
  196. DecodeJSON(t, resp, &repo)
  197. assert.EqualValues(t, 1, repo.ID)
  198. assert.EqualValues(t, "repo1", repo.Name)
  199. assert.EqualValues(t, 1, repo.Releases)
  200. assert.EqualValues(t, 1, repo.OpenIssues)
  201. assert.EqualValues(t, 3, repo.OpenPulls)
  202. req = NewRequest(t, "GET", "/api/v1/repos/user12/repo10")
  203. resp = MakeRequest(t, req, http.StatusOK)
  204. DecodeJSON(t, resp, &repo)
  205. assert.EqualValues(t, 10, repo.ID)
  206. assert.EqualValues(t, "repo10", repo.Name)
  207. assert.EqualValues(t, 1, repo.OpenPulls)
  208. assert.EqualValues(t, 1, repo.Forks)
  209. req = NewRequest(t, "GET", "/api/v1/repos/user5/repo4")
  210. resp = MakeRequest(t, req, http.StatusOK)
  211. DecodeJSON(t, resp, &repo)
  212. assert.EqualValues(t, 4, repo.ID)
  213. assert.EqualValues(t, "repo4", repo.Name)
  214. assert.EqualValues(t, 1, repo.Stars)
  215. }
  216. func TestAPIOrgRepos(t *testing.T) {
  217. defer prepareTestEnv(t)()
  218. user := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User)
  219. user2 := models.AssertExistsAndLoadBean(t, &models.User{ID: 1}).(*models.User)
  220. user3 := models.AssertExistsAndLoadBean(t, &models.User{ID: 5}).(*models.User)
  221. // User3 is an Org. Check their repos.
  222. sourceOrg := models.AssertExistsAndLoadBean(t, &models.User{ID: 3}).(*models.User)
  223. expectedResults := map[*models.User]struct {
  224. count int
  225. includesPrivate bool
  226. }{
  227. nil: {count: 1},
  228. user: {count: 3, includesPrivate: true},
  229. user2: {count: 3, includesPrivate: true},
  230. user3: {count: 1},
  231. }
  232. for userToLogin, expected := range expectedResults {
  233. var session *TestSession
  234. var testName string
  235. var token string
  236. if userToLogin != nil && userToLogin.ID > 0 {
  237. testName = fmt.Sprintf("LoggedUser%d", userToLogin.ID)
  238. session = loginUser(t, userToLogin.Name)
  239. token = getTokenForLoggedInUser(t, session)
  240. } else {
  241. testName = "AnonymousUser"
  242. session = emptyTestSession(t)
  243. }
  244. t.Run(testName, func(t *testing.T) {
  245. req := NewRequestf(t, "GET", "/api/v1/orgs/%s/repos?token="+token, sourceOrg.Name)
  246. resp := session.MakeRequest(t, req, http.StatusOK)
  247. var apiRepos []*api.Repository
  248. DecodeJSON(t, resp, &apiRepos)
  249. assert.Len(t, apiRepos, expected.count)
  250. for _, repo := range apiRepos {
  251. if !expected.includesPrivate {
  252. assert.False(t, repo.Private)
  253. }
  254. }
  255. })
  256. }
  257. }
  258. func TestAPIGetRepoByIDUnauthorized(t *testing.T) {
  259. defer prepareTestEnv(t)()
  260. user := models.AssertExistsAndLoadBean(t, &models.User{ID: 4}).(*models.User)
  261. session := loginUser(t, user.Name)
  262. token := getTokenForLoggedInUser(t, session)
  263. req := NewRequestf(t, "GET", "/api/v1/repositories/2?token="+token)
  264. session.MakeRequest(t, req, http.StatusNotFound)
  265. }
  266. func TestAPIRepoMigrate(t *testing.T) {
  267. testCases := []struct {
  268. ctxUserID, userID int64
  269. cloneURL, repoName string
  270. expectedStatus int
  271. }{
  272. {ctxUserID: 1, userID: 2, cloneURL: "https://github.com/go-gitea/test_repo.git", repoName: "git-admin", expectedStatus: http.StatusCreated},
  273. {ctxUserID: 2, userID: 2, cloneURL: "https://github.com/go-gitea/test_repo.git", repoName: "git-own", expectedStatus: http.StatusCreated},
  274. {ctxUserID: 2, userID: 1, cloneURL: "https://github.com/go-gitea/test_repo.git", repoName: "git-bad", expectedStatus: http.StatusForbidden},
  275. {ctxUserID: 2, userID: 3, cloneURL: "https://github.com/go-gitea/test_repo.git", repoName: "git-org", expectedStatus: http.StatusCreated},
  276. {ctxUserID: 2, userID: 6, cloneURL: "https://github.com/go-gitea/test_repo.git", repoName: "git-bad-org", expectedStatus: http.StatusForbidden},
  277. }
  278. defer prepareTestEnv(t)()
  279. for _, testCase := range testCases {
  280. user := models.AssertExistsAndLoadBean(t, &models.User{ID: testCase.ctxUserID}).(*models.User)
  281. session := loginUser(t, user.Name)
  282. token := getTokenForLoggedInUser(t, session)
  283. req := NewRequestWithJSON(t, "POST", "/api/v1/repos/migrate?token="+token, &api.MigrateRepoOptions{
  284. CloneAddr: testCase.cloneURL,
  285. RepoOwnerID: testCase.userID,
  286. RepoName: testCase.repoName,
  287. })
  288. resp := MakeRequest(t, req, NoExpectedStatus)
  289. if resp.Code == http.StatusUnprocessableEntity {
  290. respJSON := map[string]string{}
  291. DecodeJSON(t, resp, &respJSON)
  292. if assert.Equal(t, respJSON["message"], "Remote visit addressed rate limitation.") {
  293. t.Log("test hit github rate limitation")
  294. }
  295. } else {
  296. assert.EqualValues(t, testCase.expectedStatus, resp.Code)
  297. }
  298. }
  299. }
  300. func TestAPIRepoMigrateConflict(t *testing.T) {
  301. onGiteaRun(t, testAPIRepoMigrateConflict)
  302. }
  303. func testAPIRepoMigrateConflict(t *testing.T, u *url.URL) {
  304. username := "user2"
  305. baseAPITestContext := NewAPITestContext(t, username, "repo1")
  306. u.Path = baseAPITestContext.GitPath()
  307. t.Run("Existing", func(t *testing.T) {
  308. httpContext := baseAPITestContext
  309. httpContext.Reponame = "repo-tmp-17"
  310. dstPath, err := ioutil.TempDir("", httpContext.Reponame)
  311. assert.NoError(t, err)
  312. defer util.RemoveAll(dstPath)
  313. t.Run("CreateRepo", doAPICreateRepository(httpContext, false))
  314. user, err := models.GetUserByName(httpContext.Username)
  315. assert.NoError(t, err)
  316. userID := user.ID
  317. cloneURL := "https://github.com/go-gitea/test_repo.git"
  318. req := NewRequestWithJSON(t, "POST", "/api/v1/repos/migrate?token="+httpContext.Token,
  319. &api.MigrateRepoOptions{
  320. CloneAddr: cloneURL,
  321. RepoOwnerID: userID,
  322. RepoName: httpContext.Reponame,
  323. })
  324. resp := httpContext.Session.MakeRequest(t, req, http.StatusConflict)
  325. respJSON := map[string]string{}
  326. DecodeJSON(t, resp, &respJSON)
  327. assert.Equal(t, "The repository with the same name already exists.", respJSON["message"])
  328. })
  329. }
  330. func TestAPIOrgRepoCreate(t *testing.T) {
  331. testCases := []struct {
  332. ctxUserID int64
  333. orgName, repoName string
  334. expectedStatus int
  335. }{
  336. {ctxUserID: 1, orgName: "user3", repoName: "repo-admin", expectedStatus: http.StatusCreated},
  337. {ctxUserID: 2, orgName: "user3", repoName: "repo-own", expectedStatus: http.StatusCreated},
  338. {ctxUserID: 2, orgName: "user6", repoName: "repo-bad-org", expectedStatus: http.StatusForbidden},
  339. {ctxUserID: 28, orgName: "user3", repoName: "repo-creator", expectedStatus: http.StatusCreated},
  340. {ctxUserID: 28, orgName: "user6", repoName: "repo-not-creator", expectedStatus: http.StatusForbidden},
  341. }
  342. defer prepareTestEnv(t)()
  343. for _, testCase := range testCases {
  344. user := models.AssertExistsAndLoadBean(t, &models.User{ID: testCase.ctxUserID}).(*models.User)
  345. session := loginUser(t, user.Name)
  346. token := getTokenForLoggedInUser(t, session)
  347. req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/org/%s/repos?token="+token, testCase.orgName), &api.CreateRepoOption{
  348. Name: testCase.repoName,
  349. })
  350. session.MakeRequest(t, req, testCase.expectedStatus)
  351. }
  352. }
  353. func TestAPIRepoCreateConflict(t *testing.T) {
  354. onGiteaRun(t, testAPIRepoCreateConflict)
  355. }
  356. func testAPIRepoCreateConflict(t *testing.T, u *url.URL) {
  357. username := "user2"
  358. baseAPITestContext := NewAPITestContext(t, username, "repo1")
  359. u.Path = baseAPITestContext.GitPath()
  360. t.Run("Existing", func(t *testing.T) {
  361. httpContext := baseAPITestContext
  362. httpContext.Reponame = "repo-tmp-17"
  363. dstPath, err := ioutil.TempDir("", httpContext.Reponame)
  364. assert.NoError(t, err)
  365. defer util.RemoveAll(dstPath)
  366. t.Run("CreateRepo", doAPICreateRepository(httpContext, false))
  367. req := NewRequestWithJSON(t, "POST", "/api/v1/user/repos?token="+httpContext.Token,
  368. &api.CreateRepoOption{
  369. Name: httpContext.Reponame,
  370. })
  371. resp := httpContext.Session.MakeRequest(t, req, http.StatusConflict)
  372. respJSON := map[string]string{}
  373. DecodeJSON(t, resp, &respJSON)
  374. assert.Equal(t, respJSON["message"], "The repository with the same name already exists.")
  375. })
  376. }
  377. func TestAPIRepoTransfer(t *testing.T) {
  378. testCases := []struct {
  379. ctxUserID int64
  380. newOwner string
  381. teams *[]int64
  382. expectedStatus int
  383. }{
  384. {ctxUserID: 1, newOwner: "user2", teams: nil, expectedStatus: http.StatusAccepted},
  385. {ctxUserID: 2, newOwner: "user1", teams: nil, expectedStatus: http.StatusAccepted},
  386. {ctxUserID: 2, newOwner: "user6", teams: nil, expectedStatus: http.StatusForbidden},
  387. {ctxUserID: 1, newOwner: "user2", teams: &[]int64{2}, expectedStatus: http.StatusUnprocessableEntity},
  388. {ctxUserID: 1, newOwner: "user3", teams: &[]int64{5}, expectedStatus: http.StatusForbidden},
  389. {ctxUserID: 1, newOwner: "user3", teams: &[]int64{2}, expectedStatus: http.StatusAccepted},
  390. }
  391. defer prepareTestEnv(t)()
  392. //create repo to move
  393. user := models.AssertExistsAndLoadBean(t, &models.User{ID: 1}).(*models.User)
  394. session := loginUser(t, user.Name)
  395. token := getTokenForLoggedInUser(t, session)
  396. repoName := "moveME"
  397. repo := new(models.Repository)
  398. req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/user/repos?token=%s", token), &api.CreateRepoOption{
  399. Name: repoName,
  400. Description: "repo move around",
  401. Private: false,
  402. Readme: "Default",
  403. AutoInit: true,
  404. })
  405. resp := session.MakeRequest(t, req, http.StatusCreated)
  406. DecodeJSON(t, resp, repo)
  407. //start testing
  408. for _, testCase := range testCases {
  409. user = models.AssertExistsAndLoadBean(t, &models.User{ID: testCase.ctxUserID}).(*models.User)
  410. repo = models.AssertExistsAndLoadBean(t, &models.Repository{ID: repo.ID}).(*models.Repository)
  411. session = loginUser(t, user.Name)
  412. token = getTokenForLoggedInUser(t, session)
  413. req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/transfer?token=%s", repo.OwnerName, repo.Name, token), &api.TransferRepoOption{
  414. NewOwner: testCase.newOwner,
  415. TeamIDs: testCase.teams,
  416. })
  417. session.MakeRequest(t, req, testCase.expectedStatus)
  418. }
  419. //cleanup
  420. repo = models.AssertExistsAndLoadBean(t, &models.Repository{ID: repo.ID}).(*models.Repository)
  421. _ = models.DeleteRepository(user, repo.OwnerID, repo.ID)
  422. }