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

repo.go 6.6 kB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  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. "github.com/gogits/gogs/models"
  11. "github.com/gogits/gogs/modules/auth"
  12. "github.com/gogits/gogs/modules/log"
  13. "github.com/gogits/gogs/modules/middleware"
  14. "github.com/gogits/gogs/modules/setting"
  15. )
  16. type ApiPermission struct {
  17. Admin bool `json:"admin"`
  18. Push bool `json:"push"`
  19. Pull bool `json:"pull"`
  20. }
  21. type ApiRepository struct {
  22. Id int64 `json:"id"`
  23. Owner ApiUser `json:"owner"`
  24. FullName string `json:"full_name"`
  25. Private bool `json:"private"`
  26. Fork bool `json:"fork"`
  27. HtmlUrl string `json:"html_url"`
  28. CloneUrl string `json:"clone_url"`
  29. SshUrl string `json:"ssh_url"`
  30. Permissions ApiPermission `json:"permissions"`
  31. }
  32. func SearchRepos(ctx *middleware.Context) {
  33. opt := models.SearchOption{
  34. Keyword: path.Base(ctx.Query("q")),
  35. Uid: com.StrTo(ctx.Query("uid")).MustInt64(),
  36. Limit: com.StrTo(ctx.Query("limit")).MustInt(),
  37. }
  38. if opt.Limit == 0 {
  39. opt.Limit = 10
  40. }
  41. // Check visibility.
  42. if ctx.IsSigned && opt.Uid > 0 {
  43. if ctx.User.Id == opt.Uid {
  44. opt.Private = true
  45. } else {
  46. u, err := models.GetUserById(opt.Uid)
  47. if err != nil {
  48. ctx.JSON(500, map[string]interface{}{
  49. "ok": false,
  50. "error": err.Error(),
  51. })
  52. return
  53. }
  54. if u.IsOrganization() && u.IsOrgOwner(ctx.User.Id) {
  55. opt.Private = true
  56. }
  57. // FIXME: how about collaborators?
  58. }
  59. }
  60. repos, err := models.SearchRepositoryByName(opt)
  61. if err != nil {
  62. ctx.JSON(500, map[string]interface{}{
  63. "ok": false,
  64. "error": err.Error(),
  65. })
  66. return
  67. }
  68. results := make([]*ApiRepository, len(repos))
  69. for i := range repos {
  70. if err = repos[i].GetOwner(); err != nil {
  71. ctx.JSON(500, map[string]interface{}{
  72. "ok": false,
  73. "error": err.Error(),
  74. })
  75. return
  76. }
  77. results[i] = &ApiRepository{
  78. Id: repos[i].Id,
  79. FullName: path.Join(repos[i].Owner.Name, repos[i].Name),
  80. }
  81. }
  82. ctx.Render.JSON(200, map[string]interface{}{
  83. "ok": true,
  84. "data": results,
  85. })
  86. }
  87. func Migrate(ctx *middleware.Context, form auth.MigrateRepoForm) {
  88. u, err := models.GetUserByName(ctx.Query("username"))
  89. if err != nil {
  90. ctx.JSON(500, map[string]interface{}{
  91. "ok": false,
  92. "error": err.Error(),
  93. })
  94. return
  95. }
  96. if !u.ValidtePassword(ctx.Query("password")) {
  97. ctx.JSON(500, map[string]interface{}{
  98. "ok": false,
  99. "error": "username or password is not correct",
  100. })
  101. return
  102. }
  103. ctxUser := u
  104. // Not equal means current user is an organization.
  105. if form.Uid != u.Id {
  106. org, err := models.GetUserById(form.Uid)
  107. if err != nil {
  108. ctx.JSON(500, map[string]interface{}{
  109. "ok": false,
  110. "error": err.Error(),
  111. })
  112. return
  113. }
  114. ctxUser = org
  115. }
  116. if ctx.HasError() {
  117. ctx.JSON(500, map[string]interface{}{
  118. "ok": false,
  119. "error": ctx.GetErrMsg(),
  120. })
  121. return
  122. }
  123. if ctxUser.IsOrganization() {
  124. // Check ownership of organization.
  125. if !ctxUser.IsOrgOwner(u.Id) {
  126. ctx.JSON(403, map[string]interface{}{
  127. "ok": false,
  128. "error": "given user is not owner of organization",
  129. })
  130. return
  131. }
  132. }
  133. authStr := strings.Replace(fmt.Sprintf("://%s:%s",
  134. form.AuthUserName, form.AuthPasswd), "@", "%40", -1)
  135. url := strings.Replace(form.HttpsUrl, "://", authStr+"@", 1)
  136. repo, err := models.MigrateRepository(ctxUser, form.RepoName, form.Description, form.Private,
  137. form.Mirror, url)
  138. if err == nil {
  139. log.Trace("Repository migrated: %s/%s", ctxUser.Name, form.RepoName)
  140. ctx.JSON(200, map[string]interface{}{
  141. "ok": true,
  142. "data": "/" + ctxUser.Name + "/" + form.RepoName,
  143. })
  144. return
  145. }
  146. if repo != nil {
  147. if errDelete := models.DeleteRepository(ctxUser.Id, repo.Id, ctxUser.Name); errDelete != nil {
  148. log.Error(4, "DeleteRepository: %v", errDelete)
  149. }
  150. }
  151. ctx.JSON(500, map[string]interface{}{
  152. "ok": false,
  153. "error": err.Error(),
  154. })
  155. }
  156. // /user/repos: https://developer.github.com/v3/repos/#list-your-repositories
  157. func ListMyRepos(ctx *middleware.Context) {
  158. if !ctx.IsSigned {
  159. ctx.Error(403)
  160. return
  161. }
  162. ownRepos, err := models.GetRepositories(ctx.User.Id, true)
  163. if err != nil {
  164. ctx.JSON(500, map[string]interface{}{
  165. "ok": false,
  166. "error": err.Error(),
  167. })
  168. return
  169. }
  170. numOwnRepos := len(ownRepos)
  171. collaRepos, err := models.GetCollaborativeRepos(ctx.User.Name)
  172. if err != nil {
  173. ctx.JSON(500, map[string]interface{}{
  174. "ok": false,
  175. "error": err.Error(),
  176. })
  177. return
  178. }
  179. sshUrlFmt := "%s@%s:%s/%s.git"
  180. if setting.SshPort != 22 {
  181. sshUrlFmt = "ssh://%s@%s:%d/%s/%s.git"
  182. }
  183. repos := make([]*ApiRepository, numOwnRepos+len(collaRepos))
  184. // FIXME: make only one loop
  185. for i := range ownRepos {
  186. repos[i] = &ApiRepository{
  187. Id: ownRepos[i].Id,
  188. Owner: ApiUser{
  189. Id: ctx.User.Id,
  190. UserName: ctx.User.Name,
  191. AvatarUrl: string(setting.Protocol) + ctx.User.AvatarLink(),
  192. },
  193. FullName: ctx.User.Name + "/" + ownRepos[i].Name,
  194. Private: ownRepos[i].IsPrivate,
  195. Fork: ownRepos[i].IsFork,
  196. HtmlUrl: setting.AppUrl + ctx.User.Name + "/" + ownRepos[i].Name,
  197. SshUrl: fmt.Sprintf(sshUrlFmt, setting.RunUser, setting.Domain, ctx.User.LowerName, ownRepos[i].LowerName),
  198. Permissions: ApiPermission{true, true, true},
  199. }
  200. repos[i].CloneUrl = repos[i].HtmlUrl + ".git"
  201. }
  202. for i := range collaRepos {
  203. if err = collaRepos[i].GetOwner(); err != nil {
  204. ctx.JSON(500, map[string]interface{}{
  205. "ok": false,
  206. "error": err.Error(),
  207. })
  208. return
  209. }
  210. j := i + numOwnRepos
  211. repos[j] = &ApiRepository{
  212. Id: collaRepos[i].Id,
  213. Owner: ApiUser{
  214. Id: collaRepos[i].Owner.Id,
  215. UserName: collaRepos[i].Owner.Name,
  216. AvatarUrl: string(setting.Protocol) + collaRepos[i].Owner.AvatarLink(),
  217. },
  218. FullName: collaRepos[i].Owner.Name + "/" + collaRepos[i].Name,
  219. Private: collaRepos[i].IsPrivate,
  220. Fork: collaRepos[i].IsFork,
  221. HtmlUrl: setting.AppUrl + collaRepos[i].Owner.Name + "/" + collaRepos[i].Name,
  222. SshUrl: fmt.Sprintf(sshUrlFmt, setting.RunUser, setting.Domain, collaRepos[i].Owner.LowerName, collaRepos[i].LowerName),
  223. Permissions: ApiPermission{false, collaRepos[i].CanPush, true},
  224. }
  225. repos[j].CloneUrl = repos[j].HtmlUrl + ".git"
  226. // FIXME: cache result to reduce DB query?
  227. if collaRepos[i].Owner.IsOrganization() && collaRepos[i].Owner.IsOrgOwner(ctx.User.Id) {
  228. repos[j].Permissions.Admin = true
  229. }
  230. }
  231. ctx.JSON(200, &repos)
  232. }