chore: fix gocyclo issues

This commit is contained in:
jamesread 2025-10-11 00:52:18 +01:00
parent b330fbd1a5
commit 60814b97e2
3 changed files with 120 additions and 74 deletions

View File

@ -321,40 +321,50 @@ func (api *oliveTinAPI) GetActionBinding(ctx ctx.Context, req *connect.Request[a
func (api *oliveTinAPI) GetDashboard(ctx ctx.Context, req *connect.Request[apiv1.GetDashboardRequest]) (*connect.Response[apiv1.GetDashboardResponse], error) {
user := acl.UserFromContext(ctx, api.cfg)
if user.IsGuest() && api.cfg.AuthRequireGuestsToLogin {
return nil, connect.NewError(connect.CodePermissionDenied, fmt.Errorf("guests are not allowed to access the dashboard"))
if err := api.checkDashboardAccess(user); err != nil {
return nil, err
}
dashboardRenderRequest := &DashboardRenderRequest{
dashboardRenderRequest := api.createDashboardRenderRequest(user)
if api.isDefaultDashboard(req.Msg.Title) {
return api.buildDefaultDashboardResponse(dashboardRenderRequest)
}
return api.buildCustomDashboardResponse(dashboardRenderRequest, req.Msg.Title)
}
func (api *oliveTinAPI) checkDashboardAccess(user *acl.AuthenticatedUser) error {
if user.IsGuest() && api.cfg.AuthRequireGuestsToLogin {
return connect.NewError(connect.CodePermissionDenied, fmt.Errorf("guests are not allowed to access the dashboard"))
}
return nil
}
func (api *oliveTinAPI) createDashboardRenderRequest(user *acl.AuthenticatedUser) *DashboardRenderRequest {
return &DashboardRenderRequest{
AuthenticatedUser: user,
cfg: api.cfg,
ex: api.executor,
}
}
if req.Msg.Title == "default" || req.Msg.Title == "" || req.Msg.Title == "Actions" {
db := buildDefaultDashboard(dashboardRenderRequest)
res := &apiv1.GetDashboardResponse{
Dashboard: db,
}
return connect.NewResponse(res), nil
}
func (api *oliveTinAPI) isDefaultDashboard(title string) bool {
return title == "default" || title == "" || title == "Actions"
}
func (api *oliveTinAPI) buildDefaultDashboardResponse(rr *DashboardRenderRequest) (*connect.Response[apiv1.GetDashboardResponse], error) {
db := buildDefaultDashboard(rr)
res := &apiv1.GetDashboardResponse{
Dashboard: renderDashboard(dashboardRenderRequest, req.Msg.Title),
Dashboard: db,
}
return connect.NewResponse(res), nil
}
/*
if len(res.Actions) == 0 {
log.WithFields(log.Fields{
"username": user.Username,
"usergroupLine": user.UsergroupLine,
"provider": user.Provider,
"acls": user.Acls,
"availableActions": len(api.cfg.Actions),
}).Warn("Zero actions found for user")
}
*/
func (api *oliveTinAPI) buildCustomDashboardResponse(rr *DashboardRenderRequest, title string) (*connect.Response[apiv1.GetDashboardResponse], error) {
res := &apiv1.GetDashboardResponse{
Dashboard: renderDashboard(rr, title),
}
return connect.NewResponse(res), nil
}
@ -595,31 +605,31 @@ func (api *oliveTinAPI) Init(ctx ctx.Context, req *connect.Request[apiv1.InitReq
func (api *oliveTinAPI) buildRootDashboards(user *acl.AuthenticatedUser, dashboards []*config.DashboardComponent) []string {
var rootDashboards []string
dashboardRenderRequest := api.createDashboardRenderRequest(user)
dashboardRenderRequest := &DashboardRenderRequest{
AuthenticatedUser: user,
cfg: api.cfg,
ex: api.executor,
}
api.addDefaultDashboardIfNeeded(&rootDashboards, dashboardRenderRequest)
api.addCustomDashboards(&rootDashboards, dashboards, dashboardRenderRequest)
defaultDashboard := buildDefaultDashboard(dashboardRenderRequest)
return rootDashboards
}
func (api *oliveTinAPI) addDefaultDashboardIfNeeded(rootDashboards *[]string, rr *DashboardRenderRequest) {
defaultDashboard := buildDefaultDashboard(rr)
if defaultDashboard != nil && len(defaultDashboard.Contents) > 0 {
log.Infof("defaultDashboard: %+v", defaultDashboard.Contents)
rootDashboards = append(rootDashboards, "Actions")
*rootDashboards = append(*rootDashboards, "Actions")
}
}
func (api *oliveTinAPI) addCustomDashboards(rootDashboards *[]string, dashboards []*config.DashboardComponent, rr *DashboardRenderRequest) {
for _, dashboard := range dashboards {
// We have to build the dashboard response instead of just looping over config.dashboards,
// because we need to check if the user has access to the dashboard
db := renderDashboard(dashboardRenderRequest, dashboard.Title)
db := renderDashboard(rr, dashboard.Title)
if db != nil {
rootDashboards = append(rootDashboards, dashboard.Title)
*rootDashboards = append(*rootDashboards, dashboard.Title)
}
}
return rootDashboards
}
func buildPublicOAuth2ProvidersList(cfg *config.Config) []*apiv1.OAuth2Provider {
@ -720,7 +730,7 @@ func (api *oliveTinAPI) GetEntity(ctx ctx.Context, req *connect.Request[apiv1.Ge
log.Infof("msg: %+v", req.Msg)
if instances == nil || len(instances) == 0 {
if len(instances) == 0 {
return nil, connect.NewError(connect.CodeNotFound, fmt.Errorf("entity type %s not found", req.Msg.Type))
}

View File

@ -14,32 +14,44 @@ func renderDashboard(rr *DashboardRenderRequest, dashboardTitle string) *apiv1.D
return buildDefaultDashboard(rr)
}
return findAndRenderDashboard(rr, dashboardTitle)
}
func findAndRenderDashboard(rr *DashboardRenderRequest, dashboardTitle string) *apiv1.Dashboard {
for _, dashboard := range rr.cfg.Dashboards {
if dashboard.Title != dashboardTitle {
continue
}
if len(dashboard.Contents) == 0 {
log.WithFields(log.Fields{
"dashboard": dashboard.Title,
"username": rr.AuthenticatedUser.Username,
}).Debugf("Dashboard has no readable contents, so it will not be visible in the web ui")
logEmptyDashboard(dashboard.Title, rr.AuthenticatedUser.Username)
return nil
}
return &apiv1.Dashboard{
Title: dashboard.Title,
Contents: sortActions(removeNulls(getDashboardComponentContents(dashboard, rr))),
}
return buildDashboardFromConfig(dashboard, rr)
}
return nil
}
func logEmptyDashboard(dashboardTitle, username string) {
log.WithFields(log.Fields{
"dashboard": dashboardTitle,
"username": username,
}).Debugf("Dashboard has no readable contents, so it will not be visible in the web ui")
}
func buildDashboardFromConfig(dashboard *config.DashboardComponent, rr *DashboardRenderRequest) *apiv1.Dashboard {
return &apiv1.Dashboard{
Title: dashboard.Title,
Contents: sortActions(removeNulls(getDashboardComponentContents(dashboard, rr))),
}
}
//gocyclo:ignore
func buildDefaultDashboard(rr *DashboardRenderRequest) *apiv1.Dashboard {
db := &apiv1.Dashboard{
Title: "Default",
Title: "Actions",
Contents: make([]*apiv1.DashboardComponent, 0),
}
@ -112,28 +124,40 @@ func removeNulls(components []*apiv1.DashboardComponent) []*apiv1.DashboardCompo
func getDashboardComponentContents(dashboard *config.DashboardComponent, rr *DashboardRenderRequest) []*apiv1.DashboardComponent {
ret := make([]*apiv1.DashboardComponent, 0)
rootFieldset := createRootFieldset()
rootFieldset := &apiv1.DashboardComponent{
for _, subitem := range dashboard.Contents {
processDashboardSubitem(subitem, rr, &ret, rootFieldset)
}
return appendRootFieldsetIfNeeded(ret, rootFieldset)
}
func createRootFieldset() *apiv1.DashboardComponent {
return &apiv1.DashboardComponent{
Type: "fieldset",
Title: "Actions",
Contents: make([]*apiv1.DashboardComponent, 0),
}
}
for _, subitem := range dashboard.Contents {
if subitem.Type == "fieldset" && subitem.Entity != "" {
ret = append(ret, buildEntityFieldsets(subitem.Entity, subitem, rr)...)
} else if subitem.Type == "fieldset" {
// Handle regular fieldsets by creating them directly
ret = append(ret, buildDashboardComponentSimple(subitem, rr))
} else {
rootFieldset.Contents = append(rootFieldset.Contents, buildDashboardComponentSimple(subitem, rr))
}
func processDashboardSubitem(subitem *config.DashboardComponent, rr *DashboardRenderRequest, ret *[]*apiv1.DashboardComponent, rootFieldset *apiv1.DashboardComponent) {
if subitem.Type != "fieldset" {
rootFieldset.Contents = append(rootFieldset.Contents, buildDashboardComponentSimple(subitem, rr))
return
}
if subitem.Entity != "" {
*ret = append(*ret, buildEntityFieldsets(subitem.Entity, subitem, rr)...)
} else {
*ret = append(*ret, buildDashboardComponentSimple(subitem, rr))
}
}
func appendRootFieldsetIfNeeded(ret []*apiv1.DashboardComponent, rootFieldset *apiv1.DashboardComponent) []*apiv1.DashboardComponent {
if len(rootFieldset.Contents) > 0 {
ret = append(ret, rootFieldset)
}
return ret
}

View File

@ -7,8 +7,9 @@ import (
config "github.com/OliveTin/OliveTin/internal/config"
"github.com/OliveTin/OliveTin/internal/entities"
"github.com/stretchr/testify/assert"
"testing"
"github.com/stretchr/testify/assert"
)
func TestSanitizeUnsafe(t *testing.T) {
@ -254,9 +255,9 @@ func TestTypeSafetyCheckRawStringMultiline(t *testing.T) {
func TestTypeSafetyCheckUnicodeIdentifier(t *testing.T) {
tests := []struct {
name string
field string
value string
name string
field string
value string
expectsError bool
}{
{"Valid unicode identifier", "name", "hello_world", false},
@ -273,24 +274,35 @@ func TestTypeSafetyCheckUnicodeIdentifier(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := TypeSafetyCheck(tt.field, tt.value, "unicode_identifier")
if tt.expectsError {
if err == nil {
t.Errorf("Expected error for value '%s', but got none", tt.value)
} else {
t.Logf("Received expected error for value '%s': %v", tt.value, err)
}
} else {
if err != nil {
t.Errorf("Expected no error for value '%s', but got: %v", tt.value, err)
} else {
t.Logf("No error for valid value '%s' as expected", tt.value)
}
}
validateTypeSafetyResult(t, tt.value, tt.expectsError, err)
})
}
}
func validateTypeSafetyResult(t *testing.T, value string, expectsError bool, err error) {
if expectsError {
assertErrorExpected(t, value, err)
} else {
assertNoErrorExpected(t, value, err)
}
}
func assertErrorExpected(t *testing.T, value string, err error) {
if err == nil {
t.Errorf("Expected error for value '%s', but got none", value)
} else {
t.Logf("Received expected error for value '%s': %v", value, err)
}
}
func assertNoErrorExpected(t *testing.T, value string, err error) {
if err != nil {
t.Errorf("Expected no error for value '%s', but got: %v", value, err)
} else {
t.Logf("No error for valid value '%s' as expected", value)
}
}
func TestTypeSafetyCheckAsciiIdentifier(t *testing.T) {
tests := []struct {
name string