mirror of
https://github.com/hanzoai/forge.git
synced 2026-10-30 15:00:39 +00:00
Source files keep their SPDX-License-Identifier and Hanzo copyright line; the Gitea, Gogs and LFS Test Server copyrights they used to repeat now live once in NOTICE, alongside LICENSE. The header lint accepts any copyright line above the SPDX line, so it no longer demands an upstream one. Co-authored-by: Hanzo Dev <[email protected]>
124 lines
2.9 KiB
Go
124 lines
2.9 KiB
Go
// Copyright 2026 Hanzo AI, Inc. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package user
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/hanzoai/git/models/db"
|
|
"github.com/hanzoai/git/modules/container"
|
|
"github.com/hanzoai/git/modules/timeutil"
|
|
"github.com/hanzoai/git/modules/util"
|
|
|
|
"github.com/hanzoai/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, 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
|
|
}
|