forked from NYANDEV/forgejo
cdf6318f51
- Resolves #476 - Follow up for: #540 - Ensure that the doer and blocked person cannot follow each other. - Ensure that the block person cannot watch doer's repositories. - Add unblock button to the blocked user list. - Add blocked since information to the blocked user list. - Add extra testing to moderation code. - Blocked user will unwatch doer's owned repository upon blocking. - Add flash messages to let the user know the block/unblock action was successful. - Add "You haven't blocked any users" message. - Add organization blocking a user. Co-authored-by: Gusted <postmaster@gusted.xyz> Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/802 (cherry picked from commit 0505a1042197bd9136b58bc70ec7400a23471585) (cherry picked from commit 37b4e6ef9b85e97d651cf350c9f3ea272ee8d76a) (cherry picked from commit 217475385a815298dcbd8029e0cc8cb2c5877bae) (cherry picked from commit f2c38ce5c2f6cf4008aa1929539063715b50562c) (cherry picked from commit 1edfb68137d8c322a7a9a7c7196fc8f01ff1a889) (cherry picked from commit 2cbc12dc740e6fefc196b7fea6ac8a0ffbbfbeef) (cherry picked from commit 79ff020f182327986dcfd874bc49d4fe32efc29a)
212 lines
7.7 KiB
Go
212 lines
7.7 KiB
Go
// Copyright 2023 The Forgejo Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package integration
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
"path"
|
|
"strconv"
|
|
"testing"
|
|
|
|
"code.gitea.io/gitea/models/db"
|
|
issue_model "code.gitea.io/gitea/models/issues"
|
|
repo_model "code.gitea.io/gitea/models/repo"
|
|
"code.gitea.io/gitea/models/unittest"
|
|
user_model "code.gitea.io/gitea/models/user"
|
|
"code.gitea.io/gitea/modules/translation"
|
|
"code.gitea.io/gitea/tests"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func BlockUser(t *testing.T, doer, blockedUser *user_model.User) {
|
|
t.Helper()
|
|
|
|
unittest.AssertNotExistsBean(t, &user_model.BlockedUser{BlockID: blockedUser.ID, UserID: doer.ID})
|
|
|
|
session := loginUser(t, doer.Name)
|
|
req := NewRequestWithValues(t, "POST", "/"+blockedUser.Name, map[string]string{
|
|
"_csrf": GetCSRF(t, session, "/"+blockedUser.Name),
|
|
"action": "block",
|
|
})
|
|
resp := session.MakeRequest(t, req, http.StatusOK)
|
|
|
|
type redirect struct {
|
|
Redirect string `json:"redirect"`
|
|
}
|
|
|
|
var respBody redirect
|
|
DecodeJSON(t, resp, &respBody)
|
|
assert.EqualValues(t, "/"+blockedUser.Name, respBody.Redirect)
|
|
assert.True(t, unittest.BeanExists(t, &user_model.BlockedUser{BlockID: blockedUser.ID, UserID: doer.ID}))
|
|
}
|
|
|
|
func TestBlockUser(t *testing.T) {
|
|
defer tests.PrepareTestEnv(t)()
|
|
|
|
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 8})
|
|
blockedUser := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
|
BlockUser(t, doer, blockedUser)
|
|
|
|
// Unblock user.
|
|
session := loginUser(t, doer.Name)
|
|
req := NewRequestWithValues(t, "POST", "/"+blockedUser.Name, map[string]string{
|
|
"_csrf": GetCSRF(t, session, "/"+blockedUser.Name),
|
|
"action": "unblock",
|
|
})
|
|
resp := session.MakeRequest(t, req, http.StatusSeeOther)
|
|
|
|
loc := resp.Header().Get("Location")
|
|
assert.EqualValues(t, "/"+blockedUser.Name, loc)
|
|
unittest.AssertNotExistsBean(t, &user_model.BlockedUser{BlockID: blockedUser.ID, UserID: doer.ID})
|
|
}
|
|
|
|
func TestBlockIssueCreation(t *testing.T) {
|
|
defer tests.PrepareTestEnv(t)()
|
|
|
|
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
|
blockedUser := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2, OwnerID: doer.ID})
|
|
BlockUser(t, doer, blockedUser)
|
|
|
|
session := loginUser(t, blockedUser.Name)
|
|
req := NewRequest(t, "GET", "/"+repo.OwnerName+"/"+repo.Name+"/issues/new")
|
|
resp := session.MakeRequest(t, req, http.StatusOK)
|
|
|
|
htmlDoc := NewHTMLParser(t, resp.Body)
|
|
link, exists := htmlDoc.doc.Find("form.ui.form").Attr("action")
|
|
assert.True(t, exists)
|
|
req = NewRequestWithValues(t, "POST", link, map[string]string{
|
|
"_csrf": htmlDoc.GetCSRF(),
|
|
"title": "Title",
|
|
"content": "Hello!",
|
|
})
|
|
|
|
resp = session.MakeRequest(t, req, http.StatusOK)
|
|
htmlDoc = NewHTMLParser(t, resp.Body)
|
|
assert.Contains(t,
|
|
htmlDoc.doc.Find(".ui.negative.message").Text(),
|
|
translation.NewLocale("en-US").Tr("repo.issues.blocked_by_user"),
|
|
)
|
|
}
|
|
|
|
func TestBlockIssueReaction(t *testing.T) {
|
|
defer tests.PrepareTestEnv(t)()
|
|
|
|
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
|
blockedUser := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
|
|
issue := unittest.AssertExistsAndLoadBean(t, &issue_model.Issue{ID: 4, PosterID: doer.ID, RepoID: repo.ID})
|
|
issueURL := fmt.Sprintf("/%s/%s/issues/%d", url.PathEscape(repo.OwnerName), url.PathEscape(repo.Name), issue.Index)
|
|
|
|
BlockUser(t, doer, blockedUser)
|
|
|
|
session := loginUser(t, blockedUser.Name)
|
|
req := NewRequest(t, "GET", issueURL)
|
|
resp := session.MakeRequest(t, req, http.StatusOK)
|
|
htmlDoc := NewHTMLParser(t, resp.Body)
|
|
|
|
req = NewRequestWithValues(t, "POST", path.Join(issueURL, "/reactions/react"), map[string]string{
|
|
"_csrf": htmlDoc.GetCSRF(),
|
|
"content": "eyes",
|
|
})
|
|
resp = session.MakeRequest(t, req, http.StatusOK)
|
|
type reactionResponse struct {
|
|
Empty bool `json:"empty"`
|
|
}
|
|
|
|
var respBody reactionResponse
|
|
DecodeJSON(t, resp, &respBody)
|
|
|
|
assert.EqualValues(t, true, respBody.Empty)
|
|
}
|
|
|
|
func TestBlockCommentReaction(t *testing.T) {
|
|
defer tests.PrepareTestEnv(t)()
|
|
|
|
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5})
|
|
blockedUser := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
|
issue := unittest.AssertExistsAndLoadBean(t, &issue_model.Issue{ID: 1, RepoID: repo.ID})
|
|
comment := unittest.AssertExistsAndLoadBean(t, &issue_model.Comment{ID: 3, PosterID: doer.ID, IssueID: issue.ID})
|
|
_ = comment.LoadIssue(db.DefaultContext)
|
|
issueURL := fmt.Sprintf("/%s/%s/issues/%d", url.PathEscape(repo.OwnerName), url.PathEscape(repo.Name), issue.Index)
|
|
|
|
BlockUser(t, doer, blockedUser)
|
|
|
|
session := loginUser(t, blockedUser.Name)
|
|
req := NewRequest(t, "GET", issueURL)
|
|
resp := session.MakeRequest(t, req, http.StatusOK)
|
|
htmlDoc := NewHTMLParser(t, resp.Body)
|
|
|
|
req = NewRequestWithValues(t, "POST", path.Join(repo.Link(), "/comments/", strconv.FormatInt(comment.ID, 10), "/reactions/react"), map[string]string{
|
|
"_csrf": htmlDoc.GetCSRF(),
|
|
"content": "eyes",
|
|
})
|
|
resp = session.MakeRequest(t, req, http.StatusOK)
|
|
type reactionResponse struct {
|
|
Empty bool `json:"empty"`
|
|
}
|
|
|
|
var respBody reactionResponse
|
|
DecodeJSON(t, resp, &respBody)
|
|
|
|
assert.EqualValues(t, true, respBody.Empty)
|
|
}
|
|
|
|
// TestBlockFollow ensures that the doer and blocked user cannot follow each other.
|
|
func TestBlockFollow(t *testing.T) {
|
|
defer tests.PrepareTestEnv(t)()
|
|
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5})
|
|
blockedUser := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
|
|
|
BlockUser(t, doer, blockedUser)
|
|
|
|
// Doer cannot follow blocked user.
|
|
session := loginUser(t, doer.Name)
|
|
req := NewRequestWithValues(t, "POST", "/"+blockedUser.Name, map[string]string{
|
|
"_csrf": GetCSRF(t, session, "/"+blockedUser.Name),
|
|
"action": "follow",
|
|
})
|
|
session.MakeRequest(t, req, http.StatusSeeOther)
|
|
|
|
unittest.AssertNotExistsBean(t, &user_model.Follow{UserID: doer.ID, FollowID: blockedUser.ID})
|
|
|
|
// Blocked user cannot follow doer.
|
|
session = loginUser(t, blockedUser.Name)
|
|
req = NewRequestWithValues(t, "POST", "/"+doer.Name, map[string]string{
|
|
"_csrf": GetCSRF(t, session, "/"+doer.Name),
|
|
"action": "follow",
|
|
})
|
|
session.MakeRequest(t, req, http.StatusSeeOther)
|
|
|
|
unittest.AssertNotExistsBean(t, &user_model.Follow{UserID: blockedUser.ID, FollowID: doer.ID})
|
|
}
|
|
|
|
// TestBlockUserFromOrganization ensures that an organisation can block and unblock an user.
|
|
func TestBlockUserFromOrganization(t *testing.T) {
|
|
defer tests.PrepareTestEnv(t)()
|
|
|
|
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 15})
|
|
blockedUser := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
|
org := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 17, Type: user_model.UserTypeOrganization})
|
|
unittest.AssertNotExistsBean(t, &user_model.BlockedUser{BlockID: blockedUser.ID, UserID: org.ID})
|
|
|
|
session := loginUser(t, doer.Name)
|
|
req := NewRequestWithValues(t, "POST", org.OrganisationLink()+"/settings/blocked_users/block", map[string]string{
|
|
"_csrf": GetCSRF(t, session, org.OrganisationLink()+"/settings/blocked_users"),
|
|
"uname": blockedUser.Name,
|
|
})
|
|
session.MakeRequest(t, req, http.StatusSeeOther)
|
|
assert.True(t, unittest.BeanExists(t, &user_model.BlockedUser{BlockID: blockedUser.ID, UserID: org.ID}))
|
|
|
|
req = NewRequestWithValues(t, "POST", org.OrganisationLink()+"/settings/blocked_users/unblock", map[string]string{
|
|
"_csrf": GetCSRF(t, session, org.OrganisationLink()+"/settings/blocked_users"),
|
|
"user_id": strconv.FormatInt(blockedUser.ID, 10),
|
|
})
|
|
session.MakeRequest(t, req, http.StatusSeeOther)
|
|
unittest.AssertNotExistsBean(t, &user_model.BlockedUser{BlockID: blockedUser.ID, UserID: org.ID})
|
|
}
|