diff options
Diffstat (limited to 'models')
-rw-r--r-- | models/access.go | 8 | ||||
-rw-r--r-- | models/org.go | 230 | ||||
-rw-r--r-- | models/repo.go | 36 | ||||
-rw-r--r-- | models/user.go | 16 |
4 files changed, 220 insertions, 70 deletions
diff --git a/models/access.go b/models/access.go index 5238daba..81aa43dc 100644 --- a/models/access.go +++ b/models/access.go @@ -21,10 +21,10 @@ const ( // Access represents the accessibility of user to repository. type Access struct { Id int64 - UserName string `xorm:"unique(s)"` - RepoName string `xorm:"unique(s)"` // <user name>/<repo name> - Mode AccessType `xorm:"unique(s)"` - Created time.Time `xorm:"created"` + UserName string `xorm:"UNIQUE(s)"` + RepoName string `xorm:"UNIQUE(s)"` // <user name>/<repo name> + Mode AccessType `xorm:"UNIQUE(s)"` + Created time.Time `xorm:"CREATED"` } // AddAccess adds new access record. diff --git a/models/org.go b/models/org.go index 27228382..5d73cf3f 100644 --- a/models/org.go +++ b/models/org.go @@ -369,6 +369,13 @@ const ( ORG_ADMIN ) +func AuthorizeToAccessType(auth AuthorizeType) AccessType { + if auth == ORG_READABLE { + return READABLE + } + return WRITABLE +} + const OWNER_TEAM = "Owners" // Team represents a organization team. @@ -433,6 +440,142 @@ func (t *Team) RemoveMember(uid int64) error { return RemoveTeamMember(t.OrgId, t.Id, uid) } +// addAccessWithAuthorize inserts or updates access with given mode. +func addAccessWithAuthorize(sess *xorm.Session, access *Access, mode AccessType) error { + has, err := x.Get(access) + if err != nil { + return fmt.Errorf("fail to get access: %v", err) + } + access.Mode = mode + if has { + if _, err = sess.Id(access.Id).Update(access); err != nil { + return fmt.Errorf("fail to update access: %v", err) + } + } else { + if _, err = sess.Insert(access); err != nil { + return fmt.Errorf("fail to insert access: %v", err) + } + } + return nil +} + +// 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 + } + + if err = repo.GetOwner(); err != nil { + return err + } else if err = t.GetMembers(); err != nil { + return err + } + + sess := x.NewSession() + defer sess.Close() + if err = sess.Begin(); err != nil { + return err + } + + t.NumRepos++ + t.RepoIds += idStr + if _, err = sess.Id(t.Id).AllCols().Update(t); err != nil { + sess.Rollback() + return err + } + + // Give access to team members. + mode := AuthorizeToAccessType(t.Authorize) + + for _, u := range t.Members { + auth, err := GetHighestAuthorize(t.OrgId, u.Id, t.Id, repo.Id) + if err != nil { + sess.Rollback() + return err + } + + access := &Access{ + UserName: u.LowerName, + RepoName: path.Join(repo.Owner.LowerName, repo.LowerName), + } + if auth == 0 { + access.Mode = mode + if _, err = sess.Insert(access); err != nil { + sess.Rollback() + return fmt.Errorf("fail to insert access: %v", err) + } + } else if auth < t.Authorize { + if err = addAccessWithAuthorize(sess, access, mode); err != nil { + sess.Rollback() + return err + } + } + } + return sess.Commit() +} + +// RemoveRepository removes repository from team of organization. +func (t *Team) RemoveRepository(repoId int64) error { + idStr := "$" + com.ToStr(repoId) + "|" + if !strings.Contains(t.RepoIds, idStr) { + return nil + } + + repo, err := GetRepositoryById(repoId) + if err != nil { + return err + } + + if err = repo.GetOwner(); err != nil { + return err + } else if err = t.GetMembers(); err != nil { + return err + } + + sess := x.NewSession() + defer sess.Close() + if err = sess.Begin(); err != nil { + return err + } + + t.NumRepos-- + t.RepoIds = strings.Replace(t.RepoIds, idStr, "", 1) + if _, err = sess.Id(t.Id).AllCols().Update(t); err != nil { + sess.Rollback() + return err + } + + // Remove access to team members. + for _, u := range t.Members { + auth, err := GetHighestAuthorize(t.OrgId, u.Id, t.Id, repo.Id) + if err != nil { + sess.Rollback() + return err + } + + access := &Access{ + UserName: u.LowerName, + RepoName: path.Join(repo.Owner.LowerName, repo.LowerName), + } + if auth == 0 { + if _, err = sess.Delete(access); err != nil { + sess.Rollback() + return fmt.Errorf("fail to delete access: %v", err) + } + } else if auth < t.Authorize { + if err = addAccessWithAuthorize(sess, access, AuthorizeToAccessType(auth)); err != nil { + sess.Rollback() + 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 { @@ -554,16 +697,10 @@ func UpdateTeam(t *Team, authChanged bool) (err error) { return err } - mode := READABLE - if t.Authorize > ORG_READABLE { - mode = WRITABLE - } - access := &Access{ - Mode: mode, - } + // Update access. + mode := AuthorizeToAccessType(t.Authorize) for _, repo := range t.Repos { - access.RepoName = path.Join(org.LowerName, repo.LowerName) for _, u := range t.Members { // ORG_WRITABLE is the highest authorize level for now. // Skip checking others if current team has this level. @@ -578,8 +715,11 @@ func UpdateTeam(t *Team, authChanged bool) (err error) { } } - access.UserName = u.LowerName - if _, err = sess.Update(access); err != nil { + access := &Access{ + UserName: u.LowerName, + RepoName: path.Join(org.LowerName, repo.LowerName), + } + if err = addAccessWithAuthorize(sess, access, mode); err != nil { sess.Rollback() return err } @@ -617,36 +757,26 @@ func DeleteTeam(t *Team) error { } // Delete all accesses. - mode := READABLE - if t.Authorize > ORG_READABLE { - mode = WRITABLE - } - access := new(Access) - for _, repo := range t.Repos { - access.RepoName = path.Join(org.LowerName, repo.LowerName) for _, u := range t.Members { - access.UserName = u.LowerName - access.Mode = mode auth, err := GetHighestAuthorize(org.Id, u.Id, t.Id, repo.Id) if err != nil { sess.Rollback() return err } + access := &Access{ + UserName: u.LowerName, + RepoName: path.Join(org.LowerName, repo.LowerName), + } if auth == 0 { if _, err = sess.Delete(access); err != nil { sess.Rollback() - return err + return fmt.Errorf("fail to delete access: %v", err) } } else if auth < t.Authorize { // Downgrade authorize level. - mode := READABLE - if auth > ORG_READABLE { - mode = WRITABLE - } - access.Mode = mode - if _, err = sess.Update(access); err != nil { + if err = addAccessWithAuthorize(sess, access, AuthorizeToAccessType(auth)); err != nil { sess.Rollback() return err } @@ -779,15 +909,6 @@ func AddTeamMember(orgId, teamId, uid int64) error { TeamId: teamId, } - mode := READABLE - if t.Authorize > ORG_READABLE { - mode = WRITABLE - } - access := &Access{ - UserName: u.LowerName, - Mode: mode, - } - if _, err = sess.Insert(tu); err != nil { sess.Rollback() return err @@ -797,6 +918,7 @@ func AddTeamMember(orgId, teamId, uid int64) error { } // Give access to team repositories. + mode := AuthorizeToAccessType(t.Authorize) for _, repo := range t.Repos { auth, err := GetHighestAuthorize(orgId, uid, teamId, repo.Id) if err != nil { @@ -804,22 +926,24 @@ func AddTeamMember(orgId, teamId, uid int64) error { return err } - access.Id = 0 - access.RepoName = path.Join(org.LowerName, repo.LowerName) + access := &Access{ + UserName: u.LowerName, + RepoName: path.Join(org.LowerName, repo.LowerName), + } // Equal 0 means given access doesn't exist. if auth == 0 { + access.Mode = mode if _, err = sess.Insert(access); err != nil { sess.Rollback() - return err + return fmt.Errorf("fail to insert access: %v", err) } } else if auth < t.Authorize { - if _, err = sess.Update(access); err != nil { + if err = addAccessWithAuthorize(sess, access, mode); err != nil { sess.Rollback() return err } } } - fmt.Println("kao") // We make sure it exists before. ou := new(OrgUser) @@ -889,10 +1013,6 @@ func removeTeamMemberWithSess(orgId, teamId, uid int64, sess *xorm.Session) erro } // Delete access to team repositories. - access := &Access{ - UserName: u.LowerName, - } - for _, repo := range t.Repos { auth, err := GetHighestAuthorize(orgId, uid, teamId, repo.Id) if err != nil { @@ -900,22 +1020,22 @@ func removeTeamMemberWithSess(orgId, teamId, uid int64, sess *xorm.Session) erro return err } + access := &Access{ + UserName: u.LowerName, + RepoName: path.Join(org.LowerName, repo.LowerName), + } // Delete access if this is the last team user belongs to. if auth == 0 { - access.RepoName = path.Join(org.LowerName, repo.LowerName) - _, err = sess.Delete(access) + if _, err = sess.Delete(access); err != nil { + sess.Rollback() + return fmt.Errorf("fail to delete access: %v", err) + } } else if auth < t.Authorize { // Downgrade authorize level. - mode := READABLE - if auth > ORG_READABLE { - mode = WRITABLE + if err = addAccessWithAuthorize(sess, access, AuthorizeToAccessType(auth)); err != nil { + sess.Rollback() + return err } - access.Mode = mode - _, err = sess.Update(access) - } - if err != nil { - sess.Rollback() - return err } } diff --git a/models/repo.go b/models/repo.go index f5d1ca83..c3e9423f 100644 --- a/models/repo.go +++ b/models/repo.go @@ -519,12 +519,11 @@ func CreateRepository(u *User, name, desc, lang, license string, private, mirror sess.Rollback() return nil, err } - us, err := GetTeamMembers(u.Id, t.Id) - if err != nil { + if err = t.GetMembers(); err != nil { sess.Rollback() return nil, err } - for _, u := range us { + for _, u := range t.Members { access.Id = 0 access.UserName = u.LowerName if _, err = sess.Insert(access); err != nil { @@ -963,6 +962,37 @@ func GetCollaborators(repoName string) (us []*User, err error) { return us, nil } +type SearchOption struct { + Keyword string + Uid int64 + Limit int +} + +// SearchRepositoryByName returns given number of repositories whose name contains keyword. +func SearchRepositoryByName(opt SearchOption) (repos []*Repository, err error) { + // Prevent SQL inject. + opt.Keyword = strings.TrimSpace(opt.Keyword) + if len(opt.Keyword) == 0 { + return repos, nil + } + + opt.Keyword = strings.Split(opt.Keyword, " ")[0] + if len(opt.Keyword) == 0 { + return repos, nil + } + opt.Keyword = strings.ToLower(opt.Keyword) + + repos = make([]*Repository, 0, opt.Limit) + + // Append conditions. + sess := x.Limit(opt.Limit) + if opt.Uid > 0 { + sess.Where("owner_id=?", opt.Uid) + } + sess.And("lower_name like '%" + opt.Keyword + "%'").Find(&repos) + return repos, err +} + // Watch is connection request for receiving repository notifycation. type Watch struct { Id int64 diff --git a/models/user.go b/models/user.go index e8db1ad1..a74d8039 100644 --- a/models/user.go +++ b/models/user.go @@ -521,21 +521,21 @@ func GetUserByEmail(email string) (*User, error) { } // SearchUserByName returns given number of users whose name contains keyword. -func SearchUserByName(key string, limit int) (us []*User, err error) { +func SearchUserByName(opt SearchOption) (us []*User, err error) { // Prevent SQL inject. - key = strings.TrimSpace(key) - if len(key) == 0 { + opt.Keyword = strings.TrimSpace(opt.Keyword) + if len(opt.Keyword) == 0 { return us, nil } - key = strings.Split(key, " ")[0] - if len(key) == 0 { + opt.Keyword = strings.Split(opt.Keyword, " ")[0] + if len(opt.Keyword) == 0 { return us, nil } - key = strings.ToLower(key) + opt.Keyword = strings.ToLower(opt.Keyword) - us = make([]*User, 0, limit) - err = x.Limit(limit).Where("type=0").And("lower_name like '%" + key + "%'").Find(&us) + us = make([]*User, 0, opt.Limit) + err = x.Limit(opt.Limit).Where("type=0").And("lower_name like '%" + opt.Keyword + "%'").Find(&us) return us, err } |