| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 | 
							- // Copyright 2020 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 db
 
- import (
 
- 	"context"
 
- 	"gorm.io/gorm"
 
- 	log "unknwon.dev/clog/v2"
 
- )
 
- // PermsStore is the persistent interface for permissions.
 
- //
 
- // NOTE: All methods are sorted in alphabetical order.
 
- type PermsStore interface {
 
- 	// AccessMode returns the access mode of given user has to the repository.
 
- 	AccessMode(ctx context.Context, userID, repoID int64, opts AccessModeOptions) AccessMode
 
- 	// Authorize returns true if the user has as good as desired access mode to the
 
- 	// repository.
 
- 	Authorize(ctx context.Context, userID, repoID int64, desired AccessMode, opts AccessModeOptions) bool
 
- 	// SetRepoPerms does a full update to which users have which level of access to
 
- 	// given repository. Keys of the "accessMap" are user IDs.
 
- 	SetRepoPerms(ctx context.Context, repoID int64, accessMap map[int64]AccessMode) error
 
- }
 
- var Perms PermsStore
 
- // Access represents the highest access level of a user has to a repository. The
 
- // only access type that is not in this table is the real owner of a repository.
 
- // In case of an organization repository, the members of the owners team are in
 
- // this table.
 
- type Access struct {
 
- 	ID     int64      `gorm:"primaryKey"`
 
- 	UserID int64      `xorm:"UNIQUE(s)" gorm:"uniqueIndex:access_user_repo_unique;not null"`
 
- 	RepoID int64      `xorm:"UNIQUE(s)" gorm:"uniqueIndex:access_user_repo_unique;not null"`
 
- 	Mode   AccessMode `gorm:"not null"`
 
- }
 
- // AccessMode is the access mode of a user has to a repository.
 
- type AccessMode int
 
- const (
 
- 	AccessModeNone  AccessMode = iota // 0
 
- 	AccessModeRead                    // 1
 
- 	AccessModeWrite                   // 2
 
- 	AccessModeAdmin                   // 3
 
- 	AccessModeOwner                   // 4
 
- )
 
- func (mode AccessMode) String() string {
 
- 	switch mode {
 
- 	case AccessModeRead:
 
- 		return "read"
 
- 	case AccessModeWrite:
 
- 		return "write"
 
- 	case AccessModeAdmin:
 
- 		return "admin"
 
- 	case AccessModeOwner:
 
- 		return "owner"
 
- 	default:
 
- 		return "none"
 
- 	}
 
- }
 
- // ParseAccessMode returns corresponding access mode to given permission string.
 
- func ParseAccessMode(permission string) AccessMode {
 
- 	switch permission {
 
- 	case "write":
 
- 		return AccessModeWrite
 
- 	case "admin":
 
- 		return AccessModeAdmin
 
- 	default:
 
- 		return AccessModeRead
 
- 	}
 
- }
 
- var _ PermsStore = (*perms)(nil)
 
- type perms struct {
 
- 	*gorm.DB
 
- }
 
- type AccessModeOptions struct {
 
- 	OwnerID int64 // The ID of the repository owner.
 
- 	Private bool  // Whether the repository is private.
 
- }
 
- func (db *perms) AccessMode(ctx context.Context, userID, repoID int64, opts AccessModeOptions) (mode AccessMode) {
 
- 	if repoID <= 0 {
 
- 		return AccessModeNone
 
- 	}
 
- 	// Everyone has read access to public repository.
 
- 	if !opts.Private {
 
- 		mode = AccessModeRead
 
- 	}
 
- 	// Anonymous user gets the default access.
 
- 	if userID <= 0 {
 
- 		return mode
 
- 	}
 
- 	if userID == opts.OwnerID {
 
- 		return AccessModeOwner
 
- 	}
 
- 	access := new(Access)
 
- 	err := db.WithContext(ctx).Where("user_id = ? AND repo_id = ?", userID, repoID).First(access).Error
 
- 	if err != nil {
 
- 		if err != gorm.ErrRecordNotFound {
 
- 			log.Error("Failed to get access [user_id: %d, repo_id: %d]: %v", userID, repoID, err)
 
- 		}
 
- 		return mode
 
- 	}
 
- 	return access.Mode
 
- }
 
- func (db *perms) Authorize(ctx context.Context, userID, repoID int64, desired AccessMode, opts AccessModeOptions) bool {
 
- 	return desired <= db.AccessMode(ctx, userID, repoID, opts)
 
- }
 
- func (db *perms) SetRepoPerms(ctx context.Context, repoID int64, accessMap map[int64]AccessMode) error {
 
- 	records := make([]*Access, 0, len(accessMap))
 
- 	for userID, mode := range accessMap {
 
- 		records = append(records, &Access{
 
- 			UserID: userID,
 
- 			RepoID: repoID,
 
- 			Mode:   mode,
 
- 		})
 
- 	}
 
- 	return db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
 
- 		err := tx.Where("repo_id = ?", repoID).Delete(new(Access)).Error
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		return tx.Create(&records).Error
 
- 	})
 
- }
 
 
  |