mirror of
https://github.com/go-gitea/gitea
synced 2024-12-27 19:14:27 +00:00
900ac62251
This is a large and complex PR, so let me explain in detail its changes. First, I had to create new index mappings for Bleve and ElasticSerach as the current ones do not support search by filename. This requires Gitea to recreate the code search indexes (I do not know if this is a breaking change, but I feel it deserves a heads-up). I've used [this approach](https://www.elastic.co/guide/en/elasticsearch/reference/7.17/analysis-pathhierarchy-tokenizer.html) to model the filename index. It allows us to efficiently search for both the full path and the name of a file. Bleve, however, does not support this out-of-box, so I had to code a brand new [token filter](https://blevesearch.com/docs/Token-Filters/) to generate the search terms. I also did an overhaul in the `indexer_test.go` file. It now asserts the order of the expected results (this is important since matches based on the name of a file are more relevant than those based on its content). I've added new test scenarios that deal with searching by filename. They use a new repo included in the Gitea fixture. The screenshot below depicts how Gitea shows the search results. It shows results based on content in the same way as the current version does. In matches based on the filename, the first seven lines of the file contents are shown (BTW, this is how GitHub does it). ![image](https://github.com/user-attachments/assets/9d938d86-1a8d-4f89-8644-1921a473e858) Resolves #32096 --------- Signed-off-by: Bruno Sofiato <bruno.sofiato@gmail.com>
229 lines
7.0 KiB
Go
229 lines
7.0 KiB
Go
// Copyright 2018 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package integration
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
"strings"
|
|
"testing"
|
|
|
|
auth_model "code.gitea.io/gitea/models/auth"
|
|
"code.gitea.io/gitea/models/db"
|
|
org_model "code.gitea.io/gitea/models/organization"
|
|
"code.gitea.io/gitea/models/perm"
|
|
unit_model "code.gitea.io/gitea/models/unit"
|
|
"code.gitea.io/gitea/models/unittest"
|
|
user_model "code.gitea.io/gitea/models/user"
|
|
"code.gitea.io/gitea/modules/setting"
|
|
api "code.gitea.io/gitea/modules/structs"
|
|
"code.gitea.io/gitea/tests"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestAPIOrgCreate(t *testing.T) {
|
|
onGiteaRun(t, func(*testing.T, *url.URL) {
|
|
token := getUserToken(t, "user1", auth_model.AccessTokenScopeWriteOrganization)
|
|
|
|
org := api.CreateOrgOption{
|
|
UserName: "user1_org",
|
|
FullName: "User1's organization",
|
|
Description: "This organization created by user1",
|
|
Website: "https://try.gitea.io",
|
|
Location: "Shanghai",
|
|
Visibility: "limited",
|
|
}
|
|
req := NewRequestWithJSON(t, "POST", "/api/v1/orgs", &org).
|
|
AddTokenAuth(token)
|
|
resp := MakeRequest(t, req, http.StatusCreated)
|
|
|
|
var apiOrg api.Organization
|
|
DecodeJSON(t, resp, &apiOrg)
|
|
|
|
assert.Equal(t, org.UserName, apiOrg.Name)
|
|
assert.Equal(t, org.FullName, apiOrg.FullName)
|
|
assert.Equal(t, org.Description, apiOrg.Description)
|
|
assert.Equal(t, org.Website, apiOrg.Website)
|
|
assert.Equal(t, org.Location, apiOrg.Location)
|
|
assert.Equal(t, org.Visibility, apiOrg.Visibility)
|
|
|
|
unittest.AssertExistsAndLoadBean(t, &user_model.User{
|
|
Name: org.UserName,
|
|
LowerName: strings.ToLower(org.UserName),
|
|
FullName: org.FullName,
|
|
})
|
|
|
|
// Check owner team permission
|
|
ownerTeam, _ := org_model.GetOwnerTeam(db.DefaultContext, apiOrg.ID)
|
|
|
|
for _, ut := range unit_model.AllRepoUnitTypes {
|
|
up := perm.AccessModeOwner
|
|
if ut == unit_model.TypeExternalTracker || ut == unit_model.TypeExternalWiki {
|
|
up = perm.AccessModeRead
|
|
}
|
|
unittest.AssertExistsAndLoadBean(t, &org_model.TeamUnit{
|
|
OrgID: apiOrg.ID,
|
|
TeamID: ownerTeam.ID,
|
|
Type: ut,
|
|
AccessMode: up,
|
|
})
|
|
}
|
|
|
|
req = NewRequestf(t, "GET", "/api/v1/orgs/%s", org.UserName).
|
|
AddTokenAuth(token)
|
|
resp = MakeRequest(t, req, http.StatusOK)
|
|
DecodeJSON(t, resp, &apiOrg)
|
|
assert.EqualValues(t, org.UserName, apiOrg.Name)
|
|
|
|
req = NewRequestf(t, "GET", "/api/v1/orgs/%s/repos", org.UserName).
|
|
AddTokenAuth(token)
|
|
resp = MakeRequest(t, req, http.StatusOK)
|
|
|
|
var repos []*api.Repository
|
|
DecodeJSON(t, resp, &repos)
|
|
for _, repo := range repos {
|
|
assert.False(t, repo.Private)
|
|
}
|
|
|
|
req = NewRequestf(t, "GET", "/api/v1/orgs/%s/members", org.UserName).
|
|
AddTokenAuth(token)
|
|
resp = MakeRequest(t, req, http.StatusOK)
|
|
|
|
// user1 on this org is public
|
|
var users []*api.User
|
|
DecodeJSON(t, resp, &users)
|
|
assert.Len(t, users, 1)
|
|
assert.EqualValues(t, "user1", users[0].UserName)
|
|
})
|
|
}
|
|
|
|
func TestAPIOrgEdit(t *testing.T) {
|
|
onGiteaRun(t, func(*testing.T, *url.URL) {
|
|
session := loginUser(t, "user1")
|
|
|
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteOrganization)
|
|
org := api.EditOrgOption{
|
|
FullName: "Org3 organization new full name",
|
|
Description: "A new description",
|
|
Website: "https://try.gitea.io/new",
|
|
Location: "Beijing",
|
|
Visibility: "private",
|
|
}
|
|
req := NewRequestWithJSON(t, "PATCH", "/api/v1/orgs/org3", &org).
|
|
AddTokenAuth(token)
|
|
resp := MakeRequest(t, req, http.StatusOK)
|
|
|
|
var apiOrg api.Organization
|
|
DecodeJSON(t, resp, &apiOrg)
|
|
|
|
assert.Equal(t, "org3", apiOrg.Name)
|
|
assert.Equal(t, org.FullName, apiOrg.FullName)
|
|
assert.Equal(t, org.Description, apiOrg.Description)
|
|
assert.Equal(t, org.Website, apiOrg.Website)
|
|
assert.Equal(t, org.Location, apiOrg.Location)
|
|
assert.Equal(t, org.Visibility, apiOrg.Visibility)
|
|
})
|
|
}
|
|
|
|
func TestAPIOrgEditBadVisibility(t *testing.T) {
|
|
onGiteaRun(t, func(*testing.T, *url.URL) {
|
|
session := loginUser(t, "user1")
|
|
|
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteOrganization)
|
|
org := api.EditOrgOption{
|
|
FullName: "Org3 organization new full name",
|
|
Description: "A new description",
|
|
Website: "https://try.gitea.io/new",
|
|
Location: "Beijing",
|
|
Visibility: "badvisibility",
|
|
}
|
|
req := NewRequestWithJSON(t, "PATCH", "/api/v1/orgs/org3", &org).
|
|
AddTokenAuth(token)
|
|
MakeRequest(t, req, http.StatusUnprocessableEntity)
|
|
})
|
|
}
|
|
|
|
func TestAPIOrgDeny(t *testing.T) {
|
|
onGiteaRun(t, func(*testing.T, *url.URL) {
|
|
setting.Service.RequireSignInView = true
|
|
defer func() {
|
|
setting.Service.RequireSignInView = false
|
|
}()
|
|
|
|
orgName := "user1_org"
|
|
req := NewRequestf(t, "GET", "/api/v1/orgs/%s", orgName)
|
|
MakeRequest(t, req, http.StatusNotFound)
|
|
|
|
req = NewRequestf(t, "GET", "/api/v1/orgs/%s/repos", orgName)
|
|
MakeRequest(t, req, http.StatusNotFound)
|
|
|
|
req = NewRequestf(t, "GET", "/api/v1/orgs/%s/members", orgName)
|
|
MakeRequest(t, req, http.StatusNotFound)
|
|
})
|
|
}
|
|
|
|
func TestAPIGetAll(t *testing.T) {
|
|
defer tests.PrepareTestEnv(t)()
|
|
|
|
token := getUserToken(t, "user1", auth_model.AccessTokenScopeReadOrganization)
|
|
|
|
// accessing with a token will return all orgs
|
|
req := NewRequest(t, "GET", "/api/v1/orgs").
|
|
AddTokenAuth(token)
|
|
resp := MakeRequest(t, req, http.StatusOK)
|
|
var apiOrgList []*api.Organization
|
|
|
|
DecodeJSON(t, resp, &apiOrgList)
|
|
assert.Len(t, apiOrgList, 13)
|
|
assert.Equal(t, "Limited Org 36", apiOrgList[1].FullName)
|
|
assert.Equal(t, "limited", apiOrgList[1].Visibility)
|
|
|
|
// accessing without a token will return only public orgs
|
|
req = NewRequest(t, "GET", "/api/v1/orgs")
|
|
resp = MakeRequest(t, req, http.StatusOK)
|
|
|
|
DecodeJSON(t, resp, &apiOrgList)
|
|
assert.Len(t, apiOrgList, 9)
|
|
assert.Equal(t, "org 17", apiOrgList[0].FullName)
|
|
assert.Equal(t, "public", apiOrgList[0].Visibility)
|
|
}
|
|
|
|
func TestAPIOrgSearchEmptyTeam(t *testing.T) {
|
|
onGiteaRun(t, func(*testing.T, *url.URL) {
|
|
token := getUserToken(t, "user1", auth_model.AccessTokenScopeWriteOrganization)
|
|
orgName := "org_with_empty_team"
|
|
|
|
// create org
|
|
req := NewRequestWithJSON(t, "POST", "/api/v1/orgs", &api.CreateOrgOption{
|
|
UserName: orgName,
|
|
}).AddTokenAuth(token)
|
|
MakeRequest(t, req, http.StatusCreated)
|
|
|
|
// create team with no member
|
|
req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/orgs/%s/teams", orgName), &api.CreateTeamOption{
|
|
Name: "Empty",
|
|
IncludesAllRepositories: true,
|
|
Permission: "read",
|
|
Units: []string{"repo.code", "repo.issues", "repo.ext_issues", "repo.wiki", "repo.pulls"},
|
|
}).AddTokenAuth(token)
|
|
MakeRequest(t, req, http.StatusCreated)
|
|
|
|
// case-insensitive search for teams that have no members
|
|
req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/orgs/%s/teams/search?q=%s", orgName, "empty")).
|
|
AddTokenAuth(token)
|
|
resp := MakeRequest(t, req, http.StatusOK)
|
|
data := struct {
|
|
Ok bool
|
|
Data []*api.Team
|
|
}{}
|
|
DecodeJSON(t, resp, &data)
|
|
assert.True(t, data.Ok)
|
|
if assert.Len(t, data.Data, 1) {
|
|
assert.EqualValues(t, "Empty", data.Data[0].Name)
|
|
}
|
|
})
|
|
}
|