Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions routers/api/v1/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ func repoAssignment() func(ctx *context.APIContext) {
if err != nil {
if user_model.IsErrUserNotExist(err) {
if redirectUserID, err := user_model.LookupUserRedirect(ctx, userName); err == nil {
context.RedirectToUser(ctx.Base, userName, redirectUserID)
context.RedirectToUser(ctx.Base, ctx.Doer, userName, redirectUserID)
} else if user_model.IsErrUserRedirectNotExist(err) {
ctx.APIErrorNotFound("GetUserByName", err)
} else {
Expand Down Expand Up @@ -629,7 +629,7 @@ func orgAssignment(args ...bool) func(ctx *context.APIContext) {
if organization.IsErrOrgNotExist(err) {
redirectUserID, err := user_model.LookupUserRedirect(ctx, ctx.PathParam("org"))
if err == nil {
context.RedirectToUser(ctx.Base, ctx.PathParam("org"), redirectUserID)
context.RedirectToUser(ctx.Base, ctx.Doer, ctx.PathParam("org"), redirectUserID)
} else if user_model.IsErrUserRedirectNotExist(err) {
ctx.APIErrorNotFound("GetOrgByName", err)
} else {
Expand Down
2 changes: 1 addition & 1 deletion routers/api/v1/user/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func GetUserByPathParam(ctx *context.APIContext, name string) *user_model.User {
if err != nil {
if user_model.IsErrUserNotExist(err) {
if redirectUserID, err2 := user_model.LookupUserRedirect(ctx, username); err2 == nil {
context.RedirectToUser(ctx.Base, username, redirectUserID)
context.RedirectToUser(ctx.Base, ctx.Doer, username, redirectUserID)
} else {
ctx.APIErrorNotFound("GetUserByName", err)
}
Expand Down
16 changes: 14 additions & 2 deletions services/context/context_response.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,27 @@ import (
"code.gitea.io/gitea/modules/httplib"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/web/middleware"
)

// RedirectToUser redirect to a differently-named user
func RedirectToUser(ctx *Base, userName string, redirectUserID int64) {
func RedirectToUser(ctx *Base, doer *user_model.User, userName string, redirectUserID int64) {
user, err := user_model.GetUserByID(ctx, redirectUserID)
if err != nil {
ctx.HTTPError(http.StatusInternalServerError, "unable to get user")
if user_model.IsErrUserNotExist(err) {
ctx.HTTPError(http.StatusNotFound, "user does not exist")
} else {
ctx.HTTPError(http.StatusInternalServerError, "unable to get user")
}
return
}

// Handle Visibility
if user.Visibility != structs.VisibleTypePublic && doer == nil {
// We must be signed in to see limited or private organizations
ctx.HTTPError(http.StatusNotFound, "user does not exist")
return
}

Expand Down
2 changes: 1 addition & 1 deletion services/context/org.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func GetOrganizationByParams(ctx *Context) {
if organization.IsErrOrgNotExist(err) {
redirectUserID, err := user_model.LookupUserRedirect(ctx, orgName)
if err == nil {
RedirectToUser(ctx.Base, orgName, redirectUserID)
RedirectToUser(ctx.Base, ctx.Doer, orgName, redirectUserID)
} else if user_model.IsErrUserRedirectNotExist(err) {
ctx.NotFound(err)
} else {
Expand Down
2 changes: 1 addition & 1 deletion services/context/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ func RepoAssignment(ctx *Context) {
}

if redirectUserID, err := user_model.LookupUserRedirect(ctx, userName); err == nil {
RedirectToUser(ctx.Base, userName, redirectUserID)
RedirectToUser(ctx.Base, ctx.Doer, userName, redirectUserID)
} else if user_model.IsErrUserRedirectNotExist(err) {
ctx.NotFound(nil)
} else {
Expand Down
2 changes: 1 addition & 1 deletion services/context/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func userAssignment(ctx *Base, doer *user_model.User, errCb func(int, any)) (con
if err != nil {
if user_model.IsErrUserNotExist(err) {
if redirectUserID, err := user_model.LookupUserRedirect(ctx, username); err == nil {
RedirectToUser(ctx, username, redirectUserID)
RedirectToUser(ctx, doer, username, redirectUserID)
} else if user_model.IsErrUserRedirectNotExist(err) {
errCb(http.StatusNotFound, err)
} else {
Expand Down
72 changes: 72 additions & 0 deletions tests/integration/user_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,78 @@ func TestRenameUsername(t *testing.T) {
unittest.AssertNotExistsBean(t, &user_model.User{Name: "user2"})
}

func TestViewLimitedAndPrivateUserAndRename(t *testing.T) {
defer tests.PrepareTestEnv(t)()

// user 22 is a limited visibility org
org22 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 22})
req := NewRequest(t, "GET", "/"+org22.Name)
MakeRequest(t, req, http.StatusNotFound)

session := loginUser(t, "user1")
oldName := org22.Name
newName := "org22_renamed"
req = NewRequestWithValues(t, "POST", "/org/"+oldName+"/settings/rename", map[string]string{
"_csrf": GetUserCSRFToken(t, session),
"org_name": oldName,
"new_org_name": newName,
})
session.MakeRequest(t, req, http.StatusOK)

unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: newName})
unittest.AssertNotExistsBean(t, &user_model.User{Name: oldName})

req = NewRequest(t, "GET", "/"+oldName)
MakeRequest(t, req, http.StatusNotFound) // anonymous user cannot visit limited visibility org via old name
req = NewRequest(t, "GET", "/"+oldName)
session.MakeRequest(t, req, http.StatusTemporaryRedirect) // login user can visit limited visibility org via old name

// org 23 is a private visibility org
org23 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 23})
req = NewRequest(t, "GET", "/"+org23.Name)
MakeRequest(t, req, http.StatusNotFound)

oldName = org23.Name
newName = "org23_renamed"
req = NewRequestWithValues(t, "POST", "/org/"+oldName+"/settings/rename", map[string]string{
"_csrf": GetUserCSRFToken(t, session),
"org_name": oldName,
"new_org_name": newName,
})
session.MakeRequest(t, req, http.StatusOK)

unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: newName})
unittest.AssertNotExistsBean(t, &user_model.User{Name: oldName})

req = NewRequest(t, "GET", "/"+oldName)
MakeRequest(t, req, http.StatusNotFound) // anonymous user cannot visit limited visibility org via old name
req = NewRequest(t, "GET", "/"+oldName)
session.MakeRequest(t, req, http.StatusTemporaryRedirect) // login user can visit limited visibility org via old name

// user 31 is a private visibility user
user31 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 31})
req = NewRequest(t, "GET", "/"+user31.Name)
MakeRequest(t, req, http.StatusNotFound)

oldName = user31.Name
newName = "user31_renamed"
session2 := loginUser(t, oldName)
req = NewRequestWithValues(t, "POST", "/user/settings", map[string]string{
"_csrf": GetUserCSRFToken(t, session2),
"name": newName,
"visibility": "2", // private
})
session2.MakeRequest(t, req, http.StatusSeeOther)

unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: newName})
unittest.AssertNotExistsBean(t, &user_model.User{Name: oldName})

req = NewRequest(t, "GET", "/"+oldName)
MakeRequest(t, req, http.StatusNotFound) // anonymous user cannot visit private visibility user via old name
req = NewRequest(t, "GET", "/"+oldName)
session.MakeRequest(t, req, http.StatusTemporaryRedirect) // login user2 can visit private visibility user via old name
}

func TestRenameInvalidUsername(t *testing.T) {
defer tests.PrepareTestEnv(t)()

Expand Down