summaryrefslogtreecommitdiffstats
path: root/routers/api/v1/user
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 /routers/api/v1/user
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 'routers/api/v1/user')
-rw-r--r--routers/api/v1/user/block.go96
-rw-r--r--routers/api/v1/user/follower.go11
-rw-r--r--routers/api/v1/user/star.go27
-rw-r--r--routers/api/v1/user/watch.go27
4 files changed, 141 insertions, 20 deletions
diff --git a/routers/api/v1/user/block.go b/routers/api/v1/user/block.go
new file mode 100644
index 0000000000..7231e9add7
--- /dev/null
+++ b/routers/api/v1/user/block.go
@@ -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)
+}
diff --git a/routers/api/v1/user/follower.go b/routers/api/v1/user/follower.go
index 398c6b2567..6abb70de19 100644
--- a/routers/api/v1/user/follower.go
+++ b/routers/api/v1/user/follower.go
@@ -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)
diff --git a/routers/api/v1/user/star.go b/routers/api/v1/user/star.go
index e624884db3..ad9ed9548d 100644
--- a/routers/api/v1/user/star.go
+++ b/routers/api/v1/user/star.go
@@ -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
diff --git a/routers/api/v1/user/watch.go b/routers/api/v1/user/watch.go
index 706f4cc66b..2cc23ae476 100644
--- a/routers/api/v1/user/watch.go
+++ b/routers/api/v1/user/watch.go
@@ -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