fix: add missing checks to several API and web handlers (#39501) (#39507)

Backport #39501 by @silverwind

Several handlers skipped checks that their sibling routes or settings
already enforce. This brings them in line.

- Push mirror API honors `DISABLE_NEW_PUSH` and checks the caller's
permission
- Media API serves small files with the usual content headers
- Issue attachment API ignores comment attachments
- Push-to-create respects `FORCE_PRIVATE`
- Profile feeds and follow actions respect `ENABLE_FEED` and owner
visibility
- Tag delete route refuses release tags
- Refresh token grant only accepts refresh tokens
- Gitea migrations bound the source's page size

Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: bircni <bircni@icloud.com>
This commit is contained in:
Giteabot
2026-09-30 11:46:59 -07:00
committed by GitHub
parent 1e28bb1bd7
commit 2d58c8c3df
18 changed files with 124 additions and 27 deletions
+3 -3
View File
@@ -162,7 +162,7 @@ func GetRawFileOrLFS(ctx *context.APIContext) {
// if it's not a pointer, just serve the data directly // if it's not a pointer, just serve the data directly
if !pointer.IsValid() { if !pointer.IsValid() {
_, _ = ctx.Resp.Write(lfsPointerBuf) httplib.ServeUserContentByReader(ctx.Req, ctx.Resp, int64(len(lfsPointerBuf)), bytes.NewReader(lfsPointerBuf), httplib.ServeHeaderOptions{Filename: blob.Name()})
return return
} }
@@ -171,7 +171,7 @@ func GetRawFileOrLFS(ctx *context.APIContext) {
// If there isn't one, just serve the data directly // If there isn't one, just serve the data directly
if errors.Is(err, git_model.ErrLFSObjectNotExist) { if errors.Is(err, git_model.ErrLFSObjectNotExist) {
_, _ = ctx.Resp.Write(lfsPointerBuf) httplib.ServeUserContentByReader(ctx.Req, ctx.Resp, int64(len(lfsPointerBuf)), bytes.NewReader(lfsPointerBuf), httplib.ServeHeaderOptions{Filename: blob.Name()})
return return
} else if err != nil { } else if err != nil {
ctx.APIErrorInternal(err) ctx.APIErrorInternal(err)
@@ -198,7 +198,7 @@ func GetRawFileOrLFS(ctx *context.APIContext) {
return return
} }
defer lfsDataFile.Close() defer lfsDataFile.Close()
httplib.ServeUserContentByFile(ctx.Base.Req, ctx.Base.Resp, lfsDataFile, httplib.ServeHeaderOptions{Filename: ctx.Repo.TreePath}) httplib.ServeUserContentByFile(ctx.Base.Req, ctx.Base.Resp, lfsDataFile, httplib.ServeHeaderOptions{Filename: blob.Name()})
} }
func getBlobForEntry(ctx *context.APIContext) (blob *git.Blob, entry *git.TreeEntry, lastModified *time.Time) { func getBlobForEntry(ctx *context.APIContext) (blob *git.Blob, entry *git.TreeEntry, lastModified *time.Time) {
+2 -2
View File
@@ -386,8 +386,8 @@ func attachmentBelongsToRepoOrIssue(ctx *context.APIContext, attachment *repo_mo
ctx.APIErrorNotFound("no such attachment in repo") ctx.APIErrorNotFound("no such attachment in repo")
return false return false
} }
if attachment.IssueID == 0 { if attachment.IssueID == 0 || attachment.CommentID != 0 {
log.Debug("Requested attachment[%d] is not in an issue.", attachment.ID) log.Debug("Requested attachment[%d] is not an issue attachment.", attachment.ID)
ctx.APIErrorNotFound("no such attachment in issue") ctx.APIErrorNotFound("no such attachment in issue")
return false return false
} else if issue != nil && attachment.IssueID != issue.ID { } else if issue != nil && attachment.IssueID != issue.ID {
+6 -1
View File
@@ -291,6 +291,11 @@ func AddPushMirror(ctx *context.APIContext) {
return return
} }
if setting.Mirror.DisableNewPush {
ctx.APIError(http.StatusForbidden, "the site administrator has disabled the creation of new push mirrors")
return
}
pushMirror := web.GetForm[*api.CreatePushMirrorOption](ctx) pushMirror := web.GetForm[*api.CreatePushMirrorOption](ctx)
CreatePushMirror(ctx, pushMirror) CreatePushMirror(ctx, pushMirror)
} }
@@ -356,7 +361,7 @@ func CreatePushMirror(ctx *context.APIContext, mirrorOption *api.CreatePushMirro
address, err := git.ParseRemoteAddr(mirrorOption.RemoteAddress, mirrorOption.RemoteUsername, mirrorOption.RemotePassword) address, err := git.ParseRemoteAddr(mirrorOption.RemoteAddress, mirrorOption.RemoteUsername, mirrorOption.RemotePassword)
if err == nil { if err == nil {
err = migrations.IsMigrateURLAllowed(address, ctx.ContextUser) err = migrations.IsMigrateURLAllowed(address, ctx.Doer)
} }
if err != nil { if err != nil {
HandleRemoteAddressError(ctx, err) HandleRemoteAddressError(ctx, err)
+23
View File
@@ -10,13 +10,36 @@ import (
"gitea.dev/models/db" "gitea.dev/models/db"
repo_model "gitea.dev/models/repo" repo_model "gitea.dev/models/repo"
"gitea.dev/models/unittest" "gitea.dev/models/unittest"
user_model "gitea.dev/models/user"
"gitea.dev/modules/setting" "gitea.dev/modules/setting"
api "gitea.dev/modules/structs"
"gitea.dev/modules/test" "gitea.dev/modules/test"
"gitea.dev/services/contexttest" "gitea.dev/services/contexttest"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func TestCreatePushMirrorUsesCallerPermission(t *testing.T) {
defer test.MockVariableValue(&setting.ImportLocalPaths, true)()
ctx, resp := contexttest.MockAPIContext(t, "user2/repo1")
ctx.Doer = &user_model.User{}
ctx.ContextUser = &user_model.User{AllowImportLocal: true}
CreatePushMirror(ctx, &api.CreatePushMirrorOption{RemoteAddress: "local-mirror", Interval: "0"})
assert.Equal(t, http.StatusUnauthorized, resp.Code)
}
func TestAddPushMirrorDisabled(t *testing.T) {
defer test.MockVariableValue(&setting.Mirror.DisableNewPush, true)()
ctx, resp := contexttest.MockAPIContext(t, "user2/repo1")
AddPushMirror(ctx)
assert.Equal(t, http.StatusForbidden, resp.Code)
assert.Contains(t, resp.Body.String(), "the site administrator has disabled the creation of new push mirrors")
}
// TestPushMirrorSync verifies the endpoint attempts every push mirror instead // TestPushMirrorSync verifies the endpoint attempts every push mirror instead
// of aborting on the first failure, reporting all failed remotes with a 422. // of aborting on the first failure, reporting all failed remotes with a 422.
// Each remote name is not a configured git remote, so SyncPushMirror fails fast // Each remote name is not a configured git remote, so SyncPushMirror fails fast
+2 -1
View File
@@ -139,7 +139,8 @@ func hookPostReceiveUpdateRepoByOptions(ctx *gitea_context.PrivateContext, opts
// The repo is empty and being initialized by this push, so there is no // The repo is empty and being initialized by this push, so there is no
// dependent state (webhooks, notifications, visibility fan-out) to reconcile // dependent state (webhooks, notifications, visibility fan-out) to reconcile
// yet; setting the flags directly is sufficient in this push-to-create case. // yet; setting the flags directly is sufficient in this push-to-create case.
if isPrivate.Has() && repo.IsPrivate != isPrivate.Value() { if isPrivate.Has() && repo.IsPrivate != isPrivate.Value() &&
(isPrivate.Value() || !setting.Repository.ForcePrivate || ctx.Doer.IsAdmin) {
repo.IsPrivate = isPrivate.Value() repo.IsPrivate = isPrivate.Value()
if err := repo_model.UpdateRepositoryColsNoAutoTime(ctx, repo, "is_private"); err != nil { if err := repo_model.UpdateRepositoryColsNoAutoTime(ctx, repo, "is_private"); err != nil {
log.Error("failed to update repo is_private: %v", err) log.Error("failed to update repo is_private: %v", err)
+1 -1
View File
@@ -576,7 +576,7 @@ func handleRefreshToken(ctx *context.Context, form forms.AccessTokenForm, server
} }
token, err := oauth2_provider.ParseToken(form.RefreshToken, serverKey) token, err := oauth2_provider.ParseToken(form.RefreshToken, serverKey)
if err != nil { if err != nil || token.Kind != oauth2_provider.KindRefreshToken {
handleAccessTokenError(ctx, oauth2_provider.AccessTokenError{ handleAccessTokenError(ctx, oauth2_provider.AccessTokenError{
ErrorCode: oauth2_provider.AccessTokenErrorCodeUnauthorizedClient, ErrorCode: oauth2_provider.AccessTokenErrorCodeUnauthorizedClient,
ErrorDescription: "unable to parse refresh token", ErrorDescription: "unable to parse refresh token",
+10 -1
View File
@@ -9,7 +9,9 @@ import (
activities_model "gitea.dev/models/activities" activities_model "gitea.dev/models/activities"
"gitea.dev/models/organization" "gitea.dev/models/organization"
"gitea.dev/models/renderhelper" "gitea.dev/models/renderhelper"
user_model "gitea.dev/models/user"
"gitea.dev/modules/markup/markdown" "gitea.dev/modules/markup/markdown"
"gitea.dev/modules/setting"
"gitea.dev/services/context" "gitea.dev/services/context"
feed_service "gitea.dev/services/feed" feed_service "gitea.dev/services/feed"
@@ -28,8 +30,15 @@ func ShowUserFeedAtom(ctx *context.Context) {
// showUserFeed show user activity as RSS / Atom feed // showUserFeed show user activity as RSS / Atom feed
func showUserFeed(ctx *context.Context, formatType string) { func showUserFeed(ctx *context.Context, formatType string) {
includePrivate := ctx.IsSigned && (ctx.Doer.IsAdmin || ctx.Doer.ID == ctx.ContextUser.ID)
isOrganisation := ctx.ContextUser.IsOrganization() isOrganisation := ctx.ContextUser.IsOrganization()
if !setting.Other.EnableFeed ||
isOrganisation && !organization.HasOrgOrUserVisible(ctx, ctx.ContextUser, ctx.Doer) ||
!isOrganisation && !user_model.IsUserVisibleToViewer(ctx, ctx.ContextUser, ctx.Doer) {
ctx.NotFound(nil)
return
}
includePrivate := ctx.IsSigned && (ctx.Doer.IsAdmin || ctx.Doer.ID == ctx.ContextUser.ID)
if ctx.IsSigned && isOrganisation && !includePrivate { if ctx.IsSigned && isOrganisation && !includePrivate {
// When feed is requested by a member of the organization, // When feed is requested by a member of the organization,
// include the private repo's the member has access to. // include the private repo's the member has access to.
+5
View File
@@ -660,6 +660,11 @@ func deleteReleaseOrTag(ctx *context.Context, isDelTag bool) {
return return
} }
if isDelTag && !rel.IsTag {
ctx.HTTPError(http.StatusConflict, "a tag attached to a release cannot be deleted directly")
return
}
if err := release_service.DeleteReleaseByID(ctx, ctx.Repo.Repository, rel, ctx.Doer, isDelTag); err != nil { if err := release_service.DeleteReleaseByID(ctx, ctx.Repo.Repository, rel, ctx.Doer, isDelTag); err != nil {
if release_service.IsErrProtectedTagName(err) { if release_service.IsErrProtectedTagName(err) {
ctx.Flash.Error(ctx.Tr("repo.release.tag_name_protected")) ctx.Flash.Error(ctx.Tr("repo.release.tag_name_protected"))
+16
View File
@@ -4,6 +4,7 @@
package repo package repo
import ( import (
"net/http"
"net/http/httptest" "net/http/httptest"
"testing" "testing"
@@ -21,6 +22,21 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func TestDeleteTagRetainsReleaseAndAttachments(t *testing.T) {
unittest.PrepareTestEnv(t)
ctx, resp := contexttest.MockContext(t, "POST user2/repo1/tags/delete?id=1")
contexttest.LoadUser(t, ctx, 2)
contexttest.LoadRepo(t, ctx, 1)
release := unittest.AssertExistsAndLoadBean(t, &repo_model.Release{ID: 1})
attachment := unittest.AssertExistsAndLoadBean(t, &repo_model.Attachment{ID: 9, ReleaseID: 1})
DeleteTag(ctx)
assert.Equal(t, http.StatusConflict, resp.Code)
assert.Equal(t, release, unittest.AssertExistsAndLoadBean(t, &repo_model.Release{ID: 1}))
assert.Equal(t, attachment, unittest.AssertExistsAndLoadBean(t, &repo_model.Attachment{ID: 9}))
}
func TestNewReleasePost(t *testing.T) { func TestNewReleasePost(t *testing.T) {
unittest.PrepareTestEnv(t) unittest.PrepareTestEnv(t)
-8
View File
@@ -734,18 +734,10 @@ func UsernameSubRoute(ctx *context.Context) {
ShowGPGKeys(ctx) ShowGPGKeys(ctx)
} }
case strings.HasSuffix(username, ".rss"): case strings.HasSuffix(username, ".rss"):
if !setting.Other.EnableFeed {
ctx.HTTPError(http.StatusNotFound)
return
}
if reloadParam(".rss") { if reloadParam(".rss") {
feed.ShowUserFeedRSS(ctx) feed.ShowUserFeedRSS(ctx)
} }
case strings.HasSuffix(username, ".atom"): case strings.HasSuffix(username, ".atom"):
if !setting.Other.EnableFeed {
ctx.HTTPError(http.StatusNotFound)
return
}
if reloadParam(".atom") { if reloadParam(".atom") {
feed.ShowUserFeedAtom(ctx) feed.ShowUserFeedAtom(ctx)
} }
+7
View File
@@ -322,6 +322,13 @@ func prepareUserProfileTabData(ctx *context.Context, profileDbRepo *repo_model.R
// ActionUserFollow is for follow/unfollow user request // ActionUserFollow is for follow/unfollow user request
func ActionUserFollow(ctx *context.Context) { func ActionUserFollow(ctx *context.Context) {
isOrg := ctx.ContextUser.IsOrganization()
if isOrg && !organization.HasOrgOrUserVisible(ctx, ctx.ContextUser, ctx.Doer) ||
!isOrg && !user_model.IsUserVisibleToViewer(ctx, ctx.ContextUser, ctx.Doer) {
ctx.NotFound(nil)
return
}
var err error var err error
switch ctx.FormString("action") { switch ctx.FormString("action") {
case "follow": case "follow":
+2 -3
View File
@@ -107,9 +107,8 @@ func NewGiteaDownloader(ctx context.Context, baseURL, repoPath, username, passwo
if err != nil { if err != nil {
log.Info("Unable to get global API settings. Ignoring these.") log.Info("Unable to get global API settings. Ignoring these.")
log.Debug("giteaClient.GetGlobalAPISettings. Error: %v", err) log.Debug("giteaClient.GetGlobalAPISettings. Error: %v", err)
} } else if apiConf != nil && apiConf.MaxResponseItems > 0 {
if apiConf != nil { maxPerPage = min(apiConf.MaxResponseItems, 100)
maxPerPage = apiConf.MaxResponseItems
} }
return &GiteaDownloader{ return &GiteaDownloader{
+10 -7
View File
@@ -5,6 +5,7 @@ package migrations
import ( import (
"fmt" "fmt"
"math"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"os" "os"
@@ -317,15 +318,16 @@ func TestGiteaDownloadRepo(t *testing.T) {
func TestGiteaDownloadCommentsPaging(t *testing.T) { func TestGiteaDownloadCommentsPaging(t *testing.T) {
for _, tc := range []struct { for _, tc := range []struct {
maxResponseItems, commentCount, requests int maxResponseItems, pageSize, commentCount, requests int
paginated bool paginated bool
}{ }{
{maxResponseItems: 2, commentCount: 2, requests: 2}, {maxResponseItems: 2, pageSize: 2, commentCount: 2, requests: 2},
{maxResponseItems: 2, commentCount: 3, requests: 1}, {maxResponseItems: 2, pageSize: 2, commentCount: 3, requests: 1},
{maxResponseItems: 2, commentCount: 4, requests: 3, paginated: true}, {maxResponseItems: 2, pageSize: 2, commentCount: 4, requests: 3, paginated: true},
{maxResponseItems: 0, commentCount: 0, requests: 1}, {maxResponseItems: 0, pageSize: 10, commentCount: 0, requests: 1},
{maxResponseItems: math.MaxInt, pageSize: 100, commentCount: 0, requests: 1},
} { } {
t.Run(strconv.Itoa(tc.commentCount), func(t *testing.T) { t.Run(fmt.Sprintf("maxResponseItems=%d/comments=%d", tc.maxResponseItems, tc.commentCount), func(t *testing.T) {
commentRequests := 0 commentRequests := 0
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path { switch r.URL.Path {
@@ -352,6 +354,7 @@ func TestGiteaDownloadCommentsPaging(t *testing.T) {
downloader, err := NewGiteaDownloader(t.Context(), server.URL, "o/r", "", "", "") downloader, err := NewGiteaDownloader(t.Context(), server.URL, "o/r", "", "", "")
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, tc.pageSize, downloader.maxPerPage)
comments, _, err := downloader.GetComments(t.Context(), &base.Issue{Number: 1}) comments, _, err := downloader.GetComments(t.Context(), &base.Issue{Number: 1})
require.NoError(t, err) require.NoError(t, err)
@@ -38,6 +38,11 @@ func TestAPIGetIssueAttachment(t *testing.T) {
apiAttachment := DecodeJSON(t, resp, &api.Attachment{}) apiAttachment := DecodeJSON(t, resp, &api.Attachment{})
unittest.AssertExistsAndLoadBean(t, &repo_model.Attachment{ID: apiAttachment.ID, IssueID: issue.ID}) unittest.AssertExistsAndLoadBean(t, &repo_model.Attachment{ID: apiAttachment.ID, IssueID: issue.ID})
commentAttachment := unittest.AssertExistsAndLoadBean(t, &repo_model.Attachment{ID: 3, RepoID: repo.ID})
req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/assets/%d", repoOwner.Name, repo.Name, unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: commentAttachment.IssueID}).Index, commentAttachment.ID)).
AddTokenAuth(token)
session.MakeRequest(t, req, http.StatusNotFound)
} }
func TestAPIListIssueAttachments(t *testing.T) { func TestAPIListIssueAttachments(t *testing.T) {
@@ -22,6 +22,10 @@ func TestAPIGetRawFileOrLFS(t *testing.T) {
resp := MakeRequest(t, req, http.StatusOK) resp := MakeRequest(t, req, http.StatusOK)
assert.Equal(t, "# repo1\n\nDescription for repo1", resp.Body.String()) assert.Equal(t, "# repo1\n\nDescription for repo1", resp.Body.String())
req = NewRequest(t, "GET", "/api/v1/repos/user2/repo2/media/test.xml").AddTokenAuth(getUserToken(t, "user2", auth_model.AccessTokenScopeReadRepository))
resp = MakeRequest(t, req, http.StatusOK)
assert.Equal(t, "text/plain; charset=utf-8", resp.Header().Get("Content-Type"))
// Test with LFS // Test with LFS
onGiteaRun(t, func(t *testing.T, u *url.URL) { onGiteaRun(t, func(t *testing.T, u *url.URL) {
createLFSTestRepository(t, "repo-lfs-test") createLFSTestRepository(t, "repo-lfs-test")
+10
View File
@@ -16,6 +16,8 @@ import (
user_model "gitea.dev/models/user" user_model "gitea.dev/models/user"
"gitea.dev/modules/git" "gitea.dev/modules/git"
"gitea.dev/modules/git/gitcmd" "gitea.dev/modules/git/gitcmd"
"gitea.dev/modules/setting"
"gitea.dev/modules/test"
repo_service "gitea.dev/services/repository" repo_service "gitea.dev/services/repository"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@@ -175,6 +177,14 @@ func TestGitPushVisibilityOption(t *testing.T) {
doGitPushTestRepository(gitPath, "origin", "branch2", "-o", "repo.private=false")(t) doGitPushTestRepository(gitPath, "origin", "branch2", "-o", "repo.private=false")(t)
repo = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repo.ID}) repo = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repo.ID})
assert.True(t, repo.IsPrivate, "repo.private option must be ignored on an existing repository") assert.True(t, repo.IsPrivate, "repo.private option must be ignored on an existing repository")
defer test.MockVariableValue(&setting.Repository.ForcePrivate, true)()
forcedRepo, err := repo_service.CreateRepository(t.Context(), user, user, repo_service.CreateRepoOptions{Name: "repo-visibility-forced", DefaultBranch: "master", IsPrivate: true})
require.NoError(t, err)
u.Path = forcedRepo.FullName() + ".git"
doGitAddRemote(gitPath, "forced", u)(t)
doGitPushTestRepository(gitPath, "forced", "master", "-o", "repo.private=false")(t)
assert.True(t, unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: forcedRepo.ID}).IsPrivate)
}) })
} }
+9
View File
@@ -571,6 +571,15 @@ func testRefreshTokenInvalidation(t *testing.T) {
assert.Equal(t, "unauthorized_client", string(parsedError.ErrorCode)) assert.Equal(t, "unauthorized_client", string(parsedError.ErrorCode))
assert.Equal(t, "unable to parse refresh token", parsedError.ErrorDescription) assert.Equal(t, "unable to parse refresh token", parsedError.ErrorDescription)
req = NewRequestWithValues(t, "POST", "/login/oauth/access_token", map[string]string{
"grant_type": "refresh_token",
"client_id": "da7da3ba-9a13-4167-856f-3899de0b0138",
"client_secret": "4MK8Na6R55smdCY0WuCCumZ6hjRPnGY5saWVRHHjJiA=",
"redirect_uri": "https://example.com",
"refresh_token": parsed.AccessToken,
})
MakeRequest(t, req, http.StatusBadRequest)
req = NewRequestWithValues(t, "POST", "/login/oauth/access_token", map[string]string{ req = NewRequestWithValues(t, "POST", "/login/oauth/access_token", map[string]string{
"grant_type": "refresh_token", "grant_type": "refresh_token",
"client_id": "da7da3ba-9a13-4167-856f-3899de0b0138", "client_id": "da7da3ba-9a13-4167-856f-3899de0b0138",
+9
View File
@@ -84,6 +84,7 @@ func testViewLimitedAndPrivateUserAndRename(t *testing.T) {
org22 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 22}) org22 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 22})
req := NewRequest(t, "GET", "/"+org22.Name) req := NewRequest(t, "GET", "/"+org22.Name)
MakeRequest(t, req, http.StatusNotFound) MakeRequest(t, req, http.StatusNotFound)
MakeRequest(t, NewRequest(t, "GET", "/"+org22.Name).SetHeader("Accept", "application/rss+xml"), http.StatusNotFound)
session := loginUser(t, "user1") session := loginUser(t, "user1")
oldName := org22.Name oldName := org22.Name
@@ -106,6 +107,8 @@ func testViewLimitedAndPrivateUserAndRename(t *testing.T) {
org23 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 23}) org23 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 23})
req = NewRequest(t, "GET", "/"+org23.Name) req = NewRequest(t, "GET", "/"+org23.Name)
MakeRequest(t, req, http.StatusNotFound) MakeRequest(t, req, http.StatusNotFound)
strangerSession := loginUser(t, "user4")
strangerSession.MakeRequest(t, NewRequest(t, "POST", "/"+org23.Name+"?action=follow"), http.StatusNotFound)
oldName = org23.Name oldName = org23.Name
newName = "org23_renamed" newName = "org23_renamed"
@@ -127,6 +130,8 @@ func testViewLimitedAndPrivateUserAndRename(t *testing.T) {
user31 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 31}) user31 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 31})
req = NewRequest(t, "GET", "/"+user31.Name) req = NewRequest(t, "GET", "/"+user31.Name)
MakeRequest(t, req, http.StatusNotFound) MakeRequest(t, req, http.StatusNotFound)
MakeRequest(t, NewRequest(t, "GET", "/"+user31.Name).SetHeader("Accept", "application/rss+xml"), http.StatusNotFound)
strangerSession.MakeRequest(t, NewRequest(t, "POST", "/"+user31.Name+"?action=follow"), http.StatusNotFound)
oldName = user31.Name oldName = user31.Name
newName = "user31_renamed" newName = "user31_renamed"
@@ -330,6 +335,10 @@ func testGetUserRss(t *testing.T) {
session := loginUser(t, "user2") session := loginUser(t, "user2")
req = NewRequestf(t, "GET", "/non-existent-user.rss") req = NewRequestf(t, "GET", "/non-existent-user.rss")
session.MakeRequest(t, req, http.StatusNotFound) session.MakeRequest(t, req, http.StatusNotFound)
defer test.MockVariableValue(&setting.Other.EnableFeed, false)()
MakeRequest(t, NewRequestf(t, "GET", "/%s.rss", user34), http.StatusNotFound)
MakeRequest(t, NewRequestf(t, "GET", "/%s", user34).SetHeader("Accept", "application/rss+xml"), http.StatusNotFound)
} }
func testUserListStopWatches(t *testing.T) { func testUserListStopWatches(t *testing.T) {