feat: allow editors to access repository refs subresource
Change refs authorization from admin to editor fallback so editors can view repository branches when pushing changes to dashboards/folders. - Split refs from other read-only subresources (resources, history, status) - refs now uses accessWithEditor instead of accessWithAdmin - Updated documentation comment to reflect authorization levels - Added integration test TestIntegrationProvisioning_RefsPermissions verifying editor access and viewer denial
This commit is contained in:
@@ -330,7 +330,7 @@ func (b *APIBuilder) GetAuthorizer() authorizer.Authorizer {
|
||||
//
|
||||
// Repositories:
|
||||
// - CRUD: repositories:create/read/write/delete
|
||||
// - Subresources (files, refs, resources, history, status): repositories:read
|
||||
// - Subresources: files (any auth), refs (editor), resources/history/status (admin)
|
||||
// - Test: repositories:write
|
||||
// - Jobs subresource: jobs:create/read
|
||||
//
|
||||
@@ -413,8 +413,18 @@ func (b *APIBuilder) authorizeRepositorySubresource(ctx context.Context, a autho
|
||||
case "files":
|
||||
return authorizer.DecisionAllow, "", nil
|
||||
|
||||
// Read-only subresources: refs, resources, history, status
|
||||
case "refs", "resources", "history", "status":
|
||||
// refs subresource - editors need to see branches to push changes
|
||||
case "refs":
|
||||
return toAuthorizerDecision(b.accessWithEditor.Check(ctx, authlib.CheckRequest{
|
||||
Verb: apiutils.VerbGet,
|
||||
Group: provisioning.GROUP,
|
||||
Resource: provisioning.RepositoryResourceInfo.GetName(),
|
||||
Name: a.GetName(),
|
||||
Namespace: a.GetNamespace(),
|
||||
}, ""))
|
||||
|
||||
// Read-only subresources: resources, history, status (admin only)
|
||||
case "resources", "history", "status":
|
||||
return toAuthorizerDecision(b.accessWithAdmin.Check(ctx, authlib.CheckRequest{
|
||||
Verb: apiutils.VerbGet,
|
||||
Group: provisioning.GROUP,
|
||||
|
||||
@@ -950,3 +950,65 @@ func TestIntegrationProvisioning_JobPermissions(t *testing.T) {
|
||||
require.Equal(t, http.StatusAccepted, statusCode, "should return 202 Accepted")
|
||||
})
|
||||
}
|
||||
|
||||
func TestIntegrationProvisioning_RefsPermissions(t *testing.T) {
|
||||
testutil.SkipIntegrationTestInShortMode(t)
|
||||
|
||||
helper := runGrafana(t)
|
||||
ctx := context.Background()
|
||||
|
||||
const repo = "refs-permissions-test"
|
||||
testRepo := TestRepo{
|
||||
Name: repo,
|
||||
Target: "folder",
|
||||
Copies: map[string]string{}, // No files needed for this test
|
||||
ExpectedDashboards: 0,
|
||||
ExpectedFolders: 1, // Repository creates a folder
|
||||
}
|
||||
helper.CreateRepo(t, testRepo)
|
||||
|
||||
t.Run("editor can GET refs", func(t *testing.T) {
|
||||
var statusCode int
|
||||
result := helper.EditorREST.Get().
|
||||
Namespace("default").
|
||||
Resource("repositories").
|
||||
Name(repo).
|
||||
SubResource("refs").
|
||||
Do(ctx).StatusCode(&statusCode)
|
||||
|
||||
require.NoError(t, result.Error(), "editor should be able to GET refs")
|
||||
require.Equal(t, http.StatusOK, statusCode, "should return 200 OK")
|
||||
|
||||
// Verify we can parse the refs
|
||||
refs := &provisioning.RefList{}
|
||||
err := result.Into(refs)
|
||||
require.NoError(t, err, "should parse refs response")
|
||||
})
|
||||
|
||||
t.Run("viewer cannot GET refs", func(t *testing.T) {
|
||||
var statusCode int
|
||||
result := helper.ViewerREST.Get().
|
||||
Namespace("default").
|
||||
Resource("repositories").
|
||||
Name(repo).
|
||||
SubResource("refs").
|
||||
Do(ctx).StatusCode(&statusCode)
|
||||
|
||||
require.Error(t, result.Error(), "viewer should not be able to GET refs")
|
||||
require.Equal(t, http.StatusForbidden, statusCode, "should return 403 Forbidden")
|
||||
require.True(t, apierrors.IsForbidden(result.Error()), "error should be forbidden")
|
||||
})
|
||||
|
||||
t.Run("admin can GET refs", func(t *testing.T) {
|
||||
var statusCode int
|
||||
result := helper.AdminREST.Get().
|
||||
Namespace("default").
|
||||
Resource("repositories").
|
||||
Name(repo).
|
||||
SubResource("refs").
|
||||
Do(ctx).StatusCode(&statusCode)
|
||||
|
||||
require.NoError(t, result.Error(), "admin should be able to GET refs")
|
||||
require.Equal(t, http.StatusOK, statusCode, "should return 200 OK")
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user