mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-12-23 20:17:03 +01:00
push + pull now works with reverse proxy + basic auth on apache 2.4
This commit is contained in:
parent
937b4b5aa1
commit
37eec6c9b7
1 changed files with 81 additions and 68 deletions
|
@ -83,85 +83,98 @@ func HTTP(ctx *context.Context) {
|
||||||
|
|
||||||
// check access
|
// check access
|
||||||
if askAuth {
|
if askAuth {
|
||||||
authHead := ctx.Req.Header.Get("Authorization")
|
if setting.Service.EnableReverseProxyAuth {
|
||||||
if len(authHead) == 0 {
|
authUsername = ctx.Req.Header.Get(setting.ReverseProxyAuthUser)
|
||||||
ctx.Resp.Header().Set("WWW-Authenticate", "Basic realm=\".\"")
|
if len(authUsername) == 0 {
|
||||||
ctx.Error(http.StatusUnauthorized)
|
ctx.HandleText(401, "reverse proxy login error. authUsername empty")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
authUser, err = models.GetUserByName(authUsername)
|
||||||
auths := strings.Fields(authHead)
|
if err != nil {
|
||||||
// currently check basic auth
|
ctx.HandleText(401, "reverse proxy login error, got error while running GetUserByName")
|
||||||
// TODO: support digit auth
|
return
|
||||||
// FIXME: middlewares/context.go did basic auth check already,
|
}
|
||||||
// maybe could use that one.
|
}else{
|
||||||
if len(auths) != 2 || auths[0] != "Basic" {
|
authHead := ctx.Req.Header.Get("Authorization")
|
||||||
ctx.HandleText(http.StatusUnauthorized, "no basic auth and digit auth")
|
if len(authHead) == 0 {
|
||||||
return
|
ctx.Resp.Header().Set("WWW-Authenticate", "Basic realm=\".\"")
|
||||||
}
|
ctx.Error(http.StatusUnauthorized)
|
||||||
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assume username now is a token.
|
auths := strings.Fields(authHead)
|
||||||
token, err := models.GetAccessTokenBySHA(authUsername)
|
// 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 {
|
if err != nil {
|
||||||
if models.IsErrAccessTokenNotExist(err) || models.IsErrAccessTokenEmpty(err) {
|
ctx.HandleText(http.StatusUnauthorized, "no basic auth and digit auth")
|
||||||
ctx.HandleText(http.StatusUnauthorized, "invalid token")
|
return
|
||||||
} else {
|
}
|
||||||
ctx.Handle(http.StatusInternalServerError, "GetAccessTokenBySha", err)
|
|
||||||
|
authUser, err = models.UserSignIn(authUsername, authPasswd)
|
||||||
|
if err != nil {
|
||||||
|
if !models.IsErrUserNotExist(err) {
|
||||||
|
ctx.Handle(http.StatusInternalServerError, "UserSignIn error: %v", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
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 {
|
// Assume username now is a token.
|
||||||
var tp = models.AccessModeWrite
|
token, err := models.GetAccessTokenBySHA(authUsername)
|
||||||
if isPull {
|
if err != nil {
|
||||||
tp = models.AccessModeRead
|
if models.IsErrAccessTokenNotExist(err) || models.IsErrAccessTokenEmpty(err) {
|
||||||
}
|
ctx.HandleText(http.StatusUnauthorized, "invalid token")
|
||||||
|
} else {
|
||||||
has, err := models.HasAccess(authUser, repo, tp)
|
ctx.Handle(http.StatusInternalServerError, "GetAccessTokenBySha", err)
|
||||||
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 {
|
return
|
||||||
ctx.HandleText(http.StatusForbidden, "User permission denied")
|
}
|
||||||
|
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
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !isPull && repo.IsMirror {
|
if !isPublicPull {
|
||||||
ctx.HandleText(http.StatusForbidden, "mirror repository is read-only")
|
var tp = models.AccessModeWrite
|
||||||
return
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isPull && repo.IsMirror {
|
||||||
|
ctx.HandleText(http.StatusForbidden, "mirror repository is read-only")
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue