diff options
Diffstat (limited to 'models')
-rw-r--r-- | models/migrations/migrations.go | 1 | ||||
-rw-r--r-- | models/org.go | 36 | ||||
-rw-r--r-- | models/org_test.go | 71 | ||||
-rw-r--r-- | models/repo_list.go | 35 | ||||
-rw-r--r-- | models/user.go | 64 |
5 files changed, 194 insertions, 13 deletions
diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index 174e7b5156..d6e7f31e46 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -1,4 +1,5 @@ // Copyright 2015 The Gogs Authors. All rights reserved. +// Copyright 2017 The Gitea Authors. All rights reserved. // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. diff --git a/models/org.go b/models/org.go index daff110cf5..2e22ae987b 100644 --- a/models/org.go +++ b/models/org.go @@ -1,4 +1,5 @@ // Copyright 2014 The Gogs Authors. All rights reserved. +// Copyright 2019 The Gitea Authors. All rights reserved. // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. @@ -11,6 +12,7 @@ import ( "strings" "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/structs" "github.com/Unknwon/com" "github.com/go-xorm/builder" @@ -366,6 +368,40 @@ func getOwnedOrgsByUserID(sess *xorm.Session, userID int64) ([]*User, error) { Find(&orgs) } +// HasOrgVisible tells if the given user can see the given org +func HasOrgVisible(org *User, user *User) bool { + // Not SignedUser + if user == nil { + if org.Visibility == structs.VisibleTypePublic { + return true + } + return false + } + + if user.IsAdmin { + return true + } + + if org.Visibility == structs.VisibleTypePrivate && !org.IsUserPartOfOrg(user.ID) { + return false + } + return true +} + +// HasOrgsVisible tells if the given user can see at least one of the orgs provided +func HasOrgsVisible(orgs []*User, user *User) bool { + if len(orgs) == 0 { + return false + } + + for _, org := range orgs { + if HasOrgVisible(org, user) { + return true + } + } + return false +} + // GetOwnedOrgsByUserID returns a list of organizations are owned by given user ID. func GetOwnedOrgsByUserID(userID int64) ([]*User, error) { sess := x.NewSession() diff --git a/models/org_test.go b/models/org_test.go index 4790f69971..b484208be1 100644 --- a/models/org_test.go +++ b/models/org_test.go @@ -7,6 +7,8 @@ package models import ( "testing" + "code.gitea.io/gitea/modules/structs" + "github.com/stretchr/testify/assert" ) @@ -545,3 +547,72 @@ func TestAccessibleReposEnv_MirrorRepos(t *testing.T) { testSuccess(2, []int64{5}) testSuccess(4, []int64{}) } + +func TestHasOrgVisibleTypePublic(t *testing.T) { + assert.NoError(t, PrepareTestDatabase()) + owner := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User) + user3 := AssertExistsAndLoadBean(t, &User{ID: 3}).(*User) + + const newOrgName = "test-org-public" + org := &User{ + Name: newOrgName, + Visibility: structs.VisibleTypePublic, + } + + AssertNotExistsBean(t, &User{Name: org.Name, Type: UserTypeOrganization}) + assert.NoError(t, CreateOrganization(org, owner)) + org = AssertExistsAndLoadBean(t, + &User{Name: org.Name, Type: UserTypeOrganization}).(*User) + test1 := HasOrgVisible(org, owner) + test2 := HasOrgVisible(org, user3) + test3 := HasOrgVisible(org, nil) + assert.Equal(t, test1, true) // owner of org + assert.Equal(t, test2, true) // user not a part of org + assert.Equal(t, test3, true) // logged out user +} + +func TestHasOrgVisibleTypeLimited(t *testing.T) { + assert.NoError(t, PrepareTestDatabase()) + owner := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User) + user3 := AssertExistsAndLoadBean(t, &User{ID: 3}).(*User) + + const newOrgName = "test-org-limited" + org := &User{ + Name: newOrgName, + Visibility: structs.VisibleTypeLimited, + } + + AssertNotExistsBean(t, &User{Name: org.Name, Type: UserTypeOrganization}) + assert.NoError(t, CreateOrganization(org, owner)) + org = AssertExistsAndLoadBean(t, + &User{Name: org.Name, Type: UserTypeOrganization}).(*User) + test1 := HasOrgVisible(org, owner) + test2 := HasOrgVisible(org, user3) + test3 := HasOrgVisible(org, nil) + assert.Equal(t, test1, true) // owner of org + assert.Equal(t, test2, true) // user not a part of org + assert.Equal(t, test3, false) // logged out user +} + +func TestHasOrgVisibleTypePrivate(t *testing.T) { + assert.NoError(t, PrepareTestDatabase()) + owner := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User) + user3 := AssertExistsAndLoadBean(t, &User{ID: 3}).(*User) + + const newOrgName = "test-org-private" + org := &User{ + Name: newOrgName, + Visibility: structs.VisibleTypePrivate, + } + + AssertNotExistsBean(t, &User{Name: org.Name, Type: UserTypeOrganization}) + assert.NoError(t, CreateOrganization(org, owner)) + org = AssertExistsAndLoadBean(t, + &User{Name: org.Name, Type: UserTypeOrganization}).(*User) + test1 := HasOrgVisible(org, owner) + test2 := HasOrgVisible(org, user3) + test3 := HasOrgVisible(org, nil) + assert.Equal(t, test1, true) // owner of org + assert.Equal(t, test2, false) // user not a part of org + assert.Equal(t, test3, false) // logged out user +} diff --git a/models/repo_list.go b/models/repo_list.go index 049d1834f7..83d2665e8c 100644 --- a/models/repo_list.go +++ b/models/repo_list.go @@ -8,9 +8,11 @@ import ( "fmt" "strings" + "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" "github.com/go-xorm/builder" + "github.com/go-xorm/core" ) // RepositoryListDefaultPageSize is the default number of repositories @@ -171,6 +173,10 @@ func SearchRepositoryByName(opts *SearchRepoOptions) (RepositoryList, int64, err if !opts.Private { cond = cond.And(builder.Eq{"is_private": false}) + accessCond := builder.Or( + builder.NotIn("owner_id", builder.Select("id").From("`user`").Where(builder.Or(builder.Eq{"visibility": structs.VisibleTypeLimited}, builder.Eq{"visibility": structs.VisibleTypePrivate}))), + builder.NotIn("owner_id", builder.Select("id").From("`user`").Where(builder.Eq{"type": UserTypeOrganization}))) + cond = cond.And(accessCond) } if opts.OwnerID > 0 { @@ -193,6 +199,35 @@ func SearchRepositoryByName(opts *SearchRepoOptions) (RepositoryList, int64, err accessCond = accessCond.Or(collaborateCond) } + var exprCond builder.Cond + if DbCfg.Type == core.POSTGRES { + exprCond = builder.Expr("org_user.org_id = \"user\".id") + } else if DbCfg.Type == core.MSSQL { + exprCond = builder.Expr("org_user.org_id = [user].id") + } else { + exprCond = builder.Eq{"org_user.org_id": "user.id"} + } + + visibilityCond := builder.Or( + builder.In("owner_id", + builder.Select("org_id").From("org_user"). + LeftJoin("`user`", exprCond). + Where( + builder.And( + builder.Eq{"uid": opts.OwnerID}, + builder.Eq{"visibility": structs.VisibleTypePrivate})), + ), + builder.In("owner_id", + builder.Select("id").From("`user`"). + Where( + builder.Or( + builder.Eq{"visibility": structs.VisibleTypePublic}, + builder.Eq{"visibility": structs.VisibleTypeLimited})), + ), + builder.NotIn("owner_id", builder.Select("id").From("`user`").Where(builder.Eq{"type": UserTypeOrganization})), + ) + cond = cond.And(visibilityCond) + if opts.AllPublic { accessCond = accessCond.Or(builder.Eq{"is_private": false}) } diff --git a/models/user.go b/models/user.go index e50385d411..3fb1c3b59e 100644 --- a/models/user.go +++ b/models/user.go @@ -25,22 +25,23 @@ import ( "time" "unicode/utf8" - "github.com/Unknwon/com" - "github.com/go-xorm/builder" - "github.com/go-xorm/xorm" - "github.com/nfnt/resize" - "golang.org/x/crypto/pbkdf2" - "golang.org/x/crypto/ssh" - "code.gitea.io/git" - api "code.gitea.io/sdk/gitea" - "code.gitea.io/gitea/modules/avatar" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/generate" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" + api "code.gitea.io/sdk/gitea" + + "github.com/Unknwon/com" + "github.com/go-xorm/builder" + "github.com/go-xorm/core" + "github.com/go-xorm/xorm" + "github.com/nfnt/resize" + "golang.org/x/crypto/pbkdf2" + "golang.org/x/crypto/ssh" ) // UserType defines the user type @@ -136,8 +137,9 @@ type User struct { Description string NumTeams int NumMembers int - Teams []*Team `xorm:"-"` - Members []*User `xorm:"-"` + Teams []*Team `xorm:"-"` + Members []*User `xorm:"-"` + Visibility structs.VisibleType `xorm:"NOT NULL DEFAULT 0"` // Preferences DiffViewStyle string `xorm:"NOT NULL DEFAULT ''"` @@ -526,6 +528,16 @@ func (u *User) IsUserOrgOwner(orgID int64) bool { return isOwner } +// IsUserPartOfOrg returns true if user with userID is part of the u organisation. +func (u *User) IsUserPartOfOrg(userID int64) bool { + isMember, err := IsOrganizationMember(u.ID, userID) + if err != nil { + log.Error(4, "IsOrganizationMember: %v", err) + return false + } + return isMember +} + // IsPublicMember returns true if user public his/her membership in given organization. func (u *User) IsPublicMember(orgID int64) bool { isMember, err := IsPublicMembership(orgID, u.ID) @@ -1341,13 +1353,18 @@ type SearchUserOptions struct { UID int64 OrderBy SearchOrderBy Page int - PageSize int // Can be smaller than or equal to setting.UI.ExplorePagingNum + Private bool // Include private orgs in search + OwnerID int64 // id of user for visibility calculation + PageSize int // Can be smaller than or equal to setting.UI.ExplorePagingNum IsActive util.OptionalBool SearchByEmail bool // Search by email as well as username/full name } func (opts *SearchUserOptions) toConds() builder.Cond { - var cond builder.Cond = builder.Eq{"type": opts.Type} + + var cond = builder.NewCond() + cond = cond.And(builder.Eq{"type": opts.Type}) + if len(opts.Keyword) > 0 { lowerKeyword := strings.ToLower(opts.Keyword) keywordCond := builder.Or( @@ -1361,6 +1378,27 @@ func (opts *SearchUserOptions) toConds() builder.Cond { cond = cond.And(keywordCond) } + if !opts.Private { + // user not logged in and so they won't be allowed to see non-public orgs + cond = cond.And(builder.In("visibility", structs.VisibleTypePublic)) + } + + if opts.OwnerID > 0 { + var exprCond builder.Cond + if DbCfg.Type == core.MYSQL { + exprCond = builder.Expr("org_user.org_id = user.id") + } else if DbCfg.Type == core.MSSQL { + exprCond = builder.Expr("org_user.org_id = [user].id") + } else { + exprCond = builder.Expr("org_user.org_id = \"user\".id") + } + var accessCond = builder.NewCond() + accessCond = builder.Or( + builder.In("id", builder.Select("org_id").From("org_user").LeftJoin("`user`", exprCond).Where(builder.And(builder.Eq{"uid": opts.OwnerID}, builder.Eq{"visibility": structs.VisibleTypePrivate}))), + builder.In("visibility", structs.VisibleTypePublic, structs.VisibleTypeLimited)) + cond = cond.And(accessCond) + } + if opts.UID > 0 { cond = cond.And(builder.Eq{"id": opts.UID}) } |