// 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 *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(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 ) // check access if askAuth { authSandstormId := ctx.Req.Header.Get("X-Sandstorm-User-Id") if authSandstormId == "" { authRequired(ctx) return } authUser, err = models.GetUserBySandstormID(authSandstormId) if err != nil { ctx.Handle(500, "UserSignIn error: %v", 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(500, "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(500, "HasAccess2", err) return } else if !has { ctx.HandleText(403, "User permission denied") return } } else { ctx.HandleText(403, "User permission denied") return } } if !isPull && repo.IsMirror { ctx.HandleText(403, "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, &Config{ RepoRootPath: setting.RepoRootPath, GitBinPath: "git", UploadPack: true, ReceivePack: true, OnSucceed: callback, })(ctx.Resp, ctx.Req.Request) runtime.GC() }