feat: allow auditors to read template insights (#10860)

- Adds a template_insights pseudo-resource
- Grants auditor and template admin roles read access on template_insights
- Updates existing RBAC checks to check for read template_insights, falling back to template update permissions where necessary
- Updates TemplateLayout to show Insights tab if can read template_insights or can update template
This commit is contained in:
Cian Johnston
2023-11-24 17:21:32 +00:00
committed by GitHub
parent e73901cf56
commit dd161b172e
11 changed files with 186 additions and 77 deletions

View File

@ -3,6 +3,7 @@ package coderd_test
import (
"context"
"fmt"
"net/http"
"testing"
"time"
@ -68,3 +69,60 @@ func TestTemplateInsightsWithTemplateAdminACL(t *testing.T) {
})
}
}
func TestTemplateInsightsWithRole(t *testing.T) {
t.Parallel()
y, m, d := time.Now().UTC().Date()
today := time.Date(y, m, d, 0, 0, 0, 0, time.UTC)
type test struct {
interval codersdk.InsightsReportInterval
role string
allowed bool
}
tests := []test{
{codersdk.InsightsReportIntervalDay, rbac.RoleTemplateAdmin(), true},
{"", rbac.RoleTemplateAdmin(), true},
{codersdk.InsightsReportIntervalDay, "auditor", true},
{"", "auditor", true},
{codersdk.InsightsReportIntervalDay, rbac.RoleUserAdmin(), false},
{"", rbac.RoleUserAdmin(), false},
{codersdk.InsightsReportIntervalDay, rbac.RoleMember(), false},
{"", rbac.RoleMember(), false},
}
for _, tt := range tests {
tt := tt
t.Run(fmt.Sprintf("with interval=%q role=%q", tt.interval, tt.role), func(t *testing.T) {
t.Parallel()
client, admin := coderdenttest.New(t, &coderdenttest.Options{LicenseOptions: &coderdenttest.LicenseOptions{
Features: license.Features{
codersdk.FeatureTemplateRBAC: 1,
},
}})
version := coderdtest.CreateTemplateVersion(t, client, admin.OrganizationID, nil)
template := coderdtest.CreateTemplate(t, client, admin.OrganizationID, version.ID)
aud, _ := coderdtest.CreateAnotherUser(t, client, admin.OrganizationID, tt.role)
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitShort)
defer cancel()
_, err := aud.TemplateInsights(ctx, codersdk.TemplateInsightsRequest{
StartTime: today.AddDate(0, 0, -1),
EndTime: today,
TemplateIDs: []uuid.UUID{template.ID},
})
if tt.allowed {
require.NoError(t, err)
} else {
var sdkErr *codersdk.Error
require.ErrorAs(t, err, &sdkErr)
require.Equal(t, sdkErr.StatusCode(), http.StatusNotFound)
}
})
}
}