| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303 |
- // Copyright 2024 The Gitea Authors. All rights reserved.
- // SPDX-License-Identifier: MIT
-
- package user
-
- import (
- "context"
-
- "code.gitea.io/gitea/models/db"
- issues_model "code.gitea.io/gitea/models/issues"
- org_model "code.gitea.io/gitea/models/organization"
- repo_model "code.gitea.io/gitea/models/repo"
- user_model "code.gitea.io/gitea/models/user"
- repo_service "code.gitea.io/gitea/services/repository"
- )
-
- func CanBlockUser(ctx context.Context, doer, blocker, blockee *user_model.User) bool {
- if blocker.ID == blockee.ID {
- return false
- }
- if doer.ID == blockee.ID {
- return false
- }
-
- if blockee.IsOrganization() {
- return false
- }
-
- if user_model.IsUserBlockedBy(ctx, blockee, blocker.ID) {
- return false
- }
-
- if blocker.IsOrganization() {
- org := org_model.OrgFromUser(blocker)
- if isMember, _ := org.IsOrgMember(ctx, blockee.ID); isMember {
- return false
- }
- if isAdmin, _ := org.IsOwnedBy(ctx, doer.ID); !isAdmin && !doer.IsAdmin {
- return false
- }
- } else if !doer.IsAdmin && doer.ID != blocker.ID {
- return false
- }
-
- return true
- }
-
- func CanUnblockUser(ctx context.Context, doer, blocker, blockee *user_model.User) bool {
- if doer.ID == blockee.ID {
- return false
- }
-
- if !user_model.IsUserBlockedBy(ctx, blockee, blocker.ID) {
- return false
- }
-
- if blocker.IsOrganization() {
- org := org_model.OrgFromUser(blocker)
- if isAdmin, _ := org.IsOwnedBy(ctx, doer.ID); !isAdmin && !doer.IsAdmin {
- return false
- }
- } else if !doer.IsAdmin && doer.ID != blocker.ID {
- return false
- }
-
- return true
- }
-
- func BlockUser(ctx context.Context, doer, blocker, blockee *user_model.User, note string) error {
- if blockee.IsOrganization() {
- return user_model.ErrBlockOrganization
- }
-
- if !CanBlockUser(ctx, doer, blocker, blockee) {
- return user_model.ErrCanNotBlock
- }
-
- return db.WithTx(ctx, func(ctx context.Context) error {
- // unfollow each other
- if err := user_model.UnfollowUser(ctx, blocker.ID, blockee.ID); err != nil {
- return err
- }
- if err := user_model.UnfollowUser(ctx, blockee.ID, blocker.ID); err != nil {
- return err
- }
-
- // unstar each other
- if err := unstarRepos(ctx, blocker, blockee); err != nil {
- return err
- }
- if err := unstarRepos(ctx, blockee, blocker); err != nil {
- return err
- }
-
- // unwatch each others repositories
- if err := unwatchRepos(ctx, blocker, blockee); err != nil {
- return err
- }
- if err := unwatchRepos(ctx, blockee, blocker); err != nil {
- return err
- }
-
- // unassign each other from issues
- if err := unassignIssues(ctx, blocker, blockee); err != nil {
- return err
- }
- if err := unassignIssues(ctx, blockee, blocker); err != nil {
- return err
- }
-
- // remove each other from repository collaborations
- if err := removeCollaborations(ctx, blocker, blockee); err != nil {
- return err
- }
- if err := removeCollaborations(ctx, blockee, blocker); err != nil {
- return err
- }
-
- // cancel each other repository transfers
- if err := cancelRepositoryTransfers(ctx, doer, blocker, blockee); err != nil {
- return err
- }
- if err := cancelRepositoryTransfers(ctx, doer, blockee, blocker); err != nil {
- return err
- }
-
- return db.Insert(ctx, &user_model.Blocking{
- BlockerID: blocker.ID,
- BlockeeID: blockee.ID,
- Note: note,
- })
- })
- }
-
- func unstarRepos(ctx context.Context, starrer, repoOwner *user_model.User) error {
- opts := &repo_model.StarredReposOptions{
- ListOptions: db.ListOptions{
- Page: 1,
- PageSize: 25,
- },
- StarrerID: starrer.ID,
- RepoOwnerID: repoOwner.ID,
- }
-
- for {
- repos, err := repo_model.GetStarredRepos(ctx, opts)
- if err != nil {
- return err
- }
-
- if len(repos) == 0 {
- return nil
- }
-
- for _, repo := range repos {
- if err := repo_model.StarRepo(ctx, starrer, repo, false); err != nil {
- return err
- }
- }
-
- opts.Page++
- }
- }
-
- func unwatchRepos(ctx context.Context, watcher, repoOwner *user_model.User) error {
- opts := &repo_model.WatchedReposOptions{
- ListOptions: db.ListOptions{
- Page: 1,
- PageSize: 25,
- },
- WatcherID: watcher.ID,
- RepoOwnerID: repoOwner.ID,
- }
-
- for {
- repos, _, err := repo_model.GetWatchedRepos(ctx, opts)
- if err != nil {
- return err
- }
-
- if len(repos) == 0 {
- return nil
- }
-
- for _, repo := range repos {
- if err := repo_model.WatchRepo(ctx, watcher, repo, false); err != nil {
- return err
- }
- }
-
- opts.Page++
- }
- }
-
- func cancelRepositoryTransfers(ctx context.Context, doer, sender, recipient *user_model.User) error {
- transfers, err := repo_model.GetPendingRepositoryTransfers(ctx, &repo_model.PendingRepositoryTransferOptions{
- SenderID: sender.ID,
- RecipientID: recipient.ID,
- })
- if err != nil {
- return err
- }
-
- for _, transfer := range transfers {
- if err := repo_service.CancelRepositoryTransfer(ctx, transfer, doer); err != nil {
- return err
- }
- }
-
- return nil
- }
-
- func unassignIssues(ctx context.Context, assignee, repoOwner *user_model.User) error {
- opts := &issues_model.AssignedIssuesOptions{
- ListOptions: db.ListOptions{
- Page: 1,
- PageSize: 25,
- },
- AssigneeID: assignee.ID,
- RepoOwnerID: repoOwner.ID,
- }
-
- for {
- issues, _, err := issues_model.GetAssignedIssues(ctx, opts)
- if err != nil {
- return err
- }
-
- if len(issues) == 0 {
- return nil
- }
-
- for _, issue := range issues {
- if err := issue.LoadAssignees(ctx); err != nil {
- return err
- }
-
- if _, _, err := issues_model.ToggleIssueAssignee(ctx, issue, assignee, assignee.ID); err != nil {
- return err
- }
- }
-
- opts.Page++
- }
- }
-
- func removeCollaborations(ctx context.Context, repoOwner, collaborator *user_model.User) error {
- opts := &repo_model.FindCollaborationOptions{
- ListOptions: db.ListOptions{
- Page: 1,
- PageSize: 25,
- },
- CollaboratorID: collaborator.ID,
- RepoOwnerID: repoOwner.ID,
- }
-
- for {
- collaborations, _, err := repo_model.GetCollaborators(ctx, opts)
- if err != nil {
- return err
- }
-
- if len(collaborations) == 0 {
- return nil
- }
-
- for _, collaboration := range collaborations {
- repo, err := repo_model.GetRepositoryByID(ctx, collaboration.Collaboration.RepoID)
- if err != nil {
- return err
- }
-
- if err := repo_service.DeleteCollaboration(ctx, repo, collaborator); err != nil {
- return err
- }
- }
-
- opts.Page++
- }
- }
-
- func UnblockUser(ctx context.Context, doer, blocker, blockee *user_model.User) error {
- if blockee.IsOrganization() {
- return user_model.ErrBlockOrganization
- }
-
- if !CanUnblockUser(ctx, doer, blocker, blockee) {
- return user_model.ErrCanNotUnblock
- }
-
- return db.WithTx(ctx, func(ctx context.Context) error {
- block, err := user_model.GetBlocking(ctx, blocker.ID, blockee.ID)
- if err != nil {
- return err
- }
- if block != nil {
- _, err = db.DeleteByID[user_model.Blocking](ctx, block.ID)
- return err
- }
- return nil
- })
- }
|