#1692 add admin APIs to add/remove a user from teams
This commit is contained in:
		
							parent
							
								
									9dda9ef07c
								
							
						
					
					
						commit
						b1d41cfa60
					
				| @ -3,7 +3,7 @@ Gogs - Go Git Service [ |  | ||||||
| 
 | 
 | ||||||
| ##### Current version: 0.9.15 | ##### Current version: 0.9.16 | ||||||
| 
 | 
 | ||||||
| | Web | UI  | Preview  | | | Web | UI  | Preview  | | ||||||
| |:-------------:|:-------:|:-------:| | |:-------------:|:-------:|:-------:| | ||||||
|  | |||||||
							
								
								
									
										2
									
								
								gogs.go
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								gogs.go
									
									
									
									
									
								
							| @ -17,7 +17,7 @@ import ( | |||||||
| 	"github.com/gogits/gogs/modules/setting" | 	"github.com/gogits/gogs/modules/setting" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| const APP_VER = "0.9.15.0323" | const APP_VER = "0.9.16.0325" | ||||||
| 
 | 
 | ||||||
| func init() { | func init() { | ||||||
| 	runtime.GOMAXPROCS(runtime.NumCPU()) | 	runtime.GOMAXPROCS(runtime.NumCPU()) | ||||||
|  | |||||||
							
								
								
									
										612
									
								
								models/org.go
									
									
									
									
									
								
							
							
						
						
									
										612
									
								
								models/org.go
									
									
									
									
									
								
							| @ -426,618 +426,6 @@ func RemoveOrgUser(orgId, uid int64) error { | |||||||
| 	return sess.Commit() | 	return sess.Commit() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // ___________
 |  | ||||||
| // \__    ___/___ _____    _____
 |  | ||||||
| //   |    |_/ __ \\__  \  /     \
 |  | ||||||
| //   |    |\  ___/ / __ \|  Y Y  \
 |  | ||||||
| //   |____| \___  >____  /__|_|  /
 |  | ||||||
| //              \/     \/      \/
 |  | ||||||
| 
 |  | ||||||
| const OWNER_TEAM = "Owners" |  | ||||||
| 
 |  | ||||||
| // Team represents a organization team.
 |  | ||||||
| type Team struct { |  | ||||||
| 	ID          int64 `xorm:"pk autoincr"` |  | ||||||
| 	OrgID       int64 `xorm:"INDEX"` |  | ||||||
| 	LowerName   string |  | ||||||
| 	Name        string |  | ||||||
| 	Description string |  | ||||||
| 	Authorize   AccessMode |  | ||||||
| 	Repos       []*Repository `xorm:"-"` |  | ||||||
| 	Members     []*User       `xorm:"-"` |  | ||||||
| 	NumRepos    int |  | ||||||
| 	NumMembers  int |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // IsOwnerTeam returns true if team is owner team.
 |  | ||||||
| func (t *Team) IsOwnerTeam() bool { |  | ||||||
| 	return t.Name == OWNER_TEAM |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // IsTeamMember returns true if given user is a member of team.
 |  | ||||||
| func (t *Team) IsMember(uid int64) bool { |  | ||||||
| 	return IsTeamMember(t.OrgID, t.ID, uid) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (t *Team) getRepositories(e Engine) (err error) { |  | ||||||
| 	teamRepos := make([]*TeamRepo, 0, t.NumRepos) |  | ||||||
| 	if err = x.Where("team_id=?", t.ID).Find(&teamRepos); err != nil { |  | ||||||
| 		return fmt.Errorf("get team-repos: %v", err) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	t.Repos = make([]*Repository, 0, len(teamRepos)) |  | ||||||
| 	for i := range teamRepos { |  | ||||||
| 		repo, err := getRepositoryByID(e, teamRepos[i].RepoID) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return fmt.Errorf("getRepositoryById(%d): %v", teamRepos[i].RepoID, err) |  | ||||||
| 		} |  | ||||||
| 		t.Repos = append(t.Repos, repo) |  | ||||||
| 	} |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // GetRepositories returns all repositories in team of organization.
 |  | ||||||
| func (t *Team) GetRepositories() error { |  | ||||||
| 	return t.getRepositories(x) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (t *Team) getMembers(e Engine) (err error) { |  | ||||||
| 	t.Members, err = getTeamMembers(e, t.ID) |  | ||||||
| 	return err |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // GetMembers returns all members in team of organization.
 |  | ||||||
| func (t *Team) GetMembers() (err error) { |  | ||||||
| 	return t.getMembers(x) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // AddMember adds new member to team of organization.
 |  | ||||||
| func (t *Team) AddMember(uid int64) error { |  | ||||||
| 	return AddTeamMember(t.OrgID, t.ID, uid) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // RemoveMember removes member from team of organization.
 |  | ||||||
| func (t *Team) RemoveMember(uid int64) error { |  | ||||||
| 	return RemoveTeamMember(t.OrgID, t.ID, uid) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (t *Team) hasRepository(e Engine, repoID int64) bool { |  | ||||||
| 	return hasTeamRepo(e, t.OrgID, t.ID, repoID) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // HasRepository returns true if given repository belong to team.
 |  | ||||||
| func (t *Team) HasRepository(repoID int64) bool { |  | ||||||
| 	return t.hasRepository(x, repoID) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (t *Team) addRepository(e Engine, repo *Repository) (err error) { |  | ||||||
| 	if err = addTeamRepo(e, t.OrgID, t.ID, repo.ID); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	t.NumRepos++ |  | ||||||
| 	if _, err = e.Id(t.ID).AllCols().Update(t); err != nil { |  | ||||||
| 		return fmt.Errorf("update team: %v", err) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if err = repo.recalculateTeamAccesses(e, 0); err != nil { |  | ||||||
| 		return fmt.Errorf("recalculateAccesses: %v", err) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if err = t.getMembers(e); err != nil { |  | ||||||
| 		return fmt.Errorf("getMembers: %v", err) |  | ||||||
| 	} |  | ||||||
| 	for _, u := range t.Members { |  | ||||||
| 		if err = watchRepo(e, u.Id, repo.ID, true); err != nil { |  | ||||||
| 			return fmt.Errorf("watchRepo: %v", err) |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // AddRepository adds new repository to team of organization.
 |  | ||||||
| func (t *Team) AddRepository(repo *Repository) (err error) { |  | ||||||
| 	if repo.OwnerID != t.OrgID { |  | ||||||
| 		return errors.New("Repository does not belong to organization") |  | ||||||
| 	} else if t.HasRepository(repo.ID) { |  | ||||||
| 		return nil |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	sess := x.NewSession() |  | ||||||
| 	defer sessionRelease(sess) |  | ||||||
| 	if err = sess.Begin(); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if err = t.addRepository(sess, repo); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return sess.Commit() |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (t *Team) removeRepository(e Engine, repo *Repository, recalculate bool) (err error) { |  | ||||||
| 	if err = removeTeamRepo(e, t.ID, repo.ID); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	t.NumRepos-- |  | ||||||
| 	if _, err = e.Id(t.ID).AllCols().Update(t); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Don't need to recalculate when delete a repository from organization.
 |  | ||||||
| 	if recalculate { |  | ||||||
| 		if err = repo.recalculateTeamAccesses(e, t.ID); err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if err = t.getMembers(e); err != nil { |  | ||||||
| 		return fmt.Errorf("get team members: %v", err) |  | ||||||
| 	} |  | ||||||
| 	for _, u := range t.Members { |  | ||||||
| 		has, err := hasAccess(e, u, repo, ACCESS_MODE_READ) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} else if has { |  | ||||||
| 			continue |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		if err = watchRepo(e, u.Id, repo.ID, false); err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // RemoveRepository removes repository from team of organization.
 |  | ||||||
| func (t *Team) RemoveRepository(repoID int64) error { |  | ||||||
| 	if !t.HasRepository(repoID) { |  | ||||||
| 		return nil |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	repo, err := GetRepositoryByID(repoID) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	sess := x.NewSession() |  | ||||||
| 	defer sessionRelease(sess) |  | ||||||
| 	if err = sess.Begin(); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if err = t.removeRepository(sess, repo, true); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return sess.Commit() |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // NewTeam creates a record of new team.
 |  | ||||||
| // It's caller's responsibility to assign organization ID.
 |  | ||||||
| func NewTeam(t *Team) error { |  | ||||||
| 	if len(t.Name) == 0 { |  | ||||||
| 		return errors.New("empty team name") |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	has, err := x.Id(t.OrgID).Get(new(User)) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} else if !has { |  | ||||||
| 		return ErrOrgNotExist |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	t.LowerName = strings.ToLower(t.Name) |  | ||||||
| 	has, err = x.Where("org_id=?", t.OrgID).And("lower_name=?", t.LowerName).Get(new(Team)) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} else if has { |  | ||||||
| 		return ErrTeamAlreadyExist{t.OrgID, t.LowerName} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	sess := x.NewSession() |  | ||||||
| 	defer sess.Close() |  | ||||||
| 	if err = sess.Begin(); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if _, err = sess.Insert(t); err != nil { |  | ||||||
| 		sess.Rollback() |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Update organization number of teams.
 |  | ||||||
| 	if _, err = sess.Exec("UPDATE `user` SET num_teams=num_teams+1 WHERE id = ?", t.OrgID); err != nil { |  | ||||||
| 		sess.Rollback() |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	return sess.Commit() |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func getTeam(e Engine, orgId int64, name string) (*Team, error) { |  | ||||||
| 	t := &Team{ |  | ||||||
| 		OrgID:     orgId, |  | ||||||
| 		LowerName: strings.ToLower(name), |  | ||||||
| 	} |  | ||||||
| 	has, err := e.Get(t) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} else if !has { |  | ||||||
| 		return nil, ErrTeamNotExist |  | ||||||
| 	} |  | ||||||
| 	return t, nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // GetTeam returns team by given team name and organization.
 |  | ||||||
| func GetTeam(orgId int64, name string) (*Team, error) { |  | ||||||
| 	return getTeam(x, orgId, name) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func getTeamById(e Engine, teamId int64) (*Team, error) { |  | ||||||
| 	t := new(Team) |  | ||||||
| 	has, err := e.Id(teamId).Get(t) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} else if !has { |  | ||||||
| 		return nil, ErrTeamNotExist |  | ||||||
| 	} |  | ||||||
| 	return t, nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // GetTeamById returns team by given ID.
 |  | ||||||
| func GetTeamById(teamId int64) (*Team, error) { |  | ||||||
| 	return getTeamById(x, teamId) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // UpdateTeam updates information of team.
 |  | ||||||
| func UpdateTeam(t *Team, authChanged bool) (err error) { |  | ||||||
| 	if len(t.Name) == 0 { |  | ||||||
| 		return errors.New("empty team name") |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if len(t.Description) > 255 { |  | ||||||
| 		t.Description = t.Description[:255] |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	sess := x.NewSession() |  | ||||||
| 	defer sessionRelease(sess) |  | ||||||
| 	if err = sess.Begin(); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	t.LowerName = strings.ToLower(t.Name) |  | ||||||
| 	has, err := x.Where("org_id=?", t.OrgID).And("lower_name=?", t.LowerName).And("id!=?", t.ID).Get(new(Team)) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} else if has { |  | ||||||
| 		return ErrTeamAlreadyExist{t.OrgID, t.LowerName} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if _, err = sess.Id(t.ID).AllCols().Update(t); err != nil { |  | ||||||
| 		return fmt.Errorf("update: %v", err) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Update access for team members if needed.
 |  | ||||||
| 	if authChanged { |  | ||||||
| 		if err = t.getRepositories(sess); err != nil { |  | ||||||
| 			return fmt.Errorf("getRepositories:%v", err) |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		for _, repo := range t.Repos { |  | ||||||
| 			if err = repo.recalculateTeamAccesses(sess, 0); err != nil { |  | ||||||
| 				return fmt.Errorf("recalculateTeamAccesses: %v", err) |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return sess.Commit() |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // DeleteTeam deletes given team.
 |  | ||||||
| // It's caller's responsibility to assign organization ID.
 |  | ||||||
| func DeleteTeam(t *Team) error { |  | ||||||
| 	if err := t.GetRepositories(); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Get organization.
 |  | ||||||
| 	org, err := GetUserByID(t.OrgID) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	sess := x.NewSession() |  | ||||||
| 	defer sessionRelease(sess) |  | ||||||
| 	if err = sess.Begin(); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Delete all accesses.
 |  | ||||||
| 	for _, repo := range t.Repos { |  | ||||||
| 		if err = repo.recalculateTeamAccesses(sess, t.ID); err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Delete team-user.
 |  | ||||||
| 	if _, err = sess.Where("org_id=?", org.Id).Where("team_id=?", t.ID).Delete(new(TeamUser)); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Delete team.
 |  | ||||||
| 	if _, err = sess.Id(t.ID).Delete(new(Team)); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	// Update organization number of teams.
 |  | ||||||
| 	if _, err = sess.Exec("UPDATE `user` SET num_teams=num_teams-1 WHERE id=?", t.OrgID); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return sess.Commit() |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // ___________                    ____ ___
 |  | ||||||
| // \__    ___/___ _____    _____ |    |   \______ ___________
 |  | ||||||
| //   |    |_/ __ \\__  \  /     \|    |   /  ___// __ \_  __ \
 |  | ||||||
| //   |    |\  ___/ / __ \|  Y Y  \    |  /\___ \\  ___/|  | \/
 |  | ||||||
| //   |____| \___  >____  /__|_|  /______//____  >\___  >__|
 |  | ||||||
| //              \/     \/      \/             \/     \/
 |  | ||||||
| 
 |  | ||||||
| // TeamUser represents an team-user relation.
 |  | ||||||
| type TeamUser struct { |  | ||||||
| 	ID     int64 `xorm:"pk autoincr"` |  | ||||||
| 	OrgID  int64 `xorm:"INDEX"` |  | ||||||
| 	TeamID int64 `xorm:"UNIQUE(s)"` |  | ||||||
| 	Uid    int64 `xorm:"UNIQUE(s)"` |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func isTeamMember(e Engine, orgID, teamID, uid int64) bool { |  | ||||||
| 	has, _ := e.Where("org_id=?", orgID).And("team_id=?", teamID).And("uid=?", uid).Get(new(TeamUser)) |  | ||||||
| 	return has |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // IsTeamMember returns true if given user is a member of team.
 |  | ||||||
| func IsTeamMember(orgID, teamID, uid int64) bool { |  | ||||||
| 	return isTeamMember(x, orgID, teamID, uid) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func getTeamMembers(e Engine, teamID int64) (_ []*User, err error) { |  | ||||||
| 	teamUsers := make([]*TeamUser, 0, 10) |  | ||||||
| 	if err = e.Where("team_id=?", teamID).Find(&teamUsers); err != nil { |  | ||||||
| 		return nil, fmt.Errorf("get team-users: %v", err) |  | ||||||
| 	} |  | ||||||
| 	members := make([]*User, 0, len(teamUsers)) |  | ||||||
| 	for i := range teamUsers { |  | ||||||
| 		member := new(User) |  | ||||||
| 		if _, err = e.Id(teamUsers[i].Uid).Get(member); err != nil { |  | ||||||
| 			return nil, fmt.Errorf("get user '%d': %v", teamUsers[i].Uid, err) |  | ||||||
| 		} |  | ||||||
| 		members = append(members, member) |  | ||||||
| 	} |  | ||||||
| 	return members, nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // GetTeamMembers returns all members in given team of organization.
 |  | ||||||
| func GetTeamMembers(teamID int64) ([]*User, error) { |  | ||||||
| 	return getTeamMembers(x, teamID) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func getUserTeams(e Engine, orgId, uid int64) ([]*Team, error) { |  | ||||||
| 	tus := make([]*TeamUser, 0, 5) |  | ||||||
| 	if err := e.Where("uid=?", uid).And("org_id=?", orgId).Find(&tus); err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	ts := make([]*Team, len(tus)) |  | ||||||
| 	for i, tu := range tus { |  | ||||||
| 		t := new(Team) |  | ||||||
| 		has, err := e.Id(tu.TeamID).Get(t) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return nil, err |  | ||||||
| 		} else if !has { |  | ||||||
| 			return nil, ErrTeamNotExist |  | ||||||
| 		} |  | ||||||
| 		ts[i] = t |  | ||||||
| 	} |  | ||||||
| 	return ts, nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // GetUserTeams returns all teams that user belongs to in given organization.
 |  | ||||||
| func GetUserTeams(orgId, uid int64) ([]*Team, error) { |  | ||||||
| 	return getUserTeams(x, orgId, uid) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // AddTeamMember adds new member to given team of given organization.
 |  | ||||||
| func AddTeamMember(orgId, teamId, uid int64) error { |  | ||||||
| 	if IsTeamMember(orgId, teamId, uid) { |  | ||||||
| 		return nil |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if err := AddOrgUser(orgId, uid); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Get team and its repositories.
 |  | ||||||
| 	t, err := GetTeamById(teamId) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	t.NumMembers++ |  | ||||||
| 
 |  | ||||||
| 	if err = t.GetRepositories(); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	sess := x.NewSession() |  | ||||||
| 	defer sessionRelease(sess) |  | ||||||
| 	if err = sess.Begin(); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	tu := &TeamUser{ |  | ||||||
| 		Uid:    uid, |  | ||||||
| 		OrgID:  orgId, |  | ||||||
| 		TeamID: teamId, |  | ||||||
| 	} |  | ||||||
| 	if _, err = sess.Insert(tu); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} else if _, err = sess.Id(t.ID).Update(t); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Give access to team repositories.
 |  | ||||||
| 	for _, repo := range t.Repos { |  | ||||||
| 		if err = repo.recalculateTeamAccesses(sess, 0); err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// We make sure it exists before.
 |  | ||||||
| 	ou := new(OrgUser) |  | ||||||
| 	if _, err = sess.Where("uid=?", uid).And("org_id=?", orgId).Get(ou); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	ou.NumTeams++ |  | ||||||
| 	if t.IsOwnerTeam() { |  | ||||||
| 		ou.IsOwner = true |  | ||||||
| 	} |  | ||||||
| 	if _, err = sess.Id(ou.ID).AllCols().Update(ou); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return sess.Commit() |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func removeTeamMember(e Engine, orgId, teamId, uid int64) error { |  | ||||||
| 	if !isTeamMember(e, orgId, teamId, uid) { |  | ||||||
| 		return nil |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Get team and its repositories.
 |  | ||||||
| 	t, err := getTeamById(e, teamId) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Check if the user to delete is the last member in owner team.
 |  | ||||||
| 	if t.IsOwnerTeam() && t.NumMembers == 1 { |  | ||||||
| 		return ErrLastOrgOwner{UID: uid} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	t.NumMembers-- |  | ||||||
| 
 |  | ||||||
| 	if err = t.getRepositories(e); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Get organization.
 |  | ||||||
| 	org, err := getUserByID(e, orgId) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	tu := &TeamUser{ |  | ||||||
| 		Uid:    uid, |  | ||||||
| 		OrgID:  orgId, |  | ||||||
| 		TeamID: teamId, |  | ||||||
| 	} |  | ||||||
| 	if _, err := e.Delete(tu); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} else if _, err = e.Id(t.ID).AllCols().Update(t); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Delete access to team repositories.
 |  | ||||||
| 	for _, repo := range t.Repos { |  | ||||||
| 		if err = repo.recalculateTeamAccesses(e, 0); err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// This must exist.
 |  | ||||||
| 	ou := new(OrgUser) |  | ||||||
| 	_, err = e.Where("uid=?", uid).And("org_id=?", org.Id).Get(ou) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	ou.NumTeams-- |  | ||||||
| 	if t.IsOwnerTeam() { |  | ||||||
| 		ou.IsOwner = false |  | ||||||
| 	} |  | ||||||
| 	if _, err = e.Id(ou.ID).AllCols().Update(ou); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // RemoveTeamMember removes member from given team of given organization.
 |  | ||||||
| func RemoveTeamMember(orgId, teamId, uid int64) error { |  | ||||||
| 	sess := x.NewSession() |  | ||||||
| 	defer sessionRelease(sess) |  | ||||||
| 	if err := sess.Begin(); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	if err := removeTeamMember(sess, orgId, teamId, uid); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	return sess.Commit() |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // ___________                  __________
 |  | ||||||
| // \__    ___/___ _____    _____\______   \ ____ ______   ____
 |  | ||||||
| //   |    |_/ __ \\__  \  /     \|       _// __ \\____ \ /  _ \
 |  | ||||||
| //   |    |\  ___/ / __ \|  Y Y  \    |   \  ___/|  |_> >  <_> )
 |  | ||||||
| //   |____| \___  >____  /__|_|  /____|_  /\___  >   __/ \____/
 |  | ||||||
| //              \/     \/      \/       \/     \/|__|
 |  | ||||||
| 
 |  | ||||||
| // TeamRepo represents an team-repository relation.
 |  | ||||||
| type TeamRepo struct { |  | ||||||
| 	ID     int64 `xorm:"pk autoincr"` |  | ||||||
| 	OrgID  int64 `xorm:"INDEX"` |  | ||||||
| 	TeamID int64 `xorm:"UNIQUE(s)"` |  | ||||||
| 	RepoID int64 `xorm:"UNIQUE(s)"` |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func hasTeamRepo(e Engine, orgID, teamID, repoID int64) bool { |  | ||||||
| 	has, _ := e.Where("org_id=?", orgID).And("team_id=?", teamID).And("repo_id=?", repoID).Get(new(TeamRepo)) |  | ||||||
| 	return has |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // HasTeamRepo returns true if given repository belongs to team.
 |  | ||||||
| func HasTeamRepo(orgID, teamID, repoID int64) bool { |  | ||||||
| 	return hasTeamRepo(x, orgID, teamID, repoID) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func addTeamRepo(e Engine, orgID, teamID, repoID int64) error { |  | ||||||
| 	_, err := e.InsertOne(&TeamRepo{ |  | ||||||
| 		OrgID:  orgID, |  | ||||||
| 		TeamID: teamID, |  | ||||||
| 		RepoID: repoID, |  | ||||||
| 	}) |  | ||||||
| 	return err |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // AddTeamRepo adds new repository relation to team.
 |  | ||||||
| func AddTeamRepo(orgID, teamID, repoID int64) error { |  | ||||||
| 	return addTeamRepo(x, orgID, teamID, repoID) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func removeTeamRepo(e Engine, teamID, repoID int64) error { |  | ||||||
| 	_, err := e.Delete(&TeamRepo{ |  | ||||||
| 		TeamID: teamID, |  | ||||||
| 		RepoID: repoID, |  | ||||||
| 	}) |  | ||||||
| 	return err |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // RemoveTeamRepo deletes repository relation to team.
 |  | ||||||
| func RemoveTeamRepo(teamID, repoID int64) error { |  | ||||||
| 	return removeTeamRepo(x, teamID, repoID) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func removeOrgRepo(e Engine, orgID, repoID int64) error { | func removeOrgRepo(e Engine, orgID, repoID int64) error { | ||||||
| 	_, err := e.Delete(&TeamRepo{ | 	_, err := e.Delete(&TeamRepo{ | ||||||
| 		OrgID:  orgID, | 		OrgID:  orgID, | ||||||
|  | |||||||
							
								
								
									
										618
									
								
								models/org_team.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										618
									
								
								models/org_team.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,618 @@ | |||||||
|  | // Copyright 2016 The Gogs 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 models | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"errors" | ||||||
|  | 	"fmt" | ||||||
|  | 	"strings" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | const OWNER_TEAM = "Owners" | ||||||
|  | 
 | ||||||
|  | // Team represents a organization team.
 | ||||||
|  | type Team struct { | ||||||
|  | 	ID          int64 `xorm:"pk autoincr"` | ||||||
|  | 	OrgID       int64 `xorm:"INDEX"` | ||||||
|  | 	LowerName   string | ||||||
|  | 	Name        string | ||||||
|  | 	Description string | ||||||
|  | 	Authorize   AccessMode | ||||||
|  | 	Repos       []*Repository `xorm:"-"` | ||||||
|  | 	Members     []*User       `xorm:"-"` | ||||||
|  | 	NumRepos    int | ||||||
|  | 	NumMembers  int | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // IsOwnerTeam returns true if team is owner team.
 | ||||||
|  | func (t *Team) IsOwnerTeam() bool { | ||||||
|  | 	return t.Name == OWNER_TEAM | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // IsTeamMember returns true if given user is a member of team.
 | ||||||
|  | func (t *Team) IsMember(uid int64) bool { | ||||||
|  | 	return IsTeamMember(t.OrgID, t.ID, uid) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (t *Team) getRepositories(e Engine) (err error) { | ||||||
|  | 	teamRepos := make([]*TeamRepo, 0, t.NumRepos) | ||||||
|  | 	if err = x.Where("team_id=?", t.ID).Find(&teamRepos); err != nil { | ||||||
|  | 		return fmt.Errorf("get team-repos: %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	t.Repos = make([]*Repository, 0, len(teamRepos)) | ||||||
|  | 	for i := range teamRepos { | ||||||
|  | 		repo, err := getRepositoryByID(e, teamRepos[i].RepoID) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return fmt.Errorf("getRepositoryById(%d): %v", teamRepos[i].RepoID, err) | ||||||
|  | 		} | ||||||
|  | 		t.Repos = append(t.Repos, repo) | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // GetRepositories returns all repositories in team of organization.
 | ||||||
|  | func (t *Team) GetRepositories() error { | ||||||
|  | 	return t.getRepositories(x) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (t *Team) getMembers(e Engine) (err error) { | ||||||
|  | 	t.Members, err = getTeamMembers(e, t.ID) | ||||||
|  | 	return err | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // GetMembers returns all members in team of organization.
 | ||||||
|  | func (t *Team) GetMembers() (err error) { | ||||||
|  | 	return t.getMembers(x) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // AddMember adds new membership of the team to the organization,
 | ||||||
|  | // the user will have membership to the organization automatically when needed.
 | ||||||
|  | func (t *Team) AddMember(uid int64) error { | ||||||
|  | 	return AddTeamMember(t.OrgID, t.ID, uid) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // RemoveMember removes member from team of organization.
 | ||||||
|  | func (t *Team) RemoveMember(uid int64) error { | ||||||
|  | 	return RemoveTeamMember(t.OrgID, t.ID, uid) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (t *Team) hasRepository(e Engine, repoID int64) bool { | ||||||
|  | 	return hasTeamRepo(e, t.OrgID, t.ID, repoID) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // HasRepository returns true if given repository belong to team.
 | ||||||
|  | func (t *Team) HasRepository(repoID int64) bool { | ||||||
|  | 	return t.hasRepository(x, repoID) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (t *Team) addRepository(e Engine, repo *Repository) (err error) { | ||||||
|  | 	if err = addTeamRepo(e, t.OrgID, t.ID, repo.ID); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	t.NumRepos++ | ||||||
|  | 	if _, err = e.Id(t.ID).AllCols().Update(t); err != nil { | ||||||
|  | 		return fmt.Errorf("update team: %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if err = repo.recalculateTeamAccesses(e, 0); err != nil { | ||||||
|  | 		return fmt.Errorf("recalculateAccesses: %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if err = t.getMembers(e); err != nil { | ||||||
|  | 		return fmt.Errorf("getMembers: %v", err) | ||||||
|  | 	} | ||||||
|  | 	for _, u := range t.Members { | ||||||
|  | 		if err = watchRepo(e, u.Id, repo.ID, true); err != nil { | ||||||
|  | 			return fmt.Errorf("watchRepo: %v", err) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // AddRepository adds new repository to team of organization.
 | ||||||
|  | func (t *Team) AddRepository(repo *Repository) (err error) { | ||||||
|  | 	if repo.OwnerID != t.OrgID { | ||||||
|  | 		return errors.New("Repository does not belong to organization") | ||||||
|  | 	} else if t.HasRepository(repo.ID) { | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	sess := x.NewSession() | ||||||
|  | 	defer sessionRelease(sess) | ||||||
|  | 	if err = sess.Begin(); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if err = t.addRepository(sess, repo); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return sess.Commit() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (t *Team) removeRepository(e Engine, repo *Repository, recalculate bool) (err error) { | ||||||
|  | 	if err = removeTeamRepo(e, t.ID, repo.ID); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	t.NumRepos-- | ||||||
|  | 	if _, err = e.Id(t.ID).AllCols().Update(t); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Don't need to recalculate when delete a repository from organization.
 | ||||||
|  | 	if recalculate { | ||||||
|  | 		if err = repo.recalculateTeamAccesses(e, t.ID); err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if err = t.getMembers(e); err != nil { | ||||||
|  | 		return fmt.Errorf("get team members: %v", err) | ||||||
|  | 	} | ||||||
|  | 	for _, u := range t.Members { | ||||||
|  | 		has, err := hasAccess(e, u, repo, ACCESS_MODE_READ) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} else if has { | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if err = watchRepo(e, u.Id, repo.ID, false); err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // RemoveRepository removes repository from team of organization.
 | ||||||
|  | func (t *Team) RemoveRepository(repoID int64) error { | ||||||
|  | 	if !t.HasRepository(repoID) { | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	repo, err := GetRepositoryByID(repoID) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	sess := x.NewSession() | ||||||
|  | 	defer sessionRelease(sess) | ||||||
|  | 	if err = sess.Begin(); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if err = t.removeRepository(sess, repo, true); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return sess.Commit() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // NewTeam creates a record of new team.
 | ||||||
|  | // It's caller's responsibility to assign organization ID.
 | ||||||
|  | func NewTeam(t *Team) error { | ||||||
|  | 	if len(t.Name) == 0 { | ||||||
|  | 		return errors.New("empty team name") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	has, err := x.Id(t.OrgID).Get(new(User)) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} else if !has { | ||||||
|  | 		return ErrOrgNotExist | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	t.LowerName = strings.ToLower(t.Name) | ||||||
|  | 	has, err = x.Where("org_id=?", t.OrgID).And("lower_name=?", t.LowerName).Get(new(Team)) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} else if has { | ||||||
|  | 		return ErrTeamAlreadyExist{t.OrgID, t.LowerName} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	sess := x.NewSession() | ||||||
|  | 	defer sess.Close() | ||||||
|  | 	if err = sess.Begin(); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if _, err = sess.Insert(t); err != nil { | ||||||
|  | 		sess.Rollback() | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Update organization number of teams.
 | ||||||
|  | 	if _, err = sess.Exec("UPDATE `user` SET num_teams=num_teams+1 WHERE id = ?", t.OrgID); err != nil { | ||||||
|  | 		sess.Rollback() | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	return sess.Commit() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func getTeam(e Engine, orgId int64, name string) (*Team, error) { | ||||||
|  | 	t := &Team{ | ||||||
|  | 		OrgID:     orgId, | ||||||
|  | 		LowerName: strings.ToLower(name), | ||||||
|  | 	} | ||||||
|  | 	has, err := e.Get(t) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} else if !has { | ||||||
|  | 		return nil, ErrTeamNotExist | ||||||
|  | 	} | ||||||
|  | 	return t, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // GetTeam returns team by given team name and organization.
 | ||||||
|  | func GetTeam(orgId int64, name string) (*Team, error) { | ||||||
|  | 	return getTeam(x, orgId, name) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func getTeamByID(e Engine, teamId int64) (*Team, error) { | ||||||
|  | 	t := new(Team) | ||||||
|  | 	has, err := e.Id(teamId).Get(t) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} else if !has { | ||||||
|  | 		return nil, ErrTeamNotExist | ||||||
|  | 	} | ||||||
|  | 	return t, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // GetTeamByID returns team by given ID.
 | ||||||
|  | func GetTeamByID(teamId int64) (*Team, error) { | ||||||
|  | 	return getTeamByID(x, teamId) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // UpdateTeam updates information of team.
 | ||||||
|  | func UpdateTeam(t *Team, authChanged bool) (err error) { | ||||||
|  | 	if len(t.Name) == 0 { | ||||||
|  | 		return errors.New("empty team name") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if len(t.Description) > 255 { | ||||||
|  | 		t.Description = t.Description[:255] | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	sess := x.NewSession() | ||||||
|  | 	defer sessionRelease(sess) | ||||||
|  | 	if err = sess.Begin(); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	t.LowerName = strings.ToLower(t.Name) | ||||||
|  | 	has, err := x.Where("org_id=?", t.OrgID).And("lower_name=?", t.LowerName).And("id!=?", t.ID).Get(new(Team)) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} else if has { | ||||||
|  | 		return ErrTeamAlreadyExist{t.OrgID, t.LowerName} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if _, err = sess.Id(t.ID).AllCols().Update(t); err != nil { | ||||||
|  | 		return fmt.Errorf("update: %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Update access for team members if needed.
 | ||||||
|  | 	if authChanged { | ||||||
|  | 		if err = t.getRepositories(sess); err != nil { | ||||||
|  | 			return fmt.Errorf("getRepositories:%v", err) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		for _, repo := range t.Repos { | ||||||
|  | 			if err = repo.recalculateTeamAccesses(sess, 0); err != nil { | ||||||
|  | 				return fmt.Errorf("recalculateTeamAccesses: %v", err) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return sess.Commit() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // DeleteTeam deletes given team.
 | ||||||
|  | // It's caller's responsibility to assign organization ID.
 | ||||||
|  | func DeleteTeam(t *Team) error { | ||||||
|  | 	if err := t.GetRepositories(); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Get organization.
 | ||||||
|  | 	org, err := GetUserByID(t.OrgID) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	sess := x.NewSession() | ||||||
|  | 	defer sessionRelease(sess) | ||||||
|  | 	if err = sess.Begin(); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Delete all accesses.
 | ||||||
|  | 	for _, repo := range t.Repos { | ||||||
|  | 		if err = repo.recalculateTeamAccesses(sess, t.ID); err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Delete team-user.
 | ||||||
|  | 	if _, err = sess.Where("org_id=?", org.Id).Where("team_id=?", t.ID).Delete(new(TeamUser)); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Delete team.
 | ||||||
|  | 	if _, err = sess.Id(t.ID).Delete(new(Team)); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	// Update organization number of teams.
 | ||||||
|  | 	if _, err = sess.Exec("UPDATE `user` SET num_teams=num_teams-1 WHERE id=?", t.OrgID); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return sess.Commit() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ___________                    ____ ___
 | ||||||
|  | // \__    ___/___ _____    _____ |    |   \______ ___________
 | ||||||
|  | //   |    |_/ __ \\__  \  /     \|    |   /  ___// __ \_  __ \
 | ||||||
|  | //   |    |\  ___/ / __ \|  Y Y  \    |  /\___ \\  ___/|  | \/
 | ||||||
|  | //   |____| \___  >____  /__|_|  /______//____  >\___  >__|
 | ||||||
|  | //              \/     \/      \/             \/     \/
 | ||||||
|  | 
 | ||||||
|  | // TeamUser represents an team-user relation.
 | ||||||
|  | type TeamUser struct { | ||||||
|  | 	ID     int64 `xorm:"pk autoincr"` | ||||||
|  | 	OrgID  int64 `xorm:"INDEX"` | ||||||
|  | 	TeamID int64 `xorm:"UNIQUE(s)"` | ||||||
|  | 	Uid    int64 `xorm:"UNIQUE(s)"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func isTeamMember(e Engine, orgID, teamID, uid int64) bool { | ||||||
|  | 	has, _ := e.Where("org_id=?", orgID).And("team_id=?", teamID).And("uid=?", uid).Get(new(TeamUser)) | ||||||
|  | 	return has | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // IsTeamMember returns true if given user is a member of team.
 | ||||||
|  | func IsTeamMember(orgID, teamID, uid int64) bool { | ||||||
|  | 	return isTeamMember(x, orgID, teamID, uid) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func getTeamMembers(e Engine, teamID int64) (_ []*User, err error) { | ||||||
|  | 	teamUsers := make([]*TeamUser, 0, 10) | ||||||
|  | 	if err = e.Where("team_id=?", teamID).Find(&teamUsers); err != nil { | ||||||
|  | 		return nil, fmt.Errorf("get team-users: %v", err) | ||||||
|  | 	} | ||||||
|  | 	members := make([]*User, 0, len(teamUsers)) | ||||||
|  | 	for i := range teamUsers { | ||||||
|  | 		member := new(User) | ||||||
|  | 		if _, err = e.Id(teamUsers[i].Uid).Get(member); err != nil { | ||||||
|  | 			return nil, fmt.Errorf("get user '%d': %v", teamUsers[i].Uid, err) | ||||||
|  | 		} | ||||||
|  | 		members = append(members, member) | ||||||
|  | 	} | ||||||
|  | 	return members, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // GetTeamMembers returns all members in given team of organization.
 | ||||||
|  | func GetTeamMembers(teamID int64) ([]*User, error) { | ||||||
|  | 	return getTeamMembers(x, teamID) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func getUserTeams(e Engine, orgId, uid int64) ([]*Team, error) { | ||||||
|  | 	tus := make([]*TeamUser, 0, 5) | ||||||
|  | 	if err := e.Where("uid=?", uid).And("org_id=?", orgId).Find(&tus); err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ts := make([]*Team, len(tus)) | ||||||
|  | 	for i, tu := range tus { | ||||||
|  | 		t := new(Team) | ||||||
|  | 		has, err := e.Id(tu.TeamID).Get(t) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return nil, err | ||||||
|  | 		} else if !has { | ||||||
|  | 			return nil, ErrTeamNotExist | ||||||
|  | 		} | ||||||
|  | 		ts[i] = t | ||||||
|  | 	} | ||||||
|  | 	return ts, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // GetUserTeams returns all teams that user belongs to in given organization.
 | ||||||
|  | func GetUserTeams(orgId, uid int64) ([]*Team, error) { | ||||||
|  | 	return getUserTeams(x, orgId, uid) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // AddTeamMember adds new membership of given team to given organization,
 | ||||||
|  | // the user will have membership to given organization automatically when needed.
 | ||||||
|  | func AddTeamMember(orgID, teamID, uid int64) error { | ||||||
|  | 	if IsTeamMember(orgID, teamID, uid) { | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if err := AddOrgUser(orgID, uid); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Get team and its repositories.
 | ||||||
|  | 	t, err := GetTeamByID(teamID) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	t.NumMembers++ | ||||||
|  | 
 | ||||||
|  | 	if err = t.GetRepositories(); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	sess := x.NewSession() | ||||||
|  | 	defer sessionRelease(sess) | ||||||
|  | 	if err = sess.Begin(); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	tu := &TeamUser{ | ||||||
|  | 		Uid:    uid, | ||||||
|  | 		OrgID:  orgID, | ||||||
|  | 		TeamID: teamID, | ||||||
|  | 	} | ||||||
|  | 	if _, err = sess.Insert(tu); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} else if _, err = sess.Id(t.ID).Update(t); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Give access to team repositories.
 | ||||||
|  | 	for _, repo := range t.Repos { | ||||||
|  | 		if err = repo.recalculateTeamAccesses(sess, 0); err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// We make sure it exists before.
 | ||||||
|  | 	ou := new(OrgUser) | ||||||
|  | 	if _, err = sess.Where("uid = ?", uid).And("org_id = ?", orgID).Get(ou); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	ou.NumTeams++ | ||||||
|  | 	if t.IsOwnerTeam() { | ||||||
|  | 		ou.IsOwner = true | ||||||
|  | 	} | ||||||
|  | 	if _, err = sess.Id(ou.ID).AllCols().Update(ou); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return sess.Commit() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func removeTeamMember(e Engine, orgID, teamID, uid int64) error { | ||||||
|  | 	if !isTeamMember(e, orgID, teamID, uid) { | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Get team and its repositories.
 | ||||||
|  | 	t, err := getTeamByID(e, teamID) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Check if the user to delete is the last member in owner team.
 | ||||||
|  | 	if t.IsOwnerTeam() && t.NumMembers == 1 { | ||||||
|  | 		return ErrLastOrgOwner{UID: uid} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	t.NumMembers-- | ||||||
|  | 
 | ||||||
|  | 	if err = t.getRepositories(e); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Get organization.
 | ||||||
|  | 	org, err := getUserByID(e, orgID) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	tu := &TeamUser{ | ||||||
|  | 		Uid:    uid, | ||||||
|  | 		OrgID:  orgID, | ||||||
|  | 		TeamID: teamID, | ||||||
|  | 	} | ||||||
|  | 	if _, err := e.Delete(tu); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} else if _, err = e.Id(t.ID).AllCols().Update(t); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Delete access to team repositories.
 | ||||||
|  | 	for _, repo := range t.Repos { | ||||||
|  | 		if err = repo.recalculateTeamAccesses(e, 0); err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// This must exist.
 | ||||||
|  | 	ou := new(OrgUser) | ||||||
|  | 	_, err = e.Where("uid = ?", uid).And("org_id = ?", org.Id).Get(ou) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	ou.NumTeams-- | ||||||
|  | 	if t.IsOwnerTeam() { | ||||||
|  | 		ou.IsOwner = false | ||||||
|  | 	} | ||||||
|  | 	if _, err = e.Id(ou.ID).AllCols().Update(ou); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // RemoveTeamMember removes member from given team of given organization.
 | ||||||
|  | func RemoveTeamMember(orgID, teamID, uid int64) error { | ||||||
|  | 	sess := x.NewSession() | ||||||
|  | 	defer sessionRelease(sess) | ||||||
|  | 	if err := sess.Begin(); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	if err := removeTeamMember(sess, orgID, teamID, uid); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	return sess.Commit() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ___________                  __________
 | ||||||
|  | // \__    ___/___ _____    _____\______   \ ____ ______   ____
 | ||||||
|  | //   |    |_/ __ \\__  \  /     \|       _// __ \\____ \ /  _ \
 | ||||||
|  | //   |    |\  ___/ / __ \|  Y Y  \    |   \  ___/|  |_> >  <_> )
 | ||||||
|  | //   |____| \___  >____  /__|_|  /____|_  /\___  >   __/ \____/
 | ||||||
|  | //              \/     \/      \/       \/     \/|__|
 | ||||||
|  | 
 | ||||||
|  | // TeamRepo represents an team-repository relation.
 | ||||||
|  | type TeamRepo struct { | ||||||
|  | 	ID     int64 `xorm:"pk autoincr"` | ||||||
|  | 	OrgID  int64 `xorm:"INDEX"` | ||||||
|  | 	TeamID int64 `xorm:"UNIQUE(s)"` | ||||||
|  | 	RepoID int64 `xorm:"UNIQUE(s)"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func hasTeamRepo(e Engine, orgID, teamID, repoID int64) bool { | ||||||
|  | 	has, _ := e.Where("org_id=?", orgID).And("team_id=?", teamID).And("repo_id=?", repoID).Get(new(TeamRepo)) | ||||||
|  | 	return has | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // HasTeamRepo returns true if given repository belongs to team.
 | ||||||
|  | func HasTeamRepo(orgID, teamID, repoID int64) bool { | ||||||
|  | 	return hasTeamRepo(x, orgID, teamID, repoID) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func addTeamRepo(e Engine, orgID, teamID, repoID int64) error { | ||||||
|  | 	_, err := e.InsertOne(&TeamRepo{ | ||||||
|  | 		OrgID:  orgID, | ||||||
|  | 		TeamID: teamID, | ||||||
|  | 		RepoID: repoID, | ||||||
|  | 	}) | ||||||
|  | 	return err | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // AddTeamRepo adds new repository relation to team.
 | ||||||
|  | func AddTeamRepo(orgID, teamID, repoID int64) error { | ||||||
|  | 	return addTeamRepo(x, orgID, teamID, repoID) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func removeTeamRepo(e Engine, teamID, repoID int64) error { | ||||||
|  | 	_, err := e.Delete(&TeamRepo{ | ||||||
|  | 		TeamID: teamID, | ||||||
|  | 		RepoID: repoID, | ||||||
|  | 	}) | ||||||
|  | 	return err | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // RemoveTeamRepo deletes repository relation to team.
 | ||||||
|  | func RemoveTeamRepo(teamID, repoID int64) error { | ||||||
|  | 	return removeTeamRepo(x, teamID, repoID) | ||||||
|  | } | ||||||
| @ -18,6 +18,7 @@ import ( | |||||||
| 
 | 
 | ||||||
| type APIContext struct { | type APIContext struct { | ||||||
| 	*Context | 	*Context | ||||||
|  | 	Org *APIOrganization | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Error responses error message to client with given message.
 | // Error responses error message to client with given message.
 | ||||||
| @ -40,6 +41,7 @@ func (ctx *APIContext) Error(status int, title string, obj interface{}) { | |||||||
| 	}) | 	}) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // SetLinkHeader sets pagination link header by given totol number and page size.
 | ||||||
| func (ctx *APIContext) SetLinkHeader(total, pageSize int) { | func (ctx *APIContext) SetLinkHeader(total, pageSize int) { | ||||||
| 	page := paginater.New(total, pageSize, ctx.QueryInt("page"), 0) | 	page := paginater.New(total, pageSize, ctx.QueryInt("page"), 0) | ||||||
| 	links := make([]string, 0, 4) | 	links := make([]string, 0, 4) | ||||||
|  | |||||||
							
								
								
									
										14
									
								
								modules/context/api_org.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								modules/context/api_org.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | |||||||
|  | // Copyright 2016 The Gogs 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 context | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"github.com/gogits/gogs/models" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type APIOrganization struct { | ||||||
|  | 	Organization *models.User | ||||||
|  | 	Team         *models.Team | ||||||
|  | } | ||||||
| @ -14,13 +14,8 @@ import ( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func CreateTeam(ctx *context.APIContext, form api.CreateTeamOption) { | func CreateTeam(ctx *context.APIContext, form api.CreateTeamOption) { | ||||||
| 	org := user.GetUserByParamsName(ctx, ":orgname") |  | ||||||
| 	if ctx.Written() { |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	team := &models.Team{ | 	team := &models.Team{ | ||||||
| 		OrgID:       org.Id, | 		OrgID:       ctx.Org.Organization.Id, | ||||||
| 		Name:        form.Name, | 		Name:        form.Name, | ||||||
| 		Description: form.Description, | 		Description: form.Description, | ||||||
| 		Authorize:   models.ParseAccessMode(form.Permission), | 		Authorize:   models.ParseAccessMode(form.Permission), | ||||||
| @ -36,3 +31,30 @@ func CreateTeam(ctx *context.APIContext, form api.CreateTeamOption) { | |||||||
| 
 | 
 | ||||||
| 	ctx.JSON(201, convert.ToTeam(team)) | 	ctx.JSON(201, convert.ToTeam(team)) | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func AddTeamMember(ctx *context.APIContext) { | ||||||
|  | 	u := user.GetUserByParams(ctx) | ||||||
|  | 	if ctx.Written() { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	if err := ctx.Org.Team.AddMember(u.Id); err != nil { | ||||||
|  | 		ctx.Error(500, "AddMember", err) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ctx.Status(204) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func RemoveTeamMember(ctx *context.APIContext) { | ||||||
|  | 	u := user.GetUserByParams(ctx) | ||||||
|  | 	if ctx.Written() { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if err := ctx.Org.Team.RemoveMember(u.Id); err != nil { | ||||||
|  | 		ctx.Error(500, "RemoveMember", err) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ctx.Status(204) | ||||||
|  | } | ||||||
|  | |||||||
| @ -110,6 +110,42 @@ func ReqAdmin() macaron.Handler { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func OrgAssignment(args ...bool) macaron.Handler { | ||||||
|  | 	var ( | ||||||
|  | 		assignTeam bool | ||||||
|  | 	) | ||||||
|  | 
 | ||||||
|  | 	if len(args) > 0 { | ||||||
|  | 		assignTeam = args[0] | ||||||
|  | 	} | ||||||
|  | 	return func(ctx *context.APIContext) { | ||||||
|  | 		org, err := models.GetUserByName(ctx.Params(":orgname")) | ||||||
|  | 		if err != nil { | ||||||
|  | 			if models.IsErrUserNotExist(err) { | ||||||
|  | 				ctx.Status(404) | ||||||
|  | 			} else { | ||||||
|  | 				ctx.Error(500, "GetUserByName", err) | ||||||
|  | 			} | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 		ctx.Org = &context.APIOrganization{ | ||||||
|  | 			Organization: org, | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if assignTeam { | ||||||
|  | 			ctx.Org.Team, err = models.GetTeamByID(ctx.ParamsInt64(":teamid")) | ||||||
|  | 			if err != nil { | ||||||
|  | 				if models.IsErrUserNotExist(err) { | ||||||
|  | 					ctx.Status(404) | ||||||
|  | 				} else { | ||||||
|  | 					ctx.Error(500, "GetTeamById", err) | ||||||
|  | 				} | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // RegisterRoutes registers all v1 APIs routes to web application.
 | // RegisterRoutes registers all v1 APIs routes to web application.
 | ||||||
| // FIXME: custom form error response
 | // FIXME: custom form error response
 | ||||||
| func RegisterRoutes(m *macaron.Macaron) { | func RegisterRoutes(m *macaron.Macaron) { | ||||||
| @ -208,7 +244,7 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||||
| 		m.Group("/orgs/:orgname", func() { | 		m.Group("/orgs/:orgname", func() { | ||||||
| 			m.Combo("").Get(org.Get).Patch(bind(api.EditOrgOption{}), org.Edit) | 			m.Combo("").Get(org.Get).Patch(bind(api.EditOrgOption{}), org.Edit) | ||||||
| 			m.Combo("/teams").Get(org.ListTeams) | 			m.Combo("/teams").Get(org.ListTeams) | ||||||
| 		}) | 		}, OrgAssignment()) | ||||||
| 
 | 
 | ||||||
| 		m.Any("/*", func(ctx *context.Context) { | 		m.Any("/*", func(ctx *context.Context) { | ||||||
| 			ctx.Error(404) | 			ctx.Error(404) | ||||||
| @ -228,7 +264,13 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||||
| 			}) | 			}) | ||||||
| 
 | 
 | ||||||
| 			m.Group("/orgs/:orgname", func() { | 			m.Group("/orgs/:orgname", func() { | ||||||
| 				m.Combo("/teams").Post(bind(api.CreateTeamOption{}), admin.CreateTeam) | 				m.Group("/teams", func() { | ||||||
|  | 					m.Post("", OrgAssignment(), bind(api.CreateTeamOption{}), admin.CreateTeam) | ||||||
|  | 
 | ||||||
|  | 					m.Group("/:teamid", func() { | ||||||
|  | 						m.Combo("/memberships/:username").Put(admin.AddTeamMember).Delete(admin.RemoveTeamMember) | ||||||
|  | 					}, OrgAssignment(true)) | ||||||
|  | 				}) | ||||||
| 			}) | 			}) | ||||||
| 		}, ReqAdmin()) | 		}, ReqAdmin()) | ||||||
| 	}, context.APIContexter()) | 	}, context.APIContexter()) | ||||||
|  | |||||||
| @ -42,20 +42,12 @@ func ListUserOrgs(ctx *context.APIContext) { | |||||||
| 
 | 
 | ||||||
| // https://github.com/gogits/go-gogs-client/wiki/Organizations#get-an-organization
 | // https://github.com/gogits/go-gogs-client/wiki/Organizations#get-an-organization
 | ||||||
| func Get(ctx *context.APIContext) { | func Get(ctx *context.APIContext) { | ||||||
| 	org := user.GetUserByParamsName(ctx, ":orgname") | 	ctx.JSON(200, convert.ToOrganization(ctx.Org.Organization)) | ||||||
| 	if ctx.Written() { |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	ctx.JSON(200, convert.ToOrganization(org)) |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // https://github.com/gogits/go-gogs-client/wiki/Organizations#edit-an-organization
 | // https://github.com/gogits/go-gogs-client/wiki/Organizations#edit-an-organization
 | ||||||
| func Edit(ctx *context.APIContext, form api.EditOrgOption) { | func Edit(ctx *context.APIContext, form api.EditOrgOption) { | ||||||
| 	org := user.GetUserByParamsName(ctx, ":orgname") | 	org := ctx.Org.Organization | ||||||
| 	if ctx.Written() { |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if !org.IsOwnedBy(ctx.User.Id) { | 	if !org.IsOwnedBy(ctx.User.Id) { | ||||||
| 		ctx.Status(403) | 		ctx.Status(403) | ||||||
| 		return | 		return | ||||||
|  | |||||||
| @ -9,15 +9,10 @@ import ( | |||||||
| 
 | 
 | ||||||
| 	"github.com/gogits/gogs/modules/context" | 	"github.com/gogits/gogs/modules/context" | ||||||
| 	"github.com/gogits/gogs/routers/api/v1/convert" | 	"github.com/gogits/gogs/routers/api/v1/convert" | ||||||
| 	"github.com/gogits/gogs/routers/api/v1/user" |  | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func ListTeams(ctx *context.APIContext) { | func ListTeams(ctx *context.APIContext) { | ||||||
| 	org := user.GetUserByParamsName(ctx, ":orgname") | 	org := ctx.Org.Organization | ||||||
| 	if ctx.Written() { |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if err := org.GetTeams(); err != nil { | 	if err := org.GetTeams(); err != nil { | ||||||
| 		ctx.Error(500, "GetTeams", err) | 		ctx.Error(500, "GetTeams", err) | ||||||
| 		return | 		return | ||||||
|  | |||||||
| @ -1 +1 @@ | |||||||
| 0.9.15.0323 | 0.9.16.0325 | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user