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

Add teams to repo on collaboration page. #8045

Merged
merged 13 commits into from
Sep 23, 2019
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
17 changes: 17 additions & 0 deletions models/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -1370,6 +1370,23 @@ func (err ErrTeamAlreadyExist) Error() string {
return fmt.Sprintf("team already exists [org_id: %d, name: %s]", err.OrgID, err.Name)
}

// ErrTeamNotExist represents a "TeamNotExist" error
type ErrTeamNotExist struct {
OrgID int64
TeamID int64
Name string
}

// IsErrTeamNotExist checks if an error is a ErrTeamNotExist.
func IsErrTeamNotExist(err error) bool {
_, ok := err.(ErrTeamNotExist)
return ok
}

func (err ErrTeamNotExist) Error() string {
return fmt.Sprintf("team does not exist [org_id %d, team_id %d, name: %s]", err.OrgID, err.TeamID, err.Name)
}

//
// Two-factor authentication
//
Expand Down
11 changes: 11 additions & 0 deletions models/fixtures/repository.yml
Original file line number Diff line number Diff line change
Expand Up @@ -508,4 +508,15 @@
num_stars: 0
num_forks: 0
num_issues: 0
is_mirror: false

-
id: 43
owner_id: 26
lower_name: repo26
name: repo26
is_private: true
num_stars: 0
num_forks: 0
num_issues: 0
is_mirror: false
9 changes: 9 additions & 0 deletions models/fixtures/team.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,12 @@
authorize: 1 # owner
num_repos: 0
num_members: 1

-
id: 11
org_id: 26
lower_name: team11
name: team11
authorize: 1 # read
num_repos: 0
num_members: 0
18 changes: 18 additions & 0 deletions models/fixtures/user.yml
Original file line number Diff line number Diff line change
Expand Up @@ -410,3 +410,21 @@
num_repos: 0
num_members: 1
num_teams: 1

-
id: 26
lower_name: org26
name: org26
full_name: "Org26"
email: org26@example.com
email_notifications_preference: onmention
passwd: 7d93daa0d1e6f2305cc8fa496847d61dc7320bb16262f9c55dd753480207234cdd96a93194e408341971742f4701772a025a # password
type: 1 # organization
salt: ZogKvWdyEx
is_admin: false
avatar: avatar26
avatar_email: org26@example.com
num_repos: 1
num_members: 0
num_teams: 1
repo_admin_change_team_access: true
2 changes: 2 additions & 0 deletions models/migrations/migrations.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,8 @@ var migrations = []Migration{
NewMigration("add table columns for cross referencing issues", addCrossReferenceColumns),
// v96 -> v97
NewMigration("delete orphaned attachments", deleteOrphanedAttachments),
// v97 -> v98
NewMigration("add repo_admin_change_team_access to user", addRepoAdminChangeTeamAccessColumnForUser),
}

// Migrate database to current version
Expand Down
15 changes: 15 additions & 0 deletions models/migrations/v97.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// 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.

package migrations

import "github.com/go-xorm/xorm"

func addRepoAdminChangeTeamAccessColumnForUser(x *xorm.Engine) error {
type User struct {
RepoAdminChangeTeamAccess bool `xorm:"NOT NULL DEFAULT false"`
}

return x.Sync2(new(User))
}
8 changes: 1 addition & 7 deletions models/org.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
package models

import (
"errors"
"fmt"
"os"
"strings"
Expand All @@ -20,11 +19,6 @@ import (
"xorm.io/builder"
)

var (
// ErrTeamNotExist team does not exist
ErrTeamNotExist = errors.New("Team does not exist")
)

// IsOwnedBy returns true if given user is in the owner team.
func (org *User) IsOwnedBy(uid int64) (bool, error) {
return IsOrganizationOwner(org.ID, uid)
Expand Down Expand Up @@ -304,7 +298,7 @@ type OrgUser struct {
func isOrganizationOwner(e Engine, orgID, uid int64) (bool, error) {
ownerTeam, err := getOwnerTeam(e, orgID)
if err != nil {
if err == ErrTeamNotExist {
if IsErrTeamNotExist(err) {
log.Error("Organization does not have owner team: %d", orgID)
return false, nil
}
Expand Down
4 changes: 2 additions & 2 deletions models/org_team.go
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ func getTeam(e Engine, orgID int64, name string) (*Team, error) {
if err != nil {
return nil, err
} else if !has {
return nil, ErrTeamNotExist
return nil, ErrTeamNotExist{orgID, 0, name}
}
return t, nil
}
Expand All @@ -373,7 +373,7 @@ func getTeamByID(e Engine, teamID int64) (*Team, error) {
if err != nil {
return nil, err
} else if !has {
return nil, ErrTeamNotExist
return nil, ErrTeamNotExist{0, teamID, ""}
}
return t, nil
}
Expand Down
6 changes: 3 additions & 3 deletions models/org_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,11 @@ func TestUser_GetTeam(t *testing.T) {
assert.Equal(t, "team1", team.LowerName)

_, err = org.GetTeam("does not exist")
assert.Equal(t, ErrTeamNotExist, err)
assert.True(t, IsErrTeamNotExist(err))

nonOrg := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
_, err = nonOrg.GetTeam("team")
assert.Equal(t, ErrTeamNotExist, err)
assert.True(t, IsErrTeamNotExist(err))
}

func TestUser_GetOwnerTeam(t *testing.T) {
Expand All @@ -80,7 +80,7 @@ func TestUser_GetOwnerTeam(t *testing.T) {

nonOrg := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
_, err = nonOrg.GetOwnerTeam()
assert.Equal(t, ErrTeamNotExist, err)
assert.True(t, IsErrTeamNotExist(err))
}

func TestUser_GetTeams(t *testing.T) {
Expand Down
28 changes: 14 additions & 14 deletions models/repo_collaboration.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,6 @@ type Collaboration struct {
Mode AccessMode `xorm:"DEFAULT 2 NOT NULL"`
}

// ModeI18nKey returns the collaboration mode I18n Key
func (c *Collaboration) ModeI18nKey() string {
switch c.Mode {
case AccessModeRead:
return "repo.settings.collaboration.read"
case AccessModeWrite:
return "repo.settings.collaboration.write"
case AccessModeAdmin:
return "repo.settings.collaboration.admin"
default:
return "repo.settings.collaboration.undefined"
}
}

// AddCollaborator adds new collaboration to a repository with default access mode.
func (repo *Repository) AddCollaborator(u *User) error {
collaboration := &Collaboration{
Expand Down Expand Up @@ -183,3 +169,17 @@ func (repo *Repository) DeleteCollaboration(uid int64) (err error) {

return sess.Commit()
}

func (repo *Repository) getRepoTeams(e Engine) (teams []*Team, err error) {
return teams, e.
Join("INNER", "team_repo", "team_repo.team_id = team.id").
Where("team.org_id = ?", repo.OwnerID).
And("team_repo.repo_id=?", repo.ID).
OrderBy("CASE WHEN name LIKE '" + ownerTeamName + "' THEN '' ELSE name END").
Find(&teams)
}

// GetRepoTeams gets the list of teams that has access to the repository
func (repo *Repository) GetRepoTeams() ([]*Team, error) {
davidsvantesson marked this conversation as resolved.
Show resolved Hide resolved
return repo.getRepoTeams(x)
}
11 changes: 0 additions & 11 deletions models/repo_collaboration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,6 @@ import (
"github.com/stretchr/testify/assert"
)

func TestCollaboration_ModeI18nKey(t *testing.T) {
assert.Equal(t, "repo.settings.collaboration.read",
(&Collaboration{Mode: AccessModeRead}).ModeI18nKey())
assert.Equal(t, "repo.settings.collaboration.write",
(&Collaboration{Mode: AccessModeWrite}).ModeI18nKey())
assert.Equal(t, "repo.settings.collaboration.admin",
(&Collaboration{Mode: AccessModeAdmin}).ModeI18nKey())
assert.Equal(t, "repo.settings.collaboration.undefined",
(&Collaboration{Mode: AccessModeNone}).ModeI18nKey())
}

func TestRepository_AddCollaborator(t *testing.T) {
assert.NoError(t, PrepareTestDatabase())

Expand Down
13 changes: 7 additions & 6 deletions models/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,12 +147,13 @@ type User struct {
NumRepos int

// For organization
NumTeams int
NumMembers int
Teams []*Team `xorm:"-"`
Members UserList `xorm:"-"`
MembersIsPublic map[int64]bool `xorm:"-"`
Visibility structs.VisibleType `xorm:"NOT NULL DEFAULT 0"`
NumTeams int
NumMembers int
Teams []*Team `xorm:"-"`
Members UserList `xorm:"-"`
MembersIsPublic map[int64]bool `xorm:"-"`
Visibility structs.VisibleType `xorm:"NOT NULL DEFAULT 0"`
RepoAdminChangeTeamAccess bool `xorm:"NOT NULL DEFAULT false"`

// Preferences
DiffViewStyle string `xorm:"NOT NULL DEFAULT ''"`
Expand Down
5 changes: 4 additions & 1 deletion models/user_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,10 @@ func TestSearchUsers(t *testing.T) {
testOrgSuccess(&SearchUserOptions{OrderBy: "id ASC", Page: 3, PageSize: 2},
[]int64{19, 25})

testOrgSuccess(&SearchUserOptions{Page: 4, PageSize: 2},
testOrgSuccess(&SearchUserOptions{OrderBy: "id ASC", Page: 4, PageSize: 2},
[]int64{26})

testOrgSuccess(&SearchUserOptions{Page: 5, PageSize: 2},
[]int64{})

// test users
Expand Down
2 changes: 1 addition & 1 deletion models/userlist.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func (users UserList) loadOrganizationOwners(e Engine, orgID int64) (map[int64]*
}
ownerTeam, err := getOwnerTeam(e, orgID)
if err != nil {
if err == ErrTeamNotExist {
if IsErrTeamNotExist(err) {
log.Error("Organization does not have owner team: %d", orgID)
return nil, nil
}
Expand Down
15 changes: 8 additions & 7 deletions modules/auth/org.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,14 @@ func (f *CreateOrgForm) Validate(ctx *macaron.Context, errs binding.Errors) bind

// UpdateOrgSettingForm form for updating organization settings
type UpdateOrgSettingForm struct {
Name string `binding:"Required;AlphaDashDot;MaxSize(40)" locale:"org.org_name_holder"`
FullName string `binding:"MaxSize(100)"`
Description string `binding:"MaxSize(255)"`
Website string `binding:"ValidUrl;MaxSize(255)"`
Location string `binding:"MaxSize(50)"`
Visibility structs.VisibleType
MaxRepoCreation int
Name string `binding:"Required;AlphaDashDot;MaxSize(40)" locale:"org.org_name_holder"`
FullName string `binding:"MaxSize(100)"`
Description string `binding:"MaxSize(255)"`
Website string `binding:"ValidUrl;MaxSize(255)"`
Location string `binding:"MaxSize(50)"`
Visibility structs.VisibleType
MaxRepoCreation int
RepoAdminChangeTeamAccess bool
}

// Validate validates the fields
Expand Down
23 changes: 13 additions & 10 deletions modules/structs/org.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ package structs

// Organization represents an organization
type Organization struct {
ID int64 `json:"id"`
UserName string `json:"username"`
FullName string `json:"full_name"`
AvatarURL string `json:"avatar_url"`
Description string `json:"description"`
Website string `json:"website"`
Location string `json:"location"`
Visibility string `json:"visibility"`
ID int64 `json:"id"`
UserName string `json:"username"`
FullName string `json:"full_name"`
AvatarURL string `json:"avatar_url"`
Description string `json:"description"`
Website string `json:"website"`
Location string `json:"location"`
Visibility string `json:"visibility"`
RepoAdminChangeTeamAccess bool `json:"repo_admin_change_team_access"`
}

// CreateOrgOption options for creating an organization
Expand All @@ -26,7 +27,8 @@ type CreateOrgOption struct {
Location string `json:"location"`
// possible values are `public` (default), `limited` or `private`
// enum: public,limited,private
Visibility string `json:"visibility" binding:"In(,public,limited,private)"`
Visibility string `json:"visibility" binding:"In(,public,limited,private)"`
RepoAdminChangeTeamAccess bool `json:"repo_admin_change_team_access"`
}

// EditOrgOption options for editing an organization
Expand All @@ -37,5 +39,6 @@ type EditOrgOption struct {
Location string `json:"location"`
// possible values are `public`, `limited` or `private`
// enum: public,limited,private
Visibility string `json:"visibility" binding:"In(,public,limited,private)"`
Visibility string `json:"visibility" binding:"In(,public,limited,private)"`
RepoAdminChangeTeamAccess bool `json:"repo_admin_change_team_access"`
}
9 changes: 9 additions & 0 deletions options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,7 @@ enterred_invalid_repo_name = The repository name you entered is incorrect.
enterred_invalid_owner_name = The new owner name is not valid.
enterred_invalid_password = The password you entered is incorrect.
user_not_exist = The user does not exist.
team_not_exist = The team does not exist.
last_org_owner = You cannot remove the last user from the 'owners' team. There must be at least one owner in any given team.
cannot_add_org_to_team = An organization cannot be added as a team member.

Expand Down Expand Up @@ -1136,6 +1137,7 @@ settings.collaboration = Collaborators
settings.collaboration.admin = Administrator
settings.collaboration.write = Write
settings.collaboration.read = Read
settings.collaboration.owner = Owner
settings.collaboration.undefined = Undefined
settings.hooks = Webhooks
settings.githooks = Git Hooks
Expand Down Expand Up @@ -1217,6 +1219,11 @@ settings.collaborator_deletion_desc = Removing a collaborator will revoke their
settings.remove_collaborator_success = The collaborator has been removed.
settings.search_user_placeholder = Search user…
settings.org_not_allowed_to_be_collaborator = Organizations cannot be added as a collaborator.
settings.change_team_access_not_allowed = Changing team access for repository has been restricted to organization owner
settings.team_not_in_organization = The team is not in the same organization as the repository
settings.add_team_duplicate = Team already has the repository
settings.add_team_success = The team now have access to the repository.
settings.remove_team_success = The team's access to the repository has been removed.
settings.add_webhook = Add Webhook
settings.add_webhook.invalid_channel_name = Webhook channel name cannot be empty and cannot contain only a # character.
settings.hooks_desc = Webhooks automatically make HTTP POST requests to a server when certain Gitea events trigger. Read more in the <a target="_blank" rel="noopener noreferrer" href="%s">webhooks guide</a>.
Expand Down Expand Up @@ -1475,6 +1482,8 @@ settings.options = Organization
settings.full_name = Full Name
settings.website = Website
settings.location = Location
settings.permission = Permissions
settings.repoadminchangeteam = Repository admin can add and remove access for teams
settings.visibility = Visibility
settings.visibility.public = Public
settings.visibility.limited = Limited (Visible to logged in users only)
Expand Down
3 changes: 3 additions & 0 deletions public/css/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -747,6 +747,8 @@ footer .ui.left,footer .ui.right{line-height:40px}
.repository.settings.collaboration .collaborator.list>.item:not(:last-child){border-bottom:1px solid #ddd}
.repository.settings.collaboration #repo-collab-form #search-user-box .results{left:7px}
.repository.settings.collaboration #repo-collab-form .ui.button{margin-left:5px;margin-top:-3px}
.repository.settings.collaboration #repo-collab-team-form #search-team-box .results{left:7px}
.repository.settings.collaboration #repo-collab-team-form .ui.button{margin-left:5px;margin-top:-3px}
.repository.settings.branches .protected-branches .selection.dropdown{width:300px}
.repository.settings.branches .protected-branches .item{border:1px solid #eaeaea;padding:10px 15px}
.repository.settings.branches .protected-branches .item:not(:last-child){border-bottom:0}
Expand Down Expand Up @@ -783,6 +785,7 @@ footer .ui.left,footer .ui.right{line-height:40px}
.user-cards .list .item .meta{margin-top:5px}
#search-repo-box .results .result .image,#search-user-box .results .result .image{float:left;margin-right:8px;width:2em;height:2em}
#search-repo-box .results .result .content,#search-user-box .results .result .content{margin:6px 0}
#search-team-box .results .result .content{margin:6px 0}
#issue-filters.hide{display:none}
#issue-actions{margin-top:-1rem!important}
#issue-actions.hide{display:none}
Expand Down
Loading