diff options
Diffstat (limited to 'models/repo_collaboration.go')
-rw-r--r-- | models/repo_collaboration.go | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/models/repo_collaboration.go b/models/repo_collaboration.go new file mode 100644 index 00000000..419169f0 --- /dev/null +++ b/models/repo_collaboration.go @@ -0,0 +1,161 @@ +// 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 ( + "fmt" + "time" +) + +// Collaboration represent the relation between an individual and a repository. +type Collaboration struct { + ID int64 `xorm:"pk autoincr"` + RepoID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"` + UserID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"` + Mode AccessMode `xorm:"DEFAULT 2 NOT NULL"` + Created time.Time `xorm:"CREATED"` +} + +func (c *Collaboration) ModeName() string { + switch c.Mode { + case ACCESS_MODE_READ: + return "Read" + case ACCESS_MODE_WRITE: + return "Write" + case ACCESS_MODE_ADMIN: + return "Admin" + } + return "Undefined" +} + +// AddCollaborator adds new collaboration relation between an individual and a repository. +func (repo *Repository) AddCollaborator(u *User) error { + collaboration := &Collaboration{ + RepoID: repo.ID, + UserID: u.Id, + } + + has, err := x.Get(collaboration) + if err != nil { + return err + } else if has { + return nil + } + collaboration.Mode = ACCESS_MODE_WRITE + + sess := x.NewSession() + defer sessionRelease(sess) + if err = sess.Begin(); err != nil { + return err + } + + if _, err = sess.InsertOne(collaboration); err != nil { + return err + } + + if repo.Owner.IsOrganization() { + err = repo.recalculateTeamAccesses(sess, 0) + } else { + err = repo.recalculateAccesses(sess) + } + if err != nil { + return fmt.Errorf("recalculateAccesses 'team=%v': %v", repo.Owner.IsOrganization(), err) + } + + return sess.Commit() +} + +func (repo *Repository) getCollaborations(e Engine) ([]*Collaboration, error) { + collaborations := make([]*Collaboration, 0) + return collaborations, e.Find(&collaborations, &Collaboration{RepoID: repo.ID}) +} + +// Collaborator represents a user with collaboration details. +type Collaborator struct { + *User + Collaboration *Collaboration +} + +func (repo *Repository) getCollaborators(e Engine) ([]*Collaborator, error) { + collaborations, err := repo.getCollaborations(e) + if err != nil { + return nil, fmt.Errorf("getCollaborations: %v", err) + } + + collaborators := make([]*Collaborator, len(collaborations)) + for i, c := range collaborations { + user, err := getUserByID(e, c.UserID) + if err != nil { + return nil, err + } + collaborators[i] = &Collaborator{ + User: user, + Collaboration: c, + } + } + return collaborators, nil +} + +// GetCollaborators returns the collaborators for a repository +func (repo *Repository) GetCollaborators() ([]*Collaborator, error) { + return repo.getCollaborators(x) +} + +// ChangeCollaborationAccessMode sets new access mode for the collaboration. +func (repo *Repository) ChangeCollaborationAccessMode(uid int64, mode AccessMode) error { + // Discard invalid input + if mode <= ACCESS_MODE_NONE || mode > ACCESS_MODE_OWNER { + return nil + } + + collaboration := &Collaboration{ + RepoID: repo.ID, + UserID: uid, + } + has, err := x.Get(collaboration) + if err != nil { + return fmt.Errorf("get collaboration: %v", err) + } else if !has { + return nil + } + + collaboration.Mode = mode + + sess := x.NewSession() + defer sessionRelease(sess) + if err = sess.Begin(); err != nil { + return err + } + + if _, err = sess.Id(collaboration.ID).AllCols().Update(collaboration); err != nil { + return fmt.Errorf("update collaboration: %v", err) + } else if _, err = sess.Exec("UPDATE access SET mode = ? WHERE user_id = ? AND repo_id = ?", mode, uid, repo.ID); err != nil { + return fmt.Errorf("update access table: %v", err) + } + + return sess.Commit() +} + +// DeleteCollaboration removes collaboration relation between the user and repository. +func (repo *Repository) DeleteCollaboration(uid int64) (err error) { + collaboration := &Collaboration{ + RepoID: repo.ID, + UserID: uid, + } + + sess := x.NewSession() + defer sessionRelease(sess) + if err = sess.Begin(); err != nil { + return err + } + + if has, err := sess.Delete(collaboration); err != nil || has == 0 { + return err + } else if err = repo.recalculateAccesses(sess); err != nil { + return err + } + + return sess.Commit() +} |