func DeleteUser(ctx *middleware.Context) { uid := com.StrTo(ctx.Params(":userid")).MustInt64() if uid == 0 { ctx.Handle(404, "DeleteUser", nil) return } u, err := models.GetUserByID(uid) if err != nil { ctx.Handle(500, "GetUserByID", err) return } if err = models.DeleteUser(u); err != nil { switch { case models.IsErrUserOwnRepos(err): ctx.Flash.Error(ctx.Tr("admin.users.still_own_repo")) ctx.Redirect(setting.AppSubUrl + "/admin/users/" + ctx.Params(":userid")) case models.IsErrUserHasOrgs(err): ctx.Flash.Error(ctx.Tr("admin.users.still_has_org")) ctx.Redirect(setting.AppSubUrl + "/admin/users/" + ctx.Params(":userid")) default: ctx.Handle(500, "DeleteUser", err) } return } log.Trace("Account deleted by admin(%s): %s", ctx.User.Name, u.Name) ctx.Redirect(setting.AppSubUrl + "/admin/users") }
func EditUser(ctx *middleware.Context) { ctx.Data["Title"] = ctx.Tr("admin.users.edit_account") ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminUsers"] = true uid := com.StrTo(ctx.Params(":userid")).MustInt64() if uid == 0 { ctx.Handle(404, "EditUser", nil) return } u, err := models.GetUserByID(uid) if err != nil { ctx.Handle(500, "GetUserByID", err) return } ctx.Data["User"] = u auths, err := models.GetAuths() if err != nil { ctx.Handle(500, "GetAuths", err) return } ctx.Data["LoginSources"] = auths ctx.HTML(200, USER_EDIT) }
func TriggerTask(ctx *context.Context) { pusherID := ctx.QueryInt64("pusher") branch := ctx.Query("branch") secret := ctx.Query("secret") if len(branch) == 0 || len(secret) == 0 || pusherID <= 0 { ctx.Error(404) log.Trace("TriggerTask: branch or secret is empty, or pusher ID is not valid") return } owner, repo := parseOwnerAndRepo(ctx) if ctx.Written() { return } if secret != base.EncodeMD5(owner.Salt) { ctx.Error(404) log.Trace("TriggerTask [%s/%s]: invalid secret", owner.Name, repo.Name) return } pusher, err := models.GetUserByID(pusherID) if err != nil { if models.IsErrUserNotExist(err) { ctx.Error(404) } else { ctx.Handle(500, "GetUserByID", err) } return } log.Trace("TriggerTask '%s/%s' by %s", repo.Name, branch, pusher.Name) go models.HookQueue.Add(repo.ID) go models.AddTestPullRequestTask(pusher, repo.ID, branch, true) ctx.Status(202) }
func prepareUserInfo(ctx *context.Context) *models.User { u, err := models.GetUserByID(ctx.ParamsInt64(":userid")) if err != nil { ctx.Handle(500, "GetUserByID", err) return nil } ctx.Data["User"] = u if u.LoginSource > 0 { ctx.Data["LoginSource"], err = models.GetLoginSourceByID(u.LoginSource) if err != nil { ctx.Handle(500, "GetLoginSourceByID", err) return nil } } else { ctx.Data["LoginSource"] = &models.LoginSource{} } sources, err := models.LoginSources() if err != nil { ctx.Handle(500, "LoginSources", err) return nil } ctx.Data["Sources"] = sources return u }
func checkContextUser(ctx *context.Context, uid int64) *models.User { orgs, err := models.GetOwnedOrgsByUserIDDesc(ctx.User.ID, "updated_unix") if err != nil { ctx.Handle(500, "GetOwnedOrgsByUserIDDesc", err) return nil } ctx.Data["Orgs"] = orgs // Not equal means current user is an organization. if uid == ctx.User.ID || uid == 0 { return ctx.User } org, err := models.GetUserByID(uid) if models.IsErrUserNotExist(err) { return ctx.User } if err != nil { ctx.Handle(500, "GetUserByID", fmt.Errorf("[%d]: %v", uid, err)) return nil } // Check ownership of organization. if !org.IsOrganization() || !(ctx.User.IsAdmin || org.IsOwnedBy(ctx.User.ID)) { ctx.Error(403) return nil } return org }
// SendIssueNotifyMail sends mail notification of all watchers of repository. func SendIssueNotifyMail(u, owner *models.User, repo *models.Repository, issue *models.Issue) ([]string, error) { ws, err := models.GetWatchers(repo.ID) if err != nil { return nil, errors.New("mail.NotifyWatchers(GetWatchers): " + err.Error()) } tos := make([]string, 0, len(ws)) for i := range ws { uid := ws[i].UserID if u.Id == uid { continue } u, err := models.GetUserByID(uid) if err != nil { return nil, errors.New("mail.NotifyWatchers(GetUserById): " + err.Error()) } tos = append(tos, u.Email) } if len(tos) == 0 { return tos, nil } subject := fmt.Sprintf("[%s] %s(#%d)", repo.Name, issue.Name, issue.Index) content := fmt.Sprintf("%s<br>-<br> <a href=\"%s%s/%s/issues/%d\">View it on Gogs</a>.", base.RenderSpecialLink([]byte(issue.Content), owner.Name+"/"+repo.Name), setting.AppUrl, owner.Name, repo.Name, issue.Index) msg := NewMailMessageFrom(tos, u.Email, subject, content) msg.Info = fmt.Sprintf("Subject: %s, send issue notify emails", subject) SendAsync(&msg) return tos, nil }
func DeleteUser(ctx *context.Context) { u, err := models.GetUserByID(ctx.ParamsInt64(":userid")) if err != nil { ctx.Handle(500, "GetUserByID", err) return } if err = models.DeleteUser(u); err != nil { switch { case models.IsErrUserOwnRepos(err): ctx.Flash.Error(ctx.Tr("admin.users.still_own_repo")) ctx.JSON(200, map[string]interface{}{ "redirect": setting.AppSubUrl + "/admin/users/" + ctx.Params(":userid"), }) case models.IsErrUserHasOrgs(err): ctx.Flash.Error(ctx.Tr("admin.users.still_has_org")) ctx.JSON(200, map[string]interface{}{ "redirect": setting.AppSubUrl + "/admin/users/" + ctx.Params(":userid"), }) default: ctx.Handle(500, "DeleteUser", err) } return } log.Trace("Account deleted by admin (%s): %s", ctx.User.Name, u.Name) ctx.Flash.Success(ctx.Tr("admin.users.deletion_success")) ctx.JSON(200, map[string]interface{}{ "redirect": setting.AppSubUrl + "/admin/users", }) }
func checkContextUser(ctx *middleware.Context, uid int64) *models.User { if err := ctx.User.GetOrganizations(); err != nil { ctx.Handle(500, "GetOrganizations", err) return nil } ctx.Data["Orgs"] = ctx.User.Orgs // Not equal means current user is an organization. if uid == ctx.User.Id || uid == 0 { return ctx.User } org, err := models.GetUserByID(uid) if models.IsErrUserNotExist(err) { return ctx.User } if err != nil { ctx.Handle(500, "checkContextUser", fmt.Errorf("GetUserById(%d): %v", uid, err)) return nil } // Check ownership of organization. if !org.IsOrganization() || !org.IsOwnedBy(ctx.User.Id) { ctx.Error(403) return nil } return org }
// https://github.com/gogits/go-gogs-client/wiki/Repositories#search-repositories func Search(ctx *context.APIContext) { opts := &models.SearchRepoOptions{ Keyword: path.Base(ctx.Query("q")), OwnerID: com.StrTo(ctx.Query("uid")).MustInt64(), PageSize: com.StrTo(ctx.Query("limit")).MustInt(), } if opts.PageSize == 0 { opts.PageSize = 10 } // Check visibility. if ctx.IsSigned && opts.OwnerID > 0 { if ctx.User.Id == opts.OwnerID { opts.Private = true } else { u, err := models.GetUserByID(opts.OwnerID) if err != nil { ctx.JSON(500, map[string]interface{}{ "ok": false, "error": err.Error(), }) return } if u.IsOrganization() && u.IsOwnedBy(ctx.User.Id) { opts.Private = true } // FIXME: how about collaborators? } } repos, _, err := models.SearchRepositoryByName(opts) if err != nil { ctx.JSON(500, map[string]interface{}{ "ok": false, "error": err.Error(), }) return } results := make([]*api.Repository, 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] = &api.Repository{ ID: repos[i].ID, FullName: path.Join(repos[i].Owner.Name, repos[i].Name), } } ctx.JSON(200, map[string]interface{}{ "ok": true, "data": results, }) }
func EditUserPost(ctx *middleware.Context, form auth.AdminEditUserForm) { ctx.Data["Title"] = ctx.Tr("admin.users.edit_account") ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminUsers"] = true uid := com.StrTo(ctx.Params(":userid")).MustInt64() if uid == 0 { ctx.Handle(404, "EditUser", nil) return } u, err := models.GetUserByID(uid) if err != nil { ctx.Handle(500, "GetUserById", err) return } ctx.Data["User"] = u if ctx.HasError() { ctx.HTML(200, USER_EDIT) return } // FIXME: need password length check if len(form.Password) > 0 { u.Passwd = form.Password u.Salt = models.GetUserSalt() u.EncodePasswd() } u.FullName = form.FullName u.Email = form.Email u.Website = form.Website u.Location = form.Location if len(form.Avatar) == 0 { form.Avatar = form.Email } u.Avatar = base.EncodeMd5(form.Avatar) u.AvatarEmail = form.Avatar u.IsActive = form.Active u.IsAdmin = form.Admin u.AllowGitHook = form.AllowGitHook if err := models.UpdateUser(u); err != nil { if models.IsErrEmailAlreadyUsed(err) { ctx.Data["Err_Email"] = true ctx.RenderWithErr(ctx.Tr("form.email_been_used"), USER_EDIT, &form) } else { ctx.Handle(500, "UpdateUser", err) } return } log.Trace("Account profile updated by admin(%s): %s", ctx.User.Name, u.Name) ctx.Flash.Success(ctx.Tr("admin.users.update_profile_success")) ctx.Redirect(setting.AppSubUrl + "/admin/users/" + ctx.Params(":userid")) }
// SignedInID returns the id of signed in user. func SignedInID(ctx *macaron.Context, sess session.Store) int64 { if !models.HasEngine { return 0 } // Check access token. if IsAPIPath(ctx.Req.URL.Path) { tokenSHA := ctx.Query("token") if len(tokenSHA) == 0 { // Well, check with header again. auHead := ctx.Req.Header.Get("Authorization") if len(auHead) > 0 { auths := strings.Fields(auHead) if len(auths) == 2 && auths[0] == "token" { tokenSHA = auths[1] } } } // Let's see if token is valid. if len(tokenSHA) > 0 { t, err := models.GetAccessTokenBySHA(tokenSHA) if err != nil { if models.IsErrAccessTokenNotExist(err) { log.Error(4, "GetAccessTokenBySHA: %v", err) } return 0 } t.Updated = time.Now() if err = models.UpdateAccessToekn(t); err != nil { log.Error(4, "UpdateAccessToekn: %v", err) } return t.UID } } uid := sess.Get("uid") if uid == nil { return 0 } if id, ok := uid.(int64); ok { if _, err := models.GetUserByID(id); err != nil { if !models.IsErrUserNotExist(err) { log.Error(4, "GetUserById: %v", err) } return 0 } return id } return 0 }
// SignedInId returns the id of signed in user. func SignedInId(req *http.Request, sess session.Store) int64 { if !models.HasEngine { return 0 } // API calls need to check access token. if IsAPIPath(req.URL.Path) { auHead := req.Header.Get("Authorization") if len(auHead) > 0 { auths := strings.Fields(auHead) if len(auths) == 2 && auths[0] == "token" { t, err := models.GetAccessTokenBySHA(auths[1]) if err != nil { if err != models.ErrAccessTokenNotExist { log.Error(4, "GetAccessTokenBySHA: %v", err) } return 0 } t.Updated = time.Now() if err = models.UpdateAccessToekn(t); err != nil { log.Error(4, "UpdateAccessToekn: %v", err) } return t.UID } } } uid := sess.Get("uid") if uid == nil { return 0 } if id, ok := uid.(int64); ok { if _, err := models.GetUserByID(id); err != nil { if !models.IsErrUserNotExist(err) { log.Error(4, "GetUserById: %v", err) } return 0 } return id } return 0 }
func checkContextUser(ctx *middleware.Context, uid int64) *models.User { // Not equal means current user is an organization. if uid == ctx.User.Id || uid == 0 { return ctx.User } org, err := models.GetUserByID(uid) if models.IsErrUserNotExist(err) { return ctx.User } if err != nil { ctx.Handle(500, "checkContextUser", fmt.Errorf("GetUserById(%d): %v", uid, err)) return nil } else if !org.IsOrganization() { ctx.Error(403) return nil } return org }
func ReleaseByName(ctx *middleware.Context) { rel, err := models.GetRelease(ctx.Repo.Repository.ID, ctx.Params(":release")) if err != nil { log.Error(4, "GetRelease: %v", err) ctx.Status(500) return } publisher, err := models.GetUserByID(rel.PublisherID) if err != nil { if models.IsErrUserNotExist(err) { publisher = models.NewFakeUser() } else { ctx.Handle(422, "GetUserByID", err) return } } rel.Publisher = publisher ctx.JSON(200, ToApiRelease(rel)) }
// SendIssueNotifyMail sends mail notification of all watchers of repository. func SendIssueNotifyMail(u, owner *models.User, repo *models.Repository, issue *models.Issue) ([]string, error) { ws, err := models.GetWatchers(repo.ID) if err != nil { return nil, fmt.Errorf("GetWatchers[%d]: %v", repo.ID, err) } tos := make([]string, 0, len(ws)) for i := range ws { uid := ws[i].UserID if u.Id == uid { continue } to, err := models.GetUserByID(uid) if err != nil { return nil, fmt.Errorf("GetUserByID: %v", err) } if to.IsOrganization() { continue } tos = append(tos, to.Email) } if len(tos) == 0 { return tos, nil } subject := fmt.Sprintf("[%s] %s (#%d)", repo.Name, issue.Name, issue.Index) content := fmt.Sprintf("%s<br>-<br> <a href=\"%s%s/%s/issues/%d\">View it on Gogs</a>.", base.RenderSpecialLink([]byte(issue.Content), owner.Name+"/"+repo.Name, repo.ComposeMetas()), setting.AppUrl, owner.Name, repo.Name, issue.Index) msg := NewMessage(tos, subject, content) msg.Info = fmt.Sprintf("Subject: %s, issue notify", subject) SendAsync(msg) return tos, nil }
func ViewIssue(ctx *middleware.Context) { ctx.Data["AttachmentsEnabled"] = setting.AttachmentEnabled idx := com.StrTo(ctx.Params(":index")).MustInt64() if idx == 0 { ctx.Handle(404, "issue.ViewIssue", nil) return } issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, idx) if err != nil { if err == models.ErrIssueNotExist { ctx.Handle(404, "GetIssueByIndex", err) } else { ctx.Handle(500, "GetIssueByIndex", err) } return } // Get labels. if err = issue.GetLabels(); err != nil { ctx.Handle(500, "GetLabels", err) return } labels, err := models.GetLabelsByRepoID(ctx.Repo.Repository.ID) if err != nil { ctx.Handle(500, "GetLabels.2", err) return } checkLabels(issue.Labels, labels) ctx.Data["Labels"] = labels // Get assigned milestone. if issue.MilestoneID > 0 { ctx.Data["Milestone"], err = models.GetMilestoneByID(issue.MilestoneID) if err != nil { if models.IsErrMilestoneNotExist(err) { log.Warn("GetMilestoneById: %v", err) } else { ctx.Handle(500, "GetMilestoneById", err) return } } } // Get all milestones. ctx.Data["OpenMilestones"], err = models.GetMilestones(ctx.Repo.Repository.ID, -1, false) if err != nil { ctx.Handle(500, "GetMilestones.1: %v", err) return } ctx.Data["ClosedMilestones"], err = models.GetMilestones(ctx.Repo.Repository.ID, -1, true) if err != nil { ctx.Handle(500, "GetMilestones.2: %v", err) return } // Get all collaborators. ctx.Data["Collaborators"], err = ctx.Repo.Repository.GetCollaborators() if err != nil { ctx.Handle(500, "GetCollaborators", err) return } if ctx.IsSigned { // Update issue-user. if err = models.UpdateIssueUserPairByRead(ctx.User.Id, issue.ID); err != nil { ctx.Handle(500, "UpdateIssueUserPairByRead: %v", err) return } } // Get poster and Assignee. if err = issue.GetPoster(); err != nil { ctx.Handle(500, "GetPoster: %v", err) return } else if err = issue.GetAssignee(); err != nil { ctx.Handle(500, "GetAssignee: %v", err) return } issue.RenderedContent = string(base.RenderMarkdown([]byte(issue.Content), ctx.Repo.RepoLink)) // Get comments. comments, err := models.GetIssueComments(issue.ID) if err != nil { ctx.Handle(500, "GetIssueComments: %v", err) return } // Get posters. for i := range comments { u, err := models.GetUserByID(comments[i].PosterId) if err != nil { ctx.Handle(500, "GetUserById.2: %v", err) return } comments[i].Poster = u if comments[i].Type == models.COMMENT_TYPE_COMMENT { comments[i].Content = string(base.RenderMarkdown([]byte(comments[i].Content), ctx.Repo.RepoLink)) } } ctx.Data["AllowedTypes"] = setting.AttachmentAllowedTypes ctx.Data["Title"] = issue.Name ctx.Data["Issue"] = issue ctx.Data["Comments"] = comments ctx.Data["IsIssueOwner"] = ctx.Repo.IsOwner() || (ctx.IsSigned && issue.PosterID == ctx.User.Id) ctx.Data["IsRepoToolbarIssues"] = true ctx.Data["IsRepoToolbarIssuesList"] = false ctx.HTML(200, ISSUE_VIEW) }
// SignedInUser returns the user object of signed user. // It returns a bool value to indicate whether user uses basic auth or not. func SignedInUser(ctx *macaron.Context, sess session.Store) (*models.User, bool) { if !models.HasEngine { return nil, false } uid := SignedInID(ctx, sess) if uid <= 0 { if setting.Service.EnableReverseProxyAuth { sandstormId := ctx.Req.Header.Get(setting.ReverseProxyAuthUser) if len(sandstormId) > 0 { u, err := models.GetUserBySandstormID(sandstormId) if err != nil { if !models.IsErrSandstormUserNotExist(err) { log.Error(4, "GetUserBySandstormID: %v", err) return nil, false } // Check if enabled auto-registration. if setting.Service.EnableReverseProxyAutoRegister { randomDigit := func() string { return string(rune('0' + rand.Intn(10))) } password := "" for i := 0; i < 16; i++ { password += randomDigit() } handle := ctx.Req.Header.Get("X-Sandstorm-Preferred-Handle") if len(handle) == 0 { handle = "gogsuser" } avatarLink := ctx.Req.Header.Get("X-Sandstorm-User-Picture") if len(avatarLink) == 0 { avatarLink = "mailto:" + sandstormId } for suffix := ""; len(suffix) < 5; suffix += randomDigit() { u := &models.User{ SandstormId: sandstormId, SandstormAvatar: avatarLink, Name: handle + suffix, Email: gouuid.NewV4().String() + "@localhost", Passwd: password, IsActive: true, } err = models.CreateUser(u) if err == nil { return u, false } } // FIXME: should I create a system notice? log.Error(4, "CreateUser: %v", err) return nil, false } } newAvatar := ctx.Req.Header.Get("X-Sandstorm-User-Picture") if len(newAvatar) == 0 { newAvatar = "mailto:" + sandstormId } if u.SandstormAvatar != newAvatar { u.SandstormAvatar = newAvatar models.UpdateUser(u) } return u, false } } // Check with basic auth. baHead := ctx.Req.Header.Get("Authorization") if len(baHead) > 0 { auths := strings.Fields(baHead) if len(auths) == 2 && auths[0] == "Basic" { uname, passwd, _ := base.BasicAuthDecode(auths[1]) u, err := models.UserSignIn(uname, passwd) if err != nil { if !models.IsErrUserNotExist(err) { log.Error(4, "UserSignIn: %v", err) } return nil, false } return u, true } } return nil, false } u, err := models.GetUserByID(uid) if err != nil { log.Error(4, "GetUserById: %v", err) return nil, false } return u, false }
func Http(ctx *middleware.Context) { username := ctx.Params(":username") reponame := ctx.Params(":reponame") if strings.HasSuffix(reponame, ".git") { reponame = reponame[:len(reponame)-4] } 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") } repoUser, err := models.GetUserByName(username) if err != nil { if models.IsErrUserNotExist(err) { ctx.Handle(404, "GetUserByName", nil) } else { ctx.Handle(500, "GetUserByName", err) } return } repo, err := models.GetRepositoryByName(repoUser.Id, reponame) if err != nil { if models.IsErrRepoNotExist(err) { ctx.Handle(404, "GetRepositoryByName", nil) } else { ctx.Handle(500, "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 { baHead := ctx.Req.Header.Get("Authorization") if baHead == "" { authRequired(ctx) return } auths := strings.Fields(baHead) // 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(401, "no basic auth and digit auth") return } authUsername, authPasswd, err = base.BasicAuthDecode(auths[1]) if err != nil { ctx.HandleText(401, "no basic auth and digit auth") return } authUser, err = models.UserSignIn(authUsername, authPasswd) if err != nil { if !models.IsErrUserNotExist(err) { ctx.Handle(500, "UserSignIn error: %v", err) return } // Assume username now is a token. token, err := models.GetAccessTokenBySha(authUsername) if err != nil { if err == models.ErrAccessTokenNotExist { ctx.HandleText(401, "invalid token") } else { ctx.Handle(500, "GetAccessTokenBySha", err) } return } authUser, err = models.GetUserByID(token.UID) if err != nil { ctx.Handle(500, "GetUserById", err) return } authUsername = authUser.Name } 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.HandleText(401, "no basic auth and digit auth") return } else if !has { if tp == models.ACCESS_MODE_READ { has, err = models.HasAccess(authUser, repo, models.ACCESS_MODE_WRITE) if err != nil || !has { ctx.HandleText(401, "no basic auth and digit auth") return } } else { ctx.HandleText(401, "no basic auth and digit auth") return } } if !isPull && repo.IsMirror { ctx.HandleText(401, "can't push to mirror") return } } } callback := func(rpc string, input []byte) { if rpc == "receive-pack" { 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] refName := fields[2] // FIXME: handle error. if err = models.Update(refName, oldCommitId, newCommitId, authUsername, username, reponame, authUser.Id); err == nil { models.HookQueue.AddRepoID(repo.ID) } } lastLine = lastLine + size } else { break } } } } HTTPBackend(&Config{ RepoRootPath: setting.RepoRootPath, GitBinPath: "git", UploadPack: true, ReceivePack: true, OnSucceed: callback, })(ctx.Resp, ctx.Req.Request) runtime.GC() }
func Releases(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("repo.release.releases") ctx.Data["PageIsReleaseList"] = true rawTags, err := ctx.Repo.GitRepo.GetTags() if err != nil { ctx.Handle(500, "GetTags", err) return } releases, err := models.GetReleasesByRepoID(ctx.Repo.Repository.ID) if err != nil { ctx.Handle(500, "GetReleasesByRepoID", err) return } // Temproray cache commits count of used branches to speed up. countCache := make(map[string]int64) tags := make([]*models.Release, len(rawTags)) for i, rawTag := range rawTags { for j, r := range releases { if r == nil || (r.IsDraft && !ctx.Repo.IsOwner()) { continue } if r.TagName == rawTag { r.Publisher, err = models.GetUserByID(r.PublisherID) if err != nil { if models.IsErrUserNotExist(err) { r.Publisher = models.NewGhostUser() } else { ctx.Handle(500, "GetUserByID", err) return } } if err := calReleaseNumCommitsBehind(ctx.Repo, r, countCache); err != nil { ctx.Handle(500, "calReleaseNumCommitsBehind", err) return } r.Note = markdown.RenderString(r.Note, ctx.Repo.RepoLink, ctx.Repo.Repository.ComposeMetas()) tags[i] = r releases[j] = nil // Mark as used. break } } if tags[i] == nil { commit, err := ctx.Repo.GitRepo.GetTagCommit(rawTag) if err != nil { ctx.Handle(500, "GetTagCommit", err) return } tags[i] = &models.Release{ Title: rawTag, TagName: rawTag, Sha1: commit.ID.String(), } tags[i].NumCommits, err = commit.CommitsCount() if err != nil { ctx.Handle(500, "CommitsCount", err) return } tags[i].NumCommitsBehind = ctx.Repo.CommitsCount - tags[i].NumCommits } } for _, r := range releases { if r == nil { continue } r.Publisher, err = models.GetUserByID(r.PublisherID) if err != nil { if models.IsErrUserNotExist(err) { r.Publisher = models.NewGhostUser() } else { ctx.Handle(500, "GetUserByID", err) return } } if err := calReleaseNumCommitsBehind(ctx.Repo, r, countCache); err != nil { ctx.Handle(500, "calReleaseNumCommitsBehind", err) return } r.Note = markdown.RenderString(r.Note, ctx.Repo.RepoLink, ctx.Repo.Repository.ComposeMetas()) tags = append(tags, r) } models.SortReleases(tags) ctx.Data["Releases"] = tags ctx.HTML(200, RELEASES) }
func ListReleases(ctx *middleware.Context) { rawTags, err := ctx.Repo.GitRepo.GetTags() if err != nil { ctx.Handle(500, "GetTags", err) return } rels, err := models.GetReleasesByRepoID(ctx.Repo.Repository.ID) if err != nil { ctx.Handle(500, "GetReleasesByRepoId", err) return } // Temproray cache commits count of used branches to speed up. countCache := make(map[string]int) tags := make([]*api.Release, len(rawTags)) for i, rawTag := range rawTags { for j, rel := range rels { if rel == nil || (rel.IsDraft && !ctx.Repo.IsOwner()) { continue } if rel.TagName == rawTag { rel.Publisher, err = models.GetUserByID(rel.PublisherID) if err != nil { ctx.Handle(500, "GetUserById", err) return } // FIXME: duplicated code. // Get corresponding target if it's not the current branch. if ctx.Repo.BranchName != rel.Target { // Get count if not exists. if _, ok := countCache[rel.Target]; !ok { commit, err := ctx.Repo.GitRepo.GetCommitOfBranch(ctx.Repo.BranchName) if err != nil { ctx.Handle(500, "GetCommitOfBranch", err) return } countCache[ctx.Repo.BranchName], err = commit.CommitsCount() if err != nil { ctx.Handle(500, "CommitsCount2", err) return } } rel.NumCommitsBehind = countCache[ctx.Repo.BranchName] - rel.NumCommits } else { rel.NumCommitsBehind = ctx.Repo.CommitsCount - rel.NumCommits } rel.Note = base.RenderMarkdownString(rel.Note, ctx.Repo.RepoLink) tags[i] = ToApiRelease(rel) rels[j] = nil // Mark as used. break } } if tags[i] == nil { commit, err := ctx.Repo.GitRepo.GetCommitOfTag(rawTag) if err != nil { ctx.Handle(500, "GetCommitOfTag2", err) return } tags[i] = &api.Release{ Title: rawTag, TagName: rawTag, Sha1: commit.ID.String(), } tags[i].NumCommits, err = ctx.Repo.GitRepo.CommitsCount(commit.ID.String()) if err != nil { ctx.Handle(500, "CommitsCount", err) return } tags[i].NumCommitsBehind = ctx.Repo.CommitsCount - tags[i].NumCommits } } for _, rel := range rels { if rel == nil { continue } rel.Publisher, err = models.GetUserByID(rel.PublisherID) if err != nil { ctx.Handle(500, "GetUserById", err) return } // FIXME: duplicated code. // Get corresponding target if it's not the current branch. if ctx.Repo.BranchName != rel.Target { // Get count if not exists. if _, ok := countCache[rel.Target]; !ok { commit, err := ctx.Repo.GitRepo.GetCommitOfBranch(ctx.Repo.BranchName) if err != nil { ctx.Handle(500, "GetCommitOfBranch", err) return } countCache[ctx.Repo.BranchName], err = commit.CommitsCount() if err != nil { ctx.Handle(500, "CommitsCount2", err) return } } rel.NumCommitsBehind = countCache[ctx.Repo.BranchName] - rel.NumCommits } else { rel.NumCommitsBehind = ctx.Repo.CommitsCount - rel.NumCommits } rel.Note = base.RenderMarkdownString(rel.Note, ctx.Repo.RepoLink) tags = append(tags, ToApiRelease(rel)) } ctx.JSON(200, &tags) }
// https://github.com/gogits/go-gogs-client/wiki/Repositories#migrate func Migrate(ctx *context.APIContext, form auth.MigrateRepoForm) { ctxUser := ctx.User // Not equal means context user is an organization, // or is another user/organization if current user is admin. if form.Uid != ctxUser.Id { org, err := models.GetUserByID(form.Uid) if err != nil { if models.IsErrUserNotExist(err) { ctx.Error(422, "", err) } else { ctx.Error(500, "GetUserByID", err) } return } ctxUser = org } if ctx.HasError() { ctx.Error(422, "", ctx.GetErrMsg()) return } if ctxUser.IsOrganization() && !ctx.User.IsAdmin { // Check ownership of organization. if !ctxUser.IsOwnedBy(ctx.User.Id) { ctx.Error(403, "", "Given user is not owner of organization.") return } } remoteAddr, err := form.ParseRemoteAddr(ctx.User) if err != nil { if models.IsErrInvalidCloneAddr(err) { addrErr := err.(models.ErrInvalidCloneAddr) switch { case addrErr.IsURLError: ctx.Error(422, "", err) case addrErr.IsPermissionDenied: ctx.Error(422, "", "You are not allowed to import local repositories.") case addrErr.IsInvalidPath: ctx.Error(422, "", "Invalid local path, it does not exist or not a directory.") default: ctx.Error(500, "ParseRemoteAddr", "Unknown error type (ErrInvalidCloneAddr): "+err.Error()) } } else { ctx.Error(500, "ParseRemoteAddr", err) } return } repo, err := models.MigrateRepository(ctxUser, models.MigrateRepoOptions{ Name: form.RepoName, Description: form.Description, IsPrivate: form.Private || setting.Repository.ForcePrivate, IsMirror: form.Mirror, RemoteAddr: remoteAddr, }) if err != nil { if repo != nil { if errDelete := models.DeleteRepository(ctxUser.Id, repo.ID); errDelete != nil { log.Error(4, "DeleteRepository: %v", errDelete) } } ctx.Error(500, "MigrateRepository", models.HandleCloneUserCredentials(err.Error(), true)) return } log.Trace("Repository migrated: %s/%s", ctxUser.Name, form.RepoName) ctx.JSON(201, convert.ToRepository(ctxUser, repo, api.Permission{true, true, true})) }
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) { 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] refName := fields[2] // FIXME: handle error. if err = models.PushUpdate(models.PushUpdateOptions{ RefName: refName, OldCommitID: oldCommitId, NewCommitID: newCommitId, PusherID: authUser.Id, PusherName: authUser.Name, RepoUserName: username, RepoName: reponame, }); err == nil { go models.HookQueue.Add(repo.ID) go models.AddTestPullRequestTask(repo.ID, strings.TrimPrefix(refName, "refs/heads/")) } } lastLine = lastLine + size } else { break } } } HTTPBackend(ctx, &serviceConfig{ UploadPack: true, ReceivePack: true, OnSucceed: callback, })(ctx.Resp, ctx.Req.Request) runtime.GC() }
func Releases(ctx *middleware.Context) { ctx.Data["Title"] = ctx.Tr("repo.release.releases") ctx.Data["PageIsReleaseList"] = true rawTags, err := ctx.Repo.GitRepo.GetTags() if err != nil { ctx.Handle(500, "GetTags", err) return } rels, err := models.GetReleasesByRepoID(ctx.Repo.Repository.ID) if err != nil { ctx.Handle(500, "GetReleasesByRepoID", err) return } // Temproray cache commits count of used branches to speed up. countCache := make(map[string]int64) tags := make([]*models.Release, len(rawTags)) for i, rawTag := range rawTags { for j, rel := range rels { if rel == nil || (rel.IsDraft && !ctx.Repo.IsOwner()) { continue } if rel.TagName == rawTag { rel.Publisher, err = models.GetUserByID(rel.PublisherID) if err != nil { ctx.Handle(500, "GetUserByID", err) return } // FIXME: duplicated code. // Get corresponding target if it's not the current branch. if ctx.Repo.BranchName != rel.Target { // Get count if not exists. if _, ok := countCache[rel.Target]; !ok { commit, err := ctx.Repo.GitRepo.GetBranchCommit(ctx.Repo.BranchName) if err != nil { ctx.Handle(500, "GetBranchCommit", err) return } countCache[ctx.Repo.BranchName], err = commit.CommitsCount() if err != nil { ctx.Handle(500, "CommitsCount", err) return } } rel.NumCommitsBehind = countCache[ctx.Repo.BranchName] - rel.NumCommits } else { rel.NumCommitsBehind = ctx.Repo.CommitsCount - rel.NumCommits } rel.Note = base.RenderMarkdownString(rel.Note, ctx.Repo.RepoLink, ctx.Repo.Repository.ComposeMetas()) tags[i] = rel rels[j] = nil // Mark as used. break } } if tags[i] == nil { commit, err := ctx.Repo.GitRepo.GetTagCommit(rawTag) if err != nil { ctx.Handle(500, "GetTagCommit", err) return } tags[i] = &models.Release{ Title: rawTag, TagName: rawTag, Sha1: commit.ID.String(), } tags[i].NumCommits, err = commit.CommitsCount() if err != nil { ctx.Handle(500, "CommitsCount", err) return } tags[i].NumCommitsBehind = ctx.Repo.CommitsCount - tags[i].NumCommits } } for _, rel := range rels { if rel == nil { continue } rel.Publisher, err = models.GetUserByID(rel.PublisherID) if err != nil { ctx.Handle(500, "GetUserByID", err) return } // FIXME: duplicated code. // Get corresponding target if it's not the current branch. if ctx.Repo.BranchName != rel.Target { // Get count if not exists. if _, ok := countCache[rel.Target]; !ok { commit, err := ctx.Repo.GitRepo.GetBranchCommit(ctx.Repo.BranchName) if err != nil { ctx.Handle(500, "GetBranchCommit", err) return } countCache[ctx.Repo.BranchName], err = commit.CommitsCount() if err != nil { ctx.Handle(500, "CommitsCount", err) return } } rel.NumCommitsBehind = countCache[ctx.Repo.BranchName] - rel.NumCommits } else { rel.NumCommitsBehind = ctx.Repo.CommitsCount - rel.NumCommits } rel.Note = base.RenderMarkdownString(rel.Note, ctx.Repo.RepoLink, ctx.Repo.Repository.ComposeMetas()) tags = append(tags, rel) } models.SortReleases(tags) ctx.Data["Releases"] = tags ctx.HTML(200, RELEASES) }
func MigrateRepo(ctx *middleware.Context, form auth.MigrateRepoForm) { ctxUser := ctx.User // Not equal means current user is an organization. if form.Uid != ctxUser.Id { org, err := models.GetUserByID(form.Uid) if err != nil { if models.IsErrUserNotExist(err) { ctx.HandleAPI(422, err) } else { ctx.HandleAPI(500, err) } return } ctxUser = org } if ctx.HasError() { ctx.HandleAPI(422, ctx.GetErrMsg()) return } if ctxUser.IsOrganization() { // Check ownership of organization. if !ctxUser.IsOwnedBy(ctx.User.Id) { ctx.HandleAPI(403, "Given user is not owner of organization.") return } } // Remote address can be HTTP/HTTPS/Git URL or local path. remoteAddr := form.CloneAddr if strings.HasPrefix(form.CloneAddr, "http://") || strings.HasPrefix(form.CloneAddr, "https://") || strings.HasPrefix(form.CloneAddr, "git://") { u, err := url.Parse(form.CloneAddr) if err != nil { ctx.HandleAPI(422, err) return } if len(form.AuthUsername) > 0 || len(form.AuthPassword) > 0 { u.User = url.UserPassword(form.AuthUsername, form.AuthPassword) } remoteAddr = u.String() } else if !com.IsDir(remoteAddr) { ctx.HandleAPI(422, "Invalid local path, it does not exist or not a directory.") return } repo, err := models.MigrateRepository(ctxUser, form.RepoName, form.Description, form.Private, form.Mirror, remoteAddr) if err != nil { if repo != nil { if errDelete := models.DeleteRepository(ctxUser.Id, repo.ID); errDelete != nil { log.Error(4, "DeleteRepository: %v", errDelete) } } ctx.HandleAPI(500, err) return } log.Trace("Repository migrated: %s/%s", ctxUser.Name, form.RepoName) ctx.JSON(201, ToApiRepository(ctxUser, repo, api.Permission{true, true, true})) }
// SignedInUser returns the user object of signed user. // It returns a bool value to indicate whether user uses basic auth or not. func SignedInUser(ctx *macaron.Context, sess session.Store) (*models.User, bool) { if !models.HasEngine { return nil, false } uid := SignedInID(ctx, sess) if uid <= 0 { if setting.Service.EnableReverseProxyAuth { webAuthUser := ctx.Req.Header.Get(setting.ReverseProxyAuthUser) if len(webAuthUser) > 0 { u, err := models.GetUserByName(webAuthUser) if err != nil { if !models.IsErrUserNotExist(err) { log.Error(4, "GetUserByName: %v", err) return nil, false } // Check if enabled auto-registration. if setting.Service.EnableReverseProxyAutoRegister { u := &models.User{ Name: webAuthUser, Email: uuid.NewV4().String() + "@localhost", Passwd: webAuthUser, IsActive: true, } if err = models.CreateUser(u); err != nil { // FIXME: should I create a system notice? log.Error(4, "CreateUser: %v", err) return nil, false } else { return u, false } } } return u, false } } // Check with basic auth. baHead := ctx.Req.Header.Get("Authorization") if len(baHead) > 0 { auths := strings.Fields(baHead) if len(auths) == 2 && auths[0] == "Basic" { uname, passwd, _ := base.BasicAuthDecode(auths[1]) u, err := models.UserSignIn(uname, passwd) if err != nil { if !models.IsErrUserNotExist(err) { log.Error(4, "UserSignIn: %v", err) } return nil, false } return u, true } } return nil, false } u, err := models.GetUserByID(uid) if err != nil { log.Error(4, "GetUserById: %v", err) return nil, false } return u, false }