func TeamsRepoAction(ctx *context.Context) { if !ctx.Org.IsOwner { ctx.Error(404) return } var err error switch ctx.Params(":action") { case "add": repoName := path.Base(ctx.Query("repo_name")) var repo *models.Repository repo, err = models.GetRepositoryByName(ctx.Org.Organization.ID, repoName) if err != nil { if models.IsErrRepoNotExist(err) { ctx.Flash.Error(ctx.Tr("org.teams.add_nonexistent_repo")) ctx.Redirect(ctx.Org.OrgLink + "/teams/" + ctx.Org.Team.LowerName + "/repositories") return } ctx.Handle(500, "GetRepositoryByName", err) return } err = ctx.Org.Team.AddRepository(repo) case "remove": err = ctx.Org.Team.RemoveRepository(com.StrTo(ctx.Query("repoid")).MustInt64()) } if err != nil { log.Error(3, "Action(%s): '%s' %v", ctx.Params(":action"), ctx.Org.Team.Name, err) ctx.Handle(500, "TeamsRepoAction", err) return } ctx.Redirect(ctx.Org.OrgLink + "/teams/" + ctx.Org.Team.LowerName + "/repositories") }
func SettingsDelete(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("settings") ctx.Data["PageIsSettingsDelete"] = true if ctx.Req.Method == "POST" { if _, err := models.UserSignIn(ctx.User.Name, ctx.Query("password")); err != nil { if models.IsErrUserNotExist(err) { ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_password"), SETTINGS_DELETE, nil) } else { ctx.Handle(500, "UserSignIn", err) } return } if err := models.DeleteUser(ctx.User); err != nil { switch { case models.IsErrUserOwnRepos(err): ctx.Flash.Error(ctx.Tr("form.still_own_repo")) ctx.Redirect(setting.AppSubUrl + "/user/settings/delete") case models.IsErrUserHasOrgs(err): ctx.Flash.Error(ctx.Tr("form.still_has_org")) ctx.Redirect(setting.AppSubUrl + "/user/settings/delete") default: ctx.Handle(500, "DeleteUser", err) } } else { log.Trace("Account deleted: %s", ctx.User.Name) ctx.Redirect(setting.AppSubUrl + "/") } return } ctx.HTML(200, SETTINGS_DELETE) }
func SettingsDelete(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("org.settings") ctx.Data["PageIsSettingsDelete"] = true org := ctx.Org.Organization if ctx.Req.Method == "POST" { if _, err := models.UserSignIn(ctx.User.Name, ctx.Query("password")); err != nil { if models.IsErrUserNotExist(err) { ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_password"), SETTINGS_DELETE, nil) } else { ctx.Handle(500, "UserSignIn", err) } return } if err := models.DeleteOrganization(org); err != nil { if models.IsErrUserOwnRepos(err) { ctx.Flash.Error(ctx.Tr("form.org_still_own_repo")) ctx.Redirect(ctx.Org.OrgLink + "/settings/delete") } else { ctx.Handle(500, "DeleteOrganization", err) } } else { log.Trace("Organization deleted: %s", org.Name) ctx.Redirect(setting.AppSubUrl + "/") } return } ctx.HTML(200, SETTINGS_DELETE) }
func SignIn(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("sign_in") // Check auto-login. isSucceed, err := AutoSignIn(ctx) if err != nil { ctx.Handle(500, "AutoSignIn", err) return } redirectTo := ctx.Query("redirect_to") if len(redirectTo) > 0 { ctx.SetCookie("redirect_to", redirectTo, 0, setting.AppSubUrl) } else { redirectTo, _ = url.QueryUnescape(ctx.GetCookie("redirect_to")) } if isSucceed { if len(redirectTo) > 0 { ctx.SetCookie("redirect_to", "", -1, setting.AppSubUrl) ctx.Redirect(redirectTo) } else { ctx.Redirect(setting.AppSubUrl + "/") } return } ctx.HTML(200, SIGNIN) }
func Invitation(ctx *context.Context) { org := ctx.Org.Organization ctx.Data["Title"] = org.FullName ctx.Data["PageIsOrgMembers"] = true if ctx.Req.Method == "POST" { uname := ctx.Query("uname") u, err := models.GetUserByName(uname) if err != nil { if models.IsErrUserNotExist(err) { ctx.Flash.Error(ctx.Tr("form.user_not_exist")) ctx.Redirect(ctx.Org.OrgLink + "/invitations/new") } else { ctx.Handle(500, " GetUserByName", err) } return } if err = org.AddMember(u.ID); err != nil { ctx.Handle(500, " AddMember", err) return } log.Trace("New member added(%s): %s", org.Name, u.Name) ctx.Redirect(ctx.Org.OrgLink + "/members") return } ctx.HTML(200, MEMBER_INVITE) }
func SearchCommits(ctx *context.Context) { ctx.Data["PageIsCommits"] = true keyword := ctx.Query("q") if len(keyword) == 0 { ctx.Redirect(ctx.Repo.RepoLink + "/commits/" + ctx.Repo.BranchName) return } commits, err := ctx.Repo.Commit.SearchCommits(keyword) if err != nil { ctx.Handle(500, "SearchCommits", err) return } commits = RenderIssueLinks(commits, ctx.Repo.RepoLink) commits = models.ValidateCommitsWithEmails(commits) ctx.Data["Commits"] = commits ctx.Data["Keyword"] = keyword ctx.Data["Username"] = ctx.Repo.Owner.Name ctx.Data["Reponame"] = ctx.Repo.Repository.Name ctx.Data["CommitCount"] = commits.Len() ctx.Data["Branch"] = ctx.Repo.BranchName ctx.HTML(200, COMMITS) }
func SettingsEmailPost(ctx *context.Context, form auth.AddEmailForm) { ctx.Data["Title"] = ctx.Tr("settings") ctx.Data["PageIsSettingsEmails"] = true // Make emailaddress primary. if ctx.Query("_method") == "PRIMARY" { if err := models.MakeEmailPrimary(&models.EmailAddress{ID: ctx.QueryInt64("id")}); err != nil { ctx.Handle(500, "MakeEmailPrimary", err) return } log.Trace("Email made primary: %s", ctx.User.Name) ctx.Redirect(setting.AppSubUrl + "/user/settings/email") return } // Add Email address. emails, err := models.GetEmailAddresses(ctx.User.ID) if err != nil { ctx.Handle(500, "GetEmailAddresses", err) return } ctx.Data["Emails"] = emails if ctx.HasError() { ctx.HTML(200, SETTINGS_EMAILS) return } email := &models.EmailAddress{ UID: ctx.User.ID, Email: form.Email, IsActivated: !setting.Service.RegisterEmailConfirm, } if err := models.AddEmailAddress(email); err != nil { if models.IsErrEmailAlreadyUsed(err) { ctx.RenderWithErr(ctx.Tr("form.email_been_used"), SETTINGS_EMAILS, &form) return } ctx.Handle(500, "AddEmailAddress", err) return } // Send confirmation email if setting.Service.RegisterEmailConfirm { models.SendActivateEmailMail(ctx.Context, ctx.User, email) if err := ctx.Cache.Put("MailResendLimit_"+ctx.User.LowerName, ctx.User.LowerName, 180); err != nil { log.Error(4, "Set cache(MailResendLimit) fail: %v", err) } ctx.Flash.Info(ctx.Tr("settings.add_email_confirmation_sent", email.Email, setting.Service.ActiveCodeLives/60)) } else { ctx.Flash.Success(ctx.Tr("settings.add_email_success")) } log.Trace("Email address added: %s", email.Email) ctx.Redirect(setting.AppSubUrl + "/user/settings/email") }
func MembersAction(ctx *context.Context) { uid := com.StrTo(ctx.Query("uid")).MustInt64() if uid == 0 { ctx.Redirect(ctx.Org.OrgLink + "/members") return } org := ctx.Org.Organization var err error switch ctx.Params(":action") { case "private": if ctx.User.ID != uid && !ctx.Org.IsOwner { ctx.Error(404) return } err = models.ChangeOrgUserStatus(org.ID, uid, false) case "public": if ctx.User.ID != uid && !ctx.Org.IsOwner { ctx.Error(404) return } err = models.ChangeOrgUserStatus(org.ID, uid, true) case "remove": if !ctx.Org.IsOwner { ctx.Error(404) return } err = org.RemoveMember(uid) if models.IsErrLastOrgOwner(err) { ctx.Flash.Error(ctx.Tr("form.last_org_owner")) ctx.Redirect(ctx.Org.OrgLink + "/members") return } case "leave": err = org.RemoveMember(ctx.User.ID) if models.IsErrLastOrgOwner(err) { ctx.Flash.Error(ctx.Tr("form.last_org_owner")) ctx.Redirect(ctx.Org.OrgLink + "/members") return } } if err != nil { log.Error(4, "Action(%s): %v", ctx.Params(":action"), err) ctx.JSON(200, map[string]interface{}{ "ok": false, "err": err.Error(), }) return } if ctx.Params(":action") != "leave" { ctx.Redirect(ctx.Org.OrgLink + "/members") } else { ctx.Redirect(setting.AppSubUrl + "/") } }
func SendTestMail(ctx *context.Context) { email := ctx.Query("email") // Send a test email to the user's email address and redirect back to Config if err := models.SendTestMail(email); err != nil { ctx.Flash.Error(ctx.Tr("admin.config.test_mail_failed", email, err)) } else { ctx.Flash.Info(ctx.Tr("admin.config.test_mail_sent", email)) } ctx.Redirect(setting.AppSubUrl + "/admin/config") }
func Diff(ctx *context.Context) { ctx.Data["PageIsDiff"] = true ctx.Data["RequireHighlightJS"] = true userName := ctx.Repo.Owner.Name repoName := ctx.Repo.Repository.Name commitID := ctx.Params(":sha") commit, err := ctx.Repo.GitRepo.GetCommit(commitID) if err != nil { if git.IsErrNotExist(err) { ctx.Handle(404, "Repo.GitRepo.GetCommit", err) } else { ctx.Handle(500, "Repo.GitRepo.GetCommit", err) } return } diff, err := models.GetDiffCommit(models.RepoPath(userName, repoName), commitID, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles) if err != nil { ctx.Handle(404, "GetDiffCommit", err) return } parents := make([]string, commit.ParentCount()) for i := 0; i < commit.ParentCount(); i++ { sha, err := commit.ParentID(i) parents[i] = sha.String() if err != nil { ctx.Handle(404, "repo.Diff", err) return } } ctx.Data["CommitID"] = commitID ctx.Data["IsSplitStyle"] = ctx.Query("style") == "split" ctx.Data["Username"] = userName ctx.Data["Reponame"] = repoName ctx.Data["IsImageFile"] = commit.IsImageFile ctx.Data["Title"] = commit.Summary() + " · " + base.ShortSha(commitID) ctx.Data["Commit"] = commit ctx.Data["Author"] = models.ValidateCommitWithEmail(commit) ctx.Data["Diff"] = diff ctx.Data["Parents"] = parents ctx.Data["DiffNotAvailable"] = diff.NumFiles() == 0 ctx.Data["SourcePath"] = setting.AppSubUrl + "/" + path.Join(userName, repoName, "src", commitID) if commit.ParentCount() > 0 { ctx.Data["BeforeSourcePath"] = setting.AppSubUrl + "/" + path.Join(userName, repoName, "src", parents[0]) } ctx.Data["RawPath"] = setting.AppSubUrl + "/" + path.Join(userName, repoName, "raw", commitID) ctx.HTML(200, DIFF) }
func Email2User(ctx *context.Context) { u, err := models.GetUserByEmail(ctx.Query("email")) if err != nil { if models.IsErrUserNotExist(err) { ctx.Handle(404, "GetUserByEmail", err) } else { ctx.Handle(500, "GetUserByEmail", err) } return } ctx.Redirect(setting.AppSubUrl + "/user/" + u.Name) }
func ResetPasswd(ctx *context.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 Activate(ctx *context.Context) { code := ctx.Query("code") if len(code) == 0 { ctx.Data["IsActivatePage"] = true if ctx.User.IsActive { ctx.Error(404) return } // Resend confirmation email. if setting.Service.RegisterEmailConfirm { if ctx.Cache.IsExist("MailResendLimit_" + ctx.User.LowerName) { ctx.Data["ResendLimited"] = true } else { ctx.Data["Hours"] = setting.Service.ActiveCodeLives / 60 models.SendActivateAccountMail(ctx.Context, 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 models.IsErrUserNotExist(err) { 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(setting.AppSubUrl + "/") return } ctx.Data["IsActivateFailed"] = true ctx.HTML(200, ACTIVATE) }
func Migrate(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("new_migrate") ctx.Data["private"] = ctx.User.LastRepoVisibility ctx.Data["IsForcedPrivate"] = setting.Repository.ForcePrivate ctx.Data["mirror"] = ctx.Query("mirror") == "1" ctxUser := checkContextUser(ctx, ctx.QueryInt64("org")) if ctx.Written() { return } ctx.Data["ContextUser"] = ctxUser ctx.HTML(200, MIGRATE) }
func Dashboard(ctx *context.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_INACTIVATE_USER: success = ctx.Tr("admin.dashboard.delete_inactivate_accounts_success") err = models.DeleteInactivateUsers() case CLEAN_REPO_ARCHIVES: success = ctx.Tr("admin.dashboard.delete_repo_archives_success") err = models.DeleteRepositoryArchives() case CLEAN_MISSING_REPOS: success = ctx.Tr("admin.dashboard.delete_missing_repos_success") err = models.DeleteMissingRepositories() case GIT_GC_REPOS: success = ctx.Tr("admin.dashboard.git_gc_repos_success") err = models.GitGcRepos() case SYNC_SSH_AUTHORIZED_KEY: success = ctx.Tr("admin.dashboard.resync_all_sshkeys_success") err = models.RewriteAllPublicKeys() case SYNC_REPOSITORY_UPDATE_HOOK: success = ctx.Tr("admin.dashboard.resync_all_update_hooks_success") err = models.RewriteRepositoryUpdateHook() case REINIT_MISSING_REPOSITORY: success = ctx.Tr("admin.dashboard.reinit_missing_repos_success") err = models.ReinitMissingRepositories() } if err != nil { ctx.Flash.Error(err.Error()) } else { ctx.Flash.Success(success) } ctx.Redirect(setting.AppSubUrl + "/admin") return } ctx.Data["Stats"] = models.GetStatistic() // FIXME: update periodically updateSystemStatus() ctx.Data["SysStatus"] = sysStatus ctx.HTML(200, DASHBOARD) }
func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) { page := ctx.QueryInt("page") if page <= 0 { page = 1 } var ( repos []*models.Repository count int64 err error ) keyword := ctx.Query("q") if len(keyword) == 0 { repos, err = opts.Ranger(page, opts.PageSize) if err != nil { ctx.Handle(500, "opts.Ranger", err) return } count = opts.Counter(opts.Private) } else { repos, count, err = models.SearchRepositoryByName(&models.SearchRepoOptions{ Keyword: keyword, OrderBy: opts.OrderBy, Private: opts.Private, Page: page, PageSize: opts.PageSize, }) if err != nil { ctx.Handle(500, "SearchRepositoryByName", err) return } } ctx.Data["Keyword"] = keyword ctx.Data["Total"] = count ctx.Data["Page"] = paginater.New(int(count), opts.PageSize, page, 5) for _, repo := range repos { if err = repo.GetOwner(); err != nil { ctx.Handle(500, "GetOwner", fmt.Errorf("%d: %v", repo.ID, err)) return } } ctx.Data["Repos"] = repos ctx.HTML(200, opts.TplName) }
func CompareDiff(ctx *context.Context) { ctx.Data["IsRepoToolbarCommits"] = true ctx.Data["IsDiffCompare"] = true userName := ctx.Repo.Owner.Name repoName := ctx.Repo.Repository.Name beforeCommitID := ctx.Params(":before") afterCommitID := ctx.Params(":after") commit, err := ctx.Repo.GitRepo.GetCommit(afterCommitID) if err != nil { ctx.Handle(404, "GetCommit", err) return } diff, err := models.GetDiffRange(models.RepoPath(userName, repoName), beforeCommitID, afterCommitID, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles) if err != nil { ctx.Handle(404, "GetDiffRange", err) return } commits, err := commit.CommitsBeforeUntil(beforeCommitID) if err != nil { ctx.Handle(500, "CommitsBeforeUntil", err) return } commits = models.ValidateCommitsWithEmails(commits) ctx.Data["IsSplitStyle"] = ctx.Query("style") == "split" ctx.Data["CommitRepoLink"] = ctx.Repo.RepoLink ctx.Data["Commits"] = commits ctx.Data["CommitCount"] = commits.Len() ctx.Data["BeforeCommitID"] = beforeCommitID ctx.Data["AfterCommitID"] = afterCommitID ctx.Data["Username"] = userName ctx.Data["Reponame"] = repoName ctx.Data["IsImageFile"] = commit.IsImageFile ctx.Data["Title"] = "Comparing " + base.ShortSha(beforeCommitID) + "..." + base.ShortSha(afterCommitID) + " · " + userName + "/" + repoName ctx.Data["Commit"] = commit ctx.Data["Diff"] = diff ctx.Data["DiffNotAvailable"] = diff.NumFiles() == 0 ctx.Data["SourcePath"] = setting.AppSubUrl + "/" + path.Join(userName, repoName, "src", afterCommitID) ctx.Data["BeforeSourcePath"] = setting.AppSubUrl + "/" + path.Join(userName, repoName, "src", beforeCommitID) ctx.Data["RawPath"] = setting.AppSubUrl + "/" + path.Join(userName, repoName, "raw", afterCommitID) ctx.HTML(200, DIFF) }
func ActivateEmail(ctx *context.Context) { code := ctx.Query("code") email_string := ctx.Query("email") // Verify code. if email := models.VerifyActiveEmailCode(code, email_string); email != nil { if err := email.Activate(); err != nil { ctx.Handle(500, "ActivateEmail", err) } log.Trace("Email activated: %s", email.Email) ctx.Flash.Success(ctx.Tr("settings.add_email_success")) } ctx.Redirect(setting.AppSubUrl + "/user/settings/email") return }
func ForgotPasswdPost(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("auth.forgot_password") if setting.MailService == nil { ctx.Handle(403, "ForgotPasswdPost", nil) return } ctx.Data["IsResetRequest"] = true email := ctx.Query("email") ctx.Data["Email"] = email u, err := models.GetUserByEmail(email) if err != nil { if models.IsErrUserNotExist(err) { ctx.Data["Hours"] = setting.Service.ActiveCodeLives / 60 ctx.Data["IsResetSent"] = true ctx.HTML(200, FORGOT_PASSWORD) return } else { ctx.Handle(500, "user.ResetPasswd(check existence)", err) } return } if !u.IsLocal() { ctx.Data["Err_Email"] = true ctx.RenderWithErr(ctx.Tr("auth.non_local_account"), FORGOT_PASSWORD, nil) return } if ctx.Cache.IsExist("MailResendLimit_" + u.LowerName) { ctx.Data["ResendLimited"] = true ctx.HTML(200, FORGOT_PASSWORD) return } models.SendResetPasswordMail(ctx.Context, 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["Hours"] = setting.Service.ActiveCodeLives / 60 ctx.Data["IsResetSent"] = true ctx.HTML(200, FORGOT_PASSWORD) }
func DeleteRepo(ctx *context.Context) { repo, err := models.GetRepositoryByID(ctx.QueryInt64("id")) if err != nil { ctx.Handle(500, "GetRepositoryByID", err) return } if err := models.DeleteRepository(repo.MustOwner().ID, repo.ID); err != nil { ctx.Handle(500, "DeleteRepository", err) return } log.Trace("Repository deleted: %s/%s", repo.MustOwner().Name, repo.Name) ctx.Flash.Success(ctx.Tr("repo.settings.deletion_success")) ctx.JSON(200, map[string]interface{}{ "redirect": setting.AppSubUrl + "/admin/repos?page=" + ctx.Query("page"), }) }
func GitHooksEditPost(ctx *context.Context) { name := ctx.Params(":name") hook, err := ctx.Repo.GitRepo.GetHook(name) if err != nil { if err == git.ErrNotValidHook { ctx.Handle(404, "GetHook", err) } else { ctx.Handle(500, "GetHook", err) } return } hook.Content = ctx.Query("content") if err = hook.Update(); err != nil { ctx.Handle(500, "hook.Update", err) return } ctx.Redirect(ctx.Repo.RepoLink + "/settings/hooks/git") }
func CollaborationPost(ctx *context.Context) { name := strings.ToLower(ctx.Query("collaborator")) if len(name) == 0 || ctx.Repo.Owner.LowerName == name { ctx.Redirect(setting.AppSubUrl + ctx.Req.URL.Path) return } u, err := models.GetUserByName(name) if err != nil { if models.IsErrUserNotExist(err) { ctx.Flash.Error(ctx.Tr("form.user_not_exist")) ctx.Redirect(setting.AppSubUrl + ctx.Req.URL.Path) } else { ctx.Handle(500, "GetUserByName", err) } return } // Organization is not allowed to be added as a collaborator. if u.IsOrganization() { ctx.Flash.Error(ctx.Tr("repo.settings.org_not_allowed_to_be_collaborator")) ctx.Redirect(setting.AppSubUrl + ctx.Req.URL.Path) return } // Check if user is organization member. if ctx.Repo.Owner.IsOrganization() && ctx.Repo.Owner.IsOrgMember(u.ID) { ctx.Flash.Info(ctx.Tr("repo.settings.user_is_org_member")) ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration") return } if err = ctx.Repo.Repository.AddCollaborator(u); err != nil { ctx.Handle(500, "AddCollaborator", err) return } if setting.Service.EnableNotifyMail { models.SendCollaboratorMail(u, ctx.User, ctx.Repo.Repository) } ctx.Flash.Success(ctx.Tr("repo.settings.add_collaborator_success")) ctx.Redirect(setting.AppSubUrl + ctx.Req.URL.Path) }
func Action(ctx *context.Context) { var err error switch ctx.Params(":action") { case "watch": err = models.WatchRepo(ctx.User.ID, ctx.Repo.Repository.ID, true) case "unwatch": err = models.WatchRepo(ctx.User.ID, ctx.Repo.Repository.ID, false) case "star": err = models.StarRepo(ctx.User.ID, ctx.Repo.Repository.ID, true) case "unstar": err = models.StarRepo(ctx.User.ID, ctx.Repo.Repository.ID, false) case "desc": // FIXME: this is not used if !ctx.Repo.IsOwner() { ctx.Error(404) return } ctx.Repo.Repository.Description = ctx.Query("desc") ctx.Repo.Repository.Website = ctx.Query("site") err = models.UpdateRepository(ctx.Repo.Repository, false) } if err != nil { ctx.Handle(500, fmt.Sprintf("Action (%s)", ctx.Params(":action")), err) return } redirectTo := ctx.Query("redirect_to") if len(redirectTo) == 0 { redirectTo = ctx.Repo.RepoLink } ctx.Redirect(redirectTo) }
func RenderUserSearch(ctx *context.Context, opts *UserSearchOptions) { page := ctx.QueryInt("page") if page <= 1 { page = 1 } var ( users []*models.User count int64 err error ) keyword := ctx.Query("q") if len(keyword) == 0 { users, err = opts.Ranger(page, opts.PageSize) if err != nil { ctx.Handle(500, "opts.Ranger", err) return } count = opts.Counter() } else { users, count, err = models.SearchUserByName(&models.SearchUserOptions{ Keyword: keyword, Type: opts.Type, OrderBy: opts.OrderBy, Page: page, PageSize: opts.PageSize, }) if err != nil { ctx.Handle(500, "SearchUserByName", err) return } } ctx.Data["Keyword"] = keyword ctx.Data["Total"] = count ctx.Data["Page"] = paginater.New(int(count), opts.PageSize, page, 5) ctx.Data["Users"] = users ctx.HTML(200, opts.TplName) }
func ResetPasswdPost(ctx *context.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(setting.AppSubUrl + "/user/login") return } ctx.Data["IsResetFailed"] = true ctx.HTML(200, RESET_PASSWORD) }
func Issues(ctx *context.Context) { isPullList := ctx.Params(":type") == "pulls" if isPullList { ctx.Data["Title"] = ctx.Tr("pull_requests") ctx.Data["PageIsPulls"] = true } else { ctx.Data["Title"] = ctx.Tr("issues") ctx.Data["PageIsIssues"] = true } ctxUser := getDashboardContextUser(ctx) if ctx.Written() { return } // Organization does not have view type and filter mode. var ( viewType string sortType = ctx.Query("sort") filterMode = models.FM_ALL assigneeID int64 posterID int64 ) if ctxUser.IsOrganization() { viewType = "all" } else { viewType = ctx.Query("type") types := []string{"assigned", "created_by"} if !com.IsSliceContainsStr(types, viewType) { viewType = "all" } switch viewType { case "assigned": filterMode = models.FM_ASSIGN assigneeID = ctxUser.ID case "created_by": filterMode = models.FM_CREATE posterID = ctxUser.ID } } repoID := ctx.QueryInt64("repo") isShowClosed := ctx.Query("state") == "closed" // Get repositories. var err error var repos []*models.Repository if ctxUser.IsOrganization() { repos, _, err = ctxUser.GetUserRepositories(ctx.User.ID, 1, ctxUser.NumRepos) if err != nil { ctx.Handle(500, "GetRepositories", err) return } } else { if err := ctxUser.GetRepositories(1, ctx.User.NumRepos); err != nil { ctx.Handle(500, "GetRepositories", err) return } repos = ctxUser.Repos } allCount := 0 repoIDs := make([]int64, 0, len(repos)) showRepos := make([]*models.Repository, 0, len(repos)) for _, repo := range repos { if (isPullList && repo.NumPulls == 0) || (!isPullList && (!repo.EnableIssues || repo.EnableExternalTracker || repo.NumIssues == 0)) { continue } repoIDs = append(repoIDs, repo.ID) if isPullList { allCount += repo.NumOpenPulls repo.NumOpenIssues = repo.NumOpenPulls repo.NumClosedIssues = repo.NumClosedPulls } else { allCount += repo.NumOpenIssues } if filterMode != models.FM_ALL { // Calculate repository issue count with filter mode. numOpen, numClosed := repo.IssueStats(ctxUser.ID, filterMode, isPullList) repo.NumOpenIssues, repo.NumClosedIssues = int(numOpen), int(numClosed) } if repo.ID == repoID || (isShowClosed && repo.NumClosedIssues > 0) || (!isShowClosed && repo.NumOpenIssues > 0) { showRepos = append(showRepos, repo) } } ctx.Data["Repos"] = showRepos issueStats := models.GetUserIssueStats(repoID, ctxUser.ID, repoIDs, filterMode, isPullList) issueStats.AllCount = int64(allCount) page := ctx.QueryInt("page") if page <= 1 { page = 1 } var total int if !isShowClosed { total = int(issueStats.OpenCount) } else { total = int(issueStats.ClosedCount) } ctx.Data["Page"] = paginater.New(total, setting.UI.IssuePagingNum, page, 5) // Get issues. issues, err := models.Issues(&models.IssuesOptions{ UserID: ctxUser.ID, AssigneeID: assigneeID, RepoID: repoID, PosterID: posterID, RepoIDs: repoIDs, Page: page, IsClosed: isShowClosed, IsPull: isPullList, SortType: sortType, }) if err != nil { ctx.Handle(500, "Issues", err) return } // Get posters and repository. for i := range issues { issues[i].Repo, err = models.GetRepositoryByID(issues[i].RepoID) if err != nil { ctx.Handle(500, "GetRepositoryByID", fmt.Errorf("[#%d]%v", issues[i].ID, err)) return } if err = issues[i].Repo.GetOwner(); err != nil { ctx.Handle(500, "GetOwner", fmt.Errorf("[#%d]%v", issues[i].ID, err)) return } } ctx.Data["Issues"] = issues ctx.Data["IssueStats"] = issueStats ctx.Data["ViewType"] = viewType ctx.Data["SortType"] = sortType ctx.Data["RepoID"] = repoID ctx.Data["IsShowClosed"] = isShowClosed if isShowClosed { ctx.Data["State"] = "closed" } else { ctx.Data["State"] = "open" } ctx.HTML(200, ISSUES) }
func HTTP(ctx *context.Context) { username := ctx.Params(":username") reponame := strings.TrimSuffix(ctx.Params(":reponame"), ".git") var isPull bool service := ctx.Query("service") if service == "git-receive-pack" || strings.HasSuffix(ctx.Req.URL.Path, "git-receive-pack") { isPull = false } else if service == "git-upload-pack" || strings.HasSuffix(ctx.Req.URL.Path, "git-upload-pack") { isPull = true } else { isPull = (ctx.Req.Method == "GET") } isWiki := false if strings.HasSuffix(reponame, ".wiki") { isWiki = true reponame = reponame[:len(reponame)-5] } repoUser, err := models.GetUserByName(username) if err != nil { if models.IsErrUserNotExist(err) { ctx.Handle(http.StatusNotFound, "GetUserByName", nil) } else { ctx.Handle(http.StatusInternalServerError, "GetUserByName", err) } return } repo, err := models.GetRepositoryByName(repoUser.ID, reponame) if err != nil { if models.IsErrRepoNotExist(err) { ctx.Handle(http.StatusNotFound, "GetRepositoryByName", nil) } else { ctx.Handle(http.StatusInternalServerError, "GetRepositoryByName", err) } return } // Only public pull don't need auth. isPublicPull := !repo.IsPrivate && isPull var ( askAuth = !isPublicPull || setting.Service.RequireSignInView authUser *models.User authUsername string authPasswd string ) // check access if askAuth { authHead := ctx.Req.Header.Get("Authorization") if len(authHead) == 0 { ctx.Resp.Header().Set("WWW-Authenticate", "Basic realm=\".\"") ctx.Error(http.StatusUnauthorized) return } auths := strings.Fields(authHead) // currently check basic auth // TODO: support digit auth // FIXME: middlewares/context.go did basic auth check already, // maybe could use that one. if len(auths) != 2 || auths[0] != "Basic" { ctx.HandleText(http.StatusUnauthorized, "no basic auth and digit auth") return } authUsername, authPasswd, err = base.BasicAuthDecode(auths[1]) if err != nil { ctx.HandleText(http.StatusUnauthorized, "no basic auth and digit auth") return } authUser, err = models.UserSignIn(authUsername, authPasswd) if err != nil { if !models.IsErrUserNotExist(err) { ctx.Handle(http.StatusInternalServerError, "UserSignIn error: %v", err) return } // Assume username now is a token. token, err := models.GetAccessTokenBySHA(authUsername) if err != nil { if models.IsErrAccessTokenNotExist(err) || models.IsErrAccessTokenEmpty(err) { ctx.HandleText(http.StatusUnauthorized, "invalid token") } else { ctx.Handle(http.StatusInternalServerError, "GetAccessTokenBySha", err) } return } token.Updated = time.Now() if err = models.UpdateAccessToken(token); err != nil { ctx.Handle(http.StatusInternalServerError, "UpdateAccessToken", err) } authUser, err = models.GetUserByID(token.UID) if err != nil { ctx.Handle(http.StatusInternalServerError, "GetUserByID", err) return } } if !isPublicPull { var tp = models.ACCESS_MODE_WRITE if isPull { tp = models.ACCESS_MODE_READ } has, err := models.HasAccess(authUser, repo, tp) if err != nil { ctx.Handle(http.StatusInternalServerError, "HasAccess", err) return } else if !has { if tp == models.ACCESS_MODE_READ { has, err = models.HasAccess(authUser, repo, models.ACCESS_MODE_WRITE) if err != nil { ctx.Handle(http.StatusInternalServerError, "HasAccess2", err) return } else if !has { ctx.HandleText(http.StatusForbidden, "User permission denied") return } } else { ctx.HandleText(http.StatusForbidden, "User permission denied") return } } if !isPull && repo.IsMirror { ctx.HandleText(http.StatusForbidden, "mirror repository is read-only") return } } } callback := func(rpc string, input []byte) { if rpc != "receive-pack" || isWiki { return } var lastLine int64 = 0 for { head := input[lastLine : lastLine+2] if head[0] == '0' && head[1] == '0' { size, err := strconv.ParseInt(string(input[lastLine+2:lastLine+4]), 16, 32) if err != nil { log.Error(4, "%v", err) return } if size == 0 { //fmt.Println(string(input[lastLine:])) break } line := input[lastLine : lastLine+size] idx := bytes.IndexRune(line, '\000') if idx > -1 { line = line[:idx] } fields := strings.Fields(string(line)) if len(fields) >= 3 { oldCommitId := fields[0][4:] newCommitId := fields[1] refFullName := fields[2] // FIXME: handle error. if err = models.PushUpdate(models.PushUpdateOptions{ RefFullName: refFullName, OldCommitID: oldCommitId, NewCommitID: newCommitId, PusherID: authUser.ID, PusherName: authUser.Name, RepoUserName: username, RepoName: reponame, }); err == nil { go models.AddTestPullRequestTask(authUser, repo.ID, strings.TrimPrefix(refFullName, git.BRANCH_PREFIX), true) } } lastLine = lastLine + size } else { break } } } HTTPBackend(ctx, &serviceConfig{ UploadPack: true, ReceivePack: true, OnSucceed: callback, })(ctx.Resp, ctx.Req.Request) runtime.GC() }
func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) { ctx.Data["Title"] = ctx.Tr("repo.settings") ctx.Data["PageIsSettingsOptions"] = true repo := ctx.Repo.Repository switch ctx.Query("action") { case "update": if ctx.HasError() { ctx.HTML(200, SETTINGS_OPTIONS) return } isNameChanged := false oldRepoName := repo.Name newRepoName := form.RepoName // Check if repository name has been changed. if repo.LowerName != strings.ToLower(newRepoName) { isNameChanged = true if err := models.ChangeRepositoryName(ctx.Repo.Owner, repo.Name, newRepoName); err != nil { ctx.Data["Err_RepoName"] = true switch { case models.IsErrRepoAlreadyExist(err): ctx.RenderWithErr(ctx.Tr("form.repo_name_been_taken"), SETTINGS_OPTIONS, &form) case models.IsErrNameReserved(err): ctx.RenderWithErr(ctx.Tr("repo.form.name_reserved", err.(models.ErrNameReserved).Name), SETTINGS_OPTIONS, &form) case models.IsErrNamePatternNotAllowed(err): ctx.RenderWithErr(ctx.Tr("repo.form.name_pattern_not_allowed", err.(models.ErrNamePatternNotAllowed).Pattern), SETTINGS_OPTIONS, &form) default: ctx.Handle(500, "ChangeRepositoryName", err) } return } log.Trace("Repository name changed: %s/%s -> %s", ctx.Repo.Owner.Name, repo.Name, newRepoName) } // In case it's just a case change. repo.Name = newRepoName repo.LowerName = strings.ToLower(newRepoName) if ctx.Repo.GitRepo.IsBranchExist(form.Branch) && repo.DefaultBranch != form.Branch { repo.DefaultBranch = form.Branch if err := ctx.Repo.GitRepo.SetDefaultBranch(form.Branch); err != nil { if !git.IsErrUnsupportedVersion(err) { ctx.Handle(500, "SetDefaultBranch", err) return } } } repo.Description = form.Description repo.Website = form.Website // Visibility of forked repository is forced sync with base repository. if repo.IsFork { form.Private = repo.BaseRepo.IsPrivate } visibilityChanged := repo.IsPrivate != form.Private repo.IsPrivate = form.Private if err := models.UpdateRepository(repo, visibilityChanged); err != nil { ctx.Handle(500, "UpdateRepository", err) return } log.Trace("Repository basic settings updated: %s/%s", ctx.Repo.Owner.Name, repo.Name) if isNameChanged { if err := models.RenameRepoAction(ctx.User, oldRepoName, repo); err != nil { log.Error(4, "RenameRepoAction: %v", err) } } ctx.Flash.Success(ctx.Tr("repo.settings.update_settings_success")) ctx.Redirect(repo.Link() + "/settings") case "mirror": if !repo.IsMirror { ctx.Handle(404, "", nil) return } if form.Interval > 0 { ctx.Repo.Mirror.EnablePrune = form.EnablePrune ctx.Repo.Mirror.Interval = form.Interval ctx.Repo.Mirror.NextUpdate = time.Now().Add(time.Duration(form.Interval) * time.Hour) if err := models.UpdateMirror(ctx.Repo.Mirror); err != nil { ctx.Handle(500, "UpdateMirror", err) return } } if err := ctx.Repo.Mirror.SaveAddress(form.MirrorAddress); err != nil { ctx.Handle(500, "SaveAddress", err) return } ctx.Flash.Success(ctx.Tr("repo.settings.update_settings_success")) ctx.Redirect(repo.Link() + "/settings") case "mirror-sync": if !repo.IsMirror { ctx.Handle(404, "", nil) return } go models.MirrorQueue.Add(repo.ID) ctx.Flash.Info(ctx.Tr("repo.settings.mirror_sync_in_progress")) ctx.Redirect(repo.Link() + "/settings") case "advanced": repo.EnableWiki = form.EnableWiki repo.EnableExternalWiki = form.EnableExternalWiki repo.ExternalWikiURL = form.ExternalWikiURL repo.EnableIssues = form.EnableIssues repo.EnableExternalTracker = form.EnableExternalTracker repo.ExternalTrackerURL = form.ExternalTrackerURL repo.ExternalTrackerFormat = form.TrackerURLFormat repo.ExternalTrackerStyle = form.TrackerIssueStyle repo.EnablePulls = form.EnablePulls if err := models.UpdateRepository(repo, false); err != nil { ctx.Handle(500, "UpdateRepository", err) return } log.Trace("Repository advanced settings updated: %s/%s", ctx.Repo.Owner.Name, repo.Name) ctx.Flash.Success(ctx.Tr("repo.settings.update_settings_success")) ctx.Redirect(ctx.Repo.RepoLink + "/settings") case "convert": if !ctx.Repo.IsOwner() { ctx.Error(404) return } if repo.Name != form.RepoName { ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_repo_name"), SETTINGS_OPTIONS, nil) return } if ctx.Repo.Owner.IsOrganization() { if !ctx.Repo.Owner.IsOwnedBy(ctx.User.ID) { ctx.Error(404) return } } if !repo.IsMirror { ctx.Error(404) return } repo.IsMirror = false if _, err := models.CleanUpMigrateInfo(repo); err != nil { ctx.Handle(500, "CleanUpMigrateInfo", err) return } else if err = models.DeleteMirrorByRepoID(ctx.Repo.Repository.ID); err != nil { ctx.Handle(500, "DeleteMirrorByRepoID", err) return } log.Trace("Repository converted from mirror to regular: %s/%s", ctx.Repo.Owner.Name, repo.Name) ctx.Flash.Success(ctx.Tr("repo.settings.convert_succeed")) ctx.Redirect(setting.AppSubUrl + "/" + ctx.Repo.Owner.Name + "/" + repo.Name) case "transfer": if !ctx.Repo.IsOwner() { ctx.Error(404) return } if repo.Name != form.RepoName { ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_repo_name"), SETTINGS_OPTIONS, nil) return } if ctx.Repo.Owner.IsOrganization() { if !ctx.Repo.Owner.IsOwnedBy(ctx.User.ID) { ctx.Error(404) return } } newOwner := ctx.Query("new_owner_name") isExist, err := models.IsUserExist(0, newOwner) if err != nil { ctx.Handle(500, "IsUserExist", err) return } else if !isExist { ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_owner_name"), SETTINGS_OPTIONS, nil) return } if err = models.TransferOwnership(ctx.User, newOwner, repo); err != nil { if models.IsErrRepoAlreadyExist(err) { ctx.RenderWithErr(ctx.Tr("repo.settings.new_owner_has_same_repo"), SETTINGS_OPTIONS, nil) } else { ctx.Handle(500, "TransferOwnership", err) } return } log.Trace("Repository transfered: %s/%s -> %s", ctx.Repo.Owner.Name, repo.Name, newOwner) ctx.Flash.Success(ctx.Tr("repo.settings.transfer_succeed")) ctx.Redirect(setting.AppSubUrl + "/" + newOwner + "/" + repo.Name) case "delete": if !ctx.Repo.IsOwner() { ctx.Error(404) return } if repo.Name != form.RepoName { ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_repo_name"), SETTINGS_OPTIONS, nil) return } if ctx.Repo.Owner.IsOrganization() { if !ctx.Repo.Owner.IsOwnedBy(ctx.User.ID) { ctx.Error(404) return } } if err := models.DeleteRepository(ctx.Repo.Owner.ID, repo.ID); err != nil { ctx.Handle(500, "DeleteRepository", err) return } log.Trace("Repository deleted: %s/%s", ctx.Repo.Owner.Name, repo.Name) ctx.Flash.Success(ctx.Tr("repo.settings.deletion_success")) ctx.Redirect(ctx.Repo.Owner.DashboardLink()) case "delete-wiki": if !ctx.Repo.IsOwner() { ctx.Error(404) return } if repo.Name != form.RepoName { ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_repo_name"), SETTINGS_OPTIONS, nil) return } if ctx.Repo.Owner.IsOrganization() { if !ctx.Repo.Owner.IsOwnedBy(ctx.User.ID) { ctx.Error(404) return } } repo.DeleteWiki() log.Trace("Repository wiki deleted: %s/%s", ctx.Repo.Owner.Name, repo.Name) repo.EnableWiki = false if err := models.UpdateRepository(repo, false); err != nil { ctx.Handle(500, "UpdateRepository", err) return } ctx.Flash.Success(ctx.Tr("repo.settings.wiki_deletion_success")) ctx.Redirect(ctx.Repo.RepoLink + "/settings") default: ctx.Handle(404, "", nil) } }
func TeamsAction(ctx *context.Context) { uid := com.StrTo(ctx.Query("uid")).MustInt64() if uid == 0 { ctx.Redirect(ctx.Org.OrgLink + "/teams") return } page := ctx.Query("page") var err error switch ctx.Params(":action") { case "join": if !ctx.Org.IsOwner { ctx.Error(404) return } err = ctx.Org.Team.AddMember(ctx.User.ID) case "leave": err = ctx.Org.Team.RemoveMember(ctx.User.ID) case "remove": if !ctx.Org.IsOwner { ctx.Error(404) return } err = ctx.Org.Team.RemoveMember(uid) page = "team" case "add": if !ctx.Org.IsOwner { ctx.Error(404) return } uname := ctx.Query("uname") var u *models.User u, err = models.GetUserByName(uname) if err != nil { if models.IsErrUserNotExist(err) { ctx.Flash.Error(ctx.Tr("form.user_not_exist")) ctx.Redirect(ctx.Org.OrgLink + "/teams/" + ctx.Org.Team.LowerName) } else { ctx.Handle(500, " GetUserByName", err) } return } err = ctx.Org.Team.AddMember(u.ID) page = "team" } if err != nil { if models.IsErrLastOrgOwner(err) { ctx.Flash.Error(ctx.Tr("form.last_org_owner")) } else { log.Error(3, "Action(%s): %v", ctx.Params(":action"), err) ctx.JSON(200, map[string]interface{}{ "ok": false, "err": err.Error(), }) return } } switch page { case "team": ctx.Redirect(ctx.Org.OrgLink + "/teams/" + ctx.Org.Team.LowerName) default: ctx.Redirect(ctx.Org.OrgLink + "/teams") } }