func Dashboard(ctx *middleware.Context) { ctx.Data["Title"] = ctx.Tr("admin.dashboard") ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminDashboard"] = true // Run operation. op, _ := com.StrTo(ctx.Query("op")).Int() if op > 0 { var err error var success string switch AdminOperation(op) { case CLEAN_UNBIND_OAUTH: success = "All unbind OAuthes have been deleted." err = models.CleanUnbindOauth() case CLEAN_INACTIVATE_USER: success = "All inactivate accounts have been deleted." err = models.DeleteInactivateUsers() } if err != nil { ctx.Flash.Error(err.Error()) } else { ctx.Flash.Success(success) } ctx.Redirect("/admin") return } ctx.Data["Stats"] = models.GetStatistic() updateSystemStatus() ctx.Data["SysStatus"] = sysStatus ctx.HTML(200, DASHBOARD) }
func SearchUsers(ctx *middleware.Context) { opt := models.SearchOption{ Keyword: ctx.Query("q"), Limit: com.StrTo(ctx.Query("limit")).MustInt(), } if opt.Limit == 0 { opt.Limit = 10 } us, err := models.SearchUserByName(opt) if err != nil { ctx.JSON(500, map[string]interface{}{ "ok": false, "error": err.Error(), }) return } results := make([]*user, len(us)) for i := range us { results[i] = &user{ UserName: us[i].Name, AvatarLink: us[i].AvatarLink(), } } ctx.Render.JSON(200, map[string]interface{}{ "ok": true, "data": results, }) }
func SettingsSocial(ctx *middleware.Context) { ctx.Data["Title"] = ctx.Tr("settings") ctx.Data["PageIsUserSettings"] = true ctx.Data["PageIsSettingsSocial"] = true // Unbind social account. remove, _ := com.StrTo(ctx.Query("remove")).Int64() if remove > 0 { if err := models.DeleteOauth2ById(remove); err != nil { ctx.Handle(500, "DeleteOauth2ById", err) return } ctx.Flash.Success(ctx.Tr("settings.unbind_success")) ctx.Redirect("/user/settings/social") return } socials, err := models.GetOauthByUserId(ctx.User.Id) if err != nil { ctx.Handle(500, "GetOauthByUserId", err) return } ctx.Data["Socials"] = socials ctx.HTML(200, SETTINGS_SOCIAL) }
func Email2User(ctx *middleware.Context) { u, err := models.GetUserByEmail(ctx.Query("email")) if err != nil { if err == models.ErrUserNotExist { ctx.Handle(404, "user.Email2User(GetUserByEmail)", err) } else { ctx.Handle(500, "user.Email2User(GetUserByEmail)", err) } return } ctx.Redirect("/user/" + u.Name) }
func ResetPasswd(ctx *middleware.Context) { ctx.Data["Title"] = ctx.Tr("auth.reset_password") code := ctx.Query("code") if len(code) == 0 { ctx.Error(404) return } ctx.Data["Code"] = code ctx.Data["IsResetForm"] = true ctx.HTML(200, RESET_PASSWORD) }
func Profile(ctx *middleware.Context) { ctx.Data["Title"] = "Profile" ctx.Data["PageIsUserProfile"] = true uname := ctx.Params(":username") // Special handle for FireFox requests favicon.ico. if uname == "favicon.ico" { ctx.Redirect("/img/favicon.png") return } u, err := models.GetUserByName(uname) if err != nil { if err == models.ErrUserNotExist { ctx.Handle(404, "GetUserByName", err) } else { ctx.Handle(500, "GetUserByName", err) } return } if u.IsOrganization() { ctx.Redirect("/org/" + u.Name) return } // For security reason, hide e-mail address for anonymous visitors. if !ctx.IsSigned { u.Email = "" } ctx.Data["Owner"] = u tab := ctx.Query("tab") ctx.Data["TabName"] = tab switch tab { case "activity": ctx.Data["Feeds"], err = models.GetFeeds(u.Id, 0, true) if err != nil { ctx.Handle(500, "GetFeeds", err) return } default: ctx.Data["Repos"], err = models.GetRepositories(u.Id, ctx.IsSigned && ctx.User.Id == u.Id) if err != nil { ctx.Handle(500, "GetRepositories", err) return } } ctx.HTML(200, PROFILE) }
func Activate(ctx *middleware.Context) { code := ctx.Query("code") if len(code) == 0 { ctx.Data["IsActivatePage"] = true if ctx.User.IsActive { ctx.Error(404) return } // Resend confirmation e-mail. if setting.Service.RegisterEmailConfirm { if ctx.Cache.IsExist("MailResendLimit_" + ctx.User.LowerName) { ctx.Data["ResendLimited"] = true } else { ctx.Data["Hours"] = setting.Service.ActiveCodeLives / 60 mailer.SendActiveMail(ctx.Render, ctx.User) if err := ctx.Cache.Put("MailResendLimit_"+ctx.User.LowerName, ctx.User.LowerName, 180); err != nil { log.Error(4, "Set cache(MailResendLimit) fail: %v", err) } } } else { ctx.Data["ServiceNotEnabled"] = true } ctx.HTML(200, ACTIVATE) return } // Verify code. if user := models.VerifyUserActiveCode(code); user != nil { user.IsActive = true user.Rands = models.GetUserSalt() if err := models.UpdateUser(user); err != nil { if err == models.ErrUserNotExist { ctx.Error(404) } else { ctx.Handle(500, "UpdateUser", err) } return } log.Trace("User activated: %s", user.Name) ctx.Session.Set("uid", user.Id) ctx.Session.Set("uname", user.Name) ctx.Redirect("/") return } ctx.Data["IsActivateFailed"] = true ctx.HTML(200, ACTIVATE) }
func pagination(ctx *middleware.Context, count int64, pageNum int) int { p := com.StrTo(ctx.Query("p")).MustInt() if p < 1 { p = 1 } curCount := int64((p-1)*pageNum + pageNum) if curCount > count { p = int(count) / pageNum } else if count > curCount { ctx.Data["NextPageNum"] = p + 1 } if p > 1 { ctx.Data["LastPageNum"] = p - 1 } return p }
func ResetPasswdPost(ctx *middleware.Context) { ctx.Data["Title"] = ctx.Tr("auth.reset_password") code := ctx.Query("code") if len(code) == 0 { ctx.Error(404) return } ctx.Data["Code"] = code if u := models.VerifyUserActiveCode(code); u != nil { // Validate password length. passwd := ctx.Query("password") if len(passwd) < 6 { ctx.Data["IsResetForm"] = true ctx.Data["Err_Password"] = true ctx.RenderWithErr(ctx.Tr("auth.password_too_short"), RESET_PASSWORD, nil) return } u.Passwd = passwd u.Rands = models.GetUserSalt() u.Salt = models.GetUserSalt() u.EncodePasswd() if err := models.UpdateUser(u); err != nil { ctx.Handle(500, "UpdateUser", err) return } log.Trace("User password reset: %s", u.Name) ctx.Redirect("/user/login") return } ctx.Data["IsResetFailed"] = true ctx.HTML(200, RESET_PASSWORD) }
func ForgotPasswdPost(ctx *middleware.Context) { ctx.Data["Title"] = ctx.Tr("auth.forgot_password") if setting.MailService == nil { ctx.Handle(403, "user.ForgotPasswdPost", nil) return } ctx.Data["IsResetRequest"] = true email := ctx.Query("email") u, err := models.GetUserByEmail(email) if err != nil { if err == models.ErrUserNotExist { ctx.Data["Err_Email"] = true ctx.RenderWithErr(ctx.Tr("auth.email_not_associate"), FORGOT_PASSWORD, nil) } else { ctx.Handle(500, "user.ResetPasswd(check existence)", err) } return } if ctx.Cache.IsExist("MailResendLimit_" + u.LowerName) { ctx.Data["ResendLimited"] = true ctx.HTML(200, FORGOT_PASSWORD) return } mailer.SendResetPasswdMail(ctx.Render, u) if err = ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil { log.Error(4, "Set cache(MailResendLimit) fail: %v", err) } ctx.Data["Email"] = email ctx.Data["Hours"] = setting.Service.ActiveCodeLives / 60 ctx.Data["IsResetSent"] = true ctx.HTML(200, FORGOT_PASSWORD) }
func SearchRepos(ctx *middleware.Context) { opt := models.SearchOption{ Keyword: path.Base(ctx.Query("q")), Uid: com.StrTo(ctx.Query("uid")).MustInt64(), Limit: com.StrTo(ctx.Query("limit")).MustInt(), } if opt.Limit == 0 { opt.Limit = 10 } repos, err := models.SearchRepositoryByName(opt) if err != nil { ctx.JSON(500, map[string]interface{}{ "ok": false, "error": err.Error(), }) return } results := make([]*repo, len(repos)) for i := range repos { if err = repos[i].GetOwner(); err != nil { ctx.JSON(500, map[string]interface{}{ "ok": false, "error": err.Error(), }) return } results[i] = &repo{ RepoLink: path.Join(repos[i].Owner.Name, repos[i].Name), } } ctx.Render.JSON(200, map[string]interface{}{ "ok": true, "data": results, }) }
func Issues(ctx *middleware.Context) { ctx.Data["Title"] = "Your Issues" viewType := ctx.Query("type") types := []string{"assigned", "created_by"} if !com.IsSliceContainsStr(types, viewType) { viewType = "all" } isShowClosed := ctx.Query("state") == "closed" var filterMode int switch viewType { case "assigned": filterMode = models.FM_ASSIGN case "created_by": filterMode = models.FM_CREATE } repoId, _ := com.StrTo(ctx.Query("repoid")).Int64() issueStats := models.GetUserIssueStats(ctx.User.Id, filterMode) // Get all repositories. repos, err := models.GetRepositories(ctx.User.Id, true) if err != nil { ctx.Handle(500, "user.Issues(GetRepositories)", err) return } repoIds := make([]int64, 0, len(repos)) showRepos := make([]*models.Repository, 0, len(repos)) for _, repo := range repos { if repo.NumIssues == 0 { continue } repoIds = append(repoIds, repo.Id) repo.NumOpenIssues = repo.NumIssues - repo.NumClosedIssues issueStats.AllCount += int64(repo.NumOpenIssues) if isShowClosed { if repo.NumClosedIssues > 0 { if filterMode == models.FM_CREATE { repo.NumClosedIssues = int(models.GetIssueCountByPoster(ctx.User.Id, repo.Id, isShowClosed)) } showRepos = append(showRepos, repo) } } else { if repo.NumOpenIssues > 0 { if filterMode == models.FM_CREATE { repo.NumOpenIssues = int(models.GetIssueCountByPoster(ctx.User.Id, repo.Id, isShowClosed)) } showRepos = append(showRepos, repo) } } } if repoId > 0 { repoIds = []int64{repoId} } page, _ := com.StrTo(ctx.Query("page")).Int() // Get all issues. var ius []*models.IssueUser switch viewType { case "assigned": fallthrough case "created_by": ius, err = models.GetIssueUserPairsByMode(ctx.User.Id, repoId, isShowClosed, page, filterMode) default: ius, err = models.GetIssueUserPairsByRepoIds(repoIds, isShowClosed, page) } if err != nil { ctx.Handle(500, "user.Issues(GetAllIssueUserPairs)", err) return } issues := make([]*models.Issue, len(ius)) for i := range ius { issues[i], err = models.GetIssueById(ius[i].IssueId) if err != nil { if err == models.ErrIssueNotExist { log.Warn("user.Issues(GetIssueById #%d): issue not exist", ius[i].IssueId) continue } else { ctx.Handle(500, fmt.Sprintf("user.Issues(GetIssueById #%d)", ius[i].IssueId), err) return } } issues[i].Repo, err = models.GetRepositoryById(issues[i].RepoId) if err != nil { if err == models.ErrRepoNotExist { log.Warn("user.Issues(GetRepositoryById #%d): repository not exist", issues[i].RepoId) continue } else { ctx.Handle(500, fmt.Sprintf("user.Issues(GetRepositoryById #%d)", issues[i].RepoId), err) return } } if err = issues[i].Repo.GetOwner(); err != nil { ctx.Handle(500, "user.Issues(GetOwner)", err) return } if err = issues[i].GetPoster(); err != nil { ctx.Handle(500, "user.Issues(GetUserById)", err) return } } ctx.Data["RepoId"] = repoId ctx.Data["Repos"] = showRepos ctx.Data["Issues"] = issues ctx.Data["ViewType"] = viewType ctx.Data["IssueStats"] = issueStats ctx.Data["IsShowClosed"] = isShowClosed if isShowClosed { ctx.Data["State"] = "closed" ctx.Data["ShowCount"] = issueStats.ClosedCount } else { ctx.Data["ShowCount"] = issueStats.OpenCount } ctx.HTML(200, ISSUES) }
func SocialSignIn(ctx *middleware.Context) { if setting.OauthService == nil { ctx.Handle(404, "social.SocialSignIn(oauth service not enabled)", nil) return } next := extractPath(ctx.Query("next")) name := ctx.Params(":name") connect, ok := social.SocialMap[name] if !ok { ctx.Handle(404, "social.SocialSignIn(social login not enabled)", errors.New(name)) return } appUrl := strings.TrimSuffix(setting.AppUrl, "/") if name == "weibo" { appUrl = strings.Replace(appUrl, "localhost", "127.0.0.1", 1) } code := ctx.Query("code") if code == "" { // redirect to social login page connect.SetRedirectUrl(appUrl + ctx.Req.URL.Path) ctx.Redirect(connect.AuthCodeURL(next)) return } // handle call back tk, err := connect.Exchange(code) if err != nil { ctx.Handle(500, "social.SocialSignIn(Exchange)", err) return } next = extractPath(ctx.Query("state")) log.Trace("social.SocialSignIn(Got token)") ui, err := connect.UserInfo(tk, ctx.Req.URL) if err != nil { ctx.Handle(500, fmt.Sprintf("social.SocialSignIn(get info from %s)", name), err) return } log.Info("social.SocialSignIn(social login): %s", ui) oa, err := models.GetOauth2(ui.Identity) switch err { case nil: ctx.Session.Set("uid", oa.User.Id) ctx.Session.Set("uname", oa.User.Name) case models.ErrOauth2RecordNotExist: raw, _ := json.Marshal(tk) oa = &models.Oauth2{ Uid: -1, Type: connect.Type(), Identity: ui.Identity, Token: string(raw), } log.Trace("social.SocialSignIn(oa): %v", oa) if err = models.AddOauth2(oa); err != nil { log.Error(4, "social.SocialSignIn(add oauth2): %v", err) // 501 return } case models.ErrOauth2NotAssociated: next = "/user/sign_up" default: ctx.Handle(500, "social.SocialSignIn(GetOauth2)", err) return } oa.Updated = time.Now() if err = models.UpdateOauth2(oa); err != nil { log.Error(4, "UpdateOauth2: %v", err) } ctx.Session.Set("socialId", oa.Id) ctx.Session.Set("socialName", ui.Name) ctx.Session.Set("socialEmail", ui.Email) log.Trace("social.SocialSignIn(social ID): %v", oa.Id) ctx.Redirect(next) }
func SignUpPost(ctx *middleware.Context, cpt *captcha.Captcha, form auth.RegisterForm) { ctx.Data["Title"] = ctx.Tr("sign_up") if setting.Service.DisableRegistration { ctx.Error(403) return } isOauth := false sid, isOauth := ctx.Session.Get("socialId").(int64) if isOauth { ctx.Data["IsSocialLogin"] = true } // May redirect from home page. if ctx.Query("from") == "home" { // Clear input error box. ctx.Data["Err_UserName"] = false ctx.Data["Err_Email"] = false // Make the best guess. uname := ctx.Query("uname") i := strings.Index(uname, "@") if i > -1 { ctx.Data["email"] = uname ctx.Data["uname"] = uname[:i] } else { ctx.Data["uname"] = uname } ctx.Data["password"] = ctx.Query("password") ctx.HTML(200, SIGNUP) return } if ctx.HasError() { ctx.HTML(200, SIGNUP) return } if !cpt.VerifyReq(ctx.Req) { ctx.Data["Err_Captcha"] = true ctx.RenderWithErr(ctx.Tr("form.captcha_incorrect"), SIGNUP, &form) return } else if form.Password != form.Retype { ctx.Data["Err_Password"] = true ctx.RenderWithErr(ctx.Tr("form.password_not_match"), SIGNUP, &form) return } u := &models.User{ Name: form.UserName, Email: form.Email, Passwd: form.Password, IsActive: !setting.Service.RegisterEmailConfirm || isOauth, } if err := models.CreateUser(u); err != nil { switch err { case models.ErrUserAlreadyExist: ctx.Data["Err_UserName"] = true ctx.RenderWithErr(ctx.Tr("form.username_been_taken"), SIGNUP, &form) case models.ErrEmailAlreadyUsed: ctx.Data["Err_Email"] = true ctx.RenderWithErr(ctx.Tr("form.email_been_used"), SIGNUP, &form) case models.ErrUserNameIllegal: ctx.Data["Err_UserName"] = true ctx.RenderWithErr(ctx.Tr("form.illegal_username"), SIGNUP, &form) default: ctx.Handle(500, "CreateUser", err) } return } log.Trace("Account created: %s", u.Name) // Bind social account. if isOauth { if err := models.BindUserOauth2(u.Id, sid); err != nil { ctx.Handle(500, "BindUserOauth2", err) return } ctx.Session.Delete("socialId") log.Trace("%s OAuth binded: %s -> %d", ctx.Req.RequestURI, form.UserName, sid) } // Send confirmation e-mail, no need for social account. if !isOauth && setting.Service.RegisterEmailConfirm && u.Id > 1 { mailer.SendRegisterMail(ctx.Render, u) ctx.Data["IsSendRegisterMail"] = true ctx.Data["Email"] = u.Email ctx.Data["Hours"] = setting.Service.ActiveCodeLives / 60 ctx.HTML(200, "user/activate") if err := ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil { log.Error(4, "Set cache(MailResendLimit) fail: %v", err) } return } ctx.Redirect("/user/login") }
func SettingsSSHKeysPost(ctx *middleware.Context, form auth.AddSSHKeyForm) { ctx.Data["Title"] = ctx.Tr("settings") ctx.Data["PageIsUserSettings"] = true ctx.Data["PageIsSettingsSSHKeys"] = true var err error ctx.Data["Keys"], err = models.ListPublicKey(ctx.User.Id) if err != nil { ctx.Handle(500, "ssh.ListPublicKey", err) return } // Delete SSH key. if ctx.Query("_method") == "DELETE" { id := com.StrTo(ctx.Query("id")).MustInt64() if id <= 0 { return } if err = models.DeletePublicKey(&models.PublicKey{Id: id}); err != nil { ctx.Handle(500, "DeletePublicKey", err) } else { log.Trace("SSH key deleted: %s", ctx.User.Name) ctx.Redirect("/user/settings/ssh") } return } // Add new SSH key. if ctx.Req.Method == "POST" { if ctx.HasError() { ctx.HTML(200, SETTINGS_SSH_KEYS) return } // Remove newline characters from form.KeyContent cleanContent := strings.Replace(form.Content, "\n", "", -1) if ok, err := models.CheckPublicKeyString(cleanContent); !ok { ctx.Flash.Error(ctx.Tr("form.invalid_ssh_key", err.Error())) ctx.Redirect("/user/settings/ssh") return } k := &models.PublicKey{ OwnerId: ctx.User.Id, Name: form.SSHTitle, Content: cleanContent, } if err := models.AddPublicKey(k); err != nil { if err == models.ErrKeyAlreadyExist { ctx.RenderWithErr(ctx.Tr("form.ssh_key_been_used"), SETTINGS_SSH_KEYS, &form) return } ctx.Handle(500, "ssh.AddPublicKey", err) return } else { log.Trace("SSH key added: %s", ctx.User.Name) ctx.Flash.Success(ctx.Tr("settings.add_key_success")) ctx.Redirect("/user/settings/ssh") return } } ctx.HTML(200, SETTINGS_SSH_KEYS) }
func Migrate(ctx *middleware.Context, form auth.MigrateRepoForm) { u, err := models.GetUserByName(ctx.Query("username")) if err != nil { ctx.JSON(500, map[string]interface{}{ "ok": false, "error": err.Error(), }) return } if !u.ValidtePassword(ctx.Query("password")) { ctx.JSON(500, map[string]interface{}{ "ok": false, "error": "username or password is not correct", }) return } ctxUser := u // Not equal means current user is an organization. if form.Uid != u.Id { org, err := models.GetUserById(form.Uid) if err != nil { ctx.JSON(500, map[string]interface{}{ "ok": false, "error": err.Error(), }) return } ctxUser = org } if ctx.HasError() { ctx.JSON(500, map[string]interface{}{ "ok": false, "error": ctx.GetErrMsg(), }) return } if ctxUser.IsOrganization() { // Check ownership of organization. if !ctxUser.IsOrgOwner(u.Id) { ctx.JSON(403, map[string]interface{}{ "ok": false, "error": "given user is not owner of organization", }) return } } authStr := strings.Replace(fmt.Sprintf("://%s:%s", form.AuthUserName, form.AuthPasswd), "@", "%40", -1) url := strings.Replace(form.HttpsUrl, "://", authStr+"@", 1) repo, err := models.MigrateRepository(ctxUser, form.RepoName, form.Description, form.Private, form.Mirror, url) if err == nil { log.Trace("Repository migrated: %s/%s", ctxUser.Name, form.RepoName) ctx.JSON(200, map[string]interface{}{ "ok": true, "data": "/" + ctxUser.Name + "/" + form.RepoName, }) return } if repo != nil { if errDelete := models.DeleteRepository(ctxUser.Id, repo.Id, ctxUser.Name); errDelete != nil { log.Error(4, "DeleteRepository: %v", errDelete) } } ctx.JSON(500, map[string]interface{}{ "ok": false, "error": err.Error(), }) }