Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move accessmode into models/perm #17828

Merged
merged 2 commits into from
Nov 28, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
15 changes: 8 additions & 7 deletions cmd/serv.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"time"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/perm"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
Expand Down Expand Up @@ -64,11 +65,11 @@ func setup(logPath string, debug bool) {
}

var (
allowedCommands = map[string]models.AccessMode{
"git-upload-pack": models.AccessModeRead,
"git-upload-archive": models.AccessModeRead,
"git-receive-pack": models.AccessModeWrite,
lfsAuthenticateVerb: models.AccessModeNone,
allowedCommands = map[string]perm.AccessMode{
"git-upload-pack": perm.AccessModeRead,
"git-upload-archive": perm.AccessModeRead,
"git-receive-pack": perm.AccessModeWrite,
lfsAuthenticateVerb: perm.AccessModeNone,
}
alphaDashDotPattern = regexp.MustCompile(`[^\w-\.]`)
)
Expand Down Expand Up @@ -214,9 +215,9 @@ func runServ(c *cli.Context) error {

if verb == lfsAuthenticateVerb {
if lfsVerb == "upload" {
requestedMode = models.AccessModeWrite
requestedMode = perm.AccessModeWrite
} else if lfsVerb == "download" {
requestedMode = models.AccessModeRead
requestedMode = perm.AccessModeRead
} else {
return fail("Unknown LFS verb", "Unknown lfs verb %s", lfsVerb)
}
Expand Down
7 changes: 4 additions & 3 deletions integrations/api_helper_for_declarative_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"time"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/perm"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/queue"
api "code.gitea.io/gitea/modules/structs"
Expand Down Expand Up @@ -89,13 +90,13 @@ func doAPIEditRepository(ctx APITestContext, editRepoOption *api.EditRepoOption,
}
}

func doAPIAddCollaborator(ctx APITestContext, username string, mode models.AccessMode) func(*testing.T) {
func doAPIAddCollaborator(ctx APITestContext, username string, mode perm.AccessMode) func(*testing.T) {
return func(t *testing.T) {
permission := "read"

if mode == models.AccessModeAdmin {
if mode == perm.AccessModeAdmin {
permission = "admin"
} else if mode > models.AccessModeRead {
} else if mode > perm.AccessModeRead {
permission = "write"
}
addCollaboratorOption := &api.AddCollaboratorOption{
Expand Down
7 changes: 4 additions & 3 deletions integrations/api_keys_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"testing"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/perm"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
api "code.gitea.io/gitea/modules/structs"
Expand Down Expand Up @@ -67,7 +68,7 @@ func TestCreateReadOnlyDeployKey(t *testing.T) {
ID: newDeployKey.ID,
Name: rawKeyBody.Title,
Content: rawKeyBody.Key,
Mode: models.AccessModeRead,
Mode: perm.AccessModeRead,
})
}

Expand All @@ -92,7 +93,7 @@ func TestCreateReadWriteDeployKey(t *testing.T) {
ID: newDeployKey.ID,
Name: rawKeyBody.Title,
Content: rawKeyBody.Key,
Mode: models.AccessModeWrite,
Mode: perm.AccessModeWrite,
})
}

Expand All @@ -119,7 +120,7 @@ func TestCreateUserKey(t *testing.T) {
OwnerID: user.ID,
Name: rawKeyBody.Title,
Content: rawKeyBody.Key,
Mode: models.AccessModeWrite,
Mode: perm.AccessModeWrite,
})

// Search by fingerprint
Expand Down
25 changes: 13 additions & 12 deletions integrations/api_private_serv_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"testing"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/perm"
"code.gitea.io/gitea/modules/private"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -43,7 +44,7 @@ func TestAPIPrivateServ(t *testing.T) {
defer cancel()

// Can push to a repo we own
results, err := private.ServCommand(ctx, 1, "user2", "repo1", models.AccessModeWrite, "git-upload-pack", "")
results, err := private.ServCommand(ctx, 1, "user2", "repo1", perm.AccessModeWrite, "git-upload-pack", "")
assert.NoError(t, err)
assert.False(t, results.IsWiki)
assert.False(t, results.IsDeployKey)
Expand All @@ -56,17 +57,17 @@ func TestAPIPrivateServ(t *testing.T) {
assert.Equal(t, int64(1), results.RepoID)

// Cannot push to a private repo we're not associated with
results, err = private.ServCommand(ctx, 1, "user15", "big_test_private_1", models.AccessModeWrite, "git-upload-pack", "")
results, err = private.ServCommand(ctx, 1, "user15", "big_test_private_1", perm.AccessModeWrite, "git-upload-pack", "")
assert.Error(t, err)
assert.Empty(t, results)

// Cannot pull from a private repo we're not associated with
results, err = private.ServCommand(ctx, 1, "user15", "big_test_private_1", models.AccessModeRead, "git-upload-pack", "")
results, err = private.ServCommand(ctx, 1, "user15", "big_test_private_1", perm.AccessModeRead, "git-upload-pack", "")
assert.Error(t, err)
assert.Empty(t, results)

// Can pull from a public repo we're not associated with
results, err = private.ServCommand(ctx, 1, "user15", "big_test_public_1", models.AccessModeRead, "git-upload-pack", "")
results, err = private.ServCommand(ctx, 1, "user15", "big_test_public_1", perm.AccessModeRead, "git-upload-pack", "")
assert.NoError(t, err)
assert.False(t, results.IsWiki)
assert.False(t, results.IsDeployKey)
Expand All @@ -79,7 +80,7 @@ func TestAPIPrivateServ(t *testing.T) {
assert.Equal(t, int64(17), results.RepoID)

// Cannot push to a public repo we're not associated with
results, err = private.ServCommand(ctx, 1, "user15", "big_test_public_1", models.AccessModeWrite, "git-upload-pack", "")
results, err = private.ServCommand(ctx, 1, "user15", "big_test_public_1", perm.AccessModeWrite, "git-upload-pack", "")
assert.Error(t, err)
assert.Empty(t, results)

Expand All @@ -88,7 +89,7 @@ func TestAPIPrivateServ(t *testing.T) {
assert.NoError(t, err)

// Can pull from repo we're a deploy key for
results, err = private.ServCommand(ctx, deployKey.KeyID, "user15", "big_test_private_1", models.AccessModeRead, "git-upload-pack", "")
results, err = private.ServCommand(ctx, deployKey.KeyID, "user15", "big_test_private_1", perm.AccessModeRead, "git-upload-pack", "")
assert.NoError(t, err)
assert.False(t, results.IsWiki)
assert.True(t, results.IsDeployKey)
Expand All @@ -101,17 +102,17 @@ func TestAPIPrivateServ(t *testing.T) {
assert.Equal(t, int64(19), results.RepoID)

// Cannot push to a private repo with reading key
results, err = private.ServCommand(ctx, deployKey.KeyID, "user15", "big_test_private_1", models.AccessModeWrite, "git-upload-pack", "")
results, err = private.ServCommand(ctx, deployKey.KeyID, "user15", "big_test_private_1", perm.AccessModeWrite, "git-upload-pack", "")
assert.Error(t, err)
assert.Empty(t, results)

// Cannot pull from a private repo we're not associated with
results, err = private.ServCommand(ctx, deployKey.ID, "user15", "big_test_private_2", models.AccessModeRead, "git-upload-pack", "")
results, err = private.ServCommand(ctx, deployKey.ID, "user15", "big_test_private_2", perm.AccessModeRead, "git-upload-pack", "")
assert.Error(t, err)
assert.Empty(t, results)

// Cannot pull from a public repo we're not associated with
results, err = private.ServCommand(ctx, deployKey.ID, "user15", "big_test_public_1", models.AccessModeRead, "git-upload-pack", "")
results, err = private.ServCommand(ctx, deployKey.ID, "user15", "big_test_public_1", perm.AccessModeRead, "git-upload-pack", "")
assert.Error(t, err)
assert.Empty(t, results)

Expand All @@ -120,12 +121,12 @@ func TestAPIPrivateServ(t *testing.T) {
assert.NoError(t, err)

// Cannot push to a private repo with reading key
results, err = private.ServCommand(ctx, deployKey.KeyID, "user15", "big_test_private_1", models.AccessModeWrite, "git-upload-pack", "")
results, err = private.ServCommand(ctx, deployKey.KeyID, "user15", "big_test_private_1", perm.AccessModeWrite, "git-upload-pack", "")
assert.Error(t, err)
assert.Empty(t, results)

// Can pull from repo we're a writing deploy key for
results, err = private.ServCommand(ctx, deployKey.KeyID, "user15", "big_test_private_2", models.AccessModeRead, "git-upload-pack", "")
results, err = private.ServCommand(ctx, deployKey.KeyID, "user15", "big_test_private_2", perm.AccessModeRead, "git-upload-pack", "")
assert.NoError(t, err)
assert.False(t, results.IsWiki)
assert.True(t, results.IsDeployKey)
Expand All @@ -138,7 +139,7 @@ func TestAPIPrivateServ(t *testing.T) {
assert.Equal(t, int64(20), results.RepoID)

// Can push to repo we're a writing deploy key for
results, err = private.ServCommand(ctx, deployKey.KeyID, "user15", "big_test_private_2", models.AccessModeWrite, "git-upload-pack", "")
results, err = private.ServCommand(ctx, deployKey.KeyID, "user15", "big_test_private_2", perm.AccessModeWrite, "git-upload-pack", "")
assert.NoError(t, err)
assert.False(t, results.IsWiki)
assert.True(t, results.IsDeployKey)
Expand Down
5 changes: 3 additions & 2 deletions integrations/git_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"time"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/perm"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/git"
Expand Down Expand Up @@ -58,7 +59,7 @@ func testGit(t *testing.T, u *url.URL) {
defer util.RemoveAll(dstPath)

t.Run("CreateRepoInDifferentUser", doAPICreateRepository(forkedUserCtx, false))
t.Run("AddUserAsCollaborator", doAPIAddCollaborator(forkedUserCtx, httpContext.Username, models.AccessModeRead))
t.Run("AddUserAsCollaborator", doAPIAddCollaborator(forkedUserCtx, httpContext.Username, perm.AccessModeRead))

t.Run("ForkFromDifferentUser", doAPIForkRepository(httpContext, forkedUserCtx.Username))

Expand Down Expand Up @@ -91,7 +92,7 @@ func testGit(t *testing.T, u *url.URL) {
keyname := "my-testing-key"
forkedUserCtx.Reponame = sshContext.Reponame
t.Run("CreateRepoInDifferentUser", doAPICreateRepository(forkedUserCtx, false))
t.Run("AddUserAsCollaborator", doAPIAddCollaborator(forkedUserCtx, sshContext.Username, models.AccessModeRead))
t.Run("AddUserAsCollaborator", doAPIAddCollaborator(forkedUserCtx, sshContext.Username, perm.AccessModeRead))
t.Run("ForkFromDifferentUser", doAPIForkRepository(sshContext, forkedUserCtx.Username))

//Setup key the user ssh key
Expand Down
84 changes: 17 additions & 67 deletions models/access.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,76 +9,26 @@ import (
"fmt"

"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/perm"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/log"
)

// AccessMode specifies the users access mode
type AccessMode int

const (
// AccessModeNone no access
AccessModeNone AccessMode = iota // 0
// AccessModeRead read access
AccessModeRead // 1
// AccessModeWrite write access
AccessModeWrite // 2
// AccessModeAdmin admin access
AccessModeAdmin // 3
// AccessModeOwner owner access
AccessModeOwner // 4
)

func (mode AccessMode) String() string {
switch mode {
case AccessModeRead:
return "read"
case AccessModeWrite:
return "write"
case AccessModeAdmin:
return "admin"
case AccessModeOwner:
return "owner"
default:
return "none"
}
}

// ColorFormat provides a ColorFormatted version of this AccessMode
func (mode AccessMode) ColorFormat(s fmt.State) {
log.ColorFprintf(s, "%d:%s",
log.NewColoredIDValue(mode),
mode)
}

// ParseAccessMode returns corresponding access mode to given permission string.
func ParseAccessMode(permission string) AccessMode {
switch permission {
case "write":
return AccessModeWrite
case "admin":
return AccessModeAdmin
default:
return AccessModeRead
}
}

// Access represents the highest access level of a user to the repository. The only access type
// that is not in this table is the real owner of a repository. In case of an organization
// repository, the members of the owners team are in this table.
type Access struct {
ID int64 `xorm:"pk autoincr"`
UserID int64 `xorm:"UNIQUE(s)"`
RepoID int64 `xorm:"UNIQUE(s)"`
Mode AccessMode
Mode perm.AccessMode
}

func init() {
db.RegisterModel(new(Access))
}

func accessLevel(e db.Engine, user *user_model.User, repo *Repository) (AccessMode, error) {
mode := AccessModeNone
func accessLevel(e db.Engine, user *user_model.User, repo *Repository) (perm.AccessMode, error) {
mode := perm.AccessModeNone
var userID int64
restricted := false

Expand All @@ -88,15 +38,15 @@ func accessLevel(e db.Engine, user *user_model.User, repo *Repository) (AccessMo
}

if !restricted && !repo.IsPrivate {
mode = AccessModeRead
mode = perm.AccessModeRead
}

if userID == 0 {
return mode, nil
}

if userID == repo.OwnerID {
return AccessModeOwner, nil
return perm.AccessModeOwner, nil
}

a := &Access{UserID: userID, RepoID: repo.ID}
Expand All @@ -106,8 +56,8 @@ func accessLevel(e db.Engine, user *user_model.User, repo *Repository) (AccessMo
return a.Mode, nil
}

func maxAccessMode(modes ...AccessMode) AccessMode {
max := AccessModeNone
func maxAccessMode(modes ...perm.AccessMode) perm.AccessMode {
max := perm.AccessModeNone
for _, mode := range modes {
if mode > max {
max = mode
Expand All @@ -118,11 +68,11 @@ func maxAccessMode(modes ...AccessMode) AccessMode {

type userAccess struct {
User *user_model.User
Mode AccessMode
Mode perm.AccessMode
}

// updateUserAccess updates an access map so that user has at least mode
func updateUserAccess(accessMap map[int64]*userAccess, user *user_model.User, mode AccessMode) {
func updateUserAccess(accessMap map[int64]*userAccess, user *user_model.User, mode perm.AccessMode) {
if ua, ok := accessMap[user.ID]; ok {
ua.Mode = maxAccessMode(ua.Mode, mode)
} else {
Expand All @@ -132,9 +82,9 @@ func updateUserAccess(accessMap map[int64]*userAccess, user *user_model.User, mo

// FIXME: do cross-comparison so reduce deletions and additions to the minimum?
func (repo *Repository) refreshAccesses(e db.Engine, accessMap map[int64]*userAccess) (err error) {
minMode := AccessModeRead
minMode := perm.AccessModeRead
if !repo.IsPrivate {
minMode = AccessModeWrite
minMode = perm.AccessModeWrite
}

newAccesses := make([]Access, 0, len(accessMap))
Expand Down Expand Up @@ -208,7 +158,7 @@ func (repo *Repository) recalculateTeamAccesses(e db.Engine, ignTeamID int64) (e
// Owner team gets owner access, and skip for teams that do not
// have relations with repository.
if t.IsOwnerTeam() {
t.Authorize = AccessModeOwner
t.Authorize = perm.AccessModeOwner
} else if !t.hasRepository(e, repo.ID) {
continue
}
Expand All @@ -227,12 +177,12 @@ func (repo *Repository) recalculateTeamAccesses(e db.Engine, ignTeamID int64) (e
// recalculateUserAccess recalculates new access for a single user
// Usable if we know access only affected one user
func (repo *Repository) recalculateUserAccess(e db.Engine, uid int64) (err error) {
minMode := AccessModeRead
minMode := perm.AccessModeRead
if !repo.IsPrivate {
minMode = AccessModeWrite
minMode = perm.AccessModeWrite
}

accessMode := AccessModeNone
accessMode := perm.AccessModeNone
collaborator, err := repo.getCollaboration(e, uid)
if err != nil {
return err
Expand All @@ -255,7 +205,7 @@ func (repo *Repository) recalculateUserAccess(e db.Engine, uid int64) (err error

for _, t := range teams {
if t.IsOwnerTeam() {
t.Authorize = AccessModeOwner
t.Authorize = perm.AccessModeOwner
}

accessMode = maxAccessMode(accessMode, t.Authorize)
Expand Down
Loading