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.

user.go 10KB

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
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
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
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
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
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 ctx.HasError() {
  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]))
  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. isShowClosed := ctx.Query("state") == "closed"
  264. var closedIssueCount, createdByCount, allIssueCount int
  265. // Get all issues.
  266. allIssues := make([]models.Issue, 0, 5*len(repos))
  267. for i, repo := range repos {
  268. issues, err := models.GetIssues(0, repo.Id, posterId, 0, page, isShowClosed, false, "", "")
  269. if err != nil {
  270. ctx.Handle(200, "user.Issues(get issues)", err)
  271. return
  272. }
  273. allIssueCount += repo.NumIssues
  274. closedIssueCount += repo.NumClosedIssues
  275. // Set repository information to issues.
  276. for j := range issues {
  277. issues[j].Repo = &repos[i]
  278. }
  279. allIssues = append(allIssues, issues...)
  280. repos[i].NumOpenIssues = repo.NumIssues - repo.NumClosedIssues
  281. if repos[i].NumOpenIssues > 0 {
  282. showRepos = append(showRepos, repos[i])
  283. }
  284. }
  285. showIssues := make([]models.Issue, 0, len(allIssues))
  286. ctx.Data["IsShowClosed"] = isShowClosed
  287. // Get posters and filter issues.
  288. for i := range allIssues {
  289. u, err := models.GetUserById(allIssues[i].PosterId)
  290. if err != nil {
  291. ctx.Handle(200, "user.Issues(get poster): %v", err)
  292. return
  293. }
  294. allIssues[i].Poster = u
  295. if u.Id == ctx.User.Id {
  296. createdByCount++
  297. }
  298. if repoId > 0 && repoId != allIssues[i].Repo.Id {
  299. continue
  300. }
  301. if isShowClosed == allIssues[i].IsClosed {
  302. showIssues = append(showIssues, allIssues[i])
  303. }
  304. }
  305. ctx.Data["Repos"] = showRepos
  306. ctx.Data["Issues"] = showIssues
  307. ctx.Data["AllIssueCount"] = allIssueCount
  308. ctx.Data["ClosedIssueCount"] = closedIssueCount
  309. ctx.Data["OpenIssueCount"] = allIssueCount - closedIssueCount
  310. ctx.Data["CreatedByCount"] = createdByCount
  311. ctx.HTML(200, "issue/user")
  312. }
  313. func Pulls(ctx *middleware.Context) {
  314. ctx.HTML(200, "user/pulls")
  315. }
  316. func Stars(ctx *middleware.Context) {
  317. ctx.HTML(200, "user/stars")
  318. }
  319. func Activate(ctx *middleware.Context) {
  320. code := ctx.Query("code")
  321. if len(code) == 0 {
  322. ctx.Data["IsActivatePage"] = true
  323. if ctx.User.IsActive {
  324. ctx.Handle(404, "user.Activate", nil)
  325. return
  326. }
  327. // Resend confirmation e-mail.
  328. if base.Service.RegisterEmailConfirm {
  329. if ctx.Cache.IsExist("MailResendLimit_" + ctx.User.LowerName) {
  330. ctx.Data["ResendLimited"] = true
  331. } else {
  332. ctx.Data["Hours"] = base.Service.ActiveCodeLives / 60
  333. mailer.SendActiveMail(ctx.Render, ctx.User)
  334. }
  335. } else {
  336. ctx.Data["ServiceNotEnabled"] = true
  337. }
  338. ctx.HTML(200, "user/active")
  339. return
  340. }
  341. // Verify code.
  342. if user := models.VerifyUserActiveCode(code); user != nil {
  343. user.IsActive = true
  344. user.Rands = models.GetUserSalt()
  345. models.UpdateUser(user)
  346. log.Trace("%s User activated: %s", ctx.Req.RequestURI, user.LowerName)
  347. ctx.Session.Set("userId", user.Id)
  348. ctx.Session.Set("userName", user.Name)
  349. ctx.Redirect("/")
  350. return
  351. }
  352. ctx.Data["IsActivateFailed"] = true
  353. ctx.HTML(200, "user/active")
  354. }