Skip to content

Commit

Permalink
Move accessmode into models/perm (go-gitea#17828)
Browse files Browse the repository at this point in the history
  • Loading branch information
lunny authored and Stelios Malathouras committed Mar 28, 2022
1 parent bad431a commit 8b473fc
Show file tree
Hide file tree
Showing 59 changed files with 359 additions and 295 deletions.
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

0 comments on commit 8b473fc

Please sign in to comment.