mirror of
https://gitea.com/gitea/tea.git
synced 2026-10-26 11:01:25 +01:00
201 lines
8.8 KiB
Go
201 lines
8.8 KiB
Go
// Copyright 2026 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package services
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"testing"
|
|
|
|
gitea "gitea.dev/sdk"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestTeamRepositoryPolicyPreservesUnitPermissions(t *testing.T) {
|
|
mutations := 0
|
|
client := newTestClient(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
require.Equal(t, "/api/v1/teams/1", r.URL.Path)
|
|
if r.Method == http.MethodGet {
|
|
_, _ = w.Write([]byte(`{"id":1,"permission":"read","units_map":{"repo.code":"write","repo.issues":"read"}}`))
|
|
return
|
|
}
|
|
mutations++
|
|
body := requestJSON(t, r)
|
|
require.Equal(t, "read", body["permission"])
|
|
require.Equal(t, false, body["includes_all_repositories"])
|
|
require.Equal(t, map[string]any{"repo.code": "write", "repo.issues": "read"}, body["units_map"])
|
|
require.NotContains(t, body, "name")
|
|
require.NotContains(t, body, "description")
|
|
_, _ = w.Write([]byte(`{"id":1,"permission":"read","organization":{"username":"acme"}}`))
|
|
}))
|
|
service := Teams{Client: client}
|
|
allRepos := false
|
|
item, err := service.Edit(context.Background(), 1, TeamOptions{AllRepositories: &allRepos})
|
|
require.NoError(t, err)
|
|
require.Equal(t, "acme", item.Organization)
|
|
require.Equal(t, 1, mutations)
|
|
}
|
|
|
|
func TestTeamEditMergesUnitsUnlessReplaced(t *testing.T) {
|
|
for _, test := range []struct {
|
|
replace bool
|
|
reads int
|
|
want map[string]any
|
|
}{
|
|
{false, 1, map[string]any{"repo.code": "write", "repo.issues": "read", "repo.wiki": "write"}},
|
|
{true, 0, map[string]any{"repo.wiki": "write"}},
|
|
} {
|
|
reads := 0
|
|
client := newTestClient(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
require.Equal(t, "/api/v1/teams/5", r.URL.Path)
|
|
if r.Method == http.MethodGet {
|
|
reads++
|
|
_, _ = w.Write([]byte(`{"id":5,"permission":"write","units_map":{"repo.code":"write","repo.issues":"read","repo.wiki":"none"}}`))
|
|
return
|
|
}
|
|
body := requestJSON(t, r)
|
|
require.Equal(t, test.want, body["units_map"])
|
|
require.NotContains(t, body, "permission")
|
|
_, _ = w.Write([]byte(`{"id":5}`))
|
|
}))
|
|
_, err := (Teams{Client: client}).Edit(context.Background(), 5, TeamOptions{Units: map[string]string{"repo.wiki": "write"}, ReplaceUnits: test.replace})
|
|
require.NoError(t, err)
|
|
require.Equal(t, test.reads, reads)
|
|
}
|
|
}
|
|
|
|
func TestTeamCreateSendsPermissionAndUnits(t *testing.T) {
|
|
client := newTestClient(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
require.Equal(t, http.MethodPost, r.Method)
|
|
require.Equal(t, "/api/v1/orgs/acme/teams", r.URL.Path)
|
|
body := requestJSON(t, r)
|
|
require.Equal(t, "Developers", body["name"])
|
|
require.Equal(t, "write", body["permission"])
|
|
require.Equal(t, true, body["can_create_org_repo"])
|
|
require.Equal(t, false, body["includes_all_repositories"])
|
|
require.Equal(t, map[string]any{"repo.code": "write"}, body["units_map"])
|
|
w.WriteHeader(http.StatusCreated)
|
|
_, _ = w.Write([]byte(`{"id":3,"name":"Developers","permission":"write","can_create_org_repo":true,"units_map":{"repo.code":"write"},"organization":{"name":"acme"}}`))
|
|
}))
|
|
name, permission, createRepo, allRepos := "Developers", "write", true, false
|
|
item, err := (Teams{Client: client}).Create(context.Background(), "acme", TeamOptions{
|
|
Name: &name, Permission: &permission, CanCreateRepo: &createRepo, AllRepositories: &allRepos, Units: map[string]string{"repo.code": "write"},
|
|
})
|
|
require.NoError(t, err)
|
|
require.Equal(t, Team{ID: 3, Name: "Developers", Organization: "acme", Permission: "write", CanCreateRepo: true, Units: map[string]string{"repo.code": "write"}}, item)
|
|
}
|
|
|
|
func TestTeamAccessRequests(t *testing.T) {
|
|
var requests []string
|
|
client := newTestClient(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
requests = append(requests, r.Method+" "+r.URL.RequestURI())
|
|
switch {
|
|
case r.URL.Path == "/api/v1/teams/3/members":
|
|
_, _ = w.Write([]byte(`[{"id":2,"login":"bob"}]`))
|
|
case r.URL.Path == "/api/v1/teams/3/repos":
|
|
_, _ = w.Write([]byte(`[{"id":4,"full_name":"acme/project","html_url":"https://gitea.test/acme/project"}]`))
|
|
default:
|
|
w.WriteHeader(http.StatusNoContent)
|
|
}
|
|
}))
|
|
service := Teams{Client: client}
|
|
members, err := service.Members(context.Background(), 3, 5, 2)
|
|
require.NoError(t, err)
|
|
require.Equal(t, []TeamMember{{ID: 2, Username: "bob"}}, members.Items)
|
|
repos, err := service.Repositories(context.Background(), 3, 5, 1)
|
|
require.NoError(t, err)
|
|
require.Equal(t, "https://gitea.test/acme/project", repos.Items[0].URL)
|
|
require.NoError(t, service.SetMember(context.Background(), 3, "bob", false))
|
|
require.NoError(t, service.SetRepository(context.Background(), 3, "acme/project", true))
|
|
require.Equal(t, []string{
|
|
"GET /api/v1/teams/3/members?limit=5&page=2", "GET /api/v1/teams/3/repos?limit=5&page=1",
|
|
"DELETE /api/v1/teams/3/members/bob", "PUT /api/v1/teams/3/repos/acme/project",
|
|
}, requests)
|
|
}
|
|
|
|
func TestTeamFromKeepsAbsentValuesEmpty(t *testing.T) {
|
|
item := teamFrom(decode[gitea.Team](t, `{"id":1,"name":"Owners","permission":"owner","organization":null,"units_map":null}`))
|
|
require.Equal(t, Team{ID: 1, Name: "Owners", Permission: "owner", Units: map[string]string{}}, item)
|
|
}
|
|
|
|
func TestTeamUnitLevelAppliesThePermissionToEveryUnit(t *testing.T) {
|
|
team := Team{Permission: "write", Units: map[string]string{"repo.wiki": "none"}}
|
|
require.Equal(t, "write", team.UnitLevel("repo.code"))
|
|
require.Equal(t, "write", team.UnitLevel("repo.wiki"))
|
|
require.Equal(t, "read", team.UnitLevel("repo.ext_wiki"))
|
|
require.Equal(t, "write", Team{Permission: "none", Units: map[string]string{"repo.code": "write"}}.UnitLevel("repo.code"))
|
|
require.Equal(t, "none", Team{Permission: "none"}.UnitLevel("repo.code"))
|
|
}
|
|
|
|
func TestTeamAccessSummarizesUnits(t *testing.T) {
|
|
for _, tc := range []struct {
|
|
permission string
|
|
units map[string]string
|
|
want string
|
|
}{
|
|
{"owner", UnitPolicy("write"), "owner"},
|
|
{"admin", nil, "admin"},
|
|
{"none", UnitPolicy("write"), "write"},
|
|
{"none", UnitPolicy("read"), "read"},
|
|
{"none", map[string]string{"repo.code": "write", "repo.issues": "write", "repo.pulls": "write", "repo.wiki": "none", "repo.ext_wiki": "read"}, "write (code, issues, pulls)"},
|
|
{"none", map[string]string{"repo.code": "write", "repo.wiki": "read"}, "custom"},
|
|
{"none", map[string]string{"repo.ext_issues": "read"}, "none"},
|
|
// Gitea grants the team permission on every unit when the team has no unit rows.
|
|
{"write", nil, "write"},
|
|
{"read", map[string]string{}, "read"},
|
|
{"write", map[string]string{"repo.wiki": "read"}, "write"},
|
|
{"read", map[string]string{"repo.code": "write"}, "custom"},
|
|
} {
|
|
require.Equal(t, tc.want, Team{Permission: tc.permission, Units: tc.units}.Access(), "%v", tc.units)
|
|
}
|
|
}
|
|
|
|
func TestTeamFindSearchesTheOrganization(t *testing.T) {
|
|
var queries []string
|
|
client := newTestClient(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.URL.Path == "/api/v1/orgs/nope/teams/search" {
|
|
w.WriteHeader(http.StatusNotFound)
|
|
return
|
|
}
|
|
require.Equal(t, "/api/v1/orgs/acme/teams/search", r.URL.Path)
|
|
queries = append(queries, r.URL.Query().Get("q"))
|
|
if r.URL.Query().Get("page") != "1" {
|
|
_, _ = w.Write([]byte(`{"ok":true,"data":[]}`))
|
|
return
|
|
}
|
|
_, _ = w.Write([]byte(`{"ok":true,"data":[{"id":2,"name":"dev"},{"id":3,"name":"Dev"},{"id":4,"name":"devops"}]}`))
|
|
}))
|
|
service := Teams{Client: client}
|
|
team, err := service.Find(context.Background(), "acme", "devops")
|
|
require.NoError(t, err)
|
|
require.Equal(t, Team{ID: 4, Name: "devops", Organization: "acme", Units: map[string]string{}}, team)
|
|
team, err = service.Find(context.Background(), "acme", "3")
|
|
require.NoError(t, err)
|
|
require.Equal(t, "Dev", team.Name)
|
|
_, err = service.Find(context.Background(), "acme", "DEV")
|
|
require.EqualError(t, err, `team "DEV" is ambiguous in acme (IDs 2, 3); pass an ID`)
|
|
_, err = service.Find(context.Background(), "nope", "dev")
|
|
require.EqualError(t, err, `organization "nope" not found`)
|
|
require.Equal(t, []string{"devops", "devops", "", "", "DEV", "DEV"}, queries)
|
|
}
|
|
|
|
func TestTeamEditSendsThePermissionBeforeTheUnits(t *testing.T) {
|
|
var bodies []map[string]any
|
|
client := newTestClient(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
require.Equal(t, "/api/v1/teams/5", r.URL.Path)
|
|
if r.Method == http.MethodGet {
|
|
_, _ = w.Write([]byte(`{"id":5,"name":"devs","permission":"admin"}`))
|
|
return
|
|
}
|
|
bodies = append(bodies, requestJSON(t, r))
|
|
_, _ = w.Write([]byte(`{"id":5,"name":"devs","permission":"write"}`))
|
|
}))
|
|
permission := "write"
|
|
_, err := (Teams{Client: client}).Edit(context.Background(), 5, TeamOptions{Permission: &permission, Units: map[string]string{"repo.wiki": "read"}, ReplaceUnits: true})
|
|
require.NoError(t, err)
|
|
require.Len(t, bodies, 2)
|
|
require.Equal(t, map[string]any{"name": "devs", "permission": "write"}, bodies[0], "Gitea 28 keeps an admin team admin when one request sets both")
|
|
require.Equal(t, map[string]any{"repo.wiki": "read"}, bodies[1]["units_map"])
|
|
}
|