mirror of
https://github.com/go-gitea/gitea
synced 2025-07-23 02:38:35 +00:00
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:    --------- Co-authored-by: Lauris BH <lauris@nix.lv>
This commit is contained in:
96
routers/api/v1/user/block.go
Normal file
96
routers/api/v1/user/block.go
Normal file
@@ -0,0 +1,96 @@
|
||||
// Copyright 2024 The Gitea Authors.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package user
|
||||
|
||||
import (
|
||||
"code.gitea.io/gitea/routers/api/v1/shared"
|
||||
"code.gitea.io/gitea/services/context"
|
||||
)
|
||||
|
||||
func ListBlocks(ctx *context.APIContext) {
|
||||
// swagger:operation GET /user/blocks user userListBlocks
|
||||
// ---
|
||||
// summary: List users blocked by the authenticated user
|
||||
// parameters:
|
||||
// - name: page
|
||||
// in: query
|
||||
// description: page number of results to return (1-based)
|
||||
// type: integer
|
||||
// - name: limit
|
||||
// in: query
|
||||
// description: page size of results
|
||||
// type: integer
|
||||
// produces:
|
||||
// - application/json
|
||||
// responses:
|
||||
// "200":
|
||||
// "$ref": "#/responses/UserList"
|
||||
|
||||
shared.ListBlocks(ctx, ctx.Doer)
|
||||
}
|
||||
|
||||
func CheckUserBlock(ctx *context.APIContext) {
|
||||
// swagger:operation GET /user/blocks/{username} user userCheckUserBlock
|
||||
// ---
|
||||
// summary: Check if a user is blocked by the authenticated user
|
||||
// parameters:
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: user to check
|
||||
// type: string
|
||||
// required: true
|
||||
// responses:
|
||||
// "204":
|
||||
// "$ref": "#/responses/empty"
|
||||
// "404":
|
||||
// "$ref": "#/responses/notFound"
|
||||
|
||||
shared.CheckUserBlock(ctx, ctx.Doer)
|
||||
}
|
||||
|
||||
func BlockUser(ctx *context.APIContext) {
|
||||
// swagger:operation PUT /user/blocks/{username} user userBlockUser
|
||||
// ---
|
||||
// summary: Block a user
|
||||
// parameters:
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: user to block
|
||||
// type: string
|
||||
// required: true
|
||||
// - name: note
|
||||
// in: query
|
||||
// description: optional note for the block
|
||||
// type: string
|
||||
// responses:
|
||||
// "204":
|
||||
// "$ref": "#/responses/empty"
|
||||
// "404":
|
||||
// "$ref": "#/responses/notFound"
|
||||
// "422":
|
||||
// "$ref": "#/responses/validationError"
|
||||
|
||||
shared.BlockUser(ctx, ctx.Doer)
|
||||
}
|
||||
|
||||
func UnblockUser(ctx *context.APIContext) {
|
||||
// swagger:operation DELETE /user/blocks/{username} user userUnblockUser
|
||||
// ---
|
||||
// summary: Unblock a user
|
||||
// parameters:
|
||||
// - name: username
|
||||
// in: path
|
||||
// description: user to unblock
|
||||
// type: string
|
||||
// required: true
|
||||
// responses:
|
||||
// "204":
|
||||
// "$ref": "#/responses/empty"
|
||||
// "404":
|
||||
// "$ref": "#/responses/notFound"
|
||||
// "422":
|
||||
// "$ref": "#/responses/validationError"
|
||||
|
||||
shared.UnblockUser(ctx, ctx.Doer, ctx.Doer)
|
||||
}
|
@@ -5,6 +5,7 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
@@ -221,11 +222,17 @@ func Follow(ctx *context.APIContext) {
|
||||
// responses:
|
||||
// "204":
|
||||
// "$ref": "#/responses/empty"
|
||||
// "403":
|
||||
// "$ref": "#/responses/forbidden"
|
||||
// "404":
|
||||
// "$ref": "#/responses/notFound"
|
||||
|
||||
if err := user_model.FollowUser(ctx, ctx.Doer.ID, ctx.ContextUser.ID); err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "FollowUser", err)
|
||||
if err := user_model.FollowUser(ctx, ctx.Doer, ctx.ContextUser); err != nil {
|
||||
if errors.Is(err, user_model.ErrBlockedUser) {
|
||||
ctx.Error(http.StatusForbidden, "FollowUser", err)
|
||||
} else {
|
||||
ctx.Error(http.StatusInternalServerError, "FollowUser", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
ctx.Status(http.StatusNoContent)
|
||||
|
@@ -5,10 +5,9 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
std_context "context"
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
access_model "code.gitea.io/gitea/models/perm/access"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
@@ -20,8 +19,12 @@ import (
|
||||
|
||||
// getStarredRepos returns the repos that the user with the specified userID has
|
||||
// starred
|
||||
func getStarredRepos(ctx std_context.Context, user *user_model.User, private bool, listOptions db.ListOptions) ([]*api.Repository, error) {
|
||||
starredRepos, err := repo_model.GetStarredRepos(ctx, user.ID, private, listOptions)
|
||||
func getStarredRepos(ctx *context.APIContext, user *user_model.User, private bool) ([]*api.Repository, error) {
|
||||
starredRepos, err := repo_model.GetStarredRepos(ctx, &repo_model.StarredReposOptions{
|
||||
ListOptions: utils.GetListOptions(ctx),
|
||||
StarrerID: user.ID,
|
||||
IncludePrivate: private,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -65,7 +68,7 @@ func GetStarredRepos(ctx *context.APIContext) {
|
||||
// "$ref": "#/responses/notFound"
|
||||
|
||||
private := ctx.ContextUser.ID == ctx.Doer.ID
|
||||
repos, err := getStarredRepos(ctx, ctx.ContextUser, private, utils.GetListOptions(ctx))
|
||||
repos, err := getStarredRepos(ctx, ctx.ContextUser, private)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "getStarredRepos", err)
|
||||
return
|
||||
@@ -95,7 +98,7 @@ func GetMyStarredRepos(ctx *context.APIContext) {
|
||||
// "200":
|
||||
// "$ref": "#/responses/RepositoryList"
|
||||
|
||||
repos, err := getStarredRepos(ctx, ctx.Doer, true, utils.GetListOptions(ctx))
|
||||
repos, err := getStarredRepos(ctx, ctx.Doer, true)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "getStarredRepos", err)
|
||||
}
|
||||
@@ -152,12 +155,18 @@ func Star(ctx *context.APIContext) {
|
||||
// responses:
|
||||
// "204":
|
||||
// "$ref": "#/responses/empty"
|
||||
// "403":
|
||||
// "$ref": "#/responses/forbidden"
|
||||
// "404":
|
||||
// "$ref": "#/responses/notFound"
|
||||
|
||||
err := repo_model.StarRepo(ctx, ctx.Doer.ID, ctx.Repo.Repository.ID, true)
|
||||
err := repo_model.StarRepo(ctx, ctx.Doer, ctx.Repo.Repository, true)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "StarRepo", err)
|
||||
if errors.Is(err, user_model.ErrBlockedUser) {
|
||||
ctx.Error(http.StatusForbidden, "BlockedUser", err)
|
||||
} else {
|
||||
ctx.Error(http.StatusInternalServerError, "StarRepo", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
ctx.Status(http.StatusNoContent)
|
||||
@@ -185,7 +194,7 @@ func Unstar(ctx *context.APIContext) {
|
||||
// "404":
|
||||
// "$ref": "#/responses/notFound"
|
||||
|
||||
err := repo_model.StarRepo(ctx, ctx.Doer.ID, ctx.Repo.Repository.ID, false)
|
||||
err := repo_model.StarRepo(ctx, ctx.Doer, ctx.Repo.Repository, false)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "StarRepo", err)
|
||||
return
|
||||
|
@@ -4,10 +4,9 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
std_context "context"
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
access_model "code.gitea.io/gitea/models/perm/access"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
@@ -18,8 +17,12 @@ import (
|
||||
)
|
||||
|
||||
// getWatchedRepos returns the repos that the user with the specified userID is watching
|
||||
func getWatchedRepos(ctx std_context.Context, user *user_model.User, private bool, listOptions db.ListOptions) ([]*api.Repository, int64, error) {
|
||||
watchedRepos, total, err := repo_model.GetWatchedRepos(ctx, user.ID, private, listOptions)
|
||||
func getWatchedRepos(ctx *context.APIContext, user *user_model.User, private bool) ([]*api.Repository, int64, error) {
|
||||
watchedRepos, total, err := repo_model.GetWatchedRepos(ctx, &repo_model.WatchedReposOptions{
|
||||
ListOptions: utils.GetListOptions(ctx),
|
||||
WatcherID: user.ID,
|
||||
IncludePrivate: private,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
@@ -63,7 +66,7 @@ func GetWatchedRepos(ctx *context.APIContext) {
|
||||
// "$ref": "#/responses/notFound"
|
||||
|
||||
private := ctx.ContextUser.ID == ctx.Doer.ID
|
||||
repos, total, err := getWatchedRepos(ctx, ctx.ContextUser, private, utils.GetListOptions(ctx))
|
||||
repos, total, err := getWatchedRepos(ctx, ctx.ContextUser, private)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "getWatchedRepos", err)
|
||||
}
|
||||
@@ -92,7 +95,7 @@ func GetMyWatchedRepos(ctx *context.APIContext) {
|
||||
// "200":
|
||||
// "$ref": "#/responses/RepositoryList"
|
||||
|
||||
repos, total, err := getWatchedRepos(ctx, ctx.Doer, true, utils.GetListOptions(ctx))
|
||||
repos, total, err := getWatchedRepos(ctx, ctx.Doer, true)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "getWatchedRepos", err)
|
||||
}
|
||||
@@ -157,12 +160,18 @@ func Watch(ctx *context.APIContext) {
|
||||
// responses:
|
||||
// "200":
|
||||
// "$ref": "#/responses/WatchInfo"
|
||||
// "403":
|
||||
// "$ref": "#/responses/forbidden"
|
||||
// "404":
|
||||
// "$ref": "#/responses/notFound"
|
||||
|
||||
err := repo_model.WatchRepo(ctx, ctx.Doer.ID, ctx.Repo.Repository.ID, true)
|
||||
err := repo_model.WatchRepo(ctx, ctx.Doer, ctx.Repo.Repository, true)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "WatchRepo", err)
|
||||
if errors.Is(err, user_model.ErrBlockedUser) {
|
||||
ctx.Error(http.StatusForbidden, "BlockedUser", err)
|
||||
} else {
|
||||
ctx.Error(http.StatusInternalServerError, "WatchRepo", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
ctx.JSON(http.StatusOK, api.WatchInfo{
|
||||
@@ -197,7 +206,7 @@ func Unwatch(ctx *context.APIContext) {
|
||||
// "404":
|
||||
// "$ref": "#/responses/notFound"
|
||||
|
||||
err := repo_model.WatchRepo(ctx, ctx.Doer.ID, ctx.Repo.Repository.ID, false)
|
||||
err := repo_model.WatchRepo(ctx, ctx.Doer, ctx.Repo.Repository, false)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "UnwatchRepo", err)
|
||||
return
|
||||
|
Reference in New Issue
Block a user