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.

265 lines
6.7 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. // Copyright 2014 The Gogs 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 v1
  5. import (
  6. "fmt"
  7. "path"
  8. "strings"
  9. "github.com/Unknwon/com"
  10. api "github.com/gogits/go-gogs-client"
  11. "github.com/gogits/gogs/models"
  12. "github.com/gogits/gogs/modules/auth"
  13. "github.com/gogits/gogs/modules/base"
  14. "github.com/gogits/gogs/modules/log"
  15. "github.com/gogits/gogs/modules/middleware"
  16. "github.com/gogits/gogs/modules/setting"
  17. )
  18. // ToApiRepository converts repository to API format.
  19. func ToApiRepository(owner *models.User, repo *models.Repository, permission api.Permission) *api.Repository {
  20. cl, err := repo.CloneLink()
  21. if err != nil {
  22. log.Error(4, "CloneLink: %v", err)
  23. }
  24. return &api.Repository{
  25. Id: repo.Id,
  26. Owner: *ToApiUser(owner),
  27. FullName: owner.Name + "/" + repo.Name,
  28. Private: repo.IsPrivate,
  29. Fork: repo.IsFork,
  30. HtmlUrl: setting.AppUrl + owner.Name + "/" + repo.Name,
  31. CloneUrl: cl.HTTPS,
  32. SshUrl: cl.SSH,
  33. Permissions: permission,
  34. }
  35. }
  36. func SearchRepos(ctx *middleware.Context) {
  37. opt := models.SearchOption{
  38. Keyword: path.Base(ctx.Query("q")),
  39. Uid: com.StrTo(ctx.Query("uid")).MustInt64(),
  40. Limit: com.StrTo(ctx.Query("limit")).MustInt(),
  41. }
  42. if opt.Limit == 0 {
  43. opt.Limit = 10
  44. }
  45. // Check visibility.
  46. if ctx.IsSigned && opt.Uid > 0 {
  47. if ctx.User.Id == opt.Uid {
  48. opt.Private = true
  49. } else {
  50. u, err := models.GetUserById(opt.Uid)
  51. if err != nil {
  52. ctx.JSON(500, map[string]interface{}{
  53. "ok": false,
  54. "error": err.Error(),
  55. })
  56. return
  57. }
  58. if u.IsOrganization() && u.IsOwnedBy(ctx.User.Id) {
  59. opt.Private = true
  60. }
  61. // FIXME: how about collaborators?
  62. }
  63. }
  64. repos, err := models.SearchRepositoryByName(opt)
  65. if err != nil {
  66. ctx.JSON(500, map[string]interface{}{
  67. "ok": false,
  68. "error": err.Error(),
  69. })
  70. return
  71. }
  72. results := make([]*api.Repository, len(repos))
  73. for i := range repos {
  74. if err = repos[i].GetOwner(); err != nil {
  75. ctx.JSON(500, map[string]interface{}{
  76. "ok": false,
  77. "error": err.Error(),
  78. })
  79. return
  80. }
  81. results[i] = &api.Repository{
  82. Id: repos[i].Id,
  83. FullName: path.Join(repos[i].Owner.Name, repos[i].Name),
  84. }
  85. }
  86. ctx.JSON(200, map[string]interface{}{
  87. "ok": true,
  88. "data": results,
  89. })
  90. }
  91. func createRepo(ctx *middleware.Context, owner *models.User, opt api.CreateRepoOption) {
  92. repo, err := models.CreateRepository(owner, opt.Name, opt.Description,
  93. opt.Gitignore, opt.License, opt.Private, false, opt.AutoInit)
  94. if err != nil {
  95. if err == models.ErrRepoAlreadyExist ||
  96. err == models.ErrRepoNameIllegal {
  97. ctx.JSON(422, &base.ApiJsonErr{err.Error(), base.DOC_URL})
  98. } else {
  99. log.Error(4, "CreateRepository: %v", err)
  100. if repo != nil {
  101. if err = models.DeleteRepository(ctx.User.Id, repo.Id, ctx.User.Name); err != nil {
  102. log.Error(4, "DeleteRepository: %v", err)
  103. }
  104. }
  105. ctx.Error(500)
  106. }
  107. return
  108. }
  109. ctx.JSON(200, ToApiRepository(owner, repo, api.Permission{true, true, true}))
  110. }
  111. // POST /user/repos
  112. // https://developer.github.com/v3/repos/#create
  113. func CreateRepo(ctx *middleware.Context, opt api.CreateRepoOption) {
  114. // Shouldn't reach this condition, but just in case.
  115. if ctx.User.IsOrganization() {
  116. ctx.JSON(422, "not allowed creating repository for organization")
  117. return
  118. }
  119. createRepo(ctx, ctx.User, opt)
  120. }
  121. // POST /orgs/:org/repos
  122. // https://developer.github.com/v3/repos/#create
  123. func CreateOrgRepo(ctx *middleware.Context, opt api.CreateRepoOption) {
  124. org, err := models.GetOrgByName(ctx.Params(":org"))
  125. if err != nil {
  126. if err == models.ErrUserNotExist {
  127. ctx.Error(404)
  128. } else {
  129. ctx.Error(500)
  130. }
  131. return
  132. }
  133. if !org.IsOwnedBy(ctx.User.Id) {
  134. ctx.Error(403)
  135. return
  136. }
  137. createRepo(ctx, org, opt)
  138. }
  139. func MigrateRepo(ctx *middleware.Context, form auth.MigrateRepoForm) {
  140. u, err := models.GetUserByName(ctx.Query("username"))
  141. if err != nil {
  142. ctx.JSON(500, map[string]interface{}{
  143. "ok": false,
  144. "error": err.Error(),
  145. })
  146. return
  147. }
  148. if !u.ValidtePassword(ctx.Query("password")) {
  149. ctx.JSON(500, map[string]interface{}{
  150. "ok": false,
  151. "error": "username or password is not correct",
  152. })
  153. return
  154. }
  155. ctxUser := u
  156. // Not equal means current user is an organization.
  157. if form.Uid != u.Id {
  158. org, err := models.GetUserById(form.Uid)
  159. if err != nil {
  160. log.Error(4, "GetUserById: %v", err)
  161. ctx.Error(500)
  162. return
  163. }
  164. ctxUser = org
  165. }
  166. if ctx.HasError() {
  167. ctx.JSON(422, map[string]interface{}{
  168. "ok": false,
  169. "error": ctx.GetErrMsg(),
  170. })
  171. return
  172. }
  173. if ctxUser.IsOrganization() {
  174. // Check ownership of organization.
  175. if !ctxUser.IsOwnedBy(u.Id) {
  176. ctx.JSON(403, map[string]interface{}{
  177. "ok": false,
  178. "error": "given user is not owner of organization",
  179. })
  180. return
  181. }
  182. }
  183. authStr := strings.Replace(fmt.Sprintf("://%s:%s",
  184. form.AuthUserName, form.AuthPasswd), "@", "%40", -1)
  185. url := strings.Replace(form.HttpsUrl, "://", authStr+"@", 1)
  186. repo, err := models.MigrateRepository(ctxUser, form.RepoName, form.Description, form.Private,
  187. form.Mirror, url)
  188. if err == nil {
  189. log.Trace("Repository migrated: %s/%s", ctxUser.Name, form.RepoName)
  190. ctx.JSON(200, map[string]interface{}{
  191. "ok": true,
  192. "data": "/" + ctxUser.Name + "/" + form.RepoName,
  193. })
  194. return
  195. }
  196. if repo != nil {
  197. if errDelete := models.DeleteRepository(ctxUser.Id, repo.Id, ctxUser.Name); errDelete != nil {
  198. log.Error(4, "DeleteRepository: %v", errDelete)
  199. }
  200. }
  201. ctx.JSON(500, map[string]interface{}{
  202. "ok": false,
  203. "error": err.Error(),
  204. })
  205. }
  206. // GET /user/repos
  207. // https://developer.github.com/v3/repos/#list-your-repositories
  208. func ListMyRepos(ctx *middleware.Context) {
  209. ownRepos, err := models.GetRepositories(ctx.User.Id, true)
  210. if err != nil {
  211. ctx.JSON(500, &base.ApiJsonErr{"GetRepositories: " + err.Error(), base.DOC_URL})
  212. return
  213. }
  214. numOwnRepos := len(ownRepos)
  215. collaRepos, err := models.GetCollaborativeRepos(ctx.User.Name)
  216. if err != nil {
  217. ctx.JSON(500, &base.ApiJsonErr{"GetCollaborativeRepos: " + err.Error(), base.DOC_URL})
  218. return
  219. }
  220. repos := make([]*api.Repository, numOwnRepos+len(collaRepos))
  221. for i := range ownRepos {
  222. repos[i] = ToApiRepository(ctx.User, ownRepos[i], api.Permission{true, true, true})
  223. }
  224. for i := range collaRepos {
  225. if err = collaRepos[i].GetOwner(); err != nil {
  226. ctx.JSON(500, &base.ApiJsonErr{"GetOwner: " + err.Error(), base.DOC_URL})
  227. return
  228. }
  229. j := i + numOwnRepos
  230. repos[j] = ToApiRepository(collaRepos[i].Owner, collaRepos[i].Repository, api.Permission{false, collaRepos[i].CanPush, true})
  231. // FIXME: cache result to reduce DB query?
  232. if collaRepos[i].Owner.IsOrganization() && collaRepos[i].Owner.IsOwnedBy(ctx.User.Id) {
  233. repos[j].Permissions.Admin = true
  234. }
  235. }
  236. ctx.JSON(200, &repos)
  237. }