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.

user.go 11 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
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
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
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
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
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
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  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 user
  5. import (
  6. "fmt"
  7. "net/url"
  8. "strings"
  9. "github.com/codegangsta/martini"
  10. "github.com/gogits/gogs/models"
  11. "github.com/gogits/gogs/modules/auth"
  12. "github.com/gogits/gogs/modules/base"
  13. "github.com/gogits/gogs/modules/log"
  14. "github.com/gogits/gogs/modules/mailer"
  15. "github.com/gogits/gogs/modules/middleware"
  16. )
  17. func Dashboard(ctx *middleware.Context) {
  18. ctx.Data["Title"] = "Dashboard"
  19. ctx.Data["PageIsUserDashboard"] = true
  20. repos, err := models.GetRepositories(&models.User{Id: ctx.User.Id})
  21. if err != nil {
  22. ctx.Handle(200, "user.Dashboard", err)
  23. return
  24. }
  25. ctx.Data["MyRepos"] = repos
  26. feeds, err := models.GetFeeds(ctx.User.Id, 0, false)
  27. if err != nil {
  28. ctx.Handle(200, "user.Dashboard", err)
  29. return
  30. }
  31. ctx.Data["Feeds"] = feeds
  32. ctx.HTML(200, "user/dashboard")
  33. }
  34. func Profile(ctx *middleware.Context, params martini.Params) {
  35. ctx.Data["Title"] = "Profile"
  36. // TODO: Need to check view self or others.
  37. user, err := models.GetUserByName(params["username"])
  38. if err != nil {
  39. ctx.Handle(200, "user.Profile", err)
  40. return
  41. }
  42. ctx.Data["Owner"] = user
  43. tab := ctx.Query("tab")
  44. ctx.Data["TabName"] = tab
  45. switch tab {
  46. case "activity":
  47. feeds, err := models.GetFeeds(user.Id, 0, true)
  48. if err != nil {
  49. ctx.Handle(200, "user.Profile", err)
  50. return
  51. }
  52. ctx.Data["Feeds"] = feeds
  53. default:
  54. repos, err := models.GetRepositories(user)
  55. if err != nil {
  56. ctx.Handle(200, "user.Profile", err)
  57. return
  58. }
  59. ctx.Data["Repos"] = repos
  60. }
  61. ctx.Data["PageIsUserProfile"] = true
  62. ctx.HTML(200, "user/profile")
  63. }
  64. func SignIn(ctx *middleware.Context, form auth.LogInForm) {
  65. ctx.Data["Title"] = "Log In"
  66. if ctx.Req.Method == "GET" {
  67. // Check auto-login.
  68. userName := ctx.GetCookie(base.CookieUserName)
  69. if len(userName) == 0 {
  70. ctx.HTML(200, "user/signin")
  71. return
  72. }
  73. isSucceed := false
  74. defer func() {
  75. if !isSucceed {
  76. log.Trace("%s auto-login cookie cleared: %s", ctx.Req.RequestURI, userName)
  77. ctx.SetCookie(base.CookieUserName, "", -1)
  78. ctx.SetCookie(base.CookieRememberName, "", -1)
  79. }
  80. }()
  81. user, err := models.GetUserByName(userName)
  82. if err != nil {
  83. ctx.HTML(200, "user/signin")
  84. return
  85. }
  86. secret := base.EncodeMd5(user.Rands + user.Passwd)
  87. value, _ := ctx.GetSecureCookie(secret, base.CookieRememberName)
  88. if value != user.Name {
  89. ctx.HTML(200, "user/signin")
  90. return
  91. }
  92. isSucceed = true
  93. ctx.Session.Set("userId", user.Id)
  94. ctx.Session.Set("userName", user.Name)
  95. redirectTo, _ := url.QueryUnescape(ctx.GetCookie("redirect_to"))
  96. if len(redirectTo) > 0 {
  97. ctx.SetCookie("redirect_to", "", -1)
  98. ctx.Redirect(redirectTo)
  99. } else {
  100. ctx.Redirect("/")
  101. }
  102. return
  103. }
  104. if hasErr, ok := ctx.Data["HasError"]; ok && hasErr.(bool) {
  105. ctx.HTML(200, "user/signin")
  106. return
  107. }
  108. user, err := models.LoginUserPlain(form.UserName, form.Password)
  109. if err != nil {
  110. if err == models.ErrUserNotExist {
  111. log.Trace("%s Log in failed: %s/%s", ctx.Req.RequestURI, form.UserName, form.Password)
  112. ctx.RenderWithErr("Username or password is not correct", "user/signin", &form)
  113. return
  114. }
  115. ctx.Handle(200, "user.SignIn", err)
  116. return
  117. }
  118. if form.Remember == "on" {
  119. secret := base.EncodeMd5(user.Rands + user.Passwd)
  120. days := 86400 * base.LogInRememberDays
  121. ctx.SetCookie(base.CookieUserName, user.Name, days)
  122. ctx.SetSecureCookie(secret, base.CookieRememberName, user.Name, days)
  123. }
  124. ctx.Session.Set("userId", user.Id)
  125. ctx.Session.Set("userName", user.Name)
  126. redirectTo, _ := url.QueryUnescape(ctx.GetCookie("redirect_to"))
  127. if len(redirectTo) > 0 {
  128. ctx.SetCookie("redirect_to", "", -1)
  129. ctx.Redirect(redirectTo)
  130. } else {
  131. ctx.Redirect("/")
  132. }
  133. }
  134. func SignOut(ctx *middleware.Context) {
  135. ctx.Session.Delete("userId")
  136. ctx.Session.Delete("userName")
  137. ctx.SetCookie(base.CookieUserName, "", -1)
  138. ctx.SetCookie(base.CookieRememberName, "", -1)
  139. ctx.Redirect("/")
  140. }
  141. func SignUp(ctx *middleware.Context, form auth.RegisterForm) {
  142. ctx.Data["Title"] = "Sign Up"
  143. ctx.Data["PageIsSignUp"] = true
  144. if base.Service.DisenableRegisteration {
  145. ctx.Data["DisenableRegisteration"] = true
  146. ctx.HTML(200, "user/signup")
  147. return
  148. }
  149. if ctx.Req.Method == "GET" {
  150. ctx.HTML(200, "user/signup")
  151. return
  152. }
  153. if form.Password != form.RetypePasswd {
  154. ctx.Data["HasError"] = true
  155. ctx.Data["Err_Password"] = true
  156. ctx.Data["Err_RetypePasswd"] = true
  157. ctx.Data["ErrorMsg"] = "Password and re-type password are not same"
  158. auth.AssignForm(form, ctx.Data)
  159. }
  160. if ctx.HasError() {
  161. ctx.HTML(200, "user/signup")
  162. return
  163. }
  164. u := &models.User{
  165. Name: form.UserName,
  166. Email: form.Email,
  167. Passwd: form.Password,
  168. IsActive: !base.Service.RegisterEmailConfirm,
  169. }
  170. var err error
  171. if u, err = models.RegisterUser(u); err != nil {
  172. switch err {
  173. case models.ErrUserAlreadyExist:
  174. ctx.RenderWithErr("Username has been already taken", "user/signup", &form)
  175. case models.ErrEmailAlreadyUsed:
  176. ctx.RenderWithErr("E-mail address has been already used", "user/signup", &form)
  177. case models.ErrUserNameIllegal:
  178. ctx.RenderWithErr(models.ErrRepoNameIllegal.Error(), "user/signup", &form)
  179. default:
  180. ctx.Handle(200, "user.SignUp", err)
  181. }
  182. return
  183. }
  184. log.Trace("%s User created: %s", ctx.Req.RequestURI, strings.ToLower(form.UserName))
  185. // Send confirmation e-mail.
  186. if base.Service.RegisterEmailConfirm && u.Id > 1 {
  187. mailer.SendRegisterMail(ctx.Render, u)
  188. ctx.Data["IsSendRegisterMail"] = true
  189. ctx.Data["Email"] = u.Email
  190. ctx.Data["Hours"] = base.Service.ActiveCodeLives / 60
  191. ctx.HTML(200, "user/active")
  192. if err = ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil {
  193. log.Error("Set cache(MailResendLimit) fail: %v", err)
  194. }
  195. return
  196. }
  197. ctx.Redirect("/user/login")
  198. }
  199. func Delete(ctx *middleware.Context) {
  200. ctx.Data["Title"] = "Delete Account"
  201. ctx.Data["PageIsUserSetting"] = true
  202. ctx.Data["IsUserPageSettingDelete"] = true
  203. if ctx.Req.Method == "GET" {
  204. ctx.HTML(200, "user/delete")
  205. return
  206. }
  207. tmpUser := models.User{Passwd: ctx.Query("password")}
  208. tmpUser.EncodePasswd()
  209. if len(tmpUser.Passwd) == 0 || tmpUser.Passwd != ctx.User.Passwd {
  210. ctx.Data["HasError"] = true
  211. ctx.Data["ErrorMsg"] = "Password is not correct. Make sure you are owner of this account."
  212. } else {
  213. if err := models.DeleteUser(ctx.User); err != nil {
  214. ctx.Data["HasError"] = true
  215. switch err {
  216. case models.ErrUserOwnRepos:
  217. ctx.Data["ErrorMsg"] = "Your account still have ownership of repository, you have to delete or transfer them first."
  218. default:
  219. ctx.Handle(200, "user.Delete", err)
  220. return
  221. }
  222. } else {
  223. ctx.Redirect("/")
  224. return
  225. }
  226. }
  227. ctx.HTML(200, "user/delete")
  228. }
  229. const (
  230. TPL_FEED = `<i class="icon fa fa-%s"></i>
  231. <div class="info"><span class="meta">%s</span><br>%s</div>`
  232. )
  233. func Feeds(ctx *middleware.Context, form auth.FeedsForm) {
  234. actions, err := models.GetFeeds(form.UserId, form.Page*20, false)
  235. if err != nil {
  236. ctx.JSON(500, err)
  237. }
  238. feeds := make([]string, len(actions))
  239. for i := range actions {
  240. feeds[i] = fmt.Sprintf(TPL_FEED, base.ActionIcon(actions[i].OpType),
  241. base.TimeSince(actions[i].Created), base.ActionDesc(actions[i], ctx.User.AvatarLink()))
  242. }
  243. ctx.JSON(200, &feeds)
  244. }
  245. func Issues(ctx *middleware.Context) {
  246. ctx.Data["Title"] = "Your Issues"
  247. ctx.Data["ViewType"] = "all"
  248. page, _ := base.StrTo(ctx.Query("page")).Int()
  249. repoId, _ := base.StrTo(ctx.Query("repoid")).Int64()
  250. ctx.Data["RepoId"] = repoId
  251. var posterId int64 = 0
  252. if ctx.Query("type") == "created_by" {
  253. posterId = ctx.User.Id
  254. ctx.Data["ViewType"] = "created_by"
  255. }
  256. // Get all repositories.
  257. repos, err := models.GetRepositories(ctx.User)
  258. if err != nil {
  259. ctx.Handle(200, "user.Issues(get repositories)", err)
  260. return
  261. }
  262. showRepos := make([]models.Repository, 0, len(repos))
  263. var closedIssueCount, createdByCount int
  264. // Get all issues.
  265. allIssues := make([]models.Issue, 0, 5*len(repos))
  266. for i, repo := range repos {
  267. issues, err := models.GetIssues(0, repo.Id, posterId, 0, page, false, false, "", "")
  268. if err != nil {
  269. ctx.Handle(200, "user.Issues(get issues)", err)
  270. return
  271. }
  272. closedIssueCount += repo.NumClosedIssues
  273. // Set repository information to issues.
  274. for j := range issues {
  275. issues[j].Repo = &repos[i]
  276. }
  277. allIssues = append(allIssues, issues...)
  278. repos[i].NumOpenIssues = repo.NumIssues - repo.NumClosedIssues
  279. if repos[i].NumOpenIssues > 0 {
  280. showRepos = append(showRepos, repos[i])
  281. }
  282. }
  283. showIssues := make([]models.Issue, 0, len(allIssues))
  284. isShowClosed := ctx.Query("state") == "closed"
  285. ctx.Data["IsShowClosed"] = isShowClosed
  286. // Get posters and filter issues.
  287. for i := range allIssues {
  288. u, err := models.GetUserById(allIssues[i].PosterId)
  289. if err != nil {
  290. ctx.Handle(200, "user.Issues(get poster): %v", err)
  291. return
  292. }
  293. allIssues[i].Poster = u
  294. if u.Id == ctx.User.Id {
  295. createdByCount++
  296. }
  297. if repoId > 0 && repoId != allIssues[i].Repo.Id {
  298. continue
  299. }
  300. if isShowClosed == allIssues[i].IsClosed {
  301. showIssues = append(showIssues, allIssues[i])
  302. }
  303. }
  304. ctx.Data["Repos"] = showRepos
  305. ctx.Data["Issues"] = showIssues
  306. ctx.Data["AllIssueCount"] = len(allIssues)
  307. ctx.Data["ClosedIssueCount"] = closedIssueCount
  308. ctx.Data["OpenIssueCount"] = len(allIssues) - closedIssueCount
  309. ctx.Data["CreatedByCount"] = createdByCount
  310. ctx.HTML(200, "issue/user")
  311. }
  312. func Pulls(ctx *middleware.Context) {
  313. ctx.HTML(200, "user/pulls")
  314. }
  315. func Stars(ctx *middleware.Context) {
  316. ctx.HTML(200, "user/stars")
  317. }
  318. func Activate(ctx *middleware.Context) {
  319. code := ctx.Query("code")
  320. if len(code) == 0 {
  321. ctx.Data["IsActivatePage"] = true
  322. if ctx.User.IsActive {
  323. ctx.Handle(404, "user.Activate", nil)
  324. return
  325. }
  326. // Resend confirmation e-mail.
  327. if base.Service.RegisterEmailConfirm {
  328. if ctx.Cache.IsExist("MailResendLimit_" + ctx.User.LowerName) {
  329. ctx.Data["ResendLimited"] = true
  330. } else {
  331. ctx.Data["Hours"] = base.Service.ActiveCodeLives / 60
  332. mailer.SendActiveMail(ctx.Render, ctx.User)
  333. }
  334. } else {
  335. ctx.Data["ServiceNotEnabled"] = true
  336. }
  337. ctx.HTML(200, "user/active")
  338. return
  339. }
  340. // Verify code.
  341. if user := models.VerifyUserActiveCode(code); user != nil {
  342. user.IsActive = true
  343. user.Rands = models.GetUserSalt()
  344. models.UpdateUser(user)
  345. log.Trace("%s User activated: %s", ctx.Req.RequestURI, user.LowerName)
  346. ctx.Session.Set("userId", user.Id)
  347. ctx.Session.Set("userName", user.Name)
  348. ctx.Redirect("/")
  349. return
  350. }
  351. ctx.Data["IsActivateFailed"] = true
  352. ctx.HTML(200, "user/active")
  353. }