// 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 }
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 models.IsErrAccessTokenNotExist(err) { ctx.HandleText(401, "invalid token") } else { ctx.Handle(500, "GetAccessTokenBySha", err) } return } token.Updated = time.Now() if err = models.UpdateAccessToekn(token); err != nil { ctx.Handle(500, "UpdateAccessToekn", err) } 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() }