mirror of
https://github.com/go-gitea/gitea.git
synced 2026-11-11 19:39:02 +00:00
Adds a repository-level **"Restrict to collaborators"** option under the Issues and Pull Request unit settings. When enabled, only users with collaborator access to the base repository (owner, team members, or explicit collaborators) can open issues or pull requests against it. Public repositories often need to be visible/cloneable by everyone, but owners may want to limit who can open pull requests (e.g. restrict to an internal team while still keeping the code public) * Fixes: https://github.com/go-gitea/gitea/issues/40015 * Fixes: https://github.com/go-gitea/gitea/issues/31890 * Fixes: https://github.com/go-gitea/gitea/issues/28021 * Fixes: https://github.com/go-gitea/gitea/issues/14801 --------- Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
135 lines
3.3 KiB
Go
135 lines
3.3 KiB
Go
// Copyright 2024 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package user
|
|
|
|
import (
|
|
"context"
|
|
|
|
"gitea.dev/models/db"
|
|
"gitea.dev/modules/container"
|
|
"gitea.dev/modules/timeutil"
|
|
"gitea.dev/modules/util"
|
|
|
|
"xorm.io/builder"
|
|
)
|
|
|
|
var (
|
|
ErrBlockOrganization = util.NewInvalidArgumentErrorf("cannot block an organization")
|
|
ErrCanNotBlock = util.NewInvalidArgumentErrorf("cannot block the user")
|
|
ErrCanNotUnblock = util.NewInvalidArgumentErrorf("cannot unblock the user")
|
|
|
|
// ErrBlockedUser is for end users: the doer is blocked by the repo owner, or an assignee when creating an issue, etc
|
|
ErrBlockedUser = util.NewPermissionDeniedErrorf("you are blocked by the user")
|
|
)
|
|
|
|
type Blocking struct {
|
|
ID int64 `xorm:"pk autoincr"`
|
|
BlockerID int64 `xorm:"UNIQUE(block)"`
|
|
Blocker *User `xorm:"-"`
|
|
BlockeeID int64 `xorm:"UNIQUE(block)"`
|
|
Blockee *User `xorm:"-"`
|
|
Note string
|
|
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
|
|
}
|
|
|
|
func (*Blocking) TableName() string {
|
|
return "user_blocking"
|
|
}
|
|
|
|
func init() {
|
|
db.RegisterModel(new(Blocking))
|
|
}
|
|
|
|
func UpdateBlockingNote(ctx context.Context, id int64, note string) error {
|
|
_, err := db.GetEngine(ctx).ID(id).Cols("note").Update(&Blocking{Note: note})
|
|
return err
|
|
}
|
|
|
|
func IsUserBlockedBy(ctx context.Context, blockee *User, blockerIDs ...int64) bool {
|
|
if blockee.IsAdmin {
|
|
return false
|
|
}
|
|
|
|
return HasBlocking(ctx, blockee.ID, blockerIDs...)
|
|
}
|
|
|
|
// HasBlocking reports whether a blocking relationship exists regardless of the blockee's admin status.
|
|
func HasBlocking(ctx context.Context, blockeeID int64, blockerIDs ...int64) bool {
|
|
if len(blockerIDs) == 0 {
|
|
return false
|
|
}
|
|
|
|
cond := builder.Eq{"user_blocking.blockee_id": blockeeID}.
|
|
And(builder.In("user_blocking.blocker_id", blockerIDs))
|
|
|
|
has, _ := db.GetEngine(ctx).Where(cond).Exist(&Blocking{})
|
|
return has
|
|
}
|
|
|
|
type FindBlockingOptions struct {
|
|
db.ListOptions
|
|
BlockerID int64
|
|
BlockeeID int64
|
|
}
|
|
|
|
func (opts *FindBlockingOptions) ToOrders() string {
|
|
return "id"
|
|
}
|
|
|
|
func (opts *FindBlockingOptions) ToConds() builder.Cond {
|
|
cond := builder.NewCond()
|
|
if opts.BlockerID != 0 {
|
|
cond = cond.And(builder.Eq{"user_blocking.blocker_id": opts.BlockerID})
|
|
}
|
|
if opts.BlockeeID != 0 {
|
|
cond = cond.And(builder.Eq{"user_blocking.blockee_id": opts.BlockeeID})
|
|
}
|
|
return cond
|
|
}
|
|
|
|
func FindBlockings(ctx context.Context, opts *FindBlockingOptions) ([]*Blocking, int64, error) {
|
|
return db.FindAndCount[Blocking](ctx, opts)
|
|
}
|
|
|
|
func GetBlocking(ctx context.Context, blockerID, blockeeID int64) (*Blocking, error) {
|
|
blocks, _, err := FindBlockings(ctx, &FindBlockingOptions{
|
|
BlockerID: blockerID,
|
|
BlockeeID: blockeeID,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(blocks) == 0 {
|
|
return nil, util.NewNotExistErrorf("blocking record doesn't exist")
|
|
}
|
|
return blocks[0], nil
|
|
}
|
|
|
|
type BlockingList []*Blocking
|
|
|
|
func (blocks BlockingList) LoadAttributes(ctx context.Context) error {
|
|
ids := make(container.Set[int64], len(blocks)*2)
|
|
for _, b := range blocks {
|
|
ids.Add(b.BlockerID)
|
|
ids.Add(b.BlockeeID)
|
|
}
|
|
|
|
userList, err := GetUsersByIDs(ctx, ids.Values())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
userMap := make(map[int64]*User, len(userList))
|
|
for _, u := range userList {
|
|
userMap[u.ID] = u
|
|
}
|
|
|
|
for _, b := range blocks {
|
|
b.Blocker = userMap[b.BlockerID]
|
|
b.Blockee = userMap[b.BlockeeID]
|
|
}
|
|
|
|
return nil
|
|
}
|