aboutsummaryrefslogtreecommitdiffstats
path: root/models/user/block.go
diff options
context:
space:
mode:
authorKN4CK3R <admin@oldschoolhack.me>2024-03-04 09:16:03 +0100
committerGitHub <noreply@github.com>2024-03-04 08:16:03 +0000
commitc337ff0ec70618ef2ead7850f90ab2a8458db192 (patch)
treecf4618cf7dc258018d5f9ec827b0fda4a9ebd196 /models/user/block.go
parent8e12ba34bab7e728ac93ccfaecbe91e053ef1c89 (diff)
downloadgitea-c337ff0ec70618ef2ead7850f90ab2a8458db192.tar.gz
gitea-c337ff0ec70618ef2ead7850f90ab2a8458db192.zip
Add user blocking (#29028)
Fixes #17453 This PR adds the abbility to block a user from a personal account or organization to restrict how the blocked user can interact with the blocker. The docs explain what's the consequence of blocking a user. Screenshots: ![grafik](https://github.com/go-gitea/gitea/assets/1666336/4ed884f3-e06a-4862-afd3-3b8aa2488dc6) ![grafik](https://github.com/go-gitea/gitea/assets/1666336/ae6d4981-f252-4f50-a429-04f0f9f1cdf1) ![grafik](https://github.com/go-gitea/gitea/assets/1666336/ca153599-5b0f-4b4a-90fe-18bdfd6f0b6b) --------- Co-authored-by: Lauris BH <lauris@nix.lv>
Diffstat (limited to 'models/user/block.go')
-rw-r--r--models/user/block.go123
1 files changed, 123 insertions, 0 deletions
diff --git a/models/user/block.go b/models/user/block.go
new file mode 100644
index 0000000000..5f2b65a199
--- /dev/null
+++ b/models/user/block.go
@@ -0,0 +1,123 @@
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package user
+
+import (
+ "context"
+
+ "code.gitea.io/gitea/models/db"
+ "code.gitea.io/gitea/modules/container"
+ "code.gitea.io/gitea/modules/timeutil"
+ "code.gitea.io/gitea/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 = util.NewPermissionDeniedErrorf("user is blocked")
+)
+
+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 len(blockerIDs) == 0 {
+ return false
+ }
+
+ if blockee.IsAdmin {
+ return false
+ }
+
+ cond := builder.Eq{"user_blocking.blockee_id": blockee.ID}.
+ 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) 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, nil
+ }
+ 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
+}