| @@ -83,85 +83,98 @@ func HTTP(ctx *context.Context) { | |||
| // 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) | |||
| if setting.Service.EnableReverseProxyAuth { | |||
| authUsername = ctx.Req.Header.Get(setting.ReverseProxyAuthUser) | |||
| if len(authUsername) == 0 { | |||
| ctx.HandleText(401, "reverse proxy login error. authUsername empty") | |||
| return | |||
| } | |||
| // Assume username now is a token. | |||
| token, err := models.GetAccessTokenBySHA(authUsername) | |||
| authUser, err = models.GetUserByName(authUsername) | |||
| if err != nil { | |||
| if models.IsErrAccessTokenNotExist(err) || models.IsErrAccessTokenEmpty(err) { | |||
| ctx.HandleText(http.StatusUnauthorized, "invalid token") | |||
| } else { | |||
| ctx.Handle(http.StatusInternalServerError, "GetAccessTokenBySha", err) | |||
| } | |||
| ctx.HandleText(401, "reverse proxy login error, got error while running GetUserByName") | |||
| return | |||
| } | |||
| }else{ | |||
| authHead := ctx.Req.Header.Get("Authorization") | |||
| if len(authHead) == 0 { | |||
| ctx.Resp.Header().Set("WWW-Authenticate", "Basic realm=\".\"") | |||
| ctx.Error(http.StatusUnauthorized) | |||
| return | |||
| } | |||
| token.Updated = time.Now() | |||
| if err = models.UpdateAccessToken(token); err != nil { | |||
| ctx.Handle(http.StatusInternalServerError, "UpdateAccessToken", err) | |||
| 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 | |||
| } | |||
| authUser, err = models.GetUserByID(token.UID) | |||
| authUsername, authPasswd, err = base.BasicAuthDecode(auths[1]) | |||
| if err != nil { | |||
| ctx.Handle(http.StatusInternalServerError, "GetUserByID", err) | |||
| ctx.HandleText(http.StatusUnauthorized, "no basic auth and digit auth") | |||
| return | |||
| } | |||
| } | |||
| if !isPublicPull { | |||
| var tp = models.AccessModeWrite | |||
| if isPull { | |||
| tp = models.AccessModeRead | |||
| 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 | |||
| } | |||
| } | |||
| has, err := models.HasAccess(authUser, repo, tp) | |||
| if err != nil { | |||
| ctx.Handle(http.StatusInternalServerError, "HasAccess", err) | |||
| return | |||
| } else if !has { | |||
| if tp == models.AccessModeRead { | |||
| has, err = models.HasAccess(authUser, repo, models.AccessModeWrite) | |||
| if err != nil { | |||
| ctx.Handle(http.StatusInternalServerError, "HasAccess2", err) | |||
| return | |||
| } else if !has { | |||
| if !isPublicPull { | |||
| var tp = models.AccessModeWrite | |||
| if isPull { | |||
| tp = models.AccessModeRead | |||
| } | |||
| has, err := models.HasAccess(authUser, repo, tp) | |||
| if err != nil { | |||
| ctx.Handle(http.StatusInternalServerError, "HasAccess", err) | |||
| return | |||
| } else if !has { | |||
| if tp == models.AccessModeRead { | |||
| has, err = models.HasAccess(authUser, repo, models.AccessModeWrite) | |||
| 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 | |||
| } | |||
| } else { | |||
| ctx.HandleText(http.StatusForbidden, "User permission denied") | |||
| return | |||
| } | |||
| } | |||
| if !isPull && repo.IsMirror { | |||
| ctx.HandleText(http.StatusForbidden, "mirror repository is read-only") | |||
| return | |||
| if !isPull && repo.IsMirror { | |||
| ctx.HandleText(http.StatusForbidden, "mirror repository is read-only") | |||
| return | |||
| } | |||
| } | |||
| } | |||
| } | |||