code.gitea.io/gitea@v1.22.3/models/user/block.go (about)

     1  // Copyright 2024 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package user
     5  
     6  import (
     7  	"context"
     8  
     9  	"code.gitea.io/gitea/models/db"
    10  	"code.gitea.io/gitea/modules/container"
    11  	"code.gitea.io/gitea/modules/timeutil"
    12  	"code.gitea.io/gitea/modules/util"
    13  
    14  	"xorm.io/builder"
    15  )
    16  
    17  var (
    18  	ErrBlockOrganization = util.NewInvalidArgumentErrorf("cannot block an organization")
    19  	ErrCanNotBlock       = util.NewInvalidArgumentErrorf("cannot block the user")
    20  	ErrCanNotUnblock     = util.NewInvalidArgumentErrorf("cannot unblock the user")
    21  	ErrBlockedUser       = util.NewPermissionDeniedErrorf("user is blocked")
    22  )
    23  
    24  type Blocking struct {
    25  	ID          int64 `xorm:"pk autoincr"`
    26  	BlockerID   int64 `xorm:"UNIQUE(block)"`
    27  	Blocker     *User `xorm:"-"`
    28  	BlockeeID   int64 `xorm:"UNIQUE(block)"`
    29  	Blockee     *User `xorm:"-"`
    30  	Note        string
    31  	CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
    32  }
    33  
    34  func (*Blocking) TableName() string {
    35  	return "user_blocking"
    36  }
    37  
    38  func init() {
    39  	db.RegisterModel(new(Blocking))
    40  }
    41  
    42  func UpdateBlockingNote(ctx context.Context, id int64, note string) error {
    43  	_, err := db.GetEngine(ctx).ID(id).Cols("note").Update(&Blocking{Note: note})
    44  	return err
    45  }
    46  
    47  func IsUserBlockedBy(ctx context.Context, blockee *User, blockerIDs ...int64) bool {
    48  	if len(blockerIDs) == 0 {
    49  		return false
    50  	}
    51  
    52  	if blockee.IsAdmin {
    53  		return false
    54  	}
    55  
    56  	cond := builder.Eq{"user_blocking.blockee_id": blockee.ID}.
    57  		And(builder.In("user_blocking.blocker_id", blockerIDs))
    58  
    59  	has, _ := db.GetEngine(ctx).Where(cond).Exist(&Blocking{})
    60  	return has
    61  }
    62  
    63  type FindBlockingOptions struct {
    64  	db.ListOptions
    65  	BlockerID int64
    66  	BlockeeID int64
    67  }
    68  
    69  func (opts *FindBlockingOptions) ToConds() builder.Cond {
    70  	cond := builder.NewCond()
    71  	if opts.BlockerID != 0 {
    72  		cond = cond.And(builder.Eq{"user_blocking.blocker_id": opts.BlockerID})
    73  	}
    74  	if opts.BlockeeID != 0 {
    75  		cond = cond.And(builder.Eq{"user_blocking.blockee_id": opts.BlockeeID})
    76  	}
    77  	return cond
    78  }
    79  
    80  func FindBlockings(ctx context.Context, opts *FindBlockingOptions) ([]*Blocking, int64, error) {
    81  	return db.FindAndCount[Blocking](ctx, opts)
    82  }
    83  
    84  func GetBlocking(ctx context.Context, blockerID, blockeeID int64) (*Blocking, error) {
    85  	blocks, _, err := FindBlockings(ctx, &FindBlockingOptions{
    86  		BlockerID: blockerID,
    87  		BlockeeID: blockeeID,
    88  	})
    89  	if err != nil {
    90  		return nil, err
    91  	}
    92  	if len(blocks) == 0 {
    93  		return nil, nil
    94  	}
    95  	return blocks[0], nil
    96  }
    97  
    98  type BlockingList []*Blocking
    99  
   100  func (blocks BlockingList) LoadAttributes(ctx context.Context) error {
   101  	ids := make(container.Set[int64], len(blocks)*2)
   102  	for _, b := range blocks {
   103  		ids.Add(b.BlockerID)
   104  		ids.Add(b.BlockeeID)
   105  	}
   106  
   107  	userList, err := GetUsersByIDs(ctx, ids.Values())
   108  	if err != nil {
   109  		return err
   110  	}
   111  
   112  	userMap := make(map[int64]*User, len(userList))
   113  	for _, u := range userList {
   114  		userMap[u.ID] = u
   115  	}
   116  
   117  	for _, b := range blocks {
   118  		b.Blocker = userMap[b.BlockerID]
   119  		b.Blockee = userMap[b.BlockeeID]
   120  	}
   121  
   122  	return nil
   123  }