aboutsummaryrefslogtreecommitdiff
path: root/internal/route
diff options
context:
space:
mode:
Diffstat (limited to 'internal/route')
-rw-r--r--internal/route/lfs/route.go39
-rw-r--r--internal/route/lfs/route_test.go27
-rw-r--r--internal/route/repo/http.go39
3 files changed, 64 insertions, 41 deletions
diff --git a/internal/route/lfs/route.go b/internal/route/lfs/route.go
index c00f7374..bdacc6da 100644
--- a/internal/route/lfs/route.go
+++ b/internal/route/lfs/route.go
@@ -8,12 +8,14 @@ import (
"net/http"
"strings"
+ "github.com/pkg/errors"
"gopkg.in/macaron.v1"
log "unknwon.dev/clog/v2"
"gogs.io/gogs/internal/auth"
"gogs.io/gogs/internal/authutil"
"gogs.io/gogs/internal/conf"
+ "gogs.io/gogs/internal/context"
"gogs.io/gogs/internal/db"
"gogs.io/gogs/internal/lfsutil"
)
@@ -70,29 +72,26 @@ func authenticate() macaron.Handler {
return
}
- // If username and password authentication failed, try again using username as an access token.
+ // If username and password combination failed, try again using either username
+ // or password as the token.
if auth.IsErrBadCredentials(err) {
- token, err := db.AccessTokens.GetBySHA1(c.Req.Context(), username)
- if err != nil {
- if db.IsErrAccessTokenNotExist(err) {
- askCredentials(c.Resp)
- } else {
- internalServerError(c.Resp)
- log.Error("Failed to get access token [sha: %s]: %v", username, err)
- }
- return
- }
- if err = db.AccessTokens.Touch(c.Req.Context(), token.ID); err != nil {
- log.Error("Failed to touch access token: %v", err)
- }
-
- user, err = db.Users.GetByID(c.Req.Context(), token.UserID)
- if err != nil {
- // Once we found the token, we're supposed to find its related user,
- // thus any error is unexpected.
+ user, err = context.AuthenticateByToken(c.Req.Context(), username)
+ if err != nil && !db.IsErrAccessTokenNotExist(errors.Cause(err)) {
internalServerError(c.Resp)
- log.Error("Failed to get user [id: %d]: %v", token.UserID, err)
+ log.Error("Failed to authenticate by access token via username: %v", err)
return
+ } else if db.IsErrAccessTokenNotExist(errors.Cause(err)) {
+ // Try again using the password field as the token.
+ user, err = context.AuthenticateByToken(c.Req.Context(), password)
+ if err != nil {
+ if db.IsErrAccessTokenNotExist(errors.Cause(err)) {
+ askCredentials(c.Resp)
+ } else {
+ c.Status(http.StatusInternalServerError)
+ log.Error("Failed to authenticate by access token via password: %v", err)
+ }
+ return
+ }
}
}
diff --git a/internal/route/lfs/route_test.go b/internal/route/lfs/route_test.go
index dd8f5cde..eb0225d5 100644
--- a/internal/route/lfs/route_test.go
+++ b/internal/route/lfs/route_test.go
@@ -108,7 +108,7 @@ func Test_authenticate(t *testing.T) {
expBody: "ID: 1, Name: unknwon",
},
{
- name: "authenticate by access token",
+ name: "authenticate by access token via username",
header: http.Header{
"Authorization": []string{"Basic dXNlcm5hbWU="},
},
@@ -127,6 +127,31 @@ func Test_authenticate(t *testing.T) {
expHeader: http.Header{},
expBody: "ID: 1, Name: unknwon",
},
+ {
+ name: "authenticate by access token via password",
+ header: http.Header{
+ "Authorization": []string{"Basic dXNlcm5hbWU6cGFzc3dvcmQ="},
+ },
+ mockUsersStore: func() db.UsersStore {
+ mock := NewMockUsersStore()
+ mock.AuthenticateFunc.SetDefaultReturn(nil, auth.ErrBadCredentials{})
+ mock.GetByIDFunc.SetDefaultReturn(&db.User{ID: 1, Name: "unknwon"}, nil)
+ return mock
+ },
+ mockAccessTokensStore: func() db.AccessTokensStore {
+ mock := NewMockAccessTokensStore()
+ mock.GetBySHA1Func.SetDefaultHook(func(ctx context.Context, sha1 string) (*db.AccessToken, error) {
+ if sha1 == "password" {
+ return &db.AccessToken{}, nil
+ }
+ return nil, db.ErrAccessTokenNotExist{}
+ })
+ return mock
+ },
+ expStatusCode: http.StatusOK,
+ expHeader: http.Header{},
+ expBody: "ID: 1, Name: unknwon",
+ },
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
diff --git a/internal/route/repo/http.go b/internal/route/repo/http.go
index af51a076..89c7fa24 100644
--- a/internal/route/repo/http.go
+++ b/internal/route/repo/http.go
@@ -17,11 +17,13 @@ import (
"strings"
"time"
+ "github.com/pkg/errors"
"gopkg.in/macaron.v1"
log "unknwon.dev/clog/v2"
"gogs.io/gogs/internal/auth"
"gogs.io/gogs/internal/conf"
+ "gogs.io/gogs/internal/context"
"gogs.io/gogs/internal/db"
"gogs.io/gogs/internal/lazyregexp"
"gogs.io/gogs/internal/pathutil"
@@ -130,29 +132,26 @@ func HTTPContexter() macaron.Handler {
return
}
- // If username and password combination failed, try again using username as a token.
+ // If username and password combination failed, try again using either username
+ // or password as the token.
if authUser == nil {
- token, err := db.AccessTokens.GetBySHA1(c.Req.Context(), authUsername)
- if err != nil {
- if db.IsErrAccessTokenNotExist(err) {
- askCredentials(c, http.StatusUnauthorized, "")
- } else {
- c.Status(http.StatusInternalServerError)
- log.Error("Failed to get access token [sha: %s]: %v", authUsername, err)
- }
- return
- }
- if err = db.AccessTokens.Touch(c.Req.Context(), token.ID); err != nil {
- log.Error("Failed to touch access token: %v", err)
- }
-
- authUser, err = db.Users.GetByID(c.Req.Context(), token.UserID)
- if err != nil {
- // Once we found token, we're supposed to find its related user,
- // thus any error is unexpected.
+ authUser, err = context.AuthenticateByToken(c.Req.Context(), authUsername)
+ if err != nil && !db.IsErrAccessTokenNotExist(errors.Cause(err)) {
c.Status(http.StatusInternalServerError)
- log.Error("Failed to get user [id: %d]: %v", token.UserID, err)
+ log.Error("Failed to authenticate by access token via username: %v", err)
return
+ } else if db.IsErrAccessTokenNotExist(errors.Cause(err)) {
+ // Try again using the password field as the token.
+ authUser, err = context.AuthenticateByToken(c.Req.Context(), authPassword)
+ if err != nil {
+ if db.IsErrAccessTokenNotExist(errors.Cause(err)) {
+ askCredentials(c, http.StatusUnauthorized, "")
+ } else {
+ c.Status(http.StatusInternalServerError)
+ log.Error("Failed to authenticate by access token via password: %v", err)
+ }
+ return
+ }
}
} else if authUser.IsEnabledTwoFactor() {
askCredentials(c, http.StatusUnauthorized, `User with two-factor authentication enabled cannot perform HTTP/HTTPS operations via plain username and password