"github.com/gogits/gogs/modules/setting" | "github.com/gogits/gogs/modules/setting" | ||||
) | ) | ||||
const APP_VER = "0.5.14.0222 Beta" | |||||
const APP_VER = "0.5.15.0223 Beta" | |||||
func init() { | func init() { | ||||
runtime.GOMAXPROCS(runtime.NumCPU()) | runtime.GOMAXPROCS(runtime.NumCPU()) |
Mode AccessMode | Mode AccessMode | ||||
} | } | ||||
// Return the Access a user has to a repository. Will return NoneAccess if the | |||||
// user does not have access. User can be nil! | |||||
func AccessLevel(u *User, r *Repository) (AccessMode, error) { | |||||
func accessLevel(e Engine, u *User, repo *Repository) (AccessMode, error) { | |||||
mode := ACCESS_MODE_NONE | mode := ACCESS_MODE_NONE | ||||
if !r.IsPrivate { | |||||
if !repo.IsPrivate { | |||||
mode = ACCESS_MODE_READ | mode = ACCESS_MODE_READ | ||||
} | } | ||||
if u != nil { | if u != nil { | ||||
if u.Id == r.OwnerId { | |||||
if u.Id == repo.OwnerId { | |||||
return ACCESS_MODE_OWNER, nil | return ACCESS_MODE_OWNER, nil | ||||
} | } | ||||
a := &Access{UserID: u.Id, RepoID: r.Id} | |||||
if has, err := x.Get(a); !has || err != nil { | |||||
a := &Access{UserID: u.Id, RepoID: repo.Id} | |||||
if has, err := e.Get(a); !has || err != nil { | |||||
return mode, err | return mode, err | ||||
} | } | ||||
return a.Mode, nil | return a.Mode, nil | ||||
return mode, nil | return mode, nil | ||||
} | } | ||||
// HasAccess returns true if someone has the request access level. User can be nil! | |||||
func HasAccess(u *User, r *Repository, testMode AccessMode) (bool, error) { | |||||
mode, err := AccessLevel(u, r) | |||||
// AccessLevel returns the Access a user has to a repository. Will return NoneAccess if the | |||||
// user does not have access. User can be nil! | |||||
func AccessLevel(u *User, repo *Repository) (AccessMode, error) { | |||||
return accessLevel(x, u, repo) | |||||
} | |||||
func hasAccess(e Engine, u *User, repo *Repository, testMode AccessMode) (bool, error) { | |||||
mode, err := accessLevel(e, u, repo) | |||||
return testMode <= mode, err | return testMode <= mode, err | ||||
} | } | ||||
// HasAccess returns true if someone has the request access level. User can be nil! | |||||
func HasAccess(u *User, repo *Repository, testMode AccessMode) (bool, error) { | |||||
return hasAccess(x, u, repo, testMode) | |||||
} | |||||
// GetAccessibleRepositories finds all repositories where a user has access to, | // GetAccessibleRepositories finds all repositories where a user has access to, | ||||
// besides his own. | // besides his own. | ||||
func (u *User) GetAccessibleRepositories() (map[*Repository]AccessMode, error) { | func (u *User) GetAccessibleRepositories() (map[*Repository]AccessMode, error) { | ||||
func (repo *Repository) recalculateAccesses(e Engine) error { | func (repo *Repository) recalculateAccesses(e Engine) error { | ||||
accessMap := make(map[int64]AccessMode, 20) | accessMap := make(map[int64]AccessMode, 20) | ||||
// Give all collaborators write access | |||||
// FIXME: should be able to have read-only access. | |||||
// Give all collaborators write access. | |||||
collaborators, err := repo.getCollaborators(e) | collaborators, err := repo.getCollaborators(e) | ||||
if err != nil { | if err != nil { | ||||
return err | return err | ||||
} | } | ||||
for _, team := range repo.Owner.Teams { | for _, team := range repo.Owner.Teams { | ||||
if !(team.IsOwnerTeam() || team.HasRepository(repo)) { | |||||
continue | |||||
} else if team.IsOwnerTeam() { | |||||
if team.IsOwnerTeam() { | |||||
team.Authorize = ACCESS_MODE_OWNER | team.Authorize = ACCESS_MODE_OWNER | ||||
} | } | ||||
} | } | ||||
} | } | ||||
// FIXME: do corss-comparison so reduce deletions and additions to the minimum? | |||||
minMode := ACCESS_MODE_READ | minMode := ACCESS_MODE_READ | ||||
if !repo.IsPrivate { | if !repo.IsPrivate { | ||||
minMode = ACCESS_MODE_WRITE | minMode = ACCESS_MODE_WRITE |
return newRepoAction(x, u, repo) | return newRepoAction(x, u, repo) | ||||
} | } | ||||
func transferRepoAction(e Engine, u, newUser *User, repo *Repository) (err error) { | |||||
func transferRepoAction(e Engine, actUser, oldOwner, newOwner *User, repo *Repository) (err error) { | |||||
action := &Action{ | action := &Action{ | ||||
ActUserId: u.Id, | |||||
ActUserName: u.Name, | |||||
ActEmail: u.Email, | |||||
ActUserId: actUser.Id, | |||||
ActUserName: actUser.Name, | |||||
ActEmail: actUser.Email, | |||||
OpType: TRANSFER_REPO, | OpType: TRANSFER_REPO, | ||||
RepoId: repo.Id, | RepoId: repo.Id, | ||||
RepoUserName: newUser.Name, | |||||
RepoUserName: newOwner.Name, | |||||
RepoName: repo.Name, | RepoName: repo.Name, | ||||
IsPrivate: repo.IsPrivate, | IsPrivate: repo.IsPrivate, | ||||
Content: path.Join(repo.Owner.LowerName, repo.LowerName), | |||||
Content: path.Join(oldOwner.LowerName, repo.LowerName), | |||||
} | } | ||||
if err = notifyWatchers(e, action); err != nil { | if err = notifyWatchers(e, action); err != nil { | ||||
return fmt.Errorf("notify watchers '%d/%s'", u.Id, repo.Id) | |||||
return fmt.Errorf("notify watchers '%d/%s'", actUser.Id, repo.Id) | |||||
} | } | ||||
// Remove watch for organization. | // Remove watch for organization. | ||||
} | } | ||||
} | } | ||||
log.Trace("action.TransferRepoAction: %s/%s", u.Name, repo.Name) | |||||
log.Trace("action.TransferRepoAction: %s/%s", actUser.Name, repo.Name) | |||||
return nil | return nil | ||||
} | } | ||||
// TransferRepoAction adds new action for transferring repository. | // TransferRepoAction adds new action for transferring repository. | ||||
func TransferRepoAction(u, newUser *User, repo *Repository) (err error) { | |||||
return transferRepoAction(x, u, newUser, repo) | |||||
func TransferRepoAction(actUser, oldOwner, newOwner *User, repo *Repository) (err error) { | |||||
return transferRepoAction(x, actUser, oldOwner, newOwner, repo) | |||||
} | } | ||||
// GetFeeds returns action list of given user in given context. | // GetFeeds returns action list of given user in given context. |
NewMigration("generate collaboration from access", accessToCollaboration), // V0 -> V1 | NewMigration("generate collaboration from access", accessToCollaboration), // V0 -> V1 | ||||
NewMigration("make authorize 4 if team is owners", ownerTeamUpdate), // V1 -> V2 | NewMigration("make authorize 4 if team is owners", ownerTeamUpdate), // V1 -> V2 | ||||
NewMigration("refactor access table to use id's", accessRefactor), // V2 -> V3 | NewMigration("refactor access table to use id's", accessRefactor), // V2 -> V3 | ||||
NewMigration("generate team-repo from team", teamToTeamRepo), // V3 -> V4 | |||||
} | } | ||||
// Migrate database to current version | // Migrate database to current version | ||||
} | } | ||||
func ownerTeamUpdate(x *xorm.Engine) (err error) { | func ownerTeamUpdate(x *xorm.Engine) (err error) { | ||||
if _, err := x.Exec("UPDATE team SET authorize=4 WHERE lower_name=?", "owners"); err != nil { | |||||
return fmt.Errorf("drop table: %v", err) | |||||
if _, err := x.Exec("UPDATE `team` SET authorize=4 WHERE lower_name=?", "owners"); err != nil { | |||||
return fmt.Errorf("update owner team table: %v", err) | |||||
} | } | ||||
return nil | return nil | ||||
} | } | ||||
accessMap := make(map[UserRepo]AccessMode, 50) | accessMap := make(map[UserRepo]AccessMode, 50) | ||||
results, err := x.Query("SELECT r.id as `repo_id`, r.is_private as `is_private`, r.owner_id as `owner_id`, u.type as `owner_type` FROM `repository` r LEFT JOIN user u ON r.owner_id=u.id") | |||||
results, err := x.Query("SELECT r.id AS `repo_id`, r.is_private AS `is_private`, r.owner_id AS `owner_id`, u.type AS `owner_type` FROM `repository` r LEFT JOIN `user` u ON r.owner_id=u.id") | |||||
if err != nil { | if err != nil { | ||||
return err | |||||
return fmt.Errorf("select repositories: %v", err) | |||||
} | } | ||||
for _, repo := range results { | for _, repo := range results { | ||||
repoID := com.StrTo(repo["repo_id"]).MustInt64() | repoID := com.StrTo(repo["repo_id"]).MustInt64() | ||||
ownerID := com.StrTo(repo["owner_id"]).MustInt64() | ownerID := com.StrTo(repo["owner_id"]).MustInt64() | ||||
ownerIsOrganization := com.StrTo(repo["owner_type"]).MustInt() > 0 | ownerIsOrganization := com.StrTo(repo["owner_type"]).MustInt() > 0 | ||||
results, err := x.Query("SELECT user_id FROM collaboration WHERE repo_id=?", repoID) | |||||
results, err := x.Query("SELECT `user_id` FROM `collaboration` WHERE repo_id=?", repoID) | |||||
if err != nil { | if err != nil { | ||||
return fmt.Errorf("select repos: %v", err) | |||||
return fmt.Errorf("select collaborators: %v", err) | |||||
} | } | ||||
for _, user := range results { | for _, user := range results { | ||||
userID := com.StrTo(user["user_id"]).MustInt64() | userID := com.StrTo(user["user_id"]).MustInt64() | ||||
continue | continue | ||||
} | } | ||||
// The minimum level to add a new access record, | |||||
// because public repository has implicit open access. | |||||
minAccessLevel := AccessMode(0) | minAccessLevel := AccessMode(0) | ||||
if !isPrivate { | if !isPrivate { | ||||
minAccessLevel = 1 | minAccessLevel = 1 | ||||
repoString := "$" + string(repo["repo_id"]) + "|" | repoString := "$" + string(repo["repo_id"]) + "|" | ||||
results, err = x.Query("SELECT id, authorize, repo_ids FROM team WHERE org_id=? AND authorize > ? ORDER BY authorize ASC", ownerID, int(minAccessLevel)) | |||||
results, err = x.Query("SELECT `id`,`authorize`,`repo_ids` FROM `team` WHERE org_id=? AND authorize>? ORDER BY `authorize` ASC", ownerID, int(minAccessLevel)) | |||||
if err != nil { | if err != nil { | ||||
return fmt.Errorf("select teams from org: %v", err) | return fmt.Errorf("select teams from org: %v", err) | ||||
} | } | ||||
teamID := com.StrTo(team["id"]).MustInt64() | teamID := com.StrTo(team["id"]).MustInt64() | ||||
mode := AccessMode(com.StrTo(team["authorize"]).MustInt()) | mode := AccessMode(com.StrTo(team["authorize"]).MustInt()) | ||||
results, err := x.Query("SELECT uid FROM team_user WHERE team_id=?", teamID) | |||||
results, err := x.Query("SELECT `uid` FROM `team_user` WHERE team_id=?", teamID) | |||||
if err != nil { | if err != nil { | ||||
return fmt.Errorf("select users from team: %v", err) | return fmt.Errorf("select users from team: %v", err) | ||||
} | } | ||||
for _, user := range results { | for _, user := range results { | ||||
userID := com.StrTo(user["uid"]).MustInt64() | |||||
userID := com.StrTo(user["user_id"]).MustInt64() | |||||
accessMap[UserRepo{userID, repoID}] = mode | accessMap[UserRepo{userID, repoID}] = mode | ||||
} | } | ||||
} | } | ||||
} | } | ||||
// Drop table can't be in a session (at least not in sqlite) | // Drop table can't be in a session (at least not in sqlite) | ||||
if _, err = x.Exec("DROP TABLE access"); err != nil { | |||||
return fmt.Errorf("drop table: %v", err) | |||||
if _, err = x.Exec("DROP TABLE `access`"); err != nil { | |||||
return fmt.Errorf("drop access table: %v", err) | |||||
} | } | ||||
// Now we start writing so we make a session | // Now we start writing so we make a session | ||||
accesses = append(accesses, &Access{UserID: ur.UserID, RepoID: ur.RepoID, Mode: mode}) | accesses = append(accesses, &Access{UserID: ur.UserID, RepoID: ur.RepoID, Mode: mode}) | ||||
} | } | ||||
_, err = sess.Insert(accesses) | |||||
if _, err = sess.Insert(accesses); err != nil { | |||||
return fmt.Errorf("insert accesses: %v", err) | |||||
} | |||||
return sess.Commit() | |||||
} | |||||
func teamToTeamRepo(x *xorm.Engine) error { | |||||
type TeamRepo struct { | |||||
ID int64 `xorm:"pk autoincr"` | |||||
OrgID int64 `xorm:"INDEX"` | |||||
TeamID int64 `xorm:"UNIQUE(s)"` | |||||
RepoID int64 `xorm:"UNIQUE(s)"` | |||||
} | |||||
teamRepos := make([]*TeamRepo, 0, 50) | |||||
results, err := x.Query("SELECT `id`,`org_id`,`repo_ids` FROM `team`") | |||||
if err != nil { | |||||
return fmt.Errorf("select teams: %v", err) | |||||
} | |||||
for _, team := range results { | |||||
orgID := com.StrTo(team["org_id"]).MustInt64() | |||||
teamID := com.StrTo(team["id"]).MustInt64() | |||||
for _, idStr := range strings.Split(string(team["repo_ids"]), "|") { | |||||
repoID := com.StrTo(strings.TrimPrefix(idStr, "$")).MustInt64() | |||||
if repoID == 0 { | |||||
continue | |||||
} | |||||
teamRepos = append(teamRepos, &TeamRepo{ | |||||
OrgID: orgID, | |||||
TeamID: teamID, | |||||
RepoID: repoID, | |||||
}) | |||||
} | |||||
} | |||||
sess := x.NewSession() | |||||
defer sessionRelease(sess) | |||||
if err = sess.Begin(); err != nil { | |||||
return err | |||||
} | |||||
if err = sess.Sync2(new(TeamRepo)); err != nil { | |||||
return fmt.Errorf("sync: %v", err) | |||||
} else if _, err = sess.Insert(teamRepos); err != nil { | |||||
return fmt.Errorf("insert team-repos: %v", err) | |||||
} | |||||
return sess.Commit() | return sess.Commit() | ||||
} | } |
"github.com/go-xorm/xorm" | "github.com/go-xorm/xorm" | ||||
_ "github.com/lib/pq" | _ "github.com/lib/pq" | ||||
// "github.com/gogits/gogs/models/migrations" | |||||
"github.com/gogits/gogs/models/migrations" | |||||
"github.com/gogits/gogs/modules/setting" | "github.com/gogits/gogs/modules/setting" | ||||
) | ) | ||||
new(Watch), new(Star), new(Follow), new(Action), | new(Watch), new(Star), new(Follow), new(Action), | ||||
new(Issue), new(Comment), new(Attachment), new(IssueUser), new(Label), new(Milestone), | new(Issue), new(Comment), new(Attachment), new(IssueUser), new(Label), new(Milestone), | ||||
new(Mirror), new(Release), new(LoginSource), new(Webhook), | new(Mirror), new(Release), new(LoginSource), new(Webhook), | ||||
new(UpdateTask), new(HookTask), new(Team), new(OrgUser), new(TeamUser), | |||||
new(UpdateTask), new(HookTask), | |||||
new(Team), new(OrgUser), new(TeamUser), new(TeamRepo), | |||||
new(Notice), new(EmailAddress)) | new(Notice), new(EmailAddress)) | ||||
} | } | ||||
import ( | import ( | ||||
"errors" | "errors" | ||||
"fmt" | |||||
"os" | "os" | ||||
"strings" | "strings" | ||||
"github.com/Unknwon/com" | |||||
"github.com/gogits/gogs/modules/base" | "github.com/gogits/gogs/modules/base" | ||||
) | ) | ||||
org.NumMembers = 1 | org.NumMembers = 1 | ||||
sess := x.NewSession() | sess := x.NewSession() | ||||
defer sess.Close() | |||||
defer sessionRelease(sess) | |||||
if err = sess.Begin(); err != nil { | if err = sess.Begin(); err != nil { | ||||
return nil, err | return nil, err | ||||
} | } | ||||
if _, err = sess.Insert(org); err != nil { | if _, err = sess.Insert(org); err != nil { | ||||
sess.Rollback() | |||||
return nil, err | |||||
} | |||||
if err = os.MkdirAll(UserPath(org.Name), os.ModePerm); err != nil { | |||||
sess.Rollback() | |||||
return nil, err | return nil, err | ||||
} | } | ||||
// Create default owner team. | // Create default owner team. | ||||
t := &Team{ | t := &Team{ | ||||
OrgId: org.Id, | |||||
OrgID: org.Id, | |||||
LowerName: strings.ToLower(OWNER_TEAM), | LowerName: strings.ToLower(OWNER_TEAM), | ||||
Name: OWNER_TEAM, | Name: OWNER_TEAM, | ||||
Authorize: ACCESS_MODE_OWNER, | Authorize: ACCESS_MODE_OWNER, | ||||
NumMembers: 1, | NumMembers: 1, | ||||
} | } | ||||
if _, err = sess.Insert(t); err != nil { | if _, err = sess.Insert(t); err != nil { | ||||
sess.Rollback() | |||||
return nil, err | return nil, err | ||||
} | } | ||||
// Add initial creator to organization and owner team. | // Add initial creator to organization and owner team. | ||||
ou := &OrgUser{ | ou := &OrgUser{ | ||||
Uid: owner.Id, | Uid: owner.Id, | ||||
OrgId: org.Id, | |||||
OrgID: org.Id, | |||||
IsOwner: true, | IsOwner: true, | ||||
NumTeams: 1, | NumTeams: 1, | ||||
} | } | ||||
if _, err = sess.Insert(ou); err != nil { | if _, err = sess.Insert(ou); err != nil { | ||||
sess.Rollback() | |||||
return nil, err | return nil, err | ||||
} | } | ||||
tu := &TeamUser{ | tu := &TeamUser{ | ||||
Uid: owner.Id, | Uid: owner.Id, | ||||
OrgId: org.Id, | |||||
TeamId: t.Id, | |||||
OrgID: org.Id, | |||||
TeamID: t.ID, | |||||
} | } | ||||
if _, err = sess.Insert(tu); err != nil { | if _, err = sess.Insert(tu); err != nil { | ||||
sess.Rollback() | |||||
return nil, err | |||||
} | |||||
if err = os.MkdirAll(UserPath(org.Name), os.ModePerm); err != nil { | |||||
return nil, err | return nil, err | ||||
} | } | ||||
return err | return err | ||||
} | } | ||||
if _, err = sess.Delete(&Team{OrgId: org.Id}); err != nil { | |||||
if _, err = sess.Delete(&Team{OrgID: org.Id}); err != nil { | |||||
sess.Rollback() | sess.Rollback() | ||||
return err | return err | ||||
} | } | ||||
if _, err = sess.Delete(&OrgUser{OrgId: org.Id}); err != nil { | |||||
if _, err = sess.Delete(&OrgUser{OrgID: org.Id}); err != nil { | |||||
sess.Rollback() | sess.Rollback() | ||||
return err | return err | ||||
} | } | ||||
if _, err = sess.Delete(&TeamUser{OrgId: org.Id}); err != nil { | |||||
if _, err = sess.Delete(&TeamUser{OrgID: org.Id}); err != nil { | |||||
sess.Rollback() | sess.Rollback() | ||||
return err | return err | ||||
} | } | ||||
// OrgUser represents an organization-user relation. | // OrgUser represents an organization-user relation. | ||||
type OrgUser struct { | type OrgUser struct { | ||||
Id int64 | |||||
ID int64 `xorm:"pk autoincr"` | |||||
Uid int64 `xorm:"INDEX UNIQUE(s)"` | Uid int64 `xorm:"INDEX UNIQUE(s)"` | ||||
OrgId int64 `xorm:"INDEX UNIQUE(s)"` | |||||
OrgID int64 `xorm:"INDEX UNIQUE(s)"` | |||||
IsPublic bool | IsPublic bool | ||||
IsOwner bool | IsOwner bool | ||||
NumTeams int | NumTeams int | ||||
} | } | ||||
ou.IsPublic = public | ou.IsPublic = public | ||||
_, err = x.Id(ou.Id).AllCols().Update(ou) | |||||
_, err = x.Id(ou.ID).AllCols().Update(ou) | |||||
return err | return err | ||||
} | } | ||||
ou := &OrgUser{ | ou := &OrgUser{ | ||||
Uid: uid, | Uid: uid, | ||||
OrgId: orgId, | |||||
OrgID: orgId, | |||||
} | } | ||||
if _, err := sess.Insert(ou); err != nil { | if _, err := sess.Insert(ou); err != nil { | ||||
return err | return err | ||||
} | } | ||||
if _, err := sess.Id(ou.Id).Delete(ou); err != nil { | |||||
if _, err := sess.Id(ou.ID).Delete(ou); err != nil { | |||||
sess.Rollback() | sess.Rollback() | ||||
return err | return err | ||||
} else if _, err = sess.Exec("UPDATE `user` SET num_members = num_members - 1 WHERE id = ?", orgId); err != nil { | } else if _, err = sess.Exec("UPDATE `user` SET num_members = num_members - 1 WHERE id = ?", orgId); err != nil { | ||||
return err | return err | ||||
} | } | ||||
for _, t := range ts { | for _, t := range ts { | ||||
if err = removeTeamMember(sess, org.Id, t.Id, u.Id); err != nil { | |||||
if err = removeTeamMember(sess, org.Id, t.ID, u.Id); err != nil { | |||||
return err | return err | ||||
} | } | ||||
} | } | ||||
// Team represents a organization team. | // Team represents a organization team. | ||||
type Team struct { | type Team struct { | ||||
Id int64 | |||||
OrgId int64 `xorm:"INDEX"` | |||||
ID int64 `xorm:"pk autoincr"` | |||||
OrgID int64 `xorm:"INDEX"` | |||||
LowerName string | LowerName string | ||||
Name string | Name string | ||||
Description string | Description string | ||||
Authorize AccessMode | Authorize AccessMode | ||||
RepoIds string `xorm:"TEXT"` | |||||
Repos []*Repository `xorm:"-"` | Repos []*Repository `xorm:"-"` | ||||
Members []*User `xorm:"-"` | Members []*User `xorm:"-"` | ||||
NumRepos int | NumRepos int | ||||
// IsTeamMember returns true if given user is a member of team. | // IsTeamMember returns true if given user is a member of team. | ||||
func (t *Team) IsMember(uid int64) bool { | func (t *Team) IsMember(uid int64) bool { | ||||
return IsTeamMember(t.OrgId, t.Id, uid) | |||||
return IsTeamMember(t.OrgID, t.ID, uid) | |||||
} | } | ||||
func (t *Team) getRepositories(e Engine) error { | |||||
idStrs := strings.Split(t.RepoIds, "|") | |||||
t.Repos = make([]*Repository, 0, len(idStrs)) | |||||
for _, str := range idStrs { | |||||
if len(str) == 0 { | |||||
continue | |||||
} | |||||
id := com.StrTo(str[1:]).MustInt64() | |||||
if id == 0 { | |||||
continue | |||||
} | |||||
repo, err := getRepositoryById(e, id) | |||||
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 { | if err != nil { | ||||
return err | |||||
return fmt.Errorf("getRepositoryById(%d): %v", teamRepos[i].RepoID, err) | |||||
} | } | ||||
t.Repos = append(t.Repos, repo) | t.Repos = append(t.Repos, repo) | ||||
} | } | ||||
} | } | ||||
func (t *Team) getMembers(e Engine) (err error) { | func (t *Team) getMembers(e Engine) (err error) { | ||||
t.Members, err = getTeamMembers(e, t.Id) | |||||
t.Members, err = getTeamMembers(e, t.ID) | |||||
return err | return err | ||||
} | } | ||||
// AddMember adds new member to team of organization. | // AddMember adds new member to team of organization. | ||||
func (t *Team) AddMember(uid int64) error { | func (t *Team) AddMember(uid int64) error { | ||||
return AddTeamMember(t.OrgId, t.Id, uid) | |||||
return AddTeamMember(t.OrgID, t.ID, uid) | |||||
} | } | ||||
// RemoveMember removes member from team of organization. | // RemoveMember removes member from team of organization. | ||||
func (t *Team) RemoveMember(uid int64) error { | func (t *Team) RemoveMember(uid int64) error { | ||||
return RemoveTeamMember(t.OrgId, t.Id, uid) | |||||
return RemoveTeamMember(t.OrgID, t.ID, uid) | |||||
} | } | ||||
// AddRepository adds new repository to team of organization. | |||||
func (t *Team) AddRepository(repo *Repository) (err error) { | |||||
idStr := "$" + com.ToStr(repo.Id) + "|" | |||||
if repo.OwnerId != t.OrgId { | |||||
return errors.New("Repository not belong to organization") | |||||
} else if strings.Contains(t.RepoIds, idStr) { | |||||
return nil | |||||
} | |||||
func (t *Team) hasRepository(e Engine, repoID int64) bool { | |||||
return hasTeamRepo(e, t.OrgID, t.ID, repoID) | |||||
} | |||||
if err = repo.GetOwner(); err != nil { | |||||
return err | |||||
} else if err = t.GetMembers(); err != nil { | |||||
return err | |||||
} | |||||
// HasRepository returns true if given repository belong to team. | |||||
func (t *Team) HasRepository(repoID int64) bool { | |||||
return HasTeamRepo(t.OrgID, t.ID, repoID) | |||||
} | |||||
sess := x.NewSession() | |||||
defer sessionRelease(sess) | |||||
if err = sess.Begin(); err != nil { | |||||
func (t *Team) addRepository(e Engine, repo *Repository) (err error) { | |||||
if err = addTeamRepo(e, t.OrgID, t.ID, repo.Id); err != nil { | |||||
return err | return err | ||||
} | } | ||||
t.NumRepos++ | t.NumRepos++ | ||||
t.RepoIds += idStr | |||||
if _, err = sess.Id(t.Id).AllCols().Update(t); err != nil { | |||||
if _, err = e.Id(t.ID).AllCols().Update(t); err != nil { | |||||
return err | return err | ||||
} | } | ||||
if err = repo.recalculateAccesses(sess); err != nil { | |||||
if err = repo.recalculateAccesses(e); err != nil { | |||||
return err | return err | ||||
} | } | ||||
if err = t.getMembers(e); err != nil { | |||||
return fmt.Errorf("get team members: %v", err) | |||||
} | |||||
for _, u := range t.Members { | for _, u := range t.Members { | ||||
if err = watchRepo(sess, u.Id, repo.Id, true); err != nil { | |||||
if err = watchRepo(e, u.Id, repo.Id, true); err != nil { | |||||
return err | return err | ||||
} | } | ||||
} | } | ||||
return sess.Commit() | |||||
} | |||||
func (t *Team) HasRepository(repo *Repository) bool { | |||||
idStr := "$" + com.ToStr(repo.Id) + "|" | |||||
return strings.Contains(t.RepoIds, idStr) | |||||
return nil | |||||
} | } | ||||
// RemoveRepository removes repository from team of organization. | |||||
func (t *Team) RemoveRepository(repoId int64) error { | |||||
idStr := "$" + com.ToStr(repoId) + "|" | |||||
if !strings.Contains(t.RepoIds, idStr) { | |||||
// 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 | return nil | ||||
} | } | ||||
repo, err := GetRepositoryById(repoId) | |||||
if err != nil { | |||||
sess := x.NewSession() | |||||
defer sessionRelease(sess) | |||||
if err = sess.Begin(); err != nil { | |||||
return err | return err | ||||
} | } | ||||
if err = repo.GetOwner(); err != nil { | |||||
return err | |||||
} else if err = t.GetMembers(); err != nil { | |||||
if err = t.addRepository(sess, repo); err != nil { | |||||
return err | return err | ||||
} | } | ||||
sess := x.NewSession() | |||||
defer sessionRelease(sess) | |||||
if err = sess.Begin(); err != nil { | |||||
return sess.Commit() | |||||
} | |||||
func (t *Team) removeRepository(e Engine, repo *Repository) (err error) { | |||||
if err = removeTeamRepo(e, t.ID, repo.Id); err != nil { | |||||
return err | return err | ||||
} | } | ||||
t.NumRepos-- | t.NumRepos-- | ||||
t.RepoIds = strings.Replace(t.RepoIds, idStr, "", 1) | |||||
if _, err = sess.Id(t.Id).AllCols().Update(t); err != nil { | |||||
if _, err = e.Id(t.ID).AllCols().Update(t); err != nil { | |||||
return err | return err | ||||
} | } | ||||
if err = repo.recalculateAccesses(sess); err != nil { | |||||
if err = repo.recalculateAccesses(e); err != nil { | |||||
return err | return err | ||||
} | } | ||||
if err = t.getMembers(e); err != nil { | |||||
return fmt.Errorf("get team members: %v", err) | |||||
} | |||||
for _, u := range t.Members { | for _, u := range t.Members { | ||||
if err = watchRepo(sess, u.Id, repo.Id, false); err != nil { | |||||
has, err := hasAccess(e, u, repo, ACCESS_MODE_READ) | |||||
if err != nil { | |||||
return err | 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); err != nil { | |||||
return err | |||||
} | } | ||||
return sess.Commit() | return sess.Commit() | ||||
return ErrTeamNameIllegal | return ErrTeamNameIllegal | ||||
} | } | ||||
has, err := x.Id(t.OrgId).Get(new(User)) | |||||
has, err := x.Id(t.OrgID).Get(new(User)) | |||||
if err != nil { | if err != nil { | ||||
return err | return err | ||||
} else if !has { | } else if !has { | ||||
} | } | ||||
t.LowerName = strings.ToLower(t.Name) | t.LowerName = strings.ToLower(t.Name) | ||||
has, err = x.Where("org_id=?", t.OrgId).And("lower_name=?", t.LowerName).Get(new(Team)) | |||||
has, err = x.Where("org_id=?", t.OrgID).And("lower_name=?", t.LowerName).Get(new(Team)) | |||||
if err != nil { | if err != nil { | ||||
return err | return err | ||||
} else if has { | } else if has { | ||||
} | } | ||||
// Update organization number of teams. | // Update organization number of teams. | ||||
if _, err = sess.Exec("UPDATE `user` SET num_teams = num_teams + 1 WHERE id = ?", t.OrgId); err != nil { | |||||
if _, err = sess.Exec("UPDATE `user` SET num_teams = num_teams + 1 WHERE id = ?", t.OrgID); err != nil { | |||||
sess.Rollback() | sess.Rollback() | ||||
return err | return err | ||||
} | } | ||||
func getTeam(e Engine, orgId int64, name string) (*Team, error) { | func getTeam(e Engine, orgId int64, name string) (*Team, error) { | ||||
t := &Team{ | t := &Team{ | ||||
OrgId: orgId, | |||||
OrgID: orgId, | |||||
LowerName: strings.ToLower(name), | LowerName: strings.ToLower(name), | ||||
} | } | ||||
has, err := e.Get(t) | has, err := e.Get(t) | ||||
} | } | ||||
t.LowerName = strings.ToLower(t.Name) | t.LowerName = strings.ToLower(t.Name) | ||||
if _, err = sess.Id(t.Id).AllCols().Update(t); err != nil { | |||||
if _, err = sess.Id(t.ID).AllCols().Update(t); err != nil { | |||||
return err | return err | ||||
} | } | ||||
} | } | ||||
// Get organization. | // Get organization. | ||||
org, err := GetUserById(t.OrgId) | |||||
org, err := GetUserById(t.OrgID) | |||||
if err != nil { | if err != nil { | ||||
return err | return err | ||||
} | } | ||||
} | } | ||||
// Delete team-user. | // Delete team-user. | ||||
if _, err = sess.Where("org_id=?", org.Id).Where("team_id=?", t.Id).Delete(new(TeamUser)); err != nil { | |||||
if _, err = sess.Where("org_id=?", org.Id).Where("team_id=?", t.ID).Delete(new(TeamUser)); err != nil { | |||||
return err | return err | ||||
} | } | ||||
// Delete team. | // Delete team. | ||||
if _, err = sess.Id(t.Id).Delete(new(Team)); err != nil { | |||||
if _, err = sess.Id(t.ID).Delete(new(Team)); err != nil { | |||||
return err | return err | ||||
} | } | ||||
// Update organization number of teams. | // Update organization number of teams. | ||||
if _, err = sess.Exec("UPDATE `user` SET num_teams = num_teams - 1 WHERE id = ?", t.OrgId); err != nil { | |||||
if _, err = sess.Exec("UPDATE `user` SET num_teams=num_teams-1 WHERE id=?", t.OrgID); err != nil { | |||||
return err | return err | ||||
} | } | ||||
// TeamUser represents an team-user relation. | // TeamUser represents an team-user relation. | ||||
type TeamUser struct { | type TeamUser struct { | ||||
Id int64 | |||||
Uid int64 | |||||
OrgId int64 `xorm:"INDEX"` | |||||
TeamId int64 | |||||
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("uid=?", uid).And("org_id=?", orgId).And("team_id=?", teamId).Get(new(TeamUser)) | |||||
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 | return has | ||||
} | } | ||||
// IsTeamMember returns true if given user is a member of team. | // 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 IsTeamMember(orgID, teamID, uid int64) bool { | |||||
return isTeamMember(x, orgID, teamID, uid) | |||||
} | } | ||||
func getTeamMembers(e Engine, teamID int64) ([]*User, error) { | func getTeamMembers(e Engine, teamID int64) ([]*User, error) { | ||||
ts := make([]*Team, len(tus)) | ts := make([]*Team, len(tus)) | ||||
for i, tu := range tus { | for i, tu := range tus { | ||||
t := new(Team) | t := new(Team) | ||||
has, err := e.Id(tu.TeamId).Get(t) | |||||
has, err := e.Id(tu.TeamID).Get(t) | |||||
if err != nil { | if err != nil { | ||||
return nil, err | return nil, err | ||||
} else if !has { | } else if !has { | ||||
tu := &TeamUser{ | tu := &TeamUser{ | ||||
Uid: uid, | Uid: uid, | ||||
OrgId: orgId, | |||||
TeamId: teamId, | |||||
OrgID: orgId, | |||||
TeamID: teamId, | |||||
} | } | ||||
if _, err = sess.Insert(tu); err != nil { | if _, err = sess.Insert(tu); err != nil { | ||||
return err | return err | ||||
} else if _, err = sess.Id(t.Id).Update(t); err != nil { | |||||
} else if _, err = sess.Id(t.ID).Update(t); err != nil { | |||||
return err | return err | ||||
} | } | ||||
if t.IsOwnerTeam() { | if t.IsOwnerTeam() { | ||||
ou.IsOwner = true | ou.IsOwner = true | ||||
} | } | ||||
if _, err = sess.Id(ou.Id).AllCols().Update(ou); err != nil { | |||||
if _, err = sess.Id(ou.ID).AllCols().Update(ou); err != nil { | |||||
return err | return err | ||||
} | } | ||||
tu := &TeamUser{ | tu := &TeamUser{ | ||||
Uid: uid, | Uid: uid, | ||||
OrgId: orgId, | |||||
TeamId: teamId, | |||||
OrgID: orgId, | |||||
TeamID: teamId, | |||||
} | } | ||||
if _, err := e.Delete(tu); err != nil { | if _, err := e.Delete(tu); err != nil { | ||||
return err | return err | ||||
} else if _, err = e.Id(t.Id).AllCols().Update(t); err != nil { | |||||
} else if _, err = e.Id(t.ID).AllCols().Update(t); err != nil { | |||||
return err | return err | ||||
} | } | ||||
if t.IsOwnerTeam() { | if t.IsOwnerTeam() { | ||||
ou.IsOwner = false | ou.IsOwner = false | ||||
} | } | ||||
if _, err = e.Id(ou.Id).AllCols().Update(ou); err != nil { | |||||
if _, err = e.Id(ou.ID).AllCols().Update(ou); err != nil { | |||||
return err | return err | ||||
} | } | ||||
return nil | return nil | ||||
// RemoveTeamMember removes member from given team of given organization. | // RemoveTeamMember removes member from given team of given organization. | ||||
func RemoveTeamMember(orgId, teamId, uid int64) error { | func RemoveTeamMember(orgId, teamId, uid int64) error { | ||||
sess := x.NewSession() | sess := x.NewSession() | ||||
defer sess.Close() | |||||
defer sessionRelease(sess) | |||||
if err := sess.Begin(); err != nil { | if err := sess.Begin(); err != nil { | ||||
return err | return err | ||||
} | } | ||||
if err := removeTeamMember(sess, orgId, teamId, uid); err != nil { | if err := removeTeamMember(sess, orgId, teamId, uid); err != nil { | ||||
sess.Rollback() | |||||
return err | return err | ||||
} | } | ||||
return sess.Commit() | 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) | |||||
} |
} | } | ||||
// CreateRepository creates a repository for given user or organization. | // CreateRepository creates a repository for given user or organization. | ||||
func CreateRepository(u *User, name, desc, lang, license string, private, mirror, initReadme bool) (*Repository, error) { | |||||
func CreateRepository(u *User, name, desc, lang, license string, isPrivate, isMirror, initReadme bool) (*Repository, error) { | |||||
if !IsLegalName(name) { | if !IsLegalName(name) { | ||||
return nil, ErrRepoNameIllegal | return nil, ErrRepoNameIllegal | ||||
} | } | ||||
Name: name, | Name: name, | ||||
LowerName: strings.ToLower(name), | LowerName: strings.ToLower(name), | ||||
Description: desc, | Description: desc, | ||||
IsPrivate: private, | |||||
IsPrivate: isPrivate, | |||||
} | } | ||||
sess := x.NewSession() | sess := x.NewSession() | ||||
// Update owner team info and count. | // Update owner team info and count. | ||||
t, err := u.getOwnerTeam(sess) | t, err := u.getOwnerTeam(sess) | ||||
if err != nil { | if err != nil { | ||||
return nil, fmt.Errorf("get owner team: %v", err) | |||||
} else if err = t.getMembers(sess); err != nil { | |||||
return nil, fmt.Errorf("get team members: %v", err) | |||||
} | |||||
for _, u := range t.Members { | |||||
if err = watchRepo(sess, u.Id, repo.Id, true); err != nil { | |||||
return nil, fmt.Errorf("watch repository: %v", err) | |||||
} | |||||
} | |||||
t.RepoIds += "$" + com.ToStr(repo.Id) + "|" | |||||
t.NumRepos++ | |||||
if _, err = sess.Id(t.Id).AllCols().Update(t); err != nil { | |||||
return nil, err | |||||
return nil, fmt.Errorf("getOwnerTeam: %v", err) | |||||
} else if err = t.addRepository(sess, repo); err != nil { | |||||
return nil, fmt.Errorf("addRepository: %v", err) | |||||
} | } | ||||
} else { | } else { | ||||
if err = watchRepo(sess, u.Id, repo.Id, true); err != nil { | if err = watchRepo(sess, u.Id, repo.Id, true); err != nil { | ||||
return nil, fmt.Errorf("watch repository 2: %v", err) | |||||
return nil, fmt.Errorf("watchRepo: %v", err) | |||||
} | } | ||||
} | } | ||||
if err = newRepoAction(sess, u, repo); err != nil { | if err = newRepoAction(sess, u, repo); err != nil { | ||||
return nil, fmt.Errorf("new repository action: %v", err) | |||||
return nil, fmt.Errorf("newRepoAction: %v", err) | |||||
} | } | ||||
// No need for init mirror. | // No need for init mirror. | ||||
if !mirror { | |||||
if !isMirror { | |||||
repoPath := RepoPath(u.Name, repo.Name) | repoPath := RepoPath(u.Name, repo.Name) | ||||
if err = initRepository(sess, repoPath, u, repo, initReadme, lang, license); err != nil { | if err = initRepository(sess, repoPath, u, repo, initReadme, lang, license); err != nil { | ||||
if err2 := os.RemoveAll(repoPath); err2 != nil { | if err2 := os.RemoveAll(repoPath); err2 != nil { | ||||
} | } | ||||
// TransferOwnership transfers all corresponding setting from old user to new one. | // TransferOwnership transfers all corresponding setting from old user to new one. | ||||
func TransferOwnership(u *User, newOwner string, repo *Repository) error { | |||||
newUser, err := GetUserByName(newOwner) | |||||
func TransferOwnership(u *User, newOwnerName string, repo *Repository) error { | |||||
newOwner, err := GetUserByName(newOwnerName) | |||||
if err != nil { | if err != nil { | ||||
return fmt.Errorf("fail to get new owner(%s): %v", newOwner, err) | |||||
return fmt.Errorf("get new owner(%s): %v", newOwnerName, err) | |||||
} | } | ||||
// Check if new owner has repository with same name. | // Check if new owner has repository with same name. | ||||
has, err := IsRepositoryExist(newUser, repo.Name) | |||||
has, err := IsRepositoryExist(newOwner, repo.Name) | |||||
if err != nil { | if err != nil { | ||||
return err | return err | ||||
} else if has { | } else if has { | ||||
owner := repo.Owner | owner := repo.Owner | ||||
// Update repository. | // Update repository. | ||||
repo.OwnerId = newUser.Id | |||||
repo.Owner = newUser | |||||
repo.OwnerId = newOwner.Id | |||||
repo.Owner = newOwner | |||||
if _, err := sess.Id(repo.Id).Update(repo); err != nil { | if _, err := sess.Id(repo.Id).Update(repo); err != nil { | ||||
return err | return err | ||||
} | } | ||||
return err | return err | ||||
} | } | ||||
for _, c := range collaborators { | for _, c := range collaborators { | ||||
if c.Id == newUser.Id || newUser.IsOrgMember(c.Id) { | |||||
if c.Id == newOwner.Id || newOwner.IsOrgMember(c.Id) { | |||||
if _, err = sess.Delete(&Collaboration{RepoID: repo.Id, UserID: c.Id}); err != nil { | if _, err = sess.Delete(&Collaboration{RepoID: repo.Id, UserID: c.Id}); err != nil { | ||||
return err | return err | ||||
} | } | ||||
} | } | ||||
} | } | ||||
if newOwner.IsOrganization() { | |||||
// Update owner team info and count. | |||||
t, err := newOwner.GetOwnerTeam() | |||||
if err != nil { | |||||
return err | |||||
} else if err = t.addRepository(sess, repo); err != nil { | |||||
return err | |||||
} | |||||
} | |||||
// Update user repository number. | // Update user repository number. | ||||
if _, err = sess.Exec("UPDATE `user` SET num_repos = num_repos + 1 WHERE id = ?", newUser.Id); err != nil { | |||||
if _, err = sess.Exec("UPDATE `user` SET num_repos = num_repos + 1 WHERE id = ?", newOwner.Id); err != nil { | |||||
return err | return err | ||||
} else if _, err = sess.Exec("UPDATE `user` SET num_repos = num_repos - 1 WHERE id = ?", owner.Id); err != nil { | } else if _, err = sess.Exec("UPDATE `user` SET num_repos = num_repos - 1 WHERE id = ?", owner.Id); err != nil { | ||||
return err | return err | ||||
} else if err = repo.recalculateAccesses(sess); err != nil { | } else if err = repo.recalculateAccesses(sess); err != nil { | ||||
return err | return err | ||||
} else if err = watchRepo(sess, newUser.Id, repo.Id, true); err != nil { | |||||
} else if err = watchRepo(sess, newOwner.Id, repo.Id, true); err != nil { | |||||
return err | return err | ||||
} else if err = transferRepoAction(sess, u, newUser, repo); err != nil { | |||||
} else if err = transferRepoAction(sess, u, owner, newOwner, repo); err != nil { | |||||
return err | return err | ||||
} | } | ||||
// Change repository directory name. | // Change repository directory name. | ||||
if err = os.Rename(RepoPath(owner.Name, repo.Name), RepoPath(newUser.Name, repo.Name)); err != nil { | |||||
if err = os.Rename(RepoPath(owner.Name, repo.Name), RepoPath(newOwner.Name, repo.Name)); err != nil { | |||||
return err | return err | ||||
} | } | ||||
} | } | ||||
// DeleteRepository deletes a repository for a user or organization. | // DeleteRepository deletes a repository for a user or organization. | ||||
func DeleteRepository(uid, repoId int64, userName string) error { | |||||
repo := &Repository{Id: repoId, OwnerId: uid} | |||||
func DeleteRepository(uid, repoID int64, userName string) error { | |||||
repo := &Repository{Id: repoID, OwnerId: uid} | |||||
has, err := x.Get(repo) | has, err := x.Get(repo) | ||||
if err != nil { | if err != nil { | ||||
return err | return err | ||||
} | } | ||||
if org.IsOrganization() { | if org.IsOrganization() { | ||||
idStr := "$" + com.ToStr(repoId) + "|" | |||||
for _, t := range org.Teams { | for _, t := range org.Teams { | ||||
if !strings.Contains(t.RepoIds, idStr) { | |||||
if !t.hasRepository(sess, repoID) { | |||||
continue | continue | ||||
} | |||||
t.NumRepos-- | |||||
t.RepoIds = strings.Replace(t.RepoIds, idStr, "", 1) | |||||
if _, err = sess.Id(t.Id).AllCols().Update(t); err != nil { | |||||
} else if err = t.removeRepository(sess, repo); err != nil { | |||||
return err | return err | ||||
} | } | ||||
} | } | ||||
} | } | ||||
if _, err = sess.Delete(&Repository{Id: repoId}); err != nil { | |||||
if _, err = sess.Delete(&Repository{Id: repoID}); err != nil { | |||||
return err | return err | ||||
} else if _, err := sess.Delete(&Access{RepoID: repo.Id}); err != nil { | } else if _, err := sess.Delete(&Access{RepoID: repo.Id}); err != nil { | ||||
return err | return err | ||||
} else if _, err := sess.Delete(&Action{RepoId: repo.Id}); err != nil { | } else if _, err := sess.Delete(&Action{RepoId: repo.Id}); err != nil { | ||||
return err | return err | ||||
} else if _, err = sess.Delete(&Watch{RepoId: repoId}); err != nil { | |||||
} else if _, err = sess.Delete(&Watch{RepoId: repoID}); err != nil { | |||||
return err | return err | ||||
} else if _, err = sess.Delete(&Mirror{RepoId: repoId}); err != nil { | |||||
} else if _, err = sess.Delete(&Mirror{RepoId: repoID}); err != nil { | |||||
return err | return err | ||||
} else if _, err = sess.Delete(&IssueUser{RepoId: repoId}); err != nil { | |||||
} else if _, err = sess.Delete(&IssueUser{RepoId: repoID}); err != nil { | |||||
return err | return err | ||||
} else if _, err = sess.Delete(&Milestone{RepoId: repoId}); err != nil { | |||||
} else if _, err = sess.Delete(&Milestone{RepoId: repoID}); err != nil { | |||||
return err | return err | ||||
} else if _, err = sess.Delete(&Release{RepoId: repoId}); err != nil { | |||||
} else if _, err = sess.Delete(&Release{RepoId: repoID}); err != nil { | |||||
return err | return err | ||||
} else if _, err = sess.Delete(&Collaboration{RepoID: repoId}); err != nil { | |||||
} else if _, err = sess.Delete(&Collaboration{RepoID: repoID}); err != nil { | |||||
return err | return err | ||||
} | } | ||||
// Delete comments. | // Delete comments. | ||||
if err = x.Iterate(&Issue{RepoId: repoId}, func(idx int, bean interface{}) error { | |||||
issue := bean.(*Issue) | |||||
if _, err = sess.Delete(&Comment{IssueId: issue.Id}); err != nil { | |||||
issues := make([]*Issue, 0, 25) | |||||
if err = sess.Where("repo_id=?", repoID).Find(&issues); err != nil { | |||||
return err | |||||
} | |||||
for i := range issues { | |||||
if _, err = sess.Delete(&Comment{IssueId: issues[i].Id}); err != nil { | |||||
return err | return err | ||||
} | } | ||||
return nil | |||||
}); err != nil { | |||||
return err | |||||
} | } | ||||
if _, err = sess.Delete(&Issue{RepoId: repoId}); err != nil { | |||||
if _, err = sess.Delete(&Issue{RepoId: repoID}); err != nil { | |||||
return err | return err | ||||
} | } | ||||
if repo.IsFork { | if repo.IsFork { | ||||
if _, err = sess.Exec("UPDATE `repository` SET num_forks = num_forks - 1 WHERE id = ?", repo.ForkId); err != nil { | |||||
if _, err = sess.Exec("UPDATE `repository` SET num_forks=num_forks-1 WHERE id=?", repo.ForkId); err != nil { | |||||
return err | return err | ||||
} | } | ||||
} | } | ||||
if _, err = sess.Exec("UPDATE `user` SET num_repos = num_repos - 1 WHERE id = ?", uid); err != nil { | |||||
if _, err = sess.Exec("UPDATE `user` SET num_repos=num_repos-1 WHERE id=?", uid); err != nil { | |||||
return err | return err | ||||
} | } | ||||
// Remove repository files. | // Remove repository files. | ||||
if err = os.RemoveAll(RepoPath(userName, repo.Name)); err != nil { | if err = os.RemoveAll(RepoPath(userName, repo.Name)); err != nil { | ||||
desc := fmt.Sprintf("Fail to delete repository files(%s/%s): %v", userName, repo.Name, err) | |||||
desc := fmt.Sprintf("delete repository files(%s/%s): %v", userName, repo.Name, err) | |||||
log.Warn(desc) | log.Warn(desc) | ||||
if err = CreateRepositoryNotice(desc); err != nil { | if err = CreateRepositoryNotice(desc); err != nil { | ||||
log.Error(4, "Fail to add notice: %v", err) | |||||
log.Error(4, "add notice: %v", err) | |||||
} | } | ||||
} | } | ||||
// Update owner team info and count. | // Update owner team info and count. | ||||
t, err := u.getOwnerTeam(sess) | t, err := u.getOwnerTeam(sess) | ||||
if err != nil { | if err != nil { | ||||
return nil, fmt.Errorf("get owner team: %v", err) | |||||
} else if err = t.getMembers(sess); err != nil { | |||||
return nil, fmt.Errorf("get team members: %v", err) | |||||
} | |||||
for _, u := range t.Members { | |||||
if err = watchRepo(sess, u.Id, repo.Id, true); err != nil { | |||||
return nil, fmt.Errorf("watch repository: %v", err) | |||||
} | |||||
} | |||||
t.RepoIds += "$" + com.ToStr(repo.Id) + "|" | |||||
t.NumRepos++ | |||||
if _, err = sess.Id(t.Id).AllCols().Update(t); err != nil { | |||||
return nil, err | |||||
return nil, fmt.Errorf("getOwnerTeam: %v", err) | |||||
} else if err = t.addRepository(sess, repo); err != nil { | |||||
return nil, fmt.Errorf("addRepository: %v", err) | |||||
} | } | ||||
} else { | } else { | ||||
if err = watchRepo(sess, u.Id, repo.Id, true); err != nil { | if err = watchRepo(sess, u.Id, repo.Id, true); err != nil { | ||||
return nil, fmt.Errorf("watch repository 2: %v", err) | |||||
return nil, fmt.Errorf("watchRepo: %v", err) | |||||
} | } | ||||
} | } | ||||
if err = newRepoAction(sess, u, repo); err != nil { | if err = newRepoAction(sess, u, repo); err != nil { | ||||
return nil, fmt.Errorf("new repository action: %v", err) | |||||
return nil, fmt.Errorf("newRepoAction: %v", err) | |||||
} | } | ||||
if _, err = sess.Exec("UPDATE `repository` SET num_forks = num_forks + 1 WHERE id = ?", oldRepo.Id); err != nil { | |||||
if _, err = sess.Exec("UPDATE `repository` SET num_forks=num_forks+1 WHERE id=?", oldRepo.Id); err != nil { | |||||
return nil, err | return nil, err | ||||
} | } | ||||
u.Orgs = make([]*User, len(ous)) | u.Orgs = make([]*User, len(ous)) | ||||
for i, ou := range ous { | for i, ou := range ous { | ||||
u.Orgs[i], err = GetUserById(ou.OrgId) | |||||
u.Orgs[i], err = GetUserById(ou.OrgID) | |||||
if err != nil { | if err != nil { | ||||
return err | return err | ||||
} | } | ||||
} | } | ||||
for _, orgUser := range orgUsers { | for _, orgUser := range orgUsers { | ||||
tempIds = append(tempIds, orgUser.Id) | |||||
tempIds = append(tempIds, orgUser.ID) | |||||
} | } | ||||
ids = append(ids, tempIds...) | ids = append(ids, tempIds...) |
org := ctx.Org.Organization | org := ctx.Org.Organization | ||||
t := &models.Team{ | t := &models.Team{ | ||||
OrgId: org.Id, | |||||
OrgID: org.Id, | |||||
Name: form.TeamName, | Name: form.TeamName, | ||||
Description: form.Description, | Description: form.Description, | ||||
Authorize: auth, | Authorize: auth, |
"encoding/json" | "encoding/json" | ||||
"errors" | "errors" | ||||
"fmt" | "fmt" | ||||
"path" | |||||
"strings" | "strings" | ||||
"time" | "time" | ||||
0.5.14.0222 Beta | |||||
0.5.15.0223 Beta |