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.

profile.go 6.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. // Copyright 2015 The Gogs Authors. All rights reserved.
  2. // Copyright 2019 The Gitea Authors. All rights reserved.
  3. // Use of this source code is governed by a MIT-style
  4. // license that can be found in the LICENSE file.
  5. package user
  6. import (
  7. "fmt"
  8. "path"
  9. "strings"
  10. "code.gitea.io/gitea/models"
  11. "code.gitea.io/gitea/modules/base"
  12. "code.gitea.io/gitea/modules/context"
  13. "code.gitea.io/gitea/modules/setting"
  14. "code.gitea.io/gitea/modules/util"
  15. "code.gitea.io/gitea/routers/repo"
  16. )
  17. const (
  18. tplFollowers base.TplName = "user/meta/followers"
  19. )
  20. // GetUserByName get user by name
  21. func GetUserByName(ctx *context.Context, name string) *models.User {
  22. user, err := models.GetUserByName(name)
  23. if err != nil {
  24. if models.IsErrUserNotExist(err) {
  25. ctx.NotFound("GetUserByName", nil)
  26. } else {
  27. ctx.ServerError("GetUserByName", err)
  28. }
  29. return nil
  30. }
  31. return user
  32. }
  33. // GetUserByParams returns user whose name is presented in URL paramenter.
  34. func GetUserByParams(ctx *context.Context) *models.User {
  35. return GetUserByName(ctx, ctx.Params(":username"))
  36. }
  37. // Profile render user's profile page
  38. func Profile(ctx *context.Context) {
  39. uname := ctx.Params(":username")
  40. // Special handle for FireFox requests favicon.ico.
  41. if uname == "favicon.ico" {
  42. ctx.ServeFile(path.Join(setting.StaticRootPath, "public/img/favicon.png"))
  43. return
  44. } else if strings.HasSuffix(uname, ".png") {
  45. ctx.Error(404)
  46. return
  47. }
  48. isShowKeys := false
  49. if strings.HasSuffix(uname, ".keys") {
  50. isShowKeys = true
  51. uname = strings.TrimSuffix(uname, ".keys")
  52. }
  53. isShowGPG := false
  54. if strings.HasSuffix(uname, ".gpg") {
  55. isShowGPG = true
  56. uname = strings.TrimSuffix(uname, ".gpg")
  57. }
  58. ctxUser := GetUserByName(ctx, uname)
  59. if ctx.Written() {
  60. return
  61. }
  62. // Show SSH keys.
  63. if isShowKeys {
  64. ShowSSHKeys(ctx, ctxUser.ID)
  65. return
  66. }
  67. // Show GPG keys.
  68. if isShowGPG {
  69. ShowGPGKeys(ctx, ctxUser.ID)
  70. return
  71. }
  72. if ctxUser.IsOrganization() {
  73. showOrgProfile(ctx)
  74. return
  75. }
  76. // Show OpenID URIs
  77. openIDs, err := models.GetUserOpenIDs(ctxUser.ID)
  78. if err != nil {
  79. ctx.ServerError("GetUserOpenIDs", err)
  80. return
  81. }
  82. ctx.Data["Title"] = ctxUser.DisplayName()
  83. ctx.Data["PageIsUserProfile"] = true
  84. ctx.Data["Owner"] = ctxUser
  85. ctx.Data["OpenIDs"] = openIDs
  86. ctx.Data["EnableHeatmap"] = setting.Service.EnableUserHeatmap
  87. ctx.Data["HeatmapUser"] = ctxUser.Name
  88. showPrivate := ctx.IsSigned && (ctx.User.IsAdmin || ctx.User.ID == ctxUser.ID)
  89. orgs, err := models.GetOrgsByUserID(ctxUser.ID, showPrivate)
  90. if err != nil {
  91. ctx.ServerError("GetOrgsByUserIDDesc", err)
  92. return
  93. }
  94. ctx.Data["Orgs"] = orgs
  95. ctx.Data["HasOrgsVisible"] = models.HasOrgsVisible(orgs, ctx.User)
  96. tab := ctx.Query("tab")
  97. ctx.Data["TabName"] = tab
  98. page := ctx.QueryInt("page")
  99. if page <= 0 {
  100. page = 1
  101. }
  102. topicOnly := ctx.QueryBool("topic")
  103. var (
  104. repos []*models.Repository
  105. count int64
  106. total int
  107. orderBy models.SearchOrderBy
  108. )
  109. ctx.Data["SortType"] = ctx.Query("sort")
  110. switch ctx.Query("sort") {
  111. case "newest":
  112. orderBy = models.SearchOrderByNewest
  113. case "oldest":
  114. orderBy = models.SearchOrderByOldest
  115. case "recentupdate":
  116. orderBy = models.SearchOrderByRecentUpdated
  117. case "leastupdate":
  118. orderBy = models.SearchOrderByLeastUpdated
  119. case "reversealphabetically":
  120. orderBy = models.SearchOrderByAlphabeticallyReverse
  121. case "alphabetically":
  122. orderBy = models.SearchOrderByAlphabetically
  123. case "moststars":
  124. orderBy = models.SearchOrderByStarsReverse
  125. case "feweststars":
  126. orderBy = models.SearchOrderByStars
  127. case "mostforks":
  128. orderBy = models.SearchOrderByForksReverse
  129. case "fewestforks":
  130. orderBy = models.SearchOrderByForks
  131. default:
  132. ctx.Data["SortType"] = "recentupdate"
  133. orderBy = models.SearchOrderByRecentUpdated
  134. }
  135. keyword := strings.Trim(ctx.Query("q"), " ")
  136. ctx.Data["Keyword"] = keyword
  137. switch tab {
  138. case "activity":
  139. retrieveFeeds(ctx, models.GetFeedsOptions{RequestedUser: ctxUser,
  140. IncludePrivate: showPrivate,
  141. OnlyPerformedBy: true,
  142. IncludeDeleted: false,
  143. })
  144. if ctx.Written() {
  145. return
  146. }
  147. case "stars":
  148. ctx.Data["PageIsProfileStarList"] = true
  149. repos, count, err = models.SearchRepositoryByName(&models.SearchRepoOptions{
  150. Keyword: keyword,
  151. OrderBy: orderBy,
  152. Private: ctx.IsSigned,
  153. UserIsAdmin: ctx.IsUserSiteAdmin(),
  154. UserID: ctx.Data["SignedUserID"].(int64),
  155. Page: page,
  156. PageSize: setting.UI.User.RepoPagingNum,
  157. StarredByID: ctxUser.ID,
  158. Collaborate: util.OptionalBoolFalse,
  159. TopicOnly: topicOnly,
  160. })
  161. if err != nil {
  162. ctx.ServerError("SearchRepositoryByName", err)
  163. return
  164. }
  165. total = int(count)
  166. default:
  167. repos, count, err = models.SearchRepositoryByName(&models.SearchRepoOptions{
  168. Keyword: keyword,
  169. OwnerID: ctxUser.ID,
  170. OrderBy: orderBy,
  171. Private: ctx.IsSigned,
  172. UserIsAdmin: ctx.IsUserSiteAdmin(),
  173. UserID: ctx.Data["SignedUserID"].(int64),
  174. Page: page,
  175. IsProfile: true,
  176. PageSize: setting.UI.User.RepoPagingNum,
  177. Collaborate: util.OptionalBoolFalse,
  178. TopicOnly: topicOnly,
  179. })
  180. if err != nil {
  181. ctx.ServerError("SearchRepositoryByName", err)
  182. return
  183. }
  184. total = int(count)
  185. }
  186. ctx.Data["Repos"] = repos
  187. ctx.Data["Total"] = total
  188. pager := context.NewPagination(total, setting.UI.User.RepoPagingNum, page, 5)
  189. pager.SetDefaultParams(ctx)
  190. ctx.Data["Page"] = pager
  191. ctx.Data["ShowUserEmail"] = len(ctxUser.Email) > 0 && ctx.IsSigned && (!ctxUser.KeepEmailPrivate || ctxUser.ID == ctx.User.ID)
  192. ctx.HTML(200, tplProfile)
  193. }
  194. // Followers render user's followers page
  195. func Followers(ctx *context.Context) {
  196. u := GetUserByParams(ctx)
  197. if ctx.Written() {
  198. return
  199. }
  200. ctx.Data["Title"] = u.DisplayName()
  201. ctx.Data["CardsTitle"] = ctx.Tr("user.followers")
  202. ctx.Data["PageIsFollowers"] = true
  203. ctx.Data["Owner"] = u
  204. repo.RenderUserCards(ctx, u.NumFollowers, u.GetFollowers, tplFollowers)
  205. }
  206. // Following render user's followering page
  207. func Following(ctx *context.Context) {
  208. u := GetUserByParams(ctx)
  209. if ctx.Written() {
  210. return
  211. }
  212. ctx.Data["Title"] = u.DisplayName()
  213. ctx.Data["CardsTitle"] = ctx.Tr("user.following")
  214. ctx.Data["PageIsFollowing"] = true
  215. ctx.Data["Owner"] = u
  216. repo.RenderUserCards(ctx, u.NumFollowing, u.GetFollowing, tplFollowers)
  217. }
  218. // Action response for follow/unfollow user request
  219. func Action(ctx *context.Context) {
  220. u := GetUserByParams(ctx)
  221. if ctx.Written() {
  222. return
  223. }
  224. var err error
  225. switch ctx.Params(":action") {
  226. case "follow":
  227. err = models.FollowUser(ctx.User.ID, u.ID)
  228. case "unfollow":
  229. err = models.UnfollowUser(ctx.User.ID, u.ID)
  230. }
  231. if err != nil {
  232. ctx.ServerError(fmt.Sprintf("Action (%s)", ctx.Params(":action")), err)
  233. return
  234. }
  235. ctx.RedirectToFirst(ctx.Query("redirect_to"), u.HomeLink())
  236. }