mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-09-13 22:37:18 +00:00
fix: do permission check for repository redirect
This commit is contained in:
parent
50837322cc
commit
ca7fcacddc
6 changed files with 46 additions and 19 deletions
|
@ -14,8 +14,9 @@ import (
|
||||||
|
|
||||||
// ErrRedirectNotExist represents a "RedirectNotExist" kind of error.
|
// ErrRedirectNotExist represents a "RedirectNotExist" kind of error.
|
||||||
type ErrRedirectNotExist struct {
|
type ErrRedirectNotExist struct {
|
||||||
OwnerID int64
|
OwnerID int64
|
||||||
RepoName string
|
RepoName string
|
||||||
|
MissingPermission bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsErrRedirectNotExist check if an error is an ErrRepoRedirectNotExist.
|
// IsErrRedirectNotExist check if an error is an ErrRepoRedirectNotExist.
|
||||||
|
@ -49,8 +50,8 @@ func init() {
|
||||||
db.RegisterModel(new(Redirect))
|
db.RegisterModel(new(Redirect))
|
||||||
}
|
}
|
||||||
|
|
||||||
// LookupRedirect look up if a repository has a redirect name
|
// GetRedirect returns the redirect for a given pair of ownerID and repository name.
|
||||||
func LookupRedirect(ctx context.Context, ownerID int64, repoName string) (int64, error) {
|
func GetRedirect(ctx context.Context, ownerID int64, repoName string) (int64, error) {
|
||||||
repoName = strings.ToLower(repoName)
|
repoName = strings.ToLower(repoName)
|
||||||
redirect := &Redirect{OwnerID: ownerID, LowerName: repoName}
|
redirect := &Redirect{OwnerID: ownerID, LowerName: repoName}
|
||||||
if has, err := db.GetEngine(ctx).Get(redirect); err != nil {
|
if has, err := db.GetEngine(ctx).Get(redirect); err != nil {
|
||||||
|
|
|
@ -10,21 +10,9 @@ import (
|
||||||
repo_model "forgejo.org/models/repo"
|
repo_model "forgejo.org/models/repo"
|
||||||
"forgejo.org/models/unittest"
|
"forgejo.org/models/unittest"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLookupRedirect(t *testing.T) {
|
|
||||||
require.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
repoID, err := repo_model.LookupRedirect(db.DefaultContext, 2, "oldrepo1")
|
|
||||||
require.NoError(t, err)
|
|
||||||
assert.EqualValues(t, 1, repoID)
|
|
||||||
|
|
||||||
_, err = repo_model.LookupRedirect(db.DefaultContext, unittest.NonexistentID, "doesnotexist")
|
|
||||||
assert.True(t, repo_model.IsErrRedirectNotExist(err))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNewRedirect(t *testing.T) {
|
func TestNewRedirect(t *testing.T) {
|
||||||
// redirect to a completely new name
|
// redirect to a completely new name
|
||||||
require.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
|
@ -174,7 +174,7 @@ func repoAssignment() func(ctx *context.APIContext) {
|
||||||
repo, err := repo_model.GetRepositoryByName(ctx, owner.ID, repoName)
|
repo, err := repo_model.GetRepositoryByName(ctx, owner.ID, repoName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if repo_model.IsErrRepoNotExist(err) {
|
if repo_model.IsErrRepoNotExist(err) {
|
||||||
redirectRepoID, err := repo_model.LookupRedirect(ctx, owner.ID, repoName)
|
redirectRepoID, err := redirect_service.LookupRepoRedirect(ctx, ctx.Doer, owner.ID, repoName)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
context.RedirectToRepo(ctx.Base, redirectRepoID)
|
context.RedirectToRepo(ctx.Base, redirectRepoID)
|
||||||
} else if repo_model.IsErrRedirectNotExist(err) {
|
} else if repo_model.IsErrRedirectNotExist(err) {
|
||||||
|
|
|
@ -31,6 +31,7 @@ import (
|
||||||
"forgejo.org/modules/structs"
|
"forgejo.org/modules/structs"
|
||||||
"forgejo.org/modules/util"
|
"forgejo.org/modules/util"
|
||||||
"forgejo.org/services/context"
|
"forgejo.org/services/context"
|
||||||
|
redirect_service "forgejo.org/services/redirect"
|
||||||
repo_service "forgejo.org/services/repository"
|
repo_service "forgejo.org/services/repository"
|
||||||
|
|
||||||
"github.com/go-chi/cors"
|
"github.com/go-chi/cors"
|
||||||
|
@ -111,7 +112,7 @@ func httpBase(ctx *context.Context) *serviceHandler {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if redirectRepoID, err := repo_model.LookupRedirect(ctx, owner.ID, reponame); err == nil {
|
if redirectRepoID, err := redirect_service.LookupRepoRedirect(ctx, ctx.Doer, owner.ID, reponame); err == nil {
|
||||||
context.RedirectToRepo(ctx.Base, redirectRepoID)
|
context.RedirectToRepo(ctx.Base, redirectRepoID)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -520,7 +520,7 @@ func RepoAssignment(ctx *Context) context.CancelFunc {
|
||||||
repo, err := repo_model.GetRepositoryByName(ctx, owner.ID, repoName)
|
repo, err := repo_model.GetRepositoryByName(ctx, owner.ID, repoName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if repo_model.IsErrRepoNotExist(err) {
|
if repo_model.IsErrRepoNotExist(err) {
|
||||||
redirectRepoID, err := repo_model.LookupRedirect(ctx, owner.ID, repoName)
|
redirectRepoID, err := redirect_service.LookupRepoRedirect(ctx, ctx.Doer, owner.ID, repoName)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
RedirectToRepo(ctx.Base, redirectRepoID)
|
RedirectToRepo(ctx.Base, redirectRepoID)
|
||||||
} else if repo_model.IsErrRedirectNotExist(err) {
|
} else if repo_model.IsErrRedirectNotExist(err) {
|
||||||
|
|
37
services/redirect/repo.go
Normal file
37
services/redirect/repo.go
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
// Copyright 2025 The Forgejo Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
package redirect
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
access_model "forgejo.org/models/perm/access"
|
||||||
|
repo_model "forgejo.org/models/repo"
|
||||||
|
user_model "forgejo.org/models/user"
|
||||||
|
)
|
||||||
|
|
||||||
|
// LookupRepoRedirect returns the repository ID if there's a redirect registered for
|
||||||
|
// the ownerID repository name pair. It checks if the doer has permission to view
|
||||||
|
// the new repository.
|
||||||
|
func LookupRepoRedirect(ctx context.Context, doer *user_model.User, ownerID int64, repoName string) (int64, error) {
|
||||||
|
redirectID, err := repo_model.GetRedirect(ctx, ownerID, repoName)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
redirectRepo, err := repo_model.GetRepositoryByID(ctx, redirectID)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
perm, err := access_model.GetUserRepoPermission(ctx, redirectRepo, doer)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !perm.HasAccess() {
|
||||||
|
return 0, repo_model.ErrRedirectNotExist{OwnerID: ownerID, RepoName: repoName, MissingPermission: true}
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirectID, nil
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue