fix: do visibility check for user redirect lookup
This commit is contained in:
parent
9828aca733
commit
4019b99217
9 changed files with 50 additions and 48 deletions
|
@ -21,7 +21,8 @@ import (
|
|||
|
||||
// ErrUserRedirectNotExist represents a "UserRedirectNotExist" kind of error.
|
||||
type ErrUserRedirectNotExist struct {
|
||||
Name string
|
||||
Name string
|
||||
MissingPermission bool
|
||||
}
|
||||
|
||||
// IsErrUserRedirectNotExist check if an error is an ErrUserRedirectNotExist.
|
||||
|
@ -81,15 +82,6 @@ func GetUserRedirect(ctx context.Context, userName string) (*Redirect, error) {
|
|||
return redirect, nil
|
||||
}
|
||||
|
||||
// LookupUserRedirect look up userID if a user has a redirect name
|
||||
func LookupUserRedirect(ctx context.Context, userName string) (int64, error) {
|
||||
redirect, err := GetUserRedirect(ctx, userName)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return redirect.RedirectUserID, nil
|
||||
}
|
||||
|
||||
// NewUserRedirect create a new user redirect
|
||||
func NewUserRedirect(ctx context.Context, ID int64, oldUserName, newUserName string) error {
|
||||
oldUserName = strings.ToLower(oldUserName)
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package user_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"forgejo.org/models/db"
|
||||
"forgejo.org/models/unittest"
|
||||
user_model "forgejo.org/models/user"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestLookupUserRedirect(t *testing.T) {
|
||||
require.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
userID, err := user_model.LookupUserRedirect(db.DefaultContext, "olduser1")
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 1, userID)
|
||||
|
||||
_, err = user_model.LookupUserRedirect(db.DefaultContext, "doesnotexist")
|
||||
assert.True(t, user_model.IsErrUserRedirectNotExist(err))
|
||||
}
|
|
@ -99,6 +99,7 @@ import (
|
|||
"forgejo.org/services/auth"
|
||||
"forgejo.org/services/context"
|
||||
"forgejo.org/services/forms"
|
||||
redirect_service "forgejo.org/services/redirect"
|
||||
|
||||
_ "forgejo.org/routers/api/v1/swagger" // for swagger generation
|
||||
|
||||
|
@ -153,12 +154,12 @@ func repoAssignment() func(ctx *context.APIContext) {
|
|||
owner, err = user_model.GetUserByName(ctx, userName)
|
||||
if err != nil {
|
||||
if user_model.IsErrUserNotExist(err) {
|
||||
if redirectUserID, err := user_model.LookupUserRedirect(ctx, userName); err == nil {
|
||||
if redirectUserID, err := redirect_service.LookupUserRedirect(ctx, ctx.Doer, userName); err == nil {
|
||||
context.RedirectToUser(ctx.Base, userName, redirectUserID)
|
||||
} else if user_model.IsErrUserRedirectNotExist(err) {
|
||||
ctx.NotFound("GetUserByName", err)
|
||||
} else {
|
||||
ctx.Error(http.StatusInternalServerError, "LookupUserRedirect", err)
|
||||
ctx.Error(http.StatusInternalServerError, "LookupRedirect", err)
|
||||
}
|
||||
} else {
|
||||
ctx.Error(http.StatusInternalServerError, "GetUserByName", err)
|
||||
|
@ -638,13 +639,13 @@ func orgAssignment(args ...bool) func(ctx *context.APIContext) {
|
|||
ctx.Org.Organization, err = organization.GetOrgByName(ctx, ctx.Params(":org"))
|
||||
if err != nil {
|
||||
if organization.IsErrOrgNotExist(err) {
|
||||
redirectUserID, err := user_model.LookupUserRedirect(ctx, ctx.Params(":org"))
|
||||
redirectUserID, err := redirect_service.LookupUserRedirect(ctx, ctx.Doer, ctx.Params(":org"))
|
||||
if err == nil {
|
||||
context.RedirectToUser(ctx.Base, ctx.Params(":org"), redirectUserID)
|
||||
} else if user_model.IsErrUserRedirectNotExist(err) {
|
||||
ctx.NotFound("GetOrgByName", err)
|
||||
} else {
|
||||
ctx.Error(http.StatusInternalServerError, "LookupUserRedirect", err)
|
||||
ctx.Error(http.StatusInternalServerError, "LookupRedirect", err)
|
||||
}
|
||||
} else {
|
||||
ctx.Error(http.StatusInternalServerError, "GetOrgByName", err)
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
user_model "forgejo.org/models/user"
|
||||
"forgejo.org/services/context"
|
||||
redirect_service "forgejo.org/services/redirect"
|
||||
)
|
||||
|
||||
// GetUserByParamsName get user by name
|
||||
|
@ -16,7 +17,7 @@ func GetUserByParamsName(ctx *context.APIContext, name string) *user_model.User
|
|||
user, err := user_model.GetUserByName(ctx, username)
|
||||
if err != nil {
|
||||
if user_model.IsErrUserNotExist(err) {
|
||||
if redirectUserID, err2 := user_model.LookupUserRedirect(ctx, username); err2 == nil {
|
||||
if redirectUserID, err2 := redirect_service.LookupUserRedirect(ctx, ctx.Doer, username); err2 == nil {
|
||||
context.RedirectToUser(ctx.Base, username, redirectUserID)
|
||||
} else {
|
||||
ctx.NotFound("GetUserByName", err)
|
||||
|
|
|
@ -16,6 +16,7 @@ import (
|
|||
"forgejo.org/modules/markup/markdown"
|
||||
"forgejo.org/modules/setting"
|
||||
"forgejo.org/modules/structs"
|
||||
redirect_service "forgejo.org/services/redirect"
|
||||
)
|
||||
|
||||
// Organization contains organization context
|
||||
|
@ -48,13 +49,13 @@ func GetOrganizationByParams(ctx *Context) {
|
|||
ctx.Org.Organization, err = organization.GetOrgByName(ctx, orgName)
|
||||
if err != nil {
|
||||
if organization.IsErrOrgNotExist(err) {
|
||||
redirectUserID, err := user_model.LookupUserRedirect(ctx, orgName)
|
||||
redirectUserID, err := redirect_service.LookupUserRedirect(ctx, ctx.Doer, orgName)
|
||||
if err == nil {
|
||||
RedirectToUser(ctx.Base, orgName, redirectUserID)
|
||||
} else if user_model.IsErrUserRedirectNotExist(err) {
|
||||
ctx.NotFound("GetUserByName", err)
|
||||
} else {
|
||||
ctx.ServerError("LookupUserRedirect", err)
|
||||
ctx.ServerError("LookupRedirect", err)
|
||||
}
|
||||
} else {
|
||||
ctx.ServerError("GetUserByName", err)
|
||||
|
|
|
@ -35,6 +35,7 @@ import (
|
|||
"forgejo.org/modules/setting"
|
||||
"forgejo.org/modules/util"
|
||||
asymkey_service "forgejo.org/services/asymkey"
|
||||
redirect_service "forgejo.org/services/redirect"
|
||||
|
||||
"github.com/editorconfig/editorconfig-core-go/v2"
|
||||
)
|
||||
|
@ -477,12 +478,12 @@ func RepoAssignment(ctx *Context) context.CancelFunc {
|
|||
return nil
|
||||
}
|
||||
|
||||
if redirectUserID, err := user_model.LookupUserRedirect(ctx, userName); err == nil {
|
||||
if redirectUserID, err := redirect_service.LookupUserRedirect(ctx, ctx.Doer, userName); err == nil {
|
||||
RedirectToUser(ctx.Base, userName, redirectUserID)
|
||||
} else if user_model.IsErrUserRedirectNotExist(err) {
|
||||
ctx.NotFound("GetUserByName", nil)
|
||||
} else {
|
||||
ctx.ServerError("LookupUserRedirect", err)
|
||||
ctx.ServerError("LookupRedirect", err)
|
||||
}
|
||||
} else {
|
||||
ctx.ServerError("GetUserByName", err)
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"strings"
|
||||
|
||||
user_model "forgejo.org/models/user"
|
||||
redirect_service "forgejo.org/services/redirect"
|
||||
)
|
||||
|
||||
// UserAssignmentWeb returns a middleware to handle context-user assignment for web routes
|
||||
|
@ -68,12 +69,12 @@ func userAssignment(ctx *Base, doer *user_model.User, errCb func(int, string, an
|
|||
contextUser, err = user_model.GetUserByName(ctx, username)
|
||||
if err != nil {
|
||||
if user_model.IsErrUserNotExist(err) {
|
||||
if redirectUserID, err := user_model.LookupUserRedirect(ctx, username); err == nil {
|
||||
if redirectUserID, err := redirect_service.LookupUserRedirect(ctx, doer, username); err == nil {
|
||||
RedirectToUser(ctx, username, redirectUserID)
|
||||
} else if user_model.IsErrUserRedirectNotExist(err) {
|
||||
errCb(http.StatusNotFound, "GetUserByName", err)
|
||||
} else {
|
||||
errCb(http.StatusInternalServerError, "LookupUserRedirect", err)
|
||||
errCb(http.StatusInternalServerError, "LookupRedirect", err)
|
||||
}
|
||||
} else {
|
||||
errCb(http.StatusInternalServerError, "GetUserByName", err)
|
||||
|
|
30
services/redirect/user.go
Normal file
30
services/redirect/user.go
Normal file
|
@ -0,0 +1,30 @@
|
|||
// Copyright 2025 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
package redirect
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
user_model "forgejo.org/models/user"
|
||||
)
|
||||
|
||||
// LookupUserRedirect returns the userID if there's a redirect registered for the
|
||||
// username. It additionally checks if the doer has permission to view the new
|
||||
// user.
|
||||
func LookupUserRedirect(ctx context.Context, doer *user_model.User, userName string) (int64, error) {
|
||||
redirect, err := user_model.GetUserRedirect(ctx, userName)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
redirectUser, err := user_model.GetUserByID(ctx, redirect.RedirectUserID)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if !user_model.IsUserVisibleToViewer(ctx, redirectUser, doer) {
|
||||
return 0, user_model.ErrUserRedirectNotExist{Name: userName, MissingPermission: true}
|
||||
}
|
||||
|
||||
return redirect.RedirectUserID, nil
|
||||
}
|
|
@ -26,6 +26,7 @@ import (
|
|||
"forgejo.org/modules/test"
|
||||
"forgejo.org/modules/timeutil"
|
||||
"forgejo.org/services/auth/source/oauth2"
|
||||
redirect_service "forgejo.org/services/redirect"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -184,7 +185,7 @@ func TestRenameUser(t *testing.T) {
|
|||
require.NoError(t, RenameUser(db.DefaultContext, user, newUsername))
|
||||
unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: user.ID, Name: newUsername, LowerName: strings.ToLower(newUsername)})
|
||||
|
||||
redirectUID, err := user_model.LookupUserRedirect(db.DefaultContext, oldUsername)
|
||||
redirectUID, err := redirect_service.LookupUserRedirect(db.DefaultContext, user, oldUsername)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, user.ID, redirectUID)
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue