mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-10-30 22:11:07 +00:00
[MODERATION] add user blocking API
- Follow up for: #540, #802 - Add API routes for user blocking from user and organization perspective. - The new routes have integration testing. - The new model functions have unit tests. - Actually quite boring to write and to read this pull request. (cherry picked from commitf3afaf15c7) (cherry picked from commit6d754db3e5) (cherry picked from commitd0fc8bc9d3) (cherry picked from commit9a53b0d1a0) (cherry picked from commit44a2a4fd48) (cherry picked from commit182025db9c) (cherry picked from commit558a35963e)
This commit is contained in:
parent
cdf6318f51
commit
73776d6195
12 changed files with 626 additions and 9 deletions
|
|
@ -52,18 +52,29 @@ func UnblockUser(ctx context.Context, userID, blockID int64) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CountBlockedUsers returns the number of users the user has blocked.
|
||||||
|
func CountBlockedUsers(ctx context.Context, userID int64) (int64, error) {
|
||||||
|
return db.GetEngine(ctx).Where("user_id=?", userID).Count(&BlockedUser{})
|
||||||
|
}
|
||||||
|
|
||||||
// ListBlockedUsers returns the users that the user has blocked.
|
// ListBlockedUsers returns the users that the user has blocked.
|
||||||
// The created_unix field of the user struct is overridden by the creation_unix
|
// The created_unix field of the user struct is overridden by the creation_unix
|
||||||
// field of blockeduser.
|
// field of blockeduser.
|
||||||
func ListBlockedUsers(ctx context.Context, userID int64) ([]*User, error) {
|
func ListBlockedUsers(ctx context.Context, userID int64, opts db.ListOptions) ([]*User, error) {
|
||||||
users := make([]*User, 0, 8)
|
sess := db.GetEngine(ctx).
|
||||||
err := db.GetEngine(ctx).
|
|
||||||
Select("`forgejo_blocked_user`.created_unix, `user`.*").
|
Select("`forgejo_blocked_user`.created_unix, `user`.*").
|
||||||
Join("INNER", "forgejo_blocked_user", "`user`.id=`forgejo_blocked_user`.block_id").
|
Join("INNER", "forgejo_blocked_user", "`user`.id=`forgejo_blocked_user`.block_id").
|
||||||
Where("`forgejo_blocked_user`.user_id=?", userID).
|
Where("`forgejo_blocked_user`.user_id=?", userID)
|
||||||
Find(&users)
|
|
||||||
|
|
||||||
return users, err
|
if opts.Page > 0 {
|
||||||
|
sess = db.SetSessionPagination(sess, &opts)
|
||||||
|
users := make([]*User, 0, opts.PageSize)
|
||||||
|
|
||||||
|
return users, sess.Find(&users)
|
||||||
|
}
|
||||||
|
|
||||||
|
users := make([]*User, 0, 8)
|
||||||
|
return users, sess.Find(&users)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListBlockedByUsersID returns the ids of the users that blocked the user.
|
// ListBlockedByUsersID returns the ids of the users that blocked the user.
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ func TestUnblockUser(t *testing.T) {
|
||||||
func TestListBlockedUsers(t *testing.T) {
|
func TestListBlockedUsers(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
blockedUsers, err := user_model.ListBlockedUsers(db.DefaultContext, 4)
|
blockedUsers, err := user_model.ListBlockedUsers(db.DefaultContext, 4, db.ListOptions{})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
if assert.Len(t, blockedUsers, 1) {
|
if assert.Len(t, blockedUsers, 1) {
|
||||||
assert.EqualValues(t, 1, blockedUsers[0].ID)
|
assert.EqualValues(t, 1, blockedUsers[0].ID)
|
||||||
|
|
@ -61,3 +61,15 @@ func TestListBlockedByUsersID(t *testing.T) {
|
||||||
assert.EqualValues(t, 4, blockedByUserIDs[0])
|
assert.EqualValues(t, 4, blockedByUserIDs[0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCountBlockedUsers(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
count, err := user_model.CountBlockedUsers(db.DefaultContext, 4)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.EqualValues(t, 1, count)
|
||||||
|
|
||||||
|
count, err = user_model.CountBlockedUsers(db.DefaultContext, 1)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.EqualValues(t, 0, count)
|
||||||
|
}
|
||||||
|
|
|
||||||
13
modules/structs/moderation.go
Normal file
13
modules/structs/moderation.go
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
// Copyright 2023 The Forgejo Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package structs
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// BlockedUser represents a blocked user.
|
||||||
|
type BlockedUser struct {
|
||||||
|
BlockID int64 `json:"block_id"`
|
||||||
|
// swagger:strfmt date-time
|
||||||
|
Created time.Time `json:"created_at"`
|
||||||
|
}
|
||||||
|
|
@ -905,6 +905,12 @@ func Routes(ctx gocontext.Context) *web.Route {
|
||||||
Patch(bind(api.EditHookOption{}), user.EditHook).
|
Patch(bind(api.EditHookOption{}), user.EditHook).
|
||||||
Delete(user.DeleteHook)
|
Delete(user.DeleteHook)
|
||||||
}, reqWebhooksEnabled())
|
}, reqWebhooksEnabled())
|
||||||
|
|
||||||
|
m.Group("", func() {
|
||||||
|
m.Get("/list_blocked", user.ListBlockedUsers)
|
||||||
|
m.Put("/block/{username}", user.BlockUser)
|
||||||
|
m.Put("/unblock/{username}", user.UnblockUser)
|
||||||
|
})
|
||||||
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryUser), reqToken())
|
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryUser), reqToken())
|
||||||
|
|
||||||
// Repositories (requires repo scope, org scope)
|
// Repositories (requires repo scope, org scope)
|
||||||
|
|
@ -1321,6 +1327,12 @@ func Routes(ctx gocontext.Context) *web.Route {
|
||||||
Delete(org.DeleteHook)
|
Delete(org.DeleteHook)
|
||||||
}, reqToken(), reqOrgOwnership(), reqWebhooksEnabled())
|
}, reqToken(), reqOrgOwnership(), reqWebhooksEnabled())
|
||||||
m.Get("/activities/feeds", org.ListOrgActivityFeeds)
|
m.Get("/activities/feeds", org.ListOrgActivityFeeds)
|
||||||
|
|
||||||
|
m.Group("", func() {
|
||||||
|
m.Get("/list_blocked", reqToken(), reqOrgOwnership(), org.ListBlockedUsers)
|
||||||
|
m.Put("/block/{username}", reqToken(), reqOrgOwnership(), org.BlockUser)
|
||||||
|
m.Put("/unblock/{username}", reqToken(), reqOrgOwnership(), org.UnblockUser)
|
||||||
|
}, reqToken(), reqOrgOwnership())
|
||||||
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryOrganization), orgAssignment(true))
|
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryOrganization), orgAssignment(true))
|
||||||
m.Group("/teams/{teamid}", func() {
|
m.Group("/teams/{teamid}", func() {
|
||||||
m.Combo("").Get(reqToken(), org.GetTeam).
|
m.Combo("").Get(reqToken(), org.GetTeam).
|
||||||
|
|
|
||||||
|
|
@ -437,3 +437,95 @@ func ListOrgActivityFeeds(ctx *context.APIContext) {
|
||||||
|
|
||||||
ctx.JSON(http.StatusOK, convert.ToActivities(ctx, feeds, ctx.Doer))
|
ctx.JSON(http.StatusOK, convert.ToActivities(ctx, feeds, ctx.Doer))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListBlockedUsers list the organization's blocked users.
|
||||||
|
func ListBlockedUsers(ctx *context.APIContext) {
|
||||||
|
// swagger:operation GET /orgs/{org}/list_blocked organization orgListBlockedUsers
|
||||||
|
// ---
|
||||||
|
// summary: List the organization's blocked users
|
||||||
|
// produces:
|
||||||
|
// - application/json
|
||||||
|
// parameters:
|
||||||
|
// - name: org
|
||||||
|
// in: path
|
||||||
|
// description: name of the org
|
||||||
|
// type: string
|
||||||
|
// required: true
|
||||||
|
// - 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
|
||||||
|
// responses:
|
||||||
|
// "200":
|
||||||
|
// "$ref": "#/responses/BlockedUserList"
|
||||||
|
|
||||||
|
utils.ListUserBlockedUsers(ctx, ctx.ContextUser)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlockUser blocks a user from the organization.
|
||||||
|
func BlockUser(ctx *context.APIContext) {
|
||||||
|
// swagger:operation PUT /orgs/{org}/block/{username} organization orgBlockUser
|
||||||
|
// ---
|
||||||
|
// summary: Blocks a user from the organization
|
||||||
|
// produces:
|
||||||
|
// - application/json
|
||||||
|
// parameters:
|
||||||
|
// - name: org
|
||||||
|
// in: path
|
||||||
|
// description: name of the org
|
||||||
|
// type: string
|
||||||
|
// required: true
|
||||||
|
// - name: username
|
||||||
|
// in: path
|
||||||
|
// description: username of the user
|
||||||
|
// type: string
|
||||||
|
// required: true
|
||||||
|
// responses:
|
||||||
|
// "204":
|
||||||
|
// "$ref": "#/responses/empty"
|
||||||
|
// "404":
|
||||||
|
// "$ref": "#/responses/notFound"
|
||||||
|
|
||||||
|
user := user.GetUserByParams(ctx)
|
||||||
|
if ctx.Written() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
utils.BlockUser(ctx, ctx.Org.Organization.AsUser(), user)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnblockUser unblocks a user from the organization.
|
||||||
|
func UnblockUser(ctx *context.APIContext) {
|
||||||
|
// swagger:operation PUT /orgs/{org}/unblock/{username} organization orgUnblockUser
|
||||||
|
// ---
|
||||||
|
// summary: Unblock a user from the organization
|
||||||
|
// produces:
|
||||||
|
// - application/json
|
||||||
|
// parameters:
|
||||||
|
// - name: org
|
||||||
|
// in: path
|
||||||
|
// description: name of the org
|
||||||
|
// type: string
|
||||||
|
// required: true
|
||||||
|
// - name: username
|
||||||
|
// in: path
|
||||||
|
// description: username of the user
|
||||||
|
// type: string
|
||||||
|
// required: true
|
||||||
|
// responses:
|
||||||
|
// "204":
|
||||||
|
// "$ref": "#/responses/empty"
|
||||||
|
// "404":
|
||||||
|
// "$ref": "#/responses/notFound"
|
||||||
|
|
||||||
|
user := user.GetUserByParams(ctx)
|
||||||
|
if ctx.Written() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
utils.UnblockUser(ctx, ctx.Org.Organization.AsUser(), user)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -414,3 +414,10 @@ type swaggerRepoNewIssuePinsAllowed struct {
|
||||||
// in:body
|
// in:body
|
||||||
Body api.NewIssuePinsAllowed `json:"body"`
|
Body api.NewIssuePinsAllowed `json:"body"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BlockedUserList
|
||||||
|
// swagger:response BlockedUserList
|
||||||
|
type swaggerBlockedUserList struct {
|
||||||
|
// in:body
|
||||||
|
Body []api.BlockedUser `json:"body"`
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -202,3 +202,80 @@ func ListUserActivityFeeds(ctx *context.APIContext) {
|
||||||
|
|
||||||
ctx.JSON(http.StatusOK, convert.ToActivities(ctx, feeds, ctx.Doer))
|
ctx.JSON(http.StatusOK, convert.ToActivities(ctx, feeds, ctx.Doer))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListBlockedUsers list the authenticated user's blocked users.
|
||||||
|
func ListBlockedUsers(ctx *context.APIContext) {
|
||||||
|
// swagger:operation GET /user/list_blocked user userListBlockedUsers
|
||||||
|
// ---
|
||||||
|
// summary: List the authenticated user's blocked users
|
||||||
|
// produces:
|
||||||
|
// - application/json
|
||||||
|
// 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
|
||||||
|
// responses:
|
||||||
|
// "200":
|
||||||
|
// "$ref": "#/responses/BlockedUserList"
|
||||||
|
|
||||||
|
utils.ListUserBlockedUsers(ctx, ctx.Doer)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlockUser blocks a user from the doer.
|
||||||
|
func BlockUser(ctx *context.APIContext) {
|
||||||
|
// swagger:operation PUT /user/block/{username} user userBlockUser
|
||||||
|
// ---
|
||||||
|
// summary: Blocks a user from the doer.
|
||||||
|
// produces:
|
||||||
|
// - application/json
|
||||||
|
// parameters:
|
||||||
|
// - name: username
|
||||||
|
// in: path
|
||||||
|
// description: username of the user
|
||||||
|
// type: string
|
||||||
|
// required: true
|
||||||
|
// responses:
|
||||||
|
// "204":
|
||||||
|
// "$ref": "#/responses/empty"
|
||||||
|
// "404":
|
||||||
|
// "$ref": "#/responses/notFound"
|
||||||
|
|
||||||
|
user := GetUserByParams(ctx)
|
||||||
|
if ctx.Written() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
utils.BlockUser(ctx, ctx.Doer, user)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnblockUser unblocks a user from the doer.
|
||||||
|
func UnblockUser(ctx *context.APIContext) {
|
||||||
|
// swagger:operation PUT /user/unblock/{username} user userUnblockUser
|
||||||
|
// ---
|
||||||
|
// summary: Unblocks a user from the doer.
|
||||||
|
// produces:
|
||||||
|
// - application/json
|
||||||
|
// parameters:
|
||||||
|
// - name: username
|
||||||
|
// in: path
|
||||||
|
// description: username of the user
|
||||||
|
// type: string
|
||||||
|
// required: true
|
||||||
|
// responses:
|
||||||
|
// "204":
|
||||||
|
// "$ref": "#/responses/empty"
|
||||||
|
// "404":
|
||||||
|
// "$ref": "#/responses/notFound"
|
||||||
|
|
||||||
|
user := GetUserByParams(ctx)
|
||||||
|
if ctx.Written() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
utils.UnblockUser(ctx, ctx.Doer, user)
|
||||||
|
}
|
||||||
|
|
|
||||||
65
routers/api/v1/utils/block.go
Normal file
65
routers/api/v1/utils/block.go
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
// Copyright 2023 The Forgejo Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
"code.gitea.io/gitea/modules/context"
|
||||||
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
|
user_service "code.gitea.io/gitea/services/user"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListUserBlockedUsers lists the blocked users of the provided doer.
|
||||||
|
func ListUserBlockedUsers(ctx *context.APIContext, doer *user_model.User) {
|
||||||
|
count, err := user_model.CountBlockedUsers(ctx, doer.ID)
|
||||||
|
if err != nil {
|
||||||
|
ctx.InternalServerError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
blockedUsers, err := user_model.ListBlockedUsers(ctx, doer.ID, GetListOptions(ctx))
|
||||||
|
if err != nil {
|
||||||
|
ctx.InternalServerError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
apiBlockedUsers := make([]*api.BlockedUser, len(blockedUsers))
|
||||||
|
for i, blockedUser := range blockedUsers {
|
||||||
|
apiBlockedUsers[i] = &api.BlockedUser{
|
||||||
|
BlockID: blockedUser.ID,
|
||||||
|
Created: blockedUser.CreatedUnix.AsTime(),
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
ctx.InternalServerError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.SetTotalCountHeader(count)
|
||||||
|
ctx.JSON(http.StatusOK, apiBlockedUsers)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlockUser blocks the blockUser from the doer.
|
||||||
|
func BlockUser(ctx *context.APIContext, doer, blockUser *user_model.User) {
|
||||||
|
err := user_service.BlockUser(ctx, doer.ID, blockUser.ID)
|
||||||
|
if err != nil {
|
||||||
|
ctx.InternalServerError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Status(http.StatusNoContent)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnblockUser unblocks the blockUser from the doer.
|
||||||
|
func UnblockUser(ctx *context.APIContext, doer, blockUser *user_model.User) {
|
||||||
|
err := user_model.UnblockUser(ctx, doer.ID, blockUser.ID)
|
||||||
|
if err != nil {
|
||||||
|
ctx.InternalServerError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Status(http.StatusNoContent)
|
||||||
|
}
|
||||||
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/routers/utils"
|
"code.gitea.io/gitea/routers/utils"
|
||||||
|
|
@ -20,7 +21,7 @@ func BlockedUsers(ctx *context.Context) {
|
||||||
ctx.Data["Title"] = ctx.Tr("settings.blocked_users")
|
ctx.Data["Title"] = ctx.Tr("settings.blocked_users")
|
||||||
ctx.Data["PageIsSettingsBlockedUsers"] = true
|
ctx.Data["PageIsSettingsBlockedUsers"] = true
|
||||||
|
|
||||||
blockedUsers, err := user_model.ListBlockedUsers(ctx, ctx.Org.Organization.ID)
|
blockedUsers, err := user_model.ListBlockedUsers(ctx, ctx.Org.Organization.ID, db.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("ListBlockedUsers", err)
|
ctx.ServerError("ListBlockedUsers", err)
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ package setting
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/base"
|
"code.gitea.io/gitea/modules/base"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
|
|
@ -23,7 +24,7 @@ func BlockedUsers(ctx *context.Context) {
|
||||||
ctx.Data["BaseLink"] = setting.AppSubURL + "/user/settings/blocked_users"
|
ctx.Data["BaseLink"] = setting.AppSubURL + "/user/settings/blocked_users"
|
||||||
ctx.Data["BaseLinkNew"] = setting.AppSubURL + "/user/settings/blocked_users"
|
ctx.Data["BaseLinkNew"] = setting.AppSubURL + "/user/settings/blocked_users"
|
||||||
|
|
||||||
blockedUsers, err := user_model.ListBlockedUsers(ctx, ctx.Doer.ID)
|
blockedUsers, err := user_model.ListBlockedUsers(ctx, ctx.Doer.ID, db.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("ListBlockedUsers", err)
|
ctx.ServerError("ListBlockedUsers", err)
|
||||||
return
|
return
|
||||||
|
|
|
||||||
225
templates/swagger/v1_json.tmpl
generated
225
templates/swagger/v1_json.tmpl
generated
|
|
@ -1595,6 +1595,42 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/orgs/{org}/block/{username}": {
|
||||||
|
"put": {
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"organization"
|
||||||
|
],
|
||||||
|
"summary": "Blocks a user from the organization",
|
||||||
|
"operationId": "orgBlockUser",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "name of the org",
|
||||||
|
"name": "org",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "username of the user",
|
||||||
|
"name": "username",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"204": {
|
||||||
|
"$ref": "#/responses/empty"
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"$ref": "#/responses/notFound"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/orgs/{org}/hooks": {
|
"/orgs/{org}/hooks": {
|
||||||
"get": {
|
"get": {
|
||||||
"produces": [
|
"produces": [
|
||||||
|
|
@ -1959,6 +1995,44 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/orgs/{org}/list_blocked": {
|
||||||
|
"get": {
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"organization"
|
||||||
|
],
|
||||||
|
"summary": "List the organization's blocked users",
|
||||||
|
"operationId": "orgListBlockedUsers",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "name of the org",
|
||||||
|
"name": "org",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"description": "page number of results to return (1-based)",
|
||||||
|
"name": "page",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"description": "page size of results",
|
||||||
|
"name": "limit",
|
||||||
|
"in": "query"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"$ref": "#/responses/BlockedUserList"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/orgs/{org}/members": {
|
"/orgs/{org}/members": {
|
||||||
"get": {
|
"get": {
|
||||||
"produces": [
|
"produces": [
|
||||||
|
|
@ -2423,6 +2497,42 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/orgs/{org}/unblock/{username}": {
|
||||||
|
"put": {
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"organization"
|
||||||
|
],
|
||||||
|
"summary": "Unblock a user from the organization",
|
||||||
|
"operationId": "orgUnblockUser",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "name of the org",
|
||||||
|
"name": "org",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "username of the user",
|
||||||
|
"name": "username",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"204": {
|
||||||
|
"$ref": "#/responses/empty"
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"$ref": "#/responses/notFound"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/packages/{owner}": {
|
"/packages/{owner}": {
|
||||||
"get": {
|
"get": {
|
||||||
"produces": [
|
"produces": [
|
||||||
|
|
@ -13790,6 +13900,35 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/user/block/{username}": {
|
||||||
|
"put": {
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"user"
|
||||||
|
],
|
||||||
|
"summary": "Blocks a user from the doer.",
|
||||||
|
"operationId": "userBlockUser",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "username of the user",
|
||||||
|
"name": "username",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"204": {
|
||||||
|
"$ref": "#/responses/empty"
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"$ref": "#/responses/notFound"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/user/emails": {
|
"/user/emails": {
|
||||||
"get": {
|
"get": {
|
||||||
"produces": [
|
"produces": [
|
||||||
|
|
@ -14439,6 +14578,37 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/user/list_blocked": {
|
||||||
|
"get": {
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"user"
|
||||||
|
],
|
||||||
|
"summary": "List the authenticated user's blocked users",
|
||||||
|
"operationId": "userListBlockedUsers",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"description": "page number of results to return (1-based)",
|
||||||
|
"name": "page",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"description": "page size of results",
|
||||||
|
"name": "limit",
|
||||||
|
"in": "query"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"$ref": "#/responses/BlockedUserList"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/user/orgs": {
|
"/user/orgs": {
|
||||||
"get": {
|
"get": {
|
||||||
"produces": [
|
"produces": [
|
||||||
|
|
@ -14840,6 +15010,35 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/user/unblock/{username}": {
|
||||||
|
"put": {
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"user"
|
||||||
|
],
|
||||||
|
"summary": "Unblocks a user from the doer.",
|
||||||
|
"operationId": "userUnblockUser",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "username of the user",
|
||||||
|
"name": "username",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"204": {
|
||||||
|
"$ref": "#/responses/empty"
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"$ref": "#/responses/notFound"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/users/search": {
|
"/users/search": {
|
||||||
"get": {
|
"get": {
|
||||||
"produces": [
|
"produces": [
|
||||||
|
|
@ -15770,6 +15969,23 @@
|
||||||
},
|
},
|
||||||
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
||||||
},
|
},
|
||||||
|
"BlockedUser": {
|
||||||
|
"type": "object",
|
||||||
|
"title": "BlockedUser represents a blocked user.",
|
||||||
|
"properties": {
|
||||||
|
"block_id": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64",
|
||||||
|
"x-go-name": "BlockID"
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date-time",
|
||||||
|
"x-go-name": "Created"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
||||||
|
},
|
||||||
"Branch": {
|
"Branch": {
|
||||||
"description": "Branch represents a repository branch",
|
"description": "Branch represents a repository branch",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
|
@ -21953,6 +22169,15 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"BlockedUserList": {
|
||||||
|
"description": "BlockedUserList",
|
||||||
|
"schema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/BlockedUser"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Branch": {
|
"Branch": {
|
||||||
"description": "Branch",
|
"description": "Branch",
|
||||||
"schema": {
|
"schema": {
|
||||||
|
|
|
||||||
101
tests/integration/api_block_test.go
Normal file
101
tests/integration/api_block_test.go
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
// Copyright 2023 The Forgejo Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package integration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
auth_model "code.gitea.io/gitea/models/auth"
|
||||||
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
|
"code.gitea.io/gitea/tests"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAPIUserBlock(t *testing.T) {
|
||||||
|
defer tests.PrepareTestEnv(t)()
|
||||||
|
|
||||||
|
user := "user4"
|
||||||
|
session := loginUser(t, user)
|
||||||
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteUser)
|
||||||
|
|
||||||
|
t.Run("BlockUser", func(t *testing.T) {
|
||||||
|
defer tests.PrintCurrentTest(t)()
|
||||||
|
|
||||||
|
req := NewRequest(t, "PUT", fmt.Sprintf("/api/v1/user/block/user2?token=%s", token))
|
||||||
|
MakeRequest(t, req, http.StatusNoContent)
|
||||||
|
|
||||||
|
unittest.AssertExistsAndLoadBean(t, &user_model.BlockedUser{UserID: 4, BlockID: 2})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("ListBlocked", func(t *testing.T) {
|
||||||
|
defer tests.PrintCurrentTest(t)()
|
||||||
|
|
||||||
|
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/user/list_blocked?token=%s", token))
|
||||||
|
resp := MakeRequest(t, req, http.StatusOK)
|
||||||
|
|
||||||
|
// One user just got blocked and the other one is defined in the fixtures.
|
||||||
|
assert.Equal(t, "2", resp.Header().Get("X-Total-Count"))
|
||||||
|
|
||||||
|
var blockedUsers []api.BlockedUser
|
||||||
|
DecodeJSON(t, resp, &blockedUsers)
|
||||||
|
assert.Len(t, blockedUsers, 2)
|
||||||
|
assert.EqualValues(t, 1, blockedUsers[0].BlockID)
|
||||||
|
assert.EqualValues(t, 2, blockedUsers[1].BlockID)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("UnblockUser", func(t *testing.T) {
|
||||||
|
defer tests.PrintCurrentTest(t)()
|
||||||
|
|
||||||
|
req := NewRequest(t, "PUT", fmt.Sprintf("/api/v1/user/unblock/user2?token=%s", token))
|
||||||
|
MakeRequest(t, req, http.StatusNoContent)
|
||||||
|
|
||||||
|
unittest.AssertNotExistsBean(t, &user_model.BlockedUser{UserID: 4, BlockID: 2})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAPIOrgBlock(t *testing.T) {
|
||||||
|
defer tests.PrepareTestEnv(t)()
|
||||||
|
|
||||||
|
user := "user5"
|
||||||
|
org := "user6"
|
||||||
|
session := loginUser(t, user)
|
||||||
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteOrganization)
|
||||||
|
|
||||||
|
t.Run("BlockUser", func(t *testing.T) {
|
||||||
|
defer tests.PrintCurrentTest(t)()
|
||||||
|
|
||||||
|
req := NewRequest(t, "PUT", fmt.Sprintf("/api/v1/orgs/%s/block/user2?token=%s", org, token))
|
||||||
|
MakeRequest(t, req, http.StatusNoContent)
|
||||||
|
|
||||||
|
unittest.AssertExistsAndLoadBean(t, &user_model.BlockedUser{UserID: 6, BlockID: 2})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("ListBlocked", func(t *testing.T) {
|
||||||
|
defer tests.PrintCurrentTest(t)()
|
||||||
|
|
||||||
|
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/orgs/%s/list_blocked?token=%s", org, token))
|
||||||
|
resp := MakeRequest(t, req, http.StatusOK)
|
||||||
|
|
||||||
|
assert.Equal(t, "1", resp.Header().Get("X-Total-Count"))
|
||||||
|
|
||||||
|
var blockedUsers []api.BlockedUser
|
||||||
|
DecodeJSON(t, resp, &blockedUsers)
|
||||||
|
assert.Len(t, blockedUsers, 1)
|
||||||
|
assert.EqualValues(t, 2, blockedUsers[0].BlockID)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("UnblockUser", func(t *testing.T) {
|
||||||
|
defer tests.PrintCurrentTest(t)()
|
||||||
|
|
||||||
|
req := NewRequest(t, "PUT", fmt.Sprintf("/api/v1/orgs/%s/unblock/user2?token=%s", org, token))
|
||||||
|
MakeRequest(t, req, http.StatusNoContent)
|
||||||
|
|
||||||
|
unittest.AssertNotExistsBean(t, &user_model.BlockedUser{UserID: 6, BlockID: 2})
|
||||||
|
})
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue