From c864a0e10fbad04579d774ba922645317480f292 Mon Sep 17 00:00:00 2001 From: Stefan Majer Date: Wed, 15 Jul 2026 07:54:36 +0200 Subject: [PATCH 1/3] Use maps instead of slice for roles --- generate/generate.go | 31 +- generate/go_servicepermissions.tpl | 32 +- go/permissions/permissions.go | 12 +- go/permissions/servicepermissions.go | 702 +++++++++++++-------------- 4 files changed, 396 insertions(+), 381 deletions(-) diff --git a/generate/generate.go b/generate/generate.go index b4146acb..35f645f9 100644 --- a/generate/generate.go +++ b/generate/generate.go @@ -106,8 +106,8 @@ func servicePermissions(root string) (*permissions.ServicePermissions, error) { } methods = permissions.Methods{ // Allow service reflection to list available methods - serverReflectionInfov1alpha1: true, - serverReflectionInfo: true, + serverReflectionInfov1alpha1: struct{}{}, + serverReflectionInfo: struct{}{}, } visibility = permissions.Visibility{ Public: map[string]bool{ @@ -150,31 +150,46 @@ func servicePermissions(root string) (*permissions.ServicePermissions, error) { // Tenant switch role := *methodOpt.IdentifierValue; role { case v1.TenantRole_TENANT_ROLE_OWNER.String(), v1.TenantRole_TENANT_ROLE_EDITOR.String(), v1.TenantRole_TENANT_ROLE_VIEWER.String(), v1.TenantRole_TENANT_ROLE_GUEST.String(): - roles.Tenant[role] = append(roles.Tenant[role], methodName) + if methods := roles.Tenant[role]; methods == nil { + roles.Tenant[role] = permissions.Methods{} + } + roles.Tenant[role][methodName] = struct{}{} visibility.Tenant[methodName] = true case v1.TenantRole_TENANT_ROLE_UNSPECIFIED.String(): // noop // Project case v1.ProjectRole_PROJECT_ROLE_OWNER.String(), v1.ProjectRole_PROJECT_ROLE_EDITOR.String(), v1.ProjectRole_PROJECT_ROLE_VIEWER.String(): - roles.Project[role] = append(roles.Project[role], methodName) + if methods := roles.Project[role]; methods == nil { + roles.Project[role] = permissions.Methods{} + } + roles.Project[role][methodName] = struct{}{} visibility.Project[methodName] = true case v1.ProjectRole_PROJECT_ROLE_UNSPECIFIED.String(): // noop // Admin case v1.AdminRole_ADMIN_ROLE_EDITOR.String(), v1.AdminRole_ADMIN_ROLE_VIEWER.String(): - roles.Admin[role] = append(roles.Admin[role], methodName) + if methods := roles.Admin[role]; methods == nil { + roles.Admin[role] = permissions.Methods{} + } + roles.Admin[role][methodName] = struct{}{} visibility.Admin[methodName] = true case v1.AdminRole_ADMIN_ROLE_UNSPECIFIED.String(): // noop // Infra case v1.InfraRole_INFRA_ROLE_EDITOR.String(), v1.InfraRole_INFRA_ROLE_VIEWER.String(): - roles.Infra[role] = append(roles.Infra[role], methodName) + if methods := roles.Infra[role]; methods == nil { + roles.Infra[role] = permissions.Methods{} + } + roles.Infra[role][methodName] = struct{}{} visibility.Infra[methodName] = true case v1.InfraRole_INFRA_ROLE_UNSPECIFIED.String(): // noop // Machine case v1.MachineRole_MACHINE_ROLE_EDITOR.String(), v1.MachineRole_MACHINE_ROLE_VIEWER.String(): - roles.Machine[role] = append(roles.Machine[role], methodName) + if methods := roles.Machine[role]; methods == nil { + roles.Machine[role] = permissions.Methods{} + } + roles.Machine[role][methodName] = struct{}{} visibility.Machine[methodName] = true case v1.MachineRole_MACHINE_ROLE_UNSPECIFIED.String(): // noop @@ -197,7 +212,7 @@ func servicePermissions(root string) (*permissions.ServicePermissions, error) { return nil, fmt.Errorf("unknown method identifier value detected:%s", *methodOpt.IdentifierValue) } - methods[methodName] = true + methods[methodName] = struct{}{} } } } diff --git a/generate/go_servicepermissions.tpl b/generate/go_servicepermissions.tpl index 74fe5109..6dc21527 100644 --- a/generate/go_servicepermissions.tpl +++ b/generate/go_servicepermissions.tpl @@ -18,51 +18,51 @@ func GetServicePermissions() *ServicePermissions { Roles: Roles{ Admin: Admin{ {{- range $role, $methods := .Roles.Admin }} - "{{ $role }}": []string{ - {{- range $method := $methods }} - "{{ $method }}", + "{{ $role }}": map[string]struct{}{ + {{- range $method,$v := $methods }} + "{{ $method }}":{{ $v }}, {{- end }} }, {{- end }} }, Infra: Infra{ {{- range $role, $methods := .Roles.Infra }} - "{{ $role }}": []string{ - {{- range $method := $methods }} - "{{ $method }}", + "{{ $role }}": map[string]struct{}{ + {{- range $method,$v := $methods }} + "{{ $method }}":{{ $v }}, {{- end }} }, {{- end }} }, Machine: Machine{ {{- range $role, $methods := .Roles.Machine }} - "{{ $role }}": []string{ - {{- range $method := $methods }} - "{{ $method }}", + "{{ $role }}": map[string]struct{}{ + {{- range $method,$v := $methods }} + "{{ $method }}":{{ $v }}, {{- end }} }, {{- end }} }, Tenant: Tenant{ {{- range $role, $methods := .Roles.Tenant }} - "{{ $role }}": []string{ - {{- range $method := $methods }} - "{{ $method }}", + "{{ $role }}": map[string]struct{}{ + {{- range $method,$v := $methods }} + "{{ $method }}":{{ $v }}, {{- end }} }, {{- end }} }, Project: Project{ {{- range $role, $methods := .Roles.Project }} - "{{ $role }}": []string{ - {{- range $method := $methods }} - "{{ $method }}", + "{{ $role }}": map[string]struct{}{ + {{- range $method,$v := $methods }} + "{{ $method }}":{{ $v }}, {{- end }} }, {{- end }} }, }, - Methods: map[string]bool{ + Methods: map[string]struct{}{ {{- range $key, $value := .Methods }} "{{ $key }}": {{ $value }} , {{- end }} diff --git a/go/permissions/permissions.go b/go/permissions/permissions.go index adcde813..ee8ca8dd 100644 --- a/go/permissions/permissions.go +++ b/go/permissions/permissions.go @@ -13,16 +13,16 @@ type ( Services []string `json:"services,omitempty"` } - Methods map[string]bool + Methods map[string]struct{} Chargeable map[string]bool Auditable map[string]bool - Admin map[string][]string - Infra map[string][]string - Machine map[string][]string - Tenant map[string][]string - Project map[string][]string + Admin map[string]Methods + Infra map[string]Methods + Machine map[string]Methods + Tenant map[string]Methods + Project map[string]Methods // Roles Roles struct { diff --git a/go/permissions/servicepermissions.go b/go/permissions/servicepermissions.go index 3458ac5d..9f64d536 100755 --- a/go/permissions/servicepermissions.go +++ b/go/permissions/servicepermissions.go @@ -53,379 +53,379 @@ func GetServicePermissions() *ServicePermissions { return &ServicePermissions{ Roles: Roles{ Admin: Admin{ - "ADMIN_ROLE_EDITOR": []string{ - "/metalstack.admin.v2.AuditService/Get", - "/metalstack.admin.v2.AuditService/List", - "/metalstack.admin.v2.ComponentService/Get", - "/metalstack.admin.v2.ComponentService/Delete", - "/metalstack.admin.v2.ComponentService/List", - "/metalstack.admin.v2.FilesystemService/Create", - "/metalstack.admin.v2.FilesystemService/Update", - "/metalstack.admin.v2.FilesystemService/Delete", - "/metalstack.admin.v2.FilesystemService/Match", - "/metalstack.admin.v2.ImageService/Create", - "/metalstack.admin.v2.ImageService/Update", - "/metalstack.admin.v2.ImageService/Delete", - "/metalstack.admin.v2.ImageService/Usage", - "/metalstack.admin.v2.IPService/List", - "/metalstack.admin.v2.MachineService/Get", - "/metalstack.admin.v2.MachineService/List", - "/metalstack.admin.v2.MachineService/Delete", - "/metalstack.admin.v2.MachineService/BMCCommand", - "/metalstack.admin.v2.MachineService/GetBMC", - "/metalstack.admin.v2.MachineService/ListBMC", - "/metalstack.admin.v2.MachineService/ConsolePassword", - "/metalstack.admin.v2.MachineService/SetState", - "/metalstack.admin.v2.MachineService/Issues", - "/metalstack.admin.v2.NetworkService/Get", - "/metalstack.admin.v2.NetworkService/Create", - "/metalstack.admin.v2.NetworkService/Update", - "/metalstack.admin.v2.NetworkService/Delete", - "/metalstack.admin.v2.NetworkService/List", - "/metalstack.admin.v2.PartitionService/Create", - "/metalstack.admin.v2.PartitionService/Update", - "/metalstack.admin.v2.PartitionService/Delete", - "/metalstack.admin.v2.PartitionService/Capacity", - "/metalstack.admin.v2.ProjectService/List", - "/metalstack.admin.v2.SizeService/Create", - "/metalstack.admin.v2.SizeService/Update", - "/metalstack.admin.v2.SizeService/Delete", - "/metalstack.admin.v2.SizeImageConstraintService/Create", - "/metalstack.admin.v2.SizeImageConstraintService/Update", - "/metalstack.admin.v2.SizeImageConstraintService/Delete", - "/metalstack.admin.v2.SizeImageConstraintService/Get", - "/metalstack.admin.v2.SizeImageConstraintService/List", - "/metalstack.admin.v2.SizeReservationService/Create", - "/metalstack.admin.v2.SizeReservationService/Update", - "/metalstack.admin.v2.SizeReservationService/Delete", - "/metalstack.admin.v2.SizeReservationService/List", - "/metalstack.admin.v2.SwitchService/Get", - "/metalstack.admin.v2.SwitchService/List", - "/metalstack.admin.v2.SwitchService/Update", - "/metalstack.admin.v2.SwitchService/Delete", - "/metalstack.admin.v2.SwitchService/Migrate", - "/metalstack.admin.v2.SwitchService/Port", - "/metalstack.admin.v2.SwitchService/ConnectedMachines", - "/metalstack.admin.v2.TaskService/Get", - "/metalstack.admin.v2.TaskService/Delete", - "/metalstack.admin.v2.TaskService/Queues", - "/metalstack.admin.v2.TaskService/List", - "/metalstack.admin.v2.TenantService/Create", - "/metalstack.admin.v2.TenantService/List", - "/metalstack.admin.v2.TenantService/AddMember", - "/metalstack.admin.v2.TenantService/RemoveMember", - "/metalstack.admin.v2.TokenService/List", - "/metalstack.admin.v2.TokenService/Revoke", - "/metalstack.admin.v2.TokenService/Create", - "/metalstack.admin.v2.VPNService/AuthKey", - "/metalstack.admin.v2.VPNService/ListNodes", + "ADMIN_ROLE_EDITOR": map[string]struct{}{ + "/metalstack.admin.v2.AuditService/Get": {}, + "/metalstack.admin.v2.AuditService/List": {}, + "/metalstack.admin.v2.ComponentService/Delete": {}, + "/metalstack.admin.v2.ComponentService/Get": {}, + "/metalstack.admin.v2.ComponentService/List": {}, + "/metalstack.admin.v2.FilesystemService/Create": {}, + "/metalstack.admin.v2.FilesystemService/Delete": {}, + "/metalstack.admin.v2.FilesystemService/Match": {}, + "/metalstack.admin.v2.FilesystemService/Update": {}, + "/metalstack.admin.v2.IPService/List": {}, + "/metalstack.admin.v2.ImageService/Create": {}, + "/metalstack.admin.v2.ImageService/Delete": {}, + "/metalstack.admin.v2.ImageService/Update": {}, + "/metalstack.admin.v2.ImageService/Usage": {}, + "/metalstack.admin.v2.MachineService/BMCCommand": {}, + "/metalstack.admin.v2.MachineService/ConsolePassword": {}, + "/metalstack.admin.v2.MachineService/Delete": {}, + "/metalstack.admin.v2.MachineService/Get": {}, + "/metalstack.admin.v2.MachineService/GetBMC": {}, + "/metalstack.admin.v2.MachineService/Issues": {}, + "/metalstack.admin.v2.MachineService/List": {}, + "/metalstack.admin.v2.MachineService/ListBMC": {}, + "/metalstack.admin.v2.MachineService/SetState": {}, + "/metalstack.admin.v2.NetworkService/Create": {}, + "/metalstack.admin.v2.NetworkService/Delete": {}, + "/metalstack.admin.v2.NetworkService/Get": {}, + "/metalstack.admin.v2.NetworkService/List": {}, + "/metalstack.admin.v2.NetworkService/Update": {}, + "/metalstack.admin.v2.PartitionService/Capacity": {}, + "/metalstack.admin.v2.PartitionService/Create": {}, + "/metalstack.admin.v2.PartitionService/Delete": {}, + "/metalstack.admin.v2.PartitionService/Update": {}, + "/metalstack.admin.v2.ProjectService/List": {}, + "/metalstack.admin.v2.SizeImageConstraintService/Create": {}, + "/metalstack.admin.v2.SizeImageConstraintService/Delete": {}, + "/metalstack.admin.v2.SizeImageConstraintService/Get": {}, + "/metalstack.admin.v2.SizeImageConstraintService/List": {}, + "/metalstack.admin.v2.SizeImageConstraintService/Update": {}, + "/metalstack.admin.v2.SizeReservationService/Create": {}, + "/metalstack.admin.v2.SizeReservationService/Delete": {}, + "/metalstack.admin.v2.SizeReservationService/List": {}, + "/metalstack.admin.v2.SizeReservationService/Update": {}, + "/metalstack.admin.v2.SizeService/Create": {}, + "/metalstack.admin.v2.SizeService/Delete": {}, + "/metalstack.admin.v2.SizeService/Update": {}, + "/metalstack.admin.v2.SwitchService/ConnectedMachines": {}, + "/metalstack.admin.v2.SwitchService/Delete": {}, + "/metalstack.admin.v2.SwitchService/Get": {}, + "/metalstack.admin.v2.SwitchService/List": {}, + "/metalstack.admin.v2.SwitchService/Migrate": {}, + "/metalstack.admin.v2.SwitchService/Port": {}, + "/metalstack.admin.v2.SwitchService/Update": {}, + "/metalstack.admin.v2.TaskService/Delete": {}, + "/metalstack.admin.v2.TaskService/Get": {}, + "/metalstack.admin.v2.TaskService/List": {}, + "/metalstack.admin.v2.TaskService/Queues": {}, + "/metalstack.admin.v2.TenantService/AddMember": {}, + "/metalstack.admin.v2.TenantService/Create": {}, + "/metalstack.admin.v2.TenantService/List": {}, + "/metalstack.admin.v2.TenantService/RemoveMember": {}, + "/metalstack.admin.v2.TokenService/Create": {}, + "/metalstack.admin.v2.TokenService/List": {}, + "/metalstack.admin.v2.TokenService/Revoke": {}, + "/metalstack.admin.v2.VPNService/AuthKey": {}, + "/metalstack.admin.v2.VPNService/ListNodes": {}, }, - "ADMIN_ROLE_VIEWER": []string{ - "/metalstack.admin.v2.AuditService/Get", - "/metalstack.admin.v2.AuditService/List", - "/metalstack.admin.v2.ComponentService/Get", - "/metalstack.admin.v2.ComponentService/List", - "/metalstack.admin.v2.FilesystemService/Match", - "/metalstack.admin.v2.ImageService/Usage", - "/metalstack.admin.v2.IPService/List", - "/metalstack.admin.v2.MachineService/Get", - "/metalstack.admin.v2.MachineService/List", - "/metalstack.admin.v2.MachineService/GetBMC", - "/metalstack.admin.v2.MachineService/ListBMC", - "/metalstack.admin.v2.MachineService/ConsolePassword", - "/metalstack.admin.v2.MachineService/Issues", - "/metalstack.admin.v2.NetworkService/Get", - "/metalstack.admin.v2.NetworkService/List", - "/metalstack.admin.v2.PartitionService/Capacity", - "/metalstack.admin.v2.ProjectService/List", - "/metalstack.admin.v2.SizeImageConstraintService/Get", - "/metalstack.admin.v2.SizeImageConstraintService/List", - "/metalstack.admin.v2.SizeReservationService/List", - "/metalstack.admin.v2.SwitchService/Get", - "/metalstack.admin.v2.SwitchService/List", - "/metalstack.admin.v2.SwitchService/ConnectedMachines", - "/metalstack.admin.v2.TaskService/Get", - "/metalstack.admin.v2.TaskService/Queues", - "/metalstack.admin.v2.TaskService/List", - "/metalstack.admin.v2.TenantService/List", - "/metalstack.admin.v2.TokenService/List", - "/metalstack.admin.v2.VPNService/ListNodes", + "ADMIN_ROLE_VIEWER": map[string]struct{}{ + "/metalstack.admin.v2.AuditService/Get": {}, + "/metalstack.admin.v2.AuditService/List": {}, + "/metalstack.admin.v2.ComponentService/Get": {}, + "/metalstack.admin.v2.ComponentService/List": {}, + "/metalstack.admin.v2.FilesystemService/Match": {}, + "/metalstack.admin.v2.IPService/List": {}, + "/metalstack.admin.v2.ImageService/Usage": {}, + "/metalstack.admin.v2.MachineService/ConsolePassword": {}, + "/metalstack.admin.v2.MachineService/Get": {}, + "/metalstack.admin.v2.MachineService/GetBMC": {}, + "/metalstack.admin.v2.MachineService/Issues": {}, + "/metalstack.admin.v2.MachineService/List": {}, + "/metalstack.admin.v2.MachineService/ListBMC": {}, + "/metalstack.admin.v2.NetworkService/Get": {}, + "/metalstack.admin.v2.NetworkService/List": {}, + "/metalstack.admin.v2.PartitionService/Capacity": {}, + "/metalstack.admin.v2.ProjectService/List": {}, + "/metalstack.admin.v2.SizeImageConstraintService/Get": {}, + "/metalstack.admin.v2.SizeImageConstraintService/List": {}, + "/metalstack.admin.v2.SizeReservationService/List": {}, + "/metalstack.admin.v2.SwitchService/ConnectedMachines": {}, + "/metalstack.admin.v2.SwitchService/Get": {}, + "/metalstack.admin.v2.SwitchService/List": {}, + "/metalstack.admin.v2.TaskService/Get": {}, + "/metalstack.admin.v2.TaskService/List": {}, + "/metalstack.admin.v2.TaskService/Queues": {}, + "/metalstack.admin.v2.TenantService/List": {}, + "/metalstack.admin.v2.TokenService/List": {}, + "/metalstack.admin.v2.VPNService/ListNodes": {}, }, }, Infra: Infra{ - "INFRA_ROLE_EDITOR": []string{ - "/metalstack.infra.v2.BMCService/UpdateBMCInfo", - "/metalstack.infra.v2.BMCService/WaitForBMCCommand", - "/metalstack.infra.v2.BMCService/BMCCommandDone", - "/metalstack.infra.v2.BootService/Dhcp", - "/metalstack.infra.v2.BootService/Boot", - "/metalstack.infra.v2.ComponentService/Ping", - "/metalstack.infra.v2.EventService/Send", - "/metalstack.infra.v2.SwitchService/Get", - "/metalstack.infra.v2.SwitchService/Register", - "/metalstack.infra.v2.SwitchService/Heartbeat", + "INFRA_ROLE_EDITOR": map[string]struct{}{ + "/metalstack.infra.v2.BMCService/BMCCommandDone": {}, + "/metalstack.infra.v2.BMCService/UpdateBMCInfo": {}, + "/metalstack.infra.v2.BMCService/WaitForBMCCommand": {}, + "/metalstack.infra.v2.BootService/Boot": {}, + "/metalstack.infra.v2.BootService/Dhcp": {}, + "/metalstack.infra.v2.ComponentService/Ping": {}, + "/metalstack.infra.v2.EventService/Send": {}, + "/metalstack.infra.v2.SwitchService/Get": {}, + "/metalstack.infra.v2.SwitchService/Heartbeat": {}, + "/metalstack.infra.v2.SwitchService/Register": {}, }, - "INFRA_ROLE_VIEWER": []string{ - "/metalstack.infra.v2.SwitchService/Get", + "INFRA_ROLE_VIEWER": map[string]struct{}{ + "/metalstack.infra.v2.SwitchService/Get": {}, }, }, Machine: Machine{ - "MACHINE_ROLE_EDITOR": []string{ - "/metalstack.infra.v2.BootService/SuperUserPassword", - "/metalstack.infra.v2.BootService/Register", - "/metalstack.infra.v2.BootService/Wait", - "/metalstack.infra.v2.BootService/InstallationSucceeded", + "MACHINE_ROLE_EDITOR": map[string]struct{}{ + "/metalstack.infra.v2.BootService/InstallationSucceeded": {}, + "/metalstack.infra.v2.BootService/Register": {}, + "/metalstack.infra.v2.BootService/SuperUserPassword": {}, + "/metalstack.infra.v2.BootService/Wait": {}, }, }, Tenant: Tenant{ - "TENANT_ROLE_EDITOR": []string{ - "/metalstack.api.v2.ProjectService/Create", - "/metalstack.api.v2.TenantService/Get", - "/metalstack.api.v2.TenantService/Update", - "/metalstack.api.v2.TenantService/Delete", + "TENANT_ROLE_EDITOR": map[string]struct{}{ + "/metalstack.api.v2.ProjectService/Create": {}, + "/metalstack.api.v2.TenantService/Delete": {}, + "/metalstack.api.v2.TenantService/Get": {}, + "/metalstack.api.v2.TenantService/Update": {}, }, - "TENANT_ROLE_GUEST": []string{ - "/metalstack.api.v2.TenantService/Get", + "TENANT_ROLE_GUEST": map[string]struct{}{ + "/metalstack.api.v2.TenantService/Get": {}, }, - "TENANT_ROLE_OWNER": []string{ - "/metalstack.api.v2.AuditService/Get", - "/metalstack.api.v2.AuditService/List", - "/metalstack.api.v2.ProjectService/Create", - "/metalstack.api.v2.TenantService/Get", - "/metalstack.api.v2.TenantService/Update", - "/metalstack.api.v2.TenantService/Delete", - "/metalstack.api.v2.TenantService/RemoveMember", - "/metalstack.api.v2.TenantService/UpdateMember", - "/metalstack.api.v2.TenantService/Invite", - "/metalstack.api.v2.TenantService/InviteDelete", - "/metalstack.api.v2.TenantService/InvitesList", + "TENANT_ROLE_OWNER": map[string]struct{}{ + "/metalstack.api.v2.AuditService/Get": {}, + "/metalstack.api.v2.AuditService/List": {}, + "/metalstack.api.v2.ProjectService/Create": {}, + "/metalstack.api.v2.TenantService/Delete": {}, + "/metalstack.api.v2.TenantService/Get": {}, + "/metalstack.api.v2.TenantService/Invite": {}, + "/metalstack.api.v2.TenantService/InviteDelete": {}, + "/metalstack.api.v2.TenantService/InvitesList": {}, + "/metalstack.api.v2.TenantService/RemoveMember": {}, + "/metalstack.api.v2.TenantService/Update": {}, + "/metalstack.api.v2.TenantService/UpdateMember": {}, }, - "TENANT_ROLE_VIEWER": []string{ - "/metalstack.api.v2.TenantService/Get", - "/metalstack.api.v2.TenantService/Leave", + "TENANT_ROLE_VIEWER": map[string]struct{}{ + "/metalstack.api.v2.TenantService/Get": {}, + "/metalstack.api.v2.TenantService/Leave": {}, }, }, Project: Project{ - "PROJECT_ROLE_EDITOR": []string{ - "/metalstack.api.v2.IPService/Get", - "/metalstack.api.v2.IPService/Create", - "/metalstack.api.v2.IPService/Update", - "/metalstack.api.v2.IPService/List", - "/metalstack.api.v2.IPService/Delete", - "/metalstack.api.v2.MachineService/Get", - "/metalstack.api.v2.MachineService/Create", - "/metalstack.api.v2.MachineService/Update", - "/metalstack.api.v2.MachineService/List", - "/metalstack.api.v2.MachineService/Delete", - "/metalstack.api.v2.MachineService/BMCCommand", - "/metalstack.api.v2.MachineService/GetBMC", - "/metalstack.api.v2.NetworkService/Get", - "/metalstack.api.v2.NetworkService/Create", - "/metalstack.api.v2.NetworkService/Update", - "/metalstack.api.v2.NetworkService/List", - "/metalstack.api.v2.NetworkService/ListBaseNetworks", - "/metalstack.api.v2.NetworkService/Delete", - "/metalstack.api.v2.ProjectService/Get", - "/metalstack.api.v2.ProjectService/Update", - "/metalstack.api.v2.SizeReservationService/Get", - "/metalstack.api.v2.SizeReservationService/List", + "PROJECT_ROLE_EDITOR": map[string]struct{}{ + "/metalstack.api.v2.IPService/Create": {}, + "/metalstack.api.v2.IPService/Delete": {}, + "/metalstack.api.v2.IPService/Get": {}, + "/metalstack.api.v2.IPService/List": {}, + "/metalstack.api.v2.IPService/Update": {}, + "/metalstack.api.v2.MachineService/BMCCommand": {}, + "/metalstack.api.v2.MachineService/Create": {}, + "/metalstack.api.v2.MachineService/Delete": {}, + "/metalstack.api.v2.MachineService/Get": {}, + "/metalstack.api.v2.MachineService/GetBMC": {}, + "/metalstack.api.v2.MachineService/List": {}, + "/metalstack.api.v2.MachineService/Update": {}, + "/metalstack.api.v2.NetworkService/Create": {}, + "/metalstack.api.v2.NetworkService/Delete": {}, + "/metalstack.api.v2.NetworkService/Get": {}, + "/metalstack.api.v2.NetworkService/List": {}, + "/metalstack.api.v2.NetworkService/ListBaseNetworks": {}, + "/metalstack.api.v2.NetworkService/Update": {}, + "/metalstack.api.v2.ProjectService/Get": {}, + "/metalstack.api.v2.ProjectService/Update": {}, + "/metalstack.api.v2.SizeReservationService/Get": {}, + "/metalstack.api.v2.SizeReservationService/List": {}, }, - "PROJECT_ROLE_OWNER": []string{ - "/metalstack.api.v2.IPService/Get", - "/metalstack.api.v2.IPService/Create", - "/metalstack.api.v2.IPService/Update", - "/metalstack.api.v2.IPService/List", - "/metalstack.api.v2.IPService/Delete", - "/metalstack.api.v2.MachineService/Get", - "/metalstack.api.v2.MachineService/Create", - "/metalstack.api.v2.MachineService/Update", - "/metalstack.api.v2.MachineService/List", - "/metalstack.api.v2.MachineService/Delete", - "/metalstack.api.v2.MachineService/BMCCommand", - "/metalstack.api.v2.MachineService/GetBMC", - "/metalstack.api.v2.NetworkService/Get", - "/metalstack.api.v2.NetworkService/Create", - "/metalstack.api.v2.NetworkService/Update", - "/metalstack.api.v2.NetworkService/List", - "/metalstack.api.v2.NetworkService/ListBaseNetworks", - "/metalstack.api.v2.NetworkService/Delete", - "/metalstack.api.v2.ProjectService/Get", - "/metalstack.api.v2.ProjectService/Delete", - "/metalstack.api.v2.ProjectService/Update", - "/metalstack.api.v2.ProjectService/RemoveMember", - "/metalstack.api.v2.ProjectService/UpdateMember", - "/metalstack.api.v2.ProjectService/Invite", - "/metalstack.api.v2.ProjectService/InviteDelete", - "/metalstack.api.v2.ProjectService/InvitesList", - "/metalstack.api.v2.SizeReservationService/Get", - "/metalstack.api.v2.SizeReservationService/List", + "PROJECT_ROLE_OWNER": map[string]struct{}{ + "/metalstack.api.v2.IPService/Create": {}, + "/metalstack.api.v2.IPService/Delete": {}, + "/metalstack.api.v2.IPService/Get": {}, + "/metalstack.api.v2.IPService/List": {}, + "/metalstack.api.v2.IPService/Update": {}, + "/metalstack.api.v2.MachineService/BMCCommand": {}, + "/metalstack.api.v2.MachineService/Create": {}, + "/metalstack.api.v2.MachineService/Delete": {}, + "/metalstack.api.v2.MachineService/Get": {}, + "/metalstack.api.v2.MachineService/GetBMC": {}, + "/metalstack.api.v2.MachineService/List": {}, + "/metalstack.api.v2.MachineService/Update": {}, + "/metalstack.api.v2.NetworkService/Create": {}, + "/metalstack.api.v2.NetworkService/Delete": {}, + "/metalstack.api.v2.NetworkService/Get": {}, + "/metalstack.api.v2.NetworkService/List": {}, + "/metalstack.api.v2.NetworkService/ListBaseNetworks": {}, + "/metalstack.api.v2.NetworkService/Update": {}, + "/metalstack.api.v2.ProjectService/Delete": {}, + "/metalstack.api.v2.ProjectService/Get": {}, + "/metalstack.api.v2.ProjectService/Invite": {}, + "/metalstack.api.v2.ProjectService/InviteDelete": {}, + "/metalstack.api.v2.ProjectService/InvitesList": {}, + "/metalstack.api.v2.ProjectService/RemoveMember": {}, + "/metalstack.api.v2.ProjectService/Update": {}, + "/metalstack.api.v2.ProjectService/UpdateMember": {}, + "/metalstack.api.v2.SizeReservationService/Get": {}, + "/metalstack.api.v2.SizeReservationService/List": {}, }, - "PROJECT_ROLE_VIEWER": []string{ - "/metalstack.api.v2.IPService/Get", - "/metalstack.api.v2.IPService/List", - "/metalstack.api.v2.MachineService/Get", - "/metalstack.api.v2.MachineService/List", - "/metalstack.api.v2.NetworkService/Get", - "/metalstack.api.v2.NetworkService/List", - "/metalstack.api.v2.NetworkService/ListBaseNetworks", - "/metalstack.api.v2.ProjectService/Get", - "/metalstack.api.v2.ProjectService/Leave", - "/metalstack.api.v2.SizeReservationService/Get", - "/metalstack.api.v2.SizeReservationService/List", + "PROJECT_ROLE_VIEWER": map[string]struct{}{ + "/metalstack.api.v2.IPService/Get": {}, + "/metalstack.api.v2.IPService/List": {}, + "/metalstack.api.v2.MachineService/Get": {}, + "/metalstack.api.v2.MachineService/List": {}, + "/metalstack.api.v2.NetworkService/Get": {}, + "/metalstack.api.v2.NetworkService/List": {}, + "/metalstack.api.v2.NetworkService/ListBaseNetworks": {}, + "/metalstack.api.v2.ProjectService/Get": {}, + "/metalstack.api.v2.ProjectService/Leave": {}, + "/metalstack.api.v2.SizeReservationService/Get": {}, + "/metalstack.api.v2.SizeReservationService/List": {}, }, }, }, - Methods: map[string]bool{ - "/grpc.reflection.v1.ServerReflection/ServerReflectionInfo": true, - "/grpc.reflection.v1alpha.ServerReflection/ServerReflectionInfo": true, - "/metalstack.admin.v2.AuditService/Get": true, - "/metalstack.admin.v2.AuditService/List": true, - "/metalstack.admin.v2.ComponentService/Delete": true, - "/metalstack.admin.v2.ComponentService/Get": true, - "/metalstack.admin.v2.ComponentService/List": true, - "/metalstack.admin.v2.FilesystemService/Create": true, - "/metalstack.admin.v2.FilesystemService/Delete": true, - "/metalstack.admin.v2.FilesystemService/Match": true, - "/metalstack.admin.v2.FilesystemService/Update": true, - "/metalstack.admin.v2.IPService/List": true, - "/metalstack.admin.v2.ImageService/Create": true, - "/metalstack.admin.v2.ImageService/Delete": true, - "/metalstack.admin.v2.ImageService/Update": true, - "/metalstack.admin.v2.ImageService/Usage": true, - "/metalstack.admin.v2.MachineService/BMCCommand": true, - "/metalstack.admin.v2.MachineService/ConsolePassword": true, - "/metalstack.admin.v2.MachineService/Delete": true, - "/metalstack.admin.v2.MachineService/Get": true, - "/metalstack.admin.v2.MachineService/GetBMC": true, - "/metalstack.admin.v2.MachineService/Issues": true, - "/metalstack.admin.v2.MachineService/List": true, - "/metalstack.admin.v2.MachineService/ListBMC": true, - "/metalstack.admin.v2.MachineService/SetState": true, - "/metalstack.admin.v2.NetworkService/Create": true, - "/metalstack.admin.v2.NetworkService/Delete": true, - "/metalstack.admin.v2.NetworkService/Get": true, - "/metalstack.admin.v2.NetworkService/List": true, - "/metalstack.admin.v2.NetworkService/Update": true, - "/metalstack.admin.v2.PartitionService/Capacity": true, - "/metalstack.admin.v2.PartitionService/Create": true, - "/metalstack.admin.v2.PartitionService/Delete": true, - "/metalstack.admin.v2.PartitionService/Update": true, - "/metalstack.admin.v2.ProjectService/List": true, - "/metalstack.admin.v2.SizeImageConstraintService/Create": true, - "/metalstack.admin.v2.SizeImageConstraintService/Delete": true, - "/metalstack.admin.v2.SizeImageConstraintService/Get": true, - "/metalstack.admin.v2.SizeImageConstraintService/List": true, - "/metalstack.admin.v2.SizeImageConstraintService/Update": true, - "/metalstack.admin.v2.SizeReservationService/Create": true, - "/metalstack.admin.v2.SizeReservationService/Delete": true, - "/metalstack.admin.v2.SizeReservationService/List": true, - "/metalstack.admin.v2.SizeReservationService/Update": true, - "/metalstack.admin.v2.SizeService/Create": true, - "/metalstack.admin.v2.SizeService/Delete": true, - "/metalstack.admin.v2.SizeService/Update": true, - "/metalstack.admin.v2.SwitchService/ConnectedMachines": true, - "/metalstack.admin.v2.SwitchService/Delete": true, - "/metalstack.admin.v2.SwitchService/Get": true, - "/metalstack.admin.v2.SwitchService/List": true, - "/metalstack.admin.v2.SwitchService/Migrate": true, - "/metalstack.admin.v2.SwitchService/Port": true, - "/metalstack.admin.v2.SwitchService/Update": true, - "/metalstack.admin.v2.TaskService/Delete": true, - "/metalstack.admin.v2.TaskService/Get": true, - "/metalstack.admin.v2.TaskService/List": true, - "/metalstack.admin.v2.TaskService/Queues": true, - "/metalstack.admin.v2.TenantService/AddMember": true, - "/metalstack.admin.v2.TenantService/Create": true, - "/metalstack.admin.v2.TenantService/List": true, - "/metalstack.admin.v2.TenantService/RemoveMember": true, - "/metalstack.admin.v2.TokenService/Create": true, - "/metalstack.admin.v2.TokenService/List": true, - "/metalstack.admin.v2.TokenService/Revoke": true, - "/metalstack.admin.v2.VPNService/AuthKey": true, - "/metalstack.admin.v2.VPNService/ListNodes": true, - "/metalstack.api.v2.AuditService/Get": true, - "/metalstack.api.v2.AuditService/List": true, - "/metalstack.api.v2.FilesystemService/Get": true, - "/metalstack.api.v2.FilesystemService/List": true, - "/metalstack.api.v2.HealthService/Get": true, - "/metalstack.api.v2.IPService/Create": true, - "/metalstack.api.v2.IPService/Delete": true, - "/metalstack.api.v2.IPService/Get": true, - "/metalstack.api.v2.IPService/List": true, - "/metalstack.api.v2.IPService/Update": true, - "/metalstack.api.v2.ImageService/Get": true, - "/metalstack.api.v2.ImageService/Latest": true, - "/metalstack.api.v2.ImageService/List": true, - "/metalstack.api.v2.MachineService/BMCCommand": true, - "/metalstack.api.v2.MachineService/Create": true, - "/metalstack.api.v2.MachineService/Delete": true, - "/metalstack.api.v2.MachineService/Get": true, - "/metalstack.api.v2.MachineService/GetBMC": true, - "/metalstack.api.v2.MachineService/List": true, - "/metalstack.api.v2.MachineService/Update": true, - "/metalstack.api.v2.MethodService/List": true, - "/metalstack.api.v2.MethodService/TokenScopedList": true, - "/metalstack.api.v2.NetworkService/Create": true, - "/metalstack.api.v2.NetworkService/Delete": true, - "/metalstack.api.v2.NetworkService/Get": true, - "/metalstack.api.v2.NetworkService/List": true, - "/metalstack.api.v2.NetworkService/ListBaseNetworks": true, - "/metalstack.api.v2.NetworkService/Update": true, - "/metalstack.api.v2.PartitionService/Get": true, - "/metalstack.api.v2.PartitionService/List": true, - "/metalstack.api.v2.ProjectService/Create": true, - "/metalstack.api.v2.ProjectService/Delete": true, - "/metalstack.api.v2.ProjectService/Get": true, - "/metalstack.api.v2.ProjectService/Invite": true, - "/metalstack.api.v2.ProjectService/InviteAccept": true, - "/metalstack.api.v2.ProjectService/InviteDelete": true, - "/metalstack.api.v2.ProjectService/InviteGet": true, - "/metalstack.api.v2.ProjectService/InvitesList": true, - "/metalstack.api.v2.ProjectService/Leave": true, - "/metalstack.api.v2.ProjectService/List": true, - "/metalstack.api.v2.ProjectService/RemoveMember": true, - "/metalstack.api.v2.ProjectService/Update": true, - "/metalstack.api.v2.ProjectService/UpdateMember": true, - "/metalstack.api.v2.SizeImageConstraintService/Try": true, - "/metalstack.api.v2.SizeReservationService/Get": true, - "/metalstack.api.v2.SizeReservationService/List": true, - "/metalstack.api.v2.SizeService/Get": true, - "/metalstack.api.v2.SizeService/List": true, - "/metalstack.api.v2.TenantService/Create": true, - "/metalstack.api.v2.TenantService/Delete": true, - "/metalstack.api.v2.TenantService/Get": true, - "/metalstack.api.v2.TenantService/Invite": true, - "/metalstack.api.v2.TenantService/InviteAccept": true, - "/metalstack.api.v2.TenantService/InviteDelete": true, - "/metalstack.api.v2.TenantService/InviteGet": true, - "/metalstack.api.v2.TenantService/InvitesList": true, - "/metalstack.api.v2.TenantService/Leave": true, - "/metalstack.api.v2.TenantService/List": true, - "/metalstack.api.v2.TenantService/RemoveMember": true, - "/metalstack.api.v2.TenantService/Update": true, - "/metalstack.api.v2.TenantService/UpdateMember": true, - "/metalstack.api.v2.TokenService/Create": true, - "/metalstack.api.v2.TokenService/Get": true, - "/metalstack.api.v2.TokenService/List": true, - "/metalstack.api.v2.TokenService/Refresh": true, - "/metalstack.api.v2.TokenService/Revoke": true, - "/metalstack.api.v2.TokenService/Update": true, - "/metalstack.api.v2.UserService/Get": true, - "/metalstack.api.v2.VersionService/Get": true, - "/metalstack.infra.v2.BMCService/BMCCommandDone": true, - "/metalstack.infra.v2.BMCService/UpdateBMCInfo": true, - "/metalstack.infra.v2.BMCService/WaitForBMCCommand": true, - "/metalstack.infra.v2.BootService/Boot": true, - "/metalstack.infra.v2.BootService/Dhcp": true, - "/metalstack.infra.v2.BootService/InstallationSucceeded": true, - "/metalstack.infra.v2.BootService/Register": true, - "/metalstack.infra.v2.BootService/SuperUserPassword": true, - "/metalstack.infra.v2.BootService/Wait": true, - "/metalstack.infra.v2.ComponentService/Ping": true, - "/metalstack.infra.v2.EventService/Send": true, - "/metalstack.infra.v2.SwitchService/Get": true, - "/metalstack.infra.v2.SwitchService/Heartbeat": true, - "/metalstack.infra.v2.SwitchService/Register": true, + Methods: map[string]struct{}{ + "/grpc.reflection.v1.ServerReflection/ServerReflectionInfo": {}, + "/grpc.reflection.v1alpha.ServerReflection/ServerReflectionInfo": {}, + "/metalstack.admin.v2.AuditService/Get": {}, + "/metalstack.admin.v2.AuditService/List": {}, + "/metalstack.admin.v2.ComponentService/Delete": {}, + "/metalstack.admin.v2.ComponentService/Get": {}, + "/metalstack.admin.v2.ComponentService/List": {}, + "/metalstack.admin.v2.FilesystemService/Create": {}, + "/metalstack.admin.v2.FilesystemService/Delete": {}, + "/metalstack.admin.v2.FilesystemService/Match": {}, + "/metalstack.admin.v2.FilesystemService/Update": {}, + "/metalstack.admin.v2.IPService/List": {}, + "/metalstack.admin.v2.ImageService/Create": {}, + "/metalstack.admin.v2.ImageService/Delete": {}, + "/metalstack.admin.v2.ImageService/Update": {}, + "/metalstack.admin.v2.ImageService/Usage": {}, + "/metalstack.admin.v2.MachineService/BMCCommand": {}, + "/metalstack.admin.v2.MachineService/ConsolePassword": {}, + "/metalstack.admin.v2.MachineService/Delete": {}, + "/metalstack.admin.v2.MachineService/Get": {}, + "/metalstack.admin.v2.MachineService/GetBMC": {}, + "/metalstack.admin.v2.MachineService/Issues": {}, + "/metalstack.admin.v2.MachineService/List": {}, + "/metalstack.admin.v2.MachineService/ListBMC": {}, + "/metalstack.admin.v2.MachineService/SetState": {}, + "/metalstack.admin.v2.NetworkService/Create": {}, + "/metalstack.admin.v2.NetworkService/Delete": {}, + "/metalstack.admin.v2.NetworkService/Get": {}, + "/metalstack.admin.v2.NetworkService/List": {}, + "/metalstack.admin.v2.NetworkService/Update": {}, + "/metalstack.admin.v2.PartitionService/Capacity": {}, + "/metalstack.admin.v2.PartitionService/Create": {}, + "/metalstack.admin.v2.PartitionService/Delete": {}, + "/metalstack.admin.v2.PartitionService/Update": {}, + "/metalstack.admin.v2.ProjectService/List": {}, + "/metalstack.admin.v2.SizeImageConstraintService/Create": {}, + "/metalstack.admin.v2.SizeImageConstraintService/Delete": {}, + "/metalstack.admin.v2.SizeImageConstraintService/Get": {}, + "/metalstack.admin.v2.SizeImageConstraintService/List": {}, + "/metalstack.admin.v2.SizeImageConstraintService/Update": {}, + "/metalstack.admin.v2.SizeReservationService/Create": {}, + "/metalstack.admin.v2.SizeReservationService/Delete": {}, + "/metalstack.admin.v2.SizeReservationService/List": {}, + "/metalstack.admin.v2.SizeReservationService/Update": {}, + "/metalstack.admin.v2.SizeService/Create": {}, + "/metalstack.admin.v2.SizeService/Delete": {}, + "/metalstack.admin.v2.SizeService/Update": {}, + "/metalstack.admin.v2.SwitchService/ConnectedMachines": {}, + "/metalstack.admin.v2.SwitchService/Delete": {}, + "/metalstack.admin.v2.SwitchService/Get": {}, + "/metalstack.admin.v2.SwitchService/List": {}, + "/metalstack.admin.v2.SwitchService/Migrate": {}, + "/metalstack.admin.v2.SwitchService/Port": {}, + "/metalstack.admin.v2.SwitchService/Update": {}, + "/metalstack.admin.v2.TaskService/Delete": {}, + "/metalstack.admin.v2.TaskService/Get": {}, + "/metalstack.admin.v2.TaskService/List": {}, + "/metalstack.admin.v2.TaskService/Queues": {}, + "/metalstack.admin.v2.TenantService/AddMember": {}, + "/metalstack.admin.v2.TenantService/Create": {}, + "/metalstack.admin.v2.TenantService/List": {}, + "/metalstack.admin.v2.TenantService/RemoveMember": {}, + "/metalstack.admin.v2.TokenService/Create": {}, + "/metalstack.admin.v2.TokenService/List": {}, + "/metalstack.admin.v2.TokenService/Revoke": {}, + "/metalstack.admin.v2.VPNService/AuthKey": {}, + "/metalstack.admin.v2.VPNService/ListNodes": {}, + "/metalstack.api.v2.AuditService/Get": {}, + "/metalstack.api.v2.AuditService/List": {}, + "/metalstack.api.v2.FilesystemService/Get": {}, + "/metalstack.api.v2.FilesystemService/List": {}, + "/metalstack.api.v2.HealthService/Get": {}, + "/metalstack.api.v2.IPService/Create": {}, + "/metalstack.api.v2.IPService/Delete": {}, + "/metalstack.api.v2.IPService/Get": {}, + "/metalstack.api.v2.IPService/List": {}, + "/metalstack.api.v2.IPService/Update": {}, + "/metalstack.api.v2.ImageService/Get": {}, + "/metalstack.api.v2.ImageService/Latest": {}, + "/metalstack.api.v2.ImageService/List": {}, + "/metalstack.api.v2.MachineService/BMCCommand": {}, + "/metalstack.api.v2.MachineService/Create": {}, + "/metalstack.api.v2.MachineService/Delete": {}, + "/metalstack.api.v2.MachineService/Get": {}, + "/metalstack.api.v2.MachineService/GetBMC": {}, + "/metalstack.api.v2.MachineService/List": {}, + "/metalstack.api.v2.MachineService/Update": {}, + "/metalstack.api.v2.MethodService/List": {}, + "/metalstack.api.v2.MethodService/TokenScopedList": {}, + "/metalstack.api.v2.NetworkService/Create": {}, + "/metalstack.api.v2.NetworkService/Delete": {}, + "/metalstack.api.v2.NetworkService/Get": {}, + "/metalstack.api.v2.NetworkService/List": {}, + "/metalstack.api.v2.NetworkService/ListBaseNetworks": {}, + "/metalstack.api.v2.NetworkService/Update": {}, + "/metalstack.api.v2.PartitionService/Get": {}, + "/metalstack.api.v2.PartitionService/List": {}, + "/metalstack.api.v2.ProjectService/Create": {}, + "/metalstack.api.v2.ProjectService/Delete": {}, + "/metalstack.api.v2.ProjectService/Get": {}, + "/metalstack.api.v2.ProjectService/Invite": {}, + "/metalstack.api.v2.ProjectService/InviteAccept": {}, + "/metalstack.api.v2.ProjectService/InviteDelete": {}, + "/metalstack.api.v2.ProjectService/InviteGet": {}, + "/metalstack.api.v2.ProjectService/InvitesList": {}, + "/metalstack.api.v2.ProjectService/Leave": {}, + "/metalstack.api.v2.ProjectService/List": {}, + "/metalstack.api.v2.ProjectService/RemoveMember": {}, + "/metalstack.api.v2.ProjectService/Update": {}, + "/metalstack.api.v2.ProjectService/UpdateMember": {}, + "/metalstack.api.v2.SizeImageConstraintService/Try": {}, + "/metalstack.api.v2.SizeReservationService/Get": {}, + "/metalstack.api.v2.SizeReservationService/List": {}, + "/metalstack.api.v2.SizeService/Get": {}, + "/metalstack.api.v2.SizeService/List": {}, + "/metalstack.api.v2.TenantService/Create": {}, + "/metalstack.api.v2.TenantService/Delete": {}, + "/metalstack.api.v2.TenantService/Get": {}, + "/metalstack.api.v2.TenantService/Invite": {}, + "/metalstack.api.v2.TenantService/InviteAccept": {}, + "/metalstack.api.v2.TenantService/InviteDelete": {}, + "/metalstack.api.v2.TenantService/InviteGet": {}, + "/metalstack.api.v2.TenantService/InvitesList": {}, + "/metalstack.api.v2.TenantService/Leave": {}, + "/metalstack.api.v2.TenantService/List": {}, + "/metalstack.api.v2.TenantService/RemoveMember": {}, + "/metalstack.api.v2.TenantService/Update": {}, + "/metalstack.api.v2.TenantService/UpdateMember": {}, + "/metalstack.api.v2.TokenService/Create": {}, + "/metalstack.api.v2.TokenService/Get": {}, + "/metalstack.api.v2.TokenService/List": {}, + "/metalstack.api.v2.TokenService/Refresh": {}, + "/metalstack.api.v2.TokenService/Revoke": {}, + "/metalstack.api.v2.TokenService/Update": {}, + "/metalstack.api.v2.UserService/Get": {}, + "/metalstack.api.v2.VersionService/Get": {}, + "/metalstack.infra.v2.BMCService/BMCCommandDone": {}, + "/metalstack.infra.v2.BMCService/UpdateBMCInfo": {}, + "/metalstack.infra.v2.BMCService/WaitForBMCCommand": {}, + "/metalstack.infra.v2.BootService/Boot": {}, + "/metalstack.infra.v2.BootService/Dhcp": {}, + "/metalstack.infra.v2.BootService/InstallationSucceeded": {}, + "/metalstack.infra.v2.BootService/Register": {}, + "/metalstack.infra.v2.BootService/SuperUserPassword": {}, + "/metalstack.infra.v2.BootService/Wait": {}, + "/metalstack.infra.v2.ComponentService/Ping": {}, + "/metalstack.infra.v2.EventService/Send": {}, + "/metalstack.infra.v2.SwitchService/Get": {}, + "/metalstack.infra.v2.SwitchService/Heartbeat": {}, + "/metalstack.infra.v2.SwitchService/Register": {}, }, Visibility: Visibility{ Public: map[string]bool{ From 868357e31a137d550b5cfdee0553e5ec251df574 Mon Sep 17 00:00:00 2001 From: Stefan Majer Date: Wed, 15 Jul 2026 08:39:46 +0200 Subject: [PATCH 2/3] Typed keys --- generate/generate.go | 36 ++++++++++++-------- generate/go_servicepermissions.tpl | 11 +++--- go/permissions/permissions.go | 12 ++++--- go/permissions/servicepermissions.go | 51 ++++++++++++++-------------- 4 files changed, 60 insertions(+), 50 deletions(-) diff --git a/generate/generate.go b/generate/generate.go index 35f645f9..99ef1649 100644 --- a/generate/generate.go +++ b/generate/generate.go @@ -12,6 +12,7 @@ import ( "strings" sprig "github.com/go-task/slim-sprig/v3" + apiv2 "github.com/metal-stack/api/go/metalstack/api/v2" v1 "github.com/metal-stack/api/go/metalstack/api/v2" "github.com/metal-stack/api/go/permissions" "github.com/metal-stack/api/go/tests/protoparser" @@ -150,46 +151,51 @@ func servicePermissions(root string) (*permissions.ServicePermissions, error) { // Tenant switch role := *methodOpt.IdentifierValue; role { case v1.TenantRole_TENANT_ROLE_OWNER.String(), v1.TenantRole_TENANT_ROLE_EDITOR.String(), v1.TenantRole_TENANT_ROLE_VIEWER.String(), v1.TenantRole_TENANT_ROLE_GUEST.String(): - if methods := roles.Tenant[role]; methods == nil { - roles.Tenant[role] = permissions.Methods{} + apirole := apiv2.TenantRole(apiv2.TenantRole_value[role]) + if methods := roles.Tenant[apirole]; methods == nil { + roles.Tenant[apirole] = permissions.Methods{} } - roles.Tenant[role][methodName] = struct{}{} + roles.Tenant[apirole][methodName] = struct{}{} visibility.Tenant[methodName] = true case v1.TenantRole_TENANT_ROLE_UNSPECIFIED.String(): // noop // Project case v1.ProjectRole_PROJECT_ROLE_OWNER.String(), v1.ProjectRole_PROJECT_ROLE_EDITOR.String(), v1.ProjectRole_PROJECT_ROLE_VIEWER.String(): - if methods := roles.Project[role]; methods == nil { - roles.Project[role] = permissions.Methods{} + apirole := apiv2.ProjectRole(apiv2.ProjectRole_value[role]) + if methods := roles.Project[apirole]; methods == nil { + roles.Project[apirole] = permissions.Methods{} } - roles.Project[role][methodName] = struct{}{} + roles.Project[apirole][methodName] = struct{}{} visibility.Project[methodName] = true case v1.ProjectRole_PROJECT_ROLE_UNSPECIFIED.String(): // noop // Admin case v1.AdminRole_ADMIN_ROLE_EDITOR.String(), v1.AdminRole_ADMIN_ROLE_VIEWER.String(): - if methods := roles.Admin[role]; methods == nil { - roles.Admin[role] = permissions.Methods{} + apirole := apiv2.AdminRole(apiv2.AdminRole_value[role]) + if methods := roles.Admin[apirole]; methods == nil { + roles.Admin[apirole] = permissions.Methods{} } - roles.Admin[role][methodName] = struct{}{} + roles.Admin[apirole][methodName] = struct{}{} visibility.Admin[methodName] = true case v1.AdminRole_ADMIN_ROLE_UNSPECIFIED.String(): // noop // Infra case v1.InfraRole_INFRA_ROLE_EDITOR.String(), v1.InfraRole_INFRA_ROLE_VIEWER.String(): - if methods := roles.Infra[role]; methods == nil { - roles.Infra[role] = permissions.Methods{} + apirole := apiv2.InfraRole(apiv2.InfraRole_value[role]) + if methods := roles.Infra[apirole]; methods == nil { + roles.Infra[apirole] = permissions.Methods{} } - roles.Infra[role][methodName] = struct{}{} + roles.Infra[apirole][methodName] = struct{}{} visibility.Infra[methodName] = true case v1.InfraRole_INFRA_ROLE_UNSPECIFIED.String(): // noop // Machine case v1.MachineRole_MACHINE_ROLE_EDITOR.String(), v1.MachineRole_MACHINE_ROLE_VIEWER.String(): - if methods := roles.Machine[role]; methods == nil { - roles.Machine[role] = permissions.Methods{} + apirole := apiv2.MachineRole(apiv2.MachineRole_value[role]) + if methods := roles.Machine[apirole]; methods == nil { + roles.Machine[apirole] = permissions.Methods{} } - roles.Machine[role][methodName] = struct{}{} + roles.Machine[apirole][methodName] = struct{}{} visibility.Machine[methodName] = true case v1.MachineRole_MACHINE_ROLE_UNSPECIFIED.String(): // noop diff --git a/generate/go_servicepermissions.tpl b/generate/go_servicepermissions.tpl index 6dc21527..650d2c46 100644 --- a/generate/go_servicepermissions.tpl +++ b/generate/go_servicepermissions.tpl @@ -2,6 +2,7 @@ package permissions import ( + apiv2 "github.com/metal-stack/api/go/metalstack/api/v2" "connectrpc.com/connect" ) @@ -18,7 +19,7 @@ func GetServicePermissions() *ServicePermissions { Roles: Roles{ Admin: Admin{ {{- range $role, $methods := .Roles.Admin }} - "{{ $role }}": map[string]struct{}{ + apiv2.AdminRole_{{ $role }}: map[string]struct{}{ {{- range $method,$v := $methods }} "{{ $method }}":{{ $v }}, {{- end }} @@ -27,7 +28,7 @@ func GetServicePermissions() *ServicePermissions { }, Infra: Infra{ {{- range $role, $methods := .Roles.Infra }} - "{{ $role }}": map[string]struct{}{ + apiv2.InfraRole_{{ $role }}: map[string]struct{}{ {{- range $method,$v := $methods }} "{{ $method }}":{{ $v }}, {{- end }} @@ -36,7 +37,7 @@ func GetServicePermissions() *ServicePermissions { }, Machine: Machine{ {{- range $role, $methods := .Roles.Machine }} - "{{ $role }}": map[string]struct{}{ + apiv2.MachineRole_{{ $role }}: map[string]struct{}{ {{- range $method,$v := $methods }} "{{ $method }}":{{ $v }}, {{- end }} @@ -45,7 +46,7 @@ func GetServicePermissions() *ServicePermissions { }, Tenant: Tenant{ {{- range $role, $methods := .Roles.Tenant }} - "{{ $role }}": map[string]struct{}{ + apiv2.TenantRole_{{ $role }}: map[string]struct{}{ {{- range $method,$v := $methods }} "{{ $method }}":{{ $v }}, {{- end }} @@ -54,7 +55,7 @@ func GetServicePermissions() *ServicePermissions { }, Project: Project{ {{- range $role, $methods := .Roles.Project }} - "{{ $role }}": map[string]struct{}{ + apiv2.ProjectRole_{{ $role }}: map[string]struct{}{ {{- range $method,$v := $methods }} "{{ $method }}":{{ $v }}, {{- end }} diff --git a/go/permissions/permissions.go b/go/permissions/permissions.go index ee8ca8dd..21f30a2b 100644 --- a/go/permissions/permissions.go +++ b/go/permissions/permissions.go @@ -2,6 +2,8 @@ package permissions import ( _ "embed" + + apiv2 "github.com/metal-stack/api/go/metalstack/api/v2" ) type ( @@ -18,11 +20,11 @@ type ( Chargeable map[string]bool Auditable map[string]bool - Admin map[string]Methods - Infra map[string]Methods - Machine map[string]Methods - Tenant map[string]Methods - Project map[string]Methods + Admin map[apiv2.AdminRole]Methods + Infra map[apiv2.InfraRole]Methods + Machine map[apiv2.MachineRole]Methods + Tenant map[apiv2.TenantRole]Methods + Project map[apiv2.ProjectRole]Methods // Roles Roles struct { diff --git a/go/permissions/servicepermissions.go b/go/permissions/servicepermissions.go index 9f64d536..ce45802f 100755 --- a/go/permissions/servicepermissions.go +++ b/go/permissions/servicepermissions.go @@ -3,6 +3,7 @@ package permissions import ( "connectrpc.com/connect" + apiv2 "github.com/metal-stack/api/go/metalstack/api/v2" ) func GetServices() []string { @@ -53,7 +54,7 @@ func GetServicePermissions() *ServicePermissions { return &ServicePermissions{ Roles: Roles{ Admin: Admin{ - "ADMIN_ROLE_EDITOR": map[string]struct{}{ + apiv2.AdminRole_ADMIN_ROLE_EDITOR: map[string]struct{}{ "/metalstack.admin.v2.AuditService/Get": {}, "/metalstack.admin.v2.AuditService/List": {}, "/metalstack.admin.v2.ComponentService/Delete": {}, @@ -120,7 +121,7 @@ func GetServicePermissions() *ServicePermissions { "/metalstack.admin.v2.VPNService/AuthKey": {}, "/metalstack.admin.v2.VPNService/ListNodes": {}, }, - "ADMIN_ROLE_VIEWER": map[string]struct{}{ + apiv2.AdminRole_ADMIN_ROLE_VIEWER: map[string]struct{}{ "/metalstack.admin.v2.AuditService/Get": {}, "/metalstack.admin.v2.AuditService/List": {}, "/metalstack.admin.v2.ComponentService/Get": {}, @@ -153,7 +154,7 @@ func GetServicePermissions() *ServicePermissions { }, }, Infra: Infra{ - "INFRA_ROLE_EDITOR": map[string]struct{}{ + apiv2.InfraRole_INFRA_ROLE_EDITOR: map[string]struct{}{ "/metalstack.infra.v2.BMCService/BMCCommandDone": {}, "/metalstack.infra.v2.BMCService/UpdateBMCInfo": {}, "/metalstack.infra.v2.BMCService/WaitForBMCCommand": {}, @@ -165,12 +166,12 @@ func GetServicePermissions() *ServicePermissions { "/metalstack.infra.v2.SwitchService/Heartbeat": {}, "/metalstack.infra.v2.SwitchService/Register": {}, }, - "INFRA_ROLE_VIEWER": map[string]struct{}{ + apiv2.InfraRole_INFRA_ROLE_VIEWER: map[string]struct{}{ "/metalstack.infra.v2.SwitchService/Get": {}, }, }, Machine: Machine{ - "MACHINE_ROLE_EDITOR": map[string]struct{}{ + apiv2.MachineRole_MACHINE_ROLE_EDITOR: map[string]struct{}{ "/metalstack.infra.v2.BootService/InstallationSucceeded": {}, "/metalstack.infra.v2.BootService/Register": {}, "/metalstack.infra.v2.BootService/SuperUserPassword": {}, @@ -178,16 +179,7 @@ func GetServicePermissions() *ServicePermissions { }, }, Tenant: Tenant{ - "TENANT_ROLE_EDITOR": map[string]struct{}{ - "/metalstack.api.v2.ProjectService/Create": {}, - "/metalstack.api.v2.TenantService/Delete": {}, - "/metalstack.api.v2.TenantService/Get": {}, - "/metalstack.api.v2.TenantService/Update": {}, - }, - "TENANT_ROLE_GUEST": map[string]struct{}{ - "/metalstack.api.v2.TenantService/Get": {}, - }, - "TENANT_ROLE_OWNER": map[string]struct{}{ + apiv2.TenantRole_TENANT_ROLE_OWNER: map[string]struct{}{ "/metalstack.api.v2.AuditService/Get": {}, "/metalstack.api.v2.AuditService/List": {}, "/metalstack.api.v2.ProjectService/Create": {}, @@ -200,13 +192,22 @@ func GetServicePermissions() *ServicePermissions { "/metalstack.api.v2.TenantService/Update": {}, "/metalstack.api.v2.TenantService/UpdateMember": {}, }, - "TENANT_ROLE_VIEWER": map[string]struct{}{ + apiv2.TenantRole_TENANT_ROLE_EDITOR: map[string]struct{}{ + "/metalstack.api.v2.ProjectService/Create": {}, + "/metalstack.api.v2.TenantService/Delete": {}, + "/metalstack.api.v2.TenantService/Get": {}, + "/metalstack.api.v2.TenantService/Update": {}, + }, + apiv2.TenantRole_TENANT_ROLE_VIEWER: map[string]struct{}{ "/metalstack.api.v2.TenantService/Get": {}, "/metalstack.api.v2.TenantService/Leave": {}, }, + apiv2.TenantRole_TENANT_ROLE_GUEST: map[string]struct{}{ + "/metalstack.api.v2.TenantService/Get": {}, + }, }, Project: Project{ - "PROJECT_ROLE_EDITOR": map[string]struct{}{ + apiv2.ProjectRole_PROJECT_ROLE_OWNER: map[string]struct{}{ "/metalstack.api.v2.IPService/Create": {}, "/metalstack.api.v2.IPService/Delete": {}, "/metalstack.api.v2.IPService/Get": {}, @@ -225,12 +226,18 @@ func GetServicePermissions() *ServicePermissions { "/metalstack.api.v2.NetworkService/List": {}, "/metalstack.api.v2.NetworkService/ListBaseNetworks": {}, "/metalstack.api.v2.NetworkService/Update": {}, + "/metalstack.api.v2.ProjectService/Delete": {}, "/metalstack.api.v2.ProjectService/Get": {}, + "/metalstack.api.v2.ProjectService/Invite": {}, + "/metalstack.api.v2.ProjectService/InviteDelete": {}, + "/metalstack.api.v2.ProjectService/InvitesList": {}, + "/metalstack.api.v2.ProjectService/RemoveMember": {}, "/metalstack.api.v2.ProjectService/Update": {}, + "/metalstack.api.v2.ProjectService/UpdateMember": {}, "/metalstack.api.v2.SizeReservationService/Get": {}, "/metalstack.api.v2.SizeReservationService/List": {}, }, - "PROJECT_ROLE_OWNER": map[string]struct{}{ + apiv2.ProjectRole_PROJECT_ROLE_EDITOR: map[string]struct{}{ "/metalstack.api.v2.IPService/Create": {}, "/metalstack.api.v2.IPService/Delete": {}, "/metalstack.api.v2.IPService/Get": {}, @@ -249,18 +256,12 @@ func GetServicePermissions() *ServicePermissions { "/metalstack.api.v2.NetworkService/List": {}, "/metalstack.api.v2.NetworkService/ListBaseNetworks": {}, "/metalstack.api.v2.NetworkService/Update": {}, - "/metalstack.api.v2.ProjectService/Delete": {}, "/metalstack.api.v2.ProjectService/Get": {}, - "/metalstack.api.v2.ProjectService/Invite": {}, - "/metalstack.api.v2.ProjectService/InviteDelete": {}, - "/metalstack.api.v2.ProjectService/InvitesList": {}, - "/metalstack.api.v2.ProjectService/RemoveMember": {}, "/metalstack.api.v2.ProjectService/Update": {}, - "/metalstack.api.v2.ProjectService/UpdateMember": {}, "/metalstack.api.v2.SizeReservationService/Get": {}, "/metalstack.api.v2.SizeReservationService/List": {}, }, - "PROJECT_ROLE_VIEWER": map[string]struct{}{ + apiv2.ProjectRole_PROJECT_ROLE_VIEWER: map[string]struct{}{ "/metalstack.api.v2.IPService/Get": {}, "/metalstack.api.v2.IPService/List": {}, "/metalstack.api.v2.MachineService/Get": {}, From 7f3188758dbb5fc7626beb8dcc28df211d9b2ee5 Mon Sep 17 00:00:00 2001 From: Stefan Majer Date: Thu, 16 Jul 2026 10:00:14 +0200 Subject: [PATCH 3/3] Upsie --- generate/generate.go | 45 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/generate/generate.go b/generate/generate.go index 99ef1649..6588e2b7 100644 --- a/generate/generate.go +++ b/generate/generate.go @@ -12,8 +12,7 @@ import ( "strings" sprig "github.com/go-task/slim-sprig/v3" - apiv2 "github.com/metal-stack/api/go/metalstack/api/v2" - v1 "github.com/metal-stack/api/go/metalstack/api/v2" + v2 "github.com/metal-stack/api/go/metalstack/api/v2" "github.com/metal-stack/api/go/permissions" "github.com/metal-stack/api/go/tests/protoparser" @@ -150,68 +149,68 @@ func servicePermissions(root string) (*permissions.ServicePermissions, error) { auditable[methodName] = true // Tenant switch role := *methodOpt.IdentifierValue; role { - case v1.TenantRole_TENANT_ROLE_OWNER.String(), v1.TenantRole_TENANT_ROLE_EDITOR.String(), v1.TenantRole_TENANT_ROLE_VIEWER.String(), v1.TenantRole_TENANT_ROLE_GUEST.String(): - apirole := apiv2.TenantRole(apiv2.TenantRole_value[role]) + case v2.TenantRole_TENANT_ROLE_OWNER.String(), v2.TenantRole_TENANT_ROLE_EDITOR.String(), v2.TenantRole_TENANT_ROLE_VIEWER.String(), v2.TenantRole_TENANT_ROLE_GUEST.String(): + apirole := v2.TenantRole(v2.TenantRole_value[role]) if methods := roles.Tenant[apirole]; methods == nil { roles.Tenant[apirole] = permissions.Methods{} } roles.Tenant[apirole][methodName] = struct{}{} visibility.Tenant[methodName] = true - case v1.TenantRole_TENANT_ROLE_UNSPECIFIED.String(): + case v2.TenantRole_TENANT_ROLE_UNSPECIFIED.String(): // noop // Project - case v1.ProjectRole_PROJECT_ROLE_OWNER.String(), v1.ProjectRole_PROJECT_ROLE_EDITOR.String(), v1.ProjectRole_PROJECT_ROLE_VIEWER.String(): - apirole := apiv2.ProjectRole(apiv2.ProjectRole_value[role]) + case v2.ProjectRole_PROJECT_ROLE_OWNER.String(), v2.ProjectRole_PROJECT_ROLE_EDITOR.String(), v2.ProjectRole_PROJECT_ROLE_VIEWER.String(): + apirole := v2.ProjectRole(v2.ProjectRole_value[role]) if methods := roles.Project[apirole]; methods == nil { roles.Project[apirole] = permissions.Methods{} } roles.Project[apirole][methodName] = struct{}{} visibility.Project[methodName] = true - case v1.ProjectRole_PROJECT_ROLE_UNSPECIFIED.String(): + case v2.ProjectRole_PROJECT_ROLE_UNSPECIFIED.String(): // noop // Admin - case v1.AdminRole_ADMIN_ROLE_EDITOR.String(), v1.AdminRole_ADMIN_ROLE_VIEWER.String(): - apirole := apiv2.AdminRole(apiv2.AdminRole_value[role]) + case v2.AdminRole_ADMIN_ROLE_EDITOR.String(), v2.AdminRole_ADMIN_ROLE_VIEWER.String(): + apirole := v2.AdminRole(v2.AdminRole_value[role]) if methods := roles.Admin[apirole]; methods == nil { roles.Admin[apirole] = permissions.Methods{} } roles.Admin[apirole][methodName] = struct{}{} visibility.Admin[methodName] = true - case v1.AdminRole_ADMIN_ROLE_UNSPECIFIED.String(): + case v2.AdminRole_ADMIN_ROLE_UNSPECIFIED.String(): // noop // Infra - case v1.InfraRole_INFRA_ROLE_EDITOR.String(), v1.InfraRole_INFRA_ROLE_VIEWER.String(): - apirole := apiv2.InfraRole(apiv2.InfraRole_value[role]) + case v2.InfraRole_INFRA_ROLE_EDITOR.String(), v2.InfraRole_INFRA_ROLE_VIEWER.String(): + apirole := v2.InfraRole(v2.InfraRole_value[role]) if methods := roles.Infra[apirole]; methods == nil { roles.Infra[apirole] = permissions.Methods{} } roles.Infra[apirole][methodName] = struct{}{} visibility.Infra[methodName] = true - case v1.InfraRole_INFRA_ROLE_UNSPECIFIED.String(): + case v2.InfraRole_INFRA_ROLE_UNSPECIFIED.String(): // noop // Machine - case v1.MachineRole_MACHINE_ROLE_EDITOR.String(), v1.MachineRole_MACHINE_ROLE_VIEWER.String(): - apirole := apiv2.MachineRole(apiv2.MachineRole_value[role]) + case v2.MachineRole_MACHINE_ROLE_EDITOR.String(), v2.MachineRole_MACHINE_ROLE_VIEWER.String(): + apirole := v2.MachineRole(v2.MachineRole_value[role]) if methods := roles.Machine[apirole]; methods == nil { roles.Machine[apirole] = permissions.Methods{} } roles.Machine[apirole][methodName] = struct{}{} visibility.Machine[methodName] = true - case v1.MachineRole_MACHINE_ROLE_UNSPECIFIED.String(): + case v2.MachineRole_MACHINE_ROLE_UNSPECIFIED.String(): // noop // Visibility - case v1.Visibility_VISIBILITY_PUBLIC.String(): + case v2.Visibility_VISIBILITY_PUBLIC.String(): visibility.Public[methodName] = true - case v1.Visibility_VISIBILITY_SELF.String(): + case v2.Visibility_VISIBILITY_SELF.String(): visibility.Self[methodName] = true - case v1.Visibility_VISIBILITY_UNSPECIFIED.String(): + case v2.Visibility_VISIBILITY_UNSPECIFIED.String(): // noop // Auditable - case v1.Auditing_AUDITING_EXCLUDED.String(): + case v2.Auditing_AUDITING_EXCLUDED.String(): auditable[methodName] = false - case v1.Auditing_AUDITING_INCLUDED.String(): + case v2.Auditing_AUDITING_INCLUDED.String(): auditable[methodName] = true - case v1.Auditing_AUDITING_UNSPECIFIED.String(): + case v2.Auditing_AUDITING_UNSPECIFIED.String(): auditable[methodName] = true // noop default: