From c8b6273d1888fd53866d39a0b3b583f613bb2eef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Wed, 16 Sep 2026 16:23:51 +0200 Subject: [PATCH 01/61] Bump oapi-codegen runtime to v1.7.0 --- go.mod | 2 +- go.sum | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8241691a..447cd0fa 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/gorilla/websocket v1.5.3 github.com/labstack/echo-contrib v0.17.4 github.com/labstack/echo/v4 v4.15.3 - github.com/oapi-codegen/runtime v1.1.2 + github.com/oapi-codegen/runtime v1.7.0 github.com/prometheus/client_golang v1.23.2 github.com/shaj13/go-guardian/v2 v2.11.6 github.com/spf13/cobra v1.10.1 diff --git a/go.sum b/go.sum index 3ffde083..8fca6b90 100644 --- a/go.sum +++ b/go.sum @@ -157,10 +157,12 @@ github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+ github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oapi-codegen/nullable v1.1.0 h1:eAh8JVc5430VtYVnq00Hrbpag9PFRGWLjxR1/3KntMs= +github.com/oapi-codegen/nullable v1.1.0/go.mod h1:KUZ3vUzkmEKY90ksAmit2+5juDIhIZhfDl+0PwOQlFY= github.com/oapi-codegen/oapi-codegen/v2 v2.7.1 h1:a7Ab7YlpqkVG5HKrTaeFstm32Z5QOnyjnbsCO0jiMYM= github.com/oapi-codegen/oapi-codegen/v2 v2.7.1/go.mod h1:qzFy6iuobJw/hD1aRILee4G87/ShmhR0xYCwcUtZMCw= -github.com/oapi-codegen/runtime v1.1.2 h1:P2+CubHq8fO4Q6fV1tqDBZHCwpVpvPg7oKiYzQgXIyI= -github.com/oapi-codegen/runtime v1.1.2/go.mod h1:SK9X900oXmPWilYR5/WKPzt3Kqxn/uS/+lbpREv+eCg= +github.com/oapi-codegen/runtime v1.7.0 h1:t7358VYPvNbWJ9gdAkIK/smVeHpBf6yp8VTsaZsb/7k= +github.com/oapi-codegen/runtime v1.7.0/go.mod h1:GwV7hC2hviaMzj+ITfHVRESK5J2W/GefVwIND/bMGvU= github.com/oasdiff/yaml v0.1.1 h1:6nHx+pn9gBRM6YpBlFZFQGCCd1nuvqOBtTD3KKTgGxY= github.com/oasdiff/yaml v0.1.1/go.mod h1:EYJNoyktvWMJ0Hmhx+6qTaqMOsalUaRGT8Sj1hNcegU= github.com/oasdiff/yaml3 v0.0.14 h1:aLJee3hxBK2H5wdXd9iPcIXb93Nty1Ge0pT171eHtkw= From 3426bbc4ce114777ae0ab2147bc978b5fabd4765 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Wed, 16 Sep 2026 16:34:36 +0200 Subject: [PATCH 02/61] Replace the generic ListResponse with per-resource response schemas --- server/api.yaml | 605 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 579 insertions(+), 26 deletions(-) diff --git a/server/api.yaml b/server/api.yaml index 1892f3c6..9eaf4930 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -175,7 +175,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/AlertListResponse' 500: $ref: '#/components/responses/500' security: @@ -306,7 +306,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/AlertListResponse' 404: $ref: '#/components/responses/404' 500: @@ -459,7 +459,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/AppListResponse' 500: $ref: '#/components/responses/500' security: @@ -494,7 +494,7 @@ paths: content: application/json: schema: - type: object + $ref: '#/components/schemas/AppRow' 400: $ref: '#/components/responses/400' 401: @@ -590,7 +590,7 @@ paths: content: application/json: schema: - type: object + $ref: '#/components/schemas/AppRow' 400: $ref: '#/components/responses/400' 401: @@ -623,7 +623,7 @@ paths: content: application/json: schema: - type: object + $ref: '#/components/schemas/AppRow' 404: $ref: '#/components/responses/404' 500: @@ -649,7 +649,7 @@ paths: content: application/json: schema: - type: object + $ref: '#/components/schemas/InfoResponse' 401: $ref: '#/components/responses/401' 403: @@ -1382,7 +1382,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/DiskListResponse' 500: $ref: '#/components/responses/500' security: @@ -1487,7 +1487,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/DiskListResponse' 404: $ref: '#/components/responses/404' 500: @@ -2042,7 +2042,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/NodeListResponse' 404: $ref: '#/components/responses/404' 500: @@ -2077,7 +2077,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/ServiceListResponse' 404: $ref: '#/components/responses/404' 500: @@ -2564,7 +2564,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/GroupListResponse' 500: $ref: '#/components/responses/500' security: @@ -2601,7 +2601,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/GroupListResponse' 400: $ref: '#/components/responses/400' 401: @@ -2639,7 +2639,7 @@ paths: content: application/json: schema: - type: object + $ref: '#/components/schemas/InfoResponse' properties: info: type: string @@ -2683,7 +2683,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/GroupListResponse' 404: $ref: '#/components/responses/404' 500: @@ -2724,7 +2724,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/GroupListResponse' 400: $ref: '#/components/responses/400' 401: @@ -2758,7 +2758,7 @@ paths: content: application/json: schema: - type: object + $ref: '#/components/schemas/InfoResponse' 400: $ref: '#/components/responses/400' 401: @@ -3166,7 +3166,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/IpListResponse' 500: $ref: '#/components/responses/500' security: @@ -3243,7 +3243,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/IpListResponse' 404: $ref: '#/components/responses/404' 500: @@ -3568,7 +3568,7 @@ paths: content: application/json: schema: - type: object + $ref: '#/components/schemas/NodeRow' 400: $ref: '#/components/responses/400' 401: @@ -3600,7 +3600,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/NodeListResponse' 500: $ref: '#/components/responses/500' security: @@ -3877,7 +3877,7 @@ paths: content: application/json: schema: - type: object + $ref: '#/components/schemas/NodeRow' 400: $ref: '#/components/responses/400' 401: @@ -3917,7 +3917,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/NodeListResponse' 404: $ref: '#/components/responses/404' 500: @@ -3944,7 +3944,7 @@ paths: content: application/json: schema: - type: object + $ref: '#/components/schemas/InfoResponse' 401: $ref: '#/components/responses/401' 403: @@ -5042,7 +5042,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/ServiceListResponse' 500: $ref: '#/components/responses/500' security: @@ -5199,7 +5199,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/ServiceListResponse' 404: $ref: '#/components/responses/404' 500: @@ -7252,6 +7252,559 @@ components: total: type: integer + NodeRow: + type: object + description: | + A node row of the nodes list. Every property is optional: the `props` + query parameter selects which columns the server returns, so a row + carries only the requested subset. + properties: + node_id: + type: string + nodename: + type: string + app: + type: string + node_env: + type: string + cluster_id: + type: string + loc_country: + type: string + loc_city: + type: string + loc_addr: + type: string + loc_building: + type: string + loc_floor: + type: string + loc_room: + type: string + loc_rack: + type: string + loc_zip: + type: string + cpu_freq: + type: string + cpu_cores: + type: integer + cpu_dies: + type: integer + cpu_vendor: + type: string + cpu_model: + type: string + cpu_threads: + type: integer + mem_banks: + type: integer + mem_slots: + type: integer + mem_bytes: + type: integer + os_name: + type: string + os_release: + type: string + os_update: + type: string + os_segment: + type: string + os_arch: + type: string + os_vendor: + type: string + os_kernel: + type: string + os_concat: + type: string + team_responsible: + type: string + team_integ: + type: string + team_support: + type: string + serial: + type: string + model: + type: string + manufacturer: + type: string + type: + type: string + assetname: + type: string + asset_env: + type: string + warranty_end: + type: string + maintenance_end: + type: string + status: + type: string + role: + type: string + sec_zone: + type: string + power_cabinet1: + type: string + power_cabinet2: + type: string + power_supply_nb: + type: integer + power_protect: + type: string + power_protect_breaker: + type: string + power_breaker1: + type: string + power_breaker2: + type: string + blade_cabinet: + type: string + enclosure: + type: string + enclosureslot: + type: string + hv: + type: string + hvpool: + type: string + hvvdc: + type: string + fqdn: + type: string + connect_to: + type: string + listener_port: + type: integer + version: + type: string + collector: + type: string + sp_version: + type: string + bios_version: + type: string + tz: + type: string + last_boot: + type: string + last_comm: + type: string + node_frozen: + type: string + node_frozen_at: + type: string + snooze_till: + type: string + notifications: + type: string + action_type: + type: string + hw_obs_warn_date: + type: string + hw_obs_alert_date: + type: string + os_obs_warn_date: + type: string + os_obs_alert_date: + type: string + updated: + type: string + + NodeListResponse: + type: object + required: + - data + properties: + data: + oneOf: + - type: array + items: + $ref: '#/components/schemas/NodeRow' + - type: object + additionalProperties: + type: object + additionalProperties: + type: integer + meta: + $ref: '#/components/schemas/ListMeta' + + ServiceRow: + type: object + description: | + A service row of the services list. Every property is optional: the `props` + query parameter selects which columns the server returns, so a row + carries only the requested subset. + properties: + id: + type: integer + svc_id: + type: string + svcname: + type: string + cluster_id: + type: string + svc_status: + type: string + svc_availstatus: + type: string + svc_app: + type: string + svc_env: + type: string + svc_ha: + type: integer + svc_topology: + type: string + svc_frozen: + type: string + svc_placement: + type: string + svc_provisioned: + type: string + svc_flex_min_nodes: + type: integer + svc_flex_max_nodes: + type: integer + svc_flex_target: + type: integer + svc_flex_cpu_low_threshold: + type: integer + svc_flex_cpu_high_threshold: + type: integer + svc_autostart: + type: string + svc_nodes: + type: string + svc_drpnode: + type: string + svc_drpnodes: + type: string + svc_drptype: + type: string + svc_comment: + type: string + svc_created: + type: string + svc_status_updated: + type: string + svc_hostid: + type: string + svc_wave: + type: integer + svc_config: + type: string + svc_config_updated: + type: string + svc_metrocluster: + type: string + svc_drnoaction: + type: string + svc_notifications: + type: string + svc_snooze_till: + type: string + updated: + type: string + + ServiceListResponse: + type: object + required: + - data + properties: + data: + oneOf: + - type: array + items: + $ref: '#/components/schemas/ServiceRow' + - type: object + additionalProperties: + type: object + additionalProperties: + type: integer + meta: + $ref: '#/components/schemas/ListMeta' + + AlertRow: + type: object + description: | + A dashboard alert row. Every property is optional: the `props` query + parameter selects which columns the server returns. `alert` is computed + from `dash_fmt` and `dash_dict`. The `nodes.` and `services.` properties + come from a LEFT JOIN and are null when the alert targets the other kind + of object. + properties: + id: + type: integer + dash_type: + type: string + svc_id: + type: string + node_id: + type: string + dash_severity: + type: integer + dash_fmt: + type: string + dash_dict: + type: string + dash_created: + type: string + dash_updated: + type: string + dash_md5: + type: string + dash_dict_md5: + type: string + dash_env: + type: string + dash_instance: + type: string + alert: + type: string + description: Human readable message, rendered from dash_fmt and dash_dict. + nodes.nodename: + type: string + nullable: true + services.svcname: + type: string + nullable: true + + AlertListResponse: + type: object + required: + - data + properties: + data: + oneOf: + - type: array + items: + $ref: '#/components/schemas/AlertRow' + - type: object + additionalProperties: + type: object + additionalProperties: + type: integer + meta: + $ref: '#/components/schemas/ListMeta' + + AppRow: + type: object + description: | + An application code. Every property is optional: the `props` query + parameter selects which columns the server returns. + properties: + id: + type: integer + app: + type: string + updated: + type: string + app_domain: + type: string + app_team_ops: + type: string + description: + type: string + + AppListResponse: + type: object + required: + - data + properties: + data: + oneOf: + - type: array + items: + $ref: '#/components/schemas/AppRow' + - type: object + additionalProperties: + type: object + additionalProperties: + type: integer + meta: + $ref: '#/components/schemas/ListMeta' + + InfoResponse: + type: object + description: Outcome message of a write that returns no record. + properties: + info: + type: string + + IpRow: + type: object + description: | + An IP address detected on a node, joined to the network it belongs to. + Every property is optional: the `props` query parameter selects which + columns the server returns. + properties: + id: + type: integer + node_id: + type: string + nodename: + type: string + intf: + type: string + mac: + type: string + type: + type: string + addr: + type: string + mask: + type: string + updated: + type: string + flag_deprecated: + type: integer + net_id: + type: integer + net_name: + type: string + net_network: + type: string + net_netmask: + type: string + net_broadcast: + type: string + net_gateway: + type: string + net_begin: + type: string + net_end: + type: string + net_pvid: + type: string + net_prio: + type: integer + net_comment: + type: string + net_team_responsible: + type: string + + IpListResponse: + type: object + required: + - data + properties: + data: + oneOf: + - type: array + items: + $ref: '#/components/schemas/IpRow' + - type: object + additionalProperties: + type: object + additionalProperties: + type: integer + meta: + $ref: '#/components/schemas/ListMeta' + + DiskRow: + type: object + description: | + A disk seen on a node, with the service and array it belongs to when + known. Every property is optional: the `props` query parameter selects + which columns the server returns. + properties: + disk_id: + type: string + disk_name: + type: string + disk_devid: + type: string + disk_vendor: + type: string + disk_model: + type: string + disk_size: + type: integer + disk_used: + type: integer + disk_alloc: + type: integer + disk_raid: + type: string + disk_group: + type: string + disk_level: + type: integer + disk_arrayid: + type: string + disk_dg: + type: string + disk_region: + type: string + node_id: + type: string + nodename: + type: string + svc_id: + type: string + svcname: + type: string + app: + type: string + updated: + type: string + + DiskListResponse: + type: object + required: + - data + properties: + data: + oneOf: + - type: array + items: + $ref: '#/components/schemas/DiskRow' + - type: object + additionalProperties: + type: object + additionalProperties: + type: integer + meta: + $ref: '#/components/schemas/ListMeta' + + GroupRow: + type: object + description: | + A user group. `privilege` is "T" for a privilege-granting group and + "F" for an ordinary one. Every property is optional: the `props` query + parameter selects which columns the server returns. + properties: + id: + type: integer + role: + type: string + privilege: + type: string + description: + type: string + + GroupListResponse: + type: object + required: + - data + properties: + data: + oneOf: + - type: array + items: + $ref: '#/components/schemas/GroupRow' + - type: object + additionalProperties: + type: object + additionalProperties: + type: integer + meta: + $ref: '#/components/schemas/ListMeta' + ListResponse: type: object required: From 36ac3fae89f71d3a71212ee910e3ab136031076a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Wed, 16 Sep 2026 16:35:39 +0200 Subject: [PATCH 03/61] Update codegen_* --- feeder/codegen_server_gen.go | 263 +-- feeder/codegen_type_gen.go | 12 +- server/codegen_server_gen.go | 3084 +++++++++++++++++----------------- server/codegen_type_gen.go | 840 ++++++++- 4 files changed, 2571 insertions(+), 1628 deletions(-) diff --git a/feeder/codegen_server_gen.go b/feeder/codegen_server_gen.go index bc758f48..a6d92d47 100644 --- a/feeder/codegen_server_gen.go +++ b/feeder/codegen_server_gen.go @@ -1,11 +1,11 @@ // Package feeder provides primitives to interact with the openapi HTTP API. // -// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.5.1 DO NOT EDIT. +// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.7.1 DO NOT EDIT. package feeder import ( "bytes" - "compress/gzip" + "compress/flate" "encoding/base64" "fmt" "net/http" @@ -79,9 +79,9 @@ type ServerInterfaceWrapper struct { func (w *ServerInterfaceWrapper) PostChecks(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostChecks(ctx) @@ -92,9 +92,9 @@ func (w *ServerInterfaceWrapper) PostChecks(ctx echo.Context) error { func (w *ServerInterfaceWrapper) PostDaemonPing(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostDaemonPing(ctx) @@ -105,9 +105,9 @@ func (w *ServerInterfaceWrapper) PostDaemonPing(ctx echo.Context) error { func (w *ServerInterfaceWrapper) PostDaemonStatus(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostDaemonStatus(ctx) @@ -118,9 +118,9 @@ func (w *ServerInterfaceWrapper) PostDaemonStatus(ctx echo.Context) error { func (w *ServerInterfaceWrapper) PostInstanceAction(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostInstanceAction(ctx) @@ -131,9 +131,9 @@ func (w *ServerInterfaceWrapper) PostInstanceAction(ctx echo.Context) error { func (w *ServerInterfaceWrapper) PutInstanceActionEnd(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PutInstanceActionEnd(ctx) @@ -144,9 +144,9 @@ func (w *ServerInterfaceWrapper) PutInstanceActionEnd(ctx echo.Context) error { func (w *ServerInterfaceWrapper) PostInstanceResourceInfo(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostInstanceResourceInfo(ctx) @@ -157,15 +157,15 @@ func (w *ServerInterfaceWrapper) PostInstanceResourceInfo(ctx echo.Context) erro func (w *ServerInterfaceWrapper) PostInstanceStatus(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params PostInstanceStatusParams // ------------- Optional query parameter "sync" ------------- - err = runtime.BindQueryParameter("form", true, false, "sync", ctx.QueryParams(), ¶ms.Sync) + err = runtime.BindQueryParameterWithOptions("form", true, false, "sync", ctx.QueryParams(), ¶ms.Sync, runtime.BindQueryParameterOptions{Type: "boolean", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter sync: %s", err)) } @@ -179,9 +179,9 @@ func (w *ServerInterfaceWrapper) PostInstanceStatus(ctx echo.Context) error { func (w *ServerInterfaceWrapper) GetNodeActionQueued(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.GetNodeActionQueued(ctx) @@ -192,9 +192,9 @@ func (w *ServerInterfaceWrapper) GetNodeActionQueued(ctx echo.Context) error { func (w *ServerInterfaceWrapper) PostNodeActionQueuedDone(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostNodeActionQueuedDone(ctx) @@ -205,9 +205,9 @@ func (w *ServerInterfaceWrapper) PostNodeActionQueuedDone(ctx echo.Context) erro func (w *ServerInterfaceWrapper) PostNodeActionQueuedRunning(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostNodeActionQueuedRunning(ctx) @@ -218,9 +218,9 @@ func (w *ServerInterfaceWrapper) PostNodeActionQueuedRunning(ctx echo.Context) e func (w *ServerInterfaceWrapper) PostNodeDisk(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostNodeDisk(ctx) @@ -231,9 +231,9 @@ func (w *ServerInterfaceWrapper) PostNodeDisk(ctx echo.Context) error { func (w *ServerInterfaceWrapper) PostNodeSysReport(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostNodeSysReport(ctx) @@ -244,9 +244,9 @@ func (w *ServerInterfaceWrapper) PostNodeSysReport(ctx echo.Context) error { func (w *ServerInterfaceWrapper) PostSystem(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostSystem(ctx) @@ -257,9 +257,9 @@ func (w *ServerInterfaceWrapper) PostSystem(ctx echo.Context) error { func (w *ServerInterfaceWrapper) PostObjectConfig(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostObjectConfig(ctx) @@ -299,101 +299,121 @@ type EchoRouter interface { TRACE(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route } +// RegisterHandlersOptions configures RegisterHandlersWithOptions. +type RegisterHandlersOptions struct { + // BaseURL is prepended to every registered path so the API can be served + // under a prefix. + BaseURL string + // OperationMiddlewares lets the caller attach per-operation middleware at + // registration time. The map key is the OpenAPI `operationId` value as it + // appears in the spec (the raw, un-normalized form). Operations that have + // no entry are registered with no extra middleware. A nil map disables + // per-operation middleware entirely. + OperationMiddlewares map[string][]echo.MiddlewareFunc +} + // RegisterHandlers adds each server route to the EchoRouter. func RegisterHandlers(router EchoRouter, si ServerInterface) { - RegisterHandlersWithBaseURL(router, si, "") + RegisterHandlersWithOptions(router, si, RegisterHandlersOptions{}) } -// Registers handlers, and prepends BaseURL to the paths, so that the paths -// can be served under a prefix. +// RegisterHandlersWithBaseURL registers handlers and prepends BaseURL to the +// paths so the API can be served under a prefix. func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL string) { + RegisterHandlersWithOptions(router, si, RegisterHandlersOptions{BaseURL: baseURL}) +} + +// RegisterHandlersWithOptions registers handlers using the supplied options, +// including any per-operation middleware. +func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options RegisterHandlersOptions) { wrapper := ServerInterfaceWrapper{ Handler: si, } - router.POST(baseURL+"/checks", wrapper.PostChecks) - router.POST(baseURL+"/daemon/ping", wrapper.PostDaemonPing) - router.POST(baseURL+"/daemon/status", wrapper.PostDaemonStatus) - router.POST(baseURL+"/instance/action", wrapper.PostInstanceAction) - router.PUT(baseURL+"/instance/action", wrapper.PutInstanceActionEnd) - router.POST(baseURL+"/instance/resource_info", wrapper.PostInstanceResourceInfo) - router.POST(baseURL+"/instance/status", wrapper.PostInstanceStatus) - router.GET(baseURL+"/node/actionq", wrapper.GetNodeActionQueued) - router.POST(baseURL+"/node/actionq/done", wrapper.PostNodeActionQueuedDone) - router.POST(baseURL+"/node/actionq/running", wrapper.PostNodeActionQueuedRunning) - router.POST(baseURL+"/node/disk", wrapper.PostNodeDisk) - router.POST(baseURL+"/node/sysreport", wrapper.PostNodeSysReport) - router.POST(baseURL+"/node/system", wrapper.PostSystem) - router.POST(baseURL+"/object/config", wrapper.PostObjectConfig) - router.GET(baseURL+"/openapi.json", wrapper.GetSwagger) - router.GET(baseURL+"/version", wrapper.GetVersion) + router.POST(options.BaseURL+"/checks", wrapper.PostChecks, options.OperationMiddlewares["PostChecks"]...) + router.POST(options.BaseURL+"/daemon/ping", wrapper.PostDaemonPing, options.OperationMiddlewares["PostDaemonPing"]...) + router.POST(options.BaseURL+"/daemon/status", wrapper.PostDaemonStatus, options.OperationMiddlewares["PostDaemonStatus"]...) + router.POST(options.BaseURL+"/instance/action", wrapper.PostInstanceAction, options.OperationMiddlewares["PostInstanceAction"]...) + router.PUT(options.BaseURL+"/instance/action", wrapper.PutInstanceActionEnd, options.OperationMiddlewares["PutInstanceActionEnd"]...) + router.POST(options.BaseURL+"/instance/resource_info", wrapper.PostInstanceResourceInfo, options.OperationMiddlewares["PostInstanceResourceInfo"]...) + router.POST(options.BaseURL+"/instance/status", wrapper.PostInstanceStatus, options.OperationMiddlewares["PostInstanceStatus"]...) + router.GET(options.BaseURL+"/node/actionq", wrapper.GetNodeActionQueued, options.OperationMiddlewares["GetNodeActionQueued"]...) + router.POST(options.BaseURL+"/node/actionq/done", wrapper.PostNodeActionQueuedDone, options.OperationMiddlewares["PostNodeActionQueuedDone"]...) + router.POST(options.BaseURL+"/node/actionq/running", wrapper.PostNodeActionQueuedRunning, options.OperationMiddlewares["PostNodeActionQueuedRunning"]...) + router.POST(options.BaseURL+"/node/disk", wrapper.PostNodeDisk, options.OperationMiddlewares["PostNodeDisk"]...) + router.POST(options.BaseURL+"/node/sysreport", wrapper.PostNodeSysReport, options.OperationMiddlewares["PostNodeSysReport"]...) + router.POST(options.BaseURL+"/node/system", wrapper.PostSystem, options.OperationMiddlewares["PostSystem"]...) + router.POST(options.BaseURL+"/object/config", wrapper.PostObjectConfig, options.OperationMiddlewares["PostObjectConfig"]...) + router.GET(options.BaseURL+"/openapi.json", wrapper.GetSwagger, options.OperationMiddlewares["GetSwagger"]...) + router.GET(options.BaseURL+"/version", wrapper.GetVersion, options.OperationMiddlewares["GetVersion"]...) } -// Base64 encoded, gzipped, json marshaled Swagger object +// Base64 encoded, compressed with deflate, json marshaled OpenAPI spec. +// Stored as a slice of fixed-width chunks rather than one concatenated +// const string: with thousands of chunks the chained `+` fold is several +// times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - - "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", - "q0GlODsAAA==", + "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", } -// GetSwagger returns the content of the embedded swagger specification file -// or error if failed to decode +// decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, +// after base64-decoding and flate-decompressing the embedded blob. func decodeSpec() ([]byte, error) { - zipped, err := base64.StdEncoding.DecodeString(strings.Join(swaggerSpec, "")) + encoded := strings.Join(swaggerSpec, "") + compressed, err := base64.StdEncoding.DecodeString(encoded) if err != nil { return nil, fmt.Errorf("error base64 decoding spec: %w", err) } - zr, err := gzip.NewReader(bytes.NewReader(zipped)) - if err != nil { - return nil, fmt.Errorf("error decompressing spec: %w", err) - } + zr := flate.NewReader(bytes.NewReader(compressed)) var buf bytes.Buffer - _, err = buf.ReadFrom(zr) - if err != nil { - return nil, fmt.Errorf("error decompressing spec: %w", err) + if _, err := buf.ReadFrom(zr); err != nil { + return nil, fmt.Errorf("read flate: %w", err) + } + if err := zr.Close(); err != nil { + return nil, fmt.Errorf("close flate reader: %w", err) } return buf.Bytes(), nil @@ -401,7 +421,7 @@ func decodeSpec() ([]byte, error) { var rawSpec = decodeSpecCached() -// a naive cached of a decoded swagger spec +// a naive cache of the decoded OpenAPI spec func decodeSpecCached() func() ([]byte, error) { data, err := decodeSpec() return func() ([]byte, error) { @@ -419,12 +439,12 @@ func PathToRawSpec(pathToFile string) map[string]func() ([]byte, error) { return res } -// GetSwagger returns the Swagger specification corresponding to the generated code -// in this file. The external references of Swagger specification are resolved. -// The logic of resolving external references is tightly connected to "import-mapping" feature. -// Externally referenced files must be embedded in the corresponding golang packages. -// Urls can be supported but this task was out of the scope. -func GetSwagger() (swagger *openapi3.T, err error) { +// GetSpec returns the OpenAPI specification corresponding to the generated +// code in this file. External references in the spec are resolved through +// PathToRawSpec; externally-referenced files must be embedded in their +// corresponding Go packages (via the import-mapping feature). URL-based +// external refs are not supported. +func GetSpec() (swagger *openapi3.T, err error) { resolvePath := PathToRawSpec("") loader := openapi3.NewLoader() @@ -450,3 +470,22 @@ func GetSwagger() (swagger *openapi3.T, err error) { } return } + +// GetSpecJSON returns the raw JSON bytes of the embedded OpenAPI +// specification: decompressed but not unmarshaled. External references +// are not resolved here; the bytes are the spec exactly as embedded by +// codegen. The result is cached at package init time, so repeated calls +// are cheap. +func GetSpecJSON() ([]byte, error) { + return rawSpec() +} + +// GetSwagger returns the OpenAPI specification corresponding to the +// generated code in this file. +// +// Deprecated: GetSwagger predates kin-openapi renaming openapi3.Swagger +// to openapi3.T. Use [GetSpec] instead. This wrapper is retained for +// backwards compatibility. +func GetSwagger() (*openapi3.T, error) { + return GetSpec() +} diff --git a/feeder/codegen_type_gen.go b/feeder/codegen_type_gen.go index ef13d301..dd3d593c 100644 --- a/feeder/codegen_type_gen.go +++ b/feeder/codegen_type_gen.go @@ -1,6 +1,6 @@ // Package feeder provides primitives to interact with the openapi HTTP API. // -// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.5.1 DO NOT EDIT. +// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.7.1 DO NOT EDIT. package feeder import ( @@ -10,8 +10,8 @@ import ( ) const ( - BasicAuthScopes = "basicAuth.Scopes" - BearerAuthScopes = "bearerAuth.Scopes" + BasicAuthScopes basicAuthContextKey = "basicAuth.Scopes" + BearerAuthScopes bearerAuthContextKey = "bearerAuth.Scopes" ) // Action The begin or end action request @@ -253,6 +253,12 @@ type DaemonStatusAccepted struct { ObjectWithoutConfig *[]string `json:"object_without_config,omitempty"` } +// basicAuthContextKey is the context key for basicAuth security scheme +type basicAuthContextKey string + +// bearerAuthContextKey is the context key for bearerAuth security scheme +type bearerAuthContextKey string + // PostInstanceStatusParams defines parameters for PostInstanceStatus. type PostInstanceStatusParams struct { Sync *InQuerySync `form:"sync,omitempty" json:"sync,omitempty"` diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index ff82e61a..a070a005 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -1,11 +1,11 @@ // Package server provides primitives to interact with the openapi HTTP API. // -// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.5.1 DO NOT EDIT. +// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.7.1 DO NOT EDIT. package server import ( "bytes" - "compress/gzip" + "compress/flate" "encoding/base64" "fmt" "net/http" @@ -577,57 +577,57 @@ type ServerInterfaceWrapper struct { func (w *ServerInterfaceWrapper) GetActions(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetActionsParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -641,9 +641,9 @@ func (w *ServerInterfaceWrapper) GetActions(ctx echo.Context) error { func (w *ServerInterfaceWrapper) PostActions(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostActions(ctx) @@ -656,14 +656,14 @@ func (w *ServerInterfaceWrapper) DeleteAction(ctx echo.Context) error { // ------------- Path parameter "id" ------------- var id string - err = runtime.BindStyledParameterWithOptions("simple", "id", ctx.Param("id"), &id, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "id", ctx.Param("id"), &id, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteAction(ctx, id) @@ -676,62 +676,62 @@ func (w *ServerInterfaceWrapper) GetAction(ctx echo.Context) error { // ------------- Path parameter "id" ------------- var id string - err = runtime.BindStyledParameterWithOptions("simple", "id", ctx.Param("id"), &id, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "id", ctx.Param("id"), &id, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetActionParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -745,57 +745,57 @@ func (w *ServerInterfaceWrapper) GetAction(ctx echo.Context) error { func (w *ServerInterfaceWrapper) GetAlertEvent(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetAlertEventParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -809,9 +809,9 @@ func (w *ServerInterfaceWrapper) GetAlertEvent(ctx echo.Context) error { func (w *ServerInterfaceWrapper) DeleteAlerts(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteAlerts(ctx) @@ -822,57 +822,57 @@ func (w *ServerInterfaceWrapper) DeleteAlerts(ctx echo.Context) error { func (w *ServerInterfaceWrapper) GetAlerts(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetAlertsParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -886,9 +886,9 @@ func (w *ServerInterfaceWrapper) GetAlerts(ctx echo.Context) error { func (w *ServerInterfaceWrapper) PostAlerts(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostAlerts(ctx) @@ -901,14 +901,14 @@ func (w *ServerInterfaceWrapper) DeleteAlert(ctx echo.Context) error { // ------------- Path parameter "id" ------------- var id string - err = runtime.BindStyledParameterWithOptions("simple", "id", ctx.Param("id"), &id, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "id", ctx.Param("id"), &id, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteAlert(ctx, id) @@ -921,62 +921,62 @@ func (w *ServerInterfaceWrapper) GetAlert(ctx echo.Context) error { // ------------- Path parameter "id" ------------- var id string - err = runtime.BindStyledParameterWithOptions("simple", "id", ctx.Param("id"), &id, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "id", ctx.Param("id"), &id, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetAlertParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -992,14 +992,14 @@ func (w *ServerInterfaceWrapper) PostAlert(ctx echo.Context) error { // ------------- Path parameter "id" ------------- var id string - err = runtime.BindStyledParameterWithOptions("simple", "id", ctx.Param("id"), &id, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "id", ctx.Param("id"), &id, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostAlert(ctx, id) @@ -1010,9 +1010,9 @@ func (w *ServerInterfaceWrapper) PostAlert(ctx echo.Context) error { func (w *ServerInterfaceWrapper) DeleteApps(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteApps(ctx) @@ -1023,57 +1023,57 @@ func (w *ServerInterfaceWrapper) DeleteApps(ctx echo.Context) error { func (w *ServerInterfaceWrapper) GetApps(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetAppsParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -1087,9 +1087,9 @@ func (w *ServerInterfaceWrapper) GetApps(ctx echo.Context) error { func (w *ServerInterfaceWrapper) PostApps(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostApps(ctx) @@ -1102,14 +1102,14 @@ func (w *ServerInterfaceWrapper) DeleteApp(ctx echo.Context) error { // ------------- Path parameter "app_id" ------------- var appId string - err = runtime.BindStyledParameterWithOptions("simple", "app_id", ctx.Param("app_id"), &appId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "app_id", ctx.Param("app_id"), &appId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter app_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteApp(ctx, appId) @@ -1122,20 +1122,20 @@ func (w *ServerInterfaceWrapper) GetApp(ctx echo.Context) error { // ------------- Path parameter "app_id" ------------- var appId string - err = runtime.BindStyledParameterWithOptions("simple", "app_id", ctx.Param("app_id"), &appId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "app_id", ctx.Param("app_id"), &appId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter app_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetAppParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } @@ -1151,14 +1151,14 @@ func (w *ServerInterfaceWrapper) PostApp(ctx echo.Context) error { // ------------- Path parameter "app_id" ------------- var appId string - err = runtime.BindStyledParameterWithOptions("simple", "app_id", ctx.Param("app_id"), &appId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "app_id", ctx.Param("app_id"), &appId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter app_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostApp(ctx, appId) @@ -1171,14 +1171,14 @@ func (w *ServerInterfaceWrapper) GetAppAmIResponsible(ctx echo.Context) error { // ------------- Path parameter "app_id" ------------- var appId string - err = runtime.BindStyledParameterWithOptions("simple", "app_id", ctx.Param("app_id"), &appId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "app_id", ctx.Param("app_id"), &appId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter app_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.GetAppAmIResponsible(ctx, appId) @@ -1191,62 +1191,62 @@ func (w *ServerInterfaceWrapper) GetAppNodes(ctx echo.Context) error { // ------------- Path parameter "app_id" ------------- var appId string - err = runtime.BindStyledParameterWithOptions("simple", "app_id", ctx.Param("app_id"), &appId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "app_id", ctx.Param("app_id"), &appId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter app_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetAppNodesParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -1262,62 +1262,62 @@ func (w *ServerInterfaceWrapper) GetAppPublications(ctx echo.Context) error { // ------------- Path parameter "app_id" ------------- var appId string - err = runtime.BindStyledParameterWithOptions("simple", "app_id", ctx.Param("app_id"), &appId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "app_id", ctx.Param("app_id"), &appId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter app_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetAppPublicationsParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -1333,7 +1333,7 @@ func (w *ServerInterfaceWrapper) DeleteAppPublication(ctx echo.Context) error { // ------------- Path parameter "app_id" ------------- var appId string - err = runtime.BindStyledParameterWithOptions("simple", "app_id", ctx.Param("app_id"), &appId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "app_id", ctx.Param("app_id"), &appId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter app_id: %s", err)) } @@ -1341,14 +1341,14 @@ func (w *ServerInterfaceWrapper) DeleteAppPublication(ctx echo.Context) error { // ------------- Path parameter "group_id" ------------- var groupId string - err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter group_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteAppPublication(ctx, appId, groupId) @@ -1361,7 +1361,7 @@ func (w *ServerInterfaceWrapper) PostAppPublication(ctx echo.Context) error { // ------------- Path parameter "app_id" ------------- var appId string - err = runtime.BindStyledParameterWithOptions("simple", "app_id", ctx.Param("app_id"), &appId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "app_id", ctx.Param("app_id"), &appId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter app_id: %s", err)) } @@ -1369,14 +1369,14 @@ func (w *ServerInterfaceWrapper) PostAppPublication(ctx echo.Context) error { // ------------- Path parameter "group_id" ------------- var groupId string - err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter group_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostAppPublication(ctx, appId, groupId) @@ -1389,62 +1389,62 @@ func (w *ServerInterfaceWrapper) GetAppQuotas(ctx echo.Context) error { // ------------- Path parameter "app_id" ------------- var appId string - err = runtime.BindStyledParameterWithOptions("simple", "app_id", ctx.Param("app_id"), &appId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "app_id", ctx.Param("app_id"), &appId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter app_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetAppQuotasParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -1460,62 +1460,62 @@ func (w *ServerInterfaceWrapper) GetAppResponsibles(ctx echo.Context) error { // ------------- Path parameter "app_id" ------------- var appId string - err = runtime.BindStyledParameterWithOptions("simple", "app_id", ctx.Param("app_id"), &appId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "app_id", ctx.Param("app_id"), &appId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter app_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetAppResponsiblesParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -1531,7 +1531,7 @@ func (w *ServerInterfaceWrapper) DeleteAppResponsible(ctx echo.Context) error { // ------------- Path parameter "app_id" ------------- var appId string - err = runtime.BindStyledParameterWithOptions("simple", "app_id", ctx.Param("app_id"), &appId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "app_id", ctx.Param("app_id"), &appId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter app_id: %s", err)) } @@ -1539,14 +1539,14 @@ func (w *ServerInterfaceWrapper) DeleteAppResponsible(ctx echo.Context) error { // ------------- Path parameter "group_id" ------------- var groupId string - err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter group_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteAppResponsible(ctx, appId, groupId) @@ -1559,7 +1559,7 @@ func (w *ServerInterfaceWrapper) PostAppResponsible(ctx echo.Context) error { // ------------- Path parameter "app_id" ------------- var appId string - err = runtime.BindStyledParameterWithOptions("simple", "app_id", ctx.Param("app_id"), &appId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "app_id", ctx.Param("app_id"), &appId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter app_id: %s", err)) } @@ -1567,14 +1567,14 @@ func (w *ServerInterfaceWrapper) PostAppResponsible(ctx echo.Context) error { // ------------- Path parameter "group_id" ------------- var groupId string - err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter group_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostAppResponsible(ctx, appId, groupId) @@ -1587,62 +1587,62 @@ func (w *ServerInterfaceWrapper) GetAppServices(ctx echo.Context) error { // ------------- Path parameter "app_id" ------------- var appId string - err = runtime.BindStyledParameterWithOptions("simple", "app_id", ctx.Param("app_id"), &appId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "app_id", ctx.Param("app_id"), &appId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter app_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetAppServicesParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -1656,9 +1656,9 @@ func (w *ServerInterfaceWrapper) GetAppServices(ctx echo.Context) error { func (w *ServerInterfaceWrapper) DeleteAppsPublications(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteAppsPublications(ctx) @@ -1669,9 +1669,9 @@ func (w *ServerInterfaceWrapper) DeleteAppsPublications(ctx echo.Context) error func (w *ServerInterfaceWrapper) PostAppsPublications(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostAppsPublications(ctx) @@ -1682,9 +1682,9 @@ func (w *ServerInterfaceWrapper) PostAppsPublications(ctx echo.Context) error { func (w *ServerInterfaceWrapper) DeleteAppsResponsibles(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteAppsResponsibles(ctx) @@ -1695,9 +1695,9 @@ func (w *ServerInterfaceWrapper) DeleteAppsResponsibles(ctx echo.Context) error func (w *ServerInterfaceWrapper) PostAppsResponsibles(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostAppsResponsibles(ctx) @@ -1708,57 +1708,57 @@ func (w *ServerInterfaceWrapper) PostAppsResponsibles(ctx echo.Context) error { func (w *ServerInterfaceWrapper) GetArrays(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetArraysParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -1772,9 +1772,9 @@ func (w *ServerInterfaceWrapper) GetArrays(ctx echo.Context) error { func (w *ServerInterfaceWrapper) PostAuthNode(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostAuthNode(ctx) @@ -1785,9 +1785,9 @@ func (w *ServerInterfaceWrapper) PostAuthNode(ctx echo.Context) error { func (w *ServerInterfaceWrapper) DeleteDisks(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteDisks(ctx) @@ -1798,57 +1798,57 @@ func (w *ServerInterfaceWrapper) DeleteDisks(ctx echo.Context) error { func (w *ServerInterfaceWrapper) GetDisks(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetDisksParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -1862,9 +1862,9 @@ func (w *ServerInterfaceWrapper) GetDisks(ctx echo.Context) error { func (w *ServerInterfaceWrapper) PostDisks(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostDisks(ctx) @@ -1877,14 +1877,14 @@ func (w *ServerInterfaceWrapper) DeleteDisk(ctx echo.Context) error { // ------------- Path parameter "disk_id" ------------- var diskId string - err = runtime.BindStyledParameterWithOptions("simple", "disk_id", ctx.Param("disk_id"), &diskId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "disk_id", ctx.Param("disk_id"), &diskId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter disk_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteDisk(ctx, diskId) @@ -1897,62 +1897,62 @@ func (w *ServerInterfaceWrapper) GetDisk(ctx echo.Context) error { // ------------- Path parameter "disk_id" ------------- var diskId string - err = runtime.BindStyledParameterWithOptions("simple", "disk_id", ctx.Param("disk_id"), &diskId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "disk_id", ctx.Param("disk_id"), &diskId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter disk_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetDiskParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -1966,9 +1966,9 @@ func (w *ServerInterfaceWrapper) GetDisk(ctx echo.Context) error { func (w *ServerInterfaceWrapper) DeleteFilters(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteFilters(ctx) @@ -1979,57 +1979,57 @@ func (w *ServerInterfaceWrapper) DeleteFilters(ctx echo.Context) error { func (w *ServerInterfaceWrapper) GetFilters(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetFiltersParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -2043,9 +2043,9 @@ func (w *ServerInterfaceWrapper) GetFilters(ctx echo.Context) error { func (w *ServerInterfaceWrapper) PostFilters(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostFilters(ctx) @@ -2058,14 +2058,14 @@ func (w *ServerInterfaceWrapper) DeleteFilter(ctx echo.Context) error { // ------------- Path parameter "filter_id" ------------- var filterId string - err = runtime.BindStyledParameterWithOptions("simple", "filter_id", ctx.Param("filter_id"), &filterId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "filter_id", ctx.Param("filter_id"), &filterId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteFilter(ctx, filterId) @@ -2078,62 +2078,62 @@ func (w *ServerInterfaceWrapper) GetFilter(ctx echo.Context) error { // ------------- Path parameter "filter_id" ------------- var filterId string - err = runtime.BindStyledParameterWithOptions("simple", "filter_id", ctx.Param("filter_id"), &filterId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "filter_id", ctx.Param("filter_id"), &filterId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetFilterParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -2149,14 +2149,14 @@ func (w *ServerInterfaceWrapper) PostFilter(ctx echo.Context) error { // ------------- Path parameter "filter_id" ------------- var filterId string - err = runtime.BindStyledParameterWithOptions("simple", "filter_id", ctx.Param("filter_id"), &filterId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "filter_id", ctx.Param("filter_id"), &filterId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostFilter(ctx, filterId) @@ -2167,9 +2167,9 @@ func (w *ServerInterfaceWrapper) PostFilter(ctx echo.Context) error { func (w *ServerInterfaceWrapper) DeleteFiltersets(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteFiltersets(ctx) @@ -2180,57 +2180,57 @@ func (w *ServerInterfaceWrapper) DeleteFiltersets(ctx echo.Context) error { func (w *ServerInterfaceWrapper) GetFiltersets(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetFiltersetsParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -2244,9 +2244,9 @@ func (w *ServerInterfaceWrapper) GetFiltersets(ctx echo.Context) error { func (w *ServerInterfaceWrapper) PostFiltersets(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostFiltersets(ctx) @@ -2259,14 +2259,14 @@ func (w *ServerInterfaceWrapper) DeleteFilterset(ctx echo.Context) error { // ------------- Path parameter "filterset_id" ------------- var filtersetId string - err = runtime.BindStyledParameterWithOptions("simple", "filterset_id", ctx.Param("filterset_id"), &filtersetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "filterset_id", ctx.Param("filterset_id"), &filtersetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filterset_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteFilterset(ctx, filtersetId) @@ -2279,62 +2279,62 @@ func (w *ServerInterfaceWrapper) GetFilterset(ctx echo.Context) error { // ------------- Path parameter "filterset_id" ------------- var filtersetId string - err = runtime.BindStyledParameterWithOptions("simple", "filterset_id", ctx.Param("filterset_id"), &filtersetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "filterset_id", ctx.Param("filterset_id"), &filtersetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filterset_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetFiltersetParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -2350,14 +2350,14 @@ func (w *ServerInterfaceWrapper) PostFilterset(ctx echo.Context) error { // ------------- Path parameter "filterset_id" ------------- var filtersetId string - err = runtime.BindStyledParameterWithOptions("simple", "filterset_id", ctx.Param("filterset_id"), &filtersetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "filterset_id", ctx.Param("filterset_id"), &filtersetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filterset_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostFilterset(ctx, filtersetId) @@ -2370,14 +2370,14 @@ func (w *ServerInterfaceWrapper) GetFiltersetExport(ctx echo.Context) error { // ------------- Path parameter "filterset_id" ------------- var filtersetId string - err = runtime.BindStyledParameterWithOptions("simple", "filterset_id", ctx.Param("filterset_id"), &filtersetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "filterset_id", ctx.Param("filterset_id"), &filtersetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filterset_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.GetFiltersetExport(ctx, filtersetId) @@ -2390,62 +2390,62 @@ func (w *ServerInterfaceWrapper) GetFiltersetFilters(ctx echo.Context) error { // ------------- Path parameter "filterset_id" ------------- var filtersetId string - err = runtime.BindStyledParameterWithOptions("simple", "filterset_id", ctx.Param("filterset_id"), &filtersetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "filterset_id", ctx.Param("filterset_id"), &filtersetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filterset_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetFiltersetFiltersParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -2461,7 +2461,7 @@ func (w *ServerInterfaceWrapper) DeleteFiltersetFilter(ctx echo.Context) error { // ------------- Path parameter "filterset_id" ------------- var filtersetId string - err = runtime.BindStyledParameterWithOptions("simple", "filterset_id", ctx.Param("filterset_id"), &filtersetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "filterset_id", ctx.Param("filterset_id"), &filtersetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filterset_id: %s", err)) } @@ -2469,14 +2469,14 @@ func (w *ServerInterfaceWrapper) DeleteFiltersetFilter(ctx echo.Context) error { // ------------- Path parameter "f_id" ------------- var fId string - err = runtime.BindStyledParameterWithOptions("simple", "f_id", ctx.Param("f_id"), &fId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "f_id", ctx.Param("f_id"), &fId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter f_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteFiltersetFilter(ctx, filtersetId, fId) @@ -2489,7 +2489,7 @@ func (w *ServerInterfaceWrapper) PostFiltersetFilter(ctx echo.Context) error { // ------------- Path parameter "filterset_id" ------------- var filtersetId string - err = runtime.BindStyledParameterWithOptions("simple", "filterset_id", ctx.Param("filterset_id"), &filtersetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "filterset_id", ctx.Param("filterset_id"), &filtersetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filterset_id: %s", err)) } @@ -2497,14 +2497,14 @@ func (w *ServerInterfaceWrapper) PostFiltersetFilter(ctx echo.Context) error { // ------------- Path parameter "f_id" ------------- var fId string - err = runtime.BindStyledParameterWithOptions("simple", "f_id", ctx.Param("f_id"), &fId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "f_id", ctx.Param("f_id"), &fId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter f_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostFiltersetFilter(ctx, filtersetId, fId) @@ -2517,62 +2517,62 @@ func (w *ServerInterfaceWrapper) GetFiltersetFiltersets(ctx echo.Context) error // ------------- Path parameter "filterset_id" ------------- var filtersetId string - err = runtime.BindStyledParameterWithOptions("simple", "filterset_id", ctx.Param("filterset_id"), &filtersetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "filterset_id", ctx.Param("filterset_id"), &filtersetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filterset_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetFiltersetFiltersetsParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -2588,7 +2588,7 @@ func (w *ServerInterfaceWrapper) DeleteFiltersetFilterset(ctx echo.Context) erro // ------------- Path parameter "filterset_id" ------------- var filtersetId string - err = runtime.BindStyledParameterWithOptions("simple", "filterset_id", ctx.Param("filterset_id"), &filtersetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "filterset_id", ctx.Param("filterset_id"), &filtersetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filterset_id: %s", err)) } @@ -2596,14 +2596,14 @@ func (w *ServerInterfaceWrapper) DeleteFiltersetFilterset(ctx echo.Context) erro // ------------- Path parameter "child_id" ------------- var childId string - err = runtime.BindStyledParameterWithOptions("simple", "child_id", ctx.Param("child_id"), &childId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "child_id", ctx.Param("child_id"), &childId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter child_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteFiltersetFilterset(ctx, filtersetId, childId) @@ -2616,7 +2616,7 @@ func (w *ServerInterfaceWrapper) PostFiltersetFilterset(ctx echo.Context) error // ------------- Path parameter "filterset_id" ------------- var filtersetId string - err = runtime.BindStyledParameterWithOptions("simple", "filterset_id", ctx.Param("filterset_id"), &filtersetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "filterset_id", ctx.Param("filterset_id"), &filtersetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filterset_id: %s", err)) } @@ -2624,14 +2624,14 @@ func (w *ServerInterfaceWrapper) PostFiltersetFilterset(ctx echo.Context) error // ------------- Path parameter "child_id" ------------- var childId string - err = runtime.BindStyledParameterWithOptions("simple", "child_id", ctx.Param("child_id"), &childId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "child_id", ctx.Param("child_id"), &childId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter child_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostFiltersetFilterset(ctx, filtersetId, childId) @@ -2644,62 +2644,62 @@ func (w *ServerInterfaceWrapper) GetFiltersetNodes(ctx echo.Context) error { // ------------- Path parameter "filterset_id" ------------- var filtersetId string - err = runtime.BindStyledParameterWithOptions("simple", "filterset_id", ctx.Param("filterset_id"), &filtersetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "filterset_id", ctx.Param("filterset_id"), &filtersetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filterset_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetFiltersetNodesParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -2715,62 +2715,62 @@ func (w *ServerInterfaceWrapper) GetFiltersetServices(ctx echo.Context) error { // ------------- Path parameter "filterset_id" ------------- var filtersetId string - err = runtime.BindStyledParameterWithOptions("simple", "filterset_id", ctx.Param("filterset_id"), &filtersetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "filterset_id", ctx.Param("filterset_id"), &filtersetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filterset_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetFiltersetServicesParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -2786,14 +2786,14 @@ func (w *ServerInterfaceWrapper) GetFiltersetUsage(ctx echo.Context) error { // ------------- Path parameter "filterset_id" ------------- var filtersetId string - err = runtime.BindStyledParameterWithOptions("simple", "filterset_id", ctx.Param("filterset_id"), &filtersetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "filterset_id", ctx.Param("filterset_id"), &filtersetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filterset_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.GetFiltersetUsage(ctx, filtersetId) @@ -2804,9 +2804,9 @@ func (w *ServerInterfaceWrapper) GetFiltersetUsage(ctx echo.Context) error { func (w *ServerInterfaceWrapper) DeleteFiltersetsFilters(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteFiltersetsFilters(ctx) @@ -2817,9 +2817,9 @@ func (w *ServerInterfaceWrapper) DeleteFiltersetsFilters(ctx echo.Context) error func (w *ServerInterfaceWrapper) PostFiltersetsFilters(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostFiltersetsFilters(ctx) @@ -2830,9 +2830,9 @@ func (w *ServerInterfaceWrapper) PostFiltersetsFilters(ctx echo.Context) error { func (w *ServerInterfaceWrapper) DeleteFiltersetsFiltersets(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteFiltersetsFiltersets(ctx) @@ -2843,9 +2843,9 @@ func (w *ServerInterfaceWrapper) DeleteFiltersetsFiltersets(ctx echo.Context) er func (w *ServerInterfaceWrapper) PostFiltersetsFiltersets(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostFiltersetsFiltersets(ctx) @@ -2856,57 +2856,57 @@ func (w *ServerInterfaceWrapper) PostFiltersetsFiltersets(ctx echo.Context) erro func (w *ServerInterfaceWrapper) GetFrontendHiddenMenuEntries(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetFrontendHiddenMenuEntriesParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -2920,9 +2920,9 @@ func (w *ServerInterfaceWrapper) GetFrontendHiddenMenuEntries(ctx echo.Context) func (w *ServerInterfaceWrapper) DeleteGroups(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteGroups(ctx) @@ -2933,57 +2933,57 @@ func (w *ServerInterfaceWrapper) DeleteGroups(ctx echo.Context) error { func (w *ServerInterfaceWrapper) GetGroups(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetGroupsParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -2997,9 +2997,9 @@ func (w *ServerInterfaceWrapper) GetGroups(ctx echo.Context) error { func (w *ServerInterfaceWrapper) PostGroups(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostGroups(ctx) @@ -3012,14 +3012,14 @@ func (w *ServerInterfaceWrapper) DeleteGroup(ctx echo.Context) error { // ------------- Path parameter "group_id" ------------- var groupId string - err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter group_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteGroup(ctx, groupId) @@ -3032,62 +3032,62 @@ func (w *ServerInterfaceWrapper) GetGroup(ctx echo.Context) error { // ------------- Path parameter "group_id" ------------- var groupId string - err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter group_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetGroupParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -3103,14 +3103,14 @@ func (w *ServerInterfaceWrapper) PostGroup(ctx echo.Context) error { // ------------- Path parameter "group_id" ------------- var groupId string - err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter group_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostGroup(ctx, groupId) @@ -3123,62 +3123,62 @@ func (w *ServerInterfaceWrapper) GetGroupApps(ctx echo.Context) error { // ------------- Path parameter "group_id" ------------- var groupId string - err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter group_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetGroupAppsParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -3194,14 +3194,14 @@ func (w *ServerInterfaceWrapper) DeleteGroupHiddenMenuEntries(ctx echo.Context) // ------------- Path parameter "group_id" ------------- var groupId string - err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter group_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteGroupHiddenMenuEntries(ctx, groupId) @@ -3214,62 +3214,62 @@ func (w *ServerInterfaceWrapper) GetGroupHiddenMenuEntries(ctx echo.Context) err // ------------- Path parameter "group_id" ------------- var groupId string - err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter group_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetGroupHiddenMenuEntriesParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -3285,14 +3285,14 @@ func (w *ServerInterfaceWrapper) PostGroupHiddenMenuEntries(ctx echo.Context) er // ------------- Path parameter "group_id" ------------- var groupId string - err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter group_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostGroupHiddenMenuEntries(ctx, groupId) @@ -3305,62 +3305,62 @@ func (w *ServerInterfaceWrapper) GetGroupModulesets(ctx echo.Context) error { // ------------- Path parameter "group_id" ------------- var groupId string - err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter group_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetGroupModulesetsParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -3376,62 +3376,62 @@ func (w *ServerInterfaceWrapper) GetGroupNodes(ctx echo.Context) error { // ------------- Path parameter "group_id" ------------- var groupId string - err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter group_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetGroupNodesParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -3447,62 +3447,62 @@ func (w *ServerInterfaceWrapper) GetGroupRulesets(ctx echo.Context) error { // ------------- Path parameter "group_id" ------------- var groupId string - err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter group_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetGroupRulesetsParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -3518,62 +3518,62 @@ func (w *ServerInterfaceWrapper) GetGroupServices(ctx echo.Context) error { // ------------- Path parameter "group_id" ------------- var groupId string - err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter group_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetGroupServicesParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -3589,62 +3589,62 @@ func (w *ServerInterfaceWrapper) GetGroupUsers(ctx echo.Context) error { // ------------- Path parameter "group_id" ------------- var groupId string - err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter group_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetGroupUsersParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -3658,9 +3658,9 @@ func (w *ServerInterfaceWrapper) GetGroupUsers(ctx echo.Context) error { func (w *ServerInterfaceWrapper) DeleteIps(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteIps(ctx) @@ -3671,57 +3671,57 @@ func (w *ServerInterfaceWrapper) DeleteIps(ctx echo.Context) error { func (w *ServerInterfaceWrapper) GetIps(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetIpsParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -3737,14 +3737,14 @@ func (w *ServerInterfaceWrapper) DeleteIp(ctx echo.Context) error { // ------------- Path parameter "id" ------------- var id string - err = runtime.BindStyledParameterWithOptions("simple", "id", ctx.Param("id"), &id, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "id", ctx.Param("id"), &id, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteIp(ctx, id) @@ -3757,62 +3757,62 @@ func (w *ServerInterfaceWrapper) GetIp(ctx echo.Context) error { // ------------- Path parameter "id" ------------- var id string - err = runtime.BindStyledParameterWithOptions("simple", "id", ctx.Param("id"), &id, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "id", ctx.Param("id"), &id, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetIpParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -3826,64 +3826,64 @@ func (w *ServerInterfaceWrapper) GetIp(ctx echo.Context) error { func (w *ServerInterfaceWrapper) GetLogs(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetLogsParams // ------------- Optional query parameter "fset_id" ------------- - err = runtime.BindQueryParameter("form", true, false, "fset_id", ctx.QueryParams(), ¶ms.FsetId) + err = runtime.BindQueryParameterWithOptions("form", true, false, "fset_id", ctx.QueryParams(), ¶ms.FsetId, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter fset_id: %s", err)) } // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -3897,9 +3897,9 @@ func (w *ServerInterfaceWrapper) GetLogs(ctx echo.Context) error { func (w *ServerInterfaceWrapper) PostLogs(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostLogs(ctx) @@ -3912,62 +3912,62 @@ func (w *ServerInterfaceWrapper) GetLog(ctx echo.Context) error { // ------------- Path parameter "log_id" ------------- var logId string - err = runtime.BindStyledParameterWithOptions("simple", "log_id", ctx.Param("log_id"), &logId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "log_id", ctx.Param("log_id"), &logId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter log_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetLogParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -3981,9 +3981,9 @@ func (w *ServerInterfaceWrapper) GetLog(ctx echo.Context) error { func (w *ServerInterfaceWrapper) DeleteNodes(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteNodes(ctx) @@ -3994,57 +3994,57 @@ func (w *ServerInterfaceWrapper) DeleteNodes(ctx echo.Context) error { func (w *ServerInterfaceWrapper) GetNodes(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetNodesParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -4058,9 +4058,9 @@ func (w *ServerInterfaceWrapper) GetNodes(ctx echo.Context) error { func (w *ServerInterfaceWrapper) PostNodes(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostNodes(ctx) @@ -4071,57 +4071,57 @@ func (w *ServerInterfaceWrapper) PostNodes(ctx echo.Context) error { func (w *ServerInterfaceWrapper) GetNodesHardware(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetNodesHardwareParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -4135,57 +4135,57 @@ func (w *ServerInterfaceWrapper) GetNodesHardware(ctx echo.Context) error { func (w *ServerInterfaceWrapper) GetNodesHbas(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetNodesHbasParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -4201,14 +4201,14 @@ func (w *ServerInterfaceWrapper) DeleteNode(ctx echo.Context) error { // ------------- Path parameter "node_id" ------------- var nodeId string - err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteNode(ctx, nodeId) @@ -4221,62 +4221,62 @@ func (w *ServerInterfaceWrapper) GetNode(ctx echo.Context) error { // ------------- Path parameter "node_id" ------------- var nodeId string - err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetNodeParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -4292,14 +4292,14 @@ func (w *ServerInterfaceWrapper) PostNode(ctx echo.Context) error { // ------------- Path parameter "node_id" ------------- var nodeId string - err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostNode(ctx, nodeId) @@ -4312,62 +4312,62 @@ func (w *ServerInterfaceWrapper) GetNodeAlerts(ctx echo.Context) error { // ------------- Path parameter "node_id" ------------- var nodeId string - err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetNodeAlertsParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -4383,14 +4383,14 @@ func (w *ServerInterfaceWrapper) GetNodeAmIResponsible(ctx echo.Context) error { // ------------- Path parameter "node_id" ------------- var nodeId string - err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.GetNodeAmIResponsible(ctx, nodeId) @@ -4403,62 +4403,62 @@ func (w *ServerInterfaceWrapper) GetNodeCandidateTags(ctx echo.Context) error { // ------------- Path parameter "node_id" ------------- var nodeId string - err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetNodeCandidateTagsParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -4474,62 +4474,62 @@ func (w *ServerInterfaceWrapper) GetNodeChecks(ctx echo.Context) error { // ------------- Path parameter "node_id" ------------- var nodeId string - err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetNodeChecksParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -4545,62 +4545,62 @@ func (w *ServerInterfaceWrapper) GetNodeComplianceCandidateModulesets(ctx echo.C // ------------- Path parameter "node_id" ------------- var nodeId InPathNodeId - err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetNodeComplianceCandidateModulesetsParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -4616,62 +4616,62 @@ func (w *ServerInterfaceWrapper) GetNodeComplianceCandidateRulesets(ctx echo.Con // ------------- Path parameter "node_id" ------------- var nodeId InPathNodeId - err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetNodeComplianceCandidateRulesetsParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -4687,62 +4687,62 @@ func (w *ServerInterfaceWrapper) GetNodeComplianceLogs(ctx echo.Context) error { // ------------- Path parameter "node_id" ------------- var nodeId InPathNodeId - err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetNodeComplianceLogsParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -4758,62 +4758,62 @@ func (w *ServerInterfaceWrapper) GetNodeComplianceModulesets(ctx echo.Context) e // ------------- Path parameter "node_id" ------------- var nodeId InPathNodeId - err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetNodeComplianceModulesetsParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -4829,7 +4829,7 @@ func (w *ServerInterfaceWrapper) DeleteNodeComplianceModuleset(ctx echo.Context) // ------------- Path parameter "node_id" ------------- var nodeId InPathNodeId - err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_id: %s", err)) } @@ -4837,14 +4837,14 @@ func (w *ServerInterfaceWrapper) DeleteNodeComplianceModuleset(ctx echo.Context) // ------------- Path parameter "mset_id" ------------- var msetId InPathMsetId - err = runtime.BindStyledParameterWithOptions("simple", "mset_id", ctx.Param("mset_id"), &msetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "mset_id", ctx.Param("mset_id"), &msetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter mset_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteNodeComplianceModuleset(ctx, nodeId, msetId) @@ -4857,7 +4857,7 @@ func (w *ServerInterfaceWrapper) PostNodeComplianceModuleset(ctx echo.Context) e // ------------- Path parameter "node_id" ------------- var nodeId InPathNodeId - err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_id: %s", err)) } @@ -4865,14 +4865,14 @@ func (w *ServerInterfaceWrapper) PostNodeComplianceModuleset(ctx echo.Context) e // ------------- Path parameter "mset_id" ------------- var msetId InPathMsetId - err = runtime.BindStyledParameterWithOptions("simple", "mset_id", ctx.Param("mset_id"), &msetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "mset_id", ctx.Param("mset_id"), &msetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter mset_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostNodeComplianceModuleset(ctx, nodeId, msetId) @@ -4885,62 +4885,62 @@ func (w *ServerInterfaceWrapper) GetNodeComplianceRulesets(ctx echo.Context) err // ------------- Path parameter "node_id" ------------- var nodeId InPathNodeId - err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetNodeComplianceRulesetsParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -4956,7 +4956,7 @@ func (w *ServerInterfaceWrapper) DeleteNodeComplianceRuleset(ctx echo.Context) e // ------------- Path parameter "node_id" ------------- var nodeId InPathNodeId - err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_id: %s", err)) } @@ -4964,14 +4964,14 @@ func (w *ServerInterfaceWrapper) DeleteNodeComplianceRuleset(ctx echo.Context) e // ------------- Path parameter "rset_id" ------------- var rsetId InPathRsetId - err = runtime.BindStyledParameterWithOptions("simple", "rset_id", ctx.Param("rset_id"), &rsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "rset_id", ctx.Param("rset_id"), &rsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter rset_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteNodeComplianceRuleset(ctx, nodeId, rsetId) @@ -4984,7 +4984,7 @@ func (w *ServerInterfaceWrapper) PostNodeComplianceRuleset(ctx echo.Context) err // ------------- Path parameter "node_id" ------------- var nodeId InPathNodeId - err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_id: %s", err)) } @@ -4992,14 +4992,14 @@ func (w *ServerInterfaceWrapper) PostNodeComplianceRuleset(ctx echo.Context) err // ------------- Path parameter "rset_id" ------------- var rsetId InPathRsetId - err = runtime.BindStyledParameterWithOptions("simple", "rset_id", ctx.Param("rset_id"), &rsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "rset_id", ctx.Param("rset_id"), &rsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter rset_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostNodeComplianceRuleset(ctx, nodeId, rsetId) @@ -5012,62 +5012,62 @@ func (w *ServerInterfaceWrapper) GetNodeComplianceStatus(ctx echo.Context) error // ------------- Path parameter "node_id" ------------- var nodeId InPathNodeId - err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetNodeComplianceStatusParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -5083,62 +5083,62 @@ func (w *ServerInterfaceWrapper) GetNodeDisks(ctx echo.Context) error { // ------------- Path parameter "node_id" ------------- var nodeId string - err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetNodeDisksParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -5154,62 +5154,62 @@ func (w *ServerInterfaceWrapper) GetNodeHardware(ctx echo.Context) error { // ------------- Path parameter "node_id" ------------- var nodeId string - err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetNodeHardwareParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -5225,62 +5225,62 @@ func (w *ServerInterfaceWrapper) GetNodeHbas(ctx echo.Context) error { // ------------- Path parameter "node_id" ------------- var nodeId string - err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetNodeHbasParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -5296,62 +5296,62 @@ func (w *ServerInterfaceWrapper) GetNodeInterfaces(ctx echo.Context) error { // ------------- Path parameter "node_id" ------------- var nodeId string - err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetNodeInterfacesParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -5367,62 +5367,62 @@ func (w *ServerInterfaceWrapper) GetNodeIps(ctx echo.Context) error { // ------------- Path parameter "node_id" ------------- var nodeId string - err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetNodeIpsParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -5438,62 +5438,62 @@ func (w *ServerInterfaceWrapper) GetNodeServices(ctx echo.Context) error { // ------------- Path parameter "node_id" ------------- var nodeId string - err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetNodeServicesParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -5509,7 +5509,7 @@ func (w *ServerInterfaceWrapper) GetNodeService(ctx echo.Context) error { // ------------- Path parameter "node_id" ------------- var nodeId string - err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_id: %s", err)) } @@ -5517,62 +5517,62 @@ func (w *ServerInterfaceWrapper) GetNodeService(ctx echo.Context) error { // ------------- Path parameter "svc_id" ------------- var svcId string - err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter svc_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetNodeServiceParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -5588,14 +5588,14 @@ func (w *ServerInterfaceWrapper) PostNodeSnooze(ctx echo.Context) error { // ------------- Path parameter "node_id" ------------- var nodeId InPathNodeId - err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostNodeSnooze(ctx, nodeId) @@ -5608,62 +5608,62 @@ func (w *ServerInterfaceWrapper) GetNodeTags(ctx echo.Context) error { // ------------- Path parameter "node_id" ------------- var nodeId string - err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetNodeTagsParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -5679,14 +5679,14 @@ func (w *ServerInterfaceWrapper) GetNodeUUID(ctx echo.Context) error { // ------------- Path parameter "node_id" ------------- var nodeId string - err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.GetNodeUUID(ctx, nodeId) @@ -5697,9 +5697,9 @@ func (w *ServerInterfaceWrapper) GetNodeUUID(ctx echo.Context) error { func (w *ServerInterfaceWrapper) PutObsolescenceRefresh(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PutObsolescenceRefresh(ctx) @@ -5710,9 +5710,9 @@ func (w *ServerInterfaceWrapper) PutObsolescenceRefresh(ctx echo.Context) error func (w *ServerInterfaceWrapper) DeleteObsolescenceSettings(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteObsolescenceSettings(ctx) @@ -5723,57 +5723,57 @@ func (w *ServerInterfaceWrapper) DeleteObsolescenceSettings(ctx echo.Context) er func (w *ServerInterfaceWrapper) GetObsolescenceSettings(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetObsolescenceSettingsParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -5787,9 +5787,9 @@ func (w *ServerInterfaceWrapper) GetObsolescenceSettings(ctx echo.Context) error func (w *ServerInterfaceWrapper) PostObsolescenceSettings(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostObsolescenceSettings(ctx) @@ -5802,14 +5802,14 @@ func (w *ServerInterfaceWrapper) DeleteObsolescenceSetting(ctx echo.Context) err // ------------- Path parameter "id" ------------- var id string - err = runtime.BindStyledParameterWithOptions("simple", "id", ctx.Param("id"), &id, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "id", ctx.Param("id"), &id, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteObsolescenceSetting(ctx, id) @@ -5822,62 +5822,62 @@ func (w *ServerInterfaceWrapper) GetObsolescenceSetting(ctx echo.Context) error // ------------- Path parameter "id" ------------- var id string - err = runtime.BindStyledParameterWithOptions("simple", "id", ctx.Param("id"), &id, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "id", ctx.Param("id"), &id, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetObsolescenceSettingParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -5893,14 +5893,14 @@ func (w *ServerInterfaceWrapper) PostObsolescenceSetting(ctx echo.Context) error // ------------- Path parameter "id" ------------- var id string - err = runtime.BindStyledParameterWithOptions("simple", "id", ctx.Param("id"), &id, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "id", ctx.Param("id"), &id, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostObsolescenceSetting(ctx, id) @@ -5920,9 +5920,9 @@ func (w *ServerInterfaceWrapper) GetSwagger(ctx echo.Context) error { func (w *ServerInterfaceWrapper) DeleteServices(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteServices(ctx) @@ -5933,57 +5933,57 @@ func (w *ServerInterfaceWrapper) DeleteServices(ctx echo.Context) error { func (w *ServerInterfaceWrapper) GetServices(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetServicesParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -5997,9 +5997,9 @@ func (w *ServerInterfaceWrapper) GetServices(ctx echo.Context) error { func (w *ServerInterfaceWrapper) PostServices(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostServices(ctx) @@ -6012,14 +6012,14 @@ func (w *ServerInterfaceWrapper) DeleteService(ctx echo.Context) error { // ------------- Path parameter "svc_id" ------------- var svcId string - err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter svc_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteService(ctx, svcId) @@ -6032,62 +6032,62 @@ func (w *ServerInterfaceWrapper) GetService(ctx echo.Context) error { // ------------- Path parameter "svc_id" ------------- var svcId string - err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter svc_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetServiceParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -6103,14 +6103,14 @@ func (w *ServerInterfaceWrapper) PostService(ctx echo.Context) error { // ------------- Path parameter "svc_id" ------------- var svcId string - err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter svc_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostService(ctx, svcId) @@ -6123,62 +6123,62 @@ func (w *ServerInterfaceWrapper) GetServiceAlerts(ctx echo.Context) error { // ------------- Path parameter "svc_id" ------------- var svcId string - err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter svc_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetServiceAlertsParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -6194,14 +6194,14 @@ func (w *ServerInterfaceWrapper) GetServiceAmIResponsible(ctx echo.Context) erro // ------------- Path parameter "svc_id" ------------- var svcId string - err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter svc_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.GetServiceAmIResponsible(ctx, svcId) @@ -6214,62 +6214,62 @@ func (w *ServerInterfaceWrapper) GetServiceCandidateTags(ctx echo.Context) error // ------------- Path parameter "svc_id" ------------- var svcId string - err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter svc_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetServiceCandidateTagsParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -6285,62 +6285,62 @@ func (w *ServerInterfaceWrapper) GetServiceChecks(ctx echo.Context) error { // ------------- Path parameter "svc_id" ------------- var svcId string - err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter svc_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetServiceChecksParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -6356,62 +6356,62 @@ func (w *ServerInterfaceWrapper) GetServiceComplianceCandidateModulesets(ctx ech // ------------- Path parameter "svc_id" ------------- var svcId string - err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter svc_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetServiceComplianceCandidateModulesetsParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -6427,69 +6427,69 @@ func (w *ServerInterfaceWrapper) GetServiceComplianceCandidateRulesets(ctx echo. // ------------- Path parameter "svc_id" ------------- var svcId string - err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter svc_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetServiceComplianceCandidateRulesetsParams // ------------- Optional query parameter "slave" ------------- - err = runtime.BindQueryParameter("form", true, false, "slave", ctx.QueryParams(), ¶ms.Slave) + err = runtime.BindQueryParameterWithOptions("form", true, false, "slave", ctx.QueryParams(), ¶ms.Slave, runtime.BindQueryParameterOptions{Type: "boolean", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter slave: %s", err)) } // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -6505,62 +6505,62 @@ func (w *ServerInterfaceWrapper) GetServiceComplianceLogs(ctx echo.Context) erro // ------------- Path parameter "svc_id" ------------- var svcId string - err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter svc_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetServiceComplianceLogsParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -6576,69 +6576,69 @@ func (w *ServerInterfaceWrapper) GetServiceComplianceModulesets(ctx echo.Context // ------------- Path parameter "svc_id" ------------- var svcId string - err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter svc_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetServiceComplianceModulesetsParams // ------------- Optional query parameter "slave" ------------- - err = runtime.BindQueryParameter("form", true, false, "slave", ctx.QueryParams(), ¶ms.Slave) + err = runtime.BindQueryParameterWithOptions("form", true, false, "slave", ctx.QueryParams(), ¶ms.Slave, runtime.BindQueryParameterOptions{Type: "boolean", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter slave: %s", err)) } // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -6654,7 +6654,7 @@ func (w *ServerInterfaceWrapper) DeleteServiceComplianceModuleset(ctx echo.Conte // ------------- Path parameter "svc_id" ------------- var svcId string - err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter svc_id: %s", err)) } @@ -6662,20 +6662,20 @@ func (w *ServerInterfaceWrapper) DeleteServiceComplianceModuleset(ctx echo.Conte // ------------- Path parameter "mset_id" ------------- var msetId InPathMsetId - err = runtime.BindStyledParameterWithOptions("simple", "mset_id", ctx.Param("mset_id"), &msetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "mset_id", ctx.Param("mset_id"), &msetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter mset_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params DeleteServiceComplianceModulesetParams // ------------- Optional query parameter "slave" ------------- - err = runtime.BindQueryParameter("form", true, false, "slave", ctx.QueryParams(), ¶ms.Slave) + err = runtime.BindQueryParameterWithOptions("form", true, false, "slave", ctx.QueryParams(), ¶ms.Slave, runtime.BindQueryParameterOptions{Type: "boolean", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter slave: %s", err)) } @@ -6691,7 +6691,7 @@ func (w *ServerInterfaceWrapper) PostServiceComplianceModuleset(ctx echo.Context // ------------- Path parameter "svc_id" ------------- var svcId string - err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter svc_id: %s", err)) } @@ -6699,20 +6699,20 @@ func (w *ServerInterfaceWrapper) PostServiceComplianceModuleset(ctx echo.Context // ------------- Path parameter "mset_id" ------------- var msetId InPathMsetId - err = runtime.BindStyledParameterWithOptions("simple", "mset_id", ctx.Param("mset_id"), &msetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "mset_id", ctx.Param("mset_id"), &msetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter mset_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params PostServiceComplianceModulesetParams // ------------- Optional query parameter "slave" ------------- - err = runtime.BindQueryParameter("form", true, false, "slave", ctx.QueryParams(), ¶ms.Slave) + err = runtime.BindQueryParameterWithOptions("form", true, false, "slave", ctx.QueryParams(), ¶ms.Slave, runtime.BindQueryParameterOptions{Type: "boolean", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter slave: %s", err)) } @@ -6728,69 +6728,69 @@ func (w *ServerInterfaceWrapper) GetServiceComplianceRulesets(ctx echo.Context) // ------------- Path parameter "svc_id" ------------- var svcId string - err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter svc_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetServiceComplianceRulesetsParams // ------------- Optional query parameter "slave" ------------- - err = runtime.BindQueryParameter("form", true, false, "slave", ctx.QueryParams(), ¶ms.Slave) + err = runtime.BindQueryParameterWithOptions("form", true, false, "slave", ctx.QueryParams(), ¶ms.Slave, runtime.BindQueryParameterOptions{Type: "boolean", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter slave: %s", err)) } // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -6806,7 +6806,7 @@ func (w *ServerInterfaceWrapper) DeleteServiceComplianceRuleset(ctx echo.Context // ------------- Path parameter "svc_id" ------------- var svcId string - err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter svc_id: %s", err)) } @@ -6814,20 +6814,20 @@ func (w *ServerInterfaceWrapper) DeleteServiceComplianceRuleset(ctx echo.Context // ------------- Path parameter "rset_id" ------------- var rsetId InPathRsetId - err = runtime.BindStyledParameterWithOptions("simple", "rset_id", ctx.Param("rset_id"), &rsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "rset_id", ctx.Param("rset_id"), &rsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter rset_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params DeleteServiceComplianceRulesetParams // ------------- Optional query parameter "slave" ------------- - err = runtime.BindQueryParameter("form", true, false, "slave", ctx.QueryParams(), ¶ms.Slave) + err = runtime.BindQueryParameterWithOptions("form", true, false, "slave", ctx.QueryParams(), ¶ms.Slave, runtime.BindQueryParameterOptions{Type: "boolean", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter slave: %s", err)) } @@ -6843,7 +6843,7 @@ func (w *ServerInterfaceWrapper) PostServiceComplianceRuleset(ctx echo.Context) // ------------- Path parameter "svc_id" ------------- var svcId string - err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter svc_id: %s", err)) } @@ -6851,20 +6851,20 @@ func (w *ServerInterfaceWrapper) PostServiceComplianceRuleset(ctx echo.Context) // ------------- Path parameter "rset_id" ------------- var rsetId InPathRsetId - err = runtime.BindStyledParameterWithOptions("simple", "rset_id", ctx.Param("rset_id"), &rsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "rset_id", ctx.Param("rset_id"), &rsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter rset_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params PostServiceComplianceRulesetParams // ------------- Optional query parameter "slave" ------------- - err = runtime.BindQueryParameter("form", true, false, "slave", ctx.QueryParams(), ¶ms.Slave) + err = runtime.BindQueryParameterWithOptions("form", true, false, "slave", ctx.QueryParams(), ¶ms.Slave, runtime.BindQueryParameterOptions{Type: "boolean", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter slave: %s", err)) } @@ -6880,62 +6880,62 @@ func (w *ServerInterfaceWrapper) GetServiceComplianceStatus(ctx echo.Context) er // ------------- Path parameter "svc_id" ------------- var svcId string - err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter svc_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetServiceComplianceStatusParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -6951,62 +6951,62 @@ func (w *ServerInterfaceWrapper) GetServiceDisks(ctx echo.Context) error { // ------------- Path parameter "svc_id" ------------- var svcId string - err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter svc_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetServiceDisksParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -7022,7 +7022,7 @@ func (w *ServerInterfaceWrapper) DeleteServiceInstance(ctx echo.Context) error { // ------------- Path parameter "svc_id" ------------- var svcId string - err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter svc_id: %s", err)) } @@ -7030,14 +7030,14 @@ func (w *ServerInterfaceWrapper) DeleteServiceInstance(ctx echo.Context) error { // ------------- Path parameter "node_id" ------------- var nodeId string - err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteServiceInstance(ctx, svcId, nodeId) @@ -7050,7 +7050,7 @@ func (w *ServerInterfaceWrapper) GetServiceInstance(ctx echo.Context) error { // ------------- Path parameter "svc_id" ------------- var svcId string - err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter svc_id: %s", err)) } @@ -7058,62 +7058,62 @@ func (w *ServerInterfaceWrapper) GetServiceInstance(ctx echo.Context) error { // ------------- Path parameter "node_id" ------------- var nodeId string - err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetServiceInstanceParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -7129,62 +7129,62 @@ func (w *ServerInterfaceWrapper) GetServiceNodes(ctx echo.Context) error { // ------------- Path parameter "svc_id" ------------- var svcId string - err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter svc_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetServiceNodesParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -7200,7 +7200,7 @@ func (w *ServerInterfaceWrapper) GetServiceNode(ctx echo.Context) error { // ------------- Path parameter "svc_id" ------------- var svcId string - err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter svc_id: %s", err)) } @@ -7208,62 +7208,62 @@ func (w *ServerInterfaceWrapper) GetServiceNode(ctx echo.Context) error { // ------------- Path parameter "node_id" ------------- var nodeId string - err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetServiceNodeParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -7279,7 +7279,7 @@ func (w *ServerInterfaceWrapper) GetServiceNodeResources(ctx echo.Context) error // ------------- Path parameter "svc_id" ------------- var svcId string - err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter svc_id: %s", err)) } @@ -7287,62 +7287,62 @@ func (w *ServerInterfaceWrapper) GetServiceNodeResources(ctx echo.Context) error // ------------- Path parameter "node_id" ------------- var nodeId string - err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetServiceNodeResourcesParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -7358,7 +7358,7 @@ func (w *ServerInterfaceWrapper) GetServiceNodeResourceLogs(ctx echo.Context) er // ------------- Path parameter "svc_id" ------------- var svcId string - err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter svc_id: %s", err)) } @@ -7366,62 +7366,62 @@ func (w *ServerInterfaceWrapper) GetServiceNodeResourceLogs(ctx echo.Context) er // ------------- Path parameter "node_id" ------------- var nodeId string - err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetServiceNodeResourceLogsParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -7437,62 +7437,62 @@ func (w *ServerInterfaceWrapper) GetServiceResinfo(ctx echo.Context) error { // ------------- Path parameter "svc_id" ------------- var svcId string - err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter svc_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetServiceResinfoParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -7508,62 +7508,62 @@ func (w *ServerInterfaceWrapper) GetServiceResources(ctx echo.Context) error { // ------------- Path parameter "svc_id" ------------- var svcId string - err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter svc_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetServiceResourcesParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -7579,62 +7579,62 @@ func (w *ServerInterfaceWrapper) GetServiceResourceLogs(ctx echo.Context) error // ------------- Path parameter "svc_id" ------------- var svcId string - err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter svc_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetServiceResourceLogsParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -7650,62 +7650,62 @@ func (w *ServerInterfaceWrapper) GetServiceTags(ctx echo.Context) error { // ------------- Path parameter "svc_id" ------------- var svcId string - err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter svc_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetServiceTagsParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -7719,9 +7719,9 @@ func (w *ServerInterfaceWrapper) GetServiceTags(ctx echo.Context) error { func (w *ServerInterfaceWrapper) DeleteServicesInstances(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteServicesInstances(ctx) @@ -7732,57 +7732,57 @@ func (w *ServerInterfaceWrapper) DeleteServicesInstances(ctx echo.Context) error func (w *ServerInterfaceWrapper) GetServicesInstances(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetServicesInstancesParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -7798,62 +7798,62 @@ func (w *ServerInterfaceWrapper) GetServicesInstance(ctx echo.Context) error { // ------------- Path parameter "svc_id" ------------- var svcId string - err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter svc_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetServicesInstanceParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -7867,57 +7867,57 @@ func (w *ServerInterfaceWrapper) GetServicesInstance(ctx echo.Context) error { func (w *ServerInterfaceWrapper) GetServicesInstancesStatusLog(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetServicesInstancesStatusLogParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -7931,57 +7931,57 @@ func (w *ServerInterfaceWrapper) GetServicesInstancesStatusLog(ctx echo.Context) func (w *ServerInterfaceWrapper) GetServicesStatusLog(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetServicesStatusLogParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -7995,9 +7995,9 @@ func (w *ServerInterfaceWrapper) GetServicesStatusLog(ctx echo.Context) error { func (w *ServerInterfaceWrapper) DeleteTags(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteTags(ctx) @@ -8008,57 +8008,57 @@ func (w *ServerInterfaceWrapper) DeleteTags(ctx echo.Context) error { func (w *ServerInterfaceWrapper) GetTags(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetTagsParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -8072,9 +8072,9 @@ func (w *ServerInterfaceWrapper) GetTags(ctx echo.Context) error { func (w *ServerInterfaceWrapper) PostTags(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostTags(ctx) @@ -8085,9 +8085,9 @@ func (w *ServerInterfaceWrapper) PostTags(ctx echo.Context) error { func (w *ServerInterfaceWrapper) DeleteTagsNodes(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteTagsNodes(ctx) @@ -8098,57 +8098,57 @@ func (w *ServerInterfaceWrapper) DeleteTagsNodes(ctx echo.Context) error { func (w *ServerInterfaceWrapper) GetTagsNodes(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetTagsNodesParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -8162,9 +8162,9 @@ func (w *ServerInterfaceWrapper) GetTagsNodes(ctx echo.Context) error { func (w *ServerInterfaceWrapper) PostTagsNodes(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostTagsNodes(ctx) @@ -8175,9 +8175,9 @@ func (w *ServerInterfaceWrapper) PostTagsNodes(ctx echo.Context) error { func (w *ServerInterfaceWrapper) DeleteTagsServices(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteTagsServices(ctx) @@ -8188,57 +8188,57 @@ func (w *ServerInterfaceWrapper) DeleteTagsServices(ctx echo.Context) error { func (w *ServerInterfaceWrapper) GetTagsServices(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetTagsServicesParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -8252,9 +8252,9 @@ func (w *ServerInterfaceWrapper) GetTagsServices(ctx echo.Context) error { func (w *ServerInterfaceWrapper) PostTagsServices(ctx echo.Context) error { var err error - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostTagsServices(ctx) @@ -8267,14 +8267,14 @@ func (w *ServerInterfaceWrapper) DeleteTag(ctx echo.Context) error { // ------------- Path parameter "tag_id" ------------- var tagId int - err = runtime.BindStyledParameterWithOptions("simple", "tag_id", ctx.Param("tag_id"), &tagId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "tag_id", ctx.Param("tag_id"), &tagId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter tag_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteTag(ctx, tagId) @@ -8287,20 +8287,20 @@ func (w *ServerInterfaceWrapper) GetTag(ctx echo.Context) error { // ------------- Path parameter "tag_id" ------------- var tagId int - err = runtime.BindStyledParameterWithOptions("simple", "tag_id", ctx.Param("tag_id"), &tagId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "tag_id", ctx.Param("tag_id"), &tagId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter tag_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetTagParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } @@ -8316,14 +8316,14 @@ func (w *ServerInterfaceWrapper) PostTag(ctx echo.Context) error { // ------------- Path parameter "tag_id" ------------- var tagId int - err = runtime.BindStyledParameterWithOptions("simple", "tag_id", ctx.Param("tag_id"), &tagId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "tag_id", ctx.Param("tag_id"), &tagId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter tag_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostTag(ctx, tagId) @@ -8336,34 +8336,34 @@ func (w *ServerInterfaceWrapper) GetTagNodes(ctx echo.Context) error { // ------------- Path parameter "tag_id" ------------- var tagId int - err = runtime.BindStyledParameterWithOptions("simple", "tag_id", ctx.Param("tag_id"), &tagId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "tag_id", ctx.Param("tag_id"), &tagId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter tag_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetTagNodesParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } @@ -8379,7 +8379,7 @@ func (w *ServerInterfaceWrapper) DeleteTagNode(ctx echo.Context) error { // ------------- Path parameter "tag_id" ------------- var tagId int - err = runtime.BindStyledParameterWithOptions("simple", "tag_id", ctx.Param("tag_id"), &tagId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "tag_id", ctx.Param("tag_id"), &tagId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter tag_id: %s", err)) } @@ -8387,14 +8387,14 @@ func (w *ServerInterfaceWrapper) DeleteTagNode(ctx echo.Context) error { // ------------- Path parameter "node_id" ------------- var nodeId string - err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteTagNode(ctx, tagId, nodeId) @@ -8407,7 +8407,7 @@ func (w *ServerInterfaceWrapper) PostTagNode(ctx echo.Context) error { // ------------- Path parameter "tag_id" ------------- var tagId int - err = runtime.BindStyledParameterWithOptions("simple", "tag_id", ctx.Param("tag_id"), &tagId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "tag_id", ctx.Param("tag_id"), &tagId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter tag_id: %s", err)) } @@ -8415,14 +8415,14 @@ func (w *ServerInterfaceWrapper) PostTagNode(ctx echo.Context) error { // ------------- Path parameter "node_id" ------------- var nodeId string - err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostTagNode(ctx, tagId, nodeId) @@ -8435,62 +8435,62 @@ func (w *ServerInterfaceWrapper) GetTagServices(ctx echo.Context) error { // ------------- Path parameter "tag_id" ------------- var tagId int - err = runtime.BindStyledParameterWithOptions("simple", "tag_id", ctx.Param("tag_id"), &tagId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "tag_id", ctx.Param("tag_id"), &tagId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter tag_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Parameter object where we will unmarshal all parameters from the context var params GetTagServicesParams // ------------- Optional query parameter "props" ------------- - err = runtime.BindQueryParameter("form", true, false, "props", ctx.QueryParams(), ¶ms.Props) + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) } // ------------- Optional query parameter "limit" ------------- - err = runtime.BindQueryParameter("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit) + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) } // ------------- Optional query parameter "offset" ------------- - err = runtime.BindQueryParameter("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset) + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) } // ------------- Optional query parameter "meta" ------------- - err = runtime.BindQueryParameter("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta) + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) } // ------------- Optional query parameter "stats" ------------- - err = runtime.BindQueryParameter("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats) + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) } // ------------- Optional query parameter "orderby" ------------- - err = runtime.BindQueryParameter("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } // ------------- Optional query parameter "groupby" ------------- - err = runtime.BindQueryParameter("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby) + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } @@ -8506,7 +8506,7 @@ func (w *ServerInterfaceWrapper) DeleteTagService(ctx echo.Context) error { // ------------- Path parameter "tag_id" ------------- var tagId int - err = runtime.BindStyledParameterWithOptions("simple", "tag_id", ctx.Param("tag_id"), &tagId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "tag_id", ctx.Param("tag_id"), &tagId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter tag_id: %s", err)) } @@ -8514,14 +8514,14 @@ func (w *ServerInterfaceWrapper) DeleteTagService(ctx echo.Context) error { // ------------- Path parameter "svc_id" ------------- var svcId string - err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter svc_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.DeleteTagService(ctx, tagId, svcId) @@ -8534,7 +8534,7 @@ func (w *ServerInterfaceWrapper) PostTagService(ctx echo.Context) error { // ------------- Path parameter "tag_id" ------------- var tagId int - err = runtime.BindStyledParameterWithOptions("simple", "tag_id", ctx.Param("tag_id"), &tagId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "tag_id", ctx.Param("tag_id"), &tagId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "integer", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter tag_id: %s", err)) } @@ -8542,14 +8542,14 @@ func (w *ServerInterfaceWrapper) PostTagService(ctx echo.Context) error { // ------------- Path parameter "svc_id" ------------- var svcId string - err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) if err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter svc_id: %s", err)) } - ctx.Set(BasicAuthScopes, []string{}) + ctx.Set(string(BasicAuthScopes), []string{}) - ctx.Set(BearerAuthScopes, []string{}) + ctx.Set(string(BearerAuthScopes), []string{}) // Invoke the callback with all the unmarshaled arguments err = w.Handler.PostTagService(ctx, tagId, svcId) @@ -8580,389 +8580,434 @@ type EchoRouter interface { TRACE(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route } +// RegisterHandlersOptions configures RegisterHandlersWithOptions. +type RegisterHandlersOptions struct { + // BaseURL is prepended to every registered path so the API can be served + // under a prefix. + BaseURL string + // OperationMiddlewares lets the caller attach per-operation middleware at + // registration time. The map key is the OpenAPI `operationId` value as it + // appears in the spec (the raw, un-normalized form). Operations that have + // no entry are registered with no extra middleware. A nil map disables + // per-operation middleware entirely. + OperationMiddlewares map[string][]echo.MiddlewareFunc +} + // RegisterHandlers adds each server route to the EchoRouter. func RegisterHandlers(router EchoRouter, si ServerInterface) { - RegisterHandlersWithBaseURL(router, si, "") + RegisterHandlersWithOptions(router, si, RegisterHandlersOptions{}) } -// Registers handlers, and prepends BaseURL to the paths, so that the paths -// can be served under a prefix. +// RegisterHandlersWithBaseURL registers handlers and prepends BaseURL to the +// paths so the API can be served under a prefix. func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL string) { + RegisterHandlersWithOptions(router, si, RegisterHandlersOptions{BaseURL: baseURL}) +} + +// RegisterHandlersWithOptions registers handlers using the supplied options, +// including any per-operation middleware. +func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options RegisterHandlersOptions) { wrapper := ServerInterfaceWrapper{ Handler: si, } - router.GET(baseURL+"/actions", wrapper.GetActions) - router.POST(baseURL+"/actions", wrapper.PostActions) - router.DELETE(baseURL+"/actions/:id", wrapper.DeleteAction) - router.GET(baseURL+"/actions/:id", wrapper.GetAction) - router.GET(baseURL+"/alert_event", wrapper.GetAlertEvent) - router.DELETE(baseURL+"/alerts", wrapper.DeleteAlerts) - router.GET(baseURL+"/alerts", wrapper.GetAlerts) - router.POST(baseURL+"/alerts", wrapper.PostAlerts) - router.DELETE(baseURL+"/alerts/:id", wrapper.DeleteAlert) - router.GET(baseURL+"/alerts/:id", wrapper.GetAlert) - router.POST(baseURL+"/alerts/:id", wrapper.PostAlert) - router.DELETE(baseURL+"/apps", wrapper.DeleteApps) - router.GET(baseURL+"/apps", wrapper.GetApps) - router.POST(baseURL+"/apps", wrapper.PostApps) - router.DELETE(baseURL+"/apps/:app_id", wrapper.DeleteApp) - router.GET(baseURL+"/apps/:app_id", wrapper.GetApp) - router.POST(baseURL+"/apps/:app_id", wrapper.PostApp) - router.GET(baseURL+"/apps/:app_id/am_i_responsible", wrapper.GetAppAmIResponsible) - router.GET(baseURL+"/apps/:app_id/nodes", wrapper.GetAppNodes) - router.GET(baseURL+"/apps/:app_id/publications", wrapper.GetAppPublications) - router.DELETE(baseURL+"/apps/:app_id/publications/:group_id", wrapper.DeleteAppPublication) - router.POST(baseURL+"/apps/:app_id/publications/:group_id", wrapper.PostAppPublication) - router.GET(baseURL+"/apps/:app_id/quotas", wrapper.GetAppQuotas) - router.GET(baseURL+"/apps/:app_id/responsibles", wrapper.GetAppResponsibles) - router.DELETE(baseURL+"/apps/:app_id/responsibles/:group_id", wrapper.DeleteAppResponsible) - router.POST(baseURL+"/apps/:app_id/responsibles/:group_id", wrapper.PostAppResponsible) - router.GET(baseURL+"/apps/:app_id/services", wrapper.GetAppServices) - router.DELETE(baseURL+"/apps_publications", wrapper.DeleteAppsPublications) - router.POST(baseURL+"/apps_publications", wrapper.PostAppsPublications) - router.DELETE(baseURL+"/apps_responsibles", wrapper.DeleteAppsResponsibles) - router.POST(baseURL+"/apps_responsibles", wrapper.PostAppsResponsibles) - router.GET(baseURL+"/arrays", wrapper.GetArrays) - router.POST(baseURL+"/auth/node", wrapper.PostAuthNode) - router.DELETE(baseURL+"/disks", wrapper.DeleteDisks) - router.GET(baseURL+"/disks", wrapper.GetDisks) - router.POST(baseURL+"/disks", wrapper.PostDisks) - router.DELETE(baseURL+"/disks/:disk_id", wrapper.DeleteDisk) - router.GET(baseURL+"/disks/:disk_id", wrapper.GetDisk) - router.DELETE(baseURL+"/filters", wrapper.DeleteFilters) - router.GET(baseURL+"/filters", wrapper.GetFilters) - router.POST(baseURL+"/filters", wrapper.PostFilters) - router.DELETE(baseURL+"/filters/:filter_id", wrapper.DeleteFilter) - router.GET(baseURL+"/filters/:filter_id", wrapper.GetFilter) - router.POST(baseURL+"/filters/:filter_id", wrapper.PostFilter) - router.DELETE(baseURL+"/filtersets", wrapper.DeleteFiltersets) - router.GET(baseURL+"/filtersets", wrapper.GetFiltersets) - router.POST(baseURL+"/filtersets", wrapper.PostFiltersets) - router.DELETE(baseURL+"/filtersets/:filterset_id", wrapper.DeleteFilterset) - router.GET(baseURL+"/filtersets/:filterset_id", wrapper.GetFilterset) - router.POST(baseURL+"/filtersets/:filterset_id", wrapper.PostFilterset) - router.GET(baseURL+"/filtersets/:filterset_id/export", wrapper.GetFiltersetExport) - router.GET(baseURL+"/filtersets/:filterset_id/filters", wrapper.GetFiltersetFilters) - router.DELETE(baseURL+"/filtersets/:filterset_id/filters/:f_id", wrapper.DeleteFiltersetFilter) - router.POST(baseURL+"/filtersets/:filterset_id/filters/:f_id", wrapper.PostFiltersetFilter) - router.GET(baseURL+"/filtersets/:filterset_id/filtersets", wrapper.GetFiltersetFiltersets) - router.DELETE(baseURL+"/filtersets/:filterset_id/filtersets/:child_id", wrapper.DeleteFiltersetFilterset) - router.POST(baseURL+"/filtersets/:filterset_id/filtersets/:child_id", wrapper.PostFiltersetFilterset) - router.GET(baseURL+"/filtersets/:filterset_id/nodes", wrapper.GetFiltersetNodes) - router.GET(baseURL+"/filtersets/:filterset_id/services", wrapper.GetFiltersetServices) - router.GET(baseURL+"/filtersets/:filterset_id/usage", wrapper.GetFiltersetUsage) - router.DELETE(baseURL+"/filtersets_filters", wrapper.DeleteFiltersetsFilters) - router.POST(baseURL+"/filtersets_filters", wrapper.PostFiltersetsFilters) - router.DELETE(baseURL+"/filtersets_filtersets", wrapper.DeleteFiltersetsFiltersets) - router.POST(baseURL+"/filtersets_filtersets", wrapper.PostFiltersetsFiltersets) - router.GET(baseURL+"/frontend/hidden_menu_entries", wrapper.GetFrontendHiddenMenuEntries) - router.DELETE(baseURL+"/groups", wrapper.DeleteGroups) - router.GET(baseURL+"/groups", wrapper.GetGroups) - router.POST(baseURL+"/groups", wrapper.PostGroups) - router.DELETE(baseURL+"/groups/:group_id", wrapper.DeleteGroup) - router.GET(baseURL+"/groups/:group_id", wrapper.GetGroup) - router.POST(baseURL+"/groups/:group_id", wrapper.PostGroup) - router.GET(baseURL+"/groups/:group_id/apps", wrapper.GetGroupApps) - router.DELETE(baseURL+"/groups/:group_id/hidden_menu_entries", wrapper.DeleteGroupHiddenMenuEntries) - router.GET(baseURL+"/groups/:group_id/hidden_menu_entries", wrapper.GetGroupHiddenMenuEntries) - router.POST(baseURL+"/groups/:group_id/hidden_menu_entries", wrapper.PostGroupHiddenMenuEntries) - router.GET(baseURL+"/groups/:group_id/modulesets", wrapper.GetGroupModulesets) - router.GET(baseURL+"/groups/:group_id/nodes", wrapper.GetGroupNodes) - router.GET(baseURL+"/groups/:group_id/rulesets", wrapper.GetGroupRulesets) - router.GET(baseURL+"/groups/:group_id/services", wrapper.GetGroupServices) - router.GET(baseURL+"/groups/:group_id/users", wrapper.GetGroupUsers) - router.DELETE(baseURL+"/ips", wrapper.DeleteIps) - router.GET(baseURL+"/ips", wrapper.GetIps) - router.DELETE(baseURL+"/ips/:id", wrapper.DeleteIp) - router.GET(baseURL+"/ips/:id", wrapper.GetIp) - router.GET(baseURL+"/logs", wrapper.GetLogs) - router.POST(baseURL+"/logs", wrapper.PostLogs) - router.GET(baseURL+"/logs/:log_id", wrapper.GetLog) - router.DELETE(baseURL+"/nodes", wrapper.DeleteNodes) - router.GET(baseURL+"/nodes", wrapper.GetNodes) - router.POST(baseURL+"/nodes", wrapper.PostNodes) - router.GET(baseURL+"/nodes/hardware", wrapper.GetNodesHardware) - router.GET(baseURL+"/nodes/hbas", wrapper.GetNodesHbas) - router.DELETE(baseURL+"/nodes/:node_id", wrapper.DeleteNode) - router.GET(baseURL+"/nodes/:node_id", wrapper.GetNode) - router.POST(baseURL+"/nodes/:node_id", wrapper.PostNode) - router.GET(baseURL+"/nodes/:node_id/alerts", wrapper.GetNodeAlerts) - router.GET(baseURL+"/nodes/:node_id/am_i_responsible", wrapper.GetNodeAmIResponsible) - router.GET(baseURL+"/nodes/:node_id/candidate_tags", wrapper.GetNodeCandidateTags) - router.GET(baseURL+"/nodes/:node_id/checks", wrapper.GetNodeChecks) - router.GET(baseURL+"/nodes/:node_id/compliance/candidate_modulesets", wrapper.GetNodeComplianceCandidateModulesets) - router.GET(baseURL+"/nodes/:node_id/compliance/candidate_rulesets", wrapper.GetNodeComplianceCandidateRulesets) - router.GET(baseURL+"/nodes/:node_id/compliance/logs", wrapper.GetNodeComplianceLogs) - router.GET(baseURL+"/nodes/:node_id/compliance/modulesets", wrapper.GetNodeComplianceModulesets) - router.DELETE(baseURL+"/nodes/:node_id/compliance/modulesets/:mset_id", wrapper.DeleteNodeComplianceModuleset) - router.POST(baseURL+"/nodes/:node_id/compliance/modulesets/:mset_id", wrapper.PostNodeComplianceModuleset) - router.GET(baseURL+"/nodes/:node_id/compliance/rulesets", wrapper.GetNodeComplianceRulesets) - router.DELETE(baseURL+"/nodes/:node_id/compliance/rulesets/:rset_id", wrapper.DeleteNodeComplianceRuleset) - router.POST(baseURL+"/nodes/:node_id/compliance/rulesets/:rset_id", wrapper.PostNodeComplianceRuleset) - router.GET(baseURL+"/nodes/:node_id/compliance/status", wrapper.GetNodeComplianceStatus) - router.GET(baseURL+"/nodes/:node_id/disks", wrapper.GetNodeDisks) - router.GET(baseURL+"/nodes/:node_id/hardware", wrapper.GetNodeHardware) - router.GET(baseURL+"/nodes/:node_id/hbas", wrapper.GetNodeHbas) - router.GET(baseURL+"/nodes/:node_id/interfaces", wrapper.GetNodeInterfaces) - router.GET(baseURL+"/nodes/:node_id/ips", wrapper.GetNodeIps) - router.GET(baseURL+"/nodes/:node_id/services", wrapper.GetNodeServices) - router.GET(baseURL+"/nodes/:node_id/services/:svc_id", wrapper.GetNodeService) - router.POST(baseURL+"/nodes/:node_id/snooze", wrapper.PostNodeSnooze) - router.GET(baseURL+"/nodes/:node_id/tags", wrapper.GetNodeTags) - router.GET(baseURL+"/nodes/:node_id/uuid", wrapper.GetNodeUUID) - router.PUT(baseURL+"/obsolescence/refresh", wrapper.PutObsolescenceRefresh) - router.DELETE(baseURL+"/obsolescence/settings", wrapper.DeleteObsolescenceSettings) - router.GET(baseURL+"/obsolescence/settings", wrapper.GetObsolescenceSettings) - router.POST(baseURL+"/obsolescence/settings", wrapper.PostObsolescenceSettings) - router.DELETE(baseURL+"/obsolescence/settings/:id", wrapper.DeleteObsolescenceSetting) - router.GET(baseURL+"/obsolescence/settings/:id", wrapper.GetObsolescenceSetting) - router.POST(baseURL+"/obsolescence/settings/:id", wrapper.PostObsolescenceSetting) - router.GET(baseURL+"/openapi.json", wrapper.GetSwagger) - router.DELETE(baseURL+"/services", wrapper.DeleteServices) - router.GET(baseURL+"/services", wrapper.GetServices) - router.POST(baseURL+"/services", wrapper.PostServices) - router.DELETE(baseURL+"/services/:svc_id", wrapper.DeleteService) - router.GET(baseURL+"/services/:svc_id", wrapper.GetService) - router.POST(baseURL+"/services/:svc_id", wrapper.PostService) - router.GET(baseURL+"/services/:svc_id/alerts", wrapper.GetServiceAlerts) - router.GET(baseURL+"/services/:svc_id/am_i_responsible", wrapper.GetServiceAmIResponsible) - router.GET(baseURL+"/services/:svc_id/candidate_tags", wrapper.GetServiceCandidateTags) - router.GET(baseURL+"/services/:svc_id/checks", wrapper.GetServiceChecks) - router.GET(baseURL+"/services/:svc_id/compliance/candidate_modulesets", wrapper.GetServiceComplianceCandidateModulesets) - router.GET(baseURL+"/services/:svc_id/compliance/candidate_rulesets", wrapper.GetServiceComplianceCandidateRulesets) - router.GET(baseURL+"/services/:svc_id/compliance/logs", wrapper.GetServiceComplianceLogs) - router.GET(baseURL+"/services/:svc_id/compliance/modulesets", wrapper.GetServiceComplianceModulesets) - router.DELETE(baseURL+"/services/:svc_id/compliance/modulesets/:mset_id", wrapper.DeleteServiceComplianceModuleset) - router.POST(baseURL+"/services/:svc_id/compliance/modulesets/:mset_id", wrapper.PostServiceComplianceModuleset) - router.GET(baseURL+"/services/:svc_id/compliance/rulesets", wrapper.GetServiceComplianceRulesets) - router.DELETE(baseURL+"/services/:svc_id/compliance/rulesets/:rset_id", wrapper.DeleteServiceComplianceRuleset) - router.POST(baseURL+"/services/:svc_id/compliance/rulesets/:rset_id", wrapper.PostServiceComplianceRuleset) - router.GET(baseURL+"/services/:svc_id/compliance/status", wrapper.GetServiceComplianceStatus) - router.GET(baseURL+"/services/:svc_id/disks", wrapper.GetServiceDisks) - router.DELETE(baseURL+"/services/:svc_id/instances/:node_id", wrapper.DeleteServiceInstance) - router.GET(baseURL+"/services/:svc_id/instances/:node_id", wrapper.GetServiceInstance) - router.GET(baseURL+"/services/:svc_id/nodes", wrapper.GetServiceNodes) - router.GET(baseURL+"/services/:svc_id/nodes/:node_id", wrapper.GetServiceNode) - router.GET(baseURL+"/services/:svc_id/nodes/:node_id/resources", wrapper.GetServiceNodeResources) - router.GET(baseURL+"/services/:svc_id/nodes/:node_id/resources/logs", wrapper.GetServiceNodeResourceLogs) - router.GET(baseURL+"/services/:svc_id/resinfo", wrapper.GetServiceResinfo) - router.GET(baseURL+"/services/:svc_id/resources", wrapper.GetServiceResources) - router.GET(baseURL+"/services/:svc_id/resources/logs", wrapper.GetServiceResourceLogs) - router.GET(baseURL+"/services/:svc_id/tags", wrapper.GetServiceTags) - router.DELETE(baseURL+"/services_instances", wrapper.DeleteServicesInstances) - router.GET(baseURL+"/services_instances", wrapper.GetServicesInstances) - router.GET(baseURL+"/services_instances/:svc_id", wrapper.GetServicesInstance) - router.GET(baseURL+"/services_instances_status_log", wrapper.GetServicesInstancesStatusLog) - router.GET(baseURL+"/services_status_log", wrapper.GetServicesStatusLog) - router.DELETE(baseURL+"/tags", wrapper.DeleteTags) - router.GET(baseURL+"/tags", wrapper.GetTags) - router.POST(baseURL+"/tags", wrapper.PostTags) - router.DELETE(baseURL+"/tags/nodes", wrapper.DeleteTagsNodes) - router.GET(baseURL+"/tags/nodes", wrapper.GetTagsNodes) - router.POST(baseURL+"/tags/nodes", wrapper.PostTagsNodes) - router.DELETE(baseURL+"/tags/services", wrapper.DeleteTagsServices) - router.GET(baseURL+"/tags/services", wrapper.GetTagsServices) - router.POST(baseURL+"/tags/services", wrapper.PostTagsServices) - router.DELETE(baseURL+"/tags/:tag_id", wrapper.DeleteTag) - router.GET(baseURL+"/tags/:tag_id", wrapper.GetTag) - router.POST(baseURL+"/tags/:tag_id", wrapper.PostTag) - router.GET(baseURL+"/tags/:tag_id/nodes", wrapper.GetTagNodes) - router.DELETE(baseURL+"/tags/:tag_id/nodes/:node_id", wrapper.DeleteTagNode) - router.POST(baseURL+"/tags/:tag_id/nodes/:node_id", wrapper.PostTagNode) - router.GET(baseURL+"/tags/:tag_id/services", wrapper.GetTagServices) - router.DELETE(baseURL+"/tags/:tag_id/services/:svc_id", wrapper.DeleteTagService) - router.POST(baseURL+"/tags/:tag_id/services/:svc_id", wrapper.PostTagService) - router.GET(baseURL+"/version", wrapper.GetVersion) - -} - -// Base64 encoded, gzipped, json marshaled Swagger object + router.GET(options.BaseURL+"/actions", wrapper.GetActions, options.OperationMiddlewares["GetActions"]...) + router.POST(options.BaseURL+"/actions", wrapper.PostActions, options.OperationMiddlewares["PostActions"]...) + router.DELETE(options.BaseURL+"/actions/:id", wrapper.DeleteAction, options.OperationMiddlewares["DeleteAction"]...) + router.GET(options.BaseURL+"/actions/:id", wrapper.GetAction, options.OperationMiddlewares["GetAction"]...) + router.GET(options.BaseURL+"/alert_event", wrapper.GetAlertEvent, options.OperationMiddlewares["GetAlertEvent"]...) + router.DELETE(options.BaseURL+"/alerts", wrapper.DeleteAlerts, options.OperationMiddlewares["DeleteAlerts"]...) + router.GET(options.BaseURL+"/alerts", wrapper.GetAlerts, options.OperationMiddlewares["GetAlerts"]...) + router.POST(options.BaseURL+"/alerts", wrapper.PostAlerts, options.OperationMiddlewares["PostAlerts"]...) + router.DELETE(options.BaseURL+"/alerts/:id", wrapper.DeleteAlert, options.OperationMiddlewares["DeleteAlert"]...) + router.GET(options.BaseURL+"/alerts/:id", wrapper.GetAlert, options.OperationMiddlewares["GetAlert"]...) + router.POST(options.BaseURL+"/alerts/:id", wrapper.PostAlert, options.OperationMiddlewares["PostAlert"]...) + router.DELETE(options.BaseURL+"/apps", wrapper.DeleteApps, options.OperationMiddlewares["DeleteApps"]...) + router.GET(options.BaseURL+"/apps", wrapper.GetApps, options.OperationMiddlewares["GetApps"]...) + router.POST(options.BaseURL+"/apps", wrapper.PostApps, options.OperationMiddlewares["PostApps"]...) + router.DELETE(options.BaseURL+"/apps/:app_id", wrapper.DeleteApp, options.OperationMiddlewares["DeleteApp"]...) + router.GET(options.BaseURL+"/apps/:app_id", wrapper.GetApp, options.OperationMiddlewares["GetApp"]...) + router.POST(options.BaseURL+"/apps/:app_id", wrapper.PostApp, options.OperationMiddlewares["PostApp"]...) + router.GET(options.BaseURL+"/apps/:app_id/am_i_responsible", wrapper.GetAppAmIResponsible, options.OperationMiddlewares["GetAppAmIResponsible"]...) + router.GET(options.BaseURL+"/apps/:app_id/nodes", wrapper.GetAppNodes, options.OperationMiddlewares["GetAppNodes"]...) + router.GET(options.BaseURL+"/apps/:app_id/publications", wrapper.GetAppPublications, options.OperationMiddlewares["GetAppPublications"]...) + router.DELETE(options.BaseURL+"/apps/:app_id/publications/:group_id", wrapper.DeleteAppPublication, options.OperationMiddlewares["DeleteAppPublication"]...) + router.POST(options.BaseURL+"/apps/:app_id/publications/:group_id", wrapper.PostAppPublication, options.OperationMiddlewares["PostAppPublication"]...) + router.GET(options.BaseURL+"/apps/:app_id/quotas", wrapper.GetAppQuotas, options.OperationMiddlewares["GetAppQuotas"]...) + router.GET(options.BaseURL+"/apps/:app_id/responsibles", wrapper.GetAppResponsibles, options.OperationMiddlewares["GetAppResponsibles"]...) + router.DELETE(options.BaseURL+"/apps/:app_id/responsibles/:group_id", wrapper.DeleteAppResponsible, options.OperationMiddlewares["DeleteAppResponsible"]...) + router.POST(options.BaseURL+"/apps/:app_id/responsibles/:group_id", wrapper.PostAppResponsible, options.OperationMiddlewares["PostAppResponsible"]...) + router.GET(options.BaseURL+"/apps/:app_id/services", wrapper.GetAppServices, options.OperationMiddlewares["GetAppServices"]...) + router.DELETE(options.BaseURL+"/apps_publications", wrapper.DeleteAppsPublications, options.OperationMiddlewares["DeleteAppsPublications"]...) + router.POST(options.BaseURL+"/apps_publications", wrapper.PostAppsPublications, options.OperationMiddlewares["PostAppsPublications"]...) + router.DELETE(options.BaseURL+"/apps_responsibles", wrapper.DeleteAppsResponsibles, options.OperationMiddlewares["DeleteAppsResponsibles"]...) + router.POST(options.BaseURL+"/apps_responsibles", wrapper.PostAppsResponsibles, options.OperationMiddlewares["PostAppsResponsibles"]...) + router.GET(options.BaseURL+"/arrays", wrapper.GetArrays, options.OperationMiddlewares["GetArrays"]...) + router.POST(options.BaseURL+"/auth/node", wrapper.PostAuthNode, options.OperationMiddlewares["PostAuthNode"]...) + router.DELETE(options.BaseURL+"/disks", wrapper.DeleteDisks, options.OperationMiddlewares["DeleteDisks"]...) + router.GET(options.BaseURL+"/disks", wrapper.GetDisks, options.OperationMiddlewares["GetDisks"]...) + router.POST(options.BaseURL+"/disks", wrapper.PostDisks, options.OperationMiddlewares["PostDisks"]...) + router.DELETE(options.BaseURL+"/disks/:disk_id", wrapper.DeleteDisk, options.OperationMiddlewares["DeleteDisk"]...) + router.GET(options.BaseURL+"/disks/:disk_id", wrapper.GetDisk, options.OperationMiddlewares["GetDisk"]...) + router.DELETE(options.BaseURL+"/filters", wrapper.DeleteFilters, options.OperationMiddlewares["DeleteFilters"]...) + router.GET(options.BaseURL+"/filters", wrapper.GetFilters, options.OperationMiddlewares["GetFilters"]...) + router.POST(options.BaseURL+"/filters", wrapper.PostFilters, options.OperationMiddlewares["PostFilters"]...) + router.DELETE(options.BaseURL+"/filters/:filter_id", wrapper.DeleteFilter, options.OperationMiddlewares["DeleteFilter"]...) + router.GET(options.BaseURL+"/filters/:filter_id", wrapper.GetFilter, options.OperationMiddlewares["GetFilter"]...) + router.POST(options.BaseURL+"/filters/:filter_id", wrapper.PostFilter, options.OperationMiddlewares["PostFilter"]...) + router.DELETE(options.BaseURL+"/filtersets", wrapper.DeleteFiltersets, options.OperationMiddlewares["DeleteFiltersets"]...) + router.GET(options.BaseURL+"/filtersets", wrapper.GetFiltersets, options.OperationMiddlewares["GetFiltersets"]...) + router.POST(options.BaseURL+"/filtersets", wrapper.PostFiltersets, options.OperationMiddlewares["PostFiltersets"]...) + router.DELETE(options.BaseURL+"/filtersets/:filterset_id", wrapper.DeleteFilterset, options.OperationMiddlewares["DeleteFilterset"]...) + router.GET(options.BaseURL+"/filtersets/:filterset_id", wrapper.GetFilterset, options.OperationMiddlewares["GetFilterset"]...) + router.POST(options.BaseURL+"/filtersets/:filterset_id", wrapper.PostFilterset, options.OperationMiddlewares["PostFilterset"]...) + router.GET(options.BaseURL+"/filtersets/:filterset_id/export", wrapper.GetFiltersetExport, options.OperationMiddlewares["GetFiltersetExport"]...) + router.GET(options.BaseURL+"/filtersets/:filterset_id/filters", wrapper.GetFiltersetFilters, options.OperationMiddlewares["GetFiltersetFilters"]...) + router.DELETE(options.BaseURL+"/filtersets/:filterset_id/filters/:f_id", wrapper.DeleteFiltersetFilter, options.OperationMiddlewares["DeleteFiltersetFilter"]...) + router.POST(options.BaseURL+"/filtersets/:filterset_id/filters/:f_id", wrapper.PostFiltersetFilter, options.OperationMiddlewares["PostFiltersetFilter"]...) + router.GET(options.BaseURL+"/filtersets/:filterset_id/filtersets", wrapper.GetFiltersetFiltersets, options.OperationMiddlewares["GetFiltersetFiltersets"]...) + router.DELETE(options.BaseURL+"/filtersets/:filterset_id/filtersets/:child_id", wrapper.DeleteFiltersetFilterset, options.OperationMiddlewares["DeleteFiltersetFilterset"]...) + router.POST(options.BaseURL+"/filtersets/:filterset_id/filtersets/:child_id", wrapper.PostFiltersetFilterset, options.OperationMiddlewares["PostFiltersetFilterset"]...) + router.GET(options.BaseURL+"/filtersets/:filterset_id/nodes", wrapper.GetFiltersetNodes, options.OperationMiddlewares["GetFiltersetNodes"]...) + router.GET(options.BaseURL+"/filtersets/:filterset_id/services", wrapper.GetFiltersetServices, options.OperationMiddlewares["GetFiltersetServices"]...) + router.GET(options.BaseURL+"/filtersets/:filterset_id/usage", wrapper.GetFiltersetUsage, options.OperationMiddlewares["GetFiltersetUsage"]...) + router.DELETE(options.BaseURL+"/filtersets_filters", wrapper.DeleteFiltersetsFilters, options.OperationMiddlewares["DeleteFiltersetsFilters"]...) + router.POST(options.BaseURL+"/filtersets_filters", wrapper.PostFiltersetsFilters, options.OperationMiddlewares["PostFiltersetsFilters"]...) + router.DELETE(options.BaseURL+"/filtersets_filtersets", wrapper.DeleteFiltersetsFiltersets, options.OperationMiddlewares["DeleteFiltersetsFiltersets"]...) + router.POST(options.BaseURL+"/filtersets_filtersets", wrapper.PostFiltersetsFiltersets, options.OperationMiddlewares["PostFiltersetsFiltersets"]...) + router.GET(options.BaseURL+"/frontend/hidden_menu_entries", wrapper.GetFrontendHiddenMenuEntries, options.OperationMiddlewares["GetFrontendHiddenMenuEntries"]...) + router.DELETE(options.BaseURL+"/groups", wrapper.DeleteGroups, options.OperationMiddlewares["DeleteGroups"]...) + router.GET(options.BaseURL+"/groups", wrapper.GetGroups, options.OperationMiddlewares["GetGroups"]...) + router.POST(options.BaseURL+"/groups", wrapper.PostGroups, options.OperationMiddlewares["PostGroups"]...) + router.DELETE(options.BaseURL+"/groups/:group_id", wrapper.DeleteGroup, options.OperationMiddlewares["DeleteGroup"]...) + router.GET(options.BaseURL+"/groups/:group_id", wrapper.GetGroup, options.OperationMiddlewares["GetGroup"]...) + router.POST(options.BaseURL+"/groups/:group_id", wrapper.PostGroup, options.OperationMiddlewares["PostGroup"]...) + router.GET(options.BaseURL+"/groups/:group_id/apps", wrapper.GetGroupApps, options.OperationMiddlewares["GetGroupApps"]...) + router.DELETE(options.BaseURL+"/groups/:group_id/hidden_menu_entries", wrapper.DeleteGroupHiddenMenuEntries, options.OperationMiddlewares["DeleteGroupHiddenMenuEntries"]...) + router.GET(options.BaseURL+"/groups/:group_id/hidden_menu_entries", wrapper.GetGroupHiddenMenuEntries, options.OperationMiddlewares["GetGroupHiddenMenuEntries"]...) + router.POST(options.BaseURL+"/groups/:group_id/hidden_menu_entries", wrapper.PostGroupHiddenMenuEntries, options.OperationMiddlewares["PostGroupHiddenMenuEntries"]...) + router.GET(options.BaseURL+"/groups/:group_id/modulesets", wrapper.GetGroupModulesets, options.OperationMiddlewares["GetGroupModulesets"]...) + router.GET(options.BaseURL+"/groups/:group_id/nodes", wrapper.GetGroupNodes, options.OperationMiddlewares["GetGroupNodes"]...) + router.GET(options.BaseURL+"/groups/:group_id/rulesets", wrapper.GetGroupRulesets, options.OperationMiddlewares["GetGroupRulesets"]...) + router.GET(options.BaseURL+"/groups/:group_id/services", wrapper.GetGroupServices, options.OperationMiddlewares["GetGroupServices"]...) + router.GET(options.BaseURL+"/groups/:group_id/users", wrapper.GetGroupUsers, options.OperationMiddlewares["GetGroupUsers"]...) + router.DELETE(options.BaseURL+"/ips", wrapper.DeleteIps, options.OperationMiddlewares["DeleteIps"]...) + router.GET(options.BaseURL+"/ips", wrapper.GetIps, options.OperationMiddlewares["GetIps"]...) + router.DELETE(options.BaseURL+"/ips/:id", wrapper.DeleteIp, options.OperationMiddlewares["DeleteIp"]...) + router.GET(options.BaseURL+"/ips/:id", wrapper.GetIp, options.OperationMiddlewares["GetIp"]...) + router.GET(options.BaseURL+"/logs", wrapper.GetLogs, options.OperationMiddlewares["GetLogs"]...) + router.POST(options.BaseURL+"/logs", wrapper.PostLogs, options.OperationMiddlewares["PostLogs"]...) + router.GET(options.BaseURL+"/logs/:log_id", wrapper.GetLog, options.OperationMiddlewares["GetLog"]...) + router.DELETE(options.BaseURL+"/nodes", wrapper.DeleteNodes, options.OperationMiddlewares["DeleteNodes"]...) + router.GET(options.BaseURL+"/nodes", wrapper.GetNodes, options.OperationMiddlewares["GetNodes"]...) + router.POST(options.BaseURL+"/nodes", wrapper.PostNodes, options.OperationMiddlewares["PostNodes"]...) + router.GET(options.BaseURL+"/nodes/hardware", wrapper.GetNodesHardware, options.OperationMiddlewares["GetNodesHardware"]...) + router.GET(options.BaseURL+"/nodes/hbas", wrapper.GetNodesHbas, options.OperationMiddlewares["GetNodesHbas"]...) + router.DELETE(options.BaseURL+"/nodes/:node_id", wrapper.DeleteNode, options.OperationMiddlewares["DeleteNode"]...) + router.GET(options.BaseURL+"/nodes/:node_id", wrapper.GetNode, options.OperationMiddlewares["GetNode"]...) + router.POST(options.BaseURL+"/nodes/:node_id", wrapper.PostNode, options.OperationMiddlewares["PostNode"]...) + router.GET(options.BaseURL+"/nodes/:node_id/alerts", wrapper.GetNodeAlerts, options.OperationMiddlewares["GetNodeAlerts"]...) + router.GET(options.BaseURL+"/nodes/:node_id/am_i_responsible", wrapper.GetNodeAmIResponsible, options.OperationMiddlewares["GetNodeAmIResponsible"]...) + router.GET(options.BaseURL+"/nodes/:node_id/candidate_tags", wrapper.GetNodeCandidateTags, options.OperationMiddlewares["GetNodeCandidateTags"]...) + router.GET(options.BaseURL+"/nodes/:node_id/checks", wrapper.GetNodeChecks, options.OperationMiddlewares["GetNodeChecks"]...) + router.GET(options.BaseURL+"/nodes/:node_id/compliance/candidate_modulesets", wrapper.GetNodeComplianceCandidateModulesets, options.OperationMiddlewares["GetNodeComplianceCandidateModulesets"]...) + router.GET(options.BaseURL+"/nodes/:node_id/compliance/candidate_rulesets", wrapper.GetNodeComplianceCandidateRulesets, options.OperationMiddlewares["GetNodeComplianceCandidateRulesets"]...) + router.GET(options.BaseURL+"/nodes/:node_id/compliance/logs", wrapper.GetNodeComplianceLogs, options.OperationMiddlewares["GetNodeComplianceLogs"]...) + router.GET(options.BaseURL+"/nodes/:node_id/compliance/modulesets", wrapper.GetNodeComplianceModulesets, options.OperationMiddlewares["GetNodeComplianceModulesets"]...) + router.DELETE(options.BaseURL+"/nodes/:node_id/compliance/modulesets/:mset_id", wrapper.DeleteNodeComplianceModuleset, options.OperationMiddlewares["DeleteNodeComplianceModuleset"]...) + router.POST(options.BaseURL+"/nodes/:node_id/compliance/modulesets/:mset_id", wrapper.PostNodeComplianceModuleset, options.OperationMiddlewares["PostNodeComplianceModuleset"]...) + router.GET(options.BaseURL+"/nodes/:node_id/compliance/rulesets", wrapper.GetNodeComplianceRulesets, options.OperationMiddlewares["GetNodeComplianceRulesets"]...) + router.DELETE(options.BaseURL+"/nodes/:node_id/compliance/rulesets/:rset_id", wrapper.DeleteNodeComplianceRuleset, options.OperationMiddlewares["DeleteNodeComplianceRuleset"]...) + router.POST(options.BaseURL+"/nodes/:node_id/compliance/rulesets/:rset_id", wrapper.PostNodeComplianceRuleset, options.OperationMiddlewares["PostNodeComplianceRuleset"]...) + router.GET(options.BaseURL+"/nodes/:node_id/compliance/status", wrapper.GetNodeComplianceStatus, options.OperationMiddlewares["GetNodeComplianceStatus"]...) + router.GET(options.BaseURL+"/nodes/:node_id/disks", wrapper.GetNodeDisks, options.OperationMiddlewares["GetNodeDisks"]...) + router.GET(options.BaseURL+"/nodes/:node_id/hardware", wrapper.GetNodeHardware, options.OperationMiddlewares["GetNodeHardware"]...) + router.GET(options.BaseURL+"/nodes/:node_id/hbas", wrapper.GetNodeHbas, options.OperationMiddlewares["GetNodeHbas"]...) + router.GET(options.BaseURL+"/nodes/:node_id/interfaces", wrapper.GetNodeInterfaces, options.OperationMiddlewares["GetNodeInterfaces"]...) + router.GET(options.BaseURL+"/nodes/:node_id/ips", wrapper.GetNodeIps, options.OperationMiddlewares["GetNodeIps"]...) + router.GET(options.BaseURL+"/nodes/:node_id/services", wrapper.GetNodeServices, options.OperationMiddlewares["GetNodeServices"]...) + router.GET(options.BaseURL+"/nodes/:node_id/services/:svc_id", wrapper.GetNodeService, options.OperationMiddlewares["GetNodeService"]...) + router.POST(options.BaseURL+"/nodes/:node_id/snooze", wrapper.PostNodeSnooze, options.OperationMiddlewares["PostNodeSnooze"]...) + router.GET(options.BaseURL+"/nodes/:node_id/tags", wrapper.GetNodeTags, options.OperationMiddlewares["GetNodeTags"]...) + router.GET(options.BaseURL+"/nodes/:node_id/uuid", wrapper.GetNodeUUID, options.OperationMiddlewares["GetNodeUUID"]...) + router.PUT(options.BaseURL+"/obsolescence/refresh", wrapper.PutObsolescenceRefresh, options.OperationMiddlewares["PutObsolescenceRefresh"]...) + router.DELETE(options.BaseURL+"/obsolescence/settings", wrapper.DeleteObsolescenceSettings, options.OperationMiddlewares["DeleteObsolescenceSettings"]...) + router.GET(options.BaseURL+"/obsolescence/settings", wrapper.GetObsolescenceSettings, options.OperationMiddlewares["GetObsolescenceSettings"]...) + router.POST(options.BaseURL+"/obsolescence/settings", wrapper.PostObsolescenceSettings, options.OperationMiddlewares["PostObsolescenceSettings"]...) + router.DELETE(options.BaseURL+"/obsolescence/settings/:id", wrapper.DeleteObsolescenceSetting, options.OperationMiddlewares["DeleteObsolescenceSetting"]...) + router.GET(options.BaseURL+"/obsolescence/settings/:id", wrapper.GetObsolescenceSetting, options.OperationMiddlewares["GetObsolescenceSetting"]...) + router.POST(options.BaseURL+"/obsolescence/settings/:id", wrapper.PostObsolescenceSetting, options.OperationMiddlewares["PostObsolescenceSetting"]...) + router.GET(options.BaseURL+"/openapi.json", wrapper.GetSwagger, options.OperationMiddlewares["GetSwagger"]...) + router.DELETE(options.BaseURL+"/services", wrapper.DeleteServices, options.OperationMiddlewares["DeleteServices"]...) + router.GET(options.BaseURL+"/services", wrapper.GetServices, options.OperationMiddlewares["GetServices"]...) + router.POST(options.BaseURL+"/services", wrapper.PostServices, options.OperationMiddlewares["PostServices"]...) + router.DELETE(options.BaseURL+"/services/:svc_id", wrapper.DeleteService, options.OperationMiddlewares["DeleteService"]...) + router.GET(options.BaseURL+"/services/:svc_id", wrapper.GetService, options.OperationMiddlewares["GetService"]...) + router.POST(options.BaseURL+"/services/:svc_id", wrapper.PostService, options.OperationMiddlewares["PostService"]...) + router.GET(options.BaseURL+"/services/:svc_id/alerts", wrapper.GetServiceAlerts, options.OperationMiddlewares["GetServiceAlerts"]...) + router.GET(options.BaseURL+"/services/:svc_id/am_i_responsible", wrapper.GetServiceAmIResponsible, options.OperationMiddlewares["GetServiceAmIResponsible"]...) + router.GET(options.BaseURL+"/services/:svc_id/candidate_tags", wrapper.GetServiceCandidateTags, options.OperationMiddlewares["GetServiceCandidateTags"]...) + router.GET(options.BaseURL+"/services/:svc_id/checks", wrapper.GetServiceChecks, options.OperationMiddlewares["GetServiceChecks"]...) + router.GET(options.BaseURL+"/services/:svc_id/compliance/candidate_modulesets", wrapper.GetServiceComplianceCandidateModulesets, options.OperationMiddlewares["GetServiceComplianceCandidateModulesets"]...) + router.GET(options.BaseURL+"/services/:svc_id/compliance/candidate_rulesets", wrapper.GetServiceComplianceCandidateRulesets, options.OperationMiddlewares["GetServiceComplianceCandidateRulesets"]...) + router.GET(options.BaseURL+"/services/:svc_id/compliance/logs", wrapper.GetServiceComplianceLogs, options.OperationMiddlewares["GetServiceComplianceLogs"]...) + router.GET(options.BaseURL+"/services/:svc_id/compliance/modulesets", wrapper.GetServiceComplianceModulesets, options.OperationMiddlewares["GetServiceComplianceModulesets"]...) + router.DELETE(options.BaseURL+"/services/:svc_id/compliance/modulesets/:mset_id", wrapper.DeleteServiceComplianceModuleset, options.OperationMiddlewares["DeleteServiceComplianceModuleset"]...) + router.POST(options.BaseURL+"/services/:svc_id/compliance/modulesets/:mset_id", wrapper.PostServiceComplianceModuleset, options.OperationMiddlewares["PostServiceComplianceModuleset"]...) + router.GET(options.BaseURL+"/services/:svc_id/compliance/rulesets", wrapper.GetServiceComplianceRulesets, options.OperationMiddlewares["GetServiceComplianceRulesets"]...) + router.DELETE(options.BaseURL+"/services/:svc_id/compliance/rulesets/:rset_id", wrapper.DeleteServiceComplianceRuleset, options.OperationMiddlewares["DeleteServiceComplianceRuleset"]...) + router.POST(options.BaseURL+"/services/:svc_id/compliance/rulesets/:rset_id", wrapper.PostServiceComplianceRuleset, options.OperationMiddlewares["PostServiceComplianceRuleset"]...) + router.GET(options.BaseURL+"/services/:svc_id/compliance/status", wrapper.GetServiceComplianceStatus, options.OperationMiddlewares["GetServiceComplianceStatus"]...) + router.GET(options.BaseURL+"/services/:svc_id/disks", wrapper.GetServiceDisks, options.OperationMiddlewares["GetServiceDisks"]...) + router.DELETE(options.BaseURL+"/services/:svc_id/instances/:node_id", wrapper.DeleteServiceInstance, options.OperationMiddlewares["DeleteServiceInstance"]...) + router.GET(options.BaseURL+"/services/:svc_id/instances/:node_id", wrapper.GetServiceInstance, options.OperationMiddlewares["GetServiceInstance"]...) + router.GET(options.BaseURL+"/services/:svc_id/nodes", wrapper.GetServiceNodes, options.OperationMiddlewares["GetServiceNodes"]...) + router.GET(options.BaseURL+"/services/:svc_id/nodes/:node_id", wrapper.GetServiceNode, options.OperationMiddlewares["GetServiceNode"]...) + router.GET(options.BaseURL+"/services/:svc_id/nodes/:node_id/resources", wrapper.GetServiceNodeResources, options.OperationMiddlewares["GetServiceNodeResources"]...) + router.GET(options.BaseURL+"/services/:svc_id/nodes/:node_id/resources/logs", wrapper.GetServiceNodeResourceLogs, options.OperationMiddlewares["GetServiceNodeResourceLogs"]...) + router.GET(options.BaseURL+"/services/:svc_id/resinfo", wrapper.GetServiceResinfo, options.OperationMiddlewares["GetServiceResinfo"]...) + router.GET(options.BaseURL+"/services/:svc_id/resources", wrapper.GetServiceResources, options.OperationMiddlewares["GetServiceResources"]...) + router.GET(options.BaseURL+"/services/:svc_id/resources/logs", wrapper.GetServiceResourceLogs, options.OperationMiddlewares["GetServiceResourceLogs"]...) + router.GET(options.BaseURL+"/services/:svc_id/tags", wrapper.GetServiceTags, options.OperationMiddlewares["GetServiceTags"]...) + router.DELETE(options.BaseURL+"/services_instances", wrapper.DeleteServicesInstances, options.OperationMiddlewares["DeleteServicesInstances"]...) + router.GET(options.BaseURL+"/services_instances", wrapper.GetServicesInstances, options.OperationMiddlewares["GetServicesInstances"]...) + router.GET(options.BaseURL+"/services_instances/:svc_id", wrapper.GetServicesInstance, options.OperationMiddlewares["GetServicesInstance"]...) + router.GET(options.BaseURL+"/services_instances_status_log", wrapper.GetServicesInstancesStatusLog, options.OperationMiddlewares["GetServicesInstancesStatusLog"]...) + router.GET(options.BaseURL+"/services_status_log", wrapper.GetServicesStatusLog, options.OperationMiddlewares["GetServicesStatusLog"]...) + router.DELETE(options.BaseURL+"/tags", wrapper.DeleteTags, options.OperationMiddlewares["DeleteTags"]...) + router.GET(options.BaseURL+"/tags", wrapper.GetTags, options.OperationMiddlewares["GetTags"]...) + router.POST(options.BaseURL+"/tags", wrapper.PostTags, options.OperationMiddlewares["PostTags"]...) + router.DELETE(options.BaseURL+"/tags/nodes", wrapper.DeleteTagsNodes, options.OperationMiddlewares["DeleteTagsNodes"]...) + router.GET(options.BaseURL+"/tags/nodes", wrapper.GetTagsNodes, options.OperationMiddlewares["GetTagsNodes"]...) + router.POST(options.BaseURL+"/tags/nodes", wrapper.PostTagsNodes, options.OperationMiddlewares["PostTagsNodes"]...) + router.DELETE(options.BaseURL+"/tags/services", wrapper.DeleteTagsServices, options.OperationMiddlewares["DeleteTagsServices"]...) + router.GET(options.BaseURL+"/tags/services", wrapper.GetTagsServices, options.OperationMiddlewares["GetTagsServices"]...) + router.POST(options.BaseURL+"/tags/services", wrapper.PostTagsServices, options.OperationMiddlewares["PostTagsServices"]...) + router.DELETE(options.BaseURL+"/tags/:tag_id", wrapper.DeleteTag, options.OperationMiddlewares["DeleteTag"]...) + router.GET(options.BaseURL+"/tags/:tag_id", wrapper.GetTag, options.OperationMiddlewares["GetTag"]...) + router.POST(options.BaseURL+"/tags/:tag_id", wrapper.PostTag, options.OperationMiddlewares["PostTag"]...) + router.GET(options.BaseURL+"/tags/:tag_id/nodes", wrapper.GetTagNodes, options.OperationMiddlewares["GetTagNodes"]...) + router.DELETE(options.BaseURL+"/tags/:tag_id/nodes/:node_id", wrapper.DeleteTagNode, options.OperationMiddlewares["DeleteTagNode"]...) + router.POST(options.BaseURL+"/tags/:tag_id/nodes/:node_id", wrapper.PostTagNode, options.OperationMiddlewares["PostTagNode"]...) + router.GET(options.BaseURL+"/tags/:tag_id/services", wrapper.GetTagServices, options.OperationMiddlewares["GetTagServices"]...) + router.DELETE(options.BaseURL+"/tags/:tag_id/services/:svc_id", wrapper.DeleteTagService, options.OperationMiddlewares["DeleteTagService"]...) + router.POST(options.BaseURL+"/tags/:tag_id/services/:svc_id", wrapper.PostTagService, options.OperationMiddlewares["PostTagService"]...) + router.GET(options.BaseURL+"/version", wrapper.GetVersion, options.OperationMiddlewares["GetVersion"]...) + +} + +// Base64 encoded, compressed with deflate, json marshaled OpenAPI spec. +// Stored as a slice of fixed-width chunks rather than one concatenated +// const string: with thousands of chunks the chained `+` fold is several +// times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - - "H4sIAAAAAAAC/+y9bXPbOLIv/lVQ+v+rnNRq5MzOnFu1mdoXOUlm1nsmD8dJ9rwYpVQQ2ZKwJgEGAOVo", - "XK66n+Z+sPtJbgHgkySApGzZlux+lVgACZDsX/evG0D31SASaSY4cK0GL68GGZU0BQ3S/sX4R6oX7xTo", - "s9j8HYOKJMs0E3zwcnD2hogZ0QsgqYjzBBTowXDATFNG9WIwHHCawuDlIFWgJyweDAcSvuVMQjx4qWUO", - "w4GKFpBSc2u9ykxXpSXj88H19bAY/L2IoX1wLmLwj2tabjrueedDy7ZHljd85P/OQa5+kyLPpqvtwV+L", - "NKU/KDBfSUNMEqa0mU4mRQZSM1BECzI3l7spgsoTTaYr8gxG85Frma7+TrNsqJaRmevzUfkA38zQ9RMU", - "fQe9Zvw7S5nenu9nIxv0O0vzlPA8nYI0swWuZTFVCTqXfERekBQoV4QLkphbhSZlG9emFMOM5okevPyP", - "F8NByrgZa/DyxbCcK+Ma5iCbk30Hmno+LI+SPAaSgqYx1ZQwXr7DTHAFI/KW02kCsXmdxagj8kUBmdFE", - "ARGSvDCPJFKmHShAUzJjkMShpzE9+r3fD7OZEbWtSX+6YO5Lz5hUunqzhYTax4hyqYQMTUG4G3vfaO8X", - "+kHGIG8ur0pII6Mj8lHCjH0ntGxfkUumF+QHMhOSmDsDjxmfE2HGK0RauLH/brBunmn4A82yoFAXvfu9", - "9I9SZGr7oV4FHoMVAsQ4ARot3NuPWWQu41SuQnPK7DC9ZvRJU618r5lrKRJlP7qdhmKC1wJsMAZxcy5m", - "9pSMB8rccDwgF7AakkhwTRk3b9hcpyCByHy1xmPGTGnGI02WNMlBkUjkXKvQk9m7tz7ZtdGPDl/2uX5+", - "8cL8Y2YC3Mo7zbKERdRM/PTfyjzuVeN+/7+E2eDl4P87ra3YqWtVpx+lmCaQulHWX9h/0picw7cclB5c", - "Dwc/v/jxPkb9wmmuF0KyPyF2w/50H8P+KuSUxTFwN+bP9zHme6HJryLnxXP+7T7GfC34LGGR/aL/cT9y", - "dMY1SE4T8gnkEiR5K6VwmrG42Nz7d6Z0aXJqKNk5LSlLjE2ZZKWqYRpS5UFKpX6plHRl/rbQa/Ss9PJw", - "UKLUjhHHzMyWJh/Xxt6+qvhFTP8N7iUWCi2+yeySkhBsjyMqW+aZg9A08TX55mde7HmhPbZfrlG/5l/B", - "4cNs8PKP7dnXd9qYffit3eJtbvzw9Xro7H+H9FXS43RlySX/cM/31TNQKa9bb0TDd+0zZ4s8pfwHCTQ2", - "skjge5ZQbpFCVAYRm7HI2De9YIqIKMqlBB5BQTLGPHPjjcZ8MPSYruac7Qx8c16CVMyBcn3OjQb4TtMs", - "Mde9GL0Y/dg5WHnp9ngGnxDlkunVJ/Oa3VBTqlj0KteLSjWYa+yv9VgLrTMz4SlQCbLs7f76VciU6sHL", - "wT//53Np9ewtbOvmPZxZnwn7ZZi2DyYy4GoZkUgkxvYKSWjGBo3XM/hx9GL0k0VRBtw0vhz8NHoxejEY", - "WgfEPsgptXbe/n/uY41GpogCuWQREMpj60KR4iqSCWWsfsEe3K+TbznkMCLvKKdzkIoogDGnSVJe9QsR", - "egGS5Mq0Cp6sTJfqnmJmx1DkciEUEJpZ1roiVMKYFwyAGeGbCekEyQiBlUHjhA1+A/2qeKjhmo/6hx89", - "dZfTNTJnsN2vv/No+vcvGHr/Cxyoe3d31G+H+RRMt/8Vpdd5/XWDlP11j8Z0TWd7LOqH/2qYb9+Nqpmd", - "mk5NKFthaID4j6/m2ZtA/eOreTZN50ZwBhXIBkYXG6nfRso7EbPZilC+hgPrZ61GxLi3Jyw+MfSZMEVS", - "ymOqhVxZUDn+rJyS1FTOQRd3+cUBxMDrxHDkXJ3ULg9TJM+Mcp8mMLIslUko7vJexPD2O0TG2Xwt0sz+", - "P5NsyRKYOyhXYGIJ0yvrOZlxivENCH34+ihUA2DSUeP/FPFqpw+/rrqZJ3rixiCNt0hskGSLT7jXsn2D", - "93BJXBt5Zp7LvsjqfVVv8XmndWCxzzBcb8Zrrm+JBc8APoH/uY/Am061t9LV98eGi9HV96eGa9DV9+cH", - "Aej1sDJrp1csvnaSkYCGbRl5Y3+vQeu1aKSwaE2AEYOvwsQZXrMjrqw+KO7OFEnEfA7xmJurKYkWlM+B", - "cKENn6JlJ0iZ1hD7MOkewyFm2+r1w5UnMrljUPK2xmBDJ5SEZwubvYFyN8L/ABbHS83eMJUl1NmGRtzF", - "hmsqMt4t1mPeZGrkBkTtZvTs4eR0iETwERLBw7dJCUg9gWXxPloxbfsS21cRzVIg0tgERZ7FVC2mgsp4", - "UrYaNvN8RF4RKS4JU2O+ZA6BlwvghGlV+W9C2j+tC8cUKftZhx1IRJME5C+Gmlp1MOYG7bAEudILxuch", - "NJupvrVPhf4W+lt3Bx3Vk8hZ6Dyb5smFsUHpc0e23KqXa0ypjoxEW2NXmM8liw0Dg285tawtkkyDZJQ8", - "Y/GQGNRNjB0ZkmKleEjUMppUbYwrTXkEQ/J///f/eW5h6KYaG2RaxKV05Yyoa7BQFJfFhDeMLQeInR9n", - "4aUKE107cC0s0L2rfblma0/njefaHsroCfulvVHm8vV5b+C8v62fyyV5X5t7973p4X4dNeSpO/FUG0KE", - "73ahYV5Ie8OOVQbMoHTJpM5pQk5st7VQx5gbpG4EoFNQis6BSOAxSIjJTIrUIXKWauuN2T9iFuk2+4Wx", - "QrRd9xgrfC2BasvHbDyqtlvBgNt+lfqUKuijsg1svKtgthX4MmwQZqkON96tPbmp4VhfMitHwNDfw1qV", - "mv/tEs2zYAoxr8IGUaXYnBuiJQjTBQEb83UGRkIEzBvCsxaHjvmNQ3hmsM7IiCWxLG4Y0RGLn2MM75EE", - "sDvifZWP0wj6bdOpINV5SOnCyBtG3g6Egn1ZJ14nqgGnjaWeNgsw5iUVMvpdgnmeXJeOiGMbp1XIoCJV", - "xPSjulwiumR6UdzJuC1MkSVNmJlgPLQmxW2ydJTINEcJTTO/Iano4oObkcNhqkdIRpFzHtNyc5b1jU7W", - "34REhpuuBSrfMhsD1OVmkWLl+IRm2cmYb20dKZbzpiLe2kZSrjbTLPvFbfA3U2CCjzmzHThZUB4nhrIq", - "8ubt728/vyX2OU6vaJZNWHzdwlKzbH++KM0yz+aPLLOvx7ffw7tZJMus8pWxd5PIUUYFjwt3xc7trr5/", - "O7jIZLWzmlAn1tu02f2O8UGMD95vfNBjL/x07w708ZbaNVYhFillPNisgaaTYv//NpNqPmFX+M1MAgNv", - "G8r4gBVsSYIq8nAzNhTmG53OTJMAELsbvmIQHnfGzfJeI2NHFPE6RlteRceyrOHJB8z5w0vTrpGwe5O+", - "IwzlvHbBdp931SIJheE8EMVy1JYbzfSRxSoqM31K0wmbNLbtBncmntuj4cR8TcKKrBZOakG60Ofa1l93", - "BLDTvjt1/Co9O29M4bGY+qkQCVCOq1sdMmh3kbefQCxOBDK9cBvY+8nVe3vjo7P1GCzAVa+9gyzLp+Xr", - "6MCal0fVV7vMQCFm/bE5DCIPkYfIayLv9MqipztComm0IHQbd25deafQSQOSB4HI9SGtXK0PKkUSGLB8", - "ece5panxIUhsv3CZ3Afdlhs5/q90ECZa7BI9R4gcIESoPl6IHFew/vRbLjTtSgKjhaRzIDFTFwXI3GUk", - "t0cwymPuPX2z/3ZDIkVEiogUsRE8u4Fz1gy9tTpn581hEHmIPEReE3m7OmdbuLuBc3ZQce+nzDzP15P2", - "oH+2T/9sGym7+WeIksNECbpo92aoihwu/TJ17r5U9qm8PdJCpIVPlRZONhfJ9hOfbz9IsbFitretQJPO", - "cxIb8N3a91OZqpc9LJ57+sLudW7udUqhGuArns/AoL2HFAbPNyJuEDdIE2vDtRlA3GPsot16bYQUEYWI", - "Qgxp9LBeiBvEDVqvwamto9Nz5bno6wtglC14RhfP6N6FlOZ6YbepW5XiNQznMGf2LAQtSuTkegFcF68i", - "ZAlyV7X0zg/vliUPu0/eVj192vletPFwkOd9UvTZXkVhpK89NPirKIJMr9XTO5yDt1Ye+wuoka5CNmOm", - "LnolH3E7d7YSI5+Ynyfe0jSN/CKuNoUnwYi5ej3DCAkmGBlzN9vTq2LMlhwjb+xj7S2LsRvPe2z0grDY", - "IHXGmpW3Qnkhixshdzn+nMRxIWJbdKKUPWQTyCYeLCOwU9eM238t+H0M4g7UJE0SEZm/ZmWRQsb1//p5", - "MPSXD72YWF4eSHFmO0Su6HACMtwnhmXbLazTGG5uuzSBJSTB6qcXkwAvKlolbbu3Yn/CLq/Kfdw++YeL", - "p9p4xZgT5eGTEW9QmP7Uy+WmD6G5pj1da/DbnMWz8l4LEKY4OeCkvq44QlGLfyZks3ZX7GTBS08eTEZw", - "ewZuz3gApTtjiZP0HsrW9Q27lr8W97rL6qVujDpYPjTUzk2MJHQKyaFUHcWFpcOxA7NKMLd0fi2z6JSi", - "U3rPaShLjVoUUrNKLIYZ48zG+9JcaTIFknP2LQ/WjN631p1NZgwSj+p9LZI85UTMyGziSj3retp2BFBE", - "C9/a52wiMt8N04xKpgQn7rGE4VPA89S8yL8PhoPfz/7r7WA4GOcvXvwE1X/+Xv4vqv5jfjp731DszbHt", - "ZLeH/7zrMyxpknvu8y/zM9HC5Z6X7paRe1m+W23Yo3J+w+rNF++rHvI+7NU+uA4m8+zLt06v3H96O7ql", - "iPLY1jd0BwRSV6hUlAYOtGqlZl3OTUGuaveGPJsDnxR3H7mtCbOJ5VmBegbVY2F1nEdWHacUwfYkoHsS", - "tL1KF7rW6FofCPN7J2I26wemmtsdttreM+f08C7n1/vbRBZoqEhfG5F7gJSrj4VnHUdcC/QuoS0FujO6", - "Bfo+AlwKtDfGZX63kMUoF5I0f5TL5wTUgS7AkswY63rAWFdAxTYCWftUsEagqn0I6/N6T1MgYtaI/xjd", - "qgWJ7IStzvU1u50G3gCRGUxZIdsa7X8WUFUgq2/HFKHEXtH48dlnM/Svz/uW6PIYDHMD89TDesKE8rpW", - "fDXYw1T0enoU6FjCUqCryJQR5t2CU0YEffEp85uEGUjgEagudtXP2bHo8fs7oCuXp0R/q9PjHhTDVY8z", - "XGUEpU/E6kgkD0NZGMo6zFBWB9DWCN7R6Pi9c9AO0tjDBCD5OrL40wahOoXvmZA6eDLzrW1egxXjhJJ/", - "fvrwnrjt0FWR8wTqfFQstde5s0Gy1dC5IZ4C0epJoA5MQhp78sLRHrvJYMGSuBQU463SNdcuLAHBXU/I", - "eJDx4L7YPug8vZr1TmhbLPa5TDAtEN1whXdZ/XtwkO5/SRK98keY3qWAghatQFjzFhAGD7Uon4h5eIFd", - "GPvjO/53/VAJDnCd8X5NYLG43s5R674EeEQzlSdUQ0ymK9tcHMqCeDfm6l3GRPKK5BXJa0/knl5Z77Ev", - "h+Xr6K2DEzcjtT2CgB+pBK6bYZDDseuvm473PqZWfgskvI+E8L6t0bIRy9ud+iJY9gUWpMWYhfEwDHHv", - "2uwp1dGC8Xnv2G6v4uxIjpEcIznewOSOpWB2RmbfWjAITgQngnMDnLYYbhCZ5bavywXIDcKtSK4gJs9q", - "/3VtC6waEpkn4P4XLSC6IHohQS1EEqvnrXj+YqeEy+hHKF2TXnlv2pfv+hwV2n9yhj0lxSl2Ht3hCaRZ", - "JagzTOyKq327nP84ZNQ0vP8NcijmLKJJlcqE/FswbkyNXjDVeBN6ASSTsGQiV0RwCORLKcMIG3EeoVxu", - "mLWjKWVCac+5jkaiTAQ8Av5OjGjHIdtzSMVynZQ1uFhbGb8tjbDPs2EuihgExWbUch0afkBYKghch++6", - "Faftc9sNnG2MMdx4EsQdrjK4VQYu7JnD3Q3vwcPsdla4OMm5ZoiBa7m6lSmONpc5nE3ONhDvNc2oNnC5", - "4hCWK6T9kvHpgsUx8EkKPJ8USZS7d/qY3lXKZXcH5zNXjTMhCSxBrlx9sxF5Rzmdg1RjrgAITRLXoH4h", - "TnXlym5s58mKmA7mRq6D+e+KTCERBtrCp9l+A/1r8Tz/sJN5Bzx/WzwMpkB4CsHO/urhQeDmRLnXCWuH", - "lyBR/s3d6S7z0mwUKfSZSluuMHShSOA0aKfQ8hx5yZ8qtYST6Vqzk4hy0ke5j/mu2r0SelTlmM3m4coJ", - "BVWzca32rJjXJnPVLz/M2zVoEhaTZ2W5ueIZGFcaaGwcGZf8xpt7JpNsyRKYe1T8yeeTosZG1cmNNiQn", - "v544uF8yBUdmNB7HUekHpDanV2VN4uv+LMfmi4moimhc1D4Em1ImhXQKUi1YNiQ0y9TpTMhUnZaLt6ep", - "iIv/jnlVRJolzGDH3jPLp+XHViNy7kTF1Vy04laYrFqGm/6JMWPFZCgv/BePITM344L/sIEDj0X7bM9s", - "p7nLpH7y1rhFUxGvToq3EFHOhU3/7oaNO9hf1zr0bwX66zVomuuFq/9VrD8buAWWnqva0ge57IxkbHMf", - "hJOh2njsSMicP34jQnaAcoh7mXAv06ElzbGCfKIaEG1jkIeq3O+D094x70ReedS88tRQwe7YtOlV2zPC", - "FKkoYgJGhtoN5JjvJR5tYfoqyxQaSTSSjzNw4gdpYD0p5BB+4QsWG4ewWlJaWT1f4c1VzDJodEWyFiKJ", - "txy5MW94cqY/jcoy+omYzyG2XiEl0YLyuXHbDNbctzB9IGW62+3qsbT0eEx19f1WHmZTf6oLWNnEw/Yr", - "dq5LN26Ka9DHvxLQfyW4geam7b2jteCjQSsaYlyMPhBv9R8HbYUr7xhtcNAGowV+Sr5wvQTSY7dW1dct", - "jKgFxOWuyALd52C+RqQ3GqzBHXOLe2d1VYfZfVfPC+0t2tsn5Pj2SPPglgxjOJT4VK/8EYhTxOljwqns", - "bTflvVnNc7SZiMUniMV+aVhs8tAyFcvulnPM9x9d6pvfBQGLgH1MgLXY6Uarg5jbxlcemvPEf/2bk5zl", - "7IVQG2XKqFKXQtro0phLmDOlHWQnF7AikUjylCtCJRAOS5AEvmdC+QNNJb6/qB41MxDcCO7jBTfreR7J", - "OKyEZeTZNE8ubFmi5w53Jyw+scFHpkhKeUy1kKvyLOxUxCsHyHIHuvlVUzkHTVj2i/3Tjl1Ef/UCeFHS", - "KCZUkTdvf3/7+S0x0zy9YvF1eHH27I6PQ52tY9y8jwkzAH+OpbmxIOWm+WOZIjFosF6h4C7e0zB7pclj", - "4dNR5hZiVkSKLhdC2U1NzvYZK7bJev127AwPTKHxuEPjYbXyLhYkuIb4XsSwdSLDrhVOoXHAw0l7FUR1", - "pfCyZoSlZdFxzG+69+esc0tuq4HwMD/M/f74ShCXLKl5DsOe+6kFwzg8UyDAqvLwPE9Bssho/KKUeyHT", - "NI4lKBXU7DtK5HJipsdBXwp5oYxgmrHqcfYipuia4NGLB7BEiZh3BCRgaWvTF45Jdb0xDz50/W5u2IGv", - "MvBPtDC3KYeo0kRvZCDqmwP2m/n4jSSwVf4eRB1yuoc8BE9rKXdmze08MsJoONRMyMitgZ2koBSdw8mw", - "cPBnNE/0mCewhMR0PTH842RoSRmkmV418WOcm5ipiMo4vA+swOd+/P1EzCcxi7TnDOrQNs5S7T2qZNrs", - "Q3lbHQWMvW1qGfmbNmIH5ehf8ZjSIW/NMvbn9Mp8rMId6iCKa/bHCX5bMX1nkLrs0e/VrZq0LxHzsBPi", - "ZowMDxneoTO8amNVv0DDdpy60MbtweoxNybJE6w2V/cNV4+5m+3pVTHmNXm2kd/iL4TmMdMW/X/xbYV+", - "Hg5FlPu19mP7GkZq/X2+t77sVkTDklbrSBactd1+lbfHAPjTCoDzQki37FhgtyGaFHRf7jGHV2EjVpUm", - "K7XaxFGlbYdjv1rXhacnThNdDYDnqU3ZmytDzrI8SRoas/YaaOavQkiVAj0Bvgy3OsLnaZ0yoSZLkCqU", - "jyFKcqVBhjyZ+gv4WzmHSE+08Ddn+SQS0r2U7TTJpjlmba0zCd+Cd05FHHDNTKteSKBxy72XwOPAYwGP", - "EqFyCe2tKhF+x3H2Lfa/7MUy8HMmRBJoWsaRv+VyIqZqQhOQemIEv63XJZU83CmhSk+mIvA0tjUSaepv", - "ZUoDBznJhNT+t52IaELjWAac7GgyzVkSm79DHSKrO0KNIi/PT3nbZ4kQ4bEljS7CjUKkwcY/mR+uKTXP", - "zimPYAI8DvTh+YxGOpfgn1oK6WRK+UVAgG3zSkNLs5HOUHMQOVZJhjSNbZxJ8Sc0pXsqRAKUb3SYUL1z", - "1KTU1oHGmj4r//BCTaiMFt7LhZpEgkeBWQk1uQDJAy9FqElwWkL1QWHRqx2FQk0kJEBVsLlFZWXiEuRk", - "KoFegPyxu8tfW7pEdMo46B+7u7TdJZNCQ6S7e5RTaump8ixLVhM+9ctzIPmP5R2TPwUPNUpG/V9ccSH+", - "hIlmSaA9a7WpSlOdK2+TBppO7NTDzY3V8HAn80rWNW6jQ0E8thv+9P7siJMflG3PeUmlpFyvAmruPpIv", - "4anSHoGV0wWV8SWV0L6IRpOk2JD08fWZjd6nkAq5ItXlIY/vH3UH9PzQ87s7OZ5S1VeGf31tRZh9ev3p", - "jCyE0mSaK0JjmhXF6AKibIZAMUYxvkMxriLHfSLenHzIgH/612sX1gikU5aQGBNepukZtUSXuxaagqHh", - "L1/O3mzGhz2rTiXFP8jcwhjIXd83U2R1cmk3VQaRcbLsFw5pyEMUH1y1xFXLAwlHf1kLQres+pdh54NV", - "xxgJx0g4RsIxEo6R8DuLhGO0G6PdGO3GaPcjjHYfx5bDOhRzapVaV3SxiMG4rgEH+VXZim4yusm4udeD", - "tHTCNtW+F3PnoHPJiRFrwlyGmcItBelJDeWOZJlhRkFspmfnjYExEvrk1X5EecwMIZi4K1rTHtG5IlRr", - "Gi1smT8tqs2GXGiyAl20FifSzY/wPUryGDz7DguRfF1O4DOdo9VAq4FWIwDUBUQX/fhZ0TUEuLIVkYZI", - "Q6R5kCbSLGGUR9Cwjj2S0f8GmlQXNDPSu9VFc39/sguLymrQyiC25ZnvlIKPVC/Mfc/iAeLqkeHK6nox", - "8wpbA3EehW4Y2UzkPG6AbSOtCtcgOU1sNlqQBKQU8v7hJncDm7wl1M4RaAi0PkCTjwFmrflkLLCqvsT0", - "3RFV/uwyCKQnDKTXHoEqk9wdO0fsyQwbfLAKklQBlD6wQjqI4Gq1UpVYPRI2WD/G6VXq8oR17Bg2z09o", - "/fyuTGcQYvWeYA/K7gFkpv87Bdr03xagn7319osHU3kUgVKzPElWJAb34du/tpCNF/PQnz60ffCV3vqG", - "bUqy3ER4IN/vZlsGb7Bs/tc22Sj1AB788uuVXr6lvJ2xRocSTXUfU/0o/ElZmWm5i5mWNzbS5/eq4s93", - "MdHntzLQ8ljMs7yRcX7A7/aQpvkcDXMvPVLvpAwvcTZCUwVFJAk1vy8guiAy58TdZceY1Sc3NFprtNbe", - "qFUhVM3zgp741ZGY7piprp0EtotlKv1ORb6xt8Q9BYhJ3FPgg1zPDCRu/86O6UfC2UcQfgg/hJ+BX3fi", - "FAc9pYWkc+ifMMWfLwWBh8BD4MXXp8yQ2xntrH9dwK+o30QalwVwd9bsgehD9CH6POjL+sHu7GNZJq0F", - "cBkiDZGGSPMjTYFcsk4rV2YyK3oTxpWmPAJFhKvSUcRaIG4NtnwqB0M8Ih4Rj214PL1ytci6y1ZtYrIM", - "+d4EmQcKzPVJfCofuDEP97Kqaahl1DKLosobagfUDsemHWzGF5uuzbvM/cm225oq3PVdK19llYKjzqMx", - "P5uROJdVse1MiiWLIR6S4sqca5YQLi7JX+qOz2A0H5Hx4MfFeDAk48Ff4/Hg+fbNhKvcPaznUa46jcb8", - "c1klPKK8HIxpBclsRL7Yevu2Bvl0vfo45TEJ1Rsftaziu3dyyxXSvSXWK1+SR5+Xr88pna03/dOLtPnK", - "yYeU2W0M5Rseeat+bW0EwHJex5/7YKeMB80dgCHzjykM0Oyi2Q3iLc9dbtFWHm4tmuk5Ih94UvzdMFjK", - "LY06a+bqKdMkEZcQB7PeGGRhrpunp+/FVIkEVAR2kyrMJCibLzLLvcmWbLvlQuWKO7H5MZ3ECUVmeZIQ", - "870VSYx1KEqrNochCrRmfK5GY37uBMFVWv0wVSUDyyRbsgTmfrqV6w+N+xWzGhwa23hEGxLXpKT8fP0q", - "E/i+/Ijc6Lu7mzY//adyKvvizL46uB88T0AkRELGxGqz9gK4WPv2yZVM8Go7n+UNyDJWlsHKMvdUi+Cd", - "iNlstWdF/VEoffBqejjYzlO9YcSoBnfy5nLBokVRNCqlOlqYe9tUkuVAhgnNEjqfuzrw7mVqCA27lvh6", - "b6NSYu5rhjkQo7QPBw7t0M3o2elV7+pR98HRupzLTvh6HMp79iWPxEM4RtpURjYCwtiTOx2AjGEYEcOI", - "T5DaHYp23we5fGK0EEngIyGBGXCasVH5AQo7u2U3P10awZCDA/iqBxAhLd9mlk8TFhWvsrlTsYs9l5ui", - "wmS4sRVxPwqq2FT0MrxbyS7GGC3a5QcWt8IA5dMKUKpaJLf1Q3DnLBJbjEPeFVl9LcEQHCFJXlZHLXeb", - "Ppuuyl2WxYbLCfPUyjDMdO+qtqPgp5lLqBCpbcu1UJoGqpKZHpFI02Je3vZYcuEqpLZ0yeyGm4521dYh", - "WCDNtIdKHJq2WQLfJ1GWTxZsvrB1RNVCJLG/LN3aBYm47N0/pd8nm8/g7cd4Z7/Nkozrz7OgwaYWGUhB", - "S1HISrBT+0foUc7RdMsSGkGrxNjNlYoJDuH5dpbzW0YTLTKRiPkq2OGSLiH4ngP1IQ+iAl7JkyKrc+Ja", - "6TztrEPe8wDdwePNAzuUxySiKqIxEHc1YVoRCYl92UV6mFE7We6KJzzExnzcivQwZLWZUKiRakdVkhKi", - "sIcoRBgfxvjwgVDuL5tEu0F9W8j1warmfYVWkNA/EUKPrP0YWfuBUfWDXxfYovU9y1hXfD5Yybr4Iv2K", - "WSPZQrL1RM70eBB3p+WsyxWoNozuVNQaveunYAZuXda6CtDfrLJ1IWU7FbdGK4JW5MlakX7lrUtUhitc", - "l8DrVeQaEYeIe7qIu2GZ60AZhrpWUmlE19MmdYe0dyyBjVBGKCOUb1FCexPI8s5gfH7YIN6oxzGzLurQ", - "nfFveSnAI5qp3C391u/FTuubEerGvBK6NG31NGKY0TzRg5czmigYbsVWUbmgcjk45XLDwuHFPf11mLa0", - "hr98OFp7BOT91CQvNfnRo3UfXN5lPbs5BTh4At9m+1veBtp+VDVPy/bvrxp7mA6sbZPsVdP7OGhBs1B4", - "WOe4KrHuLd29jvm6W1Hx9RK2x7U14ecXf+vT928HtYMtVAk/jJ7GPrYnhx1nn+/HOn897nL8jwY5nSbr", - "thGw25LfxxP2QuKLxPepEl9Z0V65C+2VtyS958dvts+PkfKeI+F9YMIrb0F3nwRqDo7sniPVfWAj5YpV", - "7RrnJQk1vy8guiAy59u1rnZhu5/cFHDlBlklsko/YGOm+u9xdJ3DyHtTtCPcEG4INx/cqvKqdQ2aXbKe", - "1aUgm2kftCAxVYupoDIeEgkqFdz+y/hMuJ527/EkYUtod/bOivsfRXwIC+Q8qWTFWxgw/jBLdqiHikKO", - "5hLN5RGZyyobQB926imTDDRaEDGzGZHcvcJa4X3RjuQV0YhoDKJxnbjebf3yBjLRVqN2QO1wRNrBjC1y", - "GbXY76CeqC69kao4rwZGnYE6A3XGMeqM9nM9VfmiNtVhyAaQaEH5/JaK5ICP/6AuQV2CuqTUHWWViz7R", - "glpR2Cj5BaxOlzTJgWSUybY4wXkxDkYKEIuIxSAWO7h/EI2CE5okndG6Qyf5iEPE4QHhsJ1PB8G4xaF3", - "gSaemkd0Ijpb0LlTHkh33oX22P+IiR0Rd4i7LdxNqr1XN9px1V1w8qy6/77KI7RWnawjXkVZ36EtPmts", - "tAbJqWZLuzWsgPVfSB3d2U5GX7a9DISUygqXQ3PHKZBcQUxoIvicXDK9IJU6aCnl1VU9M3TvrXnfZ558", - "LKN5eGU0CWsgLVhQswlHrKyJlTXvxbSsFXMLS3LVP1BlizyrHK3nfWQc6R7iDOleAJMTt+1okoh5Oyq3", - "7Uu5YykR8xF5S6OFrY63IkwRSjRLgUjK50AuFyChZSviJbW3miatVSNqk+UOrv0u5mi70HbdMU52RscN", - "MbEbFBABiIA7RkAZfusMBWg6J8+meXJh2Fr6PBwJKCJv+3H+NZ17HefPdE5c29DwNjO5KgTg9ZFryvZH", - "edOv6Dk/rZq+35nSjFvB8TrN/pgxalrUtHeVW+W1rQbvtOsokEtl7/o0pppuT+VXCba8W0r++enDe2I6", - "bSUZ03Tui26amxZVt3zV5eZ5QiWB75kEpZjgRMyswjZetSJ6QTWJKLe1u6bQqOdVBz9txbmWwcMlRDfV", - "vu15H4p/H07mIej6A0++Yn6vD8h1Jv8yYlck/jIXtZOY8izcfpDXtbgQku27Yj/1cgfyoKfFg2iSGJH5", - "wXz/Qt2mZiohShQ4E4q8CHnRneecM6rN7vgIqeuSIR2GsnZougXDquGI9uAR24Pj4FVlsHNXalXWhm5l", - "V2WMc2+Y7b/H4v6hVcwNkfU0mVYZ/e9BthqwQL6FfOvB+FaLDi8p1wFq8KPmX2gkkH416deVk4w+uRGL", - "4KxNc8iq6hDW0BjJtgEy26hqzAaIWdcuqrM3Nn5bRYM9+6Qqie7cJ1VtvsWUgg+XUtAITqEQVgFa8kBC", - "sevuuXsTooP+2H4T/yWLq6Um0tD/Aev+kGpg3wtdXQtWO64p3bl1RtfsjixpRyrF30AXptJt2yqtKquP", - "nwX0Y6+0iQeiJO/cNbytFmYaUuXBQYU8KiVd+XBhnW4xKz/i2tJxLazb3J0LTWYi5/EhiWnf5Nj+pc0w", - "weuTSPDuRDU0TjHnA0lQvXf/6Emyzl3WdkI85MlI675Iz0YIpIfMYjDhCQUT1hZ1euxz35UJhePXT5MM", - "YZz8KZy38kNs7RzkDRZQwxzuU9XhYAyjC8yX423Uu7v1OUokdMdE6ELyW3C6pym9SPCQ4N2N9VmCVMx9", - "NC+jk6BzyQnNGCm7esjbv6qmO7P25ej7WRCvXgfN6JQlzAro12v3ZuWyVCq5TAYvB6PTwfXX6/8XAAD/", - "//ZvAcAFcQIA", -} - -// GetSwagger returns the content of the embedded swagger specification file -// or error if failed to decode + "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", +} + +// decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, +// after base64-decoding and flate-decompressing the embedded blob. func decodeSpec() ([]byte, error) { - zipped, err := base64.StdEncoding.DecodeString(strings.Join(swaggerSpec, "")) + encoded := strings.Join(swaggerSpec, "") + compressed, err := base64.StdEncoding.DecodeString(encoded) if err != nil { return nil, fmt.Errorf("error base64 decoding spec: %w", err) } - zr, err := gzip.NewReader(bytes.NewReader(zipped)) - if err != nil { - return nil, fmt.Errorf("error decompressing spec: %w", err) - } + zr := flate.NewReader(bytes.NewReader(compressed)) var buf bytes.Buffer - _, err = buf.ReadFrom(zr) - if err != nil { - return nil, fmt.Errorf("error decompressing spec: %w", err) + if _, err := buf.ReadFrom(zr); err != nil { + return nil, fmt.Errorf("read flate: %w", err) + } + if err := zr.Close(); err != nil { + return nil, fmt.Errorf("close flate reader: %w", err) } return buf.Bytes(), nil @@ -8970,7 +9015,7 @@ func decodeSpec() ([]byte, error) { var rawSpec = decodeSpecCached() -// a naive cached of a decoded swagger spec +// a naive cache of the decoded OpenAPI spec func decodeSpecCached() func() ([]byte, error) { data, err := decodeSpec() return func() ([]byte, error) { @@ -8988,12 +9033,12 @@ func PathToRawSpec(pathToFile string) map[string]func() ([]byte, error) { return res } -// GetSwagger returns the Swagger specification corresponding to the generated code -// in this file. The external references of Swagger specification are resolved. -// The logic of resolving external references is tightly connected to "import-mapping" feature. -// Externally referenced files must be embedded in the corresponding golang packages. -// Urls can be supported but this task was out of the scope. -func GetSwagger() (swagger *openapi3.T, err error) { +// GetSpec returns the OpenAPI specification corresponding to the generated +// code in this file. External references in the spec are resolved through +// PathToRawSpec; externally-referenced files must be embedded in their +// corresponding Go packages (via the import-mapping feature). URL-based +// external refs are not supported. +func GetSpec() (swagger *openapi3.T, err error) { resolvePath := PathToRawSpec("") loader := openapi3.NewLoader() @@ -9019,3 +9064,22 @@ func GetSwagger() (swagger *openapi3.T, err error) { } return } + +// GetSpecJSON returns the raw JSON bytes of the embedded OpenAPI +// specification: decompressed but not unmarshaled. External references +// are not resolved here; the bytes are the spec exactly as embedded by +// codegen. The result is cached at package init time, so repeated calls +// are cheap. +func GetSpecJSON() ([]byte, error) { + return rawSpec() +} + +// GetSwagger returns the OpenAPI specification corresponding to the +// generated code in this file. +// +// Deprecated: GetSwagger predates kin-openapi renaming openapi3.Swagger +// to openapi3.T. Use [GetSpec] instead. This wrapper is retained for +// backwards compatibility. +func GetSwagger() (*openapi3.T, error) { + return GetSpec() +} diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index 42c248c9..91336c21 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -1,6 +1,6 @@ // Package server provides primitives to interact with the openapi HTTP API. // -// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.5.1 DO NOT EDIT. +// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.7.1 DO NOT EDIT. package server import ( @@ -10,8 +10,8 @@ import ( ) const ( - BasicAuthScopes = "basicAuth.Scopes" - BearerAuthScopes = "bearerAuth.Scopes" + BasicAuthScopes basicAuthContextKey = "basicAuth.Scopes" + BearerAuthScopes bearerAuthContextKey = "bearerAuth.Scopes" ) // Defines values for PostFiltersJSONBodyFOp. @@ -25,18 +25,254 @@ const ( LessThanEqual PostFiltersJSONBodyFOp = "<=" ) +// Valid indicates whether the value is a known member of the PostFiltersJSONBodyFOp enum. +func (e PostFiltersJSONBodyFOp) Valid() bool { + switch e { + case Equal: + return true + case GreaterThan: + return true + case GreaterThanEqual: + return true + case IN: + return true + case LIKE: + return true + case LessThan: + return true + case LessThanEqual: + return true + default: + return false + } +} + // Defines values for PostNodesJSONBodyActionType. const ( PostNodesJSONBodyActionTypePull PostNodesJSONBodyActionType = "pull" PostNodesJSONBodyActionTypePush PostNodesJSONBodyActionType = "push" ) +// Valid indicates whether the value is a known member of the PostNodesJSONBodyActionType enum. +func (e PostNodesJSONBodyActionType) Valid() bool { + switch e { + case PostNodesJSONBodyActionTypePull: + return true + case PostNodesJSONBodyActionTypePush: + return true + default: + return false + } +} + // Defines values for PostNodeJSONBodyActionType. const ( PostNodeJSONBodyActionTypePull PostNodeJSONBodyActionType = "pull" PostNodeJSONBodyActionTypePush PostNodeJSONBodyActionType = "push" ) +// Valid indicates whether the value is a known member of the PostNodeJSONBodyActionType enum. +func (e PostNodeJSONBodyActionType) Valid() bool { + switch e { + case PostNodeJSONBodyActionTypePull: + return true + case PostNodeJSONBodyActionTypePush: + return true + default: + return false + } +} + +// AlertListResponse defines model for AlertListResponse. +type AlertListResponse struct { + Data AlertListResponse_Data `json:"data"` + Meta *ListMeta `json:"meta,omitempty"` +} + +// AlertListResponseData0 defines model for . +type AlertListResponseData0 = []AlertRow + +// AlertListResponseData1 defines model for . +type AlertListResponseData1 map[string]map[string]int + +// AlertListResponse_Data defines model for AlertListResponse.Data. +type AlertListResponse_Data struct { + union json.RawMessage +} + +// AlertRow A dashboard alert row. Every property is optional: the `props` query +// parameter selects which columns the server returns. `alert` is computed +// from `dash_fmt` and `dash_dict`. The `nodes.` and `services.` properties +// come from a LEFT JOIN and are null when the alert targets the other kind +// of object. +type AlertRow struct { + // Alert Human readable message, rendered from dash_fmt and dash_dict. + Alert *string `json:"alert,omitempty"` + DashCreated *string `json:"dash_created,omitempty"` + DashDict *string `json:"dash_dict,omitempty"` + DashDictMd5 *string `json:"dash_dict_md5,omitempty"` + DashEnv *string `json:"dash_env,omitempty"` + DashFmt *string `json:"dash_fmt,omitempty"` + DashInstance *string `json:"dash_instance,omitempty"` + DashMd5 *string `json:"dash_md5,omitempty"` + DashSeverity *int `json:"dash_severity,omitempty"` + DashType *string `json:"dash_type,omitempty"` + DashUpdated *string `json:"dash_updated,omitempty"` + Id *int `json:"id,omitempty"` + NodeId *string `json:"node_id,omitempty"` + NodesNodename *string `json:"nodes.nodename,omitempty"` + ServicesSvcname *string `json:"services.svcname,omitempty"` + SvcId *string `json:"svc_id,omitempty"` +} + +// AppListResponse defines model for AppListResponse. +type AppListResponse struct { + Data AppListResponse_Data `json:"data"` + Meta *ListMeta `json:"meta,omitempty"` +} + +// AppListResponseData0 defines model for . +type AppListResponseData0 = []AppRow + +// AppListResponseData1 defines model for . +type AppListResponseData1 map[string]map[string]int + +// AppListResponse_Data defines model for AppListResponse.Data. +type AppListResponse_Data struct { + union json.RawMessage +} + +// AppRow An application code. Every property is optional: the `props` query +// parameter selects which columns the server returns. +type AppRow struct { + App *string `json:"app,omitempty"` + AppDomain *string `json:"app_domain,omitempty"` + AppTeamOps *string `json:"app_team_ops,omitempty"` + Description *string `json:"description,omitempty"` + Id *int `json:"id,omitempty"` + Updated *string `json:"updated,omitempty"` +} + +// DiskListResponse defines model for DiskListResponse. +type DiskListResponse struct { + Data DiskListResponse_Data `json:"data"` + Meta *ListMeta `json:"meta,omitempty"` +} + +// DiskListResponseData0 defines model for . +type DiskListResponseData0 = []DiskRow + +// DiskListResponseData1 defines model for . +type DiskListResponseData1 map[string]map[string]int + +// DiskListResponse_Data defines model for DiskListResponse.Data. +type DiskListResponse_Data struct { + union json.RawMessage +} + +// DiskRow A disk seen on a node, with the service and array it belongs to when +// known. Every property is optional: the `props` query parameter selects +// which columns the server returns. +type DiskRow struct { + App *string `json:"app,omitempty"` + DiskAlloc *int `json:"disk_alloc,omitempty"` + DiskArrayid *string `json:"disk_arrayid,omitempty"` + DiskDevid *string `json:"disk_devid,omitempty"` + DiskDg *string `json:"disk_dg,omitempty"` + DiskGroup *string `json:"disk_group,omitempty"` + DiskId *string `json:"disk_id,omitempty"` + DiskLevel *int `json:"disk_level,omitempty"` + DiskModel *string `json:"disk_model,omitempty"` + DiskName *string `json:"disk_name,omitempty"` + DiskRaid *string `json:"disk_raid,omitempty"` + DiskRegion *string `json:"disk_region,omitempty"` + DiskSize *int `json:"disk_size,omitempty"` + DiskUsed *int `json:"disk_used,omitempty"` + DiskVendor *string `json:"disk_vendor,omitempty"` + NodeId *string `json:"node_id,omitempty"` + Nodename *string `json:"nodename,omitempty"` + SvcId *string `json:"svc_id,omitempty"` + Svcname *string `json:"svcname,omitempty"` + Updated *string `json:"updated,omitempty"` +} + +// GroupListResponse defines model for GroupListResponse. +type GroupListResponse struct { + Data GroupListResponse_Data `json:"data"` + Meta *ListMeta `json:"meta,omitempty"` +} + +// GroupListResponseData0 defines model for . +type GroupListResponseData0 = []GroupRow + +// GroupListResponseData1 defines model for . +type GroupListResponseData1 map[string]map[string]int + +// GroupListResponse_Data defines model for GroupListResponse.Data. +type GroupListResponse_Data struct { + union json.RawMessage +} + +// GroupRow A user group. `privilege` is "T" for a privilege-granting group and +// "F" for an ordinary one. Every property is optional: the `props` query +// parameter selects which columns the server returns. +type GroupRow struct { + Description *string `json:"description,omitempty"` + Id *int `json:"id,omitempty"` + Privilege *string `json:"privilege,omitempty"` + Role *string `json:"role,omitempty"` +} + +// InfoResponse Outcome message of a write that returns no record. +type InfoResponse struct { + Info *string `json:"info,omitempty"` +} + +// IpListResponse defines model for IpListResponse. +type IpListResponse struct { + Data IpListResponse_Data `json:"data"` + Meta *ListMeta `json:"meta,omitempty"` +} + +// IpListResponseData0 defines model for . +type IpListResponseData0 = []IpRow + +// IpListResponseData1 defines model for . +type IpListResponseData1 map[string]map[string]int + +// IpListResponse_Data defines model for IpListResponse.Data. +type IpListResponse_Data struct { + union json.RawMessage +} + +// IpRow An IP address detected on a node, joined to the network it belongs to. +// Every property is optional: the `props` query parameter selects which +// columns the server returns. +type IpRow struct { + Addr *string `json:"addr,omitempty"` + FlagDeprecated *int `json:"flag_deprecated,omitempty"` + Id *int `json:"id,omitempty"` + Intf *string `json:"intf,omitempty"` + Mac *string `json:"mac,omitempty"` + Mask *string `json:"mask,omitempty"` + NetBegin *string `json:"net_begin,omitempty"` + NetBroadcast *string `json:"net_broadcast,omitempty"` + NetComment *string `json:"net_comment,omitempty"` + NetEnd *string `json:"net_end,omitempty"` + NetGateway *string `json:"net_gateway,omitempty"` + NetId *int `json:"net_id,omitempty"` + NetName *string `json:"net_name,omitempty"` + NetNetmask *string `json:"net_netmask,omitempty"` + NetNetwork *string `json:"net_network,omitempty"` + NetPrio *int `json:"net_prio,omitempty"` + NetPvid *string `json:"net_pvid,omitempty"` + NetTeamResponsible *string `json:"net_team_responsible,omitempty"` + NodeId *string `json:"node_id,omitempty"` + Nodename *string `json:"nodename,omitempty"` + Type *string `json:"type,omitempty"` + Updated *string `json:"updated,omitempty"` +} + // ListMeta defines model for ListMeta. type ListMeta struct { AvailableProps *[]string `json:"available_props,omitempty"` @@ -65,6 +301,106 @@ type ListResponse_Data struct { union json.RawMessage } +// NodeListResponse defines model for NodeListResponse. +type NodeListResponse struct { + Data NodeListResponse_Data `json:"data"` + Meta *ListMeta `json:"meta,omitempty"` +} + +// NodeListResponseData0 defines model for . +type NodeListResponseData0 = []NodeRow + +// NodeListResponseData1 defines model for . +type NodeListResponseData1 map[string]map[string]int + +// NodeListResponse_Data defines model for NodeListResponse.Data. +type NodeListResponse_Data struct { + union json.RawMessage +} + +// NodeRow A node row of the nodes list. Every property is optional: the `props` +// query parameter selects which columns the server returns, so a row +// carries only the requested subset. +type NodeRow struct { + ActionType *string `json:"action_type,omitempty"` + App *string `json:"app,omitempty"` + AssetEnv *string `json:"asset_env,omitempty"` + Assetname *string `json:"assetname,omitempty"` + BiosVersion *string `json:"bios_version,omitempty"` + BladeCabinet *string `json:"blade_cabinet,omitempty"` + ClusterId *string `json:"cluster_id,omitempty"` + Collector *string `json:"collector,omitempty"` + ConnectTo *string `json:"connect_to,omitempty"` + CpuCores *int `json:"cpu_cores,omitempty"` + CpuDies *int `json:"cpu_dies,omitempty"` + CpuFreq *string `json:"cpu_freq,omitempty"` + CpuModel *string `json:"cpu_model,omitempty"` + CpuThreads *int `json:"cpu_threads,omitempty"` + CpuVendor *string `json:"cpu_vendor,omitempty"` + Enclosure *string `json:"enclosure,omitempty"` + Enclosureslot *string `json:"enclosureslot,omitempty"` + Fqdn *string `json:"fqdn,omitempty"` + Hv *string `json:"hv,omitempty"` + Hvpool *string `json:"hvpool,omitempty"` + Hvvdc *string `json:"hvvdc,omitempty"` + HwObsAlertDate *string `json:"hw_obs_alert_date,omitempty"` + HwObsWarnDate *string `json:"hw_obs_warn_date,omitempty"` + LastBoot *string `json:"last_boot,omitempty"` + LastComm *string `json:"last_comm,omitempty"` + ListenerPort *int `json:"listener_port,omitempty"` + LocAddr *string `json:"loc_addr,omitempty"` + LocBuilding *string `json:"loc_building,omitempty"` + LocCity *string `json:"loc_city,omitempty"` + LocCountry *string `json:"loc_country,omitempty"` + LocFloor *string `json:"loc_floor,omitempty"` + LocRack *string `json:"loc_rack,omitempty"` + LocRoom *string `json:"loc_room,omitempty"` + LocZip *string `json:"loc_zip,omitempty"` + MaintenanceEnd *string `json:"maintenance_end,omitempty"` + Manufacturer *string `json:"manufacturer,omitempty"` + MemBanks *int `json:"mem_banks,omitempty"` + MemBytes *int `json:"mem_bytes,omitempty"` + MemSlots *int `json:"mem_slots,omitempty"` + Model *string `json:"model,omitempty"` + NodeEnv *string `json:"node_env,omitempty"` + NodeFrozen *string `json:"node_frozen,omitempty"` + NodeFrozenAt *string `json:"node_frozen_at,omitempty"` + NodeId *string `json:"node_id,omitempty"` + Nodename *string `json:"nodename,omitempty"` + Notifications *string `json:"notifications,omitempty"` + OsArch *string `json:"os_arch,omitempty"` + OsConcat *string `json:"os_concat,omitempty"` + OsKernel *string `json:"os_kernel,omitempty"` + OsName *string `json:"os_name,omitempty"` + OsObsAlertDate *string `json:"os_obs_alert_date,omitempty"` + OsObsWarnDate *string `json:"os_obs_warn_date,omitempty"` + OsRelease *string `json:"os_release,omitempty"` + OsSegment *string `json:"os_segment,omitempty"` + OsUpdate *string `json:"os_update,omitempty"` + OsVendor *string `json:"os_vendor,omitempty"` + PowerBreaker1 *string `json:"power_breaker1,omitempty"` + PowerBreaker2 *string `json:"power_breaker2,omitempty"` + PowerCabinet1 *string `json:"power_cabinet1,omitempty"` + PowerCabinet2 *string `json:"power_cabinet2,omitempty"` + PowerProtect *string `json:"power_protect,omitempty"` + PowerProtectBreaker *string `json:"power_protect_breaker,omitempty"` + PowerSupplyNb *int `json:"power_supply_nb,omitempty"` + Role *string `json:"role,omitempty"` + SecZone *string `json:"sec_zone,omitempty"` + Serial *string `json:"serial,omitempty"` + SnoozeTill *string `json:"snooze_till,omitempty"` + SpVersion *string `json:"sp_version,omitempty"` + Status *string `json:"status,omitempty"` + TeamInteg *string `json:"team_integ,omitempty"` + TeamResponsible *string `json:"team_responsible,omitempty"` + TeamSupport *string `json:"team_support,omitempty"` + Type *string `json:"type,omitempty"` + Tz *string `json:"tz,omitempty"` + Updated *string `json:"updated,omitempty"` + Version *string `json:"version,omitempty"` + WarrantyEnd *string `json:"warranty_end,omitempty"` +} + // Problem defines model for Problem. type Problem struct { // Text A human-readable explanation specific to this occurrence of the @@ -72,6 +408,64 @@ type Problem struct { Text string `json:"text"` } +// ServiceListResponse defines model for ServiceListResponse. +type ServiceListResponse struct { + Data ServiceListResponse_Data `json:"data"` + Meta *ListMeta `json:"meta,omitempty"` +} + +// ServiceListResponseData0 defines model for . +type ServiceListResponseData0 = []ServiceRow + +// ServiceListResponseData1 defines model for . +type ServiceListResponseData1 map[string]map[string]int + +// ServiceListResponse_Data defines model for ServiceListResponse.Data. +type ServiceListResponse_Data struct { + union json.RawMessage +} + +// ServiceRow A service row of the services list. Every property is optional: the `props` +// query parameter selects which columns the server returns, so a row +// carries only the requested subset. +type ServiceRow struct { + ClusterId *string `json:"cluster_id,omitempty"` + Id *int `json:"id,omitempty"` + SvcApp *string `json:"svc_app,omitempty"` + SvcAutostart *string `json:"svc_autostart,omitempty"` + SvcAvailstatus *string `json:"svc_availstatus,omitempty"` + SvcComment *string `json:"svc_comment,omitempty"` + SvcConfig *string `json:"svc_config,omitempty"` + SvcConfigUpdated *string `json:"svc_config_updated,omitempty"` + SvcCreated *string `json:"svc_created,omitempty"` + SvcDrnoaction *string `json:"svc_drnoaction,omitempty"` + SvcDrpnode *string `json:"svc_drpnode,omitempty"` + SvcDrpnodes *string `json:"svc_drpnodes,omitempty"` + SvcDrptype *string `json:"svc_drptype,omitempty"` + SvcEnv *string `json:"svc_env,omitempty"` + SvcFlexCpuHighThreshold *int `json:"svc_flex_cpu_high_threshold,omitempty"` + SvcFlexCpuLowThreshold *int `json:"svc_flex_cpu_low_threshold,omitempty"` + SvcFlexMaxNodes *int `json:"svc_flex_max_nodes,omitempty"` + SvcFlexMinNodes *int `json:"svc_flex_min_nodes,omitempty"` + SvcFlexTarget *int `json:"svc_flex_target,omitempty"` + SvcFrozen *string `json:"svc_frozen,omitempty"` + SvcHa *int `json:"svc_ha,omitempty"` + SvcHostid *string `json:"svc_hostid,omitempty"` + SvcId *string `json:"svc_id,omitempty"` + SvcMetrocluster *string `json:"svc_metrocluster,omitempty"` + SvcNodes *string `json:"svc_nodes,omitempty"` + SvcNotifications *string `json:"svc_notifications,omitempty"` + SvcPlacement *string `json:"svc_placement,omitempty"` + SvcProvisioned *string `json:"svc_provisioned,omitempty"` + SvcSnoozeTill *string `json:"svc_snooze_till,omitempty"` + SvcStatus *string `json:"svc_status,omitempty"` + SvcStatusUpdated *string `json:"svc_status_updated,omitempty"` + SvcTopology *string `json:"svc_topology,omitempty"` + SvcWave *int `json:"svc_wave,omitempty"` + Svcname *string `json:"svcname,omitempty"` + Updated *string `json:"updated,omitempty"` +} + // Version defines model for version. type Version struct { Version string `json:"version"` @@ -125,6 +519,12 @@ type N409 = Problem // N500 defines model for 500. type N500 = Problem +// basicAuthContextKey is the context key for basicAuth security scheme +type basicAuthContextKey string + +// bearerAuthContextKey is the context key for bearerAuth security scheme +type bearerAuthContextKey string + // GetActionsParams defines parameters for GetActions. type GetActionsParams struct { // Props A list of properties to include in each data dictionnary. @@ -3125,6 +3525,316 @@ type PostTagNodeJSONRequestBody PostTagNodeJSONBody // PostTagServiceJSONRequestBody defines body for PostTagService for application/json ContentType. type PostTagServiceJSONRequestBody PostTagServiceJSONBody +// AsAlertListResponseData0 returns the union data inside the AlertListResponse_Data as a AlertListResponseData0 +func (t AlertListResponse_Data) AsAlertListResponseData0() (AlertListResponseData0, error) { + var body AlertListResponseData0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromAlertListResponseData0 overwrites any union data inside the AlertListResponse_Data as the provided AlertListResponseData0 +func (t *AlertListResponse_Data) FromAlertListResponseData0(v AlertListResponseData0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeAlertListResponseData0 performs a merge with any union data inside the AlertListResponse_Data, using the provided AlertListResponseData0 +func (t *AlertListResponse_Data) MergeAlertListResponseData0(v AlertListResponseData0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsAlertListResponseData1 returns the union data inside the AlertListResponse_Data as a AlertListResponseData1 +func (t AlertListResponse_Data) AsAlertListResponseData1() (AlertListResponseData1, error) { + var body AlertListResponseData1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromAlertListResponseData1 overwrites any union data inside the AlertListResponse_Data as the provided AlertListResponseData1 +func (t *AlertListResponse_Data) FromAlertListResponseData1(v AlertListResponseData1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeAlertListResponseData1 performs a merge with any union data inside the AlertListResponse_Data, using the provided AlertListResponseData1 +func (t *AlertListResponse_Data) MergeAlertListResponseData1(v AlertListResponseData1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t AlertListResponse_Data) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *AlertListResponse_Data) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + +// AsAppListResponseData0 returns the union data inside the AppListResponse_Data as a AppListResponseData0 +func (t AppListResponse_Data) AsAppListResponseData0() (AppListResponseData0, error) { + var body AppListResponseData0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromAppListResponseData0 overwrites any union data inside the AppListResponse_Data as the provided AppListResponseData0 +func (t *AppListResponse_Data) FromAppListResponseData0(v AppListResponseData0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeAppListResponseData0 performs a merge with any union data inside the AppListResponse_Data, using the provided AppListResponseData0 +func (t *AppListResponse_Data) MergeAppListResponseData0(v AppListResponseData0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsAppListResponseData1 returns the union data inside the AppListResponse_Data as a AppListResponseData1 +func (t AppListResponse_Data) AsAppListResponseData1() (AppListResponseData1, error) { + var body AppListResponseData1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromAppListResponseData1 overwrites any union data inside the AppListResponse_Data as the provided AppListResponseData1 +func (t *AppListResponse_Data) FromAppListResponseData1(v AppListResponseData1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeAppListResponseData1 performs a merge with any union data inside the AppListResponse_Data, using the provided AppListResponseData1 +func (t *AppListResponse_Data) MergeAppListResponseData1(v AppListResponseData1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t AppListResponse_Data) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *AppListResponse_Data) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + +// AsDiskListResponseData0 returns the union data inside the DiskListResponse_Data as a DiskListResponseData0 +func (t DiskListResponse_Data) AsDiskListResponseData0() (DiskListResponseData0, error) { + var body DiskListResponseData0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromDiskListResponseData0 overwrites any union data inside the DiskListResponse_Data as the provided DiskListResponseData0 +func (t *DiskListResponse_Data) FromDiskListResponseData0(v DiskListResponseData0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeDiskListResponseData0 performs a merge with any union data inside the DiskListResponse_Data, using the provided DiskListResponseData0 +func (t *DiskListResponse_Data) MergeDiskListResponseData0(v DiskListResponseData0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsDiskListResponseData1 returns the union data inside the DiskListResponse_Data as a DiskListResponseData1 +func (t DiskListResponse_Data) AsDiskListResponseData1() (DiskListResponseData1, error) { + var body DiskListResponseData1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromDiskListResponseData1 overwrites any union data inside the DiskListResponse_Data as the provided DiskListResponseData1 +func (t *DiskListResponse_Data) FromDiskListResponseData1(v DiskListResponseData1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeDiskListResponseData1 performs a merge with any union data inside the DiskListResponse_Data, using the provided DiskListResponseData1 +func (t *DiskListResponse_Data) MergeDiskListResponseData1(v DiskListResponseData1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t DiskListResponse_Data) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *DiskListResponse_Data) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + +// AsGroupListResponseData0 returns the union data inside the GroupListResponse_Data as a GroupListResponseData0 +func (t GroupListResponse_Data) AsGroupListResponseData0() (GroupListResponseData0, error) { + var body GroupListResponseData0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromGroupListResponseData0 overwrites any union data inside the GroupListResponse_Data as the provided GroupListResponseData0 +func (t *GroupListResponse_Data) FromGroupListResponseData0(v GroupListResponseData0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeGroupListResponseData0 performs a merge with any union data inside the GroupListResponse_Data, using the provided GroupListResponseData0 +func (t *GroupListResponse_Data) MergeGroupListResponseData0(v GroupListResponseData0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsGroupListResponseData1 returns the union data inside the GroupListResponse_Data as a GroupListResponseData1 +func (t GroupListResponse_Data) AsGroupListResponseData1() (GroupListResponseData1, error) { + var body GroupListResponseData1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromGroupListResponseData1 overwrites any union data inside the GroupListResponse_Data as the provided GroupListResponseData1 +func (t *GroupListResponse_Data) FromGroupListResponseData1(v GroupListResponseData1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeGroupListResponseData1 performs a merge with any union data inside the GroupListResponse_Data, using the provided GroupListResponseData1 +func (t *GroupListResponse_Data) MergeGroupListResponseData1(v GroupListResponseData1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t GroupListResponse_Data) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *GroupListResponse_Data) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + +// AsIpListResponseData0 returns the union data inside the IpListResponse_Data as a IpListResponseData0 +func (t IpListResponse_Data) AsIpListResponseData0() (IpListResponseData0, error) { + var body IpListResponseData0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromIpListResponseData0 overwrites any union data inside the IpListResponse_Data as the provided IpListResponseData0 +func (t *IpListResponse_Data) FromIpListResponseData0(v IpListResponseData0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeIpListResponseData0 performs a merge with any union data inside the IpListResponse_Data, using the provided IpListResponseData0 +func (t *IpListResponse_Data) MergeIpListResponseData0(v IpListResponseData0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsIpListResponseData1 returns the union data inside the IpListResponse_Data as a IpListResponseData1 +func (t IpListResponse_Data) AsIpListResponseData1() (IpListResponseData1, error) { + var body IpListResponseData1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromIpListResponseData1 overwrites any union data inside the IpListResponse_Data as the provided IpListResponseData1 +func (t *IpListResponse_Data) FromIpListResponseData1(v IpListResponseData1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeIpListResponseData1 performs a merge with any union data inside the IpListResponse_Data, using the provided IpListResponseData1 +func (t *IpListResponse_Data) MergeIpListResponseData1(v IpListResponseData1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t IpListResponse_Data) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *IpListResponse_Data) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + // AsListResponseData0 returns the union data inside the ListResponse_Data as a ListResponseData0 func (t ListResponse_Data) AsListResponseData0() (ListResponseData0, error) { var body ListResponseData0 @@ -3186,3 +3896,127 @@ func (t *ListResponse_Data) UnmarshalJSON(b []byte) error { err := t.union.UnmarshalJSON(b) return err } + +// AsNodeListResponseData0 returns the union data inside the NodeListResponse_Data as a NodeListResponseData0 +func (t NodeListResponse_Data) AsNodeListResponseData0() (NodeListResponseData0, error) { + var body NodeListResponseData0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromNodeListResponseData0 overwrites any union data inside the NodeListResponse_Data as the provided NodeListResponseData0 +func (t *NodeListResponse_Data) FromNodeListResponseData0(v NodeListResponseData0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeNodeListResponseData0 performs a merge with any union data inside the NodeListResponse_Data, using the provided NodeListResponseData0 +func (t *NodeListResponse_Data) MergeNodeListResponseData0(v NodeListResponseData0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsNodeListResponseData1 returns the union data inside the NodeListResponse_Data as a NodeListResponseData1 +func (t NodeListResponse_Data) AsNodeListResponseData1() (NodeListResponseData1, error) { + var body NodeListResponseData1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromNodeListResponseData1 overwrites any union data inside the NodeListResponse_Data as the provided NodeListResponseData1 +func (t *NodeListResponse_Data) FromNodeListResponseData1(v NodeListResponseData1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeNodeListResponseData1 performs a merge with any union data inside the NodeListResponse_Data, using the provided NodeListResponseData1 +func (t *NodeListResponse_Data) MergeNodeListResponseData1(v NodeListResponseData1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t NodeListResponse_Data) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *NodeListResponse_Data) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + +// AsServiceListResponseData0 returns the union data inside the ServiceListResponse_Data as a ServiceListResponseData0 +func (t ServiceListResponse_Data) AsServiceListResponseData0() (ServiceListResponseData0, error) { + var body ServiceListResponseData0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromServiceListResponseData0 overwrites any union data inside the ServiceListResponse_Data as the provided ServiceListResponseData0 +func (t *ServiceListResponse_Data) FromServiceListResponseData0(v ServiceListResponseData0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeServiceListResponseData0 performs a merge with any union data inside the ServiceListResponse_Data, using the provided ServiceListResponseData0 +func (t *ServiceListResponse_Data) MergeServiceListResponseData0(v ServiceListResponseData0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsServiceListResponseData1 returns the union data inside the ServiceListResponse_Data as a ServiceListResponseData1 +func (t ServiceListResponse_Data) AsServiceListResponseData1() (ServiceListResponseData1, error) { + var body ServiceListResponseData1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromServiceListResponseData1 overwrites any union data inside the ServiceListResponse_Data as the provided ServiceListResponseData1 +func (t *ServiceListResponse_Data) FromServiceListResponseData1(v ServiceListResponseData1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeServiceListResponseData1 performs a merge with any union data inside the ServiceListResponse_Data, using the provided ServiceListResponseData1 +func (t *ServiceListResponse_Data) MergeServiceListResponseData1(v ServiceListResponseData1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t ServiceListResponse_Data) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *ServiceListResponse_Data) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} From 872f57a8f7810487cc66f070ac145e3328361294 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Wed, 16 Sep 2026 16:38:38 +0200 Subject: [PATCH 04/61] Clear node datetime columns instead of writing an empty string --- cdb/db_nodes.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/cdb/db_nodes.go b/cdb/db_nodes.go index 5b80d435..284d25b8 100644 --- a/cdb/db_nodes.go +++ b/cdb/db_nodes.go @@ -754,12 +754,27 @@ func (oDb *DB) UpdateNodeFields(ctx context.Context, nodeID string, fields map[s "serial": true, "sp_version": true, "team_integ": true, "team_support": true, "updated": true, } + // Datetime columns reject the empty string, and one bad value fails the whole + // UPDATE: clearing a date would silently discard every other field of the same + // request. An empty value clears the column instead. + datetime := map[string]bool{ + "warranty_end": true, "maintenance_end": true, "snooze_till": true, + "node_frozen_at": true, "last_boot": true, "last_comm": true, + "hw_obs_warn_date": true, "hw_obs_alert_date": true, + "os_obs_warn_date": true, "os_obs_alert_date": true, + } setClauses := []string{"updated = NOW()"} args := []any{} for col, val := range fields { if !allowed[col] { continue } + if datetime[col] { + if s, ok := val.(string); ok && s == "" { + setClauses = append(setClauses, col+" = NULL") + continue + } + } setClauses = append(setClauses, col+" = ?") args = append(args, val) } From 981c1d071995137274161422829e7abfe549eafe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Wed, 16 Sep 2026 16:40:57 +0200 Subject: [PATCH 05/61] Fix : Guard NotifyTableChangeWithData against a nil event publisher --- cdb/session.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cdb/session.go b/cdb/session.go index 6cb230cb..3215be40 100644 --- a/cdb/session.go +++ b/cdb/session.go @@ -38,6 +38,12 @@ func (t *Session) NotifyChanges(ctx context.Context) error { } func (t *Session) NotifyTableChangeWithData(ctx context.Context, tableName string, data map[string]any) error { + // Same guard as NotifyChanges: the server component creates its session with a + // nil publisher, and dereferencing it here panicked the request after the write + // had already been committed. + if t.ev == nil { + return fmt.Errorf("NotifyTableChangeWithData: eventPublisher is not configured") + } if err := t.ev.EventPublish(tableName+"_change", data); err != nil { return fmt.Errorf("EventPublish send %s: %w", tableName, err) } From c70eb6c773fa957cc7ddc47b06c86ba348b83bdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Wed, 16 Sep 2026 16:44:33 +0200 Subject: [PATCH 06/61] Store node boolean fields as the "T"/"F" strings --- server/handlers/node_fields.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/server/handlers/node_fields.go b/server/handlers/node_fields.go index 4e272531..ba072ba8 100644 --- a/server/handlers/node_fields.go +++ b/server/handlers/node_fields.go @@ -92,7 +92,15 @@ func (f nodeBodyFields) toFields() map[string]any { } setBool := func(key string, v *bool) { if v != nil { - m[key] = *v + // These columns are varchar(1) holding the collector's "T"/"F" + // convention: alertd matches notifications="T" OR NULL. Writing a Go + // bool stores "1"/"0", which matches neither and silently disables + // notifications for the node. + if *v { + m[key] = "T" + } else { + m[key] = "F" + } } } setStr("nodename", f.Nodename) From 9f98e98fbfd877b22bc95b63568781657ab2bfc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Thu, 17 Sep 2026 10:44:39 +0200 Subject: [PATCH 07/61] Fix the node network prio column name in the net_prio prop and expose the node and service names on the alert endpoints --- server/handlers/props_mapping.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/server/handlers/props_mapping.go b/server/handlers/props_mapping.go index e2abde60..544800f0 100644 --- a/server/handlers/props_mapping.go +++ b/server/handlers/props_mapping.go @@ -258,7 +258,7 @@ var propsMapping = map[string]propMapping{ "net_begin": {SQLExpr: "COALESCE(net_begin, '') AS net_begin", Kind: "string"}, "net_end": {SQLExpr: "COALESCE(net_end, '') AS net_end", Kind: "string"}, "net_pvid": {SQLExpr: "COALESCE(net_pvid, '') AS net_pvid", Kind: "string"}, - "net_prio": {SQLExpr: "COALESCE(net_prio, 0) AS net_prio", Kind: "int64"}, + "net_prio": {SQLExpr: "COALESCE(prio, 0) AS net_prio", Kind: "int64"}, "net_comment": {SQLExpr: "COALESCE(net_comment, '') AS net_comment", Kind: "string"}, "net_team_responsible": {SQLExpr: "COALESCE(net_team_responsible, '') AS net_team_responsible", Kind: "string"}, }, @@ -642,6 +642,12 @@ var propsMapping = map[string]propMapping{ "dash_env": colStr(schema.DashboardDashEnv), "dash_instance": colStr(schema.DashboardDashInstance), }, + // A dashboard entry points at a node or a service by id only. The names live + // in the joined tables, as in the historical collector's own alert query. + Joins: map[string]JoinDef{ + "nodes": {MappingKey: "node"}, + "services": {MappingKey: "service"}, + }, }, "check": { Available: []string{ From 71bdd7a525c5449927f2684e67ab7d06676377b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Thu, 17 Sep 2026 10:46:58 +0200 Subject: [PATCH 08/61] Forward the authenticated user id to the list endpoint --- cdb/list_params.go | 22 ++++++++++++++++++++-- server/handlers/handle_list.go | 11 +++++++++++ server/handlers/resolve.go | 15 +++++++++++++++ util/logkey/main.go | 1 + 4 files changed, 47 insertions(+), 2 deletions(-) diff --git a/cdb/list_params.go b/cdb/list_params.go index 2ba64183..d37806d2 100644 --- a/cdb/list_params.go +++ b/cdb/list_params.go @@ -5,8 +5,15 @@ import "strings" // ListParams bundles the standard query parameters shared by all list endpoints. // Groups and IsManager encode the caller's access control context. type ListParams struct { - Groups []string - IsManager bool + Groups []string + IsManager bool + + // UserID is the authenticated user's auth_user.id, set only by the endpoints + // whose access control references the caller's identity rather than just its + // groups. Nil when the caller is not a user (node credentials) or when the + // endpoint does not need it. + UserID *int64 + Limit int Offset int Props []string @@ -16,6 +23,17 @@ type ListParams struct { GroupBy []string } +// HasGroup reports whether the caller belongs to the named group. Use it for the +// privileges that are not covered by IsManager, which only tracks "Manager". +func (p ListParams) HasGroup(role string) bool { + for _, g := range p.Groups { + if g == role { + return true + } + } + return false +} + func (p ListParams) OrderByClause(defaultClause string) string { if len(p.OrderBy) == 0 { return "ORDER BY " + defaultClause diff --git a/server/handlers/handle_list.go b/server/handlers/handle_list.go index c6d5d4f0..93b816a2 100644 --- a/server/handlers/handle_list.go +++ b/server/handlers/handle_list.go @@ -24,6 +24,11 @@ type listEndpointParams struct { stats *server.InQueryStats orderby *server.InQueryOrderby groupby *server.InQueryGroupby + + // withUserID asks for the authenticated user's id to be forwarded in + // cdb.ListParams. Set it only on the endpoints whose access control + // references the caller's identity and not just its groups. + withUserID bool } // handleList implements the common pipeline for all list endpoints: @@ -78,6 +83,9 @@ func (a *Api) handleList( OrderBy: query.OrderBy, GroupBy: query.GroupBy, } + if p.withUserID { + dbParams.UserID = authUserID(c) + } items, err := fetch(c.Request().Context(), dbParams) if err != nil { @@ -126,6 +134,9 @@ func (a *Api) handleItem( Props: query.Props, SelectExprs: selectExprs, } + if p.withUserID { + dbParams.UserID = authUserID(c) + } items, err := fetch(c.Request().Context(), dbParams) if err != nil { diff --git a/server/handlers/resolve.go b/server/handlers/resolve.go index 40437dc1..f55ac331 100644 --- a/server/handlers/resolve.go +++ b/server/handlers/resolve.go @@ -15,6 +15,21 @@ import ( "github.com/opensvc/oc3/xauth" ) +// authUserID returns the authenticated user's auth_user.id, or nil when the +// request is not authenticated as a user (node credentials, public path) or the +// id does not parse. +func authUserID(c echo.Context) *int64 { + user := UserInfoFromContext(c) + if user == nil { + return nil + } + id, err := strconv.ParseInt(user.GetExtensions().Get(xauth.XUserID), 10, 64) + if err != nil { + return nil + } + return &id +} + // resolveUserGroupIDs returns the group ids the authenticated user belongs to. func (a *Api) resolveUserGroupIDs(c echo.Context, log *slog.Logger) ([]int64, error) { ctx := c.Request().Context() diff --git a/util/logkey/main.go b/util/logkey/main.go index d50a937b..965e2c65 100644 --- a/util/logkey/main.go +++ b/util/logkey/main.go @@ -22,4 +22,5 @@ const ( StatusCode = "status_code" TagID = "tag_id" URI = "uri" + UserID = "user_id" ) From 6b0a5ea4cb0dead05d7e6d038931f3d9c36d5cb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Thu, 17 Sep 2026 10:48:38 +0200 Subject: [PATCH 09/61] Port the /users and /users/{user_id}/prefs endpoints --- cdb/db_users.go | 195 ++++++++++ server/api.yaml | 238 ++++++++++++ server/codegen_server_gen.go | 584 +++++++++++++++++++---------- server/codegen_type_gen.go | 176 +++++++++ server/handlers/get_user.go | 21 ++ server/handlers/get_user_prefs.go | 44 +++ server/handlers/get_users.go | 21 ++ server/handlers/post_user_prefs.go | 88 +++++ 8 files changed, 1178 insertions(+), 189 deletions(-) create mode 100644 server/handlers/get_user.go create mode 100644 server/handlers/get_user_prefs.go create mode 100644 server/handlers/get_users.go create mode 100644 server/handlers/post_user_prefs.go diff --git a/cdb/db_users.go b/cdb/db_users.go index 05185376..6678bb61 100644 --- a/cdb/db_users.go +++ b/cdb/db_users.go @@ -5,8 +5,203 @@ import ( "database/sql" "errors" "fmt" + "strconv" + "strings" ) +// usersAuthClause returns the WHERE fragment restricting a query on auth_user to +// the users the caller may see, mirroring allowed_user_ids_q() of the python +// collector (init/models/rest/lib_users.py:11). +// +// Manager and UserManager see every user. Anybody else sees the users sharing +// one of its organisational groups — the non-privilege groups it belongs to, +// excluding "UnaffectedProjects" (user_org_group_ids(), init/models/auth.py:380) +// — plus itself. The target membership ignores the "Everybody" group, which +// holds all users and would defeat the restriction. +func usersAuthClause(p ListParams) (string, []any) { + if p.IsManager || p.HasGroup("UserManager") { + return "auth_user.id > 0", nil + } + if p.UserID == nil { + // Not authenticated as a user: no organisational group, and no self. + return "1=0", nil + } + const clause = `(auth_user.id IN ( + SELECT peer.user_id + FROM auth_membership peer + JOIN auth_group peer_group ON peer_group.id = peer.group_id + WHERE peer_group.role != 'Everybody' + AND peer.group_id IN ( + SELECT own_group.id + FROM auth_group own_group + JOIN auth_membership own ON own.group_id = own_group.id + WHERE own.user_id = ? + AND own_group.privilege = 'F' + AND own_group.role != 'UnaffectedProjects' + ) + ) OR auth_user.id = ?)` + return clause, []any{*p.UserID, *p.UserID} +} + +// GetUsers lists the users visible to the caller. +func (oDb *DB) GetUsers(ctx context.Context, p ListParams) ([]map[string]any, error) { + if len(p.SelectExprs) == 0 { + return nil, fmt.Errorf("getUsers: no select expressions") + } + authClause, args := usersAuthClause(p) + query := "SELECT " + strings.Join(p.SelectExprs, ", ") + + " FROM auth_user WHERE " + authClause + if gb := p.GroupByClause(""); gb != "" { + query += " " + gb + } + query += " " + p.OrderByClause("auth_user.email, auth_user.id") + query, args = appendLimitOffset(query, args, p.Limit, p.Offset) + + rows, err := oDb.DB.QueryContext(ctx, query, args...) + if err != nil { + return nil, fmt.Errorf("getUsers: %w", err) + } + defer func() { _ = rows.Close() }() + + return scanRowsToMaps(rows, p.Props, p.TypeHints) +} + +// GetUser fetches a single user visible to the caller, identified the way +// user_id_q() does — see userIdentClause. +func (oDb *DB) GetUser(ctx context.Context, idOrEmail string, p ListParams) ([]map[string]any, error) { + if len(p.SelectExprs) == 0 { + return nil, fmt.Errorf("getUser: no select expressions") + } + + identClause, identArgs, ok := userIdentClause(idOrEmail, p.UserID) + if !ok { + return nil, nil + } + + authClause, args := usersAuthClause(p) + query := "SELECT " + strings.Join(p.SelectExprs, ", ") + + " FROM auth_user WHERE " + authClause + " AND " + identClause + args = append(args, identArgs...) + if gb := p.GroupByClause(""); gb != "" { + query += " " + gb + } + query += " " + p.OrderByClause("auth_user.email, auth_user.id") + query, args = appendLimitOffset(query, args, p.Limit, p.Offset) + + rows, err := oDb.DB.QueryContext(ctx, query, args...) + if err != nil { + return nil, fmt.Errorf("getUser: %w", err) + } + defer func() { _ = rows.Close() }() + + return scanRowsToMaps(rows, p.Props, p.TypeHints) +} + +// userIdentClause returns the WHERE fragment selecting the user designated by +// idOrEmail, mirroring user_id_q() (init/models/rest/lib_users.py:25): an email +// when the identifier contains "@", the caller itself for "self", an +// auth_user.id otherwise. +// +// ok is false when the identifier cannot designate anybody: "self" without a +// caller identity, or a value that is neither an email nor a number. The python +// code compares such a value to the numeric id column, which never matches. +func userIdentClause(idOrEmail string, callerID *int64) (clause string, args []any, ok bool) { + switch { + case strings.Contains(idOrEmail, "@"): + return "auth_user.email = ?", []any{idOrEmail}, true + case idOrEmail == "self": + if callerID == nil { + return "", nil, false + } + return "auth_user.id = ?", []any{*callerID}, true + default: + id, err := strconv.ParseInt(idOrEmail, 10, 64) + if err != nil { + return "", nil, false + } + return "auth_user.id = ?", []any{id}, true + } +} + +// UserIDForPrefs resolves idOrEmail to an auth_user.id the caller is allowed to +// see. found is false when no such user exists or it is not visible, which +// rest_post_user_prefs answers with a 403 (init/models/rest/api_users.py:141). +func (oDb *DB) UserIDForPrefs(ctx context.Context, idOrEmail string, p ListParams) (int64, bool, error) { + identClause, identArgs, ok := userIdentClause(idOrEmail, p.UserID) + if !ok { + return 0, false, nil + } + authClause, args := usersAuthClause(p) + query := "SELECT auth_user.id FROM auth_user WHERE " + authClause + " AND " + identClause + " LIMIT 1" + args = append(args, identArgs...) + + var id sql.NullInt64 + err := oDb.DB.QueryRowContext(ctx, query, args...).Scan(&id) + switch { + case errors.Is(err, sql.ErrNoRows): + return 0, false, nil + case err != nil: + return 0, false, fmt.Errorf("userIDForPrefs: %w", err) + } + return id.Int64, id.Valid, nil +} + +// UserPrefs returns the raw preferences document of the user designated by +// idOrEmail, as stored in user_prefs.prefs. +// +// found is false when the user is unknown, not visible to the caller, has no +// user_prefs row, or a NULL document — rest_get_user_prefs returns an empty +// object for all of these alike (init/models/rest/api_users.py:112). +func (oDb *DB) UserPrefs(ctx context.Context, idOrEmail string, p ListParams) (string, bool, error) { + identClause, identArgs, ok := userIdentClause(idOrEmail, p.UserID) + if !ok { + return "", false, nil + } + authClause, args := usersAuthClause(p) + query := "SELECT user_prefs.prefs FROM auth_user" + + " JOIN user_prefs ON user_prefs.user_id = auth_user.id" + + " WHERE " + authClause + " AND " + identClause + " LIMIT 1" + args = append(args, identArgs...) + + var prefs sql.NullString + err := oDb.DB.QueryRowContext(ctx, query, args...).Scan(&prefs) + switch { + case errors.Is(err, sql.ErrNoRows): + return "", false, nil + case err != nil: + return "", false, fmt.Errorf("userPrefs: %w", err) + } + return prefs.String, prefs.Valid, nil +} + +// SaveUserPrefs stores the preferences document of a user, updating the existing +// user_prefs row or inserting one. +// +// The select-then-write mirrors web2py's update_or_insert: user_prefs.user_id +// carries no unique index, so ON DUPLICATE KEY cannot be relied upon. Call it on +// a transaction-scoped *DB so the read and the write cannot interleave. +func (oDb *DB) SaveUserPrefs(ctx context.Context, userID int64, prefs string) error { + const selectQuery = "SELECT id FROM user_prefs WHERE user_id = ? LIMIT 1" + var rowID sql.NullInt64 + err := oDb.DB.QueryRowContext(ctx, selectQuery, userID).Scan(&rowID) + switch { + case errors.Is(err, sql.ErrNoRows): + const insertQuery = "INSERT INTO user_prefs (user_id, prefs) VALUES (?, ?)" + if _, err := oDb.DB.ExecContext(ctx, insertQuery, userID, prefs); err != nil { + return fmt.Errorf("saveUserPrefs insert: %w", err) + } + case err != nil: + return fmt.Errorf("saveUserPrefs select: %w", err) + default: + const updateQuery = "UPDATE user_prefs SET prefs = ? WHERE id = ?" + if _, err := oDb.DB.ExecContext(ctx, updateQuery, prefs, rowID.Int64); err != nil { + return fmt.Errorf("saveUserPrefs update: %w", err) + } + } + oDb.SetChange("user_prefs") + return nil +} + // return the default app for a user // if the user belongs to several apps, return the first one in alphabetical order func (oDb *DB) UserDefaultApp(ctx context.Context, userID *int64) (string, error) { diff --git a/server/api.yaml b/server/api.yaml index 9eaf4930..80840771 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -7150,6 +7150,162 @@ paths: - basicAuth: [ ] - bearerAuth: [ ] + /users: + get: + operationId: GetUsers + description: | + List existing users. Managers and UserManager can see all users; other + users only see the users sharing one of their organisational groups, + plus themselves. + parameters: + - $ref: '#/components/parameters/inQueryProps' + - $ref: '#/components/parameters/inQueryLimit' + - $ref: '#/components/parameters/inQueryOffset' + - $ref: '#/components/parameters/inQueryMeta' + - $ref: '#/components/parameters/inQueryStats' + - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryGroupby' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/UserListResponse' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /users/{user_id}: + get: + operationId: GetUser + description: | + Display user properties. Managers and UserManager can see all users; + other users only see the users sharing one of their organisational + groups, plus themselves. + parameters: + - in: path + name: user_id + required: true + description: | + User identifier: auth_user.id, the user email when it contains an + "@", or "self" for the authenticated user. + schema: + type: string + - $ref: '#/components/parameters/inQueryProps' + - $ref: '#/components/parameters/inQueryLimit' + - $ref: '#/components/parameters/inQueryOffset' + - $ref: '#/components/parameters/inQueryMeta' + - $ref: '#/components/parameters/inQueryStats' + - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryGroupby' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/UserListResponse' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /users/{user_id}/prefs: + get: + operationId: GetUserPrefs + description: | + Fetch the user preferences: visible columns, column filters, live mode + enabled flag, hidden group entries, ... + + Returns an empty object when the user has no preferences stored, and + also when the user does not exist or is not visible to the caller. + parameters: + - in: path + name: user_id + required: true + description: | + User identifier: auth_user.id, the user email when it contains an + "@", or "self" for the authenticated user. + schema: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/UserPrefsResponse' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + post: + operationId: PostUserPrefs + description: | + Save the user preferences: visible columns, column filters, live mode + enabled flag, hidden group entries, ... + parameters: + - in: path + name: user_id + required: true + description: | + User identifier: auth_user.id, the user email when it contains an + "@", or "self" for the authenticated user. + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - data + properties: + data: + type: object + additionalProperties: true + description: The preferences object, stored verbatim. + uuid: + type: string + description: | + Opaque sender identifier echoed in the user_prefs_change + event, so a client can ignore its own update. + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/InfoResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + /version: get: operationId: GetVersion @@ -7805,6 +7961,88 @@ components: meta: $ref: '#/components/schemas/ListMeta' + UserRow: + type: object + description: | + A user of the users list. `password` and `registration_key` are never + returned. The boolean-like columns (`email_notifications`, + `im_notifications`, `lock_filter`) carry the collector's "T"/"F" + convention, and the delay and quota columns are returned as strings. + Every property is optional: the `props` query parameter selects which + columns the server returns. + properties: + id: + type: integer + username: + type: string + email: + type: string + first_name: + type: string + last_name: + type: string + phone_work: + type: string + im_type: + type: string + im_username: + type: string + email_notifications: + type: string + im_notifications: + type: string + email_log_level: + type: string + im_log_level: + type: string + email_notifications_delay: + type: string + im_notifications_delay: + type: string + lock_filter: + type: string + registration_id: + type: string + reset_password_key: + type: string + quota_app: + type: string + quota_org_group: + type: string + quota_docker_registries: + type: string + + UserPrefsResponse: + type: object + required: + - data + description: | + The stored preferences, as saved by POST /users/{user_id}/prefs. The + collector never interprets the content; an empty object means "no + preferences stored", "user unknown" or "user not visible" alike. + properties: + data: + type: object + additionalProperties: true + + UserListResponse: + type: object + required: + - data + properties: + data: + oneOf: + - type: array + items: + $ref: '#/components/schemas/UserRow' + - type: object + additionalProperties: + type: object + additionalProperties: + type: integer + meta: + $ref: '#/components/schemas/ListMeta' + ListResponse: type: object required: diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index a070a005..6fcdaffe 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -564,6 +564,18 @@ type ServerInterface interface { // (POST /tags/{tag_id}/services/{svc_id}) PostTagService(ctx echo.Context, tagId int, svcId string) error + // (GET /users) + GetUsers(ctx echo.Context, params GetUsersParams) error + + // (GET /users/{user_id}) + GetUser(ctx echo.Context, userId string, params GetUserParams) error + + // (GET /users/{user_id}/prefs) + GetUserPrefs(ctx echo.Context, userId string) error + + // (POST /users/{user_id}/prefs) + PostUserPrefs(ctx echo.Context, userId string) error + // (GET /version) GetVersion(ctx echo.Context) error } @@ -8556,6 +8568,181 @@ func (w *ServerInterfaceWrapper) PostTagService(ctx echo.Context) error { return err } +// GetUsers converts echo context to params. +func (w *ServerInterfaceWrapper) GetUsers(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetUsersParams + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // ------------- Optional query parameter "limit" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) + } + + // ------------- Optional query parameter "offset" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) + } + + // ------------- Optional query parameter "meta" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) + } + + // ------------- Optional query parameter "stats" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) + } + + // ------------- Optional query parameter "orderby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) + } + + // ------------- Optional query parameter "groupby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetUsers(ctx, params) + return err +} + +// GetUser converts echo context to params. +func (w *ServerInterfaceWrapper) GetUser(ctx echo.Context) error { + var err error + // ------------- Path parameter "user_id" ------------- + var userId string + + err = runtime.BindStyledParameterWithOptions("simple", "user_id", ctx.Param("user_id"), &userId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter user_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetUserParams + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // ------------- Optional query parameter "limit" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) + } + + // ------------- Optional query parameter "offset" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) + } + + // ------------- Optional query parameter "meta" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) + } + + // ------------- Optional query parameter "stats" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) + } + + // ------------- Optional query parameter "orderby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) + } + + // ------------- Optional query parameter "groupby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetUser(ctx, userId, params) + return err +} + +// GetUserPrefs converts echo context to params. +func (w *ServerInterfaceWrapper) GetUserPrefs(ctx echo.Context) error { + var err error + // ------------- Path parameter "user_id" ------------- + var userId string + + err = runtime.BindStyledParameterWithOptions("simple", "user_id", ctx.Param("user_id"), &userId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter user_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetUserPrefs(ctx, userId) + return err +} + +// PostUserPrefs converts echo context to params. +func (w *ServerInterfaceWrapper) PostUserPrefs(ctx echo.Context) error { + var err error + // ------------- Path parameter "user_id" ------------- + var userId string + + err = runtime.BindStyledParameterWithOptions("simple", "user_id", ctx.Param("user_id"), &userId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter user_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostUserPrefs(ctx, userId) + return err +} + // GetVersion converts echo context to params. func (w *ServerInterfaceWrapper) GetVersion(ctx echo.Context) error { var err error @@ -8793,6 +8980,10 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.GET(options.BaseURL+"/tags/:tag_id/services", wrapper.GetTagServices, options.OperationMiddlewares["GetTagServices"]...) router.DELETE(options.BaseURL+"/tags/:tag_id/services/:svc_id", wrapper.DeleteTagService, options.OperationMiddlewares["DeleteTagService"]...) router.POST(options.BaseURL+"/tags/:tag_id/services/:svc_id", wrapper.PostTagService, options.OperationMiddlewares["PostTagService"]...) + router.GET(options.BaseURL+"/users", wrapper.GetUsers, options.OperationMiddlewares["GetUsers"]...) + router.GET(options.BaseURL+"/users/:user_id", wrapper.GetUser, options.OperationMiddlewares["GetUser"]...) + router.GET(options.BaseURL+"/users/:user_id/prefs", wrapper.GetUserPrefs, options.OperationMiddlewares["GetUserPrefs"]...) + router.POST(options.BaseURL+"/users/:user_id/prefs", wrapper.PostUserPrefs, options.OperationMiddlewares["PostUserPrefs"]...) router.GET(options.BaseURL+"/version", wrapper.GetVersion, options.OperationMiddlewares["GetVersion"]...) } @@ -8802,195 +8993,210 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "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", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index 91336c21..84c9721d 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -466,6 +466,59 @@ type ServiceRow struct { Updated *string `json:"updated,omitempty"` } +// UserListResponse defines model for UserListResponse. +type UserListResponse struct { + Data UserListResponse_Data `json:"data"` + Meta *ListMeta `json:"meta,omitempty"` +} + +// UserListResponseData0 defines model for . +type UserListResponseData0 = []UserRow + +// UserListResponseData1 defines model for . +type UserListResponseData1 map[string]map[string]int + +// UserListResponse_Data defines model for UserListResponse.Data. +type UserListResponse_Data struct { + union json.RawMessage +} + +// UserPrefsResponse The stored preferences, as saved by POST /users/{user_id}/prefs. The +// collector never interprets the content; an empty object means "no +// preferences stored", "user unknown" or "user not visible" alike. +type UserPrefsResponse struct { + Data map[string]interface{} `json:"data"` +} + +// UserRow A user of the users list. `password` and `registration_key` are never +// returned. The boolean-like columns (`email_notifications`, +// `im_notifications`, `lock_filter`) carry the collector's "T"/"F" +// convention, and the delay and quota columns are returned as strings. +// Every property is optional: the `props` query parameter selects which +// columns the server returns. +type UserRow struct { + Email *string `json:"email,omitempty"` + EmailLogLevel *string `json:"email_log_level,omitempty"` + EmailNotifications *string `json:"email_notifications,omitempty"` + EmailNotificationsDelay *string `json:"email_notifications_delay,omitempty"` + FirstName *string `json:"first_name,omitempty"` + Id *int `json:"id,omitempty"` + ImLogLevel *string `json:"im_log_level,omitempty"` + ImNotifications *string `json:"im_notifications,omitempty"` + ImNotificationsDelay *string `json:"im_notifications_delay,omitempty"` + ImType *string `json:"im_type,omitempty"` + ImUsername *string `json:"im_username,omitempty"` + LastName *string `json:"last_name,omitempty"` + LockFilter *string `json:"lock_filter,omitempty"` + PhoneWork *string `json:"phone_work,omitempty"` + QuotaApp *string `json:"quota_app,omitempty"` + QuotaDockerRegistries *string `json:"quota_docker_registries,omitempty"` + QuotaOrgGroup *string `json:"quota_org_group,omitempty"` + RegistrationId *string `json:"registration_id,omitempty"` + ResetPasswordKey *string `json:"reset_password_key,omitempty"` + Username *string `json:"username,omitempty"` +} + // Version defines model for version. type Version struct { Version string `json:"version"` @@ -3360,6 +3413,64 @@ type PostTagServiceJSONBody struct { TagAttachData *string `json:"tag_attach_data,omitempty"` } +// GetUsersParams defines parameters for GetUsers. +type GetUsersParams struct { + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` + + // Limit The maximum number of entries to return. 0 means no limit. + Limit *InQueryLimit `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Skip the first entries of the data cursor. + Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` + + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` + + // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. + Stats *InQueryStats `form:"stats,omitempty" json:"stats,omitempty"` + + // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). + Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). + Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` +} + +// GetUserParams defines parameters for GetUser. +type GetUserParams struct { + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` + + // Limit The maximum number of entries to return. 0 means no limit. + Limit *InQueryLimit `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Skip the first entries of the data cursor. + Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` + + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` + + // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. + Stats *InQueryStats `form:"stats,omitempty" json:"stats,omitempty"` + + // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). + Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). + Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` +} + +// PostUserPrefsJSONBody defines parameters for PostUserPrefs. +type PostUserPrefsJSONBody struct { + // Data The preferences object, stored verbatim. + Data map[string]interface{} `json:"data"` + + // Uuid Opaque sender identifier echoed in the user_prefs_change + // event, so a client can ignore its own update. + Uuid *string `json:"uuid,omitempty"` +} + // PostActionsJSONRequestBody defines body for PostActions for application/json ContentType. type PostActionsJSONRequestBody PostActionsJSONBody @@ -3525,6 +3636,9 @@ type PostTagNodeJSONRequestBody PostTagNodeJSONBody // PostTagServiceJSONRequestBody defines body for PostTagService for application/json ContentType. type PostTagServiceJSONRequestBody PostTagServiceJSONBody +// PostUserPrefsJSONRequestBody defines body for PostUserPrefs for application/json ContentType. +type PostUserPrefsJSONRequestBody PostUserPrefsJSONBody + // AsAlertListResponseData0 returns the union data inside the AlertListResponse_Data as a AlertListResponseData0 func (t AlertListResponse_Data) AsAlertListResponseData0() (AlertListResponseData0, error) { var body AlertListResponseData0 @@ -4020,3 +4134,65 @@ func (t *ServiceListResponse_Data) UnmarshalJSON(b []byte) error { err := t.union.UnmarshalJSON(b) return err } + +// AsUserListResponseData0 returns the union data inside the UserListResponse_Data as a UserListResponseData0 +func (t UserListResponse_Data) AsUserListResponseData0() (UserListResponseData0, error) { + var body UserListResponseData0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromUserListResponseData0 overwrites any union data inside the UserListResponse_Data as the provided UserListResponseData0 +func (t *UserListResponse_Data) FromUserListResponseData0(v UserListResponseData0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeUserListResponseData0 performs a merge with any union data inside the UserListResponse_Data, using the provided UserListResponseData0 +func (t *UserListResponse_Data) MergeUserListResponseData0(v UserListResponseData0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsUserListResponseData1 returns the union data inside the UserListResponse_Data as a UserListResponseData1 +func (t UserListResponse_Data) AsUserListResponseData1() (UserListResponseData1, error) { + var body UserListResponseData1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromUserListResponseData1 overwrites any union data inside the UserListResponse_Data as the provided UserListResponseData1 +func (t *UserListResponse_Data) FromUserListResponseData1(v UserListResponseData1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeUserListResponseData1 performs a merge with any union data inside the UserListResponse_Data, using the provided UserListResponseData1 +func (t *UserListResponse_Data) MergeUserListResponseData1(v UserListResponseData1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t UserListResponse_Data) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *UserListResponse_Data) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} diff --git a/server/handlers/get_user.go b/server/handlers/get_user.go new file mode 100644 index 00000000..47621720 --- /dev/null +++ b/server/handlers/get_user.go @@ -0,0 +1,21 @@ +package serverhandlers + +import ( + "context" + + "github.com/labstack/echo/v4" + + "github.com/opensvc/oc3/cdb" + "github.com/opensvc/oc3/server" +) + +// GetUser handles GET /users/{user_id} +func (a *Api) GetUser(c echo.Context, userId string, params server.GetUserParams) error { + return a.handleItem(c, "GetUser", "user", "user_id", userId, listEndpointParams{ + props: params.Props, limit: params.Limit, offset: params.Offset, + meta: params.Meta, stats: params.Stats, orderby: params.Orderby, groupby: params.Groupby, + withUserID: true, + }, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetUser(ctx, userId, p) + }) +} diff --git a/server/handlers/get_user_prefs.go b/server/handlers/get_user_prefs.go new file mode 100644 index 00000000..d16e1d71 --- /dev/null +++ b/server/handlers/get_user_prefs.go @@ -0,0 +1,44 @@ +package serverhandlers + +import ( + "encoding/json" + "net/http" + + "github.com/labstack/echo/v4" + + "github.com/opensvc/oc3/cdb" + "github.com/opensvc/oc3/server" + "github.com/opensvc/oc3/util/echolog" + "github.com/opensvc/oc3/util/logkey" +) + +// GetUserPrefs handles GET /users/{user_id}/prefs +func (a *Api) GetUserPrefs(c echo.Context, userId string) error { + log := echolog.GetLogHandler(c, "GetUserPrefs") + ctx := c.Request().Context() + + log.Info("called", logkey.UserID, userId) + + raw, found, err := a.ODB.UserPrefs(ctx, userId, cdb.ListParams{ + Groups: UserGroupsFromContext(c), + IsManager: IsManager(c), + UserID: authUserID(c), + }) + if err != nil { + log.Error("cannot get user prefs", logkey.UserID, userId, logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot get user prefs") + } + + // An unknown user, a user the caller cannot see, a missing row and a stored + // document that does not parse all answer with an empty object, as the python + // handler does. + prefs := map[string]any{} + if found && raw != "" { + if err := json.Unmarshal([]byte(raw), &prefs); err != nil { + log.Warn("stored user prefs are not valid json", logkey.UserID, userId, logkey.Error, err) + prefs = map[string]any{} + } + } + + return c.JSON(http.StatusOK, server.UserPrefsResponse{Data: prefs}) +} diff --git a/server/handlers/get_users.go b/server/handlers/get_users.go new file mode 100644 index 00000000..5c058fc7 --- /dev/null +++ b/server/handlers/get_users.go @@ -0,0 +1,21 @@ +package serverhandlers + +import ( + "context" + + "github.com/labstack/echo/v4" + + "github.com/opensvc/oc3/cdb" + "github.com/opensvc/oc3/server" +) + +// GetUsers handles GET /users +func (a *Api) GetUsers(c echo.Context, params server.GetUsersParams) error { + return a.handleList(c, "GetUsers", "user", listEndpointParams{ + props: params.Props, limit: params.Limit, offset: params.Offset, + meta: params.Meta, stats: params.Stats, orderby: params.Orderby, groupby: params.Groupby, + withUserID: true, + }, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetUsers(ctx, p) + }) +} diff --git a/server/handlers/post_user_prefs.go b/server/handlers/post_user_prefs.go new file mode 100644 index 00000000..975483ec --- /dev/null +++ b/server/handlers/post_user_prefs.go @@ -0,0 +1,88 @@ +package serverhandlers + +import ( + "context" + "database/sql" + "encoding/json" + "net/http" + + "github.com/labstack/echo/v4" + + "github.com/opensvc/oc3/cdb" + "github.com/opensvc/oc3/server" + "github.com/opensvc/oc3/util/echolog" + "github.com/opensvc/oc3/util/logkey" +) + +// PostUserPrefs handles POST /users/{user_id}/prefs +func (a *Api) PostUserPrefs(c echo.Context, userId string) error { + log := echolog.GetLogHandler(c, "PostUserPrefs") + odb := a.ODB + ctx, cancel := context.WithTimeout(c.Request().Context(), a.SyncTimeout) + defer cancel() + + if !IsAuthByUser(c) { + return JSONProblemf(c, http.StatusUnauthorized, "user authentication required") + } + + var body server.PostUserPrefsJSONRequestBody + if err := c.Bind(&body); err != nil { + log.Error("invalid request body", logkey.Error, err) + return JSONProblem(c, http.StatusBadRequest, err.Error()) + } + if body.Data == nil { + return JSONProblemf(c, http.StatusBadRequest, "The 'data' key is mandatory") + } + + log.Info("called", logkey.UserID, userId) + + // The python handler answers 403 when the target user is unknown or not + // visible, without distinguishing the two. + targetID, found, err := odb.UserIDForPrefs(ctx, userId, cdb.ListParams{ + Groups: UserGroupsFromContext(c), + IsManager: IsManager(c), + UserID: authUserID(c), + }) + if err != nil { + log.Error("cannot resolve user", logkey.UserID, userId, logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot resolve user") + } + if !found { + return JSONProblemf(c, http.StatusForbidden, "Not authorized") + } + + prefs, err := json.Marshal(body.Data) + if err != nil { + log.Error("cannot encode prefs", logkey.UserID, userId, logkey.Error, err) + return JSONProblemf(c, http.StatusBadRequest, "cannot encode prefs") + } + + tx, markSuccess, endTx, err := odb.BeginTxWithControl(ctx, log, &sql.TxOptions{}) + if err != nil { + log.Error("cannot start transaction", logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot save user prefs") + } + defer endTx() + + if err := tx.SaveUserPrefs(ctx, targetID, string(prefs)); err != nil { + log.Error("cannot save user prefs", logkey.UserID, targetID, logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot save user prefs") + } + + markSuccess() + + var uuid string + if body.Uuid != nil { + uuid = *body.Uuid + } + // Publishes the "user_prefs_change" event the python handler sends through + // ws_send (init/models/rest/api_users.py:149). + if err := odb.Session.NotifyTableChangeWithData(ctx, "user_prefs", map[string]any{ + "user_id": targetID, + "uuid": uuid, + }); err != nil { + log.Error("cannot notify user prefs change", logkey.Error, err) + } + + return c.JSON(http.StatusOK, map[string]string{"info": "user prefs saved"}) +} From 3cee1b35d46558e7ea6c64ed1edeadcad06efd45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Thu, 17 Sep 2026 10:49:00 +0200 Subject: [PATCH 10/61] Expose the node and service names on the alert endpoints --- cdb/db_dashboard.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cdb/db_dashboard.go b/cdb/db_dashboard.go index c08a9c31..98a0805a 100644 --- a/cdb/db_dashboard.go +++ b/cdb/db_dashboard.go @@ -40,7 +40,9 @@ func (oDb *DB) GetAlerts(ctx context.Context, p ListParams) ([]map[string]any, e return nil, fmt.Errorf("getAlerts: no select expressions") } - query := "SELECT " + strings.Join(p.SelectExprs, ", ") + " FROM dashboard" + // Joined so that "nodes.nodename" and "services.svcname" can be selected: + // a dashboard row only carries the ids. + query := "SELECT " + strings.Join(p.SelectExprs, ", ") + " FROM dashboard LEFT JOIN nodes ON nodes.node_id = dashboard.node_id LEFT JOIN services ON services.svc_id = dashboard.svc_id" var args []any if gb := p.GroupByClause(""); gb != "" { query += " " + gb @@ -62,7 +64,7 @@ func (oDb *DB) GetAlert(ctx context.Context, id string, p ListParams) ([]map[str return nil, fmt.Errorf("getAlert: no select expressions") } - query := "SELECT " + strings.Join(p.SelectExprs, ", ") + " FROM dashboard WHERE dashboard.id = ?" + query := "SELECT " + strings.Join(p.SelectExprs, ", ") + " FROM dashboard LEFT JOIN nodes ON nodes.node_id = dashboard.node_id LEFT JOIN services ON services.svc_id = dashboard.svc_id WHERE dashboard.id = ?" args := []any{id} query += " " + p.OrderByClause("dashboard.id DESC") query, args = appendLimitOffset(query, args, p.Limit, p.Offset) From 63843bc2eb36072d0ac6dc936cae440257d2f631 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Thu, 24 Sep 2026 14:37:50 +0200 Subject: [PATCH 11/61] Ignore local tool settings The directory holds per-machine tool settings, which do not belong in the repository. The rule comes last, after the whitelist entries: the JSON exception would otherwise bring its settings file back. --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 0a33e5c7..5f5f4b33 100644 --- a/.gitignore +++ b/.gitignore @@ -13,4 +13,5 @@ !Makefile .idea core/version/version.go -.trash \ No newline at end of file +.trash +.claude From 03caa51e6c820387039c0270dc01634ac0b6daae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Thu, 24 Sep 2026 14:37:52 +0200 Subject: [PATCH 12/61] Stop the request after a denied permission check JSONProblemf returns nil once the problem response is written. The require* guards and the service resolvers returned its result, so their callers went on with the action after answering 401, 403 or 404. They now go through denyRequest, which returns errRequestDenied; echo leaves the already committed response untouched. resolveService also selects svc_id: the query builder refuses a query without selected columns, and the existence check failed with a 500. --- server/handlers/delete_tag.go | 4 ++-- server/handlers/post_filterset.go | 4 ++-- server/handlers/post_group.go | 4 ++-- server/handlers/post_obsolescence_setting.go | 4 ++-- server/handlers/problems.go | 17 ++++++++++++++++ server/handlers/resolve.go | 21 +++++++++++++------- 6 files changed, 39 insertions(+), 15 deletions(-) diff --git a/server/handlers/delete_tag.go b/server/handlers/delete_tag.go index 5c5a9941..07e5aa8d 100644 --- a/server/handlers/delete_tag.go +++ b/server/handlers/delete_tag.go @@ -84,10 +84,10 @@ func (a *Api) deleteTagCascade(c echo.Context, log *slog.Logger, ctx context.Con func requireTagManager(c echo.Context) error { if !IsAuthByUser(c) { - return JSONProblemf(c, http.StatusUnauthorized, "user authentication required") + return denyRequest(c, http.StatusUnauthorized, "user authentication required") } if !IsTagManager(c) { - return JSONProblemf(c, http.StatusForbidden, "TagManager privilege required") + return denyRequest(c, http.StatusForbidden, "TagManager privilege required") } return nil } diff --git a/server/handlers/post_filterset.go b/server/handlers/post_filterset.go index a0942926..de37020e 100644 --- a/server/handlers/post_filterset.go +++ b/server/handlers/post_filterset.go @@ -116,10 +116,10 @@ func (a *Api) postFiltersetUpdate(c echo.Context, log *slog.Logger, ctx context. func requireCompManager(c echo.Context) error { if !IsAuthByUser(c) { - return JSONProblemf(c, http.StatusUnauthorized, "user authentication required") + return denyRequest(c, http.StatusUnauthorized, "user authentication required") } if !IsCompManager(c) { - return JSONProblemf(c, http.StatusForbidden, "CompManager privilege required") + return denyRequest(c, http.StatusForbidden, "CompManager privilege required") } return nil } diff --git a/server/handlers/post_group.go b/server/handlers/post_group.go index a0abd95a..0b4e1406 100644 --- a/server/handlers/post_group.go +++ b/server/handlers/post_group.go @@ -19,12 +19,12 @@ import ( func requireGroupPrivilege(c echo.Context, privilege *string) error { if privilege != nil && (*privilege == "T" || *privilege == "true") { if !IsManager(c) { - return JSONProblemf(c, http.StatusForbidden, "Manager privilege required") + return denyRequest(c, http.StatusForbidden, "Manager privilege required") } return nil } if !IsGroupManager(c) { - return JSONProblemf(c, http.StatusForbidden, "GroupManager privilege required") + return denyRequest(c, http.StatusForbidden, "GroupManager privilege required") } return nil } diff --git a/server/handlers/post_obsolescence_setting.go b/server/handlers/post_obsolescence_setting.go index eff41de2..fb6912e5 100644 --- a/server/handlers/post_obsolescence_setting.go +++ b/server/handlers/post_obsolescence_setting.go @@ -19,10 +19,10 @@ import ( func requireObsManager(c echo.Context) error { if !IsAuthByUser(c) { - return JSONProblemf(c, http.StatusUnauthorized, "user authentication required") + return denyRequest(c, http.StatusUnauthorized, "user authentication required") } if !IsObsManager(c) { - return JSONProblemf(c, http.StatusForbidden, "ObsManager privilege required") + return denyRequest(c, http.StatusForbidden, "ObsManager privilege required") } return nil } diff --git a/server/handlers/problems.go b/server/handlers/problems.go index dd1f98ff..328481f2 100644 --- a/server/handlers/problems.go +++ b/server/handlers/problems.go @@ -1,6 +1,7 @@ package serverhandlers import ( + "errors" "fmt" "net/http" @@ -9,6 +10,22 @@ import ( "github.com/opensvc/oc3/server" ) +// errRequestDenied is returned by the require* guards after they have written the +// problem response. JSONProblemf returns nil once the response is written, so a +// guard returning its result would let the caller go on with the denied action: +// callers stop on a non-nil error, and echo's error handler leaves the already +// committed response untouched. +var errRequestDenied = errors.New("request denied, problem response sent") + +// denyRequest writes the problem response and returns errRequestDenied, or the +// error that prevented writing the response. +func denyRequest(ctx echo.Context, code int, format string, args ...any) error { + if err := JSONProblemf(ctx, code, format, args...); err != nil { + return err + } + return errRequestDenied +} + func JSONProblemf(ctx echo.Context, code int, format string, args ...any) error { return JSONProblem(ctx, code, fmt.Sprintf(format, args...)) } diff --git a/server/handlers/resolve.go b/server/handlers/resolve.go index f55ac331..ac6d3f9a 100644 --- a/server/handlers/resolve.go +++ b/server/handlers/resolve.go @@ -66,31 +66,38 @@ func (a *Api) resolveNode(c echo.Context, log *slog.Logger, nodeId string) (*cdb // resolveServiceRow resolves a service by svc_id or name func (a *Api) resolveServiceRow(c echo.Context, log *slog.Logger, ctx context.Context, svcId string) (*cdb.DBService, error) { if svcId == "" { - return nil, JSONProblemf(c, http.StatusBadRequest, "invalid svc_id: ''") + return nil, denyRequest(c, http.StatusBadRequest, "invalid svc_id: ''") } svc, err := a.ODB.ServiceBySvcIDOrName(ctx, svcId) if err != nil { log.Error("cannot resolve service", "svc_id", svcId, logkey.Error, err) - return nil, JSONProblemf(c, http.StatusInternalServerError, "cannot resolve service %s", svcId) + return nil, denyRequest(c, http.StatusInternalServerError, "cannot resolve service %s", svcId) } if svc == nil { - return nil, JSONProblemf(c, http.StatusNotFound, "service %s not found", svcId) + return nil, denyRequest(c, http.StatusNotFound, "service %s not found", svcId) } return svc, nil } -// resolveService verifies that a service exists and is accessible +// resolveService verifies that a service exists and is accessible. On failure the +// problem response is written and a non-nil error returned, so that the caller +// stops: JSONProblemf alone returns nil once the response is written. func (a *Api) resolveService(c echo.Context, log *slog.Logger, svcId string) error { ctx := c.Request().Context() groups := UserGroupsFromContext(c) isManager := IsManager(c) - svcs, err := a.ODB.GetService(ctx, svcId, cdb.ListParams{Limit: 1, Groups: groups, IsManager: isManager}) + // The query builder refuses a query without selected columns: only existence + // matters here, the id is enough. + svcs, err := a.ODB.GetService(ctx, svcId, cdb.ListParams{ + Limit: 1, Groups: groups, IsManager: isManager, + SelectExprs: []string{"services.svc_id"}, Props: []string{"svc_id"}, + }) if err != nil { log.Error("cannot resolve service", "svc_id", svcId, logkey.Error, err) - return JSONProblemf(c, http.StatusInternalServerError, "cannot resolve service") + return denyRequest(c, http.StatusInternalServerError, "cannot resolve service") } if len(svcs) == 0 { - return JSONProblemf(c, http.StatusNotFound, "service %s not found", svcId) + return denyRequest(c, http.StatusNotFound, "service %s not found", svcId) } return nil } From 9c25da4dad97367dd1a982a196ae855942ccf15b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Thu, 24 Sep 2026 14:37:55 +0200 Subject: [PATCH 13/61] Expose the node and service names on the log endpoints A log event names its node and service by id only. GET /logs and GET /logs/{log_id} now LEFT JOIN nodes and services, so that the nodes.nodename and services.svcname props can be selected; most events name neither, hence the outer joins. The responses are typed as LogListResponse instead of the generic ListResponse. --- cdb/log.go | 10 +- server/api.yaml | 70 +++++- server/codegen_server_gen.go | 412 ++++++++++++++++--------------- server/codegen_type_gen.go | 103 ++++++++ server/handlers/props_mapping.go | 6 + 5 files changed, 393 insertions(+), 208 deletions(-) diff --git a/cdb/log.go b/cdb/log.go index cff02d67..d008c665 100644 --- a/cdb/log.go +++ b/cdb/log.go @@ -40,7 +40,7 @@ func (oDb *DB) GetLog(ctx context.Context, id string, p ListParams) ([]map[strin return nil, fmt.Errorf("getLog: no select expressions") } query := "SELECT " + strings.Join(p.SelectExprs, ", ") + - " FROM log WHERE log.id = ?" + " FROM log" + logJoins + " WHERE log.id = ?" args := []any{id} query, args = appendLimitOffset(query, args, p.Limit, p.Offset) rows, err := oDb.DB.QueryContext(ctx, query, args...) @@ -51,13 +51,19 @@ func (oDb *DB) GetLog(ctx context.Context, id string, p ListParams) ([]map[strin return scanRowsToMaps(rows, p.Props, p.TypeHints) } +// logJoins makes the "nodes." and "services." props selectable: a log event only +// carries the ids, and most events name no node nor service (empty ids), hence the +// LEFT JOINs. +const logJoins = " LEFT JOIN nodes ON nodes.node_id = log.node_id" + + " LEFT JOIN services ON services.svc_id = log.svc_id" + // GetLogs returns rows from the collector log table. func (oDb *DB) GetLogs(ctx context.Context, p ListParams, fset LogsFiltersetFilter) ([]map[string]any, error) { if len(p.SelectExprs) == 0 { return nil, fmt.Errorf("getLogs: no select expressions") } query := "SELECT " + strings.Join(p.SelectExprs, ", ") + - " FROM log WHERE log.id > 0" + " FROM log" + logJoins + " WHERE log.id > 0" args := []any{} if fset.Active { query, args = appendLogsFiltersetClause(query, args, fset.NodeIDs, fset.SvcIDs) diff --git a/server/api.yaml b/server/api.yaml index 80840771..3288c272 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -3358,7 +3358,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/LogListResponse' 500: $ref: '#/components/responses/500' security: @@ -3391,7 +3391,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/LogListResponse' 404: $ref: '#/components/responses/404' 500: @@ -7729,6 +7729,72 @@ components: type: string nullable: true + LogRow: + type: object + description: | + A collector log event. Every property is optional: the `props` query + parameter selects which columns the server returns. The message is `log_fmt` + with each `%(key)s` or `%(key)d` placeholder replaced by the matching value of + `log_dict`, a JSON object serialized as a string. `node_id` and `svc_id` are + empty strings when the event names no node or service; the `nodes.` and + `services.` properties come from LEFT JOINs and are then null. + properties: + id: + type: integer + log_action: + type: string + log_user: + type: string + log_fmt: + type: string + log_dict: + type: string + nullable: true + log_date: + type: string + svc_id: + type: string + node_id: + type: string + log_level: + type: string + log_entry_id: + type: integer + nullable: true + log_gtalk_sent: + type: integer + nullable: true + log_email_sent: + type: integer + nullable: true + nodes.nodename: + type: string + nullable: true + nodes.os_name: + type: string + nullable: true + services.svcname: + type: string + nullable: true + + LogListResponse: + type: object + required: + - data + properties: + data: + oneOf: + - type: array + items: + $ref: '#/components/schemas/LogRow' + - type: object + additionalProperties: + type: object + additionalProperties: + type: integer + meta: + $ref: '#/components/schemas/ListMeta' + AlertListResponse: type: object required: diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index 6fcdaffe..ecce55a8 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -8993,210 +8993,214 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "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", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index 84c9721d..126916ea 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -301,6 +301,47 @@ type ListResponse_Data struct { union json.RawMessage } +// LogListResponse defines model for LogListResponse. +type LogListResponse struct { + Data LogListResponse_Data `json:"data"` + Meta *ListMeta `json:"meta,omitempty"` +} + +// LogListResponseData0 defines model for . +type LogListResponseData0 = []LogRow + +// LogListResponseData1 defines model for . +type LogListResponseData1 map[string]map[string]int + +// LogListResponse_Data defines model for LogListResponse.Data. +type LogListResponse_Data struct { + union json.RawMessage +} + +// LogRow A collector log event. Every property is optional: the `props` query +// parameter selects which columns the server returns. The message is `log_fmt` +// with each `%(key)s` or `%(key)d` placeholder replaced by the matching value of +// `log_dict`, a JSON object serialized as a string. `node_id` and `svc_id` are +// empty strings when the event names no node or service; the `nodes.` and +// `services.` properties come from LEFT JOINs and are then null. +type LogRow struct { + Id *int `json:"id,omitempty"` + LogAction *string `json:"log_action,omitempty"` + LogDate *string `json:"log_date,omitempty"` + LogDict *string `json:"log_dict,omitempty"` + LogEmailSent *int `json:"log_email_sent,omitempty"` + LogEntryId *int `json:"log_entry_id,omitempty"` + LogFmt *string `json:"log_fmt,omitempty"` + LogGtalkSent *int `json:"log_gtalk_sent,omitempty"` + LogLevel *string `json:"log_level,omitempty"` + LogUser *string `json:"log_user,omitempty"` + NodeId *string `json:"node_id,omitempty"` + NodesNodename *string `json:"nodes.nodename,omitempty"` + NodesOsName *string `json:"nodes.os_name,omitempty"` + ServicesSvcname *string `json:"services.svcname,omitempty"` + SvcId *string `json:"svc_id,omitempty"` +} + // NodeListResponse defines model for NodeListResponse. type NodeListResponse struct { Data NodeListResponse_Data `json:"data"` @@ -4011,6 +4052,68 @@ func (t *ListResponse_Data) UnmarshalJSON(b []byte) error { return err } +// AsLogListResponseData0 returns the union data inside the LogListResponse_Data as a LogListResponseData0 +func (t LogListResponse_Data) AsLogListResponseData0() (LogListResponseData0, error) { + var body LogListResponseData0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromLogListResponseData0 overwrites any union data inside the LogListResponse_Data as the provided LogListResponseData0 +func (t *LogListResponse_Data) FromLogListResponseData0(v LogListResponseData0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeLogListResponseData0 performs a merge with any union data inside the LogListResponse_Data, using the provided LogListResponseData0 +func (t *LogListResponse_Data) MergeLogListResponseData0(v LogListResponseData0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsLogListResponseData1 returns the union data inside the LogListResponse_Data as a LogListResponseData1 +func (t LogListResponse_Data) AsLogListResponseData1() (LogListResponseData1, error) { + var body LogListResponseData1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromLogListResponseData1 overwrites any union data inside the LogListResponse_Data as the provided LogListResponseData1 +func (t *LogListResponse_Data) FromLogListResponseData1(v LogListResponseData1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeLogListResponseData1 performs a merge with any union data inside the LogListResponse_Data, using the provided LogListResponseData1 +func (t *LogListResponse_Data) MergeLogListResponseData1(v LogListResponseData1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t LogListResponse_Data) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *LogListResponse_Data) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + // AsNodeListResponseData0 returns the union data inside the NodeListResponse_Data as a NodeListResponseData0 func (t NodeListResponse_Data) AsNodeListResponseData0() (NodeListResponseData0, error) { var body NodeListResponseData0 diff --git a/server/handlers/props_mapping.go b/server/handlers/props_mapping.go index 544800f0..d5a785ef 100644 --- a/server/handlers/props_mapping.go +++ b/server/handlers/props_mapping.go @@ -847,5 +847,11 @@ var propsMapping = map[string]propMapping{ "log_gtalk_sent": colInt(schema.LogLogGtalkSent), "log_email_sent": colInt(schema.LogLogEmailSent), }, + // A log event names its node and service by id only: the names come from the + // joined tables, as in the historical collector's log table. + Joins: map[string]JoinDef{ + "nodes": {MappingKey: "node"}, + "services": {MappingKey: "service"}, + }, }, } From 2d319f5dfd42cff7388966e302beec823307fdc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Thu, 24 Sep 2026 14:37:58 +0200 Subject: [PATCH 14/61] Expose the node and service names on the instance endpoints An instance row carries only the service and node ids. The svcmon mapping joins nodes and services, nodes through a LEFT JOIN so that an instance whose node row is missing is not dropped. orderby resolves a "table.column" prop through the mapping joins, as props selection does, so that instances can be sorted by service or node name. The instance responses are typed as InstanceListResponse. --- cdb/db_services_instances.go | 4 + schema/relations.go | 1 + server/api.yaml | 92 ++++- server/codegen_server_gen.go | 420 ++++++++++++----------- server/codegen_type_gen.go | 114 ++++++ server/handlers/list_query_parameters.go | 47 ++- server/handlers/props_mapping.go | 6 + 7 files changed, 466 insertions(+), 218 deletions(-) diff --git a/cdb/db_services_instances.go b/cdb/db_services_instances.go index 3decd988..e52fa76d 100644 --- a/cdb/db_services_instances.go +++ b/cdb/db_services_instances.go @@ -10,8 +10,12 @@ import ( ) func buildServicesInstancesQuery(groups []string, isManager bool, selectExprs []string) (string, []any, error) { + // services is an inner join: the access check filters on services.svc_app. + // nodes is a left join so that "nodes.*" props can be selected without dropping + // an instance whose node row is missing. q := From(schema.TSvcmon). Via(schema.TServices). + LeftJoin(schema.TNodes). RawSelect(selectExprs...) if !isManager { diff --git a/schema/relations.go b/schema/relations.go index c64cf0c9..031f49fe 100644 --- a/schema/relations.go +++ b/schema/relations.go @@ -15,6 +15,7 @@ func init() { NodeIPNodeID.Ref = NodesNodeID SvcmonSvcID.Ref = ServicesSvcID + SvcmonNodeID.Ref = NodesNodeID SvcmonLogSvcID.Ref = ServicesSvcID ServicesLogSvcID.Ref = ServicesSvcID } diff --git a/server/api.yaml b/server/api.yaml index 3288c272..351bb8d2 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -5642,7 +5642,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/InstanceListResponse' 404: $ref: '#/components/responses/404' 500: @@ -6285,7 +6285,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/InstanceListResponse' 500: $ref: '#/components/responses/500' security: @@ -6365,7 +6365,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/InstanceListResponse' 404: $ref: '#/components/responses/404' 500: @@ -7729,6 +7729,92 @@ components: type: string nullable: true + InstanceRow: + type: object + description: | + A service instance: the state of one service on one node, as reported by + the agent. Every property is optional: the `props` query parameter selects + which columns the server returns. The `nodes.` and `services.` properties + come from joined tables; `nodes.` ones are null when the node row is missing. + properties: + svc_id: + type: string + node_id: + type: string + mon_svctype: + type: string + mon_availstatus: + type: string + mon_overallstatus: + type: string + mon_smon_status: + type: string + mon_smon_global_expect: + type: string + mon_ipstatus: + type: string + mon_fsstatus: + type: string + mon_diskstatus: + type: string + mon_containerstatus: + type: string + mon_sharestatus: + type: string + mon_syncstatus: + type: string + mon_appstatus: + type: string + mon_hbstatus: + type: string + mon_frozen: + type: string + mon_frozen_at: + type: string + mon_encap_frozen_at: + type: string + mon_vmname: + type: string + mon_vmtype: + type: string + mon_guestos: + type: string + mon_vcpus: + type: integer + mon_vmem: + type: integer + mon_updated: + type: string + mon_changed: + type: string + nodes.nodename: + type: string + nullable: true + nodes.os_name: + type: string + nullable: true + services.svcname: + type: string + nullable: true + + InstanceListResponse: + type: object + required: + - data + properties: + data: + oneOf: + - type: array + items: + $ref: '#/components/schemas/InstanceRow' + - type: object + additionalProperties: + type: object + additionalProperties: + type: integer + meta: + $ref: '#/components/schemas/ListMeta' + LogRow: type: object description: | diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index ecce55a8..eb963372 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -8993,214 +8993,218 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "7L1tc9s4tif+VVD6/7ec1Kjl9HTfrZp0TdXmppMez+1Ocp3k3hetFAORRyLGIMAAoBzFlar9NPvB9pNs", - "4YEUJQEUZcu2ZONVYgHEA3kefufg4JyrQcqLkjNgSg6eXw1KLHABCoT5i7B3WOV/SFBnmf47A5kKUirC", - "2eD54OxXxKdI5YAKnlUUJKjBcEB0U4lVPhgOGC5g8HxQSFAJyQbDgYAvFRGQDZ4rUcFwINMcCqyHVotS", - "d5VKEDYbfP8+dJO/4Rl0T854Bv55dct15z3fumnRtWVxzS3/ZwVi8ZvgVTlZbE7+khcF/kGC/koKMkSJ", - "VHo5peAlCEVAIsXRTD9ulwiyogpNFugJjGYj2zJZ/B2X5VDOU73Wp6N6A1/01MsduL6DXiv+nRREba73", - "g6YN/JUUVYFYVUxA6NUCU8ItVYCqBBuhZ6gAzCRiHFE9VGhRpnFlSRlMcUXV4Pm/PRsOCsL0XIPnz4b1", - "WglTMAPRXuwfoLDnw7KUVhmgAhTOsMKIsPodlpxJGKFXDE8oZPp1ullH6KMENMVUAuICPdNb4gVRlilA", - "YTQlQLPQbnSPfu/37XSqSW1j0e8viP3SUyKkat6so1CzjbQSkovQErgd2PtGe7/QtyIDcX16lVxoGh2h", - "dwKm5CvCdfsCXRKVox/QlAukRwaWETZDXM/nSJrbuf+ueV3vafgDLssgUbve/V76O8FLubmpF4FtEEdA", - "hCHAaW7ffkZS/RjDYhFaU2mm6bWi9wor6XvNTAlOpfnoZhmScLYkYM1jkLXXoleP0Xgg9YDjAbqAxRCl", - "nClMmH7D+jkJFFL91VrbzIhUhKUKzTGtQKKUV0zJ0M7M6J07+67lo+Uvs6+fnz3T/+iVADP0jsuSkhTr", - "hZ/+S+rtXrXG+/8FTAfPB//f6VKLndpWefpO8AmFws6y+sL+HWfoHL5UINXg+3Dw87Mf72LWjwxXKueC", - "fIPMTvvTXUz7mosJyTJgds6f72LON1yh17xibp9/u4s5X3I2pSQ1X/Tf7oaOzpgCwTBF70HMQaBXQnAr", - "Gd3DeuwXFIT6nUh17ijd4KyGpww7Y6uROIO308HzP68GREEht63MjHzOL/WOHWdhIfBi8H14NcBZRvQy", - "MX23Mlfo93Xx3gzJJ/8C+1bXfvj0fWhV2JZl6r0bnWvZvYZDf9ptf/JM1GzMI3wzLPMJxyJDWPdCgl+O", - "0Ks5iMVSbRCJeGk3+dzIss9GyH5GRkCNWYNynZCT6DInaY5STquCSSf+zCe10lOO0Gcz3Wc9tt5jpSAb", - "s6ngBfqsl5RMC/UZYZa5P7Ww/TxCGgF91rpJjlyrHpek5u8lEYxZygtAZjiMfn/1+gP659uzN+YJLACx", - "ilJ0mYOV6HbjCosZKLtYrnIQ6IKwbMz4FNk3ORqzwXCN0syjm6/1H1WBGRKAMw1xUAFS4hkMkQCWgYDM", - "rqzep1lWs0st/dfk+nBgWlMBWu17BL/roB/vbk2K7N/CPYDNw43TomNswqTCLIVwj86JJcxBELXwM47p", - "Yn8ODVCVWfDVkMw/bG3O+J6xJFaDIN1Fk4z+mLXdsfFIQ4jOEuj30Dz1L8EnL16U5e3IvbJ8kFLPbmtT", - "5jHU0l4o5RnchcTzSY+y9FIfLssk4wUmLNisABeJw9ObLNHe7w4cEeYi34f8lciLW6FHPfBDJMh6Xz4t", - "TOQFkgAMcYaw8cEMrbVWUxJJwakvgReIKDQBytnMmEpak43ZBeOXbEdKRhuEPGb7pGS9rwRTytOAaDft", - "eksBQWw6ZDDvbJ6F24zbJdzcNSyFOdCOZRc8W2lfe7zWAf5WgbumFjAL8a5pl+QbdKyskpB1NM+BZVwE", - "9V6XTgxuKqjITFPwsd0kjnHk3YrIMSM/RJnTbMwjdCoJwvowR1oqkDmhMAMDyceDD+OB8RNh1LT8MBOY", - "KcJmziWKNTweD17XPRniIiPWH8LuS6deV/c1u/Q+JTiFnkR6xqa8TZ+rb/1tpYxp4kwC6zi6FEQBUjlW", - "9c4Q40hAyoVxdq7ukLAp77uW2+GWswfJKmdBuHj2DuEsEyAlykBZL15LT/+LEwaZVsTm/ATUJRcXqyp6", - "NGY31MuWGbRhu5NezjK/oJ9SPEsyKAWkawK49S1CvEKYmnpHLXAa+F1e+HUKqGQCswDQNa2C4yzFUgV7", - "pLwonFfK2w4sC7bNsIJLvAi2B21HUGEFbxpBdW7aUUmwvRSEh6cuQ3hINxrTwLmByYTCfhV90A7fTZU3", - "7Lkhk/AcE2M0J2V9YNAIpcBqGgE0MA70IPQxvvYbiiN3LJFdZ3W0PtbbnIc3J1KeNXCFvUA09GKvJfBD", - "gvdhCPff+exWVOHvfPYQdaHblgc0ppxqfcQFonyGYA5M3Ym/2Jx9O9BEJPpM+cz4iMfMmMnmiPDz/3hy", - "AYun8jPiov4j+4xKilPIOc3MeOYvc+psTpWxSnMNac0JHOLTMTNDG3/zEGH0z/dv3zgHsF4TwZR8gwxh", - "iTCynD6yHumEZLVL2thCnxEWMGZQlGrhesqlz9m8OKSlrMF6egC9aGfp/2LfWsvRPWZ+TzdaOrobN7ds", - "/NxKT8cqSn3YIKTb9PZxGgTQ5u1gBeFG54Xe6vzUnaHAhCbS6e/AI2uLA6bEwimvfk+EfNe6baYwvdhx", - "BeuugdURtV11LaW7o8fZPsJlckA+6jc8g1sRtHrghyhp6315RK0RCoJftiOzpImW6C1xx6zTnOiQuEMk", - "OcJ6+jFLsbBxMIwuXAyEOeyHDMlqIsF/NGZESPjcJuj8ltKA9nm4NQhOJ4TLZA5ChoTXhOIMkhRPCAO/", - "SEhpJRWIEJs26i/QyhikKlHc31xWScpFiAh1c0a6WqcCvgRHDvsjdavKBeCsY+wOryCwlHJZCehulZT7", - "3+n0S+b/HPk88HPJOQ00zTO/jZlfJnwiE3MiG1ZQrtclFqxDi2GpkgkP7Ma0aqPT30qkAgYiKblQIQWb", - "JkHDXDdOKkIz/XeoQ7p6VrrWqG0gEW6fUs7DcwucXoQbOS+Cjd9IGTD+9d4ZZikEbfECs2qKU1WJgOos", - "oEgmmF0ECNg0LxR0NGvqDDUHOcdo7JAsMo1Twb8B29aeYLVfM5xxRabuCNNvfHKZYJHmobaUszSwKC6T", - "CxAs8EpaeMPX1oMHXa9uHuQyEUABy2CzhFnQ78OlCwkItXZIu5JfgkgmAvAFiB+3d/lrRxenaX7c3qVr", - "lFJwBYHQjpUe9ZI6esqqLOkiYRM/KwQc3Ro6psk3zkKN2jDyNzHOv0GiCA20l50KWyqsqoB3BXCRmKWH", - "m7e5wUwn/UpWhXUPd5f6tqMXbDjo2uelRrNMLQIS0gdR60C6DYSt4Kvy4cm8KjD7oYlKgq8lxcwGQcgS", - "Ui1PrBNbo8k0rYQAloJDn2NW2vks1ttcXxvtmhX40O57a4DcioXgxn6IRkJra57vWocHtEyF2tA7Gmth", - "C+wO+Sq0bRoyJExbpbhUOMDcpsccE9ohZXSfrhMG286mZLaluTNGzXTrCO/T7ZlgvMMvY7uU5vrOlnbZ", - "1SEo8XR7CArptimFr4m2JHIyy429IXNOOz5c8wDll737F/hrsr4Hbz/CevWzYZ8dncL4TjfnOPxozqUK", - "x0R0hEskBSjBHUsEO3V/ye0AUfcyztBO2i4FnxOttjooc6uO1326Wcw2b+URxUtO+WwR7HCJ5xD8InsK", - "Q/koQdyKBtMDP0T1pff1TsBUhuMiPmiVorgw92NgCgZ6yCHCEkk8t/76d2/ff0CnlQQhT6/0PwnJvp/q", - "7vZ8wByOu8MJBlo76d2LUtRh3e7+wi8IM2T98s6xb2/LjQeMa5jTTO9WNB4M0XhgomUqG2U3HiAu6t8Y", - "V0izyITCeIAwJRfgDUxxNOH/YCu+1/rN7fJ+u2J8HCgwb84hgs8llvKSi/rMQsCMSCWMuEguYPHZxsnr", - "tzhm9ZUnewoz4ZwCZj/ojTaQ4Mln68lfETufh2P2mRTrP6LPlKcXyZRQBeLzU6QBw8J9IPf9TlwI0qkJ", - "L9Ifls2B6eeHZr3mOh5QvDB/fam4ws1S9MKbS1qafuzZy32FYJj34necmTfWfZ7geat9+yXmBfkdckTI", - "jgCGYNxHsWW169+6V6eOdZIi7D8mhTloCW7CuOnCrUsK9BvLOWeQBEM0DMUFkadtzXh6ASJxnEUCutr2", - "5WLWEaq6wpwB2CBAgkpqrtYs7Nd04VfmUxEtk3WVqlsN8BUXpbavB89Gz0Y/bjUO60c/+eSdhLQSRC3e", - "a2Vjp5pgSdIXlcqbO2b6GfPrcq5cqdI4+AELEHVv+9drLgqsBs8H//zvD/X1STOEaV0fw94PdSF2RJmN", - "8RKYnKetw29ckkHr9Qx+HD0b/WR8SyUw3fh88NPo2eiZFgdY5WYjpxa9m//PfNePtWZdCfY2J0DuKVRy", - "Y0O5a6jueOVLBRWM0B+Y4ZmW7hJgzDCl9VO/uLtMVvYbk0zCckw+dadKlzmXgHBprj8v7NF1y3mCplxY", - "4aaJwBDiWTZ4PvgN1Au3qeFKsoM//Rhi2eV05VawRjj9+tur8f37u6ve/R+w0KZ3d3uHeIf1uCvT/Z+o", - "0xd8/7R2u/eve7yVuYJnPVcz3/5H6x6ob6BmZae6U5uVDTG0mPjPT3rvbUb985Pem8IzTTitI7ZPxmsp", - "PZzyB8/IVCv/FT4wF/YXFqWckOwEXYDR8gVmGVZcWLRQa3Pj1LLmnxvll6XP4sQaJCcraMGYCXhCYWSu", - "OxMBbpQ3PINXXyHVqPAlL0rz/yai2MzaMBOhRC1MwLSex82vmdDHX++4bDGYc6T8O88WO314X9zHGlA0", - "c6DWW0Qm20aHP3bthjJcItuGnpgblPpFNu+reYtPt2oHkvkUw/f1xB/fb8gLngl8BP9zH4LXnZbX3rf1", - "/bF1V31b359ad8y39f35Xhj0+7BRa6dXJPtuKYOC8th4v5rfl0zr1WjIabQ2gyHNX07FaQNtR74y8sCN", - "TiSifDaDbMxMkBRKc8xmgNqIVHeCgigFmY8n7TYsx2xqvX585Ulxs2N2m5sqg2veKQgzyu0Q/z1oHC80", - "+5XIUpubmrZa0Xfm+kZzeLKdrMesjdTQNYDa9eDZ/dHpMALBBwgED18nmRAEE2UbNLdqnrb5H0xfiRQp", - "AAmtEyR60iTHSOpWjWaejtALc9hG5Jg5z5+N7CVKNvYbF+ZPY8IRWXsI61tCKaYUxC8amhpxMGaa22EO", - "YqFywmYhbtZLfWV2Fe2taG/dHuvInkDOsM6TSUUvtA4qnlqwZdOn2cYmwl4rO6c+5yTTCAy+VNigtlQQ", - "BYJg9IRkQ9Tk+xgiFx81RPbAzLXV2UaG6P/+7//z1LChXWqmOdNwXIEXVonaBsOK/NIteE3ZMoDM2nGG", - "vaRT0UsDrgMF2ne1L9OsZy6Vm6RL6Qg2S3Y9rPx+B4ZaxKk74VTjQoSv5q7bzFF7S481Ckxz6ZwIVWGK", - "Tky3FVfHmGlOXQsYqq/f9Mpi1KG/oq/wuHXXZga2w3cYvjTBNRqU2bP+RnkFvW77lewTLKGP3F5L4bU8", - "ibn1BF03USrX1R6rp9v1DNH/d7+qZQkCd3HpGWYKwS+niLCUZOZyJRDlUNiYrcIwFEJhXj+eves4Ztf2", - "45kMftvcIwbJkqylSUckexodeQ/Ei73F6dcYOi3P3yamCuKd+6Su6H57sNjqwDnKj8M+rqKvE9niqbVD", - "ny41MGY1HtJCXkCdQtaaJBZynDbOgwZZmVSzWNWHRZdE5W4kbcAQieaYEhMKugwzq3GRyVRLcVH6tUmD", - "Ge9dlxwOXD1CRBqB5zEdPJdlXz/lWsLXVZflK2K8gaoOG3FnyCe4LE/GbCOIxB3sTXi2EVBSnzvjsvyl", - "DlIFPeuYEWnTceSYZdRGpv766vdXH14hs4/TK1yWCcm+d0DVstyfQepiF9dkU1ma1+OL/PCGjZSlS1Pn", - "DRc5Sv/gcfGdKwawre/fDs5H2aT5QtiS9SZ2tr9HT+ERo9m1jOVH4yf0qAw/4rsFkXzH6cDX3HB6EXfh", - "gOuTkP6whfQBC94aHDWg4nooKYxDtho5bWCATLx8gyw8Zo5d5Z26zTrz27ZT+B60p+wY1X/jVSvLlvEf", - "QAD3T2i7etA+3atgPEKX0EvrufdZaR3k4bTvgQiio1b/Udc/BEdIo+tPcZGQ9cw3Xkl8bm6tIv2JEZmu", - "5OoQ1q+6EmFsM8NsBQlWcL8ozs5bSzh6vODGc5ef4/nZFhpsklOEPQDu4mFd5KYnXb0xAx8dKoieiBjW", - "vncmK6sJbV+17/C2+cDV8mlb0CWEwd+1p4mcFzkvcl6b806vDPdsd7MonOYIb/Kdq1O6i/+lxZIHwZGr", - "Uxq6Wp3U5JX0Tli/vOMMmmp9CJSZL1wXo45my7W8AS9UkE0U38UvH1nkAFkEq+NlkePy+J+axELbcs0o", - "LvAMbPlRy2T2MVSZmx71bfqettl/2ikjRIwQMULElvPsGsZZ2/XWaZydt6eJnBc5L3Jem/N2Nc42+O4a", - "xtlB+b0fM/I8X80NFO2zfdpnm5yym30WueQwuSSaaHemqOoqDb0Sgu5+VPa+Hj7CwggLHyssTNYPyfbj", - "n+++pbF2Yra3+KBk6yWMNfbdCAZqVNXzHhrP7t7pva1hw1YoNBN8ipc/otPeAwqDlycj30S+iTBxqbjW", - "HYh79F10a681l2LkwsiF0aXRQ3tFvol8E7XX4NQULet58uz6+hwYdUu8ABzT3N4GlVYqP62rZfoVw7mp", - "uwQCYVeJp1I5MOVeRUgTVCp/Y+Xw7d4L6qgPviamm54+6Xwn0ng4qKo+SQBNL1d/6VMPCf4iTaFUtbP6", - "wG7vGnrsT6CauhxtZkRe9MpsYiN3NvIvn+ifE28FnFbyElsCw5O9RD+9mr4EBbOXjJld7emVm7Mjgcmv", - "Zlt7S5Zs5/NeML1AJNOcOiXtAl+hzJNuoIhdjj/1ceZIbANO1LQX0cTxogn9DY8+77AV2YSZf40A8KGI", - "WxCVmFKe6r+mdT1EwtT//HkpHtvJ1cwDGoEHcqiZDno1Qr8EEe6TwbxriHDRy5Z497etlyFdX36w9qdp", - "FbhrbEm+wS6vqrOAtE/XrL3imPL4/lMer8GY/vDLpsEPcfMS+mw7h9/ELZ7T9yUB3fnd55g6eNc6DMzU", - "/TVh9K0yYZmlBS9EuTcaiSEaDxULHXyYhi3D3c/etX3DJuZrN9ZtFku1cyyd5kMN7+zCEMUToIdS5DQe", - "MB2OLpg2hLkh95c0G43T6Oq+40SXtUR1dduMEMtgShgxfr+ikgpNAFWMfKmCJar3LXWnyZQA9Yjel5xW", - "BUN8iqaJrSytlss2M4BEivvOQKcJL30DFiUWRHKG7La4xlTAqkK/yL8PhoPfz/7j1WA4GFfPnv0EzX/+", - "Xv8vbf6jfzp70xLs7bnNYjen/7DrHuaYVp5x/kv/jBS3Ce6FHTK1L8s31Jo+qtc3bN68e1/LKe87J2hf", - "rBMzg/bFW6dX9j+9jd2aRFlmyinaiwKFrYvKawUHSnZCs20GjgNXSxMHPZkBS9zoIxuiME0MzgoUTWi2", - "FevwPLA6PDUJdqcN3ROh7ZW6onkdb0AcCPL7g2dk2o+ZltjusMX2njGnB3dZu97fxstAQwP6uoDcgeVj", - "PSacdRx+LVC7uLYkqK3eLVB34eCSoLw+Lv27Ydno5Yogze/l8hkBS0cXxArQ0dd1j76ugIhtObL2KWA1", - "QTWxCKvreoMLQHza8v9o2ao4Ss2Cjcz1NdtoA6+DSE8mDZFtzPbfOTRlzpbDEYkwMk+0fnzyQU/9+mnf", - "OmAehaEH0LseLheMMFuWpm8mu5+yYY8PAh2LWwpU45nSxLybc0qToM8/pX8TMAUBLAW5DV31M3YM9/jt", - "HVCNyVNzf6fRYzca3VUP012lCaWPx+pIKC+6sqIr6zBdWVsYbQXgHY2M3zsG3QIae6iACL6OzP+0BqhO", - "4WvJhQre0HxlmlfYijCE0T/fv32DbEh0U0mdwjIvFSnMc/aOkOhUdHaKxwC0egKoA6OQVkxe2Ntjggxy", - "QrOaULS1ildMuzAFBKOeIuKJiCemL+vDnadX096Jbd1hn80I08Gia6bwLqd/986k+z+SjFb5A0zz4lhB", - "8U5GWLEWIhvc16E85bPwATvX+sd3BfD7fSU6iOeMd6sC3eF6N0Zd9kXAUlzKimIFGZosTLO7mAXZbsjV", - "e4wZwWsErxG89uTc0ytjPfbFsGyVe5fOieuB2h5OwHdYAFNtN8jh6PWXbcN7H0urv0UEvA8E8L5acsua", - "L2936BuZZV/MEmFxzMZ4GIq4d432Aqs0J2zW27fbq0h7BMcRHO8KjjVhPXiAvGNZmJ25s29dmMigkUF3", - "ZVBHWw+eR0193CCD1hFglzmINewtUSUhQ0+WpuxKNKwcIlFRsP9Lc0gvkMoFyJzTTD7tZOuPZknxRP0I", - "qSvplQKn+ySvz62h/edp2FN+HBeEdIuXkaYNoU5jrtd48LfLVZBD5pqWI2ANI/IZSTFtspqgf3HCtKpR", - "OZGtN6FyQKWAOeGVRJxBIHVK7VFYc/lwadPErNxSqXNMe654tPJmRoaPDH8rSnTLfdtzKPh8FZS1sFhX", - "Zb8NibDPa2LWoRhkinUH5ipr+BnCQEFgKjzqhsu2z7BrfLY2x3BtJ5Hv4oGDPXBg3Fw/3F3xHjyb3UwL", - "u0udK4oYmBKLG6nidP3Ew+rkco3jvao5io14cnEIJxfCfMnsNCdZBiwpgFWJy6m8PehH924yMNsRrM3c", - "NE65QDAHsbAlz0boD8zwDIQcMwmAMKW2Qf6CrOiqpIlxZ3SBdAc9kO2g/7tAE6Bcszb3SbbfQL12+/mH", - "WcwfwKpXbjMxG8JjiNjpLx7uhd0sKfe6bG35JQiUf7Mj3WaKmrW6hT5VaSoYhh7kFE6Deupesw+csSk/", - "jgtwh5Vrv04sYcl4KcxRihnqI8/HbFeB3tB5lN7HK73NJMdfVSgokrVJtWeBvLKYq34pYl6t8CciGXpS", - "V55zeyBMKsCZNmBs/htv+plSkDmhMPOI9pMPJ67URtPJzjZEJ69PLM9fEgkPSFnsQLyPtq6PleinV3WN", - "4u/9IY7JG5NimeLM1UIEk1qmgGICQuakHCJclvJ0ykUhT+uT29OCZ+6/Y9YUlSaUaAYyY5bVpP7icoTO", - "Lb3YGozmkzrltSTktnGiFZpbDGbOePGoND0Y4+yHNWbw6LYP5u52UdmM6ievtE004dnixL2FFDPGTRp4", - "O222BfptO4T+zYmA5QE0rlRua4G5w2fNc4Fz56bW9F2eOUfEdhsZcix5LZXLjqjN2unXQm0HSKIx1OnB", - "AsfjTq5jqPlEtvi0C2YeqvC/C+B7y+A0gs/jB5+nGi9u917rXkvNhohEDY6koAmpW1WO2V481uYLvyhL", - "GdVlVJcPM2ewn0kDJ04hq/Ejy0mmrcbm0GlhhH3Db7a8luZGW1Er5zTbsPbGrGXu6f44rWvvUz6bQWZM", - "R4zSHLOZtu00r9lvoftAQdR226zH4dPD0dfN91t44M3yU13AwmQpNl9x68l1a9B4Sn38Bwf9z4pb3NzW", - "vbd0Wnw03BoVcTyuPhCT9R8HrYUbEznq4KAOjhr4MdnCy3OSHvFcTV97eiJzyOq4Scfd56C/RqrWGozC", - "HTPD91bryi1q94/luqK+jfr2ERm+PXJC2HPFDA7FP9Ur2UTk08inD4lPRW+9Ke5Ma55HnRl58RHyYr98", - "LSbTaJ2zZXfNOWb79y71TQQTGTYy7ENiWMM727nVspiN9auv1Xn8v/4wJas5e3Go8TKVWMpLLox3acwE", - "zIhUlmWTC1iglNOqYBJhAYjBHASCryWXfkdTzd8fZY8CG5G5I3MfL3OTnjeWtMGKSImeTCp6YWoYPbV8", - "d0KyE+N8JBIVmGVYcbGob8tOeLawDFnHqutfFRYzUIiUv5g/zdzO+6tyYK7+UYawRL+++v3Vh1dIL/P0", - "imTfw4ezZ7d8Yepslcf1+0iIZvCnsY53rF65rv5IKVEGCoxVyJn197TUXq3ySPgylR6CT52n6DLn0gQ1", - "Wd2ntdg66vXrsbN4v+rIlcdZedjqw8jlXXRI8BTxDc9g4+KGOS2cQOseiKX3xo1qK+eVbR9Lx7HjmF03", - "+udsa2Rup4rwYL+YKv7hVSyucVL7Toa5HrQkDG3yTAABaarJs6oAQVIt813ld0fTOMsESBmU7TtS5DzR", - "y2OgLrm4kJow9VzLefZCptE4eZj65eAzmVE+2+KUgLkpZu+Mk+Z5rSB8/PW7HnALh9XOf6S4Hqaeoskp", - "vZanqG+m2C/687dSxTZZfiLfPRinAJ8d5615vCR0q9tsAJKmRw2kplyk9ijspAAp8QxOhs7On+KKqjGj", - "MAequ55oEHIyNMgMilIt2iykbZyMyBSLLBwO5lh0P2Y/5bMkI6ny5EgemsZpobzXlnSb2ZS31eLAzNsm", - "56m/ac2FUM/+6Z6vLMXbSltV0OmV/ljOJtqCFldUkCX8rgL8VidtU0m/N0O1sR/ls7AlYlccYV5UN0eA", - "85oQq34Oh02PtRPI3W7rMdNayeO21k/3dVyPmV3t6ZWb8zt6spYO4y8IVxlRRgD8xRcU/TTskqgjt/aj", - "/lp6avV9vjE27YZnw0BXY1A65Nqtwurhoyv8cbnCmSPSDVUWiDuMWuVB1pM65NxfTk8sGmlWS7bEIqZN", - "u2O/kte6qhMrja4GwKrCpPitpMZoZUVpS2oujQdc+gsYYilBJcDm4VaL+zytE8JlMgchQykaUlpJBSJk", - "0Cy/gL+VMUhVori/uaySlAv7UjbTKuvmjHS1TgV8CY5c8CxgoelWlQvAWcfYc2BZYFvAUsplJaC7VVLu", - "tx+nXzL/y87ngZ9LzmmgaZ6l/pbLhE9kgikIlWjC7+p1iQULd6JYqmTCA7sxrSkvCn8rkQoYiKTkQvnf", - "NuVpgrNMBGztNJlUhGb671CH1MiOUCOv6ttU3vYp5Tw8t8DpRbiR8yLY+I342bXAeu8MsxQSYFmgD6um", - "OFWVAP/SCiiSCWYXAQI2zQsFHc2aOkPNQc4xQjIkaUzjVPBv0KbuCecUMFvrkGC1s/OkltaBxiWElv7p", - "uUywSHPv41wmKWdpYFVcJhcgWOClcJkEl8VlHy50vbq5kMtEAAUsg80dIqvklyCSiQB8AeLH7V3+2tEl", - "xRPCQP24vUvXKKXgClK1vUe9pI6esipLukjYxE/PgXxABnck3zgLNQqC/V9cMs6/QaIIDbSXnTpVKqwq", - "6W1SgIvELD3c3DoZD3fSr2RV4rY6OOCx2fDN+7MFTn6m7NrnJRYCM7UIiLn7zsekQd05v4x+Tb/L5TTH", - "IrvEAroP2TClLmjp3csz49ovoOBigZrHQ7bgP5Ydok0Yo11vj44nWPal4dcvDQmT9y/fn6GcS4UmlUQ4", - "w6UraRcgZT1FJONIxrdIxo1PuY8vnKG3JbD3//XSOjsCeZkFUK3Y61Q+ow6/87ZTqKDT+OPHs1/XPcee", - "I6ka+B9bkuLo/V0NuXFJoWzqTllCqq0y8/FDwvMQKSuedj5Uv/RRphb+uOK57ogYqH3VByuto/s8us+j", - "+zy6z6P7/Nbc59FFHl3k0UUeXeSPxkV+HBGMS//NqRF121ySznFjuwZM5xd1azSgowF9J4H+x8ZpRULW", - "lYGX585BVYIhTdaI2NQ1zlgF4ck5Ze956WlGQd4szs5bEz9A92m8OLwbMaaYZUTDhMQ+0ZlPCc8kwkrh", - "NDdFBhVv4hYZV2gByrW6i+76R/ia0ioDTwijI8mX9QI+4FnUGlFrRK0RYNQc0ot++Mx1DTFc3Ro5LXJa", - "5DQPp/GipASzFFrasUeW+99AoeaBdqp7e+6ox/fn0DBc2UzaKMSuBPZbqeAdVrke9ywbRL56YHxlZD2f", - "eomtxXEega4R2ZRXLGsx21q2FqZAMExNmlsQCITg4u7ZTezGbOKGrHYeGS0yWh9GEw+BzTqT1BjGavoi", - "3XdHrvKnrImM9IgZ6aWHoOrceceOEXsiwxYebJwkjQOlD1tFOBiZq1NLNWT1QNDgchunV4VNPrYlzFjv", - "H+Hl/m39zyCLLQOJPVx2B0ym+/8hQen+mwT0s7eav9uYrNIUpJxWlC5QBvbDd39tLlov5r4/fSio8IXa", - "+IZdQrIOLTyQ73e9QMJrHKb/tYs2ajkQb4v55Uov21LcTFlHgzKq6j6q+kHYk6JR02IXNS2uraTP71TE", - "n++ios9vpKDFsahncS3lfI/f7T5V83lUzL3kyDK+MnzE2XJNOYiIKNa/55BeIFExZEfZ0Wf13k4dtXXU", - "1l6vlSOq9k1Cj//qSFR3RuS2SALTxSCVfvclfzVDxpiCyJMxpsDHcj3Tltj4nR1zloRTlkT2i+wX2U+z", - "3/ZsK5b1pOICz6B/lhV/kpXIeJHxIuNl30+JBrdTvLWwtmM/VxYKtR4L8N1Zu0fkvsh9kfs83Ff2Y7uz", - "d3X1tQ6GKyOnRU6LnObnNAliTrZquTr9meuNCJMKsxQk4rboh/O1QNbpbHlfTxb5MfJj5Mcufjy9stXN", - "thfCWufJ2uV7Hc48UMZcXcT7esOtddiX1SxDztOOVbi6cVE6ROlwbNLB5IExSdy8x9zvTbspz8Js35Vq", - "WEYoWOg8GrOzKcoq0dTwLgWfkwyyIXJPVkwRihi/RH9ZdnwCo9kIjQc/5uPBEI0Hf83Gg6ebg3FbEHy4", - "XEd96jQasw918fEUs3oyoiTQ6Qh9NIX8TWnzyWpRc8wyFCpjPuo4xbfv5IYnpHtLt1e/JI88r1+fFTob", - "b/qnZ0X7laO3BTFhDPUbHnmLiG0EAsTqYMef+2CnjAftCMCQ+o8pDKLajWo3yG9VZTOOduJwo9F0zxF6", - "y6j7u6WwpD0atdrMVmjGlPJLyIJZbzRnxVw3j0/e84nkFGQKJkgVpgKkySJZVt5kS6bdYKH6xB2ZrJmW", - "4rhE04pSpL+3RFRrB1eptT0NkqAUYTM5GrNzSwi2cOvbiawRWCnInFCY+eFWpd62xnOrGhwa2nhAAYkr", - "VFJ/vn7lDHxffoSu9d3toO1P/75eyr4ws6+s7lvPDpCAlIsMGWnWXU83ltJ9dMUUvNLOp3kDtBzL0cRy", - "NHdUoeAPnpHpYs+C+h2X6uDF9HCwmb16TYlhBfbmzWVO0txVmiqwSnM9tkklWU+kkdCU4tnMlpW3L1NB", - "aNqVdNh7mxUjPa6e5kCU0j4MuKiHrgfPTq96l5y6C4y2zbjcyr4eg/KObckjsRCOETbVno0AMfbETgdA", - "Y9GNGN2IjxDaHYp03we4fGSwMILABwICS2C4JKP6Azg9u6E3319qwhCDA/iqB+Ahrd9mWU0oSd2rbEcq", - "bkPPdVBUGAy3QhH3I6BcUNHzcLSSOYzRUnSbHeiGig7Kx+WglEuS3JQPwcjZCGyPCNi6z3hk7siXAjTO", - "4QJVdenUOuj0yWRRB1u6uMuEeEpmaIC6d4m7pRqoXkuoSqlpqxSXCgdKlukeKS8Kty5veyYYt+VTO7qU", - "Ju5mS7vs6hCsnqbbQ/UPdduUwtckLaskJ7PcFBmVOaeZv2bdygOUX/buX+CvyfoevP0I29pvvV7j6n5y", - "HGzqoIEClOCOVoKduj9Cj1qPultJcQqdFGNiLCXhDMLr3Vrrb54mipec8tki2OESzyH4ngPFI+/C7NiK", - "I2q4lBqZky2FzuNOPuS9FrDdh7x+bwezDKVYpjgDZJ9GREkkgJqX7bLEjLox8za3wn3E58eIpPvBrO28", - "Qq2MO7KhlBCSPUQiim7iB4ymj9Jb/HEdb7cQcAfGPlgJvS9HS8T1jwTXR/B+jOD9wBD7wZ8SbKD7nkWt", - "G1gfrGvtvki/0tYRc0XM9Uhu+Hg47laLW9fnUV08ulOJ62hkPwY1cOMi142f/np1rh2V7VTqOmqRqEUe", - "rRbpV+y65spwveua8XqVvI4cFznu8XLcNYteB4oyLCsn1Up0NYnSds/2jgWxIytHVo6sfIOC2uuMLG6N", - "jc8Pm4nXqnNMjYk6tDf+O14KsBSXsrInwMv3Ypb1RRN1a10Uz3XbchkZTHFF1eD5FFMJww3fahQuUbgc", - "nHC5ZhlxN6a/KtOG1PAXE4/aPjLk3VQoryX50XPrPrC8zYF2fQhw8AC+S/d3vI2o+6OoeVy6f3+12cNw", - "YCVasleF7+OABe2y4WGZY2vG2rd0+zLm024lxlcL2h5XaMLPz/7Wp+/fDiqCLVQXP8w9rTi2R8c7Vj/f", - "jXb+dNzF+R8M52xVWTf1gN0U/D4ct1cEvhH4PlbgKxrYK3aBveKGoPf8+NX2+TFC3vMIeO8Z8IobwN1H", - "wTUHB3bPI9S9ZyVlS1ft6udFFOvfc0gvkKjYZuWrXdDue7uEeHITUWVElX6GzYjsH+NoO4c571fXHtkt", - "sltkNx+7NcVWlxVpdsmBtiwM2c7+oDjKsMwnHItsiATIgjPzL2FTbnua2OOEkjl0G3tnbvyj8A/FcjmP", - "KnXxBg9oe5jQHaqjRiKP6jKqyyNSl002gD7o1FM0GXCaIz41iZHsWGGp8Ma1R/AauTFyY5AbV4Hr7VYz", - "b3Fm1NVROkTpcETSQc/NK5F26O+gnGgevZaoOG8mjjIjyowoM45RZnTf62mKGXWJDg02AKU5ZrMbCpID", - "vv4TZUmUJVGW1LKjrnnRx1uwFBTGS34Bi9M5phWgEhPR5Sc4d/NET0HkxciLQV7cgv2D3MgZwpRu9dYd", - "OsiPfBj58ID4sBtPB5lxA0Pvwprx1nzkzsidHdy5Ux5Ie98F94h/jIkdI99Fvtvgu6SJvbpWxNX28pNn", - "zfj7Ko/QWYNy6fFyRX6HphSt1tEKBMOKzE1omGPrv6Cld2czGX3d9jzgUqrrXQ71iBNAlYQMYcrZDF0S", - "laNGHHRU9NpWSzM09sa67zJPfiyqeXhFNRFpcVqwvGabHWOdzYeuhg5EtazUdAtTctM/UGwLPWkMrad9", - "aDzCvchnEe4FeDKxYUcJ5bNurtzUL3XEEuWzEXqF09wUyVsgIhFGihSABGYzQJc5COgIRbzEZqgJ7awa", - "sVRZ9uLa73wWdVfUXbfMJztzxzV5YjdWiBwQOeCWOaB2v211BSg8Q08mFb3QaK14GvYEOM/bfox/hWde", - "w/kDniHbNtS4TS+ucQF4beQlZPuzHvRTtJwfV2nfr0QqwgzheI1mv884StooaW8rt8pLUxTeStdRIJfK", - "3uVphhXeXMprAaa8W4H++f7tG6Q7bSQZU3jm827qQV3VLV91uVlFsUDwtRQgJeEM8akR2NqqlkjlWKEU", - "M1O7awKtel5L56epONcxebiE6LrYNz3vQvDvw8g8BFl/4MlX9O/LC3Jbk39psnOJv/RD3SCmvgu3H87b", - "drgQou3bQj/L446Igx4XDsKUapL5QX9/J24LvZQQJArcCY24KOKiW885p0WbifgIiesaIR2GsLbcdAOE", - "tWTHqA8esD44DlxVOzt3hVZ1behOdFX7OPfGs/1jLO6etdzaImc9TqRVe/97gK0WW0S8FfHWveGtDhle", - "Q64DlOBHjb+ikojwqw2/rixl9MmN6JyzJs0haapDGEWjKds4yEyjXPJsAJhti6I6+9X4bxtvsCdOqqHo", - "rXFSTfBtTCl4fykFNeE4gbAIwJJ7Iopdo+fujIgO+mP7VfzHMmuOmlBL/ge0+32KgX0fdG07sNrxTOnW", - "tXM0zW5Jk25JpfgbKKcqbdhWrVXJ8vpZQD72Spt4IELy1k3Dm0phoqCQHj5oOA8LgRc+vjBGN5/WH3Hl", - "6HhJrJvYnXGFprxi2SGRad/k2P6jzTDA65NI8PZINTSPW/OBJKjeu330KFHnLmc7IRzyaKh1X6BnzQXS", - "g2ajM+ERORNWDnV6xLnvioTC/uvHCYain/wx3Lfys9jKPchrHKCGMdz7psPBKEbrmK/nW6t3d+N7lBHQ", - "HROgC9Gvw3SPk3ojwIsA73a0TyUNA131ufti+o7QH5jhGQh7KPRRgnA/mEh8CWBCF0zfXxBXOYgxM38h", - "zujCdNB8Yn+SOdYkgDirGYgIxMUMMyINSWGKZhpMyOGYlbSSukshgc5B+s6XfwP10ewohkAcM7TT3/CA", - "Lz4a2j290v/0quOhO7bOTXZioTEzPIRuwkJj5ngI9WehbRpW92mlw3iOcKXyRC9pRLJhsz4EBSZUm4IM", - "EYU0dWDC9MbHbDz4X+OBiXoYDyTQ6XhgsnmYWIpK5Xro1FRANqOapXp0qvsKMbVGlAfHYO6tyY7TUsA0", - "rIBfg0rzJTPpziCApSCfozmRZEIBpZxWBZND9x80JVR/oCGiZG7KQsOYAcMTChmaUjwbopxkGTCrWE3y", - "AQJyiEaj0ZiN2TmoShgORVCUaoEsJrMs3KwkxxIx3l4QkooLyIZapo0ZppKvPZJxkOa4xAAKzfbE/l1v", - "xMVRpZjSmt+9oumdeWUPWT7dNi+ZN3hEMYbv8Rzukgu81ucjIr192Ju1kYmzjFgY8q7Vbpexdpyaw4pA", - "sYJn6AQLmoOYYEWK0WC4ebxbVb7gyrcl/lJpm5xlK58EQZpzyBBZiqfECOLEpmoeM5gD01NzhFFKCTB7", - "0ZjMGBdg4uT4JUOVCYyx7787UtO8jfu+PHzGpvw4Lg/fi2qeg5DEvk+vMhZGMyJcElR39Wio/2qabu07", - "1rPvR3A3rwOXeEIoMQz66bt9s2Jey7hK0MHzweh08P3T9/8XAAD//w==", + "7L1tc9s4tif+VVD6/7ec1Kjl9HTfrZp0TdXmppMez+1Ocp3k3hetFAORRxLGIMAAoBzFlar9NPvB9pNs", + "4YEUJQEkZcu2ZONVYgHEA3kefufg4JyrQcrzgjNgSg6eXw0KLHAOCoT5i7B3WM3/kKDOMv13BjIVpFCE", + "s8HzwdmviE+RmgPKeVZSkKAGwwHRTQVW88FwwHAOg+eDXIJKSDYYDgR8KYmAbPBciRKGA5nOIcd6aLUs", + "dFepBGGzwffvQzf5G55B++SMZ+CfV7dcd97zzk2Lti2La275P0sQy98EL4vJcnvylzzP8Q8S9FdSkCFK", + "pNLLKQQvQCgCEimOZvpxu0SQJVVoskRPYDQb2ZbJ8u+4KIZykeq1Ph1VG/iip17twPUd9Frx7yQnanu9", + "HzRt4K8kL3PEynwCQq8WmBJuqQJUKdgIPUM5YCYR44jqoUKLMo1rS8pgikuqBs//7dlwkBOm5xo8fzas", + "1kqYghmI5mL/AIU9H5altMwA5aBwhhVGhFXvsOBMwgi9YnhCIdOv0806Qh8loCmmEhAX6JneEs+JskwB", + "CqMpAZqFdqN79Hu/b6dTTWpbi35/QeyXnhIhVf1mHYWabaSlkFyElsDtwN432vuFvhUZiOvTq+RC0+gI", + "vRMwJV8RrtqX6JKoOfoBTblAemRgGWEzxPV8jqS5nfvvmtf1noY/4KIIErXr3e+lvxO8kNubehHYBnEE", + "RBgCnM7t289Iqh9jWCxDayrMNL1W9F5hJX2vmSnBqTQf3SxDEs5WBKx5DLLmWvTqMRoPpB5wPEAXsByi", + "lDOFCdNvWD8ngUKqv1pjmxmRirBUoQWmJUiU8pIpGdqZGb11Z9+1fLT8Zfb187Nn+h+9EmCG3nFRUJJi", + "vfDTf0m93avGeP+/gOng+eD/O11psVPbKk/fCT6hkNtZ1l/Yv+MMncOXEqQafB8Ofn72413M+pHhUs25", + "IN8gs9P+dBfTvuZiQrIMmJ3z57uY8w1X6DUvmdvn3+5izpecTSlJzRf9t7uhozOmQDBM0XsQCxDolRDc", + "Skb3sB77BQWhfidSnTtKNzir5inDzthqJM7g7XTw/M+rAVGQy66VmZHP+aXeseMsLAReDr4PrwY4y4he", + "Jqbv1uYK/b4p3ush+eRfYN/qxg+fvg+tCutYpt670bmW3Ss49Kfd9ifPRPXGPMI3w3I+4VhkCOteSPDL", + "EXq1ALFcqQ0iES/sJp8bWfbZCNnPyAioMatRrhNyEl3OSTpHKadlzqQTf+aTWukpR+izme6zHlvvsVSQ", + "jdlU8Bx91ktKprn6jDDL3J9a2H4eIY2APmvdJEeuVY9LUvP3igjGLOU5IDMcRr+/ev0B/fPt2RvzBBaA", + "WEkpupyDleh24wqLGSi7WK7mINAFYdmY8Smyb3I0ZoPhBqWZR7df6z/KHDMkAGca4qAcpMQzGCIBLAMB", + "mV1ZtU+zrHqXWvpvyPXhwLSmArTa9wh+10E/3t6a5Nm/hXsAW4Qbp3nL2IRJhVkK4R6tE0tYgCBq6Wcc", + "08X+HBqgLLLgqyGZf9jKnPE9Y0msAkG6iyYZ/TEru2PrkZoQnSXQ76FF6l+CT168KIrbkXtF8SClnt3W", + "tsxjqKG9UMozuAuJ55MeReGlPlwUScZzTFiwWQHOE4ent1miud8dOCLMRb4P+SuRF7dCj3rgh0iQ1b58", + "WpjICyQBGOIMYeODGVprraIkkoJTXwIvEVFoApSzmTGVtCYbswvGL9mOlIy2CHnM9knJel8JppSnAdFu", + "2vWWAoLYdMhg0do8C7cZt0u4uW1YCgugLcvOebbWvvF4pQP8rQK3TS1gFuJd0y7JN2hZWSkha2leAMu4", + "COq9Np0Y3FRQkZmm4GO7SRzjyLsVkWNGfogyp96YR+iUEoT1YY60VCALQmEGBpKPBx/GA+Mnwqhu+WEm", + "MFOEzZxLFGt4PB68rnoyxEVGrD+E3ZdOva7uq3fpfUpwCj2J9IxNeZM+19/621IZ08SZBNZxdCmIAqTm", + "WFU7Q4wjASkXxtm5vkPCprz3WiwsvxWeqQZ/iGzT3JuHcyqFXJk9lp6lwsp8Uc5WOpsz86fV6FgiAQUX", + "yri9x8xYnzNg6i7U9nWM539xwiBDShsx8pfV05yB9FjSuhkJfqmXnxMpCZv5eDTnLMFFod9X6UewpscC", + "E9rRJ51jNgvYfabd+mBBdIyj9WJHF2ApLpKp4N+AJVgF+9keHc2tA8iOlcxKkIqH2+eTjgFI16vnCxCY", + "dr18OccCuvqYBVM+wTSBrwWkqr1r13CLNOgIMO1LlnYM0eYq0O2LtCgD8sg055C3tQahjm0Orn7P3gj7", + "CJfJAfkvzm4Hu509SOB2FnRenL1DOMsESIkyUPZMqWE1ViKbW4kM6pKLi3WDcTRmN1Q3FpppTbGTlZhl", + "frNjSvEsyaAQkG7wZuNbhJAbYWrq5zicBn6XF34+A5VMYBZwu5hWwXGWYqmCPVKe5+6MxNsOLAu2zbCC", + "S7wMtgc9maDC5qZpBNW6aUclwfZCEB6eughZ57rROKrcoSSZUNiv2RkUp7sZljV7bskkA0K0CEyK6vi6", + "FkqB1dQCaGCOc4OGuDn5vaE4cofk2XVWR6sgk+15eB0f4VkDV9jrFgm92GsJ/JDgfRjC/Xc+uxVV+Duf", + "PURd6LblMcRSTrU+4gJRPkOw2N2Uut7ppYnEciY8kegz5TNzYjlmxmlrAlY+/48nF7B8Kj8jLqo/ss+o", + "oDiFOaeZGc/8ZWKgTIwTVumcsJmNB0F8OmZmaHP6OUQY/fP92zfuOFKviWBKvkGm7UqMLKePrJGWkKyy", + "8QxE+6yttTGDvFBL11Ou7Dbz4pCWssbzYMw4Liob9hf71hqW45j5TUe0shzrQ1dZn7oqPZ2GlD5sENJt", + "evs4DbpzzNvBCsKN7ky0E8rqzpBjQhPp9HfgkY3FAVNi6ZRXvydCJ6m6baYwvdhxBZuO6vURSwnisVoc", + "b3h2O74vPfBDlLTVvjyitvbtNOKEpYnd6y1xx6zVnGiRuEMkOcJ6+jFLsbBRmYwuXUSeCT2DDMlyIsEf", + "qGFESDiKIHgUK6UB7YtwaxCcTgiXyQKEDAmvCcUZJCmeEAZ+kZDSUioQITat1V+glTFIVaK4v7kok5SL", + "EBHq5oy0tU4FfAmOHD4d061qLgBnLWO3nFEBSymXpYD2Vkm5/51Ov2T+zzFfBH4uOKeBpkXmtzHnlwmf", + "yMTEB4UVlOt1iQVr0WJYqmTCA7sxrdro9LcSqYCBSAouVEjBpknQMNeNk5LQTP8d6pCuR+5sNGobSITb", + "p5Tz8NwCpxfhRs7zYOM3UgSMf713hlkKQVs8x6yc4lSVIqA6c8iTCWYXIT+hbl4qaGnW1Bn0MoY4x2js", + "kCwyjS3O50Z7yPt8bTOccUWmLqDGb3xymWCRzkNtKWdpYFFcJhcgWOCVNPCGr60HD7pe7TzIZSKAApbB", + "ZgmzoN+HS+d1DrW2SLuCX4JIJgLwBYgfu7v8taWL0zQ/dndpG6UQXIX8+Gs9qiW19JRlUdBlwiZ+Vggc", + "u2romCbfOAs1asPI38Q4/waJIjTQXrQq7JajBePnMksPN3e5wUwn/UrWhXUPd5f6tqMXbDho2+elRrNM", + "LQMS0gdRq7DuLYSt4Kvy4cl5mWP2Qx0jC18LipkNyZMFpFqeWCe2RpNpWgoBLAWHPsessPNZrLe9viba", + "NSvwod331gC5FQvBjf0QjYTG1lrOxhumQmXoHY210AG7Q74KbZuGDAnTViouFQ4wt+nRceat+7SdMNh2", + "NiWzjubWY1DTrSXYXLdngvEWv4ztUpjLpB3tsq1DUOLp9hAU0m1TCl8TbUnMyWxu7A0557Tlw9UPUH7Z", + "u3+Ovyabe/D2I6xXP3sJoaVTGN/p5jkOPzrnUoUj9FqC95IclOCOJYKd2r9kN0DUvYwztJW2C8EXRKut", + "Fsrs1PG6TzuL2eZOHlG84JTPlsEOl3gBwS+yp6DIjxLErWgwPfBDVF96X+8ETGU4Su+DiebiwtzWhCkY", + "6CFN/JbEC+uvf/f2/Qd0WkoQ8vRK/5OQ7Pup7m7PB8zhuDucYKC1k969KER1ycjdpvsFYYasX9459u3d", + "7fGAcQ1z6undisaDIRoPTOxmaWO+xwPERfUb4wppFplQGA8QpuQCvGGSjib8H2zN91q9uV3eb1vEqQMF", + "5s05RPC5wFJeclGdWQiYEamEERfJBSw/21gz/RbHrLqAa09hJpxTwOwHvdEaEjz5bD35a2Ln83DMPpN8", + "80f0mfL0IpkSqkB8foo0YFi6D+S+34kLiD01wa76w7IFMP380KzXXA4Hipfmry8lV7heil54fWVY0489", + "e7mvEAzzXvyOM/PG2s8TPG+1b7/EvCC/Q44I2RLAEIz7yDtWu/mte3VqWSfJw/5jkpuDluAmjJsu3Lqi", + "QL+xPOcMkmCIhqG4IPK0rRlPL0AkjrNIQFfbvlzMWi5OrDFnADYIkKCSiqs1C/s1XfiV+VREw2Rdp+pG", + "A3zFeaHt68Gz0bPRj53GYfXoJ5+8k5CWgqjle61s7FQTLEn6olTz+sazfsb8upprrlRhHPyABYiqt/3r", + "NRc5VoPng3/+94fqMr8ZwrRujmGzFbiAb6LMxngBTC7SxuE3Lsig8XoGP46ejX4yvqUCmG58Pvhp9Gz0", + "TIsDrOZmI6cWvZv/z3zJMLRmXbt6ZE6A3FOo4MaGckkR3PHKlxJKGKE/MMMzLd0lwJhhSqunfnE3a63s", + "NyaZhNWYfOpOlS7nXALChUnGsbRH1w3nCZpyYYWbJgJDiGfZ4PngN1Av3KaGa6l3/vRjiFWX07UcFRrh", + "9OtvE7X07+8Sj/R/wEKb3t1tRosd1uMSePR/okqm8/3TRq6Jv+4xR8AanvUkCnj7H42sBL6B6pWd6k5N", + "VjbE0GDiPz/pvTcZ9c9Pem8KzzThNI7YPhmvpfRwyh88I1Ot/Nf4wKSPWVqUckKyE3QBRsvnmGVYcWHR", + "QqXNjVPLmn9ulF9WPosTa5CcrKEFYybgCYWRSb5BBLhR3vAMXn2FVKPClzwvzP/r+y1m1pqZCCVqaa7v", + "6Hnc/JoJffz1jssGgzlHyr/zbLnTh/fFfWwARTMHarxFZHI/tfhjN/JlwCWybeiJuc+vX2T9vuq3+LRT", + "O5DMpxi+b6ah+n5DXvBM4CP4n/sQvO60SsLS1ffHRuaUrr4/NTKedPX9+V4Y9PuwVmunVyT7bimDgvLY", + "eL+a31dM69VoyGm0JoMhzV9OxWkDbUe+MvLAjU4konw2g2zMTJAUsvdZUBOR6k6QE6Ug8/Gk3YblmG2t", + "14+vPAnXdsy1dlNlcM0bbmFGuR3ivweN44VmvxJZaHNT01Yj+s5cJqwPT7rJesyaSA1dA6hdD57dH50O", + "IxB8gEDw8HWSCUEwUbZBc6viaZuNyPSVSJEckNA6QaIndaqmpGrVaObpCL1wdy7HzHn+bGQvUXJ1DVWY", + "P40JR2TlIaxuCaWYUhC/aGhqxMGYaW6HBYilmteXOLe5WS/1ldlVtLeivXV7rCN7AjnDOk8mJb3QOih/", + "asGWTeZpG+sIe63snPpckEwjMPhSYoPaUkEUCILRE5INUZ19aohcfNQQ2QMz11ZdAh+i//u//89Tw4Z2", + "qZnmTMNxOV5aJWobDCvyS7fgDWXLADJrxxn2kk5Frwy4FhRo39W+TLOemb1ukryrJdgs2fWw8vsdGGoR", + "p+6EU40LEb6au24zR+0NPVYrMM2lCyJUiSk6Md3WXB02UcJGwFB1/aZXTr0W/RV9hcetu7bzgR6+w/Cl", + "Ca7RoMye9dfKK+h1269kn2AJfeT2RkLJ1UnMraeLvIlSua72WD/drmaI/r/7VS0rELiLS88wUwh+OUWE", + "pSQzlyuBKIfCxmwdhqEQCvP68exdxzG7th/P5JPtco8YJEuyhiYdkexpdOQ9EC92h9OvNnQanr9tTBXE", + "O/dJXdH99mCx1YFzlB+HfVxHXyeywVMbhz5tamDMKjykhbyAKqG5NUks5DitnQc1sjKJz7GqDosuiZq7", + "kbQBQyRaYEpMKOgqzKzCRSZvOsV54dcmNWa8d11yOHD1CBFpBJ7HdPBcFH39lBvpx9ddlq+I8QaqKmzE", + "nSGf4KI4GbOtIBJ3sDfh2VZASXXujIvilypIFfSsY0akTccxxyyjNjL111e/v/rwCpl9nF7hokhI9r0F", + "qhbF/gxSF7u4IZuKwrweX+SHN2ykKFzSVG+4yFH6B4+L71xpmq6+fzs4H2Wd5gthS9bb2Nn+Hj2FR4xm", + "N+pnHI2f0KMy/IjvFkTyHRen2HDD6UXchQOuT3mUwxbSByx4K3BUg4rroaQwDuk0cprAAJl4+RpZeMwc", + "u8o7dZu151lvJJQ/aE/ZMar/2qtWFA3jP4AA7p/QdvWgfbpXwXiELqGX1nPvs9JayMNp3wMRREet/qOu", + "fwiOkFrXn+I8IZuZb7yS+NzcWkX6EyMyXcvVIaxfdS3C2GaG6QQJVnC/yM/OG0s4erzgxnOXn+P5WQcN", + "1skpwh4Ad/GwKrnWk67emIGPDhVET0QMa987kxXlhDav2rd423zgavW0LS8WwuDvmtNEzoucFzmvyXmn", + "V4Z7ut0sCqdzhLf5zlXN3sX/0mDJg+DI9SkNXa1PavJKeiesXt5xBk01PgTKzBeGLJotN/AGvFBBNlF8", + "F798ZJEDZBGsjpdFjsvjf2oSC3XlmlFc4BnYYtiWyexjqDQ3Parb9D1ts/+0U0aIGCFihIgN59k1jLOm", + "663VODtvThM5L3Je5Lwm5+1qnG3x3TWMs4Pyez9m5Hm+nhso2mf7tM+2OWU3+yxyyWFySTTR7kxRVVUa", + "eiUE3f2o7H01fISFERY+VliYbB6S7cc/335LY+PEbG/xQUnnJYwN9t0KBqpV1fMeGs/u3um9zrBhKxTq", + "CT7Fyx/Rae8BhcHLk5FvIt9EmLhSXJsOxD36Ltq114ZLMXJh5MLo0uihvSLfRL6J2mtwaoqW9Tx5dn19", + "DoyqJV4Ajmlub4NKSzU/rapl+hXDuam7BAJhV4mnVHNgyr2KkCYo1fyNlcO3ey+opT74hpiue/qk851I", + "4+GgLPskATS9XP2lTz0k+Is0hUJVzuoDu71r6LE/gWrqcrSZEXnRK7OJjdzZyr98on9OvBVwGslLbAkM", + "T/YS/fR6+hIUzF4yZna1p1duzpYEJr+abe0tWbKdz3vB9AKRTHPqlDQLfIUyT7qBInY5/tTHmSOxLThR", + "0V5EE8eLJvQ3PPq8w1ZkE2b+NQLAhyJuQVRiSnmq/5pW9RAJU//z55V4bCZXMw9oBB7IoWY66NUI/RJE", + "uE8Gi7YhwkUvG+Ld37ZZhnRz+cHan6ZV4LaxJfkGu7yq1gLSPl2z8YpjyuP7T3m8AWP6wy+bBj/EzSvo", + "03UOv41bPKfvKwK687vPMXXwrnUYmKn7a8LoG2XCMksLXohybzQSQzQeKhY6+DANW4a7n71r+4ZNzNdu", + "rNsslmrnWDnNhxre2YUhiidAD6XIaTxgOhxdMK0Jc0vur2g2GqfR1X3HiS4rierqthkhlsGUMGL8fnkp", + "FZoAKhn5UgZLVO9b6k6TKQHqEb0vOS1zhvgUTRNbWVqtlm1mAIkU952BThNe+AbMCyyI5AzZbXGNqYCV", + "uX6Rfx8MB7+f/cerwXAwLp89+wnq//y9+l9a/0f/dPamIdibc5vFbk//Ydc9LDAtPeP8l/4ZKW4T3As7", + "ZGpflm+oDX1UrW9Yv3n3vlZT3ndO0L5YJ2YG7Yu3Tq/sf3obuxWJssyUU7QXBXJbF5VXCg6UbIVmXQaO", + "A1crEwc9mQFL3OgjG6IwTQzOChRNqLcV6/A8sDo8FQm2pw3dE6HtlbqieR1vQBwI8vuDZ2Taj5lW2O6w", + "xfaeMacHd1m73t/Gi0BDDfragNyB5WM9Jpx1HH4tULu4tiSoTu8WqLtwcElQXh+X/t2wbPRyRZDm93L5", + "jICVowtiBejo67pHX1dAxDYcWfsUsJqg6liE9XW9wTkgPm34f7RsVRylZsFG5vqabbSB10GkJ5OGyLZm", + "++851GXOVsMRiTAyTzR+fPJBT/36ad86YB6FoQfQux6uFowwW5Wmrye7n7Jhjw8CHYtbClTtmdLEvJtz", + "SpOgzz+lfxMwBQEsBdmFrvoZO4Z7/PYOqNrkqbi/1eixG43uqofprtKE0sdjdSSUF11Z0ZV1mK6sDkZb", + "A3hHI+P3jkE7QGMPFRDB15H5nzYA1Sl8LbhQwRuar0zzGlsRhjD65/u3b5ANia4rqVNY5aUiuXnO3hES", + "rYrOTvEYgFZPAHVgFNKIyQt7e0yQwZzQrCIUba3iNdMuTAHBqKeIeCLiienL+nDn6dW0d2Jbd9hnM8K0", + "sOiGKbzL6d+9M+n+jySjVf4A07w4VlC8lRHWrIXIBvd1KE/5LHzAzrX+8V0B/H5fiQ7iOePdqkB3uN6O", + "UVd9EbAUF7KkWEGGJkvT7C5mQbYbcvUeY0bwGsFrBK89Off0yliPfTEsW+felXPieqC2hxPwHRbAVNMN", + "cjh6/WXT8N7H0qpvEQHvAwG8r1bcsuHL2x36RmbZF7NEWByzMR6GIu5doz3HKp0TNuvt2+1VpD2C4wiO", + "dwXHmrAePEDesSzMztzZty5MZNDIoLsyqKOtB8+jpj5ukEGrCLDLOYgN7C1RKSFDT1am7Fo0rBwiUVKw", + "/0vnkF4gNRcg55xm8mkrW380S4on6kdIXUmvFDjtJ3l9bg3tP0/DnvLjuCCkW7yMNK0JdRpzvcaDv12u", + "ghwy1zQcARsYkc9Iimmd1QT9ixOmVY2aE9l4E2oOqBCwILyUiDMIpE6pPAobLh8ubZqYtVsqVY5pzxWP", + "Rt7MyPCR4W9FiXbctz2HnC/WQVkDi7VV9tuSCPu8JmYdikGm2HRgrrOGnyEMFASmwqNuuWz7DLvBZxtz", + "DDd2EvkuHjjYAwfGzfXD3RXvwbPZzbSwu9S5poiBKbG8kSpON088rE4uNjjeq5qj2IgnF4dwciHMl8xO", + "5yTLgCU5sDJxOZW7g3507zoDsx3B2sx145QLBAsQS1vybIT+wAzPQMgxkwAIU2ob5C/Iiq5Smhh3RpdI", + "d9AD2Q76v0s0Aco1a3OfZPsN1Gu3n3+YxfwBrHzlNhOzITyGiJ3+4uFe2M2Scq/L1pZfgkD5NzvSbaao", + "2ahb6FOVpoJh6EFO4TSop+41+8AZm/LjuAB3WLn2q8QSloxXwhylmKE+8nzMdhXoNZ1H6X280ttMcvxV", + "hYIiWZtUexbIa4u56pci5tUafyKSoSdV5Tm3B8KkApxpA8bmv/GmnykEWRAKM49oP/lw4kpt1J3sbEN0", + "8vrE8vwlkfCAlMUOxPto6/pYiX56VdUo/t4f4pi8MSmWKc5cLUQwqWVyyCcg5JwUQ4SLQp5OucjlaXVy", + "e5rzzP13zOqi0oQSzUBmzKKcVF9cjtC5pRdbg9F8Uqe8VoTcNE60QnOLwcwZLx6VpgdjnP2wwQwe3fbB", + "3N3OS5tR/eSVtokmPFueuLeQYsa4SQNvp806oF/XIfRvTgSsDqBxqea2Fpg7fNY8Fzh3rmtN3+WZc0Rs", + "t5Ehx5LXSrnsiNqsnX4t1HaAJBpDnR4scDzu5DqGmk9kg0/bYOahCv+7AL63DE4j+Dx+8Hmq8WK391r3", + "Wmk2RCSqcSQFTUjtqnLM9uKxNl/4RVHIqC6junyYOYP9TBo4cQpZjR/ZnGTaaqwPnZZG2Nf8ZstraW60", + "FbXmnGZb1t6YNcw93R+nVe19ymczyIzpiFE6x2ymbTvNa/Zb6D6QE9Vtm/U4fHo4+rr+fksPvFl9qgtY", + "mizF5it2nlw3Bo2n1Md/cND/rLjBzU3de0unxUfDrVERx+PqAzFZ/3HQWrg2kaMODurgqIEfky28Oifp", + "Ec9V97WnJ3IOWRU36bj7HPTXSNVGg1G4Y2b43mpd2aF2/1itK+rbqG8fkeHbIyeEPVfM4FD8U72STUQ+", + "jXz6kPhU9Nab4s605nnUmZEXHyEv9svXYjKNVjlbdtecY7Z/71LfRDCRYSPDPiSGNbzTza2WxWysX3Wt", + "zuP/9YcpWc3Zi0ONl6nAUl5yYbxLYyZgRqSyLJtcwBKlnJY5kwgLQAwWIBB8Lbj0O5oq/v4oexTYiMwd", + "mft4mZv0vLGkDVZECvRkUtILU8PoqeW7E5KdGOcjkSjHLMOKi2V1W3bCs6VlyCpWXf+qsJiBQqT4xfxp", + "5nbeXzUH5uofZQhL9Our3199eIX0Mk+vSPY9fDh7dssXps7WeVy/j4RoBn8a63jH6pWb6o8UEmWgwFiF", + "nFl/T0PtVSqPhC9T6SH41HmKLudcmqAmq/u0FttEvX49dhbvVx258jgrDlt9GLm8iw4JniK+4RlsXdww", + "p4UTaNwDsfReu1Ft5byi6WNpOXYcs+tG/5x1Rua2qggP9oup4h9exeIKJzXvZJjrQSvC0CbPBBCQupo8", + "K3MQJNUy31V+dzSNs0yAlEHZviNFLhK9PAbqkosLqQlTz7WaZy9kGo2Th6lfDj6TGeWzDqcELEwxe2ec", + "1M9rBeHjr9/1gB0cVjn/keJ6mGqKOqf0Rp6ivpliv+jP30gVW2f5iXz3YJwCfHact+bxitCtbrMBSJoe", + "NZCacpHao7CTHKTEMzgZOjt/ikuqxozCAqjueqJByMnQIDPIC7VsspC2cTIiUyyycDiYY9H9mP2Uz5KM", + "pMqTI3loGqe58l5b0m1mU95WiwMzb5tcpP6mDRdCNfune76yFG8rdaqg0yv9sZxN1IEW11SQJfy2AvxW", + "J3WppN/roZrYj/JZ2BKxK44wL6qbI8B5dYhVP4fDtsfaCeR2t/WYaa3kcVvrp/s6rsfMrvb0ys35HT3Z", + "SIfxF4TLjCgjAP7iC4p+GnZJVJFb+1F/DT21/j7fGJt2y7NhoKsxKB1ybVdh1fDRFf64XOHMEemWKgvE", + "HUat8iDrSR1y7i+nJ5a1NKskW2IR07bdsV/Ja13ViZVGVwNgZW5S/JZSY7SipLQhNVfGAy78BQyxlKAS", + "YItwq8V9ntYJ4TJZgJChFA0pLaUCETJoVl/A38oYpCpR3N9clEnKhX0p22mVdXNG2lqnAr4ER855FrDQ", + "dKuaC8BZy9gLYFlgW8BSymUpoL1VUu63H6dfMv/Lni8CPxec00DTIkv9LZcJn8gEUxAq0YTf1usSCxbu", + "RLFUyYQHdmNaU57n/lYiFTAQScGF8r9tytMEZ5kI2NppMikJzfTfoQ6pkR2hRl5Wt6m87VPKeXhugdOL", + "cCPnebDxG/Gza4713hlmKSTAskAfVk5xqkoB/qXlkCcTzC4CBGyalwpamjV1hpqDnGOEZEjSmMap4N+g", + "Sd0TzilgttEhwWpn50klrQONKwgt/dNzmWCRzr2Pc5mknKWBVXGZXIBggZfCZRJcFpd9uND1audCLhMB", + "FLAMNreIrIJfgkgmAvAFiB+7u/y1pUuKJ4SB+rG7S9soheAKUtXdo1pSS09ZFgVdJmzip+dAPiCDO5Jv", + "nIUaBcH+Ly4Z598gUYQG2otWnSoVVqX0NinAeWKWHm5unIyHO+lXsi5xGx0c8Nhu+Ob92QInP1O27fMS", + "C4GZWgbE3H3nY9Kg7pxfRr+m3+VyOsciu8QC2g/ZMKUuaOndyzPj2s8h52KJ6sdDtuA/Vh2iTRijXW+P", + "jidY9qXh1y8NCZP3L9+foTmXCk1KiXCGC1fSLkDKeopIxpGMb5GMa59yH184Q28LYO//66V1dgTyMgug", + "WrFXqXxGLX7nrlOooNP448ezXzc9x54jqQr4H1uS4uj9XQ+5cUmhbOpOWUCqrTLz8UPC8xApK552PlS/", + "9FGmFv645rluiRiofNUHK62j+zy6z6P7PLrPo/v81tzn0UUeXeTRRR5d5I/GRX4cEYwr/82pEXVdLknn", + "uLFdA6bzi6o1GtDRgL6TQP9j47Q8IZvKwMtz56BKwZAma0Rs6hpnrILw5Jyy97z0NKMgb+Zn542JH6D7", + "NF4c3o0YU8wyomFCYp9ozaeEZxJhpXA6N0UGFa/jFhlXaAnKtbqL7vpH+JrSMgNPCKMjyZfVAj7gWdQa", + "UWtErRFg1DmkF/3wmesaYriqNXJa5LTIaR5O43lBCWYpNLRjjyz3v4FC9QPNVPf23FGP78+hYbiynrRW", + "iG0J7Dup4B1Wcz3uWTaIfPXA+MrIej71EluD4zwCXSOyKS9Z1mC2jWwtTIFgmJo0tyAQCMHF3bOb2I3Z", + "xA1Z7TwyWmS0PowmHgKbtSapMYxV90W6745c5U9ZExnpETPSSw9BVbnzjh0j9kSGDTxYO0lqB0oftopw", + "MDJXq5aqyeqBoMHVNk6vcpt8rCPMWO8f4dX+bf3PIIutAok9XHYHTKb7/yFB6f7bBPSzt5q/25gs0xSk", + "nJaULlEG9sO3f20uGi/mvj99KKjwhdr6hm1CsgotPJDvd71Awmscpv+1jTYqORBvi/nlSi/bUtxMWUeD", + "MqrqPqr6QdiTolbTYhc1La6tpM/vVMSf76Kiz2+koMWxqGdxLeV8j9/tPlXzeVTMveTIKr4yfMTZcE05", + "iIgo1r/PIb1AomTIjrKjz+q9nTpq66itvV4rR1TNm4Qe/9WRqO6MyK5IAtPFIJV+9yV/NUPGmILIkzGm", + "wMdyPdOW2PidHXOWhFOWRPaL7BfZT7Nfd7YVy3pScYFn0D/Lij/JSmS8yHiR8bLvp0SD2ynuLKzt2M+V", + "hUKNxwJ8d9bsEbkvcl/kPg/3Ff3Y7uxdVX2theGKyGmR0yKn+TlNgliQTi1XpT9zvRFhUmGWgkTcFv1w", + "vhbIWp0t76vJIj9Gfoz82MaPp1e2ull3IaxNnqxcvtfhzANlzPVFvK823FiHfVn1MuQibVmFqxsXpUOU", + "DscmHUweGJPEzXvM/d60m/IszPZdq4ZlhIKFzqMxO5uirBR1De9C8AXJIBsi92TJFKGI8Uv0l1XHJzCa", + "jdB48ON8PBii8eCv2XjwdHswbguCD1frqE6dRmP2oSo+nmJWTUaUBDodoY+mkL8pbT5ZL2qOWYZCZcxH", + "Laf49p3c8IR0b+n2qpfkkefV67NCZ+tN//Qsb75y9DYnJoyhesMjbxGxrUCAWB3s+HMf7JTxoBkBGFL/", + "MYVBVLtR7Qb5rSxtxtFWHG40mu45Qm8ZdX83FJa0R6NWm9kKzZhSfglZMOuN5qyY6+bxyXs+kZyCTMEE", + "qcJUgDRZJIvSm2zJtBssVJ24I5M101Icl2haUor095aIau3gKrU2p0ESlCJsJkdjdm4JwRZufTuRFQIr", + "BFkQCjM/3CrV28Z4blWDQ0MbDyggcY1Kqs/Xr5yB78uP0LW+ux20+enfV0vZF2b2ldV969kBEpBykSEj", + "zdrr6cZSuo+umIJX2vk0b4CWYzmaWI7mjioU/MEzMl3uWVC/41IdvJgeDrazV28oMazA3ry5nJN07ipN", + "5Vilcz22SSVZTaSR0JTi2cyWlbcvU0Fo2rV02HubFSM9rp7mQJTSPgy4qIeuB89Or3qXnLoLjNZlXHay", + "r8egvGNb8kgshGOETZVnI0CMPbHTAdBYdCNGN+IjhHaHIt33AS4fGSyMIPCBgMACGC7IqPoATs9u6c33", + "l5owxOAAvuoBeEirt1mUE0pS9yqbkYpd6LkKigqD4UYo4n4ElAsqeh6OVjKHMVqKdtmBbqjooHxcDkq5", + "Islt+RCMnI3A9oiArfuMR+aOfClA4xwuUFmVTq2CTp9MllWwpYu7TIinZIYGqHuXuB3VQPVaQlVKTVup", + "uFQ4ULJM90h5nrt1edszwbgtn9rSpTBxNx3tsq1DsHqabg/VP9RtUwpfk7QokzmZzU2RUTnnNPPXrFt7", + "gPLL3v1z/DXZ3IO3H2Gd/TbrNa7vZ46DTS00kIMS3NFKsFP7R+hR61F3KyhOoZViTIylJJxBeL2dtf4W", + "aaJ4wSmfLYMdLvECgu85UDzyLsyOThxRwaXUyJxsJXQed/Ih77WAbh/y5r0dzDKUYpniDJB9GhElkQBq", + "XrbLEjNqx8xdboX7iM+PEUn3g1mbeYUaGXdkTSkhJHuIRBTdxA8YTR+lt/jjJt5uIOAWjH2wEnpfjpaI", + "6x8Jro/g/RjB+4Eh9oM/JdhC9z2LWtewPljX2n2RfqWtI+aKmOuR3PDxcNytFreuzqPaeHSnEtfRyH4M", + "auDGRa5rP/316lw7Ktup1HXUIlGLPFot0q/YdcWV4XrXFeP1KnkdOS5y3OPluGsWvQ4UZVhVTqqU6HoS", + "pW7P9o4FsSMrR1aOrHyDgtqbjCxujY3PD5uJN6pzTI2JOrQ3/lteCrAUF7K0J8Cr92KW9UUTdWNdFC90", + "22oZGUxxSdXg+RRTCcMt32oULlG4HJxwuWYZcTemvyrTltTwFxOP2j4y5N1UKK8k+dFz6z6wvM2Bdn0I", + "cPAAvk33t7yNqPujqHlcun9/tdnDcGAtWrJXhe/jgAXNsuFhmWNrxtq3dPsy5tNuJcbXC9oeV2jCz8/+", + "1qfv3w4qgi1UFz/MPY04tkfHO1Y/3412/nTcxfkfDOd0qqybesBuCn4fjtsrAt8IfB8r8BU17BW7wF5x", + "Q9B7fvxq+/wYIe95BLz3DHjFDeDuo+CagwO75xHq3rOSsqWrdvXzIor173NIL5Ao2Xblq13Q7nu7hHhy", + "E1FlRJV+hs2I7B/jaDuHOe9X1x7ZLbJbZDcfu9XFVlcVaXbJgbYqDNnM/qA4yrCcTzgW2RAJkDln5l/C", + "ptz2NLHHCSULaDf2ztz4R+EfiuVyHlXq4i0e0PYwoTtUR41EHtXlQ1SXFUE/WLVZZwXog1I9xZMBp3PE", + "pyZBkh0rLB3euPYIYiNXRhAb5MZ1AHu7Vc0bnBl1dpQOUTockXTQc/NSpC36Oygn6kevJSrO64mjzIgy", + "I8qMY5QZ7fd76qJGbaJDgw1A6Ryz2Q0FyQFfA4qyJMqSKEsq2VHVvujjLVgJCuMtv4Dl6QLTElCBiWjz", + "E5y7eaKnIPJi5MUgL3Zg/yA3coYwpZ3eukMH+ZEPIx8eEB+24+kgM25h6F1YM96ej9wZubOFO3fKB2nv", + "veAecZAxwWPku8h3W3yX1DFY14q86i5DeVaPv68yCa21KFceL1fsd2hK0modrUAwrMjChIg5tv4LWnl3", + "tpPSV23PAy6lqu7lUI84AVRKyBCmnM3QJVFzVIuDlspeXTU1Q2Nvrfsu8+XH4pqHV1wTkQanBctsNtkx", + "1tt8LEFOB6Ji1mq8hSm67h8ovoWe1AbX0z60HmFf5LcYVNjBm4kNQ0oon7Vz57a+qSKYKJ+N0Cuczk3x", + "vCUiEmGkSA5IYDYDdDkHAS2hiZfYDDWhrdUkVirMXmj7nc+iLnsEJtX98snO3HFNntiNFSIHRA64ZQ6o", + "3HGdrgGFZ+jJpKQXGrXlT8OeAeeJ248zQOGZ15D+gGfItg01ftOLq10CXpt5Bd3+rAb9FC3px1Xy9yuR", + "ijBDOF4j2u9DjpI2Strbyrny0hSLt9J1FMixsnd5mmGFt5fyWoAp+5ajf75/+wbpTlvJxxSe+bydelBX", + "jctXdW5WUiwQfC0ESEk4Q3xqBLa2riVSc6xQipmp6TWBRp2vlTPUVKJrmTxcWnRT7JuedyH493HGcAiy", + "/sCTsujfVxfmOpOCabJzCcH0Q+0gprobtx/O6zpsCNH2baGf1fFHxEGPCwdhSjXJ/KC/vxO3uV5KCBIF", + "7ohGXBRx0a3notOizUSAhMR1hZAOQ1hbbroBwlqxY9QHD1gfHAeuqpydu0KrqmZ0K7qqfJx749n+MRd3", + "z1pubZGzHifSqrz/PcBWgy0i3op4697wVosMryDXAUrwo8ZfUUlE+NWEX1eWMvrkTHTOWZP+kNRVI4yi", + "0ZRtHGSmUa54NgDMuqKpzn41/tvaG+yJl6opujNeqg7GjakG7y/VoCYcJxCWAVhyT0SxaxTdnRHRQX9s", + "v4r/WGT1URNqyP+Adr9PMbDvg66uA6sdz5RuXTtH0+yWNGlHasXfQDlVacO2Kq1KVtfRAvKxVxrFAxGS", + "t24a3lQKEwW59PBBzXlYCLz08YUxuvm0+ohrR8crYt3G7owrNOUlyw6JTPsmzfYfbYYBXp/EgrdHqqF5", + "3JoPJHH13u2jR4k6dznbCeGQR0Ot+wI9Gy6QHjQbnQmPyJmwdqjTI859VyQU9l8/TjAU/eSP4bq9n8XW", + "7kNe4wA1jOHe1x0ORjFax3w130YdvBvfp4yA7pgAXYh+HaZ7nNQbAV4EeLejfUppGOiqz90X03eE/sAM", + "z0DYQ6GPEoT7wUTiSwATumD6/oK4moMYM/MX4owuTQfNJ/YnOceaBBBnFQMRgbiYYUakISlM0UyDCTkc", + "s4KWUnfJJdAFSN/58m+gPpodxRCIY4Z2+hse8MVHQ7unV/qfXnU9dMfGuclOLDRmhofQTVhozBwPof4s", + "1KVhdZ9GWoznCJdqnugljUg2rNeHIMeEalOQIaKQpg5MmN74mI0H/2s8MFEP44EEOh0PTFYPE0tRqrke", + "OjWVkc2oZqkeneq+QkyxEeXBMZh7G7LjtBAwDSvg16DS+YqZdGcQwFKQz9GCSDKhgFJOy5zJofsPmhKq", + "P9AQUbIw5aJhzIDhCYUMTSmeDdGcZBkwq1hN8gECcohGo9GYjdk5qFIYDkWQF2qJLCazLFyvZI4lYry5", + "ICQVF5ANtUwbM0wl33gk4yDNcYkBFJrtif272oiLo0oxpRW/e0XTO/PKHrJ8um1eMm/wiGIM3+MF3CUX", + "eK3PR0R6+7A3KyMTZxmxMORdo90uY+M4dQ5rAsUKnqETLGgBYoIVyUeD4fbxbln6givfFvhLqW1ylq19", + "EgTpnEOGyEo8JUYQJzZ185jBApiemiOMUkqA2YvGZMa4ABMnxy8ZKk1gjH3/7ZGa5m3c9+XhMzblx3F5", + "+F5U8wKEJPZ9epWxMJoR4YKgqqtHQ/1X3XRr37GafT+Cu34duMATQolh0E/f7ZsVi0rGlYIOng9Gp4Pv", + "n77/vwAAAP//", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index 126916ea..e598661b 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -228,6 +228,58 @@ type InfoResponse struct { Info *string `json:"info,omitempty"` } +// InstanceListResponse defines model for InstanceListResponse. +type InstanceListResponse struct { + Data InstanceListResponse_Data `json:"data"` + Meta *ListMeta `json:"meta,omitempty"` +} + +// InstanceListResponseData0 defines model for . +type InstanceListResponseData0 = []InstanceRow + +// InstanceListResponseData1 defines model for . +type InstanceListResponseData1 map[string]map[string]int + +// InstanceListResponse_Data defines model for InstanceListResponse.Data. +type InstanceListResponse_Data struct { + union json.RawMessage +} + +// InstanceRow A service instance: the state of one service on one node, as reported by +// the agent. Every property is optional: the `props` query parameter selects +// which columns the server returns. The `nodes.` and `services.` properties +// come from joined tables; `nodes.` ones are null when the node row is missing. +type InstanceRow struct { + MonAppstatus *string `json:"mon_appstatus,omitempty"` + MonAvailstatus *string `json:"mon_availstatus,omitempty"` + MonChanged *string `json:"mon_changed,omitempty"` + MonContainerstatus *string `json:"mon_containerstatus,omitempty"` + MonDiskstatus *string `json:"mon_diskstatus,omitempty"` + MonEncapFrozenAt *string `json:"mon_encap_frozen_at,omitempty"` + MonFrozen *string `json:"mon_frozen,omitempty"` + MonFrozenAt *string `json:"mon_frozen_at,omitempty"` + MonFsstatus *string `json:"mon_fsstatus,omitempty"` + MonGuestos *string `json:"mon_guestos,omitempty"` + MonHbstatus *string `json:"mon_hbstatus,omitempty"` + MonIpstatus *string `json:"mon_ipstatus,omitempty"` + MonOverallstatus *string `json:"mon_overallstatus,omitempty"` + MonSharestatus *string `json:"mon_sharestatus,omitempty"` + MonSmonGlobalExpect *string `json:"mon_smon_global_expect,omitempty"` + MonSmonStatus *string `json:"mon_smon_status,omitempty"` + MonSvctype *string `json:"mon_svctype,omitempty"` + MonSyncstatus *string `json:"mon_syncstatus,omitempty"` + MonUpdated *string `json:"mon_updated,omitempty"` + MonVcpus *int `json:"mon_vcpus,omitempty"` + MonVmem *int `json:"mon_vmem,omitempty"` + MonVmname *string `json:"mon_vmname,omitempty"` + MonVmtype *string `json:"mon_vmtype,omitempty"` + NodeId *string `json:"node_id,omitempty"` + NodesNodename *string `json:"nodes.nodename,omitempty"` + NodesOsName *string `json:"nodes.os_name,omitempty"` + ServicesSvcname *string `json:"services.svcname,omitempty"` + SvcId *string `json:"svc_id,omitempty"` +} + // IpListResponse defines model for IpListResponse. type IpListResponse struct { Data IpListResponse_Data `json:"data"` @@ -3928,6 +3980,68 @@ func (t *GroupListResponse_Data) UnmarshalJSON(b []byte) error { return err } +// AsInstanceListResponseData0 returns the union data inside the InstanceListResponse_Data as a InstanceListResponseData0 +func (t InstanceListResponse_Data) AsInstanceListResponseData0() (InstanceListResponseData0, error) { + var body InstanceListResponseData0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromInstanceListResponseData0 overwrites any union data inside the InstanceListResponse_Data as the provided InstanceListResponseData0 +func (t *InstanceListResponse_Data) FromInstanceListResponseData0(v InstanceListResponseData0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeInstanceListResponseData0 performs a merge with any union data inside the InstanceListResponse_Data, using the provided InstanceListResponseData0 +func (t *InstanceListResponse_Data) MergeInstanceListResponseData0(v InstanceListResponseData0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsInstanceListResponseData1 returns the union data inside the InstanceListResponse_Data as a InstanceListResponseData1 +func (t InstanceListResponse_Data) AsInstanceListResponseData1() (InstanceListResponseData1, error) { + var body InstanceListResponseData1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromInstanceListResponseData1 overwrites any union data inside the InstanceListResponse_Data as the provided InstanceListResponseData1 +func (t *InstanceListResponse_Data) FromInstanceListResponseData1(v InstanceListResponseData1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeInstanceListResponseData1 performs a merge with any union data inside the InstanceListResponse_Data, using the provided InstanceListResponseData1 +func (t *InstanceListResponse_Data) MergeInstanceListResponseData1(v InstanceListResponseData1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t InstanceListResponse_Data) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *InstanceListResponse_Data) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + // AsIpListResponseData0 returns the union data inside the IpListResponse_Data as a IpListResponseData0 func (t IpListResponse_Data) AsIpListResponseData0() (IpListResponseData0, error) { var body IpListResponseData0 diff --git a/server/handlers/list_query_parameters.go b/server/handlers/list_query_parameters.go index 2fd25a9a..1f74db5a 100644 --- a/server/handlers/list_query_parameters.go +++ b/server/handlers/list_query_parameters.go @@ -2,8 +2,10 @@ package serverhandlers import ( "fmt" + "slices" "strings" + "github.com/opensvc/oc3/schema" "github.com/opensvc/oc3/server" ) @@ -91,13 +93,9 @@ func buildOrderBy(orderby *server.InQueryOrderby, mapping propMapping) ([]string desc = true token = token[1:] } - def, ok := mapping.Props[token] - if !ok { - return nil, fmt.Errorf("unknown orderby prop %q", token) - } - col := def.Col - if col == nil { - return nil, fmt.Errorf("prop %q cannot be used in orderby (no column reference)", token) + col, err := resolvePropCol(token, mapping, "orderby") + if err != nil { + return nil, err } expr := col.Qualified() if desc { @@ -107,3 +105,38 @@ func buildOrderBy(orderby *server.InQueryOrderby, mapping propMapping) ([]string } return exprs, nil } + +// resolvePropCol resolves an orderby or filter prop to its column. A +// "table.column" prop is resolved through the mapping's Joins, the same way props +// selection does, so that a list can be sorted or filtered by a joined name (e.g. +// "services.svcname"). usage names the parameter in the error messages. +func resolvePropCol(token string, mapping propMapping, usage string) (*schema.Col, error) { + if table, column, ok := strings.Cut(token, "."); ok { + jd, joinKnown := mapping.Joins[table] + if !joinKnown { + return nil, fmt.Errorf("unknown %s prop %q", usage, token) + } + refMapping, refFound := propsMapping[jd.MappingKey] + if !refFound { + return nil, fmt.Errorf("unknown %s prop %q", usage, token) + } + def, ok := refMapping.Props[column] + if !ok || !slices.Contains(refMapping.Available, column) { + return nil, fmt.Errorf("unknown %s prop %q", usage, token) + } + // The join key names the table the query joins: refuse a column that lives + // elsewhere, which would produce SQL referencing an absent table. + if def.Col == nil || def.Col.T.Name != table { + return nil, fmt.Errorf("prop %q cannot be used in %s (no column reference)", token, usage) + } + return def.Col, nil + } + def, ok := mapping.Props[token] + if !ok { + return nil, fmt.Errorf("unknown %s prop %q", usage, token) + } + if def.Col == nil { + return nil, fmt.Errorf("prop %q cannot be used in %s (no column reference)", token, usage) + } + return def.Col, nil +} diff --git a/server/handlers/props_mapping.go b/server/handlers/props_mapping.go index d5a785ef..133d0ffe 100644 --- a/server/handlers/props_mapping.go +++ b/server/handlers/props_mapping.go @@ -526,6 +526,12 @@ var propsMapping = map[string]propMapping{ "mon_updated": colStr(schema.SvcmonMonUpdated), "mon_changed": colStr(schema.SvcmonMonChanged), }, + // An instance row carries only the service and node ids: the names live in + // the joined tables, as in the historical collector's svcmon table. + Joins: map[string]JoinDef{ + "nodes": {MappingKey: "node"}, + "services": {MappingKey: "service"}, + }, }, "instance_status_log": { Available: []string{ From b9ebe8d5cc96fe8982a48b1dbb40503fccba4d6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Thu, 24 Sep 2026 14:38:01 +0200 Subject: [PATCH 15/61] Expose the cluster name on the node endpoints A node names its cluster by id only. The node mapping joins the clusters table, through a LEFT JOIN since a node may name no cluster or one the collector does not know, and NodeRow gains clusters.cluster_name. --- cdb/db_nodes.go | 3 + schema/relations.go | 2 + server/api.yaml | 4 + server/codegen_server_gen.go | 348 +++++++++++++++---------------- server/codegen_type_gen.go | 17 +- server/handlers/props_mapping.go | 13 ++ 6 files changed, 206 insertions(+), 181 deletions(-) diff --git a/cdb/db_nodes.go b/cdb/db_nodes.go index 284d25b8..3bdc737b 100644 --- a/cdb/db_nodes.go +++ b/cdb/db_nodes.go @@ -52,6 +52,9 @@ func (n *DBNode) String() string { func buildNodesQuery(groups []string, isManager bool, selectExprs []string) (string, []any, error) { q := From(schema.TNodes). + // A node may name no cluster, or one the collector does not know: a plain join + // would then drop the row. + LeftJoin(schema.TClusters). RawSelect(selectExprs...) if !isManager { diff --git a/schema/relations.go b/schema/relations.go index 031f49fe..0d5001d0 100644 --- a/schema/relations.go +++ b/schema/relations.go @@ -14,6 +14,8 @@ func init() { NodeIPNodeID.Ref = NodesNodeID + NodesClusterID.Ref = ClustersClusterID + SvcmonSvcID.Ref = ServicesSvcID SvcmonNodeID.Ref = NodesNodeID SvcmonLogSvcID.Ref = ServicesSvcID diff --git a/server/api.yaml b/server/api.yaml index 351bb8d2..f6c91f14 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -7425,6 +7425,10 @@ components: type: string cluster_id: type: string + clusters.cluster_name: + type: string + nullable: true + description: Name of the node's cluster, from the joined clusters table. loc_country: type: string loc_city: diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index eb963372..7ddebe01 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -9031,180 +9031,180 @@ var swaggerSpec = []string{ "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", - "n77/vwAAAP//", + "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", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index e598661b..307e5322 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -415,13 +415,16 @@ type NodeListResponse_Data struct { // query parameter selects which columns the server returns, so a row // carries only the requested subset. type NodeRow struct { - ActionType *string `json:"action_type,omitempty"` - App *string `json:"app,omitempty"` - AssetEnv *string `json:"asset_env,omitempty"` - Assetname *string `json:"assetname,omitempty"` - BiosVersion *string `json:"bios_version,omitempty"` - BladeCabinet *string `json:"blade_cabinet,omitempty"` - ClusterId *string `json:"cluster_id,omitempty"` + ActionType *string `json:"action_type,omitempty"` + App *string `json:"app,omitempty"` + AssetEnv *string `json:"asset_env,omitempty"` + Assetname *string `json:"assetname,omitempty"` + BiosVersion *string `json:"bios_version,omitempty"` + BladeCabinet *string `json:"blade_cabinet,omitempty"` + ClusterId *string `json:"cluster_id,omitempty"` + + // ClustersClusterName Name of the node's cluster, from the joined clusters table. + ClustersClusterName *string `json:"clusters.cluster_name,omitempty"` Collector *string `json:"collector,omitempty"` ConnectTo *string `json:"connect_to,omitempty"` CpuCores *int `json:"cpu_cores,omitempty"` diff --git a/server/handlers/props_mapping.go b/server/handlers/props_mapping.go index 133d0ffe..067d52ba 100644 --- a/server/handlers/props_mapping.go +++ b/server/handlers/props_mapping.go @@ -76,6 +76,14 @@ var propsMapping = map[string]propMapping{ "svc_id": colStr(schema.ActionQueueSvcID), }, }, + "cluster": { + Available: []string{"id", "cluster_id", "cluster_name"}, + Props: map[string]propDef{ + "id": col(schema.ClustersID), + "cluster_id": colStr(schema.ClustersClusterID), + "cluster_name": colStr(schema.ClustersClusterName), + }, + }, "node": { Available: []string{ "node_id", "nodename", "app", "node_env", "cluster_id", @@ -176,6 +184,11 @@ var propsMapping = map[string]propMapping{ "os_obs_alert_date": colStr(schema.NodesOSObsAlertDate), "updated": colStr(schema.NodesUpdated), }, + // A node names its cluster by id only: the name lives in the joined table, as + // for the node and service names of an instance. + Joins: map[string]JoinDef{ + "clusters": {MappingKey: "cluster"}, + }, }, "disk": { Available: []string{ From 7028caf6ebae9c9264392e0c2a95472e63434731 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Thu, 24 Sep 2026 14:38:04 +0200 Subject: [PATCH 16/61] Fix the obsolescence setting date updates Dates are validated as YYYY-MM-DD or YYYY-MM-DD hh:mm:ss, and an empty date clears the setting instead of being rejected by the datetime column. The nodes take the setting's dates by a copy inside the database: a date read back through the driver came in RFC 3339 form, which a datetime column refuses in strict mode. The responses are typed as ObsolescenceSettingListResponse. --- cdb/db_obsolescence.go | 38 +- server/api.yaml | 66 ++- server/codegen_server_gen.go | 419 ++++++++++--------- server/codegen_type_gen.go | 127 +++++- server/handlers/post_obsolescence_setting.go | 39 +- 5 files changed, 449 insertions(+), 240 deletions(-) diff --git a/cdb/db_obsolescence.go b/cdb/db_obsolescence.go index 17807b09..4d52eb2b 100644 --- a/cdb/db_obsolescence.go +++ b/cdb/db_obsolescence.go @@ -395,11 +395,11 @@ func (oDb *DB) UpdateObsolescenceSetting(ctx context.Context, id int, fields Upd args := []any{} if fields.ObsWarnDate != nil { setClauses = append(setClauses, "obs_warn_date = ?", "obs_warn_date_updated_by = ?", "obs_warn_date_updated = NOW()") - args = append(args, *fields.ObsWarnDate, author) + args = append(args, nullIfEmpty(*fields.ObsWarnDate), author) } if fields.ObsAlertDate != nil { setClauses = append(setClauses, "obs_alert_date = ?", "obs_alert_date_updated_by = ?", "obs_alert_date_updated = NOW()") - args = append(args, *fields.ObsAlertDate, author) + args = append(args, nullIfEmpty(*fields.ObsAlertDate), author) } if len(setClauses) == 0 { return nil @@ -421,20 +421,24 @@ func (oDb *DB) DeleteObsolescenceSetting(ctx context.Context, id int) error { return nil } -func (oDb *DB) UpdateNodeObsolescenceDates(ctx context.Context, obsType, obsName string, warnDate, alertDate sql.NullString) error { +// SyncNodeObsolescenceDates copies the stored dates of an obsolescence setting to +// the nodes it applies to. Copying inside the database keeps datetime values +// intact: passing back a date read through the driver would send it in RFC 3339 +// form, which a datetime column rejects in strict mode. +func (oDb *DB) SyncNodeObsolescenceDates(ctx context.Context, id int, obsType string) error { + var query string switch obsType { case "hw": - if _, err := oDb.ExecContext(ctx, - "UPDATE nodes SET hw_obs_warn_date = ?, hw_obs_alert_date = ? WHERE model = ?", - warnDate, alertDate, obsName); err != nil { - return fmt.Errorf("UpdateNodeObsolescenceDates: %w", err) - } + query = `UPDATE nodes JOIN obsolescence o ON o.id = ? AND nodes.model = o.obs_name + SET nodes.hw_obs_warn_date = o.obs_warn_date, nodes.hw_obs_alert_date = o.obs_alert_date` case "os": - if _, err := oDb.ExecContext(ctx, - "UPDATE nodes SET os_obs_warn_date = ?, os_obs_alert_date = ? WHERE os_concat = ?", - warnDate, alertDate, obsName); err != nil { - return fmt.Errorf("UpdateNodeObsolescenceDates: %w", err) - } + query = `UPDATE nodes JOIN obsolescence o ON o.id = ? AND nodes.os_concat = o.obs_name + SET nodes.os_obs_warn_date = o.obs_warn_date, nodes.os_obs_alert_date = o.obs_alert_date` + default: + return nil + } + if _, err := oDb.ExecContext(ctx, query, id); err != nil { + return fmt.Errorf("SyncNodeObsolescenceDates: %w", err) } return nil } @@ -654,3 +658,11 @@ func (oDb *DB) UpdateNodesObsolescence(ctx context.Context) error { } return nil } + +// nullIfEmpty maps an empty date to NULL: a datetime column rejects ”. +func nullIfEmpty(value string) any { + if value == "" { + return nil + } + return value +} diff --git a/server/api.yaml b/server/api.yaml index f6c91f14..910f162b 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -4764,7 +4764,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/ObsolescenceSettingListResponse' 500: $ref: '#/components/responses/500' security: @@ -4789,10 +4789,10 @@ paths: description: Obsolescence setting record id obs_warn_date: type: string - description: Date from which nodes matching this setting are flagged as a warning + description: Date from which nodes matching this setting are flagged as a warning. "YYYY-MM-DD" or "YYYY-MM-DD hh:mm:ss"; an empty string clears the date. obs_alert_date: type: string - description: Date from which nodes matching this setting are flagged as obsolete + description: Date from which nodes matching this setting are flagged as obsolete. "YYYY-MM-DD" or "YYYY-MM-DD hh:mm:ss"; an empty string clears the date. tags: - collector responses: @@ -4801,7 +4801,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/ObsolescenceSettingListResponse' 400: $ref: '#/components/responses/400' 401: @@ -4884,7 +4884,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/ObsolescenceSettingListResponse' 404: $ref: '#/components/responses/404' 500: @@ -4913,10 +4913,10 @@ paths: properties: obs_warn_date: type: string - description: Date from which nodes matching this setting are flagged as a warning + description: Date from which nodes matching this setting are flagged as a warning. "YYYY-MM-DD" or "YYYY-MM-DD hh:mm:ss"; an empty string clears the date. obs_alert_date: type: string - description: Date from which nodes matching this setting are flagged as obsolete + description: Date from which nodes matching this setting are flagged as obsolete. "YYYY-MM-DD" or "YYYY-MM-DD hh:mm:ss"; an empty string clears the date. tags: - collector responses: @@ -4925,7 +4925,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/ObsolescenceSettingListResponse' 400: $ref: '#/components/responses/400' 401: @@ -7819,6 +7819,56 @@ components: meta: $ref: '#/components/schemas/ListMeta' + ObsolescenceSettingRow: + type: object + description: | + An obsolescence setting: the warning and alert dates applied to the nodes + running a hardware model (`obs_type` "hw") or an OS release (`obs_type` "os"). + Every property is optional: the `props` query parameter selects which columns + the server returns. Unset dates are returned as empty strings. `obs_count` is + the number of nodes the setting applies to; hardware models whose name contains + "virt" or "cluster" are not counted. + properties: + id: + type: integer + obs_type: + type: string + enum: [hw, os] + obs_name: + type: string + obs_warn_date: + type: string + obs_alert_date: + type: string + obs_warn_date_updated_by: + type: string + obs_alert_date_updated_by: + type: string + obs_warn_date_updated: + type: string + obs_alert_date_updated: + type: string + obs_count: + type: integer + + ObsolescenceSettingListResponse: + type: object + required: + - data + properties: + data: + oneOf: + - type: array + items: + $ref: '#/components/schemas/ObsolescenceSettingRow' + - type: object + additionalProperties: + type: object + additionalProperties: + type: integer + meta: + $ref: '#/components/schemas/ListMeta' + LogRow: type: object description: | diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index 7ddebe01..96879add 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -8993,218 +8993,223 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "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", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index 307e5322..57f401c4 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -14,6 +14,24 @@ const ( BearerAuthScopes bearerAuthContextKey = "bearerAuth.Scopes" ) +// Defines values for ObsolescenceSettingRowObsType. +const ( + Hw ObsolescenceSettingRowObsType = "hw" + Os ObsolescenceSettingRowObsType = "os" +) + +// Valid indicates whether the value is a known member of the ObsolescenceSettingRowObsType enum. +func (e ObsolescenceSettingRowObsType) Valid() bool { + switch e { + case Hw: + return true + case Os: + return true + default: + return false + } +} + // Defines values for PostFiltersJSONBodyFOp. const ( Equal PostFiltersJSONBodyFOp = "=" @@ -497,6 +515,45 @@ type NodeRow struct { WarrantyEnd *string `json:"warranty_end,omitempty"` } +// ObsolescenceSettingListResponse defines model for ObsolescenceSettingListResponse. +type ObsolescenceSettingListResponse struct { + Data ObsolescenceSettingListResponse_Data `json:"data"` + Meta *ListMeta `json:"meta,omitempty"` +} + +// ObsolescenceSettingListResponseData0 defines model for . +type ObsolescenceSettingListResponseData0 = []ObsolescenceSettingRow + +// ObsolescenceSettingListResponseData1 defines model for . +type ObsolescenceSettingListResponseData1 map[string]map[string]int + +// ObsolescenceSettingListResponse_Data defines model for ObsolescenceSettingListResponse.Data. +type ObsolescenceSettingListResponse_Data struct { + union json.RawMessage +} + +// ObsolescenceSettingRow An obsolescence setting: the warning and alert dates applied to the nodes +// running a hardware model (`obs_type` "hw") or an OS release (`obs_type` "os"). +// Every property is optional: the `props` query parameter selects which columns +// the server returns. Unset dates are returned as empty strings. `obs_count` is +// the number of nodes the setting applies to; hardware models whose name contains +// "virt" or "cluster" are not counted. +type ObsolescenceSettingRow struct { + Id *int `json:"id,omitempty"` + ObsAlertDate *string `json:"obs_alert_date,omitempty"` + ObsAlertDateUpdated *string `json:"obs_alert_date_updated,omitempty"` + ObsAlertDateUpdatedBy *string `json:"obs_alert_date_updated_by,omitempty"` + ObsCount *int `json:"obs_count,omitempty"` + ObsName *string `json:"obs_name,omitempty"` + ObsType *ObsolescenceSettingRowObsType `json:"obs_type,omitempty"` + ObsWarnDate *string `json:"obs_warn_date,omitempty"` + ObsWarnDateUpdated *string `json:"obs_warn_date_updated,omitempty"` + ObsWarnDateUpdatedBy *string `json:"obs_warn_date_updated_by,omitempty"` +} + +// ObsolescenceSettingRowObsType defines model for ObsolescenceSettingRow.ObsType. +type ObsolescenceSettingRowObsType string + // Problem defines model for Problem. type Problem struct { // Text A human-readable explanation specific to this occurrence of the @@ -2573,10 +2630,10 @@ type PostObsolescenceSettingsJSONBody struct { // Id Obsolescence setting record id Id string `json:"id"` - // ObsAlertDate Date from which nodes matching this setting are flagged as obsolete + // ObsAlertDate Date from which nodes matching this setting are flagged as obsolete. "YYYY-MM-DD" or "YYYY-MM-DD hh:mm:ss"; an empty string clears the date. ObsAlertDate *string `json:"obs_alert_date,omitempty"` - // ObsWarnDate Date from which nodes matching this setting are flagged as a warning + // ObsWarnDate Date from which nodes matching this setting are flagged as a warning. "YYYY-MM-DD" or "YYYY-MM-DD hh:mm:ss"; an empty string clears the date. ObsWarnDate *string `json:"obs_warn_date,omitempty"` } @@ -2606,10 +2663,10 @@ type GetObsolescenceSettingParams struct { // PostObsolescenceSettingJSONBody defines parameters for PostObsolescenceSetting. type PostObsolescenceSettingJSONBody struct { - // ObsAlertDate Date from which nodes matching this setting are flagged as obsolete + // ObsAlertDate Date from which nodes matching this setting are flagged as obsolete. "YYYY-MM-DD" or "YYYY-MM-DD hh:mm:ss"; an empty string clears the date. ObsAlertDate *string `json:"obs_alert_date,omitempty"` - // ObsWarnDate Date from which nodes matching this setting are flagged as a warning + // ObsWarnDate Date from which nodes matching this setting are flagged as a warning. "YYYY-MM-DD" or "YYYY-MM-DD hh:mm:ss"; an empty string clears the date. ObsWarnDate *string `json:"obs_warn_date,omitempty"` } @@ -4293,6 +4350,68 @@ func (t *NodeListResponse_Data) UnmarshalJSON(b []byte) error { return err } +// AsObsolescenceSettingListResponseData0 returns the union data inside the ObsolescenceSettingListResponse_Data as a ObsolescenceSettingListResponseData0 +func (t ObsolescenceSettingListResponse_Data) AsObsolescenceSettingListResponseData0() (ObsolescenceSettingListResponseData0, error) { + var body ObsolescenceSettingListResponseData0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromObsolescenceSettingListResponseData0 overwrites any union data inside the ObsolescenceSettingListResponse_Data as the provided ObsolescenceSettingListResponseData0 +func (t *ObsolescenceSettingListResponse_Data) FromObsolescenceSettingListResponseData0(v ObsolescenceSettingListResponseData0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeObsolescenceSettingListResponseData0 performs a merge with any union data inside the ObsolescenceSettingListResponse_Data, using the provided ObsolescenceSettingListResponseData0 +func (t *ObsolescenceSettingListResponse_Data) MergeObsolescenceSettingListResponseData0(v ObsolescenceSettingListResponseData0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsObsolescenceSettingListResponseData1 returns the union data inside the ObsolescenceSettingListResponse_Data as a ObsolescenceSettingListResponseData1 +func (t ObsolescenceSettingListResponse_Data) AsObsolescenceSettingListResponseData1() (ObsolescenceSettingListResponseData1, error) { + var body ObsolescenceSettingListResponseData1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromObsolescenceSettingListResponseData1 overwrites any union data inside the ObsolescenceSettingListResponse_Data as the provided ObsolescenceSettingListResponseData1 +func (t *ObsolescenceSettingListResponse_Data) FromObsolescenceSettingListResponseData1(v ObsolescenceSettingListResponseData1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeObsolescenceSettingListResponseData1 performs a merge with any union data inside the ObsolescenceSettingListResponse_Data, using the provided ObsolescenceSettingListResponseData1 +func (t *ObsolescenceSettingListResponse_Data) MergeObsolescenceSettingListResponseData1(v ObsolescenceSettingListResponseData1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t ObsolescenceSettingListResponse_Data) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *ObsolescenceSettingListResponse_Data) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + // AsServiceListResponseData0 returns the union data inside the ServiceListResponse_Data as a ServiceListResponseData0 func (t ServiceListResponse_Data) AsServiceListResponseData0() (ServiceListResponseData0, error) { var body ServiceListResponseData0 diff --git a/server/handlers/post_obsolescence_setting.go b/server/handlers/post_obsolescence_setting.go index fb6912e5..5e0ed411 100644 --- a/server/handlers/post_obsolescence_setting.go +++ b/server/handlers/post_obsolescence_setting.go @@ -8,6 +8,7 @@ import ( "net/http" "strconv" "strings" + "time" "github.com/labstack/echo/v4" @@ -60,6 +61,13 @@ func (a *Api) postObsolescenceSettingUpdate(c echo.Context, ctx context.Context, return JSONProblemf(c, http.StatusNotFound, "obsolescence setting %s not found", id) } + if _, err := parseObsDate(obsWarnDate); err != nil { + return JSONProblemf(c, http.StatusBadRequest, "invalid obs_warn_date: %s", err) + } + if _, err := parseObsDate(obsAlertDate); err != nil { + return JSONProblemf(c, http.StatusBadRequest, "invalid obs_alert_date: %s", err) + } + changes := []string{} if obsWarnDate != nil { changes = append(changes, fmt.Sprintf("obs_warn_date: %s => %s", row.ObsWarnDate.String, *obsWarnDate)) @@ -78,23 +86,20 @@ func (a *Api) postObsolescenceSettingUpdate(c echo.Context, ctx context.Context, return JSONProblemf(c, http.StatusInternalServerError, "cannot update obsolescence setting") } - if obsWarnDate != nil { - newWarn := sql.NullString{String: *obsWarnDate, Valid: true} - if err := odb.UpdateNodeObsolescenceDates(ctx, row.ObsType, row.ObsName, newWarn, row.ObsAlertDate); err != nil { + // The nodes take the setting's dates as now stored, both at once. + if obsWarnDate != nil || obsAlertDate != nil { + if err := odb.SyncNodeObsolescenceDates(ctx, row.ID, row.ObsType); err != nil { log.Error("cannot update node obsolescence dates", "id", row.ID, logkey.Error, err) return JSONProblemf(c, http.StatusInternalServerError, "cannot update node obsolescence dates") } + } + if obsWarnDate != nil { if err := odb.DeleteDashObsWithout(ctx, row.ObsName, row.ObsType, "warn"); err != nil { log.Error("cannot clean up obsolescence dashboard alerts", "id", row.ID, logkey.Error, err) return JSONProblemf(c, http.StatusInternalServerError, "cannot clean up obsolescence dashboard alerts") } } if obsAlertDate != nil { - newAlert := sql.NullString{String: *obsAlertDate, Valid: true} - if err := odb.UpdateNodeObsolescenceDates(ctx, row.ObsType, row.ObsName, row.ObsWarnDate, newAlert); err != nil { - log.Error("cannot update node obsolescence dates", "id", row.ID, logkey.Error, err) - return JSONProblemf(c, http.StatusInternalServerError, "cannot update node obsolescence dates") - } if err := odb.DeleteDashObsWithout(ctx, row.ObsName, row.ObsType, "alert"); err != nil { log.Error("cannot clean up obsolescence dashboard alerts", "id", row.ID, logkey.Error, err) return JSONProblemf(c, http.StatusInternalServerError, "cannot clean up obsolescence dashboard alerts") @@ -146,3 +151,21 @@ func (a *Api) postObsolescenceSettingUpdate(c echo.Context, ctx context.Context, return odb.GetObsolescenceSetting(ctx, idStr, p) }) } + +// obsDateLayouts are the date forms accepted for obsolescence dates: a calendar +// date, or the "YYYY-MM-DD hh:mm:ss" form the settings are listed with. +var obsDateLayouts = []string{"2006-01-02", "2006-01-02 15:04:05"} + +// parseObsDate validates an obsolescence date from a request body. An empty string +// clears the date and maps to NULL: the column is a datetime, which rejects ”. +func parseObsDate(value *string) (sql.NullString, error) { + if value == nil || *value == "" { + return sql.NullString{}, nil + } + for _, layout := range obsDateLayouts { + if _, err := time.Parse(layout, *value); err == nil { + return sql.NullString{String: *value, Valid: true}, nil + } + } + return sql.NullString{}, fmt.Errorf("%q is not a YYYY-MM-DD or YYYY-MM-DD hh:mm:ss date", *value) +} From f12ebd016946944b58f098a1815c1caa4db84365 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Thu, 24 Sep 2026 14:38:06 +0200 Subject: [PATCH 17/61] Validate filter modifications POST /filters/{filter_id} validates the resulting definition with the rules of POST /filters: known table and operator, existing column, no other filter with the same definition (409). f_label, a generated column, is refused. The transaction is committed before the filter is read back, which returned the previous values otherwise. The filter responses are typed as FilterListResponse. --- server/api.yaml | 63 ++++- server/codegen_server_gen.go | 438 +++++++++++++++++---------------- server/codegen_type_gen.go | 169 +++++++++++-- server/handlers/post_filter.go | 108 ++++++-- 4 files changed, 512 insertions(+), 266 deletions(-) diff --git a/server/api.yaml b/server/api.yaml index 910f162b..f813dfcd 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -1516,7 +1516,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/FilterListResponse' 500: $ref: '#/components/responses/500' security: @@ -1560,7 +1560,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/FilterListResponse' 400: $ref: '#/components/responses/400' 401: @@ -1621,7 +1621,10 @@ paths: /filters/{filter_id}: post: operationId: PostFilter - description: Modify a filter properties + description: | + Modify a filter definition. The resulting definition is validated as on + creation: known table and operator, existing column, no other filter with + the same definition. `f_label` is computed from the definition. parameters: - in: path name: filter_id @@ -1642,10 +1645,12 @@ paths: type: string f_op: type: string + enum: ['=', 'LIKE', '>', '>=', '<', '<=', 'IN'] f_value: type: string f_label: type: string + description: Rejected with a 400; the label is computed from the definition. tags: - collector responses: @@ -1654,7 +1659,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/FilterListResponse' 400: $ref: '#/components/responses/400' 401: @@ -1663,6 +1668,8 @@ paths: $ref: '#/components/responses/403' 404: $ref: '#/components/responses/404' + 409: + $ref: '#/components/responses/409' 500: $ref: '#/components/responses/500' security: @@ -1726,7 +1733,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/FilterListResponse' 404: $ref: '#/components/responses/404' 500: @@ -7935,6 +7942,52 @@ components: meta: $ref: '#/components/schemas/ListMeta' + FilterRow: + type: object + description: | + A filter: one condition on a column of a collector table, which filtersets + combine. Every property is optional: the `props` query parameter selects which + columns the server returns. `f_label` and `f_cksum` are computed by the + database from the definition. + properties: + id: + type: integer + f_table: + type: string + f_field: + type: string + f_op: + type: string + f_value: + type: string + nullable: true + f_label: + type: string + f_cksum: + type: string + f_author: + type: string + f_updated: + type: string + + FilterListResponse: + type: object + required: + - data + properties: + data: + oneOf: + - type: array + items: + $ref: '#/components/schemas/FilterRow' + - type: object + additionalProperties: + type: object + additionalProperties: + type: integer + meta: + $ref: '#/components/schemas/ListMeta' + AlertListResponse: type: object required: diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index 96879add..546d3591 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -8993,223 +8993,227 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "7L37cts4ti/8Kih936kkNWo5PdP7VE26pur0TtI9nt25bDvZu6ZaKQYilySMQYABQDmKK1Xnac6DnSc5", - "hQspSgJIypZtycZfiQUQF3JdfmthYa2rQcrzgjNgSg5eXA0KLHAOCoT5i7D3WM3fSFCnmf47A5kKUijC", - "2eDF4PQV4lOk5oBynpUUJKjBcEB0U4HVfDAcMJzD4MUgl6ASkg2GAwFfSiIgG7xQooThQKZzyLEeWi0L", - "3VUqQdhs8P370E3+lmfQPjnjGfjn1S3Xnfesc9Oibcvimlv+zxLE8jfBy2Ky3J78Jc9z/IME/ZUUZIgS", - "qfRyCsELEIqARIqjmX7cLhFkSRWaLNFTGM1GtmWy/BsuiqFcpHqtz0bVBr7oqVc7cH0HvVb8O8mJ2l7v", - "B00b+CvJyxyxMp+A0KsFpoRbqgBVCjZCz1EOmEnEOKJ6qNCiTOPakjKY4pKqwYt/ez4c5ITpuQYvng+r", - "tRKmYAaiudg3oLDnw7KUlhmgHBTOsMKIsOodFpxJGKHXDE8oZPp1ullH6KMENMVUAuICPddb4jlRlilA", - "YTQlQLPQbnSPfu/33XSqSW1r0ecXxH7pKRFS1W/WUajZRloKyUVoCdwO7H2jvV/oO5GBuD69Si40jY7Q", - "ewFT8hXhqn2JLomaox/QlAukRwaWETZDXM/nSJrbuf+meV3vafgDLoogUbve/V76e8ELub2pXwLbII6A", - "CEOA07l9+xlJ9WMMi2VoTYWZpteKzhVW0veamRKcSvPRzTIk4WxFwJrHIGuuRa8eo/FA6gHHA3QByyFK", - "OVOYMP2G9XMSKKT6qzW2mRGpCEsVWmBagkQpL5mSoZ2Z0Vt39l3LR8tfZl8/PX+u/9ErAWboHRcFJSnW", - "Cz/5l9TbvWqM9/8LmA5eDP6/k5UWO7Gt8uS94BMKuZ1l/YX9O87QGXwpQarB9+Hgp+c/3sWsHxku1ZwL", - "8g0yO+1f7mLaX7mYkCwDZuf86S7mfMsV+pWXzO3zr3cx50vOppSk5ov+293Q0SlTIBim6BzEAgR6LQS3", - "ktE9rMf+hYJQvxOpzhylG5xV85RhZ2w1Emfwbjp48cfVgCjIZdfKzMhn/FLv2HEWFgIvB9+HVwOcZUQv", - "E9P3a3OFft8U7/WQfPIvsG9144dP34dWhXUsU+/d6FzL7hUc+sNu+5NnonpjHuGbYTmfcCwyhHUvJPjl", - "CL1egFiu1AaRiBd2ky+MLPtshOxnZATUmNUo1wk5iS7nJJ2jlNMyZ9KJP/NJrfSUI/TZTPdZj633WCrI", - "xmwqeI4+6yUl01x9Rphl7k8tbD+PkEZAn7VukiPXqsclqfl7RQRjlvIckBkOo99f//oB/ePd6VvzBBaA", - "WEkpupyDleh24wqLGSi7WK7mINAFYdmY8Smyb3I0ZoPhBqWZR7df69/LHDMkAGca4qAcpMQzGCIBLAMB", - "mV1ZtU+zrHqXWvpvyPXhwLSmArTa9wh+10E/3t6a5Nm/hXsAW4Qbp3nL2IRJhVkK4R6tE0tYgCBq6Wcc", - "08X+HBqgLLLgqyGZf9jKnPE9Y0msAkG6iyYZ/TEru2PrkZoQnSXQ76FF6l+CT178UhS3I/eK4kFKPbut", - "bZnHUEN7oZRncBcSzyc9isJLfbgokoznmLBgswKcJw5Pb7NEc787cESYi3wf8hWRF7dCj3rgh0iQ1b58", - "WpjICyQBGOIMYeODGVprraIkkoJTXwIvEVFoApSzmTGVtCYbswvGL9mOlIy2CHnM9knJel8JppSnAdFu", - "2vWWAoLYdMhg0do8C7cZt0u4uW1YCgugLcvOebbWvvF4pQP8rQK3TS1gFuJd0y7JN2hZWSkha2leAMu4", - "COq9Np0Y3FRQkZmm4GO7SRzjyLsVkWNGfogyp96YR+iUEoT1YY60VCALQmEGBpKPBx/GA+Mnwqhu+WEm", - "MFOEzZxLFGt4PB78WvVkiIuMWH8Iuy+del3dV+/S+5TgFHoS6Smb8iZ9rr/1d6UypokzCazj6FIQBUjN", - "sap2hhhHAlIujLNzfYeETXnvtVhYfis8Uw3+ENmmuTcP51QKuTJ7LD1LhZX5opytdDZn5k+r0bFEAgou", - "lHF7j5mxPmfA1F2o7esYz//ihEGGlDZi5M+rpzkD6bGkdTMS/FIvPydSEjbz8WjOWYKLQr+v0o9gTY8F", - "JrSjTzrHbBaw+0y79cGC6BhH68WOLsBSXCRTwb8BS7AK9rM9OppbB5AdK5mVIBUPt88nHQOQrlfPFyAw", - "7Xr5co4FdPUxC6Z8gmkCXwtIVXvXruEWadARYNqXLO0Yos1VoNsXaVEG5JFpziFvaw1CHdscXP2evRH2", - "ES6TA/JfnN4Odjt9kMDtNOi8OH2PcJYJkBJloOyZUsNqrEQ2txIZ1CUXF+sG42jMbqhuLDTTmmInKzHL", - "/GbHlOJZkkEhIN3gzca3CCE3wtTUz3E4DfwuL/x8BiqZwCzgdjGtguMsxVIFe6Q8z90ZibcdWBZsm2EF", - "l3gZbA96MkGFzU3TCKp1045Kgu2FIDw8dRGyznWjcVS5Q0kyobBfszMoTnczLGv23JJJBoRoEZgU1fF1", - "LZQCq6kF0MAc5wYNcXPye0Nx5A7Js+usjlZBJtvz8Do+wrMGrrDXLRJ6sdcS+CHB+zCE++98diuq8Hc+", - "e4i60G3LY4ilnGp9xAWifIZgsbspdb3TSxOJ5Ux4ItFnymfmxHLMjNPWBKx8/h9PL2D5TH5GXFR/ZJ9R", - "QXEKc04zM575y8RAmRgnrNI5YTMbD4L4dMzM0Ob0c4gw+sf5u7fuOFKviWBKvkGm7UqMLKePrJGWkKyy", - "8QxE+6yttTGDvFBL11Ou7Dbz4pCWssbzYMw4Liob9mf71hqW45j5TUe0shzrQ1dZn7oqPZ2GlD5sENJt", - "evs4DbpzzNvBCsKN7ky0E8rqzpBjQhPp9HfgkY3FAVNi6ZRXvydCJ6m6baYwvdhxBZuO6vURSwnisVoc", - "b3l2O74vPfBDlLTVvjyitvbtNOKEpYnd6y1xx6zVnGiRuEMkOcJ6+jFLsbBRmYwuXUSeCT2DDMlyIsEf", - "qGFESDiKIHgUK6UB7YtwaxCcTgiXyQKEDAmvCcUZJCmeEAZ+kZDSUioQITZ1zXJU9avWshE+hnNofrYn", - "ErkHhlZY6wZnN1ZDWp/faDDsZslaCfvXyBmDVCWK+5uLMkm5CLGCbs5IW+tUwJfgyOEzOt2q5gJw1jJ2", - "y0kZsJRyWQpob5WU+7/s9EvmJ4r5IvBzwTkNNC0yv6U7v0z4RCYmSimsJl2vSyxYiy7FUiUTHtiNadWm", - "r7+VSAUMRFJwoUJqPk2C7gHdOCkJzfTfoQ7pevzQRqO2xES4fUo5D88tcHoRbuQ8DzZ+I0XABaH3zjBL", - "IegRyDErpzhVpQgo8BzyZILZRchbqZuXClqaNXUGfZ0hzjG4ISQRTWOLC7zRHvKBX9sZwLgiUxfW4zeB", - "uUywSOehtpSzNLAoLpMLECzwShqox9fWgwddr3Ye5DIRQAHLYLOEWdD7xKXzfYdaW6RdwS9BJBMB+ALE", - "j91d/tzSxem7H7u7tI1SCK5CpwlrPaoltfSUZVHQZcImflYIHP5qAJsm3zgLNWrzzN/EOP8GiSI00F60", - "woaWAw7jbTNLDzd3OeNMJ/1K1oV1D6eb+rajL244aNvnpcbUTC0DEtIHlN9NJKfmZksK56AUYbfjaPHM", - "8xDNgcA2facSvNEVSdvXgn8t0wibWTeACbXW5CBtEGbjpELbE2MmSmZ7ozkW2SUW5jokUPT0sxaQeomf", - "0XgwvxwPniEbdfLuHDmxuNGJy/Hg2b4OOyrrxJ7abzqEPjIJ9cZE45YQlmjN6TJCZokGkHxGxA23us1n", - "zSo7hXmJ7j1JpPjPG+9Er4xLMI6b6rqRHLPxYEGEGg/06xlXNsJ4YM/rubK3jCDbxQvTR4OtdWk9ZvV3", - "TSbLYO8WT7puDitfRw26EViZa2qfXw60umsQ/Hr/Dh3c7NG5y62e/k36mLy6J7MlshR8VT4DfV7mmP1Q", - "XzqArwXFzMY4ywJSDY0sr2n6T9NSCMOr1i4cs8LOZ6lie31NeWFW4JMX59ajcysi1439EMVsY2stwUYN", - "30vlOTsa90uHHyMkduQiTUKeGdNWKi4VDuAU06MjiEj3aTuyte1sSmYdza2iwHRrub2j2zPBeIuj23Yp", - "zO38jnbZ1iEI3nR7yKrTbVMKX5O0KJM5mc2N60TOOW35cPUDlF/27p/jr8nmHrz9COvVz97qaukUNlV1", - "8xyHH51zqcIhzy3R0EkOSnDHEsFO7V+y29bVvczpUittF4IviEbgLZTZaa7oPu0sZps7eUTxglM+WwY7", - "XOIFBL/InqLMP0oQt6LB9MAPUX3pfb0XMJXhsOcPJjyWC3P9HaZgoIc0AbESL+wB6Pt35x/QSSlByJMr", - "/U9Csu8nurs9cDXRRu60l4HWTnr3ohDVrU13PflnbRNYzO1OSm0yjPGAcQ1z6undisaDIRoPTDB8aS/R", - "VNDZ/KYRs2aRCQWNoSm5AG/cuaMJ/wdb85xXb26X99sWwu9AgXlzDhF8LrCUl1xUh8ACZkQqYcRFcgHL", - "z9YY0G9xzCpbxR5rTzingNkPeqM1JHj62R6Nromdz8Mx+0zyzR/RZ8rTi2RKqALx+RnSgGHpPpD7fk/c", - "DYMTc3tAf1i2AKafH5r1mmwbQPHS/PWl5ArXS9m0riq76p5i2sx78Z8BmDfWfkDreat9+yXmBfnPFoiQ", - "LRFhwUC6vGO1m9+6V6eWdZI8fCBHcnNyHdyEOXEIt64o0O/3m3MGSTDmzVBcEHna1oynFyASx1kkoKtt", - "Xy5mLTfR1pgzABsESFBJxdWahf2aLvzKfCqi4X1bp+pGA3zFeUH1c89Hz0c/dhqH1aOffPJOQloKopbn", - "WtnYqSZYkvSXUs3rFBL6GfPraq65UoU5MQUsQFS97V+/cpFjNXgx+Md/f6iyo5ghTOvmGDb9i7tBQ5TZ", - "GC+AyUXaiCbCBRk0Xs/gx9Hz0V+MUV8A040vBn8ZPR891+IAq7nZyIlF7+b/M192Ia1Z1+5ymiN19xQq", - "uLGhXJYZd179pYQSRugNZnimpbsEGDNMafXUzy5VgZX9xiSTsBqz9idZPxEuTHajpY0FaviB0ZQLK9w0", - "ERhCPM0GLwa/gfrFbWq4lsvsDz+GWHU5WUv6oxFOv/4281X//i6TU/8HLLTp3d2mCNphPS4jUv8nquxk", - "3z9tJO/58x6TrqzhWU/mlXf/0Ujz4huoXtmJ7tRkZUMMDSb+45Pee5NR//ik96bwTBNOI1rgkzmAkR5O", - "ecMzMtXKf40PTD6upUUpT0j2BF2A0fI5ZhlWXFi0UGlz49Sy5p8b5eeVz+KJNUierKEFYyaYqAeTzYgI", - "cKO85Rm8/gqpRoUveV6Y/9cXBs2sNTMRStTS3IfU87j5NRP6+Os9lw0Gc46Uf+fZcqcP73PhbgBFMwdq", - "vEVkkum1HC1tRJDAJbJt6KlJkKJfZP2+6rf4rFM7kMynGL5v5vX7fkNe8EzgI/if+hC87rTKatXV98dG", - "Kqquvn9ppJDq6vvTvTDo92Gt1k6uSPbdUgYF5bHxXpnfV0zr1WjIabQmgyHNX07FaQNtR74y8sCNTiSi", - "fDaDbMzMcROyFwRRE5HqTpATVR+BrPOk3YblmG2t14+vPBksd0xeeVNlcM0rw2FGuR3ivweN44Vmr4gs", - "tLmpaasRzmxuZ9eHJ91kPWZNpIauAdSuB8/uj06HEQg+QCB4+DrJnB6bawtBc6viaRtzYPpKpEgOSGid", - "INHTOvddUrVqNPNshH5xl9jHzHn+7FUJouTqXr8wfxoTjsjKQ1gFM6SYUhA/a2hqxMGYaW6HBYilmte3", - "4re5WS/1tdlVtLeivXV7rCN7AjnDOk8nJb3QOih/ZsGWzY5sG+srS1rZOfW5IJlGYPClxAa1pYIoEASj", - "pyQbojqd3xC5UM8hsgdmrq3KqjFE//d//59nhg3tUjPNmYbjcry0StQ2GFbkl27BG8qWAWTWjjPsJZ2K", - "XhlwLSjQvqt9mWY9UyXeJBtiS9xssuth5fc7MNQiTt0JpxoXInw1l4dnjtobeqxWYJpLF0SoElP0xHRb", - "c3XYoLONgKHqPmOvJKUt+iv6Co9bd20nWD58h+FLE1yjQZk966+VV9Drtl/JPsES+sjtjQy9q5OYW8+/", - "exOlcl3tsX66Xc0Q/X/3q1pWIHAXl55hphD8cooIS0lmLvkMUQ6Fjdk6DEMhFOb149mo8TG7th/PJOju", - "co8YJEuyhiYdkexZdOQ9EC92h9OvNnQanr9tTBXEO/dJXdH99mCx1YFzlB+HfVxHX09kg6c2Dn3a1MCY", - "VXhIC3kBVYUIa5JYyHFSOw9qZGUqSWBVHRZdEjV3I2kDhki0wJSYUNBVmFmFi0whCorzwq9Nasx477rk", - "cODqESLSCDyP6eC5KPr6KTfqOay7LF8T4w1UVdiIO0N+goviyZhtBZG4g70Jz7YCSqpzZ1wUP1dBqqBn", - "HTMibX6jOWYZtZGpr17//vrDa2T2cXKFiyIh2fcWqFoU+zNIXezihmwqCvN6fJEf3rCRonBZqL3hIkfp", - "HzwuvnO1vrr6/vXgfJR13kSELVlvY2f7e/QUHjGa3ShIdDR+Qo/K8CO+WxDJd1ztZ8MNpxdxFw64PvWm", - "DltIH7DgrcBRDSquh5LCOKTTyGkCA5OFYYUsPGaOXeWdus3aC1c0KnQctKfsGNV/7VUriobxH0AA909o", - "u3rQPt2rYDxCl9BL67n3WWkt5OG074EIoqNW/1HXPwRHSK3rT3CekM0kXl5JfGZurSL9iRGZruXqENav", - "uhZhbDPDdIIEK7h/yU/PGks4erzgxnOXn+P5WQcN1skpwh4Ad/GwqmHZk67emoGPDhVET0QMa987kxXl", - "hDav2rd423zgavW0rdcYwuDvm9NEzoucFzmvyXknV4Z7ut0sCqdzhLf5zh5a7+R/abDkQXDk+pSGrtYn", - "NSlyvRNWL+84g6YaHwJl5gtDFs2WG3gDflFBNlF8F798ZJEDZBGsjpdFjsvjf2ISC3XlmlFc4BmgjMgL", - "x2T2MVSamx7Vbfqettl/2ikjRIwQMULEhvPsGsZZ0/XWapydNaeJnBc5L3Jek/N2Nc62+O4axtlB+b0f", - "M/I8W88NFO2zfdpn25yym30WueQwuSSaaHemqKoqDb0Sgu5+VHZeDR9hYYSFjxUWJpuHZPvxz7ff0tg4", - "MdtbfFDSeQljg323goFqVfWih8azu3d6rzNs2AqFeoJP8fJHdNp7QGHw8mTkm8g3ESauFNemA3GPvot2", - "7bXhUoxcGLkwujR6aK/IN5FvovYanJiiZT1Pnl1fnwOjaokXgGOa29ug0lLNT6pqmX7FcGbqLoFA2FXi", - "KdUcmHKvIqQJSjV/a+Xw7d4L0ksKl3Jqium6p08634k0Hg7Ksk8SQNPL1V/61EOC/5KmUKjKWX1gt3cN", - "PfYnUE1djjYzIi96ZTaxkTtb+Zef6J8TbwWcRvISWwLDk71EP72evgQFs5eMmV3tyZWbsyWBySuzrb0l", - "S7bzeS+YXiCSaU6dkmaBr1DmSTdQxC7Hn/o4cyS2BScq2oto4njRhP6GR5932Ipswsy/RgD4UMQtiEpM", - "KU/1X9OqHiJh6n/+tBKPzeRq5gGNwAM51EwHvRqhX4II98lg0TZEuOhlQ7z72zbLkG4uP1j707QK3Da2", - "JN9gl1fVWkDap2s2XnFMeXz/KY83YEx/+GXT4Ie4eQV9us7ht3GL5/R9RUB3fvc5pg7etQ4DM3V/TRh9", - "o0xYZmnBC1HujUZiiMZDxUIHH6Zhy3D3s3dt37CJ+asb6zaLpdo5Vk7zoYZ3dmGI4gnQQylyGg+YDkcX", - "TGvC3JL7K5qNxml0dd9xostKorq6bUaIZTAljBi/X15KhSaASka+lMES1fuWutNkSoB6RO9LTsucIT5F", - "08RWllarZZsZQCLFfWeg04QXvgHzAgsiOUN2W1xjKmBlrl/k3wbDwe+n//F6MByMy+fP/wL1f/5W/S+t", - "/6N/On3bEOzNuc1it6f/sOseFpiWnnH+S/+MFLcJ7oUdMrUvyzfUhj6q1jes37x7X6sp7zsnaF+sEzOD", - "9sVbJ1f2P72N3YpEWWbKKdqLArmti8orBQdKtkKzLgPHgauViYOezoAlbvSRDVGYJgZnBYom1NuKdXge", - "WB2eigTb04buidD2Sl3RvI43IA4E+b3hGZn2Y6YVtjtssb1nzOnBXdau97fxItBQg742IHdg+ViPCWcd", - "h18L1C6uLQmq07sF6i4cXBKU18elfzcsG71cEaT5vVw+I2Dl6IJYATr6uu7R1xUQsQ1H1j4FrCaoOhZh", - "fV1vcQ6ITxv+Hy1bFUepWbCRub5mG23gdRDpyaQhsq3Z/nsOdZmz1XBEIozME40fn37QU//6rG8dMI/C", - "0APoXQ9XC0aYrUrT15PdT9mwxweBjsUtBar2TGli3s05pUnQ55/SvwmYggCWguxCV/2MHcM9fnsHVG3y", - "VNzfavTYjUZ31cN0V2lC6eOxOhLKi66s6Mo6TFdWB6OtAbyjkfF7x6AdoLGHCojg68j8TxuA6gS+Flyo", - "4A3N16Z5ja0IQxj94/zdW2RDoutK6hRWealIbp6zd4REq6KzUzwGoNUTQB0YhTRi8sLeHhNkMCc0qwhF", - "W6t4zbQLU0Aw6ikinoh4YvqyPtx5cjXtndjWHfbZjDAtLLphCu9y+nfvTLr/I8lolT/ANC+OFRRvZYQ1", - "ayGywX0dylM+Cx+wc61/fFcAv99XooN4zni3KtAdrrdj1FVfBCzFhSwpVpChydI0u4tZkO2GXL3HmBG8", - "RvAawWtPzj25MtZjXwzL1rl35Zy4Hqjt4QR8jwUw1XSDHI5ef9k0vPextOpbRMD7QADv6xW3bPjydoe+", - "kVn2xSwRFsdsjIehiHvXaM+xSueEzXr7dnsVaY/gOILjXcGxJqwHD5B3LAuzM3f2rQsTGTQy6K4M6mjr", - "wfOoqY8bZNAqAuxyDmIDe0tUSsjQ05UpuxYNK4dIlBTs/9I5pBdIzQXIOaeZfNbK1h/NkuKJ+hFSV9Ir", - "BU77SV6fW0P7z9Owp/w4LgjpFi8jTWtCncZcr/Hgb5erIIfMNQ1HwAZG5DOSYlpnNUH/4oRpVaPmRDbe", - "hJoDKgQsCC8l4gwCqVMqj8KGy4dLmyZm7ZZKlWPac8WjkTczMnxk+FtRoh33bc8g54t1UNbAYm2V/bYk", - "wj6viVmHYpApNh2Y66zhZwgDBYGp8KhbLts+w27w2cYcw42dRL6LBw72wIFxc/1wd8V78Gx2My3sLnWu", - "KWJgSixvpIrTzRMPq5OLDY73quYoNuLJxSGcXAjzJbOTOckyYEkOrExcTuXuoB/du87AbEewNnPdOOUC", - "wQLE0pY8G6E3mOEZCDlmEgBhSm2D/BlZ0VVKE+PO6BLpDnog20H/d4kmQLlmbe6TbL+B+tXt5+9mMW+A", - "la/dZmI2hMcQsdNfPNwLu1lS7nXZ2vJLECj/Zke6zRQ1G3ULfarSVDAMPcgpnAT11L1mHzhlU34cF+AO", - "K9d+lVjCkvFKmKMUM9RHno/ZrgK9pvMovY9XeptJjr+qUFAka5NqzwJ5bTFX/VLEvF7jT0Qy9LSqPOf2", - "QJhUgDNtwNj8N970M4UgC0Jh5hHtTz48caU26k52tiF68usTy/OXRMIDUhY7EO+jretjJfrJVVWj+Ht/", - "iGPyxqRYpjhztRDBpJbJIZ+AkHNSDBEuCnky5SKXJ9XJ7UnOM/ffMauLShNKNAOZMYtyUn1xOUJnll5s", - "DUbzSZ3yWhFy0zjRCs0tBjNnvHhUmh6McfbDBjN4dNsHc3c7L21G9SevtU004dnyiXsLKWaMmzTwdtqs", - "A/p1HUL/5kTA6gAal2pua4G5w2fNc4Fz57rW9F2eOUfEdhsZcix5rZTLjqjN2unXQm0HSKIx1OnBAsfj", - "Tq5jqPmJbPBpG8w8VOF/F8D3lsFpBJ/HDz5PNF7s9l7rXivNhohENY6koAmpXVWO2V481uYL/1IUMqrL", - "qC4fZs5gP5MGTpxCVuNHNieZthrrQ6elEfY1v9nyWpobbUWtOafZlrU3Zg1zT/fHaVV7n/LZDDJjOmKU", - "zjGbadtO85r9FroP5ER122Y9Dp8ejr6uv9/SA29Wn+oCliZLsfmKnSfXjUHjKfXxHxz0PytucHNT997S", - "afHRcGtUxPG4+kBM1r8ftBauTeSog4M6OGrgx2QLr85JesRz1X3t6YmcQ1bFTTruPgP9NVK10WAU7pgZ", - "vrdaV3ao3TerdUV9G/XtIzJ8e+SEsOeKGRyKf6pXsonIp5FPHxKfit56U9yZ1jyLOjPy4iPkxX75Wkym", - "0Spny+6ac8z2713qmwgmMmxk2IfEsIZ3urnVspiN9auu1Xn8v/4wJas5e3Go8TIVWMpLLox3acwEzIhU", - "lmWTC1iilNMyZxJhAYjBAgSCrwWXfkdTxd8fZY8CG5G5I3MfL3OTnjeWtMGKSIGeTkp6YWoYPbN894Rk", - "T4zzkUiUY5ZhxcWyui074dnSMmQVq65/VVjMQCFS/Gz+NHM776+aA3P1jzKEJXr1+vfXH14jvcyTK5J9", - "Dx/Ont7yhanTdR7X7yMhmsGfxTresXrlpvojhUQZKDBWIWfW39NQe5XKI+HLVHoIPnWeoss5lyaoyeo+", - "rcU2Ua9fj53G+1VHrjxOi8NWH0Yu76JDgqeIb3kGWxc3zGnhBBr3QCy9125UWzmvaPpYWo4dx+y60T+n", - "nZG5rSrCg/1iqviHV7G4wknNOxnmetCKMLTJMwEEpK4mz8ocBEm1zHeV3x1N4ywTIGVQtu9IkYtEL4+B", - "uuTiQmrC1HOt5tkLmUbj5GHql4PPZEb5rMMpAQtTzN4ZJ/XzWkH4+Ot3PWAHh1XOf6S4Hqaaos4pvZGn", - "qG+m2C/68zdSxdZZfiLfPRinAJ8d5615vCJ0q9tsAJKmRw2kplyk9ijsSQ5S4hk8GTo7f4pLqsaMwgKo", - "7vpEg5AnQ4PMIC/UsslC2sbJiEyxyMLhYI5F92P2Uz5LMpIqT47koWmc5sp7bUm3mU15Wy0OzLxtcpH6", - "mzZcCNXsn+75ylK8rdSpgk6u9MdyNlEHWlxTQZbw2wrwW53UpZJ+r4dqYj/KZ2FLxK44wryobo4A59Uh", - "Vv0cDtseayeQ293WY6a1ksdtrZ/u67geM7vakys353f0dCMdxp8QLjOijAD4ky8o+lnYJVFFbu1H/TX0", - "1Pr7fGts2i3PhoGuxqB0yLVdhVXDR1f443KFM0ekW6osEHcYtcqDrCd1yLm/nJ5Y1tKskmyJRUzbdsd+", - "Ja91VSdWGl0NgJW5SfFbSo3RipLShtRcGQ+48BcwxFKCSoAtwq0W93laJ4TLZAFChlI0pLSUCkTIoFl9", - "AX8rY5CqRHF/c1EmKRf2pWynVdbNGWlrnQr4Ehw551nAQtOtai4AZy1jL4BlgW0BSymXpYD2Vkm5336c", - "fsn8L3u+CPxccE4DTYss9bdcJnwiE0xBqEQTfluvSyxYuBPFUiUTHtiNaU15nvtbiVTAQCQFF8r/tilP", - "E5xlImBrp8mkJDTTf4c6pEZ2hBp5Wd2m8rZPKefhuQVOL8KNnOfBxm/Ez6451ntnmKWQAMsCfVg5xakq", - "BfiXlkOeTDC7CBCwaV4qaGnW1BlqDnKOEZIhSWMap4J/gyZ1TzingNlGhwSrnZ0nlbQONK4gtPRPz2WC", - "RTr3Ps5lknKWBlbFZXIBggVeCpdJcFlc9uFC16udC7lMBFDAMtjcIrIKfgkimQjAFyB+7O7y55YuKZ4Q", - "BurH7i5toxSCK0hVd49qSS09ZVkUdJmwiZ+eA/mADO5IvnEWahQE+7+4ZJx/g0QRGmgvWnWqVFiV0tuk", - "AOeJWXq4uXEyHu6kX8m6xG10cMBju+Gb92cLnPxM2bbPSywEZmoZEHP3nY9Jg7ozfhn9mn6Xy8kci+wS", - "C2g/ZMOUuqCl9y9PjWs/h5yLJaofD9mCf191iDZhjHa9PTqeYNmXhn99aUiYnL88P0VzLhWalBLhDBeu", - "pF2AlPUUkYwjGd8iGdc+5T6+cIbeFcDO/+uldXYE8jILoFqxV6l8Ri1+565TqKDT+OPH01ebnmPPkVQF", - "/I8tSXH0/q6H3LikUDZ1pywg1VaZ+fgh4XmIlBVPOx+qX/ooUwt/XPNct0QMVL7qg5XW0X0e3efRfR7d", - "59F9fmvu8+gijy7y6CKPLvJH4yI/jgjGlf/mxIi6Lpekc9zYrgHT+ZeqNRrQ0YC+k0D/Y+O0PCGbysDL", - "c2egSsGQJmtEbOoaZ6yC8OScsve89DSjIG/mp2eNiR+g+zReHN6NGFPMMqJhQmKfaM2nhGcSYaVwOjdF", - "BhWv4xYZV2gJyrW6i+76R/ia0jIDTwijI8mX1QI+4FnUGlFrRK0RYNQ5pBf98JnrGmK4qjVyWuS0yGke", - "TuN5QQlmKTS0Y48s97+BQvUDzVT39txRj+/PoWG4sp60VohtCew7qeA9VnM97mk2iHz1wPjKyHo+9RJb", - "g+M8Al0jsikvWdZgto1sLUyBYJiaNLcgEAjBxd2zm9iN2cQNWe0sMlpktD6MJh4Cm7UmqTGMVfdFuu+O", - "XOVPWRMZ6REz0ksPQVW5844dI/ZEhg08WDtJagdKH7aKcDAyV6uWqsnqgaDB1TZOrnKbfKwjzFjvH+HV", - "/m39zyCLrQKJPVx2B0ym+7+RoHT/bQL6yVvN321MlmkKUk5LSpcoA/vh2782F40Xc9+fPhRU+Iva+oZt", - "QrIKLTyQ73e9QMJrHKb/uY02KjkQb4v55Uov21LcTFlHgzKq6j6q+kHYk6JW02IXNS2uraTP7lTEn+2i", - "os9upKDFsahncS3lfI/f7T5V81lUzL3kyCq+MnzE2XBNOYiIKNa/zyG9QKJkyI6yo8/q3E4dtXXU1l6v", - "lSOq5k1Cj//qSFR3RmRXJIHpYpBKv/uSr8yQMaYg8mSMKfCxXM+0JTZ+Z8ecJeGUJZH9IvtF9tPs151t", - "xbKeVFzgGfTPsuJPshIZLzJeZLzs+wnR4HaKOwtrO/ZzZaFQ47EA3502e0Tui9wXuc/DfUU/tjt9X1Vf", - "a2G4InJa5LTIaX5OkyAWpFPLVenPXG9EmFSYpSARt0U/nK8FslZny3k1WeTHyI+RH9v48eTKVjfrLoS1", - "yZOVy/c6nHmgjLm+iPNqw4112JdVL0Mu0pZVuLpxUTpE6XBs0sHkgTFJ3LzH3Oem3ZRnYbbvWjUsIxQs", - "dB6N2ekUZaWoa3gXgi9IBtkQuSdLpghFjF+iP606PoXRbITGgx/n48EQjQd/zsaDZ9uDcVsQfLhaR3Xq", - "NBqzD1Xx8RSzajKiJNDpCH00hfxNafPJelFzzDIUKmM+ajnFt+/khieke0u3V70kjzyvXp8VOltv+i/P", - "8+YrR+9yYsIYqjc88hYR2woEiNXBjj/3wU4ZD5oRgCH1H1MYRLUb1W6Q38rSZhxtxeFGo+meI/SOUfd3", - "Q2FJezRqtZmt0Iwp5ZeQBbPeaM6KuW4en7znE8kpyBRMkCpMBUiTRbIovcmWTLvBQtWJOzJZMy3FcYmm", - "JaVIf2+JqNYOrlJrcxokQSnCZnI0ZmeWEGzh1ncTWSGwQpAFoTDzw61SvWuM51Y1ODS08YACEteopPp8", - "/coZ+L78CF3ru9tBm5/+vFrKvjCzr6zuO88OkICUiwwZadZeTzeW0n10xRS80s6neQO0HMvRHC8u9XzS", - "Iyu8+4ZnZLrcs+x+z6U6eMk9HGwntN7Qa1iBvYxzOSfp3BWfyrFK53psk12ymkiDoynFs5mtNG9fpoIR", - "Gg/++c9//vOHN29+ePVqPNDAufkLms9f5PkLKceDn/VHgLxQy8pTk1LAwr55vcBRaA9r6bb3tgWM9LiG", - "CG51D/ejQW+Fq6MevS68PLnqXTLrLjBml3HcKWs8BvEd28JHYuEcI+yrPDMBYuyJ/Q6AxqIb9JHAzaOs", - "p3WX0PRQBP4+wHGEtQcCayOIfbggtgCGCzKqvonDCVt6//xSE54YHMDZ2AF4qKu3WZQTSlL3KpuRol3o", - "vwpKC4P5RijofqSpC+p6EY4WM4dhWuR3mbZuqOggflwOYrkiyW35EIxcjsD8iIC5+4xH5vt9KUDjKC5Q", - "WZWurYJ+n06WVbCri3tNiKdkiUbTe5e4HdVY9VpCVWJNW6m4VDhQMk73SHmeu3V52zPBuC1f29KlMHFP", - "He2yrUOwep1uD9Wf1G1TCl+TtCiTOZnNTZFXOec089cMXHuA8sve/XP8Ndncg7cfYZ39Nutlru9njoNN", - "LTSQgxLc0UqwU/tH6FFrU3crKE6hlWJMjKsknEF4vZ21FhdponjBKZ8tgx0u8QKC7zlQvPMuLJFOHFHB", - "pdTInGwldB538ifvtYxuH/jmvSnMMpRimeIMkH0aESWRAGpetsvSM2rHzF0+kPu4HxEjwu4HszbzOjUy", - "HsmaUkJI9hCJKLq5HzCaPkrX9sdNvN1AwC0Y+2Al9L4cLRHXPxJcH8H7MYL3A0PsB39KsIXuexYVr2F9", - "sK64+yL9SotHzBUx1yO5YeXhuFstLl6dR7Xx6E4lxqOR/RjUwI2LjNd++uvVGXdUtlOp8ahFohZ5tFqk", - "X7HxiivD9cYrxutVcjxyXOS4x8tx1yw6HiiKsapcVSnR9SRW3Z7tHQuSR1aOrBxZ+QYFzTcZWdwaG58d", - "NhNvVEeZGhN1aDMutLwUYCkuZGlPgFfvxSzriybqxrooXui21TIymOKSqsGLKaYShlu+1ShconA5OOFy", - "zTLubkx/VawtqeEv5h61fWTIu6kQX0nyo+fWfWB5m4Pu+hDg4AF8m+5veRtR90dR87h0//5q44fhwFq0", - "ZK8K68cBC5pl28Myx9bstW/p9mXMp91KvK8XFD6u0ISfnv+1T9+/HlQEW134eMU/zYOpwM3rx8o7Vj/f", - "jXbekXMOrQbzg+GcTpV1Uw/YTcHvw3F7ReAbge9jBb6ihr1iF9grbgh6z45fbZ8dI+Q9i4D3ngGvuAHc", - "fRRcc3Bg9yxC3XtWUrZ02K5+XkSx/n0O6QUSJduuPLYL2j23S4gnNxFVRlTpZ9iMyP4xjrZzmPNeufbI", - "bpHdIrv52K0udruqCLRLDrRVYc5m9gfFUYblfMKxyIZIgMw5M/8SNuW2p4k9TihZQLuxd+rGPwr/UCxX", - "9KhSL2/xgLaHCd2hOm0k8qguH6K6rAj6warNOitAH5TqKV4NOJ0jPjUJkuxYYenw1rVHEBu5MoLYIDeu", - "A9jbrSrf4Myos6N0iNLhiKSDnpuXIm3R30E5UT96LVFxVk8cZUaUGVFmHKPMaL/fUxdlahMdGmwASueY", - "zW4oSA74GlCUJVGWRFlSyY6q9kUfb8FKUBhv+QUsTxaYloAKTESbn+DMzRM9BZEXIy8GebED+we5kTOE", - "Ke301h06yI98GPnwgPiwHU8HmXELQ+/CmvH2fOTOyJ0t3LlTPkh77wX3iIOMCR4j30W+2+K7pI7Bulbk", - "VXcZytN6/H2VSWitRbnyeLnKxENT8lbraAWCYUUWJkTMsfWf0Mq7s52Uvmp7EXApVXUvh3rECaBSQoYw", - "5WyGLomao1octFT26qqpGRp7a913mS8/Ftc8vOKaiDQ4LVhms8mOsd7mYwlyOhAVs1bjLUzRdf9A8S30", - "tDa4nvWh9Qj7Ir/FoMIO3kxsGFJC+aydO7f1TRXBRPlshF7jdG6K5y0RkQgjRXJAArMZoMs5CGgJTbzE", - "ZqgJba0msVJh9kLb73wWddkjMKnul0925o5r8sRurBA5IHLALXNA5Y7rdA0oPENPJyW90Kgtfxb2DDhP", - "3H6cAQrPvIb0BzxDtm2o8ZteXO0S8NrMK+j2RzXop2hJP66Sv1+JVIQZwvEa0X4fcpS0UdLeVs6Vl6ZY", - "vJWuo0COlb3L0wwrvL2UXwWYsm85+sf5u7dId9pKPqbwzOft1IO6aly+qnOzkmKB4GshQErCGeJTI7C1", - "dS2RmmOFUsxMTa8JNOp8rZyhphJdy+Th0qKbYt/0vAvBv48zhkOQ9QeelEX/vrow15kUTJOdSwimH2oH", - "MdXduP1wXtdhQ4i2bwv9rI4/Ig56XDgIU6pJ5gf9/Z24zfVSQpAocEc04qKIi249F50WbSYCJCSuK4R0", - "GMLactMNENaKHaM+eMD64DhwVeXs3BVaVTWjW9FV5ePcG8/2j7m4e9Zya4uc9TiRVuX97wG2GmwR8VbE", - "W/eGt1pkeAW5DlCCHzX+ikoiwq8m/LqylNEnZ6Jzzpr0h6SuGmEUjaZs4yAzjXLFswFg1hVNdfrK+G9r", - "b7AnXqqm6M54qToYN6YavL9Ug5pwnEBYBmDJPRHFrlF0d0ZEB/2x/Sr+Y5HVR02oIf8D2v0+xcC+D7q6", - "Dqx2PFO6de0cTbNb0qQdqRV/A+VUpQ3bqrQqWV1HC8jHXmkUD0RI3rppeFMpTBTk0sMHNedhIfDSxxfG", - "6ObT6iOuHR2viHUbuzOu0JSXLDskMu2bNNt/tBkGeH0SC94eqYbmcWs+kMTVe7ePHiXq3OVsJ4RDHg21", - "7gv0bLhAetBsdCY8ImfC2qFOjzj3XZFQ2H/9OMFQ9JM/huv2fhZbuw95jQPUMIY7rzscjGK0jvlqvo06", - "eDe+TxkB3TEBuhD9Okz3OKk3ArwI8G5H+5TSMNBVn7svpu8IvcEMz0DYQ6GPEoT7wUTiSwATumD6/oy4", - "moMYM/MX4owuTQfNJ/YnOceaBBBnFQMRgbiYYUakISlM0UyDCTkcs4KWUnfJJdAFSN/58m+gPpodxRCI", - "Y4Z2+hse8MVHQ7snV/qfXnU9dMfGuclOLDRmhofQTVhozBwPof4s1KVhdZ9GWowXCJdqnugljUg2rNeH", - "IMeEalOQIaKQpg5MmN74mI0H/2s8MFEP44EEOh0PTFYPE0tRqrkeOjWVkc2oZqkeneq+QkyxEeXBMZh7", - "G7LjpBAwDSvgX0Gl8xUz6c4ggKUgX6AFkWRCAaWcljmTQ/cfNCVUf6AhomRhykXDmAHDEwoZmlI8G6I5", - "yTJgVrGa5AME5BCNRqMxG7MzUKUwHIogL9QSWUxmWbheyRxLxHhzQUgqLiAbapk2ZphKvvFIxkGa4xID", - "KDTbE/t3tREXR5ViSit+94qm9+aVPWT5dNu8ZN7gEcUYnuMF3CUXeK3PR0R6+7A3KyMTZxmxMOR9o90u", - "Y+M4dQ5rAsUKnqETLGgBYoIVyUeD4fbxbln6givfFfhLqW1ylq19EgTpnEOGyEo8JUYQJzZ185jBApie", - "miOMUkqA2YvGZMa4ABMnxy8ZKk1gjH3/7ZGa5m3c9+XhUzblx3F5+F5U8wKEJPZ9epWxMJoR4YKgqqtH", - "Q/1X3XRr37GafT+Cu34duMATQolh0E/f7ZsVi0rGlYIOXgxGJ4Pvn77/vwAAAP//", + "7L37jts6tif8KoS/b5AE7e3K7t5ngM5GA5OTy+7qs3M5leQcNLYDhZaWLXZJpEJSrjiFAPM082DzJANe", + "JMs2KclVdpXt4l9JmRQv0rr81uLiWteDmOUFo0ClGDy7HhSY4xwkcP0Xoe+xTN8IkOeJ+jsBEXNSSMLo", + "4Nng/CViUyRTQDlLygwEyMFwQFRTgWU6GA4ozmHwbJALkBFJBsMBh68l4ZAMnklewnAg4hRyrIaWi0J1", + "FZITOhv8+DG0k79lCbRPTlkC7nlVy03nvejcNG/bMr/hlv+zBL74jbOymCw2J3/B8hz/JEB9JQkJyoiQ", + "ajkFZwVwSUAgydBMPW6WCKLMJJos0GMYzUamZbL4Gy6KoZjHaq1PRtUGvqqplzuwfQe9Vvw7yYncXO9H", + "RRv4G8nLHNEynwBXqwUquV0qB1lyOkJPUQ6YCkQZytRQvkXpxpUlJTDFZSYHz/7t6XCQE6rmGjx7OqzW", + "SqiEGfDmYt+AxI4PS+OsTADlIHGCJUaEVu+wYFTACL2ieJJBol6nnXWEPglAU5wJQIyjp2pLLCfSMAVI", + "jKYEssS3G9Wj3/t9N50qUttY9IdLYr70lHAh6zdrKVRvIy65YNy3BGYGdr7R3i/0HU+A35xeBeOKRkfo", + "PYcp+YZw1b5AV0Sm6Cc0ZRypkYEmhM4QU/NZkmZm7r8pXld7Gv6Ei8JL1LZ3v5f+nrNCbG7quWcbxBIQ", + "oQhwnJq3n5BYPUYxX/jWVOhpeq3og8RSuF4zlZxlQn90vQxBGF0SsOIxSJprUavHaDwQasDxAF3CYohi", + "RiUmVL1h9ZyADGL11RrbTIiQhMYSzXFWgkAxK6kUvp3p0Vt39kPJR8Nfel+/PH2q/lErAarpHRdFRmKs", + "Fn72L6G2e90Y7//nMB08G/x/Z0stdmZaxdl7ziYZ5GaW1Rf27zhBF/C1BCEHP4aDX57+fBezfqK4lCnj", + "5DskZtq/3MW0rxmfkCQBaub85S7mfMskes1Kavf517uY8wWj04zE+ov+293Q0TmVwCnO0Afgc+DoFefM", + "SEb7sBr7eQZc/k6EvLCUrnFWzVOanbHRSIzCu+ng2R/XAyIhF10r0yNfsCu1Y8tZmHO8GPwYXg9wkhC1", + "TJy9X5nL9/u6eK+HZJN/gXmraz98/jE0KqxjmWrvWucadq/g0B9m258dE9UbcwjfBIt0wjBPEFa9EGdX", + "I/RqDnyxVBtEIFaYTT7TsuyLFrJfkBZQY1qjXCvkBLpKSZyimGVlToUVf/qTGukpRuiLnu6LGlvtsZSQ", + "jOmUsxx9UUuKprn8gjBN7J9K2H4ZIYWAvijdJEa2VY1LYv33kgjGNGY5ID0cRr+/ev0R/ePd+Vv9BOaA", + "aJll6CoFI9HNxiXmM5BmsUymwNElocmYsikyb3I0poPhGqXpRzdf69/LHFPEAScK4qAchMAzGCIONAEO", + "iVlZtU+9rHqXSvqvyfXhQLfGHJTadwh+20E93t4a5cm/+XsAnfsbp3nL2IQKiWkM/h6tEwuYAydy4WYc", + "3cX87BugLBLvqyGJe9jKnHE9Y0isAkGqiyIZ9TEru2PjkZoQrSXQ76F57F6CS148L4r9yL2iOEmpZ7a1", + "KfMoamgvFLME7kLiuaRHUTipDxdFlLAcE+ptloDzyOLpTZZo7ncLjvBzketDviTici/0qAY+RYKs9uXS", + "wkRcIgFAEaMIax/M0FhrFSWRGKz64niBiEQTyBidaVNJabIxvaTsim5JyWiDkMd0l5Ss9hXhLGOxR7Tr", + "drUljyDWHRKYtzbP/G3a7eJvbhs2gzlkLcvOWbLSvvZ4pQPcrRy3Tc1h5uNd3S7Id2hZWSkgaWmeA00Y", + "9+q9Np3o3ZRXkekm72PbSZzXJJPA9yJzzNCnKHWWO3PInalufIYYBRQzanZjZJARAMazEbNMCQfGkVRw", + "Zmi1nXlagDSAe0Io3Fr+mKHVeC22wzTK8AQyawJMo/hSlPkXDe0rYwJNFurZMVUvZoKFtQa0Hw+mhOqd", + "ukTZNDJuBSe92qk8bdo76WnTC/a0scLTIA14dLa1Qd5ppB1KvSCoGwy4SFb70ffCfXrkU2S+emMO3isF", + "cHOEMFJMQeYkgxloi3g8+DgeaDctRnXLTzOOqSR0Zk8ksLJOx4PXVU+KGE+IcUfS+4K0N4We9S6dT3Hm", + "ZAPXpz2nU9akz9W3/q6U2jNgLXIj3a44kYBkimW1M0QZ4hAzrs8aVndI6JT1XouxivfCM9Xgp8g2zb05", + "OKfCw5XXwdCzkFjqL6qUWdVFazOwgBoLxKFg3KiHMdXOnxlQeReo+Sa+q38xQiExSlf8unyaURAOR5Zq", + "RpxdqeXnRAhCZy4ezRmNcFGo91W6DUjdY45J1tEnTjGdeXSQbjdHIMA7xlGwtKML0BgX0ZSz70AjLL39", + "TI+O5tYBRMdKZiUIyfzt6aRjANL16tkcOM66Xr5IMYeuPnrBGZvgLIJvBcSyvWvXcPPY64fT7QsadwzR", + "BltU+zwuSo880s055G2tXkvDNHtXv2NnoHmEieiA3Ifn+8Fu5ycJ3M69vsPz9wgnCQchUALSHOk2nDaV", + "yGZGIoO8Yvxy1V8zGtP9G0kuJ02SeKyaDM+iBAoO8RpvNr6FD7kRKqdujsOx53dx6eYzkNEEZh6vp27l", + "DCcxFtLbI2Z5bo8one1AE2/bDEu4wgtvu/cgAaTf26MbQbZu2lKJt73ghPmnLnzOMdWo/cQ2JoD4jMkb", + "e3284nQ7v07NnhsySYMQJQKjoooeqYWSZzW1ABroaAqvH0wHXtxSHNkYleQmq8uqGK/NeVgdnuRYA5M4", + "62ux31jg+wTvaQj339lsL6rwdzY7RV1ot+UwxJZ+wYzNEMy3N6VuFjygAyGtCU8E+pKxmQ4YGFN9ZqLj", + "xb78j8eXsHgiviDGqz+SL6jIcAwpyxI9nv6r8hWiHMs4JXRmwrEQm46pHloHHwwRRv/48O6tjQZQayI4", + "I98hUXYlRobTR8ZIi0hS2Xgaomnf5JhCXsiF7SmWdpt+cUhJWe150GYc45UN+6t5aw3LcUzdpiNaWo51", + "zIOogx6kmk5BShc28Ok2tX0ce905+u1gCf5GG5LQCWVVZ8gxySJh9bfnkbXFAZV8YZVXvyd8gQyqbSZx", + "drnlCtbPiVZHLAXwh2pxvGXJfnxfauBTlLTVvhyitvbtNML0hQ6d7S1xx7TVnGiRuEMkGMJq+jGNMTdB", + "0TRb2IBYHfkJCRLlRIA7TkqLEH8QjzcSQggN2uf+Vi84nRAmojlw4RNekwwnEMV4Qii4RUKclUIC97Gp", + "bRajql+1lrXoTZxD87M9Esg+MFweSlm7sRrS+PxGg2E3S9ZK2L1GRinEMpLM3VyUUcy4jxVUc0LaWqcc", + "vnpH9h+Rq1aZcsBJy9gtB9VA44yJkkN7q8iY+8tOvyZuokjnnp8LxjJP0zxxW7rpVcQmItJBgn41aXtd", + "YU5bdCkWMpowz250qzJ93a1ESKDAo4Jx6VPzceR1D6jGSUmyRP3t6xCvhu+tNSpLjPvbpxlj/rk5ji/9", + "jYzl3sbvpPC4INTeKaYxeD0COablFMey5B4FnkMeTTC99HkrVfNCQkuzok6vr9PHORo3+CSibmxxgTfa", + "fT7wGzsDKJNkaqPq3CYwExHmceprixmNPYtiIroETj2vpIF6XG09eND2audBJiIOGWDhbRYw83qfmLC+", + "b19ri7Qr2BXwaMIBXwL/ubvLn1u6WH33c3eXtlEKzqTvNGGlR7Wklp6iLIpsEdGJmxU8h78KwMbRd0Z9", + "jco8czdRxr5DJEnmaS9aYUPLAYf2tuml+5u7nHG6k3olq8K6h9NNft/SFzcctO3zSmFqKhceCekCyu8m", + "gmX6YlkMH0BKQvfjaHHMc4rmgGebrlMJ1uiKhOlrwL+SaYTOjBtA33RQ5CBMDHTjpELZE2PKS2p6oxTz", + "5ApzfRsZMvT4ixKQaolf0HiQXo0HT5CJOnn3AVmxuNaJifHgya4OOyrrxJzarzuEPlEB9cZ445IeFmjF", + "6TJCeokakHxBxA63vExrzCozhX6J9j0JJNmva+9ErYwJ0I6b6rafGNPxYE64HA/U6xlXNsJ4YM7rmTSX", + "/CDZxgvTR4OtdGk9ZnV3jSYLb+8WT7pq9itfSw2qEWiZK2pPrwZK3TUIfrV/hw5u9ujc5UZP9yZdTF5d", + "U9sQWRK+SZeBnpY5pj/Vd37gW5Fhaq4YiAJiBY0Mryn6j+OSc82rxi4c08LMZ6hic31NeaFX4JIXH4xH", + "Zy8i1459imK2sbWWYKOG76XynB2N+6XDj+ETO2IeRz7PjG4rJRMSe3CK7tERRKT6tB3ZmnY6JbOO5lZR", + "oLu1XJ5T7QmnrMXRbboUOjlGR7to6+AFb6rdZ9WptmkG36K4KKOUzFLtOhEpy1o+XP1Axq5698/xt2h9", + "D85+hPbqZy5VtnTym6qqOcX+R1MmpP/GQctlhCgHyZllCW+n9i/ZbeuqXvp0qZW2C87mRCHwFsrsNFdU", + "n3YWM82dPCJZwTI2W3g7XOE5eL/Iji55fBJ7uuKhBj5F9aX29Z7DVPjDnj/q8FjGdfYJmIKGHkIHxAo8", + "Nweg7999+IjOSgFcnF2rfyKS/DhT3c2Bq442sqe9FJR2UrvnBa8uTdvsAL8qm8BgbntSanLRjAeUKZhT", + "T29XNB4M0Xigg+FLc4etgs76N4WYFYtMMlAYOiOX4Iw7tzTh/mArnvPqzW3zfttC+C0o0G/OIoIvBRbi", + "ivHqEJjDjAjJtbiILmFhrqrotzimla1ijrUnjGWA6U9qozUkePzFHI2uiJ0vwzH9QvL1H9GXjMWXkbmb", + "8+UJUoBhYT+Q/X6P7A2DM317QH1YOgeqnh/q9ZpLMhle6L++lkzieinr1lVlV91TTJt+L+4zAP3G2g9o", + "HW+1b79IvyD32QLhoiUizBtIl3esdv1b9+rUsk6S+w/kSK5Prr2b0CcO/tYlBbr9fimjEHlj3jTFeZGn", + "aU1YfAk8spxFPLra9GV81nIRdIU5PbCBgwAZVVytWNit6fyvzKUiGt63VapuNMA3nBeZeu7p6Ono507j", + "sHr0s0veCYhLTuTig1I2ZqoJFiR+Xsq0zuCintG/LudKpSz0iSlgDrzqbf56zXiO5eDZ4B///bFKTqSH", + "0K3rY5jsS/YGDZF6Y6wAKuZxI5oIF2TQeD2Dn0dPR3/RRn0BVDU+G/xl9HT0VIkDLFO9kTOD3vX/Z67k", + "Xkqzrlyl1kfq9ilUMG1D2SRP9rz6awkljNAbTPFMSXcBMKY4y6qnfrWZQozs1yaZgOWYtT/J+IlwoZOL", + "LUwsUMMPjKaMG+GmiEAT4nkyeDb4DeRzu6nhSirBP9wYYtnlbCXnlkI4/fqbxHP9+9tEav0fMNCmd3eT", + "oWuL9diEZP2fqJID/vi8ljvrzzvMebSCZx2Jj979RyPLkmugemVnqlOTlTUxNJj4j89q701G/eOz2pvE", + "M0U4jWiBz/oARjg45Q1LyFQp/xU+0OnwFgalPCLJI3QJWsvnmCZYMm7QQqXNtVPLmH92lF+XPotHxiB5", + "tIIWtJmgox50MjHCwY7yliXw6hvEChW+YHmh/19fGNSz1sxEMiIX+j6kmsfOr5jQxV/vmWgwmHWk/DtL", + "Flt9eJcLdw0o6jlQ4y0incuy5WhpLYIErpBpQ491fiL1Iuv3Vb/FJ53agSQuxfBjPa3mj1vygmMCF8H/", + "0ofgVadlUrmuvj83MsF19f1LI4NbV99f7oVBfwxrtXZ2TZIfhjIykA4b76X+fcm0To2GrEZrMhhS/GVV", + "nDLQtuQrLQ/s6ESgjM1mkIypPm5C5oIgaiJS1QlyIusjkFWeNNswHLOp9frxlSOB7Ja5Y2+rDG54ZdjP", + "KPsh/nvQOE5o9pKIQpmbirYa4cz6dnZ9eNJN1mPaRGroBkDtZvDs/uh0GIDgCQLBw9dJ+vRYX1vwmlsV", + "T5uYA91XIElyQFzpBIEe16kno6pVoZknI/TcXmIfU+v5M1cliBTLe/1c/6lNOCIqD2EVzBDjLAP+q4Km", + "WhyMqeJ2mANfyLS+Fb/JzWqpr/Sugr0V7K39sY7oCeQ06zyelNml0kH5EwO2THJy01hfWVLKzqrPOUkU", + "AoOvJdaoLeZEAicYPSbJENXZNIfIhnoOkTkws21VVo0h+r//+/880WxolpooztQcl+OFUaKmQbMiu7IL", + "XlO2FCAxdpxmL2FV9NKAa0GB5l3tyjTrman0NslIW+Jmo20PK3/cgaEWcOpWOFW7EOGbvjw8s9Te0GO1", + "AlNcOidcljhDj3S3FVeHCTpbCxiq7jP2yhHcor+Cr/C4dddmfvPDdxi+0ME1CpSZs/5aeXm9bruV7BMs", + "oI/cXkuQvTyJ2Xv669solZtqj9XT7WqG4P+7X9WyBIHbuPQ0M/ngl1VEWAgys8lniLQobExXYRjyoTCn", + "H89EjY/pjf14Oj9+l3tEI1mSNDTpiCRPgiPvRLzYHU6/2tBpeP42MZUX79wndQX328liqwPnKDcO+7SK", + "vh6JBk+tHfq0qYExrfCQEvIc6pzK2iQxkOOsdh7UyErnXsayOiy6IjK1IykDhgg0xxnRoaDLMLMKF+k6", + "MBnOC7c2qTHjveuSw4GrR4hIA/A8poPnoujrp1wrp7LqsnxFtDdQVmEj9gz5ES6KR2O6EURiD/YmLNkI", + "KKnOnXFR/FoFqYKadUyJMPmNUkyTzESmvnz1+6uPr5Dex9k1LoqIJD9aoGpR7M4gtbGLa7KpKPTrGXiz", + "sG/2N1moneEiR+kfPC6+s6X2uvr+9eB8lHXeRIQNWW9iZ/N78BQeMZpdqwd2NH5Ch8pwI749iOQ7Lra1", + "5oZTi7gLB1yfcm+HLaQPWPBW4KgGFTdDSX4c0mnkNIGBzsKwRBYOM8es8k7dZu2FKxoVOg7aU3aM6r/2", + "qhVFw/j3IID7J7RtPWif71UwHqFL6IXx3LustBbysNr3QATRUav/oOtPwRFS6/oznEdkPYmXUxJf6Fur", + "SH1iRKYruTq48auuRBibzDCdIMEI7uf5+UVjCUePF+x49vJzOD/roME6OYXfA2AvHlYlZHvS1Vs98NGh", + "guCJCGHtO2eyopxkzav2Ld42F7haPm3qNfow+PvmNIHzAucFzmty3tm15p5uN4vEcYrwJt+ZQ+ut/C8N", + "ljwIjlydUtPV6qQ6Ra5zwurlHWfQVONDoER/YUiC2XILb8Bz6WUTybbxywcWOUAWwfJ4WeS4PP5nOrFQ", + "V64ZyTieAUqIuLRMZh5Dpb7pUd2m72mb/aeZMkDEABEDRGw4z25gnDVdb63G2UVzmsB5gfMC5zU5b1vj", + "bIPvbmCcHZTf+yEjz4vV3EDBPtulfbbJKdvZZ4FLDpNLgol2Z4qqqtLQKyHo9kdlH6rhAywMsPChwsJo", + "/ZBsN/759lsaaydmO4sPijovYayx70YwUK2qnvXQeGb3Vu91hg0boVBP8Dlc/ghOewco9F6eDHwT+CbA", + "xKXiWncg7tB30a691lyKgQsDFwaXRg/tFfgm8E3QXoMzXbSs58mz7etyYFQt4QJwSHO7DyotZXpWVct0", + "K4YLXXcJOMK2Ek8pU6DSvgqfJihl+tbI4f3eC1JL8pdyaorpuqdLOt+JNB4OyrJPEkDdy9Zf+txDgj+P", + "Yyhk5aw+sNu7mh77E6iiLkubCRGXvTKbmMidjfzLj9TPkbMCTiN5iSmB4cheop5eTV+CvNlLxtSs9uza", + "ztmSwOSl3tbOkiWb+ZwXTC8RSRSnTkmzwJcv86QdKGCX4099nFgS24ATFe0FNHG8aEJ9w6PPO2xENqH6", + "Xy0AXChiD6ISZxmL1V/Tqh4iofJ//rIUj83kavoBhcA9OdR0B7Uarl4C9/dJYN42hL/oZUO8u9vWy5Cu", + "L99b+1O3ctw2tiDfYZtX1VpA2qVr1l5xSHl8/ymP12BMf/hl0uD7uHkJfbrO4Tdxi+P0fUlAd373OaQO", + "3rYOA9V1f3UYfaNMWGJowQlR7o1GQojGqWKhgw/TMGW4+9m7pq/fxHxtx9pnsVQzx9JpPlTwziwMZXgC", + "2aEUOQ0HTIejC6Y1YW7I/SXNBuP0eAWy+YpHmu6ykqu2epsWZQlMCSXa+5eXQqIJoJKSr6W3UPWuZe80", + "mhLIHAL4BcvKnCI2RdPI1JeWy2XrGUAgyVwnodOIFa4B8wJzIhhFZltMISugZa5e5N8Gw8Hv5//xajAc", + "jMunT/8C9X/+Vv0vrv+jfjp/2xDvzbn1Yjen/7jtHuY4Kx3j/Jf6GUlm0txzM2RsXpZrqDWtVK1vWL95", + "+76WU953ZtBtmCxkCe2Pvc6uzX96G74VodJEl1Y0lwZyUyOVVcoOpGiFaV3GjgVaS3MHPZ4BjezoIxOu", + "MI005vIUUKi3FWrynFhNnooE21OI7ojQdkpdwdQ+XWR3lAFwb1hCpg2WWiI/Awg5iDLTBUUbmLBZLQdh", + "gRgd01jBScLoM3RJ2RU1lbG0kqhg1XBZnNQAkyGizFbjtbObqjy69A7OYWUxX6yw/6KL8azU/DGn1XXX", + "Voh62Hpnx9DZAR+Nk8IR7qLUECTmohlGvzx9aqIAdP/OV94Gt/cIpdvg8YHluj0+9HpCUYkNTNof4AqQ", + "nb5GkHfhbhQgnR5H9buWOcHnGGCy2+foMsOWbkcI9bhDkO09+hw9IrbhUNylgFUEVUeGrK7rrUKbbNrw", + "wynZKhnSqBa0zHU1m9gPJ/pRkwlNZBuz/XcKddG55XBEIIz0E40fH39UU79+0rcqm0NhqAHUrofLBSNM", + "l1i8nux+irjt4i56gEt7gkuVb1AR83buQUWCLg+h+o3DFDjQGEQXuupnrWnucRtsIGubreL+VqvNbDQ4", + "DE/TYagIpY/P8EgoLzgTQ2qVw3QjdjDaCsA7Ghm/cwzaARp7qIAAvo4pym0TUJ3Bt4Jx6b0v+0o3r7AV", + "oQijf3x49xaZAPW6rn0GyyxhJNfPmRtbvFXRmSkeAtDqCaAOjEIaEZJ+b48O9khJllSEoqxVvGLa+SnA", + "G4MWEE9APCGZXB/uPLue9k4zbI86TX6eFhZdM4W3Ob68dybd/ZlqsMpPMOmOZQXJWhlhxVoIbHBfUQUZ", + "m9kTfddRv9I/rguZP+4r7UQ4Z7xbFWgP19sx6rIvAhrjQpSZjiGaLHSzvSYHyXbI1XmMGcBrAK8BvPbk", + "3LNrbT32xbB0lXuXzombgdoeTsD3mAOVTTfI4ej1F03DexdLq75FALwnAnhfLbllzZe3PfQNzLIrZgmw", + "OOTGPAxF3Ltifo5lnBI66+3b7VUyP4DjAI63BceKsE4eIG9ZpGdr7uxbpScwaGDQbRnU0tbJ86iuVuxl", + "0CoC7CoFvoa9BSoFJOjx0pRdiYYVQ8TLDMz/4hTiSyRTDiJlWSKetLL1J72kcKJ+hNQV9UpI1H6S1+fW", + "0O7zZewoW5ENQtrjZaRpTajTkHk3HPxtcxXkkLmm4QhYw4hsRmKc1deg0b8YoUrVyJSIxpuQKaCCw5yw", + "UiBGwXOntvIorLl8mDBXs1duqVQZvx1XPBpZTAPDB4bfixLtuG97ATmbr4KyBhZrq7O4IRF2eU3MOBS9", + "TLHuwFxlDTdDaCgIVPpH3XDZ9hl2jc/W5hiu7STwXThwMAcOtJlzYxvFe/BsdjstbC91rihioJIvbqWK", + "4/UTD6OTizWOd6rmIDbCycUhnFxw/SWTs5QkCdAoB1pGNsN1d9CP6l3nwzYjLJPI6MYp4wjmwBemAN0I", + "vcEUz4CLMRUACGeZaRC/2nRBpdAx7jRbINVBDWQ6qP8u0AQyplibuSTbbyBf2/38XS/mDdDyld1MyIbw", + "ECJ2+ouHe2E3Q8q9LlsbfvEC5d/MSPtMUbNWRdKlKnU9Sd+DLIMzr5661+wD53TKjuMC3GFVPqgSSxgy", + "XgpzFGOK+shzkwFuG4Fe03mQ3scrvfUkx1/jySuSlUm1Y4G8spjrfiliXq3wJyIJelzVAbR7IFRIwIky", + "YEz+G2f6mYKTOclg5hDtjz4+soVP6k5mtiF69PqR4fkrIuCElMUWxPtgqywZiX52XVWM/tEf4ui8MTEW", + "MU5sZUrQqWVyyCfARUqKIcJFIc6mjOfirDq5PctZYv87pnWJb5IRxUB6zKKcVF9cjNCFoRdTEVN/Uqu8", + "loTcNE6UQrOLwdQaLw6VpgajjP60xgwO3fZR393OS5M89dErZRNNWLJ4ZN9CjCllOh2/mTbpgH5dh9C/", + "WRGwPIDGpUxNZTZ7+Kx4znPuXFf+vssz54DY9pEhx5DXUrlsidqMnX4j1HaAJBpCnU4WOB53ch1NzY9E", + "g0/bYOahCv+7AL57BqcBfB4/+DxTeLHbe616LTUbIgLVODIDRUjtqnJMd+Kx1l/4eVGIoC6DujzNnMFu", + "JvWcOPmsxk80JYmyGutDp4UW9jW/maoWihtNZbOUZcmGtTemDXNP9cdxVfciY7MZJNp0xChOMZ0p207x", + "mvkWqg/kRHbbZj0On05HX9ffb+GAN8tPdQkLnaVYf8XOk+vGoOGU+vgPDvqfFTe4ual793RafDTcGhRx", + "OK4+EJP17wethWsTOehgrw4OGvgh2cLLc5Ie8Vx1X3N6IlJIqrhJy90XoL6GLijWbNAKd0w13xutKzrU", + "7pvluoK+Dfr2ARm+PXJCmHPFBA7FP9Ur2UTg08Cnp8SnvLfe5HemNS+Czgy8+AB5sV++Fp1ptMrZsr3m", + "HNPde5f6JoIJDBsY9pQYVvNON7caFjOxftW1Oof/1x2mZDRnLw7VXqYCC3HFuPYujSmHGRHSsGx0CQtb", + "ulwgzAFRmANH8K1gwu1oqvj7k+hRYCMwd2Du42Vu0vPGkjJYESnQ40mZXeoaRk8M3z0iySPtfCQC5Zgm", + "WDK+qG7LTliyMAxZxaqrXyXmM5CIFL/agvQZVN5fmQK19Y8ShAV6+er3Vx9fIbXMs2uS/PAfzp7v+cLU", + "+SqPq/cREcXgT0Id71C9cl39kUKgBCRoq5BR4+9pqL1K5RH/ZSo1BJtaT9FVyoQOajK6T2mxddTr1mPn", + "4X7VkSuP8+Kw1YeWy9voEO8p4luWwMbFDX1aOIHGPRBD77Ub1VTOK5o+lpZjxzG9afTPeWdkbquKcGC/", + "kCr+9CoWVzipeSdDXw9aEoYyeSaAgNTV5GmZAyexkvm28rulaZwkHITwyvYtKXIeqeVRkFeMXwpFmGqu", + "5Tw7IdNgnJymfjn4TGYZm3U4JWCui9lb46R+XikIF3/9rgbs4LDK+Y8kU8NUU9Q5pdfyFPXNFPtVff5G", + "qtg6y0/gu5NxCrDZcd6ax0tCN7rNBCApelRAasp4bI7CHuUgBJ7Bo6G186e4zOSYZjCHTHV9pEDIo6FG", + "ZpAXctFkIWXjJETEmCf+cDDLorsx+zM2ixISS0eO5KFunObSeW1JtelNOVsNDkycbWIeu5vWXAjV7J/v", + "+cpSuK3UqYLOrtXHsjZRB1pcUUGG8NsK8Bud1KWSfq+HamK/jM38lohZcYB5Qd0cAc6rQ6z6ORw2PdZW", + "ILe7rcdUaSWH21o93ddxPaZmtWfXds4f6PFaOow/IVwmRGoB8CdXUPQTv0uiitzajfpr6KnV9/lW27Qb", + "ng0NXbVBaZFruwqrhg+u8IflCqeWSDdUmSfuMGiVk6wndci5v6yeWNTSrJJskUFMm3bHbiWvcVVHRhpd", + "D4CWuU7xWwqF0YoyyxpSc2k84MJdwBALATICOve3GtznaJ0QJqI5cOFL0RBnpZDAfQbN8gu4WymFWEaS", + "uZuLMooZNy9lM62yak5IW+uUw1fvyDlLPBaaapUpB5y0jD0Hmni2BTTOmCg5tLeKjLntx+nXxP2y07nn", + "54KxzNM0T2J3y1XEJiLCGXAZKcJv63WFOfV3yrCQ0YR5dqNbY5bn7lYiJFDgUcG4dL/tjMURThLusbXj", + "aFKSLFF/+zrEWnb4GllZ3aZytk8zxvxzcxxf+hsZy72N34mbXXOs9k4xjSECmnj60HKKY1lycC8thzya", + "YHrpIWDdvJDQ0qyo09fs5RwtJH2SRjdOOfsOTeqeMJYBpmsdIiy3dp5U0trTuITQwj09ExHmcep8nIko", + "ZjT2rIqJ6BI49bwUJiLvspjow4W2VzsXMhFxyAALb3OLyCrYFfBowgFfAv+5u8ufW7rEeEIoyJ+7u7SN", + "UnAmIZbdPaoltfQUZVFki4hO3PTsyQekcUf0nVFfIyfY/cUFZew7RJJknvaiVacKiWUpnE0ScB7ppfub", + "Gyfj/k7qlaxK3EYHCzw2G747fzbAyc2Ubfu8wpxjKhceMXff+ZgUqLtgV8Gv6Xa5nKWYJ1eYQ/shG84y", + "G7T0/sW5du3nkDO+QPXjPlvw78sOwSYM0a77o+MJFn1p+PULTcLkw4sP5yhlQqJJKRBOcGFL2nlIWU0R", + "yDiQ8R7JuPYp9/GFU/SuAPrhv14YZ4cnLzOHTCn2KpXPqMXv3HUK5XUaf/p0/nLdc+w4kqqA/7ElKQ7e", + "39WQG5sUyqTuFAXEyirTH98nPA+RssJp56n6pY8ytfCnFc91S8RA5as+WGkd3OfBfR7c58F9Htzne3Of", + "Bxd5cJEHF3lwkT8YF/lxRDAu/TdnWtR1uSSt48Z09ZjOz6vWYEAHA/pOAv2PjdPyiKwrAyfPXYAsOUWK", + "rBExqWussQrckXPK3PNS04y8vJmfXzQmPkH3abg4vB0xxpgmRMGEyDzRmk8JzwTCUuI41UUGJavjFimT", + "aAHSttqL7upH+BZnZQKOEEZLki+qBXzEs6A1gtYIWsPDqCnEl/3wme3qY7iqNXBa4LTAaQ5OY3mREUxj", + "aGjHHlnufwOJ6geaqe7NuaMa351DQ3NlPWmtENsS2HdSwXssUzXueTIIfHVifKVlPZs6ia3BcQ6BrhDZ", + "lJU0aTDbWrYWKoFTnOk0t8ARcM743bMb347Z+C1Z7SIwWmC0PozGT4HNWpPUaMaq+yLVd0uucqesCYz0", + "gBnphYOgqtx5x44ReyLDBh6snSS1A6UPWwU4GJirVUvVZHUiaHC5jbPr3CQf6wgzVvtHeLl/U//Ty2LL", + "QGIHl90Bk6n+bwRI1X+TgH5xVvO3GxNlHIMQ0zLLFigB8+HbvzbjjRdz35/eF1T4XG58wzYhWYUWHsj3", + "u1kg4Q0O0//cRhuVHAi3xdxypZdtyW+nrINBGVR1H1V9EvYkr9U030ZN8xsr6Ys7FfEX26joi1spaH4s", + "6pnfSDnf43e7T9V8ERRzLzmyjK/0H3E2XFMWIqIMq99TiC8RLykyo2zps/pgpg7aOmhrp9fKElXzJqHD", + "f3UkqjshoiuSQHfRSKXffcmXesgQUxB4MsQUuFiuZ9oSE7+zZc4Sf8qSwH6B/QL7KfbrzrZiWE9IxvEM", + "+mdZcSdZCYwXGC8wXvLjjChwO8WdhbUt+9myUKjxmIfvzps9AvcF7gvc5+C+oh/bnb+vqq+1MFwROC1w", + "WuA0N6cJ4HPSqeWq9Ge2NyJUSExjEIiZoh/W1wJJq7PlQzVZ4MfAj4Ef2/jx7NpUN+suhLXOk5XL9yac", + "eaCMubqID9WGG+swL6tehpjHLauwdeOCdAjS4dikg84Do5O4OY+5P+h2XZ6Fmr4r1bC0UDDQeTSm51OU", + "lLyu4V1wNicJJENknyypJBmi7Ar9adnxMYxmIzQe/JyOB0M0Hvw5GQ+ebA7GTEHw4XId1anTaEw/VsXH", + "Y0yryYgUkE1H6JMu5K9Lm09Wi5pjmiBfGfNRyym+eSe3PCHdWbq96iU55Hn1+ozQ2XjTf3maN185epcT", + "HcZQveGRs4jYRiBAqA52/LkPtsp40IwA9Kn/kMIgqN2gdr38VpYm42grDtcaTfUcoXc0s383FJYwR6NG", + "m5kKzTjL2BUk3qw3irNCrpuHJ+/ZRLAMRAw6SBWmHITOIlmUzmRLul1joerEHemsmYbimEDTMsuQ+t4C", + "ZUo72EqtzWmQACkJnYnRmF4YQjCFW99NRIXACk7mJIOZG26V8l1jPLuqwaGhjRMKSFyhkurz9Stn4Pry", + "I3Sj724GbX76D9VSdoWZXWV13zl2gDjEjCdIS7P2erqhlO6DK6bglHYuzeuh5VCO5nhxqeOTHlnh3Tcs", + "IdPFjmX3eybkwUvu4WAzofWaXsMSzGWcq5TEqS0+lWMZp2psnV2ymkiBo2mGZzNTad68TAkjNB7885//", + "/OdPb9789PLleKCAc/MXlKbP8vyZEOPBr+ojQF7IReWpiTPA3Lx5tcCRbw8r6bZ3tgWM1LiaCPa6h/vR", + "oHvh6qBHbwovz657l8y6C4zZZRx3yhqHQXzHtvCRWDjHCPsqz4yHGHtivwOgseAGfSBw8yjrad0lND0U", + "gb8LcBxg7YHA2gBiTxfEFkBxQUbVN7E4YUPvf7hShMcHB3A2dgAe6uptFuUkI7F9lc1I0S70XwWl+cF8", + "IxR0N9LUBnU980eL6cMwJfK7TFs7VHAQPywHsViS5KZ88EYuB2B+RMDcfsYj8/2+4KBwFOOorErXVkG/", + "jyeLKtjVxr1GxFGyRKHpnUvcjmqsai2+KrG6rZRMSOwpGad6xCzP7bqc7QmnzJSvbelS6LinjnbR1sFb", + "vU61++pPqrZpBt+iuCijlMxSXeRVpCxL3DUDVx7I2FXv/jn+Fq3vwdmP0M5+6/UyV/eTYm9TCw3kIDmz", + "tOLt1P4RetTaVN2KDMfQSjE6xlUQRsG/3s5ai/M4kqxgGZstvB2u8By879lTvPMuLJFOHFHBpVjLnGQp", + "dB528ifntYxuH/j6vSlMExRjEeMEkHkaESkQh0y/bJulZ9SOmbt8IPdxPyJEhN0PZm3mdWpkPBI1pfiQ", + "7CESUXBznzCaPkrX9qd1vN1AwC0Y+2Al9K4cLQHXPxBcH8D7MYL3A0PsB39KsIHuexYVr2G9t664/SL9", + "SosHzBUw1wO5YeXguL0WF6/Oo9p4dKsS48HIfghq4NZFxms//c3qjFsq26rUeNAiQYs8WC3Sr9h4xZX+", + "euMV4/UqOR44LnDcw+W4GxYd9xTFWFauqpToahKrbs/2lgXJAysHVg6sfIuC5uuMzPfGxheHzcRr1VGm", + "2kQdmowLLS8FaIwLUZoT4OV70cv6qoi6sa4Mz1XbchkJTHGZycGzKc4EDDd8q0G4BOFycMLlhmXc7Zju", + "qlgbUsNdzD1o+8CQd1MhvpLkR8+tu8DyJgfdzSHAwQP4Nt3f8jaC7g+i5mHp/t3VxvfDgZVoyV4V1o8D", + "FjTLtvtljqnZa97S/mXM5+1KvK8WFD6u0IRfnv61T9+/HlQEW134eMk/zYMpz83rh8o7Rj/fjXbeknMO", + "rQbzyXBOp8q6rQfstuD3dNxeAfgG4PtQgS+vYS/fBvbyW4Lei+NX2xfHCHkvAuC9Z8DLbwF3HwTXHBzY", + "vQhQ956VlCkdtq2fF2VY/Z5CfIl4STcrj22Ddj+YJYSTm4AqA6p0M2xCRP8YR9PZz3kvbXtgt8Bugd1c", + "7FYXu11WBNomB9qyMGcz+4NkKMEinTDMkyHiIHJG9b+ETpnpqWOPo4zMod3YO7fjH4V/KJQrelCplzd4", + "QNnDJNuiOm0g8qAuT1FdVgR9smqzzgrQB6U6ilcDjlPEpjpBkhnLLx3e2vYAYgNXBhDr5cZVALvfqvIN", + "zgw6O0iHIB2OSDqouVnJ4xb97ZUT9aM3EhUX9cRBZgSZEWTGMcqM9vs9dVGmNtGhwAagOMV0dktBcsDX", + "gIIsCbIkyJJKdlS1L/p4C5aCQnvLL2FxNsdZCajAhLf5CS7sPMFTEHgx8KKXFzuwv5cbGUU4yzq9dYcO", + "8gMfBj48ID5sx9NeZtzA0NuwZrg9H7gzcGcLd26VD9Lce8E94iBDgsfAd4HvNvguqmOwbhR51V2G8rwe", + "f1dlElprUS49XrYy8VCXvFU6WgKnWJK5DhGzbP0ntPTubCalr9qeeVxKVd3LoRpxAqgUkCCcMTpDV0Sm", + "qBYHLZW9umpq+sbeWPdd5ssPxTUPr7gmIg1O85bZbLJjqLf5UIKcDkTFrNR481N03d9TfAs9rg2uJ31o", + "PcC+wG8hqLCDNyMThhRlbNbOnZv6popgythshF7hONXF8xaICISRJDkgjukM0FUKHFpCE6+wHmqStVaT", + "WKowc6HtdzYLuuwBmFT3yydbc8cNeWI7VggcEDhgzxxQueM6XQMSz9DjSZldKtSWP/F7BqwnbjfOAIln", + "TkP6I54h0zZU+E0trnYJOG3mJXT7oxr0c7CkH1bJ329ESEI14TiNaLcPOUjaIGn3lXPlhS4Wb6TryJNj", + "ZefyNMESby7lNQdd9i1H//jw7i1SnTaSj0k8c3k71aC2Gper6tyszDBH8K3gIARhFLGpFtjKuhZIplii", + "GFNd02sCjTpfS2eorkTXMrm/tOi62Nc970Lw7+KM4RBk/YEnZVG/Ly/MdSYFU2RnE4Kph9pBTHU3bjec", + "13XY4KPtfaGf5fFHwEEPCwfhLFMk85P6/lbc5mopPkjkuSMacFHARXvPRadEm44A8YnrCiEdhrA23HQL", + "hLVkx6APTlgfHAeuqpyd20KrqmZ0K7qqfJw749n+MRd3z1p2bYGzHibSqrz/PcBWgy0C3gp4697wVosM", + "ryDXAUrwo8ZfQUkE+NWEX9eGMvrkTLTOWZ3+kNRVI7SiUZStHWS6USx51gPMuqKpzl9q/23tDXbES9UU", + "3RkvVQfjhlSD95dqUBGOFQgLDyy5J6LYNoruzojooD+2W8V/KpL6qAk15L9Hu9+nGNj1QVfXgdWWZ0p7", + "187BNNuTJu1IrfgbSKsqTdhWpVXJ8jqaRz72SqN4IEJy76bhbaUwkZALBx/UnIc5xwsXX2ijm02rj7hy", + "dLwk1k3sTplEU1bS5JDItG/SbPfRph/g9UksuD9S9c1j13wgiat3bh89SNS5zdmOD4c8GGrdFehZc4H0", + "oNngTHhAzoSVQ50ece7bIiG///phgqHgJ38I1+3dLLZyH/IGB6h+DPeh7nAwitE45qv51urg3fo+ZQB0", + "xwTofPRrMd3DpN4A8ALA24/2KYVmoOs+d1903xF6gymeATeHQp8EcPuDjsQXADp0Qff9FTGZAh9T/Rdi", + "NFvoDopPzE8ixYoEEKMVAxGOGJ9hSoQmKZyhmQITYjimRVYK1SUXkM1BuM6XfwP5Se8ohEAcM7RT3/CA", + "Lz5q2j27Vv/0quuhOjbOTbZioTHVPIRuw0JjankI9WehLg2r+jTSYjxDuJRppJY0IsmwXh+CHJNMmYIU", + "EYkUdWBC1cbHdDz4X+OBjnoYDwRk0/FAZ/XQsRSlTNXQsa6MrEfVS3XoVPsVQoqNIA+Owdxbkx1nBYep", + "XwG/BhmnS2ZSnYEDjUE8Q3MiyCQDFLOszKkY2v+gKcnUBxqijMx1uWgYU6B4kkGCphmeDVFKkgSoUaw6", + "+QABMUSj0WhMx/QCZMk1hyLIC7lABpMZFq5XkmKBKGsuCAnJOCRDJdPGFGeCrT2SMBD6uEQDCsX2xPxd", + "bcTGUcU4yyp+d4qm9/qVnbJ82jcv6Td4RDGGH/Ac7pILnNbnAyK9XdiblZGJk4QYGPK+0W6WsXacmsKK", + "QDGCZ2gFC5oDn2BJ8tFguHm8W5au4Mp3Bf5aKpucJiufBEGcMkgQWYqnSAviyKRuHlOYA1VTM4RRnBGg", + "5qIxmVHGQcfJsSuKSh0YY95/e6Smfhv3fXn4nE7ZcVwevhfVPAcuiHmfTmXMtWZEuCCo6urQUP9VN+3t", + "O1az70Zw168DF3hCMqIZ9PMP82b5vJJxJc8Gzwajs8GPzz/+XwAAAP//", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index 57f401c4..14f18f47 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -34,31 +34,64 @@ func (e ObsolescenceSettingRowObsType) Valid() bool { // Defines values for PostFiltersJSONBodyFOp. const ( - Equal PostFiltersJSONBodyFOp = "=" - GreaterThan PostFiltersJSONBodyFOp = ">" - GreaterThanEqual PostFiltersJSONBodyFOp = ">=" - IN PostFiltersJSONBodyFOp = "IN" - LIKE PostFiltersJSONBodyFOp = "LIKE" - LessThan PostFiltersJSONBodyFOp = "<" - LessThanEqual PostFiltersJSONBodyFOp = "<=" + PostFiltersJSONBodyFOpEqual PostFiltersJSONBodyFOp = "=" + PostFiltersJSONBodyFOpGreaterThan PostFiltersJSONBodyFOp = ">" + PostFiltersJSONBodyFOpGreaterThanEqual PostFiltersJSONBodyFOp = ">=" + PostFiltersJSONBodyFOpIN PostFiltersJSONBodyFOp = "IN" + PostFiltersJSONBodyFOpLIKE PostFiltersJSONBodyFOp = "LIKE" + PostFiltersJSONBodyFOpLessThan PostFiltersJSONBodyFOp = "<" + PostFiltersJSONBodyFOpLessThanEqual PostFiltersJSONBodyFOp = "<=" ) // Valid indicates whether the value is a known member of the PostFiltersJSONBodyFOp enum. func (e PostFiltersJSONBodyFOp) Valid() bool { switch e { - case Equal: + case PostFiltersJSONBodyFOpEqual: return true - case GreaterThan: + case PostFiltersJSONBodyFOpGreaterThan: return true - case GreaterThanEqual: + case PostFiltersJSONBodyFOpGreaterThanEqual: return true - case IN: + case PostFiltersJSONBodyFOpIN: return true - case LIKE: + case PostFiltersJSONBodyFOpLIKE: return true - case LessThan: + case PostFiltersJSONBodyFOpLessThan: return true - case LessThanEqual: + case PostFiltersJSONBodyFOpLessThanEqual: + return true + default: + return false + } +} + +// Defines values for PostFilterJSONBodyFOp. +const ( + PostFilterJSONBodyFOpEqual PostFilterJSONBodyFOp = "=" + PostFilterJSONBodyFOpGreaterThan PostFilterJSONBodyFOp = ">" + PostFilterJSONBodyFOpGreaterThanEqual PostFilterJSONBodyFOp = ">=" + PostFilterJSONBodyFOpIN PostFilterJSONBodyFOp = "IN" + PostFilterJSONBodyFOpLIKE PostFilterJSONBodyFOp = "LIKE" + PostFilterJSONBodyFOpLessThan PostFilterJSONBodyFOp = "<" + PostFilterJSONBodyFOpLessThanEqual PostFilterJSONBodyFOp = "<=" +) + +// Valid indicates whether the value is a known member of the PostFilterJSONBodyFOp enum. +func (e PostFilterJSONBodyFOp) Valid() bool { + switch e { + case PostFilterJSONBodyFOpEqual: + return true + case PostFilterJSONBodyFOpGreaterThan: + return true + case PostFilterJSONBodyFOpGreaterThanEqual: + return true + case PostFilterJSONBodyFOpIN: + return true + case PostFilterJSONBodyFOpLIKE: + return true + case PostFilterJSONBodyFOpLessThan: + return true + case PostFilterJSONBodyFOpLessThanEqual: return true default: return false @@ -214,6 +247,39 @@ type DiskRow struct { Updated *string `json:"updated,omitempty"` } +// FilterListResponse defines model for FilterListResponse. +type FilterListResponse struct { + Data FilterListResponse_Data `json:"data"` + Meta *ListMeta `json:"meta,omitempty"` +} + +// FilterListResponseData0 defines model for . +type FilterListResponseData0 = []FilterRow + +// FilterListResponseData1 defines model for . +type FilterListResponseData1 map[string]map[string]int + +// FilterListResponse_Data defines model for FilterListResponse.Data. +type FilterListResponse_Data struct { + union json.RawMessage +} + +// FilterRow A filter: one condition on a column of a collector table, which filtersets +// combine. Every property is optional: the `props` query parameter selects which +// columns the server returns. `f_label` and `f_cksum` are computed by the +// database from the definition. +type FilterRow struct { + FAuthor *string `json:"f_author,omitempty"` + FCksum *string `json:"f_cksum,omitempty"` + FField *string `json:"f_field,omitempty"` + FLabel *string `json:"f_label,omitempty"` + FOp *string `json:"f_op,omitempty"` + FTable *string `json:"f_table,omitempty"` + FUpdated *string `json:"f_updated,omitempty"` + FValue *string `json:"f_value,omitempty"` + Id *int `json:"id,omitempty"` +} + // GroupListResponse defines model for GroupListResponse. type GroupListResponse struct { Data GroupListResponse_Data `json:"data"` @@ -1280,12 +1346,17 @@ type GetFilterParams struct { // PostFilterJSONBody defines parameters for PostFilter. type PostFilterJSONBody struct { FField *string `json:"f_field,omitempty"` - FLabel *string `json:"f_label,omitempty"` - FOp *string `json:"f_op,omitempty"` - FTable *string `json:"f_table,omitempty"` - FValue *string `json:"f_value,omitempty"` + + // FLabel Rejected with a 400; the label is computed from the definition. + FLabel *string `json:"f_label,omitempty"` + FOp *PostFilterJSONBodyFOp `json:"f_op,omitempty"` + FTable *string `json:"f_table,omitempty"` + FValue *string `json:"f_value,omitempty"` } +// PostFilterJSONBodyFOp defines parameters for PostFilter. +type PostFilterJSONBodyFOp string + // DeleteFiltersetsJSONBody defines parameters for DeleteFiltersets. type DeleteFiltersetsJSONBody struct { // Id Filterset record id, or filterset name @@ -3978,6 +4049,68 @@ func (t *DiskListResponse_Data) UnmarshalJSON(b []byte) error { return err } +// AsFilterListResponseData0 returns the union data inside the FilterListResponse_Data as a FilterListResponseData0 +func (t FilterListResponse_Data) AsFilterListResponseData0() (FilterListResponseData0, error) { + var body FilterListResponseData0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromFilterListResponseData0 overwrites any union data inside the FilterListResponse_Data as the provided FilterListResponseData0 +func (t *FilterListResponse_Data) FromFilterListResponseData0(v FilterListResponseData0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeFilterListResponseData0 performs a merge with any union data inside the FilterListResponse_Data, using the provided FilterListResponseData0 +func (t *FilterListResponse_Data) MergeFilterListResponseData0(v FilterListResponseData0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsFilterListResponseData1 returns the union data inside the FilterListResponse_Data as a FilterListResponseData1 +func (t FilterListResponse_Data) AsFilterListResponseData1() (FilterListResponseData1, error) { + var body FilterListResponseData1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromFilterListResponseData1 overwrites any union data inside the FilterListResponse_Data as the provided FilterListResponseData1 +func (t *FilterListResponse_Data) FromFilterListResponseData1(v FilterListResponseData1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeFilterListResponseData1 performs a merge with any union data inside the FilterListResponse_Data, using the provided FilterListResponseData1 +func (t *FilterListResponse_Data) MergeFilterListResponseData1(v FilterListResponseData1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t FilterListResponse_Data) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *FilterListResponse_Data) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + // AsGroupListResponseData0 returns the union data inside the GroupListResponse_Data as a GroupListResponseData0 func (t GroupListResponse_Data) AsGroupListResponseData0() (GroupListResponseData0, error) { var body GroupListResponseData0 diff --git a/server/handlers/post_filter.go b/server/handlers/post_filter.go index 477a6192..55e2967b 100644 --- a/server/handlers/post_filter.go +++ b/server/handlers/post_filter.go @@ -5,6 +5,7 @@ import ( "database/sql" "fmt" "net/http" + "slices" "strconv" "strings" @@ -53,12 +54,67 @@ func (a *Api) PostFilter(c echo.Context, filterId string) error { return JSONProblemf(c, http.StatusNotFound, "filter %d not found", id) } + // f_label and f_cksum are generated columns, computed from the definition. + if body.FLabel != nil { + return JSONProblemf(c, http.StatusBadRequest, "f_label is computed from the filter definition and cannot be set") + } + + // Validate the definition the filter will have once modified, with the same + // rules as POST /filters: a filter on an unknown table, column or operator would + // break the filtersets it is attached to. + fTable, fField, fOp, fValue := row.FTable, row.FField, row.FOp, row.FValue + if body.FTable != nil { + fTable = *body.FTable + } + if body.FField != nil { + fField = *body.FField + } + if body.FOp != nil { + fOp = strings.ToUpper(string(*body.FOp)) + } + if body.FValue != nil { + fValue = *body.FValue + } + switch { + case fTable == "": + return JSONProblemf(c, http.StatusBadRequest, "f_table is mandatory") + case fField == "": + return JSONProblemf(c, http.StatusBadRequest, "f_field is mandatory") + case fOp == "": + return JSONProblemf(c, http.StatusBadRequest, "f_op is mandatory") + case fValue == "": + return JSONProblemf(c, http.StatusBadRequest, "f_value is mandatory") + } + if !slices.Contains(filterTables, fTable) { + return JSONProblemf(c, http.StatusBadRequest, "f_table must be one of %s", strings.Join(filterTables, ", ")) + } + if !slices.Contains(filterOperators, fOp) { + return JSONProblemf(c, http.StatusBadRequest, "f_op must be one of %s", strings.Join(filterOperators, ", ")) + } + columnFound, err := odb.ColumnExists(ctx, fTable, fField) + if err != nil { + log.Error("cannot check filter field", "f_table", fTable, "f_field", fField, logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot check filter field") + } + if !columnFound { + return JSONProblemf(c, http.StatusBadRequest, "field not found in model's table") + } + existingID, exists, err := odb.FilterByDefinition(ctx, fTable, fField, fOp, fValue) + if err != nil { + log.Error("cannot check filter existence", logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot check filter existence") + } + if exists && existingID != id { + return JSONProblemf(c, http.StatusConflict, "a filter with the same definition already exists: %d", existingID) + } + fields := cdb.UpdateFilterFields{ FTable: body.FTable, FField: body.FField, - FOp: body.FOp, FValue: body.FValue, - FLabel: body.FLabel, + } + if body.FOp != nil { + fields.FOp = &fOp } changes := []string{} @@ -69,41 +125,41 @@ func (a *Api) PostFilter(c echo.Context, filterId string) error { changes = append(changes, fmt.Sprintf("f_field: %s => %s", row.FField, *body.FField)) } if body.FOp != nil { - changes = append(changes, fmt.Sprintf("f_op: %s => %s", row.FOp, *body.FOp)) + changes = append(changes, fmt.Sprintf("f_op: %s => %s", row.FOp, fOp)) } if body.FValue != nil { changes = append(changes, fmt.Sprintf("f_value: %s => %s", row.FValue, *body.FValue)) } - if body.FLabel != nil { - changes = append(changes, fmt.Sprintf("f_label: %s => %s", row.FLabel, *body.FLabel)) - } userEmail, _ := c.Get(XUserEmail).(string) - tx, markSuccess, endTx, err := odb.BeginTxWithControl(ctx, log, &sql.TxOptions{}) - if err != nil { - log.Error("cannot start transaction", logkey.Error, err) - return JSONProblemf(c, http.StatusInternalServerError, "cannot update filter") - } - defer endTx() - - if err := tx.UpdateFilter(ctx, id, fields, userEmail); err != nil { + // The transaction ends before the modified filter is read back: a read done + // while it is still open, on another connection, returns the previous values. + if err := func() error { + tx, markSuccess, endTx, err := odb.BeginTxWithControl(ctx, log, &sql.TxOptions{}) + if err != nil { + return fmt.Errorf("cannot start transaction: %w", err) + } + defer endTx() + if err := tx.UpdateFilter(ctx, id, fields, userEmail); err != nil { + return err + } + if logErr := tx.Log(ctx, cdb.LogEntry{ + Action: "filter.change", + User: userEmail, + Fmt: "change filter %(data)s", + Dict: map[string]any{"data": strings.Join(changes, ", ")}, + Level: "info", + }); logErr != nil { + log.Error("cannot write audit log", logkey.Error, logErr) + } + markSuccess() + return nil + }(); err != nil { log.Error("cannot update filter", "filter_id", id, logkey.Error, err) return JSONProblemf(c, http.StatusInternalServerError, "cannot update filter") } - if logErr := tx.Log(ctx, cdb.LogEntry{ - Action: "filter.change", - User: userEmail, - Fmt: "change filter %(data)s", - Dict: map[string]any{"data": strings.Join(changes, ", ")}, - Level: "info", - }); logErr != nil { - log.Error("cannot write audit log", logkey.Error, logErr) - } - - markSuccess() - if err := odb.Session.NotifyChanges(ctx); err != nil { log.Error("cannot notify changes", logkey.Error, err) } From 5a5a9db63c8ae5ae3c52d649a9330ac4dc2f3982 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Thu, 24 Sep 2026 14:38:09 +0200 Subject: [PATCH 18/61] Validate filterset modifications fset_stats and f_log_op are declared as enums and checked on every endpoint that sets them; a filterset name cannot be emptied nor take the name of another one (409). The transaction is committed before the filterset is read back. The filterset, composition, usage and export responses get their own schemas. --- server/api.yaml | 209 +++++++- server/codegen_server_gen.go | 453 +++++++++--------- server/codegen_type_gen.go | 412 +++++++++++++++- server/handlers/post_filters.go | 7 + server/handlers/post_filterset.go | 63 ++- server/handlers/post_filterset_filter.go | 7 +- server/handlers/post_filterset_filterset.go | 7 +- server/handlers/post_filtersets.go | 12 +- server/handlers/post_filtersets_filters.go | 2 +- server/handlers/post_filtersets_filtersets.go | 2 +- server/handlers/problems.go | 10 + 11 files changed, 918 insertions(+), 266 deletions(-) diff --git a/server/api.yaml b/server/api.yaml index f813dfcd..17fbe9a5 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -1762,7 +1762,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/FiltersetListResponse' 500: $ref: '#/components/responses/500' security: @@ -1788,6 +1788,7 @@ paths: description: Name of the filterset to create, or of the filterset to update fset_stats: type: string + enum: ['T', 'F'] description: Whether the filterset is a stats filterset (T or F) tags: - collector @@ -1797,7 +1798,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/FiltersetListResponse' 400: $ref: '#/components/responses/400' 401: @@ -1879,6 +1880,7 @@ paths: type: string fset_stats: type: string + enum: ['T', 'F'] tags: - collector responses: @@ -1887,7 +1889,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/FiltersetListResponse' 400: $ref: '#/components/responses/400' 401: @@ -1959,7 +1961,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/FiltersetListResponse' 404: $ref: '#/components/responses/404' 500: @@ -1988,7 +1990,7 @@ paths: content: application/json: schema: - type: object + $ref: '#/components/schemas/FiltersetUsageResponse' 404: $ref: '#/components/responses/404' 500: @@ -2016,7 +2018,7 @@ paths: content: application/json: schema: - type: object + $ref: '#/components/schemas/FiltersetExport' 500: $ref: '#/components/responses/500' security: @@ -2119,7 +2121,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/FiltersetFilterListResponse' 404: $ref: '#/components/responses/404' 500: @@ -2156,6 +2158,7 @@ paths: type: integer f_log_op: type: string + enum: ['AND', 'AND NOT', 'OR', 'OR NOT'] tags: - collector responses: @@ -2247,7 +2250,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/FiltersetListResponse' 404: $ref: '#/components/responses/404' 500: @@ -2284,6 +2287,7 @@ paths: type: integer f_log_op: type: string + enum: ['AND', 'AND NOT', 'OR', 'OR NOT'] tags: - collector responses: @@ -2374,6 +2378,7 @@ paths: description: Filter record id, or filter label f_log_op: type: string + enum: ['AND', 'AND NOT', 'OR', 'OR NOT'] description: Logical operator joining this filter to the previous one f_order: type: integer @@ -2472,6 +2477,7 @@ paths: description: Child filterset record id, or name f_log_op: type: string + enum: ['AND', 'AND NOT', 'OR', 'OR NOT'] description: Logical operator joining this filterset to the previous entry f_order: type: integer @@ -7988,6 +7994,193 @@ components: meta: $ref: '#/components/schemas/ListMeta' + FiltersetRow: + type: object + description: | + A filterset: an ordered combination of filters and other filtersets that + selects nodes and services. Every property is optional: the `props` query + parameter selects which columns the server returns. + properties: + id: + type: integer + fset_name: + type: string + fset_stats: + type: string + description: T for a stats filterset, F otherwise. + fset_author: + type: string + fset_updated: + type: string + + FiltersetListResponse: + type: object + required: + - data + properties: + data: + oneOf: + - type: array + items: + $ref: '#/components/schemas/FiltersetRow' + - type: object + additionalProperties: + type: object + additionalProperties: + type: integer + meta: + $ref: '#/components/schemas/ListMeta' + + FiltersetFilterRow: + type: object + description: | + A filter attached to a filterset: the filter properties, plus its position + (`f_order`) and the logical operator joining it to the previous entry. + properties: + id: + type: integer + f_table: + type: string + f_field: + type: string + f_op: + type: string + f_value: + type: string + nullable: true + f_label: + type: string + f_cksum: + type: string + f_author: + type: string + f_updated: + type: string + f_log_op: + type: string + f_order: + type: integer + fset_id: + type: integer + encap_fset_id: + type: integer + nullable: true + join_id: + type: integer + + FiltersetFilterListResponse: + type: object + required: + - data + properties: + data: + oneOf: + - type: array + items: + $ref: '#/components/schemas/FiltersetFilterRow' + - type: object + additionalProperties: + type: object + additionalProperties: + type: integer + meta: + $ref: '#/components/schemas/ListMeta' + + FiltersetUsageResponse: + type: object + required: + - data + properties: + data: + type: object + required: [filtersets, rulesets, thresholds] + properties: + filtersets: + type: array + description: Filtersets encapsulating this one. + items: + $ref: '#/components/schemas/FiltersetRef' + rulesets: + type: array + description: Compliance rulesets restricted by this filterset. The ruleset name is in `fset_name`. + items: + $ref: '#/components/schemas/FiltersetRef' + thresholds: + type: array + description: Check thresholds, as "chk_type.chk_instance:low-high". + items: + type: string + + FiltersetRef: + type: object + required: [id] + properties: + id: + type: integer + fset_name: + type: string + + FiltersetExport: + type: object + description: | + A filterset and every filterset it encapsulates, recursively, each with its + ordered entries. An entry holds either a filter or the name of an + encapsulated filterset. + required: [filtersets] + properties: + filtersets: + type: array + items: + $ref: '#/components/schemas/FiltersetExportItem' + + FiltersetExportItem: + type: object + required: [id, fset_name, filters] + properties: + id: + type: integer + fset_name: + type: string + fset_stats: + type: string + nullable: true + filters: + type: array + items: + $ref: '#/components/schemas/FiltersetExportEntry' + + FiltersetExportEntry: + type: object + required: [f_log_op, f_order] + properties: + f_log_op: + type: string + f_order: + type: integer + filter: + nullable: true + allOf: + - $ref: '#/components/schemas/FiltersetExportFilter' + filterset: + type: string + nullable: true + description: Name of the encapsulated filterset, when the entry is not a filter. + + FiltersetExportFilter: + type: object + required: [id, f_table, f_field, f_op, f_value] + properties: + id: + type: integer + f_table: + type: string + f_field: + type: string + f_op: + type: string + f_value: + type: string + AlertListResponse: type: object required: diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index 546d3591..ed5b66c7 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -8993,227 +8993,238 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "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", + "Jmej75++/+8AAAD//w==", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index 14f18f47..644eced3 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -98,6 +98,138 @@ func (e PostFilterJSONBodyFOp) Valid() bool { } } +// Defines values for PostFiltersetsJSONBodyFsetStats. +const ( + PostFiltersetsJSONBodyFsetStatsF PostFiltersetsJSONBodyFsetStats = "F" + PostFiltersetsJSONBodyFsetStatsT PostFiltersetsJSONBodyFsetStats = "T" +) + +// Valid indicates whether the value is a known member of the PostFiltersetsJSONBodyFsetStats enum. +func (e PostFiltersetsJSONBodyFsetStats) Valid() bool { + switch e { + case PostFiltersetsJSONBodyFsetStatsF: + return true + case PostFiltersetsJSONBodyFsetStatsT: + return true + default: + return false + } +} + +// Defines values for PostFiltersetJSONBodyFsetStats. +const ( + PostFiltersetJSONBodyFsetStatsF PostFiltersetJSONBodyFsetStats = "F" + PostFiltersetJSONBodyFsetStatsT PostFiltersetJSONBodyFsetStats = "T" +) + +// Valid indicates whether the value is a known member of the PostFiltersetJSONBodyFsetStats enum. +func (e PostFiltersetJSONBodyFsetStats) Valid() bool { + switch e { + case PostFiltersetJSONBodyFsetStatsF: + return true + case PostFiltersetJSONBodyFsetStatsT: + return true + default: + return false + } +} + +// Defines values for PostFiltersetFilterJSONBodyFLogOp. +const ( + PostFiltersetFilterJSONBodyFLogOpAND PostFiltersetFilterJSONBodyFLogOp = "AND" + PostFiltersetFilterJSONBodyFLogOpANDNOT PostFiltersetFilterJSONBodyFLogOp = "AND NOT" + PostFiltersetFilterJSONBodyFLogOpOR PostFiltersetFilterJSONBodyFLogOp = "OR" + PostFiltersetFilterJSONBodyFLogOpORNOT PostFiltersetFilterJSONBodyFLogOp = "OR NOT" +) + +// Valid indicates whether the value is a known member of the PostFiltersetFilterJSONBodyFLogOp enum. +func (e PostFiltersetFilterJSONBodyFLogOp) Valid() bool { + switch e { + case PostFiltersetFilterJSONBodyFLogOpAND: + return true + case PostFiltersetFilterJSONBodyFLogOpANDNOT: + return true + case PostFiltersetFilterJSONBodyFLogOpOR: + return true + case PostFiltersetFilterJSONBodyFLogOpORNOT: + return true + default: + return false + } +} + +// Defines values for PostFiltersetFiltersetJSONBodyFLogOp. +const ( + PostFiltersetFiltersetJSONBodyFLogOpAND PostFiltersetFiltersetJSONBodyFLogOp = "AND" + PostFiltersetFiltersetJSONBodyFLogOpANDNOT PostFiltersetFiltersetJSONBodyFLogOp = "AND NOT" + PostFiltersetFiltersetJSONBodyFLogOpOR PostFiltersetFiltersetJSONBodyFLogOp = "OR" + PostFiltersetFiltersetJSONBodyFLogOpORNOT PostFiltersetFiltersetJSONBodyFLogOp = "OR NOT" +) + +// Valid indicates whether the value is a known member of the PostFiltersetFiltersetJSONBodyFLogOp enum. +func (e PostFiltersetFiltersetJSONBodyFLogOp) Valid() bool { + switch e { + case PostFiltersetFiltersetJSONBodyFLogOpAND: + return true + case PostFiltersetFiltersetJSONBodyFLogOpANDNOT: + return true + case PostFiltersetFiltersetJSONBodyFLogOpOR: + return true + case PostFiltersetFiltersetJSONBodyFLogOpORNOT: + return true + default: + return false + } +} + +// Defines values for PostFiltersetsFiltersJSONBodyFLogOp. +const ( + PostFiltersetsFiltersJSONBodyFLogOpAND PostFiltersetsFiltersJSONBodyFLogOp = "AND" + PostFiltersetsFiltersJSONBodyFLogOpANDNOT PostFiltersetsFiltersJSONBodyFLogOp = "AND NOT" + PostFiltersetsFiltersJSONBodyFLogOpOR PostFiltersetsFiltersJSONBodyFLogOp = "OR" + PostFiltersetsFiltersJSONBodyFLogOpORNOT PostFiltersetsFiltersJSONBodyFLogOp = "OR NOT" +) + +// Valid indicates whether the value is a known member of the PostFiltersetsFiltersJSONBodyFLogOp enum. +func (e PostFiltersetsFiltersJSONBodyFLogOp) Valid() bool { + switch e { + case PostFiltersetsFiltersJSONBodyFLogOpAND: + return true + case PostFiltersetsFiltersJSONBodyFLogOpANDNOT: + return true + case PostFiltersetsFiltersJSONBodyFLogOpOR: + return true + case PostFiltersetsFiltersJSONBodyFLogOpORNOT: + return true + default: + return false + } +} + +// Defines values for PostFiltersetsFiltersetsJSONBodyFLogOp. +const ( + PostFiltersetsFiltersetsJSONBodyFLogOpAND PostFiltersetsFiltersetsJSONBodyFLogOp = "AND" + PostFiltersetsFiltersetsJSONBodyFLogOpANDNOT PostFiltersetsFiltersetsJSONBodyFLogOp = "AND NOT" + PostFiltersetsFiltersetsJSONBodyFLogOpOR PostFiltersetsFiltersetsJSONBodyFLogOp = "OR" + PostFiltersetsFiltersetsJSONBodyFLogOpORNOT PostFiltersetsFiltersetsJSONBodyFLogOp = "OR NOT" +) + +// Valid indicates whether the value is a known member of the PostFiltersetsFiltersetsJSONBodyFLogOp enum. +func (e PostFiltersetsFiltersetsJSONBodyFLogOp) Valid() bool { + switch e { + case PostFiltersetsFiltersetsJSONBodyFLogOpAND: + return true + case PostFiltersetsFiltersetsJSONBodyFLogOpANDNOT: + return true + case PostFiltersetsFiltersetsJSONBodyFLogOpOR: + return true + case PostFiltersetsFiltersetsJSONBodyFLogOpORNOT: + return true + default: + return false + } +} + // Defines values for PostNodesJSONBodyActionType. const ( PostNodesJSONBodyActionTypePull PostNodesJSONBodyActionType = "pull" @@ -280,6 +412,126 @@ type FilterRow struct { Id *int `json:"id,omitempty"` } +// FiltersetExport A filterset and every filterset it encapsulates, recursively, each with its +// ordered entries. An entry holds either a filter or the name of an +// encapsulated filterset. +type FiltersetExport struct { + Filtersets []FiltersetExportItem `json:"filtersets"` +} + +// FiltersetExportEntry defines model for FiltersetExportEntry. +type FiltersetExportEntry struct { + FLogOp string `json:"f_log_op"` + FOrder int `json:"f_order"` + Filter *FiltersetExportFilter `json:"filter,omitempty"` + + // Filterset Name of the encapsulated filterset, when the entry is not a filter. + Filterset *string `json:"filterset,omitempty"` +} + +// FiltersetExportFilter defines model for FiltersetExportFilter. +type FiltersetExportFilter struct { + FField string `json:"f_field"` + FOp string `json:"f_op"` + FTable string `json:"f_table"` + FValue string `json:"f_value"` + Id int `json:"id"` +} + +// FiltersetExportItem defines model for FiltersetExportItem. +type FiltersetExportItem struct { + Filters []FiltersetExportEntry `json:"filters"` + FsetName string `json:"fset_name"` + FsetStats *string `json:"fset_stats,omitempty"` + Id int `json:"id"` +} + +// FiltersetFilterListResponse defines model for FiltersetFilterListResponse. +type FiltersetFilterListResponse struct { + Data FiltersetFilterListResponse_Data `json:"data"` + Meta *ListMeta `json:"meta,omitempty"` +} + +// FiltersetFilterListResponseData0 defines model for . +type FiltersetFilterListResponseData0 = []FiltersetFilterRow + +// FiltersetFilterListResponseData1 defines model for . +type FiltersetFilterListResponseData1 map[string]map[string]int + +// FiltersetFilterListResponse_Data defines model for FiltersetFilterListResponse.Data. +type FiltersetFilterListResponse_Data struct { + union json.RawMessage +} + +// FiltersetFilterRow A filter attached to a filterset: the filter properties, plus its position +// (`f_order`) and the logical operator joining it to the previous entry. +type FiltersetFilterRow struct { + EncapFsetId *int `json:"encap_fset_id,omitempty"` + FAuthor *string `json:"f_author,omitempty"` + FCksum *string `json:"f_cksum,omitempty"` + FField *string `json:"f_field,omitempty"` + FLabel *string `json:"f_label,omitempty"` + FLogOp *string `json:"f_log_op,omitempty"` + FOp *string `json:"f_op,omitempty"` + FOrder *int `json:"f_order,omitempty"` + FTable *string `json:"f_table,omitempty"` + FUpdated *string `json:"f_updated,omitempty"` + FValue *string `json:"f_value,omitempty"` + FsetId *int `json:"fset_id,omitempty"` + Id *int `json:"id,omitempty"` + JoinId *int `json:"join_id,omitempty"` +} + +// FiltersetListResponse defines model for FiltersetListResponse. +type FiltersetListResponse struct { + Data FiltersetListResponse_Data `json:"data"` + Meta *ListMeta `json:"meta,omitempty"` +} + +// FiltersetListResponseData0 defines model for . +type FiltersetListResponseData0 = []FiltersetRow + +// FiltersetListResponseData1 defines model for . +type FiltersetListResponseData1 map[string]map[string]int + +// FiltersetListResponse_Data defines model for FiltersetListResponse.Data. +type FiltersetListResponse_Data struct { + union json.RawMessage +} + +// FiltersetRef defines model for FiltersetRef. +type FiltersetRef struct { + FsetName *string `json:"fset_name,omitempty"` + Id int `json:"id"` +} + +// FiltersetRow A filterset: an ordered combination of filters and other filtersets that +// selects nodes and services. Every property is optional: the `props` query +// parameter selects which columns the server returns. +type FiltersetRow struct { + FsetAuthor *string `json:"fset_author,omitempty"` + FsetName *string `json:"fset_name,omitempty"` + + // FsetStats T for a stats filterset, F otherwise. + FsetStats *string `json:"fset_stats,omitempty"` + FsetUpdated *string `json:"fset_updated,omitempty"` + Id *int `json:"id,omitempty"` +} + +// FiltersetUsageResponse defines model for FiltersetUsageResponse. +type FiltersetUsageResponse struct { + Data struct { + // Filtersets Filtersets encapsulating this one. + Filtersets []FiltersetRef `json:"filtersets"` + + // Rulesets Compliance rulesets restricted by this filterset. The ruleset name is in `fset_name`. + Rulesets []FiltersetRef `json:"rulesets"` + + // Thresholds Check thresholds, as "chk_type.chk_instance:low-high". + Thresholds []string `json:"thresholds"` + } `json:"data"` +} + // GroupListResponse defines model for GroupListResponse. type GroupListResponse struct { Data GroupListResponse_Data `json:"data"` @@ -1393,12 +1645,15 @@ type PostFiltersetsJSONBody struct { FsetName *string `json:"fset_name,omitempty"` // FsetStats Whether the filterset is a stats filterset (T or F) - FsetStats *string `json:"fset_stats,omitempty"` + FsetStats *PostFiltersetsJSONBodyFsetStats `json:"fset_stats,omitempty"` // Id Filterset record id or name, to update an existing filterset Id *string `json:"id,omitempty"` } +// PostFiltersetsJSONBodyFsetStats defines parameters for PostFiltersets. +type PostFiltersetsJSONBodyFsetStats string + // GetFiltersetParams defines parameters for GetFilterset. type GetFiltersetParams struct { // Props A list of properties to include in each data dictionnary. @@ -1425,10 +1680,13 @@ type GetFiltersetParams struct { // PostFiltersetJSONBody defines parameters for PostFilterset. type PostFiltersetJSONBody struct { - FsetName *string `json:"fset_name,omitempty"` - FsetStats *string `json:"fset_stats,omitempty"` + FsetName *string `json:"fset_name,omitempty"` + FsetStats *PostFiltersetJSONBodyFsetStats `json:"fset_stats,omitempty"` } +// PostFiltersetJSONBodyFsetStats defines parameters for PostFilterset. +type PostFiltersetJSONBodyFsetStats string + // GetFiltersetFiltersParams defines parameters for GetFiltersetFilters. type GetFiltersetFiltersParams struct { // Props A list of properties to include in each data dictionnary. @@ -1455,10 +1713,13 @@ type GetFiltersetFiltersParams struct { // PostFiltersetFilterJSONBody defines parameters for PostFiltersetFilter. type PostFiltersetFilterJSONBody struct { - FLogOp *string `json:"f_log_op,omitempty"` - FOrder *int `json:"f_order,omitempty"` + FLogOp *PostFiltersetFilterJSONBodyFLogOp `json:"f_log_op,omitempty"` + FOrder *int `json:"f_order,omitempty"` } +// PostFiltersetFilterJSONBodyFLogOp defines parameters for PostFiltersetFilter. +type PostFiltersetFilterJSONBodyFLogOp string + // GetFiltersetFiltersetsParams defines parameters for GetFiltersetFiltersets. type GetFiltersetFiltersetsParams struct { // Props A list of properties to include in each data dictionnary. @@ -1485,10 +1746,13 @@ type GetFiltersetFiltersetsParams struct { // PostFiltersetFiltersetJSONBody defines parameters for PostFiltersetFilterset. type PostFiltersetFiltersetJSONBody struct { - FLogOp *string `json:"f_log_op,omitempty"` - FOrder *int `json:"f_order,omitempty"` + FLogOp *PostFiltersetFiltersetJSONBodyFLogOp `json:"f_log_op,omitempty"` + FOrder *int `json:"f_order,omitempty"` } +// PostFiltersetFiltersetJSONBodyFLogOp defines parameters for PostFiltersetFilterset. +type PostFiltersetFiltersetJSONBodyFLogOp string + // GetFiltersetNodesParams defines parameters for GetFiltersetNodes. type GetFiltersetNodesParams struct { // Props A list of properties to include in each data dictionnary. @@ -1552,7 +1816,7 @@ type PostFiltersetsFiltersJSONBody struct { FId string `json:"f_id"` // FLogOp Logical operator joining this filter to the previous one - FLogOp *string `json:"f_log_op,omitempty"` + FLogOp *PostFiltersetsFiltersJSONBodyFLogOp `json:"f_log_op,omitempty"` // FOrder Position of the filter in the filterset FOrder *int `json:"f_order,omitempty"` @@ -1561,6 +1825,9 @@ type PostFiltersetsFiltersJSONBody struct { FsetId string `json:"fset_id"` } +// PostFiltersetsFiltersJSONBodyFLogOp defines parameters for PostFiltersetsFilters. +type PostFiltersetsFiltersJSONBodyFLogOp string + // DeleteFiltersetsFiltersetsJSONBody defines parameters for DeleteFiltersetsFiltersets. type DeleteFiltersetsFiltersetsJSONBody struct { // ChildFsetId Child filterset record id, or name @@ -1576,7 +1843,7 @@ type PostFiltersetsFiltersetsJSONBody struct { ChildFsetId string `json:"child_fset_id"` // FLogOp Logical operator joining this filterset to the previous entry - FLogOp *string `json:"f_log_op,omitempty"` + FLogOp *PostFiltersetsFiltersetsJSONBodyFLogOp `json:"f_log_op,omitempty"` // FOrder Position of the child filterset in the parent filterset FOrder *int `json:"f_order,omitempty"` @@ -1585,6 +1852,9 @@ type PostFiltersetsFiltersetsJSONBody struct { ParentFsetId string `json:"parent_fset_id"` } +// PostFiltersetsFiltersetsJSONBodyFLogOp defines parameters for PostFiltersetsFiltersets. +type PostFiltersetsFiltersetsJSONBodyFLogOp string + // GetFrontendHiddenMenuEntriesParams defines parameters for GetFrontendHiddenMenuEntries. type GetFrontendHiddenMenuEntriesParams struct { // Props A list of properties to include in each data dictionnary. @@ -4111,6 +4381,130 @@ func (t *FilterListResponse_Data) UnmarshalJSON(b []byte) error { return err } +// AsFiltersetFilterListResponseData0 returns the union data inside the FiltersetFilterListResponse_Data as a FiltersetFilterListResponseData0 +func (t FiltersetFilterListResponse_Data) AsFiltersetFilterListResponseData0() (FiltersetFilterListResponseData0, error) { + var body FiltersetFilterListResponseData0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromFiltersetFilterListResponseData0 overwrites any union data inside the FiltersetFilterListResponse_Data as the provided FiltersetFilterListResponseData0 +func (t *FiltersetFilterListResponse_Data) FromFiltersetFilterListResponseData0(v FiltersetFilterListResponseData0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeFiltersetFilterListResponseData0 performs a merge with any union data inside the FiltersetFilterListResponse_Data, using the provided FiltersetFilterListResponseData0 +func (t *FiltersetFilterListResponse_Data) MergeFiltersetFilterListResponseData0(v FiltersetFilterListResponseData0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsFiltersetFilterListResponseData1 returns the union data inside the FiltersetFilterListResponse_Data as a FiltersetFilterListResponseData1 +func (t FiltersetFilterListResponse_Data) AsFiltersetFilterListResponseData1() (FiltersetFilterListResponseData1, error) { + var body FiltersetFilterListResponseData1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromFiltersetFilterListResponseData1 overwrites any union data inside the FiltersetFilterListResponse_Data as the provided FiltersetFilterListResponseData1 +func (t *FiltersetFilterListResponse_Data) FromFiltersetFilterListResponseData1(v FiltersetFilterListResponseData1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeFiltersetFilterListResponseData1 performs a merge with any union data inside the FiltersetFilterListResponse_Data, using the provided FiltersetFilterListResponseData1 +func (t *FiltersetFilterListResponse_Data) MergeFiltersetFilterListResponseData1(v FiltersetFilterListResponseData1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t FiltersetFilterListResponse_Data) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *FiltersetFilterListResponse_Data) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + +// AsFiltersetListResponseData0 returns the union data inside the FiltersetListResponse_Data as a FiltersetListResponseData0 +func (t FiltersetListResponse_Data) AsFiltersetListResponseData0() (FiltersetListResponseData0, error) { + var body FiltersetListResponseData0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromFiltersetListResponseData0 overwrites any union data inside the FiltersetListResponse_Data as the provided FiltersetListResponseData0 +func (t *FiltersetListResponse_Data) FromFiltersetListResponseData0(v FiltersetListResponseData0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeFiltersetListResponseData0 performs a merge with any union data inside the FiltersetListResponse_Data, using the provided FiltersetListResponseData0 +func (t *FiltersetListResponse_Data) MergeFiltersetListResponseData0(v FiltersetListResponseData0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsFiltersetListResponseData1 returns the union data inside the FiltersetListResponse_Data as a FiltersetListResponseData1 +func (t FiltersetListResponse_Data) AsFiltersetListResponseData1() (FiltersetListResponseData1, error) { + var body FiltersetListResponseData1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromFiltersetListResponseData1 overwrites any union data inside the FiltersetListResponse_Data as the provided FiltersetListResponseData1 +func (t *FiltersetListResponse_Data) FromFiltersetListResponseData1(v FiltersetListResponseData1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeFiltersetListResponseData1 performs a merge with any union data inside the FiltersetListResponse_Data, using the provided FiltersetListResponseData1 +func (t *FiltersetListResponse_Data) MergeFiltersetListResponseData1(v FiltersetListResponseData1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t FiltersetListResponse_Data) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *FiltersetListResponse_Data) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + // AsGroupListResponseData0 returns the union data inside the GroupListResponse_Data as a GroupListResponseData0 func (t GroupListResponse_Data) AsGroupListResponseData0() (GroupListResponseData0, error) { var body GroupListResponseData0 diff --git a/server/handlers/post_filters.go b/server/handlers/post_filters.go index 87723cdf..a4862a74 100644 --- a/server/handlers/post_filters.go +++ b/server/handlers/post_filters.go @@ -32,6 +32,13 @@ var filterTables = []string{ var filterOperators = []string{"=", "LIKE", ">", ">=", "<", "<=", "IN"} +// filtersetLogOps are the logical operators joining an entry of a filterset to the +// previous one, as in the historical collector (gen_filtersets_filters.f_log_op). +var filtersetLogOps = []string{"AND", "AND NOT", "OR", "OR NOT"} + +// filtersetStatsValues are the accepted values of gen_filtersets.fset_stats. +var filtersetStatsValues = []string{"T", "F"} + // PostFilters handles POST /filters func (a *Api) PostFilters(c echo.Context) error { log := echolog.GetLogHandler(c, "PostFilters") diff --git a/server/handlers/post_filterset.go b/server/handlers/post_filterset.go index de37020e..9d71c6f6 100644 --- a/server/handlers/post_filterset.go +++ b/server/handlers/post_filterset.go @@ -6,6 +6,7 @@ import ( "fmt" "log/slog" "net/http" + "slices" "strconv" "strings" @@ -35,7 +36,7 @@ func (a *Api) PostFilterset(c echo.Context, filtersetId string) error { log.Info("called", "filterset_id", filtersetId) - return a.postFiltersetUpdate(c, log, ctx, filtersetId, body.FsetName, body.FsetStats) + return a.postFiltersetUpdate(c, log, ctx, filtersetId, body.FsetName, stringPtr(body.FsetStats)) } func (a *Api) postFiltersetUpdate(c echo.Context, log *slog.Logger, ctx context.Context, filtersetId string, fsetName, fsetStats *string) error { @@ -68,6 +69,23 @@ func (a *Api) postFiltersetUpdate(c echo.Context, log *slog.Logger, ctx context. return a.handleItem(c, "PostFilterset", "filterset", "id", strconv.Itoa(id), listEndpointParams{}, getFilterset) } + if fsetStats != nil && !slices.Contains(filtersetStatsValues, *fsetStats) { + return JSONProblemf(c, http.StatusBadRequest, "fset_stats must be one of %s", strings.Join(filtersetStatsValues, ", ")) + } + if fsetName != nil { + if *fsetName == "" { + return JSONProblemf(c, http.StatusBadRequest, "fset_name cannot be empty") + } + otherID, taken, err := odb.FiltersetByName(ctx, *fsetName) + if err != nil { + log.Error("cannot check filterset name", "fset_name", *fsetName, logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot check filterset name") + } + if taken && otherID != id { + return JSONProblemf(c, http.StatusConflict, "a filterset named %s already exists: %d", *fsetName, otherID) + } + } + fields := cdb.UpdateFiltersetFields{ FsetName: fsetName, FsetStats: fsetStats, @@ -83,30 +101,33 @@ func (a *Api) postFiltersetUpdate(c echo.Context, log *slog.Logger, ctx context. userEmail, _ := c.Get(XUserEmail).(string) - tx, markSuccess, endTx, err := odb.BeginTxWithControl(ctx, log, &sql.TxOptions{}) - if err != nil { - log.Error("cannot start transaction", logkey.Error, err) - return JSONProblemf(c, http.StatusInternalServerError, "cannot update filterset") - } - defer endTx() - - if err := tx.UpdateFilterset(ctx, id, fields); err != nil { + // The transaction ends before the filterset is read back: a read done while it + // is still open, on another connection, returns the previous values. + if err := func() error { + tx, markSuccess, endTx, err := odb.BeginTxWithControl(ctx, log, &sql.TxOptions{}) + if err != nil { + return fmt.Errorf("cannot start transaction: %w", err) + } + defer endTx() + if err := tx.UpdateFilterset(ctx, id, fields); err != nil { + return err + } + if logErr := tx.Log(ctx, cdb.LogEntry{ + Action: "filterset.change", + User: userEmail, + Fmt: "change filterset %(data)s", + Dict: map[string]any{"data": strings.Join(changes, ", ")}, + Level: "info", + }); logErr != nil { + log.Error("cannot write audit log", logkey.Error, logErr) + } + markSuccess() + return nil + }(); err != nil { log.Error("cannot update filterset", "filterset_id", id, logkey.Error, err) return JSONProblemf(c, http.StatusInternalServerError, "cannot update filterset") } - if logErr := tx.Log(ctx, cdb.LogEntry{ - Action: "filterset.change", - User: userEmail, - Fmt: "change filterset %(data)s", - Dict: map[string]any{"data": strings.Join(changes, ", ")}, - Level: "info", - }); logErr != nil { - log.Error("cannot write audit log", logkey.Error, logErr) - } - - markSuccess() - if err := odb.Session.NotifyChanges(ctx); err != nil { log.Error("cannot notify changes", logkey.Error, err) } diff --git a/server/handlers/post_filterset_filter.go b/server/handlers/post_filterset_filter.go index e258a845..c6246900 100644 --- a/server/handlers/post_filterset_filter.go +++ b/server/handlers/post_filterset_filter.go @@ -5,6 +5,8 @@ import ( "fmt" "log/slog" "net/http" + "slices" + "strings" "github.com/labstack/echo/v4" @@ -32,10 +34,13 @@ func (a *Api) PostFiltersetFilter(c echo.Context, filtersetId string, fId string log.Info("called", "filterset_id", filtersetId, "f_id", fId) - return a.postFiltersetFilter(c, log, ctx, filtersetId, fId, body.FLogOp, body.FOrder) + return a.postFiltersetFilter(c, log, ctx, filtersetId, fId, stringPtr(body.FLogOp), body.FOrder) } func (a *Api) postFiltersetFilter(c echo.Context, log *slog.Logger, ctx context.Context, filtersetId, fId string, fLogOp *string, fOrder *int) error { + if fLogOp != nil && !slices.Contains(filtersetLogOps, *fLogOp) { + return JSONProblemf(c, http.StatusBadRequest, "f_log_op must be one of %s", strings.Join(filtersetLogOps, ", ")) + } odb := a.ODB fsetID, found, err := odb.FiltersetID(ctx, filtersetId) diff --git a/server/handlers/post_filterset_filterset.go b/server/handlers/post_filterset_filterset.go index c42f60e3..f205835e 100644 --- a/server/handlers/post_filterset_filterset.go +++ b/server/handlers/post_filterset_filterset.go @@ -5,6 +5,8 @@ import ( "fmt" "log/slog" "net/http" + "slices" + "strings" "github.com/labstack/echo/v4" @@ -33,10 +35,13 @@ func (a *Api) PostFiltersetFilterset(c echo.Context, filtersetId string, childId log.Info("called", "filterset_id", filtersetId, "child_id", childId) - return a.postFiltersetFilterset(c, log, ctx, filtersetId, childId, body.FLogOp, body.FOrder) + return a.postFiltersetFilterset(c, log, ctx, filtersetId, childId, stringPtr(body.FLogOp), body.FOrder) } func (a *Api) postFiltersetFilterset(c echo.Context, log *slog.Logger, ctx context.Context, filtersetId, childId string, fLogOp *string, fOrder *int) error { + if fLogOp != nil && !slices.Contains(filtersetLogOps, *fLogOp) { + return JSONProblemf(c, http.StatusBadRequest, "f_log_op must be one of %s", strings.Join(filtersetLogOps, ", ")) + } odb := a.ODB parentID, found, err := odb.FiltersetID(ctx, filtersetId) diff --git a/server/handlers/post_filtersets.go b/server/handlers/post_filtersets.go index be223031..079518fd 100644 --- a/server/handlers/post_filtersets.go +++ b/server/handlers/post_filtersets.go @@ -3,7 +3,9 @@ package serverhandlers import ( "context" "net/http" + "slices" "strconv" + "strings" "github.com/labstack/echo/v4" @@ -30,9 +32,13 @@ func (a *Api) PostFiltersets(c echo.Context) error { return JSONProblem(c, http.StatusBadRequest, err.Error()) } + if body.FsetStats != nil && !slices.Contains(filtersetStatsValues, string(*body.FsetStats)) { + return JSONProblemf(c, http.StatusBadRequest, "fset_stats must be one of %s", strings.Join(filtersetStatsValues, ", ")) + } + if body.Id != nil && *body.Id != "" { log.Info("called", "filterset_id", *body.Id) - return a.postFiltersetUpdate(c, log, ctx, *body.Id, nil, body.FsetStats) + return a.postFiltersetUpdate(c, log, ctx, *body.Id, nil, stringPtr(body.FsetStats)) } if body.FsetName == nil || *body.FsetName == "" { @@ -48,12 +54,12 @@ func (a *Api) PostFiltersets(c echo.Context) error { return JSONProblemf(c, http.StatusInternalServerError, "cannot check filterset existence") } if exists { - return a.postFiltersetUpdate(c, log, ctx, strconv.Itoa(existingID), nil, body.FsetStats) + return a.postFiltersetUpdate(c, log, ctx, strconv.Itoa(existingID), nil, stringPtr(body.FsetStats)) } fsetStats := "F" if body.FsetStats != nil { - fsetStats = *body.FsetStats + fsetStats = string(*body.FsetStats) } userEmail, _ := c.Get(XUserEmail).(string) diff --git a/server/handlers/post_filtersets_filters.go b/server/handlers/post_filtersets_filters.go index 3b90b745..fac7bb3a 100644 --- a/server/handlers/post_filtersets_filters.go +++ b/server/handlers/post_filtersets_filters.go @@ -35,5 +35,5 @@ func (a *Api) PostFiltersetsFilters(c echo.Context) error { log.Info("called", "filterset_id", body.FsetId, "f_id", body.FId) - return a.postFiltersetFilter(c, log, ctx, body.FsetId, body.FId, body.FLogOp, body.FOrder) + return a.postFiltersetFilter(c, log, ctx, body.FsetId, body.FId, stringPtr(body.FLogOp), body.FOrder) } diff --git a/server/handlers/post_filtersets_filtersets.go b/server/handlers/post_filtersets_filtersets.go index 7bf40eee..c401d0b7 100644 --- a/server/handlers/post_filtersets_filtersets.go +++ b/server/handlers/post_filtersets_filtersets.go @@ -35,5 +35,5 @@ func (a *Api) PostFiltersetsFiltersets(c echo.Context) error { log.Info("called", "parent_fset_id", body.ParentFsetId, "child_fset_id", body.ChildFsetId) - return a.postFiltersetFilterset(c, log, ctx, body.ParentFsetId, body.ChildFsetId, body.FLogOp, body.FOrder) + return a.postFiltersetFilterset(c, log, ctx, body.ParentFsetId, body.ChildFsetId, stringPtr(body.FLogOp), body.FOrder) } diff --git a/server/handlers/problems.go b/server/handlers/problems.go index 328481f2..67815511 100644 --- a/server/handlers/problems.go +++ b/server/handlers/problems.go @@ -37,3 +37,13 @@ func JSONProblem(ctx echo.Context, code int, s string) error { func JSONNodeAuthProblem(c echo.Context) error { return JSONProblem(c, http.StatusForbidden, "expecting node credentials") } + +// stringPtr converts a pointer to a generated enum string type to a *string, +// keeping nil for an absent property. +func stringPtr[T ~string](value *T) *string { + if value == nil { + return nil + } + s := string(*value) + return &s +} From 04b8905a8d224465fa9e9c5c8b961a42c4abf2c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Thu, 24 Sep 2026 14:38:12 +0200 Subject: [PATCH 19/61] Type the node and service sub-resource responses GET /nodes/{node_id}/hardware, hbas, disks, ips and alerts, and GET /services/{svc_id}/disks, now declare their row schemas instead of the generic ListResponse. --- server/api.yaml | 93 ++++++- server/codegen_server_gen.go | 468 ++++++++++++++++++----------------- server/codegen_type_gen.go | 185 ++++++++++++++ 3 files changed, 508 insertions(+), 238 deletions(-) diff --git a/server/api.yaml b/server/api.yaml index 17fbe9a5..d000fac7 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -3996,7 +3996,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/AlertListResponse' 404: $ref: '#/components/responses/404' 500: @@ -4387,7 +4387,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/DiskListResponse' 404: $ref: '#/components/responses/404' 500: @@ -4422,7 +4422,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/HbaListResponse' 404: $ref: '#/components/responses/404' 500: @@ -4457,7 +4457,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/NodeHardwareListResponse' 404: $ref: '#/components/responses/404' 500: @@ -4492,7 +4492,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/IpListResponse' 404: $ref: '#/components/responses/404' 500: @@ -6164,7 +6164,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/DiskListResponse' 404: $ref: '#/components/responses/404' 500: @@ -8181,6 +8181,87 @@ components: f_value: type: string + NodeHardwareRow: + type: object + description: | + A hardware component of a node, as reported by the agent's asset push: + `hw_type` is the component family (for example `pci` or `mem`), `hw_path` its + address. Every property is optional: the `props` query parameter selects which + columns the server returns. + properties: + id: + type: integer + node_id: + type: string + hw_type: + type: string + hw_path: + type: string + hw_class: + type: string + hw_description: + type: string + hw_driver: + type: string + updated: + type: string + + NodeHardwareListResponse: + type: object + required: + - data + properties: + data: + oneOf: + - type: array + items: + $ref: '#/components/schemas/NodeHardwareRow' + - type: object + additionalProperties: + type: object + additionalProperties: + type: integer + meta: + $ref: '#/components/schemas/ListMeta' + + HbaRow: + type: object + description: | + A host bus adapter of a node, as reported by the agent: `hba_id` is its + initiator identifier (an iSCSI IQN or a Fibre Channel WWPN), `hba_type` its + transport. Every property is optional: the `props` query parameter selects + which columns the server returns. + properties: + id: + type: integer + node_id: + type: string + hba_id: + type: string + hba_type: + type: string + nullable: true + updated: + type: string + + HbaListResponse: + type: object + required: + - data + properties: + data: + oneOf: + - type: array + items: + $ref: '#/components/schemas/HbaRow' + - type: object + additionalProperties: + type: object + additionalProperties: + type: integer + meta: + $ref: '#/components/schemas/ListMeta' + AlertListResponse: type: object required: diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index ed5b66c7..50ad584d 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -8993,238 +8993,242 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "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", - "Jmej75++/+8AAAD//w==", + "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", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index 644eced3..6c931639 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -559,6 +559,35 @@ type GroupRow struct { Role *string `json:"role,omitempty"` } +// HbaListResponse defines model for HbaListResponse. +type HbaListResponse struct { + Data HbaListResponse_Data `json:"data"` + Meta *ListMeta `json:"meta,omitempty"` +} + +// HbaListResponseData0 defines model for . +type HbaListResponseData0 = []HbaRow + +// HbaListResponseData1 defines model for . +type HbaListResponseData1 map[string]map[string]int + +// HbaListResponse_Data defines model for HbaListResponse.Data. +type HbaListResponse_Data struct { + union json.RawMessage +} + +// HbaRow A host bus adapter of a node, as reported by the agent: `hba_id` is its +// initiator identifier (an iSCSI IQN or a Fibre Channel WWPN), `hba_type` its +// transport. Every property is optional: the `props` query parameter selects +// which columns the server returns. +type HbaRow struct { + HbaId *string `json:"hba_id,omitempty"` + HbaType *string `json:"hba_type,omitempty"` + Id *int `json:"id,omitempty"` + NodeId *string `json:"node_id,omitempty"` + Updated *string `json:"updated,omitempty"` +} + // InfoResponse Outcome message of a write that returns no record. type InfoResponse struct { Info *string `json:"info,omitempty"` @@ -730,6 +759,38 @@ type LogRow struct { SvcId *string `json:"svc_id,omitempty"` } +// NodeHardwareListResponse defines model for NodeHardwareListResponse. +type NodeHardwareListResponse struct { + Data NodeHardwareListResponse_Data `json:"data"` + Meta *ListMeta `json:"meta,omitempty"` +} + +// NodeHardwareListResponseData0 defines model for . +type NodeHardwareListResponseData0 = []NodeHardwareRow + +// NodeHardwareListResponseData1 defines model for . +type NodeHardwareListResponseData1 map[string]map[string]int + +// NodeHardwareListResponse_Data defines model for NodeHardwareListResponse.Data. +type NodeHardwareListResponse_Data struct { + union json.RawMessage +} + +// NodeHardwareRow A hardware component of a node, as reported by the agent's asset push: +// `hw_type` is the component family (for example `pci` or `mem`), `hw_path` its +// address. Every property is optional: the `props` query parameter selects which +// columns the server returns. +type NodeHardwareRow struct { + HwClass *string `json:"hw_class,omitempty"` + HwDescription *string `json:"hw_description,omitempty"` + HwDriver *string `json:"hw_driver,omitempty"` + HwPath *string `json:"hw_path,omitempty"` + HwType *string `json:"hw_type,omitempty"` + Id *int `json:"id,omitempty"` + NodeId *string `json:"node_id,omitempty"` + Updated *string `json:"updated,omitempty"` +} + // NodeListResponse defines model for NodeListResponse. type NodeListResponse struct { Data NodeListResponse_Data `json:"data"` @@ -4567,6 +4628,68 @@ func (t *GroupListResponse_Data) UnmarshalJSON(b []byte) error { return err } +// AsHbaListResponseData0 returns the union data inside the HbaListResponse_Data as a HbaListResponseData0 +func (t HbaListResponse_Data) AsHbaListResponseData0() (HbaListResponseData0, error) { + var body HbaListResponseData0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromHbaListResponseData0 overwrites any union data inside the HbaListResponse_Data as the provided HbaListResponseData0 +func (t *HbaListResponse_Data) FromHbaListResponseData0(v HbaListResponseData0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeHbaListResponseData0 performs a merge with any union data inside the HbaListResponse_Data, using the provided HbaListResponseData0 +func (t *HbaListResponse_Data) MergeHbaListResponseData0(v HbaListResponseData0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsHbaListResponseData1 returns the union data inside the HbaListResponse_Data as a HbaListResponseData1 +func (t HbaListResponse_Data) AsHbaListResponseData1() (HbaListResponseData1, error) { + var body HbaListResponseData1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromHbaListResponseData1 overwrites any union data inside the HbaListResponse_Data as the provided HbaListResponseData1 +func (t *HbaListResponse_Data) FromHbaListResponseData1(v HbaListResponseData1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeHbaListResponseData1 performs a merge with any union data inside the HbaListResponse_Data, using the provided HbaListResponseData1 +func (t *HbaListResponse_Data) MergeHbaListResponseData1(v HbaListResponseData1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t HbaListResponse_Data) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *HbaListResponse_Data) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + // AsInstanceListResponseData0 returns the union data inside the InstanceListResponse_Data as a InstanceListResponseData0 func (t InstanceListResponse_Data) AsInstanceListResponseData0() (InstanceListResponseData0, error) { var body InstanceListResponseData0 @@ -4815,6 +4938,68 @@ func (t *LogListResponse_Data) UnmarshalJSON(b []byte) error { return err } +// AsNodeHardwareListResponseData0 returns the union data inside the NodeHardwareListResponse_Data as a NodeHardwareListResponseData0 +func (t NodeHardwareListResponse_Data) AsNodeHardwareListResponseData0() (NodeHardwareListResponseData0, error) { + var body NodeHardwareListResponseData0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromNodeHardwareListResponseData0 overwrites any union data inside the NodeHardwareListResponse_Data as the provided NodeHardwareListResponseData0 +func (t *NodeHardwareListResponse_Data) FromNodeHardwareListResponseData0(v NodeHardwareListResponseData0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeNodeHardwareListResponseData0 performs a merge with any union data inside the NodeHardwareListResponse_Data, using the provided NodeHardwareListResponseData0 +func (t *NodeHardwareListResponse_Data) MergeNodeHardwareListResponseData0(v NodeHardwareListResponseData0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsNodeHardwareListResponseData1 returns the union data inside the NodeHardwareListResponse_Data as a NodeHardwareListResponseData1 +func (t NodeHardwareListResponse_Data) AsNodeHardwareListResponseData1() (NodeHardwareListResponseData1, error) { + var body NodeHardwareListResponseData1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromNodeHardwareListResponseData1 overwrites any union data inside the NodeHardwareListResponse_Data as the provided NodeHardwareListResponseData1 +func (t *NodeHardwareListResponse_Data) FromNodeHardwareListResponseData1(v NodeHardwareListResponseData1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeNodeHardwareListResponseData1 performs a merge with any union data inside the NodeHardwareListResponse_Data, using the provided NodeHardwareListResponseData1 +func (t *NodeHardwareListResponse_Data) MergeNodeHardwareListResponseData1(v NodeHardwareListResponseData1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t NodeHardwareListResponse_Data) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *NodeHardwareListResponse_Data) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + // AsNodeListResponseData0 returns the union data inside the NodeListResponse_Data as a NodeListResponseData0 func (t NodeListResponse_Data) AsNodeListResponseData0() (NodeListResponseData0, error) { var body NodeListResponseData0 From 15e72b63b61ac9c2b59af8a811780f0934678e8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Thu, 24 Sep 2026 14:38:15 +0200 Subject: [PATCH 20/61] Add POST /networks Declare a network, with the NetworkManager privilege. The network address must match the netmask; begin, end and broadcast are computed by the database, and team_responsible defaults to the caller's primary group. A name or an address already declared is refused with a 409. --- cdb/db_networks_create.go | 129 ++++++++ server/api.yaml | 112 +++++++ server/codegen_server_gen.go | 496 ++++++++++++++++--------------- server/codegen_type_gen.go | 51 ++++ server/handlers/post_networks.go | 165 ++++++++++ 5 files changed, 717 insertions(+), 236 deletions(-) create mode 100644 cdb/db_networks_create.go create mode 100644 server/handlers/post_networks.go diff --git a/cdb/db_networks_create.go b/cdb/db_networks_create.go new file mode 100644 index 00000000..dcc8f26c --- /dev/null +++ b/cdb/db_networks_create.go @@ -0,0 +1,129 @@ +package cdb + +import ( + "context" + "database/sql" + "errors" + "fmt" +) + +// NetworkInsert holds the columns set when declaring a network. begin, end and +// broadcast are generated by the database from network and netmask. +type NetworkInsert struct { + Name *string + Network string + Netmask int + Gateway *string + Comment *string + Pvid *int + Prio int + TeamResponsible *string +} + +// NetworkIDByName returns the id of the network with this name, if any. +func (oDb *DB) NetworkIDByName(ctx context.Context, name string) (int, bool, error) { + var id int + err := oDb.DB.QueryRowContext(ctx, "SELECT id FROM networks WHERE name = ? LIMIT 1", name).Scan(&id) + if errors.Is(err, sql.ErrNoRows) { + return 0, false, nil + } + if err != nil { + return 0, false, fmt.Errorf("NetworkIDByName: %w", err) + } + return id, true, nil +} + +// NetworkIDByAddress returns the id of the network declared with this address and +// netmask, if any. +func (oDb *DB) NetworkIDByAddress(ctx context.Context, network string, netmask int) (int, bool, error) { + var id int + err := oDb.DB.QueryRowContext(ctx, + "SELECT id FROM networks WHERE network = ? AND netmask = ? LIMIT 1", network, netmask).Scan(&id) + if errors.Is(err, sql.ErrNoRows) { + return 0, false, nil + } + if err != nil { + return 0, false, fmt.Errorf("NetworkIDByAddress: %w", err) + } + return id, true, nil +} + +// IsAssignableTeam reports whether role names an organisational group: neither a +// privilege group nor a user's private group, as required for team_responsible in +// the historical collector. +func (oDb *DB) IsAssignableTeam(ctx context.Context, role string) (bool, error) { + var n int + err := oDb.DB.QueryRowContext(ctx, + "SELECT COUNT(*) FROM auth_group WHERE role = ? AND privilege = 'F' AND role NOT LIKE 'user\\_%'", + role).Scan(&n) + if err != nil { + return false, fmt.Errorf("IsAssignableTeam: %w", err) + } + return n > 0, nil +} + +// UserPrimaryGroupRole returns the role of the user's primary group, if any. +func (oDb *DB) UserPrimaryGroupRole(ctx context.Context, userID int64) (string, bool, error) { + const query = "SELECT auth_group.role FROM auth_group " + + "JOIN auth_membership ON auth_membership.group_id = auth_group.id " + + "WHERE auth_membership.user_id = ? AND auth_membership.primary_group = 'T' LIMIT 1" + var role sql.NullString + err := oDb.DB.QueryRowContext(ctx, query, userID).Scan(&role) + return checkRow(err, role.Valid, role.String) +} + +// InsertNetwork declares a network and returns its record id. +func (oDb *DB) InsertNetwork(ctx context.Context, n NetworkInsert) (int, error) { + res, err := oDb.ExecContext(ctx, + `INSERT INTO networks (name, network, netmask, gateway, comment, pvid, prio, team_responsible) + VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, + n.Name, n.Network, n.Netmask, n.Gateway, n.Comment, n.Pvid, n.Prio, n.TeamResponsible) + if err != nil { + return 0, fmt.Errorf("InsertNetwork: %w", err) + } + id, err := res.LastInsertId() + if err != nil { + return 0, fmt.Errorf("InsertNetwork: %w", err) + } + oDb.SetChange("networks") + return int(id), nil +} + +// GetNetworkRow returns a declared network, generated columns included. +func (oDb *DB) GetNetworkRow(ctx context.Context, id int) (map[string]any, error) { + const query = `SELECT id, COALESCE(name, ''), COALESCE(network, ''), netmask, + COALESCE(broadcast, ''), COALESCE(gateway, ''), COALESCE(begin, ''), COALESCE(end, ''), + pvid, prio, COALESCE(team_responsible, ''), COALESCE(comment, ''), updated + FROM networks WHERE id = ?` + var ( + rowID int + name, network, broadcast, gateway, begin, end string + team, comment string + netmask, pvid sql.NullInt64 + prio int + updated sql.NullTime + ) + err := oDb.DB.QueryRowContext(ctx, query, id).Scan(&rowID, &name, &network, &netmask, + &broadcast, &gateway, &begin, &end, &pvid, &prio, &team, &comment, &updated) + if errors.Is(err, sql.ErrNoRows) { + return nil, nil + } + if err != nil { + return nil, fmt.Errorf("GetNetworkRow: %w", err) + } + row := map[string]any{ + "id": rowID, "name": name, "network": network, "broadcast": broadcast, + "gateway": gateway, "begin": begin, "end": end, "prio": prio, + "team_responsible": team, "comment": comment, + } + if netmask.Valid { + row["netmask"] = netmask.Int64 + } + if pvid.Valid { + row["pvid"] = pvid.Int64 + } + if updated.Valid { + row["updated"] = updated.Time.Format("2006-01-02 15:04:05") + } + return row, nil +} diff --git a/server/api.yaml b/server/api.yaml index d000fac7..1703b0ee 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -3413,6 +3413,73 @@ paths: - basicAuth: [ ] - bearerAuth: [ ] + /networks: + post: + operationId: PostNetworks + description: | + Declare a network. Requires the NetworkManager privilege. `network` must be + the IPv4 network address for `netmask`; `begin`, `end` and `broadcast` are + computed by the database. `team_responsible` defaults to the caller's primary + group. A name or an address already declared is refused with a 409. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - network + - netmask + properties: + name: + type: string + network: + type: string + description: IPv4 network address, for example 192.168.10.0 + netmask: + type: integer + minimum: 0 + maximum: 32 + description: Prefix length + gateway: + type: string + description: IPv4 address inside the network + comment: + type: string + pvid: + type: integer + description: VLAN id + prio: + type: integer + minimum: 0 + maximum: 99 + description: Priority among overlapping networks + team_responsible: + type: string + description: Organisational group responsible for the network + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/NetworkListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 409: + $ref: '#/components/responses/409' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + /nodes: post: operationId: PostNodes @@ -8262,6 +8329,51 @@ components: meta: $ref: '#/components/schemas/ListMeta' + NetworkRow: + type: object + description: | + A declared network. `begin`, `end` and `broadcast` are computed from + `network` and `netmask`. + properties: + id: + type: integer + name: + type: string + network: + type: string + netmask: + type: integer + broadcast: + type: string + gateway: + type: string + begin: + type: string + end: + type: string + pvid: + type: integer + prio: + type: integer + team_responsible: + type: string + comment: + type: string + updated: + type: string + + NetworkListResponse: + type: object + required: + - data + properties: + data: + type: array + items: + $ref: '#/components/schemas/NetworkRow' + info: + type: string + AlertListResponse: type: object required: diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index 50ad584d..6960d436 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -282,6 +282,9 @@ type ServerInterface interface { // (GET /logs/{log_id}) GetLog(ctx echo.Context, logId string, params GetLogParams) error + // (POST /networks) + PostNetworks(ctx echo.Context) error + // (DELETE /nodes) DeleteNodes(ctx echo.Context) error @@ -3989,6 +3992,19 @@ func (w *ServerInterfaceWrapper) GetLog(ctx echo.Context) error { return err } +// PostNetworks converts echo context to params. +func (w *ServerInterfaceWrapper) PostNetworks(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostNetworks(ctx) + return err +} + // DeleteNodes converts echo context to params. func (w *ServerInterfaceWrapper) DeleteNodes(ctx echo.Context) error { var err error @@ -8886,6 +8902,7 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.GET(options.BaseURL+"/logs", wrapper.GetLogs, options.OperationMiddlewares["GetLogs"]...) router.POST(options.BaseURL+"/logs", wrapper.PostLogs, options.OperationMiddlewares["PostLogs"]...) router.GET(options.BaseURL+"/logs/:log_id", wrapper.GetLog, options.OperationMiddlewares["GetLog"]...) + router.POST(options.BaseURL+"/networks", wrapper.PostNetworks, options.OperationMiddlewares["PostNetworks"]...) router.DELETE(options.BaseURL+"/nodes", wrapper.DeleteNodes, options.OperationMiddlewares["DeleteNodes"]...) router.GET(options.BaseURL+"/nodes", wrapper.GetNodes, options.OperationMiddlewares["GetNodes"]...) router.POST(options.BaseURL+"/nodes", wrapper.PostNodes, options.OperationMiddlewares["PostNodes"]...) @@ -8993,242 +9010,249 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "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", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index 6c931639..9b2b9605 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -759,6 +759,30 @@ type LogRow struct { SvcId *string `json:"svc_id,omitempty"` } +// NetworkListResponse defines model for NetworkListResponse. +type NetworkListResponse struct { + Data []NetworkRow `json:"data"` + Info *string `json:"info,omitempty"` +} + +// NetworkRow A declared network. `begin`, `end` and `broadcast` are computed from +// `network` and `netmask`. +type NetworkRow struct { + Begin *string `json:"begin,omitempty"` + Broadcast *string `json:"broadcast,omitempty"` + Comment *string `json:"comment,omitempty"` + End *string `json:"end,omitempty"` + Gateway *string `json:"gateway,omitempty"` + Id *int `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Netmask *int `json:"netmask,omitempty"` + Network *string `json:"network,omitempty"` + Prio *int `json:"prio,omitempty"` + Pvid *int `json:"pvid,omitempty"` + TeamResponsible *string `json:"team_responsible,omitempty"` + Updated *string `json:"updated,omitempty"` +} + // NodeHardwareListResponse defines model for NodeHardwareListResponse. type NodeHardwareListResponse struct { Data NodeHardwareListResponse_Data `json:"data"` @@ -2314,6 +2338,30 @@ type GetLogParams struct { Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` } +// PostNetworksJSONBody defines parameters for PostNetworks. +type PostNetworksJSONBody struct { + Comment *string `json:"comment,omitempty"` + + // Gateway IPv4 address inside the network + Gateway *string `json:"gateway,omitempty"` + Name *string `json:"name,omitempty"` + + // Netmask Prefix length + Netmask int `json:"netmask"` + + // Network IPv4 network address, for example 192.168.10.0 + Network string `json:"network"` + + // Prio Priority among overlapping networks + Prio *int `json:"prio,omitempty"` + + // Pvid VLAN id + Pvid *int `json:"pvid,omitempty"` + + // TeamResponsible Organisational group responsible for the network + TeamResponsible *string `json:"team_responsible,omitempty"` +} + // DeleteNodesJSONBody defines parameters for DeleteNodes. type DeleteNodesJSONBody struct { // NodeId Node identifier (node_id or nodename) @@ -4125,6 +4173,9 @@ type DeleteIpsJSONRequestBody DeleteIpsJSONBody // PostLogsJSONRequestBody defines body for PostLogs for application/json ContentType. type PostLogsJSONRequestBody PostLogsJSONBody +// PostNetworksJSONRequestBody defines body for PostNetworks for application/json ContentType. +type PostNetworksJSONRequestBody PostNetworksJSONBody + // DeleteNodesJSONRequestBody defines body for DeleteNodes for application/json ContentType. type DeleteNodesJSONRequestBody DeleteNodesJSONBody diff --git a/server/handlers/post_networks.go b/server/handlers/post_networks.go new file mode 100644 index 00000000..62d65583 --- /dev/null +++ b/server/handlers/post_networks.go @@ -0,0 +1,165 @@ +package serverhandlers + +import ( + "context" + "fmt" + "net/http" + "net/netip" + "strings" + + "github.com/labstack/echo/v4" + + "github.com/opensvc/oc3/cdb" + "github.com/opensvc/oc3/server" + "github.com/opensvc/oc3/util/echolog" + "github.com/opensvc/oc3/util/logkey" +) + +func IsNetworkManager(c echo.Context) bool { + return IsManager(c) || HasGroup(c, "NetworkManager") +} + +func requireNetworkManager(c echo.Context) error { + if !IsAuthByUser(c) { + return denyRequest(c, http.StatusUnauthorized, "user authentication required") + } + if !IsNetworkManager(c) { + return denyRequest(c, http.StatusForbidden, "NetworkManager privilege required") + } + return nil +} + +// PostNetworks handles POST /networks: declare a network, as the historical +// collector's rest_post_networks did. +func (a *Api) PostNetworks(c echo.Context) error { + log := echolog.GetLogHandler(c, "PostNetworks") + odb := a.ODB + ctx, cancel := context.WithTimeout(c.Request().Context(), a.SyncTimeout) + defer cancel() + + if err := requireNetworkManager(c); err != nil { + return err + } + + var body server.PostNetworksJSONRequestBody + if err := c.Bind(&body); err != nil { + log.Error("invalid request body", logkey.Error, err) + return JSONProblem(c, http.StatusBadRequest, err.Error()) + } + + // The begin, end and broadcast columns are computed with inet_aton: IPv4 only. + addr, err := netip.ParseAddr(strings.TrimSpace(body.Network)) + if err != nil || !addr.Is4() { + return JSONProblemf(c, http.StatusBadRequest, "network must be an IPv4 address, got %q", body.Network) + } + if body.Netmask < 0 || body.Netmask > 32 { + return JSONProblemf(c, http.StatusBadRequest, "netmask must be a prefix length between 0 and 32") + } + prefix := netip.PrefixFrom(addr, body.Netmask) + if masked := prefix.Masked(); masked.Addr() != addr { + return JSONProblemf(c, http.StatusBadRequest, "%s is not a network address, did you mean %s?", prefix, masked) + } + + insert := cdb.NetworkInsert{Network: addr.String(), Netmask: body.Netmask} + + if body.Gateway != nil && strings.TrimSpace(*body.Gateway) != "" { + gw, err := netip.ParseAddr(strings.TrimSpace(*body.Gateway)) + if err != nil || !gw.Is4() || !prefix.Contains(gw) { + return JSONProblemf(c, http.StatusBadRequest, "gateway must be an IPv4 address inside %s", prefix) + } + s := gw.String() + insert.Gateway = &s + } + if body.Prio != nil { + if *body.Prio < 0 || *body.Prio > 99 { + return JSONProblemf(c, http.StatusBadRequest, "prio must be between 0 and 99") + } + insert.Prio = *body.Prio + } + if body.Pvid != nil { + if *body.Pvid < 0 || *body.Pvid > 4094 { + return JSONProblemf(c, http.StatusBadRequest, "pvid must be a VLAN id between 0 and 4094") + } + insert.Pvid = body.Pvid + } + if body.Comment != nil && *body.Comment != "" { + insert.Comment = body.Comment + } + + if body.Name != nil && strings.TrimSpace(*body.Name) != "" { + name := strings.TrimSpace(*body.Name) + otherID, taken, err := odb.NetworkIDByName(ctx, name) + if err != nil { + log.Error("cannot check network name", logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot check network name") + } + if taken { + return JSONProblemf(c, http.StatusConflict, "a network named %s already exists: %d", name, otherID) + } + insert.Name = &name + } + otherID, taken, err := odb.NetworkIDByAddress(ctx, insert.Network, insert.Netmask) + if err != nil { + log.Error("cannot check network address", logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot check network address") + } + if taken { + return JSONProblemf(c, http.StatusConflict, "network %s is already declared: %d", prefix, otherID) + } + + // The responsible team defaults to the caller's primary group. + if body.TeamResponsible != nil && strings.TrimSpace(*body.TeamResponsible) != "" { + team := strings.TrimSpace(*body.TeamResponsible) + ok, err := odb.IsAssignableTeam(ctx, team) + if err != nil { + log.Error("cannot check team", logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot check team") + } + if !ok { + return JSONProblemf(c, http.StatusBadRequest, "team_responsible must be an existing organisational group, got %q", team) + } + insert.TeamResponsible = &team + } else if userID := authUserID(c); userID != nil { + role, found, err := odb.UserPrimaryGroupRole(ctx, *userID) + if err != nil { + log.Error("cannot get primary group", logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot get primary group") + } + if found { + insert.TeamResponsible = &role + } + } + + log.Info("called", "network", prefix.String()) + + id, err := odb.InsertNetwork(ctx, insert) + if err != nil { + log.Error("cannot create network", logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot create network") + } + + userEmail, _ := c.Get(XUserEmail).(string) + name := "" + if insert.Name != nil { + name = *insert.Name + } + if logErr := odb.Log(ctx, cdb.LogEntry{ + Action: "networks.create", + User: userEmail, + Fmt: "created network %(name)s %(network)s", + Dict: map[string]any{"name": name, "network": prefix.String()}, + Level: "info", + }); logErr != nil { + log.Error("cannot write audit log", logkey.Error, logErr) + } + if err := odb.Session.NotifyChanges(ctx); err != nil { + log.Error("cannot notify changes", logkey.Error, err) + } + + row, err := odb.GetNetworkRow(ctx, id) + if err != nil || row == nil { + log.Error("cannot read the created network", "id", id, logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "network %d created but cannot be read back", id) + } + return c.JSON(http.StatusOK, map[string]any{"data": []any{row}, "info": fmt.Sprintf("network %d created", id)}) +} From 0805fdbda5cc0b814d4cc74622fc16e8b1dbe3c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Thu, 24 Sep 2026 14:38:17 +0200 Subject: [PATCH 21/61] Add POST /users Create a user with its private group, with the UserManager privilege. An email or username already in use is refused with a 409. The password is hashed in the web2py format the sign-in already verifies; without one, the account exists but cannot sign in. --- cdb/db_users_create.go | 77 ++++++ server/api.yaml | 51 ++++ server/codegen_server_gen.go | 507 ++++++++++++++++++---------------- server/codegen_type_gen.go | 15 + server/handlers/post_users.go | 152 ++++++++++ xauth/w2p.go | 27 ++ 6 files changed, 586 insertions(+), 243 deletions(-) create mode 100644 cdb/db_users_create.go create mode 100644 server/handlers/post_users.go diff --git a/cdb/db_users_create.go b/cdb/db_users_create.go new file mode 100644 index 00000000..2d418891 --- /dev/null +++ b/cdb/db_users_create.go @@ -0,0 +1,77 @@ +package cdb + +import ( + "context" + "database/sql" + "errors" + "fmt" +) + +// UserInsert holds the columns set when creating a user. PasswordHash is already in +// the web2py format; empty, the account cannot sign in until a password is set. +type UserInsert struct { + Email string + Username *string + FirstName *string + LastName *string + PhoneWork *string + PasswordHash *string +} + +func (oDb *DB) userIDBy(ctx context.Context, column, value string) (int64, bool, error) { + var id int64 + err := oDb.DB.QueryRowContext(ctx, "SELECT id FROM auth_user WHERE "+column+" = ? LIMIT 1", value).Scan(&id) + if errors.Is(err, sql.ErrNoRows) { + return 0, false, nil + } + if err != nil { + return 0, false, fmt.Errorf("user by %s: %w", column, err) + } + return id, true, nil +} + +// UserIDByEmail returns the id of the user with this email, if any. +func (oDb *DB) UserIDByEmail(ctx context.Context, email string) (int64, bool, error) { + return oDb.userIDBy(ctx, "email", email) +} + +// UserIDByUsername returns the id of the user with this username, if any. +func (oDb *DB) UserIDByUsername(ctx context.Context, username string) (int64, bool, error) { + return oDb.userIDBy(ctx, "username", username) +} + +// InsertUserWithPrivateGroup creates a user, then its private group "user_" and +// the membership, as web2py does on registration (auth.settings.create_user_groups). +// Meant to run in a transaction. +func (oDb *DB) InsertUserWithPrivateGroup(ctx context.Context, u UserInsert) (int64, error) { + res, err := oDb.ExecContext(ctx, + `INSERT INTO auth_user (email, username, first_name, last_name, phone_work, password) + VALUES (?, ?, ?, ?, ?, ?)`, + u.Email, u.Username, u.FirstName, u.LastName, u.PhoneWork, u.PasswordHash) + if err != nil { + return 0, fmt.Errorf("InsertUserWithPrivateGroup user: %w", err) + } + userID, err := res.LastInsertId() + if err != nil { + return 0, fmt.Errorf("InsertUserWithPrivateGroup user id: %w", err) + } + res, err = oDb.ExecContext(ctx, + "INSERT INTO auth_group (role, description, privilege) VALUES (?, ?, 'F')", + fmt.Sprintf("user_%d", userID), fmt.Sprintf("group uniquely assigned to user %d", userID)) + if err != nil { + return 0, fmt.Errorf("InsertUserWithPrivateGroup group: %w", err) + } + groupID, err := res.LastInsertId() + if err != nil { + return 0, fmt.Errorf("InsertUserWithPrivateGroup group id: %w", err) + } + if _, err := oDb.ExecContext(ctx, + "INSERT INTO auth_membership (user_id, group_id, primary_group) VALUES (?, ?, 'F')", + userID, groupID); err != nil { + return 0, fmt.Errorf("InsertUserWithPrivateGroup membership: %w", err) + } + oDb.SetChange("auth_user") + oDb.SetChange("auth_group") + oDb.SetChange("auth_membership") + return userID, nil +} diff --git a/server/api.yaml b/server/api.yaml index 1703b0ee..b63c7acb 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -7260,6 +7260,57 @@ paths: - basicAuth: [ ] - bearerAuth: [ ] + post: + operationId: PostUsers + description: | + Create a user, with its private group "user_". Requires the UserManager + privilege. An email or username already in use is refused with a 409. Without + a password the account exists but cannot sign in. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - email + properties: + email: + type: string + username: + type: string + first_name: + type: string + last_name: + type: string + phone_work: + type: string + password: + type: string + description: At least 8 characters. Stored as a web2py hash. + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/UserListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 409: + $ref: '#/components/responses/409' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + /users/{user_id}: get: operationId: GetUser diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index 6960d436..e798a701 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -570,6 +570,9 @@ type ServerInterface interface { // (GET /users) GetUsers(ctx echo.Context, params GetUsersParams) error + // (POST /users) + PostUsers(ctx echo.Context) error + // (GET /users/{user_id}) GetUser(ctx echo.Context, userId string, params GetUserParams) error @@ -8648,6 +8651,19 @@ func (w *ServerInterfaceWrapper) GetUsers(ctx echo.Context) error { return err } +// PostUsers converts echo context to params. +func (w *ServerInterfaceWrapper) PostUsers(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostUsers(ctx) + return err +} + // GetUser converts echo context to params. func (w *ServerInterfaceWrapper) GetUser(ctx echo.Context) error { var err error @@ -8998,6 +9014,7 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.DELETE(options.BaseURL+"/tags/:tag_id/services/:svc_id", wrapper.DeleteTagService, options.OperationMiddlewares["DeleteTagService"]...) router.POST(options.BaseURL+"/tags/:tag_id/services/:svc_id", wrapper.PostTagService, options.OperationMiddlewares["PostTagService"]...) router.GET(options.BaseURL+"/users", wrapper.GetUsers, options.OperationMiddlewares["GetUsers"]...) + router.POST(options.BaseURL+"/users", wrapper.PostUsers, options.OperationMiddlewares["PostUsers"]...) router.GET(options.BaseURL+"/users/:user_id", wrapper.GetUser, options.OperationMiddlewares["GetUser"]...) router.GET(options.BaseURL+"/users/:user_id/prefs", wrapper.GetUserPrefs, options.OperationMiddlewares["GetUserPrefs"]...) router.POST(options.BaseURL+"/users/:user_id/prefs", wrapper.PostUserPrefs, options.OperationMiddlewares["PostUserPrefs"]...) @@ -9010,249 +9027,253 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "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", + "5fNKxpU8G5wPRmeDrx+//v8BAAD//w==", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index 9b2b9605..121e3c01 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -4040,6 +4040,18 @@ type GetUsersParams struct { Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` } +// PostUsersJSONBody defines parameters for PostUsers. +type PostUsersJSONBody struct { + Email string `json:"email"` + FirstName *string `json:"first_name,omitempty"` + LastName *string `json:"last_name,omitempty"` + + // Password At least 8 characters. Stored as a web2py hash. + Password *string `json:"password,omitempty"` + PhoneWork *string `json:"phone_work,omitempty"` + Username *string `json:"username,omitempty"` +} + // GetUserParams defines parameters for GetUser. type GetUserParams struct { // Props A list of properties to include in each data dictionnary. @@ -4242,6 +4254,9 @@ type PostTagNodeJSONRequestBody PostTagNodeJSONBody // PostTagServiceJSONRequestBody defines body for PostTagService for application/json ContentType. type PostTagServiceJSONRequestBody PostTagServiceJSONBody +// PostUsersJSONRequestBody defines body for PostUsers for application/json ContentType. +type PostUsersJSONRequestBody PostUsersJSONBody + // PostUserPrefsJSONRequestBody defines body for PostUserPrefs for application/json ContentType. type PostUserPrefsJSONRequestBody PostUserPrefsJSONBody diff --git a/server/handlers/post_users.go b/server/handlers/post_users.go new file mode 100644 index 00000000..0067b11f --- /dev/null +++ b/server/handlers/post_users.go @@ -0,0 +1,152 @@ +package serverhandlers + +import ( + "context" + "database/sql" + "fmt" + "net/http" + "net/mail" + "strconv" + "strings" + + "github.com/labstack/echo/v4" + "github.com/spf13/viper" + + "github.com/opensvc/oc3/cdb" + "github.com/opensvc/oc3/server" + "github.com/opensvc/oc3/util/echolog" + "github.com/opensvc/oc3/util/logkey" + "github.com/opensvc/oc3/xauth" +) + +// minPasswordLength is the shortest password accepted at user creation. +const minPasswordLength = 8 + +// userCreatedProps are the properties returned for a created user: never the +// password, the reset key nor the registration id. +var userCreatedProps = server.InQueryProps("id,email,username,first_name,last_name,phone_work") + +func IsUserManager(c echo.Context) bool { + return IsManager(c) || HasGroup(c, "UserManager") +} + +func requireUserManager(c echo.Context) error { + if !IsAuthByUser(c) { + return denyRequest(c, http.StatusUnauthorized, "user authentication required") + } + if !IsUserManager(c) { + return denyRequest(c, http.StatusForbidden, "UserManager privilege required") + } + return nil +} + +func optionalString(value *string) *string { + if value == nil { + return nil + } + s := strings.TrimSpace(*value) + if s == "" { + return nil + } + return &s +} + +// PostUsers handles POST /users: create a user, as the historical collector's +// rest_post_users did, except that an existing email or username is refused +// instead of silently updated. +func (a *Api) PostUsers(c echo.Context) error { + log := echolog.GetLogHandler(c, "PostUsers") + odb := a.ODB + ctx, cancel := context.WithTimeout(c.Request().Context(), a.SyncTimeout) + defer cancel() + + if err := requireUserManager(c); err != nil { + return err + } + + var body server.PostUsersJSONRequestBody + if err := c.Bind(&body); err != nil { + log.Error("invalid request body", logkey.Error, err) + return JSONProblem(c, http.StatusBadRequest, err.Error()) + } + + email := strings.TrimSpace(body.Email) + if addr, err := mail.ParseAddress(email); err != nil || addr.Address != email { + return JSONProblemf(c, http.StatusBadRequest, "email must be a valid address, got %q", body.Email) + } + insert := cdb.UserInsert{ + Email: email, + Username: optionalString(body.Username), + FirstName: optionalString(body.FirstName), + LastName: optionalString(body.LastName), + PhoneWork: optionalString(body.PhoneWork), + } + + if otherID, taken, err := odb.UserIDByEmail(ctx, email); err != nil { + log.Error("cannot check email", logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot check email") + } else if taken { + return JSONProblemf(c, http.StatusConflict, "a user with email %s already exists: %d", email, otherID) + } + if insert.Username != nil { + if otherID, taken, err := odb.UserIDByUsername(ctx, *insert.Username); err != nil { + log.Error("cannot check username", logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot check username") + } else if taken { + return JSONProblemf(c, http.StatusConflict, "a user named %s already exists: %d", *insert.Username, otherID) + } + } + + // Without a password the account exists but cannot sign in, as in the + // historical collector. + if body.Password != nil && *body.Password != "" { + if len(*body.Password) < minPasswordLength { + return JSONProblemf(c, http.StatusBadRequest, "password must be at least %d characters long", minPasswordLength) + } + hash, err := xauth.HashWeb2pyPassword(*body.Password, viper.GetString("w2p_hmac")) + if err != nil { + log.Error("cannot hash password", logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot hash password") + } + insert.PasswordHash = &hash + } + + log.Info("called", "email", email) + + var userID int64 + if err := func() error { + tx, markSuccess, endTx, err := odb.BeginTxWithControl(ctx, log, &sql.TxOptions{}) + if err != nil { + return fmt.Errorf("cannot start transaction: %w", err) + } + defer endTx() + if userID, err = tx.InsertUserWithPrivateGroup(ctx, insert); err != nil { + return err + } + userEmail, _ := c.Get(XUserEmail).(string) + if logErr := tx.Log(ctx, cdb.LogEntry{ + Action: "user.create", + User: userEmail, + Fmt: "add user %(email)s", + Dict: map[string]any{"email": email}, + Level: "info", + }); logErr != nil { + log.Error("cannot write audit log", logkey.Error, logErr) + } + markSuccess() + return nil + }(); err != nil { + log.Error("cannot create user", "email", email, logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot create user") + } + + if err := odb.Session.NotifyChanges(ctx); err != nil { + log.Error("cannot notify changes", logkey.Error, err) + } + + id := strconv.FormatInt(userID, 10) + return a.handleItem(c, "PostUsers", "user", "user_id", id, listEndpointParams{props: &userCreatedProps, withUserID: true}, + func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return odb.GetUser(ctx, id, p) + }) +} diff --git a/xauth/w2p.go b/xauth/w2p.go index a770b6a4..eaf0659d 100644 --- a/xauth/w2p.go +++ b/xauth/w2p.go @@ -4,6 +4,7 @@ import ( "context" "crypto/hmac" "crypto/md5" + "crypto/rand" "crypto/sha1" "crypto/sha256" "crypto/sha512" @@ -214,3 +215,29 @@ func verifyWeb2pyPassword(password, storedHash, hmacKey string) bool { computedHash := prefix + hex.EncodeToString(digestBytes) return hmac.Equal([]byte(computedHash), []byte(storedHash)) } + +// HashWeb2pyPassword returns a password hash in the web2py format that +// verifyWeb2pyPassword accepts: "sha512$$", the digest being an +// HMAC-SHA512 keyed with hmacKey and the salt when a key is configured, as web2py's +// CRYPT does, and a salted SHA-512 otherwise. +func HashWeb2pyPassword(password, hmacKey string) (string, error) { + saltBytes := make([]byte, 8) + if _, err := rand.Read(saltBytes); err != nil { + return "", fmt.Errorf("HashWeb2pyPassword: %w", err) + } + salt := hex.EncodeToString(saltBytes) + var digest []byte + if hmacKey != "" { + alg, keyPart := "sha512", hmacKey + if a, k, ok := strings.Cut(hmacKey, ":"); ok { + alg, keyPart = a, k + } + if alg != "sha512" { + return "", fmt.Errorf("HashWeb2pyPassword: unsupported hmac algorithm %q", alg) + } + digest = toHMACSHA512([]byte(keyPart+salt), []byte(password)) + } else { + digest = toSHA512([]byte(password + salt)) + } + return "sha512$" + salt + "$" + hex.EncodeToString(digest), nil +} From d5a8a4cc11e0cc42bbb3b65b04911456ea2e232f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Thu, 24 Sep 2026 14:38:20 +0200 Subject: [PATCH 22/61] Expose the node and service names on the action queue A queued action names its node, and its service when it has one, by id only. GET /actions LEFT JOINs nodes and services so that their names can be selected, and the access check qualifies node_id, now ambiguous. --- cdb/db_action_queue.go | 10 ++++++++-- schema/relations.go | 3 +++ server/handlers/props_mapping.go | 6 ++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/cdb/db_action_queue.go b/cdb/db_action_queue.go index 0a1f1ef4..50f60c40 100644 --- a/cdb/db_action_queue.go +++ b/cdb/db_action_queue.go @@ -70,13 +70,19 @@ func (oDb *DB) UpdateActionStatus(ctx context.Context, id int64, status string, return nil } +// actionQueueJoins makes the "nodes." and "services." props selectable: a queued +// action carries only the ids, and a node action names no service (empty svc_id), +// hence the LEFT JOINs. Same approach as logJoins. +const actionQueueJoins = " LEFT JOIN nodes ON nodes.node_id = action_queue.node_id" + + " LEFT JOIN services ON services.svc_id = action_queue.svc_id" + func buildActionsQuery(p ListParams, idCond string, idArgs []any) (string, []any, error) { if len(p.SelectExprs) == 0 { return "", nil, fmt.Errorf("buildActionsQuery: no columns selected") } sb := &strings.Builder{} - fmt.Fprintf(sb, "SELECT %s\nFROM action_queue", strings.Join(p.SelectExprs, ", ")) + fmt.Fprintf(sb, "SELECT %s\nFROM action_queue%s", strings.Join(p.SelectExprs, ", "), actionQueueJoins) var conds []string var args []any @@ -92,7 +98,7 @@ func buildActionsQuery(p ListParams, idCond string, idArgs []any) (string, []any conds = append(conds, "1=0") } else { conds = append(conds, - "node_id IN ("+ + "action_queue.node_id IN ("+ "SELECT n.node_id FROM nodes n"+ " JOIN apps a ON n.app = a.app"+ " JOIN apps_responsibles ar ON ar.app_id = a.id"+ diff --git a/schema/relations.go b/schema/relations.go index 0d5001d0..b4da7d7d 100644 --- a/schema/relations.go +++ b/schema/relations.go @@ -16,6 +16,9 @@ func init() { NodesClusterID.Ref = ClustersClusterID + ActionQueueNodeID.Ref = NodesNodeID + ActionQueueSvcID.Ref = ServicesSvcID + SvcmonSvcID.Ref = ServicesSvcID SvcmonNodeID.Ref = NodesNodeID SvcmonLogSvcID.Ref = ServicesSvcID diff --git a/server/handlers/props_mapping.go b/server/handlers/props_mapping.go index 067d52ba..aa8782f3 100644 --- a/server/handlers/props_mapping.go +++ b/server/handlers/props_mapping.go @@ -75,6 +75,12 @@ var propsMapping = map[string]propMapping{ "node_id": colStr(schema.ActionQueueNodeID), "svc_id": colStr(schema.ActionQueueSvcID), }, + // A queued action points at its node, and at its service when it has one, by + // id only: the names live in the joined tables, as for dashboard entries. + Joins: map[string]JoinDef{ + "nodes": {MappingKey: "node"}, + "services": {MappingKey: "service"}, + }, }, "cluster": { Available: []string{"id", "cluster_id", "cluster_name"}, From 9b7e8915349695e78568a1949bac43e0112da68a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Thu, 24 Sep 2026 14:38:23 +0200 Subject: [PATCH 23/61] Add POST /nodes/{node_id}/actions Queue an agent action on a node, as the historical collector action menu did: inventory pushes, checks, sysreport, scanscsi, freeze and thaw. The command is queued bare for a pull or feed node and wrapped in an ssh call for a push node, reaching the node by its connect_to or best routable address. Requires the NodeExec privilege and responsibility for the node. --- cdb/db_action_queue.go | 64 ++++ server/api.yaml | 66 ++++ server/codegen_server_gen.go | 522 +++++++++++++++------------- server/codegen_type_gen.go | 54 +++ server/handlers/post_node_action.go | 159 +++++++++ 5 files changed, 618 insertions(+), 247 deletions(-) create mode 100644 server/handlers/post_node_action.go diff --git a/cdb/db_action_queue.go b/cdb/db_action_queue.go index 50f60c40..4d058625 100644 --- a/cdb/db_action_queue.go +++ b/cdb/db_action_queue.go @@ -153,3 +153,67 @@ func (oDb *DB) GetActionOne(ctx context.Context, id string, p ListParams) ([]map return scanRowsToMaps(rows, p.Props, p.TypeHints) } + +// NodeActionTarget is what building an agent action command needs from a node. +type NodeActionTarget struct { + NodeID string + Nodename string + OSName string + ActionType string + Collector string + ConnectTo string +} + +// NodeActionTargetByID returns the node fields the action queue entry is built from. +func (oDb *DB) NodeActionTargetByID(ctx context.Context, nodeID string) (*NodeActionTarget, error) { + const query = "SELECT node_id, COALESCE(nodename, ''), COALESCE(os_name, ''), COALESCE(action_type, '')," + + " COALESCE(collector, ''), COALESCE(connect_to, '') FROM nodes WHERE node_id = ?" + var t NodeActionTarget + err := oDb.DB.QueryRowContext(ctx, query, nodeID). + Scan(&t.NodeID, &t.Nodename, &t.OSName, &t.ActionType, &t.Collector, &t.ConnectTo) + switch { + case errors.Is(err, sql.ErrNoRows): + return nil, nil + case err != nil: + return nil, fmt.Errorf("nodeActionTargetByID: %w", err) + } + return &t, nil +} + +// NodeReachableAddress returns the address an action should connect to, mirroring +// get_reachable_name() of the python collector: the explicit connect_to, else the +// best routable address of the node, else its name. +func (oDb *DB) NodeReachableAddress(ctx context.Context, t *NodeActionTarget) (string, error) { + if t.ConnectTo != "" { + return t.ConnectTo, nil + } + const query = "SELECT addr FROM v_nodenetworks WHERE node_id = ?" + + " AND mask IS NOT NULL AND mask != '' AND flag_deprecated = 0" + + " AND net_gateway IS NOT NULL AND net_gateway != '' AND net_gateway != '0.0.0.0'" + + " ORDER BY prio DESC, type LIMIT 1" + var addr string + err := oDb.DB.QueryRowContext(ctx, query, t.NodeID).Scan(&addr) + switch { + case errors.Is(err, sql.ErrNoRows): + return t.Nodename, nil + case err != nil: + return "", fmt.Errorf("nodeReachableAddress: %w", err) + } + return addr, nil +} + +// EnqueueNodeAction posts a node action to the action queue and returns its id. +func (oDb *DB) EnqueueNodeAction(ctx context.Context, nodeID, actionType, command, connectTo string, userID *int64) (int64, error) { + const query = "INSERT INTO action_queue (node_id, svc_id, action_type, command, user_id, connect_to)" + + " VALUES (?, '', ?, ?, ?, ?)" + res, err := oDb.ExecContext(ctx, query, nodeID, actionType, command, userID, connectTo) + if err != nil { + return 0, fmt.Errorf("enqueueNodeAction: %w", err) + } + id, err := res.LastInsertId() + if err != nil { + return 0, fmt.Errorf("enqueueNodeAction lastInsertId: %w", err) + } + oDb.SetChange("action_queue") + return id, nil +} diff --git a/server/api.yaml b/server/api.yaml index b63c7acb..0202700a 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -4684,6 +4684,72 @@ paths: tags: - collector + /nodes/{node_id}/actions: + post: + operationId: PostNodeAction + description: | + Queue an agent action on a node, as the historical collector action menu + did. The command is built from the node action_type: queued bare for a + pull or feed node, wrapped in a ssh call to nodemgr for a push node. + Requires the NodeExec privilege and responsibility for the node. + parameters: + - $ref: '#/components/parameters/inPathNodeId' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - action + properties: + action: + type: string + description: Action to queue + enum: + - pushasset + - pushdisks + - pushpkg + - pushpatch + - pushstats + - checks + - sysreport + - scanscsi + - freeze + - thaw + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + id: + type: integer + format: int64 + description: Action queue entry id + command: + type: string + description: Command queued for the agent + info: + type: string + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + tags: + - collector + /nodes/{node_id}/am_i_responsible: get: operationId: GetNodeAmIResponsible diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index e798a701..7c6ada99 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -309,6 +309,9 @@ type ServerInterface interface { // (POST /nodes/{node_id}) PostNode(ctx echo.Context, nodeId string) error + // (POST /nodes/{node_id}/actions) + PostNodeAction(ctx echo.Context, nodeId InPathNodeId) error + // (GET /nodes/{node_id}/alerts) GetNodeAlerts(ctx echo.Context, nodeId string, params GetNodeAlertsParams) error @@ -4337,6 +4340,26 @@ func (w *ServerInterfaceWrapper) PostNode(ctx echo.Context) error { return err } +// PostNodeAction converts echo context to params. +func (w *ServerInterfaceWrapper) PostNodeAction(ctx echo.Context) error { + var err error + // ------------- Path parameter "node_id" ------------- + var nodeId InPathNodeId + + err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostNodeAction(ctx, nodeId) + return err +} + // GetNodeAlerts converts echo context to params. func (w *ServerInterfaceWrapper) GetNodeAlerts(ctx echo.Context) error { var err error @@ -8927,6 +8950,7 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.DELETE(options.BaseURL+"/nodes/:node_id", wrapper.DeleteNode, options.OperationMiddlewares["DeleteNode"]...) router.GET(options.BaseURL+"/nodes/:node_id", wrapper.GetNode, options.OperationMiddlewares["GetNode"]...) router.POST(options.BaseURL+"/nodes/:node_id", wrapper.PostNode, options.OperationMiddlewares["PostNode"]...) + router.POST(options.BaseURL+"/nodes/:node_id/actions", wrapper.PostNodeAction, options.OperationMiddlewares["PostNodeAction"]...) router.GET(options.BaseURL+"/nodes/:node_id/alerts", wrapper.GetNodeAlerts, options.OperationMiddlewares["GetNodeAlerts"]...) router.GET(options.BaseURL+"/nodes/:node_id/am_i_responsible", wrapper.GetNodeAmIResponsible, options.OperationMiddlewares["GetNodeAmIResponsible"]...) router.GET(options.BaseURL+"/nodes/:node_id/candidate_tags", wrapper.GetNodeCandidateTags, options.OperationMiddlewares["GetNodeCandidateTags"]...) @@ -9027,253 +9051,257 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "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", - "5fNKxpU8G5wPRmeDrx+//v8BAAD//w==", + "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", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index 121e3c01..575677f0 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -266,6 +266,48 @@ func (e PostNodeJSONBodyActionType) Valid() bool { } } +// Defines values for PostNodeActionJSONBodyAction. +const ( + Checks PostNodeActionJSONBodyAction = "checks" + Freeze PostNodeActionJSONBodyAction = "freeze" + Pushasset PostNodeActionJSONBodyAction = "pushasset" + Pushdisks PostNodeActionJSONBodyAction = "pushdisks" + Pushpatch PostNodeActionJSONBodyAction = "pushpatch" + Pushpkg PostNodeActionJSONBodyAction = "pushpkg" + Pushstats PostNodeActionJSONBodyAction = "pushstats" + Scanscsi PostNodeActionJSONBodyAction = "scanscsi" + Sysreport PostNodeActionJSONBodyAction = "sysreport" + Thaw PostNodeActionJSONBodyAction = "thaw" +) + +// Valid indicates whether the value is a known member of the PostNodeActionJSONBodyAction enum. +func (e PostNodeActionJSONBodyAction) Valid() bool { + switch e { + case Checks: + return true + case Freeze: + return true + case Pushasset: + return true + case Pushdisks: + return true + case Pushpatch: + return true + case Pushpkg: + return true + case Pushstats: + return true + case Scanscsi: + return true + case Sysreport: + return true + case Thaw: + return true + default: + return false + } +} + // AlertListResponse defines model for AlertListResponse. type AlertListResponse struct { Data AlertListResponse_Data `json:"data"` @@ -2625,6 +2667,15 @@ type PostNodeJSONBody struct { // PostNodeJSONBodyActionType defines parameters for PostNode. type PostNodeJSONBodyActionType string +// PostNodeActionJSONBody defines parameters for PostNodeAction. +type PostNodeActionJSONBody struct { + // Action Action to queue + Action PostNodeActionJSONBodyAction `json:"action"` +} + +// PostNodeActionJSONBodyAction defines parameters for PostNodeAction. +type PostNodeActionJSONBodyAction string + // GetNodeAlertsParams defines parameters for GetNodeAlerts. type GetNodeAlertsParams struct { // Props A list of properties to include in each data dictionnary. @@ -4197,6 +4248,9 @@ type PostNodesJSONRequestBody PostNodesJSONBody // PostNodeJSONRequestBody defines body for PostNode for application/json ContentType. type PostNodeJSONRequestBody PostNodeJSONBody +// PostNodeActionJSONRequestBody defines body for PostNodeAction for application/json ContentType. +type PostNodeActionJSONRequestBody PostNodeActionJSONBody + // PostNodeComplianceModulesetJSONRequestBody defines body for PostNodeComplianceModuleset for application/json ContentType. type PostNodeComplianceModulesetJSONRequestBody = PostNodeComplianceModulesetJSONBody diff --git a/server/handlers/post_node_action.go b/server/handlers/post_node_action.go new file mode 100644 index 00000000..09e836ff --- /dev/null +++ b/server/handlers/post_node_action.go @@ -0,0 +1,159 @@ +package serverhandlers + +import ( + "context" + "net/http" + "strings" + + "github.com/google/uuid" + "github.com/labstack/echo/v4" + + "github.com/opensvc/oc3/cdb" + "github.com/opensvc/oc3/server" + "github.com/opensvc/oc3/util/echolog" + "github.com/opensvc/oc3/util/logkey" +) + +// nodeActions are the agent actions the API accepts, mirroring the node agent +// entries of the historical collector action menu. Actions that interrupt service +// (reboot, shutdown, drain, updatepkg...) are deliberately left out for now. +var nodeActions = map[string]bool{ + "pushasset": true, + "pushdisks": true, + "pushpkg": true, + "pushpatch": true, + "pushstats": true, + "checks": true, + "sysreport": true, + "scanscsi": true, + "freeze": true, + "thaw": true, +} + +// sshCmd is the ssh invocation the python collector uses to reach a push node +// (get_ssh_cmd, with the default of its ssh_cmd). +var sshCmd = []string{ + "ssh", + "-o", "StrictHostKeyChecking=no", + "-o", "CheckHostIP=no", + "-o", "ForwardX11=no", + "-o", "ConnectTimeout=5", + "-o", "PasswordAuthentication=no", +} + +// nodeActionCommand builds the queued command, as fmt_node_action() does: a pull or +// feed node reads the bare action from its queue, a push node is reached over ssh. +func nodeActionCommand(action, actionType, connectTo string) string { + var cmd []string + if actionType != "pull" && actionType != "feed" { + cmd = append(cmd, sshCmd...) + cmd = append(cmd, "opensvc@"+connectTo, "--", "sudo", "nodemgr") + } + cmd = append(cmd, action) + if action == "freeze" || action == "thaw" { + cmd = append(cmd, "--local") + } + return strings.Join(cmd, " ") +} + +// PostNodeAction handles POST /nodes/{node_id}/actions: queue an agent action. +func (a *Api) PostNodeAction(c echo.Context, nodeId server.InPathNodeId) error { + log := echolog.GetLogHandler(c, "PostNodeAction") + odb := a.ODB + ctx, cancel := context.WithTimeout(c.Request().Context(), a.SyncTimeout) + defer cancel() + + var body server.PostNodeActionJSONRequestBody + if err := c.Bind(&body); err != nil { + log.Error("invalid request body", logkey.Error, err) + return JSONProblem(c, http.StatusBadRequest, err.Error()) + } + action := string(body.Action) + if !nodeActions[action] { + return JSONProblemf(c, http.StatusBadRequest, "unsupported action %q", action) + } + + if !IsManager(c) && !HasGroup(c, "NodeExec") { + return JSONProblemf(c, http.StatusForbidden, "user has no NodeExec privilege") + } + + node, err := odb.NodeByNodeIDOrNodename(ctx, string(nodeId)) + if err != nil { + log.Error("cannot lookup node", logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot lookup node") + } + if node == nil { + return JSONProblemf(c, http.StatusNotFound, "node %s not found", nodeId) + } + + responsible, err := odb.NodeResponsible(ctx, node.NodeID, UserGroupsFromContext(c), IsManager(c)) + if err != nil { + log.Error("cannot check node responsibility", logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot check node responsibility") + } + if !responsible { + return JSONProblemf(c, http.StatusForbidden, "user is not responsible for node %s", nodeId) + } + + target, err := odb.NodeActionTargetByID(ctx, node.NodeID) + if err != nil { + log.Error("cannot read node action fields", logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot read node %s", nodeId) + } + if target == nil { + return JSONProblemf(c, http.StatusNotFound, "node %s not found", nodeId) + } + // A node feeding another collector queues its actions there; oc3 has no such + // push channel, so the caller is told rather than left with a dead entry. + if target.Collector != "" { + return JSONProblemf(c, http.StatusBadRequest, + "node %s is attached to collector %s: queue the action there", target.Nodename, target.Collector) + } + + connectTo, err := odb.NodeReachableAddress(ctx, target) + if err != nil { + log.Error("cannot find a reachable address", logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot find an address for node %s", nodeId) + } + + // An unset action_type means pull, as get_action_type() does. + actionType := target.ActionType + if actionType == "" { + actionType = "pull" + } + command := nodeActionCommand(action, actionType, connectTo) + + // Who asked, as the python collector records it: the queue keeps the caller. + id, err := odb.EnqueueNodeAction(ctx, node.NodeID, actionType, command, connectTo, authUserID(c)) + if err != nil { + log.Error("cannot queue the action", logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot queue action %s", action) + } + + log.Info("action queued", logkey.NodeID, node.NodeID, "action", action, "action_id", id) + + userEmail, _ := c.Get(XUserEmail).(string) + logEntry := cdb.LogEntry{ + Action: "node.action", + User: userEmail, + Fmt: "run %(action)s", + Dict: map[string]any{"action": action}, + Level: "info", + } + if parsed, parseErr := uuid.Parse(node.NodeID); parseErr == nil { + logEntry.NodeID = &parsed + } + if logErr := odb.Log(ctx, logEntry); logErr != nil { + log.Error("cannot write audit log", logkey.Error, logErr) + } + + if err := odb.Session.NotifyChanges(ctx); err != nil { + log.Error("cannot notify changes", logkey.Error, err) + } + + return c.JSON(http.StatusOK, map[string]any{ + "id": id, + "command": command, + "info": "action " + action + " queued on node " + target.Nodename, + }) +} From ed3ff17de3b556e8eb086e6c83ad67dea75275be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Thu, 24 Sep 2026 14:38:25 +0200 Subject: [PATCH 24/61] Add service and instance action endpoints POST /services/{svc_id}/actions queues an action for a node of the service seen alive in the last 15 minutes, acting on the whole service. POST /services/{svc_id}/instances/{node_id}/actions acts on that instance only, with --local for agents that understand it. Accepted actions are push resinfo, push config, freeze and thaw. Requires the NodeExec privilege and responsibility for the service. --- cdb/db_action_queue.go | 65 +++ server/api.yaml | 136 ++++++ server/codegen_server_gen.go | 566 ++++++++++++++----------- server/codegen_type_gen.go | 110 ++++- server/handlers/post_service_action.go | 245 +++++++++++ 5 files changed, 852 insertions(+), 270 deletions(-) create mode 100644 server/handlers/post_service_action.go diff --git a/cdb/db_action_queue.go b/cdb/db_action_queue.go index 4d058625..9474f4e9 100644 --- a/cdb/db_action_queue.go +++ b/cdb/db_action_queue.go @@ -217,3 +217,68 @@ func (oDb *DB) EnqueueNodeAction(ctx context.Context, nodeID, actionType, comman oDb.SetChange("action_queue") return id, nil } + +// ServiceLiveNode returns a node of the service seen alive in the last 15 minutes, +// as get_svc_live_nodes() does, plus the agent version an action command needs. +func (oDb *DB) ServiceLiveNode(ctx context.Context, svcID string) (*NodeActionTarget, string, error) { + const query = "SELECT nodes.node_id, COALESCE(nodes.nodename, ''), COALESCE(nodes.os_name, '')," + + " COALESCE(nodes.action_type, ''), COALESCE(nodes.collector, ''), COALESCE(nodes.connect_to, '')," + + " COALESCE(nodes.version, '')" + + " FROM svcmon JOIN nodes ON nodes.node_id = svcmon.node_id" + + " WHERE svcmon.svc_id = ? AND nodes.last_comm > NOW() - INTERVAL 15 MINUTE" + + " ORDER BY nodes.nodename LIMIT 1" + var t NodeActionTarget + var version string + err := oDb.DB.QueryRowContext(ctx, query, svcID). + Scan(&t.NodeID, &t.Nodename, &t.OSName, &t.ActionType, &t.Collector, &t.ConnectTo, &version) + switch { + case errors.Is(err, sql.ErrNoRows): + return nil, "", nil + case err != nil: + return nil, "", fmt.Errorf("serviceLiveNode: %w", err) + } + return &t, version, nil +} + +// NodeAgentVersion returns the agent version reported by a node, empty when unknown. +func (oDb *DB) NodeAgentVersion(ctx context.Context, nodeID string) (string, error) { + var version string + err := oDb.DB.QueryRowContext(ctx, "SELECT COALESCE(version, '') FROM nodes WHERE node_id = ?", nodeID).Scan(&version) + switch { + case errors.Is(err, sql.ErrNoRows): + return "", nil + case err != nil: + return "", fmt.Errorf("nodeAgentVersion: %w", err) + } + return version, nil +} + +// HasServiceInstance reports whether the service runs on that node. +func (oDb *DB) HasServiceInstance(ctx context.Context, svcID, nodeID string) (bool, error) { + var one int + err := oDb.DB.QueryRowContext(ctx, + "SELECT 1 FROM svcmon WHERE svc_id = ? AND node_id = ? LIMIT 1", svcID, nodeID).Scan(&one) + switch { + case errors.Is(err, sql.ErrNoRows): + return false, nil + case err != nil: + return false, fmt.Errorf("hasServiceInstance: %w", err) + } + return true, nil +} + +// EnqueueServiceAction posts a service action to the action queue and returns its id. +func (oDb *DB) EnqueueServiceAction(ctx context.Context, nodeID, svcID, actionType, command, connectTo string, userID *int64) (int64, error) { + const query = "INSERT INTO action_queue (node_id, svc_id, action_type, command, user_id, connect_to)" + + " VALUES (?, ?, ?, ?, ?, ?)" + res, err := oDb.ExecContext(ctx, query, nodeID, svcID, actionType, command, userID, connectTo) + if err != nil { + return 0, fmt.Errorf("enqueueServiceAction: %w", err) + } + id, err := res.LastInsertId() + if err != nil { + return 0, fmt.Errorf("enqueueServiceAction lastInsertId: %w", err) + } + oDb.SetChange("action_queue") + return id, nil +} diff --git a/server/api.yaml b/server/api.yaml index 0202700a..d3d4d297 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -5719,6 +5719,142 @@ paths: - basicAuth: [ ] - bearerAuth: [ ] + /services/{svc_id}/actions: + post: + operationId: PostServiceAction + description: | + Queue an agent action on a service, as the historical collector action menu + did: the action is posted for a node of the service seen alive in the last + 15 minutes, and asks the agent to act on the whole service rather than on + that one instance. Requires the NodeExec privilege and responsibility for + the service. + parameters: + - in: path + name: svc_id + required: true + description: Service identifier (svc_id UUID or svcname) + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - action + properties: + action: + type: string + description: Action to queue + enum: + - push resinfo + - push config + - freeze + - thaw + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + id: + type: integer + format: int64 + description: Action queue entry id + command: + type: string + description: Command queued for the agent + node_id: + type: string + description: Node the action was queued on + info: + type: string + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 409: + description: No node of the service has been seen alive recently + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + tags: + - collector + + /services/{svc_id}/instances/{node_id}/actions: + post: + operationId: PostServiceInstanceAction + description: | + Queue an agent action on one service instance, acting on that node only. + Requires the NodeExec privilege and responsibility for both the service and + the node. + parameters: + - in: path + name: svc_id + required: true + description: Service identifier (svc_id UUID or svcname) + schema: + type: string + - $ref: '#/components/parameters/inPathNodeId' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - action + properties: + action: + type: string + description: Action to queue + enum: + - push resinfo + - push config + - freeze + - thaw + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + id: + type: integer + format: int64 + description: Action queue entry id + command: + type: string + description: Command queued for the agent + info: + type: string + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + tags: + - collector + /services/{svc_id}/instances/{node_id}: delete: operationId: DeleteServiceInstance diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index 7c6ada99..12a14265 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -426,6 +426,9 @@ type ServerInterface interface { // (POST /services/{svc_id}) PostService(ctx echo.Context, svcId string) error + // (POST /services/{svc_id}/actions) + PostServiceAction(ctx echo.Context, svcId string) error + // (GET /services/{svc_id}/alerts) GetServiceAlerts(ctx echo.Context, svcId string, params GetServiceAlertsParams) error @@ -477,6 +480,9 @@ type ServerInterface interface { // (GET /services/{svc_id}/instances/{node_id}) GetServiceInstance(ctx echo.Context, svcId string, nodeId string, params GetServiceInstanceParams) error + // (POST /services/{svc_id}/instances/{node_id}/actions) + PostServiceInstanceAction(ctx echo.Context, svcId string, nodeId InPathNodeId) error + // (GET /services/{svc_id}/nodes) GetServiceNodes(ctx echo.Context, svcId string, params GetServiceNodesParams) error @@ -6171,6 +6177,26 @@ func (w *ServerInterfaceWrapper) PostService(ctx echo.Context) error { return err } +// PostServiceAction converts echo context to params. +func (w *ServerInterfaceWrapper) PostServiceAction(ctx echo.Context) error { + var err error + // ------------- Path parameter "svc_id" ------------- + var svcId string + + err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter svc_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostServiceAction(ctx, svcId) + return err +} + // GetServiceAlerts converts echo context to params. func (w *ServerInterfaceWrapper) GetServiceAlerts(ctx echo.Context) error { var err error @@ -7177,6 +7203,34 @@ func (w *ServerInterfaceWrapper) GetServiceInstance(ctx echo.Context) error { return err } +// PostServiceInstanceAction converts echo context to params. +func (w *ServerInterfaceWrapper) PostServiceInstanceAction(ctx echo.Context) error { + var err error + // ------------- Path parameter "svc_id" ------------- + var svcId string + + err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter svc_id: %s", err)) + } + + // ------------- Path parameter "node_id" ------------- + var nodeId InPathNodeId + + err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostServiceInstanceAction(ctx, svcId, nodeId) + return err +} + // GetServiceNodes converts echo context to params. func (w *ServerInterfaceWrapper) GetServiceNodes(ctx echo.Context) error { var err error @@ -8989,6 +9043,7 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.DELETE(options.BaseURL+"/services/:svc_id", wrapper.DeleteService, options.OperationMiddlewares["DeleteService"]...) router.GET(options.BaseURL+"/services/:svc_id", wrapper.GetService, options.OperationMiddlewares["GetService"]...) router.POST(options.BaseURL+"/services/:svc_id", wrapper.PostService, options.OperationMiddlewares["PostService"]...) + router.POST(options.BaseURL+"/services/:svc_id/actions", wrapper.PostServiceAction, options.OperationMiddlewares["PostServiceAction"]...) router.GET(options.BaseURL+"/services/:svc_id/alerts", wrapper.GetServiceAlerts, options.OperationMiddlewares["GetServiceAlerts"]...) router.GET(options.BaseURL+"/services/:svc_id/am_i_responsible", wrapper.GetServiceAmIResponsible, options.OperationMiddlewares["GetServiceAmIResponsible"]...) router.GET(options.BaseURL+"/services/:svc_id/candidate_tags", wrapper.GetServiceCandidateTags, options.OperationMiddlewares["GetServiceCandidateTags"]...) @@ -9006,6 +9061,7 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.GET(options.BaseURL+"/services/:svc_id/disks", wrapper.GetServiceDisks, options.OperationMiddlewares["GetServiceDisks"]...) router.DELETE(options.BaseURL+"/services/:svc_id/instances/:node_id", wrapper.DeleteServiceInstance, options.OperationMiddlewares["DeleteServiceInstance"]...) router.GET(options.BaseURL+"/services/:svc_id/instances/:node_id", wrapper.GetServiceInstance, options.OperationMiddlewares["GetServiceInstance"]...) + router.POST(options.BaseURL+"/services/:svc_id/instances/:node_id/actions", wrapper.PostServiceInstanceAction, options.OperationMiddlewares["PostServiceInstanceAction"]...) router.GET(options.BaseURL+"/services/:svc_id/nodes", wrapper.GetServiceNodes, options.OperationMiddlewares["GetServiceNodes"]...) router.GET(options.BaseURL+"/services/:svc_id/nodes/:node_id", wrapper.GetServiceNode, options.OperationMiddlewares["GetServiceNode"]...) router.GET(options.BaseURL+"/services/:svc_id/nodes/:node_id/resources", wrapper.GetServiceNodeResources, options.OperationMiddlewares["GetServiceNodeResources"]...) @@ -9051,257 +9107,265 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "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", + "g9HZ4MuHL/83AAD//w==", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index 575677f0..f3b70932 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -268,38 +268,86 @@ func (e PostNodeJSONBodyActionType) Valid() bool { // Defines values for PostNodeActionJSONBodyAction. const ( - Checks PostNodeActionJSONBodyAction = "checks" - Freeze PostNodeActionJSONBodyAction = "freeze" - Pushasset PostNodeActionJSONBodyAction = "pushasset" - Pushdisks PostNodeActionJSONBodyAction = "pushdisks" - Pushpatch PostNodeActionJSONBodyAction = "pushpatch" - Pushpkg PostNodeActionJSONBodyAction = "pushpkg" - Pushstats PostNodeActionJSONBodyAction = "pushstats" - Scanscsi PostNodeActionJSONBodyAction = "scanscsi" - Sysreport PostNodeActionJSONBodyAction = "sysreport" - Thaw PostNodeActionJSONBodyAction = "thaw" + PostNodeActionJSONBodyActionChecks PostNodeActionJSONBodyAction = "checks" + PostNodeActionJSONBodyActionFreeze PostNodeActionJSONBodyAction = "freeze" + PostNodeActionJSONBodyActionPushasset PostNodeActionJSONBodyAction = "pushasset" + PostNodeActionJSONBodyActionPushdisks PostNodeActionJSONBodyAction = "pushdisks" + PostNodeActionJSONBodyActionPushpatch PostNodeActionJSONBodyAction = "pushpatch" + PostNodeActionJSONBodyActionPushpkg PostNodeActionJSONBodyAction = "pushpkg" + PostNodeActionJSONBodyActionPushstats PostNodeActionJSONBodyAction = "pushstats" + PostNodeActionJSONBodyActionScanscsi PostNodeActionJSONBodyAction = "scanscsi" + PostNodeActionJSONBodyActionSysreport PostNodeActionJSONBodyAction = "sysreport" + PostNodeActionJSONBodyActionThaw PostNodeActionJSONBodyAction = "thaw" ) // Valid indicates whether the value is a known member of the PostNodeActionJSONBodyAction enum. func (e PostNodeActionJSONBodyAction) Valid() bool { switch e { - case Checks: + case PostNodeActionJSONBodyActionChecks: return true - case Freeze: + case PostNodeActionJSONBodyActionFreeze: + return true + case PostNodeActionJSONBodyActionPushasset: + return true + case PostNodeActionJSONBodyActionPushdisks: + return true + case PostNodeActionJSONBodyActionPushpatch: + return true + case PostNodeActionJSONBodyActionPushpkg: return true - case Pushasset: + case PostNodeActionJSONBodyActionPushstats: return true - case Pushdisks: + case PostNodeActionJSONBodyActionScanscsi: return true - case Pushpatch: + case PostNodeActionJSONBodyActionSysreport: return true - case Pushpkg: + case PostNodeActionJSONBodyActionThaw: return true - case Pushstats: + default: + return false + } +} + +// Defines values for PostServiceActionJSONBodyAction. +const ( + PostServiceActionJSONBodyActionFreeze PostServiceActionJSONBodyAction = "freeze" + PostServiceActionJSONBodyActionPushConfig PostServiceActionJSONBodyAction = "push config" + PostServiceActionJSONBodyActionPushResinfo PostServiceActionJSONBodyAction = "push resinfo" + PostServiceActionJSONBodyActionThaw PostServiceActionJSONBodyAction = "thaw" +) + +// Valid indicates whether the value is a known member of the PostServiceActionJSONBodyAction enum. +func (e PostServiceActionJSONBodyAction) Valid() bool { + switch e { + case PostServiceActionJSONBodyActionFreeze: + return true + case PostServiceActionJSONBodyActionPushConfig: + return true + case PostServiceActionJSONBodyActionPushResinfo: + return true + case PostServiceActionJSONBodyActionThaw: + return true + default: + return false + } +} + +// Defines values for PostServiceInstanceActionJSONBodyAction. +const ( + Freeze PostServiceInstanceActionJSONBodyAction = "freeze" + PushConfig PostServiceInstanceActionJSONBodyAction = "push config" + PushResinfo PostServiceInstanceActionJSONBodyAction = "push resinfo" + Thaw PostServiceInstanceActionJSONBodyAction = "thaw" +) + +// Valid indicates whether the value is a known member of the PostServiceInstanceActionJSONBodyAction enum. +func (e PostServiceInstanceActionJSONBodyAction) Valid() bool { + switch e { + case Freeze: return true - case Scanscsi: + case PushConfig: return true - case Sysreport: + case PushResinfo: return true case Thaw: return true @@ -3281,6 +3329,15 @@ type PostServiceJSONBody struct { Svcname *string `json:"svcname,omitempty"` } +// PostServiceActionJSONBody defines parameters for PostServiceAction. +type PostServiceActionJSONBody struct { + // Action Action to queue + Action PostServiceActionJSONBodyAction `json:"action"` +} + +// PostServiceActionJSONBodyAction defines parameters for PostServiceAction. +type PostServiceActionJSONBodyAction string + // GetServiceAlertsParams defines parameters for GetServiceAlerts. type GetServiceAlertsParams struct { // Props A list of properties to include in each data dictionnary. @@ -3578,6 +3635,15 @@ type GetServiceInstanceParams struct { Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` } +// PostServiceInstanceActionJSONBody defines parameters for PostServiceInstanceAction. +type PostServiceInstanceActionJSONBody struct { + // Action Action to queue + Action PostServiceInstanceActionJSONBodyAction `json:"action"` +} + +// PostServiceInstanceActionJSONBodyAction defines parameters for PostServiceInstanceAction. +type PostServiceInstanceActionJSONBodyAction string + // GetServiceNodesParams defines parameters for GetServiceNodes. type GetServiceNodesParams struct { // Props A list of properties to include in each data dictionnary. @@ -4278,6 +4344,12 @@ type PostServicesJSONRequestBody PostServicesJSONBody // PostServiceJSONRequestBody defines body for PostService for application/json ContentType. type PostServiceJSONRequestBody PostServiceJSONBody +// PostServiceActionJSONRequestBody defines body for PostServiceAction for application/json ContentType. +type PostServiceActionJSONRequestBody PostServiceActionJSONBody + +// PostServiceInstanceActionJSONRequestBody defines body for PostServiceInstanceAction for application/json ContentType. +type PostServiceInstanceActionJSONRequestBody PostServiceInstanceActionJSONBody + // DeleteServicesInstancesJSONRequestBody defines body for DeleteServicesInstances for application/json ContentType. type DeleteServicesInstancesJSONRequestBody DeleteServicesInstancesJSONBody diff --git a/server/handlers/post_service_action.go b/server/handlers/post_service_action.go new file mode 100644 index 00000000..9fd525a9 --- /dev/null +++ b/server/handlers/post_service_action.go @@ -0,0 +1,245 @@ +package serverhandlers + +import ( + "context" + "log/slog" + "net/http" + "strconv" + "strings" + + "github.com/google/uuid" + "github.com/labstack/echo/v4" + + "github.com/opensvc/oc3/cdb" + "github.com/opensvc/oc3/server" + "github.com/opensvc/oc3/util/echolog" + "github.com/opensvc/oc3/util/logkey" +) + +// serviceActions are the agent actions the API accepts on a service or on one of +// its instances. As for nodes, only what does not interrupt the service is exposed: +// start, stop, restart, switch, giveback, takeover, the sync and provisioning +// actions are deliberately left out for now. +var serviceActions = map[string]bool{ + "push resinfo": true, + "push config": true, + "freeze": true, + "thaw": true, +} + +// agentAtLeast19 reports whether the agent understands --local, as the python +// collector decides it from the leading digits of the reported version. +func agentAtLeast19(version string) bool { + if len(version) < 3 { + return false + } + v, err := strconv.ParseFloat(version[:3], 64) + if err != nil { + return false + } + return v >= 1.9 +} + +// serviceActionCommand builds the queued command, as fmt_svc_action() does. A pull +// or feed node reads the bare action from its queue; a push node is reached over +// ssh. `local` restricts the action to that one instance. +func serviceActionCommand(action, svcname, actionType, connectTo, agentVersion string, local bool) string { + var cmd []string + if actionType != "pull" && actionType != "feed" { + cmd = append(cmd, sshCmd...) + cmd = append(cmd, "opensvc@"+connectTo, "--", "sudo", "svcmgr", "--service", svcname) + } + cmd = append(cmd, action) + if local && agentAtLeast19(agentVersion) { + cmd = append(cmd, "--local") + } + return strings.Join(cmd, " ") +} + +// queueServiceAction is the part shared by the service and the instance endpoints. +func (a *Api) queueServiceAction( + c echo.Context, log *slog.Logger, ctx context.Context, + svc *cdb.DBService, target *cdb.NodeActionTarget, agentVersion, action string, local bool, +) error { + odb := a.ODB + + // A node feeding another collector queues its actions there; oc3 has no such + // push channel, so the caller is told rather than left with a dead entry. + if target.Collector != "" { + return JSONProblemf(c, http.StatusBadRequest, + "node %s is attached to collector %s: queue the action there", target.Nodename, target.Collector) + } + + connectTo, err := odb.NodeReachableAddress(ctx, target) + if err != nil { + log.Error("cannot find a reachable address", logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot find an address for node %s", target.Nodename) + } + + // An unset action_type means pull, as get_action_type() does. + actionType := target.ActionType + if actionType == "" { + actionType = "pull" + } + command := serviceActionCommand(action, svc.Svcname, actionType, connectTo, agentVersion, local) + + id, err := odb.EnqueueServiceAction(ctx, target.NodeID, svc.SvcID, actionType, command, connectTo, authUserID(c)) + if err != nil { + log.Error("cannot queue the action", logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot queue action %s", action) + } + + log.Info("action queued", "svc_id", svc.SvcID, logkey.NodeID, target.NodeID, "action", action, "action_id", id) + + userEmail, _ := c.Get(XUserEmail).(string) + logEntry := cdb.LogEntry{ + Action: "service.action", + User: userEmail, + Fmt: "run %(action)s", + Dict: map[string]any{"action": action}, + Level: "info", + } + if parsed, parseErr := uuid.Parse(svc.SvcID); parseErr == nil { + logEntry.SvcID = &parsed + } + if parsed, parseErr := uuid.Parse(target.NodeID); parseErr == nil { + logEntry.NodeID = &parsed + } + if logErr := odb.Log(ctx, logEntry); logErr != nil { + log.Error("cannot write audit log", logkey.Error, logErr) + } + + if err := odb.Session.NotifyChanges(ctx); err != nil { + log.Error("cannot notify changes", logkey.Error, err) + } + + return c.JSON(http.StatusOK, map[string]any{ + "id": id, + "command": command, + "node_id": target.NodeID, + "info": "action " + action + " queued on service " + svc.Svcname + " from node " + target.Nodename, + }) +} + +// checkServiceAction validates the body and the caller rights shared by both endpoints. +func (a *Api) checkServiceAction(c echo.Context, log *slog.Logger, ctx context.Context, svcId, action string) (*cdb.DBService, error) { + if !serviceActions[action] { + return nil, denyRequest(c, http.StatusBadRequest, "unsupported action %q", action) + } + if !IsManager(c) && !HasGroup(c, "NodeExec") { + return nil, denyRequest(c, http.StatusForbidden, "user has no NodeExec privilege") + } + + svc, err := a.resolveServiceRow(c, log, ctx, svcId) + if err != nil { + return nil, err + } + + responsible, err := a.ODB.ServiceResponsible(ctx, svc.SvcID, UserGroupsFromContext(c), IsManager(c)) + if err != nil { + log.Error("cannot check service responsibility", logkey.Error, err) + return nil, denyRequest(c, http.StatusInternalServerError, "cannot check service responsibility") + } + if !responsible { + return nil, denyRequest(c, http.StatusForbidden, "user is not responsible for service %s", svcId) + } + return svc, nil +} + +// PostServiceAction handles POST /services/{svc_id}/actions: queue an action on the +// whole service, from one of its live nodes. +func (a *Api) PostServiceAction(c echo.Context, svcId string) error { + log := echolog.GetLogHandler(c, "PostServiceAction") + ctx, cancel := context.WithTimeout(c.Request().Context(), a.SyncTimeout) + defer cancel() + + var body server.PostServiceActionJSONRequestBody + if err := c.Bind(&body); err != nil { + log.Error("invalid request body", logkey.Error, err) + return JSONProblem(c, http.StatusBadRequest, err.Error()) + } + action := string(body.Action) + + svc, err := a.checkServiceAction(c, log, ctx, svcId, action) + if err != nil { + return err + } + + target, agentVersion, err := a.ODB.ServiceLiveNode(ctx, svc.SvcID) + if err != nil { + log.Error("cannot look for a live node", logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot look for a live node of service %s", svcId) + } + if target == nil { + return JSONProblemf(c, http.StatusConflict, + "no node of service %s has been seen in the last 15 minutes", svc.Svcname) + } + + // The action is for the service as a whole: no --local, as do_svc_action does. + return a.queueServiceAction(c, log, ctx, svc, target, agentVersion, action, false) +} + +// PostServiceInstanceAction handles POST /services/{svc_id}/instances/{node_id}/actions: +// queue an action on one instance, acting on that node only. +func (a *Api) PostServiceInstanceAction(c echo.Context, svcId string, nodeId server.InPathNodeId) error { + log := echolog.GetLogHandler(c, "PostServiceInstanceAction") + odb := a.ODB + ctx, cancel := context.WithTimeout(c.Request().Context(), a.SyncTimeout) + defer cancel() + + var body server.PostServiceInstanceActionJSONRequestBody + if err := c.Bind(&body); err != nil { + log.Error("invalid request body", logkey.Error, err) + return JSONProblem(c, http.StatusBadRequest, err.Error()) + } + action := string(body.Action) + + svc, err := a.checkServiceAction(c, log, ctx, svcId, action) + if err != nil { + return err + } + + node, err := odb.NodeByNodeIDOrNodename(ctx, string(nodeId)) + if err != nil { + log.Error("cannot lookup node", logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot lookup node") + } + if node == nil { + return JSONProblemf(c, http.StatusNotFound, "node %s not found", nodeId) + } + + responsible, err := odb.NodeResponsible(ctx, node.NodeID, UserGroupsFromContext(c), IsManager(c)) + if err != nil { + log.Error("cannot check node responsibility", logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot check node responsibility") + } + if !responsible { + return JSONProblemf(c, http.StatusForbidden, "user is not responsible for node %s", nodeId) + } + + found, err := odb.HasServiceInstance(ctx, svc.SvcID, node.NodeID) + if err != nil { + log.Error("cannot check the instance", logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot check instance %s@%s", svcId, nodeId) + } + if !found { + return JSONProblemf(c, http.StatusNotFound, "service %s has no instance on node %s", svc.Svcname, node.NodeID) + } + + target, err := odb.NodeActionTargetByID(ctx, node.NodeID) + if err != nil { + log.Error("cannot read node action fields", logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot read node %s", nodeId) + } + if target == nil { + return JSONProblemf(c, http.StatusNotFound, "node %s not found", nodeId) + } + + agentVersion, err := odb.NodeAgentVersion(ctx, node.NodeID) + if err != nil { + log.Error("cannot read the agent version", logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot read node %s", nodeId) + } + + return a.queueServiceAction(c, log, ctx, svc, target, agentVersion, action, true) +} From 4d5b3d0fff7e01d2942a37fcb8678424c4ff1533 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Thu, 24 Sep 2026 14:38:28 +0200 Subject: [PATCH 25/61] Add column filters to the list endpoints GET /nodes, /services, /services_instances and /actions, and the filterset node and service lists, accept a repeated filter=prop:expr parameter, combined with AND: a substring by default, ~regex, in:a,b, eq/ne/gt/gte/ lt/lte comparisons, empty and !empty. Props resolve like orderby, joined names included, and the query builder adds the join of a filtered column even when it is not selected. An unknown prop or an invalid regular expression is refused with a 400. --- cdb/db_action_queue.go | 6 + cdb/db_apps.go | 4 +- cdb/db_nodes.go | 11 +- cdb/db_services.go | 11 +- cdb/db_services_instances.go | 13 +- cdb/db_tags.go | 4 +- cdb/list_params.go | 31 +- cdb/qb.go | 9 + server/api.yaml | 28 ++ server/codegen_server_gen.go | 566 ++++++++++++---------- server/codegen_type_gen.go | 81 ++++ server/handlers/get_actions.go | 1 + server/handlers/get_filterset_nodes.go | 1 + server/handlers/get_filterset_services.go | 1 + server/handlers/get_nodes.go | 1 + server/handlers/get_services.go | 1 + server/handlers/get_services_instances.go | 1 + server/handlers/handle_list.go | 8 + server/handlers/list_filters.go | 98 ++++ 19 files changed, 599 insertions(+), 277 deletions(-) create mode 100644 server/handlers/list_filters.go diff --git a/cdb/db_action_queue.go b/cdb/db_action_queue.go index 9474f4e9..0f605c4b 100644 --- a/cdb/db_action_queue.go +++ b/cdb/db_action_queue.go @@ -109,6 +109,12 @@ func buildActionsQuery(p ListParams, idCond string, idArgs []any) (string, []any } } + // Column filters of the request: the nodes and services joins are always in + // place here, so a filter on their names needs nothing more. + filterConds, filterArgs := p.FilterConditions() + conds = append(conds, filterConds...) + args = append(args, filterArgs...) + if len(conds) > 0 { sb.WriteString("\nWHERE " + strings.Join(conds, " AND ")) } diff --git a/cdb/db_apps.go b/cdb/db_apps.go index ce237a88..8010d39e 100644 --- a/cdb/db_apps.go +++ b/cdb/db_apps.go @@ -366,7 +366,7 @@ func (oDb *DB) GetAppNodes(ctx context.Context, appIDOrName string, p ListParams } } - query, args, err := buildNodesQuery(p.Groups, p.IsManager, p.SelectExprs) + query, args, err := buildNodesQuery(p.Groups, p.IsManager, p.SelectExprs, p.Filters) if err != nil { return nil, err } @@ -407,7 +407,7 @@ func (oDb *DB) GetAppServices(ctx context.Context, appIDOrName string, p ListPar } } - query, args, err := buildServicesQuery(p.Groups, p.IsManager, p.SelectExprs) + query, args, err := buildServicesQuery(p.Groups, p.IsManager, p.SelectExprs, p.Filters) if err != nil { return nil, err } diff --git a/cdb/db_nodes.go b/cdb/db_nodes.go index 3bdc737b..8598e9e3 100644 --- a/cdb/db_nodes.go +++ b/cdb/db_nodes.go @@ -50,7 +50,7 @@ func (n *DBNode) String() string { return fmt.Sprintf("node: {nodename: %s, node_id: %s, cluster_id: %s, app: %s}", n.Nodename, n.NodeID, n.ClusterID, n.App) } -func buildNodesQuery(groups []string, isManager bool, selectExprs []string) (string, []any, error) { +func buildNodesQuery(groups []string, isManager bool, selectExprs []string, filters []ColumnFilter) (string, []any, error) { q := From(schema.TNodes). // A node may name no cluster, or one the collector does not know: a plain join // would then drop the row. @@ -80,6 +80,9 @@ func buildNodesQuery(groups []string, isManager bool, selectExprs []string) (str q = q.Where(schema.NodesID, ">", 0) } + // Column filters of the request, ANDed with the access control above. + q = q.WhereFilters(filters) + query, args, err := q.Build() if err != nil { return "", nil, fmt.Errorf("buildNodesQuery: %w", err) @@ -88,7 +91,7 @@ func buildNodesQuery(groups []string, isManager bool, selectExprs []string) (str } func (oDb *DB) GetNodes(ctx context.Context, p ListParams) ([]map[string]any, error) { - query, args, err := buildNodesQuery(p.Groups, p.IsManager, p.SelectExprs) + query, args, err := buildNodesQuery(p.Groups, p.IsManager, p.SelectExprs, p.Filters) if err != nil { return nil, err } @@ -109,7 +112,7 @@ func (oDb *DB) GetNodes(ctx context.Context, p ListParams) ([]map[string]any, er // GetNodesByIDs fetches nodes whose node_id is in the given list. func (oDb *DB) GetNodesByIDs(ctx context.Context, ids []string, p ListParams) ([]map[string]any, error) { - query, args, err := buildNodesQuery(p.Groups, p.IsManager, p.SelectExprs) + query, args, err := buildNodesQuery(p.Groups, p.IsManager, p.SelectExprs, p.Filters) if err != nil { return nil, err } @@ -138,7 +141,7 @@ func (oDb *DB) GetNodesByIDs(ctx context.Context, ids []string, p ListParams) ([ // GetNode fetches a single node by node_id or nodename. func (oDb *DB) GetNode(ctx context.Context, nodeID string, p ListParams) ([]map[string]any, error) { - query, args, err := buildNodesQuery(p.Groups, p.IsManager, p.SelectExprs) + query, args, err := buildNodesQuery(p.Groups, p.IsManager, p.SelectExprs, p.Filters) if err != nil { return nil, err } diff --git a/cdb/db_services.go b/cdb/db_services.go index fb504cc2..7aba4a69 100644 --- a/cdb/db_services.go +++ b/cdb/db_services.go @@ -11,7 +11,7 @@ import ( "github.com/opensvc/oc3/schema" ) -func buildServicesQuery(groups []string, isManager bool, selectExprs []string) (string, []any, error) { +func buildServicesQuery(groups []string, isManager bool, selectExprs []string, filters []ColumnFilter) (string, []any, error) { q := From(schema.TServices). RawSelect(selectExprs...) @@ -38,6 +38,9 @@ func buildServicesQuery(groups []string, isManager bool, selectExprs []string) ( q = q.Where(schema.ServicesID, ">", 0) } + // Column filters of the request, ANDed with the access control above. + q = q.WhereFilters(filters) + query, args, err := q.Build() if err != nil { return "", nil, fmt.Errorf("buildServicesQuery: %w", err) @@ -46,7 +49,7 @@ func buildServicesQuery(groups []string, isManager bool, selectExprs []string) ( } func (oDb *DB) GetServices(ctx context.Context, p ListParams) ([]map[string]any, error) { - query, args, err := buildServicesQuery(p.Groups, p.IsManager, p.SelectExprs) + query, args, err := buildServicesQuery(p.Groups, p.IsManager, p.SelectExprs, p.Filters) if err != nil { return nil, err } @@ -67,7 +70,7 @@ func (oDb *DB) GetServices(ctx context.Context, p ListParams) ([]map[string]any, // GetServicesByIDs fetches services whose svc_id is in the given list. func (oDb *DB) GetServicesByIDs(ctx context.Context, ids []string, p ListParams) ([]map[string]any, error) { - query, args, err := buildServicesQuery(p.Groups, p.IsManager, p.SelectExprs) + query, args, err := buildServicesQuery(p.Groups, p.IsManager, p.SelectExprs, p.Filters) if err != nil { return nil, err } @@ -96,7 +99,7 @@ func (oDb *DB) GetServicesByIDs(ctx context.Context, ids []string, p ListParams) // GetService fetches a single service by svc_id (UUID) or svcname. func (oDb *DB) GetService(ctx context.Context, svcID string, p ListParams) ([]map[string]any, error) { - query, args, err := buildServicesQuery(p.Groups, p.IsManager, p.SelectExprs) + query, args, err := buildServicesQuery(p.Groups, p.IsManager, p.SelectExprs, p.Filters) if err != nil { return nil, err } diff --git a/cdb/db_services_instances.go b/cdb/db_services_instances.go index e52fa76d..3ebe466d 100644 --- a/cdb/db_services_instances.go +++ b/cdb/db_services_instances.go @@ -9,7 +9,7 @@ import ( "github.com/opensvc/oc3/schema" ) -func buildServicesInstancesQuery(groups []string, isManager bool, selectExprs []string) (string, []any, error) { +func buildServicesInstancesQuery(groups []string, isManager bool, selectExprs []string, filters []ColumnFilter) (string, []any, error) { // services is an inner join: the access check filters on services.svc_app. // nodes is a left join so that "nodes.*" props can be selected without dropping // an instance whose node row is missing. @@ -41,6 +41,9 @@ func buildServicesInstancesQuery(groups []string, isManager bool, selectExprs [] q = q.Where(schema.SvcmonID, ">", 0) } + // Column filters of the request, ANDed with the access control above. + q = q.WhereFilters(filters) + query, args, err := q.Build() if err != nil { return "", nil, fmt.Errorf("buildServicesInstancesQuery: %w", err) @@ -49,7 +52,7 @@ func buildServicesInstancesQuery(groups []string, isManager bool, selectExprs [] } func (oDb *DB) GetServicesInstances(ctx context.Context, p ListParams) ([]map[string]any, error) { - query, args, err := buildServicesInstancesQuery(p.Groups, p.IsManager, p.SelectExprs) + query, args, err := buildServicesInstancesQuery(p.Groups, p.IsManager, p.SelectExprs, p.Filters) if err != nil { return nil, err } @@ -70,7 +73,7 @@ func (oDb *DB) GetServicesInstances(ctx context.Context, p ListParams) ([]map[st // GetServiceNodeInstance fetches the service instance on a specific node. func (oDb *DB) GetServiceNodeInstance(ctx context.Context, svcID, nodeID string, p ListParams) ([]map[string]any, error) { - query, args, err := buildServicesInstancesQuery(p.Groups, p.IsManager, p.SelectExprs) + query, args, err := buildServicesInstancesQuery(p.Groups, p.IsManager, p.SelectExprs, p.Filters) if err != nil { return nil, err } @@ -89,7 +92,7 @@ func (oDb *DB) GetServiceNodeInstance(ctx context.Context, svcID, nodeID string, // GetNodeServices fetches all service instances on a specific node. func (oDb *DB) GetNodeServices(ctx context.Context, nodeID string, p ListParams) ([]map[string]any, error) { - query, args, err := buildServicesInstancesQuery(p.Groups, p.IsManager, p.SelectExprs) + query, args, err := buildServicesInstancesQuery(p.Groups, p.IsManager, p.SelectExprs, p.Filters) if err != nil { return nil, err } @@ -136,7 +139,7 @@ func (oDb *DB) DeleteServiceInstanceCascade(ctx context.Context, svcID, nodeID s // GetServicesInstance fetches all instances of a single service by svc_id (UUID) or svcname. func (oDb *DB) GetServicesInstance(ctx context.Context, svcID string, p ListParams) ([]map[string]any, error) { - query, args, err := buildServicesInstancesQuery(p.Groups, p.IsManager, p.SelectExprs) + query, args, err := buildServicesInstancesQuery(p.Groups, p.IsManager, p.SelectExprs, p.Filters) if err != nil { return nil, err } diff --git a/cdb/db_tags.go b/cdb/db_tags.go index 880fb0ec..af27d5b9 100644 --- a/cdb/db_tags.go +++ b/cdb/db_tags.go @@ -318,7 +318,7 @@ func (oDb *DB) DetachServiceTag(ctx context.Context, svcID, tagID string) (int64 // GetTagNodes returns nodes where a tag (by integer id) is attached, with app-based auth. func (oDb *DB) GetTagNodes(ctx context.Context, tagID int, p ListParams) ([]map[string]any, error) { - query, args, err := buildNodesQuery(p.Groups, p.IsManager, p.SelectExprs) + query, args, err := buildNodesQuery(p.Groups, p.IsManager, p.SelectExprs, p.Filters) if err != nil { return nil, err } @@ -486,7 +486,7 @@ func (oDb *DB) GetServiceCandidateTags(ctx context.Context, svcID string, p List // GetTagServices returns services where a tag (by integer id) is attached, with app-based auth. func (oDb *DB) GetTagServices(ctx context.Context, tagID int, p ListParams) ([]map[string]any, error) { - query, args, err := buildServicesQuery(p.Groups, p.IsManager, p.SelectExprs) + query, args, err := buildServicesQuery(p.Groups, p.IsManager, p.SelectExprs, p.Filters) if err != nil { return nil, err } diff --git a/cdb/list_params.go b/cdb/list_params.go index d37806d2..6c908f3a 100644 --- a/cdb/list_params.go +++ b/cdb/list_params.go @@ -1,6 +1,19 @@ package cdb -import "strings" +import ( + "strings" + + "github.com/opensvc/oc3/schema" +) + +// ColumnFilter is one column filter of a list request, already resolved to SQL. +// Col names the filtered column, so that the query builder joins its table when +// the column is not selected; Expr is the condition with "?" placeholders. +type ColumnFilter struct { + Col *schema.Col + Expr string + Args []any +} // ListParams bundles the standard query parameters shared by all list endpoints. // Groups and IsManager encode the caller's access control context. @@ -21,6 +34,9 @@ type ListParams struct { TypeHints map[string]string // Used by scanRowsToMaps to convert []byte driver values to the correct type OrderBy []string GroupBy []string + + // Filters are the column filters of the request, combined with AND. + Filters []ColumnFilter } // HasGroup reports whether the caller belongs to the named group. Use it for the @@ -50,3 +66,16 @@ func (p ListParams) GroupByClause(defaultClause string) string { } return "" } + +// FilterConditions returns the column filters as conditions to AND into a +// hand-built WHERE clause, and their arguments. Queries built with the query +// builder use Query.WhereFilters instead, which also resolves the joins. +func (p ListParams) FilterConditions() ([]string, []any) { + conds := make([]string, 0, len(p.Filters)) + var args []any + for _, f := range p.Filters { + conds = append(conds, f.Expr) + args = append(args, f.Args...) + } + return conds, args +} diff --git a/cdb/qb.go b/cdb/qb.go index 25ac2644..157a2fd6 100644 --- a/cdb/qb.go +++ b/cdb/qb.go @@ -143,6 +143,15 @@ func (q *Query) WhereRaw(expr string, args ...any) *Query { return q } +// WhereFilters adds the column filters of a list request. Each carries its column, +// so a filter on a joined table not otherwise selected still gets its join. +func (q *Query) WhereFilters(filters []ColumnFilter) *Query { + for _, f := range filters { + q.wheres = append(q.wheres, condition{col: f.Col, expr: f.Expr, args: f.Args}) + } + return q +} + // WhereIn adds a "col IN (?,...)" condition. Produces "1=0" for an empty slice. func (q *Query) WhereIn(col *schema.Col, vals []string) *Query { if len(vals) == 0 { diff --git a/server/api.yaml b/server/api.yaml index d3d4d297..20ceca0e 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -22,6 +22,7 @@ paths: - $ref: '#/components/parameters/inQueryMeta' - $ref: '#/components/parameters/inQueryStats' - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryFilter' - $ref: '#/components/parameters/inQueryGroupby' tags: - collector @@ -2042,6 +2043,7 @@ paths: - $ref: '#/components/parameters/inQueryMeta' - $ref: '#/components/parameters/inQueryStats' - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryFilter' - $ref: '#/components/parameters/inQueryGroupby' tags: - collector @@ -2077,6 +2079,7 @@ paths: - $ref: '#/components/parameters/inQueryMeta' - $ref: '#/components/parameters/inQueryStats' - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryFilter' - $ref: '#/components/parameters/inQueryGroupby' tags: - collector @@ -3671,6 +3674,7 @@ paths: - $ref: '#/components/parameters/inQueryMeta' - $ref: '#/components/parameters/inQueryStats' - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryFilter' - $ref: '#/components/parameters/inQueryGroupby' tags: - collector @@ -5179,6 +5183,7 @@ paths: - $ref: '#/components/parameters/inQueryMeta' - $ref: '#/components/parameters/inQueryStats' - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryFilter' - $ref: '#/components/parameters/inQueryGroupby' tags: - collector @@ -6558,6 +6563,7 @@ paths: - $ref: '#/components/parameters/inQueryMeta' - $ref: '#/components/parameters/inQueryStats' - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryFilter' - $ref: '#/components/parameters/inQueryGroupby' tags: - collector @@ -9054,6 +9060,28 @@ components: schema: type: string + inQueryFilter: + in: query + name: filter + required: false + description: | + Column filter, repeatable; several filters combine with AND. Each value is + `prop:expr`, `prop` being a property of the list (joined ones included, as + for orderby) and `expr` one of: + - text: case-insensitive match anywhere in the value; + - `~regex`: regular expression (RE2 syntax), case-insensitive; + - `in:a,b,c`: one of the listed values; + - `eq:v`, `ne:v`: equal, not equal; + - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + - `empty`, `!empty`: no value, any value. + An unknown property, a property without a column, or an invalid regular + expression is answered with 400. + explode: true + schema: + type: array + items: + type: string + inQueryProps: in: query name: props diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index 12a14265..c9d7dd99 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -652,6 +652,13 @@ func (w *ServerInterfaceWrapper) GetActions(ctx echo.Context) error { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + // ------------- Optional query parameter "groupby" ------------- err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) @@ -2724,6 +2731,13 @@ func (w *ServerInterfaceWrapper) GetFiltersetNodes(ctx echo.Context) error { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + // ------------- Optional query parameter "groupby" ------------- err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) @@ -2795,6 +2809,13 @@ func (w *ServerInterfaceWrapper) GetFiltersetServices(ctx echo.Context) error { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + // ------------- Optional query parameter "groupby" ------------- err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) @@ -4082,6 +4103,13 @@ func (w *ServerInterfaceWrapper) GetNodes(ctx echo.Context) error { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + // ------------- Optional query parameter "groupby" ------------- err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) @@ -6041,6 +6069,13 @@ func (w *ServerInterfaceWrapper) GetServices(ctx echo.Context) error { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + // ------------- Optional query parameter "groupby" ------------- err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) @@ -7888,6 +7923,13 @@ func (w *ServerInterfaceWrapper) GetServicesInstances(ctx echo.Context) error { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + // ------------- Optional query parameter "groupby" ------------- err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) @@ -9107,265 +9149,271 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "7L37jts41i/6KoTPOUiCcbvSlxl8XY0BTr500l3zdSeZSjKDwThQ0dKyxSmJVEjKjjsIsJ9mP9h+kg1e", - "dLFNynLFVWW7+E93yqQoklqX31pcXOvzIGZ5wShQKQbnnwcF5jgHCVz/RegbLNPfBciLRP2dgIg5KSRh", - "dHA+uPgZsSmSKaCcJWUGAuRgOCCqqcAyHQwHFOcwOB/kAmREksFwwOFjSTgkg3PJSxgORJxCjtXQclmo", - "rkJyQmeDL1+G9uWvWALdL6csAfd7VctN33u5ddG8a8n8hkv+ewl8+QtnZTFZbr78Octz/I0A9ZUkJCgj", - "QqrpFJwVwCUBgSRDM/W4mSKIMpNoskSPYTQbmZbJ8q+4KIZiHqu5PhlVC/ioXt2swPYd9JrxbyQncnO+", - "7xRt4E8kL3NEy3wCXM0WqOR2qhxkyekIPUU5YCoQZShTQ/kmpRtXppTAFJeZHJz/+elwkBOq3jU4fzqs", - "5kqohBnw9mR/B4kdH5bGWZkAykHiBEuMCK32sGBUwAi9oHiSQaK20751hN4LQFOcCUCMo6dqSSwn0jAF", - "SIymBLLEtxrVo9/+vp5OFaltTPrtNTFfekq4kPXOWgrVy4hLLhj3TYGZgZ072ntDX/ME+M3pVTCuaHSE", - "3nCYkk8IV+1LtCAyRd+gKeNIjQw0IXSGmHqfJWlm3v1XxetqTcNvcFF4idr27rfpbzgrxOainnmWQSwB", - "EYoAx6nZ/YTE6jGK+dI3p0K/pteM3koshWubqeQsE/qj62kIwmhDwIrHIGnPRc0eo/FAqAHHA3QNyyGK", - "GZWYULXD6jkBGcTqq7WWmRAhCY0lmuOsBIFiVlIpfCvTo3eu7IuSj4a/9Lp+ePpU/U/NBKimd1wUGYmx", - "mvjZf4Ra7ufWeP8vh+ngfPD/nDVa7My0irM3nE0yyM1bVjfsv3GCLuFjCUIOvgwHPzz99i7e+p7iUqaM", - "kz8gMa/9/i5e+5LxCUkSoOadP9zFO18xiV6yktp1/ngX73zO6DQjsf6if74bOrqgEjjFGXoLfA4cveCc", - "GcloH1ZjP8uAy9+IkJeW0jXOqnlKszM2GolReD0dnP/784BIyMW2memRL9lCrdhyFuYcLwdfhp8HOEmI", - "mibO3qy8y/f7univh2ST/4DZ1bUfPnwZGhW2ZZpq7VrnGnav4NC/zbI/OF5UL8whfBMs0gnDPEFY9UKc", - "LUboxRz4slEbRCBWmEWea1l2pYXsFdICakxrlGuFnECLlMQpillW5lRY8ac/qZGeYoSu9Ouu1NhqjaWE", - "ZEynnOXoSk0pmubyCmGa2D+VsL0aIYWArpRuEiPbqsYlsf67IYIxjVkOSA+H0W8vXr5Df3t98Uo/gTkg", - "WmYZWqRgJLpZuMR8BtJMlskUOLomNBlTNkVmJ0djOhiuUZp+dHNbfy1zTBEHnCiIg3IQAs9giDjQBDgk", - "ZmbVOvW06lUq6b8m14cD3RpzUGrfIfhtB/V4d2uUJ3/29wA69zdO846xCRUS0xj8PTpfLGAOnMilm3F0", - "F/Ozb4CySLxbQxL3sJU543rGkFgFglQXRTLqY1Z2x8YjNSFaS6DfQ/PYPQWXvHhWFLcj94riJKWeWdam", - "zKOopb1QzBK4C4nnkh5F4aQ+XBRRwnJMqLdZAs4ji6c3WaK93h04ws9Frg/5MxHXt0KPauBTJMhqXS4t", - "TMQ1EgAUMYqw9sEMjbVWURKJwaovjpeISDSBjNGZNpWUJhvTa8oWdEdKRhuEPKb7pGS1rghnGYs9ol23", - "qyV5BLHukMC8s3nmb9NuF39z17AZzCHrmHbOkpX2tccrHeBu5bjr1RxmPt7V7YL8AR0zKwUkHc1zoAnj", - "Xr3XpRO9i/IqMt3kfWw3ifOSZBL4rcgcM/QpSp1mZQ65M9WN54hRQDGjZjVGBhkBYDwbMcuUcGAcSQVn", - "hlbbmacFSAO4J4TCV8sfM7Qar8N2mEYZnkBmTYBpFF+LMr/S0L4yJtBkqZ4dU7UxEyysNaD9eDAlVK/U", - "JcqmkXErOOnVvsrTpr2TnjY9YU8bKzwN0oBHZ1sX5J1G2qHUC4K6wYCf/QTIF58K5jJ7njUUob8MaFJo", - "fiMSAY1xIcoMSxDKHopLLsgcsuXQePm0ziOKoLRvEZLKCTtCz6j+9xKlLEsEAqKNNGzHR4o4U0BK1Gii", - "pWPaelnSTMP50WtK1uc0/SVGvRsXEvJN2bHGpK3XfNi+wS/Uajcl3DTK2MxPM3rf3ELIvN7YrZmVjjss", - "0fw5+PJhuEZV9dBOp/or+0XU13F/kWFji5svTASiTNbfVpnEW+h4faOrPWp2pMeGv6z3Z33Huzj7Rtxb", - "82d/fmyvTx+FVW9oRI+dTvOCHovWhLu5ZNPpptxgSHdTlQ6mAqQfGulWUXnlby66Nreqfm1Nqt17c+tQ", - "o37H6WKOlSV6lQXCUuI4hURZMrgRCuf2IE73aTZ+iIqsFEpFoIIJvRNj+vjKcvnVE6141JMZm5EYZ0g9", - "iBV0+Q8zhzFEqjepLgWHOWGlMFLHpRe0vIqm9vTZT5NtIXv3+KFbH9xEUdwJ8mht6+YUfL+rrxjdALPc", - "LiufNBNfqlE3FESnIO8rmbvf2yU2tITAFFUw0dgfxqXHplUnLQ2MN7/BXkimWI5pZXBoX6/uWLtw78cd", - "qLe0S3jsoDvXAkf0kT9GurmNu16azVkQAc5zBz3o7s71Tk58L/AMtrNiF0BfO5FtvmyDL82xu/pwVC9t", - "R36GqQu92BglZ8xAXmQE07gOZBKIg9qnuDZGSWvrzVGW7WqMFiIQoeiq/spXe5u2TDkIbTU5Jp5CfI2a", - "HkOEBRoP4vRaH7mM1D+q053zjC2+ScksHQ9W5rZBFX2NoNaOrsxyUyz0FVo61utWZL0e+RTlfL0wh6wt", - "BXAT5jZSMo/MSQYz0Ke248G78cDKlbrlmxnHVPOeiZrDNBnT8eBl1VPLa2JCZuh9Hbvc9HikXqXzKc6c", - "gMn1aX+d4Fsh0V8n+BQJ1C7LQZ4pExJNSoFwggtpwiGr0xOsBLCyRWtfIMIzoPIcXaUTHJFEU7F2NWlv", - "oLYRSAJUkikBjh5jisjb528v0MXfXyFN5i/JhAN6nmJKIUP//OebV0+GZjQ15yszmOSYCvXeezqKMYtz", - "kmg1068wrruPCHZz51/QKWvzwOrXfV1KHcRhgyfMp11wIkHjt2oLEGWIQ8y4Dgtd3QpCp6z3XIyKuxW+", - "rAY/ReZsr83BodXRZQ0hDBVLLPUXZbQ53dQHD+Dk3jGt2fcuuOomYUbKLoXEnI+In5qnGVXGxUbMkWpG", - "nC3U9HMiBKEzFzPnjEa4KNR+lW6opXvMMcm29IlTTGceEK/bTbQq8C3jJERcb+linSac/QE0wtLbz/TY", - "0tw5gNgyk1kJQjJ/ezrZMgDZtvVsDhxn2zZfpFgZA9199IQzNsFZBJ8KiGV3123DzWNvyJRuX9J4yxBd", - "dp9qn8dF6ZFHujmHvKvVa8maZu/s9xy3ZR5hIjqgSK+L2zFhLk7SfrnwhnldvEE4STgIgRKQJvq+FV9T", - "iWzjDKYgF4xfr4bWjMb09s+zXfE0SeLxAWV4FiVQcIjXeLOH75RQOXVzHI49v4trN5+BjCYw8wSo6VbO", - "cBJjIb09YpbnNprc2Q408bbNsIQFXnrbveC1y4OmG0F2LtpSibe94IT5X1344phUow7ps9c3iM/7fuMA", - "Ha843Q2z1+y5IZM0CFEiMCqqiz59HUTDgb744g1Z0ndkvlIc2etEyU1ml1XX8Tbfw+qbZI45MImzvu7R", - "Gwt8n+A9DeH+G5vdiir8jc1OURfaZTkMsSaEK2MzBPPdTamb3fPQd1atCU8EusrYTN/tGFMd6qODfq7+", - "v8fXsHwirhDj1R/JFSoyHEPKskSPp/+qXTk5lnFK6MzcnENsOqZ6aH1PZIgw+tvb16/sxQ01J4Iz8gck", - "yq7EyHD6yBhp2hNkbDwN0XQY2ZhCXsil7Sla8Slq47S/XnsetBnHeGXD/mR2rWU5jqnbdESN5VhfTxH1", - "/RSpXqcgpQsb+HSbWj6OvV5NvTtYgr/R3h7ZCmVVZ8gxySJh9ff2U3H9DJV82fsc3RKKd7ozibPrHWew", - "HtK7OmIpgD9Ui+OVwTX9ZG0vCWtHdEvZDtdcLznXGtwVTQ9xhjkkFaYfoSsNVq+G6Apoxe41Ql0LHFVM", - "OaZX9lnb2eLCKxdD+oFwNwjuAsA+8NsFfL2gtwPwroHdVbzqRbp+lLuGcNtKsQ+83Q2MvmIJ/Ip5ssD8", - "dhy37RecIlxYX5/riMU2o/qFfQ5ZHgmEhQCJilKk52N6lS6qMxIDE5rRpjgn2RI9njKO4BPOi0zhjpgY", - "MJBDfqUPWRZRgWVqz1isVX8XweauE5ZFFGdYuG2HdBFtO19UXTiZe5SNXamvzWvH3f55jaKWW2OzU2Uv", - "D1vV/v9W1h2hM2H0Juox7aTqDlQ+RIIhrF4/pjHmJscJzZY2v4VO5AAJEuXEEy5vYKafFr0XG5VM8F4z", - "1q1eZTUhTERz4MLHVpMMJxDFeEIoeBRuVgoJ3McNtlmMqn7VXPzx7OqzPRLIPjBs7phY32I1pDkX6hHH", - "rlCBNdQ8mIFSiGUkmbu5KKOYcR8rqOaEdLVOOXz0juy/8aZaZcoBJx1jd9w7AxpnTJQcultFxtxfdvox", - "8cjauefngrHM0zRPYp/0ZRMR6Tv/flPK9lpgTjvsLSxkNGGe1ehWhQ7drURIoMCj6hKOy9aJI68LWTVO", - "SpIl6m9fh3j1Nv5aIyurqynO9mnGmP/dHMfX/kbGcm/jH6TwuKnV2immMXi9xjmm5RTHsuQevZtDHk0w", - "vfadaKnmpYSOZkWd3vMwH+do9eyTiLqx45i01e47J72xw5gySab2krwb6jARYR6nvraY0dgzKSaia+DU", - "syUty9jV1oMHba9uHmQi4pABFt5mATOvgcaEPR/1tXZIu4ItgEcTDvga+Lfbu3zX0cXqu2+3d+kapeBM", - "+k6cV3pUU+roKcqiyJYRnbhZwRMnNxwIiKM/GPU1coLd5CIoY39AJEnmaS86YUPHIbg2WfXU/c3bLFrd", - "SW3JqrDucTAj/9gRsw8HXetcKExN5dIjIV1A+fVEsEzniYvhLUhJ6O044x3vOUVzwLNM18k1a3VFwvQ1", - "4F/JNEJnxlWsExcpchAmpUnrNFvZE2PKS2p6N3a8VkXo8ZUSkMYkHw/SxXjwBJkA3ddvkRWLa52YGA+e", - "7OtAvLJOTGTX+qHBeyqgXhhv5dzDAq045kdIT1EDkitE7HBNbkxjVplX6E20+ySQZD+t7YmaGRP2BrEN", - "hxJjOh7MCZfjgdqecWUjjAcmpotJk7MPkl089X002EqXzlAcd9dosvT27jhtVc1+5WupwdyMK3NF7eli", - "oNRdi+BX+2/Rwe0eW1e50dO9SBeTV1nnNkSWhE/Om+xpmWP6TZ3CCz4VGbbXi0QBsYJGhtcU/cdxybnm", - "VWMXjmlh3meootvJrWfgkhdvjdf/VkSuHfsUxWxraR0BqS3fS3W6cjTuly1+DJ/YEfM48nlmdFspmZDY", - "g1N0jy2BpqpP16mGaadTMtvS3CkKdLeOXHiqPeGUdRyGmi6FznW9pV10dfCCN9Xus+pU2zSDT1FclFFK", - "ZmlUX33yf7j6gYwtevfP8adofQ3OfoT26mdyJHZ08puqqjnF/kdTJqQ/gVBHbqEoB8mZZQlvp+4vud3W", - "Vb10BEInbReczYlC4B2UudVcUX26Wcw0b+URyQqWsdnS22GB5+D9InvK2fRe3FIaBTXwKaovta43HKbC", - "fzXmnb5CwbhOJg1T0NDD3NwUeG6O4t68fvsOnZUCuDj7rP4XkeTLmepugnL0oZeNCKKgtJNaPS94lQPV", - "Jvv9SdkEBnPbaBqTWn48oEzBnPr1dkbjwRCNB/reYGlS0lXQWf+mELNikUkGCkNn5BqcV/QsTbg/2Irn", - "fNcbohXd+G47WlCgd84igqsCC7FgvIoc4DAjQnItLqJrWJoAAr2LY1rZKib0acJYBph+oxZaQ4LHVyZ8", - "ZkXsXA3H9Irk6z+iq4zF15G5NHv1BCnAsLQfyH6/R/Yy5pm+aKk+LJ0DVc8P62wYCWR4qf/6WDKJ66ms", - "W1eVXXVPcc96X9xnAHrHuoN4HLvat1+kN8h9tkC42DnVwXBA8i2zXf/WvTp1zJPkHYfDuY5u8i5Cnzj4", - "WxsKdPv9UkYh8kaLaIrzIk/TmrD4GnhkOYt4dLXpy/isI6/jCnN6YAMHATKquFqxsFvT+bfMpSJa3rdV", - "qm412AiHwfng6ejp6NutxmH1qPNGvIC45EQu3yplY2ORsCDxs9LED2glpJ7RvzbvSqUs9IkpYA686m3+", - "esl4juXgfPC3f76rag3oIXTr+hhf2qFcROqFsQKomMetiFNckEFrewbfjp6OvtdGfQFUNZ4Pvh89HT1V", - "4gDLVC/kzKB3/e+ZK62Y0qwrmVH1kbp9ChVM21C2ZoM9r/5YQgkj9DumeKakuwAYU5xl1VM/2VQhRvZr", - "k0xAM2btTzJ+IlzoWiFLEy/a8gOjKeNGuJncQ4TRi2RwPvgF5DO7qOFKZSBPGramy9lKCQ2FcPr1N3Vk", - "+ve3dVH6P2CgTe/upuDGDvOx9UX6P1HV+vnyYa0Uxnd7LGGwgmcddQxe/0+raIJroHpmZ6pTm5U1MbSY", - "+N8f1NrbjPrvD2ptEs8U4bSiBT7oAxjh4JTfWUKmSvmv8IFNeqVRyiOSPELXoLV8jmmCJeNLmxLHaHPt", - "1DLmnx3lp8Zn8cgYJI9W0II2E3TUg64NQjjYUV6xBF58glihwucsL/S/69wK+q01M5GMyKVOHaHeY9+v", - "mNDFX2+YaDGYdaT8N0uWO314lwt3DSjqd6DWLiKdZK7jaGktggQWyLShx7rcgNrIer/qXXyyVTs4Myit", - "drL5Gb+KFxwvcBH8D30IXnVqasRs6/ttq7DLtr7ftwqybOv7w70w6JdhrdbOPpPki6GMDKTDxvtZ/94w", - "rVOjIavR2gyGFH9ZFacMtB35SssDOzoRKGOzGSRjqo+bkLlEjtqIVHWCnMj6CGSVJ80yDMdsar1+fOWo", - "B7djKbivVQY3TCvhZ5TbIf570DhOaPYzEYUyN02OxfrKi44brg9PtpP1mLaRGroBULsZPLs/Oh0GIHiC", - "QPDwdZI+PdZX27zmVsXTJuZA9xVIkhwQVzpBoMd1JamoalVo5skIPbOJTsbUev7MdToiRZP7hes/tQlH", - "ROUhrIIZYpxlwH9S0FSLgzFV3K6zi8u0zpyyyc1qqi/0qoK9Feyt22Md0RPIadZ5PCmza6WD8icGbJla", - "o6axvtaqlJ1Vn3OSKAQGH0usUVvMiQROMHpMkiGqi2MNkQ31HCJzYGbbqsxLQ/R//tf/fqLZ0Ew1UZyp", - "OS7HS6NETYNmRbawE15TthQgMXacZi9hVXRjwHWgQLNX+zLNehYe+5raYh1xs9Guh5Vf7sBQCzh1J5yq", - "XYjwSSeYmFlqb+mxWoEpLp0TLkucoUe624qrwwSdrQUMVXfee5X869BfwVd43Lprs1zp4TsMn+vgGgXK", - "zFl/rby8Xrf9SvYJFtBHbq/Vu2xOYm69muXXKJWbao/V0+3qDcH/d7+qpQGBu7j0NDP54JdVRFgIMrMJ", - "yoi0KGxMV2EY8qEwpx/PRI2P6Y39eLrc7Tb3iEayJGlp0hFJngRH3ol4sbc4/WpDp+X528RUXrxzn9QV", - "3G8ni60OnKPcOOz9Kvp6JFo8tXbo06UGxrTCQ0rIc1jJdGOdBWe186BGVjpHB5bVYdGCyNSOpAwYItAc", - "Z0SHgjZhZhUu0mXdM5wXbm1SY8Z71yWHA1ePEJEG4HlMB89F0ddPuVYdfdVl+cLU3ZRV2Ig9Q36Ei+LR", - "mG4EkdiDvQlLNgJKqnNnXBQ/VUGqYAq6mSxBFKWYJpmJTP35xW8v3r1Aeh1nn3FRRCT50gFV1XL3xeE2", - "dnFNNhWF3p6Bt3jCZn9TqcAZLnKU/sHj4rsfnv7Yp++PB+ejrHPrImzIehM7m9+Dp/CI0WxRHKef0KEy", - "3IjvFkSyK/VUlLAcezIyqmadksEmgd4EU53J29bccGoSd+GA20I2+hrUYQvpAxa8FTiqQcXNUJIfh2w1", - "ctrAQGdhaJCFw8wxs7xTt1l3caNWFaeD9pQdo/qvvWpF0TL+PQjg/gltVw/ah3sVjEfoEnpuPPcuK62D", - "PKz2PRBBdNTqP+j6U3CE1Lr+DOcRWU/i5ZTEl/rWKlKfGJHpSq4ObvyqKxHGJjPMVpBgBPez/OKyNYWj", - "xwt2PHv5OZyfbaHBOjmF3wNgLx4SmZo4+X509UoPfHSoIHgiQlj73pmsKCdZ+6p9h7fNBa6ap01pax8G", - "f9N+TeC8wHmB89qcd/ZZc892N4vEcYrwJt+ZQ+ud/C8tljwIjlx9paar1ZfqFLnOF1abd5xBU60PgRL9", - "hSEJZstXeAOeSS+bSLaLXz6wyAGyCJbHyyLH5fE/04mFtuWakYzjGaCEiGvLZOYxVOqbHtVt+p622d/N", - "KwNEDBAxQMSW8+wGxlnb9dZpnF22XxM4L3Be4Lw25+1qnG3w3Q2Ms4Pyez9k5Hm5mhso2Gf7tM82OWU3", - "+yxwyWFySTDR7kxRVVUaeiUE3f2o7G01fICFARY+VFgYrR+S7cc/331LY+3EbG/xQdHWSxhr7LtZbL1S", - "Vec9NJ5ZvdV7W8OGjVCoX/AhXP4ITnsHKPRengx8E/gmwMRGca07EPfou+jWXmsuxcCFgQuDS6OH9gp8", - "E/gmaK/BmS5a1vPk2fZ1OTCqlnABOKS5vQ0qLWV6VlXLdCuGS113CTjCthJPKVOg0m6FTxOUMn1l5PDt", - "3gtSU/KXcmqL6bqnSzrfiTQeDsqyTxJA3cvWX/rQQ4I/i2MoZOWsPrDbu5oe+xOooi5LmwkR170ym5jI", - "nY38y4/Uz5GzAk4reYkpgeHIXqKeXk1fgrzZS8bUzPbss31nRwKTn/Wy9pYs2bzPecH0GpFEceqUtAt8", - "+TJP2oECdjn+1MeJJbENOFHRXkATx4sm1Dc8+rzDRmQTqv+vBYALRdyCqMRZxmL117Sqh0io/MsPjXhs", - "J1fTDygE7smhpjuo2XC1CdzfJ4F51xD+opct8e5uWy9Duj59b+1P3cpx19iC/AG7bFVnAWmXrlnb4pDy", - "+P5THq/BmP7wy6TB93FzA322ncNv4hbH6XtDQHd+9zmkDt61DgPVdX91GH2rTFhiaMEJUe6NRkKIxqli", - "oYMP0zBluPvZu6av38R8ace6zWKp5h2N03yo4J2ZGMrwBLJDKXIaDpgORxdMa8LckPsNzQbj9HgFsvmK", - "R5ruspKrtnqbFmUJTAkl2vuXl0KiCaCSko+lt1D1vmXvNJoSyBwC+DnLypwiNkXTyNSXls209RtAIMlc", - "J6HTiBWuAfMCcyIYRWZZTCEroGWuNvKvg+Hgt4v/eTEYDsbl06ffQ/2Pv1b/iut/qJ8uXrXEe/vderKb", - "r3+36xrmOCsd4/xD/YwkM2nuuRkyNpvlGmpNK1XzG9Y7b/ereeV9ZwbdhclCltD+2Ovss/lHb8O3IlSa", - "6NKK5tJAbmqkskrZgRSdMG2bsWOBVmPuoMczoJEdfWTCFaaRxlyeAgr1skJNnhOryVORYHcK0T0R2l6p", - "K5jap4vsjjIA7neWkGmLpRrkZwAhB1FmuqBoCxO2q+UgLBCjYxorOEkYPUfXlC2oqYyllUQFq4ZNcVID", - "TIaIMluN177dVOXRpXdwDiuTubLC/koX41mp+WNOq+uunRD1sPXOnqGzAz4aJ4Uj3EWpIUjMRTOMfnj6", - "1EQB6P5bt7wLbt8ilO6CxweW6/b40OsJRSW2MGl/gCtAbvU1grwLd6MA6fQ4qt+1zAk+xwCT3T5HlxnW", - "uB0h1OM+CXwqQB6389Eja1uexX1KWkVZdYjI6rxeKdjJpi2HnBKykiENb0ELX1ezCQJxwiD1MqGpbeNt", - "/0yhrj7XDEcEwkg/0frx8Tv16pdPWr7Jd4Ph4KUTIvVUJWpEtQ3DZgUI0wal12+/n/Jue6T7gKhuDVFV", - "7kNF5rt5EBUtupyI6jcOU+BAYxDbAFg/g07zldumA1mbdZVc6DTszEKDT/E0fYqKUPq4FY+E8oK/8aTx", - "3Cm4HLdw3AoGPBphv3eYugVXbsOEX27h9tcDxmeHhbnO4FPBuPTeun2hm1cYjlCE0d/evn6FTJh7XR0/", - "gybXGMn1c+beF+/UheYVDwGL9aJ6ux2HdevVTz+tKEy/R0kHlKQkSyoyUoYwXjES/fThjXMLkClApj0x", - "3cmc1fZi1rPP096Zje3pqkkJ1MGxa6b1Liem986z+z/GDVb+Ceb5sawgWScjrBgdgQ3uK5AhY7O1IIJn", - "r34eDNV/0avXytZ5fan/o/9yBwswpbVcV0W/3FdCjHACerea0h77dyPbpi8CGuNClJmObposdbO9wAfJ", - "bnjXecAaIG+AvMFLuCsLn33WxmdfzEtX2bjxfNwMBPfwPb7BHKhs+1gOBwc8b9vt+5ha9S0CQD4RgPyi", - "4ZY1R+HuUDkwy76YJcDokOXzmKI/+tf+z7GMU0JnvT3IvYr/BzAdwPSuYFoR1snj6B3LDe3MnX3rDQUG", - "DQy6K4Na2jp5HtV1l70MWgWqLVLgaxBdoFJAgh43Fu9K9K4YIl5mYP4VpxBfI5lyECnLEvGkk63f6ymF", - "U/3WbpwUCUa98i91nyL2uSS1//Qge0rOZOOobvHu1bSm5mlINBwOHXe58HLIXNNyKqwBSTYjMc7qW9/o", - "P4xQpY9kSkRrJ2QKqOAwJ6wUiFFoXWz5Cu/EmpeJCXNhfeXKTpUH3XG9pZXbNciFIBduRdduuYV8CTmb", - "rwK8Fq7rqj65ITj2eWfO+DC9TLHuM11lDTdDaFgJVPpH3fAS9xl2jc/W3jFcW0ngu3DGYc44aDsTyS76", - "+eDZ7OuUtb3huqKvgUq+vAuNHa+fxRjVXawJBqcGD9IlHJYcwmEJ118yOUtJkgCNcqBlZNODb49LUr3r", - "ZOJmhCYDj26cMo5gDnxpqveN0O+Y4hlwMaYCAOEsMw3iJ5trqRQ6eJ9mS6Q6qIFMB/XPJZpAxpQEYC4B", - "+AvIl3Y9v+rJ/A60fGEXE1JJPITC7/3Fw72wmyHlXtfQDb948fQvZqTbzO+zVoLTpbx1MU7fgyyDM6+e", - "utcEDRd0yo7j3t9hlY2ocm8YMm6EOYoxRX3kuUmft4tAr+k8SO/jld76JcdfIMsrkpXltWeBvDKZz/2y", - "6LxY4U9EEvS4KqJo10CokIATZcCYnEFPnJ4PTuYkg5lDtD9698hWjak7mbcN0aOXjwzPL4iAE1IWOxDv", - "gy1RZST62eeq3PaX/hBHZ9SJsYhxYst6gk66k0M+AS5SUgwRLgpxNmU8F2fVYfFZzhL7zzGt66OTjCgG", - "0mMW5aT64mKELg29mHKi+pNa5dUQcts4UQrNTgZTa7w4VJoajDL6zRozOHTbO31lPS9N5tlHL5RNNGHJ", - "8pHdhRhTynQtA/PaZAv023bu/YsVAc2ZNy5lasra2fNuxXOeo+66bPqhHHMHxHbT3EGGvBrlsiNqM3b6", - "jVDbAZJoiK46WeB43NmGNDU/Ei0+7YKZhyr87wL43jI4DeDz+MHnmcKL273Xqlej2RARqMaRGShC6laV", - "Y7oXj7X+ws+KQgR1GdTlnXjJD4RJPSdOPqvxPU1JoqzG+tBpqYV9zW+mJIjiRlMWLmVZsmHtjWnL3FP9", - "cVwVDcnYbAaJNh0xilNMZ8q2U7xmvoXqAzmR222zHodPp6Ov6++3dMCb5lNdw1InctZfcevJdWvQcEp9", - "/AcH/c+KW9zc1r23dFp8NNwaFHE4rj4Qk/XXg9bCtYkcdLBXBwcN/JBs4eacpEc8V93XnJ6IFJIqvNJy", - "9yWor6GrsbUbtMIdU833RuuKLWr392ZeQd8GffuADN8eaSjMuWICh+Kf6pXfIvBp4NNT4lPeW2/yO9Oa", - "l0FnBl58gLzYL0WMToZapYnZXXOO6f69S31zzwSGDQx7SgyreWc7txoWM7F+1bU6h//XHaZkNGcvDtVe", - "pgILsWBce5fGlMOMCGlYNrqGpa37LhDmgCjMgSP4VDDhdjRV/P1e9KgcEpg7MPfxMjfpeWNJGayIFOjx", - "pMyudemmJ4bvHpHkkXY+EoFyTBMsGV9Wt2UnLFkahqxi1dWvEvMZSESKn2w1/wwq769MgdqyTwnCAv38", - "4rcX714gNc2zzyT54j+cvbjlC1MXqzyu9iMiisGfhCLooa7nuvojhUAJSNBWIaPG39NSe5XKI/7LVGoI", - "NrWeokXKhA5qMrpPabF11OvWYxfhftWRK4+L4rDVh5bLu+gQ7yniK5bAxsUNfVo4gdY9EEPvtRvVFAws", - "2j6WjmPHMb1p9M/F1sjcThXhwH4hif3p1XKucFL7Toa+HtQQhjJ5JoCA1BX4aZkDJ7GS+bY4vqVpnCQc", - "hPDK9h0pch6p6VGQC8avhSJM9a7mPXsh02CcnKZ+OfiEZxmbbXFKwFyX+bfGSf28UhAu/vpNDbiFwyrn", - "P5JMDVO9ok5jvZbOqG9y2o/q87ey09ZZfgLfnYxTgM2O89Y8bgjd6DYTgKToUQGpKeOxOQp7lIMQeAaP", - "htbOn+Iyk2OawRwy1fWRAiGPhhqZQV7IZZuFlI2TEBFjnvjDwSyL7sfsz9gsSkgsW9xVgaChbpzm0nlt", - "SbXpRTlbDQ5MnG1iHrub1lwI1ds/3POVpXBbaasKOvusPpa1ibagxRUVZAi/hRw9OmmbSvqtHqqN/TI2", - "81siZsYB5gV1cwQ4r7JftAB3KqqfIc6wrlVg+66liHhlfnUkibiyD1wZ18TEJjW6eDP/oRqrMpa0E0L1", - "z7G4vvoJXU1gRujVEF0BTa60TruacIaTGAt5pdTZmKr9KVvFPRMs8QQL9WIJOI9aPo6rSl+KKqokxlkG", - "XN8jJjnmS3uiPULPdMZIBSQxrWeHMw44WaLE7EViDsqnul7DgsgUYfTD0x99evVVtcd7Sy/K8tw+tqEE", - "Z1jCAjvCm/W2VwsiVBDr7bFfwnXV1wg0lxY2H8qRjJPDlHxCGdCZFok5/kTyMh+cf//dcJATav546srz", - "Wc3DPfE1ehmafImfcF5kgL798bvRt3/5r9G3T0dPPWl6mGuuhCkWQjhndIbYHHiGi0IZGrT5YvUKfvxx", - "2wqKueus4x+/PXu1khSu9cQ6nW4+/ZrPMCVC0wW2p7rI6b3zfcY18NP0qz7ifcMgyx7Hg4YOPldpHTfb", - "z4u8eQxpUXb3WeSYKrHsOItUT/c9jRxTM9uzz/adX9DjtRxHf0K4TIjUqO5PrpsuT/x+5iocdz9yt2V8", - "rO7nK+2o3HBXa3+E9hJad8QW1rTDh/PNh3W+SS2RbtgnnmDyYCqcZF3CQ07oaPXEspZmlWSLjBnsAL17", - "lbzm/DEy0qgpgFuUQqHMoswyZ4J6XBRO/IqFABkBnftbvdh3QpiI5sCFL+9OnJVCAvd5qZov4G6lFGIZ", - "SeZuLsooZtxsyiaeVM0J6WqdcvjoHTlnicftplplqoygjrHnQBPPsoDGGRMlh+5WkTG3VTP9mLg3O517", - "fi4YyzxN8yR2tywiNhERzoDLSBF+V68F5tTfKcNCRhPmWY1uVUacu5UICRR4VDAu3budsThSlpDHgRpH", - "k5Jkifrb1yHWssPXyMrqiqyzfZox5n83x/G1v5Gx3Nv4B3Gza47V2immMURAE08fWk5xLEsO7qnlkEcT", - "TK89BKyblxI6mhV1+pq9nKOFpE/S6MYpZ39Am7onjGWA6VqHCMudPeKVtPY0NhBauF/PRIR5nDofZyKK", - "GY09s2IiugZOPZvCROSdFhN9uND26uZCJiIOGWDhbe4QWQVbAI8mHPA18G+3d/muo0uMJ4SC/HZ7l65R", - "Cs4kxHJ7j2pKHT1FWRTZMqITNz17krxp3BH9waivkRPs/uKCMvYHRJJknvaiU6cKiWUpnE3ah6Kn7m9e", - "c7G4O6ktWZW4rQ4WeGw2/OH82QAnN1N2rXOBOcdULj1i7r6T7ClQd8kW4bDK7XI5SzFPFphDd+QEzjIb", - "ifrm+YX2beeQM75E9eM+W/DXpkOwCcMVhtuj4wkWfWn45XNNwuTt87cXKGVCokkpEE5wYaueekhZvSKQ", - "cSDjWyTj2qfcxxdO0esC6Nt/PDfODk+yfQ6ZUuxVfrZRh995W2iB12n8/v3Fz+ueY0ecQQX8jy3zfPD+", - "rsZR2kx/Jh+zKCBWVpn++D7heYiUFUJYTtUvfZT54t+veK47wsAqX/XBSuvgPg/u8+A+D+7z4D6/Nfd5", - "cJEHF3lwkQcX+YNxkR9+WPqq/+bMANiOKPW/l1BqJw6eAZXVfXVGrQUwRNiEKKZESMZJjLPWfRHbOwda", - "jmlCEhMFqRCG9mwKpPCAbJLwGwdRg6nP0Uf1+gRNMDcRuXhMFarW9xEBEjuHBcdFAQkialpCpDoKHUmm", - "m/MZr2oylSLVP43GdDXUniXw4hPEaxf6V4o6Llfu83tD0lkCz/QCbuCDfYNlqga4SAb7NlE2P6yZpdok", - "vceD4Yr1om0NbcKINCFCR2yrfxfXs+pfWMap/bfQpvtwEKcQ665iKThoiabMMExFLMhgOJhygD905u8U", - "LxyW0Vrcpp363YdtWgp1RHBZ0rVkWVGE5g1XgLwrptVuvB7C3krU5uuU8VwhGqUL//KDM6w9hJPei4xU", - "cHDbsY2VXaarx734rGoNTsbgZPwqMKQp6VRuyq2zWx6RddTsZLxLkCWnSNE2IiZxo1WZwB0ZV02WA628", - "vQyaX1y2XnyC50whbc5uxBhjhVuxhMg80ZlNFM8EwlLiONUltiWrA7wpk2gJ0rbaNE/qR/gUZ2UCjlhv", - "S5LPqwm8w7OgOoLquLPkCMfGqMb06APSaivFzXBVa+C0wGmB0xycxvIiI5jG0NKOPWo8/QIS1Q+0Cz0Z", - "54wa351BTnNl/dJaIXaVb9rJ1RL46rT4Sst6NnUSW4vjHAJdIbIpK2nSYra1nAlUAqc400UegCPgnPG7", - "Zze+G7Pxr2S1y8BogdH6MBo/BTbrTNGoGavui1TfHbnKnbAxMNIDZqTnDoKqTpqOHSP2RIYtPFg7SWoH", - "Sh+2CnAwMFenlqrJ6kTQYLOMs8+5Sb275T6GWj/CzfrNwbuXxZobFw4uuwMmU/1/FyDr4/AVAnJ8tXpy", - "SJRxDEJMyyxbogTMh+/+2oy3Nua+P70v+vqZ3PiGXUKyikg4kO93s3CGG5z9f9dFG5UcCNdq3XKll23J", - "v05ZB4MyqOo+qvok7Eleq2m+i5rmN1bSl3cq4i93UdGXX6Wg+bGoZ34j5XyP3+0+VfNlUMy95EgTiO4/", - "4my5pixERBlWv6cQXyNeUmRG2dFn9da8OmjroK2dXitLVO0r1w7/1ZGobhPv3MlmuotGKv0ulv9chVCH", - "mILAk1/Dk4qQTjSuoGeOJxPDs2OCJ39+p8CCgQV3v4hW0dOpsuL2NFWGDYVkHM+gf3oqd3aqwISBCXdj", - "wl8n+ER5jyi8O8Ux9OPAqn5L6zEP6120ewQGDAwYglsd3Ff0Y7uLN1XFpA6GKwKnBU4LpY99vCaAz8lW", - "PVclj7S9EaFCYhqDQMyUTLIOGJsMwMeMb6uXBY4MHBl0Xxc/nn02BX+314Zd58nKD3wTzjxQxlydxNtq", - "wa15mM2qpyHmcccsbCnlIB2CdDg26aCzaPkTBb3V7bq4FTV9V2oJiiZn0GhML6YoKY0oQESggrM5SSAZ", - "IvtkSSXJEGUL9Kem42MYzUZoPPg2HQ+GaDz4LhkPnmwOxnIipRqrnkcrac+7KstQjGn1MiIFZNMRei+A", - "i6qkrs4JVNXeXUkG1K4NuiUTkNmTQ8kEVG2SQ55X22eEzsZOf/80b285ep0THdtQ7fDIWYJxIzog1FY8", - "/oQIO6VBaIcF+tR/yGsQ1G5Qu15+K0uTQ6wTh2uNpnqO0Gua2b9bCkuYs1KjzQTSVeezjC0g8abCUZwV", - "EuA8PHnPJoJlIGLQkasw5SB0Dt6idGZg0u0mAaQ9EkU657ChOCbQtMwyXflfoExpB1vnuv0aJEBKQmdi", - "PS3j64moEFidmNEJt0r5ujWendXg0NDGCUUprlBJ9fn6FYNxffkRutF3N4O2P/3bair7wsyuBI6vHStA", - "HGLGE5PJsTurZShE/uBK0TilnUvzemg5FPM6Xlzq+KRHVrb8d5aQ6XLPsvsNE/LgJfdwsFkOYE2vYQnm", - "hs4iJXFqS/flWMapGlunnKxepHNYZ3g2gwRhYTdTwgiNB//617/+9c3vv3/z88/jgQLO7V9Qmp7n+bkQ", - "48FP6iNAXshl5amJM8Dc7Lya4Mi3hpViBXtbAkZqXE0Et7qG+9Ggt8LVQY/eFF6efe5dcPAuMOY243ir", - "rHEYxHdsCx+JhXOMsK/yzHiIsSf2OwAaC27QBwI3j7Ia4V1C00MR+PsAxwHWHgisDSD2dEFsARQXZFR9", - "E4sTNvT+24UiPD44gLOxA/BQV7tZlJOMxHYr25Gi29B/FZTmB/OtUND9SFMb1HXujxbTh2FK5G8zbe1Q", - "wUH8sBzEoiHJTfngjVwOwPyIgLn9jEfm+33OQeEoxlFZFf6ugn4fT5ZVsKuNe42Io46JQtN7l7hbalmr", - "ufhqbOu2UjIhsafgpuoRszy383K2J5yyprKep0uh4562tIuuDt7an6rdV71XtU0z+BTFRRmlZJbqEtki", - "ZVnirri68kDGFr375/hTtL4GZz9Ct/Zbrza8up4Ue5s6aCAHyZmlFW+n7o/Qo1Kx6lZkOIZOitExroIw", - "Cv75bq1UO48jyQqWsdnS22GB5+DdZ0/p47uwRLbiiAouxVrmJI3QedgZoZzXMrb7wNfvTWGaoBiLGCeA", - "zNOISIE4ZHqzbeqeUTdm3uYDuY/7ESEi7H4wazvZUysNkqgpxYdkD5GIgpv7hNH0Ubq236/j7RYC7sDY", - "Byuh9+VoCbj+geD6AN6PEbwfGGI/+FOCDXR/ZsSP8N+0/LuuHI+pKTuPTH9zvdKONkTYHDylREjGSYwz", - "VL+4eiAHWo5pQpJzU8M+rm9jMiFtcXub7YSZ6sqVJhIAFOGMzKEK58+wkGP67Z9RTmgpQQy1uYHFtWjq", - "4+urYLGsLocvUpY1Q3IsU+BIplitZExlilXP5mr52lnuK5bAi08QNye5q5c0SUbkUi1BDQVdZwIt3Wkq", - "85+0Bm1021rmavP1JUMfFXUNhgOgZW4OYkSq9lUfEAzNnzGjUzIbDAdTDqAvuMoUL1qnFp7TDfv2uz/d", - "UGofU8cRzXPTYFad1Bd7NcG6Dp1dxzx27/QQ2ipamvP+KeM5lkaK/+WHZrSWUPecugzrq1HurLktfl1g", - "UU1ek+6DOb/54emPrt1xCqwUCzRRQqsluTjEQGW2PCTJnwGXW/NP1Q4d09tvZz+rOgRrO1jb4W6tk+Py", - "iESti7Je3rsEWXKKFGEjYoSLVcjAFWbazA6hw4sM6uji0fzisvX64F4NBkCrzO9OyRawoj2dbqE+oaVM", - "omWrsobGyOpH+BRnZQKO49qGNOvqv30yNAQtErTIg9UiurhKb9xme3cwXtUhcFzguMBxTo5zFcXvUWnY", - "UyOpKWRYKdHV9IXbzzQdRfO7ChIHVg6sHFjZz8p8V0bmt8bGl4fNxGvFsqbaRB2aXDsdmwI0xoUoTexP", - "sy96Wh8VUbfmleG5amumkcAUl5kcnE9xJmC4caoWhEsQLgcnXDI26y5p3JImqm8V12TGdBdJ3JAav7Fg", - "KgeGvNPSizWttg48jp9b94HlTfbRm0OAgwfwXbq/YzeC7g+i5mHp/oYZzj7nu9Rgrx+sqrD74cBKnLxD", - "iBwrLHiDZfq7LRXulzmmhLvZpduXMR/6lBWvd36tvvxRhjls6/vjQcUu13XwG/5pH0x1R2E9ON4x+vlu", - "tPOOnHNoJflPhnO2qqyv9YB9Lfg9HbdXAL4B+D5U4Mtr2Mt3gb38K0Hv5fGr7ctjhLyXAfDeM+DlXwF3", - "HwTXHBzYvQxQ956VlCkauaufV985MsFUiJd0s+bkLmj3rZlCOLkJqDKgSjfDJkT0j3E0nf2c97NtD+wW", - "2O2r2E0R0smyXF3qvKkHt0sGzKYsczv3j2QowSKdMMyTIeIgckaH1QVP01PHH0cZmUO3wXdhxz8KH1Eo", - "VvegEu9v8ICyiUm2Q23yQORBZZ6iyqwI+iGpza9IqsEobAiToW6nMyNMsLSXzmm2XC9h2TtPBZowma5c", - "Wsc0MckruqqMrwmpw81gMbyvquch48UxZLwIecZvWSjWibL6mO81aDKuOSXmAMcpYlOdM9SM5YdMr2x7", - "sO4DVAnONC83rlr1u1kzDWPuZMy8Ms3BkAnSIUiHY5EO6t2s5HGH/vbKifrRG4mKy/rFQWYEmRFkxjHK", - "jO6Lj3Wd0i7RocAGoDjFdPaVguSA70cGWRJkSZAlleyo3DR9vAWNoNBHiNewPJvjrARUYMK7/ASXjY8t", - "eAoCLwZedPPiFuzv5UZGEc6yrd66Qwf5gQ8DHx4QH3bjaS8zbmDoXVgzpBUJ3Bm4s4M7d0qUay4E4h4B", - "4iHzbeC7wHcbfBfVETY3CkfdXpn9oh5/X1EgneXZG49XzHiCSKLr52CloyVwiiWZ67hZy9Z/Qo13ZzPA", - "obtyR1MKfqhGnAAqBSQIZ4zO0ILIFNXioKPY7bYy876xN+Z9lyWkQr35w6s3j0iL07yV59vsGErQP5TI", - "zwNRMStlj/0UXff31KNFj2uD60kfWg+wL/BbiLTewpuRCUOKMjbr5s5NfVNFMGVsNkIvcJxWcaQCYSRJ", - "DohjOgO0SIFDR2jiAuuhJllnmZ1GhZmbvr+xWdBlD8Ckul8+2Zk7bsgTu7FC4IDAAbfMAZU7bqtrQOIZ", - "ejwps2uF2vInfs+A9cTtxxkg8cxpSL/DM2Tahgq/qcnVLoHBtpsedtAPwZJ+UJY0fCJCXwWThkI3xK7b", - "hxwkbZC0t5WM6jkHXElX373BvcvTBEu8OZWXHHQ9zBz97e3rV0h12sjKKPHM5e1Ug9oyha5ynLMywxzB", - "p4KDEPqq5lQLbGVdC3MpM8ZUFzucQKsAYuMM1SU6O17ur7a/LvZ1z7sQ/Ps4YzgEWX/g2arU782Fua3Z", - "EhXZ2UyJvqu6DYip7sbth/O2HTb4aPu20E9z/BFw0MPCQTjLFMl8o2/CG3Gbq6n4IJHnjmjARQEX3XqS", - "TiXadARIV2aFwxHWhpu+AmE17Bj0wQnrg+PAVZWzc1doVRXT70RXlY9zbzzbP+bi7lnLzi1w1sNEWnWe", - "oO1gq8UWAW8FvHVveKtDhleQ6wAl+FHjr6AkAvxqw6/PhjL6JJK1zlmdsI7U5XS0olGUrR1kulE0POsB", - "ZtuiqS5+1v7b2hvsiJeqKXprvFQdjBvyr95f/lVFOFYgLD2w5J6IYtcoujsjooP+2G4V/75I6qMm1JL/", - "Hu1+n2Jg3wdd2w6sdjxTunXtHEyzW9KkW1Ir/gLSqkoTtlVpVdJcR/PIx15pFA9ESN66afi1UphIyIWD", - "D2rOw5zjpYsvtNHNptVHXDk6boh1E7tTJtGUlTQ5JDLtW0nAfbTpB3h9EgveHqn63mPnfCDZ/PduHz1I", - "1LnL2Y4PhzwYat0X6FlzgfSg2eBMeEDOhJVDnR5x7rsiIb//+mGCoeAnfwjX7d0stnIf8gYHqH4M97bu", - "cDCK0Tjmq/etFQj96vuUAdAdE6Dz0a/FdA+TegPACwDvdrRPKTQDfe5z90X3HaHfMcUz4OZQ6L0Abn/Q", - "kfgCQIcu6L4/ISZT4GOq/9KVk3QHxSfmJ5FibiosVQxEOGJ8hikRmqRwhmYKTIjhmBZZqcst5QKyOQjX", - "+fIvIN/rFYUQiGOGduobHut1HEXYQ+NAJFLoimCqQVMxGg9UczQunz79PiaJ/j+MByO0Uk6sxVRjWpcU", - "G6FnFEGOSaZ0jhpH6x2cccDJEhGqflNmFoepTgmk54DRD09/HKF/EpmyUo4pRgUWYsF4YoIW4piV1DK5", - "QJNSX6ihTCJBZhQR6oviqNhsP8pJL8t5njIlXEjficpwkOGu1mqpLuCBMsBCov9CcYo5jqWWbW8l45Do", - "vFBoAZPviiVKsUhHroiOImUUogXj1853Vx9o++Uis/j7vlnUn+fC7aK+ivXss2b3PrV/VMfW2epOanZM", - "tZ5FX6Nmx9TqWdRfzW5D4apPK3XOOcKlTCM1pRFJhvX8rFBbpEARkUhRMyZULXxMx4P/fzzQkVHjgYBs", - "Oh40texKmaqhYywh0QOZqTpwt/0KIQ1PwAzH4BJakx1nBYepH6S/BBmnDTOpzsCBxiDO0ZwIMskAxSwr", - "cyqG9h9oSjL1gYYoI3NAOUtgTIHiSQYJmmZ4NkQpSRKgFrYAlZyAGKLRaDSmY3oJsuSaQxHkhVwio7IM", - "C9czSbFAlLUnhITWr0NT9RRngq09kjAQ+khV4xHF9sT8XS3ExlrGOMsqfneKpjd6y05ZPt02L+kdPCIA", - "/hbP4S65wIuKHwjp7QP2V44onCTEwJA3rXYzjbWQixRWBIoRPEMrWNAc+ARLkrcAexMCUpauAOzXBf5Y", - "AhJAk5VPgiBOGSTKrqq+RqQFcWTSu48pzIGqVzOEUZwRoCYZAZlRxkEbf2xBUamD58z+d9sBejfu2wy4", - "oFN2HCbAvajmOXBhC007lTHXmhHhgqCqq0ND/aNuurXvWL19P4K73g5cYF3NXDHohy9mZ/m8knElzwbn", - "g9HZ4MuHL/83AAD//w==", + "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", + "DL59/Pa/AwAA//8=", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index f3b70932..01607ff8 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -1179,6 +1179,9 @@ type InPathNodeId = string // InPathRsetId defines model for inPathRsetId. type InPathRsetId = string +// InQueryFilter defines model for inQueryFilter. +type InQueryFilter = []string + // InQueryGroupby defines model for inQueryGroupby. type InQueryGroupby = string @@ -1244,6 +1247,19 @@ type GetActionsParams struct { // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` } @@ -1948,6 +1964,19 @@ type GetFiltersetNodesParams struct { // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` } @@ -1972,6 +2001,19 @@ type GetFiltersetServicesParams struct { // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` } @@ -2478,6 +2520,19 @@ type GetNodesParams struct { // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` } @@ -3245,6 +3300,19 @@ type GetServicesParams struct { // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` } @@ -3868,6 +3936,19 @@ type GetServicesInstancesParams struct { // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` } diff --git a/server/handlers/get_actions.go b/server/handlers/get_actions.go index 06491111..0869d316 100644 --- a/server/handlers/get_actions.go +++ b/server/handlers/get_actions.go @@ -14,6 +14,7 @@ func (a *Api) GetActions(c echo.Context, params server.GetActionsParams) error { return a.handleList(c, "GetActions", "action_queue", listEndpointParams{ props: params.Props, limit: params.Limit, offset: params.Offset, meta: params.Meta, stats: params.Stats, orderby: params.Orderby, groupby: params.Groupby, + filter: params.Filter, }, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { return a.ODB.GetActions(ctx, p) }) diff --git a/server/handlers/get_filterset_nodes.go b/server/handlers/get_filterset_nodes.go index 3f61a74e..6d8f42b4 100644 --- a/server/handlers/get_filterset_nodes.go +++ b/server/handlers/get_filterset_nodes.go @@ -36,6 +36,7 @@ func (a *Api) GetFiltersetNodes(c echo.Context, filtersetId string, params serve return a.handleList(c, "GetFiltersetNodes", "node", listEndpointParams{ props: params.Props, limit: params.Limit, offset: params.Offset, meta: params.Meta, stats: params.Stats, orderby: params.Orderby, groupby: params.Groupby, + filter: params.Filter, }, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { return a.ODB.GetNodesByIDs(ctx, nodeIDs, p) }) diff --git a/server/handlers/get_filterset_services.go b/server/handlers/get_filterset_services.go index 073bf159..07fc791d 100644 --- a/server/handlers/get_filterset_services.go +++ b/server/handlers/get_filterset_services.go @@ -36,6 +36,7 @@ func (a *Api) GetFiltersetServices(c echo.Context, filtersetId string, params se return a.handleList(c, "GetFiltersetServices", "service", listEndpointParams{ props: params.Props, limit: params.Limit, offset: params.Offset, meta: params.Meta, stats: params.Stats, orderby: params.Orderby, groupby: params.Groupby, + filter: params.Filter, }, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { return a.ODB.GetServicesByIDs(ctx, svcIDs, p) }) diff --git a/server/handlers/get_nodes.go b/server/handlers/get_nodes.go index d62ed0d0..fd125c7a 100644 --- a/server/handlers/get_nodes.go +++ b/server/handlers/get_nodes.go @@ -15,6 +15,7 @@ func (a *Api) GetNodes(c echo.Context, params server.GetNodesParams) error { return a.handleList(c, "GetNodes", "node", listEndpointParams{ props: params.Props, limit: params.Limit, offset: params.Offset, meta: params.Meta, stats: params.Stats, orderby: params.Orderby, groupby: params.Groupby, + filter: params.Filter, }, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { return odb.GetNodes(ctx, p) }) diff --git a/server/handlers/get_services.go b/server/handlers/get_services.go index 972f43fe..00363a1e 100644 --- a/server/handlers/get_services.go +++ b/server/handlers/get_services.go @@ -15,6 +15,7 @@ func (a *Api) GetServices(c echo.Context, params server.GetServicesParams) error return a.handleList(c, "GetServices", "service", listEndpointParams{ props: params.Props, limit: params.Limit, offset: params.Offset, meta: params.Meta, stats: params.Stats, orderby: params.Orderby, groupby: params.Groupby, + filter: params.Filter, }, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { return odb.GetServices(ctx, p) }) diff --git a/server/handlers/get_services_instances.go b/server/handlers/get_services_instances.go index 31a066f6..e60cadab 100644 --- a/server/handlers/get_services_instances.go +++ b/server/handlers/get_services_instances.go @@ -15,6 +15,7 @@ func (a *Api) GetServicesInstances(c echo.Context, params server.GetServicesInst return a.handleList(c, "GetServicesInstances", "instance", listEndpointParams{ props: params.Props, limit: params.Limit, offset: params.Offset, meta: params.Meta, stats: params.Stats, orderby: params.Orderby, groupby: params.Groupby, + filter: params.Filter, }, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { return odb.GetServicesInstances(ctx, p) }) diff --git a/server/handlers/handle_list.go b/server/handlers/handle_list.go index 93b816a2..2b22dbf6 100644 --- a/server/handlers/handle_list.go +++ b/server/handlers/handle_list.go @@ -24,6 +24,7 @@ type listEndpointParams struct { stats *server.InQueryStats orderby *server.InQueryOrderby groupby *server.InQueryGroupby + filter *server.InQueryFilter // withUserID asks for the authenticated user's id to be forwarded in // cdb.ListParams. Set it only on the endpoints whose access control @@ -51,6 +52,11 @@ func (a *Api) handleList( return JSONProblem(c, http.StatusBadRequest, err.Error()) } + filters, err := buildFilters(p.filter, mapping) + if err != nil { + return JSONProblem(c, http.StatusBadRequest, err.Error()) + } + log := echolog.GetLogHandler(c, handlerName) groups := UserGroupsFromContext(c) isManager := IsManager(c) @@ -63,6 +69,7 @@ func (a *Api) handleList( "stats", query.WithStats, "orderby", query.OrderBy, "groupby", query.GroupBy, + "filters", len(filters), "is_manager", isManager, ) @@ -82,6 +89,7 @@ func (a *Api) handleList( TypeHints: buildTypeHints(query.Props, mapping), OrderBy: query.OrderBy, GroupBy: query.GroupBy, + Filters: filters, } if p.withUserID { dbParams.UserID = authUserID(c) diff --git a/server/handlers/list_filters.go b/server/handlers/list_filters.go new file mode 100644 index 00000000..7931bde0 --- /dev/null +++ b/server/handlers/list_filters.go @@ -0,0 +1,98 @@ +package serverhandlers + +import ( + "fmt" + "regexp" + "strings" + + "github.com/opensvc/oc3/cdb" + "github.com/opensvc/oc3/server" +) + +// likeEscaper protects the LIKE wildcards of a text filter: "50%" searches for the +// string "50%", not for anything starting with "50". +var likeEscaper = strings.NewReplacer(`\`, `\\`, `%`, `\%`, `_`, `\_`) + +// buildFilters turns the filter query parameters of a list request into SQL +// conditions, combined with AND by the caller. +// +// Each value is "prop:expr". The prop is resolved like an orderby prop, joined +// props included, and must have a column. The expr is one of: +// +// text case-insensitive match anywhere in the value (LIKE %text%) +// ~regex regular expression, case-insensitive (REGEXP) +// in:a,b one of the listed values +// eq:v ne:v equal, not equal +// gt: gte: lt: lte: comparisons +// empty !empty no value, any value +// +// Case-insensitivity comes from the utf8_general_ci collation of the collector +// tables, which LIKE and REGEXP both honour. Regular expressions are checked with +// Go's RE2 parser first: an invalid one is a 400 naming the column rather than a +// database error, and RE2 is a subset of the PCRE MariaDB evaluates them with. +func buildFilters(filters *server.InQueryFilter, mapping propMapping) ([]cdb.ColumnFilter, error) { + if filters == nil { + return nil, nil + } + out := make([]cdb.ColumnFilter, 0, len(*filters)) + for _, raw := range *filters { + prop, expr, ok := strings.Cut(raw, ":") + prop = strings.TrimSpace(prop) + if !ok || prop == "" { + return nil, fmt.Errorf("invalid filter %q: expected prop:expr", raw) + } + col, err := resolvePropCol(prop, mapping, "filter") + if err != nil { + return nil, err + } + if expr == "" { + // An empty filter matches everything: nothing to add. + continue + } + column := col.Qualified() + f := cdb.ColumnFilter{Col: col} + + switch { + case expr == "empty": + f.Expr = fmt.Sprintf("(%s IS NULL OR %s = '')", column, column) + case expr == "!empty": + f.Expr = fmt.Sprintf("(%s IS NOT NULL AND %s <> '')", column, column) + case strings.HasPrefix(expr, "~"): + pattern := expr[1:] + if _, err := regexp.Compile(pattern); err != nil { + return nil, fmt.Errorf("invalid regular expression for %s: %v", prop, err) + } + f.Expr = column + " REGEXP ?" + f.Args = []any{pattern} + case strings.HasPrefix(expr, "in:"): + values := strings.Split(expr[len("in:"):], ",") + f.Expr = fmt.Sprintf("%s IN (%s)", column, cdb.Placeholders(len(values))) + for _, v := range values { + f.Args = append(f.Args, v) + } + default: + op, value, isOp := comparison(expr) + if isOp { + f.Expr = column + " " + op + " ?" + f.Args = []any{value} + } else { + f.Expr = column + " LIKE ?" + f.Args = []any{"%" + likeEscaper.Replace(expr) + "%"} + } + } + out = append(out, f) + } + return out, nil +} + +// comparison recognises the "eq:", "ne:", "gt:"… operators of a filter. +func comparison(expr string) (op, value string, ok bool) { + for prefix, sql := range map[string]string{ + "eq:": "=", "ne:": "<>", "gt:": ">", "gte:": ">=", "lt:": "<", "lte:": "<=", + } { + if strings.HasPrefix(expr, prefix) { + return sql, expr[len(prefix):], true + } + } + return "", "", false +} From 8ac29e40077c466ca51b8776aea12d2b27cd53ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Thu, 24 Sep 2026 15:15:39 +0200 Subject: [PATCH 26/61] Queue agent actions through PUT /actions Replace the dedicated POST /nodes/{node_id}/actions, POST /services/{svc_id}/actions and POST /services/{svc_id}/instances/{node_id}/actions endpoints with PUT /actions, as the historical collector's REST API and action menu do (rest_put_action_queue, json_action_one). The body is one entry or a list; node_id and svc_id queue an instance action, svc_id alone a service action from a live node, node_id alone a node action, and vmname names the node. rid limits an instance action to resources, entries differing only by rid being merged into one action. One entry answers with the queued action, a list with the queued actions and the refusals. Instance actions follow do_instance_action: NodeExec privilege and responsibility for the service, the node only having to exist. The agent version is read past a leading "v", so that om3 agents get --local and an instance freeze no longer freezes the whole object. --- server/api.yaml | 283 +++----- server/codegen_server_gen.go | 626 ++++++++---------- server/codegen_type_gen.go | 205 +++--- server/handlers/post_service_action.go | 245 ------- server/handlers/put_actions.go | 229 +++++++ ...st_node_action.go => queue_node_action.go} | 104 +-- server/handlers/queue_service_action.go | 228 +++++++ server/handlers/queue_service_action_test.go | 63 ++ 8 files changed, 1031 insertions(+), 952 deletions(-) delete mode 100644 server/handlers/post_service_action.go create mode 100644 server/handlers/put_actions.go rename server/handlers/{post_node_action.go => queue_node_action.go} (55%) create mode 100644 server/handlers/queue_service_action.go create mode 100644 server/handlers/queue_service_action_test.go diff --git a/server/api.yaml b/server/api.yaml index 20ceca0e..88f6e8c1 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -81,6 +81,66 @@ paths: security: - basicAuth: [ ] - bearerAuth: [ ] + put: + operationId: PutActions + description: | + Enqueue agent actions, as the historical collector's PUT /actions does. The + body is one entry, or a list of entries; the fields present select the + target: + + - node_id and svc_id: an action on that instance of the service, acting on + that node only (--local), or on the resources given by rid (--rid). + Requires the NodeExec privilege and responsibility for the service. + - svc_id alone: an action on the whole service, posted for a node of the + service seen alive in the last 15 minutes. Same requirements. + - node_id alone: a node action. Requires the NodeExec privilege and + responsibility for the node. + + Accepted actions: push resinfo, push config, freeze and thaw on a service + or an instance; pushasset, pushdisks, pushpkg, pushpatch, pushstats, + checks, sysreport, scanscsi, freeze and thaw on a node. Compliance actions + (module, moduleset, ruleset) and agent options are not supported. + + One entry answers with the queued action, as GET /actions/{id} does, or + with a problem. A list always answers 200, with the queued actions in + data and one message per refused entry in error; entries differing only + by rid are merged into one action on those resources. + requestBody: + required: true + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/ActionEnqueue' + - type: array + items: + $ref: '#/components/schemas/ActionEnqueue' + tags: + - collector + responses: + 200: + description: | + The queued action for one entry; for a list, an object with the + queued actions in data and the refusals in error. + content: + application/json: + schema: + type: object + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 409: + $ref: '#/components/responses/409' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] /actions/{id}: get: @@ -4688,72 +4748,6 @@ paths: tags: - collector - /nodes/{node_id}/actions: - post: - operationId: PostNodeAction - description: | - Queue an agent action on a node, as the historical collector action menu - did. The command is built from the node action_type: queued bare for a - pull or feed node, wrapped in a ssh call to nodemgr for a push node. - Requires the NodeExec privilege and responsibility for the node. - parameters: - - $ref: '#/components/parameters/inPathNodeId' - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - action - properties: - action: - type: string - description: Action to queue - enum: - - pushasset - - pushdisks - - pushpkg - - pushpatch - - pushstats - - checks - - sysreport - - scanscsi - - freeze - - thaw - responses: - 200: - description: OK - content: - application/json: - schema: - type: object - properties: - id: - type: integer - format: int64 - description: Action queue entry id - command: - type: string - description: Command queued for the agent - info: - type: string - 400: - $ref: '#/components/responses/400' - 401: - $ref: '#/components/responses/401' - 403: - $ref: '#/components/responses/403' - 404: - $ref: '#/components/responses/404' - 500: - $ref: '#/components/responses/500' - security: - - basicAuth: [ ] - - bearerAuth: [ ] - tags: - - collector - /nodes/{node_id}/am_i_responsible: get: operationId: GetNodeAmIResponsible @@ -5724,142 +5718,6 @@ paths: - basicAuth: [ ] - bearerAuth: [ ] - /services/{svc_id}/actions: - post: - operationId: PostServiceAction - description: | - Queue an agent action on a service, as the historical collector action menu - did: the action is posted for a node of the service seen alive in the last - 15 minutes, and asks the agent to act on the whole service rather than on - that one instance. Requires the NodeExec privilege and responsibility for - the service. - parameters: - - in: path - name: svc_id - required: true - description: Service identifier (svc_id UUID or svcname) - schema: - type: string - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - action - properties: - action: - type: string - description: Action to queue - enum: - - push resinfo - - push config - - freeze - - thaw - responses: - 200: - description: OK - content: - application/json: - schema: - type: object - properties: - id: - type: integer - format: int64 - description: Action queue entry id - command: - type: string - description: Command queued for the agent - node_id: - type: string - description: Node the action was queued on - info: - type: string - 400: - $ref: '#/components/responses/400' - 401: - $ref: '#/components/responses/401' - 403: - $ref: '#/components/responses/403' - 404: - $ref: '#/components/responses/404' - 409: - description: No node of the service has been seen alive recently - 500: - $ref: '#/components/responses/500' - security: - - basicAuth: [ ] - - bearerAuth: [ ] - tags: - - collector - - /services/{svc_id}/instances/{node_id}/actions: - post: - operationId: PostServiceInstanceAction - description: | - Queue an agent action on one service instance, acting on that node only. - Requires the NodeExec privilege and responsibility for both the service and - the node. - parameters: - - in: path - name: svc_id - required: true - description: Service identifier (svc_id UUID or svcname) - schema: - type: string - - $ref: '#/components/parameters/inPathNodeId' - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - action - properties: - action: - type: string - description: Action to queue - enum: - - push resinfo - - push config - - freeze - - thaw - responses: - 200: - description: OK - content: - application/json: - schema: - type: object - properties: - id: - type: integer - format: int64 - description: Action queue entry id - command: - type: string - description: Command queued for the agent - info: - type: string - 400: - $ref: '#/components/responses/400' - 401: - $ref: '#/components/responses/401' - 403: - $ref: '#/components/responses/403' - 404: - $ref: '#/components/responses/404' - 500: - $ref: '#/components/responses/500' - security: - - basicAuth: [ ] - - bearerAuth: [ ] - tags: - - collector - /services/{svc_id}/instances/{node_id}: delete: operationId: DeleteServiceInstance @@ -8072,6 +7930,27 @@ components: type: string nullable: true + ActionEnqueue: + type: object + description: One action to enqueue with PUT /actions. + required: + - action + properties: + action: + type: string + description: Agent action to run + node_id: + type: string + description: Target node (node_id or nodename) + svc_id: + type: string + description: Target service (svc_id or svcname) + rid: + type: string + description: Resource ids to limit an instance action to, comma separated + vmname: + type: string + description: Target node by name, in place of node_id, for an encapsulated node InstanceRow: type: object description: | diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index c9d7dd99..c9fa4d8d 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -27,6 +27,9 @@ type ServerInterface interface { // (POST /actions) PostActions(ctx echo.Context) error + // (PUT /actions) + PutActions(ctx echo.Context) error + // (DELETE /actions/{id}) DeleteAction(ctx echo.Context, id string) error @@ -309,9 +312,6 @@ type ServerInterface interface { // (POST /nodes/{node_id}) PostNode(ctx echo.Context, nodeId string) error - // (POST /nodes/{node_id}/actions) - PostNodeAction(ctx echo.Context, nodeId InPathNodeId) error - // (GET /nodes/{node_id}/alerts) GetNodeAlerts(ctx echo.Context, nodeId string, params GetNodeAlertsParams) error @@ -426,9 +426,6 @@ type ServerInterface interface { // (POST /services/{svc_id}) PostService(ctx echo.Context, svcId string) error - // (POST /services/{svc_id}/actions) - PostServiceAction(ctx echo.Context, svcId string) error - // (GET /services/{svc_id}/alerts) GetServiceAlerts(ctx echo.Context, svcId string, params GetServiceAlertsParams) error @@ -480,9 +477,6 @@ type ServerInterface interface { // (GET /services/{svc_id}/instances/{node_id}) GetServiceInstance(ctx echo.Context, svcId string, nodeId string, params GetServiceInstanceParams) error - // (POST /services/{svc_id}/instances/{node_id}/actions) - PostServiceInstanceAction(ctx echo.Context, svcId string, nodeId InPathNodeId) error - // (GET /services/{svc_id}/nodes) GetServiceNodes(ctx echo.Context, svcId string, params GetServiceNodesParams) error @@ -684,6 +678,19 @@ func (w *ServerInterfaceWrapper) PostActions(ctx echo.Context) error { return err } +// PutActions converts echo context to params. +func (w *ServerInterfaceWrapper) PutActions(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PutActions(ctx) + return err +} + // DeleteAction converts echo context to params. func (w *ServerInterfaceWrapper) DeleteAction(ctx echo.Context) error { var err error @@ -4374,26 +4381,6 @@ func (w *ServerInterfaceWrapper) PostNode(ctx echo.Context) error { return err } -// PostNodeAction converts echo context to params. -func (w *ServerInterfaceWrapper) PostNodeAction(ctx echo.Context) error { - var err error - // ------------- Path parameter "node_id" ------------- - var nodeId InPathNodeId - - err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_id: %s", err)) - } - - ctx.Set(string(BasicAuthScopes), []string{}) - - ctx.Set(string(BearerAuthScopes), []string{}) - - // Invoke the callback with all the unmarshaled arguments - err = w.Handler.PostNodeAction(ctx, nodeId) - return err -} - // GetNodeAlerts converts echo context to params. func (w *ServerInterfaceWrapper) GetNodeAlerts(ctx echo.Context) error { var err error @@ -6212,26 +6199,6 @@ func (w *ServerInterfaceWrapper) PostService(ctx echo.Context) error { return err } -// PostServiceAction converts echo context to params. -func (w *ServerInterfaceWrapper) PostServiceAction(ctx echo.Context) error { - var err error - // ------------- Path parameter "svc_id" ------------- - var svcId string - - err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter svc_id: %s", err)) - } - - ctx.Set(string(BasicAuthScopes), []string{}) - - ctx.Set(string(BearerAuthScopes), []string{}) - - // Invoke the callback with all the unmarshaled arguments - err = w.Handler.PostServiceAction(ctx, svcId) - return err -} - // GetServiceAlerts converts echo context to params. func (w *ServerInterfaceWrapper) GetServiceAlerts(ctx echo.Context) error { var err error @@ -7238,34 +7205,6 @@ func (w *ServerInterfaceWrapper) GetServiceInstance(ctx echo.Context) error { return err } -// PostServiceInstanceAction converts echo context to params. -func (w *ServerInterfaceWrapper) PostServiceInstanceAction(ctx echo.Context) error { - var err error - // ------------- Path parameter "svc_id" ------------- - var svcId string - - err = runtime.BindStyledParameterWithOptions("simple", "svc_id", ctx.Param("svc_id"), &svcId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter svc_id: %s", err)) - } - - // ------------- Path parameter "node_id" ------------- - var nodeId InPathNodeId - - err = runtime.BindStyledParameterWithOptions("simple", "node_id", ctx.Param("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_id: %s", err)) - } - - ctx.Set(string(BasicAuthScopes), []string{}) - - ctx.Set(string(BearerAuthScopes), []string{}) - - // Invoke the callback with all the unmarshaled arguments - err = w.Handler.PostServiceInstanceAction(ctx, svcId, nodeId) - return err -} - // GetServiceNodes converts echo context to params. func (w *ServerInterfaceWrapper) GetServiceNodes(ctx echo.Context) error { var err error @@ -8952,6 +8891,7 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.GET(options.BaseURL+"/actions", wrapper.GetActions, options.OperationMiddlewares["GetActions"]...) router.POST(options.BaseURL+"/actions", wrapper.PostActions, options.OperationMiddlewares["PostActions"]...) + router.PUT(options.BaseURL+"/actions", wrapper.PutActions, options.OperationMiddlewares["PutActions"]...) router.DELETE(options.BaseURL+"/actions/:id", wrapper.DeleteAction, options.OperationMiddlewares["DeleteAction"]...) router.GET(options.BaseURL+"/actions/:id", wrapper.GetAction, options.OperationMiddlewares["GetAction"]...) router.GET(options.BaseURL+"/alert_event", wrapper.GetAlertEvent, options.OperationMiddlewares["GetAlertEvent"]...) @@ -9046,7 +8986,6 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.DELETE(options.BaseURL+"/nodes/:node_id", wrapper.DeleteNode, options.OperationMiddlewares["DeleteNode"]...) router.GET(options.BaseURL+"/nodes/:node_id", wrapper.GetNode, options.OperationMiddlewares["GetNode"]...) router.POST(options.BaseURL+"/nodes/:node_id", wrapper.PostNode, options.OperationMiddlewares["PostNode"]...) - router.POST(options.BaseURL+"/nodes/:node_id/actions", wrapper.PostNodeAction, options.OperationMiddlewares["PostNodeAction"]...) router.GET(options.BaseURL+"/nodes/:node_id/alerts", wrapper.GetNodeAlerts, options.OperationMiddlewares["GetNodeAlerts"]...) router.GET(options.BaseURL+"/nodes/:node_id/am_i_responsible", wrapper.GetNodeAmIResponsible, options.OperationMiddlewares["GetNodeAmIResponsible"]...) router.GET(options.BaseURL+"/nodes/:node_id/candidate_tags", wrapper.GetNodeCandidateTags, options.OperationMiddlewares["GetNodeCandidateTags"]...) @@ -9085,7 +9024,6 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.DELETE(options.BaseURL+"/services/:svc_id", wrapper.DeleteService, options.OperationMiddlewares["DeleteService"]...) router.GET(options.BaseURL+"/services/:svc_id", wrapper.GetService, options.OperationMiddlewares["GetService"]...) router.POST(options.BaseURL+"/services/:svc_id", wrapper.PostService, options.OperationMiddlewares["PostService"]...) - router.POST(options.BaseURL+"/services/:svc_id/actions", wrapper.PostServiceAction, options.OperationMiddlewares["PostServiceAction"]...) router.GET(options.BaseURL+"/services/:svc_id/alerts", wrapper.GetServiceAlerts, options.OperationMiddlewares["GetServiceAlerts"]...) router.GET(options.BaseURL+"/services/:svc_id/am_i_responsible", wrapper.GetServiceAmIResponsible, options.OperationMiddlewares["GetServiceAmIResponsible"]...) router.GET(options.BaseURL+"/services/:svc_id/candidate_tags", wrapper.GetServiceCandidateTags, options.OperationMiddlewares["GetServiceCandidateTags"]...) @@ -9103,7 +9041,6 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.GET(options.BaseURL+"/services/:svc_id/disks", wrapper.GetServiceDisks, options.OperationMiddlewares["GetServiceDisks"]...) router.DELETE(options.BaseURL+"/services/:svc_id/instances/:node_id", wrapper.DeleteServiceInstance, options.OperationMiddlewares["DeleteServiceInstance"]...) router.GET(options.BaseURL+"/services/:svc_id/instances/:node_id", wrapper.GetServiceInstance, options.OperationMiddlewares["GetServiceInstance"]...) - router.POST(options.BaseURL+"/services/:svc_id/instances/:node_id/actions", wrapper.PostServiceInstanceAction, options.OperationMiddlewares["PostServiceInstanceAction"]...) router.GET(options.BaseURL+"/services/:svc_id/nodes", wrapper.GetServiceNodes, options.OperationMiddlewares["GetServiceNodes"]...) router.GET(options.BaseURL+"/services/:svc_id/nodes/:node_id", wrapper.GetServiceNode, options.OperationMiddlewares["GetServiceNode"]...) router.GET(options.BaseURL+"/services/:svc_id/nodes/:node_id/resources", wrapper.GetServiceNodeResources, options.OperationMiddlewares["GetServiceNodeResources"]...) @@ -9149,271 +9086,270 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "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", - "DL59/Pa/AwAA//8=", + "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", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index 01607ff8..93aace64 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -266,94 +266,22 @@ func (e PostNodeJSONBodyActionType) Valid() bool { } } -// Defines values for PostNodeActionJSONBodyAction. -const ( - PostNodeActionJSONBodyActionChecks PostNodeActionJSONBodyAction = "checks" - PostNodeActionJSONBodyActionFreeze PostNodeActionJSONBodyAction = "freeze" - PostNodeActionJSONBodyActionPushasset PostNodeActionJSONBodyAction = "pushasset" - PostNodeActionJSONBodyActionPushdisks PostNodeActionJSONBodyAction = "pushdisks" - PostNodeActionJSONBodyActionPushpatch PostNodeActionJSONBodyAction = "pushpatch" - PostNodeActionJSONBodyActionPushpkg PostNodeActionJSONBodyAction = "pushpkg" - PostNodeActionJSONBodyActionPushstats PostNodeActionJSONBodyAction = "pushstats" - PostNodeActionJSONBodyActionScanscsi PostNodeActionJSONBodyAction = "scanscsi" - PostNodeActionJSONBodyActionSysreport PostNodeActionJSONBodyAction = "sysreport" - PostNodeActionJSONBodyActionThaw PostNodeActionJSONBodyAction = "thaw" -) - -// Valid indicates whether the value is a known member of the PostNodeActionJSONBodyAction enum. -func (e PostNodeActionJSONBodyAction) Valid() bool { - switch e { - case PostNodeActionJSONBodyActionChecks: - return true - case PostNodeActionJSONBodyActionFreeze: - return true - case PostNodeActionJSONBodyActionPushasset: - return true - case PostNodeActionJSONBodyActionPushdisks: - return true - case PostNodeActionJSONBodyActionPushpatch: - return true - case PostNodeActionJSONBodyActionPushpkg: - return true - case PostNodeActionJSONBodyActionPushstats: - return true - case PostNodeActionJSONBodyActionScanscsi: - return true - case PostNodeActionJSONBodyActionSysreport: - return true - case PostNodeActionJSONBodyActionThaw: - return true - default: - return false - } -} +// ActionEnqueue One action to enqueue with PUT /actions. +type ActionEnqueue struct { + // Action Agent action to run + Action string `json:"action"` -// Defines values for PostServiceActionJSONBodyAction. -const ( - PostServiceActionJSONBodyActionFreeze PostServiceActionJSONBodyAction = "freeze" - PostServiceActionJSONBodyActionPushConfig PostServiceActionJSONBodyAction = "push config" - PostServiceActionJSONBodyActionPushResinfo PostServiceActionJSONBodyAction = "push resinfo" - PostServiceActionJSONBodyActionThaw PostServiceActionJSONBodyAction = "thaw" -) + // NodeId Target node (node_id or nodename) + NodeId *string `json:"node_id,omitempty"` -// Valid indicates whether the value is a known member of the PostServiceActionJSONBodyAction enum. -func (e PostServiceActionJSONBodyAction) Valid() bool { - switch e { - case PostServiceActionJSONBodyActionFreeze: - return true - case PostServiceActionJSONBodyActionPushConfig: - return true - case PostServiceActionJSONBodyActionPushResinfo: - return true - case PostServiceActionJSONBodyActionThaw: - return true - default: - return false - } -} + // Rid Resource ids to limit an instance action to, comma separated + Rid *string `json:"rid,omitempty"` -// Defines values for PostServiceInstanceActionJSONBodyAction. -const ( - Freeze PostServiceInstanceActionJSONBodyAction = "freeze" - PushConfig PostServiceInstanceActionJSONBodyAction = "push config" - PushResinfo PostServiceInstanceActionJSONBodyAction = "push resinfo" - Thaw PostServiceInstanceActionJSONBodyAction = "thaw" -) + // SvcId Target service (svc_id or svcname) + SvcId *string `json:"svc_id,omitempty"` -// Valid indicates whether the value is a known member of the PostServiceInstanceActionJSONBodyAction enum. -func (e PostServiceInstanceActionJSONBodyAction) Valid() bool { - switch e { - case Freeze: - return true - case PushConfig: - return true - case PushResinfo: - return true - case Thaw: - return true - default: - return false - } + // Vmname Target node by name, in place of node_id, for an encapsulated node + Vmname *string `json:"vmname,omitempty"` } // AlertListResponse defines model for AlertListResponse. @@ -1273,6 +1201,14 @@ type PostActionsJSONBody struct { Status *string `json:"status,omitempty"` } +// PutActionsJSONBody defines parameters for PutActions. +type PutActionsJSONBody struct { + union json.RawMessage +} + +// PutActionsJSONBody1 defines parameters for PutActions. +type PutActionsJSONBody1 = []ActionEnqueue + // GetActionParams defines parameters for GetAction. type GetActionParams struct { // Props A list of properties to include in each data dictionnary. @@ -2770,15 +2706,6 @@ type PostNodeJSONBody struct { // PostNodeJSONBodyActionType defines parameters for PostNode. type PostNodeJSONBodyActionType string -// PostNodeActionJSONBody defines parameters for PostNodeAction. -type PostNodeActionJSONBody struct { - // Action Action to queue - Action PostNodeActionJSONBodyAction `json:"action"` -} - -// PostNodeActionJSONBodyAction defines parameters for PostNodeAction. -type PostNodeActionJSONBodyAction string - // GetNodeAlertsParams defines parameters for GetNodeAlerts. type GetNodeAlertsParams struct { // Props A list of properties to include in each data dictionnary. @@ -3397,15 +3324,6 @@ type PostServiceJSONBody struct { Svcname *string `json:"svcname,omitempty"` } -// PostServiceActionJSONBody defines parameters for PostServiceAction. -type PostServiceActionJSONBody struct { - // Action Action to queue - Action PostServiceActionJSONBodyAction `json:"action"` -} - -// PostServiceActionJSONBodyAction defines parameters for PostServiceAction. -type PostServiceActionJSONBodyAction string - // GetServiceAlertsParams defines parameters for GetServiceAlerts. type GetServiceAlertsParams struct { // Props A list of properties to include in each data dictionnary. @@ -3703,15 +3621,6 @@ type GetServiceInstanceParams struct { Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` } -// PostServiceInstanceActionJSONBody defines parameters for PostServiceInstanceAction. -type PostServiceInstanceActionJSONBody struct { - // Action Action to queue - Action PostServiceInstanceActionJSONBodyAction `json:"action"` -} - -// PostServiceInstanceActionJSONBodyAction defines parameters for PostServiceInstanceAction. -type PostServiceInstanceActionJSONBodyAction string - // GetServiceNodesParams defines parameters for GetServiceNodes. type GetServiceNodesParams struct { // Props A list of properties to include in each data dictionnary. @@ -4287,6 +4196,9 @@ type PostUserPrefsJSONBody struct { // PostActionsJSONRequestBody defines body for PostActions for application/json ContentType. type PostActionsJSONRequestBody PostActionsJSONBody +// PutActionsJSONRequestBody defines body for PutActions for application/json ContentType. +type PutActionsJSONRequestBody PutActionsJSONBody + // DeleteAlertsJSONRequestBody defines body for DeleteAlerts for application/json ContentType. type DeleteAlertsJSONRequestBody DeleteAlertsJSONBody @@ -4395,9 +4307,6 @@ type PostNodesJSONRequestBody PostNodesJSONBody // PostNodeJSONRequestBody defines body for PostNode for application/json ContentType. type PostNodeJSONRequestBody PostNodeJSONBody -// PostNodeActionJSONRequestBody defines body for PostNodeAction for application/json ContentType. -type PostNodeActionJSONRequestBody PostNodeActionJSONBody - // PostNodeComplianceModulesetJSONRequestBody defines body for PostNodeComplianceModuleset for application/json ContentType. type PostNodeComplianceModulesetJSONRequestBody = PostNodeComplianceModulesetJSONBody @@ -4425,12 +4334,6 @@ type PostServicesJSONRequestBody PostServicesJSONBody // PostServiceJSONRequestBody defines body for PostService for application/json ContentType. type PostServiceJSONRequestBody PostServiceJSONBody -// PostServiceActionJSONRequestBody defines body for PostServiceAction for application/json ContentType. -type PostServiceActionJSONRequestBody PostServiceActionJSONBody - -// PostServiceInstanceActionJSONRequestBody defines body for PostServiceInstanceAction for application/json ContentType. -type PostServiceInstanceActionJSONRequestBody PostServiceInstanceActionJSONBody - // DeleteServicesInstancesJSONRequestBody defines body for DeleteServicesInstances for application/json ContentType. type DeleteServicesInstancesJSONRequestBody DeleteServicesInstancesJSONBody @@ -5520,3 +5423,65 @@ func (t *UserListResponse_Data) UnmarshalJSON(b []byte) error { err := t.union.UnmarshalJSON(b) return err } + +// AsActionEnqueue returns the union data inside the PutActionsJSONBody as a ActionEnqueue +func (t PutActionsJSONBody) AsActionEnqueue() (ActionEnqueue, error) { + var body ActionEnqueue + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromActionEnqueue overwrites any union data inside the PutActionsJSONBody as the provided ActionEnqueue +func (t *PutActionsJSONBody) FromActionEnqueue(v ActionEnqueue) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeActionEnqueue performs a merge with any union data inside the PutActionsJSONBody, using the provided ActionEnqueue +func (t *PutActionsJSONBody) MergeActionEnqueue(v ActionEnqueue) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsPutActionsJSONBody1 returns the union data inside the PutActionsJSONBody as a PutActionsJSONBody1 +func (t PutActionsJSONBody) AsPutActionsJSONBody1() (PutActionsJSONBody1, error) { + var body PutActionsJSONBody1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromPutActionsJSONBody1 overwrites any union data inside the PutActionsJSONBody as the provided PutActionsJSONBody1 +func (t *PutActionsJSONBody) FromPutActionsJSONBody1(v PutActionsJSONBody1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergePutActionsJSONBody1 performs a merge with any union data inside the PutActionsJSONBody, using the provided PutActionsJSONBody1 +func (t *PutActionsJSONBody) MergePutActionsJSONBody1(v PutActionsJSONBody1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t PutActionsJSONBody) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *PutActionsJSONBody) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} diff --git a/server/handlers/post_service_action.go b/server/handlers/post_service_action.go deleted file mode 100644 index 9fd525a9..00000000 --- a/server/handlers/post_service_action.go +++ /dev/null @@ -1,245 +0,0 @@ -package serverhandlers - -import ( - "context" - "log/slog" - "net/http" - "strconv" - "strings" - - "github.com/google/uuid" - "github.com/labstack/echo/v4" - - "github.com/opensvc/oc3/cdb" - "github.com/opensvc/oc3/server" - "github.com/opensvc/oc3/util/echolog" - "github.com/opensvc/oc3/util/logkey" -) - -// serviceActions are the agent actions the API accepts on a service or on one of -// its instances. As for nodes, only what does not interrupt the service is exposed: -// start, stop, restart, switch, giveback, takeover, the sync and provisioning -// actions are deliberately left out for now. -var serviceActions = map[string]bool{ - "push resinfo": true, - "push config": true, - "freeze": true, - "thaw": true, -} - -// agentAtLeast19 reports whether the agent understands --local, as the python -// collector decides it from the leading digits of the reported version. -func agentAtLeast19(version string) bool { - if len(version) < 3 { - return false - } - v, err := strconv.ParseFloat(version[:3], 64) - if err != nil { - return false - } - return v >= 1.9 -} - -// serviceActionCommand builds the queued command, as fmt_svc_action() does. A pull -// or feed node reads the bare action from its queue; a push node is reached over -// ssh. `local` restricts the action to that one instance. -func serviceActionCommand(action, svcname, actionType, connectTo, agentVersion string, local bool) string { - var cmd []string - if actionType != "pull" && actionType != "feed" { - cmd = append(cmd, sshCmd...) - cmd = append(cmd, "opensvc@"+connectTo, "--", "sudo", "svcmgr", "--service", svcname) - } - cmd = append(cmd, action) - if local && agentAtLeast19(agentVersion) { - cmd = append(cmd, "--local") - } - return strings.Join(cmd, " ") -} - -// queueServiceAction is the part shared by the service and the instance endpoints. -func (a *Api) queueServiceAction( - c echo.Context, log *slog.Logger, ctx context.Context, - svc *cdb.DBService, target *cdb.NodeActionTarget, agentVersion, action string, local bool, -) error { - odb := a.ODB - - // A node feeding another collector queues its actions there; oc3 has no such - // push channel, so the caller is told rather than left with a dead entry. - if target.Collector != "" { - return JSONProblemf(c, http.StatusBadRequest, - "node %s is attached to collector %s: queue the action there", target.Nodename, target.Collector) - } - - connectTo, err := odb.NodeReachableAddress(ctx, target) - if err != nil { - log.Error("cannot find a reachable address", logkey.Error, err) - return JSONProblemf(c, http.StatusInternalServerError, "cannot find an address for node %s", target.Nodename) - } - - // An unset action_type means pull, as get_action_type() does. - actionType := target.ActionType - if actionType == "" { - actionType = "pull" - } - command := serviceActionCommand(action, svc.Svcname, actionType, connectTo, agentVersion, local) - - id, err := odb.EnqueueServiceAction(ctx, target.NodeID, svc.SvcID, actionType, command, connectTo, authUserID(c)) - if err != nil { - log.Error("cannot queue the action", logkey.Error, err) - return JSONProblemf(c, http.StatusInternalServerError, "cannot queue action %s", action) - } - - log.Info("action queued", "svc_id", svc.SvcID, logkey.NodeID, target.NodeID, "action", action, "action_id", id) - - userEmail, _ := c.Get(XUserEmail).(string) - logEntry := cdb.LogEntry{ - Action: "service.action", - User: userEmail, - Fmt: "run %(action)s", - Dict: map[string]any{"action": action}, - Level: "info", - } - if parsed, parseErr := uuid.Parse(svc.SvcID); parseErr == nil { - logEntry.SvcID = &parsed - } - if parsed, parseErr := uuid.Parse(target.NodeID); parseErr == nil { - logEntry.NodeID = &parsed - } - if logErr := odb.Log(ctx, logEntry); logErr != nil { - log.Error("cannot write audit log", logkey.Error, logErr) - } - - if err := odb.Session.NotifyChanges(ctx); err != nil { - log.Error("cannot notify changes", logkey.Error, err) - } - - return c.JSON(http.StatusOK, map[string]any{ - "id": id, - "command": command, - "node_id": target.NodeID, - "info": "action " + action + " queued on service " + svc.Svcname + " from node " + target.Nodename, - }) -} - -// checkServiceAction validates the body and the caller rights shared by both endpoints. -func (a *Api) checkServiceAction(c echo.Context, log *slog.Logger, ctx context.Context, svcId, action string) (*cdb.DBService, error) { - if !serviceActions[action] { - return nil, denyRequest(c, http.StatusBadRequest, "unsupported action %q", action) - } - if !IsManager(c) && !HasGroup(c, "NodeExec") { - return nil, denyRequest(c, http.StatusForbidden, "user has no NodeExec privilege") - } - - svc, err := a.resolveServiceRow(c, log, ctx, svcId) - if err != nil { - return nil, err - } - - responsible, err := a.ODB.ServiceResponsible(ctx, svc.SvcID, UserGroupsFromContext(c), IsManager(c)) - if err != nil { - log.Error("cannot check service responsibility", logkey.Error, err) - return nil, denyRequest(c, http.StatusInternalServerError, "cannot check service responsibility") - } - if !responsible { - return nil, denyRequest(c, http.StatusForbidden, "user is not responsible for service %s", svcId) - } - return svc, nil -} - -// PostServiceAction handles POST /services/{svc_id}/actions: queue an action on the -// whole service, from one of its live nodes. -func (a *Api) PostServiceAction(c echo.Context, svcId string) error { - log := echolog.GetLogHandler(c, "PostServiceAction") - ctx, cancel := context.WithTimeout(c.Request().Context(), a.SyncTimeout) - defer cancel() - - var body server.PostServiceActionJSONRequestBody - if err := c.Bind(&body); err != nil { - log.Error("invalid request body", logkey.Error, err) - return JSONProblem(c, http.StatusBadRequest, err.Error()) - } - action := string(body.Action) - - svc, err := a.checkServiceAction(c, log, ctx, svcId, action) - if err != nil { - return err - } - - target, agentVersion, err := a.ODB.ServiceLiveNode(ctx, svc.SvcID) - if err != nil { - log.Error("cannot look for a live node", logkey.Error, err) - return JSONProblemf(c, http.StatusInternalServerError, "cannot look for a live node of service %s", svcId) - } - if target == nil { - return JSONProblemf(c, http.StatusConflict, - "no node of service %s has been seen in the last 15 minutes", svc.Svcname) - } - - // The action is for the service as a whole: no --local, as do_svc_action does. - return a.queueServiceAction(c, log, ctx, svc, target, agentVersion, action, false) -} - -// PostServiceInstanceAction handles POST /services/{svc_id}/instances/{node_id}/actions: -// queue an action on one instance, acting on that node only. -func (a *Api) PostServiceInstanceAction(c echo.Context, svcId string, nodeId server.InPathNodeId) error { - log := echolog.GetLogHandler(c, "PostServiceInstanceAction") - odb := a.ODB - ctx, cancel := context.WithTimeout(c.Request().Context(), a.SyncTimeout) - defer cancel() - - var body server.PostServiceInstanceActionJSONRequestBody - if err := c.Bind(&body); err != nil { - log.Error("invalid request body", logkey.Error, err) - return JSONProblem(c, http.StatusBadRequest, err.Error()) - } - action := string(body.Action) - - svc, err := a.checkServiceAction(c, log, ctx, svcId, action) - if err != nil { - return err - } - - node, err := odb.NodeByNodeIDOrNodename(ctx, string(nodeId)) - if err != nil { - log.Error("cannot lookup node", logkey.Error, err) - return JSONProblemf(c, http.StatusInternalServerError, "cannot lookup node") - } - if node == nil { - return JSONProblemf(c, http.StatusNotFound, "node %s not found", nodeId) - } - - responsible, err := odb.NodeResponsible(ctx, node.NodeID, UserGroupsFromContext(c), IsManager(c)) - if err != nil { - log.Error("cannot check node responsibility", logkey.Error, err) - return JSONProblemf(c, http.StatusInternalServerError, "cannot check node responsibility") - } - if !responsible { - return JSONProblemf(c, http.StatusForbidden, "user is not responsible for node %s", nodeId) - } - - found, err := odb.HasServiceInstance(ctx, svc.SvcID, node.NodeID) - if err != nil { - log.Error("cannot check the instance", logkey.Error, err) - return JSONProblemf(c, http.StatusInternalServerError, "cannot check instance %s@%s", svcId, nodeId) - } - if !found { - return JSONProblemf(c, http.StatusNotFound, "service %s has no instance on node %s", svc.Svcname, node.NodeID) - } - - target, err := odb.NodeActionTargetByID(ctx, node.NodeID) - if err != nil { - log.Error("cannot read node action fields", logkey.Error, err) - return JSONProblemf(c, http.StatusInternalServerError, "cannot read node %s", nodeId) - } - if target == nil { - return JSONProblemf(c, http.StatusNotFound, "node %s not found", nodeId) - } - - agentVersion, err := odb.NodeAgentVersion(ctx, node.NodeID) - if err != nil { - log.Error("cannot read the agent version", logkey.Error, err) - return JSONProblemf(c, http.StatusInternalServerError, "cannot read node %s", nodeId) - } - - return a.queueServiceAction(c, log, ctx, svc, target, agentVersion, action, true) -} diff --git a/server/handlers/put_actions.go b/server/handlers/put_actions.go new file mode 100644 index 00000000..2f29b164 --- /dev/null +++ b/server/handlers/put_actions.go @@ -0,0 +1,229 @@ +package serverhandlers + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "log/slog" + "net/http" + "strconv" + "strings" + + "github.com/labstack/echo/v4" + + "github.com/opensvc/oc3/cdb" + "github.com/opensvc/oc3/util/echolog" + "github.com/opensvc/oc3/util/logkey" +) + +// actionEntry is one action to enqueue, with the fields of the historical +// collector's PUT /actions (rest_put_action_queue). The keys it does not support +// are kept to be refused rather than silently dropped. +type actionEntry struct { + NodeID string `json:"node_id"` + SvcID string `json:"svc_id"` + Action string `json:"action"` + Rid string `json:"rid"` + VMName string `json:"vmname"` + + unsupported []string +} + +// unsupportedActionKeys are accepted by the historical collector but not ported: +// compliance runs and agent options. +var unsupportedActionKeys = []string{"module", "moduleset", "ruleset", "options"} + +func (e *actionEntry) UnmarshalJSON(data []byte) error { + type plain actionEntry + var fields plain + if err := json.Unmarshal(data, &fields); err != nil { + return err + } + var raw map[string]json.RawMessage + if err := json.Unmarshal(data, &raw); err != nil { + return err + } + *e = actionEntry(fields) + for _, key := range unsupportedActionKeys { + if _, ok := raw[key]; ok { + e.unsupported = append(e.unsupported, key) + } + } + return nil +} + +// queueActionEntry dispatches one entry as json_action_one() does: node and +// service make an instance action, a service alone a service action, a node alone +// a node action. vmname names the node in place of node_id. +func (a *Api) queueActionEntry(c echo.Context, log *slog.Logger, ctx context.Context, e actionEntry) (*queuedAction, error) { + if len(e.unsupported) > 0 { + return nil, refuseAction(http.StatusBadRequest, "unsupported keys: %s", strings.Join(e.unsupported, ", ")) + } + if e.Action == "" { + return nil, refuseAction(http.StatusBadRequest, "no action specified") + } + nodeID := e.NodeID + if e.VMName != "" { + nodeID = e.VMName + } + switch { + case e.SvcID != "" && nodeID != "": + return a.queueInstanceAction(c, log, ctx, nodeID, e.SvcID, e.Action, e.Rid) + case e.Rid != "": + return nil, refuseAction(http.StatusBadRequest, "rid requires both node_id and svc_id") + case nodeID != "": + return a.queueNodeAction(c, log, ctx, nodeID, e.Action) + case e.SvcID != "": + return a.queueServiceAction(c, log, ctx, e.SvcID, e.Action) + } + return nil, refuseAction(http.StatusBadRequest, "node_id or svc_id must be specified") +} + +// factorizeActionEntries merges the entries that target the same resources of an +// instance with the same action into one action on all of them, as +// factorize_actions() does: selecting three resources queues one agent run. +func factorizeActionEntries(entries []actionEntry) []actionEntry { + type key struct{ svcID, nodeID, action string } + var out []actionEntry + var order []key + rids := map[key][]string{} + for _, e := range entries { + nodeID := e.NodeID + if e.VMName != "" { + nodeID = e.VMName + } + if e.Rid == "" || e.SvcID == "" || nodeID == "" || len(e.unsupported) > 0 { + out = append(out, e) + continue + } + k := key{e.SvcID, nodeID, e.Action} + if _, seen := rids[k]; !seen { + order = append(order, k) + } + rids[k] = append(rids[k], e.Rid) + } + for _, k := range order { + out = append(out, actionEntry{NodeID: k.nodeID, SvcID: k.svcID, Action: k.action, Rid: strings.Join(rids[k], ",")}) + } + return out +} + +// queuedActionRows reads back the queued actions, with the default props of +// GET /actions/{id}. The caller has just created them: they are read without the +// node responsibility filter of the action list, which would hide an instance +// action queued on a node the caller is not responsible for. +func (a *Api) queuedActionRows(ctx context.Context, ids []int64) ([]map[string]any, ListQueryParameters, error) { + mapping := propsMapping["action_queue"] + query, err := buildListQueryParameters(nil, nil, nil, nil, nil, nil, nil, mapping) + if err != nil { + return nil, query, err + } + selectExprs, err := buildSelectClause(query.Props, mapping) + if err != nil { + return nil, query, err + } + rows := []map[string]any{} + for _, id := range ids { + items, err := a.ODB.GetActionOne(ctx, strconv.FormatInt(id, 10), cdb.ListParams{ + IsManager: true, + Limit: 1, + Props: query.Props, + SelectExprs: selectExprs, + TypeHints: buildTypeHints(query.Props, mapping), + }) + if err != nil { + return nil, query, err + } + rows = append(rows, items...) + } + return rows, query, nil +} + +// PutActions handles PUT /actions: enqueue agent actions, as the historical +// collector's REST API and action menu do. +func (a *Api) PutActions(c echo.Context) error { + log := echolog.GetLogHandler(c, "PutActions") + ctx, cancel := context.WithTimeout(c.Request().Context(), a.SyncTimeout) + defer cancel() + + if !IsAuthByUser(c) { + return JSONProblemf(c, http.StatusUnauthorized, "user authentication required") + } + + var raw json.RawMessage + if err := json.NewDecoder(c.Request().Body).Decode(&raw); err != nil { + return JSONProblem(c, http.StatusBadRequest, err.Error()) + } + + // A list: every entry is tried, and the answer collects what was queued and + // what was refused, as the historical handle_list() does. + if trimmed := bytes.TrimSpace(raw); len(trimmed) > 0 && trimmed[0] == '[' { + var entries []actionEntry + if err := json.Unmarshal(raw, &entries); err != nil { + return JSONProblem(c, http.StatusBadRequest, err.Error()) + } + var ids []int64 + refusals := []string{} + for _, e := range factorizeActionEntries(entries) { + queued, err := a.queueActionEntry(c, log, ctx, e) + if err != nil { + refusals = append(refusals, describeRefusal(e, err)) + continue + } + ids = append(ids, queued.ID) + } + if len(ids) > 0 { + if err := a.ODB.Session.NotifyChanges(ctx); err != nil { + log.Error("cannot notify changes", logkey.Error, err) + } + } + rows, _, err := a.queuedActionRows(ctx, ids) + if err != nil { + log.Error("cannot read the queued actions", logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "actions queued, but cannot read them back") + } + return c.JSON(http.StatusOK, map[string]any{ + "info": []string{fmt.Sprintf("%d action(s) queued", len(ids))}, + "error": refusals, + "data": rows, + }) + } + + var entry actionEntry + if err := json.Unmarshal(raw, &entry); err != nil { + return JSONProblem(c, http.StatusBadRequest, err.Error()) + } + queued, err := a.queueActionEntry(c, log, ctx, entry) + if err != nil { + return actionProblem(c, err) + } + if err := a.ODB.Session.NotifyChanges(ctx); err != nil { + log.Error("cannot notify changes", logkey.Error, err) + } + rows, query, err := a.queuedActionRows(ctx, []int64{queued.ID}) + if err != nil { + log.Error("cannot read the queued action", "action_id", queued.ID, logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "action %d queued, but cannot read it back", queued.ID) + } + return c.JSON(http.StatusOK, newListResponse(rows, propsMapping["action_queue"], query)) +} + +// describeRefusal names the refused entry in the message of a list answer. +func describeRefusal(e actionEntry, err error) string { + var target []string + for _, part := range []struct{ key, value string }{ + {"node_id", e.NodeID}, {"vmname", e.VMName}, {"svc_id", e.SvcID}, {"rid", e.Rid}, + } { + if part.value != "" { + target = append(target, part.key+"="+part.value) + } + } + msg := err.Error() + var refusal *actionRefusal + if errors.As(err, &refusal) { + msg = fmt.Sprintf("%d: %s", refusal.status, refusal.msg) + } + return fmt.Sprintf("%s on %s: %s", e.Action, strings.Join(target, " "), msg) +} diff --git a/server/handlers/post_node_action.go b/server/handlers/queue_node_action.go similarity index 55% rename from server/handlers/post_node_action.go rename to server/handlers/queue_node_action.go index 09e836ff..f3e8f5e8 100644 --- a/server/handlers/post_node_action.go +++ b/server/handlers/queue_node_action.go @@ -2,6 +2,9 @@ package serverhandlers import ( "context" + "errors" + "fmt" + "log/slog" "net/http" "strings" @@ -9,8 +12,6 @@ import ( "github.com/labstack/echo/v4" "github.com/opensvc/oc3/cdb" - "github.com/opensvc/oc3/server" - "github.com/opensvc/oc3/util/echolog" "github.com/opensvc/oc3/util/logkey" ) @@ -56,78 +57,104 @@ func nodeActionCommand(action, actionType, connectTo string) string { return strings.Join(cmd, " ") } -// PostNodeAction handles POST /nodes/{node_id}/actions: queue an agent action. -func (a *Api) PostNodeAction(c echo.Context, nodeId server.InPathNodeId) error { - log := echolog.GetLogHandler(c, "PostNodeAction") - odb := a.ODB - ctx, cancel := context.WithTimeout(c.Request().Context(), a.SyncTimeout) - defer cancel() +// queuedAction is an action posted to the action queue. +type queuedAction struct { + ID int64 + Command string + NodeID string + Info string +} + +// actionRefusal is a queueing request that did not go through, with the HTTP +// status that says why. Internal failures are logged where they happen and +// refused with a 500 and a generic message. +type actionRefusal struct { + status int + msg string +} + +func (e *actionRefusal) Error() string { return e.msg } - var body server.PostNodeActionJSONRequestBody - if err := c.Bind(&body); err != nil { - log.Error("invalid request body", logkey.Error, err) - return JSONProblem(c, http.StatusBadRequest, err.Error()) +func refuseAction(status int, format string, args ...any) error { + return &actionRefusal{status: status, msg: fmt.Sprintf(format, args...)} +} + +// actionProblem writes the problem response of a refused queueing request. +func actionProblem(c echo.Context, err error) error { + var refusal *actionRefusal + if errors.As(err, &refusal) { + return JSONProblem(c, refusal.status, refusal.msg) } - action := string(body.Action) - if !nodeActions[action] { - return JSONProblemf(c, http.StatusBadRequest, "unsupported action %q", action) + return JSONProblem(c, http.StatusInternalServerError, err.Error()) +} + +// actionTypeOf returns how the node reads its queue; an unset action_type means +// pull, as get_action_type() does. +func actionTypeOf(target *cdb.NodeActionTarget) string { + if target.ActionType == "" { + return "pull" } + return target.ActionType +} +// queueNodeAction queues an agent action on a node, as do_node_action() does: +// NodeExec privilege, responsibility for the node, and a command run by nodemgr. +func (a *Api) queueNodeAction(c echo.Context, log *slog.Logger, ctx context.Context, nodeID, action string) (*queuedAction, error) { + odb := a.ODB + if !nodeActions[action] { + return nil, refuseAction(http.StatusBadRequest, "unsupported action %q", action) + } if !IsManager(c) && !HasGroup(c, "NodeExec") { - return JSONProblemf(c, http.StatusForbidden, "user has no NodeExec privilege") + return nil, refuseAction(http.StatusForbidden, "user has no NodeExec privilege") } - node, err := odb.NodeByNodeIDOrNodename(ctx, string(nodeId)) + node, err := odb.NodeByNodeIDOrNodename(ctx, nodeID) if err != nil { log.Error("cannot lookup node", logkey.Error, err) - return JSONProblemf(c, http.StatusInternalServerError, "cannot lookup node") + return nil, refuseAction(http.StatusInternalServerError, "cannot lookup node") } if node == nil { - return JSONProblemf(c, http.StatusNotFound, "node %s not found", nodeId) + return nil, refuseAction(http.StatusNotFound, "node %s not found", nodeID) } responsible, err := odb.NodeResponsible(ctx, node.NodeID, UserGroupsFromContext(c), IsManager(c)) if err != nil { log.Error("cannot check node responsibility", logkey.Error, err) - return JSONProblemf(c, http.StatusInternalServerError, "cannot check node responsibility") + return nil, refuseAction(http.StatusInternalServerError, "cannot check node responsibility") } if !responsible { - return JSONProblemf(c, http.StatusForbidden, "user is not responsible for node %s", nodeId) + return nil, refuseAction(http.StatusForbidden, "user is not responsible for node %s", nodeID) } target, err := odb.NodeActionTargetByID(ctx, node.NodeID) if err != nil { log.Error("cannot read node action fields", logkey.Error, err) - return JSONProblemf(c, http.StatusInternalServerError, "cannot read node %s", nodeId) + return nil, refuseAction(http.StatusInternalServerError, "cannot read node %s", nodeID) } if target == nil { - return JSONProblemf(c, http.StatusNotFound, "node %s not found", nodeId) + return nil, refuseAction(http.StatusNotFound, "node %s not found", nodeID) } // A node feeding another collector queues its actions there; oc3 has no such // push channel, so the caller is told rather than left with a dead entry. if target.Collector != "" { - return JSONProblemf(c, http.StatusBadRequest, + return nil, refuseAction(http.StatusBadRequest, "node %s is attached to collector %s: queue the action there", target.Nodename, target.Collector) } connectTo, err := odb.NodeReachableAddress(ctx, target) if err != nil { log.Error("cannot find a reachable address", logkey.Error, err) - return JSONProblemf(c, http.StatusInternalServerError, "cannot find an address for node %s", nodeId) + return nil, refuseAction(http.StatusInternalServerError, "cannot find an address for node %s", nodeID) } - // An unset action_type means pull, as get_action_type() does. - actionType := target.ActionType - if actionType == "" { - actionType = "pull" - } + actionType := actionTypeOf(target) command := nodeActionCommand(action, actionType, connectTo) // Who asked, as the python collector records it: the queue keeps the caller. id, err := odb.EnqueueNodeAction(ctx, node.NodeID, actionType, command, connectTo, authUserID(c)) if err != nil { log.Error("cannot queue the action", logkey.Error, err) - return JSONProblemf(c, http.StatusInternalServerError, "cannot queue action %s", action) + return nil, refuseAction(http.StatusInternalServerError, "cannot queue action %s", action) } log.Info("action queued", logkey.NodeID, node.NodeID, "action", action, "action_id", id) @@ -147,13 +174,10 @@ func (a *Api) PostNodeAction(c echo.Context, nodeId server.InPathNodeId) error { log.Error("cannot write audit log", logkey.Error, logErr) } - if err := odb.Session.NotifyChanges(ctx); err != nil { - log.Error("cannot notify changes", logkey.Error, err) - } - - return c.JSON(http.StatusOK, map[string]any{ - "id": id, - "command": command, - "info": "action " + action + " queued on node " + target.Nodename, - }) + return &queuedAction{ + ID: id, + Command: command, + NodeID: node.NodeID, + Info: "action " + action + " queued on node " + target.Nodename, + }, nil } diff --git a/server/handlers/queue_service_action.go b/server/handlers/queue_service_action.go new file mode 100644 index 00000000..d72df3b3 --- /dev/null +++ b/server/handlers/queue_service_action.go @@ -0,0 +1,228 @@ +package serverhandlers + +import ( + "context" + "log/slog" + "net/http" + "regexp" + "strconv" + "strings" + + "github.com/google/uuid" + "github.com/labstack/echo/v4" + + "github.com/opensvc/oc3/cdb" + "github.com/opensvc/oc3/util/logkey" +) + +// serviceActions are the agent actions the API accepts on a service or on one of +// its instances. As for nodes, only what does not interrupt the service is exposed: +// start, stop, restart, switch, giveback, takeover, the sync and provisioning +// actions are deliberately left out for now. +var serviceActions = map[string]bool{ + "push resinfo": true, + "push config": true, + "freeze": true, + "thaw": true, +} + +// ridPattern bounds a resource id list ("fs#1,ip#0"): the command reaches a push +// node through a remote shell, where anything else could be interpreted. +var ridPattern = regexp.MustCompile(`^[A-Za-z0-9_#.:,-]+$`) + +// agentAtLeast19 reports whether the agent understands --local, as the python +// collector decides it from the leading digits of the reported version. The om3 +// agent reports "v3.0.0-...", whose leading "v" the python collector could not +// read: it then left --local out, and an instance freeze froze the whole object. +// The prefix is skipped here, om3 accepting --local on these actions. +func agentAtLeast19(version string) bool { + version = strings.TrimPrefix(strings.TrimPrefix(version, "v"), "V") + if len(version) < 3 { + return false + } + v, err := strconv.ParseFloat(version[:3], 64) + if err != nil { + return false + } + return v >= 1.9 +} + +// serviceActionCommand builds the queued command, as fmt_svc_action() does. A pull +// or feed node reads the bare action from its queue; a push node is reached over +// ssh. A resource id limits the action to those resources; otherwise `local` +// restricts it to the instance of that node, except for the actions that only +// make sense cluster-wide. +func serviceActionCommand(action, svcname, actionType, connectTo, agentVersion, rid string, local bool) string { + var cmd []string + if actionType != "pull" && actionType != "feed" { + cmd = append(cmd, sshCmd...) + cmd = append(cmd, "opensvc@"+connectTo, "--", "sudo", "svcmgr", "--service", svcname) + } + cmd = append(cmd, action) + switch { + case rid != "": + cmd = append(cmd, "--rid", rid) + case local && agentAtLeast19(agentVersion) && action != "create" && action != "takeover" && action != "switch": + cmd = append(cmd, "--local") + } + return strings.Join(cmd, " ") +} + +// enqueueServiceCommand is the part shared by service and instance actions: build +// the command for the target node and post it to the queue, as enqueue_svc_action() +// does, then write the audit log entry. +func (a *Api) enqueueServiceCommand( + c echo.Context, log *slog.Logger, ctx context.Context, + svc *cdb.DBService, target *cdb.NodeActionTarget, agentVersion, action, rid string, local bool, +) (*queuedAction, error) { + odb := a.ODB + + // A node feeding another collector queues its actions there; oc3 has no such + // push channel, so the caller is told rather than left with a dead entry. + if target.Collector != "" { + return nil, refuseAction(http.StatusBadRequest, + "node %s is attached to collector %s: queue the action there", target.Nodename, target.Collector) + } + + connectTo, err := odb.NodeReachableAddress(ctx, target) + if err != nil { + log.Error("cannot find a reachable address", logkey.Error, err) + return nil, refuseAction(http.StatusInternalServerError, "cannot find an address for node %s", target.Nodename) + } + + actionType := actionTypeOf(target) + command := serviceActionCommand(action, svc.Svcname, actionType, connectTo, agentVersion, rid, local) + + id, err := odb.EnqueueServiceAction(ctx, target.NodeID, svc.SvcID, actionType, command, connectTo, authUserID(c)) + if err != nil { + log.Error("cannot queue the action", logkey.Error, err) + return nil, refuseAction(http.StatusInternalServerError, "cannot queue action %s", action) + } + + log.Info("action queued", "svc_id", svc.SvcID, logkey.NodeID, target.NodeID, "action", action, "rid", rid, "action_id", id) + + userEmail, _ := c.Get(XUserEmail).(string) + logEntry := cdb.LogEntry{ + Action: "service.action", + User: userEmail, + Fmt: "run %(action)s", + Dict: map[string]any{"action": action}, + Level: "info", + } + if rid != "" { + logEntry.Action = "service.resource.action" + logEntry.Fmt = "run %(action)s on rid %(rid)s" + logEntry.Dict["rid"] = rid + } + if parsed, parseErr := uuid.Parse(svc.SvcID); parseErr == nil { + logEntry.SvcID = &parsed + } + if parsed, parseErr := uuid.Parse(target.NodeID); parseErr == nil { + logEntry.NodeID = &parsed + } + if logErr := odb.Log(ctx, logEntry); logErr != nil { + log.Error("cannot write audit log", logkey.Error, logErr) + } + + return &queuedAction{ + ID: id, + Command: command, + NodeID: target.NodeID, + Info: "action " + action + " queued on service " + svc.Svcname + " from node " + target.Nodename, + }, nil +} + +// checkServiceAction validates the action and the caller rights shared by service +// and instance actions: NodeExec privilege and responsibility for the service. +func (a *Api) checkServiceAction(c echo.Context, log *slog.Logger, ctx context.Context, svcID, action string) (*cdb.DBService, error) { + if !serviceActions[action] { + return nil, refuseAction(http.StatusBadRequest, "unsupported action %q", action) + } + if !IsManager(c) && !HasGroup(c, "NodeExec") { + return nil, refuseAction(http.StatusForbidden, "user has no NodeExec privilege") + } + if svcID == "" { + return nil, refuseAction(http.StatusBadRequest, "invalid svc_id: ''") + } + + svc, err := a.ODB.ServiceBySvcIDOrName(ctx, svcID) + if err != nil { + log.Error("cannot resolve service", "svc_id", svcID, logkey.Error, err) + return nil, refuseAction(http.StatusInternalServerError, "cannot resolve service %s", svcID) + } + if svc == nil { + return nil, refuseAction(http.StatusNotFound, "service %s not found", svcID) + } + + responsible, err := a.ODB.ServiceResponsible(ctx, svc.SvcID, UserGroupsFromContext(c), IsManager(c)) + if err != nil { + log.Error("cannot check service responsibility", logkey.Error, err) + return nil, refuseAction(http.StatusInternalServerError, "cannot check service responsibility") + } + if !responsible { + return nil, refuseAction(http.StatusForbidden, "user is not responsible for service %s", svcID) + } + return svc, nil +} + +// queueServiceAction queues an action on a whole service, as do_svc_action() +// does: posted for a node of the service seen alive in the last 15 minutes, +// without --local. +func (a *Api) queueServiceAction(c echo.Context, log *slog.Logger, ctx context.Context, svcID, action string) (*queuedAction, error) { + svc, err := a.checkServiceAction(c, log, ctx, svcID, action) + if err != nil { + return nil, err + } + + target, agentVersion, err := a.ODB.ServiceLiveNode(ctx, svc.SvcID) + if err != nil { + log.Error("cannot look for a live node", logkey.Error, err) + return nil, refuseAction(http.StatusInternalServerError, "cannot look for a live node of service %s", svcID) + } + if target == nil { + return nil, refuseAction(http.StatusConflict, + "no node of service %s has been seen in the last 15 minutes", svc.Svcname) + } + + return a.enqueueServiceCommand(c, log, ctx, svc, target, agentVersion, action, "", false) +} + +// queueInstanceAction queues an action on the instance of a service on one node, +// as do_instance_action() does: NodeExec privilege and responsibility for the +// service; the node only has to exist. The action acts on that instance only +// (--local), or on the given resources (--rid). +func (a *Api) queueInstanceAction(c echo.Context, log *slog.Logger, ctx context.Context, nodeID, svcID, action, rid string) (*queuedAction, error) { + if rid != "" && !ridPattern.MatchString(rid) { + return nil, refuseAction(http.StatusBadRequest, "invalid rid %q", rid) + } + svc, err := a.checkServiceAction(c, log, ctx, svcID, action) + if err != nil { + return nil, err + } + + node, err := a.ODB.NodeByNodeIDOrNodename(ctx, nodeID) + if err != nil { + log.Error("cannot lookup node", logkey.Error, err) + return nil, refuseAction(http.StatusInternalServerError, "cannot lookup node") + } + if node == nil { + return nil, refuseAction(http.StatusNotFound, "node %s not found", nodeID) + } + + target, err := a.ODB.NodeActionTargetByID(ctx, node.NodeID) + if err != nil { + log.Error("cannot read node action fields", logkey.Error, err) + return nil, refuseAction(http.StatusInternalServerError, "cannot read node %s", nodeID) + } + if target == nil { + return nil, refuseAction(http.StatusNotFound, "node %s not found", nodeID) + } + + agentVersion, err := a.ODB.NodeAgentVersion(ctx, node.NodeID) + if err != nil { + log.Error("cannot read the agent version", logkey.Error, err) + return nil, refuseAction(http.StatusInternalServerError, "cannot read node %s", nodeID) + } + + return a.enqueueServiceCommand(c, log, ctx, svc, target, agentVersion, action, rid, true) +} diff --git a/server/handlers/queue_service_action_test.go b/server/handlers/queue_service_action_test.go new file mode 100644 index 00000000..ba35e78e --- /dev/null +++ b/server/handlers/queue_service_action_test.go @@ -0,0 +1,63 @@ +package serverhandlers + +import "testing" + +func TestServiceActionCommand(t *testing.T) { + cases := []struct { + name string + action, actionType, version, rid string + local bool + want string + }{ + {"instance, python agent", "freeze", "pull", "2.1-1234", "", true, "freeze --local"}, + {"instance, om3 agent", "freeze", "feed", "v3.0.0-rc40-2-g2b577", "", true, "freeze --local"}, + {"instance, old agent", "freeze", "pull", "1.8-100", "", true, "freeze"}, + {"instance, unknown version", "freeze", "pull", "", "", true, "freeze"}, + {"instance, cluster-wide action", "switch", "pull", "2.1", "", true, "switch"}, + {"instance, resources", "freeze", "pull", "2.1", "fs#1,ip#0", true, "freeze --rid fs#1,ip#0"}, + {"service", "freeze", "pull", "2.1", "", false, "freeze"}, + {"push node", "thaw", "push", "2.1", "", true, + "ssh -o StrictHostKeyChecking=no -o CheckHostIP=no -o ForwardX11=no -o ConnectTimeout=5 -o PasswordAuthentication=no opensvc@10.0.0.1 -- sudo svcmgr --service svc1 thaw --local"}, + } + for _, c := range cases { + got := serviceActionCommand(c.action, "svc1", c.actionType, "10.0.0.1", c.version, c.rid, c.local) + if got != c.want { + t.Errorf("%s: got %q, want %q", c.name, got, c.want) + } + } +} + +func TestFactorizeActionEntries(t *testing.T) { + entries := []actionEntry{ + {NodeID: "n1", SvcID: "s1", Action: "freeze", Rid: "fs#1"}, + {NodeID: "n1", Action: "pushasset"}, + {NodeID: "n1", SvcID: "s1", Action: "freeze", Rid: "ip#0"}, + {NodeID: "n2", SvcID: "s1", Action: "freeze", Rid: "fs#1"}, + } + got := factorizeActionEntries(entries) + if len(got) != 3 { + t.Fatalf("got %d entries, want 3: %+v", len(got), got) + } + if got[0].Action != "pushasset" { + t.Errorf("entries without rid come first, as factorize_actions() does: %+v", got) + } + if got[1].Rid != "fs#1,ip#0" || got[1].NodeID != "n1" { + t.Errorf("rids of the same instance and action are merged: %+v", got[1]) + } + if got[2].Rid != "fs#1" || got[2].NodeID != "n2" { + t.Errorf("another instance keeps its own entry: %+v", got[2]) + } +} + +func TestActionEntryUnsupportedKeys(t *testing.T) { + var e actionEntry + if err := e.UnmarshalJSON([]byte(`{"node_id":"n1","action":"compliance_check","module":"m1"}`)); err != nil { + t.Fatal(err) + } + if e.NodeID != "n1" || e.Action != "compliance_check" { + t.Errorf("known fields are read: %+v", e) + } + if len(e.unsupported) != 1 || e.unsupported[0] != "module" { + t.Errorf("module is kept to be refused: %+v", e.unsupported) + } +} From c27cbcf713cf2d9f824627af3847e015e279f3be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Thu, 24 Sep 2026 16:00:03 +0200 Subject: [PATCH 27/61] Return the total number of rows with paginated lists List endpoints fill meta.total whenever meta is requested, the default, as the historical collector did. The total comes from the page when it tells it (no limit, partial page, empty first page); otherwise the fetcher runs again with the same access control, filters and grouping, selecting COUNT(*) OVER () without sort for one row, so that a grouped list counts its groups. GET /alerts and GET /tags return it too. A failed count is logged and the total left out. --- cdb/db_tags.go | 9 + cdb/list_params.go | 9 + server/api.yaml | 10 +- server/codegen_server_gen.go | 504 ++++++++++++++-------------- server/codegen_type_gen.go | 456 ++++++++++++++++++++----- server/handlers/get_alerts.go | 11 +- server/handlers/get_tags.go | 14 +- server/handlers/handle_list.go | 58 +++- server/handlers/handle_list_test.go | 26 ++ server/handlers/list_response.go | 16 +- 10 files changed, 763 insertions(+), 350 deletions(-) create mode 100644 server/handlers/handle_list_test.go diff --git a/cdb/db_tags.go b/cdb/db_tags.go index af27d5b9..baa96c40 100644 --- a/cdb/db_tags.go +++ b/cdb/db_tags.go @@ -21,6 +21,15 @@ type Tag struct { } // GetTags returns all tags with id > 0, or a specific tag if tagID is provided +// CountTags returns the number of tags, for the total of the paginated tag list. +func (oDb *DB) CountTags(ctx context.Context) (int, error) { + var n int + if err := oDb.DB.QueryRowContext(ctx, "SELECT COUNT(*) FROM tags WHERE id > 0").Scan(&n); err != nil { + return 0, fmt.Errorf("countTags: %w", err) + } + return n, nil +} + func (oDb *DB) GetTags(ctx context.Context, tagID *int, limit, offset int) ([]Tag, error) { query := ` SELECT id, tag_name, tag_created, tag_exclude, tag_data, tag_id diff --git a/cdb/list_params.go b/cdb/list_params.go index 6c908f3a..891bb45c 100644 --- a/cdb/list_params.go +++ b/cdb/list_params.go @@ -37,6 +37,10 @@ type ListParams struct { // Filters are the column filters of the request, combined with AND. Filters []ColumnFilter + + // CountOnly asks for the query of a list without its sort: the rows are only + // counted, see OrderByClause. + CountOnly bool } // HasGroup reports whether the caller belongs to the named group. Use it for the @@ -51,6 +55,11 @@ func (p ListParams) HasGroup(role string) bool { } func (p ListParams) OrderByClause(defaultClause string) string { + if p.CountOnly { + // A count does not depend on the order of the rows: sorting them first + // would only cost. + return "" + } if len(p.OrderBy) == 0 { return "ORDER BY " + defaultClause } diff --git a/server/api.yaml b/server/api.yaml index 88f6e8c1..1786e29c 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -7604,6 +7604,10 @@ components: type: integer total: type: integer + description: | + Number of rows of the list without pagination, the filters applied; for + a grouped list, the number of groups. With stats, the number of rows the + statistics are computed from. NodeRow: type: object @@ -8917,7 +8921,11 @@ components: in: query name: meta required: false - description: Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + description: | + Include metadata in the response. Enabled by default. Use false or 0 to omit + the meta field. The metadata of a list carries its total number of rows + without pagination (total), as well as the rows returned (count), the offset + and the limit. schema: type: string diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index c9fa4d8d..63a77cc4 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -9099,257 +9099,259 @@ var swaggerSpec = []string{ "NGn9VynKYrzwEXue08cKjEQynwmJUEyq9TJQRAsyNY9bdgRVZpqMF+QhDKYD2zJe/IUWRV/NEzPnR4Oe", "fyWub68Td/7OcqY35/veyEH6meVl7r61mS1wLd1UJehS8gF5QnKgXJmvnJmhQpPCxpUppTChZaZ7x39+", "0u/ljJt39Y6f1JvLuIYpyOZk/wBNPULMsi/JQdOUalqxnQRVCK5gQF5yI1dSs53urQPyQQGZ0EyBIawn", - "ZkkiZ9oqANCUTBhkaWg1pke3/X0zmRixujHpd+fMfukJk0rXO+uYGZeRlFIJGZqCsAN7d7Tzhr6xcu6y", - "9KqENDQ6IG8lTNjndf4lj1FWmJGBp0Yao1x1JO1k7F+MXjNr6j+mRREkate726a/laJQm4t6FliGk/+G", - "bsDoFdz9lCXmMU7lIjSnAl/TaUbvNNXKt81cS5Ep/Og4DSvIKgI2PAZpcy5m9pQMe8oMOOyRc1j0SSK4", - "poybHTbPKcggMV+tscyUKc14op2CIIkouVahleHorSv7ZrCA5S9c189Pnpj/mZkAR3qnRZGxhJqJH/1L", - "meV+bYz3PyRMese9/360RGxHtlUdvZVinEFu37K6Yf9BU3IKn0pQ2sjhn5/8cBNv/cBpqWdCsi+Q2tf+", - "dBOvfSXkmKUpcPvOn2/ina+FJq9Eyd06f7mJdz4XfJKxBL/on2+Gjk64BslpRt6BnIMkL6UUVjK6h83Y", - "z5DrXvJPJZSwybxvOBCKXYwQAdvNCr63H96TI9uGPLZkRFxRYkfYkE9T4LoxpCwNdtkAH5UhsKm0qZyC", - "RhOCPHS9jHarJOwj32jSN9IpKFHKBAhLUUKi9rbwS2nKk8bCjfTJc0pqXeF7iZonbTNWIOcsAfLQ9jNz", - "rkCOb7R5bsVU2/rHC4JKxcjSIqMJ4mS3JxbCUk6AJ7RQZYYqzllemyJ8afP8s/p0H+t+YvwvsJT7LAOp", - "f2dKnzq5iBboyoc3isX8X3B4M+kd/7MBMdvoGEc+FRebyLP/tUfTlJk50eztKpEFfl8HA56VrP3w8Vvf", - "Ap4t0zRrR4S2vmm47OCWmYV5VHVK1WwsqEwJNb2IFBcD8nIOcrEEGUwRUdhFHqPmQ9NPnRFUZ0Ne2/9O", - "JSpyMWPJzJkUyilLFABW16oBOcPXnZmxzRpLDemQT6TIyZmZ0miS6zNrFuKfRjWfDYjBy2eGgtTAtTqa", - "Nn8viWDIE5EDweEo+f3lq/fkr29OXuMTVALhZZaRixlY/W8XrpGq7WSFnoEk54ynQy4mxO6kNXHWRIx5", - "dHNbfytzyokEmhpATHJQik7BGN88RbMJZ1at01l3bpUDHytiayIBGd9nKdWPt7eO8vTP4R7A5+HGSd4y", - "diWvwj1aX4yOCKYXfsbBLvbn0ABlkQa3hqX+YRvy3Sv71aAS6KaLIRnzMSvbdlP2VoToRGq3h2qBvSkP", - "N9m4KK5H7hXFnZR6dlmbMo+TBtYhiUjhJiSeT3oUhZf6aFGMUpFTxoPNGmg+ctbXJks017sDR4S5yPch", - "XzB1fi30aAa+iwRZrcunhZk6JwqAE8EJRYzUtxC3oiSD26z6knRBmCZjyASfImw0mmxovXw7UjLZIOQh", - "v0pKNusa0SwTSUC0Y7tZUkAQY4cU5q3N03AbOunCzW3DZjCHrGXauUhX2tcer3SAv1XStldLmIZ4F9sV", - "+wItMysVpC3Nc+CpkEG916YTg4sKKjJsCj62m8SxRxzXInPs0HdR6ixX5pE71htvDzgSwe1qrAyyAsD6", - "wRKRGeEgJMGTo77Tdu7cCLQF3GPG4bvljx3ajNdiO0xGGR1D5kyAySg5V2V+htC+MiaMZapnMORmY8ZU", - "OWsAvb4wYRxX6hNlk5F1Qnnp1b0q0Ia+7EAbTjjQJopAg7bg0dvWBnknI3Q/doKgfjAQZj8F+uXnQvjM", - "nmdLisAvA0gKy9+YbroClLGHklIqNods0bc+YdR5zBAUeqIhrVz2A/KM478XZCayVBFgaKRRNz4xxDkD", - "9EYg0fIhX/E71NPwfvSaklcOpLZLjHo3TjTk3iOrJpM2XvNx+wa/NKvdlHCTUSamYZrBffMLoUl9REyz", - "zEnHHZboTpi/feyvUVU9tPcI5rX7Iubr+L9If2mL2y/MFB6eVt/WmMRb6Hh9o6s9Wu5Ihw1fHqGv73gb", - "Z1+Ke2v+7M6PzfVhkED1hqXocdNZvqDDopFwN5dsO12WGyzpbqrS3kSBDkMjbFXVGc7lRdfmVtWvrUm1", - "fW+uHWrU77i7mGNliUFlQajWNJlBaiwZuhQKx+7YFvssN75PiqxURkWQQijciSF/eOa4/MyGkmCghpiy", - "hGbEPEgNdPmXsEd3TJs3mS6FhDkTpbJSx6cXUF6NJi4uJ0yTTSF78/ihXR9cRlHcCPJobOvmFEK/m684", - "ugRmuV5WvtNMfGpG3VAQrYK8q2Ruf2+b2EAJQTmpYKK1P6xLT0zqkDYjDaw3f4m9iJ5RPeSVwYG+XuxY", - "u3Bvxx2IW9omPHbQnWsndvYkjmBzE3e9sptzwRR4zx1w0N2d662c+EHRKWxnxTaAvnZ+v/yyS3xpgzTM", - "h+O4tB35GSY+9OKiN70RJnmRMTyyrToRCWafktoYZY2tt0dZrqs1WpgijJOz+iufXdm09UyCQqvJM/EZ", - "JOdk2aNPqCLDXjI7xyOXgflHdbpznImLxzM2nQ17K3PbHrcXMIIaO7oyy02x0FVoYWTgtch6HPkuyvl6", - "YR5ZWyqQNihyYGQem7MMpoCntsPe+2HPyZW65fFUUo68Z2MsKU+HfNh7VfVEec1sgBW/rWOXyx6P1Kv0", - "PiWFFzD5Pu1vY3otJPrbmN5FAnXL8pDnTChNxqUiNKWFtsGz1ekJNQLY2KK1L5DQKXB9TM5mYzpiKVIx", - "uprQG4g2AkuBazZhIMlDygl79/zdCTn5r9cYFU1esbEE8nxGOYeM/P3vb18/6tvRzJzP7GBaUq7Me2/p", - "KMYuzkui1Uy/w7huPyLYzZ1/wieiyQNrYV+lxiAOFzxhP+2FZBoQv1VbQLggEhIh080AMMYnovNcrIq7", - "Fr6sBr+LzNlcm4dDq6PLGkJYKtZU4xcVfHm6iQcP4OXeIa/Z9ya46jJhRu6iC9rN6unyabz5shlzhMFz", - "UlyY6edMKcanPmbOBR/RojD7VfqhFvaYU5Zt6ZPMKJ8GQDy229hmkFvGSZk639LFOU2k+AJ8RHWwn+2x", - "pbl1ALVlJtMSlBbh9tl4ywBs29YLvEG1bfPVjBpjoL0PTjgTY5qN4HMBiW7vum24eRIMmcL2BU+2DNFm", - "95n2eVKUAXmEzTnkba1BS9Y2B2d/xXFb9hGhRnsU6XVyPSbMyZ20X06CYV4nbwlNUwlKkRS0vavRiK+p", - "RLZ1BnPQF0Ker4bWDIb8+s+zffE0aRrwAWV0OkqhkJCs8WYH3ynjeuLnOJoEflfnfj4DPRrDNBCghq1S", - "0DShSgd7JCLP3d0DbzvwNNg2pRou6CLYHgSvbR40bATdumhHJcH2QjIRfnURimMyjRjS5y77sJD3/dIB", - "OkFxuhtmr9lzQyYhCDEicFRU18K6Ooj6PbwmFQxZwhtV3ymOqsvHl5ldVl3e3HyPqO8deuYgNM26ukcv", - "LfBDgvduCPffxfRaVOHvYnoXdaFblscQW4ZwZWJKYL67KXW5ex54w9mZ8EyRs0xM8W7HkGOoDwb9nP3P", - "h+eweKTOiJDVH+mZvU80E1mK4+FftSsHMwAwPnXJCcRkyHFovCfSJ5T89d2b1+7ihpkToxn7AqmxKymx", - "nD6wRhp6gqyNhxANw8iGHK/Vu56qEZ9iNg799eh5QDNOyMqGfWp3rWE5DrnfdCRLy7G+nqLq+ynavM5A", - "Sh82COk2s/zllbcNoYa7QzWEG93tka1Q1nSGnLJspJz+3n4qjs9wLRedz9EdoQSnO9U0O99xBushvasj", - "lgrkfbU4Xltc003WdpKwbkS/lG1xzXWSc43BfdH0kGRUQlph+gE5Q7B61idnwCt2rxHqWuCoYcohP3PP", - "us4OF575GDIMhNtBcBsADoHfNuAbBL0tgHcN7K7i1SDSDaPcNYTbVIpd4O1uYPS1SOE3KtMLKq/Hcdt8", - "wV2EC+vr8x2xuGZSv7DLIcsDRahSoElRqtnxkJ/NLqozEgsTlqNNaM6yBXk4EZLAZ5oXmcEdCbNgIIf8", - "DA9ZLkYF1TN3xuKs+psINvedsFyMkowqv+0wuxhtO180XSSbB5SNW2moLWjHXf95jaGWa2Ozu8peAbaq", - "/f+NfGQK86Z0Juohb6XqFlTeJ0oQal4/5AmVNiMOzxYuGwqm/YCUqHIcCJe3MDNMi8GLjUYmBK8ZY2tQ", - "WY2ZUKM5SBViq3FGUxgldMw4BBRuVioNMsQNrlkNqn7+9AfNeHbz2R4o4h7oL++YON9iNaQ9F+oQx25Q", - "gTPUApiBc0j0SAt/c1GOEiFDrGCaU9bWOpHwKThy+MabadUzCTRtGbvl3hnwJBOqlNDeqjLh/7KTT2lA", - "1s4DPxdCZIGmeZqEpK8YqxHe+Q+bUq7XBZW8xd6iSo/GIrAabDXo0N/KlAYOclRdwvHZOsko6EI2jeOS", - "Zan5O9QhWb2Nv9Yoyupqird9kgkRfrekyXm4UYg82PiFFQE3tVk7pzyBoNc4p7yc0ESXMqB3c8hHY8rP", - "QydapnmhoaXZUGfwPCzEOaieQxIRG1uOSRvtoXPSSzuMudBs4i7J+6GOUCMqk1moLRE8CUxKqNE5SB7Y", - "koZl7GvrwIOuVzsPCjWSkAFVwWYF06CBJpQ7Hw21tki7QlyAHI0l0HOQP2zv8mNLF6fvftjepW2UQgod", - "OnFe6VFNqaWnKosiW4z42M8KgTi5fk9BMvoieKhRMuonF8WF+AIjzbJAe9EKG1oOwdFkxamHm7dZtNjJ", - "bMmqsO5wMKO/7IjZ+722dV4YTM31IiAhfUD5zViJDLMKJvAOtGb8epzxnvfcRXMgsEzfybVodCXK9rXg", - "38g0TLjLq4xNmBfWpjRpnGYbe2LIZclt76Udj6qIPDwzAtKa5MPe7GLYe+Qyv755R5xYXOsk1LD36KoO", - "xCvrxEZ2rR8afOAK6oXJRoZGqsiKY35AcIoISM4wRTEuvs6kas0q+wrcRLdPimjxdG1PzMyEcjeIXTiU", - "GvJhb86kHvbM9gwrG2HYszFdQtsMj5Du4qnvosFWurSG4vi7jsaLYO+W01bTHFa+jhrszbgyN9Q+u+gZ", - "ddcg+NX+W3Rws8fWVW709C/Sx+RVjsINkaXhs/cm+6zMKX9cp/CCz0VG3fUiVUBioJHlNUP/SVJKibxq", - "7cIhL+z7LFW0O7lxBj558c56/a9F5Lqx76KYbSytJSC14XupTlcOxv2yxY8REjtqnoxCnhlsK7VQmgZw", - "CvbYEmhq+rSdath2PmHTLc2togC7teTCM+2p5KLlMNR2KTAX5ZZ21dYhCN5Me8iqM22TDD6PkqIczdh0", - "NqqvPoU/XP1AJi4698/p59H6Grz9GO/Uz+ZIbOkUNlVN84yGH50JpcMJhFpyC41y0FI4lgh2av+S221d", - "0wsjEFppu5BizgwCb6HMreaK6dPOYrZ5K49oUYhMTBfBDhd0DsEvckU5mz6oa0qjYAa+i+rLrOuthIkK", - "X415j1cohMTU4zABhB725qaic3sU9/bNu/fkqFQg1dFX878RS78dme42KAcPvVxEEAejnczqZSGrHKgu", - "NfRTTOCLmNtF09hCBMMeFwbm1K93Mxr2+mTYw3uDrvBEBZ3xN4OYDYuMMzAYOmPn4L2i52jC/8FWPOe7", - "3hCt6CZ029GBAtw5hwjOCqrUhZBV5ICEKVNaorgYncPCBhDgLg55ZavY0KexEBlQ/tgstIYED89s+MyK", - "2DnrD/kZy9d/JGeZSM5H9tLs2SNiAMPCfSD3/R64y5hHeNHSfFg+B26e79fZMFLI6AL/+lQKTeuprFtX", - "lV11S3HPuC/+MwDcsfYgHs+udu03wg3yny0wqXZOddDvsXzLbNe/dadOLfNkecvhcI7RTcFF4IlDuHVJ", - "gX6/30xwGAWjRZDigsjTtqYiOQc5cpzFArra9hVy2pLXcYU5A7BBggI9qrjasLBf04W3zKciGt63Vapu", - "NLgIh95x78ngyeCHrcZh9aj3RryCpJRML94ZZeNikahiybPSxg+gEjLP4K/Ld820LvDEFKgEWfW2f70S", - "Mqe6d9z769/fV5UpcAhsXR/jWzOUi2lcmCiAq3nSiDilBes1tqf3w+DJ4Cc06gvgpvG499PgyeCJEQdU", - "z3AhVVp/8++pL62Y0awrmVHxSN09RQqBNpSr8OHOq7FywID8QTmdGumuAIacZln11FOXKsTKfjTJFCzH", - "rP1J1k9EC6wss7Dxog0/MJkIaYWbzT3EBD9Je8e9X0E/c4vqr9RMC6RhW3Y5Wim4YhBOt/626lD3/q6K", - "TvcHLLTp3N2WZ9lhPq4aTfcnqhx1nR+oSkl9+7hWaeXHK6yQsQKAPWUy3vxnoyaHb6B6ZkemU5P3kXoa", - "XP/Pj2btTc7+50ezNk2nhtIa4QUf8cRGeVjrD5GyiUELK4zjsmQhrHnA0gfkHBAW5JSnVAu5cDl0rPpH", - "L5i1F90oT5dOjgfWgnmwAi/QrsAwCSw9wyS4UV6LFF5+hsTAyOciL/DfdTIGfGvNfSxjeoG5Jsx79LJS", - "hY8h3wrV4EjnefkPkS52+vA+n+8asrRFPBq7SJi/fkdt962FnMAFsW3kIdYnMBtZ71e9i4+2qhNvyqXV", - "Ti6h43fxgucFPoL/uQvBm07LEkTb+v7QqBu0re9PjXo/2/r+fFsMWnr405XKsaGWlXpC888Qx4wZSwxz", - "3zVNhGatHJIKqMzAsUgtuueONm0JwLqGl8u/+tSl44MsVcbqVObVltmbvH485EP+uKoAYyUCum+Ol+KE", - "CG5TONRVblYdsX3sx6dE8CEntqu9aGHI/uHjx5lIaPYI5ynqGnRYSEeRKZsDNwawZKnpK1n6aGCGacoU", - "UouUTmLEzWtgVuZK59BMcNhYExhokDUW4mCIzZJj1+AOCEiNXTDtO83YvC5kadA4+eHPJGe81OZDvaO5", - "9QwziQ4oNVjZZDeXJgIadFmvmUVgyU5kDvmzJIHCrMGRzjGG9JrHDO7r27+s07ZPJhLgCzijk17Yy7Zu", - "nUNeVZa0H/0pPooxf3YUzCxg/1mcT90/qE5m9p+Yu6w/5MkMEtNPLZQNPe4TlVCuEsUCE8C1kEaGLreU", - "IX9oa9D2l7Vo+1VOLptI0nKYNXxVfeTnjvPx0G/I31SM46piqmXifmTTauuQQX99ueTCo68s/YasaEjZ", - "XYjC2n54dERcHT2aXdCFqgf/8cmTfuANijBuE17bvHd8efWqQLt7UiqXUXmBVfikFPJpXRQxZZMJSMt4", - "2WLIHRPhASnIKcJpLXDYJtEbLFzzn1fNllegZZfewdZSJiulxIyg7VYBZe2xNY/ix9tQke/Xvy7yZi2l", - "nzqhYkikj4m1rHeuoowh3yANUlOGFZmTUtFM1YRgPt0BKmVXPG9b319uRYF/6/dWuN3q8gy0x6v7An9v", - "qBSfDUucDbsh3Z1RO+Q7A2ME9G50pkgmplNIhxzFH7FpY0jTB2U6Qc50HfSwyu12GZajNu3cbsDYUxt7", - "x7LY32vNXTKRVBjpXg+j3AIi9TpjXjBVZHThsirXl1zxplAdLrGdrIe86Zshl3DNXM4hc3t02o+un6ty", - "/eyRJ2evjUrUSRgvhpfZgw7WiqdtlCH2VUQzY4kYnaDIw7p25KhqpeMMHhnkalObDbk767MX6JlWy2xv", - "Ev9Ek4Wp6kywCl9MaJaBfEpyJw6G3HA71hPRszpX2iY3m6m+xFVFD+vdZ7PbYx3VEcgh6zwcl9m50UH5", - "Iwu2bC1621gnsjDKzqnPOUsNAoNPJUXUlkimQTJKHrK0T+pymP1loV3rlXBtlYXdJ//v//zfR8iGdqqp", - "4UzkuJwurBK1DciK4sJNeE3ZcoDUWhTIXsqp6KUroQUF2r26Kt9qx1Kj31NNtOWmzGjX8KRvN+BpjTh1", - "J5yKh4bwGVNKTR21N/RYrcAMl86Z1CXNyAPstnJWYcPM10KEK1dLpyK/Lforng4etu7aLFC+/yd+zzGc", - "1oAyG91XK6/gsdnVSvYxVdBFbq9VuF7GXlx7/ervUSqX1R6r8WzVG+IB3u2qliUI3MWlh8wUgl9OEVGl", - "2NSlJGXaobAhX4VhJITCvH48e4ox5Jf242GB+23uEUSyLG1o0gFLH0VH3p05hm53EFSGTsPzt4mpgnjn", - "Nqkrut/uLLba98AOLw77sIq+HqgGT60d+rSpgSGv8JAR8hJWcts5Z8FR7TyokRVm5aK6Oiy6YHrmRjIG", - "DFNkTjOGlz+WgeUVLjLNSUbzwq9Nasx467pkf+DqASLSCDwPRGUjSC2Krn7K5TchiQGoKy7Ll7bStq7i", - "Pt0Z8gNaFA+GfCMK1B3sYVzZWkRode5Mi+JpdS0FbAlXmxeQkxnlaWbvorx4+fvL9y8JruPoKy2KEUu/", - "tUBVs9yr4nB3W2FNNhUFbk8vWC5ps7+tTeSN9zxI/2AMDrkRH2WdTZ9QS9ab2Nn+Hj2FB4xmi+Iw/YQe", - "leFHfNcgkn3JJkepyGkgB7NpxiRMruzDJphqTde65oYzk7gJB9wWssGLz/stpPc9Kq8JKi6HksI4ZKuR", - "0wQGGG6/RBYeM8fO8kbdZu3lDBt1G/faU3aI6r/2qhVFw/gPIIDbJ7RdPWgfb1UwHqBL6Ln13PustBby", - "cNp3TwTRQav/qOvvgiOk1vVHNB+x9bSdXkl8inkqiPnEhE1WsnNJ61ddiTC2ueC2ggQruJ/lJ6eNKRw8", - "XnDjuXQn8fxsCw3W6ajCHgCXaqC66NWRrl7jwAeHCqInIoa1XzmTFeU4aybXafG2+cDV8mmC2WZCGPxt", - "8zWR8yLnRc5rct7RV+Se7W4WTRO8/rzOd/bQeif/S4Ml94IjV1+JdLX6UkyK731htXmHGTTV+BAkxS8M", - "aTRbvsMb8EwH2USLXfzykUX2kEWoPlwWOSyP/xGmEtyWXU4LSadAUqbOHZPZx0iJNz2q2/QdbbP/sq+M", - "EDFCxAgRG86zSxhnTddbq3F22nxN5LzIeZHzmpy3q3G2wXeXMM72yu99n5Hn6WpuoGifXaV9tskpu9ln", - "kUv2k0uiiXZjiqqqy9QpBfjuR2XvquEjLIyw8L7CwtH6IdnV+Ofbb2msnZhdWXzQaOsljDX23QgGqlXV", - "cQeNZ1fv9N7WsGErFOoXfIyXP6LT3gMKg5cnI99Evokwcam41h2IV+i7aNdeay7FyIWRC6NLo4P2inwT", - "+SZqr94RFhXoePLs+vocGFVLvAAc09xeB5WWenZU1cf2K4ZTrLQIdWkb8whw7bYipAlKPXtt5fD13gsy", - "UwoXb2yK6bqnTzrfiDTu98qySxJA7OUqLn7sIMGr4j17eXsX6bE7gRrqcrSJlYK63Nm1kTsb+ZcfmJ9H", - "3hJ2jeQltgSGJ3uJeXo1fQkJZi8Zcjvbo6/unS0JTF7gsq4sWbJ9n/eC6TlhqeHUCWuW9AxlnnQDRexy", - "+KmPU0diG3Cior2IJg4XTZhvePB5h63IZhz/jwLAhyKuQVTSLBOJ+WtSVUBmXP/bz0vx2Eyuhg8YBB7I", - "oYYdzGyk2QQZ7pPCvG2IcJnrhnj3t60XHl+ffrDaN7ZK2ja2Yl9gl62yH7dLlmO3qrUtjimPbz/l8RqM", - "6Q6/bBr8EDcvoc+2c/hN3OI5fV8S0I3ffY6pg3etw+DqTtpChnWZsNTSghei3BqNxBCNu4qF9j5MY4Il", - "7bvZu7Zv2MR85ca6zmrn9h1LpznWabYTIxkdQ7YvVcrjAdP+6IJJTZgbcn9Js9E4PVyBbL/igaa7rOSq", - "q96GoiyFCeMMvX95qTQZAyk5+1RC6Az0qmXvZITV+D2zFlmZcyImZDLC4guudD9OG98AimjhOwmdjETh", - "GzAvqGRKcGKXJQyyAl7mZiP/0uv3fj/5z5e9fm9YPnnyE9T/+Ev1r6T+h/np5HVDvDffjZPdfP37Xdcw", - "p1npGedv5meihU1zL+2Qid0s31BrWqmaX7/eebdfy1fedmbQXZgsZgntjr2Ovtp/dDZ8K0LlKZZWtJcG", - "clsjVVTKDrRqhWnbjB0HtJbmDnk4BT5yow9suMJkhJgrUEChXlasyXPHavJUJNieQvSKCO1KqSua2ncX", - "2R1kANwfImWTBkstkZ8FhBJUmWFB0QYmbFbLIVQRwYc8MXCSCX5Mzrm44LYyFiqJClb1l8VJLTDpEy5c", - "NV73dluVB0vv0BxWJnPmhP0ZFuNZqfljT6vrrq0Qdb/1zhVDZw98tE4KT7iLUUOQ2otmlPz85ImNAsD+", - "W7e8DW5fI5Rug8d7luv28NDrHYpKbGDS7gBXgd7qawR9E+5GBdrrcTS/o8yJPscIk/0+R58ZtnQ7QqzH", - "fSfwqQJ92M7HgKxteBavUtIayqpDRFbn9drATjFpOOSMkNWCILwFFL6+ZhsE4oVB5mUKqW3jbX+fQV19", - "bjkcU4QSfKLx48P35tWvHjV8k+97/d4rL0TqqErMiGYb+ssVEMqXKL1+++2Ud7tCuo+I6toQVeU+NGS+", - "mwfR0KLPiWh+kzABCTwBtQ2AdTPokK/8Nh3o2qyr5EKrYWcXGn2Kd9OnaAili1vxQCgv+hvvNJ67Cy7H", - "LRy3ggEPRthfOUzdgiu3YcJv13D76x7js/3CXEfwuRBSB2/dvsTmFYZjnFDy13dvXhMb5l5Xx89gmWuM", - "5ficvfclW3WhfcV9wGKdqN5tx37deg3TTyMKM+xRwoCSGcvSioyMIUxXjMQwfQTj3CJkipDpipjuzpzV", - "dmLWo6+TzpmN3emqTQnUwrFrpvUuJ6a3zrNXf4wbrfw7mOfHsYIWrYywYnRENritQIZMTNeCCJ69ftHr", - "m/+S12+MrfPmFP+Df/mDBYTRWr6rot9uKyFGPAG9WU3pjv3bke2yLwGe0EKVGUY3jRfY7C7wQbob3vUe", - "sEbIGyFv9BLuysJHX9H47Ip5+SobLz0flwPBHXyPb6kErps+lv3BAc+bdvtVTK36FhEg3xGA/HLJLWuO", - "wt2hcmSWq2KWCKNjls9Div7oXvs/pzqZMT7t7EHuVPw/guk7Baad52XP0LehxDsPvHesT7QzO3ctUBQ5", - "OnL0tXO0I8Y7z9RY2TnI0VUo3MUM5JoRoEipICUPlzb1Snyw6hNZZmD/lcwgOSd6JkHNRJaqR61y4ANO", - "KcYNNHbjTpHgqFOGp/Zzyi7XsK4+AckVpX9ykVrXeLtrUlPzJKYyjseau1yp2Weuabgt1pCnmLKEZvW9", - "cvIvwbjRR3rGVGMn9AxIIWHORKmI4NC4OvMd/o81P5ZQ9kr8yqWgKtO65wJNI3tslAtRLlyLrt1yz/kU", - "cjFfBXgNXNdW33JDcFzlrTzrJQ0yxbpXdpU1/AyBsBK4Do+64YfuMuwan629o7+2ksh38RTFnqLwZq6T", - "XfTz3rPZ9ylrd4d2RV8D13JxExo7WT/tsaq7WBMMXg0epUs8jtmH4xiJXzI9mrE0BT7KgZcjl4B8e+ST", - "6V2nK7cjLHP8YONESAJzkAtbH3BA/qCcTkGqIVcAhGaZbVBPXTanUuH1AJ4tiOlgBrIdzD8XZAyZMBJA", - "+ATgr6BfufX8hpP5A3j50i0mJqu4D6Xlu4uHW2E3S8qdLrpbfgni6V/tSNeZQWityKdPeWO5z9CDIoOj", - "oJ661RQQJ3wiDuNm4X4Vpqiye1gyXgpzklBOushzm6BvF4Fe03mU3ocrvfElh1+CKyiSjeV1xQJ5ZTJf", - "u+XpebnCn4Sl5GFVptGtgXGlgabGgLFZiR55PR+SzVkGU49of/D+gatLU3eyb+uTB68eWJ6/YArukLLY", - "gXjvbREsK9GPvlYFvb91hziYsyehKqGpKxwKmNYnh3wMUs1Y0Se0KNTRRMhcHVWHxUe5SN0/h7yuwM4y", - "ZhgIxyzKcfXF1YCcWnqxBUvxkzrltSTkpnFiFJqbDOXOePGoNDMYF/zxGjN4dNt7vBSflza37YOXxiYa", - "i3TxwO1CQjkXWC3BvjbdAv22nXv/6kTA8syblnpmC+e5827Dc4Gj7row+74cc0fEdtnsRJa8lsplR9Rm", - "7fRLobY9JNEYjnVngeNh5zNCan6gGnzaBjP3VfjfBPC9ZnAawefhg88jgxe3e69Nr6VmI0yRGkdmYAip", - "XVUO+ZV4rPELPysKFdVlVJc34iXfEyYNnDiFrMYPfMZSYzXWh04LFPY1v9miI4YbbeG5mcjSDWtvyBvm", - "nulPk6osSSamU0jRdKQkmVE+Nbad4TX7LUwfyJnebpt1OHy6O/q6/n4LD7xZfqpzWGCqaPyKW0+uG4PG", - "U+rDPzjoflbc4Oam7r2m0+KD4daoiONx9Z6YrL/ttRauTeSog4M6OGrg+2QLL89JOsRz1X3t6YmaQVqF", - "VzruPgXzNbDeW7MBFe6QI99brau2qN0/lvOK+jbq23tk+HZIdGHPFVPYF/9UpwwakU8jn94lPpWd9aa8", - "Ma15GnVm5MV7yIvdcspgutUqr8zumnPIr9671DVZTWTYyLB3iWGRd7Zzq2UxG+tXXavz+H/9YUpWc3bi", - "UPQyFVSpCyHRuzTkEqZMacuyo3NYuMryilAJhMMcJIHPhVB+R1PF3x9Uh9okkbkjcx8uc7OON5aMwUpY", - "QR6Oy+wci0M9snz3gKUP0PnIFMkpT6kWclHdlh2LdGEZsopVN79qKqegCSue4p/4buf91TPgrrBUSqgi", - "L17+/vL9S2KmefSVpd/Ch7Mn13xh6mSVx81+jJhh8EexzHqsHLqu/lihSAoa0CoU3Pp7GmqvUnksfJnK", - "DCEmzlN0MRMKg5qs7jNabB31+vXYSbxfdeDK46TYb/WBcnkXHRI8RXwtUti4uIGnhWNo3AOx9F67UW1J", - "wqLpY2k5dhzyy0b/nGyNzG1VER7sF9Pk371q0RVOat7JwOtBS8IwJs8YCLC6xj8vc5AsMTLfld93NE3T", - "VIJSQdm+I0XOR2Z6HPSFkOfKEKZ51/I9V0Km0Ti5m/pl7xOeZWK6xSkBczOFyjipnzcKwsdfv5sBt3BY", - "5fwnWphhqlfUea/X0hl1TU77yXz+RnbaOstP5Ls74xQQ08O8NU+XhG51mw1AMvRogNREyMQehT3IQSk6", - "hQd9Z+dPaJnpIc9gDpnp+sCAkAd9RGaQF3rRZCFj46RMJVSm4XAwx6JXY/ZnYjpKWaIb3FWBoD42TnLt", - "vbZk2nBR3laLA1Nvm5on/qY1F0L19o+3fGUp3lbaqoKOvpqP5WyiLWhxRQVZwm8gx4BO2qaSfq+HamK/", - "TEzDloidcYR5Ud0cAM6r7BcU4F5F9QKSjGKtAtd3LUXEa/urJ0nEmXvgzLomxi6p0cnb+c/VWJWxhE4I", - "0z+n6vzsKTkbw5Txsz45A56eoU47G0tB04QqfWbU2ZCb/Skb5UNTqumYKvNiDTQfNXwcZ5W+VFVUSUKz", - "DCTeI2Y5lQt3oj0gzzBjpAGSlNezo5kEmi5IavcitQflE6zXcMH0jFDy85NfQnr1dbXHV5ZeVOS5e2xD", - "CU6phgvqCW/Gba8WxLhiztvjvoTvqq8VaD4tbD+UJxmnhAn7TDLgUxSJOf3M8jLvHf/0Y7+XM27/eOLL", - "81nNwz/xNXrp23yJn2leZEB++OXHwQ//9u+DH54MngTS9AjfXJkwLERoLviUiDnIjBaFMTT48ovVK/jl", - "l20rKOa+s46//f7s9UpSuMYT63S6+fQbOaWcKaQL6k51idd7F/qMa+Bn2a/6iLcNgxx7HA4a2vtcpXXc", - "bDcv8uYxpEPZ7WeRQ27Esucs0jzd9TRyyO1sj766d34jD9dyHP2J0DJlGlHdn3w3XR6F/cxVOO7VyN2G", - "8bG6n6/RUbnhrkZ/BHoJnTtiC2u64eP55v063+SOSDfsk0AweTQVYuXDfc8A6RTLohZ/lSgcWbvZg5Kv", - "VFTbA8uRFV/LmrxFqQwsLcos82a0p0XhBbxUKdAj4PNwaxAsj5lQozlIFUrUk2Sl0iBDbq3lF/C3cg6J", - "Hmnhby7KUSKk3ZRNAGqaU9bWOpHwKThyLtKAn8606pmxmlrGngNPA8sCnmRClRLaW1Um/GbQ5FPq3+zZ", - "PPBzIUQWaJqnib/lYiTGakQzkHpkCL+t1wWVPNwpo0qPxiKwGmw1Vp+/lSkNHOSoEFL7dzsTyciYTgGP", - "azIalyxLzd+hDgnKjlCjKKs7td72SSZE+N2SJufhRiHyYOMX5mfXnJq1c8oTGAFPA314OaGJLiX4p5ZD", - "PhpTfh4gYGxeaGhpNtQZag5yDgrJkKTBxokUX6BJ3WMhMqB8rcOI6p1d6JW0DjQuMbfyv16oEZXJzPu4", - "UKNE8CQwK6FG5yB5YFOEGgWnJVQXLnS92rlQqJGEDKgKNreIrEJcgByNJdBzkD9s7/JjS5eEjhkH/cP2", - "Lm2jFFJoSPT2HtWUWnqqsiiyxYiP/fQcyAqHuGP0RfBQo2TU/8UVF+ILjDTLAu1Fq05VmupSeZvQ6YJT", - "Dzev+WT8ncyWrErcRgcHPDYbvnh/tsDJz5Rt67ygUlKuFwExd9tZ+QyoOxUX8XTL76M5mlGZXlAJ7aEW", - "NMtc6Orb5yfoDM8hF3JB6sdDxuNvyw7RiIx3Hq6PjsdUdaXhV8+RhNm75+9OyEwoTcalIjSlhSuTGiBl", - "84pIxpGMr5GMayd0F+c5J28K4O/+9tw6OwLZ+SVkRrFXCd0GLY7qbbEIQS/zhw8nL9ZdzZ7AhAr4H1qq", - "+uguXg28dKkBbQJnVUBirDL8+CHhuY+UFWNeDkt4d/dLH2SC+Q8rnuuWuLHKV7230jq6z6P7PLrPo/s8", - "us+vzX0eXeTRRR5d5NFFfm9c5Psfx77qvzlCUbfNJekcN7ZrwHR+VrVGAzoa0N/F6EhJd+XayDq75SO2", - "rhG8jHcKupScGNomzGYxcxYrSE/6QXvl17xmEGTQ/OS08eI76EONOSR2I8aE8pQZrDCyT7Sm1qNTRajW", - "NJlhvVkt6uBFLjRZgHatLueJ+RE+J1mZgieO0ZHk82oC7+k0qo6oOm7spvChMeoMkvNuIM11DTFc1Ro5", - "LXJa5DQPp4m8yBjlCTS0Y4eCJ7+CJvUDzaon9vDRjO9Pp4RcWb+0VohttUy2UsFbqmdm3JO0F/nqjvEV", - "ynox8RJbg+M8At0gsokoedpgtrULxFyD5DTDjOcgCUgp5M2zm9yN2eR3stppZLTIaF0YTd4FNmvNV4aM", - "Vfclpu+OXOXPXhYZ6R4z0nMPQVVpVA8dI3ZEhg08WDtJagdKF7aKcDAyV6uWqsnqjqDB5TKOvuY2D+WW", - "WGOzfkKX67eloIMstowm9nDZDTCZ6f+HAm36bxKQ56vVkyOqTBJQalJm2YKkYD98+9cWsrExt/3pQ5GF", - "z/TGN2wTklV84Z58v8tFE17iRP3HNtqo5EC8MuaXK51sS/l9yjoalFFVd1HVd8KelLWalruoaXlpJX16", - "oyL+dBcVffpdCloeinqWl1LOt/jdblM1n0bF3EmOLIMsw0ecDdeUg4gko+b3GSTnRJac2FF29Fm9s6+O", - "2jpqa6/XyhFV8zqhx391IKo7ZWpbJAF2QaTS7dLkCxwyxhREnvxOnjSEdEfjCjrmL7ExPDsmLwnnLoks", - "GFlw90sWFT3dVVbcnoLFsqHSQtIpdE+94s+8EpkwMuFuTPjbmN5R3mMG705oAt04sCpm0HgswHonzR6R", - "ASMDxuBWD/cV3dju5G1VPqSF4YrIaZHTYh3QEK8pkHO2Vc9VidFcb8K40pQnoIiw9UOcAwbSVg/Mu+pl", - "kSMjR0bd18aPR19t9cvthRLXebLyA1+GM/eUMVcn8a5acGMedrPqaah50jILV1c0SocoHQ5NOmCGmHBt", - "x3fYjoVbuO27UlgLhYIFz4MhP5mQtLSigDBFCinmLIW0T9yTJdcsI1xckD8tOz6EwXRAhr0fZsNenwx7", - "P6bD3qPNwUTOtDZj1fOojqIGQ/7e/ROL/btmphVkkwH5oECqqr4kMfKmKkRJeeovlGcHDR7t2z35zmPT", - "K0vEV22SR55X22eFzsZO//Qkb245eZMzjG2odnjgrUe2ER0QC40dfkKEndIgNMMCQ+o/5jWIajeq3SC/", - "laXNRdqKw1GjmZ4D8oZn7u+GwlL2rNRqM1vBn2aZuIA0mArHcFZMgHP/5L0YK5GBSgAjV2EiQWF+yaL0", - "ZmDCdsRC1RE8wXyaluKEIpMyy7AMtiKZ0Q6u6GvzNUSB1oxP1WDIV8qBvxmrzVLgPrhV6jeN8dysevuG", - "Nu5QlOIKlVSfr1uhA9+XXysD3/W720Gbn/5dNZWrwsy+Cr1vPCsgEhIh05Xi3IHSvLEq770rs+CVdj7N", - "G6DlWKjmcHGp55MeWEneP0TKJosrlt1vhdJ7L7n7vc1U12t6jWqwN3QuZiyZubJUOdXJzIyNKSerFxlw", - "NMnodGqL1tvN1DAgw94//vGPfzz+44/HL14MewY4N38hs9lxnh8rNew9NR8B8kIvKk9NkgGVdufNBAeh", - "Nawk4r6yJVBixkUiuNY13I4GvRaujnr0svDy6GvnYlo3gTG3GcdbZY3HIL5hW/hALJxDhH2VZyZAjB2x", - "3x7QWHSD3hO4eZCVtm4Smu6LwL8KcBxh7Z7A2ghi7y6ILYDTgg2qb+Jwwobef3dhCE/29uBsbA881NVu", - "FuU4Y4nbymak6Db0XwWlhcF8IxT0aqSpC+o6DkeL4WGYEfnbTFs3VHQQ3y8HsVqS5KZ8CEYuR2B+NcD8", - "Fcs01lXbKyTvvvuBOYufSzDAS0hSVlVwqyjhh+NFFR3rAmVHzFP4xMDvKxfRWwq7mrmECs5iW6mF0jRQ", - "fc70SESeu3l521PJha2E29KlwECpLe2qrUOwEJ5pD5WyNG2TDD6PkqIczdh0hvVi1Uxkqb/84MoDmbjo", - "3D+nn0fra/D2Y3xrv/XSm6vrmdFgUwsN5KClcLQS7NT+ETqU7TTdiowm0EoxGBSrmOAQnu/Wso3zZKRF", - "ITIxXQQ7XNA5BPc5UAf0JkyXrcCjwlcJypx0KXTudwop7z2O7U7z9YtWlKckoSqhKRD7NGFaEQkZbrbL", - "9TNoB9nbnCa3caEihpDdDshtZodq5E1SNaWEoO8+ElH0ix+WX3wnNH2QvvAP63i7gYBbMPbeSuir8sxE", - "XH9PcH0E74cI3vcMse/9scIGuu9Yn7yG9cES5e6LdKtSHjFXxFz35EqWh+OutUR5dYDVxqM7FSqPRvZ9", - "UAPfXaq89tNfrlq5o7KdCpZHLRK1yL3VIt1KlldcGa5aXjFep8LlkeMix91fjrtk6fJAaY1l/atKia5m", - "vdru2d6xrHlk5cjKkZW/oyz6OiPLa2Pj0/1m4rUaKxM0Ufs2RUPLpgBPaKFKewK83Bec1idD1I15ZXRu", - "2pbTSGFCy0z3jic0U9Df8K1G4RKFy94Jl0sWg3dj+mtrbUgNf0n4qO0jQ95MnflKkh88t14FlrdJ6y4P", - "AfYewLfp/pbdiLo/ipr7pfuvrsJ+GA6sREt2qtN+GLCgWfw9LHNs5V+7S9cvYz7uVih+tSzxYYUm/Pzk", - "ly59f9mrCLa6fPKSf5oHU4Gr2veVd6x+vhntvCPn7Fsl5zvDOVtV1vd6wL4X/N4dt1cEvhH43lfgK2vY", - "K3eBvfI7Qe/p4avt00OEvKcR8N4y4JXfAXfvBdfsHdg9jVD3lpWUrTW2q5+XZNT8PoPknMiSb5Yq2wXt", - "vrNTiCc3EVVGVOln2JSp7jGOtnOY81649shukd2+i90MId1Zlqsr5C7LCO2SOG1ZzbOZAUILklI1Gwsq", - "0z6RoHLB8f+MT4TtifHHo4zNod3gO3HjH4SPKNY4ulf5mjd4wNjELNuhpG0k8qgy72QZekfQd1Zt1pkB", - "uiBVT8VroMmMiAkmSbJjhaXDa9cegWzkymg3BrlxFcBebyn6BmdGnR2lQ5QOByQdzLtFKZMW/R2UE/Wj", - "lxIVp/WLo8yIMiPKjEOUGe13fOpKTm2iw4ANIMmM8ul3CpI9vgoUZUmUJVGWVLKjKpjRxVuwFBToLT+H", - "xdGcZiWQgjLZ5ic4de+JnoLIi5EXg7y4BfsHuVFwQrNsq7du30F+5MPIh3vEh+14OsiMGxh6F9aMN+gj", - "d0bubOHOnXJC2rsvtEMsZEzyGPku8t0G343qGKxLRV5tr115Uo9/VaUSWgtYLj1erpxxH+vkGh2tQXKq", - "2RxDxBxb/4ksvTubiemrtuOAS6kqltk3I46BlApSQjPBp+SC6RmpxUFLda9thThDY2/M+yZz5seKnPtX", - "kZOwBqcFa3M22TEW6bxHRTp3i4raE520UhguzAJ1/0DFLvKwttAedWGOiBMjToxRiFt4c2TjlkaZmLZz", - "56aCqkKeMjEdkJc0mWHFvQVhilCiWQ5EUj4FcjEDCS2xjBcUhxpnrSUoljrP3oL7XUyj8rsHNtjt8snO", - "3HFJntiNFSIHRA64Zg6o/HdbfQmaTsnDcZmdG9SWPwq7Epzr7mq8B5pOvZb3ezoltq1v8JuZXO1D8BrZ", - "S+j2z2rQj9H0vl91gj8zpRlHwvFa3X6nc5S0UdJeV6KW51hh3krXQSAxy5XL05RqujmVVxKwVlxO/vru", - "zWtiOm1kLNN06nOPmkFdCS9fqbppmVFJ4HMhQSkmOBETFNjGulZEz6gmCeVYCGwMjeJgS+8plq9reXm4", - "Hum62MeeNyH4r+JQYh9k/Z5ncjG/L2/Ybc0kZsjOZREzD7WDmOoy3dVw3rbTiRBtXxf6WZ6XRBx0v3AQ", - "zTJDMo/N93fiNjdTCUGiwKXSiIsiLrr2BHZGtGHISEhcVwhpP4S15abvQFhLdoz64A7rg8PAVZWzc1do", - "VRWabkVXlY/zyni2e5DGzbOWm1vkrPuJtCrvfwew1WCLiLci3ro1vNUiwyvItYcS/KDxV1QSEX414ddX", - "Sxldkiw65yzmS2R1qQlUNIay0UGGjWrJswFgti2a6uQF+m9rb7AnXqqm6K3xUnX0bsxNeHu5CQ3hOIGw", - "CMCSWyKKXaPoboyI9vpj+1X8hyKtj5pIQ/4HtPttioGrPujadmC145nStWvnaJpdkybdkovxV9BOVdqw", - "rUqrsuX9tYB87JR3cU+E5LWbht8rhZmGXHn4oOY8KiVd+PgCjW4xqT7iytHxklg3sTsXmkxEydN9ItOu", - "Wbb9R5thgNclE+H1kWroPW7Oe5Lp+srto3uJOnc52wnhkHtDrVcFetZcIB1oNjoT7pEzYeVQp0Oc+65I", - "KOy/vp9gKPrJ78P9fD+LrdyHvMQBahjDvas77I1itI756n1rxfO++z5lBHSHBOhC9Osw3f2k3gjwIsC7", - "Hu1TKmSgr13uvmDfAfmDcjoFaQ+FPiiQ7geMxFcAGLqAfZ8SoWcghxz/IoJnC+xg+MT+pGbUkAARvGIg", - "JomQU8qZQpKiGZkaMKH6Q15kpTJdcgXZHJTvfPlX0B9wRTEE4pChnfmGh3odxxB23zoQmVakkGxuGpCK", - "ybBnmkfD8smTnxKW4v9h2BuQU6sQkL6bTDXkZgCWwRQG5BknkFOWGZ1jxkG9QzMJNF0Qxs1vxsySMMEc", - "QjgHSn5+8suA/J3pmSj1kFNSUKUuhExt0EKSiJI7JldkXOKFGi40UWzKCeOhKI6Kza5GOeGyvOcpEyaV", - "Dp2o9HsZbWutluoDHiQDqjT5d5LMqKSJRtn2TgsJKSaSIhcw/rFYkBlVs4EvoqOYCQ6jCyHPve+uPtD2", - "y0V28bd9s6g7z8XbRV0V69FXZPcuxYJMx8bZ6k5qdshRz5LvUbND7vQs6a5mt6Fw06eROueY0FLPRmZK", - "A5b26/k5oXYxA06YJoaaKeNm4UM+7P2vYQ8jo4Y9Bdlk2MPMPyi6Sj0zQydYch1Hxal6cLf7CjENT8QM", - "h+ASWpMdR4WESRikvwKdzJbMZDqDBJ6AOiZzptg4A5KIrMy56rt/kAlmLlN9krE51qGHIQdOxxmkZJLR", - "aZ/MWJoCd7AFuJYMVJ8MBoMhH/JT0KVEDiWQF3pBrMqyLFzPZEYV4aI5IaJQv/aNTBtymimx9kgqQOGR", - "KuIRw/bM/l0txMVaJjTLKn73iqa3uGV3WT5dNy/hDh4QAH9H53CTXBBExfeE9K4C9leOKJqmzMKQt412", - "O421kIsZrAgUK3j6TrCQOcgx1SxvAPZlCEhZ+gKw3xT0UwlEAU9XPgmBZCYgNXZV9TVGKIhHNh/8kMMc", - "uHm1IJQkGQNukxGwKRcS0PgTF5yUGDxn97/dDsDduG0z4IRPxGGYALeimucgFbP76VXGEjUjoQUjVVeP", - "hvpb3XRt37F6+9UI7no7aEHHLGPIoB+/2Z2V80rGlTLrHfcGR71vH7/9/wAAAP//", + "ZkkiZ3rIUQOApmTCIEsH5P2sMbKYEGq/XUIlbgXTZjs0zRrbJMWFGvKKggs6ZZxq5G/s+cjIGXIBWWb+", + "jzMVF8rtKKTkYSJKrh/1sUlMJgr0kBtGs2xuNhmJ2rfNZqbdPvwbHHhzN9+dM0uCEyaVrj+5kzK4C0kp", + "lZChL21n7P/Unb/0GyuAL8tISkjDPAPyVsKEfV4XLOQxCjEzMvDUqAkU+I7XnPD/i1G4Zk39x7Qogtzm", + "enfb9LdSFGpzUc8Cy3CKyRA0GIWHu5+yxDzGqVyE5lTgazrN6J2mWvm2mWspMkueOA0rYSvOcqTamIvl", + "jWFPmQGHPXIOiz5JBNeUcbPD5jkFGSTmqzWWmTKlGU+001wEiV+FVoajt67smwEplvFxXT8/eWL+Z2YC", + "HOmdFkXGEuTIo38ps9yvjfH+h4RJ77j334+WUPLItqqjt1KMM8jtW1Y37D9oSk7hUwlKGwXx85MfbuKt", + "Hzgt9UxI9gVS+9qfbuK1r4QcszQFbt/5802887XQ5JUouVvnLzfxzueCTzKW4Bf9883Q0QnXIDnNyDuQ", + "c5DkpZTCSkb3sBn7GXLdS/6phBI2mfcNB0KxixEiYLtZwff2w3tyZNuQx5aMiCtK7Agb8mkKXDeGlKXR", + "PxuoqLJQNtEElVPQaNuQh66XUbuVhH3kG036RjoFJUqZAGEpSkhUhxYXKk150li4kT55TkmtK3wvUfOk", + "bcYK5JwlQB7afmbOFfryjTbPrZhqW/94QVCpGFlaZDRBAO/2xGJrygnwhBaqzFDFOZNwU4QvjbF/Vp/u", + "Y91PjP8FlnKfZSD170zpUycX0TRe+fBGsZj/Cw5vJr3jfzawbxsd48in4mITEve/9miaMjMnmr1dJbLA", + "7+tgwLOStR8+futbwLNlmmbtCB3XNw2XHdwyszCPqk6pmo0FlSmhppcBbwPycg5ysQQZTBFR2EUeo+ZD", + "m1SdEVRnQ147JpxKVORixpKZs3WUU5YoAKyuVQNyhq87M2ObNZYa0iGfSJGTMzOl0STXZ9ZexT+Naj6z", + "8PXMUJAauFZH0+bvJREMeSJyIDgcJb+/fPWe/PXNyWt8gkogvMwycjEDq//twjVStZ2s0DOQ5JzxdMjF", + "hNidtDB1TcSYRze39bcyp5xIoKlB6iQHpegU+kQCT9Gew5lV63Rmp1vlwMeK2JpIQMb3mXD14+2tozz9", + "c7gH8Hm4cZK3jF3Jq3CP1hejh4TphZ9xsIv9OTRAWaTBrWGpf9iGfPfKfjWoBLrpYkjGfMzK6N6UvRUh", + "OpHa7aFaYG/Kw002LorrkXtFcSelnl3WpszjpIF1SCJSuAmJ55MeReGlPloUo1TklPFgswaaj5z1tckS", + "zfXuwBFhLvJ9yBdMnV8LPZqB7yJBVuvyaWGmzokC4ERwQhEj9S3ErSjJ4DarviRdEKbJGDLBpwgbjSYb", + "WvfjjpRMNgh5yK+Sks26RjTLRBIQ7dhulhQQxNghhXlr8zTcht7DcHPbsBnMIWuZdi7Slfa1xysd4G+V", + "tO3VEqYh3sV2xb5Ay8xKBWlL8xx4KmRQ77XpxOCigooMm4KP7SZx7NnLtcgcO/RdlDrLlXnkjj0msCcv", + "ieB2NVYGWQFg/WCJyIxwEJLgkVbfaTt3oAXaAu4x4/Dd8scObcZrsR0mo4yOIXMmwGSUnKsyP0NoXxkT", + "xjLVMxhyszFjqpw1gF5fmDCOK/WJssnIOqG89OpeFWhDH3ugDSccaBNFoEFb8Ohta4O8kxG6HztBUD8Y", + "CLOfAv3ycyF8Zs+zJUXglwEkheVvTDddAcrYQ0kpFZtDtuhbnzDqPGYICj3RkFYu+wF5xvHfCzITWaoI", + "MDTSqBufGOKcAXojkGj5kK/4HeppeD96TckrJ2XbJUa9Gycacu9ZWpNJG6/5uH2DX5rVbkq4ySgT0zDN", + "4L75hdCkPrumWeak4w5LdEff3z7216iqHtp7BPPafRHzdfxfpL+0xe0XZgpPdatva0ziLXS8vtHVHi13", + "pMOGL8/213e8jbMvxb01f3bnx+b6MHqhesNS9LjpLF/QYdFIuJtLtp0uyw2WdDdVaW+iQIehEbaq6gzn", + "8qJrc6vq19ak2r431w416nfcXcyxssSgsiBUa5rMIDWWDF0KhWN3bIt9lhvfJ0VW2oPqQijciSF/eOa4", + "/MzGuODRspiyhGbEPEgNdPmXsEd3TJs3mS6FhDkTpbJSx6cXUF6NJi5gKEyTTSF78/ihXR9cRlHcCPJo", + "bOvmFEK/m684ugRmuV5WvtNMfGpG3VAQrYK8q2Ruf2+b2EAJQTmpYKK1P6xLT0zqWDsjDaw3f4m9iJ5R", + "PeSVwYG+XuxYu3Bvxx2IW9omPHbQnWsndvYkjmBzE3e9sptzwRR4zx1w0N2d662c+EHRKWxnxTaAvnZ+", + "v/yyS3xpgzTMh+O4tB35GSY+9OLCSr0RJnmRMTyyrToRCWafktoYZY2tt0dZrqs1WpgijJOz+iufXdm0", + "9UyCQqvJM/EZJOdk2QOjuYa9ZHaORy4D84/qdOc4ExePZ2w6G/ZW5rY9oDBgBDV2dGWWm2Khq9DCkMVr", + "kfU48l2U8/XCPLK2VCBttObAyDw2ZxlMAU9th733w56TK3XL46mkHHnPBn9Sng75sPeq6onymtkAK35b", + "xy6XPR6pV+l9SgovYPJ92t/G9FpI9LcxvYsE6pblIc+ZUJqMS0VoSgttw1Wr0xNqBLCxRWtfIKFT4PqY", + "nM3GdMRSpGJ0NaE3EG0ElgLXbMJAkoeUE/bu+bsTcvJfrzFcm7xiYwnk+YxyDhn5+9/fvn7Ut6OZOZ/Z", + "wbSkXJn33tJRjF2cl0SrmX6Hcd1+RLCbO/+ET0STB9bCvkqNQRwueMJ+2gvJNCB+q7aAcEEkJEKmmwFg", + "jE9E57lYFXctfFkNfheZs7k2D4dWR5c1hLBUrKnGLyr48nQTDx7Ay702jh3Z9ya46jJhRu4GDtrN6uny", + "abySsxlzhMFzUlyY6edMKcanPmbOBR/RojD7VfqhFvaYU5Zt6ZPMKJ8GQDy229hmkFvGSZk639LFOU2k", + "+AJ8RHWwn+2xpbl1ALVlJtMSlBbh9tl4ywBs29YLvNq1bfPVjBpjoL0PTjgTY5qN4HMBiW7vum24eRIM", + "mcL2BU+2DNFm95n2eVKUAXmEzTnkba1BS9Y2B2d/xXFb9hGhRnsU6XVyPSbMyZ20X06CYV4nbwlNUwlK", + "kRS0vavRiK+pRLZ1BnPQF0Ker4bWDIb8+s+zffE0aRrwAWV0OkqhkJCs8WYH3ynjeuLnOJoEflfnfj4D", + "PRrDNBCghq1S0DShSgd7JCLP3d0DbzvwNNg2pRou6CLYHgSvbR40bATdumhHJcH2QjIRfnURimMyjRjS", + "5y77sJD3/dIBOkFxuhtmr9lzQyYhCDEicFRU18K6Ooj6PbwmFQxZwhtV3ymOqlvRl5ldVt0q3XyPqO8d", + "euYgNM085+ErNytX7nFvXrLsN07BlI1bhfQpmQg55NQ6Wdy1QdtzeW0T29SA/J3pmXX8rvfA12OMjGk2", + "25yo1Rgag2yteOri4b20zgrpjruhn34X02vR5r+L6V1U525ZHltyGYWWiSmB+e7W4OWuqtg709YLwRQ5", + "y8QUr6fYS9E2bunsfz48h8UjdUaErP5Iz+yVqJnIUhwP/6q9UZhdgfGpS/wgJkOOQ+NVlz6h5K/v3rx2", + "d0/MnBjN2BdIjWlMiRVWA2tnojPLmqmIMjESbsgxZYHrqRohNmbj8MgBnSdoiQpZmeFP7a41jN8h91u/", + "ZGn81jdsVH3FRpvXGVTsgzch9WyWv7y1tyGXcXeohnCjuwCzFY2bzpBTlo2UgyDbD/bxGa7lonMogCOU", + "4HSnmmbnO85gPSp5dcRSgbyvRtNrC826ydpOEtaN6JeyLd7FTnKuMbjvQgAkGZWQVmbJgJwh3j7rkzPg", + "FbvXIPtsU28P+Zl71nV20PbMx5BhLN+O49swfAi/t2H3IG5vwexreH0VcgfBehior4H0plLsgtB3w9Ov", + "RQq/UZleUHk9vufmC+4iXFhfn++UyDWT+oVdzokeKEKVAk2KUs2Oh/xsdlEd81iYsBxtQnOWLcjDiZAE", + "PtO8yAzuSJgFAznkZ3hOdDEqqJ65YyLnmLiJeHnfIdHFKMmo8ps/s4vRtiNS00WyeUDZuJWG2oKm6PUf", + "ORlquTY2u6vsFWCr+gijketNoSnamaiHvJWqW1B5nyhBqHn9kFfJiwTPFi6hC2YugZSochyI+LcwM0yL", + "wbuZRiYEb0pja1BZjZlQozlIFWKrcUZTGCV0zDgEFG5WKg0yxA2uWQ2qfv4MDs2QfPPZHijiHugvr8k4", + "92g1pD3a6hCKb1CBM9QCmIFzSPRIC39zUY4SIUOsYJpT1tY6kfApOHL40p5p1TMJNG0Zu+XqHPAkE6qU", + "0N6qMuH/spNPaUDWzgM/F0JkgaZ5moSkrxirEaYtCJtSrtcFlbzF3qJKj8YisBpsNejQ38qUBg5yVN0j", + "8tk6ySjoBTeN45Jlqfk71CFZTSiw1ijK6naNt32SCRF+t6TJebhRiDzY+IUVAU+7WTunPIGg4zunvJzQ", + "RJcyoHdzyEdjys9Dh3KmeaGhpdlQZ/BIL8Q5qJ5DEhEbW056G+2ho95L+7y50Gzi7vn7oY5QIyqTWagt", + "ETwJTEqo0TlIHtiShmXsa+vAg65XOw8KNZKQAVXBZgXToIEmlDviDbW2SLtCXIAcjSXQc5A/bO/yY0sX", + "p+9+2N6lbZRCCh06NF/pUU2ppacqiyJbjPjYzwqBUL9+T0Ey+iJ4qFEy6icXxYX4AiPNskB70QobWs7x", + "0WTFqYebt1m02Mlsyaqw7nC2pL/siNn7vbZ1XhhMzfUiICF9QPnNWIkMEyMm8A60Zvx6nPGe99xFcyCw", + "TN/hu2h0Jcr2teDfyDRMZsyrpFOYc7c63aoP5I09MeSy5Lb30o5HVUQenhkBaU3yYW92Mew9cll137wj", + "TiyudRJq2Ht0VWf6lXVig9PWDw0+cAX1wmQjySRVZMUxPyA4RQQkZ5j+efWUzppV9hW4iW6fFNHi6dqe", + "mJkJ5S5Bu4guNeTD3pxJPeyZ7RlWNsKwZ8PShLZJKiHdxVPfRYOtdGmNJvJ3HY0Xwd4tB8amOax8HTXY", + "y31lbqh9dtEz6q5B8Kv9t+jgZo+tq9zo6V+kj8mrNIsbIkvDZ+9l/FmZU/64zkIGn4uMuhtSqoDEQCPL", + "a4b+k6SUEnnV2oVDXtj3rZz/BpzcOAOfvHhnvf7XInLd2HdRzDaW1hJT2/C9VKcrB+N+2eLHCIkdNU9G", + "Ic8MtpVaKE0DOAV7bImVNX3aTjVsO5+w6ZbmVlGA3VrS+Zn2VHLRchhquxSYTnNLu2rrEARvpj1k1Zm2", + "SQafR0lRjmZsOhvVt7fCH65+IBMXnfvn9PNofQ3efox36mfTPLZ0CpuqpnlGw4/OhNLhHEgt6ZFGOWgp", + "HEsEO7V/ye22rumFEQittF1IMWcGgbdQ5lZzxfRpZzHbvJVHtChEJqaLYIcLOofgF7mitFMf1DVlgjAD", + "30X1Zdb1VsJEhW/3vMdbIEJi9nSYAEIPe/lU0bk9inv75t17clQqkOroq/nfiKXfjkx3G5SDh14uIoiD", + "0U5m9bKQVRpXl936KeYgRsztomlskYdhjwsDc+rXuxkNe30y7OHVR1fUo4LO+JtBzIZFxhkYDJ2xc/De", + "MnQ04f9gK57zXS+5VnQTurDpQAHunEMEZwVV6kLIKnJAwpQpLVFcjM5hYQMIcBeHvLJVbOjTWIgMKH9s", + "FlpDgodnNnxmReyc9Yf8jOXrP5KzTCTnIxvEePYIi00s3Ady3++Bu096hHdFzYflc+A2ALJK6JFCRhf4", + "16dSaFpPZd26quyqWwrdxn3xnwHgjrUH8Xh2tWu/EW6Q/2yBSbVztoZ+j+VbZrv+rTt1apkny1sOh3OM", + "bgouAk8cwq1LCvT7/WaCwygYLYIUF0SetjUVyTnIkeMsFtDVtq+Q05bUlCvMGYANEhToUcXVhoX9mi68", + "ZT4V0fC+rVJ1o8FFOPSOe08GTwY/bDUOq0e9l/oVJKVkevHOKBsXi0QVS56VNn4AlZB5Bn9dvmumdYEn", + "pkAlyKq3/euVkDnVvePeX//+viqugUNg6/oY35qhXEzjwkQBXM2TRsQpLVivsT29HwZPBj+hUV8AN43H", + "vZ8GTwZPjDigeoYLqSoTmH9PfZnRjGZdSe6KR+ruKVIItKFckRJ3Xo3FDwbkD8rp1Eh3BTDkNMuqp566", + "bCdW9qNJpmA5Zu1Psn4iWmBxnIWNF234gclESCvcbPokJvhJ2jvu/Qr6mVtUf6UeXSCT3LLL0UrNGINw", + "uvW3FZ2693eFgLo/YKFN5+62wswO83EFdbo/UaXZ6/xAVabr28e1YjE/XmGRjxUA7Kn08eY/G2VFfAPV", + "MzsynZq8j9TT4Pp/fjRrb3L2Pz+atWk6NZTWCC/4iCc2ysNaf4iUTQxaWGEcl+gLYc0Dlj4g54CwIKc8", + "pVrIhUsDZNU/esGsvehGebp0cjywFsyDFXiBdgWGSWD1HCbBjfJapPDyMyQGRj4XeYH/rvNJ4Ftr7mMZ", + "0wtMl2Heo5fFNnwM+VaoBkc6z8t/iHSx04f3+XzXkKWtQ9LYRcL8JUhqu28t5AQuiG0jD7HEgtnIer/q", + "XXy0VZ14s0atdnI5Kb+LFzwv8BH8z10I3nRaVlHa1veHRumjbX1/apQs2tb359ti0NLDn67ajw21rNRT", + "v6ogN2PGEsP0fU0ToVnuh6QCKjNwLFKL7rmjTVtesS5D5lLIPnV3qSBLlbE6lXm1ZfYmrx8P+ZA/rorY", + "WImA7pvjpTghgtssFHWhnlVHbB/78SkRfMiJ7WovWhiyf/j4cSYSLJ0npB0K6/thLSBFpmwO3BjAkqWm", + "r2Tpo4EZpilTSC1SOokRN6+BWZmr/kMzwWFjTWCgQdZYiIMhNtGPXYM7ICA1dsHM9TRj87pIqEHj5Ic/", + "k5zxUpsP9Y7m1jPMJDqg1GBlk91cmgho0GW9ZhaBJTuROeTPkgQKswZHOscY0mseM7ivb/+yTts+mUiA", + "L+CMTnph7wu7dQ55VbXTfvSn+CjG/NlRMDmC/WdxPnX/oDqZ2X/aW3hDnswgMf3UQtnQ4z5RCeUqUSww", + "AVwLaSQZc0sZ8oe2vm9/Wee3X6UVs7kwLYdZw1fVR37uOB8P/Yb8TcU4ruKoWtYeQDattg4Z9NeXSy48", + "+srSb8iKhpTdhSgsT4hHR8SVAqTZBV2oevAfnzzpB96gCOM2Z7dN3ceXV68KtLsnpXJJoRdYSFBKIZ/W", + "dR1TNpmAtIyXLYbcMREekIKcIpzWAodtEr3BwjX/edVseQVadukdbK3GslINzQjabkVc1h5b8yh+vA0V", + "+X796yJv1lL6qRMq9vYq5ZV3rqKMId8gDVJThhWZk1LRTNWEYD7dASplV/9vW99fbkWBf+v3Vrjd6vIM", + "tMer+wJ/b6gUnw1LnA27Id2dUTvkOwNjBPRudKZIJqZTSG2VWUps5hvS9EGZTpAzXQc9rHK7XYblqE07", + "txsw9tQd37Hk+Pdac5fMhRVGutfDKLeASL3OmBdMFRlduMTQ9SVXvClUh0tsJ+shb/pmyCVcM5dzyNwe", + "nfaj6+eqXD975MnZa6MSdRLGi+Fl9qCDteJpG2WIfRXRzFgiRico8rAufzmqWuk4g0cGudrsbEPuzvrs", + "BXqm1TJhncQ/0WRhqjoTrMIXE5plIJ+S3ImDITfcjiVR9KxO97bJzWaqL3FV0cN699ns9lhHdQRyyDoP", + "x2V2bnRQ/siCLVtO3zbWiSyMsnPqc85Sg8DgU0kRtSWSaZCMkocs7ZO6omd/WSvYeiVcW2Vh98n/+z//", + "9xGyoZ1qajgTOS6nC6tEbQOyorhwE15TthwgtRYFspdyKnrpSmhBgXavrsq32rFa6vcURG25KTPaNTzp", + "2w14WiNO3Qmn4qEhfMasWFNH7Q09Visww6VzJnVJM/IAu62cVdgw87UQ4crV0qlOcYv+iqeDh627Nmus", + "7/+J33MMpzWgzEb31coreGx2tZJ9TBV0kdtrRbqXsRfXXoL7e5TKZbXHajxb9YZ4gHe7qmUJAndx6SEz", + "heCXU0RUKTZ1WVWZdihsyFdhGAmhMK8fz55iDPml/XhYo3+bewSRLEsbmnTA0kfRkXdnjqHbHQSVodPw", + "/G1iqiDeuU3qiu63O4ut9j2ww4vDPqyirweqwVNrhz5tamDIKzxkhLyEldx2zllwVDsPamSFWbmorg6L", + "LpieuZGMAcMUmdOM4eWPZWB5hYtMc5LRvPBrkxoz3rou2R+4eoCINALPA1HZCFKLoqufcvlNSGIA6orL", + "8qUtFq6ruE93hvyAFsWDId+IAnUHexhXthYRWp0706J4Wl1LAVuF1uYF5GRGeZrZuygvXv7+8v1Lgus4", + "+kqLYsTSby1Q1Sz3qjjc3VZYk01FgdvTC1Z82uxvyyt54z0P0j8Yg0NuxEdZFwQg1JL1Jna2v0dP4QGj", + "2aI4TD+hR2X4Ed81iGRfsslRKnIayMFsmjEJk6tcsQmmWtO1rrnhzCRuwgG3hWzw4vN+C+l9j8prgorL", + "oaQwDtlq5DSBAYbbL5GFx8yxs7xRt1l7RcZG6cm99pQdovqvvWpF0TD+Awjg9gltVw/ax1sVjAfoEnpu", + "Pfc+K62FPJz23RNBdNDqP+r6u+AIqXX9Ec1HbD1tp1cSn2KeCmI+MWGTlexc0vpVVyKMbS64rSDBCu5n", + "+clpYwoHjxfceC7dSTw/20KDdTqqsAfApRqoLnp1pKvXOPDBoYLoiYhh7VfOZEU5zprJdVq8bT5wtXza", + "lYMMsNzb5msi50XOi5zX5Lyjr8g9290smiZ4/Xmd7+yh9U7+lwZL7gVHrr4S6Wr1pZgU3/vCavMOM2iq", + "8SFIil8Y0mi2fIc34JkOsokWu/jlI4vsIYtQfbgsclge/yNMJbgtu5wWkk6BpEydOyazj5ESb3pUt+k7", + "2mb/ZV8ZIWKEiBEiNpxnlzDOmq63VuPstPmayHmR8yLnNTlvV+Nsg+8uYZztld/7PiPP09XcQNE+u0r7", + "bJNTdrPPIpfsJ5dEE+3GFFVVl6lTCvDdj8reVcNHWBhh4X2FhaP1Q7Kr8c+339JYOzG7svig0dZLGGvs", + "uxEMVKuq4w4az67e6b2tYcNWKNQv+Bgvf0SnvQcUBi9PRr6JfBNh4lJxrTsQr9B30a691lyKkQsjF0aX", + "RgftFfkm8k3UXr0jLCrQ8eTZ9fU5MKqWeAE4prm9Diot9eyoqo/tVwynWGkR6tI25hHg2m1FSBOUevba", + "yuHrvRdkphQu3tgU03VPn3S+EWnc75VllySA2MtVXPzYQYJXxXv28vYu0mN3AjXU5WgTKwV1ubNrI3c2", + "8i8/MD+PvCXsGslLbAkMT/YS8/Rq+hISzF4y5Ha2R1/dO1sSmLzAZV1ZsmT7Pu8F03PCUsOpE9Ys6RnK", + "POkGitjl8FMfp47ENuBERXsRTRwumjDf8ODzDluRzTj+HwWAD0Vcg6ikWSYS89ekqoDMuP63n5fisZlc", + "DR8wCDyQQw07mNlIswky3CeFedsQ4TLXDfHub1svPL4+/WC1b2yVtG1sxb7ALltlP26XLMduVWtbHFMe", + "337K4zUY0x1+2TT4IW5eQp9t5/CbuMVz+r4koBu/+xxTB+9ah8HVnbSFDOsyYamlBS9EuTUaiSEadxUL", + "7X2YxgRL2nezd23fsIn5yo11ndXO7TuWTnOs02wnRjI6hmxfqpTHA6b90QWTmjA35P6SZqNxergC2X7F", + "A013WclVV70NRVkKE8YZev/yUmkyBlJy9qmE0BnoVcveyQir8XtmLbIy50RMyGSExRdc6X6cNr4BFNHC", + "dxI6GYnCN2BeUMmU4MQuSxhkBbzMzUb+pdfv/X7yny97/d6wfPLkJ6j/8ZfqX0n9D/PTyeuGeG++Gye7", + "+fr3u65hTrPSM87fzM9EC5vmXtohE7tZvqHWtFI1v369826/lq+87cyguzBZzBLaHXsdfbX/6Gz4VoTK", + "UyytaC8N5LZGqqiUHWjVCtO2GTsOaC3NHfJwCnzkRh/YcIXJCDFXoIBCvaxYk+eO1eSpSLA9hegVEdqV", + "Ulc0te8usjvIALg/RMomDZZaIj8LCCWoMsOCog1M2KyWQ6gigg95YuAkE/yYnHNxwW1lLFQSFazqL4uT", + "WmDSJ1y4arzu7bYqD5beoTmsTObMCfszLMazUvPHnlbXXVsh6n7rnSuGzh74aJ0UnnAXo4YgtRfNKPn5", + "yRMbBYD9t255G9y+RijdBo/3LNft4aHXOxSV2MCk3QGuAr3V1wj6JtyNCrTX42h+R5kTfY4RJvt9jj4z", + "bOl2hFiP+07gUwX6sJ2PAVnb8CxepaQ1lFWHiKzO67WBnWLScMgZIasFQXgLKHx9zTYIxAuDzMsUUtvG", + "2/4+g7r63HI4pggl+ETjx4fvzatfPWr4Jt/3+r1XXojUUZWYEc029JcrIJQvUXr99tsp73aFdB8R1bUh", + "qsp9aMh8Nw+ioUWfE9H8JmECEngCahsA62bQIV/5bTrQtVlXyYVWw84uNPoU76ZP0RBKF7figVBe9Dfe", + "aTx3F1yOWzhuBQMejLC/cpi6BVduw4TfruH21z3GZ/uFuY7gcyGkDt66fYnNKwzHOKHkr+/evCY2zL2u", + "jp/BMtcYy/E5e+9LtupC+4r7gMU6Ub3bjv269Rqmn0YUZtijhAElM5alFRkZQ5iuGIlh+gjGuUXIFCHT", + "FTHdnTmr7cSsR18nnTMbu9NVmxKohWPXTOtdTkxvnWev/hg3Wvl3MM+PYwUtWhlhxeiIbHBbgQyZmK4F", + "ETx7/aLXN/8lr98YW+fNKf4H//IHCwijtXxXRb/dVkKMeAJ6s5rSHfu3I9tlXwI8oYUqM4xuGi+w2V3g", + "g3Q3vOs9YI2QN0Le6CXclYWPvqLx2RXz8lU2Xno+LgeCO/ge31IJXDd9LPuDA5437farmFr1LSJAviMA", + "+eWSW9YchbtD5cgsV8UsEUbHLJ+HFP3RvfZ/TnUyY3za2YPcqfh/BNN3Ckw7z8ueoW9DiXceeO9Yn2hn", + "du5aoChydOToa+doR4x3nqmxsnOQo6tQuIsZyDUjQJFSQUoeLm3qlfhg1SeyzMD+K5lBck70TIKaiSxV", + "j1rlwAecUowbaOzGnSLBUacMT+3nlF2uYV19ApIrSv/kIrWu8XbXpKbmSUxlHI81d7lSs89c03BbrCFP", + "MWUJzep75eRfgnGjj/SMqcZO6BmQQsKciVIRwaFxdeY7/B9rfiyh7JX4lUtBVaZ1zwWaRvbYKBeiXLgW", + "XbvlnvMp5GK+CvAauK6tvuWG4LjKW3nWSxpkinWv7Cpr+BkCYSVwHR51ww/dZdg1Plt7R39tJZHv4imK", + "PUXhzVwnu+jnvWez71PW7g7tir4GruXiJjR2sn7aY1V3sSYYvBo8Spd4HLMPxzESv2R6NGNpCnyUAy9H", + "LgH59sgn07tOV25HWOb4wcaJkATmIBe2PuCA/EE5nYJUQ64ACM0y26CeumxOpcLrATxbENPBDGQ7mH8u", + "yBgyYSSA8AnAX0G/cuv5DSfzB/DypVtMTFZxH0rLdxcPt8JulpQ7XXS3/BLE07/aka4zg9BakU+f8sZy", + "n6EHRQZHQT11qykgTvhEHMbNwv0qTFFl97BkvBTmJKGcdJHnNkHfLgK9pvMovQ9XeuNLDr8EV1AkG8vr", + "igXyymS+dsvT83KFPwlLycOqTKNbA+NKA02NAWOzEj3yej4km7MMph7R/uD9A1eXpu5k39YnD149sDx/", + "wRTcIWWxA/He2yJYVqIffa0Ken/rDnEwZ09CVUJTVzgUMK1PDvkYpJqxok9oUaijiZC5OqoOi49ykbp/", + "DnldgZ1lzDAQjlmU4+qLqwE5tfRiC5biJ3XKa0nITePEKDQ3Gcqd8eJRaWYwLvjjNWbw6Lb3eCk+L21u", + "2wcvjU00FunigduFhHIusFqCfW26BfptO/f+1YmA5Zk3LfXMFs5z592G5wJH3XVh9n055o6I7bLZiSx5", + "LZXLjqjN2umXQm17SKIxHOvOAsfDzmeE1PxANfi0DWbuq/C/CeB7zeA0gs/DB59HBi9u916bXkvNRpgi", + "NY7MwBBSu6oc8ivxWOMXflYUKqrLqC5vxEu+J0waOHEKWY0f+IylxmqsD50WKOxrfrNFRww32sJzM5Gl", + "G9bekDfMPdOfJlVZkkxMp5Ci6UhJMqN8amw7w2v2W5g+kDO93TbrcPh0d/R1/f0WHniz/FTnsMBU0fgV", + "t55cNwaNp9SHf3DQ/ay4wc1N3XtNp8UHw61REcfj6j0xWX/bay1cm8hRBwd1cNTA98kWXp6TdIjnqvva", + "0xM1g7QKr3TcfQrma2C9t2YDKtwhR763WldtUbt/LOcV9W3Ut/fI8O2Q6MKeK6awL/6pThk0Ip9GPr1L", + "fCo76015Y1rzNOrMyIv3kBe75ZTBdKtVXpndNeeQX713qWuymsiwkWHvEsMi72znVstiNtavulbn8f/6", + "w5Ss5uzEoehlKqhSF0Kid2nIJUyZ0pZlR+ewcJXlFaESCIc5SAKfC6H8jqaKvz+oDrVJInNH5j5c5mYd", + "bywZg5Wwgjwcl9k5Fod6ZPnuAUsfoPORKZJTnlIt5KK6LTsW6cIyZBWrbn7VVE5BE1Y8xT/x3c77q2fA", + "XWGplFBFXrz8/eX7l8RM8+grS7+FD2dPrvnC1Mkqj5v9GDHD4I9imfVYOXRd/bFCkRQ0oFUouPX3NNRe", + "pfJY+DKVGUJMnKfoYiYUBjVZ3We02Drq9euxk3i/6sCVx0mx3+oD5fIuOiR4ivhapLBxcQNPC8fQuAdi", + "6b12o9qShEXTx9Jy7Djkl43+OdkamduqIjzYL6bJv3vVoiuc1LyTgdeDloRhTJ4xEGB1jX9e5iBZYmS+", + "K7/vaJqmqQSlgrJ9R4qcj8z0OOgLIc+VIUzzruV7roRMo3FyN/XL3ic8y8R0i1MC5mYKlXFSP28UhI+/", + "fjcDbuGwyvlPtDDDVK+o816vpTPqmpz2k/n8jey0dZafyHd3xikgpod5a54uCd3qNhuAZOjRAKmJkIk9", + "CnuQg1J0Cg/6zs6f0DLTQ57BHDLT9YEBIQ/6iMwgL/SiyULGxkmZSqhMw+FgjkWvxuzPxHSUskQ3uKsC", + "QX1snOTae23JtOGivK0WB6beNjVP/E1rLoTq7R9v+cpSvK20VQUdfTUfy9lEW9DiigqyhN9AjgGdtE0l", + "/V4P1cR+mZiGLRE74wjzoro5AJxX2S8owL2K6gUkGcVaBa7vWoqI1/ZXT5KIM/fAmXVNjF1So5O385+r", + "sSpjCZ0Qpn9O1fnZU3I2hinjZ31yBjw9Q512NpaCpglV+syosyE3+1M2yoemVNMxVebFGmg+avg4zip9", + "qaqokoRmGUi8R8xyKhfuRHtAnmHGSAMkKa9nRzMJNF2Q1O5Fag/KJ1iv4YLpGaHk5ye/hPTq62qPryy9", + "qMhz99iGEpxSDRfUE96M214tiHHFnLfHfQnfVV8r0Hxa2H4oTzJOCRP2mWTApygSc/qZ5WXeO/7px34v", + "Z9z+8cSX57Oah3/ia/TSt/kSP9O8yID88MuPgx/+7d8HPzwZPAmk6RG+uTJhWIjQXPApEXOQGS0KY2jw", + "5RerV/DLL9tWUMx9Zx1/+/3Z65WkcI0n1ul08+k3cko5U0gX1J3qEq/3LvQZ18DPsl/1EW8bBjn2OBw0", + "tPe5Suu42W5e5M1jSIey288ih9yIZc9ZpHm662nkkNvZHn117/xGHq7lOPoToWXKNKK6P/luujwK+5mr", + "cNyrkbsN42N1P1+jo3LDXY3+CPQSOnfEFtZ0w8fzzft1vskdkW7YJ4Fg8mgqxMqH+54B0imWRS3+KlE4", + "snazByVfqai2B5YjK76WNXmLUhlYWpRZ5s1oT4vCC3ipUqBHwOfh1iBYHjOhRnOQKpSoJ8lKpUGG3FrL", + "L+Bv5RwSPdLC31yUo0RIuymbANQ0p6ytdSLhU3DkXKQBP51p1TNjNbWMPQeeBpYFPMmEKiW0t6pM+M2g", + "yafUv9mzeeDnQogs0DRPE3/LxUiM1YhmIPXIEH5brwsqebhTRpUejUVgNdhqrD5/K1MaOMhRIaT273Ym", + "kpExnQIe12Q0LlmWmr9DHRKUHaFGUVZ3ar3tk0yI8LslTc7DjULkwcYvzM+uOTVr55QnMAKeBvrwckIT", + "XUrwTy2HfDSm/DxAwNi80NDSbKgz1BzkHBSSIUmDjRMpvkCTusdCZED5WocR1Tu70CtpHWhcYm7lf71Q", + "IyqTmfdxoUaJ4ElgVkKNzkHywKYINQpOS6guXOh6tXOhUCMJGVAVbG4RWYW4ADkaS6DnIH/Y3uXHli4J", + "HTMO+oftXdpGKaTQkOjtPaoptfRUZVFkixEf++k5kBUOccfoi+ChRsmo/4srLsQXGGmWBdqLVp2qNNWl", + "8jah0wWnHm5e88n4O5ktWZW4jQ4OeGw2fPH+bIGTnynb1nlBpaRcLwJi7raz8hlQdyou4umW30dzNKMy", + "vaAS2kMtaJa50NW3z0/QGZ5DLuSC1I+HjMfflh2iERnvPFwfHY+p6krDr54jCbN3z9+dkJlQmoxLRWhK", + "C1cmNUDK5hWRjCMZXyMZ107oLs5zTt4UwN/97bl1dgSy80vIjGKvEroNWhzV22IRgl7mDx9OXqy7mj2B", + "CRXwP7RU9dFdvBp46VID2gTOqoDEWGX48UPCcx8pK8a8HJbw7u6XPsgE8x9WPNctcWOVr3pvpXV0n0f3", + "eXSfR/d5dJ9fm/s8usijizy6yKOL/N64yPc/jn3Vf3OEom6bS9I5bmzXgOn8rGqNBnQ0oL+L0ZGS7sq1", + "kXV2y0dsXSN4Ge8UdCk5MbRNmM1i5ixWkJ70g/bKr3nNIMig+clp48V30Icac0jsRowJ5SkzWGFkn2hN", + "rUenilCtaTLDerNa1MGLXGiyAO1aXc4T8yN8TrIyBU8coyPJ59UE3tNpVB1RddzYTeFDY9QZJOfdQJrr", + "GmK4qjVyWuS0yGkeThN5kTHKE2hoxw4FT34FTeoHmlVP7OGjGd+fTgm5sn5prRDbaplspYK3VM/MuCdp", + "L/LVHeMrlPVi4iW2Bsd5BLpBZBNR8rTBbGsXiLkGyWmGGc9BEpBSyJtnN7kbs8nvZLXTyGiR0bowmrwL", + "bNaarwwZq+5LTN8ducqfvSwy0j1mpOcegqrSqB46RuyIDBt4sHaS1A6ULmwV4WBkrlYtVZPVHUGDy2Uc", + "fc1tHsotscZm/YQu129LQQdZbBlN7OGyG2Ay0/8PBdr03yQgz1erJ0dUmSSg1KTMsgVJwX749q8tZGNj", + "bvvThyILn+mNb9gmJKv4wj35fpeLJrzEifqPbbRRyYF4ZcwvVzrZlvL7lHU0KKOq7qKq74Q9KWs1LXdR", + "0/LSSvr0RkX86S4q+vS7FLQ8FPUsL6Wcb/G73aZqPo2KuZMcWQZZho84G64pBxFJRs3vM0jOiSw5saPs", + "6LN6Z18dtXXU1l6vlSOq5nVCj//qQFR3ytS2SALsgkil26XJFzhkjCmIPPmdPGkI6Y7GFXTMX2JjeHZM", + "XhLOXRJZMLLg7pcsKnq6q6y4PQWLZUOlhaRT6J56xZ95JTJhZMLdmPC3Mb2jvMcM3p3QBLpxYFXMoPFY", + "gPVOmj0iA0YGjMGtHu4rurHdyduqfEgLwxWR0yKnxTqgIV5TIOdsq56rEqO53oRxpSlPQBFh64c4Bwyk", + "rR6Yd9XLIkdGjoy6r40fj77a6pfbCyWu82TlB74MZ+4pY65O4l214MY87GbV01DzpGUWrq5olA5ROhya", + "dMAMMeHaju+wHQu3cNt3pbAWCgULngdDfjIhaWlFAWGKFFLMWQppn7gnS65ZRri4IH9adnwIg+mADHs/", + "zIa9Phn2fkyHvUebg4mcaW3GqudRHUUNhvy9+ycW+3fNTCvIJgPyQYFUVX1JYuRNVYiS8tRfKM8OGjza", + "t3vyncemV5aIr9okjzyvts8KnY2d/ulJ3txy8iZnGNtQ7fDAW49sIzogFho7/IQIO6VBaIYFhtR/zGsQ", + "1W5Uu0F+K0ubi7QVh6NGMz0H5A3P3N8NhaXsWanVZraCP80ycQFpMBWO4ayYAOf+yXsxViIDlQBGrsJE", + "gsL8kkXpzcCE7YiFqiN4gvk0LcUJRSZllmEZbEUyox1c0dfma4gCrRmfqsGQr5QDfzNWm6XAfXCr1G8a", + "47lZ9fYNbdyhKMUVKqk+X7dCB74vv1YGvut3t4M2P/27aipXhZl9FXrfeFZAJCRCpivFuQOleWNV3ntX", + "ZsEr7XyaN0DLsVDN4eJSzyc9sJK8f4iUTRZXLLvfCqX3XnL3e5uprtf0GtVgb+hczFgyc2WpcqqTmRkb", + "U05WLzLgaJLR6dQWrbebqWFAhr1//OMf/3j8xx+PX7wY9gxwbv5CZrPjPD9Wath7aj4C5IVeVJ6aJAMq", + "7c6bCQ5Ca1hJxH1lS6DEjItEcK1ruB0Nei1cHfXoZeHl0dfOxbRuAmNuM463yhqPQXzDtvCBWDiHCPsq", + "z0yAGDtivz2gsegGvSdw8yArbd0kNN0XgX8V4DjC2j2BtRHE3l0QWwCnBRtU38ThhA29/+7CEJ7s7cHZ", + "2B54qKvdLMpxxhK3lc1I0W3ovwpKC4P5Rijo1UhTF9R1HI4Ww8MwI/K3mbZuqOggvl8OYrUkyU35EIxc", + "jsD8aoD5K5ZprKu2V0jeffcDcxY/l2CAl5CkrKrgVlHCD8eLKjrWBcqOmKfwiYHfVy6itxR2NXMJFZzF", + "tlILpWmg+pzpkYg8d/PytqeSC1sJt6VLgYFSW9pVW4dgITzTHipladomGXweJUU5mrHpDOvFqpnIUn/5", + "wZUHMnHRuX9OP4/W1+Dtx/jWfuulN1fXM6PBphYayEFL4Wgl2Kn9I3Qo22m6FRlNoJViMChWMcEhPN+t", + "ZRvnyUiLQmRiugh2uKBzCO5zoA7oTZguW4FHha8SlDnpUujc7xRS3nsc253m6xetKE9JQlVCUyD2acK0", + "IhIy3GyX62fQDrK3OU1u40JFDCG7HZDbzA7VyJukakoJQd99JKLoFz8sv/hOaPogfeEf1vF2AwG3YOy9", + "ldBX5ZmJuP6e4PoI3g8RvO8ZYt/7Y4UNdN+xPnkN64Mlyt0X6ValPGKuiLnuyZUsD8dda4ny6gCrjUd3", + "KlQejez7oAa+u1R57ae/XLVyR2U7FSyPWiRqkXurRbqVLK+4Mly1vGK8ToXLI8dFjru/HHfJ0uWB0hrL", + "+leVEl3NerXds71jWfPIypGVIyt/R1n0dUaW18bGp/vNxGs1ViZoovZtioaWTQGe0EKV9gR4uS84rU+G", + "qBvzyujctC2nkcKElpnuHU9opqC/4VuNwiUKl70TLpcsBu/G9NfW2pAa/pLwUdtHhryZOvOVJD94br0K", + "LG+T1l0eAuw9gG/T/S27EXV/FDX3S/dfXYX9MBxYiZbsVKf9MGBBs/h7WObYyr92l65fxnzcrVD8alni", + "wwpN+PnJL136/rJXEWx1+eQl/zQPpgJXte8r71j9fDPaeUfO2bdKzneGc7aqrO/1gH0v+L07bq8IfCPw", + "va/AV9awV+4Ce+V3gt7Tw1fbp4cIeU8j4L1lwCu/A+7eC67ZO7B7GqHuLSspW2tsVz8vyaj5fQbJOZEl", + "3yxVtgvafWenEE9uIqqMqNLPsClT3WMcbecw571w7ZHdIrt9F7sZQrqzLFdXyF2WEdolcdqymmczA4QW", + "JKVqNhZUpn0iQeWC4/8ZnwjbE+OPRxmbQ7vBd+LGPwgfUaxxdK/yNW/wgLGJWbZDSdtI5FFl3sky9I6g", + "76zarDMDdEGqnorXQJMZERNMkmTHCkuH1649AtnIldFuDHLjKoC93lL0Dc6MOjtKhygdDkg6mHeLUiYt", + "+jsoJ+pHLyUqTusXR5kRZUaUGYcoM9rv+NSVnNpEhwEbQJIZ5dPvFCR7fBUoypIoS6IsqWRHVTCji7dg", + "KSjQW34Oi6M5zUogBWWyzU9w6t4TPQWRFyMvBnlxC/YPcqPghGbZVm/dvoP8yIeRD/eID9vxdJAZNzD0", + "LqwZb9BH7ozc2cKdO+WEtHdfaIdYyJjkMfJd5LsNvhvVMViXirzaXrvypB7/qkoltBawXHq8XDnjPtbJ", + "NTpag+RUszmGiDm2/hNZenc2E9NXbccBl1JVLLNvRhwDKRWkhGaCT8kF0zNSi4OW6l7bCnGGxt6Y903m", + "zI8VOfevIidhDU4L1uZssmMs0nmPinTuFhW1JzpppTBcmAXq/oGKXeRhbaE96sIcESdGnBijELfw5sjG", + "LY0yMW3nzk0FVYU8ZWI6IC9pMsOKewvCFKFEsxyIpHwK5GIGElpiGS8oDjXOWktQLHWevQX3u5hG5XcP", + "bLDb5ZOdueOSPLEbK0QOiBxwzRxQ+e+2+hI0nZKH4zI7N6gtfxR2JTjX3dV4DzSdei3v93RKbFvf4Dcz", + "udqH4DWyl9Dtn9WgH6Ppfb/qBH9mSjOOhOO1uv1O5yhpo6S9rkQtz7HCvJWug0BiliuXpynVdHMqryRg", + "rbic/PXdm9fEdNrIWKbp1OceNYO6El6+UnXTMqOSwOdCglJMcCImKLCNda2InlFNEsqxENgYGsXBlt5T", + "LF/X8vJwPdJ1sY89b0LwX8WhxD7I+j3P5GJ+X96w25pJzJCdyyJmHmoHMdVluqvhvG2nEyHavi70szwv", + "iTjofuEgmmWGZB6b7+/EbW6mEoJEgUulERdFXHTtCeyMaMOQkZC4rhDSfghry03fgbCW7Bj1wR3WB4eB", + "qypn567Qqio03YquKh/nlfFs9yCNm2ctN7fIWfcTaVXe/w5gq8EWEW9FvHVreKtFhleQaw8l+EHjr6gk", + "Ivxqwq+vljK6JFl0zlnMl8jqUhOoaAxlo4MMG9WSZwPAbFs01ckL9N/W3mBPvFRN0Vvjpero3Zib8PZy", + "ExrCcQJhEYAlt0QUu0bR3RgR7fXH9qv4D0VaHzWRhvwPaPfbFANXfdC17cBqxzOla9fO0TS7Jk26JRfj", + "r6CdqrRhW5VWZcv7awH52Cnv4p4IyWs3Db9XCjMNufLwQc15VEq68PEFGt1iUn3ElaPjJbFuYncuNJmI", + "kqf7RKZds2z7jzbDAK9LJsLrI9XQe9yc9yTT9ZXbR/cSde5ythPCIfeGWq8K9Ky5QDrQbHQm3CNnwsqh", + "Toc4912RUNh/fT/BUPST34f7+X4WW7kPeYkD1DCGe1d32BvFaB3z1fvWiud9933KCOgOCdCF6NdhuvtJ", + "vRHgRYB3PdqnVMhAX7vcfcG+A/IH5XQK0h4KfVAg3Q8Yia8AMHQB+z4lQs9ADjn+RQTPFtjB8In9Sc2o", + "IQEieMVATBIhp5QzhSRFMzI1YEL1h7zISmW65AqyOSjf+fKvoD/gimIIxCFDO/MND/U6jiHsvnUgMq1I", + "IdncNCAVk2HPNI+G5ZMnPyUsxf/DsDcgp1YhIH03mWrIzQAsgykMyDNOIKcsMzrHjIN6h2YSaLogjJvf", + "jJklYYI5hHAOlPz85JcB+TvTM1HqIaekoEpdCJnaoIUkESV3TK7IuMQLNVxootiUE8ZDURwVm12NcsJl", + "ec9TJkwqHTpR6fcy2tZaLdUHPEgGVGny7ySZUUkTjbLtnRYSUkwkRS5g/GOxIDOqZgNfREcxExxGF0Ke", + "e99dfaDtl4vs4m/7ZlF3nou3i7oq1qOvyO5digWZjo2z1Z3U7JCjniXfo2aH3OlZ0l3NbkPhpk8jdc4x", + "oaWejcyUBizt1/NzQu1iBpwwTQw1U8bNwod82Ptfwx5GRg17CrLJsIeZf1B0lXpmhk6w5DqOilP14G73", + "FWIanogZDsEltCY7jgoJkzBIfwU6mS2ZyXQGCTwBdUzmTLFxBiQRWZlz1Xf/IBPMXKb6JGNzrEMPQw6c", + "jjNIySSj0z6ZsTQF7mALcC0ZqD4ZDAZDPuSnoEuJHEogL/SCWJVlWbieyYwqwkVzQkShfu0bmTbkNFNi", + "7ZFUgMIjVcQjhu2Z/btaiIu1TGiWVfzuFU1vccvusny6bl7CHTwgAP6OzuEmuSCIiu8J6V0F7K8cUTRN", + "mYUhbxvtdhprIRczWBEoVvD0nWAhc5BjqlneAOzLEJCy9AVgvynopxKIAp6ufBICyUxAauyq6muMUBCP", + "bD74IYc5cPNqQShJMgbcJiNgUy4koPEnLjgpMXjO7n+7HYC7cdtmwAmfiMMwAW5FNc9BKmb306uMJWpG", + "QgtGqq4eDfW3uunavmP19qsR3PV20IKOWcaQQT9+szsr55WMK2XWO+4NjnrfPn77/wEAAP//", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index 93aace64..72330e01 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -716,7 +716,11 @@ type ListMeta struct { IncludedProps *[]string `json:"included_props,omitempty"` Limit *int `json:"limit,omitempty"` Offset *int `json:"offset,omitempty"` - Total *int `json:"total,omitempty"` + + // Total Number of rows of the list without pagination, the filters applied; for + // a grouped list, the number of groups. With stats, the number of rows the + // statistics are computed from. + Total *int `json:"total,omitempty"` } // ListResponse defines model for ListResponse. @@ -1166,7 +1170,10 @@ type GetActionsParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -1220,7 +1227,10 @@ type GetActionParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -1244,7 +1254,10 @@ type GetAlertEventParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -1278,7 +1291,10 @@ type GetAlertsParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -1315,7 +1331,10 @@ type GetAlertParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -1360,7 +1379,10 @@ type GetAppsParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -1406,7 +1428,10 @@ type GetAppNodesParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -1430,7 +1455,10 @@ type GetAppPublicationsParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -1454,7 +1482,10 @@ type GetAppQuotasParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -1478,7 +1509,10 @@ type GetAppResponsiblesParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -1502,7 +1536,10 @@ type GetAppServicesParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -1562,7 +1599,10 @@ type GetArraysParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -1598,7 +1638,10 @@ type GetDisksParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -1637,7 +1680,10 @@ type GetDiskParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -1667,7 +1713,10 @@ type GetFiltersParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -1709,7 +1758,10 @@ type GetFilterParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -1753,7 +1805,10 @@ type GetFiltersetsParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -1792,7 +1847,10 @@ type GetFiltersetParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -1825,7 +1883,10 @@ type GetFiltersetFiltersParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -1858,7 +1919,10 @@ type GetFiltersetFiltersetsParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -1891,7 +1955,10 @@ type GetFiltersetNodesParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -1928,7 +1995,10 @@ type GetFiltersetServicesParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -2019,7 +2089,10 @@ type GetFrontendHiddenMenuEntriesParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -2052,7 +2125,10 @@ type GetGroupsParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -2090,7 +2166,10 @@ type GetGroupParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -2123,7 +2202,10 @@ type GetGroupAppsParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -2153,7 +2235,10 @@ type GetGroupHiddenMenuEntriesParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -2183,7 +2268,10 @@ type GetGroupModulesetsParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -2207,7 +2295,10 @@ type GetGroupNodesParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -2231,7 +2322,10 @@ type GetGroupRulesetsParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -2255,7 +2349,10 @@ type GetGroupServicesParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -2279,7 +2376,10 @@ type GetGroupUsersParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -2309,7 +2409,10 @@ type GetIpsParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -2333,7 +2436,10 @@ type GetIpParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -2360,7 +2466,10 @@ type GetLogsParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -2393,7 +2502,10 @@ type GetLogParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -2447,7 +2559,10 @@ type GetNodesParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -2565,7 +2680,10 @@ type GetNodesHardwareParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -2589,7 +2707,10 @@ type GetNodesHbasParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -2613,7 +2734,10 @@ type GetNodeParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -2717,7 +2841,10 @@ type GetNodeAlertsParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -2741,7 +2868,10 @@ type GetNodeCandidateTagsParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -2765,7 +2895,10 @@ type GetNodeChecksParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -2789,7 +2922,10 @@ type GetNodeComplianceCandidateModulesetsParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -2813,7 +2949,10 @@ type GetNodeComplianceCandidateRulesetsParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -2837,7 +2976,10 @@ type GetNodeComplianceLogsParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -2861,7 +3003,10 @@ type GetNodeComplianceModulesetsParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -2888,7 +3033,10 @@ type GetNodeComplianceRulesetsParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -2915,7 +3063,10 @@ type GetNodeComplianceStatusParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -2939,7 +3090,10 @@ type GetNodeDisksParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -2963,7 +3117,10 @@ type GetNodeHardwareParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -2987,7 +3144,10 @@ type GetNodeHbasParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -3011,7 +3171,10 @@ type GetNodeInterfacesParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -3035,7 +3198,10 @@ type GetNodeIpsParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -3059,7 +3225,10 @@ type GetNodeServicesParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -3083,7 +3252,10 @@ type GetNodeServiceParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -3113,7 +3285,10 @@ type GetNodeTagsParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -3143,7 +3318,10 @@ type GetObsolescenceSettingsParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -3179,7 +3357,10 @@ type GetObsolescenceSettingParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -3218,7 +3399,10 @@ type GetServicesParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -3284,7 +3468,10 @@ type GetServiceParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -3335,7 +3522,10 @@ type GetServiceAlertsParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -3359,7 +3549,10 @@ type GetServiceCandidateTagsParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -3383,7 +3576,10 @@ type GetServiceChecksParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -3407,7 +3603,10 @@ type GetServiceComplianceCandidateModulesetsParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -3434,7 +3633,10 @@ type GetServiceComplianceCandidateRulesetsParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -3458,7 +3660,10 @@ type GetServiceComplianceLogsParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -3485,7 +3690,10 @@ type GetServiceComplianceModulesetsParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -3524,7 +3732,10 @@ type GetServiceComplianceRulesetsParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -3560,7 +3771,10 @@ type GetServiceComplianceStatusParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -3584,7 +3798,10 @@ type GetServiceDisksParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -3608,7 +3825,10 @@ type GetServiceInstanceParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -3632,7 +3852,10 @@ type GetServiceNodesParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -3656,7 +3879,10 @@ type GetServiceNodeParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -3680,7 +3906,10 @@ type GetServiceNodeResourcesParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -3704,7 +3933,10 @@ type GetServiceNodeResourceLogsParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -3728,7 +3960,10 @@ type GetServiceResinfoParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -3752,7 +3987,10 @@ type GetServiceResourcesParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -3776,7 +4014,10 @@ type GetServiceResourceLogsParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -3800,7 +4041,10 @@ type GetServiceTagsParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -3836,7 +4080,10 @@ type GetServicesInstancesParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -3873,7 +4120,10 @@ type GetServicesInstanceParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -3897,7 +4147,10 @@ type GetServicesInstancesStatusLogParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -3921,7 +4174,10 @@ type GetServicesStatusLogParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -3951,7 +4207,10 @@ type GetTagsParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -3994,7 +4253,10 @@ type GetTagsNodesParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -4039,7 +4301,10 @@ type GetTagsServicesParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -4105,7 +4370,10 @@ type GetTagServicesParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -4134,7 +4402,10 @@ type GetUsersParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. @@ -4170,7 +4441,10 @@ type GetUserParams struct { // Offset Skip the first entries of the data cursor. Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` - // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit the meta field. + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. diff --git a/server/handlers/get_alerts.go b/server/handlers/get_alerts.go index 9b8a8e68..cb38154b 100644 --- a/server/handlers/get_alerts.go +++ b/server/handlers/get_alerts.go @@ -67,7 +67,7 @@ func (a *Api) handleAlerts( return JSONProblemf(c, http.StatusInternalServerError, "cannot build select clause") } - items, err := fetch(c.Request().Context(), cdb.ListParams{ + dbParams := cdb.ListParams{ Groups: UserGroupsFromContext(c), IsManager: IsManager(c), Limit: query.Page.Limit, @@ -77,7 +77,8 @@ func (a *Api) handleAlerts( TypeHints: buildTypeHints(fetchProps, mapping), OrderBy: query.OrderBy, GroupBy: query.GroupBy, - }) + } + items, err := fetch(c.Request().Context(), dbParams) if err != nil { log.Error("cannot fetch alerts", logkey.Error, err) return JSONProblemf(c, http.StatusInternalServerError, "cannot get alerts") @@ -91,5 +92,9 @@ func (a *Api) handleAlerts( return JSONProblemf(c, http.StatusNotFound, "alert %s not found", itemVal) } - return c.JSON(http.StatusOK, newListResponse(items, mapping, query)) + response := newListResponse(items, mapping, query) + if !isItem && query.WithMeta && !query.WithStats { + response = response.withTotal(listTotal(c.Request().Context(), log, fetch, dbParams, len(items))) + } + return c.JSON(http.StatusOK, response) } diff --git a/server/handlers/get_tags.go b/server/handlers/get_tags.go index 1789a495..719041bd 100644 --- a/server/handlers/get_tags.go +++ b/server/handlers/get_tags.go @@ -41,7 +41,19 @@ func (a *Api) handleGetTags(c echo.Context, tagID *int, query ListQueryParameter log.Error("cannot project tag props", logkey.Error, err) return JSONProblemf(c, http.StatusInternalServerError, "cannot project tag props") } - return c.JSON(http.StatusOK, newListResponse(filteredItems, propsMapping["tag"], query)) + response := newListResponse(filteredItems, propsMapping["tag"], query) + if query.WithMeta && !query.WithStats { + total, known := totalFromPage(query.Page.Limit, query.Page.Offset, len(tags)) + if !known { + if total, err = odb.CountTags(ctx); err != nil { + log.Error("cannot count tags", logkey.Error, err) + } + } + if err == nil { + response = response.withTotal(&total) + } + } + return c.JSON(http.StatusOK, response) } // GetTags handles GET /tags diff --git a/server/handlers/handle_list.go b/server/handlers/handle_list.go index 2b22dbf6..31dfd31a 100644 --- a/server/handlers/handle_list.go +++ b/server/handlers/handle_list.go @@ -2,6 +2,7 @@ package serverhandlers import ( "context" + "log/slog" "net/http" "github.com/labstack/echo/v4" @@ -101,7 +102,62 @@ func (a *Api) handleList( return JSONProblemf(c, http.StatusInternalServerError, "cannot get %s", mappingKey) } - return c.JSON(http.StatusOK, newListResponse(items, mapping, query)) + response := newListResponse(items, mapping, query) + if query.WithMeta && !query.WithStats { + response = response.withTotal(listTotal(c.Request().Context(), log, fetch, dbParams, len(items))) + } + return c.JSON(http.StatusOK, response) +} + +// totalFromPage returns the list total when the page alone tells it: every row +// was asked for, the page is not full, or the first page is empty. Only a full +// page, or an empty page past the first, needs a count. +func totalFromPage(limit, offset, pageLen int) (int, bool) { + switch { + case limit <= 0: + // No limit: the offset is not applied either, the page is the whole list. + return pageLen, true + case pageLen > 0 && pageLen < limit: + return offset + pageLen, true + case pageLen == 0 && offset == 0: + return 0, true + } + return 0, false +} + +// listTotal counts the rows of a list without pagination, for meta.total. The +// fetcher runs again with the same access control, filters and grouping, but +// selects a window count instead of the columns, without sort and for one row: +// COUNT(*) OVER () counts the rows of the final result, so a grouped list counts +// its groups, as the historical collector did. A failed count is logged and the +// total left out, rather than failing a list whose rows were read. +func listTotal(ctx context.Context, log *slog.Logger, fetch listFetcher, p cdb.ListParams, pageLen int) *int { + if total, known := totalFromPage(p.Limit, p.Offset, pageLen); known { + return &total + } + count := p + count.CountOnly = true + count.SelectExprs = []string{"COUNT(*) OVER ()"} + count.Props = []string{"total"} + count.TypeHints = map[string]string{"total": "int64"} + count.Limit = 1 + count.Offset = 0 + rows, err := fetch(ctx, count) + if err != nil { + log.Error("cannot count the list rows", logkey.Error, err) + return nil + } + if len(rows) == 0 { + return intPtr(0) + } + switch n := rows[0]["total"].(type) { + case int64: + return intPtr(int(n)) + case int: + return intPtr(n) + } + log.Error("unexpected list count", "value", rows[0]["total"]) + return nil } // handleItem is like handleList but expects exactly one result and returns 404 diff --git a/server/handlers/handle_list_test.go b/server/handlers/handle_list_test.go new file mode 100644 index 00000000..0f9d388f --- /dev/null +++ b/server/handlers/handle_list_test.go @@ -0,0 +1,26 @@ +package serverhandlers + +import "testing" + +func TestTotalFromPage(t *testing.T) { + cases := []struct { + name string + limit, offset, pageLen int + total int + known bool + }{ + {"no limit: the page is the list", 0, 0, 120, 120, true}, + {"no limit, offset ignored", 0, 50, 120, 120, true}, + {"partial first page", 50, 0, 12, 12, true}, + {"partial last page", 50, 100, 7, 107, true}, + {"empty list", 50, 0, 0, 0, true}, + {"full page: rows may follow", 50, 0, 50, 0, false}, + {"empty page past the end", 50, 200, 0, 0, false}, + } + for _, c := range cases { + total, known := totalFromPage(c.limit, c.offset, c.pageLen) + if total != c.total || known != c.known { + t.Errorf("%s: got (%d, %v), want (%d, %v)", c.name, total, known, c.total, c.known) + } + } +} diff --git a/server/handlers/list_response.go b/server/handlers/list_response.go index 4aafa131..1bd4635c 100644 --- a/server/handlers/list_response.go +++ b/server/handlers/list_response.go @@ -15,7 +15,7 @@ type listMeta struct { IncludedProps []string `json:"included_props,omitempty"` Limit int `json:"limit,omitempty"` Offset int `json:"offset,omitempty"` - Total int `json:"total,omitempty"` + Total *int `json:"total,omitempty"` } type listResponse struct { @@ -102,7 +102,7 @@ func newListResponse(items []map[string]any, mapping propMapping, query ListQuer Data: statsData, Meta: &listMeta{ Distinct: distinct, - Total: len(items), + Total: intPtr(len(items)), }, } } @@ -125,3 +125,15 @@ func newListResponse(items []map[string]any, mapping propMapping, query ListQuer return response } + +func intPtr(n int) *int { return &n } + +// withTotal sets meta.total, the number of rows of the list without pagination, +// as the historical collector returned it along with every paginated answer. A +// response without meta is left alone: meta=false asks for the rows only. +func (r listResponse) withTotal(total *int) listResponse { + if r.Meta != nil && total != nil { + r.Meta.Total = total + } + return r +} From 48b0093b78b579503e74dc7fa537fe775d9c18f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Thu, 24 Sep 2026 16:51:53 +0200 Subject: [PATCH 28/61] Install git in the image The sysreports history is committed with git, and so is the history of the form definitions: the image only had bash, so neither could work. --- Dockerfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 32937aed..33139812 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,7 +21,9 @@ RUN echo "Cache busted at $(date): oc3 version: $(./dist/oc3 version)" FROM alpine:3.22.4 ARG BUILDTIME -RUN apk add --no-cache bash +# git keeps the history of the form definitions (forms revisions) and of +# the sysreports. +RUN apk add --no-cache bash git COPY --from=builder /opt/oc3/dist/oc3 /usr/bin/oc3 From 0832d25391ee21286ac398f3b2a5842b47ef7f7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Thu, 24 Sep 2026 16:51:55 +0200 Subject: [PATCH 29/61] Port the /form* endpoints Port the forms API of the historical collector (api_forms.py, the forms part of api_workflows.py and lib_forms.py), keeping its behavior: - /forms and /forms/{form_id}: list, show, create, modify and delete, with the FormsManager privilege, the publication and responsibility checks and the collector's messages. The body may be one entry or a list, JSON or form-encoded. form_definition is form_yaml parsed. - /forms/{form_id}/publications and /responsibles, and the bulk /forms_publications and /forms_responsibles. - /forms/{form_id}/am_i_responsible, answering {"data": bool}. - /forms/{form_id}/revisions, /revisions/{cid}, /diff/{cid} and /rollback/{cid}, over one git repository per form under server.directories.forms. - PUT /forms/{form_id}: submission. The data is validated against the form inputs (conditions, forced keys, strict static and dynamic candidates), a results record is stored, and the outputs run: db, rest (calling this API as the submitter, or an external url, with the vm2 mangler), script, mail (server.mail.*) and workflow. Async forms answer at once and run in the background. Internal forms, the negative ids, are embedded. - /form_output_results/{results_id} (GET, PUT), /forms_revisions and /forms_store, with /forms_store/{store_id}/dump. List endpoints may declare virtual props, computed after the fetch from the props they require, as the collector's vprops. --- cdb/db_forms.go | 315 +++++ cdb/db_forms_store.go | 160 +++ cdb/db_forms_submit.go | 201 +++ cmd/conf.go | 6 + go.mod | 2 +- server/api.yaml | 1184 ++++++++++++++++++ server/codegen_server_gen.go | 1731 ++++++++++++++++++++++---- server/codegen_type_gen.go | 1078 ++++++++++++++-- server/handlers/forms.go | 367 ++++++ server/handlers/forms_common.go | 301 +++++ server/handlers/forms_engine.go | 297 +++++ server/handlers/forms_engine_test.go | 133 ++ server/handlers/forms_git.go | 149 +++ server/handlers/forms_internal.json | 686 ++++++++++ server/handlers/forms_outputs.go | 663 ++++++++++ server/handlers/forms_store.go | 297 +++++ server/handlers/forms_submit.go | 529 ++++++++ server/handlers/forms_team.go | 235 ++++ server/handlers/forms_validate.go | 224 ++++ server/handlers/handle_list.go | 71 +- server/handlers/props_mapping.go | 82 ++ util/git/track.go | 262 ++++ 22 files changed, 8622 insertions(+), 351 deletions(-) create mode 100644 cdb/db_forms.go create mode 100644 cdb/db_forms_store.go create mode 100644 cdb/db_forms_submit.go create mode 100644 server/handlers/forms.go create mode 100644 server/handlers/forms_common.go create mode 100644 server/handlers/forms_engine.go create mode 100644 server/handlers/forms_engine_test.go create mode 100644 server/handlers/forms_git.go create mode 100644 server/handlers/forms_internal.json create mode 100644 server/handlers/forms_outputs.go create mode 100644 server/handlers/forms_store.go create mode 100644 server/handlers/forms_submit.go create mode 100644 server/handlers/forms_team.go create mode 100644 server/handlers/forms_validate.go create mode 100644 util/git/track.go diff --git a/cdb/db_forms.go b/cdb/db_forms.go new file mode 100644 index 00000000..d8215b1a --- /dev/null +++ b/cdb/db_forms.go @@ -0,0 +1,315 @@ +package cdb + +import ( + "context" + "database/sql" + "errors" + "fmt" + "sort" + "strings" +) + +// Form is a row of the forms table. +type Form struct { + ID int64 + Name string + Yaml string + Author string + Created string + Type string + Folder string +} + +// formCols lists the forms columns a caller may set, as the historical collector +// wrote any posted key to the table. +var formCols = map[string]bool{ + "form_name": true, "form_yaml": true, "form_author": true, + "form_created": true, "form_type": true, "form_folder": true, +} + +// IsFormColumn reports whether a posted key is a settable forms column. +func IsFormColumn(key string) bool { return formCols[key] } + +// formPublishedCond restricts forms to those published to one of the caller's +// groups, as the historical collector does for a non-manager. +func formPublishedCond(formIDExpr string, groups []string) (string, []any) { + if len(groups) == 0 { + return "1=0", nil + } + args := make([]any, len(groups)) + for i, g := range groups { + args[i] = g + } + return formIDExpr + " IN (SELECT ftp.form_id FROM forms_team_publication ftp" + + " JOIN auth_group ag ON ag.id = ftp.group_id WHERE ag.role IN (" + Placeholders(len(groups)) + "))", args +} + +// GetForms lists the forms visible to the caller, one form when formID is set. +func (oDb *DB) GetForms(ctx context.Context, formID *int64, p ListParams) ([]map[string]any, error) { + if len(p.SelectExprs) == 0 { + return nil, fmt.Errorf("getForms: no select expressions") + } + conds := []string{"forms.id > 0"} + var args []any + if formID != nil { + conds = append(conds, "forms.id = ?") + args = append(args, *formID) + } + if !p.IsManager { + cond, condArgs := formPublishedCond("forms.id", p.Groups) + conds = append(conds, cond) + args = append(args, condArgs...) + } + filterConds, filterArgs := p.FilterConditions() + conds = append(conds, filterConds...) + args = append(args, filterArgs...) + + query := "SELECT " + strings.Join(p.SelectExprs, ", ") + " FROM forms WHERE " + strings.Join(conds, " AND ") + if gb := p.GroupByClause(""); gb != "" { + query += " " + gb + } + query += " " + p.OrderByClause("forms.form_name") + query, args = appendLimitOffset(query, args, p.Limit, p.Offset) + rows, err := oDb.DB.QueryContext(ctx, query, args...) + if err != nil { + return nil, fmt.Errorf("getForms: %w", err) + } + defer func() { _ = rows.Close() }() + return scanRowsToMaps(rows, p.Props, p.TypeHints) +} + +// FormByID returns a form, nil when it does not exist. +func (oDb *DB) FormByID(ctx context.Context, id int64) (*Form, error) { + var f Form + var name, yaml, author, typ, folder sql.NullString + err := oDb.DB.QueryRowContext(ctx, "SELECT id, form_name, form_yaml, form_author, COALESCE(form_created, ''),"+ + " form_type, form_folder FROM forms WHERE id = ?", id). + Scan(&f.ID, &name, &yaml, &author, &f.Created, &typ, &folder) + switch { + case errors.Is(err, sql.ErrNoRows): + return nil, nil + case err != nil: + return nil, fmt.Errorf("formByID: %w", err) + } + f.Name, f.Yaml, f.Author, f.Type, f.Folder = name.String, yaml.String, author.String, typ.String, folder.String + return &f, nil +} + +// FormIDByName returns the id of the form with that name. +func (oDb *DB) FormIDByName(ctx context.Context, name string) (int64, bool, error) { + var id int64 + err := oDb.DB.QueryRowContext(ctx, "SELECT id FROM forms WHERE form_name = ?", name).Scan(&id) + switch { + case errors.Is(err, sql.ErrNoRows): + return 0, false, nil + case err != nil: + return 0, false, fmt.Errorf("formIDByName: %w", err) + } + return id, true, nil +} + +// FormVisible reports whether the form exists and the caller may see it: a +// manager sees every form, others the forms published to one of their groups. +func (oDb *DB) FormVisible(ctx context.Context, formID int64, groups []string, isManager bool) (bool, error) { + return oDb.formLinked(ctx, "forms_team_publication", formID, groups, isManager) +} + +// FormResponsible reports whether the caller is responsible for the form: a +// manager is responsible for every form, others through a responsible group. +func (oDb *DB) FormResponsible(ctx context.Context, formID int64, groups []string, isManager bool) (bool, error) { + return oDb.formLinked(ctx, "forms_team_responsible", formID, groups, isManager) +} + +func (oDb *DB) formLinked(ctx context.Context, table string, formID int64, groups []string, isManager bool) (bool, error) { + query := "SELECT 1 FROM forms WHERE forms.id = ?" + args := []any{formID} + if !isManager { + if len(groups) == 0 { + return false, nil + } + query += " AND forms.id IN (SELECT t.form_id FROM " + table + " t JOIN auth_group ag ON ag.id = t.group_id" + + " WHERE ag.role IN (" + Placeholders(len(groups)) + "))" + for _, g := range groups { + args = append(args, g) + } + } + var one int + err := oDb.DB.QueryRowContext(ctx, query+" LIMIT 1", args...).Scan(&one) + switch { + case errors.Is(err, sql.ErrNoRows): + return false, nil + case err != nil: + return false, fmt.Errorf("formLinked %s: %w", table, err) + } + return true, nil +} + +// sortedKeys returns the keys of a column map in a stable order, for the SQL. +func sortedKeys(fields map[string]any) []string { + keys := make([]string, 0, len(fields)) + for k := range fields { + keys = append(keys, k) + } + sort.Strings(keys) + return keys +} + +// InsertForm creates a form from settable columns and returns its id. +func (oDb *DB) InsertForm(ctx context.Context, fields map[string]any) (int64, error) { + keys := sortedKeys(fields) + args := make([]any, len(keys)) + for i, k := range keys { + if !formCols[k] { + return 0, fmt.Errorf("insertForm: unknown column %s", k) + } + args[i] = fields[k] + } + query := "INSERT INTO forms (" + strings.Join(keys, ", ") + ") VALUES (" + Placeholders(len(keys)) + ")" + res, err := oDb.ExecContext(ctx, query, args...) + if err != nil { + return 0, fmt.Errorf("insertForm: %w", err) + } + oDb.SetChange("forms") + return res.LastInsertId() +} + +// UpdateForm sets settable columns of a form. +func (oDb *DB) UpdateForm(ctx context.Context, id int64, fields map[string]any) error { + if len(fields) == 0 { + return nil + } + keys := sortedKeys(fields) + sets := make([]string, len(keys)) + args := make([]any, 0, len(keys)+1) + for i, k := range keys { + if !formCols[k] { + return fmt.Errorf("updateForm: unknown column %s", k) + } + sets[i] = k + " = ?" + args = append(args, fields[k]) + } + args = append(args, id) + if _, err := oDb.ExecContext(ctx, "UPDATE forms SET "+strings.Join(sets, ", ")+" WHERE id = ?", args...); err != nil { + return fmt.Errorf("updateForm: %w", err) + } + oDb.SetChange("forms") + return nil +} + +// DeleteForm deletes a form with its publications and responsibles. +func (oDb *DB) DeleteForm(ctx context.Context, id int64) error { + for _, table := range []string{"forms", "forms_team_publication", "forms_team_responsible"} { + col := "form_id" + if table == "forms" { + col = "id" + } + if _, err := oDb.ExecContext(ctx, "DELETE FROM "+table+" WHERE "+col+" = ?", id); err != nil { + return fmt.Errorf("deleteForm %s: %w", table, err) + } + oDb.SetChange(table) + } + return nil +} + +// FormTeamTable names the table of a form/group link: publications or +// responsibles. +type FormTeamTable string + +const ( + FormPublications FormTeamTable = "forms_team_publication" + FormResponsibles FormTeamTable = "forms_team_responsible" +) + +// FormTeamExists reports whether the form is linked to the group. +func (oDb *DB) FormTeamExists(ctx context.Context, table FormTeamTable, formID, groupID int64) (bool, error) { + var one int + err := oDb.DB.QueryRowContext(ctx, "SELECT 1 FROM "+string(table)+" WHERE form_id = ? AND group_id = ? LIMIT 1", + formID, groupID).Scan(&one) + switch { + case errors.Is(err, sql.ErrNoRows): + return false, nil + case err != nil: + return false, fmt.Errorf("formTeamExists: %w", err) + } + return true, nil +} + +// InsertFormTeam links the form to the group. +func (oDb *DB) InsertFormTeam(ctx context.Context, table FormTeamTable, formID, groupID int64) error { + if _, err := oDb.ExecContext(ctx, "INSERT INTO "+string(table)+" (form_id, group_id) VALUES (?, ?)", formID, groupID); err != nil { + return fmt.Errorf("insertFormTeam: %w", err) + } + oDb.SetChange(string(table)) + return nil +} + +// DeleteFormTeam unlinks the form from the group. +func (oDb *DB) DeleteFormTeam(ctx context.Context, table FormTeamTable, formID, groupID int64) error { + if _, err := oDb.ExecContext(ctx, "DELETE FROM "+string(table)+" WHERE form_id = ? AND group_id = ?", formID, groupID); err != nil { + return fmt.Errorf("deleteFormTeam: %w", err) + } + oDb.SetChange(string(table)) + return nil +} + +// GetFormTeam lists the groups linked to a form, as auth_group rows. +func (oDb *DB) GetFormTeam(ctx context.Context, table FormTeamTable, formID int64, p ListParams) ([]map[string]any, error) { + if len(p.SelectExprs) == 0 { + return nil, fmt.Errorf("getFormTeam: no select expressions") + } + conds := []string{"t.form_id = ?"} + args := []any{formID} + filterConds, filterArgs := p.FilterConditions() + conds = append(conds, filterConds...) + args = append(args, filterArgs...) + query := "SELECT " + strings.Join(p.SelectExprs, ", ") + " FROM auth_group JOIN " + string(table) + + " t ON t.group_id = auth_group.id WHERE " + strings.Join(conds, " AND ") + if gb := p.GroupByClause(""); gb != "" { + query += " " + gb + } + query += " " + p.OrderByClause("auth_group.role") + query, args = appendLimitOffset(query, args, p.Limit, p.Offset) + rows, err := oDb.DB.QueryContext(ctx, query, args...) + if err != nil { + return nil, fmt.Errorf("getFormTeam: %w", err) + } + defer func() { _ = rows.Close() }() + return scanRowsToMaps(rows, p.Props, p.TypeHints) +} + +// UserName returns "First Last" of a user, as the historical collector names the +// author of a change, and the email. +func (oDb *DB) UserName(ctx context.Context, userID int64) (string, string, error) { + var first, last, email sql.NullString + err := oDb.DB.QueryRowContext(ctx, "SELECT first_name, last_name, email FROM auth_user WHERE id = ?", userID). + Scan(&first, &last, &email) + switch { + case errors.Is(err, sql.ErrNoRows): + return "Unknown", "", nil + case err != nil: + return "", "", fmt.Errorf("userName: %w", err) + } + return first.String + " " + last.String, email.String, nil +} + +// UserEmailByName returns the email of the user named "First Last", as +// email_of() resolves a mail recipient given by name. +func (oDb *DB) UserEmailByName(ctx context.Context, name string) (string, bool, error) { + rows, err := oDb.DB.QueryContext(ctx, `SELECT email FROM auth_user WHERE CONCAT(first_name, " ", last_name) = ?`, name) + if err != nil { + return "", false, fmt.Errorf("userEmailByName: %w", err) + } + defer func() { _ = rows.Close() }() + var emails []string + for rows.Next() { + var email sql.NullString + if err := rows.Scan(&email); err != nil { + return "", false, fmt.Errorf("userEmailByName: %w", err) + } + emails = append(emails, email.String) + } + if len(emails) != 1 { + return "", false, rows.Err() + } + return emails[0], true, rows.Err() +} diff --git a/cdb/db_forms_store.go b/cdb/db_forms_store.go new file mode 100644 index 00000000..f322c3aa --- /dev/null +++ b/cdb/db_forms_store.go @@ -0,0 +1,160 @@ +package cdb + +import ( + "context" + "database/sql" + "errors" + "fmt" + "strconv" + "strings" +) + +// listQuery runs a hand-built list query: the select expressions of the request +// over from, the conditions and the filters ANDed, then grouping, sort and page. +func (oDb *DB) listQuery(ctx context.Context, name, from string, conds []string, args []any, defaultOrder string, p ListParams) ([]map[string]any, error) { + if len(p.SelectExprs) == 0 { + return nil, fmt.Errorf("%s: no select expressions", name) + } + filterConds, filterArgs := p.FilterConditions() + conds = append(conds, filterConds...) + args = append(args, filterArgs...) + query := "SELECT " + strings.Join(p.SelectExprs, ", ") + " FROM " + from + if len(conds) > 0 { + query += " WHERE " + strings.Join(conds, " AND ") + } + if gb := p.GroupByClause(""); gb != "" { + query += " " + gb + } + query += " " + p.OrderByClause(defaultOrder) + query, args = appendLimitOffset(query, args, p.Limit, p.Offset) + rows, err := oDb.DB.QueryContext(ctx, query, args...) + if err != nil { + return nil, fmt.Errorf("%s: %w", name, err) + } + defer func() { _ = rows.Close() }() + return scanRowsToMaps(rows, p.Props, p.TypeHints) +} + +// GetFormsRevisions lists the form revisions, one when idOrMD5 is set: a +// numeric value is an id, anything else a md5, as the historical handler does. +func (oDb *DB) GetFormsRevisions(ctx context.Context, idOrMD5 *string, p ListParams) ([]map[string]any, error) { + conds := []string{"forms_revisions.id > 0"} + var args []any + if idOrMD5 != nil { + if _, err := strconv.ParseInt(*idOrMD5, 10, 64); err == nil { + conds = append(conds, "forms_revisions.id = ?") + } else { + conds = append(conds, "forms_revisions.form_md5 = ?") + } + args = append(args, *idOrMD5) + } + return oDb.listQuery(ctx, "getFormsRevisions", "forms_revisions", conds, args, "forms_revisions.id", p) +} + +// formsStoreFrom joins the stored forms to the revision they were submitted +// with, as the v_forms_store view of the historical collector. +const formsStoreFrom = "forms_store JOIN forms_revisions ON forms_revisions.form_md5 = forms_store.form_md5" + +// GetFormsStore lists the forms stored by workflows, one when storeID is set. +func (oDb *DB) GetFormsStore(ctx context.Context, storeID *int64, p ListParams) ([]map[string]any, error) { + conds := []string{"forms_store.id > 0"} + var args []any + if storeID != nil { + conds = append(conds, "forms_store.id = ?") + args = append(args, *storeID) + } + return oDb.listQuery(ctx, "getFormsStore", formsStoreFrom, conds, args, "forms_store.id", p) +} + +// GetWorkflows lists the workflows, one when id is set. +func (oDb *DB) GetWorkflows(ctx context.Context, id *int64, p ListParams) ([]map[string]any, error) { + conds := []string{"workflows.id > 0"} + var args []any + if id != nil { + conds = append(conds, "workflows.id = ?") + args = append(args, *id) + } + return oDb.listQuery(ctx, "getWorkflows", "workflows", conds, args, "workflows.id", p) +} + +// WorkflowIDByHead returns the workflow started by a stored form. +func (oDb *DB) WorkflowIDByHead(ctx context.Context, headID int64) (int64, bool, error) { + var id int64 + err := oDb.DB.QueryRowContext(ctx, "SELECT id FROM workflows WHERE form_head_id = ?", headID).Scan(&id) + switch { + case errors.Is(err, sql.ErrNoRows): + return 0, false, nil + case err != nil: + return 0, false, fmt.Errorf("workflowIDByHead: %w", err) + } + return id, true, nil +} + +// FormResultsAccess is the caller of a form results request, for the access +// filter of q_filter(user_field, node_field, svc_field). +type FormResultsAccess struct { + IsManager bool + UserID *int64 + NodeID string +} + +// FormOutputResults returns the results structure of a submission, as stored, +// when the caller may read it: a manager reads every result; a user those +// submitted by the users sharing one of their organization groups; a node +// those of its services, and its own. +func (oDb *DB) FormOutputResults(ctx context.Context, id int64, access FormResultsAccess) (string, bool, error) { + query := "SELECT COALESCE(results, '') FROM form_output_results WHERE id = ?" + args := []any{id} + switch { + case access.NodeID != "": + query += " AND (node_id = ? OR svc_id IN (SELECT svc_id FROM svcmon WHERE node_id = ?))" + args = append(args, access.NodeID, access.NodeID) + case access.IsManager: + case access.UserID != nil: + query += " AND user_id IN (SELECT DISTINCT m.user_id FROM auth_membership m" + + " WHERE m.group_id IN (SELECT g.id FROM auth_group g JOIN auth_membership am ON am.group_id = g.id" + + " WHERE am.user_id = ? AND g.privilege = 'F'))" + args = append(args, *access.UserID) + default: + return "", false, nil + } + var results string + err := oDb.DB.QueryRowContext(ctx, query, args...).Scan(&results) + switch { + case errors.Is(err, sql.ErrNoRows): + return "", false, nil + case err != nil: + return "", false, fmt.Errorf("formOutputResults: %w", err) + } + return results, true, nil +} + +// InsertFormOutputResults stores the results structure of a new submission. +func (oDb *DB) InsertFormOutputResults(ctx context.Context, userID *int64, nodeID, svcID, results string) (int64, error) { + res, err := oDb.ExecContext(ctx, "INSERT INTO form_output_results (user_id, node_id, svc_id, results) VALUES (?, ?, ?, ?)", + userID, nodeID, svcID, results) + if err != nil { + return 0, fmt.Errorf("insertFormOutputResults: %w", err) + } + oDb.SetChange("form_output_results") + return res.LastInsertId() +} + +// UpdateFormOutputResults replaces the results structure of a submission. +func (oDb *DB) UpdateFormOutputResults(ctx context.Context, id int64, results string) error { + if _, err := oDb.ExecContext(ctx, "UPDATE form_output_results SET results = ? WHERE id = ?", results, id); err != nil { + return fmt.Errorf("updateFormOutputResults: %w", err) + } + oDb.SetChange("form_output_results") + return nil +} + +// ReadFormOutputResults returns the stored results structure, without access +// filter: for the submission engine, which owns it. +func (oDb *DB) ReadFormOutputResults(ctx context.Context, id int64) (string, error) { + var results sql.NullString + if err := oDb.DB.QueryRowContext(ctx, "SELECT results FROM form_output_results WHERE id = ?", id).Scan(&results); err != nil { + return "", fmt.Errorf("readFormOutputResults: %w", err) + } + return results.String, nil +} diff --git a/cdb/db_forms_submit.go b/cdb/db_forms_submit.go new file mode 100644 index 00000000..9f727233 --- /dev/null +++ b/cdb/db_forms_submit.go @@ -0,0 +1,201 @@ +package cdb + +import ( + "context" + "crypto/md5" + "database/sql" + "encoding/hex" + "errors" + "fmt" + "strings" +) + +// TableColumns returns the columns of a table of the collector database, none +// when the table does not exist. +func (oDb *DB) TableColumns(ctx context.Context, table string) ([]string, error) { + rows, err := oDb.DB.QueryContext(ctx, "SELECT column_name FROM information_schema.columns"+ + " WHERE table_schema = DATABASE() AND table_name = ? ORDER BY ordinal_position", table) + if err != nil { + return nil, fmt.Errorf("tableColumns: %w", err) + } + defer func() { _ = rows.Close() }() + var cols []string + for rows.Next() { + var col string + if err := rows.Scan(&col); err != nil { + return nil, fmt.Errorf("tableColumns: %w", err) + } + cols = append(cols, col) + } + return cols, rows.Err() +} + +// InsertRow inserts a row in a table, the keys checked against its columns by +// the caller. +func (oDb *DB) InsertRow(ctx context.Context, table string, row map[string]any) error { + keys := sortedKeys(row) + quoted := make([]string, len(keys)) + args := make([]any, len(keys)) + for i, k := range keys { + quoted[i] = "`" + strings.ReplaceAll(k, "`", "") + "`" + args[i] = row[k] + } + query := "INSERT INTO `" + strings.ReplaceAll(table, "`", "") + "` (" + strings.Join(quoted, ", ") + + ") VALUES (" + Placeholders(len(keys)) + ")" + if _, err := oDb.ExecContext(ctx, query, args...); err != nil { + return err + } + oDb.SetChange(table) + return nil +} + +// UserPrimaryOrgGroupRole returns the role of the user's primary group when it +// is not a privilege group, as user_primary_group() does. +func (oDb *DB) UserPrimaryOrgGroupRole(ctx context.Context, userID int64) (string, bool, error) { + var role sql.NullString + err := oDb.DB.QueryRowContext(ctx, "SELECT auth_group.role FROM auth_group"+ + " JOIN auth_membership ON auth_membership.group_id = auth_group.id"+ + " WHERE auth_membership.user_id = ? AND auth_membership.primary_group = 'T'"+ + " AND auth_group.privilege = 'F' LIMIT 1", userID).Scan(&role) + switch { + case errors.Is(err, sql.ErrNoRows): + return "", false, nil + case err != nil: + return "", false, fmt.Errorf("userPrimaryOrgGroupRole: %w", err) + } + return role.String, role.Valid, nil +} + +// InsertFormRevisionMD5 records the definition a form is submitted with, once +// per content, and returns its md5, as insert_form_md5() does. +func (oDb *DB) InsertFormRevisionMD5(ctx context.Context, f *Form) (string, error) { + sum := md5.Sum([]byte(f.Yaml)) + formMD5 := hex.EncodeToString(sum[:]) + var one int + err := oDb.DB.QueryRowContext(ctx, "SELECT 1 FROM forms_revisions WHERE form_md5 = ?", formMD5).Scan(&one) + switch { + case err == nil: + return formMD5, nil + case !errors.Is(err, sql.ErrNoRows): + return "", fmt.Errorf("insertFormRevisionMD5: %w", err) + } + if _, err := oDb.ExecContext(ctx, "INSERT INTO forms_revisions (form_id, form_yaml, form_folder, form_name, form_md5)"+ + " VALUES (?, ?, ?, ?, ?)", f.ID, f.Yaml, f.Folder, f.Name, formMD5); err != nil { + return "", fmt.Errorf("insertFormRevisionMD5: %w", err) + } + oDb.SetChange("forms_revisions") + return formMD5, nil +} + +// StoredFormLink is what a workflow step needs from a stored form. +type StoredFormLink struct { + ID int64 + PrevID *int64 + NextID *int64 + Submitter string + SubmitDate string +} + +// StoredFormLinkByID returns the links of a stored form, nil when it does not +// exist. +func (oDb *DB) StoredFormLinkByID(ctx context.Context, id int64) (*StoredFormLink, error) { + var l StoredFormLink + var prev, next sql.NullInt64 + err := oDb.DB.QueryRowContext(ctx, "SELECT id, form_prev_id, form_next_id, form_submitter,"+ + " DATE_FORMAT(form_submit_date, '%Y-%m-%d %H:%i:%s') FROM forms_store WHERE id = ?", id). + Scan(&l.ID, &prev, &next, &l.Submitter, &l.SubmitDate) + switch { + case errors.Is(err, sql.ErrNoRows): + return nil, nil + case err != nil: + return nil, fmt.Errorf("storedFormLinkByID: %w", err) + } + if prev.Valid { + l.PrevID = &prev.Int64 + } + if next.Valid { + l.NextID = &next.Int64 + } + return &l, nil +} + +// StoredFormInsert is a new step of a workflow. +type StoredFormInsert struct { + MD5 string + Submitter string + Assignee string + Date string + PrevID *int64 + NextID *int64 + HeadID *int64 + Data string + ResultsID int64 +} + +// InsertStoredForm stores a submitted form as a workflow step and returns its id. +func (oDb *DB) InsertStoredForm(ctx context.Context, s StoredFormInsert) (int64, error) { + res, err := oDb.ExecContext(ctx, "INSERT INTO forms_store (form_md5, form_submitter, form_assignee,"+ + " form_submit_date, form_prev_id, form_next_id, form_head_id, form_data, results_id)"+ + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", + s.MD5, s.Submitter, s.Assignee, s.Date, s.PrevID, s.NextID, s.HeadID, s.Data, s.ResultsID) + if err != nil { + return 0, fmt.Errorf("insertStoredForm: %w", err) + } + oDb.SetChange("forms_store") + return res.LastInsertId() +} + +// SetStoredFormNext links a workflow step to the next one. +func (oDb *DB) SetStoredFormNext(ctx context.Context, id, nextID int64) error { + if _, err := oDb.ExecContext(ctx, "UPDATE forms_store SET form_next_id = ? WHERE id = ?", nextID, id); err != nil { + return fmt.Errorf("setStoredFormNext: %w", err) + } + oDb.SetChange("forms_store") + return nil +} + +// SetStoredFormHead makes a stored form the head of its own workflow. +func (oDb *DB) SetStoredFormHead(ctx context.Context, id int64) error { + if _, err := oDb.ExecContext(ctx, "UPDATE forms_store SET form_head_id = ? WHERE id = ?", id, id); err != nil { + return fmt.Errorf("setStoredFormHead: %w", err) + } + oDb.SetChange("forms_store") + return nil +} + +// WorkflowInsert is a new workflow, or the new state of an existing one. +type WorkflowInsert struct { + Status string + MD5 string + Steps int + LastAssignee string + LastUpdate string + LastFormID int64 + LastFormName string + HeadID int64 + Creator string + CreateDate string +} + +// InsertWorkflow creates a workflow and returns its id. +func (oDb *DB) InsertWorkflow(ctx context.Context, w WorkflowInsert) (int64, error) { + res, err := oDb.ExecContext(ctx, "INSERT INTO workflows (status, form_md5, steps, last_assignee, last_update,"+ + " last_form_id, last_form_name, form_head_id, creator, create_date) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + w.Status, w.MD5, w.Steps, w.LastAssignee, w.LastUpdate, w.LastFormID, w.LastFormName, w.HeadID, w.Creator, w.CreateDate) + if err != nil { + return 0, fmt.Errorf("insertWorkflow: %w", err) + } + oDb.SetChange("workflows") + return res.LastInsertId() +} + +// UpdateWorkflowStep records a new step of the workflow started by headID. +func (oDb *DB) UpdateWorkflowStep(ctx context.Context, headID int64, w WorkflowInsert) error { + if _, err := oDb.ExecContext(ctx, "UPDATE workflows SET status = ?, steps = ?, last_assignee = ?,"+ + " last_form_id = ?, last_form_name = ?, last_update = ? WHERE form_head_id = ?", + w.Status, w.Steps, w.LastAssignee, w.LastFormID, w.LastFormName, w.LastUpdate, headID); err != nil { + return fmt.Errorf("updateWorkflowStep: %w", err) + } + oDb.SetChange("workflows") + return nil +} diff --git a/cmd/conf.go b/cmd/conf.go index dbaa7e74..57e6a888 100644 --- a/cmd/conf.go +++ b/cmd/conf.go @@ -61,6 +61,12 @@ func setDefaultServerConfig() { viper.SetDefault(s+".ui.enable", false) viper.SetDefault(s+".sync.timeout", "2s") viper.SetDefault(s+".allow_anon_register", false) + // One git repository per form, holding its yaml history, as the historical + // collector keeps them under private/forms. + viper.SetDefault(s+".directories.forms", "/oc3/uploads/forms") + // The javascript sandbox running the manglers of the form rest outputs. + viper.SetDefault(s+".forms.nodejs", "/usr/bin/nodejs") + viper.SetDefault(s+".forms.vm2", "/usr/local/bin/vm2") viper.SetDefault(s+".log.request.level", "none") setDefaultAuthConfig() diff --git a/go.mod b/go.mod index 447cd0fa..cfb36d2f 100644 --- a/go.mod +++ b/go.mod @@ -17,6 +17,7 @@ require ( github.com/shaj13/go-guardian/v2 v2.11.6 github.com/spf13/cobra v1.10.1 github.com/spf13/viper v1.21.0 + gopkg.in/yaml.v3 v3.0.1 ) require ( @@ -64,7 +65,6 @@ require ( golang.org/x/time v0.15.0 // indirect golang.org/x/tools v0.44.0 // indirect google.golang.org/protobuf v1.36.10 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect ) tool github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen diff --git a/server/api.yaml b/server/api.yaml index 1786e29c..80454594 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -2618,6 +2618,1142 @@ paths: - basicAuth: [ ] - bearerAuth: [ ] + /form_output_results/{results_id}: + get: + operationId: GetFormOutputResults + description: | + Show the results structure of a form submission. + parameters: + - in: path + name: results_id + required: true + description: Results id + schema: + type: integer + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + put: + operationId: PutFormOutputResults + description: | + Add a result or log lines to an output of a form submission results. + parameters: + - in: path + name: results_id + required: true + description: Results id + schema: + type: integer + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + output_id: + type: string + description: The id of the form output for which to store the result + result: + description: The result to add for output_id, a JSON document or its string form + log: + description: The log lines to append to output_id logs, [[lvl, fmt, data], ...], lvl 0 for info, 1 for error + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /forms: + get: + operationId: GetForms + description: | + List the forms. A manager sees every form, others the forms published to + one of their groups. form_definition is form_yaml parsed. + parameters: + - $ref: '#/components/parameters/inQueryProps' + - $ref: '#/components/parameters/inQueryLimit' + - $ref: '#/components/parameters/inQueryOffset' + - $ref: '#/components/parameters/inQueryMeta' + - $ref: '#/components/parameters/inQueryStats' + - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryGroupby' + - $ref: '#/components/parameters/inQueryFilter' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/FormListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + post: + operationId: PostForms + description: | + Create forms, as the historical collector's POST /forms: one entry or a list. + form_name is mandatory, the other keys are forms columns (form_yaml, + form_type, form_folder...). The author and the creation date are set, and + the form is published to and made the responsibility of the creator's + default group. Requires the FormsManager privilege. + requestBody: + required: true + content: + application/json: + schema: + oneOf: + - type: object + additionalProperties: true + - type: array + items: + type: object + additionalProperties: true + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 409: + $ref: '#/components/responses/409' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + delete: + operationId: DeleteForms + description: | + Delete forms: an entry with the 'id' key, or a list of them. Same + requirements as DELETE /forms/{form_id}. + requestBody: + required: true + content: + application/json: + schema: + oneOf: + - type: object + additionalProperties: true + - type: array + items: + type: object + additionalProperties: true + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /forms/{form_id}: + get: + operationId: GetForm + description: | + Show a form, as GET /forms restricted to one id: empty when the form does + not exist or is not published to the caller. + parameters: + - in: path + name: form_id + required: true + description: Form id + schema: + type: integer + - $ref: '#/components/parameters/inQueryProps' + - $ref: '#/components/parameters/inQueryLimit' + - $ref: '#/components/parameters/inQueryOffset' + - $ref: '#/components/parameters/inQueryMeta' + - $ref: '#/components/parameters/inQueryStats' + - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryGroupby' + - $ref: '#/components/parameters/inQueryFilter' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/FormListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + post: + operationId: PostForm + description: | + Modify a form. The keys are forms columns; form_definition, a JSON document + or its string form, is stored as form_yaml. A new form_yaml is recorded in + the form's revision history. Requires the FormsManager privilege. + parameters: + - in: path + name: form_id + required: true + description: Form id + schema: + type: integer + requestBody: + required: true + content: + application/json: + schema: + type: object + additionalProperties: true + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/FormListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 409: + $ref: '#/components/responses/409' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + put: + operationId: PutForm + description: | + Submit a form: validate the data against the form inputs and run its + outputs (db, rest, script, mail, workflow). The body may also be + form-encoded, data given as its JSON string, as in the historical examples. The answer is the results + structure, also stored and readable with GET /form_output_results/{id}. A + negative id designates an internal form. The form must be published to the + caller, unless a manager. + parameters: + - in: path + name: form_id + required: true + description: Form id + schema: + type: integer + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + data: + description: The information the form expects, as an object, a list of objects or their JSON string form. + prev_wfid: + description: The previous step id in an existing workflow. + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + delete: + operationId: DeleteForm + description: | + Delete a form, with its publications and responsibles. Requires the + FormsManager privilege and responsibility for the form. + parameters: + - in: path + name: form_id + required: true + description: Form id + schema: + type: integer + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /forms/{form_id}/am_i_responsible: + get: + operationId: GetFormAmIResponsible + description: | + Tell whether the caller is responsible for the form, as {"data": true} or + {"data": false}. + parameters: + - in: path + name: form_id + required: true + description: Form id + schema: + type: integer + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /forms/{form_id}/diff/{cid}: + get: + operationId: GetFormDiff + description: | + Show the change made by a revision, or the differences between cid and + other when set, as git prints them. + parameters: + - in: path + name: form_id + required: true + description: Form id + schema: + type: integer + - in: path + name: cid + required: true + description: Git commit id of a form revision + schema: + type: string + - in: query + name: other + required: false + description: Another revision to compare cid with + schema: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /forms/{form_id}/publications: + get: + operationId: GetFormPublications + description: | + List the groups the form is published to. Requires the form to be + published to the caller, unless a manager. + parameters: + - in: path + name: form_id + required: true + description: Form id + schema: + type: integer + - $ref: '#/components/parameters/inQueryProps' + - $ref: '#/components/parameters/inQueryLimit' + - $ref: '#/components/parameters/inQueryOffset' + - $ref: '#/components/parameters/inQueryMeta' + - $ref: '#/components/parameters/inQueryStats' + - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryGroupby' + - $ref: '#/components/parameters/inQueryFilter' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /forms/{form_id}/publications/{group_id}: + post: + operationId: PostFormPublication + description: | + Publish the form to a group. Requires the FormsManager privilege and + responsibility for the form. An existing link answers with an info message. + parameters: + - in: path + name: form_id + required: true + description: Form id + schema: + type: integer + - in: path + name: group_id + required: true + description: Group id or role + schema: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + delete: + operationId: DeleteFormPublication + description: | + Unpublish the form from a group. Requires the FormsManager privilege + and responsibility for the form. A missing link answers with an info message. + parameters: + - in: path + name: form_id + required: true + description: Form id + schema: + type: integer + - in: path + name: group_id + required: true + description: Group id or role + schema: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /forms/{form_id}/responsibles: + get: + operationId: GetFormResponsibles + description: | + List the groups the form is the responsibility of. Requires the form to be + published to the caller, unless a manager. + parameters: + - in: path + name: form_id + required: true + description: Form id + schema: + type: integer + - $ref: '#/components/parameters/inQueryProps' + - $ref: '#/components/parameters/inQueryLimit' + - $ref: '#/components/parameters/inQueryOffset' + - $ref: '#/components/parameters/inQueryMeta' + - $ref: '#/components/parameters/inQueryStats' + - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryGroupby' + - $ref: '#/components/parameters/inQueryFilter' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /forms/{form_id}/responsibles/{group_id}: + post: + operationId: PostFormResponsible + description: | + Make a group responsible for the form. Requires the FormsManager privilege and + responsibility for the form. An existing link answers with an info message. + parameters: + - in: path + name: form_id + required: true + description: Form id + schema: + type: integer + - in: path + name: group_id + required: true + description: Group id or role + schema: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + delete: + operationId: DeleteFormResponsible + description: | + Remove a responsible group from the form. Requires the FormsManager privilege + and responsibility for the form. A missing link answers with an info message. + parameters: + - in: path + name: form_id + required: true + description: Form id + schema: + type: integer + - in: path + name: group_id + required: true + description: Group id or role + schema: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /forms/{form_id}/revisions: + get: + operationId: GetFormRevisions + description: | + List the revisions of the form definition, from its git history: an empty + list when the form is not published to the caller. + parameters: + - in: path + name: form_id + required: true + description: Form id + schema: + type: integer + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /forms/{form_id}/revisions/{cid}: + get: + operationId: GetFormRevision + description: | + Show the form definition at a revision, as {"data": {"oid", "content"}}. + parameters: + - in: path + name: form_id + required: true + description: Form id + schema: + type: integer + - in: path + name: cid + required: true + description: Git commit id of a form revision + schema: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /forms/{form_id}/rollback/{cid}: + post: + operationId: PostFormRollback + description: | + Restore the form definition of a revision, recorded as a new revision. + Requires the FormsManager privilege and responsibility for the form. + parameters: + - in: path + name: form_id + required: true + description: Form id + schema: + type: integer + - in: path + name: cid + required: true + description: Git commit id of a form revision + schema: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /forms_publications: + post: + operationId: PostFormsPublications + description: | + Same as POST /forms/{form_id}/publications/{group_id}, the form_id and + group_id keys given in the body: one entry or a list. + requestBody: + required: true + content: + application/json: + schema: + oneOf: + - type: object + additionalProperties: true + - type: array + items: + type: object + additionalProperties: true + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + delete: + operationId: DeleteFormsPublications + description: | + Same as DELETE /forms/{form_id}/publications/{group_id}, the form_id and + group_id keys given in the body: one entry or a list. + requestBody: + required: true + content: + application/json: + schema: + oneOf: + - type: object + additionalProperties: true + - type: array + items: + type: object + additionalProperties: true + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /forms_responsibles: + post: + operationId: PostFormsResponsibles + description: | + Same as POST /forms/{form_id}/responsibles/{group_id}, the form_id and + group_id keys given in the body: one entry or a list. + requestBody: + required: true + content: + application/json: + schema: + oneOf: + - type: object + additionalProperties: true + - type: array + items: + type: object + additionalProperties: true + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + delete: + operationId: DeleteFormsResponsibles + description: | + Same as DELETE /forms/{form_id}/responsibles/{group_id}, the form_id and + group_id keys given in the body: one entry or a list. + requestBody: + required: true + content: + application/json: + schema: + oneOf: + - type: object + additionalProperties: true + - type: array + items: + type: object + additionalProperties: true + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /forms_revisions: + get: + operationId: GetFormsRevisions + description: | + List the form revisions stored for workflows. + parameters: + - $ref: '#/components/parameters/inQueryProps' + - $ref: '#/components/parameters/inQueryLimit' + - $ref: '#/components/parameters/inQueryOffset' + - $ref: '#/components/parameters/inQueryMeta' + - $ref: '#/components/parameters/inQueryStats' + - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryGroupby' + - $ref: '#/components/parameters/inQueryFilter' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /forms_revisions/{revision_id}: + get: + operationId: GetFormsRevision + description: | + Show a form revision, by id or by md5. + parameters: + - in: path + name: revision_id + required: true + description: Revision id or md5 + schema: + type: string + - $ref: '#/components/parameters/inQueryProps' + - $ref: '#/components/parameters/inQueryLimit' + - $ref: '#/components/parameters/inQueryOffset' + - $ref: '#/components/parameters/inQueryMeta' + - $ref: '#/components/parameters/inQueryStats' + - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryGroupby' + - $ref: '#/components/parameters/inQueryFilter' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /forms_store: + get: + operationId: GetFormsStore + description: | + List the forms stored by workflows, with the revision they were submitted + with. + parameters: + - $ref: '#/components/parameters/inQueryProps' + - $ref: '#/components/parameters/inQueryLimit' + - $ref: '#/components/parameters/inQueryOffset' + - $ref: '#/components/parameters/inQueryMeta' + - $ref: '#/components/parameters/inQueryStats' + - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryGroupby' + - $ref: '#/components/parameters/inQueryFilter' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /forms_store/{store_id}: + get: + operationId: GetFormStore + description: | + Show a form stored by a workflow. + parameters: + - in: path + name: store_id + required: true + description: Stored form id + schema: + type: integer + - $ref: '#/components/parameters/inQueryProps' + - $ref: '#/components/parameters/inQueryLimit' + - $ref: '#/components/parameters/inQueryOffset' + - $ref: '#/components/parameters/inQueryMeta' + - $ref: '#/components/parameters/inQueryStats' + - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryGroupby' + - $ref: '#/components/parameters/inQueryFilter' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /forms_store/{store_id}/dump: + get: + operationId: GetFormStoreDump + description: | + Show a form stored by a workflow, with its workflow, the workflow head and + tail stored forms. + parameters: + - in: path + name: store_id + required: true + description: Stored form id + schema: + type: integer + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + /groups: get: operationId: GetGroups @@ -8185,6 +9321,54 @@ components: f_updated: type: string + FormRow: + type: object + description: | + A form: its definition, form_yaml, drives the inputs a submission expects + and the outputs it runs. form_definition is form_yaml parsed. Every + property is optional: the `props` query parameter selects which columns + the server returns. + properties: + id: + type: integer + form_name: + type: string + form_yaml: + type: string + form_definition: + nullable: true + description: form_yaml parsed, absent when it does not parse + form_author: + type: string + form_created: + type: string + form_type: + type: string + description: obj, custo, folder or generic + form_folder: + type: string + + FormListResponse: + type: object + required: + - data + properties: + data: + oneOf: + - type: array + items: + $ref: '#/components/schemas/FormRow' + - type: object + additionalProperties: + type: object + additionalProperties: + type: integer + meta: + $ref: '#/components/schemas/ListMeta' + info: + type: string + description: The change made, on a modification + FilterListResponse: type: object required: diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index 63a77cc4..6f276ded 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -216,6 +216,93 @@ type ServerInterface interface { // (POST /filtersets_filtersets) PostFiltersetsFiltersets(ctx echo.Context) error + // (GET /form_output_results/{results_id}) + GetFormOutputResults(ctx echo.Context, resultsId int) error + + // (PUT /form_output_results/{results_id}) + PutFormOutputResults(ctx echo.Context, resultsId int) error + + // (DELETE /forms) + DeleteForms(ctx echo.Context) error + + // (GET /forms) + GetForms(ctx echo.Context, params GetFormsParams) error + + // (POST /forms) + PostForms(ctx echo.Context) error + + // (DELETE /forms/{form_id}) + DeleteForm(ctx echo.Context, formId int) error + + // (GET /forms/{form_id}) + GetForm(ctx echo.Context, formId int, params GetFormParams) error + + // (POST /forms/{form_id}) + PostForm(ctx echo.Context, formId int) error + + // (PUT /forms/{form_id}) + PutForm(ctx echo.Context, formId int) error + + // (GET /forms/{form_id}/am_i_responsible) + GetFormAmIResponsible(ctx echo.Context, formId int) error + + // (GET /forms/{form_id}/diff/{cid}) + GetFormDiff(ctx echo.Context, formId int, cid string, params GetFormDiffParams) error + + // (GET /forms/{form_id}/publications) + GetFormPublications(ctx echo.Context, formId int, params GetFormPublicationsParams) error + + // (DELETE /forms/{form_id}/publications/{group_id}) + DeleteFormPublication(ctx echo.Context, formId int, groupId string) error + + // (POST /forms/{form_id}/publications/{group_id}) + PostFormPublication(ctx echo.Context, formId int, groupId string) error + + // (GET /forms/{form_id}/responsibles) + GetFormResponsibles(ctx echo.Context, formId int, params GetFormResponsiblesParams) error + + // (DELETE /forms/{form_id}/responsibles/{group_id}) + DeleteFormResponsible(ctx echo.Context, formId int, groupId string) error + + // (POST /forms/{form_id}/responsibles/{group_id}) + PostFormResponsible(ctx echo.Context, formId int, groupId string) error + + // (GET /forms/{form_id}/revisions) + GetFormRevisions(ctx echo.Context, formId int) error + + // (GET /forms/{form_id}/revisions/{cid}) + GetFormRevision(ctx echo.Context, formId int, cid string) error + + // (POST /forms/{form_id}/rollback/{cid}) + PostFormRollback(ctx echo.Context, formId int, cid string) error + + // (DELETE /forms_publications) + DeleteFormsPublications(ctx echo.Context) error + + // (POST /forms_publications) + PostFormsPublications(ctx echo.Context) error + + // (DELETE /forms_responsibles) + DeleteFormsResponsibles(ctx echo.Context) error + + // (POST /forms_responsibles) + PostFormsResponsibles(ctx echo.Context) error + + // (GET /forms_revisions) + GetFormsRevisions(ctx echo.Context, params GetFormsRevisionsParams) error + + // (GET /forms_revisions/{revision_id}) + GetFormsRevision(ctx echo.Context, revisionId string, params GetFormsRevisionParams) error + + // (GET /forms_store) + GetFormsStore(ctx echo.Context, params GetFormsStoreParams) error + + // (GET /forms_store/{store_id}) + GetFormStore(ctx echo.Context, storeId int, params GetFormStoreParams) error + + // (GET /forms_store/{store_id}/dump) + GetFormStoreDump(ctx echo.Context, storeId int) error + // (GET /frontend/hidden_menu_entries) GetFrontendHiddenMenuEntries(ctx echo.Context, params GetFrontendHiddenMenuEntriesParams) error @@ -2907,6 +2994,1052 @@ func (w *ServerInterfaceWrapper) PostFiltersetsFiltersets(ctx echo.Context) erro return err } +// GetFormOutputResults converts echo context to params. +func (w *ServerInterfaceWrapper) GetFormOutputResults(ctx echo.Context) error { + var err error + // ------------- Path parameter "results_id" ------------- + var resultsId int + + err = runtime.BindStyledParameterWithOptions("simple", "results_id", ctx.Param("results_id"), &resultsId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter results_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetFormOutputResults(ctx, resultsId) + return err +} + +// PutFormOutputResults converts echo context to params. +func (w *ServerInterfaceWrapper) PutFormOutputResults(ctx echo.Context) error { + var err error + // ------------- Path parameter "results_id" ------------- + var resultsId int + + err = runtime.BindStyledParameterWithOptions("simple", "results_id", ctx.Param("results_id"), &resultsId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter results_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PutFormOutputResults(ctx, resultsId) + return err +} + +// DeleteForms converts echo context to params. +func (w *ServerInterfaceWrapper) DeleteForms(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.DeleteForms(ctx) + return err +} + +// GetForms converts echo context to params. +func (w *ServerInterfaceWrapper) GetForms(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetFormsParams + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // ------------- Optional query parameter "limit" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) + } + + // ------------- Optional query parameter "offset" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) + } + + // ------------- Optional query parameter "meta" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) + } + + // ------------- Optional query parameter "stats" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) + } + + // ------------- Optional query parameter "orderby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) + } + + // ------------- Optional query parameter "groupby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) + } + + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetForms(ctx, params) + return err +} + +// PostForms converts echo context to params. +func (w *ServerInterfaceWrapper) PostForms(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostForms(ctx) + return err +} + +// DeleteForm converts echo context to params. +func (w *ServerInterfaceWrapper) DeleteForm(ctx echo.Context) error { + var err error + // ------------- Path parameter "form_id" ------------- + var formId int + + err = runtime.BindStyledParameterWithOptions("simple", "form_id", ctx.Param("form_id"), &formId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter form_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.DeleteForm(ctx, formId) + return err +} + +// GetForm converts echo context to params. +func (w *ServerInterfaceWrapper) GetForm(ctx echo.Context) error { + var err error + // ------------- Path parameter "form_id" ------------- + var formId int + + err = runtime.BindStyledParameterWithOptions("simple", "form_id", ctx.Param("form_id"), &formId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter form_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetFormParams + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // ------------- Optional query parameter "limit" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) + } + + // ------------- Optional query parameter "offset" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) + } + + // ------------- Optional query parameter "meta" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) + } + + // ------------- Optional query parameter "stats" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) + } + + // ------------- Optional query parameter "orderby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) + } + + // ------------- Optional query parameter "groupby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) + } + + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetForm(ctx, formId, params) + return err +} + +// PostForm converts echo context to params. +func (w *ServerInterfaceWrapper) PostForm(ctx echo.Context) error { + var err error + // ------------- Path parameter "form_id" ------------- + var formId int + + err = runtime.BindStyledParameterWithOptions("simple", "form_id", ctx.Param("form_id"), &formId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter form_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostForm(ctx, formId) + return err +} + +// PutForm converts echo context to params. +func (w *ServerInterfaceWrapper) PutForm(ctx echo.Context) error { + var err error + // ------------- Path parameter "form_id" ------------- + var formId int + + err = runtime.BindStyledParameterWithOptions("simple", "form_id", ctx.Param("form_id"), &formId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter form_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PutForm(ctx, formId) + return err +} + +// GetFormAmIResponsible converts echo context to params. +func (w *ServerInterfaceWrapper) GetFormAmIResponsible(ctx echo.Context) error { + var err error + // ------------- Path parameter "form_id" ------------- + var formId int + + err = runtime.BindStyledParameterWithOptions("simple", "form_id", ctx.Param("form_id"), &formId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter form_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetFormAmIResponsible(ctx, formId) + return err +} + +// GetFormDiff converts echo context to params. +func (w *ServerInterfaceWrapper) GetFormDiff(ctx echo.Context) error { + var err error + // ------------- Path parameter "form_id" ------------- + var formId int + + err = runtime.BindStyledParameterWithOptions("simple", "form_id", ctx.Param("form_id"), &formId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter form_id: %s", err)) + } + + // ------------- Path parameter "cid" ------------- + var cid string + + err = runtime.BindStyledParameterWithOptions("simple", "cid", ctx.Param("cid"), &cid, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter cid: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetFormDiffParams + // ------------- Optional query parameter "other" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "other", ctx.QueryParams(), ¶ms.Other, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter other: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetFormDiff(ctx, formId, cid, params) + return err +} + +// GetFormPublications converts echo context to params. +func (w *ServerInterfaceWrapper) GetFormPublications(ctx echo.Context) error { + var err error + // ------------- Path parameter "form_id" ------------- + var formId int + + err = runtime.BindStyledParameterWithOptions("simple", "form_id", ctx.Param("form_id"), &formId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter form_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetFormPublicationsParams + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // ------------- Optional query parameter "limit" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) + } + + // ------------- Optional query parameter "offset" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) + } + + // ------------- Optional query parameter "meta" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) + } + + // ------------- Optional query parameter "stats" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) + } + + // ------------- Optional query parameter "orderby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) + } + + // ------------- Optional query parameter "groupby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) + } + + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetFormPublications(ctx, formId, params) + return err +} + +// DeleteFormPublication converts echo context to params. +func (w *ServerInterfaceWrapper) DeleteFormPublication(ctx echo.Context) error { + var err error + // ------------- Path parameter "form_id" ------------- + var formId int + + err = runtime.BindStyledParameterWithOptions("simple", "form_id", ctx.Param("form_id"), &formId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter form_id: %s", err)) + } + + // ------------- Path parameter "group_id" ------------- + var groupId string + + err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter group_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.DeleteFormPublication(ctx, formId, groupId) + return err +} + +// PostFormPublication converts echo context to params. +func (w *ServerInterfaceWrapper) PostFormPublication(ctx echo.Context) error { + var err error + // ------------- Path parameter "form_id" ------------- + var formId int + + err = runtime.BindStyledParameterWithOptions("simple", "form_id", ctx.Param("form_id"), &formId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter form_id: %s", err)) + } + + // ------------- Path parameter "group_id" ------------- + var groupId string + + err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter group_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostFormPublication(ctx, formId, groupId) + return err +} + +// GetFormResponsibles converts echo context to params. +func (w *ServerInterfaceWrapper) GetFormResponsibles(ctx echo.Context) error { + var err error + // ------------- Path parameter "form_id" ------------- + var formId int + + err = runtime.BindStyledParameterWithOptions("simple", "form_id", ctx.Param("form_id"), &formId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter form_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetFormResponsiblesParams + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // ------------- Optional query parameter "limit" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) + } + + // ------------- Optional query parameter "offset" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) + } + + // ------------- Optional query parameter "meta" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) + } + + // ------------- Optional query parameter "stats" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) + } + + // ------------- Optional query parameter "orderby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) + } + + // ------------- Optional query parameter "groupby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) + } + + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetFormResponsibles(ctx, formId, params) + return err +} + +// DeleteFormResponsible converts echo context to params. +func (w *ServerInterfaceWrapper) DeleteFormResponsible(ctx echo.Context) error { + var err error + // ------------- Path parameter "form_id" ------------- + var formId int + + err = runtime.BindStyledParameterWithOptions("simple", "form_id", ctx.Param("form_id"), &formId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter form_id: %s", err)) + } + + // ------------- Path parameter "group_id" ------------- + var groupId string + + err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter group_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.DeleteFormResponsible(ctx, formId, groupId) + return err +} + +// PostFormResponsible converts echo context to params. +func (w *ServerInterfaceWrapper) PostFormResponsible(ctx echo.Context) error { + var err error + // ------------- Path parameter "form_id" ------------- + var formId int + + err = runtime.BindStyledParameterWithOptions("simple", "form_id", ctx.Param("form_id"), &formId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter form_id: %s", err)) + } + + // ------------- Path parameter "group_id" ------------- + var groupId string + + err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter group_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostFormResponsible(ctx, formId, groupId) + return err +} + +// GetFormRevisions converts echo context to params. +func (w *ServerInterfaceWrapper) GetFormRevisions(ctx echo.Context) error { + var err error + // ------------- Path parameter "form_id" ------------- + var formId int + + err = runtime.BindStyledParameterWithOptions("simple", "form_id", ctx.Param("form_id"), &formId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter form_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetFormRevisions(ctx, formId) + return err +} + +// GetFormRevision converts echo context to params. +func (w *ServerInterfaceWrapper) GetFormRevision(ctx echo.Context) error { + var err error + // ------------- Path parameter "form_id" ------------- + var formId int + + err = runtime.BindStyledParameterWithOptions("simple", "form_id", ctx.Param("form_id"), &formId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter form_id: %s", err)) + } + + // ------------- Path parameter "cid" ------------- + var cid string + + err = runtime.BindStyledParameterWithOptions("simple", "cid", ctx.Param("cid"), &cid, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter cid: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetFormRevision(ctx, formId, cid) + return err +} + +// PostFormRollback converts echo context to params. +func (w *ServerInterfaceWrapper) PostFormRollback(ctx echo.Context) error { + var err error + // ------------- Path parameter "form_id" ------------- + var formId int + + err = runtime.BindStyledParameterWithOptions("simple", "form_id", ctx.Param("form_id"), &formId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter form_id: %s", err)) + } + + // ------------- Path parameter "cid" ------------- + var cid string + + err = runtime.BindStyledParameterWithOptions("simple", "cid", ctx.Param("cid"), &cid, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter cid: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostFormRollback(ctx, formId, cid) + return err +} + +// DeleteFormsPublications converts echo context to params. +func (w *ServerInterfaceWrapper) DeleteFormsPublications(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.DeleteFormsPublications(ctx) + return err +} + +// PostFormsPublications converts echo context to params. +func (w *ServerInterfaceWrapper) PostFormsPublications(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostFormsPublications(ctx) + return err +} + +// DeleteFormsResponsibles converts echo context to params. +func (w *ServerInterfaceWrapper) DeleteFormsResponsibles(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.DeleteFormsResponsibles(ctx) + return err +} + +// PostFormsResponsibles converts echo context to params. +func (w *ServerInterfaceWrapper) PostFormsResponsibles(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostFormsResponsibles(ctx) + return err +} + +// GetFormsRevisions converts echo context to params. +func (w *ServerInterfaceWrapper) GetFormsRevisions(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetFormsRevisionsParams + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // ------------- Optional query parameter "limit" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) + } + + // ------------- Optional query parameter "offset" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) + } + + // ------------- Optional query parameter "meta" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) + } + + // ------------- Optional query parameter "stats" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) + } + + // ------------- Optional query parameter "orderby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) + } + + // ------------- Optional query parameter "groupby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) + } + + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetFormsRevisions(ctx, params) + return err +} + +// GetFormsRevision converts echo context to params. +func (w *ServerInterfaceWrapper) GetFormsRevision(ctx echo.Context) error { + var err error + // ------------- Path parameter "revision_id" ------------- + var revisionId string + + err = runtime.BindStyledParameterWithOptions("simple", "revision_id", ctx.Param("revision_id"), &revisionId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter revision_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetFormsRevisionParams + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // ------------- Optional query parameter "limit" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) + } + + // ------------- Optional query parameter "offset" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) + } + + // ------------- Optional query parameter "meta" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) + } + + // ------------- Optional query parameter "stats" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) + } + + // ------------- Optional query parameter "orderby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) + } + + // ------------- Optional query parameter "groupby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) + } + + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetFormsRevision(ctx, revisionId, params) + return err +} + +// GetFormsStore converts echo context to params. +func (w *ServerInterfaceWrapper) GetFormsStore(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetFormsStoreParams + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // ------------- Optional query parameter "limit" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) + } + + // ------------- Optional query parameter "offset" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) + } + + // ------------- Optional query parameter "meta" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) + } + + // ------------- Optional query parameter "stats" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) + } + + // ------------- Optional query parameter "orderby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) + } + + // ------------- Optional query parameter "groupby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) + } + + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetFormsStore(ctx, params) + return err +} + +// GetFormStore converts echo context to params. +func (w *ServerInterfaceWrapper) GetFormStore(ctx echo.Context) error { + var err error + // ------------- Path parameter "store_id" ------------- + var storeId int + + err = runtime.BindStyledParameterWithOptions("simple", "store_id", ctx.Param("store_id"), &storeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter store_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetFormStoreParams + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // ------------- Optional query parameter "limit" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) + } + + // ------------- Optional query parameter "offset" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) + } + + // ------------- Optional query parameter "meta" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) + } + + // ------------- Optional query parameter "stats" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) + } + + // ------------- Optional query parameter "orderby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) + } + + // ------------- Optional query parameter "groupby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) + } + + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetFormStore(ctx, storeId, params) + return err +} + +// GetFormStoreDump converts echo context to params. +func (w *ServerInterfaceWrapper) GetFormStoreDump(ctx echo.Context) error { + var err error + // ------------- Path parameter "store_id" ------------- + var storeId int + + err = runtime.BindStyledParameterWithOptions("simple", "store_id", ctx.Param("store_id"), &storeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter store_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetFormStoreDump(ctx, storeId) + return err +} + // GetFrontendHiddenMenuEntries converts echo context to params. func (w *ServerInterfaceWrapper) GetFrontendHiddenMenuEntries(ctx echo.Context) error { var err error @@ -8954,6 +10087,35 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.POST(options.BaseURL+"/filtersets_filters", wrapper.PostFiltersetsFilters, options.OperationMiddlewares["PostFiltersetsFilters"]...) router.DELETE(options.BaseURL+"/filtersets_filtersets", wrapper.DeleteFiltersetsFiltersets, options.OperationMiddlewares["DeleteFiltersetsFiltersets"]...) router.POST(options.BaseURL+"/filtersets_filtersets", wrapper.PostFiltersetsFiltersets, options.OperationMiddlewares["PostFiltersetsFiltersets"]...) + router.GET(options.BaseURL+"/form_output_results/:results_id", wrapper.GetFormOutputResults, options.OperationMiddlewares["GetFormOutputResults"]...) + router.PUT(options.BaseURL+"/form_output_results/:results_id", wrapper.PutFormOutputResults, options.OperationMiddlewares["PutFormOutputResults"]...) + router.DELETE(options.BaseURL+"/forms", wrapper.DeleteForms, options.OperationMiddlewares["DeleteForms"]...) + router.GET(options.BaseURL+"/forms", wrapper.GetForms, options.OperationMiddlewares["GetForms"]...) + router.POST(options.BaseURL+"/forms", wrapper.PostForms, options.OperationMiddlewares["PostForms"]...) + router.DELETE(options.BaseURL+"/forms/:form_id", wrapper.DeleteForm, options.OperationMiddlewares["DeleteForm"]...) + router.GET(options.BaseURL+"/forms/:form_id", wrapper.GetForm, options.OperationMiddlewares["GetForm"]...) + router.POST(options.BaseURL+"/forms/:form_id", wrapper.PostForm, options.OperationMiddlewares["PostForm"]...) + router.PUT(options.BaseURL+"/forms/:form_id", wrapper.PutForm, options.OperationMiddlewares["PutForm"]...) + router.GET(options.BaseURL+"/forms/:form_id/am_i_responsible", wrapper.GetFormAmIResponsible, options.OperationMiddlewares["GetFormAmIResponsible"]...) + router.GET(options.BaseURL+"/forms/:form_id/diff/:cid", wrapper.GetFormDiff, options.OperationMiddlewares["GetFormDiff"]...) + router.GET(options.BaseURL+"/forms/:form_id/publications", wrapper.GetFormPublications, options.OperationMiddlewares["GetFormPublications"]...) + router.DELETE(options.BaseURL+"/forms/:form_id/publications/:group_id", wrapper.DeleteFormPublication, options.OperationMiddlewares["DeleteFormPublication"]...) + router.POST(options.BaseURL+"/forms/:form_id/publications/:group_id", wrapper.PostFormPublication, options.OperationMiddlewares["PostFormPublication"]...) + router.GET(options.BaseURL+"/forms/:form_id/responsibles", wrapper.GetFormResponsibles, options.OperationMiddlewares["GetFormResponsibles"]...) + router.DELETE(options.BaseURL+"/forms/:form_id/responsibles/:group_id", wrapper.DeleteFormResponsible, options.OperationMiddlewares["DeleteFormResponsible"]...) + router.POST(options.BaseURL+"/forms/:form_id/responsibles/:group_id", wrapper.PostFormResponsible, options.OperationMiddlewares["PostFormResponsible"]...) + router.GET(options.BaseURL+"/forms/:form_id/revisions", wrapper.GetFormRevisions, options.OperationMiddlewares["GetFormRevisions"]...) + router.GET(options.BaseURL+"/forms/:form_id/revisions/:cid", wrapper.GetFormRevision, options.OperationMiddlewares["GetFormRevision"]...) + router.POST(options.BaseURL+"/forms/:form_id/rollback/:cid", wrapper.PostFormRollback, options.OperationMiddlewares["PostFormRollback"]...) + router.DELETE(options.BaseURL+"/forms_publications", wrapper.DeleteFormsPublications, options.OperationMiddlewares["DeleteFormsPublications"]...) + router.POST(options.BaseURL+"/forms_publications", wrapper.PostFormsPublications, options.OperationMiddlewares["PostFormsPublications"]...) + router.DELETE(options.BaseURL+"/forms_responsibles", wrapper.DeleteFormsResponsibles, options.OperationMiddlewares["DeleteFormsResponsibles"]...) + router.POST(options.BaseURL+"/forms_responsibles", wrapper.PostFormsResponsibles, options.OperationMiddlewares["PostFormsResponsibles"]...) + router.GET(options.BaseURL+"/forms_revisions", wrapper.GetFormsRevisions, options.OperationMiddlewares["GetFormsRevisions"]...) + router.GET(options.BaseURL+"/forms_revisions/:revision_id", wrapper.GetFormsRevision, options.OperationMiddlewares["GetFormsRevision"]...) + router.GET(options.BaseURL+"/forms_store", wrapper.GetFormsStore, options.OperationMiddlewares["GetFormsStore"]...) + router.GET(options.BaseURL+"/forms_store/:store_id", wrapper.GetFormStore, options.OperationMiddlewares["GetFormStore"]...) + router.GET(options.BaseURL+"/forms_store/:store_id/dump", wrapper.GetFormStoreDump, options.OperationMiddlewares["GetFormStoreDump"]...) router.GET(options.BaseURL+"/frontend/hidden_menu_entries", wrapper.GetFrontendHiddenMenuEntries, options.OperationMiddlewares["GetFrontendHiddenMenuEntries"]...) router.DELETE(options.BaseURL+"/groups", wrapper.DeleteGroups, options.OperationMiddlewares["DeleteGroups"]...) router.GET(options.BaseURL+"/groups", wrapper.GetGroups, options.OperationMiddlewares["GetGroups"]...) @@ -9086,272 +10248,309 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "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", + "4HQwOhl8/fT1/w8AAP//", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index 72330e01..6fca09fb 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -550,6 +550,45 @@ type FiltersetUsageResponse struct { } `json:"data"` } +// FormListResponse defines model for FormListResponse. +type FormListResponse struct { + Data FormListResponse_Data `json:"data"` + + // Info The change made, on a modification + Info *string `json:"info,omitempty"` + Meta *ListMeta `json:"meta,omitempty"` +} + +// FormListResponseData0 defines model for . +type FormListResponseData0 = []FormRow + +// FormListResponseData1 defines model for . +type FormListResponseData1 map[string]map[string]int + +// FormListResponse_Data defines model for FormListResponse.Data. +type FormListResponse_Data struct { + union json.RawMessage +} + +// FormRow A form: its definition, form_yaml, drives the inputs a submission expects +// and the outputs it runs. form_definition is form_yaml parsed. Every +// property is optional: the `props` query parameter selects which columns +// the server returns. +type FormRow struct { + FormAuthor *string `json:"form_author,omitempty"` + FormCreated *string `json:"form_created,omitempty"` + + // FormDefinition form_yaml parsed, absent when it does not parse + FormDefinition interface{} `json:"form_definition,omitempty"` + FormFolder *string `json:"form_folder,omitempty"` + FormName *string `json:"form_name,omitempty"` + + // FormType obj, custo, folder or generic + FormType *string `json:"form_type,omitempty"` + FormYaml *string `json:"form_yaml,omitempty"` + Id *int `json:"id,omitempty"` +} + // GroupListResponse defines model for GroupListResponse. type GroupListResponse struct { Data GroupListResponse_Data `json:"data"` @@ -2078,8 +2117,31 @@ type PostFiltersetsFiltersetsJSONBody struct { // PostFiltersetsFiltersetsJSONBodyFLogOp defines parameters for PostFiltersetsFiltersets. type PostFiltersetsFiltersetsJSONBodyFLogOp string -// GetFrontendHiddenMenuEntriesParams defines parameters for GetFrontendHiddenMenuEntries. -type GetFrontendHiddenMenuEntriesParams struct { +// PutFormOutputResultsJSONBody defines parameters for PutFormOutputResults. +type PutFormOutputResultsJSONBody struct { + // Log The log lines to append to output_id logs, [[lvl, fmt, data], ...], lvl 0 for info, 1 for error + Log interface{} `json:"log,omitempty"` + + // OutputId The id of the form output for which to store the result + OutputId *string `json:"output_id,omitempty"` + + // Result The result to add for output_id, a JSON document or its string form + Result interface{} `json:"result,omitempty"` +} + +// DeleteFormsJSONBody defines parameters for DeleteForms. +type DeleteFormsJSONBody struct { + union json.RawMessage +} + +// DeleteFormsJSONBody0 defines parameters for DeleteForms. +type DeleteFormsJSONBody0 map[string]interface{} + +// DeleteFormsJSONBody1 defines parameters for DeleteForms. +type DeleteFormsJSONBody1 = []map[string]interface{} + +// GetFormsParams defines parameters for GetForms. +type GetFormsParams struct { // Props A list of properties to include in each data dictionnary. Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` @@ -2103,19 +2165,34 @@ type GetFrontendHiddenMenuEntriesParams struct { // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` -} -// DeleteGroupsJSONBody defines parameters for DeleteGroups. -type DeleteGroupsJSONBody struct { - // Id Group record id - Id *string `json:"id,omitempty"` + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` +} - // Role Group role/name - Role *string `json:"role,omitempty"` +// PostFormsJSONBody defines parameters for PostForms. +type PostFormsJSONBody struct { + union json.RawMessage } -// GetGroupsParams defines parameters for GetGroups. -type GetGroupsParams struct { +// PostFormsJSONBody0 defines parameters for PostForms. +type PostFormsJSONBody0 map[string]interface{} + +// PostFormsJSONBody1 defines parameters for PostForms. +type PostFormsJSONBody1 = []map[string]interface{} + +// GetFormParams defines parameters for GetForm. +type GetFormParams struct { // Props A list of properties to include in each data dictionnary. Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` @@ -2139,24 +2216,41 @@ type GetGroupsParams struct { // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` + + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` } -// PostGroupsJSONBody defines parameters for PostGroups. -type PostGroupsJSONBody struct { - Description *string `json:"description,omitempty"` +// PostFormJSONBody defines parameters for PostForm. +type PostFormJSONBody map[string]interface{} - // Id Existing group id (selects update instead of create) - Id *string `json:"id,omitempty"` +// PutFormJSONBody defines parameters for PutForm. +type PutFormJSONBody struct { + // Data The information the form expects, as an object, a list of objects or their JSON string form. + Data interface{} `json:"data,omitempty"` - // Privilege 'T' for a privilege group, 'F' otherwise - Privilege *string `json:"privilege,omitempty"` + // PrevWfid The previous step id in an existing workflow. + PrevWfid interface{} `json:"prev_wfid,omitempty"` +} - // Role Group role/name - Role *string `json:"role,omitempty"` +// GetFormDiffParams defines parameters for GetFormDiff. +type GetFormDiffParams struct { + // Other Another revision to compare cid with + Other *string `form:"other,omitempty" json:"other,omitempty"` } -// GetGroupParams defines parameters for GetGroup. -type GetGroupParams struct { +// GetFormPublicationsParams defines parameters for GetFormPublications. +type GetFormPublicationsParams struct { // Props A list of properties to include in each data dictionnary. Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` @@ -2180,19 +2274,23 @@ type GetGroupParams struct { // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` -} - -// PostGroupJSONBody defines parameters for PostGroup. -type PostGroupJSONBody struct { - Description *string `json:"description,omitempty"` - // Privilege 'T' for a privilege group, 'F' otherwise - Privilege *string `json:"privilege,omitempty"` - Role *string `json:"role,omitempty"` + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` } -// GetGroupAppsParams defines parameters for GetGroupApps. -type GetGroupAppsParams struct { +// GetFormResponsiblesParams defines parameters for GetFormResponsibles. +type GetFormResponsiblesParams struct { // Props A list of properties to include in each data dictionnary. Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` @@ -2216,16 +2314,67 @@ type GetGroupAppsParams struct { // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` + + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` } -// DeleteGroupHiddenMenuEntriesJSONBody defines parameters for DeleteGroupHiddenMenuEntries. -type DeleteGroupHiddenMenuEntriesJSONBody struct { - // MenuEntry Menu entry key to unhide - MenuEntry string `json:"menu_entry"` +// DeleteFormsPublicationsJSONBody defines parameters for DeleteFormsPublications. +type DeleteFormsPublicationsJSONBody struct { + union json.RawMessage } -// GetGroupHiddenMenuEntriesParams defines parameters for GetGroupHiddenMenuEntries. -type GetGroupHiddenMenuEntriesParams struct { +// DeleteFormsPublicationsJSONBody0 defines parameters for DeleteFormsPublications. +type DeleteFormsPublicationsJSONBody0 map[string]interface{} + +// DeleteFormsPublicationsJSONBody1 defines parameters for DeleteFormsPublications. +type DeleteFormsPublicationsJSONBody1 = []map[string]interface{} + +// PostFormsPublicationsJSONBody defines parameters for PostFormsPublications. +type PostFormsPublicationsJSONBody struct { + union json.RawMessage +} + +// PostFormsPublicationsJSONBody0 defines parameters for PostFormsPublications. +type PostFormsPublicationsJSONBody0 map[string]interface{} + +// PostFormsPublicationsJSONBody1 defines parameters for PostFormsPublications. +type PostFormsPublicationsJSONBody1 = []map[string]interface{} + +// DeleteFormsResponsiblesJSONBody defines parameters for DeleteFormsResponsibles. +type DeleteFormsResponsiblesJSONBody struct { + union json.RawMessage +} + +// DeleteFormsResponsiblesJSONBody0 defines parameters for DeleteFormsResponsibles. +type DeleteFormsResponsiblesJSONBody0 map[string]interface{} + +// DeleteFormsResponsiblesJSONBody1 defines parameters for DeleteFormsResponsibles. +type DeleteFormsResponsiblesJSONBody1 = []map[string]interface{} + +// PostFormsResponsiblesJSONBody defines parameters for PostFormsResponsibles. +type PostFormsResponsiblesJSONBody struct { + union json.RawMessage +} + +// PostFormsResponsiblesJSONBody0 defines parameters for PostFormsResponsibles. +type PostFormsResponsiblesJSONBody0 map[string]interface{} + +// PostFormsResponsiblesJSONBody1 defines parameters for PostFormsResponsibles. +type PostFormsResponsiblesJSONBody1 = []map[string]interface{} + +// GetFormsRevisionsParams defines parameters for GetFormsRevisions. +type GetFormsRevisionsParams struct { // Props A list of properties to include in each data dictionnary. Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` @@ -2249,16 +2398,23 @@ type GetGroupHiddenMenuEntriesParams struct { // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` -} -// PostGroupHiddenMenuEntriesJSONBody defines parameters for PostGroupHiddenMenuEntries. -type PostGroupHiddenMenuEntriesJSONBody struct { - // MenuEntry Menu entry key to hide - MenuEntry string `json:"menu_entry"` + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` } -// GetGroupModulesetsParams defines parameters for GetGroupModulesets. -type GetGroupModulesetsParams struct { +// GetFormsRevisionParams defines parameters for GetFormsRevision. +type GetFormsRevisionParams struct { // Props A list of properties to include in each data dictionnary. Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` @@ -2282,10 +2438,23 @@ type GetGroupModulesetsParams struct { // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` + + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` } -// GetGroupNodesParams defines parameters for GetGroupNodes. -type GetGroupNodesParams struct { +// GetFormsStoreParams defines parameters for GetFormsStore. +type GetFormsStoreParams struct { // Props A list of properties to include in each data dictionnary. Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` @@ -2309,10 +2478,23 @@ type GetGroupNodesParams struct { // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` + + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` } -// GetGroupRulesetsParams defines parameters for GetGroupRulesets. -type GetGroupRulesetsParams struct { +// GetFormStoreParams defines parameters for GetFormStore. +type GetFormStoreParams struct { // Props A list of properties to include in each data dictionnary. Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` @@ -2336,10 +2518,23 @@ type GetGroupRulesetsParams struct { // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` + + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` } -// GetGroupServicesParams defines parameters for GetGroupServices. -type GetGroupServicesParams struct { +// GetFrontendHiddenMenuEntriesParams defines parameters for GetFrontendHiddenMenuEntries. +type GetFrontendHiddenMenuEntriesParams struct { // Props A list of properties to include in each data dictionnary. Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` @@ -2365,8 +2560,17 @@ type GetGroupServicesParams struct { Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` } -// GetGroupUsersParams defines parameters for GetGroupUsers. -type GetGroupUsersParams struct { +// DeleteGroupsJSONBody defines parameters for DeleteGroups. +type DeleteGroupsJSONBody struct { + // Id Group record id + Id *string `json:"id,omitempty"` + + // Role Group role/name + Role *string `json:"role,omitempty"` +} + +// GetGroupsParams defines parameters for GetGroups. +type GetGroupsParams struct { // Props A list of properties to include in each data dictionnary. Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` @@ -2392,14 +2596,22 @@ type GetGroupUsersParams struct { Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` } -// DeleteIpsJSONBody defines parameters for DeleteIps. -type DeleteIpsJSONBody struct { - // Id Ip identifier (node_ip.id) - Id string `json:"id"` +// PostGroupsJSONBody defines parameters for PostGroups. +type PostGroupsJSONBody struct { + Description *string `json:"description,omitempty"` + + // Id Existing group id (selects update instead of create) + Id *string `json:"id,omitempty"` + + // Privilege 'T' for a privilege group, 'F' otherwise + Privilege *string `json:"privilege,omitempty"` + + // Role Group role/name + Role *string `json:"role,omitempty"` } -// GetIpsParams defines parameters for GetIps. -type GetIpsParams struct { +// GetGroupParams defines parameters for GetGroup. +type GetGroupParams struct { // Props A list of properties to include in each data dictionnary. Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` @@ -2425,8 +2637,17 @@ type GetIpsParams struct { Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` } -// GetIpParams defines parameters for GetIp. -type GetIpParams struct { +// PostGroupJSONBody defines parameters for PostGroup. +type PostGroupJSONBody struct { + Description *string `json:"description,omitempty"` + + // Privilege 'T' for a privilege group, 'F' otherwise + Privilege *string `json:"privilege,omitempty"` + Role *string `json:"role,omitempty"` +} + +// GetGroupAppsParams defines parameters for GetGroupApps. +type GetGroupAppsParams struct { // Props A list of properties to include in each data dictionnary. Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` @@ -2452,10 +2673,244 @@ type GetIpParams struct { Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` } -// GetLogsParams defines parameters for GetLogs. -type GetLogsParams struct { - // FsetId Restrict to log events matching this filterset (gen_filtersets.id or fset_name) - FsetId *string `form:"fset_id,omitempty" json:"fset_id,omitempty"` +// DeleteGroupHiddenMenuEntriesJSONBody defines parameters for DeleteGroupHiddenMenuEntries. +type DeleteGroupHiddenMenuEntriesJSONBody struct { + // MenuEntry Menu entry key to unhide + MenuEntry string `json:"menu_entry"` +} + +// GetGroupHiddenMenuEntriesParams defines parameters for GetGroupHiddenMenuEntries. +type GetGroupHiddenMenuEntriesParams struct { + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` + + // Limit The maximum number of entries to return. 0 means no limit. + Limit *InQueryLimit `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Skip the first entries of the data cursor. + Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` + + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. + Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` + + // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. + Stats *InQueryStats `form:"stats,omitempty" json:"stats,omitempty"` + + // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). + Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). + Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` +} + +// PostGroupHiddenMenuEntriesJSONBody defines parameters for PostGroupHiddenMenuEntries. +type PostGroupHiddenMenuEntriesJSONBody struct { + // MenuEntry Menu entry key to hide + MenuEntry string `json:"menu_entry"` +} + +// GetGroupModulesetsParams defines parameters for GetGroupModulesets. +type GetGroupModulesetsParams struct { + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` + + // Limit The maximum number of entries to return. 0 means no limit. + Limit *InQueryLimit `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Skip the first entries of the data cursor. + Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` + + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. + Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` + + // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. + Stats *InQueryStats `form:"stats,omitempty" json:"stats,omitempty"` + + // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). + Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). + Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` +} + +// GetGroupNodesParams defines parameters for GetGroupNodes. +type GetGroupNodesParams struct { + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` + + // Limit The maximum number of entries to return. 0 means no limit. + Limit *InQueryLimit `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Skip the first entries of the data cursor. + Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` + + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. + Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` + + // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. + Stats *InQueryStats `form:"stats,omitempty" json:"stats,omitempty"` + + // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). + Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). + Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` +} + +// GetGroupRulesetsParams defines parameters for GetGroupRulesets. +type GetGroupRulesetsParams struct { + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` + + // Limit The maximum number of entries to return. 0 means no limit. + Limit *InQueryLimit `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Skip the first entries of the data cursor. + Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` + + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. + Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` + + // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. + Stats *InQueryStats `form:"stats,omitempty" json:"stats,omitempty"` + + // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). + Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). + Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` +} + +// GetGroupServicesParams defines parameters for GetGroupServices. +type GetGroupServicesParams struct { + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` + + // Limit The maximum number of entries to return. 0 means no limit. + Limit *InQueryLimit `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Skip the first entries of the data cursor. + Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` + + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. + Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` + + // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. + Stats *InQueryStats `form:"stats,omitempty" json:"stats,omitempty"` + + // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). + Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). + Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` +} + +// GetGroupUsersParams defines parameters for GetGroupUsers. +type GetGroupUsersParams struct { + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` + + // Limit The maximum number of entries to return. 0 means no limit. + Limit *InQueryLimit `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Skip the first entries of the data cursor. + Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` + + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. + Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` + + // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. + Stats *InQueryStats `form:"stats,omitempty" json:"stats,omitempty"` + + // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). + Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). + Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` +} + +// DeleteIpsJSONBody defines parameters for DeleteIps. +type DeleteIpsJSONBody struct { + // Id Ip identifier (node_ip.id) + Id string `json:"id"` +} + +// GetIpsParams defines parameters for GetIps. +type GetIpsParams struct { + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` + + // Limit The maximum number of entries to return. 0 means no limit. + Limit *InQueryLimit `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Skip the first entries of the data cursor. + Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` + + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. + Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` + + // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. + Stats *InQueryStats `form:"stats,omitempty" json:"stats,omitempty"` + + // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). + Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). + Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` +} + +// GetIpParams defines parameters for GetIp. +type GetIpParams struct { + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` + + // Limit The maximum number of entries to return. 0 means no limit. + Limit *InQueryLimit `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Skip the first entries of the data cursor. + Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` + + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. + Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` + + // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. + Stats *InQueryStats `form:"stats,omitempty" json:"stats,omitempty"` + + // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). + Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). + Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` +} + +// GetLogsParams defines parameters for GetLogs. +type GetLogsParams struct { + // FsetId Restrict to log events matching this filterset (gen_filtersets.id or fset_name) + FsetId *string `form:"fset_id,omitempty" json:"fset_id,omitempty"` // Props A list of properties to include in each data dictionnary. Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` @@ -4548,6 +5003,33 @@ type DeleteFiltersetsFiltersetsJSONRequestBody DeleteFiltersetsFiltersetsJSONBod // PostFiltersetsFiltersetsJSONRequestBody defines body for PostFiltersetsFiltersets for application/json ContentType. type PostFiltersetsFiltersetsJSONRequestBody PostFiltersetsFiltersetsJSONBody +// PutFormOutputResultsJSONRequestBody defines body for PutFormOutputResults for application/json ContentType. +type PutFormOutputResultsJSONRequestBody PutFormOutputResultsJSONBody + +// DeleteFormsJSONRequestBody defines body for DeleteForms for application/json ContentType. +type DeleteFormsJSONRequestBody DeleteFormsJSONBody + +// PostFormsJSONRequestBody defines body for PostForms for application/json ContentType. +type PostFormsJSONRequestBody PostFormsJSONBody + +// PostFormJSONRequestBody defines body for PostForm for application/json ContentType. +type PostFormJSONRequestBody PostFormJSONBody + +// PutFormJSONRequestBody defines body for PutForm for application/json ContentType. +type PutFormJSONRequestBody PutFormJSONBody + +// DeleteFormsPublicationsJSONRequestBody defines body for DeleteFormsPublications for application/json ContentType. +type DeleteFormsPublicationsJSONRequestBody DeleteFormsPublicationsJSONBody + +// PostFormsPublicationsJSONRequestBody defines body for PostFormsPublications for application/json ContentType. +type PostFormsPublicationsJSONRequestBody PostFormsPublicationsJSONBody + +// DeleteFormsResponsiblesJSONRequestBody defines body for DeleteFormsResponsibles for application/json ContentType. +type DeleteFormsResponsiblesJSONRequestBody DeleteFormsResponsiblesJSONBody + +// PostFormsResponsiblesJSONRequestBody defines body for PostFormsResponsibles for application/json ContentType. +type PostFormsResponsiblesJSONRequestBody PostFormsResponsiblesJSONBody + // DeleteGroupsJSONRequestBody defines body for DeleteGroups for application/json ContentType. type DeleteGroupsJSONRequestBody DeleteGroupsJSONBody @@ -5016,22 +5498,22 @@ func (t *FiltersetListResponse_Data) UnmarshalJSON(b []byte) error { return err } -// AsGroupListResponseData0 returns the union data inside the GroupListResponse_Data as a GroupListResponseData0 -func (t GroupListResponse_Data) AsGroupListResponseData0() (GroupListResponseData0, error) { - var body GroupListResponseData0 +// AsFormListResponseData0 returns the union data inside the FormListResponse_Data as a FormListResponseData0 +func (t FormListResponse_Data) AsFormListResponseData0() (FormListResponseData0, error) { + var body FormListResponseData0 err := json.Unmarshal(t.union, &body) return body, err } -// FromGroupListResponseData0 overwrites any union data inside the GroupListResponse_Data as the provided GroupListResponseData0 -func (t *GroupListResponse_Data) FromGroupListResponseData0(v GroupListResponseData0) error { +// FromFormListResponseData0 overwrites any union data inside the FormListResponse_Data as the provided FormListResponseData0 +func (t *FormListResponse_Data) FromFormListResponseData0(v FormListResponseData0) error { b, err := json.Marshal(v) t.union = b return err } -// MergeGroupListResponseData0 performs a merge with any union data inside the GroupListResponse_Data, using the provided GroupListResponseData0 -func (t *GroupListResponse_Data) MergeGroupListResponseData0(v GroupListResponseData0) error { +// MergeFormListResponseData0 performs a merge with any union data inside the FormListResponse_Data, using the provided FormListResponseData0 +func (t *FormListResponse_Data) MergeFormListResponseData0(v FormListResponseData0) error { b, err := json.Marshal(v) if err != nil { return err @@ -5042,22 +5524,22 @@ func (t *GroupListResponse_Data) MergeGroupListResponseData0(v GroupListResponse return err } -// AsGroupListResponseData1 returns the union data inside the GroupListResponse_Data as a GroupListResponseData1 -func (t GroupListResponse_Data) AsGroupListResponseData1() (GroupListResponseData1, error) { - var body GroupListResponseData1 +// AsFormListResponseData1 returns the union data inside the FormListResponse_Data as a FormListResponseData1 +func (t FormListResponse_Data) AsFormListResponseData1() (FormListResponseData1, error) { + var body FormListResponseData1 err := json.Unmarshal(t.union, &body) return body, err } -// FromGroupListResponseData1 overwrites any union data inside the GroupListResponse_Data as the provided GroupListResponseData1 -func (t *GroupListResponse_Data) FromGroupListResponseData1(v GroupListResponseData1) error { +// FromFormListResponseData1 overwrites any union data inside the FormListResponse_Data as the provided FormListResponseData1 +func (t *FormListResponse_Data) FromFormListResponseData1(v FormListResponseData1) error { b, err := json.Marshal(v) t.union = b return err } -// MergeGroupListResponseData1 performs a merge with any union data inside the GroupListResponse_Data, using the provided GroupListResponseData1 -func (t *GroupListResponse_Data) MergeGroupListResponseData1(v GroupListResponseData1) error { +// MergeFormListResponseData1 performs a merge with any union data inside the FormListResponse_Data, using the provided FormListResponseData1 +func (t *FormListResponse_Data) MergeFormListResponseData1(v FormListResponseData1) error { b, err := json.Marshal(v) if err != nil { return err @@ -5068,12 +5550,74 @@ func (t *GroupListResponse_Data) MergeGroupListResponseData1(v GroupListResponse return err } -func (t GroupListResponse_Data) MarshalJSON() ([]byte, error) { +func (t FormListResponse_Data) MarshalJSON() ([]byte, error) { b, err := t.union.MarshalJSON() return b, err } -func (t *GroupListResponse_Data) UnmarshalJSON(b []byte) error { +func (t *FormListResponse_Data) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + +// AsGroupListResponseData0 returns the union data inside the GroupListResponse_Data as a GroupListResponseData0 +func (t GroupListResponse_Data) AsGroupListResponseData0() (GroupListResponseData0, error) { + var body GroupListResponseData0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromGroupListResponseData0 overwrites any union data inside the GroupListResponse_Data as the provided GroupListResponseData0 +func (t *GroupListResponse_Data) FromGroupListResponseData0(v GroupListResponseData0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeGroupListResponseData0 performs a merge with any union data inside the GroupListResponse_Data, using the provided GroupListResponseData0 +func (t *GroupListResponse_Data) MergeGroupListResponseData0(v GroupListResponseData0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsGroupListResponseData1 returns the union data inside the GroupListResponse_Data as a GroupListResponseData1 +func (t GroupListResponse_Data) AsGroupListResponseData1() (GroupListResponseData1, error) { + var body GroupListResponseData1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromGroupListResponseData1 overwrites any union data inside the GroupListResponse_Data as the provided GroupListResponseData1 +func (t *GroupListResponse_Data) FromGroupListResponseData1(v GroupListResponseData1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeGroupListResponseData1 performs a merge with any union data inside the GroupListResponse_Data, using the provided GroupListResponseData1 +func (t *GroupListResponse_Data) MergeGroupListResponseData1(v GroupListResponseData1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t GroupListResponse_Data) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *GroupListResponse_Data) UnmarshalJSON(b []byte) error { err := t.union.UnmarshalJSON(b) return err } @@ -5759,3 +6303,375 @@ func (t *PutActionsJSONBody) UnmarshalJSON(b []byte) error { err := t.union.UnmarshalJSON(b) return err } + +// AsDeleteFormsJSONBody0 returns the union data inside the DeleteFormsJSONBody as a DeleteFormsJSONBody0 +func (t DeleteFormsJSONBody) AsDeleteFormsJSONBody0() (DeleteFormsJSONBody0, error) { + var body DeleteFormsJSONBody0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromDeleteFormsJSONBody0 overwrites any union data inside the DeleteFormsJSONBody as the provided DeleteFormsJSONBody0 +func (t *DeleteFormsJSONBody) FromDeleteFormsJSONBody0(v DeleteFormsJSONBody0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeDeleteFormsJSONBody0 performs a merge with any union data inside the DeleteFormsJSONBody, using the provided DeleteFormsJSONBody0 +func (t *DeleteFormsJSONBody) MergeDeleteFormsJSONBody0(v DeleteFormsJSONBody0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsDeleteFormsJSONBody1 returns the union data inside the DeleteFormsJSONBody as a DeleteFormsJSONBody1 +func (t DeleteFormsJSONBody) AsDeleteFormsJSONBody1() (DeleteFormsJSONBody1, error) { + var body DeleteFormsJSONBody1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromDeleteFormsJSONBody1 overwrites any union data inside the DeleteFormsJSONBody as the provided DeleteFormsJSONBody1 +func (t *DeleteFormsJSONBody) FromDeleteFormsJSONBody1(v DeleteFormsJSONBody1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeDeleteFormsJSONBody1 performs a merge with any union data inside the DeleteFormsJSONBody, using the provided DeleteFormsJSONBody1 +func (t *DeleteFormsJSONBody) MergeDeleteFormsJSONBody1(v DeleteFormsJSONBody1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t DeleteFormsJSONBody) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *DeleteFormsJSONBody) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + +// AsPostFormsJSONBody0 returns the union data inside the PostFormsJSONBody as a PostFormsJSONBody0 +func (t PostFormsJSONBody) AsPostFormsJSONBody0() (PostFormsJSONBody0, error) { + var body PostFormsJSONBody0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromPostFormsJSONBody0 overwrites any union data inside the PostFormsJSONBody as the provided PostFormsJSONBody0 +func (t *PostFormsJSONBody) FromPostFormsJSONBody0(v PostFormsJSONBody0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergePostFormsJSONBody0 performs a merge with any union data inside the PostFormsJSONBody, using the provided PostFormsJSONBody0 +func (t *PostFormsJSONBody) MergePostFormsJSONBody0(v PostFormsJSONBody0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsPostFormsJSONBody1 returns the union data inside the PostFormsJSONBody as a PostFormsJSONBody1 +func (t PostFormsJSONBody) AsPostFormsJSONBody1() (PostFormsJSONBody1, error) { + var body PostFormsJSONBody1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromPostFormsJSONBody1 overwrites any union data inside the PostFormsJSONBody as the provided PostFormsJSONBody1 +func (t *PostFormsJSONBody) FromPostFormsJSONBody1(v PostFormsJSONBody1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergePostFormsJSONBody1 performs a merge with any union data inside the PostFormsJSONBody, using the provided PostFormsJSONBody1 +func (t *PostFormsJSONBody) MergePostFormsJSONBody1(v PostFormsJSONBody1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t PostFormsJSONBody) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *PostFormsJSONBody) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + +// AsDeleteFormsPublicationsJSONBody0 returns the union data inside the DeleteFormsPublicationsJSONBody as a DeleteFormsPublicationsJSONBody0 +func (t DeleteFormsPublicationsJSONBody) AsDeleteFormsPublicationsJSONBody0() (DeleteFormsPublicationsJSONBody0, error) { + var body DeleteFormsPublicationsJSONBody0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromDeleteFormsPublicationsJSONBody0 overwrites any union data inside the DeleteFormsPublicationsJSONBody as the provided DeleteFormsPublicationsJSONBody0 +func (t *DeleteFormsPublicationsJSONBody) FromDeleteFormsPublicationsJSONBody0(v DeleteFormsPublicationsJSONBody0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeDeleteFormsPublicationsJSONBody0 performs a merge with any union data inside the DeleteFormsPublicationsJSONBody, using the provided DeleteFormsPublicationsJSONBody0 +func (t *DeleteFormsPublicationsJSONBody) MergeDeleteFormsPublicationsJSONBody0(v DeleteFormsPublicationsJSONBody0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsDeleteFormsPublicationsJSONBody1 returns the union data inside the DeleteFormsPublicationsJSONBody as a DeleteFormsPublicationsJSONBody1 +func (t DeleteFormsPublicationsJSONBody) AsDeleteFormsPublicationsJSONBody1() (DeleteFormsPublicationsJSONBody1, error) { + var body DeleteFormsPublicationsJSONBody1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromDeleteFormsPublicationsJSONBody1 overwrites any union data inside the DeleteFormsPublicationsJSONBody as the provided DeleteFormsPublicationsJSONBody1 +func (t *DeleteFormsPublicationsJSONBody) FromDeleteFormsPublicationsJSONBody1(v DeleteFormsPublicationsJSONBody1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeDeleteFormsPublicationsJSONBody1 performs a merge with any union data inside the DeleteFormsPublicationsJSONBody, using the provided DeleteFormsPublicationsJSONBody1 +func (t *DeleteFormsPublicationsJSONBody) MergeDeleteFormsPublicationsJSONBody1(v DeleteFormsPublicationsJSONBody1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t DeleteFormsPublicationsJSONBody) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *DeleteFormsPublicationsJSONBody) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + +// AsPostFormsPublicationsJSONBody0 returns the union data inside the PostFormsPublicationsJSONBody as a PostFormsPublicationsJSONBody0 +func (t PostFormsPublicationsJSONBody) AsPostFormsPublicationsJSONBody0() (PostFormsPublicationsJSONBody0, error) { + var body PostFormsPublicationsJSONBody0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromPostFormsPublicationsJSONBody0 overwrites any union data inside the PostFormsPublicationsJSONBody as the provided PostFormsPublicationsJSONBody0 +func (t *PostFormsPublicationsJSONBody) FromPostFormsPublicationsJSONBody0(v PostFormsPublicationsJSONBody0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergePostFormsPublicationsJSONBody0 performs a merge with any union data inside the PostFormsPublicationsJSONBody, using the provided PostFormsPublicationsJSONBody0 +func (t *PostFormsPublicationsJSONBody) MergePostFormsPublicationsJSONBody0(v PostFormsPublicationsJSONBody0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsPostFormsPublicationsJSONBody1 returns the union data inside the PostFormsPublicationsJSONBody as a PostFormsPublicationsJSONBody1 +func (t PostFormsPublicationsJSONBody) AsPostFormsPublicationsJSONBody1() (PostFormsPublicationsJSONBody1, error) { + var body PostFormsPublicationsJSONBody1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromPostFormsPublicationsJSONBody1 overwrites any union data inside the PostFormsPublicationsJSONBody as the provided PostFormsPublicationsJSONBody1 +func (t *PostFormsPublicationsJSONBody) FromPostFormsPublicationsJSONBody1(v PostFormsPublicationsJSONBody1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergePostFormsPublicationsJSONBody1 performs a merge with any union data inside the PostFormsPublicationsJSONBody, using the provided PostFormsPublicationsJSONBody1 +func (t *PostFormsPublicationsJSONBody) MergePostFormsPublicationsJSONBody1(v PostFormsPublicationsJSONBody1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t PostFormsPublicationsJSONBody) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *PostFormsPublicationsJSONBody) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + +// AsDeleteFormsResponsiblesJSONBody0 returns the union data inside the DeleteFormsResponsiblesJSONBody as a DeleteFormsResponsiblesJSONBody0 +func (t DeleteFormsResponsiblesJSONBody) AsDeleteFormsResponsiblesJSONBody0() (DeleteFormsResponsiblesJSONBody0, error) { + var body DeleteFormsResponsiblesJSONBody0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromDeleteFormsResponsiblesJSONBody0 overwrites any union data inside the DeleteFormsResponsiblesJSONBody as the provided DeleteFormsResponsiblesJSONBody0 +func (t *DeleteFormsResponsiblesJSONBody) FromDeleteFormsResponsiblesJSONBody0(v DeleteFormsResponsiblesJSONBody0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeDeleteFormsResponsiblesJSONBody0 performs a merge with any union data inside the DeleteFormsResponsiblesJSONBody, using the provided DeleteFormsResponsiblesJSONBody0 +func (t *DeleteFormsResponsiblesJSONBody) MergeDeleteFormsResponsiblesJSONBody0(v DeleteFormsResponsiblesJSONBody0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsDeleteFormsResponsiblesJSONBody1 returns the union data inside the DeleteFormsResponsiblesJSONBody as a DeleteFormsResponsiblesJSONBody1 +func (t DeleteFormsResponsiblesJSONBody) AsDeleteFormsResponsiblesJSONBody1() (DeleteFormsResponsiblesJSONBody1, error) { + var body DeleteFormsResponsiblesJSONBody1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromDeleteFormsResponsiblesJSONBody1 overwrites any union data inside the DeleteFormsResponsiblesJSONBody as the provided DeleteFormsResponsiblesJSONBody1 +func (t *DeleteFormsResponsiblesJSONBody) FromDeleteFormsResponsiblesJSONBody1(v DeleteFormsResponsiblesJSONBody1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeDeleteFormsResponsiblesJSONBody1 performs a merge with any union data inside the DeleteFormsResponsiblesJSONBody, using the provided DeleteFormsResponsiblesJSONBody1 +func (t *DeleteFormsResponsiblesJSONBody) MergeDeleteFormsResponsiblesJSONBody1(v DeleteFormsResponsiblesJSONBody1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t DeleteFormsResponsiblesJSONBody) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *DeleteFormsResponsiblesJSONBody) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + +// AsPostFormsResponsiblesJSONBody0 returns the union data inside the PostFormsResponsiblesJSONBody as a PostFormsResponsiblesJSONBody0 +func (t PostFormsResponsiblesJSONBody) AsPostFormsResponsiblesJSONBody0() (PostFormsResponsiblesJSONBody0, error) { + var body PostFormsResponsiblesJSONBody0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromPostFormsResponsiblesJSONBody0 overwrites any union data inside the PostFormsResponsiblesJSONBody as the provided PostFormsResponsiblesJSONBody0 +func (t *PostFormsResponsiblesJSONBody) FromPostFormsResponsiblesJSONBody0(v PostFormsResponsiblesJSONBody0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergePostFormsResponsiblesJSONBody0 performs a merge with any union data inside the PostFormsResponsiblesJSONBody, using the provided PostFormsResponsiblesJSONBody0 +func (t *PostFormsResponsiblesJSONBody) MergePostFormsResponsiblesJSONBody0(v PostFormsResponsiblesJSONBody0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsPostFormsResponsiblesJSONBody1 returns the union data inside the PostFormsResponsiblesJSONBody as a PostFormsResponsiblesJSONBody1 +func (t PostFormsResponsiblesJSONBody) AsPostFormsResponsiblesJSONBody1() (PostFormsResponsiblesJSONBody1, error) { + var body PostFormsResponsiblesJSONBody1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromPostFormsResponsiblesJSONBody1 overwrites any union data inside the PostFormsResponsiblesJSONBody as the provided PostFormsResponsiblesJSONBody1 +func (t *PostFormsResponsiblesJSONBody) FromPostFormsResponsiblesJSONBody1(v PostFormsResponsiblesJSONBody1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergePostFormsResponsiblesJSONBody1 performs a merge with any union data inside the PostFormsResponsiblesJSONBody, using the provided PostFormsResponsiblesJSONBody1 +func (t *PostFormsResponsiblesJSONBody) MergePostFormsResponsiblesJSONBody1(v PostFormsResponsiblesJSONBody1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t PostFormsResponsiblesJSONBody) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *PostFormsResponsiblesJSONBody) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} diff --git a/server/handlers/forms.go b/server/handlers/forms.go new file mode 100644 index 00000000..2156c275 --- /dev/null +++ b/server/handlers/forms.go @@ -0,0 +1,367 @@ +package serverhandlers + +import ( + "context" + "encoding/json" + "fmt" + "log/slog" + "net/http" + "sort" + "strconv" + "strings" + "time" + + "github.com/labstack/echo/v4" + "gopkg.in/yaml.v3" + + "github.com/opensvc/oc3/cdb" + "github.com/opensvc/oc3/server" + "github.com/opensvc/oc3/util/echolog" +) + +// GetForms handles GET /forms: the forms published to the caller, all of them +// for a manager. +func (a *Api) GetForms(c echo.Context, params server.GetFormsParams) error { + return a.handleList(c, "GetForms", "form", listEndpointParams{ + props: params.Props, limit: params.Limit, offset: params.Offset, + meta: params.Meta, stats: params.Stats, orderby: params.Orderby, groupby: params.Groupby, + filter: params.Filter, virtual: formDefinitionProp, + }, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetForms(ctx, nil, p) + }) +} + +// GetForm handles GET /forms/{form_id}: as GET /forms for one id, empty rather +// than 404 when the form is not visible, as the historical line handler does. +func (a *Api) GetForm(c echo.Context, formId int, params server.GetFormParams) error { + id := int64(formId) + return a.handleList(c, "GetForm", "form", listEndpointParams{ + props: params.Props, limit: params.Limit, offset: params.Offset, + meta: params.Meta, stats: params.Stats, orderby: params.Orderby, groupby: params.Groupby, + filter: params.Filter, virtual: formDefinitionProp, + }, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetForms(ctx, &id, p) + }) +} + +// formResponse reads a form back with its default props, as the historical +// handlers answer a change with rest_get_form().handler(id). The caller has just +// written it: it is read without the publication filter. +func (a *Api) formResponse(ctx context.Context, formID int64) (map[string]any, error) { + items, err := a.defaultRows(ctx, "form", formDefinitionProp, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetForms(ctx, &formID, p) + }) + if err != nil { + return nil, err + } + return map[string]any{"data": items}, nil +} + +// formFields turns posted keys into forms columns: form_definition, a JSON +// document or its string form, becomes form_yaml, and a posted form_yaml must +// parse. Keys that are not columns are refused, where the historical collector +// failed on the database insert. +func formFields(entry map[string]any) (map[string]any, error) { + fields := map[string]any{} + keys := make([]string, 0, len(entry)) + for k := range entry { + keys = append(keys, k) + } + sort.Strings(keys) + var invalid []string + for _, k := range keys { + v := entry[k] + switch { + case k == "id": + // The path names the form; the historical handler drops the key too. + case k == "form_definition": + definition := v + if s, ok := v.(string); ok { + if err := json.Unmarshal([]byte(s), &definition); err != nil { + return nil, formErrorf(http.StatusBadRequest, "invalid form_definition: %s", err) + } + } + b, err := yaml.Marshal(numbersAsValues(definition)) + if err != nil { + return nil, formErrorf(http.StatusBadRequest, "invalid form_definition: %s", err) + } + fields["form_yaml"] = string(b) + case cdb.IsFormColumn(k): + s, _ := entryString(entry, k) + if v == nil { + fields[k] = nil + continue + } + if k == "form_yaml" { + if _, err := parseFormYaml(s); err != nil { + return nil, formErrorf(http.StatusBadRequest, "invalid form_yaml: %s", err) + } + } + fields[k] = s + default: + invalid = append(invalid, k) + } + } + if len(invalid) > 0 { + return nil, formErrorf(http.StatusBadRequest, "invalid properties: %s", strings.Join(invalid, ", ")) + } + return fields, nil +} + +// numbersAsValues converts the json.Number of a decoded body to plain numbers, +// so that the yaml encoder writes them as numbers and not as strings. +func numbersAsValues(v any) any { + switch t := v.(type) { + case json.Number: + if i, err := t.Int64(); err == nil { + return i + } + if f, err := t.Float64(); err == nil { + return f + } + return t.String() + case map[string]any: + for k, item := range t { + t[k] = numbersAsValues(item) + } + case []any: + for i, item := range t { + t[i] = numbersAsValues(item) + } + } + return v +} + +// PostForms handles POST /forms: create forms. +func (a *Api) PostForms(c echo.Context) error { + log := echolog.GetLogHandler(c, "PostForms") + ctx, cancel := context.WithTimeout(c.Request().Context(), a.SyncTimeout) + defer cancel() + if err := requireFormsManager(c); err != nil { + return formProblem(c, err) + } + entries, isList, err := decodeEntries(c) + if err != nil { + return formProblem(c, err) + } + caller, err := a.formCaller(ctx, c) + if err != nil { + return formProblem(c, formInternal(log, "cannot read the caller", err)) + } + defer a.formNotify(ctx, log) + return runEntries(c, entries, isList, func(entry map[string]any) (map[string]any, error) { + return a.createForm(ctx, c, log, caller, entry) + }) +} + +func (a *Api) createForm(ctx context.Context, c echo.Context, log *slog.Logger, caller formCaller, entry map[string]any) (map[string]any, error) { + name, ok := entryString(entry, "form_name") + if !ok || name == "" { + return nil, formErrorf(http.StatusBadRequest, "Key 'form_name' is mandatory") + } + fields, err := formFields(entry) + if err != nil { + return nil, err + } + if _, exists, err := a.ODB.FormIDByName(ctx, name); err != nil { + return nil, formInternal(log, "cannot check the form name", err) + } else if exists { + return nil, formErrorf(http.StatusConflict, "a form named %s already exists", name) + } + fields["form_created"] = time.Now().Format(time.DateTime) + fields["form_author"] = caller.name + + id, err := a.ODB.InsertForm(ctx, fields) + if err != nil { + return nil, formInternal(log, "cannot create the form", err) + } + + // The creator's default group is made responsible for the form and the form + // is published to it, as lib_forms_add_default_team_*() do. + if caller.id != 0 { + groupID, found, err := a.ODB.UserDefaultGroupID(ctx, caller.id) + if err != nil { + return nil, formInternal(log, "cannot read the default group", err) + } + if found { + for _, table := range []cdb.FormTeamTable{cdb.FormResponsibles, cdb.FormPublications} { + if err := a.ODB.InsertFormTeam(ctx, table, id, groupID); err != nil { + return nil, formInternal(log, "cannot link the form to the default group", err) + } + } + } + } + if yamlText, ok := fields["form_yaml"].(string); ok { + a.formCommit(log, id, yamlText, caller) + } + + a.formLog(ctx, c, log, "form.add", "Form %(form_name)s added", map[string]any{"form_name": name}) + return a.formResponse(ctx, id) +} + +// PostForm handles POST /forms/{form_id}: modify a form. +func (a *Api) PostForm(c echo.Context, formId int) error { + log := echolog.GetLogHandler(c, "PostForm") + ctx, cancel := context.WithTimeout(c.Request().Context(), a.SyncTimeout) + defer cancel() + if err := requireFormsManager(c); err != nil { + return formProblem(c, err) + } + entries, isList, err := decodeEntries(c) + if err != nil { + return formProblem(c, err) + } + if isList { + return JSONProblem(c, http.StatusBadRequest, "expecting an object") + } + result, err := a.updateForm(ctx, c, log, int64(formId), entries[0]) + if err != nil { + return formProblem(c, err) + } + a.formNotify(ctx, log) + return c.JSON(http.StatusOK, result) +} + +func (a *Api) updateForm(ctx context.Context, c echo.Context, log *slog.Logger, id int64, entry map[string]any) (map[string]any, error) { + form, err := a.ODB.FormByID(ctx, id) + if err != nil { + return nil, formInternal(log, "cannot read the form", err) + } + if form == nil { + return nil, formErrorf(http.StatusNotFound, "Form %d not found", id) + } + fields, err := formFields(entry) + if err != nil { + return nil, err + } + if name, ok := fields["form_name"].(string); ok && name != form.Name { + if otherID, exists, err := a.ODB.FormIDByName(ctx, name); err != nil { + return nil, formInternal(log, "cannot check the form name", err) + } else if exists && otherID != id { + return nil, formErrorf(http.StatusConflict, "a form named %s already exists", name) + } + } + if err := a.ODB.UpdateForm(ctx, id, fields); err != nil { + return nil, formInternal(log, "cannot update the form", err) + } + + d := map[string]any{"form_name": form.Name, "data": formChanges(form, fields)} + a.formLog(ctx, c, log, "form.change", "Form %(form_name)s change: %(data)s", d) + + if yamlText, ok := fields["form_yaml"].(string); ok && yamlText != "" { + caller, err := a.formCaller(ctx, c) + if err != nil { + return nil, formInternal(log, "cannot read the caller", err) + } + a.formCommit(log, id, yamlText, caller) + } + + result, err := a.formResponse(ctx, id) + if err != nil { + return nil, formInternal(log, "cannot read the form back", err) + } + result["info"] = pyFormat("Form %(form_name)s change: %(data)s", d) + return result, nil +} + +// formChanges describes a change as beautify_change() does: "key: old => new", +// for the changed columns, sorted. +func formChanges(form *cdb.Form, fields map[string]any) string { + current := map[string]string{ + "form_name": form.Name, "form_yaml": form.Yaml, "form_author": form.Author, + "form_created": form.Created, "form_type": form.Type, "form_folder": form.Folder, + } + keys := make([]string, 0, len(fields)) + for k := range fields { + keys = append(keys, k) + } + sort.Strings(keys) + var out []string + for _, k := range keys { + old, known := current[k] + if !known { + continue + } + value := "" + if fields[k] != nil { + value = fmt.Sprint(fields[k]) + } + if old != value { + out = append(out, fmt.Sprintf("%s: %s => %s", k, old, value)) + } + } + return strings.Join(out, ", ") +} + +// DeleteForm handles DELETE /forms/{form_id}. +func (a *Api) DeleteForm(c echo.Context, formId int) error { + log := echolog.GetLogHandler(c, "DeleteForm") + ctx, cancel := context.WithTimeout(c.Request().Context(), a.SyncTimeout) + defer cancel() + result, err := a.deleteForm(ctx, c, log, int64(formId)) + if err != nil { + return formProblem(c, err) + } + a.formNotify(ctx, log) + return c.JSON(http.StatusOK, result) +} + +// DeleteForms handles DELETE /forms: the forms named by the 'id' key. +func (a *Api) DeleteForms(c echo.Context) error { + log := echolog.GetLogHandler(c, "DeleteForms") + ctx, cancel := context.WithTimeout(c.Request().Context(), a.SyncTimeout) + defer cancel() + entries, isList, err := decodeEntries(c) + if err != nil { + return formProblem(c, err) + } + defer a.formNotify(ctx, log) + return runEntries(c, entries, isList, func(entry map[string]any) (map[string]any, error) { + s, ok := entryString(entry, "id") + if !ok { + return nil, formErrorf(http.StatusBadRequest, "The 'id' key is mandatory") + } + id, err := parseFormID(s) + if err != nil { + return nil, err + } + return a.deleteForm(ctx, c, log, id) + }) +} + +func (a *Api) deleteForm(ctx context.Context, c echo.Context, log *slog.Logger, id int64) (map[string]any, error) { + if err := requireFormsManager(c); err != nil { + return nil, err + } + if err := a.requireFormResponsible(c, log, ctx, id); err != nil { + return nil, err + } + form, err := a.ODB.FormByID(ctx, id) + if err != nil { + return nil, formInternal(log, "cannot read the form", err) + } + if form == nil { + return nil, formErrorf(http.StatusNotFound, "Form %d not found", id) + } + if err := a.ODB.DeleteForm(ctx, id); err != nil { + return nil, formInternal(log, "cannot delete the form", err) + } + d := map[string]any{"form_name": form.Name} + a.formLog(ctx, c, log, "form.del", "Form %(form_name)s deleted", d) + return map[string]any{"info": pyFormat("Form %(form_name)s deleted", d)}, nil +} + +// GetFormAmIResponsible handles GET /forms/{form_id}/am_i_responsible. +func (a *Api) GetFormAmIResponsible(c echo.Context, formId int) error { + log := echolog.GetLogHandler(c, "GetFormAmIResponsible") + ctx, cancel := context.WithTimeout(c.Request().Context(), a.SyncTimeout) + defer cancel() + ok, err := a.ODB.FormResponsible(ctx, int64(formId), UserGroupsFromContext(c), IsManager(c)) + if err != nil { + return formProblem(c, formInternal(log, "cannot check form responsibility", err)) + } + return c.JSON(http.StatusOK, map[string]bool{"data": ok}) +} + +// formIDString renders a form id as the historical messages print it. +func formIDString(id int64) string { return strconv.FormatInt(id, 10) } diff --git a/server/handlers/forms_common.go b/server/handlers/forms_common.go new file mode 100644 index 00000000..30177aa8 --- /dev/null +++ b/server/handlers/forms_common.go @@ -0,0 +1,301 @@ +package serverhandlers + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "log/slog" + "net/http" + "strconv" + "strings" + + "github.com/labstack/echo/v4" + "gopkg.in/yaml.v3" + + "github.com/opensvc/oc3/cdb" + "github.com/opensvc/oc3/util/logkey" +) + +// formError is a forms request refused with an HTTP status, the way the +// historical collector raised HTTP(status, message). +type formError struct { + status int + msg string +} + +func (e *formError) Error() string { return e.msg } + +func formErrorf(status int, format string, args ...any) error { + return &formError{status: status, msg: fmt.Sprintf(format, args...)} +} + +// formProblem writes the problem response of a forms request. +func formProblem(c echo.Context, err error) error { + var fe *formError + if errors.As(err, &fe) { + return JSONProblem(c, fe.status, fe.msg) + } + return JSONProblem(c, http.StatusInternalServerError, err.Error()) +} + +// formInternal logs an internal failure and turns it into a 500 with a +// message that does not leak the database error. +func formInternal(log *slog.Logger, msg string, err error) error { + log.Error(msg, logkey.Error, err) + return formErrorf(http.StatusInternalServerError, "%s", msg) +} + +// requireFormsManager refuses a caller without the FormsManager privilege, as +// check_privilege("FormsManager") does: a manager always passes. +func requireFormsManager(c echo.Context) error { + if !IsAuthByUser(c) { + return formErrorf(http.StatusUnauthorized, "user authentication required") + } + if !IsManager(c) && !HasGroup(c, "FormsManager") { + return formErrorf(http.StatusForbidden, "user has no FormsManager privilege") + } + return nil +} + +// formCaller is the authenticated user, as the forms record it. +type formCaller struct { + id int64 + name string // "First Last", as user_name() + email string +} + +// author returns "First Last ", as user_name(email=True). +func (fc formCaller) author() string { + if fc.email == "" { + return fc.name + } + return fc.name + " <" + fc.email + ">" +} + +func (a *Api) formCaller(ctx context.Context, c echo.Context) (formCaller, error) { + id := authUserID(c) + if id == nil { + if nodeID, _ := c.Get(XNodeID).(string); nodeID != "" { + return formCaller{name: "agent"}, nil + } + return formCaller{name: "Unknown"}, nil + } + name, email, err := a.ODB.UserName(ctx, *id) + if err != nil { + return formCaller{}, err + } + return formCaller{id: *id, name: name, email: email}, nil +} + +// decodeEntries reads a JSON body holding one object or a list of objects, as +// the historical collector's handlers accept both. isList tells which. A +// form-encoded body, as the historical examples post (curl -d key=value), is +// read as one object of strings. +func decodeEntries(c echo.Context) (entries []map[string]any, isList bool, err error) { + contentType := c.Request().Header.Get(echo.HeaderContentType) + if strings.HasPrefix(contentType, echo.MIMEApplicationForm) || strings.HasPrefix(contentType, echo.MIMEMultipartForm) { + values, err := c.FormParams() + if err != nil { + return nil, false, formErrorf(http.StatusBadRequest, "invalid request body: %s", err) + } + entry := make(map[string]any, len(values)) + for k, v := range values { + if len(v) > 0 { + entry[k] = v[0] + } + } + return []map[string]any{entry}, false, nil + } + var raw json.RawMessage + if err := json.NewDecoder(c.Request().Body).Decode(&raw); err != nil { + return nil, false, formErrorf(http.StatusBadRequest, "invalid request body: %s", err) + } + decoder := json.NewDecoder(bytes.NewReader(raw)) + decoder.UseNumber() + if trimmed := bytes.TrimSpace(raw); len(trimmed) > 0 && trimmed[0] == '[' { + if err := decoder.Decode(&entries); err != nil { + return nil, true, formErrorf(http.StatusBadRequest, "invalid request body: %s", err) + } + return entries, true, nil + } + var entry map[string]any + if err := decoder.Decode(&entry); err != nil { + return nil, false, formErrorf(http.StatusBadRequest, "invalid request body: %s", err) + } + return []map[string]any{entry}, false, nil +} + +// entryString reads a key of a decoded entry as a string, as posted form +// variables are. +func entryString(entry map[string]any, key string) (string, bool) { + v, ok := entry[key] + if !ok || v == nil { + return "", ok + } + switch t := v.(type) { + case string: + return t, true + case json.Number: + return t.String(), true + } + return fmt.Sprint(v), true +} + +// runEntries answers a request whose body is one entry or a list. One entry +// answers with its result or its problem; a list always answers 200 and merges +// the info, error and data keys of every entry, as handle_list() does. +func runEntries(c echo.Context, entries []map[string]any, isList bool, run func(entry map[string]any) (map[string]any, error)) error { + if !isList { + result, err := run(entries[0]) + if err != nil { + return formProblem(c, err) + } + return c.JSON(http.StatusOK, result) + } + merged := map[string][]any{"info": {}, "error": {}, "data": {}} + for _, entry := range entries { + result, err := run(entry) + if err != nil { + status := http.StatusInternalServerError + var fe *formError + if errors.As(err, &fe) { + status = fe.status + } + merged["error"] = append(merged["error"], fmt.Sprintf("%d %s: %s", status, http.StatusText(status), err.Error())) + continue + } + for _, key := range []string{"info", "error", "data"} { + value, ok := result[key] + if !ok { + continue + } + switch v := value.(type) { + case []any: + merged[key] = append(merged[key], v...) + case []map[string]any: + for _, item := range v { + merged[key] = append(merged[key], item) + } + case []string: + for _, item := range v { + merged[key] = append(merged[key], item) + } + default: + merged[key] = append(merged[key], v) + } + } + } + return c.JSON(http.StatusOK, merged) +} + +// parseFormYaml parses a form definition into JSON-ready values. +func parseFormYaml(s string) (any, error) { + var v any + if err := yaml.Unmarshal([]byte(s), &v); err != nil { + return nil, err + } + return jsonReady(v), nil +} + +// jsonReady converts the maps yaml decodes with non-string keys, which JSON +// cannot encode, keying them by their text. +func jsonReady(v any) any { + switch t := v.(type) { + case map[string]any: + for k, item := range t { + t[k] = jsonReady(item) + } + return t + case map[any]any: + out := make(map[string]any, len(t)) + for k, item := range t { + out[fmt.Sprint(k)] = jsonReady(item) + } + return out + case []any: + for i, item := range t { + t[i] = jsonReady(item) + } + return t + } + return v +} + +// formDefinitionProp computes form_definition from form_yaml, left out when the +// yaml does not parse, as mangle_form_data() does. +var formDefinitionProp = map[string]virtualProp{ + "form_definition": { + requires: []string{"form_yaml"}, + compute: func(item map[string]any) (any, bool) { + s, _ := item["form_yaml"].(string) + v, err := parseFormYaml(s) + if err != nil { + return nil, false + } + return v, true + }, + }, +} + +// parseFormID reads a form id given as a path segment or a body key. +func parseFormID(s string) (int64, error) { + id, err := strconv.ParseInt(s, 10, 64) + if err != nil { + return 0, formErrorf(http.StatusBadRequest, "invalid form id %q", s) + } + return id, nil +} + +// requireFormResponsible refuses a caller not responsible for the form, as +// form_responsible() does, with its 404. +func (a *Api) requireFormResponsible(c echo.Context, log *slog.Logger, ctx context.Context, formID int64) error { + ok, err := a.ODB.FormResponsible(ctx, formID, UserGroupsFromContext(c), IsManager(c)) + if err != nil { + return formInternal(log, "cannot check form responsibility", err) + } + if !ok { + return formErrorf(http.StatusNotFound, "Form %d not found or you are not responsible", formID) + } + return nil +} + +// requireFormPublished refuses a caller the form is not published to, as +// form_published() does, with its 404. +func (a *Api) requireFormPublished(c echo.Context, log *slog.Logger, ctx context.Context, formID int64) error { + ok, err := a.ODB.FormVisible(ctx, formID, UserGroupsFromContext(c), IsManager(c)) + if err != nil { + return formInternal(log, "cannot check form publication", err) + } + if !ok { + return formErrorf(http.StatusNotFound, "Form %d not found or not published to you", formID) + } + return nil +} + +// formLog writes an audit log entry of a forms change. +func (a *Api) formLog(ctx context.Context, c echo.Context, log *slog.Logger, action, format string, dict map[string]any) { + userEmail, _ := c.Get(XUserEmail).(string) + if err := a.ODB.Log(ctx, cdb.LogEntry{Action: action, User: userEmail, Fmt: format, Dict: dict, Level: "info"}); err != nil { + log.Error("cannot write audit log", logkey.Error, err) + } +} + +// formNotify publishes the changes of a forms request to the messenger. +func (a *Api) formNotify(ctx context.Context, log *slog.Logger) { + if err := a.ODB.Session.NotifyChanges(ctx); err != nil { + log.Error("cannot notify changes", logkey.Error, err) + } +} + +// pyFormat renders a historical collector message, "%(key)s" placeholders +// filled from dict, for the info messages the answers carry. +func pyFormat(format string, dict map[string]any) string { + out := format + for k, v := range dict { + out = strings.ReplaceAll(out, "%("+k+")s", fmt.Sprint(v)) + out = strings.ReplaceAll(out, "%("+k+")d", fmt.Sprint(v)) + } + return out +} diff --git a/server/handlers/forms_engine.go b/server/handlers/forms_engine.go new file mode 100644 index 00000000..d8e84ffa --- /dev/null +++ b/server/handlers/forms_engine.go @@ -0,0 +1,297 @@ +package serverhandlers + +import ( + "encoding/json" + "fmt" + "sort" + "strconv" + "strings" +) + +// The functions of this file port the form data helpers of the historical +// collector (init/models/rest/lib_forms.py), keeping their semantics: form data +// is the object a form submission carries, keyed by input id. + +// formValueString returns the text of a submitted value when it is one; the +// historical conditions compare strings, a number never equals "1". +func formValueString(v any) (string, bool) { + s, ok := v.(string) + return s, ok +} + +// formValueText renders a submitted value as unicode(val) does, for the +// dereferencing of "#key" references. +func formValueText(v any) string { + switch t := v.(type) { + case nil: + return "None" + case string: + return t + case bool: + if t { + return "True" + } + return "False" + case json.Number: + return t.String() + case float64: + return strconv.FormatFloat(t, 'f', -1, 64) + } + b, err := json.Marshal(v) + if err != nil { + return fmt.Sprint(v) + } + return string(b) +} + +// formGetVal returns the value of a dotted key "a.b.c" in nested objects, as +// form_get_val() does. +func formGetVal(d any, key string) (any, error) { + parts := strings.Split(key, ".") + cur := d + for _, part := range parts { + m, ok := cur.(map[string]any) + if !ok { + return nil, fmt.Errorf("%s", part) + } + v, ok := m[part] + if !ok { + return nil, fmt.Errorf("%s", part) + } + cur = v + } + return cur, nil +} + +// formRestArgs splits a rest url into path elements, "#key" references +// replaced by their value, as form_rest_args() does: +// "/arrays/#id/diskgroups" gives [arrays 554 diskgroups]. +func formRestArgs(url string, d any) ([]string, error) { + var args []string + for _, s := range strings.Split(strings.TrimRight(url, "/"), "/") { + if s == "" { + continue + } + if strings.HasPrefix(s, "#") { + v, err := formGetVal(d, strings.TrimLeft(s, "#")) + if err != nil { + return nil, err + } + args = append(args, formValueText(v)) + continue + } + args = append(args, s) + } + return args, nil +} + +// formDereference replaces the "#key" references of s by the values of the +// data, nested keys as "#a.b", as form_dereference() does: keys are replaced +// longest name first, so that "#name" does not eat the start of "#names". +func formDereference(s string, data map[string]any, prefix string) string { + keys := make([]string, 0, len(data)) + for k := range data { + keys = append(keys, k) + } + sort.Sort(sort.Reverse(sort.StringSlice(keys))) + for _, k := range keys { + if sub, ok := data[k].(map[string]any); ok { + s = formDereference(s, sub, prefix+k+".") + continue + } + s = strings.ReplaceAll(s, "#"+prefix+k, formValueText(data[k])) + } + return s +} + +// formEmpty tells whether a submitted value counts as empty in a condition. +func formEmpty(d map[string]any, key string) bool { + v, ok := d[key] + if !ok || v == nil { + return true + } + s, isString := v.(string) + return isString && (s == "" || s == "undefined") +} + +// checkFormConditions evaluates an input condition: one condition, or a list of +// them that must all hold. +func checkFormConditions(cond any, d map[string]any) (bool, error) { + if list, ok := cond.([]any); ok { + for _, c := range list { + ok, err := checkFormCondition(c, d) + if err != nil || !ok { + return false, err + } + } + return true, nil + } + return checkFormCondition(cond, d) +} + +// checkFormCondition evaluates one "#var op value" condition, as +// check_condition() does: ==, !=, IN, NOT IN, > and <, "empty" standing for a +// missing or empty value. +func checkFormCondition(condAny any, d map[string]any) (bool, error) { + if condAny == nil { + return false, fmt.Errorf("malformed condition: None") + } + cond, ok := condAny.(string) + if !ok { + return false, fmt.Errorf("malformed condition: %v", condAny) + } + if cond == "" || cond == "none" { + return true, nil + } + getVarVal := func(op string) (string, string, error) { + parts := strings.SplitN(cond, op, 2) + if len(parts) != 2 { + return "", "", fmt.Errorf("malformed output condition: %s", cond) + } + v, val := strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1]) + if !strings.HasPrefix(v, "#") || len(v) < 2 { + return "", "", fmt.Errorf("malformed output condition: %s", cond) + } + return v[1:], val, nil + } + if d == nil { + return false, fmt.Errorf("no form data") + } + switch { + case strings.Contains(cond, "=="): + v, val, err := getVarVal("==") + if err != nil { + return false, err + } + if val == "empty" { + return formEmpty(d, v), nil + } + s, isString := formValueString(d[v]) + return isString && s == val, nil + case strings.Contains(cond, "!="): + v, val, err := getVarVal("!=") + if err != nil { + return false, err + } + if val == "empty" { + return !formEmpty(d, v), nil + } + if _, ok := d[v]; !ok { + return true, nil + } + s, isString := formValueString(d[v]) + return !isString || s != val, nil + case strings.Contains(cond, " NOT IN "): + v, val, err := getVarVal("NOT IN") + if err != nil { + return false, err + } + if _, ok := d[v]; !ok { + return true, nil + } + s, isString := formValueString(d[v]) + return !isString || !containsString(strings.Split(val, ","), s), nil + case strings.Contains(cond, " IN "): + v, val, err := getVarVal("IN") + if err != nil { + return false, err + } + if _, ok := d[v]; !ok { + return false, nil + } + s, isString := formValueString(d[v]) + return isString && containsString(strings.Split(val, ","), s), nil + case strings.Contains(cond, " > "), strings.Contains(cond, " < "): + op := ">" + if !strings.Contains(cond, " > ") { + op = "<" + } + v, val, err := getVarVal(op) + if err != nil { + return false, err + } + ref, err := strconv.ParseFloat(val, 64) + if err != nil { + return false, nil + } + raw, ok := d[v] + if !ok { + return false, nil + } + f, err := strconv.ParseFloat(formValueText(raw), 64) + if err != nil { + return false, nil + } + if op == ">" { + return f > ref, nil + } + return f < ref, nil + } + return false, fmt.Errorf("operator is not supported in condition %s", cond) +} + +func containsString(list []string, s string) bool { + for _, item := range list { + if item == s { + return true + } + } + return false +} + +// checkInputCondition tells whether an input applies to the data. +func checkInputCondition(input map[string]any, d map[string]any) (bool, error) { + cond, ok := input["Condition"] + if !ok { + return true, nil + } + return checkFormConditions(cond, d) +} + +// checkOutputCondition tells whether an output runs for the data. A condition +// is only allowed on a dict-format output. +func checkOutputCondition(output map[string]any, d any) (bool, error) { + cond, ok := output["Condition"] + if !ok { + return true, nil + } + if output["Format"] != "dict" { + return false, fmt.Errorf("Output condition can only be set on dict-format output") + } + m, _ := d.(map[string]any) + return checkFormCondition(cond, m) +} + +// defString reads a string property of a form definition element. +func defString(m map[string]any, key string) string { + s, _ := m[key].(string) + return s +} + +// defBool reads a boolean property of a form definition element. +func defBool(m map[string]any, key string) bool { + switch t := m[key].(type) { + case bool: + return t + case string: + return t == "yes" || t == "true" || t == "True" + } + return false +} + +// defList reads a list property of a form definition element. +func defList(m map[string]any, key string) []any { + l, _ := m[key].([]any) + return l +} + +// defMaps reads a list of objects of a form definition element. +func defMaps(m map[string]any, key string) []map[string]any { + var out []map[string]any + for _, item := range defList(m, key) { + if sub, ok := item.(map[string]any); ok { + out = append(out, sub) + } + } + return out +} diff --git a/server/handlers/forms_engine_test.go b/server/handlers/forms_engine_test.go new file mode 100644 index 00000000..51705a65 --- /dev/null +++ b/server/handlers/forms_engine_test.go @@ -0,0 +1,133 @@ +package serverhandlers + +import ( + "encoding/json" + "reflect" + "testing" +) + +func TestCheckFormCondition(t *testing.T) { + d := map[string]any{ + "os": "linux", + "size": "12", + "count": json.Number("3"), + "blank": "", + "undef": "undefined", + } + cases := []struct { + cond string + want bool + }{ + {"", true}, + {"none", true}, + {"#os == linux", true}, + {"#os == aix", false}, + {"#missing == linux", false}, + {"#count == 3", false}, // a number never equals a string, as in python + {"#blank == empty", true}, + {"#undef == empty", true}, + {"#missing == empty", true}, + {"#os == empty", false}, + {"#os != aix", true}, + {"#os != linux", false}, + {"#missing != linux", true}, + {"#count != 3", true}, + {"#os != empty", true}, + {"#blank != empty", false}, + {"#os IN aix,linux", true}, + {"#os IN aix,sunos", false}, + {"#missing IN linux", false}, + {"#os NOT IN aix,sunos", true}, + {"#os NOT IN aix,linux", false}, + {"#missing NOT IN linux", true}, + {"#size > 10", true}, + {"#size > 12", false}, + {"#size < 13", true}, + {"#count > 2", true}, + {"#os > 2", false}, + } + for _, c := range cases { + got, err := checkFormCondition(c.cond, d) + if err != nil { + t.Errorf("%q: unexpected error %s", c.cond, err) + continue + } + if got != c.want { + t.Errorf("%q: got %v, want %v", c.cond, got, c.want) + } + } + for _, bad := range []any{nil, "os == linux", "#os ~ linux"} { + if _, err := checkFormCondition(bad, d); err == nil { + t.Errorf("%v: expected an error", bad) + } + } +} + +func TestCheckFormConditionsList(t *testing.T) { + d := map[string]any{"os": "linux", "arch": "x86_64"} + ok, err := checkFormConditions([]any{"#os == linux", "#arch == x86_64"}, d) + if err != nil || !ok { + t.Errorf("all conditions hold: got %v %v", ok, err) + } + ok, err = checkFormConditions([]any{"#os == linux", "#arch == ppc"}, d) + if err != nil || ok { + t.Errorf("one condition fails: got %v %v", ok, err) + } +} + +func TestFormDereference(t *testing.T) { + data := map[string]any{ + "name": "db1", + "names": "db1,db2", + "array": map[string]any{"id": json.Number("554")}, + } + got := formDereference("#names for #name on #array.id", data, "") + if want := "db1,db2 for db1 on 554"; got != want { + t.Errorf("got %q, want %q", got, want) + } +} + +func TestFormRestArgs(t *testing.T) { + data := map[string]any{"id": json.Number("554"), "dg": map[string]any{"id": "2525"}} + got, err := formRestArgs("/arrays/#id/diskgroups/#dg.id/quotas/", data) + if err != nil { + t.Fatal(err) + } + if want := []string{"arrays", "554", "diskgroups", "2525", "quotas"}; !reflect.DeepEqual(got, want) { + t.Errorf("got %v, want %v", got, want) + } + if _, err := formRestArgs("/arrays/#missing", data); err == nil { + t.Error("a missing reference must fail") + } +} + +func TestCheckOutputCondition(t *testing.T) { + d := map[string]any{"os": "linux"} + if _, err := checkOutputCondition(map[string]any{"Condition": "#os == linux"}, d); err == nil { + t.Error("a condition on a non-dict output must fail") + } + ok, err := checkOutputCondition(map[string]any{"Condition": "#os == linux", "Format": "dict"}, d) + if err != nil || !ok { + t.Errorf("got %v %v", ok, err) + } + ok, err = checkOutputCondition(map[string]any{}, d) + if err != nil || !ok { + t.Errorf("no condition: got %v %v", ok, err) + } +} + +func TestInternalForms(t *testing.T) { + for id := int64(-1); id >= -10; id-- { + f, ok := internalFormByID(id) + if !ok { + t.Errorf("internal form %d missing", id) + continue + } + if f.Name == "" || len(defMaps(f.Definition, "Outputs")) == 0 && id > -9 { + t.Errorf("internal form %d: incomplete %+v", id, f) + } + } + if _, ok := internalFormByID(-11); ok { + t.Error("internal form -11 must not exist") + } +} diff --git a/server/handlers/forms_git.go b/server/handlers/forms_git.go new file mode 100644 index 00000000..ed888a67 --- /dev/null +++ b/server/handlers/forms_git.go @@ -0,0 +1,149 @@ +package serverhandlers + +import ( + "context" + "log/slog" + "net/http" + "strconv" + + "github.com/labstack/echo/v4" + "github.com/spf13/viper" + + "github.com/opensvc/oc3/server" + "github.com/opensvc/oc3/util/echolog" + "github.com/opensvc/oc3/util/git" + "github.com/opensvc/oc3/util/logkey" +) + +// formTrack is the git history of the form definitions: one repository per +// form, holding its yaml in a file named "forms", as the historical collector +// lays them out. +func formTrack() git.Track { + return git.Track{Dir: viper.GetString("server.directories.forms"), File: "forms"} +} + +// formCommit records a new form definition in its history. As the historical +// collector, a failed commit does not fail the change of the form: it is logged. +func (a *Api) formCommit(log *slog.Logger, formID int64, content string, caller formCaller) { + if err := formTrack().Commit(strconv.FormatInt(formID, 10), content, caller.author()); err != nil { + log.Error("cannot record the form revision", "form_id", formID, logkey.Error, err) + } +} + +// formRevisionsAllowed tells whether the caller may read the history of a form: +// the historical handlers answer an empty list rather than an error otherwise. +func (a *Api) formRevisionsAllowed(ctx context.Context, c echo.Context, log *slog.Logger, formID int64) (bool, error) { + ok, err := a.ODB.FormVisible(ctx, formID, UserGroupsFromContext(c), IsManager(c)) + if err != nil { + return false, formInternal(log, "cannot check form publication", err) + } + return ok, nil +} + +// GetFormRevisions handles GET /forms/{form_id}/revisions. +func (a *Api) GetFormRevisions(c echo.Context, formId int) error { + log := echolog.GetLogHandler(c, "GetFormRevisions") + ctx := c.Request().Context() + allowed, err := a.formRevisionsAllowed(ctx, c, log, int64(formId)) + if err != nil { + return formProblem(c, err) + } + if !allowed { + return c.JSON(http.StatusOK, []any{}) + } + revisions, err := formTrack().Timeline(strconv.Itoa(formId)) + if err != nil { + return formProblem(c, formInternal(log, "cannot read the form history", err)) + } + return c.JSON(http.StatusOK, map[string]any{"data": revisions}) +} + +// GetFormRevision handles GET /forms/{form_id}/revisions/{cid}. +func (a *Api) GetFormRevision(c echo.Context, formId int, cid string) error { + log := echolog.GetLogHandler(c, "GetFormRevision") + ctx := c.Request().Context() + if !git.ValidRev(cid) { + return JSONProblemf(c, http.StatusBadRequest, "invalid revision %q", cid) + } + allowed, err := a.formRevisionsAllowed(ctx, c, log, int64(formId)) + if err != nil { + return formProblem(c, err) + } + if !allowed { + return c.JSON(http.StatusOK, []any{}) + } + blob, err := formTrack().At(strconv.Itoa(formId), cid) + if err != nil { + return formProblem(c, formErrorf(http.StatusNotFound, "revision %s not found", cid)) + } + if blob == nil { + return c.JSON(http.StatusOK, map[string]any{"data": ""}) + } + return c.JSON(http.StatusOK, map[string]any{"data": blob}) +} + +// GetFormDiff handles GET /forms/{form_id}/diff/{cid}: the change of a revision, +// or its differences with another. +func (a *Api) GetFormDiff(c echo.Context, formId int, cid string, params server.GetFormDiffParams) error { + log := echolog.GetLogHandler(c, "GetFormDiff") + ctx := c.Request().Context() + if !git.ValidRev(cid) || (params.Other != nil && *params.Other != "" && !git.ValidRev(*params.Other)) { + return JSONProblemf(c, http.StatusBadRequest, "invalid revision") + } + allowed, err := a.formRevisionsAllowed(ctx, c, log, int64(formId)) + if err != nil { + return formProblem(c, err) + } + if !allowed { + return c.JSON(http.StatusOK, []any{}) + } + var out string + if params.Other != nil && *params.Other != "" { + out, err = formTrack().Diff(strconv.Itoa(formId), cid, *params.Other) + } else { + out, err = formTrack().Show(strconv.Itoa(formId), cid) + } + if err != nil { + return formProblem(c, formErrorf(http.StatusNotFound, "revision %s not found", cid)) + } + return c.JSON(http.StatusOK, map[string]any{"data": out}) +} + +// PostFormRollback handles POST /forms/{form_id}/rollback/{cid}: restore the +// definition of a revision, recorded as a new revision, and store it as the +// form yaml. +func (a *Api) PostFormRollback(c echo.Context, formId int, cid string) error { + log := echolog.GetLogHandler(c, "PostFormRollback") + ctx, cancel := context.WithTimeout(c.Request().Context(), a.SyncTimeout) + defer cancel() + if !git.ValidRev(cid) { + return JSONProblemf(c, http.StatusBadRequest, "invalid revision %q", cid) + } + if err := requireFormsManager(c); err != nil { + return formProblem(c, err) + } + formID := int64(formId) + if err := a.requireFormResponsible(c, log, ctx, formID); err != nil { + return formProblem(c, err) + } + caller, err := a.formCaller(ctx, c) + if err != nil { + return formProblem(c, formInternal(log, "cannot read the caller", err)) + } + track := formTrack() + id := strconv.Itoa(formId) + if err := track.Rollback(id, cid, caller.author()); err != nil { + log.Error("cannot roll the form back", "form_id", formId, "cid", cid, logkey.Error, err) + return formProblem(c, formErrorf(http.StatusNotFound, "cannot roll form %d back to %s", formId, cid)) + } + content, err := track.Read(id) + if err != nil { + return formProblem(c, formInternal(log, "cannot read the restored form", err)) + } + if err := a.ODB.UpdateForm(ctx, formID, map[string]any{"form_yaml": content}); err != nil { + return formProblem(c, formInternal(log, "cannot store the restored form", err)) + } + a.formNotify(ctx, log) + // The historical handler returns nothing. + return c.JSON(http.StatusOK, nil) +} diff --git a/server/handlers/forms_internal.json b/server/handlers/forms_internal.json new file mode 100644 index 00000000..c00f90cf --- /dev/null +++ b/server/handlers/forms_internal.json @@ -0,0 +1,686 @@ +[ + { + "id": -1, + "form_name": "internal_add_contextual_thresholds", + "form_folder": "/internal", + "form_type": "generic", + "form_definition": { + "Vertical": true, + "Outputs": [ + { + "Type": "json", + "Format": "dict", + "Dest": "rest", + "Function": "/checks/contextual_settings", + "Handler": "POST" + } + ], + "Inputs": [ + { + "Id": "chk_type", + "Label": "Type", + "LabelCss": "check16", + "Type": "string", + "Mandatory": true, + "Function": "/checks/live", + "Args": [ + "props = chk_type", + "groupby = chk_type", + "orderby = chk_type", + "meta = 0", + "limit = 0" + ], + "DisableAutoDefault": true + }, + { + "Id": "chk_instance", + "Label": "Instance regex", + "LabelCss": "check16", + "Type": "string", + "Mandatory": true + }, + { + "Id": "chk_low", + "Label": "Low threshold", + "LabelCss": "fa-step-backward", + "Type": "integer", + "Constraint": "match [0-9]*" + }, + { + "Id": "chk_high", + "Label": "High threshold", + "LabelCss": "fa-step-forward", + "Type": "integer", + "Constraint": "match [0-9]*" + }, + { + "Id": "fset_id", + "Label": "Filterset", + "LabelCss": "filter16", + "Type": "string", + "Mandatory": true, + "Function": "/filtersets", + "Args": [ + "props = id,fset_name", + "orderby = fset_name", + "meta = 0", + "limit = 0" + ], + "Value": "#id", + "Format": "#fset_name", + "DisableAutoDefault": true + } + ] + } + }, + { + "id": -2, + "form_name": "internal_add_dns_record", + "form_folder": "/internal", + "form_type": "generic", + "form_definition": { + "Outputs": [ + { + "Dest": "rest", + "Function": "/dns/records", + "Handler": "POST", + "Type": "json", + "Format": "dict" + } + ], + "Vertical": true, + "Css": "dns48", + "Inputs": [ + { + "Mandatory": true, + "DisplayModeLabel": "name", + "LabelCss": "dns16", + "Label": "Name", + "Type": "string", + "Id": "name" + }, + { + "Function": "/dns/domains", + "Mandatory": true, + "Format": "#name", + "Args": [ + "props = id,name", + "limit = 0", + "meta = 0", + "orderby = name" + ], + "Value": "#id", + "DisplayModeLabel": "zone", + "LabelCss": "dns16", + "Label": "Domain", + "Type": "string", + "Id": "domain_id" + }, + { + "Default": 120, + "Label": "TTL", + "DisplayModeLabel": "ttl", + "LabelCss": "dns16", + "Type": "integer", + "Id": "ttl" + }, + { + "Default": 0, + "Label": "Priority", + "DisplayModeLabel": "prio", + "LabelCss": "dns16", + "Type": "integer", + "Id": "prio" + }, + { + "Mandatory": true, + "Default": "A", + "Label": "Type", + "Candidates": [ + "A", + "AAAA", + "A6", + "CNAME", + "DNAME", + "DNSKEY", + "DS", + "HINFO", + "ISDN", + "KEY", + "LOC", + "MX", + "NAPTR", + "NS", + "NSEC", + "PTR", + "SOA", + "SRV", + "TXT" + ], + "LabelCss": "dns16", + "DisplayModeLabel": "type", + "Type": "string", + "Id": "type" + }, + { + "Function": "/networks", + "Mandatory": false, + "Format": "#name (#network/#netmask)", + "Args": [ + "props = id,name,network,netmask", + "limit = 0", + "meta = 0", + "orderby = name" + ], + "Value": "#id", + "DisplayModeLabel": "network", + "LabelCss": "net16", + "Label": "Network", + "Type": "string", + "Id": "network", + "Condition": "#type == A" + }, + { + "Label": "Content", + "Key": "content", + "LabelCss": "dns16", + "DisplayModeLabel": "content", + "Type": "string", + "Id": "content_not_a", + "Condition": "#type != A" + }, + { + "Function": "/networks/#network/ips", + "Format": "#ip (t:#type n:#nodename r:#record_name)", + "Args": [ + "props = ip,type,nodename,record_name" + ], + "Value": "#ip", + "DisplayModeLabel": "content", + "Key": "content", + "LabelCss": "dns16", + "Label": "Content", + "Type": "string", + "Id": "content_a", + "Condition": "#type == A" + } + ] + } + }, + { + "id": -3, + "form_name": "internal_add_network_segment", + "form_folder": "/internal", + "form_type": "generic", + "form_definition": { + "Outputs": [ + { + "Dest": "rest", + "Function": "/networks/#net_id/segments", + "Handler": "POST", + "Type": "json", + "Format": "dict" + } + ], + "Css": "net16 fa-2x", + "Inputs": [ + { + "Mandatory": true, + "Default": "static", + "StrictCandidates": true, + "DisplayModeLabel": "type", + "Candidates": [ + "static", + "dynamic" + ], + "LabelCss": "net16", + "Label": "Type", + "Id": "seg_type" + }, + { + "Function": "/networks", + "Mandatory": true, + "Format": "#name #network/#netmask", + "Args": [ + "props = id,name,network,netmask", + "limit = 0", + "meta = 0", + "orderby = network" + ], + "Value": "#id", + "DisplayModeLabel": "network", + "LabelCss": "net16", + "Label": "Network", + "Type": "integer", + "Id": "net_id" + }, + { + "Label": "Begin", + "DisplayModeLabel": "begin", + "Type": "string", + "Id": "seg_begin", + "LabelCss": "net16" + }, + { + "Label": "End", + "DisplayModeLabel": "end", + "Type": "string", + "Id": "seg_end", + "LabelCss": "net16" + } + ] + } + }, + { + "id": -4, + "form_name": "internal_add_quota", + "form_folder": "/internal", + "form_type": "generic", + "form_definition": { + "Outputs": [ + { + "Function": "/arrays/#array_id/diskgroups/#dg_id/quotas", + "Format": "dict", + "Keys": [ + "app_id", + "quota" + ], + "Dest": "rest", + "Handler": "POST", + "Type": "json" + } + ], + "Css": "disk48", + "Inputs": [ + { + "Function": "/arrays", + "Mandatory": true, + "DisableAutoDefault": true, + "Format": "#array_name", + "Args": [ + "props = array_name,id", + "limit = 0", + "meta = 0", + "orderby = array_name", + "filters = array_model !vdisk%" + ], + "Value": "#id", + "DisplayModeLabel": "array", + "LabelCss": "hd16", + "Label": "Array", + "Type": "string", + "Id": "array_id" + }, + { + "Function": "/arrays/#array_id/diskgroups", + "Mandatory": true, + "Format": "#dg_name", + "Args": [ + "props = dg_name,id", + "limit = 0", + "meta = 0", + "orderby = dg_name" + ], + "Value": "#id", + "DisplayModeLabel": "diskgroup", + "LabelCss": "hd16", + "Label": "Diskgroup", + "Type": "string", + "Id": "dg_id", + "Condition": "#array_id != 0" + }, + { + "Function": "/apps", + "DisableAutoDefault": true, + "Mandatory": true, + "Format": "#app", + "Args": [ + "props = id,app", + "limit = 0", + "meta = 0", + "orderby = app" + ], + "Value": "#id", + "DisplayModeLabel": "app", + "LabelCss": "svc", + "Label": "App", + "Type": "string", + "Id": "app_id" + }, + { + "Mandatory": true, + "DisplayModeLabel": "quota", + "LabelCss": "hd16", + "Label": "Quota", + "Type": "integer", + "Id": "quota", + "Unit": "mb" + } + ] + } + }, + { + "id": -5, + "form_name": "internal_add_default_thresholds", + "form_folder": "/internal", + "form_type": "generic", + "form_definition": { + "Vertical": true, + "Outputs": [ + { + "Type": "json", + "Format": "dict", + "Dest": "rest", + "Function": "/checks/defaults", + "Handler": "POST" + } + ], + "Inputs": [ + { + "Id": "chk_type", + "Label": "Type", + "LabelCss": "check16", + "Type": "string", + "Mandatory": true, + "Function": "/checks/live", + "Args": [ + "props = chk_type", + "groupby = chk_type", + "orderby = chk_type", + "meta = 0", + "limit = 0" + ], + "DisableAutoDefault": true + }, + { + "Id": "chk_inst", + "Label": "Instance regex", + "LabelCss": "check16", + "Type": "string", + "Mandatory": true + }, + { + "Id": "chk_prio", + "Label": "Priority", + "LabelCss": "fa-sort", + "Type": "integer", + "Constraint": "match [0-9]*" + }, + { + "Id": "chk_low", + "Label": "Low threshold", + "LabelCss": "fa-step-backward", + "Type": "integer", + "Constraint": "match [0-9]*" + }, + { + "Id": "chk_high", + "Label": "High threshold", + "LabelCss": "fa-step-forward", + "Type": "integer", + "Constraint": "match [0-9]*" + } + ] + } + }, + { + "id": -6, + "form_name": "internal_add_user", + "form_folder": "/internal", + "form_type": "generic", + "form_definition": { + "Vertical": true, + "Outputs": [ + { + "Type": "json", + "Format": "dict", + "Dest": "rest", + "LogRequestData": false, + "Function": "/users", + "Handler": "POST" + } + ], + "Inputs": [ + { + "Id": "email", + "Label": "Email", + "LabelCss": "fa-mail", + "Type": "string", + "Mandatory": true, + "Constraint": "match ^([\\w\\!\\#$\\%\\&'\\*\\+\\-\\/\\=\\?\\^\\`{\\|\\}\\~]+\\.)*[\\w\\!\\#$\\%\\&'\\*\\+\\-\\/\\=\\?\\^\\`{\\|\\}\\~]+@((((([a-z0-9]{1}[a-z0-9\\-]{0,62}[a-z0-9]{1})|[a-z])\\.)+[a-z]{2,6})|(\\d{1,3}\\.){3}\\d{1,3}(\\:\\d{1,5})?)$" + }, + { + "Id": "username", + "Label": "Username", + "LabelCss": "guy16", + "Type": "string", + "Mandatory": false, + "Help": "Needed for LDAP login" + }, + { + "Id": "first_name", + "Label": "First Name", + "LabelCss": "guy16", + "Type": "string", + "Mandatory": true + }, + { + "Id": "last_name", + "Label": "Last Name", + "LabelCss": "guy16", + "Type": "string", + "Mandatory": true + }, + { + "Id": "password", + "Label": "Password", + "LabelCss": "key", + "Type": "password", + "Mandatory": true, + "Constraint": "match ^......*" + } + ] + } + }, + { + "id": -7, + "form_name": "internal_notification_period", + "form_folder": "/internal", + "form_type": "generic", + "form_definition": { + "Vertical": false, + "Outputs": [ + { + "Type": "json", + "Format": "dict" + } + ], + "Inputs": [ + { + "Id": "period", + "Label": "Period", + "LabelCss": "fa-bell", + "Candidates": [ + { + "Value": "always", + "Label": "Always" + }, + { + "Value": "never", + "Label": "Never" + }, + { + "Value": "custom", + "Label": "Custom" + } + ], + "Default": "always" + }, + { + "Id": "begin", + "Label": "Begin", + "LabelCss": "fa-clock", + "Type": "time", + "Default": "08:00", + "Condition": "#period == custom" + }, + { + "Id": "end", + "Label": "End", + "LabelCss": "fa-clock", + "Type": "time", + "Default": "18:00", + "Condition": "#period == custom" + } + ] + } + }, + { + "id": -8, + "form_name": "internal_notification_periods", + "form_folder": "/internal", + "form_type": "generic", + "form_definition": { + "Vertical": false, + "Outputs": [ + { + "Type": "json", + "Format": "dict" + } + ], + "Inputs": [ + { + "Id": "mon", + "Label": "Monday", + "LabelCss": "fa-calendar", + "Type": "form", + "Form": "internal_notification_period" + }, + { + "Id": "tue", + "Label": "Tuesday", + "LabelCss": "fa-calendar", + "Type": "form", + "Form": "internal_notification_period" + }, + { + "Id": "wed", + "Label": "Wednesday", + "LabelCss": "fa-calendar", + "Type": "form", + "Form": "internal_notification_period" + }, + { + "Id": "thu", + "Label": "Thursday", + "LabelCss": "fa-calendar", + "Type": "form", + "Form": "internal_notification_period" + }, + { + "Id": "fri", + "Label": "Friday", + "LabelCss": "fa-calendar", + "Type": "form", + "Form": "internal_notification_period" + }, + { + "Id": "sat", + "Label": "Saturday", + "LabelCss": "fa-calendar", + "Type": "form", + "Form": "internal_notification_period" + }, + { + "Id": "sun", + "Label": "Sunday", + "LabelCss": "fa-calendar", + "Type": "form", + "Form": "internal_notification_period" + } + ] + } + }, + { + "id": -9, + "form_name": "generic_list", + "form_folder": "/internal", + "form_type": "generic", + "form_definition": { + "Outputs": [ + { + "Type": "json", + "Format": "list" + } + ], + "Inputs": [ + { + "Id": "entry", + "Label": "", + "LabelCss": "fa-chevron-circle-right" + } + ] + } + }, + { + "id": -10, + "form_name": "generic_check", + "form_folder": "/internal", + "form_type": "generic", + "form_definition": { + "Outputs": [ + { + "Type": "json", + "Format": "dict" + } + ], + "Inputs": [ + { + "Help": "The base severity the alerts are created with. The collector gives a +1 severity bonus for production nodes and services. The checker can also give bonus.", + "LabelCss": "fa-exclamation-triangle", + "Default": 1, + "Label": "Base severity", + "Type": "integer", + "Candidates": [ + { + "Value": 0, + "Label": "Notice" + }, + { + "Value": 1, + "Label": "Warning" + }, + { + "Value": 2, + "Label": "Error" + }, + { + "Value": 3, + "Label": "Critical" + } + ], + "Id": "base_severity", + "DisplayModeLabel": "base severity" + }, + { + "Help": "The polling interval in seconds", + "LabelCss": "fa-clock", + "Default": 30, + "Label": "Interval", + "Type": "integer", + "Id": "interval", + "DisplayModeLabel": "interval" + }, + { + "Help": "The name of each pollers that should handle this check", + "Form": "generic_list", + "Label": "Pollers", + "LabelCss": "fa-rss", + "DisplayModeLabel": "pollers", + "Type": "form", + "Id": "pollers" + } + ] + } + } +] \ No newline at end of file diff --git a/server/handlers/forms_outputs.go b/server/handlers/forms_outputs.go new file mode 100644 index 00000000..5d6447b8 --- /dev/null +++ b/server/handlers/forms_outputs.go @@ -0,0 +1,663 @@ +package serverhandlers + +import ( + "bufio" + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "html" + "io" + "net/http" + "net/smtp" + "os" + "os/exec" + "strings" + "sync" + "time" + + "github.com/spf13/viper" + + "github.com/opensvc/oc3/cdb" +) + +// formattedData returns the data an output works on: the submitted data, or +// its JSON string form for a json-typed output, as get_form_formatted_data(). +func (s *formSubmission) formattedData(output map[string]any) (any, error) { + if s.data == nil { + return nil, errors.New("no form data") + } + if defString(output, "Type") == "json" { + b, err := json.Marshal(s.data) + if err != nil { + return nil, err + } + return string(b), nil + } + return s.data, nil +} + +// outputDB inserts the data in a table of the collector database, keeping only +// the keys that are columns of the table, as output_db() does. +func (s *formSubmission) outputDB(ctx context.Context, output map[string]any) error { + outputID := defString(output, "Id") + data, ok := s.data.(map[string]any) + if !ok { + return errors.New("a db output expects the form data as an object") + } + table := defString(output, "Table") + if table == "" { + s.formLog(ctx, outputID, 1, "form.submit", "Table must be set in db type Output", nil) + return nil + } + cols, err := s.a.ODB.TableColumns(ctx, table) + if err != nil { + return err + } + if len(cols) == 0 { + s.formLog(ctx, outputID, 1, "form.submit", "Table %(t)s not found", map[string]any{"t": table}) + return nil + } + row := map[string]any{} + for _, col := range cols { + if v, ok := data[col]; ok { + if m, isMap := v.(map[string]any); isMap { + b, _ := json.Marshal(m) + v = string(b) + } else if l, isList := v.([]any); isList { + b, _ := json.Marshal(l) + v = string(b) + } else if n, isNumber := v.(json.Number); isNumber { + v = n.String() + } + row[col] = v + } + } + if err := s.a.ODB.InsertRow(ctx, table, row); err != nil { + s.formLog(ctx, outputID, 1, "form.submit", "Data insertion in database table error: %(err)s", map[string]any{"err": err.Error()}) + return nil + } + s.formLog(ctx, outputID, 0, "form.submit", "Data inserted in database table", nil) + return nil +} + +// outputScript runs a script of the collector host, as output_script() does: +// the data, the output id and the results structure are its arguments, each +// line it writes is logged as it comes, stdout as info and stderr as error, and +// its exit code adds to the return code. +func (s *formSubmission) outputScript(ctx context.Context, output map[string]any) error { + path := defString(output, "Path") + outputID := defString(output, "Id") + if outputID == "" { + outputID = path + } + if path == "" { + s.formLog(ctx, outputID, 1, "form.submit", "Path must be set in script type Output", nil) + s.addReturnCode(1) + return nil + } + if _, err := os.Stat(path); err != nil { + s.formLog(ctx, outputID, 1, "form.submit", "Script %(path)s does not exists", map[string]any{"path": path}) + s.addReturnCode(1) + return nil + } + data, err := s.formattedData(output) + if err != nil { + return err + } + arg, ok := data.(string) + if !ok { + b, _ := json.Marshal(data) + arg = string(b) + } + s.mu.Lock() + resultsJSON, _ := json.Marshal(s.results) + s.mu.Unlock() + + cmd := exec.CommandContext(ctx, path, arg, outputID, string(resultsJSON)) + stdout, err := cmd.StdoutPipe() + if err != nil { + return err + } + stderr, err := cmd.StderrPipe() + if err != nil { + return err + } + if err := cmd.Start(); err != nil { + s.formLog(ctx, outputID, 1, "form.submit", "Script %(path)s execution error: %(err)s", map[string]any{"path": path, "err": err.Error()}) + s.addReturnCode(1) + return nil + } + var wg sync.WaitGroup + stream := func(r io.Reader, ret int) { + defer wg.Done() + reader := bufio.NewReader(r) + for { + line, err := reader.ReadString('\n') + if line != "" { + s.formLog(ctx, outputID, ret, "form.submit", line, nil) + s.save(ctx, true) + } + if err != nil { + return + } + } + } + wg.Add(2) + go stream(stdout, 0) + go stream(stderr, 1) + wg.Wait() + code := 0 + if err := cmd.Wait(); err != nil { + var exitErr *exec.ExitError + if !errors.As(err, &exitErr) { + s.formLog(ctx, outputID, 1, "form.submit", "Script %(path)s execution error: %(err)s", map[string]any{"path": path, "err": err.Error()}) + s.addReturnCode(1) + return nil + } + code = exitErr.ExitCode() + } + s.addReturnCode(code) + if code != 0 { + s.formLog(ctx, outputID, 1, "form.submit", "Script returned error code %(ret)s", map[string]any{"ret": fmt.Sprint(code)}) + } + s.save(ctx, false) + return nil +} + +// mangle runs the mangler of a rest output, a javascript function of the form +// definition, in the vm2 sandbox of nodejs, as the historical collector does: +// its printed JSON result replaces the data sent. +func (s *formSubmission) mangle(ctx context.Context, mangler string) (any, error) { + s.mu.Lock() + outputs, _ := json.Marshal(s.results["outputs"]) + s.mu.Unlock() + data, err := json.Marshal(s.data) + if err != nil { + return nil, err + } + script := fmt.Sprintf("var mangle = %s; var out = mangle(%s, %s, %d); console.log(JSON.stringify(out));", + mangler, data, outputs, s.resultsID) + f, err := os.CreateTemp("", "oc3-form-mangle-*.js") + if err != nil { + return nil, err + } + defer func() { _ = os.Remove(f.Name()) }() + if _, err := f.WriteString(script); err != nil { + _ = f.Close() + return nil, err + } + _ = f.Close() + nodejs := viper.GetString("server.forms.nodejs") + vm2 := viper.GetString("server.forms.vm2") + var stdout, stderr bytes.Buffer + cmd := exec.CommandContext(ctx, nodejs, vm2, f.Name()) + cmd.Stdout = &stdout + cmd.Stderr = &stderr + _ = cmd.Run() + var lines []string + for _, line := range strings.Split(stdout.String(), "\n") { + if line != "" && !strings.Contains(line, "[vm] ") { + lines = append(lines, line) + } + } + if len(lines) == 0 { + return nil, fmt.Errorf("mangling produced no data:\nmangler: %s\noutput: %s\nerror: %s", script, stdout.String(), stderr.String()) + } + var out any + decoder := json.NewDecoder(strings.NewReader(strings.Join(lines, "\n"))) + decoder.UseNumber() + if err := decoder.Decode(&out); err != nil { + return nil, err + } + return out, nil +} + +// outputRest calls the collector API as the submitter, or an external url, as +// output_rest() does: "#key" references of the url replaced, the data mangled +// or trimmed to Keys, and the answer's info, error and data kept in the +// results. +func (s *formSubmission) outputRest(ctx context.Context, output map[string]any) error { + action := defString(output, "Handler") + url := defString(output, "Function") + outputID := defString(output, "Id") + wait := 0 + if n, ok := output["WaitResult"].(json.Number); ok { + if i, err := n.Int64(); err == nil { + wait = int(i) + } + } else if f, ok := output["WaitResult"].(float64); ok { + wait = int(f) + } + + s.formLog(ctx, outputID, 0, "form.submit", "rest %(action)s %(url)s", map[string]any{"action": action, "url": url}) + s.save(ctx, false) + + if url == "" { + return errors.New("Function must be defined in a rest output") + } + switch action { + case http.MethodGet, http.MethodPost, http.MethodDelete, http.MethodPut: + default: + return errors.New("Handler must be set to either GET, POST, DELETE or PUT in a rest output") + } + args, err := formRestArgs(url, s.data) + if err != nil { + return fmt.Errorf("%s", err) + } + if len(args) == 0 { + return errors.New("Function must be defined in a rest output") + } + + vars := s.data + if mangler := defString(output, "Mangle"); mangler != "" { + if vars, err = s.mangle(ctx, mangler); err != nil { + return err + } + } + if _, isString := vars.(string); isString { + return errors.New("The mangler must not return a str") + } + if keys := defList(output, "Keys"); len(keys) > 0 { + if m, ok := vars.(map[string]any); ok { + retained := map[string]any{} + for _, k := range keys { + if ks, ok := k.(string); ok { + if v, found := m[ks]; found { + retained[ks] = v + } + } + } + vars = retained + } + } + logRequest := true + if v, ok := output["LogRequestData"].(bool); ok { + logRequest = v + } + if logRequest { + s.mu.Lock() + ensureMap(s.results, "request_data")[outputID] = vars + s.mu.Unlock() + } + s.save(ctx, false) + + external := strings.HasPrefix(args[0], "http") + call := func() (*apiResponse, error) { + if external { + full := args[0] + "//" + strings.Join(args[1:], "/") + return s.callAPI(ctx, action, "", vars, full) + } + return s.callAPI(ctx, action, "/"+strings.Join(args, "/"), vars, "") + } + + var resp *apiResponse + if action == http.MethodGet && wait > 0 { + for ; wait > 0; wait-- { + if resp, err = call(); err != nil { + break + } + if m, ok := resp.body.(map[string]any); ok { + if list, ok := m["data"].([]any); ok && len(list) > 0 { + break + } + } + resp = nil + time.Sleep(time.Second) + } + if err == nil && resp == nil { + err = errors.New("Timed out waiting for a result") + } + } else { + resp, err = call() + } + if err == nil && !external && resp.status >= 300 { + err = errors.New(problemTextOf(resp)) + } + if err != nil { + s.formLog(ctx, outputID, 1, "form.submit", "error:\n%(result)s", map[string]any{"result": err.Error()}) + s.addReturnCode(1) + return nil + } + + // The call may have changed the results, through PUT /form_output_results. + s.reload(ctx) + s.restPostRun(output, outputID, resp.body) + return nil +} + +// restPostRun keeps the answer of a rest call in the results, as post_run() +// does: info lines logged, error lines logged with the return code raised, and +// data added to the output. +func (s *formSubmission) restPostRun(output map[string]any, outputID string, body any) { + jd, ok := body.(map[string]any) + if !ok { + return + } + switch info := jd["info"].(type) { + case []any: + for _, line := range info { + s.appendLog(outputID, 0, formValueText(line), nil) + } + case string: + if info != "" { + s.appendLog(outputID, 0, info, nil) + } + } + if errValue, ok := jd["error"]; ok && !isFalsy(errValue) { + s.addReturnCode(1) + switch e := errValue.(type) { + case []any: + for _, line := range e { + s.appendLog(outputID, 1, formValueText(line), nil) + } + case map[string]any: + for k, v := range e { + s.appendLog(outputID, 1, k+": "+formValueText(v), nil) + } + default: + s.appendLog(outputID, 1, formValueText(e), nil) + } + } + data, ok := jd["data"] + if !ok { + return + } + s.mu.Lock() + outputs := ensureMap(s.results, "outputs") + switch current := outputs[outputID].(type) { + case nil: + outputs[outputID] = data + case []any: + outputs[outputID] = append(current, data) + default: + outputs[outputID] = []any{current, data} + } + s.mu.Unlock() + + waited := false + switch w := output["WaitResult"].(type) { + case json.Number: + n, _ := w.Int64() + waited = n > 0 + case float64: + waited = w > 0 + } + if !waited { + return + } + entries, isList := data.([]any) + if !isList { + entries = []any{data} + } + for _, entry := range entries { + m, ok := entry.(map[string]any) + if !ok { + continue + } + if ret, ok := m["ret"]; ok && formValueText(ret) != "0" { + s.addReturnCode(1) + } + if stderr, ok := m["stderr"].(string); ok && stderr != "" { + s.appendLog(outputID, 1, stderr, nil) + } + } +} + +// outputMail mails the submitted data, as output_mail() does: to the output +// recipients, or to the given ones, a recipient given by name resolved to the +// user's email. The SMTP server is set by server.mail.server. +func (s *formSubmission) outputMail(ctx context.Context, output map[string]any, to []string, recordID int64) error { + outputID := defString(output, "Id") + if to == nil { + switch t := output["To"].(type) { + case string: + to = []string{t} + case []any: + for _, item := range t { + if str, ok := item.(string); ok { + to = append(to, str) + } + } + } + } + var recipients []string + for _, t := range to { + if strings.Contains(t, "@") { + recipients = append(recipients, t) + continue + } + email, found, err := s.a.ODB.UserEmailByName(ctx, t) + if err != nil { + return err + } + if found && email != "" { + recipients = append(recipients, email) + } + } + if len(recipients) == 0 { + s.formLog(ctx, outputID, 1, "form.submit", "No mail destination", nil) + return nil + } + if s.data == nil { + s.formLog(ctx, outputID, 1, "form.submit", "no form data", nil) + return nil + } + title := defString(s.definition, "Label") + if title == "" { + title = s.formName + } + dump, _ := json.MarshalIndent(s.data, "", " ") + next := "" + if recordID != 0 { + next = fmt.Sprintf("

Workflow step %d

", recordID) + } + body := fmt.Sprintf("

Form submitted on %s by %s

%s
%s", + time.Now().Format("2006-01-02 15:04"), html.EscapeString(s.caller.name), html.EscapeString(string(dump)), next) + if err := sendFormMail(recipients, title, body); err != nil { + s.formLog(ctx, outputID, 1, "form.submit", "Mail sending error: %(err)s", map[string]any{"err": err.Error()}) + return nil + } + s.formLog(ctx, outputID, 0, "form.submit", "Mail sent to %(to)s on form %(form_name)s submission.", + map[string]any{"to": strings.Join(recipients, ", "), "form_name": s.formName}) + return nil +} + +// sendFormMail sends an html mail through the configured SMTP server: +// server.mail.server (host:port), server.mail.sender and, optionally, +// server.mail.login as "user:password". +func sendFormMail(to []string, subject, body string) error { + server := viper.GetString("server.mail.server") + sender := viper.GetString("server.mail.sender") + if server == "" || sender == "" { + return errors.New("mail is not configured (server.mail.server, server.mail.sender)") + } + var auth smtp.Auth + if login := viper.GetString("server.mail.login"); login != "" { + user, password, _ := strings.Cut(login, ":") + host, _, _ := strings.Cut(server, ":") + auth = smtp.PlainAuth("", user, password, host) + } + msg := "From: " + sender + "\r\n" + + "To: " + strings.Join(to, ", ") + "\r\n" + + "Subject: " + strings.ReplaceAll(subject, "\n", " ") + "\r\n" + + "MIME-Version: 1.0\r\n" + + "Content-Type: text/html; charset=utf-8\r\n\r\n" + body + return smtp.SendMail(server, auth, sender, to, []byte(msg)) +} + +// outputWorkflow stores the submitted form as a workflow step, as +// output_workflow() does: a new workflow, or the next step of the workflow the +// submission continues (prev_wfid). The workflow stays pending while next forms +// are defined, and the assignee may be mailed. +func (s *formSubmission) outputWorkflow(ctx context.Context, output map[string]any) error { + outputID := defString(output, "Id") + if s.form == nil { + return errors.New("an internal form cannot store a workflow step") + } + data, err := s.formattedData(output) + if err != nil { + return err + } + formData, ok := data.(string) + if !ok { + b, _ := json.Marshal(data) + formData = string(b) + } + formMD5, err := s.a.ODB.InsertFormRevisionMD5(ctx, s.form) + if err != nil { + return err + } + + stepDefs := output + if scripts, ok := output["Scripts"].(map[string]any); ok { + key := "Success" + if s.returnCode() != 0 { + key = "Error" + } + stepDefs, _ = scripts[key].(map[string]any) + } + var nextForms []any + assignee := "" + if stepDefs != nil { + nextForms = defList(stepDefs, "NextForms") + assignee = defString(stepDefs, "NextAssignee") + } + var nextID *int64 + status := "pending" + if len(nextForms) == 0 { + zero := int64(0) + nextID = &zero + status = "closed" + } + + now := time.Now().Format(time.DateTime) + primaryGroup := "" + if s.caller.id > 0 { + if role, found, err := s.a.ODB.UserPrimaryOrgGroupRole(ctx, s.caller.id); err != nil { + return err + } else if found { + primaryGroup = role + } + } + + var recordID, workflowID int64 + if s.prevWfid != nil { + prev, err := s.a.ODB.StoredFormLinkByID(ctx, *s.prevWfid) + if err != nil { + return err + } + if prev == nil { + return fmt.Errorf("workflow step %d not found", *s.prevWfid) + } + if prev.NextID != nil { + s.formLog(ctx, outputID, 0, "form.store", "This step is already completed (id=%(id)d)", map[string]any{"id": prev.ID}) + return nil + } + if assignee == "" { + assignee = primaryGroup + } + if assignee == "" { + assignee = prev.Submitter + } + if assignee == "" { + assignee = s.caller.name + } + + // Walk back to the head of the workflow. + headID := *s.prevWfid + var head *cdb.StoredFormLink + iter := 0 + for iter < 100 { + iter++ + row, err := s.a.ODB.StoredFormLinkByID(ctx, headID) + if err != nil { + return err + } + if row == nil { + break + } + if row.PrevID == nil { + head = row + break + } + headID = *row.PrevID + } + + if recordID, err = s.a.ODB.InsertStoredForm(ctx, cdb.StoredFormInsert{ + MD5: formMD5, Submitter: s.caller.name, Assignee: assignee, Date: now, + PrevID: s.prevWfid, NextID: nextID, HeadID: &headID, Data: formData, ResultsID: s.resultsID, + }); err != nil { + return err + } + if err := s.a.ODB.SetStoredFormNext(ctx, *s.prevWfid, recordID); err != nil { + return err + } + if nextID == nil { + s.formLog(ctx, outputID, 0, "form.store", "Workflow %(head_id)d step %(form_name)s added with id %(id)d", + map[string]any{"form_name": s.formName, "head_id": headID, "id": recordID}) + } else { + s.formLog(ctx, outputID, 0, "form.store", "Workflow %(head_id)d closed on last step %(form_name)s with id %(id)d", + map[string]any{"form_name": s.formName, "head_id": headID, "id": recordID}) + } + w := cdb.WorkflowInsert{ + Status: status, MD5: formMD5, Steps: iter + 1, LastAssignee: assignee, LastUpdate: now, + LastFormID: recordID, LastFormName: s.formName, HeadID: headID, + } + id, found, err := s.a.ODB.WorkflowIDByHead(ctx, headID) + if err != nil { + return err + } + if found { + workflowID = id + if err := s.a.ODB.UpdateWorkflowStep(ctx, headID, w); err != nil { + return err + } + } else { + // Should not happen: the workflow is recreated from its head. + w.Creator, w.CreateDate = s.caller.name, now + if head != nil { + w.Creator, w.CreateDate = head.Submitter, head.SubmitDate + } + if workflowID, err = s.a.ODB.InsertWorkflow(ctx, w); err != nil { + return err + } + } + } else { + if assignee == "" { + assignee = primaryGroup + } + if assignee == "" { + assignee = s.caller.name + } + if recordID, err = s.a.ODB.InsertStoredForm(ctx, cdb.StoredFormInsert{ + MD5: formMD5, Submitter: s.caller.name, Assignee: assignee, Date: now, + Data: formData, ResultsID: s.resultsID, + }); err != nil { + return err + } + if err := s.a.ODB.SetStoredFormHead(ctx, recordID); err != nil { + return err + } + s.formLog(ctx, outputID, 0, "form.store", "New workflow %(form_name)s created with id %(id)d", + map[string]any{"form_name": s.formName, "id": recordID}) + if workflowID, err = s.a.ODB.InsertWorkflow(ctx, cdb.WorkflowInsert{ + Status: status, MD5: formMD5, Steps: 1, LastAssignee: assignee, LastUpdate: now, + LastFormID: recordID, LastFormName: s.formName, HeadID: recordID, + Creator: s.caller.name, CreateDate: now, + }); err != nil { + return err + } + } + + s.mu.Lock() + ensureMap(s.results, "outputs")[outputID] = map[string]any{"workflow_id": workflowID, "head_form_id": recordID} + s.mu.Unlock() + s.save(ctx, false) + + if nextID == nil && defBool(output, "Mail") { + return s.outputMail(ctx, output, []string{assignee}, recordID) + } + return nil +} diff --git a/server/handlers/forms_store.go b/server/handlers/forms_store.go new file mode 100644 index 00000000..7e68f3a6 --- /dev/null +++ b/server/handlers/forms_store.go @@ -0,0 +1,297 @@ +package serverhandlers + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "log/slog" + "net/http" + "strconv" + + "github.com/labstack/echo/v4" + + "github.com/opensvc/oc3/cdb" + "github.com/opensvc/oc3/server" + "github.com/opensvc/oc3/util/echolog" +) + +// GetFormsRevisions handles GET /forms_revisions. +func (a *Api) GetFormsRevisions(c echo.Context, params server.GetFormsRevisionsParams) error { + return a.handleList(c, "GetFormsRevisions", "form_revision", listEndpointParams{ + props: params.Props, limit: params.Limit, offset: params.Offset, + meta: params.Meta, stats: params.Stats, orderby: params.Orderby, groupby: params.Groupby, + filter: params.Filter, virtual: formDefinitionProp, + }, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetFormsRevisions(ctx, nil, p) + }) +} + +// GetFormsRevision handles GET /forms_revisions/{revision_id}: by id or md5. +func (a *Api) GetFormsRevision(c echo.Context, revisionId string, params server.GetFormsRevisionParams) error { + return a.handleList(c, "GetFormsRevision", "form_revision", listEndpointParams{ + props: params.Props, limit: params.Limit, offset: params.Offset, + meta: params.Meta, stats: params.Stats, orderby: params.Orderby, groupby: params.Groupby, + filter: params.Filter, virtual: formDefinitionProp, + }, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetFormsRevisions(ctx, &revisionId, p) + }) +} + +// GetFormsStore handles GET /forms_store. +func (a *Api) GetFormsStore(c echo.Context, params server.GetFormsStoreParams) error { + return a.handleList(c, "GetFormsStore", "form_store", listEndpointParams{ + props: params.Props, limit: params.Limit, offset: params.Offset, + meta: params.Meta, stats: params.Stats, orderby: params.Orderby, groupby: params.Groupby, + filter: params.Filter, virtual: formDefinitionProp, + }, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetFormsStore(ctx, nil, p) + }) +} + +// GetFormStore handles GET /forms_store/{store_id}. +func (a *Api) GetFormStore(c echo.Context, storeId int, params server.GetFormStoreParams) error { + id := int64(storeId) + return a.handleList(c, "GetFormStore", "form_store", listEndpointParams{ + props: params.Props, limit: params.Limit, offset: params.Offset, + meta: params.Meta, stats: params.Stats, orderby: params.Orderby, groupby: params.Groupby, + filter: params.Filter, virtual: formDefinitionProp, + }, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetFormsStore(ctx, &id, p) + }) +} + +// defaultRows reads rows with the default props of a mapping, virtual props +// computed, for the handlers answering with records they assemble. +func (a *Api) defaultRows(ctx context.Context, mappingKey string, virtual map[string]virtualProp, fetch listFetcher) ([]map[string]any, error) { + mapping := propsMapping[mappingKey] + query, err := buildListQueryParameters(nil, nil, nil, nil, nil, nil, nil, mapping) + if err != nil { + return nil, err + } + fetchProps := fetchPropsFor(query.Props, virtual) + selectExprs, err := buildSelectClause(fetchProps, mapping) + if err != nil { + return nil, err + } + items, err := fetch(ctx, cdb.ListParams{ + IsManager: true, Props: fetchProps, SelectExprs: selectExprs, + TypeHints: buildTypeHints(fetchProps, mapping), + }) + if err != nil { + return nil, err + } + computeVirtualProps(items, query.Props, virtual) + return items, nil +} + +func (a *Api) storedForm(ctx context.Context, id int64) (map[string]any, error) { + rows, err := a.defaultRows(ctx, "form_store", formDefinitionProp, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetFormsStore(ctx, &id, p) + }) + if err != nil || len(rows) == 0 { + return nil, err + } + return rows[0], nil +} + +// asInt64 reads an id column of a row. +func asInt64(v any) (int64, bool) { + switch t := v.(type) { + case int64: + return t, true + case int: + return int64(t), true + case string: + n, err := strconv.ParseInt(t, 10, 64) + return n, err == nil + case []byte: + n, err := strconv.ParseInt(string(t), 10, 64) + return n, err == nil + } + return 0, false +} + +// workflowDump returns a workflow with its head and tail stored forms, as +// /workflows/{id}/dump does in the historical collector. +func (a *Api) workflowDump(ctx context.Context, workflowID int64) (map[string]any, error) { + rows, err := a.defaultRows(ctx, "workflow", nil, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetWorkflows(ctx, &workflowID, p) + }) + if err != nil || len(rows) == 0 { + return nil, err + } + wf := rows[0] + if headID, ok := asInt64(wf["form_head_id"]); ok { + if wf["head"], err = a.storedForm(ctx, headID); err != nil { + return nil, err + } + } + if lastID, ok := asInt64(wf["last_form_id"]); ok { + if wf["tail"], err = a.storedForm(ctx, lastID); err != nil { + return nil, err + } + } + return wf, nil +} + +// GetFormStoreDump handles GET /forms_store/{store_id}/dump: the stored form +// with its workflow, the workflow carrying its head and tail stored forms. +func (a *Api) GetFormStoreDump(c echo.Context, storeId int) error { + log := echolog.GetLogHandler(c, "GetFormStoreDump") + ctx := c.Request().Context() + stored, err := a.storedForm(ctx, int64(storeId)) + if err != nil { + return formProblem(c, formInternal(log, "cannot read the stored form", err)) + } + if stored == nil { + return JSONProblemf(c, http.StatusNotFound, "stored form %d not found", storeId) + } + if headID, ok := asInt64(stored["form_head_id"]); ok { + workflowID, found, err := a.ODB.WorkflowIDByHead(ctx, headID) + if err != nil { + return formProblem(c, formInternal(log, "cannot read the workflow", err)) + } + if found { + if stored["workflow"], err = a.workflowDump(ctx, workflowID); err != nil { + return formProblem(c, formInternal(log, "cannot read the workflow", err)) + } + } + } + return c.JSON(http.StatusOK, map[string]any{"data": []any{stored}}) +} + +// formResultsAccess describes the caller for the results access filter. +func formResultsAccess(c echo.Context) cdb.FormResultsAccess { + nodeID, _ := c.Get(XNodeID).(string) + return cdb.FormResultsAccess{IsManager: IsManager(c), UserID: authUserID(c), NodeID: nodeID} +} + +// GetFormOutputResults handles GET /form_output_results/{results_id}: the +// results structure as stored. +func (a *Api) GetFormOutputResults(c echo.Context, resultsId int) error { + log := echolog.GetLogHandler(c, "GetFormOutputResults") + results, err := a.readFormResults(c.Request().Context(), c, int64(resultsId)) + if err != nil { + return formProblem(c, formResultsError(log, err)) + } + return c.JSON(http.StatusOK, results) +} + +// formResultsError keeps a refusal as it is and logs an internal failure. +func formResultsError(log *slog.Logger, err error) error { + var fe *formError + if errors.As(err, &fe) { + return err + } + return formInternal(log, "cannot read the results", err) +} + +// readFormResults reads a results structure the caller may see, 404 otherwise. +func (a *Api) readFormResults(ctx context.Context, c echo.Context, id int64) (map[string]any, error) { + s, found, err := a.ODB.FormOutputResults(ctx, id, formResultsAccess(c)) + if err != nil { + return nil, err + } + if !found { + return nil, formErrorf(http.StatusNotFound, "results not found") + } + var results map[string]any + decoder := json.NewDecoder(bytes.NewReader([]byte(s))) + decoder.UseNumber() + if err := decoder.Decode(&results); err != nil { + return nil, formErrorf(http.StatusInternalServerError, "unreadable results: %s", err) + } + return results, nil +} + +// PutFormOutputResults handles PUT /form_output_results/{results_id}: add a +// result and log lines to an output, as scripts run by a form report them. +func (a *Api) PutFormOutputResults(c echo.Context, resultsId int) error { + log := echolog.GetLogHandler(c, "PutFormOutputResults") + ctx, cancel := context.WithTimeout(c.Request().Context(), a.SyncTimeout) + defer cancel() + id := int64(resultsId) + results, err := a.readFormResults(ctx, c, id) + if err != nil { + return formProblem(c, formResultsError(log, err)) + } + entries, isList, err := decodeEntries(c) + if err != nil { + return formProblem(c, err) + } + if isList { + return JSONProblem(c, http.StatusBadRequest, "expecting an object") + } + body := entries[0] + outputID, _ := entryString(body, "output_id") + result, hasResult := body["result"] + logLines, hasLog := body["log"] + if (!hasResult || isEmpty(result)) && (!hasLog || isEmpty(logLines)) { + return c.JSON(http.StatusOK, results) + } + if hasResult && !isEmpty(result) { + outputs := ensureMap(results, "outputs") + list, _ := outputs[outputID].([]any) + outputs[outputID] = append(list, decodedJSON(result)) + } + if hasLog && !isEmpty(logLines) { + logs := ensureMap(results, "log") + list, _ := logs[outputID].([]any) + switch lines := decodedJSON(logLines).(type) { + case []any: + list = append(list, lines...) + default: + list = append(list, lines) + } + logs[outputID] = list + } + b, err := json.Marshal(results) + if err != nil { + return formProblem(c, formInternal(log, "cannot encode the results", err)) + } + if err := a.ODB.UpdateFormOutputResults(ctx, id, string(b)); err != nil { + return formProblem(c, formInternal(log, "cannot store the results", err)) + } + a.formNotify(ctx, log) + return c.JSON(http.StatusOK, results) +} + +func isEmpty(v any) bool { + switch t := v.(type) { + case nil: + return true + case string: + return t == "" + case []any: + return len(t) == 0 + case map[string]any: + return len(t) == 0 + } + return false +} + +// decodedJSON decodes a value posted as its JSON string form, as +// sjson.loads(result) does, and keeps any other value as it is. +func decodedJSON(v any) any { + s, ok := v.(string) + if !ok { + return v + } + var out any + decoder := json.NewDecoder(bytes.NewReader([]byte(s))) + decoder.UseNumber() + if err := decoder.Decode(&out); err != nil { + return s + } + return out +} + +func ensureMap(m map[string]any, key string) map[string]any { + sub, ok := m[key].(map[string]any) + if !ok { + sub = map[string]any{} + m[key] = sub + } + return sub +} diff --git a/server/handlers/forms_submit.go b/server/handlers/forms_submit.go new file mode 100644 index 00000000..d6e2ccde --- /dev/null +++ b/server/handlers/forms_submit.go @@ -0,0 +1,529 @@ +package serverhandlers + +import ( + "bytes" + "context" + _ "embed" + "encoding/json" + "fmt" + "io" + "log/slog" + "net" + "net/http" + "net/url" + "strconv" + "strings" + "sync" + "time" + + "github.com/labstack/echo/v4" + "github.com/spf13/viper" + + "github.com/opensvc/oc3/cdb" + "github.com/opensvc/oc3/util/echolog" + "github.com/opensvc/oc3/util/logkey" +) + +// internalFormsJSON holds the forms the historical collector defines in code +// (lib_forms_internal.py), designated by a negative id. +// +//go:embed forms_internal.json +var internalFormsJSON []byte + +type internalForm struct { + ID int64 `json:"id"` + Name string `json:"form_name"` + Folder string `json:"form_folder"` + Type string `json:"form_type"` + Definition map[string]any `json:"form_definition"` +} + +var ( + internalFormsOnce sync.Once + internalForms map[int64]internalForm +) + +// internalFormByID returns an internal form, as get_internal_form() does. The +// definition is decoded on every call: the submission assigns output ids in it. +func internalFormByID(id int64) (internalForm, bool) { + internalFormsOnce.Do(func() { + var list []internalForm + if err := json.Unmarshal(internalFormsJSON, &list); err != nil { + panic(fmt.Sprintf("forms_internal.json: %s", err)) + } + internalForms = make(map[int64]internalForm, len(list)) + for _, f := range list { + internalForms[f.ID] = f + } + }) + f, ok := internalForms[id] + if !ok { + return f, false + } + b, _ := json.Marshal(f.Definition) + decoder := json.NewDecoder(bytes.NewReader(b)) + decoder.UseNumber() + var definition map[string]any + _ = decoder.Decode(&definition) + f.Definition = definition + return f, true +} + +// formSubmission is one PUT /forms/{form_id}: the form, the submitted data, the +// caller and the results structure, stored in form_output_results and updated +// as the outputs run. Outputs may run after the request has been answered, for +// an Async form: the submission carries all it needs. +type formSubmission struct { + a *Api + log *slog.Logger + formID int64 + formName string + form *cdb.Form // nil for an internal form + definition map[string]any + data any + prevWfid *int64 + caller formCaller + nodeID string + userEmail string + auth string // Authorization header, for the calls of rest outputs + + mu sync.Mutex + results map[string]any + resultsID int64 +} + +// PutForm handles PUT /forms/{form_id}: submit a form. +func (a *Api) PutForm(c echo.Context, formId int) error { + log := echolog.GetLogHandler(c, "PutForm") + ctx := c.Request().Context() + + entries, isList, err := decodeEntries(c) + if err != nil { + return formProblem(c, err) + } + if isList { + return JSONProblem(c, http.StatusBadRequest, "expecting an object with the data and prev_wfid keys") + } + body := entries[0] + + s := &formSubmission{a: a, log: log, formID: int64(formId), auth: c.Request().Header.Get("Authorization")} + s.userEmail, _ = c.Get(XUserEmail).(string) + s.nodeID, _ = c.Get(XNodeID).(string) + if s.caller, err = a.formCaller(ctx, c); err != nil { + return formProblem(c, formInternal(log, "cannot read the caller", err)) + } + + // The data may come as its JSON string form, as a posted form variable. + s.data = body["data"] + if text, ok := s.data.(string); ok { + decoder := json.NewDecoder(strings.NewReader(text)) + decoder.UseNumber() + if err := decoder.Decode(&s.data); err != nil { + return JSONProblemf(c, http.StatusBadRequest, "unparsable form data: %s", text) + } + } + if prev, ok := entryString(body, "prev_wfid"); ok && prev != "" && prev != "None" { + id, err := strconv.ParseInt(prev, 10, 64) + if err != nil { + return JSONProblemf(c, http.StatusBadRequest, "invalid prev_wfid %q", prev) + } + s.prevWfid = &id + } + + if err := s.loadForm(ctx, c); err != nil { + return formProblem(c, err) + } + + s.results = map[string]any{ + "form_id": s.formID, + "submitted_data": s.data, + "outputs_order": []any{}, + "request_data": map[string]any{}, + "outputs": map[string]any{}, + "log": map[string]any{}, + "returncode": 0, + "status": "QUEUED", + } + + if done, err := s.workflowStepDone(ctx); err != nil { + return formProblem(c, formInternal(log, "cannot read the workflow step", err)) + } else if done { + s.appendLog("", 1, "This step is already completed (id=%(id)d)", map[string]any{"id": *s.prevWfid}) + return c.JSON(http.StatusOK, s.results) + } + + if err := s.validate(ctx); err != nil { + return formProblem(c, err) + } + + var userID *int64 + if s.caller.id > 0 { + userID = &s.caller.id + } + b, err := json.Marshal(s.results) + if err != nil { + return formProblem(c, formInternal(log, "cannot encode the results", err)) + } + if s.resultsID, err = a.ODB.InsertFormOutputResults(ctx, userID, s.nodeID, "", string(b)); err != nil { + return formProblem(c, formInternal(log, "cannot store the results", err)) + } + s.results["results_id"] = s.resultsID + log.Info("form submitted", "form_id", s.formID, "results_id", s.resultsID) + + if defBool(s.definition, "Async") { + // Answered at once; the outputs run on the server, the results record + // telling their progress, as the historical collector queued them. + response := s.snapshot() + go s.run(context.WithoutCancel(ctx)) + return c.JSON(http.StatusOK, response) + } + s.run(ctx) + return c.JSON(http.StatusOK, s.snapshot()) +} + +// loadForm finds the form: an internal one for a negative id, else a form of +// the database the caller may use: published to one of their groups, unless a +// manager. +func (s *formSubmission) loadForm(ctx context.Context, c echo.Context) error { + notFound := formErrorf(http.StatusNotFound, "the requested form does not exist or you don't have permission to use it") + if s.formID < 0 { + f, ok := internalFormByID(s.formID) + if !ok { + return notFound + } + s.formName = f.Name + s.definition = f.Definition + return nil + } + visible, err := s.a.ODB.FormVisible(ctx, s.formID, UserGroupsFromContext(c), IsManager(c)) + if err != nil { + return formInternal(s.log, "cannot check form publication", err) + } + if !visible { + return notFound + } + if s.form, err = s.a.ODB.FormByID(ctx, s.formID); err != nil { + return formInternal(s.log, "cannot read the form", err) + } + if s.form == nil { + return notFound + } + s.formName = s.form.Name + definition, err := parseFormYaml(s.form.Yaml) + if err != nil { + return formErrorf(http.StatusBadRequest, "invalid form definition: %s", err) + } + s.definition, _ = definition.(map[string]any) + if s.definition == nil { + s.definition = map[string]any{} + } + return nil +} + +// workflowStepDone tells whether the submission continues a workflow step that +// already has a next step, as workflow_continuation() does. +func (s *formSubmission) workflowStepDone(ctx context.Context) (bool, error) { + if s.formID < 0 || s.prevWfid == nil { + return false, nil + } + for _, output := range defMaps(s.definition, "Outputs") { + if defString(output, "Dest") != "workflow" { + continue + } + prev, err := s.a.ODB.StoredFormLinkByID(ctx, *s.prevWfid) + if err != nil { + return false, err + } + if prev != nil && prev.NextID != nil { + return true, nil + } + } + return false, nil +} + +// snapshot returns a copy of the results structure, safe to encode while the +// outputs keep running. +func (s *formSubmission) snapshot() map[string]any { + s.mu.Lock() + defer s.mu.Unlock() + b, _ := json.Marshal(s.results) + var out map[string]any + decoder := json.NewDecoder(bytes.NewReader(b)) + decoder.UseNumber() + _ = decoder.Decode(&out) + return out +} + +// appendLog adds a line to the log of an output, without writing the collector +// log: for the lines of rest answers, as the historical collector appends them +// directly. +func (s *formSubmission) appendLog(outputID string, ret int, format string, d map[string]any) { + s.mu.Lock() + defer s.mu.Unlock() + logs := ensureMap(s.results, "log") + list, _ := logs[outputID].([]any) + if d == nil { + d = map[string]any{} + } + logs[outputID] = append(list, []any{ret, format, d}) +} + +// formLog adds a line to the log of an output and to the collector log, as +// form_log() does. +func (s *formSubmission) formLog(ctx context.Context, outputID string, ret int, action, format string, d map[string]any) { + s.appendLog(outputID, ret, format, d) + level := "info" + if ret != 0 { + level = "error" + } + if d == nil { + d = map[string]any{} + } + if err := s.a.ODB.Log(ctx, cdb.LogEntry{Action: action, User: s.userEmail, Fmt: format, Dict: d, Level: level}); err != nil { + s.log.Error("cannot write audit log", logkey.Error, err) + } +} + +// addReturnCode adds to the return code of the submission. +func (s *formSubmission) addReturnCode(n int) { + s.mu.Lock() + defer s.mu.Unlock() + s.results["returncode"] = s.returnCodeLocked() + n +} + +func (s *formSubmission) returnCode() int { + s.mu.Lock() + defer s.mu.Unlock() + return s.returnCodeLocked() +} + +func (s *formSubmission) returnCodeLocked() int { + switch t := s.results["returncode"].(type) { + case int: + return t + case json.Number: + n, _ := t.Int64() + return int(n) + case float64: + return int(t) + } + return 0 +} + +func (s *formSubmission) setStatus(status string) { + s.mu.Lock() + defer s.mu.Unlock() + s.results["status"] = status +} + +// save stores the results structure, as update_results() does. mergeOutputs +// first takes in the outputs other clients stored meanwhile, through +// PUT /form_output_results, as reload_outputs=True does. +func (s *formSubmission) save(ctx context.Context, mergeOutputs bool) { + if mergeOutputs { + if current, err := s.stored(ctx); err == nil { + s.mu.Lock() + outputs := ensureMap(s.results, "outputs") + if stored, ok := current["outputs"].(map[string]any); ok { + for k, v := range stored { + outputs[k] = v + } + } + s.mu.Unlock() + } + } + s.mu.Lock() + b, err := json.Marshal(s.results) + s.mu.Unlock() + if err != nil { + s.log.Error("cannot encode the results", logkey.Error, err) + return + } + if err := s.a.ODB.UpdateFormOutputResults(ctx, s.resultsID, string(b)); err != nil { + s.log.Error("cannot store the results", "results_id", s.resultsID, logkey.Error, err) + return + } + if err := s.a.ODB.Session.NotifyChanges(ctx); err != nil { + s.log.Error("cannot notify changes", logkey.Error, err) + } +} + +func (s *formSubmission) stored(ctx context.Context) (map[string]any, error) { + text, err := s.a.ODB.ReadFormOutputResults(ctx, s.resultsID) + if err != nil { + return nil, err + } + var current map[string]any + decoder := json.NewDecoder(strings.NewReader(text)) + decoder.UseNumber() + if err := decoder.Decode(¤t); err != nil { + return nil, err + } + return current, nil +} + +// reload replaces the results structure by the stored one, as reload_results() +// does after a rest call, which may have changed it. +func (s *formSubmission) reload(ctx context.Context) { + current, err := s.stored(ctx) + if err != nil { + s.log.Error("cannot reload the results", "results_id", s.resultsID, logkey.Error, err) + return + } + s.mu.Lock() + s.results = current + s.mu.Unlock() +} + +// run runs the outputs of the form in order, as __form_submit() does: an output +// may be skipped after an error, or by its condition; an output failing stops +// the run. +func (s *formSubmission) run(ctx context.Context) { + defer func() { + if r := recover(); r != nil { + s.formLog(ctx, "", 1, "form.submit", fmt.Sprint(r), nil) + s.addReturnCode(1) + } + s.setStatus("COMPLETED") + s.save(ctx, false) + }() + + s.setStatus("RUNNING") + s.save(ctx, false) + + outputs := defMaps(s.definition, "Outputs") + for i, output := range outputs { + if _, ok := output["Id"]; !ok { + output["Id"] = fmt.Sprintf("output-%d", i) + } + } + for _, output := range outputs { + outputID := defString(output, "Id") + s.mu.Lock() + ensureMap(s.results, "log")[outputID] = []any{} + order, _ := s.results["outputs_order"].([]any) + s.results["outputs_order"] = append(order, outputID) + s.mu.Unlock() + + if defBool(output, "SkipOnErrors") && s.returnCode() != 0 { + s.formLog(ctx, outputID, 1, "form.submit", "%(output_id)s: skip (previous output error)", + map[string]any{"output_id": outputID}) + s.save(ctx, false) + continue + } + run, err := checkOutputCondition(output, s.data) + if err != nil { + s.formLog(ctx, outputID, 1, "form.submit", err.Error(), nil) + s.save(ctx, false) + continue + } + if !run { + continue + } + + switch defString(output, "Dest") { + case "db": + err = s.outputDB(ctx, output) + case "script": + err = s.outputScript(ctx, output) + case "rest": + err = s.outputRest(ctx, output) + case "mail": + err = s.outputMail(ctx, output, nil, 0) + case "workflow": + err = s.outputWorkflow(ctx, output) + } + if err != nil { + s.formLog(ctx, outputID, 1, "form.submit", err.Error(), nil) + s.addReturnCode(1) + break + } + s.save(ctx, false) + } +} + +// formsAPIBase is the base url of the collector API, for the rest outputs and +// the dynamic candidates checks, which call it as the submitter: the configured +// server.forms.api_url, else the local listener of this server. +func formsAPIBase() string { + if base := viper.GetString("server.forms.api_url"); base != "" { + return strings.TrimRight(base, "/") + } + addr := viper.GetString("server.addr") + host, port, err := net.SplitHostPort(addr) + if err != nil { + return "http://" + addr + "/api" + } + if host == "" || host == "0.0.0.0" || host == "::" { + host = "127.0.0.1" + } + return "http://" + net.JoinHostPort(host, port) + "/api" +} + +var formsHTTPClient = &http.Client{Timeout: 10 * time.Minute} + +// apiResponse is the answer of an API call: its status and its decoded body. +type apiResponse struct { + status int + body any + raw []byte +} + +// callAPI calls the collector API as the submitter: a GET carries vars in its +// query string, the other methods in a JSON body. fullURL is used as it is when +// set, for the external calls of rest outputs, without the credentials. +func (s *formSubmission) callAPI(ctx context.Context, method, path string, vars any, fullURL string) (*apiResponse, error) { + target := fullURL + if target == "" { + target = formsAPIBase() + path + } + var body io.Reader + if method == http.MethodGet && fullURL == "" { + if m, ok := vars.(map[string]any); ok && len(m) > 0 { + q := url.Values{} + for k, v := range m { + q.Set(k, formValueText(v)) + } + target += "?" + q.Encode() + } + } else if vars != nil { + b, err := json.Marshal(vars) + if err != nil { + return nil, err + } + body = bytes.NewReader(b) + } + req, err := http.NewRequestWithContext(ctx, method, target, body) + if err != nil { + return nil, err + } + req.Header.Set("Content-Type", "application/json") + req.Header.Set("Accept", "application/json") + if fullURL == "" && s.auth != "" { + req.Header.Set("Authorization", s.auth) + } + resp, err := formsHTTPClient.Do(req) + if err != nil { + return nil, err + } + defer func() { _ = resp.Body.Close() }() + raw, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + out := &apiResponse{status: resp.StatusCode, raw: raw} + decoder := json.NewDecoder(bytes.NewReader(raw)) + decoder.UseNumber() + _ = decoder.Decode(&out.body) + return out, nil +} + +// problemTextOf returns the message of an API error answer. +func problemTextOf(r *apiResponse) string { + if m, ok := r.body.(map[string]any); ok { + if text, ok := m["text"].(string); ok { + return text + } + } + return strings.TrimSpace(string(r.raw)) +} diff --git a/server/handlers/forms_team.go b/server/handlers/forms_team.go new file mode 100644 index 00000000..958167e6 --- /dev/null +++ b/server/handlers/forms_team.go @@ -0,0 +1,235 @@ +package serverhandlers + +import ( + "context" + "log/slog" + "net/http" + "strconv" + + "github.com/labstack/echo/v4" + + "github.com/opensvc/oc3/cdb" + "github.com/opensvc/oc3/server" + "github.com/opensvc/oc3/util/echolog" + "github.com/opensvc/oc3/xauth" +) + +// formTeam describes one kind of form/group link: the publications, which make +// a form usable by a group, and the responsibles, who may change it. Each has +// the log actions and messages of the historical collector. +type formTeam struct { + table cdb.FormTeamTable + addAction string + addFmt string + addedFmt string + delAction string + delFmt string + deletedFmt string +} + +var ( + formPublicationTeam = formTeam{ + table: cdb.FormPublications, + addAction: "form.publication.add", + addFmt: "Form %(form_id)s published to group %(role)s", + addedFmt: "Form %(form_id)s already published to group %(role)s", + delAction: "form.publication.delete", + delFmt: "Form %(form_id)s unpublished to group %(group_id)s", + deletedFmt: "Form %(form_id)s already unpublished to group %(group_id)s", + } + formResponsibleTeam = formTeam{ + table: cdb.FormResponsibles, + addAction: "form.responsible.add", + addFmt: "Form %(form_id)s responsibility to group %(role)s added", + addedFmt: "Form %(form_id)s responsibility to group %(role)s already added", + delAction: "form.responsible.delete", + delFmt: "Form %(form_id)s responsibility to group %(group_id)s removed", + deletedFmt: "Form %(form_id)s responsibility to group %(group_id)s already removed", + } +) + +// GetFormPublications handles GET /forms/{form_id}/publications. +func (a *Api) GetFormPublications(c echo.Context, formId int, params server.GetFormPublicationsParams) error { + return a.getFormTeam(c, "GetFormPublications", cdb.FormPublications, int64(formId), listEndpointParams{ + props: params.Props, limit: params.Limit, offset: params.Offset, + meta: params.Meta, stats: params.Stats, orderby: params.Orderby, groupby: params.Groupby, + filter: params.Filter, + }) +} + +// GetFormResponsibles handles GET /forms/{form_id}/responsibles. +func (a *Api) GetFormResponsibles(c echo.Context, formId int, params server.GetFormResponsiblesParams) error { + return a.getFormTeam(c, "GetFormResponsibles", cdb.FormResponsibles, int64(formId), listEndpointParams{ + props: params.Props, limit: params.Limit, offset: params.Offset, + meta: params.Meta, stats: params.Stats, orderby: params.Orderby, groupby: params.Groupby, + filter: params.Filter, + }) +} + +// getFormTeam lists the groups linked to a form. Both lists require the form to +// be published to the caller, as form_published() does for both. +func (a *Api) getFormTeam(c echo.Context, handlerName string, table cdb.FormTeamTable, formID int64, p listEndpointParams) error { + log := echolog.GetLogHandler(c, handlerName) + if err := a.requireFormPublished(c, log, c.Request().Context(), formID); err != nil { + return formProblem(c, err) + } + return a.handleList(c, handlerName, "auth_group", p, func(ctx context.Context, lp cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetFormTeam(ctx, table, formID, lp) + }) +} + +// PostFormPublication handles POST /forms/{form_id}/publications/{group_id}. +func (a *Api) PostFormPublication(c echo.Context, formId int, groupId string) error { + return a.formTeamOne(c, "PostFormPublication", formPublicationTeam, true, strconv.Itoa(formId), groupId) +} + +// DeleteFormPublication handles DELETE /forms/{form_id}/publications/{group_id}. +func (a *Api) DeleteFormPublication(c echo.Context, formId int, groupId string) error { + return a.formTeamOne(c, "DeleteFormPublication", formPublicationTeam, false, strconv.Itoa(formId), groupId) +} + +// PostFormResponsible handles POST /forms/{form_id}/responsibles/{group_id}. +func (a *Api) PostFormResponsible(c echo.Context, formId int, groupId string) error { + return a.formTeamOne(c, "PostFormResponsible", formResponsibleTeam, true, strconv.Itoa(formId), groupId) +} + +// DeleteFormResponsible handles DELETE /forms/{form_id}/responsibles/{group_id}. +func (a *Api) DeleteFormResponsible(c echo.Context, formId int, groupId string) error { + return a.formTeamOne(c, "DeleteFormResponsible", formResponsibleTeam, false, strconv.Itoa(formId), groupId) +} + +// PostFormsPublications handles POST /forms_publications. +func (a *Api) PostFormsPublications(c echo.Context) error { + return a.formTeamBulk(c, "PostFormsPublications", formPublicationTeam, true) +} + +// DeleteFormsPublications handles DELETE /forms_publications. +func (a *Api) DeleteFormsPublications(c echo.Context) error { + return a.formTeamBulk(c, "DeleteFormsPublications", formPublicationTeam, false) +} + +// PostFormsResponsibles handles POST /forms_responsibles. +func (a *Api) PostFormsResponsibles(c echo.Context) error { + return a.formTeamBulk(c, "PostFormsResponsibles", formResponsibleTeam, true) +} + +// DeleteFormsResponsibles handles DELETE /forms_responsibles. +func (a *Api) DeleteFormsResponsibles(c echo.Context) error { + return a.formTeamBulk(c, "DeleteFormsResponsibles", formResponsibleTeam, false) +} + +func (a *Api) formTeamOne(c echo.Context, handlerName string, team formTeam, add bool, formID, groupID string) error { + log := echolog.GetLogHandler(c, handlerName) + ctx, cancel := context.WithTimeout(c.Request().Context(), a.SyncTimeout) + defer cancel() + result, err := a.formTeamChange(ctx, c, log, team, add, formID, groupID) + if err != nil { + return formProblem(c, err) + } + a.formNotify(ctx, log) + return c.JSON(http.StatusOK, result) +} + +// formTeamBulk takes the form and the group from the body keys form_id and +// group_id, one entry or a list, as the historical /forms_publications and +// /forms_responsibles handlers do. +func (a *Api) formTeamBulk(c echo.Context, handlerName string, team formTeam, add bool) error { + log := echolog.GetLogHandler(c, handlerName) + ctx, cancel := context.WithTimeout(c.Request().Context(), a.SyncTimeout) + defer cancel() + entries, isList, err := decodeEntries(c) + if err != nil { + return formProblem(c, err) + } + defer a.formNotify(ctx, log) + return runEntries(c, entries, isList, func(entry map[string]any) (map[string]any, error) { + formID, ok := entryString(entry, "form_id") + if !ok { + return nil, formErrorf(http.StatusBadRequest, "The 'form_id' key is mandatory") + } + groupID, ok := entryString(entry, "group_id") + if !ok { + return nil, formErrorf(http.StatusBadRequest, "The 'group_id' key is mandatory") + } + return a.formTeamChange(ctx, c, log, team, add, formID, groupID) + }) +} + +// formTeamChange links or unlinks a form and a group. Adding resolves the group +// as lib_org_group() does, by id or role, among the caller's groups for a +// non-manager, and refuses privilege groups. An existing link, or a missing +// one, answers with an info message rather than an error. +func (a *Api) formTeamChange(ctx context.Context, c echo.Context, log *slog.Logger, team formTeam, add bool, formIDStr, groupIDStr string) (map[string]any, error) { + if err := requireFormsManager(c); err != nil { + return nil, err + } + formID, err := parseFormID(formIDStr) + if err != nil { + return nil, err + } + if err := a.requireFormResponsible(c, log, ctx, formID); err != nil { + return nil, err + } + + if !add { + groupID, err := strconv.ParseInt(groupIDStr, 10, 64) + if err != nil { + return nil, formErrorf(http.StatusBadRequest, "invalid group id %q", groupIDStr) + } + d := map[string]any{"form_id": formIDStr, "group_id": groupIDStr} + exists, err := a.ODB.FormTeamExists(ctx, team.table, formID, groupID) + if err != nil { + return nil, formInternal(log, "cannot check the form group link", err) + } + if !exists { + return map[string]any{"info": pyFormat(team.deletedFmt, d)}, nil + } + if err := a.ODB.DeleteFormTeam(ctx, team.table, formID, groupID); err != nil { + return nil, formInternal(log, "cannot unlink the form and the group", err) + } + a.formLog(ctx, c, log, team.delAction, team.delFmt, d) + return map[string]any{"info": pyFormat(team.delFmt, d)}, nil + } + + var userGroupIDs []int64 + isManager := IsManager(c) + if !isManager { + user := UserInfoFromContext(c) + if user == nil { + return nil, formErrorf(http.StatusUnauthorized, "missing user context") + } + userID, err := strconv.ParseInt(user.GetExtensions().Get(xauth.XUserID), 10, 64) + if err != nil { + return nil, formErrorf(http.StatusBadRequest, "invalid user id") + } + if userGroupIDs, err = a.ODB.UserGroupIDs(ctx, userID); err != nil { + return nil, formInternal(log, "cannot list user groups", err) + } + } + group, status, err := a.ODB.OrgGroup(ctx, groupIDStr, userGroupIDs, isManager) + if err != nil { + return nil, formInternal(log, "cannot resolve the group", err) + } + switch status { + case cdb.OrgGroupNotFound: + return nil, formErrorf(http.StatusNotFound, "Group not found: %s", groupIDStr) + case cdb.OrgGroupAmbiguous: + return nil, formErrorf(http.StatusBadRequest, "Ambiguous group id: %s", groupIDStr) + case cdb.OrgGroupPrivileged: + return nil, formErrorf(http.StatusForbidden, "Operation not allowed on privilege group: %s", group.Role) + } + + d := map[string]any{"form_id": formIDStr, "role": group.Role} + exists, err := a.ODB.FormTeamExists(ctx, team.table, formID, group.ID) + if err != nil { + return nil, formInternal(log, "cannot check the form group link", err) + } + if exists { + return map[string]any{"info": pyFormat(team.addedFmt, d)}, nil + } + if err := a.ODB.InsertFormTeam(ctx, team.table, formID, group.ID); err != nil { + return nil, formInternal(log, "cannot link the form and the group", err) + } + a.formLog(ctx, c, log, team.addAction, team.addFmt, d) + return map[string]any{"info": pyFormat(team.addFmt, d)}, nil +} diff --git a/server/handlers/forms_validate.go b/server/handlers/forms_validate.go new file mode 100644 index 00000000..2238278b --- /dev/null +++ b/server/handlers/forms_validate.go @@ -0,0 +1,224 @@ +package serverhandlers + +import ( + "context" + "fmt" + "net/http" + "strings" +) + +// validate checks the submitted data against the inputs of the form, as +// validate_data() does: one object, or a list of objects each checked. +func (s *formSubmission) validate(ctx context.Context) error { + switch t := s.data.(type) { + case map[string]any: + return s.validateData(ctx, t) + case []any: + for _, item := range t { + m, ok := item.(map[string]any) + if !ok { + return formErrorf(http.StatusBadRequest, "form data list entries must be objects") + } + if err := s.validateData(ctx, m); err != nil { + return err + } + } + } + return nil +} + +func (s *formSubmission) validateData(ctx context.Context, data map[string]any) error { + for _, input := range defMaps(s.definition, "Inputs") { + if err := s.validateInput(ctx, data, input); err != nil { + return err + } + } + return nil +} + +// validateInput checks one input, as validate_input_data() does: mandatory +// values, forced keys, strict static candidates and strict dynamic candidates, +// the last ones fetched from the API as the submitter. +func (s *formSubmission) validateInput(ctx context.Context, data map[string]any, input map[string]any) error { + inputID := defString(input, "Id") + keyID := defString(input, "Key") + lookup := inputID + if keyID != "" { + lookup = keyID + } + val := data[lookup] + + applies, err := checkInputCondition(input, data) + if err != nil { + return formErrorf(http.StatusBadRequest, "%s", err) + } + if !applies { + return nil + } + if val == nil { + if defBool(input, "Mandatory") { + return formErrorf(http.StatusBadRequest, "Missing value for mandatory input '%s'", inputID) + } + return nil + } + + vals, isList := val.([]any) + if !isList { + vals = []any{val} + } + + // Forced keys: "key=value" entries the submitted data must carry as defined. + var keyDefs []string + for _, k := range defList(input, "Keys") { + if ks, ok := k.(string); ok { + keyDefs = append(keyDefs, ks) + } + } + refData := []map[string]any{data} + if isList { + refData = nil + for _, item := range vals { + if m, ok := item.(map[string]any); ok { + refData = append(refData, m) + } + } + } + for _, ref := range refData { + for _, keyDef := range keyDefs { + key, forced, found := strings.Cut(keyDef, "=") + if !found { + continue + } + key = strings.TrimSpace(key) + forced = formDereference(strings.TrimSpace(forced), ref, "") + refVal, ok := ref[key] + if !ok { + return formErrorf(http.StatusBadRequest, "missing key '%s', from input %s", key, inputID) + } + if !strings.Contains(forced, "#") && forced != formValueText(refVal) { + return formErrorf(http.StatusBadRequest, "unallowed key value '%s=%s', expecting '%s', from input %s", + key, formValueText(refVal), forced, inputID) + } + } + } + + strict := defBool(input, "StrictCandidates") + mandatory := defBool(input, "Mandatory") + + // Strict static candidates. + if candidates := defList(input, "Candidates"); len(candidates) > 0 && strict { + var allowed []string + for _, candidate := range candidates { + if m, ok := candidate.(map[string]any); ok { + if v, ok := m["Value"]; ok { + allowed = append(allowed, formValueText(v)) + continue + } + } + allowed = append(allowed, formValueText(candidate)) + } + for _, v := range vals { + if isFalsy(v) && !mandatory { + continue + } + if !containsString(allowed, formValueText(v)) { + return formErrorf(http.StatusBadRequest, "Input '%s' value '%s' not in allowed candidates", inputID, formValueText(v)) + } + } + } + + // Strict dynamic candidates: the key to compare is a forced key naming the + // input, else the input Value property. + var key string + for _, keyDef := range keyDefs { + k, v, found := strings.Cut(keyDef, "=") + if found && strings.TrimSpace(k) == inputID { + key = strings.TrimSpace(v) + } + } + if key == "" { + key = defString(input, "Value") + } + fn := defString(input, "Function") + if fn == "" || key == "" || !strict { + return nil + } + fn = formDereference(fn, data, "") + if !strings.HasPrefix(fn, "/") { + return nil + } + key = strings.TrimLeft(key, "#") + for _, v := range vals { + args, err := formRestArgs(fn, data) + if err != nil { + return formErrorf(http.StatusBadRequest, "cannot build the candidates url %s: missing %s", fn, err) + } + kwargs := map[string]any{} + for _, entry := range defList(input, "Args") { + es, ok := entry.(string) + if !ok { + continue + } + es = formDereference(es, data, "") + k, kv, found := strings.Cut(es, "=") + if !found { + continue + } + kwargs[strings.TrimSpace(k)] = formDereference(strings.TrimSpace(kv), data, "") + } + keyVal := v + if m, ok := v.(map[string]any); ok { + keyVal = m[key] + } + kwargs["limit"] = 0 + kwargs["search"] = formValueText(keyVal) + kwargs["search_props"] = key + path := "/" + strings.Join(args, "/") + resp, err := s.callAPI(ctx, http.MethodGet, path, kwargs, "") + if err != nil { + return formErrorf(http.StatusBadRequest, "cannot verify the submitted value is a valid candidate: %s", err) + } + if resp.status == http.StatusNotFound { + return formErrorf(http.StatusBadRequest, "Unknown handler '%s': can not verify the submitted value is a valid candidates", fn) + } + if resp.status >= 300 { + return formErrorf(http.StatusBadRequest, "cannot verify the submitted value is a valid candidate: %s", problemTextOf(resp)) + } + var candidates []string + if m, ok := resp.body.(map[string]any); ok { + list, _ := m["data"].([]any) + for _, candidate := range list { + cv, err := formGetVal(candidate, key) + if err != nil { + return formErrorf(http.StatusBadRequest, "Key '%s' not in candidates", key) + } + candidates = append(candidates, formValueText(cv)) + } + } + if isFalsy(keyVal) && !mandatory { + continue + } + if !containsString(candidates, formValueText(keyVal)) { + return formErrorf(http.StatusBadRequest, "Input '%s' value '%s' not in allowed candidates %s obtained from %s", + inputID, formValueText(keyVal), fmt.Sprint(candidates), path) + } + } + return nil +} + +// isFalsy tells whether a value is false for python: empty or zero. +func isFalsy(v any) bool { + switch t := v.(type) { + case nil: + return true + case string: + return t == "" + case bool: + return !t + case []any: + return len(t) == 0 + case map[string]any: + return len(t) == 0 + } + return formValueText(v) == "0" +} diff --git a/server/handlers/handle_list.go b/server/handlers/handle_list.go index 31dfd31a..7a42ded8 100644 --- a/server/handlers/handle_list.go +++ b/server/handlers/handle_list.go @@ -4,6 +4,7 @@ import ( "context" "log/slog" "net/http" + "slices" "github.com/labstack/echo/v4" @@ -31,6 +32,68 @@ type listEndpointParams struct { // cdb.ListParams. Set it only on the endpoints whose access control // references the caller's identity and not just its groups. withUserID bool + + // virtual are the props computed from other props rather than read from a + // column, as the historical collector's vprops, e.g. form_definition parsed + // from form_yaml. They are listed in the mapping's Available props, without a + // SQL expression. + virtual map[string]virtualProp +} + +// virtualProp is a prop computed after the fetch, from the props it requires. +// The required props are fetched even when not asked for, then dropped. +type virtualProp struct { + requires []string + // compute returns the value, or false to leave the prop out of the row. + compute func(item map[string]any) (any, bool) +} + +// fetchPropsFor replaces the virtual props of a selection by the props they +// require, keeping the order and without duplicates. +func fetchPropsFor(props []string, virtual map[string]virtualProp) []string { + if len(virtual) == 0 { + return props + } + out := make([]string, 0, len(props)) + for _, prop := range props { + if v, ok := virtual[prop]; ok { + out = ensureProps(out, v.requires...) + continue + } + out = ensureProps(out, prop) + } + return out +} + +// computeVirtualProps fills the virtual props asked for, then removes the props +// fetched only to compute them. +func computeVirtualProps(items []map[string]any, props []string, virtual map[string]virtualProp) { + if len(virtual) == 0 { + return + } + var wanted []string + for _, prop := range props { + if _, ok := virtual[prop]; ok { + wanted = append(wanted, prop) + } + } + if len(wanted) == 0 { + return + } + for _, item := range items { + for _, prop := range wanted { + if value, ok := virtual[prop].compute(item); ok { + item[prop] = value + } + } + for _, prop := range wanted { + for _, required := range virtual[prop].requires { + if !slices.Contains(props, required) { + delete(item, required) + } + } + } + } } // handleList implements the common pipeline for all list endpoints: @@ -74,7 +137,8 @@ func (a *Api) handleList( "is_manager", isManager, ) - selectExprs, err := buildSelectClause(query.Props, mapping) + fetchProps := fetchPropsFor(query.Props, p.virtual) + selectExprs, err := buildSelectClause(fetchProps, mapping) if err != nil { log.Error("cannot build select clause", logkey.Error, err) return JSONProblemf(c, http.StatusInternalServerError, "cannot build select clause") @@ -85,9 +149,9 @@ func (a *Api) handleList( IsManager: isManager, Limit: query.Page.Limit, Offset: query.Page.Offset, - Props: query.Props, + Props: fetchProps, SelectExprs: selectExprs, - TypeHints: buildTypeHints(query.Props, mapping), + TypeHints: buildTypeHints(fetchProps, mapping), OrderBy: query.OrderBy, GroupBy: query.GroupBy, Filters: filters, @@ -101,6 +165,7 @@ func (a *Api) handleList( log.Error("cannot fetch items", logkey.Error, err) return JSONProblemf(c, http.StatusInternalServerError, "cannot get %s", mappingKey) } + computeVirtualProps(items, query.Props, p.virtual) response := newListResponse(items, mapping, query) if query.WithMeta && !query.WithStats { diff --git a/server/handlers/props_mapping.go b/server/handlers/props_mapping.go index aa8782f3..04eae65a 100644 --- a/server/handlers/props_mapping.go +++ b/server/handlers/props_mapping.go @@ -382,6 +382,88 @@ var propsMapping = map[string]propMapping{ "description": colStr(schema.AuthGroupDescription), }, }, + // Forms, as the historical collector lists them: form_definition is not a + // column but form_yaml parsed, computed by the forms handlers. + "form": { + Available: []string{ + "id", "form_name", "form_yaml", "form_author", "form_created", + "form_type", "form_folder", "form_definition", + }, + Props: map[string]propDef{ + "id": col(schema.FormsID), + "form_name": colStr(schema.FormsFormName), + "form_yaml": colStr(schema.FormsFormYaml), + "form_author": colStr(schema.FormsFormAuthor), + "form_created": colStr(schema.FormsFormCreated), + "form_type": colStr(schema.FormsFormType), + "form_folder": colStr(schema.FormsFormFolder), + }, + }, + // Form revisions: the definition of a form as submitted, kept by md5. + "form_revision": { + Available: []string{ + "id", "form_yaml", "form_md5", "form_date", "form_id", + "form_folder", "form_name", "form_definition", + }, + Props: map[string]propDef{ + "id": col(schema.FormsRevisionsID), + "form_yaml": colStr(schema.FormsRevisionsFormYaml), + "form_md5": colStr(schema.FormsRevisionsFormMD5), + "form_date": colStr(schema.FormsRevisionsFormDate), + "form_id": col(schema.FormsRevisionsFormID), + "form_folder": colStr(schema.FormsRevisionsFormFolder), + "form_name": colStr(schema.FormsRevisionsFormName), + }, + }, + // Forms stored by workflows, joined to the revision they were submitted with, + // as the historical collector's v_forms_store view does: the revision columns + // keep their own name, flat. + "form_store": { + Available: []string{ + "id", "results_id", "form_submitter", "form_submit_date", "form_data", + "form_next_id", "form_prev_id", "form_assignee", "form_head_id", + "form_md5", "form_var_id", "form_yaml", "form_date", "form_id", + "form_folder", "form_name", "form_definition", + }, + Props: map[string]propDef{ + "id": col(schema.FormsStoreID), + "results_id": col(schema.FormsStoreResultsID), + "form_submitter": colStr(schema.FormsStoreFormSubmitter), + "form_submit_date": colStr(schema.FormsStoreFormSubmitDate), + "form_data": colStr(schema.FormsStoreFormData), + "form_next_id": col(schema.FormsStoreFormNextID), + "form_prev_id": col(schema.FormsStoreFormPrevID), + "form_assignee": colStr(schema.FormsStoreFormAssignee), + "form_head_id": col(schema.FormsStoreFormHeadID), + "form_md5": colStr(schema.FormsStoreFormMD5), + "form_var_id": col(schema.FormsStoreFormVarID), + "form_yaml": colStr(schema.FormsRevisionsFormYaml), + "form_date": colStr(schema.FormsRevisionsFormDate), + "form_id": col(schema.FormsRevisionsFormID), + "form_folder": colStr(schema.FormsRevisionsFormFolder), + "form_name": colStr(schema.FormsRevisionsFormName), + }, + }, + // Workflows chaining stored forms. + "workflow": { + Available: []string{ + "id", "form_head_id", "status", "steps", "creator", "create_date", + "last_assignee", "last_update", "form_md5", "last_form_id", "last_form_name", + }, + Props: map[string]propDef{ + "id": col(schema.WorkflowsID), + "form_head_id": col(schema.WorkflowsFormHeadID), + "status": colStr(schema.WorkflowsStatus), + "steps": col(schema.WorkflowsSteps), + "creator": colStr(schema.WorkflowsCreator), + "create_date": colStr(schema.WorkflowsCreateDate), + "last_assignee": colStr(schema.WorkflowsLastAssignee), + "last_update": colStr(schema.WorkflowsLastUpdate), + "form_md5": colStr(schema.WorkflowsFormMD5), + "last_form_id": col(schema.WorkflowsLastFormID), + "last_form_name": colStr(schema.WorkflowsLastFormName), + }, + }, "user": { Available: []string{ "id", "username", "email", "first_name", "last_name", "phone_work", diff --git a/util/git/track.go b/util/git/track.go new file mode 100644 index 00000000..faba58bb --- /dev/null +++ b/util/git/track.go @@ -0,0 +1,262 @@ +package git + +import ( + "bytes" + "fmt" + "os" + "os/exec" + "path/filepath" + "regexp" + "sort" + "strings" + + "github.com/spf13/viper" +) + +// Track keeps the history of one text document per object in git, as the +// historical collector's gittrack module does for forms: one repository per +// object id under Dir, holding the document in a file named File. +type Track struct { + Dir string + File string +} + +// revPattern bounds the revisions passed to git: a commit id, a ref and the +// usual suffixes, never an option. +var revPattern = regexp.MustCompile(`^[A-Za-z0-9][A-Za-z0-9._/^~@{}-]*$`) + +// ValidRev reports whether s may be passed to git as a revision. +func ValidRev(s string) bool { return revPattern.MatchString(s) } + +func (t Track) repo(id string) string { return filepath.Join(t.Dir, id) } + +func (t Track) git(id string, args ...string) (string, error) { + cmd := exec.Command("git", append([]string{"--git-dir=" + filepath.Join(t.repo(id), ".git")}, args...)...) + var out, errOut bytes.Buffer + cmd.Stdout = &out + cmd.Stderr = &errOut + if err := cmd.Run(); err != nil { + return out.String(), fmt.Errorf("git %s: %w: %s", args[0], err, strings.TrimSpace(errOut.String())) + } + return out.String(), nil +} + +func (t Track) gitIn(id string, args ...string) error { + cmd := exec.Command("git", args...) + cmd.Dir = t.repo(id) + if out, err := cmd.CombinedOutput(); err != nil { + return fmt.Errorf("git %s: %w: %s", args[0], err, strings.TrimSpace(string(out))) + } + return nil +} + +// Exists reports whether the object has a history. +func (t Track) Exists(id string) bool { + _, err := os.Stat(filepath.Join(t.repo(id), ".git")) + return err == nil +} + +// authorArg formats "Name " for git --author, which requires the angle +// brackets even without an address. +func authorArg(author string) []string { + if author == "" { + return nil + } + if !strings.Contains(author, "<") { + author += " <>" + } + return []string{"--author=" + author} +} + +func (t Track) init(id, author string) error { + if err := os.MkdirAll(t.repo(id), 0o755); err != nil { + return err + } + email := viper.GetString("git.user_email") + if email == "" { + email = "nobody@localhost.localdomain" + } + for _, args := range [][]string{ + {"init"}, + {"config", "user.email", email}, + {"config", "user.name", "collector"}, + } { + if err := t.gitIn(id, args...); err != nil { + return err + } + } + return nil +} + +// Commit records a new content of the object's document. +func (t Track) Commit(id, content, author string) error { + if !t.Exists(id) { + if err := t.init(id, author); err != nil { + return err + } + } + _ = os.Remove(filepath.Join(t.repo(id), ".git", "index.lock")) + if err := os.WriteFile(filepath.Join(t.repo(id), t.File), []byte(content), 0o644); err != nil { + return err + } + if err := t.gitIn(id, "add", t.File); err != nil { + return err + } + args := append([]string{"commit", "-m", "change"}, authorArg(author)...) + // An unchanged content leaves nothing to commit: not an error. + _ = t.gitIn(id, append(args, "-a")...) + return nil +} + +// Read returns the current content of the object's document. +func (t Track) Read(id string) (string, error) { + b, err := os.ReadFile(filepath.Join(t.repo(id), t.File)) + return string(b), err +} + +// Revision is one entry of an object's history, as gittrack's parse_log() +// returns them for objects other than sysreports. +type Revision struct { + ID string `json:"id"` + CID string `json:"cid"` + Start string `json:"start"` + Content string `json:"content,omitempty"` + Stat []string `json:"stat"` + Summary string `json:"summary,omitempty"` + Group string `json:"group"` +} + +// Timeline returns the last 300 revisions of the object, newest first. +func (t Track) Timeline(id string) ([]Revision, error) { + if !t.Exists(id) { + return []Revision{}, nil + } + out, err := t.git(id, "log", "-n", "300", "--stat=510,500", "--date=iso", "--all") + if err != nil { + return nil, err + } + return parseLog(out, id), nil +} + +func parseLog(s, id string) []Revision { + var data []Revision + var d Revision + var stat strings.Builder + flush := func() { + if d.Start == "" { + return + } + changed := map[string]bool{} + for _, line := range strings.Split(stat.String(), "\n") { + if strings.Contains(line, "files changed") { + d.Summary = strings.TrimSpace(line) + continue + } + if !strings.Contains(line, " | ") { + continue + } + fpath := strings.Trim(strings.TrimSpace(strings.SplitN(line, " | ", 2)[0]), `"`) + changed[fpath] = true + } + d.Stat = make([]string, 0, len(changed)) + for fpath := range changed { + d.Stat = append(d.Stat, fpath) + } + sort.Strings(d.Stat) + d.Group = id + data = append(data, d) + } + for _, line := range strings.Split(s, "\n") { + switch { + case strings.HasPrefix(line, "commit"): + flush() + d = Revision{} + stat.Reset() + if fields := strings.Fields(line); len(fields) > 1 { + d.CID = fields[1] + d.ID = fields[1] + } + case strings.HasPrefix(line, "Author:"): + d.Content = line + case strings.HasPrefix(strings.TrimSpace(line), "rollback"): + d.Content += "
" + line + case strings.HasPrefix(line, "Date:"): + if fields := strings.Fields(line); len(fields) >= 3 { + d.Start = fields[1] + "T" + fields[2] + } + case d.CID != "" && d.Start != "": + stat.WriteString(line + "\n") + } + } + flush() + if data == nil { + data = []Revision{} + } + return data +} + +// Blob is the content of the document at a revision. +type Blob struct { + OID string `json:"oid"` + Content string `json:"content"` +} + +// At returns the document at a revision, nil when the revision holds none. +func (t Track) At(id, rev string) (*Blob, error) { + if !t.Exists(id) { + return nil, nil + } + out, err := t.git(id, "ls-tree", "-r", rev) + if err != nil { + return nil, err + } + for _, line := range strings.Split(out, "\n") { + fields := strings.Fields(line) + if len(fields) < 4 { + continue + } + content, err := t.git(id, "show", fields[2]) + if err != nil { + return nil, err + } + return &Blob{OID: fields[2], Content: content}, nil + } + return nil, nil +} + +// Show returns the change made by a revision, with its stats, as git prints it. +func (t Track) Show(id, rev string) (string, error) { + if !t.Exists(id) { + return "", nil + } + return t.git(id, "show", "--pretty=format:%ci%n%b", rev, "--numstat", "--patch") +} + +// Diff returns the differences of the document between two revisions. +func (t Track) Diff(id, rev1, rev2 string) (string, error) { + if !t.Exists(id) { + return "", nil + } + return t.git(id, "diff", "--pretty=format:%ci%n%b", rev1, rev2, "--", t.File) +} + +// Rollback restores the document of a revision as a new commit. +func (t Track) Rollback(id, rev, author string) error { + if !t.Exists(id) { + return fmt.Errorf("no history for %s", id) + } + shown, err := t.git(id, "show", "--pretty=format:%ci%n%b", rev, "--patch") + if err != nil { + return err + } + date := "" + if first, _, _ := strings.Cut(shown, "\n"); !strings.Contains(first, "diff") { + date = first + } + if err := t.gitIn(id, "checkout", rev, "--", t.File); err != nil { + return err + } + args := append([]string{"commit", "-m", "rollback to " + date}, authorArg(author)...) + _ = t.gitIn(id, append(args, "-a")...) + return nil +} From eba9a8906de615cbd86ef4c49bd93ed72449c8db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Mon, 28 Sep 2026 09:56:28 +0200 Subject: [PATCH 30/61] Add the GET /packages endpoint List the packages installed on the nodes the user can see, as the historical packages table: joined with nodes, whose app scopes the access, and left-joined with pkg_sig_provider for the provider of the signing key (sig_provider). Ordered by node name, package name and architecture by default; the nodes. props come through the join, and the list takes the filter parameter and returns its total. The response is typed in the spec (PackageRow, PackageListResponse). --- cdb/db_packages.go | 217 ++++++++ schema/relations.go | 3 + server/api.yaml | 191 +++++++ server/codegen_server_gen.go | 737 ++++++++++++++++----------- server/codegen_type_gen.go | 179 +++++++ server/handlers/get_packages.go | 22 + server/handlers/get_packages_diff.go | 72 +++ server/handlers/props_mapping.go | 33 ++ 8 files changed, 1151 insertions(+), 303 deletions(-) create mode 100644 server/handlers/get_packages.go create mode 100644 server/handlers/get_packages_diff.go diff --git a/cdb/db_packages.go b/cdb/db_packages.go index b37210df..c67fb2f5 100644 --- a/cdb/db_packages.go +++ b/cdb/db_packages.go @@ -2,7 +2,11 @@ package cdb import ( "context" + "fmt" + "strings" "time" + + "github.com/opensvc/oc3/schema" ) func (oDb *DB) PurgePackagesOutdated(ctx context.Context, maxAge time.Duration) error { @@ -30,3 +34,216 @@ func (oDb *DB) PurgePatchesOutdated(ctx context.Context, maxAge time.Duration) e } return nil } + +// buildPackagesQuery lists the packages installed on the nodes the user may see, +// as the historical packages table does: joined with nodes, whose app scopes the +// access, and with pkg_sig_provider, which names the signing key's provider. +func buildPackagesQuery(groups []string, isManager bool, selectExprs []string, filters []ColumnFilter) (string, []any, error) { + // nodes is an inner join: a package of an unknown node is not listed, and the + // access check filters on nodes.app. pkg_sig_provider is a left join: most + // signatures have no known provider. + q := From(schema.TPackages). + Via(schema.TNodes). + LeftJoin(schema.TPkgSigProvider). + RawSelect(selectExprs...) + + if !isManager { + cleanGroups := cleanGroups(groups) + if len(cleanGroups) == 0 { + q = q.WhereRaw("1=0") + } else { + args := make([]any, len(cleanGroups)) + for i, g := range cleanGroups { + args[i] = g + } + q = q.WhereRaw( + "nodes.app IN ("+ + "SELECT a.app FROM apps a"+ + " JOIN apps_responsibles ar ON ar.app_id = a.id"+ + " JOIN auth_group ag ON ag.id = ar.group_id"+ + " WHERE ag.role IN ("+Placeholders(len(cleanGroups))+")"+ + ")", + args..., + ) + } + } else { + q = q.Where(schema.PackagesID, ">", 0) + } + + // Column filters of the request, ANDed with the access control above. + q = q.WhereFilters(filters) + + query, args, err := q.Build() + if err != nil { + return "", nil, fmt.Errorf("buildPackagesQuery: %w", err) + } + return query, args, nil +} + +// GetPackages lists packages, ordered by node, name and architecture by default, +// as the historical packages table. +func (oDb *DB) GetPackages(ctx context.Context, p ListParams) ([]map[string]any, error) { + query, args, err := buildPackagesQuery(p.Groups, p.IsManager, p.SelectExprs, p.Filters) + if err != nil { + return nil, err + } + if gb := p.GroupByClause(""); gb != "" { + query += " " + gb + } + query += " " + p.OrderByClause("nodes.nodename, packages.pkg_name, packages.pkg_arch") + query, args = appendLimitOffset(query, args, p.Limit, p.Offset) + + rows, err := oDb.DB.QueryContext(ctx, query, args...) + if err != nil { + return nil, fmt.Errorf("getPackages: %w", err) + } + defer func() { _ = rows.Close() }() + + return scanRowsToMaps(rows, p.Props, p.TypeHints) +} + +// PackageDiffNode is a node compared by a packages diff. +type PackageDiffNode struct { + NodeID string `json:"node_id"` + Nodename string `json:"nodename"` +} + +// PackageDiffRow is a package version installed on some of the compared nodes +// but not on all of them. +type PackageDiffRow struct { + NodeID string `json:"node_id"` + PkgName string `json:"pkg_name"` + PkgVersion string `json:"pkg_version"` + PkgArch string `json:"pkg_arch"` + PkgType string `json:"pkg_type"` +} + +// appsOfGroups is the condition restricting an app column to the apps one of the +// groups is responsible for, and its arguments; "1=0" without groups. +func appsOfGroups(appCol string, groups []string) (string, []any) { + cleanGroups := cleanGroups(groups) + if len(cleanGroups) == 0 { + return "1=0", nil + } + args := make([]any, len(cleanGroups)) + for i, g := range cleanGroups { + args[i] = g + } + return appCol + " IN (" + + "SELECT a.app FROM apps a" + + " JOIN apps_responsibles ar ON ar.app_id = a.id" + + " JOIN auth_group ag ON ag.id = ar.group_id" + + " WHERE ag.role IN (" + Placeholders(len(cleanGroups)) + ")" + + ")", args +} + +// PackagesDiffNodes resolves the nodes a packages diff compares, as the +// historical lib_packages_diff: the given nodes, plus the nodes running the +// given services, or with encap the encapsulated nodes of those services (the +// nodes named after their instances' mon_vmname). Unless the user is a manager, +// only the nodes and services of the apps their groups are responsible for count. +// The nodes are returned by name. +func (oDb *DB) PackagesDiffNodes(ctx context.Context, nodeIDs, svcIDs []string, encap bool, groups []string, isManager bool) ([]PackageDiffNode, error) { + var parts []string + var args []any + + if len(nodeIDs) > 0 { + part := "SELECT nodes.node_id FROM nodes WHERE nodes.node_id IN (" + Placeholders(len(nodeIDs)) + ")" + for _, id := range nodeIDs { + args = append(args, id) + } + if !isManager { + cond, condArgs := appsOfGroups("nodes.app", groups) + part += " AND " + cond + args = append(args, condArgs...) + } + parts = append(parts, part) + } + + if len(svcIDs) > 0 { + var part string + if encap { + part = "SELECT nodes.node_id FROM svcmon" + + " JOIN services ON services.svc_id = svcmon.svc_id" + + " JOIN nodes ON nodes.nodename = svcmon.mon_vmname" + + " WHERE svcmon.mon_vmname IS NOT NULL AND svcmon.mon_vmname != ''" + + " AND svcmon.svc_id IN (" + Placeholders(len(svcIDs)) + ")" + } else { + part = "SELECT svcmon.node_id FROM svcmon" + + " JOIN services ON services.svc_id = svcmon.svc_id" + + " WHERE svcmon.svc_id IN (" + Placeholders(len(svcIDs)) + ")" + } + for _, id := range svcIDs { + args = append(args, id) + } + if !isManager { + cond, condArgs := appsOfGroups("services.svc_app", groups) + part += " AND " + cond + args = append(args, condArgs...) + } + parts = append(parts, part) + } + + if len(parts) == 0 { + return []PackageDiffNode{}, nil + } + query := "SELECT nodes.node_id, COALESCE(nodes.nodename, '') FROM nodes" + + " WHERE nodes.node_id IN (" + strings.Join(parts, " UNION ") + ")" + + " ORDER BY nodes.nodename, nodes.node_id" + rows, err := oDb.DB.QueryContext(ctx, query, args...) + if err != nil { + return nil, fmt.Errorf("packagesDiffNodes: %w", err) + } + defer func() { _ = rows.Close() }() + nodes := []PackageDiffNode{} + for rows.Next() { + var n PackageDiffNode + if err := rows.Scan(&n.NodeID, &n.Nodename); err != nil { + return nil, fmt.Errorf("packagesDiffNodes: %w", err) + } + nodes = append(nodes, n) + } + return nodes, rows.Err() +} + +// PackagesDiff lists, on the given nodes, the package versions that are not +// installed on all of them: a package (name, version, architecture, type) +// present on every node is left out, as in the historical lib_packages_diff. +func (oDb *DB) PackagesDiff(ctx context.Context, nodeIDs []string) ([]PackageDiffRow, error) { + if len(nodeIDs) < 2 { + return []PackageDiffRow{}, nil + } + in := Placeholders(len(nodeIDs)) + query := "SELECT p.node_id, p.pkg_name, p.pkg_version, p.pkg_arch, COALESCE(p.pkg_type, '')" + + " FROM packages p JOIN (" + + " SELECT pkg_name, pkg_version, pkg_arch, pkg_type FROM packages" + + " WHERE node_id IN (" + in + ")" + + " GROUP BY pkg_name, pkg_version, pkg_arch, pkg_type" + + " HAVING COUNT(DISTINCT node_id) != ?" + + " ) u ON p.pkg_name = u.pkg_name AND p.pkg_version = u.pkg_version" + + " AND p.pkg_arch = u.pkg_arch AND p.pkg_type <=> u.pkg_type" + + " WHERE p.node_id IN (" + in + ")" + + " ORDER BY p.pkg_name, p.pkg_arch, p.pkg_type, p.pkg_version, p.node_id" + args := make([]any, 0, 2*len(nodeIDs)+1) + for _, id := range nodeIDs { + args = append(args, id) + } + args = append(args, len(nodeIDs)) + for _, id := range nodeIDs { + args = append(args, id) + } + rows, err := oDb.DB.QueryContext(ctx, query, args...) + if err != nil { + return nil, fmt.Errorf("packagesDiff: %w", err) + } + defer func() { _ = rows.Close() }() + out := []PackageDiffRow{} + for rows.Next() { + var r PackageDiffRow + if err := rows.Scan(&r.NodeID, &r.PkgName, &r.PkgVersion, &r.PkgArch, &r.PkgType); err != nil { + return nil, fmt.Errorf("packagesDiff: %w", err) + } + out = append(out, r) + } + return out, rows.Err() +} diff --git a/schema/relations.go b/schema/relations.go index b4da7d7d..92f1314a 100644 --- a/schema/relations.go +++ b/schema/relations.go @@ -19,6 +19,9 @@ func init() { ActionQueueNodeID.Ref = NodesNodeID ActionQueueSvcID.Ref = ServicesSvcID + PackagesNodeID.Ref = NodesNodeID + PackagesPkgSig.Ref = PkgSigProviderSigID + SvcmonSvcID.Ref = ServicesSvcID SvcmonNodeID.Ref = NodesNodeID SvcmonLogSvcID.Ref = ServicesSvcID diff --git a/server/api.yaml b/server/api.yaml index 80454594..645253ff 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -6302,6 +6302,88 @@ paths: 500: $ref: '#/components/responses/500' + /packages: + get: + operationId: GetPackages + description: | + List the packages installed on the nodes the user can see, with the + provider of their signing key. Ordered by node name, package name and + architecture by default. The `nodes.` properties come from the joined + nodes table. + parameters: + - $ref: '#/components/parameters/inQueryProps' + - $ref: '#/components/parameters/inQueryLimit' + - $ref: '#/components/parameters/inQueryOffset' + - $ref: '#/components/parameters/inQueryMeta' + - $ref: '#/components/parameters/inQueryStats' + - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryFilter' + - $ref: '#/components/parameters/inQueryGroupby' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/PackageListResponse' + 401: + $ref: '#/components/responses/401' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /packages/diff: + get: + operationId: GetPackagesDiff + description: | + List the differences in installed packages between nodes: the package + versions installed on some of the compared nodes but not on all of them, + one row per node having it. The nodes compared are the given nodes, plus + the nodes running the given services, or with `encap` the encapsulated + nodes of those services (the nodes named after their instances' + `mon_vmname`). Only the nodes and services of the apps the user's groups + are responsible for are compared, unless the user is a manager. + Fewer than two nodes is a 400, except with `encap`, which then returns an + empty list. + parameters: + - in: query + name: node_ids + description: A comma-separated list of node ids to compare + schema: + type: string + - in: query + name: svc_ids + description: A comma-separated list of service ids whose nodes to compare + schema: + type: string + - in: query + name: encap + description: With svc_ids, compare the services' encapsulated nodes instead of their hosts + schema: + type: boolean + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/PackagesDiffResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + /services: get: operationId: GetServices @@ -9159,6 +9241,115 @@ components: type: string nullable: true + PackageRow: + type: object + description: | + A package installed on a node, as the agent reports it. Every property is + optional: the `props` query parameter selects which columns the server + returns. `sig_provider` names the provider of the signing key and is empty + when the signature is unknown. The `nodes.` properties come from the joined + nodes table. + properties: + id: + type: integer + node_id: + type: string + pkg_name: + type: string + pkg_version: + type: string + pkg_arch: + type: string + pkg_type: + type: string + nullable: true + pkg_sig: + type: string + nullable: true + sig_provider: + type: string + nullable: true + pkg_install_date: + type: string + nullable: true + pkg_updated: + type: string + nodes.nodename: + type: string + nullable: true + nodes.app: + type: string + nullable: true + nodes.os_name: + type: string + nullable: true + + PackageListResponse: + type: object + required: + - data + properties: + data: + oneOf: + - type: array + items: + $ref: '#/components/schemas/PackageRow' + - type: object + additionalProperties: + type: object + additionalProperties: + type: integer + meta: + $ref: '#/components/schemas/ListMeta' + + PackageDiffRow: + type: object + description: A package version installed on a compared node, and missing from at least one other. + required: [node_id, pkg_name, pkg_version, pkg_arch, pkg_type] + properties: + node_id: + type: string + pkg_name: + type: string + pkg_version: + type: string + pkg_arch: + type: string + pkg_type: + type: string + + PackageDiffNode: + type: object + required: [node_id, nodename] + properties: + node_id: + type: string + nodename: + type: string + + PackagesDiffResponse: + type: object + required: [data, meta] + properties: + data: + type: array + items: + $ref: '#/components/schemas/PackageDiffRow' + meta: + type: object + required: [node_ids, nodes] + properties: + node_ids: + description: The ids of the compared nodes, as the historical API returns them. + type: array + items: + type: string + nodes: + description: The compared nodes with their names, ordered by name. + type: array + items: + $ref: '#/components/schemas/PackageDiffNode' + InstanceListResponse: type: object required: diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index 6f276ded..f0595f6e 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -495,6 +495,12 @@ type ServerInterface interface { // (GET /openapi.json) GetSwagger(ctx echo.Context) error + // (GET /packages) + GetPackages(ctx echo.Context, params GetPackagesParams) error + + // (GET /packages/diff) + GetPackagesDiff(ctx echo.Context, params GetPackagesDiffParams) error + // (DELETE /services) DeleteServices(ctx echo.Context) error @@ -7124,6 +7130,113 @@ func (w *ServerInterfaceWrapper) GetSwagger(ctx echo.Context) error { return err } +// GetPackages converts echo context to params. +func (w *ServerInterfaceWrapper) GetPackages(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetPackagesParams + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // ------------- Optional query parameter "limit" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) + } + + // ------------- Optional query parameter "offset" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) + } + + // ------------- Optional query parameter "meta" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) + } + + // ------------- Optional query parameter "stats" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) + } + + // ------------- Optional query parameter "orderby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) + } + + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + + // ------------- Optional query parameter "groupby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetPackages(ctx, params) + return err +} + +// GetPackagesDiff converts echo context to params. +func (w *ServerInterfaceWrapper) GetPackagesDiff(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetPackagesDiffParams + // ------------- Optional query parameter "node_ids" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "node_ids", ctx.QueryParams(), ¶ms.NodeIds, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter node_ids: %s", err)) + } + + // ------------- Optional query parameter "svc_ids" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "svc_ids", ctx.QueryParams(), ¶ms.SvcIds, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter svc_ids: %s", err)) + } + + // ------------- Optional query parameter "encap" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "encap", ctx.QueryParams(), ¶ms.Encap, runtime.BindQueryParameterOptions{Type: "boolean", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter encap: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetPackagesDiff(ctx, params) + return err +} + // DeleteServices converts echo context to params. func (w *ServerInterfaceWrapper) DeleteServices(ctx echo.Context) error { var err error @@ -10180,6 +10293,8 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.GET(options.BaseURL+"/obsolescence/settings/:id", wrapper.GetObsolescenceSetting, options.OperationMiddlewares["GetObsolescenceSetting"]...) router.POST(options.BaseURL+"/obsolescence/settings/:id", wrapper.PostObsolescenceSetting, options.OperationMiddlewares["PostObsolescenceSetting"]...) router.GET(options.BaseURL+"/openapi.json", wrapper.GetSwagger, options.OperationMiddlewares["GetSwagger"]...) + router.GET(options.BaseURL+"/packages", wrapper.GetPackages, options.OperationMiddlewares["GetPackages"]...) + router.GET(options.BaseURL+"/packages/diff", wrapper.GetPackagesDiff, options.OperationMiddlewares["GetPackagesDiff"]...) router.DELETE(options.BaseURL+"/services", wrapper.DeleteServices, options.OperationMiddlewares["DeleteServices"]...) router.GET(options.BaseURL+"/services", wrapper.GetServices, options.OperationMiddlewares["GetServices"]...) router.POST(options.BaseURL+"/services", wrapper.PostServices, options.OperationMiddlewares["PostServices"]...) @@ -10248,309 +10363,325 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "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", - "4HQwOhl8/fT1/w8AAP//", + "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", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index 6fca09fb..94fbfbc0 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -1018,6 +1018,71 @@ type ObsolescenceSettingRow struct { // ObsolescenceSettingRowObsType defines model for ObsolescenceSettingRow.ObsType. type ObsolescenceSettingRowObsType string +// PackageDiffNode defines model for PackageDiffNode. +type PackageDiffNode struct { + NodeId string `json:"node_id"` + Nodename string `json:"nodename"` +} + +// PackageDiffRow A package version installed on a compared node, and missing from at least one other. +type PackageDiffRow struct { + NodeId string `json:"node_id"` + PkgArch string `json:"pkg_arch"` + PkgName string `json:"pkg_name"` + PkgType string `json:"pkg_type"` + PkgVersion string `json:"pkg_version"` +} + +// PackageListResponse defines model for PackageListResponse. +type PackageListResponse struct { + Data PackageListResponse_Data `json:"data"` + Meta *ListMeta `json:"meta,omitempty"` +} + +// PackageListResponseData0 defines model for . +type PackageListResponseData0 = []PackageRow + +// PackageListResponseData1 defines model for . +type PackageListResponseData1 map[string]map[string]int + +// PackageListResponse_Data defines model for PackageListResponse.Data. +type PackageListResponse_Data struct { + union json.RawMessage +} + +// PackageRow A package installed on a node, as the agent reports it. Every property is +// optional: the `props` query parameter selects which columns the server +// returns. `sig_provider` names the provider of the signing key and is empty +// when the signature is unknown. The `nodes.` properties come from the joined +// nodes table. +type PackageRow struct { + Id *int `json:"id,omitempty"` + NodeId *string `json:"node_id,omitempty"` + NodesApp *string `json:"nodes.app,omitempty"` + NodesNodename *string `json:"nodes.nodename,omitempty"` + NodesOsName *string `json:"nodes.os_name,omitempty"` + PkgArch *string `json:"pkg_arch,omitempty"` + PkgInstallDate *string `json:"pkg_install_date,omitempty"` + PkgName *string `json:"pkg_name,omitempty"` + PkgSig *string `json:"pkg_sig,omitempty"` + PkgType *string `json:"pkg_type,omitempty"` + PkgUpdated *string `json:"pkg_updated,omitempty"` + PkgVersion *string `json:"pkg_version,omitempty"` + SigProvider *string `json:"sig_provider,omitempty"` +} + +// PackagesDiffResponse defines model for PackagesDiffResponse. +type PackagesDiffResponse struct { + Data []PackageDiffRow `json:"data"` + Meta struct { + // NodeIds The ids of the compared nodes, as the historical API returns them. + NodeIds []string `json:"node_ids"` + + // Nodes The compared nodes with their names, ordered by name. + Nodes []PackageDiffNode `json:"nodes"` + } `json:"meta"` +} + // Problem defines model for Problem. type Problem struct { // Text A human-readable explanation specific to this occurrence of the @@ -3837,6 +3902,58 @@ type PostObsolescenceSettingJSONBody struct { ObsWarnDate *string `json:"obs_warn_date,omitempty"` } +// GetPackagesParams defines parameters for GetPackages. +type GetPackagesParams struct { + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` + + // Limit The maximum number of entries to return. 0 means no limit. + Limit *InQueryLimit `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Skip the first entries of the data cursor. + Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` + + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. + Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` + + // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. + Stats *InQueryStats `form:"stats,omitempty" json:"stats,omitempty"` + + // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). + Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` + + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). + Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` +} + +// GetPackagesDiffParams defines parameters for GetPackagesDiff. +type GetPackagesDiffParams struct { + // NodeIds A comma-separated list of node ids to compare + NodeIds *string `form:"node_ids,omitempty" json:"node_ids,omitempty"` + + // SvcIds A comma-separated list of service ids whose nodes to compare + SvcIds *string `form:"svc_ids,omitempty" json:"svc_ids,omitempty"` + + // Encap With svc_ids, compare the services' encapsulated nodes instead of their hosts + Encap *bool `form:"encap,omitempty" json:"encap,omitempty"` +} + // DeleteServicesJSONBody defines parameters for DeleteServices. type DeleteServicesJSONBody struct { // SvcId Service id or name @@ -6118,6 +6235,68 @@ func (t *ObsolescenceSettingListResponse_Data) UnmarshalJSON(b []byte) error { return err } +// AsPackageListResponseData0 returns the union data inside the PackageListResponse_Data as a PackageListResponseData0 +func (t PackageListResponse_Data) AsPackageListResponseData0() (PackageListResponseData0, error) { + var body PackageListResponseData0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromPackageListResponseData0 overwrites any union data inside the PackageListResponse_Data as the provided PackageListResponseData0 +func (t *PackageListResponse_Data) FromPackageListResponseData0(v PackageListResponseData0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergePackageListResponseData0 performs a merge with any union data inside the PackageListResponse_Data, using the provided PackageListResponseData0 +func (t *PackageListResponse_Data) MergePackageListResponseData0(v PackageListResponseData0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsPackageListResponseData1 returns the union data inside the PackageListResponse_Data as a PackageListResponseData1 +func (t PackageListResponse_Data) AsPackageListResponseData1() (PackageListResponseData1, error) { + var body PackageListResponseData1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromPackageListResponseData1 overwrites any union data inside the PackageListResponse_Data as the provided PackageListResponseData1 +func (t *PackageListResponse_Data) FromPackageListResponseData1(v PackageListResponseData1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergePackageListResponseData1 performs a merge with any union data inside the PackageListResponse_Data, using the provided PackageListResponseData1 +func (t *PackageListResponse_Data) MergePackageListResponseData1(v PackageListResponseData1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t PackageListResponse_Data) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *PackageListResponse_Data) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + // AsServiceListResponseData0 returns the union data inside the ServiceListResponse_Data as a ServiceListResponseData0 func (t ServiceListResponse_Data) AsServiceListResponseData0() (ServiceListResponseData0, error) { var body ServiceListResponseData0 diff --git a/server/handlers/get_packages.go b/server/handlers/get_packages.go new file mode 100644 index 00000000..2443491f --- /dev/null +++ b/server/handlers/get_packages.go @@ -0,0 +1,22 @@ +package serverhandlers + +import ( + "context" + + "github.com/labstack/echo/v4" + + "github.com/opensvc/oc3/cdb" + "github.com/opensvc/oc3/server" +) + +// GetPackages handles GET /packages +func (a *Api) GetPackages(c echo.Context, params server.GetPackagesParams) error { + odb := a.ODB + return a.handleList(c, "GetPackages", "package", listEndpointParams{ + props: params.Props, limit: params.Limit, offset: params.Offset, + meta: params.Meta, stats: params.Stats, orderby: params.Orderby, groupby: params.Groupby, + filter: params.Filter, + }, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return odb.GetPackages(ctx, p) + }) +} diff --git a/server/handlers/get_packages_diff.go b/server/handlers/get_packages_diff.go new file mode 100644 index 00000000..89e4cc2a --- /dev/null +++ b/server/handlers/get_packages_diff.go @@ -0,0 +1,72 @@ +package serverhandlers + +import ( + "context" + "net/http" + "strings" + + "github.com/labstack/echo/v4" + + "github.com/opensvc/oc3/server" + "github.com/opensvc/oc3/util/echolog" + "github.com/opensvc/oc3/util/logkey" +) + +// splitIDs reads a comma-separated list of ids, blanks dropped. +func splitIDs(s *string) []string { + if s == nil { + return nil + } + var ids []string + for _, id := range strings.Split(*s, ",") { + if id = strings.TrimSpace(id); id != "" { + ids = append(ids, id) + } + } + return ids +} + +// GetPackagesDiff handles GET /packages/diff, as the historical +// rest_get_packages_diff: the package versions installed on some of the compared +// nodes but not on all of them. +func (a *Api) GetPackagesDiff(c echo.Context, params server.GetPackagesDiffParams) error { + log := echolog.GetLogHandler(c, "GetPackagesDiff") + ctx, cancel := context.WithTimeout(c.Request().Context(), a.SyncTimeout) + defer cancel() + + encap := params.Encap != nil && *params.Encap + nodes, err := a.ODB.PackagesDiffNodes(ctx, splitIDs(params.NodeIds), splitIDs(params.SvcIds), encap, + UserGroupsFromContext(c), IsManager(c)) + if err != nil { + log.Error("cannot resolve the nodes to compare", logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot resolve the nodes to compare") + } + // With encap, a service without encapsulated nodes has nothing to compare: an + // empty answer rather than an error, as the historical API. + if len(nodes) < 2 && !encap { + return JSONProblemf(c, http.StatusBadRequest, "At least two nodes should be selected") + } + + nodeIDs := make([]string, len(nodes)) + resultNodes := make([]server.PackageDiffNode, len(nodes)) + for i, n := range nodes { + nodeIDs[i] = n.NodeID + resultNodes[i] = server.PackageDiffNode{NodeId: n.NodeID, Nodename: n.Nodename} + } + rows, err := a.ODB.PackagesDiff(ctx, nodeIDs) + if err != nil { + log.Error("cannot compare packages", logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot compare packages") + } + data := make([]server.PackageDiffRow, len(rows)) + for i, r := range rows { + data[i] = server.PackageDiffRow{ + NodeId: r.NodeID, PkgName: r.PkgName, PkgVersion: r.PkgVersion, + PkgArch: r.PkgArch, PkgType: r.PkgType, + } + } + resp := server.PackagesDiffResponse{Data: data} + resp.Meta.NodeIds = nodeIDs + resp.Meta.Nodes = resultNodes + return c.JSON(http.StatusOK, resp) +} diff --git a/server/handlers/props_mapping.go b/server/handlers/props_mapping.go index 04eae65a..052098d1 100644 --- a/server/handlers/props_mapping.go +++ b/server/handlers/props_mapping.go @@ -634,6 +634,39 @@ var propsMapping = map[string]propMapping{ "services": {MappingKey: "service"}, }, }, + // Packages installed on the nodes, as the historical packages table lists them. + // sig_provider names the provider of the signing key, from pkg_sig_provider; + // it is empty when the signature is unknown. + "package": { + Available: []string{ + "id", "node_id", + "pkg_name", "pkg_version", "pkg_arch", "pkg_type", + "pkg_sig", "sig_provider", + "pkg_install_date", "pkg_updated", + }, + Default: []string{ + "id", "node_id", + "pkg_name", "pkg_version", "pkg_arch", "pkg_type", + "sig_provider", "pkg_install_date", "pkg_updated", + }, + Props: map[string]propDef{ + "id": col(schema.PackagesID), + "node_id": colStr(schema.PackagesNodeID), + "pkg_name": colStr(schema.PackagesPkgName), + "pkg_version": colStr(schema.PackagesPkgVersion), + "pkg_arch": colStr(schema.PackagesPkgArch), + "pkg_type": colStr(schema.PackagesPkgType), + "pkg_sig": colStr(schema.PackagesPkgSig), + "sig_provider": colStr(schema.PkgSigProviderSigProvider), + "pkg_install_date": colStr(schema.PackagesPkgInstallDate), + "pkg_updated": colStr(schema.PackagesPkgUpdated), + }, + // A package row carries only the node id: its name and properties live in + // the joined nodes table. + Joins: map[string]JoinDef{ + "nodes": {MappingKey: "node"}, + }, + }, "instance_status_log": { Available: []string{ "id", From 25f4f6fad2ed3691a734e64ef1c5e8166e58882a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Mon, 28 Sep 2026 11:13:52 +0200 Subject: [PATCH 31/61] Type the node compliance list responses GET /nodes/{node_id}/compliance/status, /modulesets and /rulesets answered with the generic ListResponse, whose rows are untyped. Describe their rows (ComplianceStatusRow, ModulesetRow, RulesetRow) and list responses in the spec; the JSON the handlers return is unchanged. --- server/api.yaml | 113 +++++- server/codegen_server_gen.go | 642 ++++++++++++++++++----------------- server/codegen_type_gen.go | 269 +++++++++++++++ 3 files changed, 702 insertions(+), 322 deletions(-) diff --git a/server/api.yaml b/server/api.yaml index 645253ff..998ff30c 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -5455,7 +5455,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/ModulesetListResponse' 404: description: Node not found 500: @@ -5536,7 +5536,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/RulesetListResponse' 404: description: Node not found 500: @@ -5617,7 +5617,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/ComplianceStatusListResponse' 404: description: Node not found 500: @@ -9350,6 +9350,113 @@ components: items: $ref: '#/components/schemas/PackageDiffNode' + ComplianceStatusRow: + type: object + description: | + The last run of a compliance module on a node, or on a service's instance + on it. Every property is optional: the `props` query parameter selects which + columns the server returns. `run_status` is the module's exit code: 0 ok, + 1 not ok, 2 not applicable. + properties: + id: + type: integer + run_module: + type: string + node_id: + type: string + svc_id: + type: string + run_status: + type: integer + run_log: + type: string + run_date: + type: string + run_action: + type: string + rset_md5: + type: string + + ComplianceStatusListResponse: + type: object + required: + - data + properties: + data: + oneOf: + - type: array + items: + $ref: '#/components/schemas/ComplianceStatusRow' + - type: object + additionalProperties: + type: object + additionalProperties: + type: integer + meta: + $ref: '#/components/schemas/ListMeta' + + ModulesetRow: + type: object + description: A compliance moduleset. Every property is optional, as selected by `props`. + properties: + id: + type: integer + modset_name: + type: string + modset_author: + type: string + modset_updated: + type: string + + ModulesetListResponse: + type: object + required: + - data + properties: + data: + oneOf: + - type: array + items: + $ref: '#/components/schemas/ModulesetRow' + - type: object + additionalProperties: + type: object + additionalProperties: + type: integer + meta: + $ref: '#/components/schemas/ListMeta' + + RulesetRow: + type: object + description: A compliance ruleset. Every property is optional, as selected by `props`. + properties: + id: + type: integer + ruleset_name: + type: string + ruleset_type: + type: string + ruleset_public: + type: string + + RulesetListResponse: + type: object + required: + - data + properties: + data: + oneOf: + - type: array + items: + $ref: '#/components/schemas/RulesetRow' + - type: object + additionalProperties: + type: object + additionalProperties: + type: integer + meta: + $ref: '#/components/schemas/ListMeta' + InstanceListResponse: type: object required: diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index f0595f6e..57792b76 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -10363,325 +10363,329 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "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", + "lTIbnA9GZ4MvH7/8/wEAAP//", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index 94fbfbc0..6b48b20e 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -354,6 +354,39 @@ type AppRow struct { Updated *string `json:"updated,omitempty"` } +// ComplianceStatusListResponse defines model for ComplianceStatusListResponse. +type ComplianceStatusListResponse struct { + Data ComplianceStatusListResponse_Data `json:"data"` + Meta *ListMeta `json:"meta,omitempty"` +} + +// ComplianceStatusListResponseData0 defines model for . +type ComplianceStatusListResponseData0 = []ComplianceStatusRow + +// ComplianceStatusListResponseData1 defines model for . +type ComplianceStatusListResponseData1 map[string]map[string]int + +// ComplianceStatusListResponse_Data defines model for ComplianceStatusListResponse.Data. +type ComplianceStatusListResponse_Data struct { + union json.RawMessage +} + +// ComplianceStatusRow The last run of a compliance module on a node, or on a service's instance +// on it. Every property is optional: the `props` query parameter selects which +// columns the server returns. `run_status` is the module's exit code: 0 ok, +// 1 not ok, 2 not applicable. +type ComplianceStatusRow struct { + Id *int `json:"id,omitempty"` + NodeId *string `json:"node_id,omitempty"` + RsetMd5 *string `json:"rset_md5,omitempty"` + RunAction *string `json:"run_action,omitempty"` + RunDate *string `json:"run_date,omitempty"` + RunLog *string `json:"run_log,omitempty"` + RunModule *string `json:"run_module,omitempty"` + RunStatus *int `json:"run_status,omitempty"` + SvcId *string `json:"svc_id,omitempty"` +} + // DiskListResponse defines model for DiskListResponse. type DiskListResponse struct { Data DiskListResponse_Data `json:"data"` @@ -820,6 +853,31 @@ type LogRow struct { SvcId *string `json:"svc_id,omitempty"` } +// ModulesetListResponse defines model for ModulesetListResponse. +type ModulesetListResponse struct { + Data ModulesetListResponse_Data `json:"data"` + Meta *ListMeta `json:"meta,omitempty"` +} + +// ModulesetListResponseData0 defines model for . +type ModulesetListResponseData0 = []ModulesetRow + +// ModulesetListResponseData1 defines model for . +type ModulesetListResponseData1 map[string]map[string]int + +// ModulesetListResponse_Data defines model for ModulesetListResponse.Data. +type ModulesetListResponse_Data struct { + union json.RawMessage +} + +// ModulesetRow A compliance moduleset. Every property is optional, as selected by `props`. +type ModulesetRow struct { + Id *int `json:"id,omitempty"` + ModsetAuthor *string `json:"modset_author,omitempty"` + ModsetName *string `json:"modset_name,omitempty"` + ModsetUpdated *string `json:"modset_updated,omitempty"` +} + // NetworkListResponse defines model for NetworkListResponse. type NetworkListResponse struct { Data []NetworkRow `json:"data"` @@ -1090,6 +1148,31 @@ type Problem struct { Text string `json:"text"` } +// RulesetListResponse defines model for RulesetListResponse. +type RulesetListResponse struct { + Data RulesetListResponse_Data `json:"data"` + Meta *ListMeta `json:"meta,omitempty"` +} + +// RulesetListResponseData0 defines model for . +type RulesetListResponseData0 = []RulesetRow + +// RulesetListResponseData1 defines model for . +type RulesetListResponseData1 map[string]map[string]int + +// RulesetListResponse_Data defines model for RulesetListResponse.Data. +type RulesetListResponse_Data struct { + union json.RawMessage +} + +// RulesetRow A compliance ruleset. Every property is optional, as selected by `props`. +type RulesetRow struct { + Id *int `json:"id,omitempty"` + RulesetName *string `json:"ruleset_name,omitempty"` + RulesetPublic *string `json:"ruleset_public,omitempty"` + RulesetType *string `json:"ruleset_type,omitempty"` +} + // ServiceListResponse defines model for ServiceListResponse. type ServiceListResponse struct { Data ServiceListResponse_Data `json:"data"` @@ -5367,6 +5450,68 @@ func (t *AppListResponse_Data) UnmarshalJSON(b []byte) error { return err } +// AsComplianceStatusListResponseData0 returns the union data inside the ComplianceStatusListResponse_Data as a ComplianceStatusListResponseData0 +func (t ComplianceStatusListResponse_Data) AsComplianceStatusListResponseData0() (ComplianceStatusListResponseData0, error) { + var body ComplianceStatusListResponseData0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromComplianceStatusListResponseData0 overwrites any union data inside the ComplianceStatusListResponse_Data as the provided ComplianceStatusListResponseData0 +func (t *ComplianceStatusListResponse_Data) FromComplianceStatusListResponseData0(v ComplianceStatusListResponseData0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeComplianceStatusListResponseData0 performs a merge with any union data inside the ComplianceStatusListResponse_Data, using the provided ComplianceStatusListResponseData0 +func (t *ComplianceStatusListResponse_Data) MergeComplianceStatusListResponseData0(v ComplianceStatusListResponseData0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsComplianceStatusListResponseData1 returns the union data inside the ComplianceStatusListResponse_Data as a ComplianceStatusListResponseData1 +func (t ComplianceStatusListResponse_Data) AsComplianceStatusListResponseData1() (ComplianceStatusListResponseData1, error) { + var body ComplianceStatusListResponseData1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromComplianceStatusListResponseData1 overwrites any union data inside the ComplianceStatusListResponse_Data as the provided ComplianceStatusListResponseData1 +func (t *ComplianceStatusListResponse_Data) FromComplianceStatusListResponseData1(v ComplianceStatusListResponseData1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeComplianceStatusListResponseData1 performs a merge with any union data inside the ComplianceStatusListResponse_Data, using the provided ComplianceStatusListResponseData1 +func (t *ComplianceStatusListResponse_Data) MergeComplianceStatusListResponseData1(v ComplianceStatusListResponseData1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t ComplianceStatusListResponse_Data) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *ComplianceStatusListResponse_Data) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + // AsDiskListResponseData0 returns the union data inside the DiskListResponse_Data as a DiskListResponseData0 func (t DiskListResponse_Data) AsDiskListResponseData0() (DiskListResponseData0, error) { var body DiskListResponseData0 @@ -6049,6 +6194,68 @@ func (t *LogListResponse_Data) UnmarshalJSON(b []byte) error { return err } +// AsModulesetListResponseData0 returns the union data inside the ModulesetListResponse_Data as a ModulesetListResponseData0 +func (t ModulesetListResponse_Data) AsModulesetListResponseData0() (ModulesetListResponseData0, error) { + var body ModulesetListResponseData0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromModulesetListResponseData0 overwrites any union data inside the ModulesetListResponse_Data as the provided ModulesetListResponseData0 +func (t *ModulesetListResponse_Data) FromModulesetListResponseData0(v ModulesetListResponseData0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeModulesetListResponseData0 performs a merge with any union data inside the ModulesetListResponse_Data, using the provided ModulesetListResponseData0 +func (t *ModulesetListResponse_Data) MergeModulesetListResponseData0(v ModulesetListResponseData0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsModulesetListResponseData1 returns the union data inside the ModulesetListResponse_Data as a ModulesetListResponseData1 +func (t ModulesetListResponse_Data) AsModulesetListResponseData1() (ModulesetListResponseData1, error) { + var body ModulesetListResponseData1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromModulesetListResponseData1 overwrites any union data inside the ModulesetListResponse_Data as the provided ModulesetListResponseData1 +func (t *ModulesetListResponse_Data) FromModulesetListResponseData1(v ModulesetListResponseData1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeModulesetListResponseData1 performs a merge with any union data inside the ModulesetListResponse_Data, using the provided ModulesetListResponseData1 +func (t *ModulesetListResponse_Data) MergeModulesetListResponseData1(v ModulesetListResponseData1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t ModulesetListResponse_Data) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *ModulesetListResponse_Data) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + // AsNodeHardwareListResponseData0 returns the union data inside the NodeHardwareListResponse_Data as a NodeHardwareListResponseData0 func (t NodeHardwareListResponse_Data) AsNodeHardwareListResponseData0() (NodeHardwareListResponseData0, error) { var body NodeHardwareListResponseData0 @@ -6297,6 +6504,68 @@ func (t *PackageListResponse_Data) UnmarshalJSON(b []byte) error { return err } +// AsRulesetListResponseData0 returns the union data inside the RulesetListResponse_Data as a RulesetListResponseData0 +func (t RulesetListResponse_Data) AsRulesetListResponseData0() (RulesetListResponseData0, error) { + var body RulesetListResponseData0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromRulesetListResponseData0 overwrites any union data inside the RulesetListResponse_Data as the provided RulesetListResponseData0 +func (t *RulesetListResponse_Data) FromRulesetListResponseData0(v RulesetListResponseData0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeRulesetListResponseData0 performs a merge with any union data inside the RulesetListResponse_Data, using the provided RulesetListResponseData0 +func (t *RulesetListResponse_Data) MergeRulesetListResponseData0(v RulesetListResponseData0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsRulesetListResponseData1 returns the union data inside the RulesetListResponse_Data as a RulesetListResponseData1 +func (t RulesetListResponse_Data) AsRulesetListResponseData1() (RulesetListResponseData1, error) { + var body RulesetListResponseData1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromRulesetListResponseData1 overwrites any union data inside the RulesetListResponse_Data as the provided RulesetListResponseData1 +func (t *RulesetListResponse_Data) FromRulesetListResponseData1(v RulesetListResponseData1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeRulesetListResponseData1 performs a merge with any union data inside the RulesetListResponse_Data, using the provided RulesetListResponseData1 +func (t *RulesetListResponse_Data) MergeRulesetListResponseData1(v RulesetListResponseData1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t RulesetListResponse_Data) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *RulesetListResponse_Data) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + // AsServiceListResponseData0 returns the union data inside the ServiceListResponse_Data as a ServiceListResponseData0 func (t ServiceListResponse_Data) AsServiceListResponseData0() (ServiceListResponseData0, error) { var body ServiceListResponseData0 From 05360801a03d2955abf4c329cec1ffe41295d9b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Mon, 28 Sep 2026 11:27:46 +0200 Subject: [PATCH 32/61] Filter and join nodes in GET /nodes/hardware The nodes hardware list takes the filter parameter, and left-joins the nodes table (node_hw.node_id reference) so that its rows can carry and be sorted on nodes.nodename, nodes.app and nodes.os_name; a component of an unknown node is kept. The response is typed as NodeHardwareListResponse instead of the generic ListResponse, and NodeHardwareRow describes the joined properties. --- cdb/db_node_hardware.go | 10 +- schema/relations.go | 1 + server/api.yaml | 21 +- server/codegen_server_gen.go | 651 +++++++++++++------------- server/codegen_type_gen.go | 19 +- server/handlers/get_nodes_hardware.go | 1 + server/handlers/props_mapping.go | 5 + 7 files changed, 380 insertions(+), 328 deletions(-) diff --git a/cdb/db_node_hardware.go b/cdb/db_node_hardware.go index fe50fb90..32e730f6 100644 --- a/cdb/db_node_hardware.go +++ b/cdb/db_node_hardware.go @@ -7,8 +7,11 @@ import ( "github.com/opensvc/oc3/schema" ) -func buildNodeHardwareQuery(groups []string, isManager bool, selectExprs []string) (string, []any, error) { +func buildNodeHardwareQuery(groups []string, isManager bool, selectExprs []string, filters []ColumnFilter) (string, []any, error) { + // nodes is a left join, for the nodes. props: a component of an unknown node + // is kept, as before the join. q := From(schema.TNodeHW). + LeftJoin(schema.TNodes). RawSelect(selectExprs...) if !isManager { @@ -35,6 +38,9 @@ func buildNodeHardwareQuery(groups []string, isManager bool, selectExprs []strin q = q.Where(schema.NodeHWID, ">", 0) } + // Column filters of the request, ANDed with the access control above. + q = q.WhereFilters(filters) + query, args, err := q.Build() if err != nil { return "", nil, fmt.Errorf("buildNodeHardwareQuery: %w", err) @@ -43,7 +49,7 @@ func buildNodeHardwareQuery(groups []string, isManager bool, selectExprs []strin } func (oDb *DB) queryHardware(ctx context.Context, nodeID string, defaultOrderBy string, p ListParams) ([]map[string]any, error) { - query, args, err := buildNodeHardwareQuery(p.Groups, p.IsManager, p.SelectExprs) + query, args, err := buildNodeHardwareQuery(p.Groups, p.IsManager, p.SelectExprs, p.Filters) if err != nil { return nil, err } diff --git a/schema/relations.go b/schema/relations.go index 92f1314a..fb2e01ef 100644 --- a/schema/relations.go +++ b/schema/relations.go @@ -20,6 +20,7 @@ func init() { ActionQueueSvcID.Ref = ServicesSvcID PackagesNodeID.Ref = NodesNodeID + NodeHWNodeID.Ref = NodesNodeID PackagesPkgSig.Ref = PkgSigProviderSigID SvcmonSvcID.Ref = ServicesSvcID diff --git a/server/api.yaml b/server/api.yaml index 998ff30c..41789d52 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -4933,7 +4933,9 @@ paths: /nodes/hardware: get: operationId: GetNodesHardware - description: List all nodes PCI and memory hardware + description: | + List the PCI and memory hardware of the nodes the user can see, as their + agents report it. The `nodes.` properties come from the joined nodes table. parameters: - $ref: '#/components/parameters/inQueryProps' - $ref: '#/components/parameters/inQueryLimit' @@ -4941,6 +4943,7 @@ paths: - $ref: '#/components/parameters/inQueryMeta' - $ref: '#/components/parameters/inQueryStats' - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryFilter' - $ref: '#/components/parameters/inQueryGroupby' tags: - collector @@ -4950,7 +4953,9 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListResponse' + $ref: '#/components/schemas/NodeHardwareListResponse' + 401: + $ref: '#/components/responses/401' 500: $ref: '#/components/responses/500' security: @@ -9878,7 +9883,8 @@ components: A hardware component of a node, as reported by the agent's asset push: `hw_type` is the component family (for example `pci` or `mem`), `hw_path` its address. Every property is optional: the `props` query parameter selects which - columns the server returns. + columns the server returns. The `nodes.` properties come from the joined nodes + table, null for a component of an unknown node. properties: id: type: integer @@ -9896,6 +9902,15 @@ components: type: string updated: type: string + nodes.nodename: + type: string + nullable: true + nodes.app: + type: string + nullable: true + nodes.os_name: + type: string + nullable: true NodeHardwareListResponse: type: object diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index 57792b76..f9780c1c 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -5333,6 +5333,13 @@ func (w *ServerInterfaceWrapper) GetNodesHardware(ctx echo.Context) error { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + // ------------- Optional query parameter "groupby" ------------- err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) @@ -10363,329 +10370,329 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "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", - "lTIbnA9GZ4MvH7/8/wEAAP//", + "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", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index 6b48b20e..01bec71c 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -922,7 +922,8 @@ type NodeHardwareListResponse_Data struct { // NodeHardwareRow A hardware component of a node, as reported by the agent's asset push: // `hw_type` is the component family (for example `pci` or `mem`), `hw_path` its // address. Every property is optional: the `props` query parameter selects which -// columns the server returns. +// columns the server returns. The `nodes.` properties come from the joined nodes +// table, null for a component of an unknown node. type NodeHardwareRow struct { HwClass *string `json:"hw_class,omitempty"` HwDescription *string `json:"hw_description,omitempty"` @@ -931,6 +932,9 @@ type NodeHardwareRow struct { HwType *string `json:"hw_type,omitempty"` Id *int `json:"id,omitempty"` NodeId *string `json:"node_id,omitempty"` + NodesApp *string `json:"nodes.app,omitempty"` + NodesNodename *string `json:"nodes.nodename,omitempty"` + NodesOsName *string `json:"nodes.os_name,omitempty"` Updated *string `json:"updated,omitempty"` } @@ -3295,6 +3299,19 @@ type GetNodesHardwareParams struct { // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` } diff --git a/server/handlers/get_nodes_hardware.go b/server/handlers/get_nodes_hardware.go index 47a663fc..0df939e8 100644 --- a/server/handlers/get_nodes_hardware.go +++ b/server/handlers/get_nodes_hardware.go @@ -15,6 +15,7 @@ func (a *Api) GetNodesHardware(c echo.Context, params server.GetNodesHardwarePar return a.handleList(c, "GetNodesHardware", "node_hw", listEndpointParams{ props: params.Props, limit: params.Limit, offset: params.Offset, meta: params.Meta, stats: params.Stats, orderby: params.Orderby, groupby: params.Groupby, + filter: params.Filter, }, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { return odb.GetNodesHardware(ctx, p) }) diff --git a/server/handlers/props_mapping.go b/server/handlers/props_mapping.go index 052098d1..c1a56e4e 100644 --- a/server/handlers/props_mapping.go +++ b/server/handlers/props_mapping.go @@ -316,6 +316,11 @@ var propsMapping = map[string]propMapping{ "hw_driver": colStr(schema.NodeHWHWDriver), "updated": colStr(schema.NodeHWUpdated), }, + // A component carries only the node id: its name lives in the joined nodes + // table, as in the historical nodes hardware table. + Joins: map[string]JoinDef{ + "nodes": {MappingKey: "node"}, + }, }, "hba": { Available: []string{"id", "node_id", "hba_id", "hba_type", "updated"}, From 0c451065d8c2fd19a43faf3fe6b5effe1c2ef046 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Mon, 28 Sep 2026 11:40:31 +0200 Subject: [PATCH 33/61] Add the GET /workflows endpoint List the requests: the workflows started by the submission of a form with a workflow output, as the historical rest_get_workflows, to any authenticated user. The workflows query left-joins forms_revisions by form_md5, so that the workflow mapping also offers form_name, form_folder and form_yaml; they stay out of the default props, which keeps the /forms_store dump output unchanged. The list takes the filter parameter, and its response is typed (WorkflowRow, WorkflowListResponse). --- cdb/db_forms_store.go | 6 +- server/api.yaml | 99 +++++ server/codegen_server_gen.go | 727 +++++++++++++++++-------------- server/codegen_type_gen.go | 143 ++++++ server/handlers/get_workflows.go | 23 + server/handlers/props_mapping.go | 13 +- 6 files changed, 687 insertions(+), 324 deletions(-) create mode 100644 server/handlers/get_workflows.go diff --git a/cdb/db_forms_store.go b/cdb/db_forms_store.go index f322c3aa..8863f856 100644 --- a/cdb/db_forms_store.go +++ b/cdb/db_forms_store.go @@ -66,6 +66,10 @@ func (oDb *DB) GetFormsStore(ctx context.Context, storeID *int64, p ListParams) return oDb.listQuery(ctx, "getFormsStore", formsStoreFrom, conds, args, "forms_store.id", p) } +// workflowsFrom joins the form revision a workflow started from, for its name, +// folder and definition; a workflow whose revision is missing is still listed. +const workflowsFrom = "workflows LEFT JOIN forms_revisions ON forms_revisions.form_md5 = workflows.form_md5" + // GetWorkflows lists the workflows, one when id is set. func (oDb *DB) GetWorkflows(ctx context.Context, id *int64, p ListParams) ([]map[string]any, error) { conds := []string{"workflows.id > 0"} @@ -74,7 +78,7 @@ func (oDb *DB) GetWorkflows(ctx context.Context, id *int64, p ListParams) ([]map conds = append(conds, "workflows.id = ?") args = append(args, *id) } - return oDb.listQuery(ctx, "getWorkflows", "workflows", conds, args, "workflows.id", p) + return oDb.listQuery(ctx, "getWorkflows", workflowsFrom, conds, args, "workflows.id", p) } // WorkflowIDByHead returns the workflow started by a stored form. diff --git a/server/api.yaml b/server/api.yaml index 41789d52..42c75e05 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -8742,6 +8742,41 @@ paths: 500: $ref: '#/components/responses/500' + /workflows: + get: + operationId: GetWorkflows + description: | + List the requests: the workflows started by the submission of a form with a + workflow output. As the historical API, + every workflow is listed to any authenticated user. `form_name`, + `form_folder` and `form_yaml` are those of the form revision the request + started from. + parameters: + - $ref: '#/components/parameters/inQueryProps' + - $ref: '#/components/parameters/inQueryLimit' + - $ref: '#/components/parameters/inQueryOffset' + - $ref: '#/components/parameters/inQueryMeta' + - $ref: '#/components/parameters/inQueryStats' + - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryFilter' + - $ref: '#/components/parameters/inQueryGroupby' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/WorkflowListResponse' + 401: + $ref: '#/components/responses/401' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + components: responses: @@ -9462,6 +9497,70 @@ components: meta: $ref: '#/components/schemas/ListMeta' + WorkflowRow: + type: object + description: | + A request: the workflow started by the submission of a form with a workflow + output. `form_head_id` is the stored submission that started it, + `last_form_id` and `last_form_name` its latest step; `status` is `pending` + while a next step awaits `last_assignee`, `closed` otherwise. Every property + is optional: the `props` query parameter selects which columns the server + returns. `form_name`, `form_folder` and `form_yaml` come from the joined form + revision and are null when it is missing. + properties: + id: + type: integer + form_head_id: + type: integer + form_name: + type: string + nullable: true + last_form_id: + type: integer + nullable: true + last_form_name: + type: string + nullable: true + form_folder: + type: string + nullable: true + status: + type: string + steps: + type: integer + creator: + type: string + last_assignee: + type: string + create_date: + type: string + last_update: + type: string + form_md5: + type: string + nullable: true + form_yaml: + type: string + nullable: true + + WorkflowListResponse: + type: object + required: + - data + properties: + data: + oneOf: + - type: array + items: + $ref: '#/components/schemas/WorkflowRow' + - type: object + additionalProperties: + type: object + additionalProperties: + type: integer + meta: + $ref: '#/components/schemas/ListMeta' + InstanceListResponse: type: object required: diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index f9780c1c..b0c2176b 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -680,6 +680,9 @@ type ServerInterface interface { // (GET /version) GetVersion(ctx echo.Context) error + + // (GET /workflows) + GetWorkflows(ctx echo.Context, params GetWorkflowsParams) error } // ServerInterfaceWrapper converts echo contexts to parameters. @@ -10095,6 +10098,77 @@ func (w *ServerInterfaceWrapper) GetVersion(ctx echo.Context) error { return err } +// GetWorkflows converts echo context to params. +func (w *ServerInterfaceWrapper) GetWorkflows(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetWorkflowsParams + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // ------------- Optional query parameter "limit" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) + } + + // ------------- Optional query parameter "offset" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) + } + + // ------------- Optional query parameter "meta" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) + } + + // ------------- Optional query parameter "stats" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) + } + + // ------------- Optional query parameter "orderby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) + } + + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + + // ------------- Optional query parameter "groupby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetWorkflows(ctx, params) + return err +} + // This is a simple interface which specifies echo.Route addition functions which // are present on both echo.Echo and echo.Group, since we want to allow using // either of them for path registration @@ -10362,6 +10436,7 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.GET(options.BaseURL+"/users/:user_id/prefs", wrapper.GetUserPrefs, options.OperationMiddlewares["GetUserPrefs"]...) router.POST(options.BaseURL+"/users/:user_id/prefs", wrapper.PostUserPrefs, options.OperationMiddlewares["PostUserPrefs"]...) router.GET(options.BaseURL+"/version", wrapper.GetVersion, options.OperationMiddlewares["GetVersion"]...) + router.GET(options.BaseURL+"/workflows", wrapper.GetWorkflows, options.OperationMiddlewares["GetWorkflows"]...) } @@ -10370,329 +10445,337 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "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", + "8cv/HwAA//8=", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index 01bec71c..f6a9e718 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -1288,6 +1288,47 @@ type UserRow struct { Username *string `json:"username,omitempty"` } +// WorkflowListResponse defines model for WorkflowListResponse. +type WorkflowListResponse struct { + Data WorkflowListResponse_Data `json:"data"` + Meta *ListMeta `json:"meta,omitempty"` +} + +// WorkflowListResponseData0 defines model for . +type WorkflowListResponseData0 = []WorkflowRow + +// WorkflowListResponseData1 defines model for . +type WorkflowListResponseData1 map[string]map[string]int + +// WorkflowListResponse_Data defines model for WorkflowListResponse.Data. +type WorkflowListResponse_Data struct { + union json.RawMessage +} + +// WorkflowRow A request: the workflow started by the submission of a form with a workflow +// output. `form_head_id` is the stored submission that started it, +// `last_form_id` and `last_form_name` its latest step; `status` is `pending` +// while a next step awaits `last_assignee`, `closed` otherwise. Every property +// is optional: the `props` query parameter selects which columns the server +// returns. `form_name`, `form_folder` and `form_yaml` come from the joined form +// revision and are null when it is missing. +type WorkflowRow struct { + CreateDate *string `json:"create_date,omitempty"` + Creator *string `json:"creator,omitempty"` + FormFolder *string `json:"form_folder,omitempty"` + FormHeadId *int `json:"form_head_id,omitempty"` + FormMd5 *string `json:"form_md5,omitempty"` + FormName *string `json:"form_name,omitempty"` + FormYaml *string `json:"form_yaml,omitempty"` + Id *int `json:"id,omitempty"` + LastAssignee *string `json:"last_assignee,omitempty"` + LastFormId *int `json:"last_form_id,omitempty"` + LastFormName *string `json:"last_form_name,omitempty"` + LastUpdate *string `json:"last_update,omitempty"` + Status *string `json:"status,omitempty"` + Steps *int `json:"steps,omitempty"` +} + // Version defines model for version. type Version struct { Version string `json:"version"` @@ -5139,6 +5180,46 @@ type PostUserPrefsJSONBody struct { Uuid *string `json:"uuid,omitempty"` } +// GetWorkflowsParams defines parameters for GetWorkflows. +type GetWorkflowsParams struct { + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` + + // Limit The maximum number of entries to return. 0 means no limit. + Limit *InQueryLimit `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Skip the first entries of the data cursor. + Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` + + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. + Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` + + // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. + Stats *InQueryStats `form:"stats,omitempty" json:"stats,omitempty"` + + // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). + Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` + + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). + Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` +} + // PostActionsJSONRequestBody defines body for PostActions for application/json ContentType. type PostActionsJSONRequestBody PostActionsJSONBody @@ -6707,6 +6788,68 @@ func (t *UserListResponse_Data) UnmarshalJSON(b []byte) error { return err } +// AsWorkflowListResponseData0 returns the union data inside the WorkflowListResponse_Data as a WorkflowListResponseData0 +func (t WorkflowListResponse_Data) AsWorkflowListResponseData0() (WorkflowListResponseData0, error) { + var body WorkflowListResponseData0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromWorkflowListResponseData0 overwrites any union data inside the WorkflowListResponse_Data as the provided WorkflowListResponseData0 +func (t *WorkflowListResponse_Data) FromWorkflowListResponseData0(v WorkflowListResponseData0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeWorkflowListResponseData0 performs a merge with any union data inside the WorkflowListResponse_Data, using the provided WorkflowListResponseData0 +func (t *WorkflowListResponse_Data) MergeWorkflowListResponseData0(v WorkflowListResponseData0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsWorkflowListResponseData1 returns the union data inside the WorkflowListResponse_Data as a WorkflowListResponseData1 +func (t WorkflowListResponse_Data) AsWorkflowListResponseData1() (WorkflowListResponseData1, error) { + var body WorkflowListResponseData1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromWorkflowListResponseData1 overwrites any union data inside the WorkflowListResponse_Data as the provided WorkflowListResponseData1 +func (t *WorkflowListResponse_Data) FromWorkflowListResponseData1(v WorkflowListResponseData1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeWorkflowListResponseData1 performs a merge with any union data inside the WorkflowListResponse_Data, using the provided WorkflowListResponseData1 +func (t *WorkflowListResponse_Data) MergeWorkflowListResponseData1(v WorkflowListResponseData1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t WorkflowListResponse_Data) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *WorkflowListResponse_Data) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + // AsActionEnqueue returns the union data inside the PutActionsJSONBody as a ActionEnqueue func (t PutActionsJSONBody) AsActionEnqueue() (ActionEnqueue, error) { var body ActionEnqueue diff --git a/server/handlers/get_workflows.go b/server/handlers/get_workflows.go new file mode 100644 index 00000000..caf3962c --- /dev/null +++ b/server/handlers/get_workflows.go @@ -0,0 +1,23 @@ +package serverhandlers + +import ( + "context" + + "github.com/labstack/echo/v4" + + "github.com/opensvc/oc3/cdb" + "github.com/opensvc/oc3/server" +) + +// GetWorkflows handles GET /workflows, as the historical rest_get_workflows: +// every workflow is listed to any authenticated user. +func (a *Api) GetWorkflows(c echo.Context, params server.GetWorkflowsParams) error { + odb := a.ODB + return a.handleList(c, "GetWorkflows", "workflow", listEndpointParams{ + props: params.Props, limit: params.Limit, offset: params.Offset, + meta: params.Meta, stats: params.Stats, orderby: params.Orderby, groupby: params.Groupby, + filter: params.Filter, + }, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return odb.GetWorkflows(ctx, nil, p) + }) +} diff --git a/server/handlers/props_mapping.go b/server/handlers/props_mapping.go index c1a56e4e..f6bd5678 100644 --- a/server/handlers/props_mapping.go +++ b/server/handlers/props_mapping.go @@ -449,11 +449,19 @@ var propsMapping = map[string]propMapping{ "form_name": colStr(schema.FormsRevisionsFormName), }, }, - // Workflows chaining stored forms. + // Workflows chaining stored forms: the requests. form_name, form_folder and + // form_yaml are those of the form revision the request started from, joined + // by form_md5 as in the historical workflows table; they are not among the + // default props, which stay those of the workflows table (the /dump output). "workflow": { Available: []string{ "id", "form_head_id", "status", "steps", "creator", "create_date", "last_assignee", "last_update", "form_md5", "last_form_id", "last_form_name", + "form_name", "form_folder", "form_yaml", + }, + Default: []string{ + "id", "form_head_id", "status", "steps", "creator", "create_date", + "last_assignee", "last_update", "form_md5", "last_form_id", "last_form_name", }, Props: map[string]propDef{ "id": col(schema.WorkflowsID), @@ -467,6 +475,9 @@ var propsMapping = map[string]propMapping{ "form_md5": colStr(schema.WorkflowsFormMD5), "last_form_id": col(schema.WorkflowsLastFormID), "last_form_name": colStr(schema.WorkflowsLastFormName), + "form_name": colStr(schema.FormsRevisionsFormName), + "form_folder": colStr(schema.FormsRevisionsFormFolder), + "form_yaml": colStr(schema.FormsRevisionsFormYaml), }, }, "user": { From 477c7c5835983540db4cc8fa364d6f90b06ccaf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Mon, 28 Sep 2026 11:53:08 +0200 Subject: [PATCH 34/61] Filter GET /workflows on the caller's team The assigned parameter keeps the pending workflows related to the caller's team, their full name and the roles of their non-privilege groups, as the forced filters of the historical tables: "team" those whose last assignee is in the team (Assigned to my team), "tiers" those created by the team and assigned to someone else (Pending tiers action). An unknown value is a 400. --- cdb/db_forms_store.go | 38 +- server/api.yaml | 11 + server/codegen_server_gen.go | 671 ++++++++++++++++--------------- server/codegen_type_gen.go | 28 ++ server/handlers/forms_store.go | 2 +- server/handlers/get_workflows.go | 20 +- 6 files changed, 433 insertions(+), 337 deletions(-) diff --git a/cdb/db_forms_store.go b/cdb/db_forms_store.go index 8863f856..95872118 100644 --- a/cdb/db_forms_store.go +++ b/cdb/db_forms_store.go @@ -70,14 +70,48 @@ func (oDb *DB) GetFormsStore(ctx context.Context, storeID *int64, p ListParams) // folder and definition; a workflow whose revision is missing is still listed. const workflowsFrom = "workflows LEFT JOIN forms_revisions ON forms_revisions.form_md5 = workflows.form_md5" -// GetWorkflows lists the workflows, one when id is set. -func (oDb *DB) GetWorkflows(ctx context.Context, id *int64, p ListParams) ([]map[string]any, error) { +// myTeamNames is the subquery naming the caller and their team, as the historical +// requests tables compare them with a workflow's creator and last assignee: the +// user's full name ("first last") and the roles of their non-privilege groups. +const myTeamNames = "(SELECT CONCAT(COALESCE(first_name, ''), ' ', COALESCE(last_name, '')) FROM auth_user WHERE id = ?" + + " UNION SELECT auth_group.role FROM auth_group" + + " JOIN auth_membership ON auth_membership.group_id = auth_group.id" + + " WHERE auth_membership.user_id = ? AND auth_group.privilege = 'F')" + +// Workflows assigned to the caller's team, or started by it and awaiting a +// tier, as the historical "Assigned to my team" and "Pending tiers action". +const ( + WorkflowsAssignedTeam = "team" + WorkflowsAssignedTiers = "tiers" +) + +// GetWorkflows lists the workflows, one when id is set. assigned, when set, +// keeps the pending workflows assigned to the caller's team (WorkflowsAssignedTeam), +// or started by it and assigned to someone else (WorkflowsAssignedTiers); it +// requires p.UserID, and matches nothing without it. +func (oDb *DB) GetWorkflows(ctx context.Context, id *int64, assigned string, p ListParams) ([]map[string]any, error) { conds := []string{"workflows.id > 0"} var args []any if id != nil { conds = append(conds, "workflows.id = ?") args = append(args, *id) } + switch { + case assigned == "": + case p.UserID == nil: + conds = append(conds, "1=0") + case assigned == WorkflowsAssignedTeam: + conds = append(conds, "workflows.status != 'closed'", + "workflows.last_assignee IN "+myTeamNames) + args = append(args, *p.UserID, *p.UserID) + case assigned == WorkflowsAssignedTiers: + conds = append(conds, "workflows.status != 'closed'", + "workflows.last_assignee NOT IN "+myTeamNames, + "workflows.creator IN "+myTeamNames) + args = append(args, *p.UserID, *p.UserID, *p.UserID, *p.UserID) + default: + return nil, fmt.Errorf("getWorkflows: unknown assigned value %q", assigned) + } return oDb.listQuery(ctx, "getWorkflows", workflowsFrom, conds, args, "workflows.id", p) } diff --git a/server/api.yaml b/server/api.yaml index 42c75e05..12f3effa 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -8760,6 +8760,17 @@ paths: - $ref: '#/components/parameters/inQueryOrderby' - $ref: '#/components/parameters/inQueryFilter' - $ref: '#/components/parameters/inQueryGroupby' + - in: query + name: assigned + description: | + Keep the pending workflows (status not closed) related to the caller's + team, the caller's full name and the roles of their non-privilege + groups: `team` those whose last assignee is in the team, as the + historical "Assigned to my team"; `tiers` those created by the team and + assigned to someone else, as the historical "Pending tiers action". + schema: + type: string + enum: [team, tiers] tags: - collector responses: diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index b0c2176b..fb9d4e5b 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -10164,6 +10164,13 @@ func (w *ServerInterfaceWrapper) GetWorkflows(ctx echo.Context) error { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } + // ------------- Optional query parameter "assigned" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "assigned", ctx.QueryParams(), ¶ms.Assigned, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter assigned: %s", err)) + } + // Invoke the callback with all the unmarshaled arguments err = w.Handler.GetWorkflows(ctx, params) return err @@ -10445,337 +10452,339 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "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", - "8cv/HwAA//8=", + "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", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index f6a9e718..def30dbc 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -266,6 +266,24 @@ func (e PostNodeJSONBodyActionType) Valid() bool { } } +// Defines values for GetWorkflowsParamsAssigned. +const ( + Team GetWorkflowsParamsAssigned = "team" + Tiers GetWorkflowsParamsAssigned = "tiers" +) + +// Valid indicates whether the value is a known member of the GetWorkflowsParamsAssigned enum. +func (e GetWorkflowsParamsAssigned) Valid() bool { + switch e { + case Team: + return true + case Tiers: + return true + default: + return false + } +} + // ActionEnqueue One action to enqueue with PUT /actions. type ActionEnqueue struct { // Action Agent action to run @@ -5218,8 +5236,18 @@ type GetWorkflowsParams struct { // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` + + // Assigned Keep the pending workflows (status not closed) related to the caller's + // team, the caller's full name and the roles of their non-privilege + // groups: `team` those whose last assignee is in the team, as the + // historical "Assigned to my team"; `tiers` those created by the team and + // assigned to someone else, as the historical "Pending tiers action". + Assigned *GetWorkflowsParamsAssigned `form:"assigned,omitempty" json:"assigned,omitempty"` } +// GetWorkflowsParamsAssigned defines parameters for GetWorkflows. +type GetWorkflowsParamsAssigned string + // PostActionsJSONRequestBody defines body for PostActions for application/json ContentType. type PostActionsJSONRequestBody PostActionsJSONBody diff --git a/server/handlers/forms_store.go b/server/handlers/forms_store.go index 7e68f3a6..72fc3e21 100644 --- a/server/handlers/forms_store.go +++ b/server/handlers/forms_store.go @@ -116,7 +116,7 @@ func asInt64(v any) (int64, bool) { // /workflows/{id}/dump does in the historical collector. func (a *Api) workflowDump(ctx context.Context, workflowID int64) (map[string]any, error) { rows, err := a.defaultRows(ctx, "workflow", nil, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { - return a.ODB.GetWorkflows(ctx, &workflowID, p) + return a.ODB.GetWorkflows(ctx, &workflowID, "", p) }) if err != nil || len(rows) == 0 { return nil, err diff --git a/server/handlers/get_workflows.go b/server/handlers/get_workflows.go index caf3962c..f23cb92f 100644 --- a/server/handlers/get_workflows.go +++ b/server/handlers/get_workflows.go @@ -2,6 +2,7 @@ package serverhandlers import ( "context" + "net/http" "github.com/labstack/echo/v4" @@ -10,14 +11,27 @@ import ( ) // GetWorkflows handles GET /workflows, as the historical rest_get_workflows: -// every workflow is listed to any authenticated user. +// every workflow is listed to any authenticated user. The assigned parameter +// narrows the list to the historical "Assigned to my team" and "Pending tiers +// action" tables. func (a *Api) GetWorkflows(c echo.Context, params server.GetWorkflowsParams) error { odb := a.ODB + assigned := "" + if params.Assigned != nil { + assigned = string(*params.Assigned) + } + switch assigned { + case "", cdb.WorkflowsAssignedTeam, cdb.WorkflowsAssignedTiers: + default: + return JSONProblemf(c, http.StatusBadRequest, "invalid assigned value %q: expected %s or %s", + assigned, cdb.WorkflowsAssignedTeam, cdb.WorkflowsAssignedTiers) + } return a.handleList(c, "GetWorkflows", "workflow", listEndpointParams{ props: params.Props, limit: params.Limit, offset: params.Offset, meta: params.Meta, stats: params.Stats, orderby: params.Orderby, groupby: params.Groupby, - filter: params.Filter, + filter: params.Filter, + withUserID: assigned != "", }, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { - return odb.GetWorkflows(ctx, nil, p) + return odb.GetWorkflows(ctx, nil, assigned, p) }) } From a9e733a23f1f3dc840c01c506821d52554c85ff7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Mon, 28 Sep 2026 13:18:25 +0200 Subject: [PATCH 35/61] Share the HTTP error helpers of the forms handlers formError, formErrorf, formProblem and formInternal carry an HTTP status through the handlers and write it once, as the historical collector raised HTTP(status, message). They are not specific to forms: renamed httpError, httpErrorf, httpProblem and httpInternal, they move to problems.go for the compliance handlers to use as well. --- server/handlers/forms.go | 60 +++++++++++++++---------------- server/handlers/forms_common.go | 55 +++++++--------------------- server/handlers/forms_git.go | 26 +++++++------- server/handlers/forms_store.go | 24 ++++++------- server/handlers/forms_submit.go | 22 ++++++------ server/handlers/forms_team.go | 34 +++++++++--------- server/handlers/forms_validate.go | 24 ++++++------- server/handlers/problems.go | 33 +++++++++++++++++ 8 files changed, 141 insertions(+), 137 deletions(-) diff --git a/server/handlers/forms.go b/server/handlers/forms.go index 2156c275..d01c072e 100644 --- a/server/handlers/forms.go +++ b/server/handlers/forms.go @@ -78,12 +78,12 @@ func formFields(entry map[string]any) (map[string]any, error) { definition := v if s, ok := v.(string); ok { if err := json.Unmarshal([]byte(s), &definition); err != nil { - return nil, formErrorf(http.StatusBadRequest, "invalid form_definition: %s", err) + return nil, httpErrorf(http.StatusBadRequest, "invalid form_definition: %s", err) } } b, err := yaml.Marshal(numbersAsValues(definition)) if err != nil { - return nil, formErrorf(http.StatusBadRequest, "invalid form_definition: %s", err) + return nil, httpErrorf(http.StatusBadRequest, "invalid form_definition: %s", err) } fields["form_yaml"] = string(b) case cdb.IsFormColumn(k): @@ -94,7 +94,7 @@ func formFields(entry map[string]any) (map[string]any, error) { } if k == "form_yaml" { if _, err := parseFormYaml(s); err != nil { - return nil, formErrorf(http.StatusBadRequest, "invalid form_yaml: %s", err) + return nil, httpErrorf(http.StatusBadRequest, "invalid form_yaml: %s", err) } } fields[k] = s @@ -103,7 +103,7 @@ func formFields(entry map[string]any) (map[string]any, error) { } } if len(invalid) > 0 { - return nil, formErrorf(http.StatusBadRequest, "invalid properties: %s", strings.Join(invalid, ", ")) + return nil, httpErrorf(http.StatusBadRequest, "invalid properties: %s", strings.Join(invalid, ", ")) } return fields, nil } @@ -138,15 +138,15 @@ func (a *Api) PostForms(c echo.Context) error { ctx, cancel := context.WithTimeout(c.Request().Context(), a.SyncTimeout) defer cancel() if err := requireFormsManager(c); err != nil { - return formProblem(c, err) + return httpProblem(c, err) } entries, isList, err := decodeEntries(c) if err != nil { - return formProblem(c, err) + return httpProblem(c, err) } caller, err := a.formCaller(ctx, c) if err != nil { - return formProblem(c, formInternal(log, "cannot read the caller", err)) + return httpProblem(c, httpInternal(log, "cannot read the caller", err)) } defer a.formNotify(ctx, log) return runEntries(c, entries, isList, func(entry map[string]any) (map[string]any, error) { @@ -157,23 +157,23 @@ func (a *Api) PostForms(c echo.Context) error { func (a *Api) createForm(ctx context.Context, c echo.Context, log *slog.Logger, caller formCaller, entry map[string]any) (map[string]any, error) { name, ok := entryString(entry, "form_name") if !ok || name == "" { - return nil, formErrorf(http.StatusBadRequest, "Key 'form_name' is mandatory") + return nil, httpErrorf(http.StatusBadRequest, "Key 'form_name' is mandatory") } fields, err := formFields(entry) if err != nil { return nil, err } if _, exists, err := a.ODB.FormIDByName(ctx, name); err != nil { - return nil, formInternal(log, "cannot check the form name", err) + return nil, httpInternal(log, "cannot check the form name", err) } else if exists { - return nil, formErrorf(http.StatusConflict, "a form named %s already exists", name) + return nil, httpErrorf(http.StatusConflict, "a form named %s already exists", name) } fields["form_created"] = time.Now().Format(time.DateTime) fields["form_author"] = caller.name id, err := a.ODB.InsertForm(ctx, fields) if err != nil { - return nil, formInternal(log, "cannot create the form", err) + return nil, httpInternal(log, "cannot create the form", err) } // The creator's default group is made responsible for the form and the form @@ -181,12 +181,12 @@ func (a *Api) createForm(ctx context.Context, c echo.Context, log *slog.Logger, if caller.id != 0 { groupID, found, err := a.ODB.UserDefaultGroupID(ctx, caller.id) if err != nil { - return nil, formInternal(log, "cannot read the default group", err) + return nil, httpInternal(log, "cannot read the default group", err) } if found { for _, table := range []cdb.FormTeamTable{cdb.FormResponsibles, cdb.FormPublications} { if err := a.ODB.InsertFormTeam(ctx, table, id, groupID); err != nil { - return nil, formInternal(log, "cannot link the form to the default group", err) + return nil, httpInternal(log, "cannot link the form to the default group", err) } } } @@ -205,18 +205,18 @@ func (a *Api) PostForm(c echo.Context, formId int) error { ctx, cancel := context.WithTimeout(c.Request().Context(), a.SyncTimeout) defer cancel() if err := requireFormsManager(c); err != nil { - return formProblem(c, err) + return httpProblem(c, err) } entries, isList, err := decodeEntries(c) if err != nil { - return formProblem(c, err) + return httpProblem(c, err) } if isList { return JSONProblem(c, http.StatusBadRequest, "expecting an object") } result, err := a.updateForm(ctx, c, log, int64(formId), entries[0]) if err != nil { - return formProblem(c, err) + return httpProblem(c, err) } a.formNotify(ctx, log) return c.JSON(http.StatusOK, result) @@ -225,10 +225,10 @@ func (a *Api) PostForm(c echo.Context, formId int) error { func (a *Api) updateForm(ctx context.Context, c echo.Context, log *slog.Logger, id int64, entry map[string]any) (map[string]any, error) { form, err := a.ODB.FormByID(ctx, id) if err != nil { - return nil, formInternal(log, "cannot read the form", err) + return nil, httpInternal(log, "cannot read the form", err) } if form == nil { - return nil, formErrorf(http.StatusNotFound, "Form %d not found", id) + return nil, httpErrorf(http.StatusNotFound, "Form %d not found", id) } fields, err := formFields(entry) if err != nil { @@ -236,13 +236,13 @@ func (a *Api) updateForm(ctx context.Context, c echo.Context, log *slog.Logger, } if name, ok := fields["form_name"].(string); ok && name != form.Name { if otherID, exists, err := a.ODB.FormIDByName(ctx, name); err != nil { - return nil, formInternal(log, "cannot check the form name", err) + return nil, httpInternal(log, "cannot check the form name", err) } else if exists && otherID != id { - return nil, formErrorf(http.StatusConflict, "a form named %s already exists", name) + return nil, httpErrorf(http.StatusConflict, "a form named %s already exists", name) } } if err := a.ODB.UpdateForm(ctx, id, fields); err != nil { - return nil, formInternal(log, "cannot update the form", err) + return nil, httpInternal(log, "cannot update the form", err) } d := map[string]any{"form_name": form.Name, "data": formChanges(form, fields)} @@ -251,14 +251,14 @@ func (a *Api) updateForm(ctx context.Context, c echo.Context, log *slog.Logger, if yamlText, ok := fields["form_yaml"].(string); ok && yamlText != "" { caller, err := a.formCaller(ctx, c) if err != nil { - return nil, formInternal(log, "cannot read the caller", err) + return nil, httpInternal(log, "cannot read the caller", err) } a.formCommit(log, id, yamlText, caller) } result, err := a.formResponse(ctx, id) if err != nil { - return nil, formInternal(log, "cannot read the form back", err) + return nil, httpInternal(log, "cannot read the form back", err) } result["info"] = pyFormat("Form %(form_name)s change: %(data)s", d) return result, nil @@ -300,7 +300,7 @@ func (a *Api) DeleteForm(c echo.Context, formId int) error { defer cancel() result, err := a.deleteForm(ctx, c, log, int64(formId)) if err != nil { - return formProblem(c, err) + return httpProblem(c, err) } a.formNotify(ctx, log) return c.JSON(http.StatusOK, result) @@ -313,13 +313,13 @@ func (a *Api) DeleteForms(c echo.Context) error { defer cancel() entries, isList, err := decodeEntries(c) if err != nil { - return formProblem(c, err) + return httpProblem(c, err) } defer a.formNotify(ctx, log) return runEntries(c, entries, isList, func(entry map[string]any) (map[string]any, error) { s, ok := entryString(entry, "id") if !ok { - return nil, formErrorf(http.StatusBadRequest, "The 'id' key is mandatory") + return nil, httpErrorf(http.StatusBadRequest, "The 'id' key is mandatory") } id, err := parseFormID(s) if err != nil { @@ -338,13 +338,13 @@ func (a *Api) deleteForm(ctx context.Context, c echo.Context, log *slog.Logger, } form, err := a.ODB.FormByID(ctx, id) if err != nil { - return nil, formInternal(log, "cannot read the form", err) + return nil, httpInternal(log, "cannot read the form", err) } if form == nil { - return nil, formErrorf(http.StatusNotFound, "Form %d not found", id) + return nil, httpErrorf(http.StatusNotFound, "Form %d not found", id) } if err := a.ODB.DeleteForm(ctx, id); err != nil { - return nil, formInternal(log, "cannot delete the form", err) + return nil, httpInternal(log, "cannot delete the form", err) } d := map[string]any{"form_name": form.Name} a.formLog(ctx, c, log, "form.del", "Form %(form_name)s deleted", d) @@ -358,7 +358,7 @@ func (a *Api) GetFormAmIResponsible(c echo.Context, formId int) error { defer cancel() ok, err := a.ODB.FormResponsible(ctx, int64(formId), UserGroupsFromContext(c), IsManager(c)) if err != nil { - return formProblem(c, formInternal(log, "cannot check form responsibility", err)) + return httpProblem(c, httpInternal(log, "cannot check form responsibility", err)) } return c.JSON(http.StatusOK, map[string]bool{"data": ok}) } diff --git a/server/handlers/forms_common.go b/server/handlers/forms_common.go index 30177aa8..9770a9da 100644 --- a/server/handlers/forms_common.go +++ b/server/handlers/forms_common.go @@ -18,43 +18,14 @@ import ( "github.com/opensvc/oc3/util/logkey" ) -// formError is a forms request refused with an HTTP status, the way the -// historical collector raised HTTP(status, message). -type formError struct { - status int - msg string -} - -func (e *formError) Error() string { return e.msg } - -func formErrorf(status int, format string, args ...any) error { - return &formError{status: status, msg: fmt.Sprintf(format, args...)} -} - -// formProblem writes the problem response of a forms request. -func formProblem(c echo.Context, err error) error { - var fe *formError - if errors.As(err, &fe) { - return JSONProblem(c, fe.status, fe.msg) - } - return JSONProblem(c, http.StatusInternalServerError, err.Error()) -} - -// formInternal logs an internal failure and turns it into a 500 with a -// message that does not leak the database error. -func formInternal(log *slog.Logger, msg string, err error) error { - log.Error(msg, logkey.Error, err) - return formErrorf(http.StatusInternalServerError, "%s", msg) -} - // requireFormsManager refuses a caller without the FormsManager privilege, as // check_privilege("FormsManager") does: a manager always passes. func requireFormsManager(c echo.Context) error { if !IsAuthByUser(c) { - return formErrorf(http.StatusUnauthorized, "user authentication required") + return httpErrorf(http.StatusUnauthorized, "user authentication required") } if !IsManager(c) && !HasGroup(c, "FormsManager") { - return formErrorf(http.StatusForbidden, "user has no FormsManager privilege") + return httpErrorf(http.StatusForbidden, "user has no FormsManager privilege") } return nil } @@ -98,7 +69,7 @@ func decodeEntries(c echo.Context) (entries []map[string]any, isList bool, err e if strings.HasPrefix(contentType, echo.MIMEApplicationForm) || strings.HasPrefix(contentType, echo.MIMEMultipartForm) { values, err := c.FormParams() if err != nil { - return nil, false, formErrorf(http.StatusBadRequest, "invalid request body: %s", err) + return nil, false, httpErrorf(http.StatusBadRequest, "invalid request body: %s", err) } entry := make(map[string]any, len(values)) for k, v := range values { @@ -110,19 +81,19 @@ func decodeEntries(c echo.Context) (entries []map[string]any, isList bool, err e } var raw json.RawMessage if err := json.NewDecoder(c.Request().Body).Decode(&raw); err != nil { - return nil, false, formErrorf(http.StatusBadRequest, "invalid request body: %s", err) + return nil, false, httpErrorf(http.StatusBadRequest, "invalid request body: %s", err) } decoder := json.NewDecoder(bytes.NewReader(raw)) decoder.UseNumber() if trimmed := bytes.TrimSpace(raw); len(trimmed) > 0 && trimmed[0] == '[' { if err := decoder.Decode(&entries); err != nil { - return nil, true, formErrorf(http.StatusBadRequest, "invalid request body: %s", err) + return nil, true, httpErrorf(http.StatusBadRequest, "invalid request body: %s", err) } return entries, true, nil } var entry map[string]any if err := decoder.Decode(&entry); err != nil { - return nil, false, formErrorf(http.StatusBadRequest, "invalid request body: %s", err) + return nil, false, httpErrorf(http.StatusBadRequest, "invalid request body: %s", err) } return []map[string]any{entry}, false, nil } @@ -150,7 +121,7 @@ func runEntries(c echo.Context, entries []map[string]any, isList bool, run func( if !isList { result, err := run(entries[0]) if err != nil { - return formProblem(c, err) + return httpProblem(c, err) } return c.JSON(http.StatusOK, result) } @@ -159,7 +130,7 @@ func runEntries(c echo.Context, entries []map[string]any, isList bool, run func( result, err := run(entry) if err != nil { status := http.StatusInternalServerError - var fe *formError + var fe *httpError if errors.As(err, &fe) { status = fe.status } @@ -243,7 +214,7 @@ var formDefinitionProp = map[string]virtualProp{ func parseFormID(s string) (int64, error) { id, err := strconv.ParseInt(s, 10, 64) if err != nil { - return 0, formErrorf(http.StatusBadRequest, "invalid form id %q", s) + return 0, httpErrorf(http.StatusBadRequest, "invalid form id %q", s) } return id, nil } @@ -253,10 +224,10 @@ func parseFormID(s string) (int64, error) { func (a *Api) requireFormResponsible(c echo.Context, log *slog.Logger, ctx context.Context, formID int64) error { ok, err := a.ODB.FormResponsible(ctx, formID, UserGroupsFromContext(c), IsManager(c)) if err != nil { - return formInternal(log, "cannot check form responsibility", err) + return httpInternal(log, "cannot check form responsibility", err) } if !ok { - return formErrorf(http.StatusNotFound, "Form %d not found or you are not responsible", formID) + return httpErrorf(http.StatusNotFound, "Form %d not found or you are not responsible", formID) } return nil } @@ -266,10 +237,10 @@ func (a *Api) requireFormResponsible(c echo.Context, log *slog.Logger, ctx conte func (a *Api) requireFormPublished(c echo.Context, log *slog.Logger, ctx context.Context, formID int64) error { ok, err := a.ODB.FormVisible(ctx, formID, UserGroupsFromContext(c), IsManager(c)) if err != nil { - return formInternal(log, "cannot check form publication", err) + return httpInternal(log, "cannot check form publication", err) } if !ok { - return formErrorf(http.StatusNotFound, "Form %d not found or not published to you", formID) + return httpErrorf(http.StatusNotFound, "Form %d not found or not published to you", formID) } return nil } diff --git a/server/handlers/forms_git.go b/server/handlers/forms_git.go index ed888a67..13b1ea44 100644 --- a/server/handlers/forms_git.go +++ b/server/handlers/forms_git.go @@ -35,7 +35,7 @@ func (a *Api) formCommit(log *slog.Logger, formID int64, content string, caller func (a *Api) formRevisionsAllowed(ctx context.Context, c echo.Context, log *slog.Logger, formID int64) (bool, error) { ok, err := a.ODB.FormVisible(ctx, formID, UserGroupsFromContext(c), IsManager(c)) if err != nil { - return false, formInternal(log, "cannot check form publication", err) + return false, httpInternal(log, "cannot check form publication", err) } return ok, nil } @@ -46,14 +46,14 @@ func (a *Api) GetFormRevisions(c echo.Context, formId int) error { ctx := c.Request().Context() allowed, err := a.formRevisionsAllowed(ctx, c, log, int64(formId)) if err != nil { - return formProblem(c, err) + return httpProblem(c, err) } if !allowed { return c.JSON(http.StatusOK, []any{}) } revisions, err := formTrack().Timeline(strconv.Itoa(formId)) if err != nil { - return formProblem(c, formInternal(log, "cannot read the form history", err)) + return httpProblem(c, httpInternal(log, "cannot read the form history", err)) } return c.JSON(http.StatusOK, map[string]any{"data": revisions}) } @@ -67,14 +67,14 @@ func (a *Api) GetFormRevision(c echo.Context, formId int, cid string) error { } allowed, err := a.formRevisionsAllowed(ctx, c, log, int64(formId)) if err != nil { - return formProblem(c, err) + return httpProblem(c, err) } if !allowed { return c.JSON(http.StatusOK, []any{}) } blob, err := formTrack().At(strconv.Itoa(formId), cid) if err != nil { - return formProblem(c, formErrorf(http.StatusNotFound, "revision %s not found", cid)) + return httpProblem(c, httpErrorf(http.StatusNotFound, "revision %s not found", cid)) } if blob == nil { return c.JSON(http.StatusOK, map[string]any{"data": ""}) @@ -92,7 +92,7 @@ func (a *Api) GetFormDiff(c echo.Context, formId int, cid string, params server. } allowed, err := a.formRevisionsAllowed(ctx, c, log, int64(formId)) if err != nil { - return formProblem(c, err) + return httpProblem(c, err) } if !allowed { return c.JSON(http.StatusOK, []any{}) @@ -104,7 +104,7 @@ func (a *Api) GetFormDiff(c echo.Context, formId int, cid string, params server. out, err = formTrack().Show(strconv.Itoa(formId), cid) } if err != nil { - return formProblem(c, formErrorf(http.StatusNotFound, "revision %s not found", cid)) + return httpProblem(c, httpErrorf(http.StatusNotFound, "revision %s not found", cid)) } return c.JSON(http.StatusOK, map[string]any{"data": out}) } @@ -120,28 +120,28 @@ func (a *Api) PostFormRollback(c echo.Context, formId int, cid string) error { return JSONProblemf(c, http.StatusBadRequest, "invalid revision %q", cid) } if err := requireFormsManager(c); err != nil { - return formProblem(c, err) + return httpProblem(c, err) } formID := int64(formId) if err := a.requireFormResponsible(c, log, ctx, formID); err != nil { - return formProblem(c, err) + return httpProblem(c, err) } caller, err := a.formCaller(ctx, c) if err != nil { - return formProblem(c, formInternal(log, "cannot read the caller", err)) + return httpProblem(c, httpInternal(log, "cannot read the caller", err)) } track := formTrack() id := strconv.Itoa(formId) if err := track.Rollback(id, cid, caller.author()); err != nil { log.Error("cannot roll the form back", "form_id", formId, "cid", cid, logkey.Error, err) - return formProblem(c, formErrorf(http.StatusNotFound, "cannot roll form %d back to %s", formId, cid)) + return httpProblem(c, httpErrorf(http.StatusNotFound, "cannot roll form %d back to %s", formId, cid)) } content, err := track.Read(id) if err != nil { - return formProblem(c, formInternal(log, "cannot read the restored form", err)) + return httpProblem(c, httpInternal(log, "cannot read the restored form", err)) } if err := a.ODB.UpdateForm(ctx, formID, map[string]any{"form_yaml": content}); err != nil { - return formProblem(c, formInternal(log, "cannot store the restored form", err)) + return httpProblem(c, httpInternal(log, "cannot store the restored form", err)) } a.formNotify(ctx, log) // The historical handler returns nothing. diff --git a/server/handlers/forms_store.go b/server/handlers/forms_store.go index 72fc3e21..47f55543 100644 --- a/server/handlers/forms_store.go +++ b/server/handlers/forms_store.go @@ -142,7 +142,7 @@ func (a *Api) GetFormStoreDump(c echo.Context, storeId int) error { ctx := c.Request().Context() stored, err := a.storedForm(ctx, int64(storeId)) if err != nil { - return formProblem(c, formInternal(log, "cannot read the stored form", err)) + return httpProblem(c, httpInternal(log, "cannot read the stored form", err)) } if stored == nil { return JSONProblemf(c, http.StatusNotFound, "stored form %d not found", storeId) @@ -150,11 +150,11 @@ func (a *Api) GetFormStoreDump(c echo.Context, storeId int) error { if headID, ok := asInt64(stored["form_head_id"]); ok { workflowID, found, err := a.ODB.WorkflowIDByHead(ctx, headID) if err != nil { - return formProblem(c, formInternal(log, "cannot read the workflow", err)) + return httpProblem(c, httpInternal(log, "cannot read the workflow", err)) } if found { if stored["workflow"], err = a.workflowDump(ctx, workflowID); err != nil { - return formProblem(c, formInternal(log, "cannot read the workflow", err)) + return httpProblem(c, httpInternal(log, "cannot read the workflow", err)) } } } @@ -173,18 +173,18 @@ func (a *Api) GetFormOutputResults(c echo.Context, resultsId int) error { log := echolog.GetLogHandler(c, "GetFormOutputResults") results, err := a.readFormResults(c.Request().Context(), c, int64(resultsId)) if err != nil { - return formProblem(c, formResultsError(log, err)) + return httpProblem(c, formResultsError(log, err)) } return c.JSON(http.StatusOK, results) } // formResultsError keeps a refusal as it is and logs an internal failure. func formResultsError(log *slog.Logger, err error) error { - var fe *formError + var fe *httpError if errors.As(err, &fe) { return err } - return formInternal(log, "cannot read the results", err) + return httpInternal(log, "cannot read the results", err) } // readFormResults reads a results structure the caller may see, 404 otherwise. @@ -194,13 +194,13 @@ func (a *Api) readFormResults(ctx context.Context, c echo.Context, id int64) (ma return nil, err } if !found { - return nil, formErrorf(http.StatusNotFound, "results not found") + return nil, httpErrorf(http.StatusNotFound, "results not found") } var results map[string]any decoder := json.NewDecoder(bytes.NewReader([]byte(s))) decoder.UseNumber() if err := decoder.Decode(&results); err != nil { - return nil, formErrorf(http.StatusInternalServerError, "unreadable results: %s", err) + return nil, httpErrorf(http.StatusInternalServerError, "unreadable results: %s", err) } return results, nil } @@ -214,11 +214,11 @@ func (a *Api) PutFormOutputResults(c echo.Context, resultsId int) error { id := int64(resultsId) results, err := a.readFormResults(ctx, c, id) if err != nil { - return formProblem(c, formResultsError(log, err)) + return httpProblem(c, formResultsError(log, err)) } entries, isList, err := decodeEntries(c) if err != nil { - return formProblem(c, err) + return httpProblem(c, err) } if isList { return JSONProblem(c, http.StatusBadRequest, "expecting an object") @@ -248,10 +248,10 @@ func (a *Api) PutFormOutputResults(c echo.Context, resultsId int) error { } b, err := json.Marshal(results) if err != nil { - return formProblem(c, formInternal(log, "cannot encode the results", err)) + return httpProblem(c, httpInternal(log, "cannot encode the results", err)) } if err := a.ODB.UpdateFormOutputResults(ctx, id, string(b)); err != nil { - return formProblem(c, formInternal(log, "cannot store the results", err)) + return httpProblem(c, httpInternal(log, "cannot store the results", err)) } a.formNotify(ctx, log) return c.JSON(http.StatusOK, results) diff --git a/server/handlers/forms_submit.go b/server/handlers/forms_submit.go index d6e2ccde..c3f168ba 100644 --- a/server/handlers/forms_submit.go +++ b/server/handlers/forms_submit.go @@ -99,7 +99,7 @@ func (a *Api) PutForm(c echo.Context, formId int) error { entries, isList, err := decodeEntries(c) if err != nil { - return formProblem(c, err) + return httpProblem(c, err) } if isList { return JSONProblem(c, http.StatusBadRequest, "expecting an object with the data and prev_wfid keys") @@ -110,7 +110,7 @@ func (a *Api) PutForm(c echo.Context, formId int) error { s.userEmail, _ = c.Get(XUserEmail).(string) s.nodeID, _ = c.Get(XNodeID).(string) if s.caller, err = a.formCaller(ctx, c); err != nil { - return formProblem(c, formInternal(log, "cannot read the caller", err)) + return httpProblem(c, httpInternal(log, "cannot read the caller", err)) } // The data may come as its JSON string form, as a posted form variable. @@ -131,7 +131,7 @@ func (a *Api) PutForm(c echo.Context, formId int) error { } if err := s.loadForm(ctx, c); err != nil { - return formProblem(c, err) + return httpProblem(c, err) } s.results = map[string]any{ @@ -146,14 +146,14 @@ func (a *Api) PutForm(c echo.Context, formId int) error { } if done, err := s.workflowStepDone(ctx); err != nil { - return formProblem(c, formInternal(log, "cannot read the workflow step", err)) + return httpProblem(c, httpInternal(log, "cannot read the workflow step", err)) } else if done { s.appendLog("", 1, "This step is already completed (id=%(id)d)", map[string]any{"id": *s.prevWfid}) return c.JSON(http.StatusOK, s.results) } if err := s.validate(ctx); err != nil { - return formProblem(c, err) + return httpProblem(c, err) } var userID *int64 @@ -162,10 +162,10 @@ func (a *Api) PutForm(c echo.Context, formId int) error { } b, err := json.Marshal(s.results) if err != nil { - return formProblem(c, formInternal(log, "cannot encode the results", err)) + return httpProblem(c, httpInternal(log, "cannot encode the results", err)) } if s.resultsID, err = a.ODB.InsertFormOutputResults(ctx, userID, s.nodeID, "", string(b)); err != nil { - return formProblem(c, formInternal(log, "cannot store the results", err)) + return httpProblem(c, httpInternal(log, "cannot store the results", err)) } s.results["results_id"] = s.resultsID log.Info("form submitted", "form_id", s.formID, "results_id", s.resultsID) @@ -185,7 +185,7 @@ func (a *Api) PutForm(c echo.Context, formId int) error { // the database the caller may use: published to one of their groups, unless a // manager. func (s *formSubmission) loadForm(ctx context.Context, c echo.Context) error { - notFound := formErrorf(http.StatusNotFound, "the requested form does not exist or you don't have permission to use it") + notFound := httpErrorf(http.StatusNotFound, "the requested form does not exist or you don't have permission to use it") if s.formID < 0 { f, ok := internalFormByID(s.formID) if !ok { @@ -197,13 +197,13 @@ func (s *formSubmission) loadForm(ctx context.Context, c echo.Context) error { } visible, err := s.a.ODB.FormVisible(ctx, s.formID, UserGroupsFromContext(c), IsManager(c)) if err != nil { - return formInternal(s.log, "cannot check form publication", err) + return httpInternal(s.log, "cannot check form publication", err) } if !visible { return notFound } if s.form, err = s.a.ODB.FormByID(ctx, s.formID); err != nil { - return formInternal(s.log, "cannot read the form", err) + return httpInternal(s.log, "cannot read the form", err) } if s.form == nil { return notFound @@ -211,7 +211,7 @@ func (s *formSubmission) loadForm(ctx context.Context, c echo.Context) error { s.formName = s.form.Name definition, err := parseFormYaml(s.form.Yaml) if err != nil { - return formErrorf(http.StatusBadRequest, "invalid form definition: %s", err) + return httpErrorf(http.StatusBadRequest, "invalid form definition: %s", err) } s.definition, _ = definition.(map[string]any) if s.definition == nil { diff --git a/server/handlers/forms_team.go b/server/handlers/forms_team.go index 958167e6..dfd30373 100644 --- a/server/handlers/forms_team.go +++ b/server/handlers/forms_team.go @@ -71,7 +71,7 @@ func (a *Api) GetFormResponsibles(c echo.Context, formId int, params server.GetF func (a *Api) getFormTeam(c echo.Context, handlerName string, table cdb.FormTeamTable, formID int64, p listEndpointParams) error { log := echolog.GetLogHandler(c, handlerName) if err := a.requireFormPublished(c, log, c.Request().Context(), formID); err != nil { - return formProblem(c, err) + return httpProblem(c, err) } return a.handleList(c, handlerName, "auth_group", p, func(ctx context.Context, lp cdb.ListParams) ([]map[string]any, error) { return a.ODB.GetFormTeam(ctx, table, formID, lp) @@ -124,7 +124,7 @@ func (a *Api) formTeamOne(c echo.Context, handlerName string, team formTeam, add defer cancel() result, err := a.formTeamChange(ctx, c, log, team, add, formID, groupID) if err != nil { - return formProblem(c, err) + return httpProblem(c, err) } a.formNotify(ctx, log) return c.JSON(http.StatusOK, result) @@ -139,17 +139,17 @@ func (a *Api) formTeamBulk(c echo.Context, handlerName string, team formTeam, ad defer cancel() entries, isList, err := decodeEntries(c) if err != nil { - return formProblem(c, err) + return httpProblem(c, err) } defer a.formNotify(ctx, log) return runEntries(c, entries, isList, func(entry map[string]any) (map[string]any, error) { formID, ok := entryString(entry, "form_id") if !ok { - return nil, formErrorf(http.StatusBadRequest, "The 'form_id' key is mandatory") + return nil, httpErrorf(http.StatusBadRequest, "The 'form_id' key is mandatory") } groupID, ok := entryString(entry, "group_id") if !ok { - return nil, formErrorf(http.StatusBadRequest, "The 'group_id' key is mandatory") + return nil, httpErrorf(http.StatusBadRequest, "The 'group_id' key is mandatory") } return a.formTeamChange(ctx, c, log, team, add, formID, groupID) }) @@ -174,18 +174,18 @@ func (a *Api) formTeamChange(ctx context.Context, c echo.Context, log *slog.Logg if !add { groupID, err := strconv.ParseInt(groupIDStr, 10, 64) if err != nil { - return nil, formErrorf(http.StatusBadRequest, "invalid group id %q", groupIDStr) + return nil, httpErrorf(http.StatusBadRequest, "invalid group id %q", groupIDStr) } d := map[string]any{"form_id": formIDStr, "group_id": groupIDStr} exists, err := a.ODB.FormTeamExists(ctx, team.table, formID, groupID) if err != nil { - return nil, formInternal(log, "cannot check the form group link", err) + return nil, httpInternal(log, "cannot check the form group link", err) } if !exists { return map[string]any{"info": pyFormat(team.deletedFmt, d)}, nil } if err := a.ODB.DeleteFormTeam(ctx, team.table, formID, groupID); err != nil { - return nil, formInternal(log, "cannot unlink the form and the group", err) + return nil, httpInternal(log, "cannot unlink the form and the group", err) } a.formLog(ctx, c, log, team.delAction, team.delFmt, d) return map[string]any{"info": pyFormat(team.delFmt, d)}, nil @@ -196,39 +196,39 @@ func (a *Api) formTeamChange(ctx context.Context, c echo.Context, log *slog.Logg if !isManager { user := UserInfoFromContext(c) if user == nil { - return nil, formErrorf(http.StatusUnauthorized, "missing user context") + return nil, httpErrorf(http.StatusUnauthorized, "missing user context") } userID, err := strconv.ParseInt(user.GetExtensions().Get(xauth.XUserID), 10, 64) if err != nil { - return nil, formErrorf(http.StatusBadRequest, "invalid user id") + return nil, httpErrorf(http.StatusBadRequest, "invalid user id") } if userGroupIDs, err = a.ODB.UserGroupIDs(ctx, userID); err != nil { - return nil, formInternal(log, "cannot list user groups", err) + return nil, httpInternal(log, "cannot list user groups", err) } } group, status, err := a.ODB.OrgGroup(ctx, groupIDStr, userGroupIDs, isManager) if err != nil { - return nil, formInternal(log, "cannot resolve the group", err) + return nil, httpInternal(log, "cannot resolve the group", err) } switch status { case cdb.OrgGroupNotFound: - return nil, formErrorf(http.StatusNotFound, "Group not found: %s", groupIDStr) + return nil, httpErrorf(http.StatusNotFound, "Group not found: %s", groupIDStr) case cdb.OrgGroupAmbiguous: - return nil, formErrorf(http.StatusBadRequest, "Ambiguous group id: %s", groupIDStr) + return nil, httpErrorf(http.StatusBadRequest, "Ambiguous group id: %s", groupIDStr) case cdb.OrgGroupPrivileged: - return nil, formErrorf(http.StatusForbidden, "Operation not allowed on privilege group: %s", group.Role) + return nil, httpErrorf(http.StatusForbidden, "Operation not allowed on privilege group: %s", group.Role) } d := map[string]any{"form_id": formIDStr, "role": group.Role} exists, err := a.ODB.FormTeamExists(ctx, team.table, formID, group.ID) if err != nil { - return nil, formInternal(log, "cannot check the form group link", err) + return nil, httpInternal(log, "cannot check the form group link", err) } if exists { return map[string]any{"info": pyFormat(team.addedFmt, d)}, nil } if err := a.ODB.InsertFormTeam(ctx, team.table, formID, group.ID); err != nil { - return nil, formInternal(log, "cannot link the form and the group", err) + return nil, httpInternal(log, "cannot link the form and the group", err) } a.formLog(ctx, c, log, team.addAction, team.addFmt, d) return map[string]any{"info": pyFormat(team.addFmt, d)}, nil diff --git a/server/handlers/forms_validate.go b/server/handlers/forms_validate.go index 2238278b..6eb0fb88 100644 --- a/server/handlers/forms_validate.go +++ b/server/handlers/forms_validate.go @@ -17,7 +17,7 @@ func (s *formSubmission) validate(ctx context.Context) error { for _, item := range t { m, ok := item.(map[string]any) if !ok { - return formErrorf(http.StatusBadRequest, "form data list entries must be objects") + return httpErrorf(http.StatusBadRequest, "form data list entries must be objects") } if err := s.validateData(ctx, m); err != nil { return err @@ -50,14 +50,14 @@ func (s *formSubmission) validateInput(ctx context.Context, data map[string]any, applies, err := checkInputCondition(input, data) if err != nil { - return formErrorf(http.StatusBadRequest, "%s", err) + return httpErrorf(http.StatusBadRequest, "%s", err) } if !applies { return nil } if val == nil { if defBool(input, "Mandatory") { - return formErrorf(http.StatusBadRequest, "Missing value for mandatory input '%s'", inputID) + return httpErrorf(http.StatusBadRequest, "Missing value for mandatory input '%s'", inputID) } return nil } @@ -93,10 +93,10 @@ func (s *formSubmission) validateInput(ctx context.Context, data map[string]any, forced = formDereference(strings.TrimSpace(forced), ref, "") refVal, ok := ref[key] if !ok { - return formErrorf(http.StatusBadRequest, "missing key '%s', from input %s", key, inputID) + return httpErrorf(http.StatusBadRequest, "missing key '%s', from input %s", key, inputID) } if !strings.Contains(forced, "#") && forced != formValueText(refVal) { - return formErrorf(http.StatusBadRequest, "unallowed key value '%s=%s', expecting '%s', from input %s", + return httpErrorf(http.StatusBadRequest, "unallowed key value '%s=%s', expecting '%s', from input %s", key, formValueText(refVal), forced, inputID) } } @@ -122,7 +122,7 @@ func (s *formSubmission) validateInput(ctx context.Context, data map[string]any, continue } if !containsString(allowed, formValueText(v)) { - return formErrorf(http.StatusBadRequest, "Input '%s' value '%s' not in allowed candidates", inputID, formValueText(v)) + return httpErrorf(http.StatusBadRequest, "Input '%s' value '%s' not in allowed candidates", inputID, formValueText(v)) } } } @@ -151,7 +151,7 @@ func (s *formSubmission) validateInput(ctx context.Context, data map[string]any, for _, v := range vals { args, err := formRestArgs(fn, data) if err != nil { - return formErrorf(http.StatusBadRequest, "cannot build the candidates url %s: missing %s", fn, err) + return httpErrorf(http.StatusBadRequest, "cannot build the candidates url %s: missing %s", fn, err) } kwargs := map[string]any{} for _, entry := range defList(input, "Args") { @@ -176,13 +176,13 @@ func (s *formSubmission) validateInput(ctx context.Context, data map[string]any, path := "/" + strings.Join(args, "/") resp, err := s.callAPI(ctx, http.MethodGet, path, kwargs, "") if err != nil { - return formErrorf(http.StatusBadRequest, "cannot verify the submitted value is a valid candidate: %s", err) + return httpErrorf(http.StatusBadRequest, "cannot verify the submitted value is a valid candidate: %s", err) } if resp.status == http.StatusNotFound { - return formErrorf(http.StatusBadRequest, "Unknown handler '%s': can not verify the submitted value is a valid candidates", fn) + return httpErrorf(http.StatusBadRequest, "Unknown handler '%s': can not verify the submitted value is a valid candidates", fn) } if resp.status >= 300 { - return formErrorf(http.StatusBadRequest, "cannot verify the submitted value is a valid candidate: %s", problemTextOf(resp)) + return httpErrorf(http.StatusBadRequest, "cannot verify the submitted value is a valid candidate: %s", problemTextOf(resp)) } var candidates []string if m, ok := resp.body.(map[string]any); ok { @@ -190,7 +190,7 @@ func (s *formSubmission) validateInput(ctx context.Context, data map[string]any, for _, candidate := range list { cv, err := formGetVal(candidate, key) if err != nil { - return formErrorf(http.StatusBadRequest, "Key '%s' not in candidates", key) + return httpErrorf(http.StatusBadRequest, "Key '%s' not in candidates", key) } candidates = append(candidates, formValueText(cv)) } @@ -199,7 +199,7 @@ func (s *formSubmission) validateInput(ctx context.Context, data map[string]any, continue } if !containsString(candidates, formValueText(keyVal)) { - return formErrorf(http.StatusBadRequest, "Input '%s' value '%s' not in allowed candidates %s obtained from %s", + return httpErrorf(http.StatusBadRequest, "Input '%s' value '%s' not in allowed candidates %s obtained from %s", inputID, formValueText(keyVal), fmt.Sprint(candidates), path) } } diff --git a/server/handlers/problems.go b/server/handlers/problems.go index 67815511..b73c482a 100644 --- a/server/handlers/problems.go +++ b/server/handlers/problems.go @@ -3,11 +3,13 @@ package serverhandlers import ( "errors" "fmt" + "log/slog" "net/http" "github.com/labstack/echo/v4" "github.com/opensvc/oc3/server" + "github.com/opensvc/oc3/util/logkey" ) // errRequestDenied is returned by the require* guards after they have written the @@ -47,3 +49,34 @@ func stringPtr[T ~string](value *T) *string { s := string(*value) return &s } + +// httpError is a request refused with an HTTP status, the way the historical +// collector raised HTTP(status, message): the handlers return it, and write it +// once with httpProblem. +type httpError struct { + status int + msg string +} + +func (e *httpError) Error() string { return e.msg } + +func httpErrorf(status int, format string, args ...any) error { + return &httpError{status: status, msg: fmt.Sprintf(format, args...)} +} + +// httpProblem writes the problem response of a refused request: its status for +// an httpError, 500 otherwise. +func httpProblem(c echo.Context, err error) error { + var he *httpError + if errors.As(err, &he) { + return JSONProblem(c, he.status, he.msg) + } + return JSONProblem(c, http.StatusInternalServerError, err.Error()) +} + +// httpInternal logs an internal failure and turns it into a 500 with a +// message that does not leak the database error. +func httpInternal(log *slog.Logger, msg string, err error) error { + log.Error(msg, logkey.Error, err) + return httpErrorf(http.StatusInternalServerError, "%s", msg) +} From 4b3d12be9cc83c21572f11a44c7ded388ef77c78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Mon, 28 Sep 2026 13:19:26 +0200 Subject: [PATCH 36/61] Add the compliance status and logs endpoints Port the /compliance/logs and /compliance/status endpoints of the historical api_compliance: GET /compliance/logs and /logs/{log_id}, GET /compliance/status and /status/{status_id}, scoped as q_filter(node_field) to the nodes whose app is published to one of the caller's groups; DELETE /compliance/status/{status_id} and its bulk form DELETE /compliance/status ({"id": ...}), which require the CompExec privilege and the node's responsibility, and log the deletion. The run and log rows are typed (ComplianceLogRow and its list response; ComplianceStatusListResponse). The fset-id filterset of the historical lists is not supported, as nowhere else in oc3; nor is the refresh of the "compliance differences in cluster" dashboard alert, which oc3 does not compute. --- cdb/db_compliance_api.go | 96 +++ server/api.yaml | 257 ++++++++ server/codegen_server_gen.go | 931 +++++++++++++++++---------- server/codegen_type_gen.go | 196 ++++++ server/handlers/compliance_status.go | 153 +++++ 5 files changed, 1300 insertions(+), 333 deletions(-) create mode 100644 cdb/db_compliance_api.go create mode 100644 server/handlers/compliance_status.go diff --git a/cdb/db_compliance_api.go b/cdb/db_compliance_api.go new file mode 100644 index 00000000..47b3eea6 --- /dev/null +++ b/cdb/db_compliance_api.go @@ -0,0 +1,96 @@ +package cdb + +import ( + "context" + "database/sql" + "errors" + "fmt" +) + +// compPublishedNodesCond restricts a node_id column to the nodes the caller may +// see, as q_filter(node_field=...) of the historical collector: those whose app is +// published to one of the caller's groups; every node for a manager. +func compPublishedNodesCond(nodeCol string, groups []string, isManager bool) (string, []any) { + if isManager { + return "1=1", nil + } + clean := cleanGroups(groups) + if len(clean) == 0 { + return "1=0", nil + } + args := make([]any, len(clean)) + for i, g := range clean { + args[i] = g + } + return nodeCol + " IN (SELECT n.node_id FROM nodes n" + + " JOIN apps a ON a.app = n.app" + + " JOIN apps_publications ap ON ap.app_id = a.id" + + " JOIN auth_group ag ON ag.id = ap.group_id" + + " WHERE ag.role IN (" + Placeholders(len(clean)) + "))", args +} + +// GetComplianceLogs lists the compliance module runs (check, fixable, fix) of the +// nodes the caller may see, the most recent first; one when id is set. +func (oDb *DB) GetComplianceLogs(ctx context.Context, id *int64, p ListParams) ([]map[string]any, error) { + cond, args := compPublishedNodesCond("comp_log.node_id", p.Groups, p.IsManager) + conds := []string{cond} + if id != nil { + conds = append(conds, "comp_log.id = ?") + args = append(args, *id) + } + return oDb.listQuery(ctx, "getComplianceLogs", "comp_log", conds, args, "comp_log.id DESC", p) +} + +// GetComplianceStatus lists the last check run of each module-node-service tuple, +// for the nodes the caller may see; one when id is set. +func (oDb *DB) GetComplianceStatus(ctx context.Context, id *int64, p ListParams) ([]map[string]any, error) { + cond, args := compPublishedNodesCond("comp_status.node_id", p.Groups, p.IsManager) + conds := []string{cond} + if id != nil { + conds = append(conds, "comp_status.id = ?") + args = append(args, *id) + } + return oDb.listQuery(ctx, "getComplianceStatus", "comp_status", conds, args, "comp_status.id DESC", p) +} + +// CompStatusRun is the last check run of a module on a node, or on a service +// instance on that node. +type CompStatusRun struct { + ID int64 + RunModule string + NodeID string + SvcID string + Nodename string + Svcname string +} + +// CompStatusRunVisible returns a check run of a node the caller may see, nil when +// there is none. +func (oDb *DB) CompStatusRunVisible(ctx context.Context, id int64, groups []string, isManager bool) (*CompStatusRun, error) { + cond, args := compPublishedNodesCond("comp_status.node_id", groups, isManager) + query := "SELECT comp_status.id, comp_status.run_module, COALESCE(comp_status.node_id, ''), COALESCE(comp_status.svc_id, '')," + + " COALESCE(nodes.nodename, ''), COALESCE(services.svcname, '')" + + " FROM comp_status" + + " LEFT JOIN nodes ON nodes.node_id = comp_status.node_id" + + " LEFT JOIN services ON services.svc_id = comp_status.svc_id" + + " WHERE comp_status.id = ? AND " + cond + var r CompStatusRun + err := oDb.DB.QueryRowContext(ctx, query, append([]any{id}, args...)...). + Scan(&r.ID, &r.RunModule, &r.NodeID, &r.SvcID, &r.Nodename, &r.Svcname) + switch { + case errors.Is(err, sql.ErrNoRows): + return nil, nil + case err != nil: + return nil, fmt.Errorf("compStatusRunVisible: %w", err) + } + return &r, nil +} + +// DeleteCompStatusRun deletes a check run. +func (oDb *DB) DeleteCompStatusRun(ctx context.Context, id int64) error { + if _, err := oDb.DB.ExecContext(ctx, "DELETE FROM comp_status WHERE id = ?", id); err != nil { + return fmt.Errorf("deleteCompStatusRun: %w", err) + } + oDb.SetChange("comp_status") + return nil +} diff --git a/server/api.yaml b/server/api.yaml index 12f3effa..d642bcc5 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -8788,6 +8788,218 @@ paths: - basicAuth: [ ] - bearerAuth: [ ] + /compliance/logs: + get: + operationId: GetComplianceLogs + description: | + List the compliance modules' check, fixable and fix runs of the nodes the + user can see: those whose app is published to one of the user's groups, every + node for a manager. The most recent first by default. + parameters: + - $ref: '#/components/parameters/inQueryProps' + - $ref: '#/components/parameters/inQueryLimit' + - $ref: '#/components/parameters/inQueryOffset' + - $ref: '#/components/parameters/inQueryMeta' + - $ref: '#/components/parameters/inQueryStats' + - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryFilter' + - $ref: '#/components/parameters/inQueryGroupby' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ComplianceLogListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /compliance/logs/{log_id}: + get: + operationId: GetComplianceLog + description: | + Display the properties of a module run. + parameters: + - in: path + name: log_id + required: true + description: Id of the run (comp_log.id) + schema: + type: string + - $ref: '#/components/parameters/inQueryProps' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ComplianceLogListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /compliance/status: + get: + operationId: GetComplianceStatus + description: | + List the last check run of each module-node-service tuple, for the nodes the + user can see: those whose app is published to one of the user's groups, every + node for a manager. + parameters: + - $ref: '#/components/parameters/inQueryProps' + - $ref: '#/components/parameters/inQueryLimit' + - $ref: '#/components/parameters/inQueryOffset' + - $ref: '#/components/parameters/inQueryMeta' + - $ref: '#/components/parameters/inQueryStats' + - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryFilter' + - $ref: '#/components/parameters/inQueryGroupby' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ComplianceStatusListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + delete: + operationId: DeleteComplianceStatus + description: | + Delete the last check run of a module-node-service tuple, named by the `id` + key of the body. Requires the CompExec privilege and the responsibility of the + node. The deletion is logged. + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + id: + type: integer + description: Id of the run (comp_status.id) + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /compliance/status/{status_id}: + get: + operationId: GetComplianceStatusRun + description: | + Display the last check run of a module-node-service tuple. + parameters: + - in: path + name: status_id + required: true + description: Id of the run (comp_status.id) + schema: + type: string + - $ref: '#/components/parameters/inQueryProps' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ComplianceStatusListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + delete: + operationId: DeleteComplianceStatusRun + description: | + Delete the last check run of a module-node-service tuple. Requires the + CompExec privilege and the responsibility of the node. The deletion is logged. + parameters: + - in: path + name: status_id + required: true + description: Id of the run (comp_status.id) + schema: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + components: responses: @@ -9572,6 +9784,51 @@ components: meta: $ref: '#/components/schemas/ListMeta' + ComplianceLogRow: + type: object + description: | + A run of a compliance module on a node, or on a service instance on that + node: its action (check, fixable, fix), its exit code (`run_status`: 0 ok, + 1 not ok, 2 not applicable) and its log. Every property is optional: the + `props` query parameter selects which columns the server returns. + properties: + id: + type: integer + run_module: + type: string + run_status: + type: integer + run_log: + type: string + run_date: + type: string + run_action: + type: string + rset_md5: + type: string + node_id: + type: string + svc_id: + type: string + + ComplianceLogListResponse: + type: object + required: + - data + properties: + data: + oneOf: + - type: array + items: + $ref: '#/components/schemas/ComplianceLogRow' + - type: object + additionalProperties: + type: object + additionalProperties: + type: integer + meta: + $ref: '#/components/schemas/ListMeta' + InstanceListResponse: type: object required: diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index fb9d4e5b..c8c1a5b1 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -123,6 +123,24 @@ type ServerInterface interface { // (POST /auth/node) PostAuthNode(ctx echo.Context) error + // (GET /compliance/logs) + GetComplianceLogs(ctx echo.Context, params GetComplianceLogsParams) error + + // (GET /compliance/logs/{log_id}) + GetComplianceLog(ctx echo.Context, logId string, params GetComplianceLogParams) error + + // (DELETE /compliance/status) + DeleteComplianceStatus(ctx echo.Context) error + + // (GET /compliance/status) + GetComplianceStatus(ctx echo.Context, params GetComplianceStatusParams) error + + // (DELETE /compliance/status/{status_id}) + DeleteComplianceStatusRun(ctx echo.Context, statusId string) error + + // (GET /compliance/status/{status_id}) + GetComplianceStatusRun(ctx echo.Context, statusId string, params GetComplianceStatusRunParams) error + // (DELETE /disks) DeleteDisks(ctx echo.Context) error @@ -1918,6 +1936,239 @@ func (w *ServerInterfaceWrapper) PostAuthNode(ctx echo.Context) error { return err } +// GetComplianceLogs converts echo context to params. +func (w *ServerInterfaceWrapper) GetComplianceLogs(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetComplianceLogsParams + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // ------------- Optional query parameter "limit" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) + } + + // ------------- Optional query parameter "offset" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) + } + + // ------------- Optional query parameter "meta" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) + } + + // ------------- Optional query parameter "stats" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) + } + + // ------------- Optional query parameter "orderby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) + } + + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + + // ------------- Optional query parameter "groupby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetComplianceLogs(ctx, params) + return err +} + +// GetComplianceLog converts echo context to params. +func (w *ServerInterfaceWrapper) GetComplianceLog(ctx echo.Context) error { + var err error + // ------------- Path parameter "log_id" ------------- + var logId string + + err = runtime.BindStyledParameterWithOptions("simple", "log_id", ctx.Param("log_id"), &logId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter log_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetComplianceLogParams + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetComplianceLog(ctx, logId, params) + return err +} + +// DeleteComplianceStatus converts echo context to params. +func (w *ServerInterfaceWrapper) DeleteComplianceStatus(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.DeleteComplianceStatus(ctx) + return err +} + +// GetComplianceStatus converts echo context to params. +func (w *ServerInterfaceWrapper) GetComplianceStatus(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetComplianceStatusParams + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // ------------- Optional query parameter "limit" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) + } + + // ------------- Optional query parameter "offset" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) + } + + // ------------- Optional query parameter "meta" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) + } + + // ------------- Optional query parameter "stats" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) + } + + // ------------- Optional query parameter "orderby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) + } + + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + + // ------------- Optional query parameter "groupby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetComplianceStatus(ctx, params) + return err +} + +// DeleteComplianceStatusRun converts echo context to params. +func (w *ServerInterfaceWrapper) DeleteComplianceStatusRun(ctx echo.Context) error { + var err error + // ------------- Path parameter "status_id" ------------- + var statusId string + + err = runtime.BindStyledParameterWithOptions("simple", "status_id", ctx.Param("status_id"), &statusId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter status_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.DeleteComplianceStatusRun(ctx, statusId) + return err +} + +// GetComplianceStatusRun converts echo context to params. +func (w *ServerInterfaceWrapper) GetComplianceStatusRun(ctx echo.Context) error { + var err error + // ------------- Path parameter "status_id" ------------- + var statusId string + + err = runtime.BindStyledParameterWithOptions("simple", "status_id", ctx.Param("status_id"), &statusId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter status_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetComplianceStatusRunParams + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetComplianceStatusRun(ctx, statusId, params) + return err +} + // DeleteDisks converts echo context to params. func (w *ServerInterfaceWrapper) DeleteDisks(ctx echo.Context) error { var err error @@ -10257,6 +10508,12 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.POST(options.BaseURL+"/apps_responsibles", wrapper.PostAppsResponsibles, options.OperationMiddlewares["PostAppsResponsibles"]...) router.GET(options.BaseURL+"/arrays", wrapper.GetArrays, options.OperationMiddlewares["GetArrays"]...) router.POST(options.BaseURL+"/auth/node", wrapper.PostAuthNode, options.OperationMiddlewares["PostAuthNode"]...) + router.GET(options.BaseURL+"/compliance/logs", wrapper.GetComplianceLogs, options.OperationMiddlewares["GetComplianceLogs"]...) + router.GET(options.BaseURL+"/compliance/logs/:log_id", wrapper.GetComplianceLog, options.OperationMiddlewares["GetComplianceLog"]...) + router.DELETE(options.BaseURL+"/compliance/status", wrapper.DeleteComplianceStatus, options.OperationMiddlewares["DeleteComplianceStatus"]...) + router.GET(options.BaseURL+"/compliance/status", wrapper.GetComplianceStatus, options.OperationMiddlewares["GetComplianceStatus"]...) + router.DELETE(options.BaseURL+"/compliance/status/:status_id", wrapper.DeleteComplianceStatusRun, options.OperationMiddlewares["DeleteComplianceStatusRun"]...) + router.GET(options.BaseURL+"/compliance/status/:status_id", wrapper.GetComplianceStatusRun, options.OperationMiddlewares["GetComplianceStatusRun"]...) router.DELETE(options.BaseURL+"/disks", wrapper.DeleteDisks, options.OperationMiddlewares["DeleteDisks"]...) router.GET(options.BaseURL+"/disks", wrapper.GetDisks, options.OperationMiddlewares["GetDisks"]...) router.POST(options.BaseURL+"/disks", wrapper.PostDisks, options.OperationMiddlewares["PostDisks"]...) @@ -10452,339 +10709,347 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "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", + "ZDo4H4zOBl8/ff3/AwAA//8=", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index def30dbc..b38e0544 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -372,6 +372,39 @@ type AppRow struct { Updated *string `json:"updated,omitempty"` } +// ComplianceLogListResponse defines model for ComplianceLogListResponse. +type ComplianceLogListResponse struct { + Data ComplianceLogListResponse_Data `json:"data"` + Meta *ListMeta `json:"meta,omitempty"` +} + +// ComplianceLogListResponseData0 defines model for . +type ComplianceLogListResponseData0 = []ComplianceLogRow + +// ComplianceLogListResponseData1 defines model for . +type ComplianceLogListResponseData1 map[string]map[string]int + +// ComplianceLogListResponse_Data defines model for ComplianceLogListResponse.Data. +type ComplianceLogListResponse_Data struct { + union json.RawMessage +} + +// ComplianceLogRow A run of a compliance module on a node, or on a service instance on that +// node: its action (check, fixable, fix), its exit code (`run_status`: 0 ok, +// 1 not ok, 2 not applicable) and its log. Every property is optional: the +// `props` query parameter selects which columns the server returns. +type ComplianceLogRow struct { + Id *int `json:"id,omitempty"` + NodeId *string `json:"node_id,omitempty"` + RsetMd5 *string `json:"rset_md5,omitempty"` + RunAction *string `json:"run_action,omitempty"` + RunDate *string `json:"run_date,omitempty"` + RunLog *string `json:"run_log,omitempty"` + RunModule *string `json:"run_module,omitempty"` + RunStatus *int `json:"run_status,omitempty"` + SvcId *string `json:"svc_id,omitempty"` +} + // ComplianceStatusListResponse defines model for ComplianceStatusListResponse. type ComplianceStatusListResponse struct { Data ComplianceStatusListResponse_Data `json:"data"` @@ -1871,6 +1904,104 @@ type PostAuthNodeJSONBody struct { Nodename string `json:"nodename"` } +// GetComplianceLogsParams defines parameters for GetComplianceLogs. +type GetComplianceLogsParams struct { + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` + + // Limit The maximum number of entries to return. 0 means no limit. + Limit *InQueryLimit `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Skip the first entries of the data cursor. + Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` + + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. + Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` + + // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. + Stats *InQueryStats `form:"stats,omitempty" json:"stats,omitempty"` + + // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). + Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` + + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). + Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` +} + +// GetComplianceLogParams defines parameters for GetComplianceLog. +type GetComplianceLogParams struct { + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` +} + +// DeleteComplianceStatusJSONBody defines parameters for DeleteComplianceStatus. +type DeleteComplianceStatusJSONBody struct { + // Id Id of the run (comp_status.id) + Id *int `json:"id,omitempty"` +} + +// GetComplianceStatusParams defines parameters for GetComplianceStatus. +type GetComplianceStatusParams struct { + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` + + // Limit The maximum number of entries to return. 0 means no limit. + Limit *InQueryLimit `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Skip the first entries of the data cursor. + Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` + + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. + Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` + + // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. + Stats *InQueryStats `form:"stats,omitempty" json:"stats,omitempty"` + + // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). + Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` + + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). + Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` +} + +// GetComplianceStatusRunParams defines parameters for GetComplianceStatusRun. +type GetComplianceStatusRunParams struct { + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` +} + // DeleteDisksJSONBody defines parameters for DeleteDisks. type DeleteDisksJSONBody struct { // DiskId Disk identifier @@ -5287,6 +5418,9 @@ type PostAppsResponsiblesJSONRequestBody PostAppsResponsiblesJSONBody // PostAuthNodeJSONRequestBody defines body for PostAuthNode for application/json ContentType. type PostAuthNodeJSONRequestBody PostAuthNodeJSONBody +// DeleteComplianceStatusJSONRequestBody defines body for DeleteComplianceStatus for application/json ContentType. +type DeleteComplianceStatusJSONRequestBody DeleteComplianceStatusJSONBody + // DeleteDisksJSONRequestBody defines body for DeleteDisks for application/json ContentType. type DeleteDisksJSONRequestBody DeleteDisksJSONBody @@ -5576,6 +5710,68 @@ func (t *AppListResponse_Data) UnmarshalJSON(b []byte) error { return err } +// AsComplianceLogListResponseData0 returns the union data inside the ComplianceLogListResponse_Data as a ComplianceLogListResponseData0 +func (t ComplianceLogListResponse_Data) AsComplianceLogListResponseData0() (ComplianceLogListResponseData0, error) { + var body ComplianceLogListResponseData0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromComplianceLogListResponseData0 overwrites any union data inside the ComplianceLogListResponse_Data as the provided ComplianceLogListResponseData0 +func (t *ComplianceLogListResponse_Data) FromComplianceLogListResponseData0(v ComplianceLogListResponseData0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeComplianceLogListResponseData0 performs a merge with any union data inside the ComplianceLogListResponse_Data, using the provided ComplianceLogListResponseData0 +func (t *ComplianceLogListResponse_Data) MergeComplianceLogListResponseData0(v ComplianceLogListResponseData0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsComplianceLogListResponseData1 returns the union data inside the ComplianceLogListResponse_Data as a ComplianceLogListResponseData1 +func (t ComplianceLogListResponse_Data) AsComplianceLogListResponseData1() (ComplianceLogListResponseData1, error) { + var body ComplianceLogListResponseData1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromComplianceLogListResponseData1 overwrites any union data inside the ComplianceLogListResponse_Data as the provided ComplianceLogListResponseData1 +func (t *ComplianceLogListResponse_Data) FromComplianceLogListResponseData1(v ComplianceLogListResponseData1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeComplianceLogListResponseData1 performs a merge with any union data inside the ComplianceLogListResponse_Data, using the provided ComplianceLogListResponseData1 +func (t *ComplianceLogListResponse_Data) MergeComplianceLogListResponseData1(v ComplianceLogListResponseData1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t ComplianceLogListResponse_Data) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *ComplianceLogListResponse_Data) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + // AsComplianceStatusListResponseData0 returns the union data inside the ComplianceStatusListResponse_Data as a ComplianceStatusListResponseData0 func (t ComplianceStatusListResponse_Data) AsComplianceStatusListResponseData0() (ComplianceStatusListResponseData0, error) { var body ComplianceStatusListResponseData0 diff --git a/server/handlers/compliance_status.go b/server/handlers/compliance_status.go new file mode 100644 index 00000000..efe63ed3 --- /dev/null +++ b/server/handlers/compliance_status.go @@ -0,0 +1,153 @@ +package serverhandlers + +import ( + "context" + "fmt" + "net/http" + "strconv" + + "github.com/google/uuid" + "github.com/labstack/echo/v4" + + "github.com/opensvc/oc3/cdb" + "github.com/opensvc/oc3/server" + "github.com/opensvc/oc3/util/echolog" + "github.com/opensvc/oc3/util/logkey" +) + +// parseCompID reads the integer id of a compliance record from a path. +func parseCompID(raw string) (int64, error) { + id, err := strconv.ParseInt(raw, 10, 64) + if err != nil { + return 0, httpErrorf(http.StatusBadRequest, "invalid id %q: an integer is expected", raw) + } + return id, nil +} + +// GetComplianceLogs handles GET /compliance/logs, as the historical +// rest_get_compliance_logs: the runs of the nodes the caller may see. +func (a *Api) GetComplianceLogs(c echo.Context, params server.GetComplianceLogsParams) error { + return a.handleList(c, "GetComplianceLogs", "comp_log", listEndpointParams{ + props: params.Props, limit: params.Limit, offset: params.Offset, + meta: params.Meta, stats: params.Stats, orderby: params.Orderby, groupby: params.Groupby, + filter: params.Filter, + }, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetComplianceLogs(ctx, nil, p) + }) +} + +// GetComplianceLog handles GET /compliance/logs/{log_id}. +func (a *Api) GetComplianceLog(c echo.Context, logId string, params server.GetComplianceLogParams) error { + id, err := parseCompID(logId) + if err != nil { + return httpProblem(c, err) + } + return a.handleItem(c, "GetComplianceLog", "comp_log", "id", logId, listEndpointParams{ + props: params.Props, + }, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetComplianceLogs(ctx, &id, p) + }) +} + +// GetComplianceStatus handles GET /compliance/status, as the historical +// rest_get_compliance_status: the last runs of the nodes the caller may see. +func (a *Api) GetComplianceStatus(c echo.Context, params server.GetComplianceStatusParams) error { + return a.handleList(c, "GetComplianceStatus", "comp_status", listEndpointParams{ + props: params.Props, limit: params.Limit, offset: params.Offset, + meta: params.Meta, stats: params.Stats, orderby: params.Orderby, groupby: params.Groupby, + filter: params.Filter, + }, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetComplianceStatus(ctx, nil, p) + }) +} + +// GetComplianceStatusRun handles GET /compliance/status/{status_id}. +func (a *Api) GetComplianceStatusRun(c echo.Context, statusId string, params server.GetComplianceStatusRunParams) error { + id, err := parseCompID(statusId) + if err != nil { + return httpProblem(c, err) + } + return a.handleItem(c, "GetComplianceStatusRun", "comp_status", "id", statusId, listEndpointParams{ + props: params.Props, + }, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetComplianceStatus(ctx, &id, p) + }) +} + +// DeleteComplianceStatusRun handles DELETE /compliance/status/{status_id}. +func (a *Api) DeleteComplianceStatusRun(c echo.Context, statusId string) error { + id, err := parseCompID(statusId) + if err != nil { + return httpProblem(c, err) + } + return a.deleteComplianceStatusRun(c, id) +} + +// DeleteComplianceStatus handles DELETE /compliance/status, the bulk form taking +// the id of the run in the body, as the historical rest_delete_compliance_status_runs. +func (a *Api) DeleteComplianceStatus(c echo.Context) error { + var body server.DeleteComplianceStatusJSONRequestBody + if err := c.Bind(&body); err != nil { + return JSONProblem(c, http.StatusBadRequest, err.Error()) + } + if body.Id == nil { + return JSONProblemf(c, http.StatusBadRequest, "The 'id' key is mandatory") + } + return a.deleteComplianceStatusRun(c, int64(*body.Id)) +} + +// deleteComplianceStatusRun deletes the last check run of a module-node-service +// tuple, as the historical rest_delete_compliance_status_run: the CompExec +// privilege and the responsibility of the node are required, and the deletion is +// logged. +func (a *Api) deleteComplianceStatusRun(c echo.Context, id int64) error { + log := echolog.GetLogHandler(c, "DeleteComplianceStatusRun") + ctx := c.Request().Context() + if !IsManager(c) && !HasGroup(c, "CompExec") { + return JSONProblemf(c, http.StatusForbidden, "the CompExec privilege is required") + } + groups := UserGroupsFromContext(c) + run, err := a.ODB.CompStatusRunVisible(ctx, id, groups, IsManager(c)) + if err != nil { + return httpProblem(c, httpInternal(log, "cannot read the run", err)) + } + if run == nil { + return c.JSON(http.StatusOK, map[string]string{"info": fmt.Sprintf("Run %d not found or you are not responsible for the node", id)}) + } + if run.NodeID != "" { + responsible, err := a.ODB.NodeResponsible(ctx, run.NodeID, groups, IsManager(c)) + if err != nil { + return httpProblem(c, httpInternal(log, "cannot check the node responsibility", err)) + } + if !responsible { + return JSONProblemf(c, http.StatusForbidden, "user is not responsible for node %s", run.NodeID) + } + } + if err := a.ODB.DeleteCompStatusRun(ctx, id); err != nil { + return httpProblem(c, httpInternal(log, "cannot delete the run", err)) + } + target := "node " + run.Nodename + if run.SvcID != "" { + target = "service " + run.Svcname + " on " + target + } + a.compLog(c, "compliance.status.delete", "deleted run module %(module)s on %(target)s", + map[string]any{"module": run.RunModule, "target": target}, run.NodeID, run.SvcID) + a.notifyChanges(log, ctx) + return c.JSON(http.StatusOK, map[string]string{"info": fmt.Sprintf("Run %d deleted", id)}) +} + +// compLog writes a compliance change to the collector log, as _log() does in the +// historical collector. +func (a *Api) compLog(c echo.Context, action, format string, dict map[string]any, nodeID, svcID string) { + userEmail, _ := c.Get(XUserEmail).(string) + entry := cdb.LogEntry{Action: action, User: userEmail, Fmt: format, Dict: dict, Level: "info"} + if id, err := uuid.Parse(nodeID); err == nil { + entry.NodeID = &id + } + if id, err := uuid.Parse(svcID); err == nil { + entry.SvcID = &id + } + if err := a.ODB.Log(c.Request().Context(), entry); err != nil { + echolog.GetLogHandler(c, action).Error("cannot write audit log", logkey.Error, err) + } +} From 2a59c8cfac9ff83b9590a3aa9a7e481e44ef82be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Mon, 28 Sep 2026 13:29:09 +0200 Subject: [PATCH 37/61] Add the compliance rulesets endpoints Port the ruleset endpoints of the historical api_compliance: - GET /compliance/rulesets and /rulesets/{rset_id} (id or name), the rulesets published to one of the caller's groups; - POST /compliance/rulesets, creating a ruleset published to and under the responsibility of the caller's default group (the Manager group without one), or updating it when the name exists; - POST /compliance/rulesets/{rset_id}, updating its name, type or publicity, checked; - PUT /compliance/rulesets/{rset_id} action=clone, copying its variables, children and, for a contextual ruleset, its filterset as _clone; - DELETE /compliance/rulesets/{rset_id} and the bulk DELETE /compliance/rulesets ({"id": ...}), removing its relations; - GET /compliance/rulesets/{rset_id}/usage and /am_i_responsible. Changes require the CompManager privilege and, but for creation, the responsibility of the ruleset; refusals are 403, unknown rulesets 404, taken names 409. Every change is logged, and creation, renaming, cloning and deletion rebuild comp_rulesets_chains, as comp_rulesets_chains(). Bodies may be JSON or form-encoded, as the historical examples post. --- cdb/db_compliance_rulesets.go | 400 +++++++++++ server/api.yaml | 399 +++++++++++ server/codegen_server_gen.go | 957 ++++++++++++++++--------- server/codegen_type_gen.go | 169 +++++ server/handlers/compliance_common.go | 125 ++++ server/handlers/compliance_rulesets.go | 336 +++++++++ 6 files changed, 2045 insertions(+), 341 deletions(-) create mode 100644 cdb/db_compliance_rulesets.go create mode 100644 server/handlers/compliance_common.go create mode 100644 server/handlers/compliance_rulesets.go diff --git a/cdb/db_compliance_rulesets.go b/cdb/db_compliance_rulesets.go new file mode 100644 index 00000000..390231b0 --- /dev/null +++ b/cdb/db_compliance_rulesets.go @@ -0,0 +1,400 @@ +package cdb + +import ( + "context" + "database/sql" + "errors" + "fmt" + "strconv" + "strings" +) + +// rolesCond restricts an auth_group alias to the caller's groups, "1=0" without +// any: the join condition of the publication and responsibility checks. +func rolesCond(alias string, groups []string, orgOnly bool) (string, []any) { + clean := cleanGroups(groups) + if len(clean) == 0 { + return "1=0", nil + } + args := make([]any, len(clean)) + for i, g := range clean { + args[i] = g + } + cond := alias + ".role IN (" + Placeholders(len(clean)) + ")" + if orgOnly { + cond += " AND " + alias + ".privilege = 'F'" + } + return cond, args +} + +// compRulesetVisibleCond restricts comp_rulesets to the rulesets published to one +// of the caller's groups, every ruleset for a manager, as the historical +// rest_get_compliance_rulesets. +func compRulesetVisibleCond(groups []string, isManager bool) (string, []any) { + if isManager { + return "1=1", nil + } + cond, args := rolesCond("ag", groups, false) + return "comp_rulesets.id IN (SELECT p.ruleset_id FROM comp_ruleset_team_publication p" + + " JOIN auth_group ag ON ag.id = p.group_id WHERE " + cond + ")", args +} + +// GetComplianceRulesets lists the rulesets the caller may see; one when id is set. +func (oDb *DB) GetComplianceRulesets(ctx context.Context, id *int64, p ListParams) ([]map[string]any, error) { + cond, args := compRulesetVisibleCond(p.Groups, p.IsManager) + conds := []string{cond} + if id != nil { + conds = append(conds, "comp_rulesets.id = ?") + args = append(args, *id) + } + return oDb.listQuery(ctx, "getComplianceRulesets", "comp_rulesets", conds, args, "comp_rulesets.ruleset_name", p) +} + +// CompRulesetID resolves a ruleset given by id or by name, as ruleset_id_q(); +// false when there is none. +func (oDb *DB) CompRulesetID(ctx context.Context, idOrName string) (int64, bool, error) { + var id int64 + var err error + if n, convErr := strconv.ParseInt(idOrName, 10, 64); convErr == nil { + err = oDb.DB.QueryRowContext(ctx, "SELECT id FROM comp_rulesets WHERE id = ?", n).Scan(&id) + } else { + err = oDb.DB.QueryRowContext(ctx, "SELECT id FROM comp_rulesets WHERE ruleset_name = ? LIMIT 1", idOrName).Scan(&id) + } + switch { + case errors.Is(err, sql.ErrNoRows): + return 0, false, nil + case err != nil: + return 0, false, fmt.Errorf("compRulesetID: %w", err) + } + return id, true, nil +} + +// CompRulesetVisible tells whether a ruleset is published to one of the caller's +// groups; always for a manager. +func (oDb *DB) CompRulesetVisible(ctx context.Context, id int64, groups []string, isManager bool) (bool, error) { + cond, args := compRulesetVisibleCond(groups, isManager) + return oDb.exists(ctx, "compRulesetVisible", "SELECT 1 FROM comp_rulesets WHERE comp_rulesets.id = ? AND "+cond, append([]any{id}, args...)...) +} + +// CompRulesetResponsible tells whether one of the caller's organization groups is +// responsible for a ruleset, as ruleset_responsible(); always for a manager. +func (oDb *DB) CompRulesetResponsible(ctx context.Context, id int64, groups []string, isManager bool) (bool, error) { + if isManager { + return oDb.exists(ctx, "compRulesetResponsible", "SELECT 1 FROM comp_rulesets WHERE id = ?", id) + } + cond, args := rolesCond("ag", groups, true) + return oDb.exists(ctx, "compRulesetResponsible", "SELECT 1 FROM comp_ruleset_team_responsible r"+ + " JOIN auth_group ag ON ag.id = r.group_id WHERE r.ruleset_id = ? AND "+cond, append([]any{id}, args...)...) +} + +func (oDb *DB) exists(ctx context.Context, name, query string, args ...any) (bool, error) { + var one int + err := oDb.DB.QueryRowContext(ctx, query+" LIMIT 1", args...).Scan(&one) + switch { + case errors.Is(err, sql.ErrNoRows): + return false, nil + case err != nil: + return false, fmt.Errorf("%s: %w", name, err) + } + return true, nil +} + +// CompRulesetName returns the name of a ruleset by id. +func (oDb *DB) CompRulesetNameByID(ctx context.Context, id int64) (string, error) { + var name sql.NullString + if err := oDb.DB.QueryRowContext(ctx, "SELECT ruleset_name FROM comp_rulesets WHERE id = ?", id).Scan(&name); err != nil { + return "", fmt.Errorf("compRulesetNameByID: %w", err) + } + return name.String, nil +} + +// DefaultGroupOrManager returns the group a new compliance object is given to: +// the user's default group, else the Manager group, as add_default_teams(). +func (oDb *DB) DefaultGroupOrManager(ctx context.Context, userID *int64) (int64, error) { + if userID != nil { + if gid, ok, err := oDb.UserDefaultGroupID(ctx, *userID); err != nil { + return 0, err + } else if ok { + return gid, nil + } + } + var gid int64 + if err := oDb.DB.QueryRowContext(ctx, "SELECT id FROM auth_group WHERE role = 'Manager' LIMIT 1").Scan(&gid); err != nil { + return 0, fmt.Errorf("defaultGroupOrManager: %w", err) + } + return gid, nil +} + +// CreateCompRuleset inserts a ruleset, published to and under the responsibility +// of groupID, as create_ruleset() and add_default_teams(). +func (oDb *DB) CreateCompRuleset(ctx context.Context, name, rtype, public string, groupID int64) (int64, error) { + res, err := oDb.DB.ExecContext(ctx, "INSERT INTO comp_rulesets (ruleset_name, ruleset_type, ruleset_public) VALUES (?, ?, ?)", + name, rtype, public) + if err != nil { + return 0, fmt.Errorf("createCompRuleset: %w", err) + } + id, err := res.LastInsertId() + if err != nil { + return 0, fmt.Errorf("createCompRuleset: %w", err) + } + if err := oDb.addRulesetTeams(ctx, id, groupID); err != nil { + return 0, err + } + oDb.SetChange("comp_rulesets") + return id, nil +} + +func (oDb *DB) addRulesetTeams(ctx context.Context, rulesetID, groupID int64) error { + for _, table := range []string{"comp_ruleset_team_responsible", "comp_ruleset_team_publication"} { + if _, err := oDb.DB.ExecContext(ctx, "INSERT INTO "+table+" (ruleset_id, group_id) VALUES (?, ?)", rulesetID, groupID); err != nil { + return fmt.Errorf("addRulesetTeams: %w", err) + } + oDb.SetChange(table) + } + return nil +} + +// UpdateCompRuleset sets the given columns of a ruleset; the keys are checked by +// the caller. +func (oDb *DB) UpdateCompRuleset(ctx context.Context, id int64, fields map[string]any) error { + if len(fields) == 0 { + return nil + } + sets := make([]string, 0, len(fields)) + args := make([]any, 0, len(fields)+1) + for _, k := range sortedKeys(fields) { + sets = append(sets, k+" = ?") + args = append(args, fields[k]) + } + args = append(args, id) + if _, err := oDb.DB.ExecContext(ctx, "UPDATE comp_rulesets SET "+strings.Join(sets, ", ")+" WHERE id = ?", args...); err != nil { + return fmt.Errorf("updateCompRuleset: %w", err) + } + oDb.SetChange("comp_rulesets") + return nil +} + +// DeleteCompRuleset deletes a ruleset with its filtersets, node and service +// attachments, publication and responsible groups, parent and child relations, +// variables and moduleset links, as delete_ruleset(). +func (oDb *DB) DeleteCompRuleset(ctx context.Context, id int64) error { + for _, q := range []struct{ table, cond string }{ + {"comp_rulesets_filtersets", "ruleset_id = ?"}, + {"comp_rulesets_nodes", "ruleset_id = ?"}, + {"comp_rulesets_services", "ruleset_id = ?"}, + {"comp_ruleset_team_publication", "ruleset_id = ?"}, + {"comp_ruleset_team_responsible", "ruleset_id = ?"}, + {"comp_rulesets_rulesets", "parent_rset_id = ? OR child_rset_id = ?"}, + {"comp_rulesets_variables", "ruleset_id = ?"}, + {"comp_rulesets", "id = ?"}, + {"comp_moduleset_ruleset", "ruleset_id = ?"}, + } { + args := []any{id} + if strings.Count(q.cond, "?") == 2 { + args = append(args, id) + } + if _, err := oDb.DB.ExecContext(ctx, "DELETE FROM "+q.table+" WHERE "+q.cond, args...); err != nil { + return fmt.Errorf("deleteCompRuleset: %s: %w", q.table, err) + } + oDb.SetChange(q.table) + } + return nil +} + +// CloneCompRuleset copies a ruleset as "_clone": its type and publicity, +// the filterset of a contextual ruleset, its variables (authored by author), its +// children, under the responsibility and publication of groupID, as +// clone_ruleset(). It returns the id and the name of the copy. +func (oDb *DB) CloneCompRuleset(ctx context.Context, id int64, author string, groupID int64) (int64, string, error) { + var name, rtype, public sql.NullString + err := oDb.DB.QueryRowContext(ctx, "SELECT ruleset_name, ruleset_type, ruleset_public FROM comp_rulesets WHERE id = ?", id). + Scan(&name, &rtype, &public) + if errors.Is(err, sql.ErrNoRows) { + return 0, "", ErrCompNotFound + } else if err != nil { + return 0, "", fmt.Errorf("cloneCompRuleset: %w", err) + } + cloneName := name.String + "_clone" + if _, found, err := oDb.CompRulesetID(ctx, cloneName); err != nil { + return 0, "", err + } else if found { + return 0, "", fmt.Errorf("%w: a ruleset named %s already exists", ErrCompConflict, cloneName) + } + res, err := oDb.DB.ExecContext(ctx, "INSERT INTO comp_rulesets (ruleset_name, ruleset_type, ruleset_public) VALUES (?, ?, ?)", + cloneName, rtype, public) + if err != nil { + return 0, "", fmt.Errorf("cloneCompRuleset: %w", err) + } + newID, err := res.LastInsertId() + if err != nil { + return 0, "", fmt.Errorf("cloneCompRuleset: %w", err) + } + stmts := []struct { + query string + args []any + }{ + {"INSERT INTO comp_rulesets_variables (ruleset_id, var_name, var_class, var_value, var_author, var_updated)" + + " SELECT ?, var_name, var_class, var_value, ?, NOW() FROM comp_rulesets_variables WHERE ruleset_id = ?", []any{newID, author, id}}, + {"INSERT INTO comp_rulesets_rulesets (parent_rset_id, child_rset_id)" + + " SELECT ?, child_rset_id FROM comp_rulesets_rulesets WHERE parent_rset_id = ?", []any{newID, id}}, + } + if rtype.String == "contextual" { + stmts = append(stmts, struct { + query string + args []any + }{"INSERT INTO comp_rulesets_filtersets (ruleset_id, fset_id)" + + " SELECT ?, fset_id FROM comp_rulesets_filtersets WHERE ruleset_id = ? LIMIT 1", []any{newID, id}}) + } + for _, st := range stmts { + if _, err := oDb.DB.ExecContext(ctx, st.query, st.args...); err != nil { + return 0, "", fmt.Errorf("cloneCompRuleset: %w", err) + } + } + if err := oDb.addRulesetTeams(ctx, newID, groupID); err != nil { + return 0, "", err + } + for _, t := range []string{"comp_rulesets", "comp_rulesets_variables", "comp_rulesets_rulesets", "comp_rulesets_filtersets"} { + oDb.SetChange(t) + } + return newID, cloneName, nil +} + +// CompRulesetsChains rebuilds comp_rulesets_chains, the flattened ruleset +// hierarchy: one row per ruleset (chain_len 1), and one per path from a ruleset to +// each of its descendants, named "a > b > c", as comp_rulesets_chains(). +func (oDb *DB) CompRulesetsChains(ctx context.Context) error { + names := map[int64]string{} + var order []int64 + rows, err := oDb.DB.QueryContext(ctx, "SELECT id, COALESCE(ruleset_name, '') FROM comp_rulesets ORDER BY id") + if err != nil { + return fmt.Errorf("compRulesetsChains: %w", err) + } + for rows.Next() { + var id int64 + var name string + if err := rows.Scan(&id, &name); err != nil { + _ = rows.Close() + return fmt.Errorf("compRulesetsChains: %w", err) + } + names[id] = name + order = append(order, id) + } + _ = rows.Close() + children := map[int64][]int64{} + rows, err = oDb.DB.QueryContext(ctx, "SELECT rr.parent_rset_id, rr.child_rset_id FROM comp_rulesets_rulesets rr"+ + " JOIN comp_rulesets r ON r.id = rr.child_rset_id ORDER BY rr.id") + if err != nil { + return fmt.Errorf("compRulesetsChains: %w", err) + } + for rows.Next() { + var parent, child int64 + if err := rows.Scan(&parent, &child); err != nil { + _ = rows.Close() + return fmt.Errorf("compRulesetsChains: %w", err) + } + children[parent] = append(children[parent], child) + } + _ = rows.Close() + + type chain struct { + head, tail int64 + length int + text string + } + var chains []chain + var walk func(path []int64) + walk = func(path []int64) { + last := path[len(path)-1] + for _, child := range children[last] { + // A ruleset already in the path would loop: the relation is refused on + // attachment, a stored cycle is not followed. + loop := false + for _, p := range path { + if p == child { + loop = true + } + } + if loop { + continue + } + next := append(append([]int64{}, path...), child) + parts := make([]string, len(next)) + for i, id := range next { + parts[i] = names[id] + } + chains = append(chains, chain{next[0], child, len(next), strings.Join(parts, " > ")}) + walk(next) + } + } + for _, id := range order { + chains = append(chains, chain{id, id, 1, ""}) + walk([]int64{id}) + } + + if _, err := oDb.DB.ExecContext(ctx, "DELETE FROM comp_rulesets_chains"); err != nil { + return fmt.Errorf("compRulesetsChains: %w", err) + } + for start := 0; start < len(chains); start += 500 { + end := min(start+500, len(chains)) + values := make([]string, 0, end-start) + args := make([]any, 0, 4*(end-start)) + for _, c := range chains[start:end] { + values = append(values, "(?, ?, ?, ?)") + args = append(args, c.head, c.tail, c.length, c.text) + } + if _, err := oDb.DB.ExecContext(ctx, "INSERT INTO comp_rulesets_chains (head_rset_id, tail_rset_id, chain_len, chain) VALUES "+ + strings.Join(values, ", ")+" ON DUPLICATE KEY UPDATE chain_len = VALUES(chain_len), chain = VALUES(chain)", args...); err != nil { + return fmt.Errorf("compRulesetsChains: %w", err) + } + } + oDb.SetChange("comp_rulesets_chains") + return nil +} + +// CompRulesetUsage lists what uses a ruleset: the modulesets and the parent +// rulesets holding it, the nodes and the services it is attached to. +func (oDb *DB) CompRulesetUsage(ctx context.Context, id int64) (map[string][]map[string]any, error) { + out := map[string][]map[string]any{} + for _, q := range []struct{ key, idKey, nameKey, query string }{ + {"modulesets", "id", "modset_name", "SELECT m.id, m.modset_name FROM comp_moduleset_ruleset mr JOIN comp_moduleset m ON m.id = mr.modset_id WHERE mr.ruleset_id = ? ORDER BY m.modset_name"}, + {"rulesets", "id", "ruleset_name", "SELECT r.id, COALESCE(r.ruleset_name, '') FROM comp_rulesets_rulesets rr JOIN comp_rulesets r ON r.id = rr.parent_rset_id WHERE rr.child_rset_id = ? ORDER BY r.ruleset_name"}, + {"nodes", "node_id", "nodename", "SELECT rn.node_id, COALESCE(n.nodename, '') FROM comp_rulesets_nodes rn JOIN nodes n ON n.node_id = rn.node_id WHERE rn.ruleset_id = ? ORDER BY n.nodename"}, + {"services", "svc_id", "svcname", "SELECT rs.svc_id, COALESCE(s.svcname, '') FROM comp_rulesets_services rs JOIN services s ON s.svc_id = rs.svc_id WHERE rs.ruleset_id = ? ORDER BY s.svcname"}, + } { + entries, err := oDb.namedPairs(ctx, q.query, id, q.idKey, q.nameKey) + if err != nil { + return nil, fmt.Errorf("compRulesetUsage: %s: %w", q.key, err) + } + out[q.key] = entries + } + return out, nil +} + +// namedPairs runs a query returning (id, name) rows, as a list of objects with +// the given keys; an integer id stays a number. +func (oDb *DB) namedPairs(ctx context.Context, query string, arg any, idKey, nameKey string) ([]map[string]any, error) { + rows, err := oDb.DB.QueryContext(ctx, query, arg) + if err != nil { + return nil, err + } + defer func() { _ = rows.Close() }() + out := []map[string]any{} + for rows.Next() { + var id, name sql.NullString + if err := rows.Scan(&id, &name); err != nil { + return nil, err + } + var idv any = id.String + if n, err := strconv.ParseInt(id.String, 10, 64); err == nil && idKey == "id" { + idv = n + } + out = append(out, map[string]any{idKey: idv, nameKey: name.String}) + } + return out, rows.Err() +} + +// Errors of the compliance designer, mapped to HTTP statuses by the handlers. +var ( + ErrCompNotFound = errors.New("not found") + ErrCompConflict = errors.New("conflict") +) diff --git a/server/api.yaml b/server/api.yaml index d642bcc5..cc171bf3 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -9000,6 +9000,363 @@ paths: - basicAuth: [ ] - bearerAuth: [ ] + /compliance/rulesets: + get: + operationId: GetComplianceRulesets + description: | + List the rulesets published to one of the user's groups, every ruleset for a + manager. + parameters: + - $ref: '#/components/parameters/inQueryProps' + - $ref: '#/components/parameters/inQueryLimit' + - $ref: '#/components/parameters/inQueryOffset' + - $ref: '#/components/parameters/inQueryMeta' + - $ref: '#/components/parameters/inQueryStats' + - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryFilter' + - $ref: '#/components/parameters/inQueryGroupby' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/RulesetListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + post: + operationId: PostComplianceRulesets + description: | + Create a ruleset named ruleset_name, of type explicit and public unless given, + published to and under the responsibility of the user's default group (the + Manager group without one). When a ruleset of that name exists, its other given + properties are updated instead, as POST /compliance/rulesets/{rset_id}. + Requires the CompManager privilege. The change is logged and the ruleset chains + are rebuilt. + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + ruleset_name: + type: string + ruleset_type: + type: string + enum: [explicit, contextual] + ruleset_public: + description: A boolean, or "T" / "F" as stored. + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/RulesetListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 409: + $ref: '#/components/responses/409' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + delete: + operationId: DeleteComplianceRulesets + description: | + Delete the ruleset named by the id key of the body, as + DELETE /compliance/rulesets/{rset_id}. + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + id: + description: Ruleset id or name + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /compliance/rulesets/{rset_id}: + get: + operationId: GetComplianceRuleset + description: | + Display a ruleset published to one of the user's groups. + parameters: + - in: path + name: rset_id + required: true + description: Ruleset id or name + schema: + type: string + - $ref: '#/components/parameters/inQueryProps' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/RulesetListResponse' + 401: + $ref: '#/components/responses/401' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + post: + operationId: PostComplianceRuleset + description: | + Update the given properties of a ruleset. Requires the CompManager privilege and + the responsibility of the ruleset. The change is logged. + parameters: + - in: path + name: rset_id + required: true + description: Ruleset id or name + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + ruleset_name: + type: string + ruleset_type: + type: string + enum: [explicit, contextual] + ruleset_public: + description: A boolean, or "T" / "F" as stored. + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/RulesetListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 409: + $ref: '#/components/responses/409' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + put: + operationId: PutComplianceRuleset + description: | + Special actions on a ruleset. `clone` copies it as "_clone", with its type, + publicity, variables, children and, for a contextual ruleset, its filterset, + published to and under the responsibility of the user's default group. Requires + the CompManager privilege. + parameters: + - in: path + name: rset_id + required: true + description: Ruleset id or name + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [action] + properties: + action: + type: string + enum: [clone] + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 409: + $ref: '#/components/responses/409' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + delete: + operationId: DeleteComplianceRuleset + description: | + Delete a ruleset, with its parent and child relations, node and service + attachments, publication and responsible groups, variables, filtersets and + moduleset links. Requires the CompManager privilege and the responsibility of + the ruleset. The deletion is logged. + parameters: + - in: path + name: rset_id + required: true + description: Ruleset id or name + schema: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /compliance/rulesets/{rset_id}/usage: + get: + operationId: GetComplianceRulesetUsage + description: | + Display what uses a ruleset published to one of the user's groups: the + modulesets and parent rulesets holding it, the nodes and services it is attached + to. + parameters: + - in: path + name: rset_id + required: true + description: Ruleset id or name + schema: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + data: + $ref: '#/components/schemas/RulesetUsage' + 401: + $ref: '#/components/responses/401' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /compliance/rulesets/{rset_id}/am_i_responsible: + get: + operationId: GetComplianceRulesetAmIResponsible + description: | + Tell whether one of the user's groups is responsible for the ruleset. + parameters: + - in: path + name: rset_id + required: true + description: Ruleset id or name + schema: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + data: + type: boolean + 401: + $ref: '#/components/responses/401' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + components: responses: @@ -9829,6 +10186,48 @@ components: meta: $ref: '#/components/schemas/ListMeta' + RulesetUsage: + type: object + description: What uses a ruleset. + properties: + modulesets: + type: array + items: + type: object + properties: + id: + type: integer + modset_name: + type: string + rulesets: + description: The rulesets holding this one as a child. + type: array + items: + type: object + properties: + id: + type: integer + ruleset_name: + type: string + nodes: + type: array + items: + type: object + properties: + node_id: + type: string + nodename: + type: string + services: + type: array + items: + type: object + properties: + svc_id: + type: string + svcname: + type: string + InstanceListResponse: type: object required: diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index c8c1a5b1..3b21f69b 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -129,6 +129,33 @@ type ServerInterface interface { // (GET /compliance/logs/{log_id}) GetComplianceLog(ctx echo.Context, logId string, params GetComplianceLogParams) error + // (DELETE /compliance/rulesets) + DeleteComplianceRulesets(ctx echo.Context) error + + // (GET /compliance/rulesets) + GetComplianceRulesets(ctx echo.Context, params GetComplianceRulesetsParams) error + + // (POST /compliance/rulesets) + PostComplianceRulesets(ctx echo.Context) error + + // (DELETE /compliance/rulesets/{rset_id}) + DeleteComplianceRuleset(ctx echo.Context, rsetId string) error + + // (GET /compliance/rulesets/{rset_id}) + GetComplianceRuleset(ctx echo.Context, rsetId string, params GetComplianceRulesetParams) error + + // (POST /compliance/rulesets/{rset_id}) + PostComplianceRuleset(ctx echo.Context, rsetId string) error + + // (PUT /compliance/rulesets/{rset_id}) + PutComplianceRuleset(ctx echo.Context, rsetId string) error + + // (GET /compliance/rulesets/{rset_id}/am_i_responsible) + GetComplianceRulesetAmIResponsible(ctx echo.Context, rsetId string) error + + // (GET /compliance/rulesets/{rset_id}/usage) + GetComplianceRulesetUsage(ctx echo.Context, rsetId string) error + // (DELETE /compliance/status) DeleteComplianceStatus(ctx echo.Context) error @@ -2036,6 +2063,232 @@ func (w *ServerInterfaceWrapper) GetComplianceLog(ctx echo.Context) error { return err } +// DeleteComplianceRulesets converts echo context to params. +func (w *ServerInterfaceWrapper) DeleteComplianceRulesets(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.DeleteComplianceRulesets(ctx) + return err +} + +// GetComplianceRulesets converts echo context to params. +func (w *ServerInterfaceWrapper) GetComplianceRulesets(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetComplianceRulesetsParams + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // ------------- Optional query parameter "limit" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) + } + + // ------------- Optional query parameter "offset" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) + } + + // ------------- Optional query parameter "meta" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) + } + + // ------------- Optional query parameter "stats" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) + } + + // ------------- Optional query parameter "orderby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) + } + + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + + // ------------- Optional query parameter "groupby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetComplianceRulesets(ctx, params) + return err +} + +// PostComplianceRulesets converts echo context to params. +func (w *ServerInterfaceWrapper) PostComplianceRulesets(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostComplianceRulesets(ctx) + return err +} + +// DeleteComplianceRuleset converts echo context to params. +func (w *ServerInterfaceWrapper) DeleteComplianceRuleset(ctx echo.Context) error { + var err error + // ------------- Path parameter "rset_id" ------------- + var rsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "rset_id", ctx.Param("rset_id"), &rsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter rset_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.DeleteComplianceRuleset(ctx, rsetId) + return err +} + +// GetComplianceRuleset converts echo context to params. +func (w *ServerInterfaceWrapper) GetComplianceRuleset(ctx echo.Context) error { + var err error + // ------------- Path parameter "rset_id" ------------- + var rsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "rset_id", ctx.Param("rset_id"), &rsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter rset_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetComplianceRulesetParams + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetComplianceRuleset(ctx, rsetId, params) + return err +} + +// PostComplianceRuleset converts echo context to params. +func (w *ServerInterfaceWrapper) PostComplianceRuleset(ctx echo.Context) error { + var err error + // ------------- Path parameter "rset_id" ------------- + var rsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "rset_id", ctx.Param("rset_id"), &rsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter rset_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostComplianceRuleset(ctx, rsetId) + return err +} + +// PutComplianceRuleset converts echo context to params. +func (w *ServerInterfaceWrapper) PutComplianceRuleset(ctx echo.Context) error { + var err error + // ------------- Path parameter "rset_id" ------------- + var rsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "rset_id", ctx.Param("rset_id"), &rsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter rset_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PutComplianceRuleset(ctx, rsetId) + return err +} + +// GetComplianceRulesetAmIResponsible converts echo context to params. +func (w *ServerInterfaceWrapper) GetComplianceRulesetAmIResponsible(ctx echo.Context) error { + var err error + // ------------- Path parameter "rset_id" ------------- + var rsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "rset_id", ctx.Param("rset_id"), &rsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter rset_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetComplianceRulesetAmIResponsible(ctx, rsetId) + return err +} + +// GetComplianceRulesetUsage converts echo context to params. +func (w *ServerInterfaceWrapper) GetComplianceRulesetUsage(ctx echo.Context) error { + var err error + // ------------- Path parameter "rset_id" ------------- + var rsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "rset_id", ctx.Param("rset_id"), &rsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter rset_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetComplianceRulesetUsage(ctx, rsetId) + return err +} + // DeleteComplianceStatus converts echo context to params. func (w *ServerInterfaceWrapper) DeleteComplianceStatus(ctx echo.Context) error { var err error @@ -10510,6 +10763,15 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.POST(options.BaseURL+"/auth/node", wrapper.PostAuthNode, options.OperationMiddlewares["PostAuthNode"]...) router.GET(options.BaseURL+"/compliance/logs", wrapper.GetComplianceLogs, options.OperationMiddlewares["GetComplianceLogs"]...) router.GET(options.BaseURL+"/compliance/logs/:log_id", wrapper.GetComplianceLog, options.OperationMiddlewares["GetComplianceLog"]...) + router.DELETE(options.BaseURL+"/compliance/rulesets", wrapper.DeleteComplianceRulesets, options.OperationMiddlewares["DeleteComplianceRulesets"]...) + router.GET(options.BaseURL+"/compliance/rulesets", wrapper.GetComplianceRulesets, options.OperationMiddlewares["GetComplianceRulesets"]...) + router.POST(options.BaseURL+"/compliance/rulesets", wrapper.PostComplianceRulesets, options.OperationMiddlewares["PostComplianceRulesets"]...) + router.DELETE(options.BaseURL+"/compliance/rulesets/:rset_id", wrapper.DeleteComplianceRuleset, options.OperationMiddlewares["DeleteComplianceRuleset"]...) + router.GET(options.BaseURL+"/compliance/rulesets/:rset_id", wrapper.GetComplianceRuleset, options.OperationMiddlewares["GetComplianceRuleset"]...) + router.POST(options.BaseURL+"/compliance/rulesets/:rset_id", wrapper.PostComplianceRuleset, options.OperationMiddlewares["PostComplianceRuleset"]...) + router.PUT(options.BaseURL+"/compliance/rulesets/:rset_id", wrapper.PutComplianceRuleset, options.OperationMiddlewares["PutComplianceRuleset"]...) + router.GET(options.BaseURL+"/compliance/rulesets/:rset_id/am_i_responsible", wrapper.GetComplianceRulesetAmIResponsible, options.OperationMiddlewares["GetComplianceRulesetAmIResponsible"]...) + router.GET(options.BaseURL+"/compliance/rulesets/:rset_id/usage", wrapper.GetComplianceRulesetUsage, options.OperationMiddlewares["GetComplianceRulesetUsage"]...) router.DELETE(options.BaseURL+"/compliance/status", wrapper.DeleteComplianceStatus, options.OperationMiddlewares["DeleteComplianceStatus"]...) router.GET(options.BaseURL+"/compliance/status", wrapper.GetComplianceStatus, options.OperationMiddlewares["GetComplianceStatus"]...) router.DELETE(options.BaseURL+"/compliance/status/:status_id", wrapper.DeleteComplianceStatusRun, options.OperationMiddlewares["DeleteComplianceStatusRun"]...) @@ -10709,347 +10971,360 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "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", - "ZDo4H4zOBl8/ff3/AwAA//8=", + "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", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index b38e0544..97d9facb 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -32,6 +32,57 @@ func (e ObsolescenceSettingRowObsType) Valid() bool { } } +// Defines values for PostComplianceRulesetsJSONBodyRulesetType. +const ( + PostComplianceRulesetsJSONBodyRulesetTypeContextual PostComplianceRulesetsJSONBodyRulesetType = "contextual" + PostComplianceRulesetsJSONBodyRulesetTypeExplicit PostComplianceRulesetsJSONBodyRulesetType = "explicit" +) + +// Valid indicates whether the value is a known member of the PostComplianceRulesetsJSONBodyRulesetType enum. +func (e PostComplianceRulesetsJSONBodyRulesetType) Valid() bool { + switch e { + case PostComplianceRulesetsJSONBodyRulesetTypeContextual: + return true + case PostComplianceRulesetsJSONBodyRulesetTypeExplicit: + return true + default: + return false + } +} + +// Defines values for PostComplianceRulesetJSONBodyRulesetType. +const ( + PostComplianceRulesetJSONBodyRulesetTypeContextual PostComplianceRulesetJSONBodyRulesetType = "contextual" + PostComplianceRulesetJSONBodyRulesetTypeExplicit PostComplianceRulesetJSONBodyRulesetType = "explicit" +) + +// Valid indicates whether the value is a known member of the PostComplianceRulesetJSONBodyRulesetType enum. +func (e PostComplianceRulesetJSONBodyRulesetType) Valid() bool { + switch e { + case PostComplianceRulesetJSONBodyRulesetTypeContextual: + return true + case PostComplianceRulesetJSONBodyRulesetTypeExplicit: + return true + default: + return false + } +} + +// Defines values for PutComplianceRulesetJSONBodyAction. +const ( + Clone PutComplianceRulesetJSONBodyAction = "clone" +) + +// Valid indicates whether the value is a known member of the PutComplianceRulesetJSONBodyAction enum. +func (e PutComplianceRulesetJSONBodyAction) Valid() bool { + switch e { + case Clone: + return true + default: + return false + } +} + // Defines values for PostFiltersJSONBodyFOp. const ( PostFiltersJSONBodyFOpEqual PostFiltersJSONBodyFOp = "=" @@ -1228,6 +1279,28 @@ type RulesetRow struct { RulesetType *string `json:"ruleset_type,omitempty"` } +// RulesetUsage What uses a ruleset. +type RulesetUsage struct { + Modulesets *[]struct { + Id *int `json:"id,omitempty"` + ModsetName *string `json:"modset_name,omitempty"` + } `json:"modulesets,omitempty"` + Nodes *[]struct { + NodeId *string `json:"node_id,omitempty"` + Nodename *string `json:"nodename,omitempty"` + } `json:"nodes,omitempty"` + + // Rulesets The rulesets holding this one as a child. + Rulesets *[]struct { + Id *int `json:"id,omitempty"` + RulesetName *string `json:"ruleset_name,omitempty"` + } `json:"rulesets,omitempty"` + Services *[]struct { + SvcId *string `json:"svc_id,omitempty"` + Svcname *string `json:"svcname,omitempty"` + } `json:"services,omitempty"` +} + // ServiceListResponse defines model for ServiceListResponse. type ServiceListResponse struct { Data ServiceListResponse_Data `json:"data"` @@ -1950,6 +2023,90 @@ type GetComplianceLogParams struct { Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` } +// DeleteComplianceRulesetsJSONBody defines parameters for DeleteComplianceRulesets. +type DeleteComplianceRulesetsJSONBody struct { + // Id Ruleset id or name + Id interface{} `json:"id,omitempty"` +} + +// GetComplianceRulesetsParams defines parameters for GetComplianceRulesets. +type GetComplianceRulesetsParams struct { + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` + + // Limit The maximum number of entries to return. 0 means no limit. + Limit *InQueryLimit `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Skip the first entries of the data cursor. + Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` + + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. + Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` + + // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. + Stats *InQueryStats `form:"stats,omitempty" json:"stats,omitempty"` + + // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). + Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` + + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). + Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` +} + +// PostComplianceRulesetsJSONBody defines parameters for PostComplianceRulesets. +type PostComplianceRulesetsJSONBody struct { + RulesetName *string `json:"ruleset_name,omitempty"` + + // RulesetPublic A boolean, or "T" / "F" as stored. + RulesetPublic interface{} `json:"ruleset_public,omitempty"` + RulesetType *PostComplianceRulesetsJSONBodyRulesetType `json:"ruleset_type,omitempty"` +} + +// PostComplianceRulesetsJSONBodyRulesetType defines parameters for PostComplianceRulesets. +type PostComplianceRulesetsJSONBodyRulesetType string + +// GetComplianceRulesetParams defines parameters for GetComplianceRuleset. +type GetComplianceRulesetParams struct { + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` +} + +// PostComplianceRulesetJSONBody defines parameters for PostComplianceRuleset. +type PostComplianceRulesetJSONBody struct { + RulesetName *string `json:"ruleset_name,omitempty"` + + // RulesetPublic A boolean, or "T" / "F" as stored. + RulesetPublic interface{} `json:"ruleset_public,omitempty"` + RulesetType *PostComplianceRulesetJSONBodyRulesetType `json:"ruleset_type,omitempty"` +} + +// PostComplianceRulesetJSONBodyRulesetType defines parameters for PostComplianceRuleset. +type PostComplianceRulesetJSONBodyRulesetType string + +// PutComplianceRulesetJSONBody defines parameters for PutComplianceRuleset. +type PutComplianceRulesetJSONBody struct { + Action PutComplianceRulesetJSONBodyAction `json:"action"` +} + +// PutComplianceRulesetJSONBodyAction defines parameters for PutComplianceRuleset. +type PutComplianceRulesetJSONBodyAction string + // DeleteComplianceStatusJSONBody defines parameters for DeleteComplianceStatus. type DeleteComplianceStatusJSONBody struct { // Id Id of the run (comp_status.id) @@ -5418,6 +5575,18 @@ type PostAppsResponsiblesJSONRequestBody PostAppsResponsiblesJSONBody // PostAuthNodeJSONRequestBody defines body for PostAuthNode for application/json ContentType. type PostAuthNodeJSONRequestBody PostAuthNodeJSONBody +// DeleteComplianceRulesetsJSONRequestBody defines body for DeleteComplianceRulesets for application/json ContentType. +type DeleteComplianceRulesetsJSONRequestBody DeleteComplianceRulesetsJSONBody + +// PostComplianceRulesetsJSONRequestBody defines body for PostComplianceRulesets for application/json ContentType. +type PostComplianceRulesetsJSONRequestBody PostComplianceRulesetsJSONBody + +// PostComplianceRulesetJSONRequestBody defines body for PostComplianceRuleset for application/json ContentType. +type PostComplianceRulesetJSONRequestBody PostComplianceRulesetJSONBody + +// PutComplianceRulesetJSONRequestBody defines body for PutComplianceRuleset for application/json ContentType. +type PutComplianceRulesetJSONRequestBody PutComplianceRulesetJSONBody + // DeleteComplianceStatusJSONRequestBody defines body for DeleteComplianceStatus for application/json ContentType. type DeleteComplianceStatusJSONRequestBody DeleteComplianceStatusJSONBody diff --git a/server/handlers/compliance_common.go b/server/handlers/compliance_common.go new file mode 100644 index 00000000..31d2e1e4 --- /dev/null +++ b/server/handlers/compliance_common.go @@ -0,0 +1,125 @@ +package serverhandlers + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "net/http" + "strings" + + "github.com/labstack/echo/v4" + + "github.com/opensvc/oc3/cdb" + "github.com/opensvc/oc3/util/echolog" +) + +// checkCompManager refuses a caller without the CompManager privilege, as +// check_privilege("CompManager") and @auth.requires_membership('CompManager') +// do. Unlike requireCompManager, it returns the refusal as an httpError rather +// than writing it. +func checkCompManager(c echo.Context) error { + if !IsAuthByUser(c) { + return httpErrorf(http.StatusUnauthorized, "user authentication required") + } + if !IsCompManager(c) { + return httpErrorf(http.StatusForbidden, "CompManager privilege required") + } + return nil +} + +// compDesignerError turns the errors of the compliance designer queries into +// HTTP statuses: 404 for a missing object, 409 for a name already taken, 500 +// otherwise. +func compDesignerError(c echo.Context, name string, err error) error { + switch { + case errors.Is(err, cdb.ErrCompNotFound): + return httpErrorf(http.StatusNotFound, "%s", err.Error()) + case errors.Is(err, cdb.ErrCompConflict): + return httpErrorf(http.StatusConflict, "%s", strings.TrimPrefix(err.Error(), cdb.ErrCompConflict.Error()+": ")) + } + return httpInternal(echolog.GetLogHandler(c, name), "cannot "+name, err) +} + +// resolveRuleset returns the id of a ruleset given by id or by name: 404 when +// there is none. +func (a *Api) resolveRuleset(ctx context.Context, idOrName string) (int64, error) { + id, found, err := a.ODB.CompRulesetID(ctx, idOrName) + if err != nil { + return 0, err + } + if !found { + return 0, httpErrorf(http.StatusNotFound, "ruleset %s not found", idOrName) + } + return id, nil +} + +// compBool reads a boolean property the way the historical collector accepted +// it, a JSON boolean or "T", "F", "true", "false", "yes", "no", "1", "0", and +// stores it as its "T" or "F" varchar(1). +func compBool(key string, v any) (string, error) { + switch t := v.(type) { + case bool: + if t { + return "T", nil + } + return "F", nil + case string: + switch strings.ToLower(strings.TrimSpace(t)) { + case "t", "true", "yes", "y", "1": + return "T", nil + case "f", "false", "no", "n", "0": + return "F", nil + } + case float64: + if t == 1 { + return "T", nil + } else if t == 0 { + return "F", nil + } + } + return "", httpErrorf(http.StatusBadRequest, "invalid %s value %v: a boolean is expected", key, v) +} + +// compString reads a string property, trimmed; an empty one is refused when +// required. +func compString(key string, v any, required bool) (string, error) { + s, ok := v.(string) + if !ok { + if v == nil && !required { + return "", nil + } + return "", httpErrorf(http.StatusBadRequest, "invalid %s value %v: a string is expected", key, v) + } + s = strings.TrimSpace(s) + if s == "" && required { + return "", httpErrorf(http.StatusBadRequest, "the '%s' key is mandatory", key) + } + return s, nil +} + +// compOneOf checks a value against the accepted ones. +func compOneOf(key, v string, accepted ...string) error { + for _, a := range accepted { + if v == a { + return nil + } + } + return httpErrorf(http.StatusBadRequest, "invalid %s value %q: expected one of %s", key, v, strings.Join(accepted, ", ")) +} + +// compInfo answers with an informational message, as the historical handlers' +// dict(info=...). +func compInfo(c echo.Context, format string, args ...any) error { + return c.JSON(http.StatusOK, map[string]string{"info": fmt.Sprintf(format, args...)}) +} + +// compJSON renders the properties of a change for the log, as the historical +// collector logs str(vars). +func compJSON(v any) string { + b, err := json.Marshal(v) + if err != nil { + return fmt.Sprint(v) + } + return string(b) +} diff --git a/server/handlers/compliance_rulesets.go b/server/handlers/compliance_rulesets.go new file mode 100644 index 00000000..723f6e0c --- /dev/null +++ b/server/handlers/compliance_rulesets.go @@ -0,0 +1,336 @@ +package serverhandlers + +import ( + "context" + "fmt" + "net/http" + "strconv" + + "github.com/labstack/echo/v4" + + "github.com/opensvc/oc3/cdb" + "github.com/opensvc/oc3/server" + "github.com/opensvc/oc3/util/echolog" +) + +// GetComplianceRulesets handles GET /compliance/rulesets, as the historical +// rest_get_compliance_rulesets: the rulesets published to the caller's groups. +func (a *Api) GetComplianceRulesets(c echo.Context, params server.GetComplianceRulesetsParams) error { + return a.handleList(c, "GetComplianceRulesets", "ruleset", listEndpointParams{ + props: params.Props, limit: params.Limit, offset: params.Offset, + meta: params.Meta, stats: params.Stats, orderby: params.Orderby, groupby: params.Groupby, + filter: params.Filter, + }, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetComplianceRulesets(ctx, nil, p) + }) +} + +// GetComplianceRuleset handles GET /compliance/rulesets/{rset_id}, the ruleset +// given by id or by name, when published to one of the caller's groups. +func (a *Api) GetComplianceRuleset(c echo.Context, rsetId string, params server.GetComplianceRulesetParams) error { + id, err := a.resolveRuleset(c.Request().Context(), rsetId) + if err != nil { + return httpProblem(c, err) + } + return a.rulesetResponse(c, id, params.Props) +} + +// rulesetResponse answers with a ruleset, as the historical handlers end with +// rest_get_compliance_ruleset().handler(id). +func (a *Api) rulesetResponse(c echo.Context, id int64, props *server.InQueryProps) error { + return a.handleItem(c, "GetComplianceRuleset", "ruleset", "id", strconv.FormatInt(id, 10), listEndpointParams{ + props: props, + }, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetComplianceRulesets(ctx, &id, p) + }) +} + +// PostComplianceRulesets handles POST /compliance/rulesets, as the historical +// rest_post_compliance_rulesets: a ruleset named ruleset_name is created, +// published to and under the responsibility of the caller's default group; when +// it exists, its other given properties are updated instead. +func (a *Api) PostComplianceRulesets(c echo.Context) error { + entries, _, err := decodeEntries(c) + if err != nil { + return httpProblem(c, httpErrorf(http.StatusBadRequest, "%s", err)) + } + if len(entries) != 1 { + return httpProblem(c, httpErrorf(http.StatusBadRequest, "one ruleset is expected")) + } + entry := entries[0] + ctx := c.Request().Context() + name, err := compString("ruleset_name", entry["ruleset_name"], true) + if err != nil { + return httpProblem(c, err) + } + if id, found, err := a.ODB.CompRulesetID(ctx, name); err != nil { + return httpProblem(c, compDesignerError(c, "PostComplianceRulesets", err)) + } else if found { + delete(entry, "ruleset_name") + if len(entry) == 0 { + return compInfo(c, "No fields to update") + } + return a.updateRuleset(c, id, entry) + } + if err := checkCompManager(c); err != nil { + return httpProblem(c, err) + } + rtype := "explicit" + if v, ok := entry["ruleset_type"]; ok { + if rtype, err = compString("ruleset_type", v, true); err != nil { + return httpProblem(c, err) + } + if err := compOneOf("ruleset_type", rtype, "explicit", "contextual"); err != nil { + return httpProblem(c, err) + } + } + public := "T" + if v, ok := entry["ruleset_public"]; ok { + if public, err = compBool("ruleset_public", v); err != nil { + return httpProblem(c, err) + } + } + groupID, err := a.ODB.DefaultGroupOrManager(ctx, authUserID(c)) + if err != nil { + return httpProblem(c, compDesignerError(c, "PostComplianceRulesets", err)) + } + id, err := a.ODB.CreateCompRuleset(ctx, name, rtype, public, groupID) + if err != nil { + return httpProblem(c, compDesignerError(c, "PostComplianceRulesets", err)) + } + a.afterRulesetChange(c, true) + a.compLog(c, "compliance.ruleset.add", "added ruleset %(rset_name)s", map[string]any{"rset_name": name}, "", "") + return a.rulesetResponse(c, id, nil) +} + +// PostComplianceRuleset handles POST /compliance/rulesets/{rset_id}, as the +// historical rest_post_compliance_ruleset: the given properties are updated, by a +// CompManager responsible for the ruleset. +func (a *Api) PostComplianceRuleset(c echo.Context, rsetId string) error { + entries, _, err := decodeEntries(c) + if err != nil { + return httpProblem(c, httpErrorf(http.StatusBadRequest, "%s", err)) + } + if len(entries) != 1 { + return httpProblem(c, httpErrorf(http.StatusBadRequest, "one set of properties is expected")) + } + id, err := a.resolveRuleset(c.Request().Context(), rsetId) + if err != nil { + return httpProblem(c, err) + } + return a.updateRuleset(c, id, entries[0]) +} + +// updateRuleset checks and applies a change of ruleset properties. +func (a *Api) updateRuleset(c echo.Context, id int64, entry map[string]any) error { + ctx := c.Request().Context() + if err := checkCompManager(c); err != nil { + return httpProblem(c, err) + } + if err := a.requireRulesetResponsible(ctx, c, id); err != nil { + return httpProblem(c, err) + } + fields := map[string]any{} + for k, v := range entry { + switch k { + case "ruleset_name": + name, err := compString(k, v, true) + if err != nil { + return httpProblem(c, err) + } + if other, found, err := a.ODB.CompRulesetID(ctx, name); err != nil { + return httpProblem(c, compDesignerError(c, "PostComplianceRuleset", err)) + } else if found && other != id { + return httpProblem(c, httpErrorf(http.StatusConflict, "a ruleset named '%s' already exists", name)) + } + fields[k] = name + case "ruleset_type": + rtype, err := compString(k, v, true) + if err != nil { + return httpProblem(c, err) + } + if err := compOneOf(k, rtype, "explicit", "contextual"); err != nil { + return httpProblem(c, err) + } + fields[k] = rtype + case "ruleset_public": + public, err := compBool(k, v) + if err != nil { + return httpProblem(c, err) + } + fields[k] = public + case "id": + default: + return httpProblem(c, httpErrorf(http.StatusBadRequest, "unknown ruleset property %s", k)) + } + } + if len(fields) == 0 { + return compInfo(c, "No fields to update") + } + if err := a.ODB.UpdateCompRuleset(ctx, id, fields); err != nil { + return httpProblem(c, compDesignerError(c, "PostComplianceRuleset", err)) + } + // The chains name their rulesets: a renaming rewrites them. + _, renamed := fields["ruleset_name"] + a.afterRulesetChange(c, renamed) + a.compLog(c, "compliance.ruleset.change", "update properties %(data)s", map[string]any{"data": compJSON(fields)}, "", "") + return a.rulesetResponse(c, id, nil) +} + +// PutComplianceRuleset handles PUT /compliance/rulesets/{rset_id}, the special +// actions on a ruleset, as the historical rest_put_compliance_ruleset: clone. +func (a *Api) PutComplianceRuleset(c echo.Context, rsetId string) error { + entries, _, err := decodeEntries(c) + if err != nil || len(entries) != 1 { + return httpProblem(c, httpErrorf(http.StatusBadRequest, "an action is expected")) + } + ctx := c.Request().Context() + id, err := a.resolveRuleset(ctx, rsetId) + if err != nil { + return httpProblem(c, err) + } + action, _ := entries[0]["action"].(string) + if action != "clone" { + return httpProblem(c, httpErrorf(http.StatusBadRequest, "unsupported action %q", action)) + } + if err := checkCompManager(c); err != nil { + return httpProblem(c, err) + } + caller, err := a.formCaller(ctx, c) + if err != nil { + return httpProblem(c, compDesignerError(c, "PutComplianceRuleset", err)) + } + groupID, err := a.ODB.DefaultGroupOrManager(ctx, authUserID(c)) + if err != nil { + return httpProblem(c, compDesignerError(c, "PutComplianceRuleset", err)) + } + name, err := a.ODB.CompRulesetNameByID(ctx, id) + if err != nil { + return httpProblem(c, compDesignerError(c, "PutComplianceRuleset", err)) + } + _, cloneName, err := a.ODB.CloneCompRuleset(ctx, id, caller.name, groupID) + if err != nil { + return httpProblem(c, compDesignerError(c, "PutComplianceRuleset", err)) + } + a.afterRulesetChange(c, true) + a.compLog(c, "compliance.ruleset.clone", "cloned ruleset %(o)s from %(n)s", map[string]any{"n": name, "o": cloneName}, "", "") + return compInfo(c, "clone done. new ruleset name %s", cloneName) +} + +// DeleteComplianceRuleset handles DELETE /compliance/rulesets/{rset_id}. +func (a *Api) DeleteComplianceRuleset(c echo.Context, rsetId string) error { + id, err := a.resolveRuleset(c.Request().Context(), rsetId) + if err != nil { + return httpProblem(c, err) + } + return a.deleteRuleset(c, id) +} + +// DeleteComplianceRulesets handles DELETE /compliance/rulesets, the bulk form +// naming the ruleset by the id key of the body. +func (a *Api) DeleteComplianceRulesets(c echo.Context) error { + entries, _, err := decodeEntries(c) + if err != nil || len(entries) != 1 { + return httpProblem(c, httpErrorf(http.StatusBadRequest, "The 'id' key is mandatory")) + } + raw, ok := entries[0]["id"] + if !ok { + return httpProblem(c, httpErrorf(http.StatusBadRequest, "The 'id' key is mandatory")) + } + id, err := a.resolveRuleset(c.Request().Context(), fmt.Sprint(raw)) + if err != nil { + return httpProblem(c, err) + } + return a.deleteRuleset(c, id) +} + +// deleteRuleset deletes a ruleset and all its relations, as delete_ruleset(): by +// a CompManager whose group is responsible for it. +func (a *Api) deleteRuleset(c echo.Context, id int64) error { + ctx := c.Request().Context() + if err := checkCompManager(c); err != nil { + return httpProblem(c, err) + } + if err := a.requireRulesetResponsible(ctx, c, id); err != nil { + return httpProblem(c, err) + } + name, err := a.ODB.CompRulesetNameByID(ctx, id) + if err != nil { + return httpProblem(c, compDesignerError(c, "DeleteComplianceRuleset", err)) + } + if err := a.ODB.DeleteCompRuleset(ctx, id); err != nil { + return httpProblem(c, compDesignerError(c, "DeleteComplianceRuleset", err)) + } + a.afterRulesetChange(c, true) + a.compLog(c, "compliance.ruleset.delete", "deleted ruleset %(rset_name)s", map[string]any{"rset_name": name}, "", "") + return compInfo(c, "Ruleset %d deleted", id) +} + +// requireRulesetResponsible refuses a caller none of whose groups is responsible +// for the ruleset. +func (a *Api) requireRulesetResponsible(ctx context.Context, c echo.Context, id int64) error { + ok, err := a.ODB.CompRulesetResponsible(ctx, id, UserGroupsFromContext(c), IsManager(c)) + if err != nil { + return compDesignerError(c, "check the ruleset responsibility", err) + } + if !ok { + return httpErrorf(http.StatusForbidden, "you are not responsible for this ruleset") + } + return nil +} + +// afterRulesetChange rebuilds the ruleset chains when the hierarchy or the names +// changed, and announces the change. +func (a *Api) afterRulesetChange(c echo.Context, chains bool) { + ctx := c.Request().Context() + log := echolog.GetLogHandler(c, "compliance") + if chains { + if err := a.ODB.CompRulesetsChains(ctx); err != nil { + log.Error("cannot rebuild the ruleset chains", "error", err) + } + } + a.notifyChanges(log, ctx) +} + +// GetComplianceRulesetUsage handles GET /compliance/rulesets/{rset_id}/usage, as +// the historical rest_get_compliance_ruleset_usage: the modulesets and parent +// rulesets holding the ruleset, the nodes and services it is attached to. +func (a *Api) GetComplianceRulesetUsage(c echo.Context, rsetId string) error { + ctx := c.Request().Context() + id, found, err := a.ODB.CompRulesetID(ctx, rsetId) + if err != nil { + return httpProblem(c, compDesignerError(c, "GetComplianceRulesetUsage", err)) + } + if found { + found, err = a.ODB.CompRulesetVisible(ctx, id, UserGroupsFromContext(c), IsManager(c)) + if err != nil { + return httpProblem(c, compDesignerError(c, "GetComplianceRulesetUsage", err)) + } + } + if !found { + return httpProblem(c, httpErrorf(http.StatusNotFound, "ruleset not found or not visible to your groups")) + } + usage, err := a.ODB.CompRulesetUsage(ctx, id) + if err != nil { + return httpProblem(c, compDesignerError(c, "GetComplianceRulesetUsage", err)) + } + return c.JSON(http.StatusOK, map[string]any{"data": usage}) +} + +// GetComplianceRulesetAmIResponsible handles GET +// /compliance/rulesets/{rset_id}/am_i_responsible: whether one of the caller's +// groups is responsible for the ruleset. +func (a *Api) GetComplianceRulesetAmIResponsible(c echo.Context, rsetId string) error { + ctx := c.Request().Context() + id, found, err := a.ODB.CompRulesetID(ctx, rsetId) + if err != nil { + return httpProblem(c, compDesignerError(c, "GetComplianceRulesetAmIResponsible", err)) + } + ok := false + if found { + if ok, err = a.ODB.CompRulesetResponsible(ctx, id, UserGroupsFromContext(c), IsManager(c)); err != nil { + return httpProblem(c, compDesignerError(c, "GetComplianceRulesetAmIResponsible", err)) + } + } + return c.JSON(http.StatusOK, map[string]bool{"data": ok}) +} From 88539808a4da4d5c82d869d9b5d829715c82f0e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Mon, 28 Sep 2026 13:32:24 +0200 Subject: [PATCH 38/61] Add the compliance ruleset variables endpoints Port the ruleset variable endpoints of the historical api_compliance: - GET /compliance/rulesets/{rset_id}/variables and /variables/{var_id} (id or name), for a ruleset published to the caller, to one of their groups or to Everybody; - POST /compliance/rulesets/{rset_id}/variables and its form naming the ruleset in the body, POST /compliance/rulesets_variables, creating a variable or updating the one of that name; - POST /compliance/rulesets/{rset_id}/variables/{var_id}, updating its name, class or value; a name taken in the ruleset is a 409; - PUT /compliance/rulesets/{rset_id}/variables/{var_id} action=copy or move to dst_ruleset; - DELETE /compliance/rulesets/{rset_id}/variables/{var_id}. Changes require the CompManager privilege and the responsibility of the ruleset (for a copy, the publication of the source), record the author and the date, and are logged. var_value may be any JSON value, stored serialized. Two departures from the historical handlers: the deletion checks the privilege and the responsibility, as its description says, where the code only checked the publication; and a copy or a move to a ruleset already holding a variable of that name is refused. The ruleset_variable props mapping and the RulesetVariableRow schema describe the rows. --- cdb/db_compliance_variables.go | 148 ++++ server/api.yaml | 381 +++++++++ server/codegen_server_gen.go | 978 +++++++++++++++--------- server/codegen_type_gen.go | 209 +++++ server/handlers/compliance_variables.go | 363 +++++++++ server/handlers/props_mapping.go | 13 + 6 files changed, 1738 insertions(+), 354 deletions(-) create mode 100644 cdb/db_compliance_variables.go create mode 100644 server/handlers/compliance_variables.go diff --git a/cdb/db_compliance_variables.go b/cdb/db_compliance_variables.go new file mode 100644 index 00000000..0f3ecd69 --- /dev/null +++ b/cdb/db_compliance_variables.go @@ -0,0 +1,148 @@ +package cdb + +import ( + "context" + "database/sql" + "errors" + "fmt" + "strconv" + "strings" +) + +// CompRulesetPublished tells whether a ruleset is published to the caller: to +// one of the caller's groups or to Everybody, as ruleset_publication(); always +// for a manager. +func (oDb *DB) CompRulesetPublished(ctx context.Context, id int64, groups []string, isManager bool) (bool, error) { + if ok, err := oDb.CompRulesetVisible(ctx, id, groups, isManager); err != nil || ok { + return ok, err + } + return oDb.RulesetHasEverybodyPublication(ctx, strconv.FormatInt(id, 10)) +} + +// GetComplianceRulesetVariables lists the variables of a ruleset, by name; one +// when varID is set. +func (oDb *DB) GetComplianceRulesetVariables(ctx context.Context, rulesetID int64, varID *int64, p ListParams) ([]map[string]any, error) { + conds := []string{"comp_rulesets_variables.ruleset_id = ?"} + args := []any{rulesetID} + if varID != nil { + conds = append(conds, "comp_rulesets_variables.id = ?") + args = append(args, *varID) + } + return oDb.listQuery(ctx, "getComplianceRulesetVariables", "comp_rulesets_variables", conds, args, "comp_rulesets_variables.var_name", p) +} + +// CompRulesetVariableID resolves a variable of a ruleset given by id or by name, +// as comp_ruleset_variable_id(); false when the ruleset has none such. +func (oDb *DB) CompRulesetVariableID(ctx context.Context, rulesetID int64, idOrName string) (int64, bool, error) { + var id int64 + var err error + if n, convErr := strconv.ParseInt(idOrName, 10, 64); convErr == nil { + err = oDb.DB.QueryRowContext(ctx, "SELECT id FROM comp_rulesets_variables WHERE ruleset_id = ? AND id = ?", rulesetID, n).Scan(&id) + } else { + err = oDb.DB.QueryRowContext(ctx, "SELECT id FROM comp_rulesets_variables WHERE ruleset_id = ? AND var_name = ? LIMIT 1", rulesetID, idOrName).Scan(&id) + } + switch { + case errors.Is(err, sql.ErrNoRows): + return 0, false, nil + case err != nil: + return 0, false, fmt.Errorf("compRulesetVariableID: %w", err) + } + return id, true, nil +} + +// CompRulesetVariable is a variable of a ruleset, as the change logs name it. +type CompRulesetVariable struct { + ID int64 + RulesetID int64 + RulesetName string + Name string + Class string + Value string +} + +// CompRulesetVariableByID returns a variable with the name of its ruleset. +func (oDb *DB) CompRulesetVariableByID(ctx context.Context, id int64) (*CompRulesetVariable, error) { + var v CompRulesetVariable + var rname, value sql.NullString + err := oDb.DB.QueryRowContext(ctx, "SELECT v.id, v.ruleset_id, r.ruleset_name, v.var_name, v.var_class, v.var_value"+ + " FROM comp_rulesets_variables v JOIN comp_rulesets r ON r.id = v.ruleset_id WHERE v.id = ?", id). + Scan(&v.ID, &v.RulesetID, &rname, &v.Name, &v.Class, &value) + switch { + case errors.Is(err, sql.ErrNoRows): + return nil, ErrCompNotFound + case err != nil: + return nil, fmt.Errorf("compRulesetVariableByID: %w", err) + } + v.RulesetName, v.Value = rname.String, value.String + return &v, nil +} + +// CreateCompRulesetVariable inserts a variable in a ruleset; fields holds +// var_name and optionally var_class and var_value. +func (oDb *DB) CreateCompRulesetVariable(ctx context.Context, rulesetID int64, fields map[string]any, author string) (int64, error) { + cols := []string{"ruleset_id", "var_author", "var_updated"} + vals := []string{"?", "?", "NOW()"} + args := []any{rulesetID, author} + if _, ok := fields["var_class"]; !ok { + fields["var_class"] = "" + } + for _, k := range sortedKeys(fields) { + cols = append(cols, k) + vals = append(vals, "?") + args = append(args, fields[k]) + } + res, err := oDb.DB.ExecContext(ctx, "INSERT INTO comp_rulesets_variables ("+strings.Join(cols, ", ")+") VALUES ("+strings.Join(vals, ", ")+")", args...) + if err != nil { + return 0, fmt.Errorf("createCompRulesetVariable: %w", err) + } + oDb.SetChange("comp_rulesets_variables") + return res.LastInsertId() +} + +// UpdateCompRulesetVariable sets the given columns of a variable, its author and +// its update date. +func (oDb *DB) UpdateCompRulesetVariable(ctx context.Context, id int64, fields map[string]any, author string) error { + sets := []string{"var_author = ?", "var_updated = NOW()"} + args := []any{author} + for _, k := range sortedKeys(fields) { + sets = append(sets, k+" = ?") + args = append(args, fields[k]) + } + args = append(args, id) + if _, err := oDb.DB.ExecContext(ctx, "UPDATE comp_rulesets_variables SET "+strings.Join(sets, ", ")+" WHERE id = ?", args...); err != nil { + return fmt.Errorf("updateCompRulesetVariable: %w", err) + } + oDb.SetChange("comp_rulesets_variables") + return nil +} + +// DeleteCompRulesetVariable deletes a variable. +func (oDb *DB) DeleteCompRulesetVariable(ctx context.Context, id int64) error { + if _, err := oDb.DB.ExecContext(ctx, "DELETE FROM comp_rulesets_variables WHERE id = ?", id); err != nil { + return fmt.Errorf("deleteCompRulesetVariable: %w", err) + } + oDb.SetChange("comp_rulesets_variables") + return nil +} + +// CopyCompRulesetVariable copies a variable to another ruleset, authored by +// author, as copy_variable_to_ruleset(). +func (oDb *DB) CopyCompRulesetVariable(ctx context.Context, id, dstRulesetID int64, author string) (int64, error) { + res, err := oDb.DB.ExecContext(ctx, "INSERT INTO comp_rulesets_variables (ruleset_id, var_name, var_class, var_value, var_author, var_updated)"+ + " SELECT ?, var_name, var_class, var_value, ?, NOW() FROM comp_rulesets_variables WHERE id = ?", dstRulesetID, author, id) + if err != nil { + return 0, fmt.Errorf("copyCompRulesetVariable: %w", err) + } + oDb.SetChange("comp_rulesets_variables") + return res.LastInsertId() +} + +// MoveCompRulesetVariable moves a variable to another ruleset, as +// move_variable_to_ruleset(). +func (oDb *DB) MoveCompRulesetVariable(ctx context.Context, id, dstRulesetID int64) error { + if _, err := oDb.DB.ExecContext(ctx, "UPDATE comp_rulesets_variables SET ruleset_id = ? WHERE id = ?", dstRulesetID, id); err != nil { + return fmt.Errorf("moveCompRulesetVariable: %w", err) + } + oDb.SetChange("comp_rulesets_variables") + return nil +} diff --git a/server/api.yaml b/server/api.yaml index cc171bf3..65ee1863 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -9357,6 +9357,347 @@ paths: - basicAuth: [ ] - bearerAuth: [ ] + /compliance/rulesets/{rset_id}/variables: + get: + operationId: GetComplianceRulesetVariables + description: | + List the variables of a ruleset published to the user (to one of the user's + groups, or to Everybody). + parameters: + - in: path + name: rset_id + required: true + description: Ruleset id or name + schema: + type: string + - $ref: '#/components/parameters/inQueryProps' + - $ref: '#/components/parameters/inQueryLimit' + - $ref: '#/components/parameters/inQueryOffset' + - $ref: '#/components/parameters/inQueryMeta' + - $ref: '#/components/parameters/inQueryStats' + - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryFilter' + - $ref: '#/components/parameters/inQueryGroupby' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/RulesetVariableListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + post: + operationId: PostComplianceRulesetVariables + description: | + Create a variable named var_name in the ruleset; when the ruleset has one of + that name, its other given properties are updated instead. Requires the + CompManager privilege and the responsibility of the ruleset. The change is + logged. + parameters: + - in: path + name: rset_id + required: true + description: Ruleset id or name + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + var_name: + type: string + var_class: + type: string + description: The class of the variable, telling the modules how to read its value. + var_value: + description: The value, a string or any JSON value, stored serialized. + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/RulesetVariableListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 409: + $ref: '#/components/responses/409' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /compliance/rulesets_variables: + post: + operationId: PostComplianceRulesetsVariables + description: | + Create or update a variable, as POST /compliance/rulesets/{rset_id}/variables, + the ruleset being named by the ruleset_id or ruleset_name key of the body. + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + ruleset_id: + type: integer + ruleset_name: + type: string + var_name: + type: string + var_class: + type: string + var_value: + description: The value, a string or any JSON value, stored serialized. + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/RulesetVariableListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 409: + $ref: '#/components/responses/409' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /compliance/rulesets/{rset_id}/variables/{var_id}: + get: + operationId: GetComplianceRulesetVariable + description: | + Display a variable of a ruleset published to the user. + parameters: + - in: path + name: rset_id + required: true + description: Ruleset id or name + schema: + type: string + - in: path + name: var_id + required: true + description: Variable id or name + schema: + type: string + - $ref: '#/components/parameters/inQueryProps' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/RulesetVariableListResponse' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + post: + operationId: PostComplianceRulesetVariable + description: | + Update the given properties of a variable. Requires the CompManager privilege + and the responsibility of the ruleset. The change is logged. + parameters: + - in: path + name: rset_id + required: true + description: Ruleset id or name + schema: + type: string + - in: path + name: var_id + required: true + description: Variable id or name + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + var_name: + type: string + var_class: + type: string + description: The class of the variable, telling the modules how to read its value. + var_value: + description: The value, a string or any JSON value, stored serialized. + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/RulesetVariableListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 409: + $ref: '#/components/responses/409' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + put: + operationId: PutComplianceRulesetVariable + description: | + Special actions on a variable: copy or move it to dst_ruleset (id or name). + Requires the CompManager privilege, the publication of the source ruleset for a + copy or its responsibility for a move, and the responsibility of the destination, + which must not have a variable of the same name. + parameters: + - in: path + name: rset_id + required: true + description: Ruleset id or name + schema: + type: string + - in: path + name: var_id + required: true + description: Variable id or name + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [action, dst_ruleset] + properties: + action: + type: string + enum: [copy, move] + dst_ruleset: + description: Id or name of the destination ruleset + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 409: + $ref: '#/components/responses/409' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + delete: + operationId: DeleteComplianceRulesetVariable + description: | + Delete a variable. Requires the CompManager privilege and the responsibility of + the ruleset. The deletion is logged. + parameters: + - in: path + name: rset_id + required: true + description: Ruleset id or name + schema: + type: string + - in: path + name: var_id + required: true + description: Variable id or name + schema: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + components: responses: @@ -10228,6 +10569,46 @@ components: svcname: type: string + RulesetVariableRow: + type: object + description: | + A variable of a compliance ruleset. Every property is optional: the `props` + query parameter selects which columns the server returns. + properties: + id: + type: integer + ruleset_id: + type: integer + var_name: + type: string + var_class: + type: string + var_value: + type: string + nullable: true + var_author: + type: string + var_updated: + type: string + + RulesetVariableListResponse: + type: object + required: + - data + properties: + data: + oneOf: + - type: array + items: + $ref: '#/components/schemas/RulesetVariableRow' + - type: object + additionalProperties: + type: object + additionalProperties: + type: integer + meta: + $ref: '#/components/schemas/ListMeta' + InstanceListResponse: type: object required: diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index 3b21f69b..e29d0831 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -156,6 +156,27 @@ type ServerInterface interface { // (GET /compliance/rulesets/{rset_id}/usage) GetComplianceRulesetUsage(ctx echo.Context, rsetId string) error + // (GET /compliance/rulesets/{rset_id}/variables) + GetComplianceRulesetVariables(ctx echo.Context, rsetId string, params GetComplianceRulesetVariablesParams) error + + // (POST /compliance/rulesets/{rset_id}/variables) + PostComplianceRulesetVariables(ctx echo.Context, rsetId string) error + + // (DELETE /compliance/rulesets/{rset_id}/variables/{var_id}) + DeleteComplianceRulesetVariable(ctx echo.Context, rsetId string, varId string) error + + // (GET /compliance/rulesets/{rset_id}/variables/{var_id}) + GetComplianceRulesetVariable(ctx echo.Context, rsetId string, varId string, params GetComplianceRulesetVariableParams) error + + // (POST /compliance/rulesets/{rset_id}/variables/{var_id}) + PostComplianceRulesetVariable(ctx echo.Context, rsetId string, varId string) error + + // (PUT /compliance/rulesets/{rset_id}/variables/{var_id}) + PutComplianceRulesetVariable(ctx echo.Context, rsetId string, varId string) error + + // (POST /compliance/rulesets_variables) + PostComplianceRulesetsVariables(ctx echo.Context) error + // (DELETE /compliance/status) DeleteComplianceStatus(ctx echo.Context) error @@ -2289,6 +2310,238 @@ func (w *ServerInterfaceWrapper) GetComplianceRulesetUsage(ctx echo.Context) err return err } +// GetComplianceRulesetVariables converts echo context to params. +func (w *ServerInterfaceWrapper) GetComplianceRulesetVariables(ctx echo.Context) error { + var err error + // ------------- Path parameter "rset_id" ------------- + var rsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "rset_id", ctx.Param("rset_id"), &rsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter rset_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetComplianceRulesetVariablesParams + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // ------------- Optional query parameter "limit" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) + } + + // ------------- Optional query parameter "offset" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) + } + + // ------------- Optional query parameter "meta" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) + } + + // ------------- Optional query parameter "stats" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) + } + + // ------------- Optional query parameter "orderby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) + } + + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + + // ------------- Optional query parameter "groupby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetComplianceRulesetVariables(ctx, rsetId, params) + return err +} + +// PostComplianceRulesetVariables converts echo context to params. +func (w *ServerInterfaceWrapper) PostComplianceRulesetVariables(ctx echo.Context) error { + var err error + // ------------- Path parameter "rset_id" ------------- + var rsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "rset_id", ctx.Param("rset_id"), &rsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter rset_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostComplianceRulesetVariables(ctx, rsetId) + return err +} + +// DeleteComplianceRulesetVariable converts echo context to params. +func (w *ServerInterfaceWrapper) DeleteComplianceRulesetVariable(ctx echo.Context) error { + var err error + // ------------- Path parameter "rset_id" ------------- + var rsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "rset_id", ctx.Param("rset_id"), &rsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter rset_id: %s", err)) + } + + // ------------- Path parameter "var_id" ------------- + var varId string + + err = runtime.BindStyledParameterWithOptions("simple", "var_id", ctx.Param("var_id"), &varId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter var_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.DeleteComplianceRulesetVariable(ctx, rsetId, varId) + return err +} + +// GetComplianceRulesetVariable converts echo context to params. +func (w *ServerInterfaceWrapper) GetComplianceRulesetVariable(ctx echo.Context) error { + var err error + // ------------- Path parameter "rset_id" ------------- + var rsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "rset_id", ctx.Param("rset_id"), &rsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter rset_id: %s", err)) + } + + // ------------- Path parameter "var_id" ------------- + var varId string + + err = runtime.BindStyledParameterWithOptions("simple", "var_id", ctx.Param("var_id"), &varId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter var_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetComplianceRulesetVariableParams + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetComplianceRulesetVariable(ctx, rsetId, varId, params) + return err +} + +// PostComplianceRulesetVariable converts echo context to params. +func (w *ServerInterfaceWrapper) PostComplianceRulesetVariable(ctx echo.Context) error { + var err error + // ------------- Path parameter "rset_id" ------------- + var rsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "rset_id", ctx.Param("rset_id"), &rsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter rset_id: %s", err)) + } + + // ------------- Path parameter "var_id" ------------- + var varId string + + err = runtime.BindStyledParameterWithOptions("simple", "var_id", ctx.Param("var_id"), &varId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter var_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostComplianceRulesetVariable(ctx, rsetId, varId) + return err +} + +// PutComplianceRulesetVariable converts echo context to params. +func (w *ServerInterfaceWrapper) PutComplianceRulesetVariable(ctx echo.Context) error { + var err error + // ------------- Path parameter "rset_id" ------------- + var rsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "rset_id", ctx.Param("rset_id"), &rsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter rset_id: %s", err)) + } + + // ------------- Path parameter "var_id" ------------- + var varId string + + err = runtime.BindStyledParameterWithOptions("simple", "var_id", ctx.Param("var_id"), &varId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter var_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PutComplianceRulesetVariable(ctx, rsetId, varId) + return err +} + +// PostComplianceRulesetsVariables converts echo context to params. +func (w *ServerInterfaceWrapper) PostComplianceRulesetsVariables(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostComplianceRulesetsVariables(ctx) + return err +} + // DeleteComplianceStatus converts echo context to params. func (w *ServerInterfaceWrapper) DeleteComplianceStatus(ctx echo.Context) error { var err error @@ -10772,6 +11025,13 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.PUT(options.BaseURL+"/compliance/rulesets/:rset_id", wrapper.PutComplianceRuleset, options.OperationMiddlewares["PutComplianceRuleset"]...) router.GET(options.BaseURL+"/compliance/rulesets/:rset_id/am_i_responsible", wrapper.GetComplianceRulesetAmIResponsible, options.OperationMiddlewares["GetComplianceRulesetAmIResponsible"]...) router.GET(options.BaseURL+"/compliance/rulesets/:rset_id/usage", wrapper.GetComplianceRulesetUsage, options.OperationMiddlewares["GetComplianceRulesetUsage"]...) + router.GET(options.BaseURL+"/compliance/rulesets/:rset_id/variables", wrapper.GetComplianceRulesetVariables, options.OperationMiddlewares["GetComplianceRulesetVariables"]...) + router.POST(options.BaseURL+"/compliance/rulesets/:rset_id/variables", wrapper.PostComplianceRulesetVariables, options.OperationMiddlewares["PostComplianceRulesetVariables"]...) + router.DELETE(options.BaseURL+"/compliance/rulesets/:rset_id/variables/:var_id", wrapper.DeleteComplianceRulesetVariable, options.OperationMiddlewares["DeleteComplianceRulesetVariable"]...) + router.GET(options.BaseURL+"/compliance/rulesets/:rset_id/variables/:var_id", wrapper.GetComplianceRulesetVariable, options.OperationMiddlewares["GetComplianceRulesetVariable"]...) + router.POST(options.BaseURL+"/compliance/rulesets/:rset_id/variables/:var_id", wrapper.PostComplianceRulesetVariable, options.OperationMiddlewares["PostComplianceRulesetVariable"]...) + router.PUT(options.BaseURL+"/compliance/rulesets/:rset_id/variables/:var_id", wrapper.PutComplianceRulesetVariable, options.OperationMiddlewares["PutComplianceRulesetVariable"]...) + router.POST(options.BaseURL+"/compliance/rulesets_variables", wrapper.PostComplianceRulesetsVariables, options.OperationMiddlewares["PostComplianceRulesetsVariables"]...) router.DELETE(options.BaseURL+"/compliance/status", wrapper.DeleteComplianceStatus, options.OperationMiddlewares["DeleteComplianceStatus"]...) router.GET(options.BaseURL+"/compliance/status", wrapper.GetComplianceStatus, options.OperationMiddlewares["GetComplianceStatus"]...) router.DELETE(options.BaseURL+"/compliance/status/:status_id", wrapper.DeleteComplianceStatusRun, options.OperationMiddlewares["DeleteComplianceStatusRun"]...) @@ -10971,360 +11231,370 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "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", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index 97d9facb..f7e9e9b1 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -83,6 +83,24 @@ func (e PutComplianceRulesetJSONBodyAction) Valid() bool { } } +// Defines values for PutComplianceRulesetVariableJSONBodyAction. +const ( + Copy PutComplianceRulesetVariableJSONBodyAction = "copy" + Move PutComplianceRulesetVariableJSONBodyAction = "move" +) + +// Valid indicates whether the value is a known member of the PutComplianceRulesetVariableJSONBodyAction enum. +func (e PutComplianceRulesetVariableJSONBodyAction) Valid() bool { + switch e { + case Copy: + return true + case Move: + return true + default: + return false + } +} + // Defines values for PostFiltersJSONBodyFOp. const ( PostFiltersJSONBodyFOpEqual PostFiltersJSONBodyFOp = "=" @@ -1301,6 +1319,35 @@ type RulesetUsage struct { } `json:"services,omitempty"` } +// RulesetVariableListResponse defines model for RulesetVariableListResponse. +type RulesetVariableListResponse struct { + Data RulesetVariableListResponse_Data `json:"data"` + Meta *ListMeta `json:"meta,omitempty"` +} + +// RulesetVariableListResponseData0 defines model for . +type RulesetVariableListResponseData0 = []RulesetVariableRow + +// RulesetVariableListResponseData1 defines model for . +type RulesetVariableListResponseData1 map[string]map[string]int + +// RulesetVariableListResponse_Data defines model for RulesetVariableListResponse.Data. +type RulesetVariableListResponse_Data struct { + union json.RawMessage +} + +// RulesetVariableRow A variable of a compliance ruleset. Every property is optional: the `props` +// query parameter selects which columns the server returns. +type RulesetVariableRow struct { + Id *int `json:"id,omitempty"` + RulesetId *int `json:"ruleset_id,omitempty"` + VarAuthor *string `json:"var_author,omitempty"` + VarClass *string `json:"var_class,omitempty"` + VarName *string `json:"var_name,omitempty"` + VarUpdated *string `json:"var_updated,omitempty"` + VarValue *string `json:"var_value,omitempty"` +} + // ServiceListResponse defines model for ServiceListResponse. type ServiceListResponse struct { Data ServiceListResponse_Data `json:"data"` @@ -2107,6 +2154,94 @@ type PutComplianceRulesetJSONBody struct { // PutComplianceRulesetJSONBodyAction defines parameters for PutComplianceRuleset. type PutComplianceRulesetJSONBodyAction string +// GetComplianceRulesetVariablesParams defines parameters for GetComplianceRulesetVariables. +type GetComplianceRulesetVariablesParams struct { + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` + + // Limit The maximum number of entries to return. 0 means no limit. + Limit *InQueryLimit `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Skip the first entries of the data cursor. + Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` + + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. + Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` + + // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. + Stats *InQueryStats `form:"stats,omitempty" json:"stats,omitempty"` + + // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). + Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` + + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). + Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` +} + +// PostComplianceRulesetVariablesJSONBody defines parameters for PostComplianceRulesetVariables. +type PostComplianceRulesetVariablesJSONBody struct { + // VarClass The class of the variable, telling the modules how to read its value. + VarClass *string `json:"var_class,omitempty"` + VarName *string `json:"var_name,omitempty"` + + // VarValue The value, a string or any JSON value, stored serialized. + VarValue interface{} `json:"var_value,omitempty"` +} + +// GetComplianceRulesetVariableParams defines parameters for GetComplianceRulesetVariable. +type GetComplianceRulesetVariableParams struct { + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` +} + +// PostComplianceRulesetVariableJSONBody defines parameters for PostComplianceRulesetVariable. +type PostComplianceRulesetVariableJSONBody struct { + // VarClass The class of the variable, telling the modules how to read its value. + VarClass *string `json:"var_class,omitempty"` + VarName *string `json:"var_name,omitempty"` + + // VarValue The value, a string or any JSON value, stored serialized. + VarValue interface{} `json:"var_value,omitempty"` +} + +// PutComplianceRulesetVariableJSONBody defines parameters for PutComplianceRulesetVariable. +type PutComplianceRulesetVariableJSONBody struct { + Action PutComplianceRulesetVariableJSONBodyAction `json:"action"` + + // DstRuleset Id or name of the destination ruleset + DstRuleset interface{} `json:"dst_ruleset"` +} + +// PutComplianceRulesetVariableJSONBodyAction defines parameters for PutComplianceRulesetVariable. +type PutComplianceRulesetVariableJSONBodyAction string + +// PostComplianceRulesetsVariablesJSONBody defines parameters for PostComplianceRulesetsVariables. +type PostComplianceRulesetsVariablesJSONBody struct { + RulesetId *int `json:"ruleset_id,omitempty"` + RulesetName *string `json:"ruleset_name,omitempty"` + VarClass *string `json:"var_class,omitempty"` + VarName *string `json:"var_name,omitempty"` + + // VarValue The value, a string or any JSON value, stored serialized. + VarValue interface{} `json:"var_value,omitempty"` +} + // DeleteComplianceStatusJSONBody defines parameters for DeleteComplianceStatus. type DeleteComplianceStatusJSONBody struct { // Id Id of the run (comp_status.id) @@ -5587,6 +5722,18 @@ type PostComplianceRulesetJSONRequestBody PostComplianceRulesetJSONBody // PutComplianceRulesetJSONRequestBody defines body for PutComplianceRuleset for application/json ContentType. type PutComplianceRulesetJSONRequestBody PutComplianceRulesetJSONBody +// PostComplianceRulesetVariablesJSONRequestBody defines body for PostComplianceRulesetVariables for application/json ContentType. +type PostComplianceRulesetVariablesJSONRequestBody PostComplianceRulesetVariablesJSONBody + +// PostComplianceRulesetVariableJSONRequestBody defines body for PostComplianceRulesetVariable for application/json ContentType. +type PostComplianceRulesetVariableJSONRequestBody PostComplianceRulesetVariableJSONBody + +// PutComplianceRulesetVariableJSONRequestBody defines body for PutComplianceRulesetVariable for application/json ContentType. +type PutComplianceRulesetVariableJSONRequestBody PutComplianceRulesetVariableJSONBody + +// PostComplianceRulesetsVariablesJSONRequestBody defines body for PostComplianceRulesetsVariables for application/json ContentType. +type PostComplianceRulesetsVariablesJSONRequestBody PostComplianceRulesetsVariablesJSONBody + // DeleteComplianceStatusJSONRequestBody defines body for DeleteComplianceStatus for application/json ContentType. type DeleteComplianceStatusJSONRequestBody DeleteComplianceStatusJSONBody @@ -7057,6 +7204,68 @@ func (t *RulesetListResponse_Data) UnmarshalJSON(b []byte) error { return err } +// AsRulesetVariableListResponseData0 returns the union data inside the RulesetVariableListResponse_Data as a RulesetVariableListResponseData0 +func (t RulesetVariableListResponse_Data) AsRulesetVariableListResponseData0() (RulesetVariableListResponseData0, error) { + var body RulesetVariableListResponseData0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromRulesetVariableListResponseData0 overwrites any union data inside the RulesetVariableListResponse_Data as the provided RulesetVariableListResponseData0 +func (t *RulesetVariableListResponse_Data) FromRulesetVariableListResponseData0(v RulesetVariableListResponseData0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeRulesetVariableListResponseData0 performs a merge with any union data inside the RulesetVariableListResponse_Data, using the provided RulesetVariableListResponseData0 +func (t *RulesetVariableListResponse_Data) MergeRulesetVariableListResponseData0(v RulesetVariableListResponseData0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsRulesetVariableListResponseData1 returns the union data inside the RulesetVariableListResponse_Data as a RulesetVariableListResponseData1 +func (t RulesetVariableListResponse_Data) AsRulesetVariableListResponseData1() (RulesetVariableListResponseData1, error) { + var body RulesetVariableListResponseData1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromRulesetVariableListResponseData1 overwrites any union data inside the RulesetVariableListResponse_Data as the provided RulesetVariableListResponseData1 +func (t *RulesetVariableListResponse_Data) FromRulesetVariableListResponseData1(v RulesetVariableListResponseData1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeRulesetVariableListResponseData1 performs a merge with any union data inside the RulesetVariableListResponse_Data, using the provided RulesetVariableListResponseData1 +func (t *RulesetVariableListResponse_Data) MergeRulesetVariableListResponseData1(v RulesetVariableListResponseData1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t RulesetVariableListResponse_Data) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *RulesetVariableListResponse_Data) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + // AsServiceListResponseData0 returns the union data inside the ServiceListResponse_Data as a ServiceListResponseData0 func (t ServiceListResponse_Data) AsServiceListResponseData0() (ServiceListResponseData0, error) { var body ServiceListResponseData0 diff --git a/server/handlers/compliance_variables.go b/server/handlers/compliance_variables.go new file mode 100644 index 00000000..6504d060 --- /dev/null +++ b/server/handlers/compliance_variables.go @@ -0,0 +1,363 @@ +package serverhandlers + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + "strconv" + + "github.com/labstack/echo/v4" + + "github.com/opensvc/oc3/cdb" + "github.com/opensvc/oc3/server" +) + +// requireRulesetPublished refuses a caller the ruleset is not published to. +func (a *Api) requireRulesetPublished(ctx context.Context, c echo.Context, id int64) error { + ok, err := a.ODB.CompRulesetPublished(ctx, id, UserGroupsFromContext(c), IsManager(c)) + if err != nil { + return compDesignerError(c, "check the ruleset publication", err) + } + if !ok { + return httpErrorf(http.StatusForbidden, "you are not member of one of the ruleset publication groups") + } + return nil +} + +// resolveRulesetVariable returns the ids of a ruleset and of one of its +// variables, each given by id or by name. +func (a *Api) resolveRulesetVariable(ctx context.Context, rsetID, varID string) (int64, int64, error) { + rid, err := a.resolveRuleset(ctx, rsetID) + if err != nil { + return 0, 0, err + } + vid, found, err := a.ODB.CompRulesetVariableID(ctx, rid, varID) + if err != nil { + return 0, 0, err + } + if !found { + return 0, 0, httpErrorf(http.StatusNotFound, "variable %s not found", varID) + } + return rid, vid, nil +} + +// variableFields checks the settable properties of a variable. var_value may be +// given as a string, or as any JSON value, stored serialized. +func variableFields(entry map[string]any) (map[string]any, error) { + fields := map[string]any{} + for k, v := range entry { + switch k { + case "var_name": + name, err := compString(k, v, true) + if err != nil { + return nil, err + } + fields[k] = name + case "var_class": + class, err := compString(k, v, false) + if err != nil { + return nil, err + } + fields[k] = class + case "var_value": + if s, ok := v.(string); ok { + fields[k] = s + } else if v == nil { + fields[k] = nil + } else { + b, err := json.Marshal(v) + if err != nil { + return nil, httpErrorf(http.StatusBadRequest, "invalid var_value: %s", err) + } + fields[k] = string(b) + } + case "id", "ruleset_id", "ruleset_name", "var_author", "var_updated": + default: + return nil, httpErrorf(http.StatusBadRequest, "unknown variable property %s", k) + } + } + return fields, nil +} + +// GetComplianceRulesetVariables handles GET /compliance/rulesets/{rset_id}/variables: +// the variables of a ruleset published to the caller. +func (a *Api) GetComplianceRulesetVariables(c echo.Context, rsetId string, params server.GetComplianceRulesetVariablesParams) error { + ctx := c.Request().Context() + rid, err := a.resolveRuleset(ctx, rsetId) + if err == nil { + err = a.requireRulesetPublished(ctx, c, rid) + } + if err != nil { + return httpProblem(c, err) + } + return a.handleList(c, "GetComplianceRulesetVariables", "ruleset_variable", listEndpointParams{ + props: params.Props, limit: params.Limit, offset: params.Offset, + meta: params.Meta, stats: params.Stats, orderby: params.Orderby, groupby: params.Groupby, + filter: params.Filter, + }, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetComplianceRulesetVariables(ctx, rid, nil, p) + }) +} + +// GetComplianceRulesetVariable handles GET +// /compliance/rulesets/{rset_id}/variables/{var_id}. +func (a *Api) GetComplianceRulesetVariable(c echo.Context, rsetId, varId string, params server.GetComplianceRulesetVariableParams) error { + ctx := c.Request().Context() + rid, vid, err := a.resolveRulesetVariable(ctx, rsetId, varId) + if err == nil { + err = a.requireRulesetPublished(ctx, c, rid) + } + if err != nil { + return httpProblem(c, err) + } + return a.variableResponse(c, rid, vid, params.Props) +} + +func (a *Api) variableResponse(c echo.Context, rid, vid int64, props *server.InQueryProps) error { + return a.handleItem(c, "GetComplianceRulesetVariable", "ruleset_variable", "id", strconv.FormatInt(vid, 10), listEndpointParams{ + props: props, + }, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetComplianceRulesetVariables(ctx, rid, &vid, p) + }) +} + +// PostComplianceRulesetVariables handles POST /compliance/rulesets/{rset_id}/variables, +// as the historical rest_post_compliance_ruleset_variables: a variable named +// var_name is created, or updated when the ruleset has one of that name. +func (a *Api) PostComplianceRulesetVariables(c echo.Context, rsetId string) error { + entry, err := oneEntry(c) + if err != nil { + return httpProblem(c, err) + } + rid, err := a.resolveRuleset(c.Request().Context(), rsetId) + if err != nil { + return httpProblem(c, err) + } + return a.createOrUpdateVariable(c, rid, entry) +} + +// PostComplianceRulesetsVariables handles POST /compliance/rulesets_variables, +// the form naming the ruleset by ruleset_id or ruleset_name in the body. +func (a *Api) PostComplianceRulesetsVariables(c echo.Context) error { + entry, err := oneEntry(c) + if err != nil { + return httpProblem(c, err) + } + ref, ok := entry["ruleset_id"] + if !ok { + ref, ok = entry["ruleset_name"] + } + if !ok { + return httpProblem(c, httpErrorf(http.StatusBadRequest, "The 'ruleset_id' or 'ruleset_name' is mandatory")) + } + rid, err := a.resolveRuleset(c.Request().Context(), fmt.Sprint(ref)) + if err != nil { + return httpProblem(c, err) + } + return a.createOrUpdateVariable(c, rid, entry) +} + +func (a *Api) createOrUpdateVariable(c echo.Context, rid int64, entry map[string]any) error { + ctx := c.Request().Context() + if err := checkCompManager(c); err != nil { + return httpProblem(c, err) + } + if err := a.requireRulesetResponsible(ctx, c, rid); err != nil { + return httpProblem(c, err) + } + fields, err := variableFields(entry) + if err != nil { + return httpProblem(c, err) + } + name, ok := fields["var_name"].(string) + if !ok { + return httpProblem(c, httpErrorf(http.StatusBadRequest, "var_name is mandatory in the posted data")) + } + if vid, found, err := a.ODB.CompRulesetVariableID(ctx, rid, name); err != nil { + return httpProblem(c, compDesignerError(c, "PostComplianceRulesetVariables", err)) + } else if found { + return a.updateVariable(c, rid, vid, fields) + } + caller, err := a.formCaller(ctx, c) + if err != nil { + return httpProblem(c, compDesignerError(c, "PostComplianceRulesetVariables", err)) + } + vid, err := a.ODB.CreateCompRulesetVariable(ctx, rid, fields, caller.name) + if err != nil { + return httpProblem(c, compDesignerError(c, "PostComplianceRulesetVariables", err)) + } + fields["ruleset_id"] = rid + a.compLog(c, "compliance.ruleset.variable.create", "properties %(data)s", map[string]any{"data": compJSON(fields)}, "", "") + a.afterRulesetChange(c, false) + return a.variableResponse(c, rid, vid, nil) +} + +// PostComplianceRulesetVariable handles POST +// /compliance/rulesets/{rset_id}/variables/{var_id}: a change of the variable +// properties, by a CompManager responsible for the ruleset. +func (a *Api) PostComplianceRulesetVariable(c echo.Context, rsetId, varId string) error { + entry, err := oneEntry(c) + if err != nil { + return httpProblem(c, err) + } + ctx := c.Request().Context() + rid, vid, err := a.resolveRulesetVariable(ctx, rsetId, varId) + if err == nil { + err = checkCompManager(c) + } + if err == nil { + err = a.requireRulesetResponsible(ctx, c, rid) + } + if err != nil { + return httpProblem(c, err) + } + fields, err := variableFields(entry) + if err != nil { + return httpProblem(c, err) + } + return a.updateVariable(c, rid, vid, fields) +} + +func (a *Api) updateVariable(c echo.Context, rid, vid int64, fields map[string]any) error { + ctx := c.Request().Context() + if name, ok := fields["var_name"].(string); ok { + if other, found, err := a.ODB.CompRulesetVariableID(ctx, rid, name); err != nil { + return httpProblem(c, compDesignerError(c, "PostComplianceRulesetVariable", err)) + } else if found && other != vid { + return httpProblem(c, httpErrorf(http.StatusConflict, "'var_name' already exist in the same ruleset")) + } + } + before, err := a.ODB.CompRulesetVariableByID(ctx, vid) + if err != nil { + return httpProblem(c, compDesignerError(c, "PostComplianceRulesetVariable", err)) + } + caller, err := a.formCaller(ctx, c) + if err != nil { + return httpProblem(c, compDesignerError(c, "PostComplianceRulesetVariable", err)) + } + if err := a.ODB.UpdateCompRulesetVariable(ctx, vid, fields, caller.name); err != nil { + return httpProblem(c, compDesignerError(c, "PostComplianceRulesetVariable", err)) + } + a.compLog(c, "compliance.ruleset.variable.change", "changed properties %(data)s", map[string]any{ + "data": compJSON(map[string]any{"ruleset": before.RulesetName, "variable": before.Name, "changes": fields}), + }, "", "") + a.afterRulesetChange(c, false) + return a.variableResponse(c, rid, vid, nil) +} + +// DeleteComplianceRulesetVariable handles DELETE +// /compliance/rulesets/{rset_id}/variables/{var_id}, by a CompManager responsible +// for the ruleset, as the historical handler describes it. +func (a *Api) DeleteComplianceRulesetVariable(c echo.Context, rsetId, varId string) error { + ctx := c.Request().Context() + rid, vid, err := a.resolveRulesetVariable(ctx, rsetId, varId) + if err == nil { + err = checkCompManager(c) + } + if err == nil { + err = a.requireRulesetResponsible(ctx, c, rid) + } + if err != nil { + return httpProblem(c, err) + } + v, err := a.ODB.CompRulesetVariableByID(ctx, vid) + if err != nil { + return httpProblem(c, compDesignerError(c, "DeleteComplianceRulesetVariable", err)) + } + if err := a.ODB.DeleteCompRulesetVariable(ctx, vid); err != nil { + return httpProblem(c, compDesignerError(c, "DeleteComplianceRulesetVariable", err)) + } + a.compLog(c, "compliance.ruleset.variable.delete", "deleted variable %(var_name)s from ruleset %(rset_name)s", + map[string]any{"var_name": v.Name, "rset_name": v.RulesetName}, "", "") + a.afterRulesetChange(c, false) + return compInfo(c, "variable deleted") +} + +// PutComplianceRulesetVariable handles PUT +// /compliance/rulesets/{rset_id}/variables/{var_id}, the special actions on a +// variable, as the historical rest_put_compliance_ruleset_variable: copy or move +// to dst_ruleset. A copy requires the source ruleset to be published to the +// caller, a move its responsibility; both the responsibility of the destination. +func (a *Api) PutComplianceRulesetVariable(c echo.Context, rsetId, varId string) error { + entry, err := oneEntry(c) + if err != nil { + return httpProblem(c, err) + } + ctx := c.Request().Context() + rid, vid, err := a.resolveRulesetVariable(ctx, rsetId, varId) + if err != nil { + return httpProblem(c, err) + } + action, _ := entry["action"].(string) + if action != "copy" && action != "move" { + return httpProblem(c, httpErrorf(http.StatusBadRequest, "unsupported action %q", action)) + } + dst, ok := entry["dst_ruleset"] + if !ok { + return httpProblem(c, httpErrorf(http.StatusBadRequest, "dst_ruleset not found in data")) + } + dstID, err := a.resolveRuleset(ctx, fmt.Sprint(dst)) + if err != nil { + return httpProblem(c, err) + } + if err := checkCompManager(c); err != nil { + return httpProblem(c, err) + } + if action == "copy" { + err = a.requireRulesetPublished(ctx, c, rid) + } else { + err = a.requireRulesetResponsible(ctx, c, rid) + } + if err == nil { + err = a.requireRulesetResponsible(ctx, c, dstID) + } + if err != nil { + return httpProblem(c, err) + } + v, err := a.ODB.CompRulesetVariableByID(ctx, vid) + if err != nil { + return httpProblem(c, compDesignerError(c, "PutComplianceRulesetVariable", err)) + } + // Names are unique in a ruleset: the historical handlers refuse a duplicate on + // creation and change, not on copy or move; refused here as well. + if _, found, err := a.ODB.CompRulesetVariableID(ctx, dstID, v.Name); err != nil { + return httpProblem(c, compDesignerError(c, "PutComplianceRulesetVariable", err)) + } else if found { + return httpProblem(c, httpErrorf(http.StatusConflict, "the destination ruleset already has a variable named %s", v.Name)) + } + dstName, err := a.ODB.CompRulesetNameByID(ctx, dstID) + if err != nil { + return httpProblem(c, compDesignerError(c, "PutComplianceRulesetVariable", err)) + } + dict := map[string]any{"rset_name": v.RulesetName, "dst_rset_name": dstName, "var_name": v.Name} + if action == "copy" { + caller, err := a.formCaller(ctx, c) + if err != nil { + return httpProblem(c, compDesignerError(c, "PutComplianceRulesetVariable", err)) + } + if _, err := a.ODB.CopyCompRulesetVariable(ctx, vid, dstID, caller.name); err != nil { + return httpProblem(c, compDesignerError(c, "PutComplianceRulesetVariable", err)) + } + a.compLog(c, "compliance.variable.copy", "copy variable %(var_name)s from ruleset %(rset_name)s to %(dst_rset_name)s", dict, "", "") + } else { + if err := a.ODB.MoveCompRulesetVariable(ctx, vid, dstID); err != nil { + return httpProblem(c, compDesignerError(c, "PutComplianceRulesetVariable", err)) + } + a.compLog(c, "compliance.variable.change", "move variable %(var_name)s from ruleset %(rset_name)s to %(dst_rset_name)s", dict, "", "") + } + a.afterRulesetChange(c, false) + return compInfo(c, "variable %s done", action) +} + +// oneEntry reads a body holding one object, JSON or form-encoded. +func oneEntry(c echo.Context) (map[string]any, error) { + entries, _, err := decodeEntries(c) + if err != nil { + return nil, httpErrorf(http.StatusBadRequest, "%s", err) + } + if len(entries) != 1 { + return nil, httpErrorf(http.StatusBadRequest, "one object is expected in the body") + } + return entries[0], nil +} diff --git a/server/handlers/props_mapping.go b/server/handlers/props_mapping.go index f6bd5678..8d989e63 100644 --- a/server/handlers/props_mapping.go +++ b/server/handlers/props_mapping.go @@ -757,6 +757,19 @@ var propsMapping = map[string]propMapping{ "ruleset_public": colStr(schema.CompRulesetsRulesetPublic), }, }, + // Variables of a compliance ruleset: the rules the modules apply. + "ruleset_variable": { + Available: []string{"id", "ruleset_id", "var_name", "var_class", "var_value", "var_author", "var_updated"}, + Props: map[string]propDef{ + "id": col(schema.CompRulesetsVariablesID), + "ruleset_id": colInt(schema.CompRulesetsVariablesRulesetID), + "var_name": colStr(schema.CompRulesetsVariablesVarName), + "var_class": colStr(schema.CompRulesetsVariablesVarClass), + "var_value": colStr(schema.CompRulesetsVariablesVarValue), + "var_author": colStr(schema.CompRulesetsVariablesVarAuthor), + "var_updated": colStr(schema.CompRulesetsVariablesVarUpdated), + }, + }, "alert_event": { Available: []string{"id", "svc_id", "node_id", "dash_begin", "dash_end", "dash_md5"}, Props: map[string]propDef{ From 246ab6a26edfa88a8e9d00c650a7ae0404ed70b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Mon, 28 Sep 2026 13:34:56 +0200 Subject: [PATCH 39/61] Add the compliance ruleset composition endpoints Port the ruleset hierarchy and filterset endpoints of the historical api_compliance: - POST and DELETE /compliance/rulesets/{rset_id}/rulesets/{child_rset_id}, as attach_ruleset_to_ruleset() and detach_ruleset_from_ruleset(): by a CompManager responsible for the parent, the child being published to them for a detach. Attaching a ruleset to itself (400), twice or under one of its descendants (409) is refused; the ruleset chains are rebuilt. - POST and DELETE /compliance/rulesets/{rset_id}/filtersets/{fset_id}, the filterset of a contextual ruleset, replaced on attach and removed whichever it is on detach, as the historical handlers do. Rulesets and filtersets are given by id or name; changes are logged. --- cdb/db_compliance_ruleset_links.go | 105 +++ server/api.yaml | 177 ++++ server/codegen_server_gen.go | 859 +++++++++++--------- server/handlers/compliance_ruleset_links.go | 179 ++++ 4 files changed, 957 insertions(+), 363 deletions(-) create mode 100644 cdb/db_compliance_ruleset_links.go create mode 100644 server/handlers/compliance_ruleset_links.go diff --git a/cdb/db_compliance_ruleset_links.go b/cdb/db_compliance_ruleset_links.go new file mode 100644 index 00000000..9727a112 --- /dev/null +++ b/cdb/db_compliance_ruleset_links.go @@ -0,0 +1,105 @@ +package cdb + +import ( + "context" + "database/sql" + "errors" + "fmt" +) + +// CompRulesetChildAttached tells whether child is a child of parent. +func (oDb *DB) CompRulesetChildAttached(ctx context.Context, parent, child int64) (bool, error) { + return oDb.exists(ctx, "compRulesetChildAttached", + "SELECT 1 FROM comp_rulesets_rulesets WHERE parent_rset_id = ? AND child_rset_id = ?", parent, child) +} + +// CompRulesetLoop tells whether attaching child under parent would close a loop: +// child already is an ancestor of parent, as rset_loop(). +func (oDb *DB) CompRulesetLoop(ctx context.Context, child, parent int64) (bool, error) { + parents := map[int64][]int64{} + rows, err := oDb.DB.QueryContext(ctx, "SELECT parent_rset_id, child_rset_id FROM comp_rulesets_rulesets") + if err != nil { + return false, fmt.Errorf("compRulesetLoop: %w", err) + } + for rows.Next() { + var p, c int64 + if err := rows.Scan(&p, &c); err != nil { + _ = rows.Close() + return false, fmt.Errorf("compRulesetLoop: %w", err) + } + parents[c] = append(parents[c], p) + } + _ = rows.Close() + seen := map[int64]bool{} + todo := []int64{parent} + for len(todo) > 0 { + id := todo[0] + todo = todo[1:] + for _, p := range parents[id] { + if p == child { + return true, nil + } + if !seen[p] { + seen[p] = true + todo = append(todo, p) + } + } + } + return false, nil +} + +// AttachCompRulesetChild makes child a child of parent. +func (oDb *DB) AttachCompRulesetChild(ctx context.Context, parent, child int64) error { + if _, err := oDb.DB.ExecContext(ctx, "INSERT INTO comp_rulesets_rulesets (parent_rset_id, child_rset_id) VALUES (?, ?)", parent, child); err != nil { + return fmt.Errorf("attachCompRulesetChild: %w", err) + } + oDb.SetChange("comp_rulesets_rulesets") + return nil +} + +// DetachCompRulesetChild removes child from the children of parent. +func (oDb *DB) DetachCompRulesetChild(ctx context.Context, parent, child int64) error { + if _, err := oDb.DB.ExecContext(ctx, "DELETE FROM comp_rulesets_rulesets WHERE parent_rset_id = ? AND child_rset_id = ?", parent, child); err != nil { + return fmt.Errorf("detachCompRulesetChild: %w", err) + } + oDb.SetChange("comp_rulesets_rulesets") + return nil +} + +// CompRulesetFilterset returns the filterset of a contextual ruleset, with its +// name; false when it has none. +func (oDb *DB) CompRulesetFilterset(ctx context.Context, rulesetID int64) (int64, string, bool, error) { + var id int64 + var name sql.NullString + err := oDb.DB.QueryRowContext(ctx, "SELECT f.id, f.fset_name FROM comp_rulesets_filtersets rf"+ + " JOIN gen_filtersets f ON f.id = rf.fset_id WHERE rf.ruleset_id = ? LIMIT 1", rulesetID).Scan(&id, &name) + switch { + case errors.Is(err, sql.ErrNoRows): + return 0, "", false, nil + case err != nil: + return 0, "", false, fmt.Errorf("compRulesetFilterset: %w", err) + } + return id, name.String, true, nil +} + +// SetCompRulesetFilterset gives a ruleset its filterset, replacing the previous +// one: a ruleset has at most one, as update_or_insert() keeps it. +func (oDb *DB) SetCompRulesetFilterset(ctx context.Context, rulesetID, fsetID int64) error { + if _, err := oDb.DB.ExecContext(ctx, "DELETE FROM comp_rulesets_filtersets WHERE ruleset_id = ?", rulesetID); err != nil { + return fmt.Errorf("setCompRulesetFilterset: %w", err) + } + if _, err := oDb.DB.ExecContext(ctx, "INSERT INTO comp_rulesets_filtersets (ruleset_id, fset_id) VALUES (?, ?)", rulesetID, fsetID); err != nil { + return fmt.Errorf("setCompRulesetFilterset: %w", err) + } + oDb.SetChange("comp_rulesets_filtersets") + return nil +} + +// DeleteCompRulesetFilterset removes the filterset of a ruleset. +func (oDb *DB) DeleteCompRulesetFilterset(ctx context.Context, rulesetID int64) error { + if _, err := oDb.DB.ExecContext(ctx, "DELETE FROM comp_rulesets_filtersets WHERE ruleset_id = ?", rulesetID); err != nil { + return fmt.Errorf("deleteCompRulesetFilterset: %w", err) + } + oDb.SetChange("comp_rulesets_filtersets") + return nil +} diff --git a/server/api.yaml b/server/api.yaml index 65ee1863..81cbf23d 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -9698,6 +9698,183 @@ paths: - basicAuth: [ ] - bearerAuth: [ ] + /compliance/rulesets/{rset_id}/rulesets/{child_rset_id}: + post: + operationId: PostComplianceRulesetRuleset + description: | + Make a ruleset a child of another. Requires the CompManager privilege and the + responsibility of the parent. Attaching a ruleset to itself, twice, or under + one of its own descendants is refused. The change is logged and the ruleset + chains are rebuilt. + parameters: + - in: path + name: rset_id + required: true + description: Parent ruleset id or name + schema: + type: string + - in: path + name: child_rset_id + required: true + description: Child ruleset id or name + schema: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 409: + $ref: '#/components/responses/409' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + delete: + operationId: DeleteComplianceRulesetRuleset + description: | + Remove a ruleset from the children of another. Requires the CompManager + privilege, the responsibility of the parent and the publication of the child. + The change is logged and the ruleset chains are rebuilt. + parameters: + - in: path + name: rset_id + required: true + description: Parent ruleset id or name + schema: + type: string + - in: path + name: child_rset_id + required: true + description: Child ruleset id or name + schema: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /compliance/rulesets/{rset_id}/filtersets/{fset_id}: + post: + operationId: PostComplianceRulesetFilterset + description: | + Give a contextual ruleset the filterset selecting the nodes and services it + applies to, replacing its previous one. Requires the CompManager privilege and + the responsibility of the ruleset. The change is logged. + parameters: + - in: path + name: rset_id + required: true + description: Ruleset id or name + schema: + type: string + - in: path + name: fset_id + required: true + description: Filterset id or name + schema: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + delete: + operationId: DeleteComplianceRulesetFilterset + description: | + Remove the filterset of a ruleset, whichever it is, as the historical handler. + Requires the CompManager privilege and the responsibility of the ruleset. The + change is logged. + parameters: + - in: path + name: rset_id + required: true + description: Ruleset id or name + schema: + type: string + - in: path + name: fset_id + required: true + description: Filterset id or name + schema: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + components: responses: diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index e29d0831..1e2b48d8 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -153,6 +153,18 @@ type ServerInterface interface { // (GET /compliance/rulesets/{rset_id}/am_i_responsible) GetComplianceRulesetAmIResponsible(ctx echo.Context, rsetId string) error + // (DELETE /compliance/rulesets/{rset_id}/filtersets/{fset_id}) + DeleteComplianceRulesetFilterset(ctx echo.Context, rsetId string, fsetId string) error + + // (POST /compliance/rulesets/{rset_id}/filtersets/{fset_id}) + PostComplianceRulesetFilterset(ctx echo.Context, rsetId string, fsetId string) error + + // (DELETE /compliance/rulesets/{rset_id}/rulesets/{child_rset_id}) + DeleteComplianceRulesetRuleset(ctx echo.Context, rsetId string, childRsetId string) error + + // (POST /compliance/rulesets/{rset_id}/rulesets/{child_rset_id}) + PostComplianceRulesetRuleset(ctx echo.Context, rsetId string, childRsetId string) error + // (GET /compliance/rulesets/{rset_id}/usage) GetComplianceRulesetUsage(ctx echo.Context, rsetId string) error @@ -2290,6 +2302,118 @@ func (w *ServerInterfaceWrapper) GetComplianceRulesetAmIResponsible(ctx echo.Con return err } +// DeleteComplianceRulesetFilterset converts echo context to params. +func (w *ServerInterfaceWrapper) DeleteComplianceRulesetFilterset(ctx echo.Context) error { + var err error + // ------------- Path parameter "rset_id" ------------- + var rsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "rset_id", ctx.Param("rset_id"), &rsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter rset_id: %s", err)) + } + + // ------------- Path parameter "fset_id" ------------- + var fsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "fset_id", ctx.Param("fset_id"), &fsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter fset_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.DeleteComplianceRulesetFilterset(ctx, rsetId, fsetId) + return err +} + +// PostComplianceRulesetFilterset converts echo context to params. +func (w *ServerInterfaceWrapper) PostComplianceRulesetFilterset(ctx echo.Context) error { + var err error + // ------------- Path parameter "rset_id" ------------- + var rsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "rset_id", ctx.Param("rset_id"), &rsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter rset_id: %s", err)) + } + + // ------------- Path parameter "fset_id" ------------- + var fsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "fset_id", ctx.Param("fset_id"), &fsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter fset_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostComplianceRulesetFilterset(ctx, rsetId, fsetId) + return err +} + +// DeleteComplianceRulesetRuleset converts echo context to params. +func (w *ServerInterfaceWrapper) DeleteComplianceRulesetRuleset(ctx echo.Context) error { + var err error + // ------------- Path parameter "rset_id" ------------- + var rsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "rset_id", ctx.Param("rset_id"), &rsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter rset_id: %s", err)) + } + + // ------------- Path parameter "child_rset_id" ------------- + var childRsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "child_rset_id", ctx.Param("child_rset_id"), &childRsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter child_rset_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.DeleteComplianceRulesetRuleset(ctx, rsetId, childRsetId) + return err +} + +// PostComplianceRulesetRuleset converts echo context to params. +func (w *ServerInterfaceWrapper) PostComplianceRulesetRuleset(ctx echo.Context) error { + var err error + // ------------- Path parameter "rset_id" ------------- + var rsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "rset_id", ctx.Param("rset_id"), &rsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter rset_id: %s", err)) + } + + // ------------- Path parameter "child_rset_id" ------------- + var childRsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "child_rset_id", ctx.Param("child_rset_id"), &childRsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter child_rset_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostComplianceRulesetRuleset(ctx, rsetId, childRsetId) + return err +} + // GetComplianceRulesetUsage converts echo context to params. func (w *ServerInterfaceWrapper) GetComplianceRulesetUsage(ctx echo.Context) error { var err error @@ -11024,6 +11148,10 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.POST(options.BaseURL+"/compliance/rulesets/:rset_id", wrapper.PostComplianceRuleset, options.OperationMiddlewares["PostComplianceRuleset"]...) router.PUT(options.BaseURL+"/compliance/rulesets/:rset_id", wrapper.PutComplianceRuleset, options.OperationMiddlewares["PutComplianceRuleset"]...) router.GET(options.BaseURL+"/compliance/rulesets/:rset_id/am_i_responsible", wrapper.GetComplianceRulesetAmIResponsible, options.OperationMiddlewares["GetComplianceRulesetAmIResponsible"]...) + router.DELETE(options.BaseURL+"/compliance/rulesets/:rset_id/filtersets/:fset_id", wrapper.DeleteComplianceRulesetFilterset, options.OperationMiddlewares["DeleteComplianceRulesetFilterset"]...) + router.POST(options.BaseURL+"/compliance/rulesets/:rset_id/filtersets/:fset_id", wrapper.PostComplianceRulesetFilterset, options.OperationMiddlewares["PostComplianceRulesetFilterset"]...) + router.DELETE(options.BaseURL+"/compliance/rulesets/:rset_id/rulesets/:child_rset_id", wrapper.DeleteComplianceRulesetRuleset, options.OperationMiddlewares["DeleteComplianceRulesetRuleset"]...) + router.POST(options.BaseURL+"/compliance/rulesets/:rset_id/rulesets/:child_rset_id", wrapper.PostComplianceRulesetRuleset, options.OperationMiddlewares["PostComplianceRulesetRuleset"]...) router.GET(options.BaseURL+"/compliance/rulesets/:rset_id/usage", wrapper.GetComplianceRulesetUsage, options.OperationMiddlewares["GetComplianceRulesetUsage"]...) router.GET(options.BaseURL+"/compliance/rulesets/:rset_id/variables", wrapper.GetComplianceRulesetVariables, options.OperationMiddlewares["GetComplianceRulesetVariables"]...) router.POST(options.BaseURL+"/compliance/rulesets/:rset_id/variables", wrapper.PostComplianceRulesetVariables, options.OperationMiddlewares["PostComplianceRulesetVariables"]...) @@ -11231,370 +11359,375 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "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", + "z09//v8BAAD//w==", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/handlers/compliance_ruleset_links.go b/server/handlers/compliance_ruleset_links.go new file mode 100644 index 00000000..9e22cebb --- /dev/null +++ b/server/handlers/compliance_ruleset_links.go @@ -0,0 +1,179 @@ +package serverhandlers + +import ( + "net/http" + + "github.com/labstack/echo/v4" +) + +// PostComplianceRulesetRuleset handles POST +// /compliance/rulesets/{rset_id}/rulesets/{child_rset_id}, as the historical +// attach_ruleset_to_ruleset(): by a CompManager responsible for the parent, a +// ruleset becomes a child of another, unless that would close a loop. +func (a *Api) PostComplianceRulesetRuleset(c echo.Context, rsetId, childRsetId string) error { + ctx := c.Request().Context() + parent, err := a.resolveRuleset(ctx, rsetId) + if err != nil { + return httpProblem(c, err) + } + child, err := a.resolveRuleset(ctx, childRsetId) + if err != nil { + return httpProblem(c, err) + } + if err := checkCompManager(c); err != nil { + return httpProblem(c, err) + } + if parent == child { + return httpProblem(c, httpErrorf(http.StatusBadRequest, "abort action to avoid introducing a recursion loop")) + } + if err := a.requireRulesetResponsible(ctx, c, parent); err != nil { + return httpProblem(c, err) + } + if attached, err := a.ODB.CompRulesetChildAttached(ctx, parent, child); err != nil { + return httpProblem(c, compDesignerError(c, "PostComplianceRulesetRuleset", err)) + } else if attached { + return httpProblem(c, httpErrorf(http.StatusConflict, "ruleset already attached")) + } + if loop, err := a.ODB.CompRulesetLoop(ctx, child, parent); err != nil { + return httpProblem(c, compDesignerError(c, "PostComplianceRulesetRuleset", err)) + } else if loop { + return httpProblem(c, httpErrorf(http.StatusConflict, "the parent ruleset is already a child of the encapsulated ruleset. abort encapsulation not to cause infinite recursion")) + } + names, err := a.rulesetNames(c, parent, child) + if err != nil { + return httpProblem(c, err) + } + if err := a.ODB.AttachCompRulesetChild(ctx, parent, child); err != nil { + return httpProblem(c, compDesignerError(c, "PostComplianceRulesetRuleset", err)) + } + a.afterRulesetChange(c, true) + a.compLog(c, "compliance.ruleset.attach", "attach ruleset %(rset_name)s to %(dst_rset_name)s", + map[string]any{"rset_name": names[1], "dst_rset_name": names[0]}, "", "") + return compInfo(c, "ruleset attached") +} + +// DeleteComplianceRulesetRuleset handles DELETE +// /compliance/rulesets/{rset_id}/rulesets/{child_rset_id}, as the historical +// detach_ruleset_from_ruleset(): by a CompManager responsible for the parent, the +// child being published to them. +func (a *Api) DeleteComplianceRulesetRuleset(c echo.Context, rsetId, childRsetId string) error { + ctx := c.Request().Context() + parent, err := a.resolveRuleset(ctx, rsetId) + if err != nil { + return httpProblem(c, err) + } + child, err := a.resolveRuleset(ctx, childRsetId) + if err != nil { + return httpProblem(c, err) + } + if err := checkCompManager(c); err != nil { + return httpProblem(c, err) + } + if err := a.requireRulesetResponsible(ctx, c, parent); err != nil { + return httpProblem(c, err) + } + if err := a.requireRulesetPublished(ctx, c, child); err != nil { + return httpProblem(c, err) + } + names, err := a.rulesetNames(c, parent, child) + if err != nil { + return httpProblem(c, err) + } + if err := a.ODB.DetachCompRulesetChild(ctx, parent, child); err != nil { + return httpProblem(c, compDesignerError(c, "DeleteComplianceRulesetRuleset", err)) + } + a.afterRulesetChange(c, true) + a.compLog(c, "compliance.ruleset.detach", "detach ruleset %(rset_name)s from %(parent_rset_name)s", + map[string]any{"rset_name": names[1], "parent_rset_name": names[0]}, "", "") + return compInfo(c, "ruleset detached") +} + +// rulesetNames returns the names of rulesets, for the logs. +func (a *Api) rulesetNames(c echo.Context, ids ...int64) ([]string, error) { + names := make([]string, len(ids)) + for i, id := range ids { + name, err := a.ODB.CompRulesetNameByID(c.Request().Context(), id) + if err != nil { + return nil, compDesignerError(c, "read the ruleset name", err) + } + names[i] = name + } + return names, nil +} + +// PostComplianceRulesetFilterset handles POST +// /compliance/rulesets/{rset_id}/filtersets/{fset_id}, as the historical +// attach_filterset_to_ruleset(): the filterset selecting the nodes and services a +// contextual ruleset applies to, replacing the previous one. +func (a *Api) PostComplianceRulesetFilterset(c echo.Context, rsetId, fsetId string) error { + ctx := c.Request().Context() + rid, err := a.resolveRuleset(ctx, rsetId) + if err != nil { + return httpProblem(c, err) + } + fid, fname, err := a.ODB.FiltersetByIDOrName(ctx, fsetId) + if err != nil { + return httpProblem(c, compDesignerError(c, "PostComplianceRulesetFilterset", err)) + } + if fid == 0 { + return httpProblem(c, httpErrorf(http.StatusNotFound, "filterset %s not found", fsetId)) + } + if err := checkCompManager(c); err != nil { + return httpProblem(c, err) + } + if err := a.requireRulesetResponsible(ctx, c, rid); err != nil { + return httpProblem(c, err) + } + if current, _, found, err := a.ODB.CompRulesetFilterset(ctx, rid); err != nil { + return httpProblem(c, compDesignerError(c, "PostComplianceRulesetFilterset", err)) + } else if found && current == int64(fid) { + return compInfo(c, "filterset attached") + } + names, err := a.rulesetNames(c, rid) + if err != nil { + return httpProblem(c, err) + } + if err := a.ODB.SetCompRulesetFilterset(ctx, rid, int64(fid)); err != nil { + return httpProblem(c, compDesignerError(c, "PostComplianceRulesetFilterset", err)) + } + a.afterRulesetChange(c, false) + a.compLog(c, "compliance.ruleset.change", "attach filterset %(fset_name)s to ruleset %(rset_name)s", + map[string]any{"rset_name": names[0], "fset_name": fname}, "", "") + return compInfo(c, "filterset attached") +} + +// DeleteComplianceRulesetFilterset handles DELETE +// /compliance/rulesets/{rset_id}/filtersets/{fset_id}, as the historical +// detach_filterset_from_ruleset(): the ruleset's filterset is removed, whichever +// it is. +func (a *Api) DeleteComplianceRulesetFilterset(c echo.Context, rsetId, fsetId string) error { + ctx := c.Request().Context() + rid, err := a.resolveRuleset(ctx, rsetId) + if err != nil { + return httpProblem(c, err) + } + if err := checkCompManager(c); err != nil { + return httpProblem(c, err) + } + if err := a.requireRulesetResponsible(ctx, c, rid); err != nil { + return httpProblem(c, err) + } + _, fname, found, err := a.ODB.CompRulesetFilterset(ctx, rid) + if err != nil { + return httpProblem(c, compDesignerError(c, "DeleteComplianceRulesetFilterset", err)) + } + if !found { + return httpProblem(c, httpErrorf(http.StatusNotFound, "filterset not found")) + } + names, err := a.rulesetNames(c, rid) + if err != nil { + return httpProblem(c, err) + } + if err := a.ODB.DeleteCompRulesetFilterset(ctx, rid); err != nil { + return httpProblem(c, compDesignerError(c, "DeleteComplianceRulesetFilterset", err)) + } + a.afterRulesetChange(c, false) + a.compLog(c, "compliance.filterset.detach", "detach filterset %(fset_name)s from ruleset %(rset_name)s", + map[string]any{"rset_name": names[0], "fset_name": fname}, "", "") + return compInfo(c, "filterset detached") +} From 268715a6db57ab2b8153534d742cfeeece9ba1dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Mon, 28 Sep 2026 13:38:28 +0200 Subject: [PATCH 40/61] Add the compliance ruleset publication and responsible endpoints Port the ruleset group endpoints of the historical api_compliance: - GET /compliance/rulesets/{rset_id}/publications and /responsibles, the groups of a ruleset, a non-manager seeing only their own among them; - POST and DELETE /compliance/rulesets/{rset_id}/publications/{group_id} and /responsibles/{group_id}, and their bulk forms naming both in the body, /compliance/rulesets_publications and /rulesets_responsibles. As attach_group_to_ruleset() and detach_group_from_ruleset(), changes require the CompManager privilege and the responsibility of the ruleset; a non-manager may attach only one of their groups; Everybody may not be made responsible, nor be given the publication of a contextual ruleset; an already attached group is answered with an information. Groups are given by id or role; changes are logged. The group logic is written once over a CompKind naming the tables of a kind, for the modulesets to use as well. --- cdb/db_compliance_rulesets.go | 6 + cdb/db_compliance_teams.go | 112 +++ server/api.yaml | 432 +++++++++++ server/codegen_server_gen.go | 1104 ++++++++++++++++++--------- server/codegen_type_gen.go | 128 ++++ server/handlers/compliance_teams.go | 189 +++++ 6 files changed, 1602 insertions(+), 369 deletions(-) create mode 100644 cdb/db_compliance_teams.go create mode 100644 server/handlers/compliance_teams.go diff --git a/cdb/db_compliance_rulesets.go b/cdb/db_compliance_rulesets.go index 390231b0..7f2b5647 100644 --- a/cdb/db_compliance_rulesets.go +++ b/cdb/db_compliance_rulesets.go @@ -398,3 +398,9 @@ var ( ErrCompNotFound = errors.New("not found") ErrCompConflict = errors.New("conflict") ) + +// RulesetIsContextual tells whether a ruleset is contextual, applied through its +// filterset rather than by attachment. +func (oDb *DB) RulesetIsContextual(ctx context.Context, id int64) (bool, error) { + return oDb.exists(ctx, "rulesetIsContextual", "SELECT 1 FROM comp_rulesets WHERE id = ? AND ruleset_type = 'contextual'", id) +} diff --git a/cdb/db_compliance_teams.go b/cdb/db_compliance_teams.go new file mode 100644 index 00000000..f58912cb --- /dev/null +++ b/cdb/db_compliance_teams.go @@ -0,0 +1,112 @@ +package cdb + +import ( + "context" + "fmt" +) + +// CompKind names the tables of a compliance object kind that has publication and +// responsible groups: rulesets and modulesets. +type CompKind struct { + // Name is the kind as the messages name it: "ruleset", "moduleset". + Name string + // Table and NameCol are the object table and its name column. + Table, NameCol string + // TeamPrefix is the prefix of the group tables, completed by "publication" + // or "responsible"; FK is their column naming the object. + TeamPrefix, FK string +} + +var ( + CompRulesetKind = CompKind{Name: "ruleset", Table: "comp_rulesets", NameCol: "ruleset_name", TeamPrefix: "comp_ruleset_team_", FK: "ruleset_id"} + CompModulesetKind = CompKind{Name: "moduleset", Table: "comp_moduleset", NameCol: "modset_name", TeamPrefix: "comp_moduleset_team_", FK: "modset_id"} +) + +// CompTeamTypes are the two kinds of groups of a compliance object. +var CompTeamTypes = []string{"publication", "responsible"} + +func (k CompKind) teamTable(gtype string) (string, error) { + for _, t := range CompTeamTypes { + if t == gtype { + return k.TeamPrefix + gtype, nil + } + } + return "", fmt.Errorf("unknown group type %q", gtype) +} + +// GetCompTeamGroups lists the publication or responsible groups of a compliance +// object; a non-manager sees only those they are a member of, as the historical +// rest_get_compliance_*_publications and _responsibles. +func (oDb *DB) GetCompTeamGroups(ctx context.Context, k CompKind, objID int64, gtype string, p ListParams) ([]map[string]any, error) { + table, err := k.teamTable(gtype) + if err != nil { + return nil, err + } + conds := []string{"auth_group.id IN (SELECT group_id FROM " + table + " WHERE " + k.FK + " = ?)"} + args := []any{objID} + if !p.IsManager { + cond, condArgs := rolesCond("auth_group", p.Groups, false) + conds = append(conds, cond) + args = append(args, condArgs...) + } + return oDb.listQuery(ctx, "getCompTeamGroups", "auth_group", conds, args, "auth_group.role", p) +} + +// CompTeamAttached tells whether a group is a publication or responsible group of +// a compliance object. +func (oDb *DB) CompTeamAttached(ctx context.Context, k CompKind, objID int64, gtype string, groupID int64) (bool, error) { + table, err := k.teamTable(gtype) + if err != nil { + return false, err + } + return oDb.exists(ctx, "compTeamAttached", "SELECT 1 FROM "+table+" WHERE "+k.FK+" = ? AND group_id = ?", objID, groupID) +} + +// AttachCompTeam makes a group a publication or responsible group of a +// compliance object. +func (oDb *DB) AttachCompTeam(ctx context.Context, k CompKind, objID int64, gtype string, groupID int64) error { + table, err := k.teamTable(gtype) + if err != nil { + return err + } + if _, err := oDb.DB.ExecContext(ctx, "INSERT INTO "+table+" ("+k.FK+", group_id) VALUES (?, ?)", objID, groupID); err != nil { + return fmt.Errorf("attachCompTeam: %w", err) + } + oDb.SetChange(table) + return nil +} + +// DetachCompTeam removes a publication or responsible group from a compliance +// object. +func (oDb *DB) DetachCompTeam(ctx context.Context, k CompKind, objID int64, gtype string, groupID int64) error { + table, err := k.teamTable(gtype) + if err != nil { + return err + } + if _, err := oDb.DB.ExecContext(ctx, "DELETE FROM "+table+" WHERE "+k.FK+" = ? AND group_id = ?", objID, groupID); err != nil { + return fmt.Errorf("detachCompTeam: %w", err) + } + oDb.SetChange(table) + return nil +} + +// CompObjectName returns the name of a compliance object. +func (oDb *DB) CompObjectName(ctx context.Context, k CompKind, objID int64) (string, error) { + var name string + if err := oDb.DB.QueryRowContext(ctx, "SELECT COALESCE("+k.NameCol+", '') FROM "+k.Table+" WHERE id = ?", objID).Scan(&name); err != nil { + return "", fmt.Errorf("compObjectName: %w", err) + } + return name, nil +} + +// CompObjectResponsible tells whether one of the caller's organization groups is +// responsible for a compliance object, as ruleset_responsible() and +// moduleset_responsible(); always for a manager, when the object exists. +func (oDb *DB) CompObjectResponsible(ctx context.Context, k CompKind, objID int64, groups []string, isManager bool) (bool, error) { + if isManager { + return oDb.exists(ctx, "compObjectResponsible", "SELECT 1 FROM "+k.Table+" WHERE id = ?", objID) + } + cond, args := rolesCond("ag", groups, true) + return oDb.exists(ctx, "compObjectResponsible", "SELECT 1 FROM "+k.TeamPrefix+"responsible r"+ + " JOIN auth_group ag ON ag.id = r.group_id WHERE r."+k.FK+" = ? AND "+cond, append([]any{objID}, args...)...) +} diff --git a/server/api.yaml b/server/api.yaml index 81cbf23d..7103eeb6 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -9875,6 +9875,438 @@ paths: - basicAuth: [ ] - bearerAuth: [ ] + /compliance/rulesets/{rset_id}/publications: + get: + operationId: GetComplianceRulesetPublications + description: | + List the publication groups of a ruleset; a non-manager sees only the ones they are + a member of. + parameters: + - in: path + name: rset_id + required: true + description: Ruleset id or name + schema: + type: string + - $ref: '#/components/parameters/inQueryProps' + - $ref: '#/components/parameters/inQueryLimit' + - $ref: '#/components/parameters/inQueryOffset' + - $ref: '#/components/parameters/inQueryMeta' + - $ref: '#/components/parameters/inQueryStats' + - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryFilter' + - $ref: '#/components/parameters/inQueryGroupby' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/GroupListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /compliance/rulesets/{rset_id}/publications/{group_id}: + post: + operationId: PostComplianceRulesetPublication + description: | + Make a group a publication group of the ruleset. Requires the CompManager privilege + and the responsibility of the ruleset; a non-manager may attach only one of their + groups. Everybody may not be made responsible, nor be given the publication of a + contextual ruleset. The change is logged. + parameters: + - in: path + name: rset_id + required: true + description: Ruleset id or name + schema: + type: string + - in: path + name: group_id + required: true + description: Group id or role + schema: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + delete: + operationId: DeleteComplianceRulesetPublication + description: | + Remove a publication group from the ruleset. Requires the CompManager privilege and + the responsibility of the ruleset. The change is logged. + parameters: + - in: path + name: rset_id + required: true + description: Ruleset id or name + schema: + type: string + - in: path + name: group_id + required: true + description: Group id or role + schema: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /compliance/rulesets_publications: + post: + operationId: PostComplianceRulesetsPublications + description: | + Attach a publication group to a ruleset, as + POST /compliance/rulesets/{rset_id}/publications/{group_id}, both named in the body. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [ruleset_id, group_id] + properties: + ruleset_id: + description: Ruleset id or name + group_id: + description: Group id or role + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + delete: + operationId: DeleteComplianceRulesetsPublications + description: | + Detach a publication group from a ruleset, as + DELETE /compliance/rulesets/{rset_id}/publications/{group_id}, both named in the body. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [ruleset_id, group_id] + properties: + ruleset_id: + description: Ruleset id or name + group_id: + description: Group id or role + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /compliance/rulesets/{rset_id}/responsibles: + get: + operationId: GetComplianceRulesetResponsibles + description: | + List the responsible groups of a ruleset; a non-manager sees only the ones they are + a member of. + parameters: + - in: path + name: rset_id + required: true + description: Ruleset id or name + schema: + type: string + - $ref: '#/components/parameters/inQueryProps' + - $ref: '#/components/parameters/inQueryLimit' + - $ref: '#/components/parameters/inQueryOffset' + - $ref: '#/components/parameters/inQueryMeta' + - $ref: '#/components/parameters/inQueryStats' + - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryFilter' + - $ref: '#/components/parameters/inQueryGroupby' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/GroupListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /compliance/rulesets/{rset_id}/responsibles/{group_id}: + post: + operationId: PostComplianceRulesetResponsible + description: | + Make a group a responsible group of the ruleset. Requires the CompManager privilege + and the responsibility of the ruleset; a non-manager may attach only one of their + groups. Everybody may not be made responsible, nor be given the publication of a + contextual ruleset. The change is logged. + parameters: + - in: path + name: rset_id + required: true + description: Ruleset id or name + schema: + type: string + - in: path + name: group_id + required: true + description: Group id or role + schema: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + delete: + operationId: DeleteComplianceRulesetResponsible + description: | + Remove a responsible group from the ruleset. Requires the CompManager privilege and + the responsibility of the ruleset. The change is logged. + parameters: + - in: path + name: rset_id + required: true + description: Ruleset id or name + schema: + type: string + - in: path + name: group_id + required: true + description: Group id or role + schema: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /compliance/rulesets_responsibles: + post: + operationId: PostComplianceRulesetsResponsibles + description: | + Attach a responsible group to a ruleset, as + POST /compliance/rulesets/{rset_id}/responsibles/{group_id}, both named in the body. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [ruleset_id, group_id] + properties: + ruleset_id: + description: Ruleset id or name + group_id: + description: Group id or role + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + delete: + operationId: DeleteComplianceRulesetsResponsibles + description: | + Detach a responsible group from a ruleset, as + DELETE /compliance/rulesets/{rset_id}/responsibles/{group_id}, both named in the body. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [ruleset_id, group_id] + properties: + ruleset_id: + description: Ruleset id or name + group_id: + description: Group id or role + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + components: responses: diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index 1e2b48d8..70dff46e 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -159,6 +159,24 @@ type ServerInterface interface { // (POST /compliance/rulesets/{rset_id}/filtersets/{fset_id}) PostComplianceRulesetFilterset(ctx echo.Context, rsetId string, fsetId string) error + // (GET /compliance/rulesets/{rset_id}/publications) + GetComplianceRulesetPublications(ctx echo.Context, rsetId string, params GetComplianceRulesetPublicationsParams) error + + // (DELETE /compliance/rulesets/{rset_id}/publications/{group_id}) + DeleteComplianceRulesetPublication(ctx echo.Context, rsetId string, groupId string) error + + // (POST /compliance/rulesets/{rset_id}/publications/{group_id}) + PostComplianceRulesetPublication(ctx echo.Context, rsetId string, groupId string) error + + // (GET /compliance/rulesets/{rset_id}/responsibles) + GetComplianceRulesetResponsibles(ctx echo.Context, rsetId string, params GetComplianceRulesetResponsiblesParams) error + + // (DELETE /compliance/rulesets/{rset_id}/responsibles/{group_id}) + DeleteComplianceRulesetResponsible(ctx echo.Context, rsetId string, groupId string) error + + // (POST /compliance/rulesets/{rset_id}/responsibles/{group_id}) + PostComplianceRulesetResponsible(ctx echo.Context, rsetId string, groupId string) error + // (DELETE /compliance/rulesets/{rset_id}/rulesets/{child_rset_id}) DeleteComplianceRulesetRuleset(ctx echo.Context, rsetId string, childRsetId string) error @@ -186,6 +204,18 @@ type ServerInterface interface { // (PUT /compliance/rulesets/{rset_id}/variables/{var_id}) PutComplianceRulesetVariable(ctx echo.Context, rsetId string, varId string) error + // (DELETE /compliance/rulesets_publications) + DeleteComplianceRulesetsPublications(ctx echo.Context) error + + // (POST /compliance/rulesets_publications) + PostComplianceRulesetsPublications(ctx echo.Context) error + + // (DELETE /compliance/rulesets_responsibles) + DeleteComplianceRulesetsResponsibles(ctx echo.Context) error + + // (POST /compliance/rulesets_responsibles) + PostComplianceRulesetsResponsibles(ctx echo.Context) error + // (POST /compliance/rulesets_variables) PostComplianceRulesetsVariables(ctx echo.Context) error @@ -2358,6 +2388,274 @@ func (w *ServerInterfaceWrapper) PostComplianceRulesetFilterset(ctx echo.Context return err } +// GetComplianceRulesetPublications converts echo context to params. +func (w *ServerInterfaceWrapper) GetComplianceRulesetPublications(ctx echo.Context) error { + var err error + // ------------- Path parameter "rset_id" ------------- + var rsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "rset_id", ctx.Param("rset_id"), &rsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter rset_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetComplianceRulesetPublicationsParams + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // ------------- Optional query parameter "limit" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) + } + + // ------------- Optional query parameter "offset" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) + } + + // ------------- Optional query parameter "meta" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) + } + + // ------------- Optional query parameter "stats" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) + } + + // ------------- Optional query parameter "orderby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) + } + + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + + // ------------- Optional query parameter "groupby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetComplianceRulesetPublications(ctx, rsetId, params) + return err +} + +// DeleteComplianceRulesetPublication converts echo context to params. +func (w *ServerInterfaceWrapper) DeleteComplianceRulesetPublication(ctx echo.Context) error { + var err error + // ------------- Path parameter "rset_id" ------------- + var rsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "rset_id", ctx.Param("rset_id"), &rsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter rset_id: %s", err)) + } + + // ------------- Path parameter "group_id" ------------- + var groupId string + + err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter group_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.DeleteComplianceRulesetPublication(ctx, rsetId, groupId) + return err +} + +// PostComplianceRulesetPublication converts echo context to params. +func (w *ServerInterfaceWrapper) PostComplianceRulesetPublication(ctx echo.Context) error { + var err error + // ------------- Path parameter "rset_id" ------------- + var rsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "rset_id", ctx.Param("rset_id"), &rsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter rset_id: %s", err)) + } + + // ------------- Path parameter "group_id" ------------- + var groupId string + + err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter group_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostComplianceRulesetPublication(ctx, rsetId, groupId) + return err +} + +// GetComplianceRulesetResponsibles converts echo context to params. +func (w *ServerInterfaceWrapper) GetComplianceRulesetResponsibles(ctx echo.Context) error { + var err error + // ------------- Path parameter "rset_id" ------------- + var rsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "rset_id", ctx.Param("rset_id"), &rsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter rset_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetComplianceRulesetResponsiblesParams + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // ------------- Optional query parameter "limit" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) + } + + // ------------- Optional query parameter "offset" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) + } + + // ------------- Optional query parameter "meta" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) + } + + // ------------- Optional query parameter "stats" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) + } + + // ------------- Optional query parameter "orderby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) + } + + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + + // ------------- Optional query parameter "groupby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetComplianceRulesetResponsibles(ctx, rsetId, params) + return err +} + +// DeleteComplianceRulesetResponsible converts echo context to params. +func (w *ServerInterfaceWrapper) DeleteComplianceRulesetResponsible(ctx echo.Context) error { + var err error + // ------------- Path parameter "rset_id" ------------- + var rsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "rset_id", ctx.Param("rset_id"), &rsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter rset_id: %s", err)) + } + + // ------------- Path parameter "group_id" ------------- + var groupId string + + err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter group_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.DeleteComplianceRulesetResponsible(ctx, rsetId, groupId) + return err +} + +// PostComplianceRulesetResponsible converts echo context to params. +func (w *ServerInterfaceWrapper) PostComplianceRulesetResponsible(ctx echo.Context) error { + var err error + // ------------- Path parameter "rset_id" ------------- + var rsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "rset_id", ctx.Param("rset_id"), &rsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter rset_id: %s", err)) + } + + // ------------- Path parameter "group_id" ------------- + var groupId string + + err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter group_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostComplianceRulesetResponsible(ctx, rsetId, groupId) + return err +} + // DeleteComplianceRulesetRuleset converts echo context to params. func (w *ServerInterfaceWrapper) DeleteComplianceRulesetRuleset(ctx echo.Context) error { var err error @@ -2653,6 +2951,58 @@ func (w *ServerInterfaceWrapper) PutComplianceRulesetVariable(ctx echo.Context) return err } +// DeleteComplianceRulesetsPublications converts echo context to params. +func (w *ServerInterfaceWrapper) DeleteComplianceRulesetsPublications(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.DeleteComplianceRulesetsPublications(ctx) + return err +} + +// PostComplianceRulesetsPublications converts echo context to params. +func (w *ServerInterfaceWrapper) PostComplianceRulesetsPublications(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostComplianceRulesetsPublications(ctx) + return err +} + +// DeleteComplianceRulesetsResponsibles converts echo context to params. +func (w *ServerInterfaceWrapper) DeleteComplianceRulesetsResponsibles(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.DeleteComplianceRulesetsResponsibles(ctx) + return err +} + +// PostComplianceRulesetsResponsibles converts echo context to params. +func (w *ServerInterfaceWrapper) PostComplianceRulesetsResponsibles(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostComplianceRulesetsResponsibles(ctx) + return err +} + // PostComplianceRulesetsVariables converts echo context to params. func (w *ServerInterfaceWrapper) PostComplianceRulesetsVariables(ctx echo.Context) error { var err error @@ -11150,6 +11500,12 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.GET(options.BaseURL+"/compliance/rulesets/:rset_id/am_i_responsible", wrapper.GetComplianceRulesetAmIResponsible, options.OperationMiddlewares["GetComplianceRulesetAmIResponsible"]...) router.DELETE(options.BaseURL+"/compliance/rulesets/:rset_id/filtersets/:fset_id", wrapper.DeleteComplianceRulesetFilterset, options.OperationMiddlewares["DeleteComplianceRulesetFilterset"]...) router.POST(options.BaseURL+"/compliance/rulesets/:rset_id/filtersets/:fset_id", wrapper.PostComplianceRulesetFilterset, options.OperationMiddlewares["PostComplianceRulesetFilterset"]...) + router.GET(options.BaseURL+"/compliance/rulesets/:rset_id/publications", wrapper.GetComplianceRulesetPublications, options.OperationMiddlewares["GetComplianceRulesetPublications"]...) + router.DELETE(options.BaseURL+"/compliance/rulesets/:rset_id/publications/:group_id", wrapper.DeleteComplianceRulesetPublication, options.OperationMiddlewares["DeleteComplianceRulesetPublication"]...) + router.POST(options.BaseURL+"/compliance/rulesets/:rset_id/publications/:group_id", wrapper.PostComplianceRulesetPublication, options.OperationMiddlewares["PostComplianceRulesetPublication"]...) + router.GET(options.BaseURL+"/compliance/rulesets/:rset_id/responsibles", wrapper.GetComplianceRulesetResponsibles, options.OperationMiddlewares["GetComplianceRulesetResponsibles"]...) + router.DELETE(options.BaseURL+"/compliance/rulesets/:rset_id/responsibles/:group_id", wrapper.DeleteComplianceRulesetResponsible, options.OperationMiddlewares["DeleteComplianceRulesetResponsible"]...) + router.POST(options.BaseURL+"/compliance/rulesets/:rset_id/responsibles/:group_id", wrapper.PostComplianceRulesetResponsible, options.OperationMiddlewares["PostComplianceRulesetResponsible"]...) router.DELETE(options.BaseURL+"/compliance/rulesets/:rset_id/rulesets/:child_rset_id", wrapper.DeleteComplianceRulesetRuleset, options.OperationMiddlewares["DeleteComplianceRulesetRuleset"]...) router.POST(options.BaseURL+"/compliance/rulesets/:rset_id/rulesets/:child_rset_id", wrapper.PostComplianceRulesetRuleset, options.OperationMiddlewares["PostComplianceRulesetRuleset"]...) router.GET(options.BaseURL+"/compliance/rulesets/:rset_id/usage", wrapper.GetComplianceRulesetUsage, options.OperationMiddlewares["GetComplianceRulesetUsage"]...) @@ -11159,6 +11515,10 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.GET(options.BaseURL+"/compliance/rulesets/:rset_id/variables/:var_id", wrapper.GetComplianceRulesetVariable, options.OperationMiddlewares["GetComplianceRulesetVariable"]...) router.POST(options.BaseURL+"/compliance/rulesets/:rset_id/variables/:var_id", wrapper.PostComplianceRulesetVariable, options.OperationMiddlewares["PostComplianceRulesetVariable"]...) router.PUT(options.BaseURL+"/compliance/rulesets/:rset_id/variables/:var_id", wrapper.PutComplianceRulesetVariable, options.OperationMiddlewares["PutComplianceRulesetVariable"]...) + router.DELETE(options.BaseURL+"/compliance/rulesets_publications", wrapper.DeleteComplianceRulesetsPublications, options.OperationMiddlewares["DeleteComplianceRulesetsPublications"]...) + router.POST(options.BaseURL+"/compliance/rulesets_publications", wrapper.PostComplianceRulesetsPublications, options.OperationMiddlewares["PostComplianceRulesetsPublications"]...) + router.DELETE(options.BaseURL+"/compliance/rulesets_responsibles", wrapper.DeleteComplianceRulesetsResponsibles, options.OperationMiddlewares["DeleteComplianceRulesetsResponsibles"]...) + router.POST(options.BaseURL+"/compliance/rulesets_responsibles", wrapper.PostComplianceRulesetsResponsibles, options.OperationMiddlewares["PostComplianceRulesetsResponsibles"]...) router.POST(options.BaseURL+"/compliance/rulesets_variables", wrapper.PostComplianceRulesetsVariables, options.OperationMiddlewares["PostComplianceRulesetsVariables"]...) router.DELETE(options.BaseURL+"/compliance/status", wrapper.DeleteComplianceStatus, options.OperationMiddlewares["DeleteComplianceStatus"]...) router.GET(options.BaseURL+"/compliance/status", wrapper.GetComplianceStatus, options.OperationMiddlewares["GetComplianceStatus"]...) @@ -11359,375 +11719,381 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "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", - "z09//v8BAAD//w==", + "7L19k9u2sjf4VbDa3bJdl9Y4OTlPPRnXrVo/iZPjexPbd+ycU7cOXRqIbEk4QwIMAEpWXNnaT7MfbD/J", + "FhrgiySCosbzIs3gn8QjgCAA9suvG43uL6NE5IXgwLUanX8ZFVTSHDRI/Ivx91QvflWg36Tm7xRUIlmh", + "meCj89GbH4mYEb0Akou0zECBHkUjZpoKqhejaMRpDqPzUa5AT1g6ikYSfi+ZhHR0rmUJ0UglC8ipGVqv", + "C9NVacn4fPTnn5F7+VuRQv/LuUih+72m5brvvdi7aNm3ZHnNJf9XCXL9E8s0yN13/yCyMudkhs0RkVAA", + "1XSawUuiYAmSZq5NkUTkU8aBrJhekFdvfxyT1zRZkCXNSiBMxfyykKI4h8+FvIwI/nFJpsD4nFBi/gKp", + "19VKM6Y0efovwTikRHBQhPEkK1NII0JVzGdCEiFTkNP1M0J5Si5xXNOViNl5zAl5TjR81uckoQqeM66A", + "K6bZEkhOdbIglK9XC5BAGMc34jxf2gcv/28Jc/h8eU4kzMuMSmJGB6WY4OTpxetviVpzTT8/i3ZGr0Zg", + "/JxG0yi5PHdzqpcFqX2XqrrC7+dLsyMczpeX5wR+L2kWES60/WfVba5tt7kG+49MV/+3Dxq2opIpwVVE", + "zAbxMp+aL2P2J6W69ca80Gvz6P9m/3VOuLCTisy+2H+OY/6Kk5JfcbHi9QeK2h/LfGpRakJJgnQSESEJ", + "5YTxJc1YWu1ezFvbx8x81AokpJZUvnvxYhzzUTSCz0VmGMtRLZL474Y4Gxq3tDZqkzTTkKsO2o6qH6iU", + "dN2m9Z+lKIvpuovY85w+V2AkkvlMSIRiVq2XgSJakLl53LIjqDLTZLomT2E8H9uW6frfaVFEapmYOT8b", + "j7pX4vqOBnHnLyxnene+H40cpJ9ZXubuW5vZAtfSTVWCLiUfkxckB8qV+cqZGco3KWzcmFIKM1pmenT+", + "1xfRKGfcvGt0/qLeXMY1zEG2J/sraNohxCz7khw0TammFdtJUIXgCsbkNTdyJTXb6d46Jr8pIDOaKTCE", + "9cIsSeRMxxw1AGhKZgyydEw+Llojixmh9tslVOJWMG22Q9OstU1SrFTMKwou6JxxqpG/seczI2fICrLM", + "/B9nKlbK7Sik5GkiSq6fRdgkZjMFOuaG0Sybm01Gou7aZjPTYR/+HQ68u5sfrpglwRmTStef3EkZ3IWk", + "lEpI35e2M+7+1IO/9DsrgK/LSEpIwzxj8l7CjH3eFizkOQoxMzLw1KgJFPiO15zw/3ejcM2aoue0KLzc", + "5noP2/T3UhRqd1GvPMtwiskQNBiFh7ufssQ8xqlc++ZU4GsGzeiDplp1bTPXUmSWPHEaVsJWnOVItTUX", + "yxvxSJkB4xG5gnVEEsE1ZdzssHlOQQaJ+WqtZaZMacYT7TQXQeJXvpXh6L0r+9OAFMv4uK7vXrww/zMz", + "AY70TosiYwly5Nm/lFnul9Z4/4eE2eh89L+fNVDyzLaqs/dSTDPI7Vs2N+x/0ZRcwO8lKG0UxHcvvrmL", + "t/7GaakXQrI/ILWv/ctdvPYnIacsTYHbd353F+98KzT5SZTcrfP7u3jnD4LPMpbgF/3r3dDRG65BcpqR", + "DyCXIMlrKYWVjO5hM/Yr5LrX/PcSSthl3nccCMUuRoiA7WYF3/vfPpIz24Y81jAiriixI+zIpzlw3RpS", + "lkb/7KCiykLZRRNUzkGjbUOeul5G7VYS9lnXaLJrpAtQopQJEJaihER1aHGh0pQnrYUb6ZPnlNS6ousl", + "apn0zViBXLIEyFPbz8y5Ql9doy1zK6b61j9dE1QqRpYWGU0QwLs9sdiacgI8oYUqM1RxziTcFeGNMfbP", + "6tN9qvuJ6b/AUu6rDKT+hSl94eQimsYbH94oFvN/weHdbHT+zxb27aNjHPlCrHYhcfRlRNOUmTnR7P0m", + "kXl+3wYDHSvZ+uHTn5EFPHumadaO0HF703DZ3i0zC+tQ1SlVi6mgMiXU9DLgbUxeL0GuG5DBFBGFXeQ5", + "aj60SdUlQXUW89ox4VSiIqsFSxbO1lFOWaIAsLpWjcklvu7SjG3WWGpIYz6TIieXZkqTWa4vrb2KfxrV", + "fGnh66WhIDV2rY6mzd8NEcQ8ETkQHI6SX17/9JH8x7s3b/EJKoHwMsvIagFW/9uFa6RqO1mhFyDJFeNp", + "zMWM2J20MHVLxJhHd7f1b2VOOZFAU4PUSQ5K0TlERAJP0Z7DmVXrdGanW+W4ixWxNZGAjN9lwtWP97dO", + "8vSv/h7Al/7GWd4zdiWv/D16X4weEqbX3YyDXezPvgHKIvVuDUu7h23J907Zr8aVQDddDMmYj1kZ3buy", + "tyJEJ1KHPVQL7F15uMvGRXE7cq8oHqTUs8valXmctLAOSUQKdyHxuqRHUXRSHy2KSSpyyri3WQPNJ876", + "2mWJ9noP4Ag/F3V9yB9EXmTMcP0vYn4rhLnxhodIojsL7FDQsuTWGE3qzs6nTwQnFPEUuhPxrwri1QDS", + "gMcF1TE3/c7RweMw5dNkAclVRGbss5FR+I9nEfaAz0wjY5Cnl7LkE2OnlurynLwg4iqK+TfodBVXEfkW", + "/+X4aZqB9TGbMTIx38tWztVd8RW5Gba6jsDHMwGfjjJb0BgTnc2GcbyNmZh72+yn9Dbbne9ez0HKoyG1", + "DzjkLTOsfcnD5tlmjZ0O54wqfT3ufaJq/o254ITpAxWUj5EMLu6B5C1WNy9oTg+ftETCACEQmHIgU/7I", + "1NWtMKIZ+CEyX7WuLkOWqSuiAHibsdBLVNG60YvWApR0TZgmU8gEn6PnxRiDsT3B+2pei/lNgkGzrgnN", + "MpF4rCNsN0vycBF2SGHZ2zz3t+EBnL+5b9gMlpD1TDsX6Ub71uOVGdXdKmnfqyXMfaIB2xX7A3pmVipI", + "e5qXwFMhvaZjn1npXZRXcmCT97HDQLsNX7gVmWOHfohSp1lZh9yxJ+02eCER3K7GyiArACr9nxnhICTR", + "Fm1bGeFiQkBbn9WUcbgbXT+bZHQKmfOizSbJlSrzS/SOVf44Ml1bkG42ZkqVc6jhwSnMGMeVdomy2cSe", + "43TSq3uVpw2PqT1tOGFPmyg8Ddr6Xzrb+rxGswme4A3y4nRjGz/7KdCvPxeiy3P4qqEI/DKApND8xnTb", + "m64iIiEppWJLyNaRPVZFnccMQeFhLqTVqfeYvOL47zVZiCxVBBj6Oakb38BQDNqiObrxKY/5huu+nkbn", + "R68peSPYZL/EqHfjjYa8MxylzaSt13zav8GvzWp3JdzMoD8/zeC+dQuhWR3+RbPMSccDluiix/78FG1R", + "VT10ZxTDW/dFzNfp/iJR4862X5gpC8pdl/Eo2kfH2xtd7VGzIwM2vAmP297xPs6+FvfW/DmcH9vrwwDA", + "6g2N6HHTaV4wYNFIuLtLtp2uyw2WdHdV6WhmrCIvHMBWVYVBXF907W5V/dqaVPv35tahRv2Oh4s5Npbo", + "VRaEak2TBaTGkqGNUDh3kU/Yp9n4iBRZaWO9CqFwJ2L+9NJx+aV14WF0lpizhGbEPEgNdPmXsNEvTJs3", + "mS6FhCUTpbJSp0svoLyazFzMrZ8m20L27vFDvz64jqK4E+TR2tbdKfh+N19xcg3Mcrus/KCZ+MKMuqMg", + "egX5UMnc/94+sYESgnJSwURrf9hTMTGrw9WNNLAH4g32cmcKlcGBx6XYsT4FvZ8TNdzSPuFxgO7c8uja", + "YBaCzW3c9ZPdnBVT0Hl0j4Mefj7dy4m/KTqH/azYB9C3QuCaL9vgSxvnaD4cx6UdyM8w60Iv7mZGZ5Bm", + "7SGvOhEJZp+S2hhlra230SCuqzVamCKMk8v6K1/e2LT1QoJCq6lj4gtIrkjTAwOi41GyuMKohbH5R+XP", + "P8/E6vmCzRfxaGNu+2PyPUZQa0c3ZrkrFgYLLSHz2xH1Qub3K+UZn4nuw5pkQfkcSE7xOIYTSnKRspkL", + "Euji61vSGG6PuoS2kLk9wG28Lxhil0/WNM8ikkq2hCrGuSi1MuKqnObM3ieBz4X1TlfwTpQaezE8plJj", + "O1YzuGGnenhSUKkgdXI95l/pnarkur2hMECwm3n0CXbT3hcgtbW23Q3eXmlE6FQB19awZpqkAqxNje2j", + "LgveDDET2SYo3JqDX/uY1irMaXNuYvqviCSl0sJ8cDM+EZLMgYNkSafSqRbzlRoHbwDdijDAkR8i5qsX", + "1sHCpQJpLz+NDZuwJctgDnjYGo8+xiOHMeqW53NJOephe5eK8jTm8einqidiN2bvK/D7imK6brRRvcru", + "c1bRaTx1fdq/TemtkOjfpvQhEqhbVgd5LoTSZFoqQlNaaHv7qzpJpQaMFUI25wKEzoHrc3K5mNIJS5GK", + "0e2MIhb9BSwFrtmMgSRPKSfsww8f3pA3//UWbz+Sn9hUAvlhQTmHjPzjH+/fPovsaGbOl3YwLSlX5r33", + "dCxrF9dJotVMv8LR1n9ceNjR3hs+E20e2LpFUWqMiXaxyPbTriTTgLZctQWECyIhETLdvU9RoadBc7Fw", + "91b4shr8ITJne20dHLod3mcJ39ik+EUFbyId8BASOrnXgi5k37vgqutE7bsL7ehDUy+bp/GG+24IP95F", + "kWJlpo94l8+7mDkXfEKLYid+p4XqTY8lZdmePtZeSP3t9qogyD3jpExd7eniHKhS/AF8QrW3n+2xp7l3", + "ALVnJvMSlBb+9sV0zwBs39YLzJSwb/PVgkrY1wcnnIkpzSbW8unvum+4ZeK9gYDta57sGaLPB2Tal0nh", + "CyrD5hzyvlavXWGbvbO/4WsQ9hGhJkd0ceLN7Zgwbx6k/fLGe2vizXtC01SCUiQFba8+t2LtKpFtD4Y4", + "6JWQV5thduOY335sS1dsXZp6LPKMzicpFBKSLd4ccI7CuJ51cxxNPL+rq24+Az2Zwtxz3wNbpaBpQpX2", + "9khEnrurvJ3twFNv25xqWNG1t90LXvu86dgIunfRjkq87YVkwv/qwhfTaBrxhoy7O898J3HXDtbzitPD", + "MHvNnjsyCUGIEYGTosqyMNRZHI0w64A3fBETFHylOKqSDF1ndlmVpGX3PaJO49ExB6Fp1hEbs5GoZCMt", + "0m7Okqh1Iq5sxDqkL8lMyJhT62RxWThszyYLCrapMfkH0wt7CLTdA1+P8XKm2Wxzojbj6QyyteJpiO/t", + "2jrLpzsehn66rctmD/SKmf9iWRORmok5geXh1uD1bn7bFETWC8EUuczEHG972xxDNobx8v98egXrZ+qS", + "CFn9kV7aDAML6wCXgH/V3ihMVsb43OVRE7OY49B4czwilPzHh3dv3VVuMydGM/YHpMY0psQKq7G1M9GZ", + "Zc1URJkYFRtzzADmeqpWuJ3ZODx+ROcJWqJCVmb4S7trLeM35t3WL2mM3/rCuqpvrGvzOoOKD7lbY5bf", + "c0UGd8d3RabaukFo3HSGnLJsohwE2R/kg89wLdeDw4IcoXinO9c0uzpwBts3FDZHLBXIx2o0/VrljbwV", + "aVuP/hBl7sbiOiXv1l1AjGbwi17039XZpqbrSgqPB0uCXKR7ImNcjx4vQtofyNK1428tvB9GQYPoxo3Y", + "TTU9HupB3601eNcFM0gyKiGtTNsxuUSb7TIil8ArlVEbape72C/ml+5Z19mZR5ddQt1vD/bbgn12oM8G", + "7LP/vLZfj923ZfNtmm1eg89v7G0Zem0mH2LlHUi0IoW/UZmuqLyd84v2Cx6i+NteX9dJo2sm9QuHnDU+", + "UYQqBZoUpVqcx/xysaqOCi3UbEab0Zxla/J0JiSBzzQvMoNdE2YBZQ75JZ41riYF1Qt31OicW3dy/2rj", + "SKQTBJqnnEsN+8XcXRzDkw8bKLC5e00OWvNA52HmapJkVHWb6YvVZN9Rvuki2dIDitxu+tq8LpPrJ+hx", + "d2YH4qtbhmSHS5lbky4PVap4pEl9+tfKOq7QizOYl2N+3QwkEVGCUPP6mFdpdAXP1i61KObQhJSocuq5", + "OGctND97eLMEGVHozdmFrV4dPWVCTZYglY/TpxlNYZLQKePgwRlZqTRIH4O6ZjWu+nXnEmzfbDOf7Yki", + "7oFoRwxWQ9pT4QE32gwYcj4OD1TiHBI90aK7uSgniZA+VjDNKetrnUn43Tuy/+67adULCTTtGbvnBjrw", + "JBOqlNDfqjLR/WVnv6ce8b/0/FwIkXmalmniUwhiqiaYQM/vhXC9VlT2ZPPIqNKTqfCsBlsNKO5uZUoD", + "BzmpruN2uQmSifcAyTROS5al5m9fh2Qztd1WoyirS6qd7bNMCP+7JU2u/I1C5N7GP1jhOaQya+fGOvWe", + "GeWUlzOa6FJ6oEAO+WRK+ZXvPNs0rzX0NBvq9J6G+zgHEYNPImJjT5BEq90XJXHt4yIudB1M3o2+hJpQ", + "mSx8bYngiWdSQk2uQHLPlrQQTFfbAB50vfp5UKiJhAyo8jYrmHvtUqGcY8HX2iPtCrECOZlKoFcgv9nf", + "5dueLk7ffbO/S98ohRTaF2+y0aOaUk9PVRZFtp7waTcreKJko5GCZPKH4L5GyWg3uSguxB8w0SzztBe9", + "sKEnBAYtdZy6v3mfIY+dzJZsCusBx7L6jwM9A9Gob50rg6m5XnskZBdQfjdVIsMU/Ql8AK0Zv51zrI73", + "PERzwLPMrrgV0epKlO1rwb+RaVhWh1fpj7H6S3UwXMeyWPtbltz2btwXqIrI00sjIK0nIh4tVvHomavv", + "8u4DcWJxq5NQ8ejZTYXD9F6mIb9xBfXCZKvcAVVk40xrTHCKCEgusRDR5gG3NavsK3AT3T4posXLrT0x", + "MxPK5RJxwZAq5vFoyaSOR2Z74spGiEc2olNoWy4B0kMOuYZosI0uvYF43V0n07W3d0+shWn2K19HDfaO", + "fJkbal+sRkbdtQh+s/8eHdzusXeVOz27F9nF5O9pckXn8CObzd5iHaJt0XVNnLTF+02JsPqZT/2z8fgH", + "CtuDOIluo6ezrApfs+WgnJ8tQmHgYohdBnFNDAtrW59KL2w2leErLq7mfmxnGr00Yhq9Ks00+nWUdy/r", + "F26O0Jpm6709+30rysuN/RAVVmtpPSS6RZq1P7z2gTvPuOpOChrzr1AfLedWzJtMYYrNDWBdshTkpQt0", + "sKk/7G+V+0axOarHK1jbJMBOvcS8jpUwXaixGk1jWaVbPMQXbvMYVy6gG8ozeoTO5L0ywxFKrQ0Gjdgr", + "aBSbDx5o8LUn07lPE/ULsWjUJr4BL+zRVgoVxM2cQm+pnI6T6LwzqNMRoeq+g87SOnxxQyWpWgIsmNJC", + "Yk6eV+/f1He29ALyQ7IJOIL03ITfeHWdQZVJy/pRnS7ElX4ZnGJhGzXsS3JQb1Y13WEpDdzed4pgV6ho", + "57to+NyZi29R5pQ/r+t4wOcioy5BiiogYTOWWBvB4PYkKaVEG8N+RLwjb963EfLp0c84g645X9xiEM7F", + "ww3BuRgagCPvIvzGvcQvf6sORTnNWNLbxYMH//RvAmaL2d2GfyyoJqUyVmG9Cx035tJWwpaaqg6KOvKj", + "/X2Ryo2c8rz5+obG3lf7E9W00s4ozKTZTpRj40mTBcvSDcl4I4QyZN5VZGDPrl0r0/D+d/eQ4N+pZEaE", + "3qYYq97xgMVZe4kdYm3pmncqDgwQcjd0Gn4IJK+I3de+pLIvYtE0+6NZTKtX3JrGXtcvlYOT8HXRxQfL", + "g7dC7W7sh0jlraX13H1vBXpUsu5kYj32BE34OMEIbF8YCLaVWihNPYci2GPPnXbTpy9y1LbzGZvvae7l", + "K+zWk6TJtKeSi55LC7ZLwZ3fsa9d9XXwutVMu+8I2bTNMvg8SYpysmDzxaTOuOb/cPUDmVgN7p/Tz5Pt", + "NXT2Y3xQP1vdsKeT/1zcNC+o/9GFUNqPJnqAxiQHLYVjCW+n/i+5/2Dd9MKbQr20jT4GxQTvocy9Z6Om", + "Tz+L2ea9PKJFITIxX3s7rOgSvF/khkpF/KZuKXuzGfghqi+zrvcSZsqfhecjZmsREouGwwzQX2D9O4ou", + "rXX5/t2Hj+SsVCDV2RfzvwlL/zwz3W3cMAYWu5t7HIx2MquXhayql7qizi+x9C4e8LlbbzlQrkg84iLm", + "rde7GcWjiMQjTFHmXLPVOR3+xoUmhkWmGcQjQjN21el/rWii+4NtIKhDE1NWdONLrOZAAe6cQwSXBVVq", + "JWR1O0PCnCktUVxMrmBtL2ngLlYub0itR3oqRAaUPzcLrSHB00t7zW1D7FxGMb9k+faP5DITydXEXja+", + "fEYMYFi7D+S+3xOX9+0Mc7qZD8uXwO1F5SpLYwoZtQ7130uhaT2V7aPc6hD3nlIs4L50BxzijvVftuvY", + "1aH9JrhB3YGMTKqDMyxHI5bvme32tx7UqWeeLO8Jjs/xFqJ3ERje6G9tKLDb/b4QHCbeGzlIcV7kaVtT", + "kVyBnDjOYh5dbfsKOe8pJ7XBnL6ScNZN5rjasHC3pvNvWZeK+IeQV7NMrG5F3VWDP0SV115bV+1SaxK5", + "YBvXl6Cl0lztaaWoRb/FTMjcHjvQ+pmY22S1Y3KJqU0XQNMq56BudGprKExqV72JaSOikVXw8fqCd/MT", + "pou2hUupBmWeheIluWzVQ7wsgKeMzy8x51kGhBIOn21PQlfUPGxHpEqxOQcwSiDJhIL0spUlfMtOjfnX", + "Rf14jm2bVUXuD5s5tqr4VGWIvey+c2TazXAWFXdUTmd6T7I1a+j5w1WwvS+db5NJd38dhBZReOoxmB6u", + "luSw4Qaf1W4k2712IsgNwvGLeke/A2+4b5D3sKv85pGeYNw+A0dDoYZmFm4d+m6STavBXdwbnY9ejF+M", + "v9l7iFY92nlQqCApJdPrD0bYuSu2VLHkVWmvrKEQNM/gr827FloXeCMGqARZ9bZ//SRkTvXofPQf//g4", + "ilpDYOv2GH+2bygzjQsTBXC1TFrJOGjBRq3tGX0zfjH+CwZtFcBN4/noL+MX4xeG36he4ELOrMME/z3v", + "KiBlJPtGDUy8MuWeIoVAtxWzQRruPtLvJZQwJr9STucGUCuAmNMsq5566YpCWLiNXjAFzZh1vKCNA6RF", + "YQZf21QarThfI2is9LBVZpjgb9LR+ehn0K/cosxCnQRU3oJbTZczxv/LyM33mJnIaNhh/X/BtETD+7+z", + "uYqGP2BV6+DuH7AQxQHzkSnI6fqAJ6pqZIMfwNzW5hWfEIkhTkKi+/bFCxT51vJ05UyrEvtn/1KWny3O", + "GIJCahCGTLOVyfY/DTf81b6xa6B6ZmemU5v3kXpaXP/PT2btbc7+5yezNk3nhtJa18c+YUS+6mCtX0XK", + "ZsZA22AcVw8JLcknLH2CUVFGX1KeGq23dtVSrD7HaAHronOjvGz8yk+syH2yYdGhhMYYKHJhJaAb5a1I", + "4fVnSIzl/oPIC/x3nWob31pzH8uYXuNVYvMe9/7m7vAmQ74XqsWRDtn9L5GuD/rwXSdDW6jRVqdv7SLB", + "uMUeTbR1pRAQYupSkadY5sBsZL1f9S4+26tOOovrbHZyif+/ihc6XtBF8N8NIXjTCft+M6TvN7bvX4b0", + "/Yvt+92Qvt/dF4OWHfz5mltSstGTTj11RVS1vTLvf/tIKqWKhR+c520qUutQ4Y42I5vKHNPNiVlVafOl", + "SzMHWapIYWxWrh2zt3n9POYxf05cEIOVCOgxP2/ECalsmSrl89bZV4T9+JwIHnNiu9ocVIbsnz5/nomE", + "Zs+qGvP2oEqJUiagyJwtgRs7TLLU9JUsfTY2w7RlCqlFyiAx4uY1NiuzqyE0Exx21gQGGmSthTgYYlMb", + "2DW4QCpSYxcs8E0ztoQKrmCZ/W/+SnLGS20+1Aea28M4JtHnr8Ybm+zm0kZA4yHrNbPwLNmJzJi/ShIo", + "zBoc6ZxjpgrzmMF9kf3LnpNFZCYB/gDn56MrG/Dr1hlze3+k+ugv8VG8021HwbzR9p/F1dz9g+pkYf9p", + "ExTGPFlAYvqptbJxwxFRCeUqUcwzAVwLadVickuJ+VMbCxQ1OYuiKrDAlgy0HGYtWVVf6XDXtfBSR8zf", + "VYxDKFcrgxzrEu3IptXWIYP+/LrhwrMvLP0TWdGQsssVR0kVYkdeWR6k2YquVT34ty9eRJ43KMK4LW1s", + "K5zxJitdga7OWalc7dy1oTWQUsiXFYeTlM1mIC3jZeuYOybCCzAg5wintbARQS2iN1i45r9ONVvegJZt", + "PFR9QMu+x8lHRIGD/Fnbj215tD7dh4r8uP11kTdrKf3SCRWb2JPy6kCkooyY75AGqSnDisxZqWimakIw", + "n+4ElfJ3L74f0vf7e1Hgf0ajDW63ujwD3XGQ9iP+3lIpXTYscTbsjnR3Rm3MDwbGCOjd6EyRTMznkNqS", + "WrQqItZ2+9tbEEzXl9o2ud0uw3LUrp07DBgz04iJd6qkXLZg7yYLRrvsVMPer7XmrlkmxI90b4dR7gGR", + "djpjfmSqyOi6ukRTXXdB53cdVr6frGPe9s2Qa7hmrueQuT86jYLr56ZcP0fkyTlqoxJ1Et4Hxjy/Xgdr", + "xdP2Fjn2VUQzY4kYnaDI05SqxVRQmU6qVjrN4JlBrrZwTcxdeEV1vqKaWj4S/0SThakqDKO6np7QLAP5", + "kuROHMTccDssQa71oj6c2eVmM9XXuKrgYX34bHZ/rKMGAjlknafTMrvC08dnFmxhEIdrrHN8G2XXuoOa", + "xhx+LymitkQyDZJR8pSlETFch8EVUeUBiJxXwrVVFnZE/r//5/99hmxop5oazkSOy+naKlHbgKwoVm7C", + "W8qWA6TWokD2Uk5FN66EHhRo9+qmfKsbq+s8r8MeysiJzfxU7WoR1fbtD6AZliXpgBTUN29GBpx6EE7F", + "Q0P4jAVD5o7aW3qsVmCGS5dM6pJm5Al2e7J5Jx0drZtXKStXiwRub5Ni/AGS2yzXaI3hHylLdJ/+CqeD", + "p6278COe2InfDxjYYkCZjZOolZf32OxmJfuUKhgit6vyDTuxF9jqu+NQ8aC/8XaVynW1x2a8WvWGcIB3", + "v6qlAYGHuPSQmXzwyykiFyqFSbqYdigs5pswjPhQWKcfz55ixPzafjzzsr3uEUSyLG1p0jFLnwVH3oM5", + "hu53EFSGTsvzt4upvHjnPqkruN8eLLY69sCOThz22yb6eqJaPLV16NOnBmJe4SEj5CVslGxxzoKz2nlQ", + "IyubKEdXh0UrphduJGPAMEWWNGN43665y1PhItOcZDQvurVJjRnvXZccD1w9QUQagOeJqGwEqUUx1E/Z", + "fBOSGIC64bJ8zdAbqKu4T3eG/IQWxZOY70SBuoM9jCvbigitzp1pUbysbgKCeSteGMGCgAvK08xe//vx", + "9S+vP74muI6zL7QoJiz9sweqmuXeFIe7C2JbsqkocHtG3jsQu/2N8JVpZ7znSfoHQ3DInfgo61rJhFqy", + "3sXO9vfgKTxhNFsUp+kn7FAZ3YjvFkRyVzGhSSpy6iktaJoxyb4ouu949VcI23LDmUnchQNuD9ngxdvj", + "FtLHHpXXBhXXQ0l+HLLXyGkDAwy3b5BFh5ljZ3mnbrM++nvDZ2KI/R3U/1d51YqiZfx7EMD9E9qhHrRP", + "9yoYT9Al9IP13HdZaT3k4bTvkQiik1b/Qdc/BEdIrevPaD5h22WZOiXxBSaeIOYTEzbbSIgorV91I8LY", + "5svdCxKs4H6Vv7loTeHk8YIbz2WYCudne2iwzgDo9wBs5qofSldvceCTQwXBExHC2m+cyWzmeTogjUgn", + "uGqeJpjgy4fB37dfEzgvcF7gvDbnnX1B7tnvZtE0wevP23znKpYd4n9pseRRcOTmK5GuNl+KRU87X1ht", + "3mkGTbU+BEnxC0MazJav8Aa80l420eIQv3xgkSNkEapPl0VOy+N/htlb92WX00LSOZCUqSvHZPYxUuJN", + "j+o2/UDb7L/sKwNEDBAxQMSW8+waxlnb9dZrnF20XxM4L3Be4Lw25x1qnO3w3TWMs6Pyez9m5HmxmRso", + "2Gc3aZ/tcsph9lngkuPkkmCi3Zmiapf93JsC/PCjsg/V8AEWBlj4WGHhZPuQ7Gb88/23NLZOzG4sPmiy", + "9xLGFvvuBAPVqup8gMazq3d6b2/YsBUK9Qs+hcsfwWnfAQq9lycD3wS+CTCxUVzbDsQb9F30a68tl2Lg", + "wsCFwaUxQHsFvgl8E7TX6AyLCgw8eXZ9uxwYVUu4ABzS3N4GlZZ6gWHqKFI6FcMFFreFurSNeQS4dlvh", + "0wSlXry1cvh27wWZKfnr5bbFdN2zSzrfiTSORmU5JAkg9nIVFz8NkOBV8Z6jvL2L9DicQA11OdpM6lI+", + "Z5mY7xGltjp5XfvHVfp5QrCOUERm7LNNs8BT828iS1tOoCqC5GrQYTX2hHKiAM5d0ZumDCRT1rRXC5u8", + "T3Bol25/olyQQmRTmMcc+cUWcHEpzm36vlwobeAGcO2yRE/XJIUZLTNfztimrtEvZi+CQnhUlSU3vv5Q", + "v/TtALp7UVNbouDsSybmVTTDwZVKrGwwImAIr+07N3qTVjJAlpw8NTOdZGLuz2Zmp36yt6+PiBSP/uil", + "Rbau3tyQTF2WlrA7MTRT15tnKRZjdeQ2Fek6IlTFvMqg1fG6sy9Sge7PqNV80YtqkrdZJtW9xNnZyBQh", + "R9bjSSdbo7WKRA/CVDVjIKqKeQWr9gnyFmUH4PSIgJP77o8MMu3L67WlXtxfE/NXhNy3LoDAZ7PpzJa0", + "sEeapOQZKFd9N4r5BueabiVPXQrJrYqEmyztTB3nZH2KpleV4tb+tmJ6IUptxMGzMfnHAnhr1jgYtbO3", + "ZT5UZGvbYAZLnF3MW7CPSnAVD1IsTAs0xTKt7999+LhfbW7k4zUixZOU3SVf30zK3lbmyYIyrmJupiNh", + "WrLMW3jhFnVy+2t3OimqDvabdzjdicv/gKWZ49HHeETOSDz6KR6ZTVVaSEjH7ZGqBLXAy9zQakVao8gu", + "4rMuadZydRxLWpajkB4PKh9bL68Nyc9WMZMrjmy4vqASC6TzlCQLlqVEQkZdsXTrscT0tK48tY3sxPLa", + "0UakxkYd1frCSUSWVDI6zUBFZIY6DkEL1tWu60mTjPGr7dTdnaKiVZh3S0DaakNueVaiVHlzG5lyAIrf", + "Z7h24PBOe9V9nVDO4YGVc6jV0iD8PRRh3yfVHZOb5EDV8UCcHnsKHhiqQnS245Orxd4wCepkZSfG3JCg", + "25hsMN66d+kZoF6Aeo8kQWpRdoiMDwUkjGZN7W/eFhOXSSY4XJJEFEaGGCtVkXgUly9e/CUx5I7/ggl2", + "i0cttIglVZ3pmjC93gB4iB8lIBiM3MldQ7YN9jQD1WDwpgzhRvhZ8dZtanYJsPKByi/77dviBL9nt/jY", + "CMmyD4Y4rBCH1WtxDs8S+hGyjKwWgB4mH0juThfaQJKBGPqwrKGnY8elVHdnEb0VQ+4Iqa3xH5x9mQ1w", + "elxALpYWNtePbuDliKwWLFnAEqTRgUyhWxOrFjMDzlhCM1drRw7yZPrdEzvYuq42eR3nxE/Vcu7ZXtx8", + "WT2rva+bBafIg4p+/5ktoRPrbTGfrXLF+LwVOdZyLxokGnP8jIbLREQkFBlNzAPoqpSwZKI0aBaOx9YN", + "zBiY8TgV5vDcvhjotZPLd0NZvsQIZv7cxQwQBaBsfWbzsOCWEdeESog5JTnkU4P1ZkNh2yEZgo/JDRqC", + "Gk4sqAFfEkLvbkiuDEyO5bC4NzPChjq+B83uAdoHJIC9U+1ur9w97JxCAWfvcNGv9MrwkOWbLl7aJv/9", + "nBTzQTbrtvbPaZXlyWKAxqfDZMzdoSd5vQS5xhq3pj8XmkyB5HQzN2VEuJCmwZ5tbUMRg0FivmtafCVq", + "D5wdfLUnr4iH54fdYPA6POdOAf4hWWYDwA8APwD8o5ArhwJ8TwaZIwX4R3JSFAB+APgdAH+XlwLAHwrw", + "A2cHgH/6irj+CWOrJnL4sXcToVzr3zo+y7Acx+s+fgkS81qERD3io3V9oIOx67eOY37AJR+y546PT5kP", + "C956b6cs75Lrf7BXKwa+cuNjB+X+sJR7RQTU3bcZwoy7ISYx7+PHMbEJ6Rift96oBWFaQTaLiF6xBDAs", + "GWMtY+70O94DXHFiZg48pVy7sKxZqSAddlMPQ1sGcHG32g48HNT4Y46pxKppezOzrBZUk1KBOvQm0rkV", + "HvXdOxuAU2ywkyILkaU26ibyh+oYCVBVeoi5FkMdgb/hCh9cXOaA+xF25bemP08a6tb3CPY7suuuG/7r", + "TfqvCJ887WKGyoJFDahFY8c+G0rEf6+nG1zZwZV9y/eqKmJ7mPerji/BRyVgXIaPJZV4CZAwvukyWy1g", + "4xeyoMoJm5jXSTZ2smuQ/uQam2ZAzL821LwB7DE/0Il2FFLuxi5Eme+YZFSpjgsqZptMU7WBFQlEREOW", + "VSHLDjaRhVgZtSGBpvhxlzQrYdyVNruinc4LpKYRH+2eEDZFhBL7BGbo5mvyHx/eva3a7B1Sg8oYzdgf", + "eJ30SC6DPmyhdeJWRg2hzr4YIhyaPqR67LhydVSUdlR+/mpSe99m9z94+R5agpAaROw3Ug41Oh4NoR9h", + "TpJD1VrA18PzmByiXgaea3/lKfLjVC0BbAewHcD2LWRgqQj9nCSiWBsaw7N6hmdzqdKTCiY8bVj72aCr", + "55Hv+F2JUiawnfm3er3hpy356SouiKXhhl4Rm4LSjOPbopjjXXqSl0pjINCCLmELBeF0aG7dKkNTsQQJ", + "fIP5X0SxHkUj8207ssBEoxYF7hL0m3qpHd+/oi9fLpnNsUNmmeCf6PBP3Fyd5SbDx+AM/75bjRGZCr1w", + "nmDnAJ6KdH1IRYBbqUm7ryBfK8SwlWHugJoCbTZuPR4q9YX6zLv1mTc5bkBq8Jvgt+5c34HbAredeAjw", + "zRVuvo4m9Fz/uQlNeCv1bQNvBt48nlrPh2vCG+C3bk0YuC1w26lrwo24wN64HSFdJE3L7TS0UE1zIB5t", + "nE6TKTA+3ywk19AkEnorS/h2gbnhnNoOtLnZ7OUbJXMZ1zDHMLf92c03HPjB1R5c7UfnN1Ka6nJoTciM", + "Km3rGWOp0VYt0+dcpPDcBbYTXRZ4ZbXN8ZcsvYz5NnPvHlK+/gzJ0BA9W9/4a6JfPtjl32a1ya7yrHbX", + "XYXWbbkSSlFei0OPrrzkLreAwbw9DFNl677TeuD74mZqFgllKx9lvW/7/R93yW8rr8++2P8PDPU8WGN2", + "Ba0fog7JzWjDi5Jfp+T4hk7rOMat9y5c5HwYiq5d4f4wOh+mco6KDo+zAP4xyOaj94ikTF2pQaH5pid5", + "Oi2zK4OR8mdWlj4xP09Y+gRdE0wZ5JRSLeS67VG0sZQ2O7+1ZjSVc9A46EsX69EIZb0A7upipIQqYk8V", + "Ym5ne/bFvbOnaP6PuKybslzc+zq5/IqwFLhmMwZytK/wUTVQ8C+evhWTOhLbEdUV7QWT4FZMgjtB+OYb", + "DtMcx3a5tO2kRpHNOP4fBUCXr/gWRCXNMoHlKo2ioNr6b/7Hdx3unMg9ICVdbziSWzGDpoOZjTSbIP19", + "Ulj2DYHGvr+579EMlpB1e7mx3eunxlZJ+8ZW7A84ZKvcXd5uWd6la7a2+C5UT1ApA0BXA2OGwy8MufBy", + "cwN99pkGu7ilwxZoCOjuLNJwIfB6YAS4lgyU816qAhI2YwmSig+i3BuNhKQiDxULHb216yrFDRK4tq/f", + "xHQF0G71eMy+g0hIhEwJSzGdkJ0YyegUsr0WZzA2H50umNWEuSP3G5oNxunpCmT7FU/TPK3lKnoPnShL", + "YcY4Q+8fXu+bAik5+70EX3zTTcve2WTGIOsQwD+IrMzRZT+baLyQ1xQcJU0h0a67wrOJKLoGzAsqmRKc", + "2GUJg6yq+3P/PopGv7z5z9ejyNbKh/of/179K6n/YX5687bznp2bbEd01KFr8ERZ/d38TLQgCa7HDpnY", + "zeoaaksrVfOL6p13+9W88tM9B2MdwmTHoa6OPK7KqaWzL/Yfgw3filC5vZxvE4LmZrKG/pqa3b0wbZ+x", + "44BWY+6Qp3PgEzf62EZiziaIuTxHZ/WyQqadh5Zpx5Fga6+92OqrCe1GqSuY2g8X2Z1minqRslmLpRrk", + "ZwGhBFVmWMC9hQkZpmRhNoclJsCMeWLgJBP8nFxxseLEgjOjJCpYFRH4zBSOZYFJRLhwWTLd21dML2w0", + "PmaNaE/m0gn7S/N2s12leXld6aLVtReiHrfeuWHo3AEfrZOio4SIUUOQ4hcglHz34sVLFyozhWzvlvfB", + "7VuE0n3weJDGDej1UdwgaGHS4QBXgd7ra7Qo97bdjQp0p8fR/O4S0QSfY4DJXT7HLjOscTva1uB5PHV8", + "qkCftvPRI2tbnsWblLSz9i3IzXm9bSW7aoSsFgThra2f1NVsg0A6YZB5mUJq23nbPxaA6HdzOKbwoiTV", + "qvXj04/m1T89a/kmP46i0U+dEGmgKqnuYEfNCgjlDUqv396pYI4ATg2m+4Cobg1RVe7DAXUKdwFWpxPR", + "/CZhBhJ4AmofABtm0NmkA502HejarKvkQq9hF2r0PWSfImbsHuBWPBHKC/7GB43nHoLLcQ/HbWDAkxH2", + "Nw5T9+DKfZiwSzkEfHZauXK8mOsMPhdCam8ZvdfYvMFwjBNq06/YMHcbNqAxsRW6gI1JwnJ8zt77kr26", + "0L7iMWCxQVTvtuN47PB++mlFYfYnibD1i113e2+2bST66cMb5xYgU4BMN8R0D+asdhCznn2Z7be3XdpC", + "d7rq8oP6OXbLtD7kxPTeefbmj3GDlf8AM3g6VsC0nX5G2DA6AhvcVyBDJuZbQQSv3v44isx/ydt3xtZ5", + "d4H/wb+6gwWE0VpdV0VvwyQKJ6BHqCndsX8/sm36EuAJLVSZYXSTywfoLvBBehje7TxgDZA3QN7gJTyU", + "hc++oPE5FPPyTTZuPB/XA8EDfI/vqQSu2z6W48EBP7Tt9puYWvUtAkB+IAD5dcMtW47Cw6FyYJabYpYA", + "o0Mlt1OK/jjDXMD9aNumC86pThaMzwd7kN/iyAFMh2TD942+DSU+eODtUqDu4eWq1+Hs/KEaP3B04Oj7", + "5mhHjA+eqUtF5+Dl6CoUbrUAuWUEKFIqSMnTxqbeiA9WUVUUR0Uur7JeSFALkaXqWa8c+A2nFOIGWrvx", + "oEhwMijDU/855ZBrWDefgOSG0j+5SK1bvN01q6l5FlIZh2PNQ67UHDPXtNwWW8hTzFlCs/peOfmXYNzo", + "I71gqrUTegGkkLBkolREcGhdnfkK/8eWH0soeyV+41JQlWm94wJNK3tskAtBLtyKrt1zz/kCcrHcBHgt", + "XNedQMGjbm/yVp71knqZYtsru8ka3QyBsBK49o+644ceMuwWn229I9paSeC7cIpiT1F4O9fJIfr56Nns", + "65S1u0O7oa+Ba7m+C42dbJ/2WNVdbAmGTg0epEs4jjmG4xgh84kodVHqic3XpM6+uH9U8RKdHp8PC7Gq", + "CrSZzkRpWSa6lOBi+4XMiSqnOVPKAwx+Bv2TkPk7fPuFHWafO8d1I0jOHT6aZupDPDTNSeSnU6+ScNwa", + "r+wyQNPUlsUvM21EWibmJGMc85cSyomlyk5qqoiuUwuWR0ZVN6F5MzHvro69uWlFAdyWR7UczVLTQUXk", + "n//MlllEZrmOSEo1/RSR8Xj8KSLZMiMvsNKAkc0R+Qb/DVIK1FL1ON1vZ3VVOvxA7ouZEVYLlizMTLA2", + "d0tQdEEA19L5CkcfZnVpikPXc4qqe2ipSMrcaEuzDCuK0McsZH436SYCNr5ZjTQk1xb2O7fRelqum6uH", + "T1wBO8RJlGRMaUel+Zh8oDnE3H19lzOiqklH7LvPvqBS7C1J9xNO8vrcLTi8m+FO0TRFTEmz9y2Ot5Jl", + "i6yiLyOmwW7OIY9VP2DVoNGfnwIDnGRarkrMqjF5VdW0JgpA2ZLX2BbZnJiq6bxRNjvmTd1sJl3J7DF2", + "nGzm6MSf1jTPjDWjuovqOvwW8oDdfkT4wYfkt3rkKGT+yKpk78lFhpwWGU1i+G7BDOhB10U9xhNF3r/7", + "8NGpmHOsX2/1Vq2kxjFHrjOYc6P4aoSjWgfQFawVobJibpsMV5GnNb9GbhQjkSPLxjORpSDH47Er80pL", + "vRCyrrBdZd8lNomXBKJAR6bZptNFaLddf988nNMUemp047hm5TFPYUYNikOBs1n8m6AI+dWJs7r+t9e/", + "FRTv6SreE/CFtNDfsHRkqHQRexrLA3nEfqwqGZljjQzUdtX7bsrffMxylDF7KlbsB6V7w2GQmT1mrlv5", + "I/OcPGzoiH66ik6pIj+/rpSQITItGabu1gI1EkvPCeSFxkAu3hj2qQAVcy60TfCIdrYi5u8NpYBSn2ZZ", + "d6U1BxfvnkJDDGYApI8FkDYJ0oyqQLjXDRlfblt9O960mO+60yLD9+jSw+INNeo0JimHVctsZMqdWEFK", + "GG+Q5BPz+5KhF9cC5fVXA8J7UnrXQ6AHAMg7zot771z0KE/hPKcjH8ppzrRj5PO6ZoqtnkE1JXROGW+5", + "hQjjRVmlwC254dyYW1+5Ik/TaYT6PiL2JRHJKcsishLyapaJlTMNpyJdk5yuCc2UIFOwxuRz4IlIIbVn", + "B2TOlsAN+xvhgCLDSgjEF+4MvGUDw2eaFwh/0fjkagUIH1qHhzGvTw8j++pKxiAWpimtk8vV+GXn1JKl", + "f47Jq5hzmFPNlng6kYJic041mH0hhn8lp1lLOOLOVXUKt8FMzC2aiUjJM1CK0Mrv1nPwdFLCaKveP9XU", + "c9DDba4/I7VrgoPPBSTa+j0oJ1ZqRS2Xu/1FEWu9MNkmFvsNMBJCwnKymvnOmOqwDqWhMN+U8Y1M4xUF", + "j8NRz0ke9TQG9xnNJ2zSspi9wQcfIcuMiVJnwLd8akFH/fiG2YxU+iVGGo9H5wRpgQgZ89aPM5op+LPH", + "eHmVv7lozS8Y20cOk7uoLGWz2dmXZFBwS7KgfA7W0zldY7iCxa6RE2rEjObSzZMp6BUAJwlLrfvU+mzR", + "lrY+VUXmTBtQixUvF5D30NqPbDa7F2N58xU/M8zwasCIPe530RjVTnjyFnxtJoVXbvNqY6FVn9bsrwED", + "1at/N4Zm8258cHSbF7ICG/151nZ17s+RZY8aie88YcsExC7aAlCPh2kYJnOs9L491+B/Cv6nm7Wc79tq", + "PjGY15YcZ19QMuw7b/mtEgONeHA3PYcfKcZ838kKeUUwwJBjTN2Vs1WVK2zJ0QoiOShFu/1RzTFMS+Ac", + "gwo3e+SKNkmBuLXjXdWHuNOrzcGcul1/8PtttsFrnsOZxuLYfqZpGePXYpvKjRuYJjDNvSun9oH9tWBt", + "Z0DMLePbi/akA74N+Dbg2yMRIQPxbX2vuu2+xCebmulW2x4Z0L1Xb2jQ2QHo1oEP9AoqZOs9BDg6yBvY", + "J7DPEegr62IfgHfrrhv3/tpBRKiumLYHHS7Ax97Sygu9jjmeDW9GF147lPCinng4iDvBE4SamIaexm0R", + "G6F640Ru84D3SzwSLI1HEYmrzxKP/vxzADk9mkO3QMQ3QMQiy6Y0uWpouBufXEBzE3qbjvH7NnRcx01S", + "Y/1zWNVt45gPBDCH3iCoAYlbTuCBAEzuh7cm2wfLPpv5A82h5/K275gpqvlgUoVpVG02VNqGN7o4xqlI", + "177ben13w7dOnMN1tcAtd2EFVzzRumt6rxxRX9kM/BD44U60x/b5zXW1h8eJezfaY+s8J3BL4Jb71x53", + "zxG19gj8EPjhjrTHYFfohi1aX4rE3GfuRorqS5rT47sMh+nhMP3h+cwmLXdv9c/9GUa3fD4Rma7dAdV0", + "TfL0r0NYbH/2R3fFwA6cp3/1ZYGsZx1qQAWWDiw9QaU3TFXWGnK6bhRk1GRtbO75LGBNViDB5nvVGtKY", + "m259rP4BJxI0aWC7R8N2Z1/wf4NVaMN+tLkz7WcpD0dtjV+DXv9hUDXLEFMamDcw7y7znqVlXlybg1u5", + "55qfjD6t/iILoM4toynLWnZqrvax/49mZvcmAkJK/lsmR4k7mZ4tWJoCn+TAywlwLdmQmw+mN3G9iR2h", + "CVXGRkwkj5mJ3XUjF6igYq4ACM0yd33ipcttWiqQigierYnpsHm/Yk2mkAk+J1r4yNat5284mV+Bl6/d", + "YgIuvG3Vclqa4l7YzZLyoKSill+8R0Q/25FuKutPV+Kdn10YtSs51Fm0QWTgfVBkcOYtUXSvWc7e8Jk4", + "jQxnR5V8vg53r3LGV8KcJJSTIfLcpgA8RKDXdB6k9+lKb3zJMBF+bFndhSRlYZOi+0Xye6H0DQvkjcl8", + "2ZW8XQL79QZ/EpaSpwoyzL7m1sC40sYUEDObmR2rnO8WvayCSHdf8eTjE8R0tBVpim+LyJOfnlieXzEF", + "D0hZHEC8j1JjNLhm4D3HTYiDgcoJVQlNgdhH0JLNIZ+CVAtWRIQWhXKhCLLMQIFWZ7lI3T+37mkxsPkv", + "24FuW3e+8JPuZpdtGSdGobnJUO6Mlw6VZgbjgj/fYoYO3YYJFPO81JjF8slrYxNNRbp+4nYhoZhae1rt", + "QboH+u0zyatrXMA1mzGQ5Ckt9WJiRVhzu+vZEV3vCojtJhHbj0wVGXWkSxrlciBqs3b6tVDbEZJo8Cg/", + "WOB4mheWq0ztSM1PVItP+2DmsQr/uwC+twxOA/g8ffB5ZvDifu+16dVoto68wf2qssrs+pUea/zCr4pC", + "BXUZ1OWdeMmPhEk9J07+7I8LlhqrsT50ai60urMlY2MZbrS5/BciS3esvZi3zD0sRZBU1S4zMZ+7agO0", + "yvnMheE1+y1MH7CxSHtsswGHTw9HX9ffb90Bb5pPdQVrogUp8St2Onmauf+zPeinO9DAW2chfCYGQ4Gg", + "iQdWrR12Vtzi5rbuvaXT4pPh1qCIw3H1kZisfztqLVybyEEHe3Vw0MCPyRZuzkkGxHPVfXcTcdXpotv1", + "QjcVbsyR763WVXvU7q/NvIK+Dfr2ERm+XKRDgiux25H4p97ilAOfBj59RHwqB+tNeWda8yLozMCLj5AX", + "FcglS4aozarnNTSnS1pyo96lD9XEA8MGhn1EDIu8s59bLYvZWL8qnXSH/7c7TMlqzkEcil6mgiq1EjKt", + "krvPmdKWZSdXsK6K4mOZfA5LkAQ+F0J1O5oq/v4N1xmYOzD3g2VuNvDGkjFYCSvI02mZXeFlUFdQ/glL", + "n6DzkSmSU55SLeS6nQzMMmQVq25+1VTOQRNWvLQFds07nPdXL4CTBeVpZrMjV8n7WOHqv3sPZ9/c8oWp", + "N5s8bvZjwgyDP9vrbmVpcLM+yCR7fvXHCkVS0IBWoeDW39NSe5XKY/7LVGYIMXOeotVCKAxqsrrPaLFt", + "1Nutx96E+1UnrjzeFMetPlAuH6JDvKeIb0UK3bnup9C6B9Iq+YMjmn+wou1j6Tl2jPl1o3/e7I3M7VUR", + "Hdjvjq9g3Lh+CDJ/+z5Gg5PadzLwelBDGMbkmQIBhmIfybjMQbLEyHyXos7RNE1TCUp5ZfuBFLmcmOlx", + "0Cshr5QhTPOu5j03QqbBOHmY+uXo051kYr7HKQFLM4XKOKmfNwqii79+MQPuTS1pnf9ECzNM9Yqc6mTB", + "+JzoBVNkhumWFGjydA58Uv+pnH/A0OnEcFutKH43n79Vb8V0QD4MfPdgnAJifpq35mlD6Fa32QAkQ48G", + "SM2ETOxR2BNXH/FJ5Oz8GS0zHfMMlpCZrk8MCHkSITLD6nFtFjI2TspUQmXqDwdzLHozZn8m5pOUJboj", + "t1SEjbNcd15bMm24qM5WiwPTzja1TLqbtlwI1ds/3fOVpXBbaa8KOvtiPlZf0sYGLW6oIEv4LeTo0Un7", + "VNIv9VBt7JeJud8SsTMOMC+omxPAeZX94i/F9yMkmVEflLi+Wyki3tpfO5JEXLoHLq1rYuqSGr15v/yu", + "GqsyltAJYfrnVF1dviSXU5gzfhmRS+DpJeq0y6kUNE2o0pdGncXc7E+pbYpHVIlU0ylV5sUaaN6ubXNZ", + "6Uu1WS0V7xGznMq1O9Eek1fEsDFW2uD17GgmgaZrktq9SO1B+axUkLoixuS7F9/79Orbao9vSrcmIs/d", + "YztKcE41rGhHeDNue7UgxhVz3h73Jbqu+lqB1qWF7Yfafcl7CTP2mWTA5ygSc/qZ5WU+Ov/Lt9EoZ9z+", + "8SLayV+JY+I8uie+RS+RzZf4meZFBuSb778df/M//uf4mxfjF540PaJrrkwYFiI0F3xOxBJkRovCGBq8", + "+WL1Cr7/ft8KimXXWcfff3n1diMpXOuJbTrdffqdnFPOFLV1VHoKdns/4xb4afpVH/G+YZBjj9NBQ9+9", + "+H5I3+/vT6hXcbPDvMi7x5AOZfefRcbciOWOs0jz9NDTyJjb2Z59ce/8kzzdynH0b4SWKdOI6v6t66bL", + "M7+fuQrHvRm52zI+NvfzLToqd9zV6I9AL6FzR+xhTTd8ON98XOeb3BHpjn3iCSYPpsLNmApV4vbjsi3M", + "Rz/9DJBOsaxr8VeJwom1mztQ8o2KantgObHi68sIuEFt/xwVpTKwtCizrCVmG6RIi6IT8FKlQE+AL/2t", + "XrA8ZUJNliCVL1FPkpVKg/S5tZov0N3KOSR6okV3c1FOEiHtpuwCUNOcsr7WmYTfvSPnIvX46UyrXhir", + "qWfsJfDUsyzgSSZUKaG/VWWi2wya/Z52b/Zi6fm5ECLzNC3TpLtlNRFTNaEZSD0xhN/Xa0Ul93fKqNKT", + "qfCsBluN1dfdypQGDnJSCKm7dzsTycSYTh6PazKZlixLzd++DgnKDl+jKKs7tZ3ts0wI/7slTa78jULk", + "3sY/WDe75tSsnVOewAR46unDyxlNdCmhe2o55JMp5VceAsbmtYaeZkOdvmYv56CQ9EkabJxJ8Qe0qXsq", + "RAaUb3WYUH2wC72S1p7GBnOr7tcLNaEyWXQ+LtQkETzxzEqoyRVI7tkUoSbeaQk1hAtdr34uFGoiIQOq", + "vM09IqsQK5CTqQR6BfKb/V2+7emS0CnjoL/Z36VvlEIKDYne36OaUk9PVRZFtp7waTc9e7LCIe6Y/CG4", + "r1Ey2v3FFRfiD5holnnai16dqjTVpepsQqcLTt3fvOWT6e5ktmRT4rY6OOCx2/BH588WOHUzZd86V1RK", + "yvXaI+buOyufAXUXYhVOt7p9NGcLKtMVHVIV8P0Pb9ANnkMu5JpUD1ZXQZo70BgL6G6CRITij0zGnM7x", + "JFiCoVnC3HHzpQ2mvWydlJFE5NBkHPqXYBzS6gV0moEnggoB/N+qBQWr9dFZrdW3H+rJPfICZI5Dp3RP", + "IBTNMscdP/2ALMo+/PDhDVkIpcm0VISmtND27pOHZ8wrAr+ES0m3SMa1e33IsQAn7wrgH/7+g3XjeOoO", + "SMgMZKlS1Y17XPD7oiy8/vPffnvz47YTvSPkojJpTi0Jf3CEb4aUuqSHNjW1KiAx9iZ+fJ/wPEbKCtE8", + "pyW8h3vcTzJ1/m8bPvmeiLjKC3+00jocDISDgXAwEA4GwsHArR0MBOd/cP4H539w/j8a5//xR+hv+m/O", + "UNTtc0k6x43t6jGdX1WtwYAOBvRXMTpS0kO5ELPNbvmEbWuETsa7AF1KTgxtE2YP5ZzFCrIjsaK9zGxe", + "M/YyaP7movXiB+hDDdkxDiPGhPKUGawwsU/0HhrTuSJUa5ossJKuFnVYJhearEG7VpfNxfwIn5OsTKEj", + "QtOR5A/VBD7SeVAdQXXc2R3oU2PUBSRXw0Ca6+pjuKo1cFrgtMBpHZwm8iJjlCfQ0o4DSrn8DJrUD7Tr", + "udjDRzO+P8zph/qltULsq9KylwreU70w475JR4GvHhhfoawXs05ia3Fch0A3iGwmSp62mG3rajTXIDnN", + "MJc7SAJSCnn37CYPYzb5lax2ERgtMNoQRpMPgc16M7EhY9V9iel7IFd152ULjPSIGemHDoKqYsxPHSMO", + "RIYtPFg7SWoHyhC2CnDwkTJX/eGHqquavh4ILGyWcfYlt6k29wQdm/UT2qzf3j3x8loTVtzBbnfAbab/", + "rwq06b9LSR1frZ4cUWWSgFKzMsvWJAX74fu/tpCtjbnvT+8LMXyld75hn7SsAg2P5PtdL6zwGkfr3/bR", + "RiUHwq24brkyyMiUX6e1g2X5KHX2xTU19oOwL2WtreUh2lpeW1df3KmkvzhEU198lZ6Wp6Kl5bV09D1+", + "t/vU0BdBPw+SI03Qpf/Is+WqckiRZNT8voDkisiSEzvKgT6sD/bVQWk/JqW9/fkP8Go5ImtfN+zwb52I", + "Kk+Z2hdpgF0QuQy7VPkjDhliDgKPfiWPGkJ6oHEHwzK3uBgfT/IWH//5k6gEFgwsePuJWU6NFfenaLFs", + "qLSQdA7DU7N0Z2YJTBiY8DAm/NuUPlDeYwbvzmgCwziwKuPQeszDem/aPQIDBgYMwa8d3FcMY7s376vC", + "KT0MVwROC5wWKqD6eE2BXLK9eq5KnOZ6E8aVpjwBRYStnOIcMC6jpo8ZP1QvCxwZODLovj5+PPti637u", + "LxG5zZOVH/g6nHmkjLk5iQ/VglvzsJtVT0Mtk55ZuIqqQToE6XBq0gEzyPirWn7AdixZw23fjZJiKBQs", + "eB7H/M2MpKUVBYQpUkixZCmkEXFPllyzjHCxIv/WdHwK4/mYxKNvFvEoIvHo2zQePdsdTORMazNWPY/q", + "KGoc84/unzaft21mWkE2G5PfFEhVVdYkRt5UJTgpT7tLBNpBvUf9dk++8hj1xhL1VZvUIc+r7bNCZ2en", + "//Iib285eZczjHWodnjcWYltJ1oglFg7/YQJB6VJaEcL+tR/yHsQ1G5Qu15+K0ubq7QXh6NGMz3H5B3P", + "3N8thaXsWanVZopg8eksEytIvalyDGeFBDmPT96LqRIZqAQwkhVmEhTmnyzKzgxN2I5YqK6fgvk2LcUJ", + "RWZllmEBcEUyox1cudv2a4gCrRmfq3HMNwqhv5uq3SLoXXCr1O9a47lZjY4NbTygqMUNKqk+37BCCF1f", + "fqsA/tDvbgdtf/oP1VRuCjN31SZ+17ECIiERMt0oS+4pShzqET+6Mgyd0q5L83poORSyOV1c2vFJT6wY", + "8a8iZbP1Dcvu90Lpo5fc0Wg3FfaWXqPaVXZbLViycGWrcqqThRkbU1JWLzLgaJbR+dyW67ebqWFM4tF/", + "//d///fzX399/uOP8cgA5/YvZLE4z/NzpeLRS/MRIC/0uvLUJBlQaXfeTHDsW8NGou4bWwIlZlwkgltd", + "w/1o0Fvh6qBHrwsvz74MLrZ1Fxhzn3G8V9Z0GMR3bAufiIVzirCv8sx4iHEg9jsCGgtu0EcCN0+yEtdd", + "QtNjEfg3AY4DrD0SWBtA7MMFsQVwWrBx9U0cTtjR+x9WhvDk6AjOxo7AQ13tZlFOM5a4rSxockXn+yJF", + "DadVPW1IWpZBWgWj+eq5r5jGA4yYuygU6SrAM0kUmxsxQK5gPSao8CElU3e+ZkR4VL0Q/yKUpzGnMlkw", + "DVjuzHROYUbL7MDq8DHfXx7+fbUrwUH4qCrDu+/+QIrCVxx7lrLZbD+Dm14gAQPAGW+xec35U9ArAG4Z", + "/rwtFWLuan9tiQdlGNAyPSbUoNKFrCoyLW32GcGxKr3tlEcxFxyIFCtSgD3mJgu6NKKCOUa3j9ejGYRh", + "hp+zZTW1iBRZqWLeCCdZcm6xSdWxCsmNDPJASXUJPKHFJfbBf6oSi4ZXAgNnKBTUj5KnzQuMkEoJnWmQ", + "TsLV0fRPYn6ZCz5Z5qbT5TMXSdA8S3najOk2ixZFI1KfKDI35K+MCISdeDnzW7UdESl5BqoljplBXS5A", + "YRzzn2CFU6Sc6JVwM8A+3714ERH4nEChNzYkcjBPL4ATiZWDzJxjbjFZxpTeI0Z/NPS3B+O/MkvI6XMF", + "ppuG1B5qi5mlAZYqokW1zAry/24kw07UgxHbB0Qe+99cB2Gniqzw0zvVsW8iNhb5wHn8w+y5ezKqXmCj", + "vR1xPNmgy+rbcaWBpo1qXQiFWeG6JobPd02rLo15F/IVCeL+sPC9COP2lZx9btbqg/u9pq07Nzdjtrro", + "+XN/WD5GHRkq2neG4IYKJ/GP6yReNSS5a4h5r4gFPP2Q8bT77id2Kv+DBKrtfQssdtsIZPJ0uq6uIbkb", + "SRPWUYHuvVD6xkX0ngr7Zi6+yv/YVmqhNPWUATY9DAxy8+psTyUXNNHeSsbYpcCI9D3tqq+DtyKxaffV", + "FDdtsww+T5KinCzYfIGF+9VCZGl3HeiNBzKxGtw/p58n22vo7Mf43n7bNdA317Og3qYeGshBS+Foxdup", + "/yMMqJ9uuhUZTaCXYtDvY8xC8M93b/3sZTLRohCZmK+9HVZ0Cd599hRkvwsf8V7gUeGrBGVO2gidx527", + "s/PC7P7ohO0b7cayTqhKaArEPk2YVkSCNaBcUsVxP8jeZ7nex83VEKt/PyC3nYazlaBS1ZTig77HSEQh", + "AOG0AhAOQtMnGXTw2zbebiHgHox9tBL6pjwzAdc/ElwfwPspgvcjQ+xHH7+xg+7PMGJqb364Gtbb3n60", + "9arqEDBXwFzh7nsnx+UTNmmdJHt57wJPfIkhbMLs4bQDNvZweTd7C4b/2QOsPh7N31y0Xh+M7KAGWmW6", + "D0qGQg3tYTqU2k/PhSbrViUcdAWZH+FzkpUpdDjtG9Ksq3cPyaAStEjQIo9Wi2AxpMG4zfXuYbyqQ+C4", + "wHGB4zo5rqli1mjLAZXCPTXNmvqjlRLdTC+637Pd1Kqq1WZfQfHAyoGVAyv7WVkeysjy1tj44riZeKuY", + "3QxN1MgG7/ZsykYIbbMvnWG8GV3CRrSsu3EyOp/RTEG0Gz0bhEsQLscmXDIx769E3pImpm91um3H7A7t", + "35Eav4hgKgeGvH2G/KGDVlt3JE6fW28Cy9vswNeHAEcP4Pt0f89uBN0fRM3j0v0NM5x9yRXo/bGUru5+", + "/aC9P90HBzaiJTuEyKnCgvdUL351pf39Mie1O1bfMr9dGbPLD9925m5x385O7jRDE7578f2Qvt8fVQTb", + "K73DP+2DKU9OnMfKO1Y/3412PpBzKugQOOeuVdbXesC+Fvw+HLdXAL4B+D5W4Ctr2CsPgb3yK0Hvxemr", + "7YtThLwXAfDeM+CVXwF3HwXXHB3YvQhQ956VlC3qeqifl2TU/L6A5IrIku/WhD0E7X6wUwgnNwFVBlTZ", + "zbApU8NjHG1nP+f96NoDuwV2+yp2M4T0YFmuTp7Y1Gs8JHFaUza9nQFCC5JStZgKKtOISFC54Ph/xmfC", + "9sT440nGltBv8L1x45+EjygUk3xUhTF2eMDYxCxTuzjRVzw4EHlQmQ9RZVYE/WDVZp0ZYAhSreWDtUKN", + "eACaLIiYYZIkO5ZfOrx17QHIBq4MdqOXGzcB7GGKu2HMg/T2W9scdHaQDkE6nIp0MO8WpUx69LdXTtSP", + "XktUXNQvDjIjyIwgM05RZvTf8alLZvaJDgM2gCQLyudfKUiO+CpQkCVBlgRZUsmOqmDGEG9BIyjQW34F", + "67MlzUogBWWyz09w4d4TPAWBFwMvenlxD/b3cqMrn7bPW3fsID/wYeDDI+LDfjztZcYdDH0Ia4Yb9IE7", + "A3f2cOdBOSHt3Rc6IBYyJHkMfBf4bofvJnUM1rUir/bXrnxTj39TpRJ6C1g2Hq9EyJSwNCJUEWp0tAbJ", + "qWZLDBFzbP1vpPHu7Camr9rOPS6lqlhmZEacYiXelNBM8LktrVuLg57qXvsKcfrG3pn3XebMDxU5j68i", + "Z1OKuq82Z5sdQ5HOR1Sk87CoqCPRSRuF4fwsUPf3VOwiT2sL7dkQ5gg4MeDEEIW4hzcnNm5pkol5P3fu", + "Kqgq5CkT8zF5TZMFVtxbE6YIJZrlQCTlcyCrBUjoiWVcURxqmvWWoGh0nr0F94uYB+X3CGyw++WTg7nj", + "mjxxGCsEDggccMscUPnv9voSNJ2Tp9MyuzKoLX/mdyU4193NeA80nXda3h/pnNi2yOA3M7nah9BpZDfQ", + "7Z/VoJ+C6f246gR/ZkozjoTTaXV3O52DpA2S9rYStfyAFeatdB17ErPcuDxNqaa7U/lJAtaKy8l/fHj3", + "lphOOxnLNJ13uUfNoK6EV1epunmZUUngcyFBKSY4ETMU2Ma6VkQvqCYJ5VgIbAqt4mCN9xTL1/W83F+P", + "dFvsY8+7EPw3cShxDLL+yDO5mN+bG3Z7M4kZsnNZxMxD/SCmukx3M5y373TCR9u3hX6a85KAgx4XDqJZ", + "Zkjmufn+TtzmZio+SOS5VBpwUcBFt57Azog2DBnxiesKIR2HsLbc9BUIq2HHoA8esD44DVxVOTsPhVZV", + "oeledFX5OG+MZ4cHadw9a7m5Bc56nEir8v4PAFsttgh4K+Cte8NbPTK8glxHKMFPGn8FJRHgVxt+fbGU", + "MSTJonPOYr5EVpeaQEVjKBsdZNioGp71ALN90VRvfkT/be0N7oiXqil6b7xUHb0bchPeX25CQzhOIKw9", + "sOSeiOLQKLo7I6Kj/tjdKv63Iq2PmkhL/nu0+32KgZs+6Np3YHXgmdKta+dgmt2SJt2Ti/Fn0E5V2rCt", + "Squy5v6aRz4Oyrt4JELy1k3Dr5XCTEOuOvig5jwqJV138QUa3WJWfcSNo+OGWHexOxeazETJ02Mi06FZ", + "truPNv0Ab0gmwtsjVd973JyPJNP1jdtHjxJ1HnK248Mhj4Zabwr0bLlABtBscCY8ImfCxqHOgDj3Q5GQ", + "33/9OMFQ8JM/hvv53Sy2cR/yGgeofgz3oe5wNIrROuar920Vz/vq+5QB0J0SoPPRr8N0j5N6A8ALAO92", + "tE+pkIG+DLn7gn3H5FfK6RykPRT6TYF0P2AkvgLA0AXs+5IIvQAZc/yLCJ6tsYPhE/uTWlBDAkTwioGY", + "JELOKWcKSYpmZG7AhIpiXmSlMl1yBdkSVNf58s+gf8MVhRCIU4Z25hue6nUcQ9iRdSAyrUgh2dI0IBWT", + "eGSaJ3H54sVfEpbi/yEejcmFVQhI322mirkZgGUwhzF5xQnklGVG55hxUO/QTAJN14Rx85sxsyTMMIcQ", + "zoGS7158Pyb/YHohSh1zSgqq1ErI1AYtJIkouWNyRaYlXqjhQhPF5pww7oviqNjsZpQTLqvzPGXGpNK+", + "E5VolNG+1mqpXcCDZECVJv+TJAsqaaJRtn3QQkKKiaTICqbfFmuyoGox7oroKBaCw2Ql5FXnu6sPtP9y", + "kV38fd8sGs5z4XbRUMV69gXZfUixINOxdbZ6kJqNOepZ8jVqNuZOz5LhanYfCjd9Wqlzzgkt9WJipjRm", + "aVTPzwm11QI4YZoYaqaMm4XHPB79X/EII6PikYJsFo8w8w+KrlIvzNAJllzHUXGqHbjbfYWQhidghlNw", + "CW3JjrNCwswP0n8CnSwaZjKdQQJPQJ2TJVNsmgFJRFbmXEXuH2SGmctURDK2xDr0EHPgdJpBSmYZnUdk", + "wdIUuIMtwLVkoCIyHo9jHvML0KVEDiWQF3pNrMqyLFzPZEEV4aI9IaJQv0ZGpsWcZkpsPZIKUHikinjE", + "sD2zf1cLcbGWCc2yit87RdN73LKHLJ9um5dwB08IgH+gS7hLLvCi4kdCejcB+ytHFE1TZmHI+1a7ncZW", + "yMUCNgSKFTyREyxkCXJKNctbgL0JASnLrgDsdwX9vQSigKcbn4RAshCQGruq+hoTFMQTmw8+5rAEbl4t", + "CCVJxoDbZARszoUENP7EipMSg+fs/vfbAbgb920GvOEzcRomwL2o5iVIxex+dipjiZqR0IKRqmuHhvp7", + "3XRr37F6+80I7no7aEGnLGPIoHZHjAE8y8RqXyr3BRAnNNQ5/lU/SJSm0giq6dq60Mtpzup0H9Teu7DO", + "jJhXTxFR6qLUY/LK+kwWzIgAltCMvHr/JkLulOv6JQZHZExpl0aer7tkJLk0r0J3wmUUc/vXTGQpyEs0", + "w+wva5pnl4Ti2bZQtecfpynBKBtXbc2tN+bVAmdS5B7Q8o96G4Pr8ujS9e6c+/wnQIGfuACeGsu6Iean", + "Lk+fQa1JJhSkz4iEjOrmppBFr09UzDXQPNr4jczKLLMnSobikIxEZjRdZbdzwZ/XTsHKbD8nl2asS0eS", + "K/xvRpUmVCk254CeQafL7FspMk7MW5wTj17Z3jjVfI0949FLcqkZSFWNnqCvs+ZX08kh+tbTSuQgOBDI", + "FFQvIxvveu/2DscmNDF7G49aSOV38xEaqFKNPmpjE+BljlehgOZGw5qxWkr0TuByxbtDzc/h+vDudRyO", + "I5eV7CllNjofjc9Gf3768/8PAAD//w==", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index f7e9e9b1..daabde25 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -2154,6 +2154,86 @@ type PutComplianceRulesetJSONBody struct { // PutComplianceRulesetJSONBodyAction defines parameters for PutComplianceRuleset. type PutComplianceRulesetJSONBodyAction string +// GetComplianceRulesetPublicationsParams defines parameters for GetComplianceRulesetPublications. +type GetComplianceRulesetPublicationsParams struct { + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` + + // Limit The maximum number of entries to return. 0 means no limit. + Limit *InQueryLimit `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Skip the first entries of the data cursor. + Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` + + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. + Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` + + // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. + Stats *InQueryStats `form:"stats,omitempty" json:"stats,omitempty"` + + // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). + Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` + + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). + Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` +} + +// GetComplianceRulesetResponsiblesParams defines parameters for GetComplianceRulesetResponsibles. +type GetComplianceRulesetResponsiblesParams struct { + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` + + // Limit The maximum number of entries to return. 0 means no limit. + Limit *InQueryLimit `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Skip the first entries of the data cursor. + Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` + + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. + Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` + + // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. + Stats *InQueryStats `form:"stats,omitempty" json:"stats,omitempty"` + + // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). + Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` + + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). + Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` +} + // GetComplianceRulesetVariablesParams defines parameters for GetComplianceRulesetVariables. type GetComplianceRulesetVariablesParams struct { // Props A list of properties to include in each data dictionnary. @@ -2231,6 +2311,42 @@ type PutComplianceRulesetVariableJSONBody struct { // PutComplianceRulesetVariableJSONBodyAction defines parameters for PutComplianceRulesetVariable. type PutComplianceRulesetVariableJSONBodyAction string +// DeleteComplianceRulesetsPublicationsJSONBody defines parameters for DeleteComplianceRulesetsPublications. +type DeleteComplianceRulesetsPublicationsJSONBody struct { + // GroupId Group id or role + GroupId interface{} `json:"group_id"` + + // RulesetId Ruleset id or name + RulesetId interface{} `json:"ruleset_id"` +} + +// PostComplianceRulesetsPublicationsJSONBody defines parameters for PostComplianceRulesetsPublications. +type PostComplianceRulesetsPublicationsJSONBody struct { + // GroupId Group id or role + GroupId interface{} `json:"group_id"` + + // RulesetId Ruleset id or name + RulesetId interface{} `json:"ruleset_id"` +} + +// DeleteComplianceRulesetsResponsiblesJSONBody defines parameters for DeleteComplianceRulesetsResponsibles. +type DeleteComplianceRulesetsResponsiblesJSONBody struct { + // GroupId Group id or role + GroupId interface{} `json:"group_id"` + + // RulesetId Ruleset id or name + RulesetId interface{} `json:"ruleset_id"` +} + +// PostComplianceRulesetsResponsiblesJSONBody defines parameters for PostComplianceRulesetsResponsibles. +type PostComplianceRulesetsResponsiblesJSONBody struct { + // GroupId Group id or role + GroupId interface{} `json:"group_id"` + + // RulesetId Ruleset id or name + RulesetId interface{} `json:"ruleset_id"` +} + // PostComplianceRulesetsVariablesJSONBody defines parameters for PostComplianceRulesetsVariables. type PostComplianceRulesetsVariablesJSONBody struct { RulesetId *int `json:"ruleset_id,omitempty"` @@ -5731,6 +5847,18 @@ type PostComplianceRulesetVariableJSONRequestBody PostComplianceRulesetVariableJ // PutComplianceRulesetVariableJSONRequestBody defines body for PutComplianceRulesetVariable for application/json ContentType. type PutComplianceRulesetVariableJSONRequestBody PutComplianceRulesetVariableJSONBody +// DeleteComplianceRulesetsPublicationsJSONRequestBody defines body for DeleteComplianceRulesetsPublications for application/json ContentType. +type DeleteComplianceRulesetsPublicationsJSONRequestBody DeleteComplianceRulesetsPublicationsJSONBody + +// PostComplianceRulesetsPublicationsJSONRequestBody defines body for PostComplianceRulesetsPublications for application/json ContentType. +type PostComplianceRulesetsPublicationsJSONRequestBody PostComplianceRulesetsPublicationsJSONBody + +// DeleteComplianceRulesetsResponsiblesJSONRequestBody defines body for DeleteComplianceRulesetsResponsibles for application/json ContentType. +type DeleteComplianceRulesetsResponsiblesJSONRequestBody DeleteComplianceRulesetsResponsiblesJSONBody + +// PostComplianceRulesetsResponsiblesJSONRequestBody defines body for PostComplianceRulesetsResponsibles for application/json ContentType. +type PostComplianceRulesetsResponsiblesJSONRequestBody PostComplianceRulesetsResponsiblesJSONBody + // PostComplianceRulesetsVariablesJSONRequestBody defines body for PostComplianceRulesetsVariables for application/json ContentType. type PostComplianceRulesetsVariablesJSONRequestBody PostComplianceRulesetsVariablesJSONBody diff --git a/server/handlers/compliance_teams.go b/server/handlers/compliance_teams.go new file mode 100644 index 00000000..4db3241e --- /dev/null +++ b/server/handlers/compliance_teams.go @@ -0,0 +1,189 @@ +package serverhandlers + +import ( + "context" + "fmt" + "net/http" + + "github.com/labstack/echo/v4" + + "github.com/opensvc/oc3/cdb" + "github.com/opensvc/oc3/server" +) + +// compTeamList answers with the publication or responsible groups of a +// compliance object; a non-manager sees only their own among them. +func (a *Api) compTeamList(c echo.Context, name string, k cdb.CompKind, objID int64, gtype string, params listEndpointParams) error { + return a.handleList(c, name, "auth_group", params, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetCompTeamGroups(ctx, k, objID, gtype, p) + }) +} + +// compTeamChange attaches or detaches a publication or responsible group of a +// compliance object, as attach_group_to_ruleset() and detach_group_from_ruleset() +// and their moduleset counterparts: by a CompManager responsible for the object. +// A non-manager may attach only one of their groups; Everybody may not be made +// responsible, nor be given the publication of a contextual ruleset. +func (a *Api) compTeamChange(c echo.Context, name string, k cdb.CompKind, objID int64, gtype, groupRef string, attach bool) error { + ctx := c.Request().Context() + if err := checkCompManager(c); err != nil { + return httpProblem(c, err) + } + if ok, err := a.ODB.CompObjectResponsible(ctx, k, objID, UserGroupsFromContext(c), IsManager(c)); err != nil { + return httpProblem(c, compDesignerError(c, name, err)) + } else if !ok { + return httpProblem(c, httpErrorf(http.StatusForbidden, "%s not found or not owned by you", k.Name)) + } + group, found, err := a.ODB.AuthGroupByIDOrRole(ctx, groupRef) + if err != nil { + return httpProblem(c, compDesignerError(c, name, err)) + } + if !found { + return httpProblem(c, httpErrorf(http.StatusNotFound, "group %s not found", groupRef)) + } + objName, err := a.ODB.CompObjectName(ctx, k, objID) + if err != nil { + return httpProblem(c, compDesignerError(c, name, err)) + } + dict := map[string]any{"gtype": gtype, "role": group.Role} + nameKey := "rset_name" + if k.Name == "moduleset" { + nameKey = "modset_name" + } + dict[nameKey] = objName + if !attach { + if err := a.ODB.DetachCompTeam(ctx, k, objID, gtype, group.ID); err != nil { + return httpProblem(c, compDesignerError(c, name, err)) + } + a.compLog(c, "compliance."+k.Name+".detach", "detach %(gtype)s group %(role)s from "+k.Name+" %("+nameKey+")s", dict, "", "") + a.afterRulesetChange(c, false) + return compInfo(c, "group detached") + } + if group.Role == "Everybody" { + if gtype == "responsible" { + return httpProblem(c, httpErrorf(http.StatusBadRequest, "Giving responsibility of a %s to Everybody is not allowed", k.Name)) + } + if k.Name == "ruleset" { + if contextual, err := a.rulesetIsContextual(ctx, objID); err != nil { + return httpProblem(c, compDesignerError(c, name, err)) + } else if contextual { + return httpProblem(c, httpErrorf(http.StatusBadRequest, "Publishing a contextual ruleset to Everybody is not allowed")) + } + } + } + if !IsManager(c) && !HasGroup(c, group.Role) { + return httpProblem(c, httpErrorf(http.StatusForbidden, "you can't attach a group you are not a member of")) + } + if attached, err := a.ODB.CompTeamAttached(ctx, k, objID, gtype, group.ID); err != nil { + return httpProblem(c, compDesignerError(c, name, err)) + } else if attached { + return compInfo(c, "%s group already attached", gtype) + } + if err := a.ODB.AttachCompTeam(ctx, k, objID, gtype, group.ID); err != nil { + return httpProblem(c, compDesignerError(c, name, err)) + } + a.compLog(c, "compliance."+k.Name+".change", "attach %(gtype)s group %(role)s to "+k.Name+" %("+nameKey+")s", dict, "", "") + a.afterRulesetChange(c, false) + return compInfo(c, "group attached") +} + +func (a *Api) rulesetIsContextual(ctx context.Context, id int64) (bool, error) { + return a.ODB.RulesetIsContextual(ctx, id) +} + +// compTeamBody reads the object and the group a bulk form names in its body. +func compTeamBody(c echo.Context, objKey string) (string, string, error) { + entry, err := oneEntry(c) + if err != nil { + return "", "", err + } + obj, ok := entry[objKey] + if !ok { + return "", "", httpErrorf(http.StatusBadRequest, "The '%s' key is mandatory", objKey) + } + group, ok := entry["group_id"] + if !ok { + return "", "", httpErrorf(http.StatusBadRequest, "The 'group_id' key is mandatory") + } + return fmt.Sprint(obj), fmt.Sprint(group), nil +} + +func listParams(props *server.InQueryProps, limit *server.InQueryLimit, offset *server.InQueryOffset, meta *server.InQueryMeta, stats *server.InQueryStats, orderby *server.InQueryOrderby, groupby *server.InQueryGroupby, filter *server.InQueryFilter) listEndpointParams { + return listEndpointParams{props: props, limit: limit, offset: offset, meta: meta, stats: stats, orderby: orderby, groupby: groupby, filter: filter} +} + +// GetComplianceRulesetPublications handles GET /compliance/rulesets/{rset_id}/publications. +func (a *Api) GetComplianceRulesetPublications(c echo.Context, rsetId string, params server.GetComplianceRulesetPublicationsParams) error { + id, err := a.resolveRuleset(c.Request().Context(), rsetId) + if err != nil { + return httpProblem(c, err) + } + return a.compTeamList(c, "GetComplianceRulesetPublications", cdb.CompRulesetKind, id, "publication", + listParams(params.Props, params.Limit, params.Offset, params.Meta, params.Stats, params.Orderby, params.Groupby, params.Filter)) +} + +// GetComplianceRulesetResponsibles handles GET /compliance/rulesets/{rset_id}/responsibles. +func (a *Api) GetComplianceRulesetResponsibles(c echo.Context, rsetId string, params server.GetComplianceRulesetResponsiblesParams) error { + id, err := a.resolveRuleset(c.Request().Context(), rsetId) + if err != nil { + return httpProblem(c, err) + } + return a.compTeamList(c, "GetComplianceRulesetResponsibles", cdb.CompRulesetKind, id, "responsible", + listParams(params.Props, params.Limit, params.Offset, params.Meta, params.Stats, params.Orderby, params.Groupby, params.Filter)) +} + +func (a *Api) rulesetTeamChange(c echo.Context, name, rsetRef, groupRef, gtype string, attach bool) error { + id, err := a.resolveRuleset(c.Request().Context(), rsetRef) + if err != nil { + return httpProblem(c, err) + } + return a.compTeamChange(c, name, cdb.CompRulesetKind, id, gtype, groupRef, attach) +} + +// PostComplianceRulesetPublication handles POST /compliance/rulesets/{rset_id}/publications/{group_id}. +func (a *Api) PostComplianceRulesetPublication(c echo.Context, rsetId, groupId string) error { + return a.rulesetTeamChange(c, "PostComplianceRulesetPublication", rsetId, groupId, "publication", true) +} + +// DeleteComplianceRulesetPublication handles DELETE /compliance/rulesets/{rset_id}/publications/{group_id}. +func (a *Api) DeleteComplianceRulesetPublication(c echo.Context, rsetId, groupId string) error { + return a.rulesetTeamChange(c, "DeleteComplianceRulesetPublication", rsetId, groupId, "publication", false) +} + +// PostComplianceRulesetResponsible handles POST /compliance/rulesets/{rset_id}/responsibles/{group_id}. +func (a *Api) PostComplianceRulesetResponsible(c echo.Context, rsetId, groupId string) error { + return a.rulesetTeamChange(c, "PostComplianceRulesetResponsible", rsetId, groupId, "responsible", true) +} + +// DeleteComplianceRulesetResponsible handles DELETE /compliance/rulesets/{rset_id}/responsibles/{group_id}. +func (a *Api) DeleteComplianceRulesetResponsible(c echo.Context, rsetId, groupId string) error { + return a.rulesetTeamChange(c, "DeleteComplianceRulesetResponsible", rsetId, groupId, "responsible", false) +} + +func (a *Api) rulesetsTeamBulk(c echo.Context, name, gtype string, attach bool) error { + rset, group, err := compTeamBody(c, "ruleset_id") + if err != nil { + return httpProblem(c, err) + } + return a.rulesetTeamChange(c, name, rset, group, gtype, attach) +} + +// PostComplianceRulesetsPublications handles POST /compliance/rulesets_publications. +func (a *Api) PostComplianceRulesetsPublications(c echo.Context) error { + return a.rulesetsTeamBulk(c, "PostComplianceRulesetsPublications", "publication", true) +} + +// DeleteComplianceRulesetsPublications handles DELETE /compliance/rulesets_publications. +func (a *Api) DeleteComplianceRulesetsPublications(c echo.Context) error { + return a.rulesetsTeamBulk(c, "DeleteComplianceRulesetsPublications", "publication", false) +} + +// PostComplianceRulesetsResponsibles handles POST /compliance/rulesets_responsibles. +func (a *Api) PostComplianceRulesetsResponsibles(c echo.Context) error { + return a.rulesetsTeamBulk(c, "PostComplianceRulesetsResponsibles", "responsible", true) +} + +// DeleteComplianceRulesetsResponsibles handles DELETE /compliance/rulesets_responsibles. +func (a *Api) DeleteComplianceRulesetsResponsibles(c echo.Context) error { + return a.rulesetsTeamBulk(c, "DeleteComplianceRulesetsResponsibles", "responsible", false) +} From 75a1bd2d40c21e0bee5d6641f8bb97de2bc305ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Mon, 28 Sep 2026 13:43:41 +0200 Subject: [PATCH 41/61] Store the slave flag of compliance service attachments as T or F comp_rulesets_services.slave and comp_modulesets_services.slave are varchar(1) columns the historical collector fills with "T" or "F", as its web2py boolean fields do. oc3 passed a Go boolean, stored as "1" or "0", which the historical collector reads as false; and compared the column with a boolean, which MySQL casts "T" and "F" to 0 alike, so that the non-encapsulated queries also matched encapsulated attachments. Attachments are now stored "T" or "F"; queries read "T" and "1" as true, anything else as false, so that rows stored earlier keep their meaning. --- cdb/db_compliance.go | 56 ++++++++++++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/cdb/db_compliance.go b/cdb/db_compliance.go index 214d2dd2..646524c6 100644 --- a/cdb/db_compliance.go +++ b/cdb/db_compliance.go @@ -333,8 +333,8 @@ func (oDb *DB) CompNodeModulesets(ctx context.Context, nodeID string) (moduleset // CompServiceModulesets returns the modset ids attached to a service func (oDb *DB) CompServiceModulesets(ctx context.Context, svcID string, slave bool) (modulesets []int, err error) { - const query = `SELECT modset_id FROM comp_modulesets_services WHERE svc_id = ? AND slave = ?` - rows, err := oDb.DB.QueryContext(ctx, query, svcID, slave) + query := `SELECT modset_id FROM comp_modulesets_services WHERE svc_id = ? AND ` + compSlaveCond("slave", slave) + rows, err := oDb.DB.QueryContext(ctx, query, svcID) if err != nil { return nil, err } @@ -421,8 +421,8 @@ func (oDb *DB) CompServiceCandidateModulesets(ctx context.Context, svcID string, // CompServiceRulesets returns the ruleset ids attached to a service func (oDb *DB) CompServiceRulesets(ctx context.Context, svcID string, slave bool) (rulesets []int, err error) { - const query = `SELECT ruleset_id FROM comp_rulesets_services WHERE svc_id = ? AND slave = ?` - rows, err := oDb.DB.QueryContext(ctx, query, svcID, slave) + query := `SELECT ruleset_id FROM comp_rulesets_services WHERE svc_id = ? AND ` + compSlaveCond("slave", slave) + rows, err := oDb.DB.QueryContext(ctx, query, svcID) if err != nil { return nil, err } @@ -723,10 +723,10 @@ func (oDb *DB) CompServiceAttachedModulesets(ctx context.Context, svcID string, SELECT comp_moduleset.id, comp_moduleset.modset_name, comp_moduleset.modset_author, comp_moduleset.modset_updated FROM comp_moduleset JOIN comp_modulesets_services ON comp_moduleset.id = comp_modulesets_services.modset_id - WHERE comp_modulesets_services.svc_id = ? AND comp_modulesets_services.slave = ? + WHERE comp_modulesets_services.svc_id = ? AND ` + compSlaveCond("comp_modulesets_services.slave", slave) + ` ` - args := []any{svcID, slave} + args := []any{svcID} filter, filterArgs, err := QFilter(ctx, QFilterInput{ SvcField: "comp_modulesets_services.svc_id", IsManager: isManager, @@ -774,10 +774,10 @@ func (oDb *DB) CompServiceAttachedRulesets(ctx context.Context, svcID string, sl SELECT comp_rulesets.id, comp_rulesets.ruleset_name, comp_rulesets.ruleset_public, comp_rulesets.ruleset_type FROM comp_rulesets JOIN comp_rulesets_services ON comp_rulesets.id = comp_rulesets_services.ruleset_id - WHERE comp_rulesets_services.svc_id = ? AND comp_rulesets_services.slave = ? + WHERE comp_rulesets_services.svc_id = ? AND ` + compSlaveCond("comp_rulesets_services.slave", slave) + ` ` - args := []any{svcID, slave} + args := []any{svcID} filter, filterArgs, err := QFilter(ctx, QFilterInput{ SvcField: "comp_rulesets_services.svc_id", IsManager: isManager, @@ -974,10 +974,10 @@ func (oDb *DB) CompModulesetAttachNode(ctx context.Context, nodeID, modulesetID // CompModulesetSvcAttached checks if a moduleset is already attached to a service. func (oDb *DB) CompModulesetSvcAttached(ctx context.Context, svcID, modulesetID string, slave bool) (bool, error) { - const query = "SELECT EXISTS(SELECT 1 FROM comp_modulesets_services WHERE svc_id = ? AND modset_id = ? AND slave = ?)" + query := "SELECT EXISTS(SELECT 1 FROM comp_modulesets_services WHERE svc_id = ? AND modset_id = ? AND " + compSlaveCond("slave", slave) + ")" var exists bool - err := oDb.DB.QueryRowContext(ctx, query, svcID, modulesetID, slave).Scan(&exists) + err := oDb.DB.QueryRowContext(ctx, query, svcID, modulesetID).Scan(&exists) if err != nil { return false, fmt.Errorf("compModulesetSvcAttached: %w", err) } @@ -1019,7 +1019,7 @@ func (oDb *DB) CompModulesetSvcAttachable(ctx context.Context, svcID, modulesetI func (oDb *DB) CompModulesetAttachService(ctx context.Context, svcID, modulesetID string, slave bool) (int64, error) { const query = "INSERT INTO comp_modulesets_services (svc_id, modset_id, slave) VALUES (?, ?, ?)" - result, err := oDb.ExecContext(ctx, query, svcID, modulesetID, slave) + result, err := oDb.ExecContext(ctx, query, svcID, modulesetID, compSlaveFlag(slave)) if err != nil { return 0, fmt.Errorf("compModulesetAttachService: %w", err) } @@ -1035,9 +1035,9 @@ func (oDb *DB) CompModulesetAttachService(ctx context.Context, svcID, modulesetI // CompModulesetDetachService detaches a moduleset from a service. func (oDb *DB) CompModulesetDetachService(ctx context.Context, svcID, modulesetID string, slave bool) (int64, error) { - const query = "DELETE FROM comp_modulesets_services WHERE svc_id = ? AND modset_id = ? AND slave = ?" + query := "DELETE FROM comp_modulesets_services WHERE svc_id = ? AND modset_id = ? AND " + compSlaveCond("slave", slave) - result, err := oDb.ExecContext(ctx, query, svcID, modulesetID, slave) + result, err := oDb.ExecContext(ctx, query, svcID, modulesetID) if err != nil { return 0, fmt.Errorf("compModulesetDetachService: %w", err) } @@ -1057,10 +1057,10 @@ func (oDb *DB) CompModulesetDetachService(ctx context.Context, svcID, modulesetI // CompRulesetSvcAttached checks if a ruleset is already attached to a service. func (oDb *DB) CompRulesetSvcAttached(ctx context.Context, svcID, rulesetID string, slave bool) (bool, error) { - const query = "SELECT EXISTS(SELECT 1 FROM comp_rulesets_services WHERE svc_id = ? AND ruleset_id = ? AND slave = ?)" + query := "SELECT EXISTS(SELECT 1 FROM comp_rulesets_services WHERE svc_id = ? AND ruleset_id = ? AND " + compSlaveCond("slave", slave) + ")" var exists bool - err := oDb.DB.QueryRowContext(ctx, query, svcID, rulesetID, slave).Scan(&exists) + err := oDb.DB.QueryRowContext(ctx, query, svcID, rulesetID).Scan(&exists) if err != nil { return false, fmt.Errorf("compRulesetSvcAttached: %w", err) } @@ -1104,7 +1104,7 @@ func (oDb *DB) CompRulesetSvcAttachable(ctx context.Context, svcID, rulesetID st func (oDb *DB) CompRulesetAttachService(ctx context.Context, svcID, rulesetID string, slave bool) (int64, error) { const query = "INSERT INTO comp_rulesets_services (svc_id, ruleset_id, slave) VALUES (?, ?, ?)" - result, err := oDb.ExecContext(ctx, query, svcID, rulesetID, slave) + result, err := oDb.ExecContext(ctx, query, svcID, rulesetID, compSlaveFlag(slave)) if err != nil { return 0, fmt.Errorf("compRulesetAttachService: %w", err) } @@ -1120,9 +1120,9 @@ func (oDb *DB) CompRulesetAttachService(ctx context.Context, svcID, rulesetID st // CompRulesetDetachService detaches a ruleset from a service. func (oDb *DB) CompRulesetDetachService(ctx context.Context, svcID, rulesetID string, slave bool) (int64, error) { - const query = "DELETE FROM comp_rulesets_services WHERE svc_id = ? AND ruleset_id = ? AND slave = ?" + query := "DELETE FROM comp_rulesets_services WHERE svc_id = ? AND ruleset_id = ? AND " + compSlaveCond("slave", slave) - result, err := oDb.ExecContext(ctx, query, svcID, rulesetID, slave) + result, err := oDb.ExecContext(ctx, query, svcID, rulesetID) if err != nil { return 0, fmt.Errorf("compRulesetDetachService: %w", err) } @@ -1261,3 +1261,23 @@ func (oDb *DB) GetNodeComplianceStatus(ctx context.Context, nodeID string, p Lis return scanRowsToMaps(rows, p.Props, p.TypeHints) } + +// compSlaveFlag is the stored value of the slave flag of a service attachment: +// "T" or "F", as the historical collector's web2py boolean fields store it. +func compSlaveFlag(slave bool) string { + if slave { + return "T" + } + return "F" +} + +// compSlaveCond selects the service attachments of the given slave flag, stored +// "T" or "F" by the historical collector and, before this was fixed, 1 or 0 by +// oc3: comparing the varchar(1) column with a boolean would cast "T" and "F" to +// 0 alike. +func compSlaveCond(col string, slave bool) string { + if slave { + return col + " IN ('T', '1')" + } + return "(" + col + " IS NULL OR " + col + " NOT IN ('T', '1'))" +} From 264e663554fadf68f595884c5b3de798664941b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Mon, 28 Sep 2026 13:44:49 +0200 Subject: [PATCH 42/61] Add the compliance ruleset node and service attachment endpoints Port the ruleset attachment endpoints of the historical api_compliance: - GET /compliance/rulesets/{rset_id}/nodes and /services (slave for the encapsulated services), what a ruleset published to the caller is attached to, among the nodes and services the caller may see; - GET /compliance/rulesets/{rset_id}/candidate_nodes and /candidate_services, what it may be attached to: the nodes whose responsible team, the services whose app has a responsible group, among the ruleset's publication groups, not attached yet; - POST and DELETE /compliance/rulesets_nodes and /rulesets_services, the bulk forms naming the ruleset (ruleset_id or ruleset_name), the node or the service and the slave flag (encap accepted) in the body, handled as the existing /nodes/{node_id}/compliance/rulesets/{rset_id} and /services/{svc_id}/compliance/rulesets/{rset_id}. The list queries are written over the CompKind, which names the node and service attachment tables too, for the modulesets to use as well. --- cdb/db_compliance_attachments.go | 71 ++ cdb/db_compliance_teams.go | 11 +- server/api.yaml | 374 +++++++ server/codegen_server_gen.go | 1169 ++++++++++++++------- server/codegen_type_gen.go | 218 ++++ server/handlers/compliance_attachments.go | 170 +++ 6 files changed, 1636 insertions(+), 377 deletions(-) create mode 100644 cdb/db_compliance_attachments.go create mode 100644 server/handlers/compliance_attachments.go diff --git a/cdb/db_compliance_attachments.go b/cdb/db_compliance_attachments.go new file mode 100644 index 00000000..fd18ac12 --- /dev/null +++ b/cdb/db_compliance_attachments.go @@ -0,0 +1,71 @@ +package cdb + +import ( + "context" +) + +// compPublishedServicesCond restricts a svc_id column to the services the caller +// may see, as q_filter(svc_field=...): those whose app is published to one of the +// caller's groups; every service for a manager. +func compPublishedServicesCond(svcCol string, groups []string, isManager bool) (string, []any) { + if isManager { + return "1=1", nil + } + cond, args := rolesCond("ag", groups, false) + return svcCol + " IN (SELECT s.svc_id FROM services s" + + " JOIN apps a ON a.app = s.svc_app" + + " JOIN apps_publications ap ON ap.app_id = a.id" + + " JOIN auth_group ag ON ag.id = ap.group_id" + + " WHERE " + cond + ")", args +} + +// GetCompObjectNodes lists the nodes a ruleset or a moduleset is attached to, +// or with candidates the nodes it may be attached to: those whose responsible +// team is one of its publication groups, not attached yet. Both are restricted +// to the nodes the caller may see. +func (oDb *DB) GetCompObjectNodes(ctx context.Context, k CompKind, objID int64, candidates bool, p ListParams) ([]map[string]any, error) { + attached := "SELECT node_id FROM " + k.NodesTable + " WHERE " + k.FK + " = ?" + var conds []string + var args []any + if candidates { + conds = append(conds, + "nodes.team_responsible IN (SELECT ag.role FROM "+k.TeamPrefix+"publication tp"+ + " JOIN auth_group ag ON ag.id = tp.group_id WHERE tp."+k.FK+" = ?)", + "nodes.node_id NOT IN ("+attached+")") + args = append(args, objID, objID) + } else { + conds = append(conds, "nodes.node_id IN ("+attached+")") + args = append(args, objID) + } + cond, condArgs := compPublishedNodesCond("nodes.node_id", p.Groups, p.IsManager) + conds = append(conds, cond) + args = append(args, condArgs...) + return oDb.listQuery(ctx, "getCompObjectNodes", "nodes", conds, args, "nodes.nodename", p) +} + +// GetCompObjectServices lists the services a ruleset or a moduleset is attached +// to, as the service itself or with slave as its encapsulated service; or with +// candidates the services it may be attached to: those whose app has one of its +// publication groups among its responsibles, not attached yet. Both are +// restricted to the services the caller may see. +func (oDb *DB) GetCompObjectServices(ctx context.Context, k CompKind, objID int64, slave, candidates bool, p ListParams) ([]map[string]any, error) { + attached := "SELECT svc_id FROM " + k.ServicesTable + " WHERE " + k.FK + " = ? AND " + compSlaveCond("slave", slave) + var conds []string + var args []any + if candidates { + conds = append(conds, + "services.svc_app IN (SELECT a.app FROM apps a"+ + " JOIN apps_responsibles ar ON ar.app_id = a.id"+ + " JOIN "+k.TeamPrefix+"publication tp ON tp.group_id = ar.group_id"+ + " WHERE tp."+k.FK+" = ?)", + "services.svc_id NOT IN ("+attached+")") + args = append(args, objID, objID) + } else { + conds = append(conds, "services.svc_id IN ("+attached+")") + args = append(args, objID) + } + cond, condArgs := compPublishedServicesCond("services.svc_id", p.Groups, p.IsManager) + conds = append(conds, cond) + args = append(args, condArgs...) + return oDb.listQuery(ctx, "getCompObjectServices", "services", conds, args, "services.svcname", p) +} diff --git a/cdb/db_compliance_teams.go b/cdb/db_compliance_teams.go index f58912cb..98f3c865 100644 --- a/cdb/db_compliance_teams.go +++ b/cdb/db_compliance_teams.go @@ -15,11 +15,18 @@ type CompKind struct { // TeamPrefix is the prefix of the group tables, completed by "publication" // or "responsible"; FK is their column naming the object. TeamPrefix, FK string + // NodesTable and ServicesTable hold the attachments to nodes and services, + // by FK and node_id, or FK, svc_id and slave. + NodesTable, ServicesTable string } var ( - CompRulesetKind = CompKind{Name: "ruleset", Table: "comp_rulesets", NameCol: "ruleset_name", TeamPrefix: "comp_ruleset_team_", FK: "ruleset_id"} - CompModulesetKind = CompKind{Name: "moduleset", Table: "comp_moduleset", NameCol: "modset_name", TeamPrefix: "comp_moduleset_team_", FK: "modset_id"} + CompRulesetKind = CompKind{Name: "ruleset", Table: "comp_rulesets", NameCol: "ruleset_name", + TeamPrefix: "comp_ruleset_team_", FK: "ruleset_id", + NodesTable: "comp_rulesets_nodes", ServicesTable: "comp_rulesets_services"} + CompModulesetKind = CompKind{Name: "moduleset", Table: "comp_moduleset", NameCol: "modset_name", + TeamPrefix: "comp_moduleset_team_", FK: "modset_id", + NodesTable: "comp_node_moduleset", ServicesTable: "comp_modulesets_services"} ) // CompTeamTypes are the two kinds of groups of a compliance object. diff --git a/server/api.yaml b/server/api.yaml index 7103eeb6..75810919 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -10307,6 +10307,380 @@ paths: - basicAuth: [ ] - bearerAuth: [ ] + /compliance/rulesets/{rset_id}/nodes: + get: + operationId: GetComplianceRulesetNodes + description: | + List the nodes a ruleset published to the user is attached to, among the nodes + the user can see. + parameters: + - in: path + name: rset_id + required: true + description: Ruleset id or name + schema: + type: string + - $ref: '#/components/parameters/inQueryProps' + - $ref: '#/components/parameters/inQueryLimit' + - $ref: '#/components/parameters/inQueryOffset' + - $ref: '#/components/parameters/inQueryMeta' + - $ref: '#/components/parameters/inQueryStats' + - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryFilter' + - $ref: '#/components/parameters/inQueryGroupby' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/NodeListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /compliance/rulesets/{rset_id}/candidate_nodes: + get: + operationId: GetComplianceRulesetCandidateNodes + description: | + List the nodes a ruleset published to the user may be attached to: the nodes + the user can see whose responsible team is one of the ruleset's publication + groups, not attached yet. + parameters: + - in: path + name: rset_id + required: true + description: Ruleset id or name + schema: + type: string + - $ref: '#/components/parameters/inQueryProps' + - $ref: '#/components/parameters/inQueryLimit' + - $ref: '#/components/parameters/inQueryOffset' + - $ref: '#/components/parameters/inQueryMeta' + - $ref: '#/components/parameters/inQueryStats' + - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryFilter' + - $ref: '#/components/parameters/inQueryGroupby' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/NodeListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /compliance/rulesets/{rset_id}/services: + get: + operationId: GetComplianceRulesetServices + description: | + List the services a ruleset published to the user is attached to, as the + service itself or, with slave, as its encapsulated service, among the services + the user can see. + parameters: + - in: path + name: rset_id + required: true + description: Ruleset id or name + schema: + type: string + - in: query + name: slave + description: With true, the encapsulated services + schema: + type: boolean + - $ref: '#/components/parameters/inQueryProps' + - $ref: '#/components/parameters/inQueryLimit' + - $ref: '#/components/parameters/inQueryOffset' + - $ref: '#/components/parameters/inQueryMeta' + - $ref: '#/components/parameters/inQueryStats' + - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryFilter' + - $ref: '#/components/parameters/inQueryGroupby' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ServiceListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /compliance/rulesets/{rset_id}/candidate_services: + get: + operationId: GetComplianceRulesetCandidateServices + description: | + List the services a ruleset published to the user may be attached to, as the + service or with slave as its encapsulated service: the services the user can see + whose app has one of the ruleset's publication groups among its responsibles, + not attached yet. + parameters: + - in: path + name: rset_id + required: true + description: Ruleset id or name + schema: + type: string + - in: query + name: slave + description: With true, the encapsulated services + schema: + type: boolean + - $ref: '#/components/parameters/inQueryProps' + - $ref: '#/components/parameters/inQueryLimit' + - $ref: '#/components/parameters/inQueryOffset' + - $ref: '#/components/parameters/inQueryMeta' + - $ref: '#/components/parameters/inQueryStats' + - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryFilter' + - $ref: '#/components/parameters/inQueryGroupby' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ServiceListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /compliance/rulesets_nodes: + post: + operationId: PostComplianceRulesetsNodes + description: | + Attach a ruleset to a node, as POST /nodes/{node_id}/compliance/rulesets/{rset_id}. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [node_id] + properties: + node_id: + type: string + ruleset_id: + description: Ruleset id or name + ruleset_name: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 409: + $ref: '#/components/responses/409' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + delete: + operationId: DeleteComplianceRulesetsNodes + description: | + Detach a ruleset from a node, as DELETE /nodes/{node_id}/compliance/rulesets/{rset_id}. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [node_id] + properties: + node_id: + type: string + ruleset_id: + description: Ruleset id or name + ruleset_name: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /compliance/rulesets_services: + post: + operationId: PostComplianceRulesetsServices + description: | + Attach a ruleset to a service, as POST /services/{svc_id}/compliance/rulesets/{rset_id}. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [svc_id] + properties: + svc_id: + type: string + ruleset_id: + description: Ruleset id or name + ruleset_name: + type: string + slave: + description: A boolean; true for the encapsulated service. encap is accepted as well. + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 409: + $ref: '#/components/responses/409' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + delete: + operationId: DeleteComplianceRulesetsServices + description: | + Detach a ruleset from a service, as DELETE /services/{svc_id}/compliance/rulesets/{rset_id}. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [svc_id] + properties: + svc_id: + type: string + ruleset_id: + description: Ruleset id or name + ruleset_name: + type: string + slave: + description: A boolean; true for the encapsulated service. encap is accepted as well. + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + components: responses: diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index 70dff46e..bb16f915 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -153,12 +153,21 @@ type ServerInterface interface { // (GET /compliance/rulesets/{rset_id}/am_i_responsible) GetComplianceRulesetAmIResponsible(ctx echo.Context, rsetId string) error + // (GET /compliance/rulesets/{rset_id}/candidate_nodes) + GetComplianceRulesetCandidateNodes(ctx echo.Context, rsetId string, params GetComplianceRulesetCandidateNodesParams) error + + // (GET /compliance/rulesets/{rset_id}/candidate_services) + GetComplianceRulesetCandidateServices(ctx echo.Context, rsetId string, params GetComplianceRulesetCandidateServicesParams) error + // (DELETE /compliance/rulesets/{rset_id}/filtersets/{fset_id}) DeleteComplianceRulesetFilterset(ctx echo.Context, rsetId string, fsetId string) error // (POST /compliance/rulesets/{rset_id}/filtersets/{fset_id}) PostComplianceRulesetFilterset(ctx echo.Context, rsetId string, fsetId string) error + // (GET /compliance/rulesets/{rset_id}/nodes) + GetComplianceRulesetNodes(ctx echo.Context, rsetId string, params GetComplianceRulesetNodesParams) error + // (GET /compliance/rulesets/{rset_id}/publications) GetComplianceRulesetPublications(ctx echo.Context, rsetId string, params GetComplianceRulesetPublicationsParams) error @@ -183,6 +192,9 @@ type ServerInterface interface { // (POST /compliance/rulesets/{rset_id}/rulesets/{child_rset_id}) PostComplianceRulesetRuleset(ctx echo.Context, rsetId string, childRsetId string) error + // (GET /compliance/rulesets/{rset_id}/services) + GetComplianceRulesetServices(ctx echo.Context, rsetId string, params GetComplianceRulesetServicesParams) error + // (GET /compliance/rulesets/{rset_id}/usage) GetComplianceRulesetUsage(ctx echo.Context, rsetId string) error @@ -204,6 +216,12 @@ type ServerInterface interface { // (PUT /compliance/rulesets/{rset_id}/variables/{var_id}) PutComplianceRulesetVariable(ctx echo.Context, rsetId string, varId string) error + // (DELETE /compliance/rulesets_nodes) + DeleteComplianceRulesetsNodes(ctx echo.Context) error + + // (POST /compliance/rulesets_nodes) + PostComplianceRulesetsNodes(ctx echo.Context) error + // (DELETE /compliance/rulesets_publications) DeleteComplianceRulesetsPublications(ctx echo.Context) error @@ -216,6 +234,12 @@ type ServerInterface interface { // (POST /compliance/rulesets_responsibles) PostComplianceRulesetsResponsibles(ctx echo.Context) error + // (DELETE /compliance/rulesets_services) + DeleteComplianceRulesetsServices(ctx echo.Context) error + + // (POST /compliance/rulesets_services) + PostComplianceRulesetsServices(ctx echo.Context) error + // (POST /compliance/rulesets_variables) PostComplianceRulesetsVariables(ctx echo.Context) error @@ -2332,6 +2356,169 @@ func (w *ServerInterfaceWrapper) GetComplianceRulesetAmIResponsible(ctx echo.Con return err } +// GetComplianceRulesetCandidateNodes converts echo context to params. +func (w *ServerInterfaceWrapper) GetComplianceRulesetCandidateNodes(ctx echo.Context) error { + var err error + // ------------- Path parameter "rset_id" ------------- + var rsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "rset_id", ctx.Param("rset_id"), &rsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter rset_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetComplianceRulesetCandidateNodesParams + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // ------------- Optional query parameter "limit" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) + } + + // ------------- Optional query parameter "offset" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) + } + + // ------------- Optional query parameter "meta" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) + } + + // ------------- Optional query parameter "stats" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) + } + + // ------------- Optional query parameter "orderby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) + } + + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + + // ------------- Optional query parameter "groupby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetComplianceRulesetCandidateNodes(ctx, rsetId, params) + return err +} + +// GetComplianceRulesetCandidateServices converts echo context to params. +func (w *ServerInterfaceWrapper) GetComplianceRulesetCandidateServices(ctx echo.Context) error { + var err error + // ------------- Path parameter "rset_id" ------------- + var rsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "rset_id", ctx.Param("rset_id"), &rsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter rset_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetComplianceRulesetCandidateServicesParams + // ------------- Optional query parameter "slave" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "slave", ctx.QueryParams(), ¶ms.Slave, runtime.BindQueryParameterOptions{Type: "boolean", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter slave: %s", err)) + } + + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // ------------- Optional query parameter "limit" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) + } + + // ------------- Optional query parameter "offset" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) + } + + // ------------- Optional query parameter "meta" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) + } + + // ------------- Optional query parameter "stats" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) + } + + // ------------- Optional query parameter "orderby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) + } + + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + + // ------------- Optional query parameter "groupby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetComplianceRulesetCandidateServices(ctx, rsetId, params) + return err +} + // DeleteComplianceRulesetFilterset converts echo context to params. func (w *ServerInterfaceWrapper) DeleteComplianceRulesetFilterset(ctx echo.Context) error { var err error @@ -2388,6 +2575,84 @@ func (w *ServerInterfaceWrapper) PostComplianceRulesetFilterset(ctx echo.Context return err } +// GetComplianceRulesetNodes converts echo context to params. +func (w *ServerInterfaceWrapper) GetComplianceRulesetNodes(ctx echo.Context) error { + var err error + // ------------- Path parameter "rset_id" ------------- + var rsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "rset_id", ctx.Param("rset_id"), &rsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter rset_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetComplianceRulesetNodesParams + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // ------------- Optional query parameter "limit" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) + } + + // ------------- Optional query parameter "offset" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) + } + + // ------------- Optional query parameter "meta" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) + } + + // ------------- Optional query parameter "stats" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) + } + + // ------------- Optional query parameter "orderby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) + } + + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + + // ------------- Optional query parameter "groupby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetComplianceRulesetNodes(ctx, rsetId, params) + return err +} + // GetComplianceRulesetPublications converts echo context to params. func (w *ServerInterfaceWrapper) GetComplianceRulesetPublications(ctx echo.Context) error { var err error @@ -2712,6 +2977,91 @@ func (w *ServerInterfaceWrapper) PostComplianceRulesetRuleset(ctx echo.Context) return err } +// GetComplianceRulesetServices converts echo context to params. +func (w *ServerInterfaceWrapper) GetComplianceRulesetServices(ctx echo.Context) error { + var err error + // ------------- Path parameter "rset_id" ------------- + var rsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "rset_id", ctx.Param("rset_id"), &rsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter rset_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetComplianceRulesetServicesParams + // ------------- Optional query parameter "slave" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "slave", ctx.QueryParams(), ¶ms.Slave, runtime.BindQueryParameterOptions{Type: "boolean", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter slave: %s", err)) + } + + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // ------------- Optional query parameter "limit" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) + } + + // ------------- Optional query parameter "offset" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) + } + + // ------------- Optional query parameter "meta" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) + } + + // ------------- Optional query parameter "stats" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) + } + + // ------------- Optional query parameter "orderby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) + } + + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + + // ------------- Optional query parameter "groupby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetComplianceRulesetServices(ctx, rsetId, params) + return err +} + // GetComplianceRulesetUsage converts echo context to params. func (w *ServerInterfaceWrapper) GetComplianceRulesetUsage(ctx echo.Context) error { var err error @@ -2951,6 +3301,32 @@ func (w *ServerInterfaceWrapper) PutComplianceRulesetVariable(ctx echo.Context) return err } +// DeleteComplianceRulesetsNodes converts echo context to params. +func (w *ServerInterfaceWrapper) DeleteComplianceRulesetsNodes(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.DeleteComplianceRulesetsNodes(ctx) + return err +} + +// PostComplianceRulesetsNodes converts echo context to params. +func (w *ServerInterfaceWrapper) PostComplianceRulesetsNodes(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostComplianceRulesetsNodes(ctx) + return err +} + // DeleteComplianceRulesetsPublications converts echo context to params. func (w *ServerInterfaceWrapper) DeleteComplianceRulesetsPublications(ctx echo.Context) error { var err error @@ -3003,6 +3379,32 @@ func (w *ServerInterfaceWrapper) PostComplianceRulesetsResponsibles(ctx echo.Con return err } +// DeleteComplianceRulesetsServices converts echo context to params. +func (w *ServerInterfaceWrapper) DeleteComplianceRulesetsServices(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.DeleteComplianceRulesetsServices(ctx) + return err +} + +// PostComplianceRulesetsServices converts echo context to params. +func (w *ServerInterfaceWrapper) PostComplianceRulesetsServices(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostComplianceRulesetsServices(ctx) + return err +} + // PostComplianceRulesetsVariables converts echo context to params. func (w *ServerInterfaceWrapper) PostComplianceRulesetsVariables(ctx echo.Context) error { var err error @@ -11498,8 +11900,11 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.POST(options.BaseURL+"/compliance/rulesets/:rset_id", wrapper.PostComplianceRuleset, options.OperationMiddlewares["PostComplianceRuleset"]...) router.PUT(options.BaseURL+"/compliance/rulesets/:rset_id", wrapper.PutComplianceRuleset, options.OperationMiddlewares["PutComplianceRuleset"]...) router.GET(options.BaseURL+"/compliance/rulesets/:rset_id/am_i_responsible", wrapper.GetComplianceRulesetAmIResponsible, options.OperationMiddlewares["GetComplianceRulesetAmIResponsible"]...) + router.GET(options.BaseURL+"/compliance/rulesets/:rset_id/candidate_nodes", wrapper.GetComplianceRulesetCandidateNodes, options.OperationMiddlewares["GetComplianceRulesetCandidateNodes"]...) + router.GET(options.BaseURL+"/compliance/rulesets/:rset_id/candidate_services", wrapper.GetComplianceRulesetCandidateServices, options.OperationMiddlewares["GetComplianceRulesetCandidateServices"]...) router.DELETE(options.BaseURL+"/compliance/rulesets/:rset_id/filtersets/:fset_id", wrapper.DeleteComplianceRulesetFilterset, options.OperationMiddlewares["DeleteComplianceRulesetFilterset"]...) router.POST(options.BaseURL+"/compliance/rulesets/:rset_id/filtersets/:fset_id", wrapper.PostComplianceRulesetFilterset, options.OperationMiddlewares["PostComplianceRulesetFilterset"]...) + router.GET(options.BaseURL+"/compliance/rulesets/:rset_id/nodes", wrapper.GetComplianceRulesetNodes, options.OperationMiddlewares["GetComplianceRulesetNodes"]...) router.GET(options.BaseURL+"/compliance/rulesets/:rset_id/publications", wrapper.GetComplianceRulesetPublications, options.OperationMiddlewares["GetComplianceRulesetPublications"]...) router.DELETE(options.BaseURL+"/compliance/rulesets/:rset_id/publications/:group_id", wrapper.DeleteComplianceRulesetPublication, options.OperationMiddlewares["DeleteComplianceRulesetPublication"]...) router.POST(options.BaseURL+"/compliance/rulesets/:rset_id/publications/:group_id", wrapper.PostComplianceRulesetPublication, options.OperationMiddlewares["PostComplianceRulesetPublication"]...) @@ -11508,6 +11913,7 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.POST(options.BaseURL+"/compliance/rulesets/:rset_id/responsibles/:group_id", wrapper.PostComplianceRulesetResponsible, options.OperationMiddlewares["PostComplianceRulesetResponsible"]...) router.DELETE(options.BaseURL+"/compliance/rulesets/:rset_id/rulesets/:child_rset_id", wrapper.DeleteComplianceRulesetRuleset, options.OperationMiddlewares["DeleteComplianceRulesetRuleset"]...) router.POST(options.BaseURL+"/compliance/rulesets/:rset_id/rulesets/:child_rset_id", wrapper.PostComplianceRulesetRuleset, options.OperationMiddlewares["PostComplianceRulesetRuleset"]...) + router.GET(options.BaseURL+"/compliance/rulesets/:rset_id/services", wrapper.GetComplianceRulesetServices, options.OperationMiddlewares["GetComplianceRulesetServices"]...) router.GET(options.BaseURL+"/compliance/rulesets/:rset_id/usage", wrapper.GetComplianceRulesetUsage, options.OperationMiddlewares["GetComplianceRulesetUsage"]...) router.GET(options.BaseURL+"/compliance/rulesets/:rset_id/variables", wrapper.GetComplianceRulesetVariables, options.OperationMiddlewares["GetComplianceRulesetVariables"]...) router.POST(options.BaseURL+"/compliance/rulesets/:rset_id/variables", wrapper.PostComplianceRulesetVariables, options.OperationMiddlewares["PostComplianceRulesetVariables"]...) @@ -11515,10 +11921,14 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.GET(options.BaseURL+"/compliance/rulesets/:rset_id/variables/:var_id", wrapper.GetComplianceRulesetVariable, options.OperationMiddlewares["GetComplianceRulesetVariable"]...) router.POST(options.BaseURL+"/compliance/rulesets/:rset_id/variables/:var_id", wrapper.PostComplianceRulesetVariable, options.OperationMiddlewares["PostComplianceRulesetVariable"]...) router.PUT(options.BaseURL+"/compliance/rulesets/:rset_id/variables/:var_id", wrapper.PutComplianceRulesetVariable, options.OperationMiddlewares["PutComplianceRulesetVariable"]...) + router.DELETE(options.BaseURL+"/compliance/rulesets_nodes", wrapper.DeleteComplianceRulesetsNodes, options.OperationMiddlewares["DeleteComplianceRulesetsNodes"]...) + router.POST(options.BaseURL+"/compliance/rulesets_nodes", wrapper.PostComplianceRulesetsNodes, options.OperationMiddlewares["PostComplianceRulesetsNodes"]...) router.DELETE(options.BaseURL+"/compliance/rulesets_publications", wrapper.DeleteComplianceRulesetsPublications, options.OperationMiddlewares["DeleteComplianceRulesetsPublications"]...) router.POST(options.BaseURL+"/compliance/rulesets_publications", wrapper.PostComplianceRulesetsPublications, options.OperationMiddlewares["PostComplianceRulesetsPublications"]...) router.DELETE(options.BaseURL+"/compliance/rulesets_responsibles", wrapper.DeleteComplianceRulesetsResponsibles, options.OperationMiddlewares["DeleteComplianceRulesetsResponsibles"]...) router.POST(options.BaseURL+"/compliance/rulesets_responsibles", wrapper.PostComplianceRulesetsResponsibles, options.OperationMiddlewares["PostComplianceRulesetsResponsibles"]...) + router.DELETE(options.BaseURL+"/compliance/rulesets_services", wrapper.DeleteComplianceRulesetsServices, options.OperationMiddlewares["DeleteComplianceRulesetsServices"]...) + router.POST(options.BaseURL+"/compliance/rulesets_services", wrapper.PostComplianceRulesetsServices, options.OperationMiddlewares["PostComplianceRulesetsServices"]...) router.POST(options.BaseURL+"/compliance/rulesets_variables", wrapper.PostComplianceRulesetsVariables, options.OperationMiddlewares["PostComplianceRulesetsVariables"]...) router.DELETE(options.BaseURL+"/compliance/status", wrapper.DeleteComplianceStatus, options.OperationMiddlewares["DeleteComplianceStatus"]...) router.GET(options.BaseURL+"/compliance/status", wrapper.GetComplianceStatus, options.OperationMiddlewares["GetComplianceStatus"]...) @@ -11719,381 +12129,390 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "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", - "I5eV7CllNjofjc9Gf3768/8PAAD//w==", + "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", + "/w8AAP//", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index daabde25..360e16f6 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -2154,6 +2154,129 @@ type PutComplianceRulesetJSONBody struct { // PutComplianceRulesetJSONBodyAction defines parameters for PutComplianceRuleset. type PutComplianceRulesetJSONBodyAction string +// GetComplianceRulesetCandidateNodesParams defines parameters for GetComplianceRulesetCandidateNodes. +type GetComplianceRulesetCandidateNodesParams struct { + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` + + // Limit The maximum number of entries to return. 0 means no limit. + Limit *InQueryLimit `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Skip the first entries of the data cursor. + Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` + + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. + Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` + + // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. + Stats *InQueryStats `form:"stats,omitempty" json:"stats,omitempty"` + + // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). + Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` + + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). + Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` +} + +// GetComplianceRulesetCandidateServicesParams defines parameters for GetComplianceRulesetCandidateServices. +type GetComplianceRulesetCandidateServicesParams struct { + // Slave With true, the encapsulated services + Slave *bool `form:"slave,omitempty" json:"slave,omitempty"` + + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` + + // Limit The maximum number of entries to return. 0 means no limit. + Limit *InQueryLimit `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Skip the first entries of the data cursor. + Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` + + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. + Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` + + // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. + Stats *InQueryStats `form:"stats,omitempty" json:"stats,omitempty"` + + // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). + Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` + + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). + Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` +} + +// GetComplianceRulesetNodesParams defines parameters for GetComplianceRulesetNodes. +type GetComplianceRulesetNodesParams struct { + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` + + // Limit The maximum number of entries to return. 0 means no limit. + Limit *InQueryLimit `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Skip the first entries of the data cursor. + Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` + + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. + Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` + + // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. + Stats *InQueryStats `form:"stats,omitempty" json:"stats,omitempty"` + + // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). + Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` + + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). + Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` +} + // GetComplianceRulesetPublicationsParams defines parameters for GetComplianceRulesetPublications. type GetComplianceRulesetPublicationsParams struct { // Props A list of properties to include in each data dictionnary. @@ -2234,6 +2357,49 @@ type GetComplianceRulesetResponsiblesParams struct { Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` } +// GetComplianceRulesetServicesParams defines parameters for GetComplianceRulesetServices. +type GetComplianceRulesetServicesParams struct { + // Slave With true, the encapsulated services + Slave *bool `form:"slave,omitempty" json:"slave,omitempty"` + + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` + + // Limit The maximum number of entries to return. 0 means no limit. + Limit *InQueryLimit `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Skip the first entries of the data cursor. + Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` + + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. + Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` + + // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. + Stats *InQueryStats `form:"stats,omitempty" json:"stats,omitempty"` + + // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). + Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` + + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). + Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` +} + // GetComplianceRulesetVariablesParams defines parameters for GetComplianceRulesetVariables. type GetComplianceRulesetVariablesParams struct { // Props A list of properties to include in each data dictionnary. @@ -2311,6 +2477,24 @@ type PutComplianceRulesetVariableJSONBody struct { // PutComplianceRulesetVariableJSONBodyAction defines parameters for PutComplianceRulesetVariable. type PutComplianceRulesetVariableJSONBodyAction string +// DeleteComplianceRulesetsNodesJSONBody defines parameters for DeleteComplianceRulesetsNodes. +type DeleteComplianceRulesetsNodesJSONBody struct { + NodeId string `json:"node_id"` + + // RulesetId Ruleset id or name + RulesetId interface{} `json:"ruleset_id,omitempty"` + RulesetName *string `json:"ruleset_name,omitempty"` +} + +// PostComplianceRulesetsNodesJSONBody defines parameters for PostComplianceRulesetsNodes. +type PostComplianceRulesetsNodesJSONBody struct { + NodeId string `json:"node_id"` + + // RulesetId Ruleset id or name + RulesetId interface{} `json:"ruleset_id,omitempty"` + RulesetName *string `json:"ruleset_name,omitempty"` +} + // DeleteComplianceRulesetsPublicationsJSONBody defines parameters for DeleteComplianceRulesetsPublications. type DeleteComplianceRulesetsPublicationsJSONBody struct { // GroupId Group id or role @@ -2347,6 +2531,28 @@ type PostComplianceRulesetsResponsiblesJSONBody struct { RulesetId interface{} `json:"ruleset_id"` } +// DeleteComplianceRulesetsServicesJSONBody defines parameters for DeleteComplianceRulesetsServices. +type DeleteComplianceRulesetsServicesJSONBody struct { + // RulesetId Ruleset id or name + RulesetId interface{} `json:"ruleset_id,omitempty"` + RulesetName *string `json:"ruleset_name,omitempty"` + + // Slave A boolean; true for the encapsulated service. encap is accepted as well. + Slave interface{} `json:"slave,omitempty"` + SvcId string `json:"svc_id"` +} + +// PostComplianceRulesetsServicesJSONBody defines parameters for PostComplianceRulesetsServices. +type PostComplianceRulesetsServicesJSONBody struct { + // RulesetId Ruleset id or name + RulesetId interface{} `json:"ruleset_id,omitempty"` + RulesetName *string `json:"ruleset_name,omitempty"` + + // Slave A boolean; true for the encapsulated service. encap is accepted as well. + Slave interface{} `json:"slave,omitempty"` + SvcId string `json:"svc_id"` +} + // PostComplianceRulesetsVariablesJSONBody defines parameters for PostComplianceRulesetsVariables. type PostComplianceRulesetsVariablesJSONBody struct { RulesetId *int `json:"ruleset_id,omitempty"` @@ -5847,6 +6053,12 @@ type PostComplianceRulesetVariableJSONRequestBody PostComplianceRulesetVariableJ // PutComplianceRulesetVariableJSONRequestBody defines body for PutComplianceRulesetVariable for application/json ContentType. type PutComplianceRulesetVariableJSONRequestBody PutComplianceRulesetVariableJSONBody +// DeleteComplianceRulesetsNodesJSONRequestBody defines body for DeleteComplianceRulesetsNodes for application/json ContentType. +type DeleteComplianceRulesetsNodesJSONRequestBody DeleteComplianceRulesetsNodesJSONBody + +// PostComplianceRulesetsNodesJSONRequestBody defines body for PostComplianceRulesetsNodes for application/json ContentType. +type PostComplianceRulesetsNodesJSONRequestBody PostComplianceRulesetsNodesJSONBody + // DeleteComplianceRulesetsPublicationsJSONRequestBody defines body for DeleteComplianceRulesetsPublications for application/json ContentType. type DeleteComplianceRulesetsPublicationsJSONRequestBody DeleteComplianceRulesetsPublicationsJSONBody @@ -5859,6 +6071,12 @@ type DeleteComplianceRulesetsResponsiblesJSONRequestBody DeleteComplianceRuleset // PostComplianceRulesetsResponsiblesJSONRequestBody defines body for PostComplianceRulesetsResponsibles for application/json ContentType. type PostComplianceRulesetsResponsiblesJSONRequestBody PostComplianceRulesetsResponsiblesJSONBody +// DeleteComplianceRulesetsServicesJSONRequestBody defines body for DeleteComplianceRulesetsServices for application/json ContentType. +type DeleteComplianceRulesetsServicesJSONRequestBody DeleteComplianceRulesetsServicesJSONBody + +// PostComplianceRulesetsServicesJSONRequestBody defines body for PostComplianceRulesetsServices for application/json ContentType. +type PostComplianceRulesetsServicesJSONRequestBody PostComplianceRulesetsServicesJSONBody + // PostComplianceRulesetsVariablesJSONRequestBody defines body for PostComplianceRulesetsVariables for application/json ContentType. type PostComplianceRulesetsVariablesJSONRequestBody PostComplianceRulesetsVariablesJSONBody diff --git a/server/handlers/compliance_attachments.go b/server/handlers/compliance_attachments.go new file mode 100644 index 00000000..c1b5b161 --- /dev/null +++ b/server/handlers/compliance_attachments.go @@ -0,0 +1,170 @@ +package serverhandlers + +import ( + "context" + "fmt" + "net/http" + "strconv" + + "github.com/labstack/echo/v4" + + "github.com/opensvc/oc3/cdb" + "github.com/opensvc/oc3/server" +) + +// compObjectNodes answers with the nodes a compliance object is attached to, or +// its candidate nodes. +func (a *Api) compObjectNodes(c echo.Context, name string, k cdb.CompKind, objID int64, candidates bool, params listEndpointParams) error { + return a.handleList(c, name, "node", params, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetCompObjectNodes(ctx, k, objID, candidates, p) + }) +} + +// compObjectServices answers with the services a compliance object is attached +// to, or its candidate services. +func (a *Api) compObjectServices(c echo.Context, name string, k cdb.CompKind, objID int64, slave *bool, candidates bool, params listEndpointParams) error { + isSlave := slave != nil && *slave + return a.handleList(c, name, "service", params, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetCompObjectServices(ctx, k, objID, isSlave, candidates, p) + }) +} + +// publishedRuleset resolves a ruleset the caller may read: published to one of +// their groups or to Everybody. +func (a *Api) publishedRuleset(c echo.Context, rsetID string) (int64, error) { + ctx := c.Request().Context() + id, err := a.resolveRuleset(ctx, rsetID) + if err == nil { + err = a.requireRulesetPublished(ctx, c, id) + } + return id, err +} + +// GetComplianceRulesetNodes handles GET /compliance/rulesets/{rset_id}/nodes. +func (a *Api) GetComplianceRulesetNodes(c echo.Context, rsetId string, params server.GetComplianceRulesetNodesParams) error { + id, err := a.publishedRuleset(c, rsetId) + if err != nil { + return httpProblem(c, err) + } + return a.compObjectNodes(c, "GetComplianceRulesetNodes", cdb.CompRulesetKind, id, false, + listParams(params.Props, params.Limit, params.Offset, params.Meta, params.Stats, params.Orderby, params.Groupby, params.Filter)) +} + +// GetComplianceRulesetCandidateNodes handles GET /compliance/rulesets/{rset_id}/candidate_nodes. +func (a *Api) GetComplianceRulesetCandidateNodes(c echo.Context, rsetId string, params server.GetComplianceRulesetCandidateNodesParams) error { + id, err := a.publishedRuleset(c, rsetId) + if err != nil { + return httpProblem(c, err) + } + return a.compObjectNodes(c, "GetComplianceRulesetCandidateNodes", cdb.CompRulesetKind, id, true, + listParams(params.Props, params.Limit, params.Offset, params.Meta, params.Stats, params.Orderby, params.Groupby, params.Filter)) +} + +// GetComplianceRulesetServices handles GET /compliance/rulesets/{rset_id}/services. +func (a *Api) GetComplianceRulesetServices(c echo.Context, rsetId string, params server.GetComplianceRulesetServicesParams) error { + id, err := a.publishedRuleset(c, rsetId) + if err != nil { + return httpProblem(c, err) + } + return a.compObjectServices(c, "GetComplianceRulesetServices", cdb.CompRulesetKind, id, params.Slave, false, + listParams(params.Props, params.Limit, params.Offset, params.Meta, params.Stats, params.Orderby, params.Groupby, params.Filter)) +} + +// GetComplianceRulesetCandidateServices handles GET /compliance/rulesets/{rset_id}/candidate_services. +func (a *Api) GetComplianceRulesetCandidateServices(c echo.Context, rsetId string, params server.GetComplianceRulesetCandidateServicesParams) error { + id, err := a.publishedRuleset(c, rsetId) + if err != nil { + return httpProblem(c, err) + } + return a.compObjectServices(c, "GetComplianceRulesetCandidateServices", cdb.CompRulesetKind, id, params.Slave, true, + listParams(params.Props, params.Limit, params.Offset, params.Meta, params.Stats, params.Orderby, params.Groupby, params.Filter)) +} + +// compAttachBody reads the bulk attachment forms: the object by id or name, the +// node or service, and for a service whether it is the encapsulated one (slave, +// or encap as the historical ruleset examples post it). +type compAttachBody struct { + obj, target string + slave bool +} + +func readCompAttachBody(c echo.Context, idKey, nameKey, targetKey string) (compAttachBody, error) { + entry, err := oneEntry(c) + if err != nil { + return compAttachBody{}, err + } + var b compAttachBody + target, ok := entry[targetKey] + if !ok { + return b, httpErrorf(http.StatusBadRequest, "'%s' must be specified", targetKey) + } + b.target = fmt.Sprint(target) + if v, ok := entry[idKey]; ok { + b.obj = fmt.Sprint(v) + } else if v, ok := entry[nameKey]; ok { + b.obj = fmt.Sprint(v) + } else { + return b, httpErrorf(http.StatusBadRequest, "Either '%s' or '%s' must be specified", idKey, nameKey) + } + for _, key := range []string{"slave", "encap"} { + if v, ok := entry[key]; ok { + flag, err := compBool(key, v) + if err != nil { + return b, err + } + b.slave = flag == "T" + } + } + return b, nil +} + +// rulesetsNodes attaches or detaches a ruleset named in the body to a node, as +// POST and DELETE /nodes/{node_id}/compliance/rulesets/{rset_id} do. +func (a *Api) rulesetsNodes(c echo.Context, attach bool) error { + b, err := readCompAttachBody(c, "ruleset_id", "ruleset_name", "node_id") + if err != nil { + return httpProblem(c, err) + } + id, err := a.resolveRuleset(c.Request().Context(), b.obj) + if err != nil { + return httpProblem(c, err) + } + if attach { + return a.PostNodeComplianceRuleset(c, b.target, strconv.FormatInt(id, 10)) + } + return a.DeleteNodeComplianceRuleset(c, b.target, strconv.FormatInt(id, 10)) +} + +// PostComplianceRulesetsNodes handles POST /compliance/rulesets_nodes. +func (a *Api) PostComplianceRulesetsNodes(c echo.Context) error { return a.rulesetsNodes(c, true) } + +// DeleteComplianceRulesetsNodes handles DELETE /compliance/rulesets_nodes. +func (a *Api) DeleteComplianceRulesetsNodes(c echo.Context) error { return a.rulesetsNodes(c, false) } + +// rulesetsServices attaches or detaches a ruleset named in the body to a +// service, as POST and DELETE /services/{svc_id}/compliance/rulesets/{rset_id} do. +func (a *Api) rulesetsServices(c echo.Context, attach bool) error { + b, err := readCompAttachBody(c, "ruleset_id", "ruleset_name", "svc_id") + if err != nil { + return httpProblem(c, err) + } + id, err := a.resolveRuleset(c.Request().Context(), b.obj) + if err != nil { + return httpProblem(c, err) + } + slave := b.slave + if attach { + return a.PostServiceComplianceRuleset(c, b.target, strconv.FormatInt(id, 10), server.PostServiceComplianceRulesetParams{Slave: &slave}) + } + return a.DeleteServiceComplianceRuleset(c, b.target, strconv.FormatInt(id, 10), server.DeleteServiceComplianceRulesetParams{Slave: &slave}) +} + +// PostComplianceRulesetsServices handles POST /compliance/rulesets_services. +func (a *Api) PostComplianceRulesetsServices(c echo.Context) error { + return a.rulesetsServices(c, true) +} + +// DeleteComplianceRulesetsServices handles DELETE /compliance/rulesets_services. +func (a *Api) DeleteComplianceRulesetsServices(c echo.Context) error { + return a.rulesetsServices(c, false) +} From c3ab97003a635bc4e257bc3ee378e2dcc3e933eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Mon, 28 Sep 2026 13:47:41 +0200 Subject: [PATCH 43/61] Add the compliance modulesets endpoints Port the moduleset endpoints of the historical api_compliance: - GET /compliance/modulesets and /modulesets/{modset_id} (id or name), the modulesets published to one of the caller's groups; - POST /compliance/modulesets, creating a moduleset authored by the caller, published to and under the responsibility of their default group; a taken name is a 409; - POST /compliance/modulesets/{modset_id}, renaming it and recording the update date; - PUT /compliance/modulesets/{modset_id} action=clone, copying its modules, rulesets and children as _clone; - DELETE /compliance/modulesets/{modset_id} and the bulk DELETE /compliance/modulesets ({"id": ...}), removing its relations; - GET /compliance/modulesets/{modset_id}/usage (the parent modulesets) and /am_i_responsible. Changes require the CompManager privilege and, but for creation, the responsibility of the moduleset; they are logged. The visibility and the publication checks, Everybody included, are written over the CompKind. --- cdb/db_compliance_modulesets.go | 162 ++++ cdb/db_compliance_teams.go | 23 + server/api.yaml | 355 ++++++++ server/codegen_server_gen.go | 1036 ++++++++++++++-------- server/codegen_type_gen.go | 101 ++- server/handlers/compliance_modulesets.go | 294 ++++++ 6 files changed, 1585 insertions(+), 386 deletions(-) create mode 100644 cdb/db_compliance_modulesets.go create mode 100644 server/handlers/compliance_modulesets.go diff --git a/cdb/db_compliance_modulesets.go b/cdb/db_compliance_modulesets.go new file mode 100644 index 00000000..a5cfdb92 --- /dev/null +++ b/cdb/db_compliance_modulesets.go @@ -0,0 +1,162 @@ +package cdb + +import ( + "context" + "database/sql" + "errors" + "fmt" + "strconv" +) + +// GetComplianceModulesets lists the modulesets published to one of the caller's +// groups, every moduleset for a manager; one when id is set. +func (oDb *DB) GetComplianceModulesets(ctx context.Context, id *int64, p ListParams) ([]map[string]any, error) { + cond, args := compObjectVisibleCond(CompModulesetKind, p.Groups, p.IsManager) + conds := []string{cond} + if id != nil { + conds = append(conds, "comp_moduleset.id = ?") + args = append(args, *id) + } + return oDb.listQuery(ctx, "getComplianceModulesets", "comp_moduleset", conds, args, "comp_moduleset.modset_name", p) +} + +// CompModulesetID resolves a moduleset given by id or by name, as +// moduleset_id_q(); false when there is none. +func (oDb *DB) CompModulesetID(ctx context.Context, idOrName string) (int64, bool, error) { + var id int64 + var err error + if n, convErr := strconv.ParseInt(idOrName, 10, 64); convErr == nil { + err = oDb.DB.QueryRowContext(ctx, "SELECT id FROM comp_moduleset WHERE id = ?", n).Scan(&id) + } else { + err = oDb.DB.QueryRowContext(ctx, "SELECT id FROM comp_moduleset WHERE modset_name = ? LIMIT 1", idOrName).Scan(&id) + } + switch { + case errors.Is(err, sql.ErrNoRows): + return 0, false, nil + case err != nil: + return 0, false, fmt.Errorf("compModulesetID: %w", err) + } + return id, true, nil +} + +// CreateCompModuleset inserts a moduleset authored by author, published to and +// under the responsibility of groupID, as create_moduleset() and +// add_default_teams_to_modset(). +func (oDb *DB) CreateCompModuleset(ctx context.Context, name, author string, groupID int64) (int64, error) { + res, err := oDb.DB.ExecContext(ctx, "INSERT INTO comp_moduleset (modset_name, modset_author, modset_updated) VALUES (?, ?, NOW())", name, author) + if err != nil { + return 0, fmt.Errorf("createCompModuleset: %w", err) + } + id, err := res.LastInsertId() + if err != nil { + return 0, fmt.Errorf("createCompModuleset: %w", err) + } + if err := oDb.addModulesetTeams(ctx, id, groupID); err != nil { + return 0, err + } + oDb.SetChange("comp_moduleset") + return id, nil +} + +func (oDb *DB) addModulesetTeams(ctx context.Context, modsetID, groupID int64) error { + for _, table := range []string{"comp_moduleset_team_responsible", "comp_moduleset_team_publication"} { + if _, err := oDb.DB.ExecContext(ctx, "INSERT INTO "+table+" (modset_id, group_id) VALUES (?, ?)", modsetID, groupID); err != nil { + return fmt.Errorf("addModulesetTeams: %w", err) + } + oDb.SetChange(table) + } + return nil +} + +// RenameCompModuleset renames a moduleset and records the update date. +func (oDb *DB) RenameCompModuleset(ctx context.Context, id int64, name string) error { + if _, err := oDb.DB.ExecContext(ctx, "UPDATE comp_moduleset SET modset_name = ?, modset_updated = NOW() WHERE id = ?", name, id); err != nil { + return fmt.Errorf("renameCompModuleset: %w", err) + } + oDb.SetChange("comp_moduleset") + return nil +} + +// DeleteCompModuleset deletes a moduleset with its node and service attachments, +// publication and responsible groups, modules, parent and child relations and +// ruleset links, as delete_moduleset(). +func (oDb *DB) DeleteCompModuleset(ctx context.Context, id int64) error { + for _, q := range []struct{ table, cond string }{ + {"comp_node_moduleset", "modset_id = ?"}, + {"comp_modulesets_services", "modset_id = ?"}, + {"comp_moduleset_team_publication", "modset_id = ?"}, + {"comp_moduleset_team_responsible", "modset_id = ?"}, + {"comp_moduleset_modules", "modset_id = ?"}, + {"comp_moduleset", "id = ?"}, + {"comp_moduleset_moduleset", "parent_modset_id = ? OR child_modset_id = ?"}, + {"comp_moduleset_ruleset", "modset_id = ?"}, + } { + args := []any{id} + if q.table == "comp_moduleset_moduleset" { + args = append(args, id) + } + if _, err := oDb.DB.ExecContext(ctx, "DELETE FROM "+q.table+" WHERE "+q.cond, args...); err != nil { + return fmt.Errorf("deleteCompModuleset: %s: %w", q.table, err) + } + oDb.SetChange(q.table) + } + return nil +} + +// CloneCompModuleset copies a moduleset as "_clone", authored by author: +// its modules, its rulesets and its children, under the responsibility and +// publication of groupID, as clone_moduleset(). It returns the id and the name +// of the copy. +func (oDb *DB) CloneCompModuleset(ctx context.Context, id int64, author string, groupID int64) (int64, string, error) { + var name string + err := oDb.DB.QueryRowContext(ctx, "SELECT modset_name FROM comp_moduleset WHERE id = ?", id).Scan(&name) + if errors.Is(err, sql.ErrNoRows) { + return 0, "", ErrCompNotFound + } else if err != nil { + return 0, "", fmt.Errorf("cloneCompModuleset: %w", err) + } + cloneName := name + "_clone" + if _, found, err := oDb.CompModulesetID(ctx, cloneName); err != nil { + return 0, "", err + } else if found { + return 0, "", fmt.Errorf("%w: a moduleset named %s already exists", ErrCompConflict, cloneName) + } + res, err := oDb.DB.ExecContext(ctx, "INSERT INTO comp_moduleset (modset_name, modset_author, modset_updated) VALUES (?, ?, NOW())", cloneName, author) + if err != nil { + return 0, "", fmt.Errorf("cloneCompModuleset: %w", err) + } + newID, err := res.LastInsertId() + if err != nil { + return 0, "", fmt.Errorf("cloneCompModuleset: %w", err) + } + for _, st := range []struct { + query string + args []any + }{ + {"INSERT INTO comp_moduleset_modules (modset_id, modset_mod_name, modset_mod_author, modset_mod_updated, autofix)" + + " SELECT ?, modset_mod_name, modset_mod_author, NOW(), autofix FROM comp_moduleset_modules WHERE modset_id = ?", []any{newID, id}}, + {"INSERT INTO comp_moduleset_ruleset (modset_id, ruleset_id) SELECT ?, ruleset_id FROM comp_moduleset_ruleset WHERE modset_id = ?", []any{newID, id}}, + {"INSERT INTO comp_moduleset_moduleset (parent_modset_id, child_modset_id) SELECT ?, child_modset_id FROM comp_moduleset_moduleset WHERE parent_modset_id = ?", []any{newID, id}}, + } { + if _, err := oDb.DB.ExecContext(ctx, st.query, st.args...); err != nil { + return 0, "", fmt.Errorf("cloneCompModuleset: %w", err) + } + } + if err := oDb.addModulesetTeams(ctx, newID, groupID); err != nil { + return 0, "", err + } + for _, t := range []string{"comp_moduleset", "comp_moduleset_modules", "comp_moduleset_ruleset", "comp_moduleset_moduleset"} { + oDb.SetChange(t) + } + return newID, cloneName, nil +} + +// CompModulesetUsage lists the modulesets holding a moduleset as a child. +func (oDb *DB) CompModulesetUsage(ctx context.Context, id int64) (map[string][]map[string]any, error) { + parents, err := oDb.namedPairs(ctx, "SELECT m.id, m.modset_name FROM comp_moduleset_moduleset mm"+ + " JOIN comp_moduleset m ON m.id = mm.parent_modset_id WHERE mm.child_modset_id = ? ORDER BY m.modset_name", id, "id", "modset_name") + if err != nil { + return nil, fmt.Errorf("compModulesetUsage: %w", err) + } + return map[string][]map[string]any{"modulesets": parents}, nil +} diff --git a/cdb/db_compliance_teams.go b/cdb/db_compliance_teams.go index 98f3c865..929d024a 100644 --- a/cdb/db_compliance_teams.go +++ b/cdb/db_compliance_teams.go @@ -117,3 +117,26 @@ func (oDb *DB) CompObjectResponsible(ctx context.Context, k CompKind, objID int6 return oDb.exists(ctx, "compObjectResponsible", "SELECT 1 FROM "+k.TeamPrefix+"responsible r"+ " JOIN auth_group ag ON ag.id = r.group_id WHERE r."+k.FK+" = ? AND "+cond, append([]any{objID}, args...)...) } + +// compObjectVisibleCond restricts a compliance object table to the objects +// published to one of the caller's groups; every object for a manager. +func compObjectVisibleCond(k CompKind, groups []string, isManager bool) (string, []any) { + if isManager { + return "1=1", nil + } + cond, args := rolesCond("ag", groups, false) + return k.Table + ".id IN (SELECT tp." + k.FK + " FROM " + k.TeamPrefix + "publication tp" + + " JOIN auth_group ag ON ag.id = tp.group_id WHERE " + cond + ")", args +} + +// CompObjectPublished tells whether a compliance object is published to the +// caller: to one of their groups or to Everybody, as ruleset_publication() and +// moduleset_publication(); always for a manager, when it exists. +func (oDb *DB) CompObjectPublished(ctx context.Context, k CompKind, objID int64, groups []string, isManager bool) (bool, error) { + cond, args := compObjectVisibleCond(k, groups, isManager) + if ok, err := oDb.exists(ctx, "compObjectPublished", "SELECT 1 FROM "+k.Table+" WHERE "+k.Table+".id = ? AND "+cond, append([]any{objID}, args...)...); err != nil || ok { + return ok, err + } + return oDb.exists(ctx, "compObjectPublished", "SELECT 1 FROM "+k.TeamPrefix+"publication tp"+ + " JOIN auth_group ag ON ag.id = tp.group_id WHERE tp."+k.FK+" = ? AND ag.role = 'Everybody'", objID) +} diff --git a/server/api.yaml b/server/api.yaml index 75810919..940ec254 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -10681,6 +10681,361 @@ paths: - basicAuth: [ ] - bearerAuth: [ ] + /compliance/modulesets: + get: + operationId: GetComplianceModulesets + description: | + List the modulesets published to one of the user's groups, every moduleset for + a manager. + parameters: + - $ref: '#/components/parameters/inQueryProps' + - $ref: '#/components/parameters/inQueryLimit' + - $ref: '#/components/parameters/inQueryOffset' + - $ref: '#/components/parameters/inQueryMeta' + - $ref: '#/components/parameters/inQueryStats' + - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryFilter' + - $ref: '#/components/parameters/inQueryGroupby' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ModulesetListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + post: + operationId: PostComplianceModulesets + description: | + Create a moduleset named modset_name, authored by the user, published to and + under the responsibility of the user's default group (the Manager group without + one). A taken name is a 409. Requires the CompManager privilege. The creation is + logged. + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + modset_name: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ModulesetListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 409: + $ref: '#/components/responses/409' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + delete: + operationId: DeleteComplianceModulesets + description: | + Delete the moduleset named by the id key of the body, as + DELETE /compliance/modulesets/{modset_id}. + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + id: + description: Moduleset id or name + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /compliance/modulesets/{modset_id}: + get: + operationId: GetComplianceModuleset + description: | + Display a moduleset published to one of the user's groups. + parameters: + - in: path + name: modset_id + required: true + description: Moduleset id or name + schema: + type: string + - $ref: '#/components/parameters/inQueryProps' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ModulesetListResponse' + 401: + $ref: '#/components/responses/401' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + post: + operationId: PostComplianceModuleset + description: | + Rename a moduleset, recording its update date. Requires the CompManager + privilege and the responsibility of the moduleset. The change is logged. + parameters: + - in: path + name: modset_id + required: true + description: Moduleset id or name + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + modset_name: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ModulesetListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 409: + $ref: '#/components/responses/409' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + put: + operationId: PutComplianceModuleset + description: | + Special actions on a moduleset. `clone` copies it as "_clone", authored by + the user, with its modules, rulesets and children, published to and under the + responsibility of the user's default group. Requires the CompManager privilege. + parameters: + - in: path + name: modset_id + required: true + description: Moduleset id or name + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [action] + properties: + action: + type: string + enum: [clone] + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 409: + $ref: '#/components/responses/409' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + delete: + operationId: DeleteComplianceModuleset + description: | + Delete a moduleset, with its parent and child relations, node and service + attachments, publication and responsible groups, modules and ruleset links. + Requires the CompManager privilege and the responsibility of the moduleset. The + deletion is logged. + parameters: + - in: path + name: modset_id + required: true + description: Moduleset id or name + schema: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /compliance/modulesets/{modset_id}/usage: + get: + operationId: GetComplianceModulesetUsage + description: | + Display what uses a moduleset published to the user: the modulesets holding it + as a child. + parameters: + - in: path + name: modset_id + required: true + description: Moduleset id or name + schema: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + data: + type: object + properties: + modulesets: + type: array + items: + type: object + properties: + id: + type: integer + modset_name: + type: string + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /compliance/modulesets/{modset_id}/am_i_responsible: + get: + operationId: GetComplianceModulesetAmIResponsible + description: | + Tell whether one of the user's groups is responsible for the moduleset. + parameters: + - in: path + name: modset_id + required: true + description: Moduleset id or name + schema: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + data: + type: boolean + 401: + $ref: '#/components/responses/401' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + components: responses: diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index bb16f915..aea4f732 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -129,6 +129,33 @@ type ServerInterface interface { // (GET /compliance/logs/{log_id}) GetComplianceLog(ctx echo.Context, logId string, params GetComplianceLogParams) error + // (DELETE /compliance/modulesets) + DeleteComplianceModulesets(ctx echo.Context) error + + // (GET /compliance/modulesets) + GetComplianceModulesets(ctx echo.Context, params GetComplianceModulesetsParams) error + + // (POST /compliance/modulesets) + PostComplianceModulesets(ctx echo.Context) error + + // (DELETE /compliance/modulesets/{modset_id}) + DeleteComplianceModuleset(ctx echo.Context, modsetId string) error + + // (GET /compliance/modulesets/{modset_id}) + GetComplianceModuleset(ctx echo.Context, modsetId string, params GetComplianceModulesetParams) error + + // (POST /compliance/modulesets/{modset_id}) + PostComplianceModuleset(ctx echo.Context, modsetId string) error + + // (PUT /compliance/modulesets/{modset_id}) + PutComplianceModuleset(ctx echo.Context, modsetId string) error + + // (GET /compliance/modulesets/{modset_id}/am_i_responsible) + GetComplianceModulesetAmIResponsible(ctx echo.Context, modsetId string) error + + // (GET /compliance/modulesets/{modset_id}/usage) + GetComplianceModulesetUsage(ctx echo.Context, modsetId string) error + // (DELETE /compliance/rulesets) DeleteComplianceRulesets(ctx echo.Context) error @@ -2150,6 +2177,232 @@ func (w *ServerInterfaceWrapper) GetComplianceLog(ctx echo.Context) error { return err } +// DeleteComplianceModulesets converts echo context to params. +func (w *ServerInterfaceWrapper) DeleteComplianceModulesets(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.DeleteComplianceModulesets(ctx) + return err +} + +// GetComplianceModulesets converts echo context to params. +func (w *ServerInterfaceWrapper) GetComplianceModulesets(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetComplianceModulesetsParams + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // ------------- Optional query parameter "limit" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) + } + + // ------------- Optional query parameter "offset" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) + } + + // ------------- Optional query parameter "meta" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) + } + + // ------------- Optional query parameter "stats" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) + } + + // ------------- Optional query parameter "orderby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) + } + + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + + // ------------- Optional query parameter "groupby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetComplianceModulesets(ctx, params) + return err +} + +// PostComplianceModulesets converts echo context to params. +func (w *ServerInterfaceWrapper) PostComplianceModulesets(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostComplianceModulesets(ctx) + return err +} + +// DeleteComplianceModuleset converts echo context to params. +func (w *ServerInterfaceWrapper) DeleteComplianceModuleset(ctx echo.Context) error { + var err error + // ------------- Path parameter "modset_id" ------------- + var modsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "modset_id", ctx.Param("modset_id"), &modsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter modset_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.DeleteComplianceModuleset(ctx, modsetId) + return err +} + +// GetComplianceModuleset converts echo context to params. +func (w *ServerInterfaceWrapper) GetComplianceModuleset(ctx echo.Context) error { + var err error + // ------------- Path parameter "modset_id" ------------- + var modsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "modset_id", ctx.Param("modset_id"), &modsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter modset_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetComplianceModulesetParams + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetComplianceModuleset(ctx, modsetId, params) + return err +} + +// PostComplianceModuleset converts echo context to params. +func (w *ServerInterfaceWrapper) PostComplianceModuleset(ctx echo.Context) error { + var err error + // ------------- Path parameter "modset_id" ------------- + var modsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "modset_id", ctx.Param("modset_id"), &modsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter modset_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostComplianceModuleset(ctx, modsetId) + return err +} + +// PutComplianceModuleset converts echo context to params. +func (w *ServerInterfaceWrapper) PutComplianceModuleset(ctx echo.Context) error { + var err error + // ------------- Path parameter "modset_id" ------------- + var modsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "modset_id", ctx.Param("modset_id"), &modsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter modset_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PutComplianceModuleset(ctx, modsetId) + return err +} + +// GetComplianceModulesetAmIResponsible converts echo context to params. +func (w *ServerInterfaceWrapper) GetComplianceModulesetAmIResponsible(ctx echo.Context) error { + var err error + // ------------- Path parameter "modset_id" ------------- + var modsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "modset_id", ctx.Param("modset_id"), &modsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter modset_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetComplianceModulesetAmIResponsible(ctx, modsetId) + return err +} + +// GetComplianceModulesetUsage converts echo context to params. +func (w *ServerInterfaceWrapper) GetComplianceModulesetUsage(ctx echo.Context) error { + var err error + // ------------- Path parameter "modset_id" ------------- + var modsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "modset_id", ctx.Param("modset_id"), &modsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter modset_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetComplianceModulesetUsage(ctx, modsetId) + return err +} + // DeleteComplianceRulesets converts echo context to params. func (w *ServerInterfaceWrapper) DeleteComplianceRulesets(ctx echo.Context) error { var err error @@ -11892,6 +12145,15 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.POST(options.BaseURL+"/auth/node", wrapper.PostAuthNode, options.OperationMiddlewares["PostAuthNode"]...) router.GET(options.BaseURL+"/compliance/logs", wrapper.GetComplianceLogs, options.OperationMiddlewares["GetComplianceLogs"]...) router.GET(options.BaseURL+"/compliance/logs/:log_id", wrapper.GetComplianceLog, options.OperationMiddlewares["GetComplianceLog"]...) + router.DELETE(options.BaseURL+"/compliance/modulesets", wrapper.DeleteComplianceModulesets, options.OperationMiddlewares["DeleteComplianceModulesets"]...) + router.GET(options.BaseURL+"/compliance/modulesets", wrapper.GetComplianceModulesets, options.OperationMiddlewares["GetComplianceModulesets"]...) + router.POST(options.BaseURL+"/compliance/modulesets", wrapper.PostComplianceModulesets, options.OperationMiddlewares["PostComplianceModulesets"]...) + router.DELETE(options.BaseURL+"/compliance/modulesets/:modset_id", wrapper.DeleteComplianceModuleset, options.OperationMiddlewares["DeleteComplianceModuleset"]...) + router.GET(options.BaseURL+"/compliance/modulesets/:modset_id", wrapper.GetComplianceModuleset, options.OperationMiddlewares["GetComplianceModuleset"]...) + router.POST(options.BaseURL+"/compliance/modulesets/:modset_id", wrapper.PostComplianceModuleset, options.OperationMiddlewares["PostComplianceModuleset"]...) + router.PUT(options.BaseURL+"/compliance/modulesets/:modset_id", wrapper.PutComplianceModuleset, options.OperationMiddlewares["PutComplianceModuleset"]...) + router.GET(options.BaseURL+"/compliance/modulesets/:modset_id/am_i_responsible", wrapper.GetComplianceModulesetAmIResponsible, options.OperationMiddlewares["GetComplianceModulesetAmIResponsible"]...) + router.GET(options.BaseURL+"/compliance/modulesets/:modset_id/usage", wrapper.GetComplianceModulesetUsage, options.OperationMiddlewares["GetComplianceModulesetUsage"]...) router.DELETE(options.BaseURL+"/compliance/rulesets", wrapper.DeleteComplianceRulesets, options.OperationMiddlewares["DeleteComplianceRulesets"]...) router.GET(options.BaseURL+"/compliance/rulesets", wrapper.GetComplianceRulesets, options.OperationMiddlewares["GetComplianceRulesets"]...) router.POST(options.BaseURL+"/compliance/rulesets", wrapper.PostComplianceRulesets, options.OperationMiddlewares["PostComplianceRulesets"]...) @@ -12129,390 +12391,396 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "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", - "/w8AAP//", + "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", + "/wAAAP//", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index 360e16f6..21743af5 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -32,6 +32,21 @@ func (e ObsolescenceSettingRowObsType) Valid() bool { } } +// Defines values for PutComplianceModulesetJSONBodyAction. +const ( + PutComplianceModulesetJSONBodyActionClone PutComplianceModulesetJSONBodyAction = "clone" +) + +// Valid indicates whether the value is a known member of the PutComplianceModulesetJSONBodyAction enum. +func (e PutComplianceModulesetJSONBodyAction) Valid() bool { + switch e { + case PutComplianceModulesetJSONBodyActionClone: + return true + default: + return false + } +} + // Defines values for PostComplianceRulesetsJSONBodyRulesetType. const ( PostComplianceRulesetsJSONBodyRulesetTypeContextual PostComplianceRulesetsJSONBodyRulesetType = "contextual" @@ -70,13 +85,13 @@ func (e PostComplianceRulesetJSONBodyRulesetType) Valid() bool { // Defines values for PutComplianceRulesetJSONBodyAction. const ( - Clone PutComplianceRulesetJSONBodyAction = "clone" + PutComplianceRulesetJSONBodyActionClone PutComplianceRulesetJSONBodyAction = "clone" ) // Valid indicates whether the value is a known member of the PutComplianceRulesetJSONBodyAction enum. func (e PutComplianceRulesetJSONBodyAction) Valid() bool { switch e { - case Clone: + case PutComplianceRulesetJSONBodyActionClone: return true default: return false @@ -2070,6 +2085,76 @@ type GetComplianceLogParams struct { Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` } +// DeleteComplianceModulesetsJSONBody defines parameters for DeleteComplianceModulesets. +type DeleteComplianceModulesetsJSONBody struct { + // Id Moduleset id or name + Id interface{} `json:"id,omitempty"` +} + +// GetComplianceModulesetsParams defines parameters for GetComplianceModulesets. +type GetComplianceModulesetsParams struct { + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` + + // Limit The maximum number of entries to return. 0 means no limit. + Limit *InQueryLimit `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Skip the first entries of the data cursor. + Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` + + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. + Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` + + // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. + Stats *InQueryStats `form:"stats,omitempty" json:"stats,omitempty"` + + // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). + Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` + + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). + Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` +} + +// PostComplianceModulesetsJSONBody defines parameters for PostComplianceModulesets. +type PostComplianceModulesetsJSONBody struct { + ModsetName *string `json:"modset_name,omitempty"` +} + +// GetComplianceModulesetParams defines parameters for GetComplianceModuleset. +type GetComplianceModulesetParams struct { + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` +} + +// PostComplianceModulesetJSONBody defines parameters for PostComplianceModuleset. +type PostComplianceModulesetJSONBody struct { + ModsetName *string `json:"modset_name,omitempty"` +} + +// PutComplianceModulesetJSONBody defines parameters for PutComplianceModuleset. +type PutComplianceModulesetJSONBody struct { + Action PutComplianceModulesetJSONBodyAction `json:"action"` +} + +// PutComplianceModulesetJSONBodyAction defines parameters for PutComplianceModuleset. +type PutComplianceModulesetJSONBodyAction string + // DeleteComplianceRulesetsJSONBody defines parameters for DeleteComplianceRulesets. type DeleteComplianceRulesetsJSONBody struct { // Id Ruleset id or name @@ -6032,6 +6117,18 @@ type PostAppsResponsiblesJSONRequestBody PostAppsResponsiblesJSONBody // PostAuthNodeJSONRequestBody defines body for PostAuthNode for application/json ContentType. type PostAuthNodeJSONRequestBody PostAuthNodeJSONBody +// DeleteComplianceModulesetsJSONRequestBody defines body for DeleteComplianceModulesets for application/json ContentType. +type DeleteComplianceModulesetsJSONRequestBody DeleteComplianceModulesetsJSONBody + +// PostComplianceModulesetsJSONRequestBody defines body for PostComplianceModulesets for application/json ContentType. +type PostComplianceModulesetsJSONRequestBody PostComplianceModulesetsJSONBody + +// PostComplianceModulesetJSONRequestBody defines body for PostComplianceModuleset for application/json ContentType. +type PostComplianceModulesetJSONRequestBody PostComplianceModulesetJSONBody + +// PutComplianceModulesetJSONRequestBody defines body for PutComplianceModuleset for application/json ContentType. +type PutComplianceModulesetJSONRequestBody PutComplianceModulesetJSONBody + // DeleteComplianceRulesetsJSONRequestBody defines body for DeleteComplianceRulesets for application/json ContentType. type DeleteComplianceRulesetsJSONRequestBody DeleteComplianceRulesetsJSONBody diff --git a/server/handlers/compliance_modulesets.go b/server/handlers/compliance_modulesets.go new file mode 100644 index 00000000..94a0d889 --- /dev/null +++ b/server/handlers/compliance_modulesets.go @@ -0,0 +1,294 @@ +package serverhandlers + +import ( + "context" + "fmt" + "net/http" + "strconv" + + "github.com/labstack/echo/v4" + + "github.com/opensvc/oc3/cdb" + "github.com/opensvc/oc3/server" +) + +// resolveModuleset returns the id of a moduleset given by id or by name: 404 when +// there is none. +func (a *Api) resolveModuleset(ctx context.Context, idOrName string) (int64, error) { + id, found, err := a.ODB.CompModulesetID(ctx, idOrName) + if err != nil { + return 0, err + } + if !found { + return 0, httpErrorf(http.StatusNotFound, "moduleset %s not found", idOrName) + } + return id, nil +} + +// requireModulesetResponsible refuses a caller none of whose groups is +// responsible for the moduleset. +func (a *Api) requireModulesetResponsible(ctx context.Context, c echo.Context, id int64) error { + ok, err := a.ODB.CompObjectResponsible(ctx, cdb.CompModulesetKind, id, UserGroupsFromContext(c), IsManager(c)) + if err != nil { + return compDesignerError(c, "check the moduleset responsibility", err) + } + if !ok { + return httpErrorf(http.StatusForbidden, "you are not responsible for this moduleset") + } + return nil +} + +// requireModulesetPublished refuses a caller the moduleset is not published to. +func (a *Api) requireModulesetPublished(ctx context.Context, c echo.Context, id int64) error { + ok, err := a.ODB.CompObjectPublished(ctx, cdb.CompModulesetKind, id, UserGroupsFromContext(c), IsManager(c)) + if err != nil { + return compDesignerError(c, "check the moduleset publication", err) + } + if !ok { + return httpErrorf(http.StatusForbidden, "you are not member of one of the moduleset publication groups") + } + return nil +} + +// publishedModuleset resolves a moduleset the caller may read. +func (a *Api) publishedModuleset(c echo.Context, modsetID string) (int64, error) { + ctx := c.Request().Context() + id, err := a.resolveModuleset(ctx, modsetID) + if err == nil { + err = a.requireModulesetPublished(ctx, c, id) + } + return id, err +} + +// GetComplianceModulesets handles GET /compliance/modulesets, as the historical +// rest_get_compliance_modulesets: the modulesets published to the caller's groups. +func (a *Api) GetComplianceModulesets(c echo.Context, params server.GetComplianceModulesetsParams) error { + return a.handleList(c, "GetComplianceModulesets", "moduleset", + listParams(params.Props, params.Limit, params.Offset, params.Meta, params.Stats, params.Orderby, params.Groupby, params.Filter), + func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetComplianceModulesets(ctx, nil, p) + }) +} + +// GetComplianceModuleset handles GET /compliance/modulesets/{modset_id}. +func (a *Api) GetComplianceModuleset(c echo.Context, modsetId string, params server.GetComplianceModulesetParams) error { + id, err := a.resolveModuleset(c.Request().Context(), modsetId) + if err != nil { + return httpProblem(c, err) + } + return a.modulesetResponse(c, id, params.Props) +} + +func (a *Api) modulesetResponse(c echo.Context, id int64, props *server.InQueryProps) error { + return a.handleItem(c, "GetComplianceModuleset", "moduleset", "id", strconv.FormatInt(id, 10), listEndpointParams{ + props: props, + }, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetComplianceModulesets(ctx, &id, p) + }) +} + +// PostComplianceModulesets handles POST /compliance/modulesets, as the historical +// create_moduleset(): a moduleset named modset_name, authored by the caller, +// published to and under the responsibility of their default group. +func (a *Api) PostComplianceModulesets(c echo.Context) error { + entry, err := oneEntry(c) + if err != nil { + return httpProblem(c, err) + } + name, err := compString("modset_name", entry["modset_name"], true) + if err != nil { + return httpProblem(c, err) + } + ctx := c.Request().Context() + if err := checkCompManager(c); err != nil { + return httpProblem(c, err) + } + if _, found, err := a.ODB.CompModulesetID(ctx, name); err != nil { + return httpProblem(c, compDesignerError(c, "PostComplianceModulesets", err)) + } else if found { + return httpProblem(c, httpErrorf(http.StatusConflict, "a moduleset named '%s' already exists", name)) + } + caller, err := a.formCaller(ctx, c) + if err != nil { + return httpProblem(c, compDesignerError(c, "PostComplianceModulesets", err)) + } + groupID, err := a.ODB.DefaultGroupOrManager(ctx, authUserID(c)) + if err != nil { + return httpProblem(c, compDesignerError(c, "PostComplianceModulesets", err)) + } + id, err := a.ODB.CreateCompModuleset(ctx, name, caller.name, groupID) + if err != nil { + return httpProblem(c, compDesignerError(c, "PostComplianceModulesets", err)) + } + a.afterRulesetChange(c, false) + a.compLog(c, "compliance.moduleset.add", "added moduleset %(modset_name)s", map[string]any{"modset_name": name}, "", "") + return a.modulesetResponse(c, id, nil) +} + +// PostComplianceModuleset handles POST /compliance/modulesets/{modset_id}, as the +// historical rest_post_compliance_moduleset: a renaming, by a CompManager +// responsible for the moduleset, recording the update date. +func (a *Api) PostComplianceModuleset(c echo.Context, modsetId string) error { + entry, err := oneEntry(c) + if err != nil { + return httpProblem(c, err) + } + ctx := c.Request().Context() + id, err := a.resolveModuleset(ctx, modsetId) + if err == nil { + err = checkCompManager(c) + } + if err == nil { + err = a.requireModulesetResponsible(ctx, c, id) + } + if err != nil { + return httpProblem(c, err) + } + var name string + for k, v := range entry { + switch k { + case "modset_name": + if name, err = compString(k, v, true); err != nil { + return httpProblem(c, err) + } + case "id", "modset_author", "modset_updated": + default: + return httpProblem(c, httpErrorf(http.StatusBadRequest, "unknown moduleset property %s", k)) + } + } + if name == "" { + return compInfo(c, "No fields to update") + } + if other, found, err := a.ODB.CompModulesetID(ctx, name); err != nil { + return httpProblem(c, compDesignerError(c, "PostComplianceModuleset", err)) + } else if found && other != id { + return httpProblem(c, httpErrorf(http.StatusConflict, "a moduleset named '%s' already exists", name)) + } + if err := a.ODB.RenameCompModuleset(ctx, id, name); err != nil { + return httpProblem(c, compDesignerError(c, "PostComplianceModuleset", err)) + } + a.afterRulesetChange(c, false) + a.compLog(c, "compliance.moduleset.change", "update properties %(data)s", map[string]any{"data": compJSON(map[string]any{"modset_name": name})}, "", "") + return a.modulesetResponse(c, id, nil) +} + +// PutComplianceModuleset handles PUT /compliance/modulesets/{modset_id}, the +// special actions on a moduleset, as the historical rest_put_compliance_moduleset: +// clone. +func (a *Api) PutComplianceModuleset(c echo.Context, modsetId string) error { + entry, err := oneEntry(c) + if err != nil { + return httpProblem(c, err) + } + ctx := c.Request().Context() + id, err := a.resolveModuleset(ctx, modsetId) + if err != nil { + return httpProblem(c, err) + } + if action, _ := entry["action"].(string); action != "clone" { + return httpProblem(c, httpErrorf(http.StatusBadRequest, "unsupported action %q", action)) + } + if err := checkCompManager(c); err != nil { + return httpProblem(c, err) + } + caller, err := a.formCaller(ctx, c) + if err != nil { + return httpProblem(c, compDesignerError(c, "PutComplianceModuleset", err)) + } + groupID, err := a.ODB.DefaultGroupOrManager(ctx, authUserID(c)) + if err != nil { + return httpProblem(c, compDesignerError(c, "PutComplianceModuleset", err)) + } + name, err := a.ODB.CompObjectName(ctx, cdb.CompModulesetKind, id) + if err != nil { + return httpProblem(c, compDesignerError(c, "PutComplianceModuleset", err)) + } + _, cloneName, err := a.ODB.CloneCompModuleset(ctx, id, caller.name, groupID) + if err != nil { + return httpProblem(c, compDesignerError(c, "PutComplianceModuleset", err)) + } + a.afterRulesetChange(c, false) + a.compLog(c, "compliance.moduleset.clone", "cloned moduleset %(o)s from %(n)s", map[string]any{"n": name, "o": cloneName}, "", "") + return compInfo(c, "clone done. new moduleset name %s", cloneName) +} + +// DeleteComplianceModuleset handles DELETE /compliance/modulesets/{modset_id}. +func (a *Api) DeleteComplianceModuleset(c echo.Context, modsetId string) error { + id, err := a.resolveModuleset(c.Request().Context(), modsetId) + if err != nil { + return httpProblem(c, err) + } + return a.deleteModuleset(c, id) +} + +// DeleteComplianceModulesets handles DELETE /compliance/modulesets, the bulk +// form naming the moduleset by the id key of the body. +func (a *Api) DeleteComplianceModulesets(c echo.Context) error { + entry, err := oneEntry(c) + if err != nil { + return httpProblem(c, err) + } + raw, ok := entry["id"] + if !ok { + return httpProblem(c, httpErrorf(http.StatusBadRequest, "The 'id' key is mandatory")) + } + id, err := a.resolveModuleset(c.Request().Context(), fmt.Sprint(raw)) + if err != nil { + return httpProblem(c, err) + } + return a.deleteModuleset(c, id) +} + +// deleteModuleset deletes a moduleset and all its relations, as +// delete_moduleset(): by a CompManager whose group is responsible for it. +func (a *Api) deleteModuleset(c echo.Context, id int64) error { + ctx := c.Request().Context() + if err := checkCompManager(c); err != nil { + return httpProblem(c, err) + } + if err := a.requireModulesetResponsible(ctx, c, id); err != nil { + return httpProblem(c, err) + } + name, err := a.ODB.CompObjectName(ctx, cdb.CompModulesetKind, id) + if err != nil { + return httpProblem(c, compDesignerError(c, "DeleteComplianceModuleset", err)) + } + if err := a.ODB.DeleteCompModuleset(ctx, id); err != nil { + return httpProblem(c, compDesignerError(c, "DeleteComplianceModuleset", err)) + } + a.afterRulesetChange(c, false) + a.compLog(c, "compliance.moduleset.delete", "deleted moduleset %(modset_name)s", map[string]any{"modset_name": name}, "", "") + return compInfo(c, "Moduleset %d deleted", id) +} + +// GetComplianceModulesetUsage handles GET /compliance/modulesets/{modset_id}/usage, +// as the historical rest_get_compliance_moduleset_usage: the modulesets holding +// it as a child. +func (a *Api) GetComplianceModulesetUsage(c echo.Context, modsetId string) error { + id, err := a.publishedModuleset(c, modsetId) + if err != nil { + return httpProblem(c, err) + } + usage, err := a.ODB.CompModulesetUsage(c.Request().Context(), id) + if err != nil { + return httpProblem(c, compDesignerError(c, "GetComplianceModulesetUsage", err)) + } + return c.JSON(http.StatusOK, map[string]any{"data": usage}) +} + +// GetComplianceModulesetAmIResponsible handles GET +// /compliance/modulesets/{modset_id}/am_i_responsible. +func (a *Api) GetComplianceModulesetAmIResponsible(c echo.Context, modsetId string) error { + ctx := c.Request().Context() + id, found, err := a.ODB.CompModulesetID(ctx, modsetId) + if err != nil { + return httpProblem(c, compDesignerError(c, "GetComplianceModulesetAmIResponsible", err)) + } + ok := false + if found { + if ok, err = a.ODB.CompObjectResponsible(ctx, cdb.CompModulesetKind, id, UserGroupsFromContext(c), IsManager(c)); err != nil { + return httpProblem(c, compDesignerError(c, "GetComplianceModulesetAmIResponsible", err)) + } + } + return c.JSON(http.StatusOK, map[string]bool{"data": ok}) +} From e35bdfb3f42bd8b10f841c86ed8f99d6862d2c65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Mon, 28 Sep 2026 13:52:27 +0200 Subject: [PATCH 44/61] Add the compliance moduleset modules endpoints List, show, create, update and delete the modules of a moduleset, as the historical collector's /compliance/modulesets//modules handlers. A module name is unique in its moduleset, the autofix flag is stored as T or F, and changes require the CompManager privilege and the responsibility of the moduleset. --- cdb/db_compliance_modules.go | 95 +++ server/api.yaml | 265 +++++++ server/codegen_server_gen.go | 995 ++++++++++++++++---------- server/codegen_type_gen.go | 156 ++++ server/handlers/compliance_modules.go | 210 ++++++ server/handlers/props_mapping.go | 12 + 6 files changed, 1343 insertions(+), 390 deletions(-) create mode 100644 cdb/db_compliance_modules.go create mode 100644 server/handlers/compliance_modules.go diff --git a/cdb/db_compliance_modules.go b/cdb/db_compliance_modules.go new file mode 100644 index 00000000..949ec31d --- /dev/null +++ b/cdb/db_compliance_modules.go @@ -0,0 +1,95 @@ +package cdb + +import ( + "context" + "database/sql" + "errors" + "fmt" + "strconv" + "strings" +) + +// GetComplianceModulesetModules lists the modules of a moduleset, by name; one +// when modID is set. +func (oDb *DB) GetComplianceModulesetModules(ctx context.Context, modsetID int64, modID *int64, p ListParams) ([]map[string]any, error) { + conds := []string{"comp_moduleset_modules.modset_id = ?"} + args := []any{modsetID} + if modID != nil { + conds = append(conds, "comp_moduleset_modules.id = ?") + args = append(args, *modID) + } + return oDb.listQuery(ctx, "getComplianceModulesetModules", "comp_moduleset_modules", conds, args, "comp_moduleset_modules.modset_mod_name", p) +} + +// CompModulesetModuleID resolves a module of a moduleset given by id or by name, +// as comp_moduleset_module_id(); false when the moduleset has none such. +func (oDb *DB) CompModulesetModuleID(ctx context.Context, modsetID int64, idOrName string) (int64, bool, error) { + var id int64 + var err error + if n, convErr := strconv.ParseInt(idOrName, 10, 64); convErr == nil { + err = oDb.DB.QueryRowContext(ctx, "SELECT id FROM comp_moduleset_modules WHERE modset_id = ? AND id = ?", modsetID, n).Scan(&id) + } else { + err = oDb.DB.QueryRowContext(ctx, "SELECT id FROM comp_moduleset_modules WHERE modset_id = ? AND modset_mod_name = ? LIMIT 1", modsetID, idOrName).Scan(&id) + } + switch { + case errors.Is(err, sql.ErrNoRows): + return 0, false, nil + case err != nil: + return 0, false, fmt.Errorf("compModulesetModuleID: %w", err) + } + return id, true, nil +} + +// CompModulesetModuleName returns the name of a module. +func (oDb *DB) CompModulesetModuleName(ctx context.Context, id int64) (string, error) { + var name string + if err := oDb.DB.QueryRowContext(ctx, "SELECT modset_mod_name FROM comp_moduleset_modules WHERE id = ?", id).Scan(&name); err != nil { + return "", fmt.Errorf("compModulesetModuleName: %w", err) + } + return name, nil +} + +// CreateCompModulesetModule inserts a module in a moduleset; fields holds +// modset_mod_name and optionally autofix. +func (oDb *DB) CreateCompModulesetModule(ctx context.Context, modsetID int64, fields map[string]any, author string) (int64, error) { + cols := []string{"modset_id", "modset_mod_author", "modset_mod_updated"} + vals := []string{"?", "?", "NOW()"} + args := []any{modsetID, author} + for _, k := range sortedKeys(fields) { + cols = append(cols, k) + vals = append(vals, "?") + args = append(args, fields[k]) + } + res, err := oDb.DB.ExecContext(ctx, "INSERT INTO comp_moduleset_modules ("+strings.Join(cols, ", ")+") VALUES ("+strings.Join(vals, ", ")+")", args...) + if err != nil { + return 0, fmt.Errorf("createCompModulesetModule: %w", err) + } + oDb.SetChange("comp_moduleset_modules") + return res.LastInsertId() +} + +// UpdateCompModulesetModule sets the given columns of a module, its author and +// its update date. +func (oDb *DB) UpdateCompModulesetModule(ctx context.Context, id int64, fields map[string]any, author string) error { + sets := []string{"modset_mod_author = ?", "modset_mod_updated = NOW()"} + args := []any{author} + for _, k := range sortedKeys(fields) { + sets = append(sets, k+" = ?") + args = append(args, fields[k]) + } + args = append(args, id) + if _, err := oDb.DB.ExecContext(ctx, "UPDATE comp_moduleset_modules SET "+strings.Join(sets, ", ")+" WHERE id = ?", args...); err != nil { + return fmt.Errorf("updateCompModulesetModule: %w", err) + } + oDb.SetChange("comp_moduleset_modules") + return nil +} + +// DeleteCompModulesetModule deletes a module. +func (oDb *DB) DeleteCompModulesetModule(ctx context.Context, id int64) error { + if _, err := oDb.DB.ExecContext(ctx, "DELETE FROM comp_moduleset_modules WHERE id = ?", id); err != nil { + return fmt.Errorf("deleteCompModulesetModule: %w", err) + } + oDb.SetChange("comp_moduleset_modules") + return nil +} diff --git a/server/api.yaml b/server/api.yaml index 940ec254..2606e9ab 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -11036,6 +11036,232 @@ paths: - basicAuth: [ ] - bearerAuth: [ ] + /compliance/modulesets/{modset_id}/modules: + get: + operationId: GetComplianceModulesetModules + description: | + List the modules of a moduleset published to the user (to one of the user's + groups, or to Everybody). + parameters: + - in: path + name: modset_id + required: true + description: Moduleset id or name + schema: + type: string + - $ref: '#/components/parameters/inQueryProps' + - $ref: '#/components/parameters/inQueryLimit' + - $ref: '#/components/parameters/inQueryOffset' + - $ref: '#/components/parameters/inQueryMeta' + - $ref: '#/components/parameters/inQueryStats' + - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryFilter' + - $ref: '#/components/parameters/inQueryGroupby' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ModulesetModuleListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + post: + operationId: PostComplianceModulesetModules + description: | + Create a module named modset_mod_name in the moduleset; a taken name is a 409. + Requires the CompManager privilege and the responsibility of the moduleset. The + creation is logged. + parameters: + - in: path + name: modset_id + required: true + description: Moduleset id or name + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + modset_mod_name: + type: string + autofix: + description: A boolean, or "T" / "F" as stored. Whether the agent fixes the module on check failure. + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ModulesetModuleListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 409: + $ref: '#/components/responses/409' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /compliance/modulesets/{modset_id}/modules/{mod_id}: + get: + operationId: GetComplianceModulesetModule + description: | + Display a module of a moduleset published to the user. + parameters: + - in: path + name: modset_id + required: true + description: Moduleset id or name + schema: + type: string + - in: path + name: mod_id + required: true + description: Module id or name + schema: + type: string + - $ref: '#/components/parameters/inQueryProps' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ModulesetModuleListResponse' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + post: + operationId: PostComplianceModulesetModule + description: | + Update the name or the autofix flag of a module. Requires the CompManager + privilege and the responsibility of the moduleset. The change is logged. + parameters: + - in: path + name: modset_id + required: true + description: Moduleset id or name + schema: + type: string + - in: path + name: mod_id + required: true + description: Module id or name + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + modset_mod_name: + type: string + autofix: + description: A boolean, or "T" / "F" as stored. Whether the agent fixes the module on check failure. + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ModulesetModuleListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 409: + $ref: '#/components/responses/409' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + delete: + operationId: DeleteComplianceModulesetModule + description: | + Delete a module. Requires the CompManager privilege and the responsibility of + the moduleset. The deletion is logged. + parameters: + - in: path + name: modset_id + required: true + description: Moduleset id or name + schema: + type: string + - in: path + name: mod_id + required: true + description: Module id or name + schema: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + components: responses: @@ -11947,6 +12173,45 @@ components: meta: $ref: '#/components/schemas/ListMeta' + ModulesetModuleRow: + type: object + description: | + A module of a compliance moduleset. Every property is optional: the `props` + query parameter selects which columns the server returns. + properties: + id: + type: integer + modset_id: + type: integer + modset_mod_name: + type: string + autofix: + type: string + nullable: true + modset_mod_author: + type: string + nullable: true + modset_mod_updated: + type: string + + ModulesetModuleListResponse: + type: object + required: + - data + properties: + data: + oneOf: + - type: array + items: + $ref: '#/components/schemas/ModulesetModuleRow' + - type: object + additionalProperties: + type: object + additionalProperties: + type: integer + meta: + $ref: '#/components/schemas/ListMeta' + InstanceListResponse: type: object required: diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index aea4f732..6a426057 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -153,6 +153,21 @@ type ServerInterface interface { // (GET /compliance/modulesets/{modset_id}/am_i_responsible) GetComplianceModulesetAmIResponsible(ctx echo.Context, modsetId string) error + // (GET /compliance/modulesets/{modset_id}/modules) + GetComplianceModulesetModules(ctx echo.Context, modsetId string, params GetComplianceModulesetModulesParams) error + + // (POST /compliance/modulesets/{modset_id}/modules) + PostComplianceModulesetModules(ctx echo.Context, modsetId string) error + + // (DELETE /compliance/modulesets/{modset_id}/modules/{mod_id}) + DeleteComplianceModulesetModule(ctx echo.Context, modsetId string, modId string) error + + // (GET /compliance/modulesets/{modset_id}/modules/{mod_id}) + GetComplianceModulesetModule(ctx echo.Context, modsetId string, modId string, params GetComplianceModulesetModuleParams) error + + // (POST /compliance/modulesets/{modset_id}/modules/{mod_id}) + PostComplianceModulesetModule(ctx echo.Context, modsetId string, modId string) error + // (GET /compliance/modulesets/{modset_id}/usage) GetComplianceModulesetUsage(ctx echo.Context, modsetId string) error @@ -2383,6 +2398,197 @@ func (w *ServerInterfaceWrapper) GetComplianceModulesetAmIResponsible(ctx echo.C return err } +// GetComplianceModulesetModules converts echo context to params. +func (w *ServerInterfaceWrapper) GetComplianceModulesetModules(ctx echo.Context) error { + var err error + // ------------- Path parameter "modset_id" ------------- + var modsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "modset_id", ctx.Param("modset_id"), &modsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter modset_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetComplianceModulesetModulesParams + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // ------------- Optional query parameter "limit" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) + } + + // ------------- Optional query parameter "offset" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) + } + + // ------------- Optional query parameter "meta" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) + } + + // ------------- Optional query parameter "stats" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) + } + + // ------------- Optional query parameter "orderby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) + } + + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + + // ------------- Optional query parameter "groupby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetComplianceModulesetModules(ctx, modsetId, params) + return err +} + +// PostComplianceModulesetModules converts echo context to params. +func (w *ServerInterfaceWrapper) PostComplianceModulesetModules(ctx echo.Context) error { + var err error + // ------------- Path parameter "modset_id" ------------- + var modsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "modset_id", ctx.Param("modset_id"), &modsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter modset_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostComplianceModulesetModules(ctx, modsetId) + return err +} + +// DeleteComplianceModulesetModule converts echo context to params. +func (w *ServerInterfaceWrapper) DeleteComplianceModulesetModule(ctx echo.Context) error { + var err error + // ------------- Path parameter "modset_id" ------------- + var modsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "modset_id", ctx.Param("modset_id"), &modsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter modset_id: %s", err)) + } + + // ------------- Path parameter "mod_id" ------------- + var modId string + + err = runtime.BindStyledParameterWithOptions("simple", "mod_id", ctx.Param("mod_id"), &modId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter mod_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.DeleteComplianceModulesetModule(ctx, modsetId, modId) + return err +} + +// GetComplianceModulesetModule converts echo context to params. +func (w *ServerInterfaceWrapper) GetComplianceModulesetModule(ctx echo.Context) error { + var err error + // ------------- Path parameter "modset_id" ------------- + var modsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "modset_id", ctx.Param("modset_id"), &modsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter modset_id: %s", err)) + } + + // ------------- Path parameter "mod_id" ------------- + var modId string + + err = runtime.BindStyledParameterWithOptions("simple", "mod_id", ctx.Param("mod_id"), &modId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter mod_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetComplianceModulesetModuleParams + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetComplianceModulesetModule(ctx, modsetId, modId, params) + return err +} + +// PostComplianceModulesetModule converts echo context to params. +func (w *ServerInterfaceWrapper) PostComplianceModulesetModule(ctx echo.Context) error { + var err error + // ------------- Path parameter "modset_id" ------------- + var modsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "modset_id", ctx.Param("modset_id"), &modsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter modset_id: %s", err)) + } + + // ------------- Path parameter "mod_id" ------------- + var modId string + + err = runtime.BindStyledParameterWithOptions("simple", "mod_id", ctx.Param("mod_id"), &modId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter mod_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostComplianceModulesetModule(ctx, modsetId, modId) + return err +} + // GetComplianceModulesetUsage converts echo context to params. func (w *ServerInterfaceWrapper) GetComplianceModulesetUsage(ctx echo.Context) error { var err error @@ -12153,6 +12359,11 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.POST(options.BaseURL+"/compliance/modulesets/:modset_id", wrapper.PostComplianceModuleset, options.OperationMiddlewares["PostComplianceModuleset"]...) router.PUT(options.BaseURL+"/compliance/modulesets/:modset_id", wrapper.PutComplianceModuleset, options.OperationMiddlewares["PutComplianceModuleset"]...) router.GET(options.BaseURL+"/compliance/modulesets/:modset_id/am_i_responsible", wrapper.GetComplianceModulesetAmIResponsible, options.OperationMiddlewares["GetComplianceModulesetAmIResponsible"]...) + router.GET(options.BaseURL+"/compliance/modulesets/:modset_id/modules", wrapper.GetComplianceModulesetModules, options.OperationMiddlewares["GetComplianceModulesetModules"]...) + router.POST(options.BaseURL+"/compliance/modulesets/:modset_id/modules", wrapper.PostComplianceModulesetModules, options.OperationMiddlewares["PostComplianceModulesetModules"]...) + router.DELETE(options.BaseURL+"/compliance/modulesets/:modset_id/modules/:mod_id", wrapper.DeleteComplianceModulesetModule, options.OperationMiddlewares["DeleteComplianceModulesetModule"]...) + router.GET(options.BaseURL+"/compliance/modulesets/:modset_id/modules/:mod_id", wrapper.GetComplianceModulesetModule, options.OperationMiddlewares["GetComplianceModulesetModule"]...) + router.POST(options.BaseURL+"/compliance/modulesets/:modset_id/modules/:mod_id", wrapper.PostComplianceModulesetModule, options.OperationMiddlewares["PostComplianceModulesetModule"]...) router.GET(options.BaseURL+"/compliance/modulesets/:modset_id/usage", wrapper.GetComplianceModulesetUsage, options.OperationMiddlewares["GetComplianceModulesetUsage"]...) router.DELETE(options.BaseURL+"/compliance/rulesets", wrapper.DeleteComplianceRulesets, options.OperationMiddlewares["DeleteComplianceRulesets"]...) router.GET(options.BaseURL+"/compliance/rulesets", wrapper.GetComplianceRulesets, options.OperationMiddlewares["GetComplianceRulesets"]...) @@ -12391,396 +12602,400 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "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", - "/wAAAP//", + "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", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index 21743af5..005e41be 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -1005,6 +1005,34 @@ type ModulesetListResponse_Data struct { union json.RawMessage } +// ModulesetModuleListResponse defines model for ModulesetModuleListResponse. +type ModulesetModuleListResponse struct { + Data ModulesetModuleListResponse_Data `json:"data"` + Meta *ListMeta `json:"meta,omitempty"` +} + +// ModulesetModuleListResponseData0 defines model for . +type ModulesetModuleListResponseData0 = []ModulesetModuleRow + +// ModulesetModuleListResponseData1 defines model for . +type ModulesetModuleListResponseData1 map[string]map[string]int + +// ModulesetModuleListResponse_Data defines model for ModulesetModuleListResponse.Data. +type ModulesetModuleListResponse_Data struct { + union json.RawMessage +} + +// ModulesetModuleRow A module of a compliance moduleset. Every property is optional: the `props` +// query parameter selects which columns the server returns. +type ModulesetModuleRow struct { + Autofix *string `json:"autofix,omitempty"` + Id *int `json:"id,omitempty"` + ModsetId *int `json:"modset_id,omitempty"` + ModsetModAuthor *string `json:"modset_mod_author,omitempty"` + ModsetModName *string `json:"modset_mod_name,omitempty"` + ModsetModUpdated *string `json:"modset_mod_updated,omitempty"` +} + // ModulesetRow A compliance moduleset. Every property is optional, as selected by `props`. type ModulesetRow struct { Id *int `json:"id,omitempty"` @@ -2155,6 +2183,66 @@ type PutComplianceModulesetJSONBody struct { // PutComplianceModulesetJSONBodyAction defines parameters for PutComplianceModuleset. type PutComplianceModulesetJSONBodyAction string +// GetComplianceModulesetModulesParams defines parameters for GetComplianceModulesetModules. +type GetComplianceModulesetModulesParams struct { + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` + + // Limit The maximum number of entries to return. 0 means no limit. + Limit *InQueryLimit `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Skip the first entries of the data cursor. + Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` + + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. + Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` + + // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. + Stats *InQueryStats `form:"stats,omitempty" json:"stats,omitempty"` + + // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). + Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` + + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). + Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` +} + +// PostComplianceModulesetModulesJSONBody defines parameters for PostComplianceModulesetModules. +type PostComplianceModulesetModulesJSONBody struct { + // Autofix A boolean, or "T" / "F" as stored. Whether the agent fixes the module on check failure. + Autofix interface{} `json:"autofix,omitempty"` + ModsetModName *string `json:"modset_mod_name,omitempty"` +} + +// GetComplianceModulesetModuleParams defines parameters for GetComplianceModulesetModule. +type GetComplianceModulesetModuleParams struct { + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` +} + +// PostComplianceModulesetModuleJSONBody defines parameters for PostComplianceModulesetModule. +type PostComplianceModulesetModuleJSONBody struct { + // Autofix A boolean, or "T" / "F" as stored. Whether the agent fixes the module on check failure. + Autofix interface{} `json:"autofix,omitempty"` + ModsetModName *string `json:"modset_mod_name,omitempty"` +} + // DeleteComplianceRulesetsJSONBody defines parameters for DeleteComplianceRulesets. type DeleteComplianceRulesetsJSONBody struct { // Id Ruleset id or name @@ -6129,6 +6217,12 @@ type PostComplianceModulesetJSONRequestBody PostComplianceModulesetJSONBody // PutComplianceModulesetJSONRequestBody defines body for PutComplianceModuleset for application/json ContentType. type PutComplianceModulesetJSONRequestBody PutComplianceModulesetJSONBody +// PostComplianceModulesetModulesJSONRequestBody defines body for PostComplianceModulesetModules for application/json ContentType. +type PostComplianceModulesetModulesJSONRequestBody PostComplianceModulesetModulesJSONBody + +// PostComplianceModulesetModuleJSONRequestBody defines body for PostComplianceModulesetModule for application/json ContentType. +type PostComplianceModulesetModuleJSONRequestBody PostComplianceModulesetModuleJSONBody + // DeleteComplianceRulesetsJSONRequestBody defines body for DeleteComplianceRulesets for application/json ContentType. type DeleteComplianceRulesetsJSONRequestBody DeleteComplianceRulesetsJSONBody @@ -7337,6 +7431,68 @@ func (t *ModulesetListResponse_Data) UnmarshalJSON(b []byte) error { return err } +// AsModulesetModuleListResponseData0 returns the union data inside the ModulesetModuleListResponse_Data as a ModulesetModuleListResponseData0 +func (t ModulesetModuleListResponse_Data) AsModulesetModuleListResponseData0() (ModulesetModuleListResponseData0, error) { + var body ModulesetModuleListResponseData0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromModulesetModuleListResponseData0 overwrites any union data inside the ModulesetModuleListResponse_Data as the provided ModulesetModuleListResponseData0 +func (t *ModulesetModuleListResponse_Data) FromModulesetModuleListResponseData0(v ModulesetModuleListResponseData0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeModulesetModuleListResponseData0 performs a merge with any union data inside the ModulesetModuleListResponse_Data, using the provided ModulesetModuleListResponseData0 +func (t *ModulesetModuleListResponse_Data) MergeModulesetModuleListResponseData0(v ModulesetModuleListResponseData0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsModulesetModuleListResponseData1 returns the union data inside the ModulesetModuleListResponse_Data as a ModulesetModuleListResponseData1 +func (t ModulesetModuleListResponse_Data) AsModulesetModuleListResponseData1() (ModulesetModuleListResponseData1, error) { + var body ModulesetModuleListResponseData1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromModulesetModuleListResponseData1 overwrites any union data inside the ModulesetModuleListResponse_Data as the provided ModulesetModuleListResponseData1 +func (t *ModulesetModuleListResponse_Data) FromModulesetModuleListResponseData1(v ModulesetModuleListResponseData1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeModulesetModuleListResponseData1 performs a merge with any union data inside the ModulesetModuleListResponse_Data, using the provided ModulesetModuleListResponseData1 +func (t *ModulesetModuleListResponse_Data) MergeModulesetModuleListResponseData1(v ModulesetModuleListResponseData1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t ModulesetModuleListResponse_Data) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *ModulesetModuleListResponse_Data) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + // AsNodeHardwareListResponseData0 returns the union data inside the NodeHardwareListResponse_Data as a NodeHardwareListResponseData0 func (t NodeHardwareListResponse_Data) AsNodeHardwareListResponseData0() (NodeHardwareListResponseData0, error) { var body NodeHardwareListResponseData0 diff --git a/server/handlers/compliance_modules.go b/server/handlers/compliance_modules.go new file mode 100644 index 00000000..4987f061 --- /dev/null +++ b/server/handlers/compliance_modules.go @@ -0,0 +1,210 @@ +package serverhandlers + +import ( + "context" + "net/http" + "strconv" + + "github.com/labstack/echo/v4" + + "github.com/opensvc/oc3/cdb" + "github.com/opensvc/oc3/server" +) + +// resolveModulesetModule returns the ids of a moduleset and of one of its +// modules, each given by id or by name. +func (a *Api) resolveModulesetModule(ctx context.Context, modsetID, modID string) (int64, int64, error) { + mid, err := a.resolveModuleset(ctx, modsetID) + if err != nil { + return 0, 0, err + } + id, found, err := a.ODB.CompModulesetModuleID(ctx, mid, modID) + if err != nil { + return 0, 0, err + } + if !found { + return 0, 0, httpErrorf(http.StatusNotFound, "module %s not found", modID) + } + return mid, id, nil +} + +// moduleFields checks the settable properties of a module. +func moduleFields(entry map[string]any) (map[string]any, error) { + fields := map[string]any{} + for k, v := range entry { + switch k { + case "modset_mod_name": + name, err := compString(k, v, true) + if err != nil { + return nil, err + } + fields[k] = name + case "autofix": + flag, err := compBool(k, v) + if err != nil { + return nil, err + } + fields[k] = flag + case "id", "modset_id", "modset_mod_author", "modset_mod_updated": + default: + return nil, httpErrorf(http.StatusBadRequest, "unknown module property %s", k) + } + } + return fields, nil +} + +// GetComplianceModulesetModules handles GET /compliance/modulesets/{modset_id}/modules: +// the modules of a moduleset published to the caller. +func (a *Api) GetComplianceModulesetModules(c echo.Context, modsetId string, params server.GetComplianceModulesetModulesParams) error { + mid, err := a.publishedModuleset(c, modsetId) + if err != nil { + return httpProblem(c, err) + } + return a.handleList(c, "GetComplianceModulesetModules", "moduleset_module", + listParams(params.Props, params.Limit, params.Offset, params.Meta, params.Stats, params.Orderby, params.Groupby, params.Filter), + func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetComplianceModulesetModules(ctx, mid, nil, p) + }) +} + +// GetComplianceModulesetModule handles GET /compliance/modulesets/{modset_id}/modules/{mod_id}. +func (a *Api) GetComplianceModulesetModule(c echo.Context, modsetId, modId string, params server.GetComplianceModulesetModuleParams) error { + ctx := c.Request().Context() + mid, id, err := a.resolveModulesetModule(ctx, modsetId, modId) + if err == nil { + err = a.requireModulesetPublished(ctx, c, mid) + } + if err != nil { + return httpProblem(c, err) + } + return a.moduleResponse(c, mid, id, params.Props) +} + +func (a *Api) moduleResponse(c echo.Context, mid, id int64, props *server.InQueryProps) error { + return a.handleItem(c, "GetComplianceModulesetModule", "moduleset_module", "id", strconv.FormatInt(id, 10), listEndpointParams{ + props: props, + }, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetComplianceModulesetModules(ctx, mid, &id, p) + }) +} + +// PostComplianceModulesetModules handles POST /compliance/modulesets/{modset_id}/modules, +// as the historical rest_post_compliance_moduleset_modules: a module named +// modset_mod_name is created, by a CompManager responsible for the moduleset. +func (a *Api) PostComplianceModulesetModules(c echo.Context, modsetId string) error { + entry, err := oneEntry(c) + if err != nil { + return httpProblem(c, err) + } + ctx := c.Request().Context() + mid, err := a.resolveModuleset(ctx, modsetId) + if err == nil { + err = checkCompManager(c) + } + if err == nil { + err = a.requireModulesetResponsible(ctx, c, mid) + } + if err != nil { + return httpProblem(c, err) + } + fields, err := moduleFields(entry) + if err != nil { + return httpProblem(c, err) + } + name, ok := fields["modset_mod_name"].(string) + if !ok { + return httpProblem(c, httpErrorf(http.StatusBadRequest, "modset_mod_name is mandatory in the posted data")) + } + if _, found, err := a.ODB.CompModulesetModuleID(ctx, mid, name); err != nil { + return httpProblem(c, compDesignerError(c, "PostComplianceModulesetModules", err)) + } else if found { + return httpProblem(c, httpErrorf(http.StatusConflict, "this module name already exists")) + } + caller, err := a.formCaller(ctx, c) + if err != nil { + return httpProblem(c, compDesignerError(c, "PostComplianceModulesetModules", err)) + } + id, err := a.ODB.CreateCompModulesetModule(ctx, mid, fields, caller.name) + if err != nil { + return httpProblem(c, compDesignerError(c, "PostComplianceModulesetModules", err)) + } + fields["modset_id"] = mid + a.compLog(c, "compliance.moduleset.module.create", "properties %(data)s", map[string]any{"data": compJSON(fields)}, "", "") + a.afterRulesetChange(c, false) + return a.moduleResponse(c, mid, id, nil) +} + +// PostComplianceModulesetModule handles POST +// /compliance/modulesets/{modset_id}/modules/{mod_id}: a change of the module +// name or autofix flag, by a CompManager responsible for the moduleset. +func (a *Api) PostComplianceModulesetModule(c echo.Context, modsetId, modId string) error { + entry, err := oneEntry(c) + if err != nil { + return httpProblem(c, err) + } + ctx := c.Request().Context() + mid, id, err := a.resolveModulesetModule(ctx, modsetId, modId) + if err == nil { + err = checkCompManager(c) + } + if err == nil { + err = a.requireModulesetResponsible(ctx, c, mid) + } + if err != nil { + return httpProblem(c, err) + } + fields, err := moduleFields(entry) + if err != nil { + return httpProblem(c, err) + } + if name, ok := fields["modset_mod_name"].(string); ok { + if other, found, err := a.ODB.CompModulesetModuleID(ctx, mid, name); err != nil { + return httpProblem(c, compDesignerError(c, "PostComplianceModulesetModule", err)) + } else if found && other != id { + return httpProblem(c, httpErrorf(http.StatusConflict, "this module name already exists")) + } + } + caller, err := a.formCaller(ctx, c) + if err != nil { + return httpProblem(c, compDesignerError(c, "PostComplianceModulesetModule", err)) + } + if err := a.ODB.UpdateCompModulesetModule(ctx, id, fields, caller.name); err != nil { + return httpProblem(c, compDesignerError(c, "PostComplianceModulesetModule", err)) + } + fields["id"] = id + a.compLog(c, "compliance.moduleset.module.change", "changed properties %(data)s", map[string]any{"data": compJSON(fields)}, "", "") + a.afterRulesetChange(c, false) + return a.moduleResponse(c, mid, id, nil) +} + +// DeleteComplianceModulesetModule handles DELETE +// /compliance/modulesets/{modset_id}/modules/{mod_id}, by a CompManager +// responsible for the moduleset, as the historical handler describes it. +func (a *Api) DeleteComplianceModulesetModule(c echo.Context, modsetId, modId string) error { + ctx := c.Request().Context() + mid, id, err := a.resolveModulesetModule(ctx, modsetId, modId) + if err == nil { + err = checkCompManager(c) + } + if err == nil { + err = a.requireModulesetResponsible(ctx, c, mid) + } + if err != nil { + return httpProblem(c, err) + } + name, err := a.ODB.CompModulesetModuleName(ctx, id) + if err != nil { + return httpProblem(c, compDesignerError(c, "DeleteComplianceModulesetModule", err)) + } + modset, err := a.ODB.CompObjectName(ctx, cdb.CompModulesetKind, mid) + if err != nil { + return httpProblem(c, compDesignerError(c, "DeleteComplianceModulesetModule", err)) + } + if err := a.ODB.DeleteCompModulesetModule(ctx, id); err != nil { + return httpProblem(c, compDesignerError(c, "DeleteComplianceModulesetModule", err)) + } + a.compLog(c, "compliance.moduleset.module.delete", "deleted module %(mod_name)s from moduleset %(modset_name)s", + map[string]any{"mod_name": name, "modset_name": modset}, "", "") + a.afterRulesetChange(c, false) + return compInfo(c, "module deleted") +} diff --git a/server/handlers/props_mapping.go b/server/handlers/props_mapping.go index 8d989e63..8f59f436 100644 --- a/server/handlers/props_mapping.go +++ b/server/handlers/props_mapping.go @@ -757,6 +757,18 @@ var propsMapping = map[string]propMapping{ "ruleset_public": colStr(schema.CompRulesetsRulesetPublic), }, }, + // Modules of a compliance moduleset: the agent modules it runs. + "moduleset_module": { + Available: []string{"id", "modset_id", "modset_mod_name", "autofix", "modset_mod_author", "modset_mod_updated"}, + Props: map[string]propDef{ + "id": col(schema.CompModulesetModulesID), + "modset_id": colInt(schema.CompModulesetModulesModsetID), + "modset_mod_name": colStr(schema.CompModulesetModulesModsetModName), + "autofix": colStr(schema.CompModulesetModulesAutofix), + "modset_mod_author": colStr(schema.CompModulesetModulesModsetModAuthor), + "modset_mod_updated": colStr(schema.CompModulesetModulesModsetModUpdated), + }, + }, // Variables of a compliance ruleset: the rules the modules apply. "ruleset_variable": { Available: []string{"id", "ruleset_id", "var_name", "var_class", "var_value", "var_author", "var_updated"}, From 1f18c259e53d911e089aa2bf380cdedbf7f3e0e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Mon, 28 Sep 2026 13:57:14 +0200 Subject: [PATCH 45/61] Add the compliance moduleset composition endpoints Attach and detach child modulesets and rulesets of a moduleset, as the historical /compliance/modulesets//modulesets/ and /compliance/modulesets//rulesets/ handlers. Unlike the historical collector, an attachment closing a moduleset loop is refused, and the attached moduleset or ruleset must be published to the caller. The loop walk is shared with the ruleset composition. --- cdb/db_compliance_moduleset_links.go | 60 ++ cdb/db_compliance_ruleset_links.go | 12 +- server/api.yaml | 177 ++++ server/codegen_server_gen.go | 920 ++++++++++-------- server/handlers/compliance_moduleset_links.go | 163 ++++ 5 files changed, 935 insertions(+), 397 deletions(-) create mode 100644 cdb/db_compliance_moduleset_links.go create mode 100644 server/handlers/compliance_moduleset_links.go diff --git a/cdb/db_compliance_moduleset_links.go b/cdb/db_compliance_moduleset_links.go new file mode 100644 index 00000000..4c210f64 --- /dev/null +++ b/cdb/db_compliance_moduleset_links.go @@ -0,0 +1,60 @@ +package cdb + +import ( + "context" + "fmt" +) + +// CompModulesetChildAttached tells whether child is a child of parent. +func (oDb *DB) CompModulesetChildAttached(ctx context.Context, parent, child int64) (bool, error) { + return oDb.exists(ctx, "compModulesetChildAttached", + "SELECT 1 FROM comp_moduleset_moduleset WHERE parent_modset_id = ? AND child_modset_id = ?", parent, child) +} + +// CompModulesetLoop tells whether attaching child under parent would close a +// loop: child already is an ancestor of parent. +func (oDb *DB) CompModulesetLoop(ctx context.Context, child, parent int64) (bool, error) { + return oDb.compLoop(ctx, "compModulesetLoop", "SELECT parent_modset_id, child_modset_id FROM comp_moduleset_moduleset", child, parent) +} + +// AttachCompModulesetChild makes child a child of parent. +func (oDb *DB) AttachCompModulesetChild(ctx context.Context, parent, child int64) error { + if _, err := oDb.DB.ExecContext(ctx, "INSERT INTO comp_moduleset_moduleset (parent_modset_id, child_modset_id) VALUES (?, ?)", parent, child); err != nil { + return fmt.Errorf("attachCompModulesetChild: %w", err) + } + oDb.SetChange("comp_moduleset_moduleset") + return nil +} + +// DetachCompModulesetChild removes child from the children of parent. +func (oDb *DB) DetachCompModulesetChild(ctx context.Context, parent, child int64) error { + if _, err := oDb.DB.ExecContext(ctx, "DELETE FROM comp_moduleset_moduleset WHERE parent_modset_id = ? AND child_modset_id = ?", parent, child); err != nil { + return fmt.Errorf("detachCompModulesetChild: %w", err) + } + oDb.SetChange("comp_moduleset_moduleset") + return nil +} + +// CompModulesetRulesetAttached tells whether a ruleset is attached to a moduleset. +func (oDb *DB) CompModulesetRulesetAttached(ctx context.Context, modsetID, rulesetID int64) (bool, error) { + return oDb.exists(ctx, "compModulesetRulesetAttached", + "SELECT 1 FROM comp_moduleset_ruleset WHERE modset_id = ? AND ruleset_id = ?", modsetID, rulesetID) +} + +// AttachCompModulesetRuleset attaches a ruleset to a moduleset. +func (oDb *DB) AttachCompModulesetRuleset(ctx context.Context, modsetID, rulesetID int64) error { + if _, err := oDb.DB.ExecContext(ctx, "INSERT INTO comp_moduleset_ruleset (modset_id, ruleset_id) VALUES (?, ?)", modsetID, rulesetID); err != nil { + return fmt.Errorf("attachCompModulesetRuleset: %w", err) + } + oDb.SetChange("comp_moduleset_ruleset") + return nil +} + +// DetachCompModulesetRuleset detaches a ruleset from a moduleset. +func (oDb *DB) DetachCompModulesetRuleset(ctx context.Context, modsetID, rulesetID int64) error { + if _, err := oDb.DB.ExecContext(ctx, "DELETE FROM comp_moduleset_ruleset WHERE modset_id = ? AND ruleset_id = ?", modsetID, rulesetID); err != nil { + return fmt.Errorf("detachCompModulesetRuleset: %w", err) + } + oDb.SetChange("comp_moduleset_ruleset") + return nil +} diff --git a/cdb/db_compliance_ruleset_links.go b/cdb/db_compliance_ruleset_links.go index 9727a112..8f4d7d97 100644 --- a/cdb/db_compliance_ruleset_links.go +++ b/cdb/db_compliance_ruleset_links.go @@ -16,16 +16,22 @@ func (oDb *DB) CompRulesetChildAttached(ctx context.Context, parent, child int64 // CompRulesetLoop tells whether attaching child under parent would close a loop: // child already is an ancestor of parent, as rset_loop(). func (oDb *DB) CompRulesetLoop(ctx context.Context, child, parent int64) (bool, error) { + return oDb.compLoop(ctx, "compRulesetLoop", "SELECT parent_rset_id, child_rset_id FROM comp_rulesets_rulesets", child, parent) +} + +// compLoop tells whether child is an ancestor of parent in the parent-child +// pairs the query returns. +func (oDb *DB) compLoop(ctx context.Context, name, query string, child, parent int64) (bool, error) { parents := map[int64][]int64{} - rows, err := oDb.DB.QueryContext(ctx, "SELECT parent_rset_id, child_rset_id FROM comp_rulesets_rulesets") + rows, err := oDb.DB.QueryContext(ctx, query) if err != nil { - return false, fmt.Errorf("compRulesetLoop: %w", err) + return false, fmt.Errorf("%s: %w", name, err) } for rows.Next() { var p, c int64 if err := rows.Scan(&p, &c); err != nil { _ = rows.Close() - return false, fmt.Errorf("compRulesetLoop: %w", err) + return false, fmt.Errorf("%s: %w", name, err) } parents[c] = append(parents[c], p) } diff --git a/server/api.yaml b/server/api.yaml index 2606e9ab..655252c6 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -11262,6 +11262,183 @@ paths: - basicAuth: [ ] - bearerAuth: [ ] + /compliance/modulesets/{modset_id}/modulesets/{child_modset_id}: + post: + operationId: PostComplianceModulesetModuleset + description: | + Attach a moduleset published to the user to a moduleset, as a child. Requires + the CompManager privilege and the responsibility of the parent. An attachment + closing a loop is a 409; an existing one answers an info message. The change is + logged. + parameters: + - in: path + name: modset_id + required: true + description: Moduleset id or name + schema: + type: string + - in: path + name: child_modset_id + required: true + description: Child moduleset id or name + schema: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 409: + $ref: '#/components/responses/409' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + delete: + operationId: DeleteComplianceModulesetModuleset + description: | + Detach a child moduleset from a moduleset. Requires the CompManager privilege + and the responsibility of the parent. The change is logged. + parameters: + - in: path + name: modset_id + required: true + description: Moduleset id or name + schema: + type: string + - in: path + name: child_modset_id + required: true + description: Child moduleset id or name + schema: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /compliance/modulesets/{modset_id}/rulesets/{rset_id}: + post: + operationId: PostComplianceModulesetRuleset + description: | + Attach a ruleset published to the user to a moduleset: its variables join the + execution environment of the moduleset's modules. Requires the CompManager + privilege and the responsibility of the moduleset. An existing attachment + answers an info message. The change is logged. + parameters: + - in: path + name: modset_id + required: true + description: Moduleset id or name + schema: + type: string + - in: path + name: rset_id + required: true + description: Ruleset id or name + schema: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + delete: + operationId: DeleteComplianceModulesetRuleset + description: | + Detach a ruleset published to the user from a moduleset. Requires the + CompManager privilege and the responsibility of the moduleset. The change is + logged. + parameters: + - in: path + name: modset_id + required: true + description: Moduleset id or name + schema: + type: string + - in: path + name: rset_id + required: true + description: Ruleset id or name + schema: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + components: responses: diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index 6a426057..4d578016 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -168,6 +168,18 @@ type ServerInterface interface { // (POST /compliance/modulesets/{modset_id}/modules/{mod_id}) PostComplianceModulesetModule(ctx echo.Context, modsetId string, modId string) error + // (DELETE /compliance/modulesets/{modset_id}/modulesets/{child_modset_id}) + DeleteComplianceModulesetModuleset(ctx echo.Context, modsetId string, childModsetId string) error + + // (POST /compliance/modulesets/{modset_id}/modulesets/{child_modset_id}) + PostComplianceModulesetModuleset(ctx echo.Context, modsetId string, childModsetId string) error + + // (DELETE /compliance/modulesets/{modset_id}/rulesets/{rset_id}) + DeleteComplianceModulesetRuleset(ctx echo.Context, modsetId string, rsetId string) error + + // (POST /compliance/modulesets/{modset_id}/rulesets/{rset_id}) + PostComplianceModulesetRuleset(ctx echo.Context, modsetId string, rsetId string) error + // (GET /compliance/modulesets/{modset_id}/usage) GetComplianceModulesetUsage(ctx echo.Context, modsetId string) error @@ -2589,6 +2601,118 @@ func (w *ServerInterfaceWrapper) PostComplianceModulesetModule(ctx echo.Context) return err } +// DeleteComplianceModulesetModuleset converts echo context to params. +func (w *ServerInterfaceWrapper) DeleteComplianceModulesetModuleset(ctx echo.Context) error { + var err error + // ------------- Path parameter "modset_id" ------------- + var modsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "modset_id", ctx.Param("modset_id"), &modsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter modset_id: %s", err)) + } + + // ------------- Path parameter "child_modset_id" ------------- + var childModsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "child_modset_id", ctx.Param("child_modset_id"), &childModsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter child_modset_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.DeleteComplianceModulesetModuleset(ctx, modsetId, childModsetId) + return err +} + +// PostComplianceModulesetModuleset converts echo context to params. +func (w *ServerInterfaceWrapper) PostComplianceModulesetModuleset(ctx echo.Context) error { + var err error + // ------------- Path parameter "modset_id" ------------- + var modsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "modset_id", ctx.Param("modset_id"), &modsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter modset_id: %s", err)) + } + + // ------------- Path parameter "child_modset_id" ------------- + var childModsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "child_modset_id", ctx.Param("child_modset_id"), &childModsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter child_modset_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostComplianceModulesetModuleset(ctx, modsetId, childModsetId) + return err +} + +// DeleteComplianceModulesetRuleset converts echo context to params. +func (w *ServerInterfaceWrapper) DeleteComplianceModulesetRuleset(ctx echo.Context) error { + var err error + // ------------- Path parameter "modset_id" ------------- + var modsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "modset_id", ctx.Param("modset_id"), &modsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter modset_id: %s", err)) + } + + // ------------- Path parameter "rset_id" ------------- + var rsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "rset_id", ctx.Param("rset_id"), &rsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter rset_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.DeleteComplianceModulesetRuleset(ctx, modsetId, rsetId) + return err +} + +// PostComplianceModulesetRuleset converts echo context to params. +func (w *ServerInterfaceWrapper) PostComplianceModulesetRuleset(ctx echo.Context) error { + var err error + // ------------- Path parameter "modset_id" ------------- + var modsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "modset_id", ctx.Param("modset_id"), &modsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter modset_id: %s", err)) + } + + // ------------- Path parameter "rset_id" ------------- + var rsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "rset_id", ctx.Param("rset_id"), &rsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter rset_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostComplianceModulesetRuleset(ctx, modsetId, rsetId) + return err +} + // GetComplianceModulesetUsage converts echo context to params. func (w *ServerInterfaceWrapper) GetComplianceModulesetUsage(ctx echo.Context) error { var err error @@ -12364,6 +12488,10 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.DELETE(options.BaseURL+"/compliance/modulesets/:modset_id/modules/:mod_id", wrapper.DeleteComplianceModulesetModule, options.OperationMiddlewares["DeleteComplianceModulesetModule"]...) router.GET(options.BaseURL+"/compliance/modulesets/:modset_id/modules/:mod_id", wrapper.GetComplianceModulesetModule, options.OperationMiddlewares["GetComplianceModulesetModule"]...) router.POST(options.BaseURL+"/compliance/modulesets/:modset_id/modules/:mod_id", wrapper.PostComplianceModulesetModule, options.OperationMiddlewares["PostComplianceModulesetModule"]...) + router.DELETE(options.BaseURL+"/compliance/modulesets/:modset_id/modulesets/:child_modset_id", wrapper.DeleteComplianceModulesetModuleset, options.OperationMiddlewares["DeleteComplianceModulesetModuleset"]...) + router.POST(options.BaseURL+"/compliance/modulesets/:modset_id/modulesets/:child_modset_id", wrapper.PostComplianceModulesetModuleset, options.OperationMiddlewares["PostComplianceModulesetModuleset"]...) + router.DELETE(options.BaseURL+"/compliance/modulesets/:modset_id/rulesets/:rset_id", wrapper.DeleteComplianceModulesetRuleset, options.OperationMiddlewares["DeleteComplianceModulesetRuleset"]...) + router.POST(options.BaseURL+"/compliance/modulesets/:modset_id/rulesets/:rset_id", wrapper.PostComplianceModulesetRuleset, options.OperationMiddlewares["PostComplianceModulesetRuleset"]...) router.GET(options.BaseURL+"/compliance/modulesets/:modset_id/usage", wrapper.GetComplianceModulesetUsage, options.OperationMiddlewares["GetComplianceModulesetUsage"]...) router.DELETE(options.BaseURL+"/compliance/rulesets", wrapper.DeleteComplianceRulesets, options.OperationMiddlewares["DeleteComplianceRulesets"]...) router.GET(options.BaseURL+"/compliance/rulesets", wrapper.GetComplianceRulesets, options.OperationMiddlewares["GetComplianceRulesets"]...) @@ -12602,400 +12730,404 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "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", + "9pQiG12OxhejPz/9+f8HAAD//w==", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/handlers/compliance_moduleset_links.go b/server/handlers/compliance_moduleset_links.go new file mode 100644 index 00000000..636e5275 --- /dev/null +++ b/server/handlers/compliance_moduleset_links.go @@ -0,0 +1,163 @@ +package serverhandlers + +import ( + "net/http" + + "github.com/labstack/echo/v4" + + "github.com/opensvc/oc3/cdb" +) + +// modulesetParent resolves the moduleset a composition change applies to, with +// its name, and checks the caller is a CompManager responsible for it. +func (a *Api) modulesetParent(c echo.Context, modsetID string) (int64, string, error) { + ctx := c.Request().Context() + id, err := a.resolveModuleset(ctx, modsetID) + if err == nil { + err = checkCompManager(c) + } + if err == nil { + err = a.requireModulesetResponsible(ctx, c, id) + } + if err != nil { + return 0, "", err + } + name, err := a.ODB.CompObjectName(ctx, cdb.CompModulesetKind, id) + if err != nil { + return 0, "", compDesignerError(c, "read the moduleset name", err) + } + return id, name, nil +} + +// PostComplianceModulesetModuleset handles POST +// /compliance/modulesets/{modset_id}/modulesets/{child_modset_id}, as the +// historical attach_moduleset_to_moduleset(): by a CompManager responsible for +// the parent, a moduleset published to them becomes a child of another, unless +// that would close a loop. +func (a *Api) PostComplianceModulesetModuleset(c echo.Context, modsetId, childModsetId string) error { + ctx := c.Request().Context() + parent, parentName, err := a.modulesetParent(c, modsetId) + if err != nil { + return httpProblem(c, err) + } + child, err := a.publishedModuleset(c, childModsetId) + if err != nil { + return httpProblem(c, err) + } + if parent == child { + return httpProblem(c, httpErrorf(http.StatusBadRequest, "abort action to avoid introducing a recursion loop")) + } + if attached, err := a.ODB.CompModulesetChildAttached(ctx, parent, child); err != nil { + return httpProblem(c, compDesignerError(c, "PostComplianceModulesetModuleset", err)) + } else if attached { + return compInfo(c, "already attached") + } + if loop, err := a.ODB.CompModulesetLoop(ctx, child, parent); err != nil { + return httpProblem(c, compDesignerError(c, "PostComplianceModulesetModuleset", err)) + } else if loop { + return httpProblem(c, httpErrorf(http.StatusConflict, "the parent moduleset is already a child of the encapsulated moduleset. abort encapsulation not to cause infinite recursion")) + } + childName, err := a.ODB.CompObjectName(ctx, cdb.CompModulesetKind, child) + if err != nil { + return httpProblem(c, compDesignerError(c, "PostComplianceModulesetModuleset", err)) + } + if err := a.ODB.AttachCompModulesetChild(ctx, parent, child); err != nil { + return httpProblem(c, compDesignerError(c, "PostComplianceModulesetModuleset", err)) + } + a.compLog(c, "compliance.moduleset.moduleset.attach", "attached moduleset %(child_modset_name)s to moduleset %(parent_modset_name)s", + map[string]any{"child_modset_name": childName, "parent_modset_name": parentName}, "", "") + a.afterRulesetChange(c, false) + return compInfo(c, "moduleset attached") +} + +// DeleteComplianceModulesetModuleset handles DELETE +// /compliance/modulesets/{modset_id}/modulesets/{child_modset_id}, as the +// historical detach_moduleset_from_moduleset(), by a CompManager responsible for +// the parent. +func (a *Api) DeleteComplianceModulesetModuleset(c echo.Context, modsetId, childModsetId string) error { + ctx := c.Request().Context() + parent, parentName, err := a.modulesetParent(c, modsetId) + if err != nil { + return httpProblem(c, err) + } + child, err := a.resolveModuleset(ctx, childModsetId) + if err != nil { + return httpProblem(c, err) + } + childName, err := a.ODB.CompObjectName(ctx, cdb.CompModulesetKind, child) + if err != nil { + return httpProblem(c, compDesignerError(c, "DeleteComplianceModulesetModuleset", err)) + } + if err := a.ODB.DetachCompModulesetChild(ctx, parent, child); err != nil { + return httpProblem(c, compDesignerError(c, "DeleteComplianceModulesetModuleset", err)) + } + a.compLog(c, "compliance.moduleset.detach", "detach moduleset %(child_modset_name)s from moduleset %(parent_modset_name)s", + map[string]any{"child_modset_name": childName, "parent_modset_name": parentName}, "", "") + a.afterRulesetChange(c, false) + return compInfo(c, "moduleset detached") +} + +// PostComplianceModulesetRuleset handles POST +// /compliance/modulesets/{modset_id}/rulesets/{rset_id}, as the historical +// attach_ruleset_to_moduleset(): by a CompManager responsible for the moduleset, +// a ruleset published to them adds its variables to the modules' environment. +func (a *Api) PostComplianceModulesetRuleset(c echo.Context, modsetId, rsetId string) error { + ctx := c.Request().Context() + modset, modsetName, err := a.modulesetParent(c, modsetId) + if err != nil { + return httpProblem(c, err) + } + rset, err := a.resolveRuleset(ctx, rsetId) + if err == nil { + err = a.requireRulesetPublished(ctx, c, rset) + } + if err != nil { + return httpProblem(c, err) + } + if attached, err := a.ODB.CompModulesetRulesetAttached(ctx, modset, rset); err != nil { + return httpProblem(c, compDesignerError(c, "PostComplianceModulesetRuleset", err)) + } else if attached { + return compInfo(c, "already attached") + } + names, err := a.rulesetNames(c, rset) + if err != nil { + return httpProblem(c, err) + } + if err := a.ODB.AttachCompModulesetRuleset(ctx, modset, rset); err != nil { + return httpProblem(c, compDesignerError(c, "PostComplianceModulesetRuleset", err)) + } + a.compLog(c, "compliance.moduleset.ruleset.attach", "attach ruleset %(rset_name)s to moduleset %(modset_name)s", + map[string]any{"rset_name": names[0], "modset_name": modsetName}, "", "") + a.afterRulesetChange(c, false) + return compInfo(c, "ruleset attached") +} + +// DeleteComplianceModulesetRuleset handles DELETE +// /compliance/modulesets/{modset_id}/rulesets/{rset_id}, as the historical +// detach_ruleset_from_moduleset(): by a CompManager responsible for the +// moduleset, the ruleset being published to them. +func (a *Api) DeleteComplianceModulesetRuleset(c echo.Context, modsetId, rsetId string) error { + ctx := c.Request().Context() + modset, modsetName, err := a.modulesetParent(c, modsetId) + if err != nil { + return httpProblem(c, err) + } + rset, err := a.resolveRuleset(ctx, rsetId) + if err == nil { + err = a.requireRulesetPublished(ctx, c, rset) + } + if err != nil { + return httpProblem(c, err) + } + names, err := a.rulesetNames(c, rset) + if err != nil { + return httpProblem(c, err) + } + if err := a.ODB.DetachCompModulesetRuleset(ctx, modset, rset); err != nil { + return httpProblem(c, compDesignerError(c, "DeleteComplianceModulesetRuleset", err)) + } + a.compLog(c, "compliance.ruleset.detach", "detach ruleset %(rset_name)s from moduleset %(modset_name)s", + map[string]any{"rset_name": names[0], "modset_name": modsetName}, "", "") + a.afterRulesetChange(c, false) + return compInfo(c, "ruleset detached") +} From a79aad8b5db3f62a815659cee84151126dd0c45d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Mon, 28 Sep 2026 13:59:31 +0200 Subject: [PATCH 46/61] Read the form-encoded body of DELETE requests The standard library parses the form body of POST, PUT and PATCH requests only, so a DELETE sent with curl -d, as the historical examples of the bulk detach endpoints do, reached the handlers without its keys. --- server/handlers/forms_common.go | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/server/handlers/forms_common.go b/server/handlers/forms_common.go index 9770a9da..13bc3e5f 100644 --- a/server/handlers/forms_common.go +++ b/server/handlers/forms_common.go @@ -6,8 +6,10 @@ import ( "encoding/json" "errors" "fmt" + "io" "log/slog" "net/http" + "net/url" "strconv" "strings" @@ -67,7 +69,7 @@ func (a *Api) formCaller(ctx context.Context, c echo.Context) (formCaller, error func decodeEntries(c echo.Context) (entries []map[string]any, isList bool, err error) { contentType := c.Request().Header.Get(echo.HeaderContentType) if strings.HasPrefix(contentType, echo.MIMEApplicationForm) || strings.HasPrefix(contentType, echo.MIMEMultipartForm) { - values, err := c.FormParams() + values, err := formValues(c, contentType) if err != nil { return nil, false, httpErrorf(http.StatusBadRequest, "invalid request body: %s", err) } @@ -98,6 +100,20 @@ func decodeEntries(c echo.Context) (entries []map[string]any, isList bool, err e return []map[string]any{entry}, false, nil } +// formValues reads a form-encoded body. The standard library parses the body of +// POST, PUT and PATCH requests only, while the historical examples also send +// DELETE requests with curl -d, so an url-encoded body is read directly. +func formValues(c echo.Context, contentType string) (url.Values, error) { + if !strings.HasPrefix(contentType, echo.MIMEApplicationForm) { + return c.FormParams() + } + b, err := io.ReadAll(c.Request().Body) + if err != nil { + return nil, err + } + return url.ParseQuery(string(b)) +} + // entryString reads a key of a decoded entry as a string, as posted form // variables are. func entryString(entry map[string]any, key string) (string, bool) { From 6bcc4f98c3b3e5fe27b17a94aa3e6924c30e6454 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Mon, 28 Sep 2026 13:59:31 +0200 Subject: [PATCH 47/61] Add the compliance moduleset publications and responsibles endpoints List, attach and detach the publication and responsible groups of a moduleset, by path or with the bulk /compliance/modulesets_publications and /compliance/modulesets_responsibles forms, sharing the ruleset rules: a CompManager responsible for the moduleset may attach only their own groups, and Everybody may not be made responsible. --- server/api.yaml | 430 ++++++++++ server/codegen_server_gen.go | 1159 ++++++++++++++++++--------- server/codegen_type_gen.go | 128 +++ server/handlers/compliance_teams.go | 76 ++ 4 files changed, 1395 insertions(+), 398 deletions(-) diff --git a/server/api.yaml b/server/api.yaml index 655252c6..57bf700f 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -11439,6 +11439,436 @@ paths: - basicAuth: [ ] - bearerAuth: [ ] + /compliance/modulesets/{modset_id}/publications: + get: + operationId: GetComplianceModulesetPublications + description: | + List the publication groups of a moduleset; a non-manager sees only the ones they are + a member of. + parameters: + - in: path + name: modset_id + required: true + description: Moduleset id or name + schema: + type: string + - $ref: '#/components/parameters/inQueryProps' + - $ref: '#/components/parameters/inQueryLimit' + - $ref: '#/components/parameters/inQueryOffset' + - $ref: '#/components/parameters/inQueryMeta' + - $ref: '#/components/parameters/inQueryStats' + - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryFilter' + - $ref: '#/components/parameters/inQueryGroupby' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/GroupListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /compliance/modulesets/{modset_id}/publications/{group_id}: + post: + operationId: PostComplianceModulesetPublication + description: | + Make a group a publication group of the moduleset. Requires the CompManager privilege + and the responsibility of the moduleset; a non-manager may attach only one of their + groups. Everybody may not be made responsible. The change is logged. + parameters: + - in: path + name: modset_id + required: true + description: Moduleset id or name + schema: + type: string + - in: path + name: group_id + required: true + description: Group id or role + schema: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + delete: + operationId: DeleteComplianceModulesetPublication + description: | + Remove a publication group from the moduleset. Requires the CompManager privilege and + the responsibility of the moduleset. The change is logged. + parameters: + - in: path + name: modset_id + required: true + description: Moduleset id or name + schema: + type: string + - in: path + name: group_id + required: true + description: Group id or role + schema: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /compliance/modulesets_publications: + post: + operationId: PostComplianceModulesetsPublications + description: | + Attach a publication group to a moduleset, as + POST /compliance/modulesets/{modset_id}/publications/{group_id}, both named in the body. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [modset_id, group_id] + properties: + modset_id: + description: Moduleset id or name + group_id: + description: Group id or role + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + delete: + operationId: DeleteComplianceModulesetsPublications + description: | + Detach a publication group from a moduleset, as + DELETE /compliance/modulesets/{modset_id}/publications/{group_id}, both named in the body. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [modset_id, group_id] + properties: + modset_id: + description: Moduleset id or name + group_id: + description: Group id or role + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /compliance/modulesets/{modset_id}/responsibles: + get: + operationId: GetComplianceModulesetResponsibles + description: | + List the responsible groups of a moduleset; a non-manager sees only the ones they are + a member of. + parameters: + - in: path + name: modset_id + required: true + description: Moduleset id or name + schema: + type: string + - $ref: '#/components/parameters/inQueryProps' + - $ref: '#/components/parameters/inQueryLimit' + - $ref: '#/components/parameters/inQueryOffset' + - $ref: '#/components/parameters/inQueryMeta' + - $ref: '#/components/parameters/inQueryStats' + - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryFilter' + - $ref: '#/components/parameters/inQueryGroupby' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/GroupListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /compliance/modulesets/{modset_id}/responsibles/{group_id}: + post: + operationId: PostComplianceModulesetResponsible + description: | + Make a group a responsible group of the moduleset. Requires the CompManager privilege + and the responsibility of the moduleset; a non-manager may attach only one of their + groups. Everybody may not be made responsible. The change is logged. + parameters: + - in: path + name: modset_id + required: true + description: Moduleset id or name + schema: + type: string + - in: path + name: group_id + required: true + description: Group id or role + schema: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + delete: + operationId: DeleteComplianceModulesetResponsible + description: | + Remove a responsible group from the moduleset. Requires the CompManager privilege and + the responsibility of the moduleset. The change is logged. + parameters: + - in: path + name: modset_id + required: true + description: Moduleset id or name + schema: + type: string + - in: path + name: group_id + required: true + description: Group id or role + schema: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /compliance/modulesets_responsibles: + post: + operationId: PostComplianceModulesetsResponsibles + description: | + Attach a responsible group to a moduleset, as + POST /compliance/modulesets/{modset_id}/responsibles/{group_id}, both named in the body. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [modset_id, group_id] + properties: + modset_id: + description: Moduleset id or name + group_id: + description: Group id or role + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + delete: + operationId: DeleteComplianceModulesetsResponsibles + description: | + Detach a responsible group from a moduleset, as + DELETE /compliance/modulesets/{modset_id}/responsibles/{group_id}, both named in the body. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [modset_id, group_id] + properties: + modset_id: + description: Moduleset id or name + group_id: + description: Group id or role + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + components: responses: diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index 4d578016..f7066a60 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -174,6 +174,24 @@ type ServerInterface interface { // (POST /compliance/modulesets/{modset_id}/modulesets/{child_modset_id}) PostComplianceModulesetModuleset(ctx echo.Context, modsetId string, childModsetId string) error + // (GET /compliance/modulesets/{modset_id}/publications) + GetComplianceModulesetPublications(ctx echo.Context, modsetId string, params GetComplianceModulesetPublicationsParams) error + + // (DELETE /compliance/modulesets/{modset_id}/publications/{group_id}) + DeleteComplianceModulesetPublication(ctx echo.Context, modsetId string, groupId string) error + + // (POST /compliance/modulesets/{modset_id}/publications/{group_id}) + PostComplianceModulesetPublication(ctx echo.Context, modsetId string, groupId string) error + + // (GET /compliance/modulesets/{modset_id}/responsibles) + GetComplianceModulesetResponsibles(ctx echo.Context, modsetId string, params GetComplianceModulesetResponsiblesParams) error + + // (DELETE /compliance/modulesets/{modset_id}/responsibles/{group_id}) + DeleteComplianceModulesetResponsible(ctx echo.Context, modsetId string, groupId string) error + + // (POST /compliance/modulesets/{modset_id}/responsibles/{group_id}) + PostComplianceModulesetResponsible(ctx echo.Context, modsetId string, groupId string) error + // (DELETE /compliance/modulesets/{modset_id}/rulesets/{rset_id}) DeleteComplianceModulesetRuleset(ctx echo.Context, modsetId string, rsetId string) error @@ -183,6 +201,18 @@ type ServerInterface interface { // (GET /compliance/modulesets/{modset_id}/usage) GetComplianceModulesetUsage(ctx echo.Context, modsetId string) error + // (DELETE /compliance/modulesets_publications) + DeleteComplianceModulesetsPublications(ctx echo.Context) error + + // (POST /compliance/modulesets_publications) + PostComplianceModulesetsPublications(ctx echo.Context) error + + // (DELETE /compliance/modulesets_responsibles) + DeleteComplianceModulesetsResponsibles(ctx echo.Context) error + + // (POST /compliance/modulesets_responsibles) + PostComplianceModulesetsResponsibles(ctx echo.Context) error + // (DELETE /compliance/rulesets) DeleteComplianceRulesets(ctx echo.Context) error @@ -2657,6 +2687,274 @@ func (w *ServerInterfaceWrapper) PostComplianceModulesetModuleset(ctx echo.Conte return err } +// GetComplianceModulesetPublications converts echo context to params. +func (w *ServerInterfaceWrapper) GetComplianceModulesetPublications(ctx echo.Context) error { + var err error + // ------------- Path parameter "modset_id" ------------- + var modsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "modset_id", ctx.Param("modset_id"), &modsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter modset_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetComplianceModulesetPublicationsParams + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // ------------- Optional query parameter "limit" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) + } + + // ------------- Optional query parameter "offset" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) + } + + // ------------- Optional query parameter "meta" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) + } + + // ------------- Optional query parameter "stats" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) + } + + // ------------- Optional query parameter "orderby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) + } + + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + + // ------------- Optional query parameter "groupby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetComplianceModulesetPublications(ctx, modsetId, params) + return err +} + +// DeleteComplianceModulesetPublication converts echo context to params. +func (w *ServerInterfaceWrapper) DeleteComplianceModulesetPublication(ctx echo.Context) error { + var err error + // ------------- Path parameter "modset_id" ------------- + var modsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "modset_id", ctx.Param("modset_id"), &modsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter modset_id: %s", err)) + } + + // ------------- Path parameter "group_id" ------------- + var groupId string + + err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter group_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.DeleteComplianceModulesetPublication(ctx, modsetId, groupId) + return err +} + +// PostComplianceModulesetPublication converts echo context to params. +func (w *ServerInterfaceWrapper) PostComplianceModulesetPublication(ctx echo.Context) error { + var err error + // ------------- Path parameter "modset_id" ------------- + var modsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "modset_id", ctx.Param("modset_id"), &modsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter modset_id: %s", err)) + } + + // ------------- Path parameter "group_id" ------------- + var groupId string + + err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter group_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostComplianceModulesetPublication(ctx, modsetId, groupId) + return err +} + +// GetComplianceModulesetResponsibles converts echo context to params. +func (w *ServerInterfaceWrapper) GetComplianceModulesetResponsibles(ctx echo.Context) error { + var err error + // ------------- Path parameter "modset_id" ------------- + var modsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "modset_id", ctx.Param("modset_id"), &modsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter modset_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetComplianceModulesetResponsiblesParams + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // ------------- Optional query parameter "limit" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) + } + + // ------------- Optional query parameter "offset" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) + } + + // ------------- Optional query parameter "meta" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) + } + + // ------------- Optional query parameter "stats" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) + } + + // ------------- Optional query parameter "orderby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) + } + + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + + // ------------- Optional query parameter "groupby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetComplianceModulesetResponsibles(ctx, modsetId, params) + return err +} + +// DeleteComplianceModulesetResponsible converts echo context to params. +func (w *ServerInterfaceWrapper) DeleteComplianceModulesetResponsible(ctx echo.Context) error { + var err error + // ------------- Path parameter "modset_id" ------------- + var modsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "modset_id", ctx.Param("modset_id"), &modsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter modset_id: %s", err)) + } + + // ------------- Path parameter "group_id" ------------- + var groupId string + + err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter group_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.DeleteComplianceModulesetResponsible(ctx, modsetId, groupId) + return err +} + +// PostComplianceModulesetResponsible converts echo context to params. +func (w *ServerInterfaceWrapper) PostComplianceModulesetResponsible(ctx echo.Context) error { + var err error + // ------------- Path parameter "modset_id" ------------- + var modsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "modset_id", ctx.Param("modset_id"), &modsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter modset_id: %s", err)) + } + + // ------------- Path parameter "group_id" ------------- + var groupId string + + err = runtime.BindStyledParameterWithOptions("simple", "group_id", ctx.Param("group_id"), &groupId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter group_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostComplianceModulesetResponsible(ctx, modsetId, groupId) + return err +} + // DeleteComplianceModulesetRuleset converts echo context to params. func (w *ServerInterfaceWrapper) DeleteComplianceModulesetRuleset(ctx echo.Context) error { var err error @@ -2733,6 +3031,58 @@ func (w *ServerInterfaceWrapper) GetComplianceModulesetUsage(ctx echo.Context) e return err } +// DeleteComplianceModulesetsPublications converts echo context to params. +func (w *ServerInterfaceWrapper) DeleteComplianceModulesetsPublications(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.DeleteComplianceModulesetsPublications(ctx) + return err +} + +// PostComplianceModulesetsPublications converts echo context to params. +func (w *ServerInterfaceWrapper) PostComplianceModulesetsPublications(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostComplianceModulesetsPublications(ctx) + return err +} + +// DeleteComplianceModulesetsResponsibles converts echo context to params. +func (w *ServerInterfaceWrapper) DeleteComplianceModulesetsResponsibles(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.DeleteComplianceModulesetsResponsibles(ctx) + return err +} + +// PostComplianceModulesetsResponsibles converts echo context to params. +func (w *ServerInterfaceWrapper) PostComplianceModulesetsResponsibles(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostComplianceModulesetsResponsibles(ctx) + return err +} + // DeleteComplianceRulesets converts echo context to params. func (w *ServerInterfaceWrapper) DeleteComplianceRulesets(ctx echo.Context) error { var err error @@ -12490,9 +12840,19 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.POST(options.BaseURL+"/compliance/modulesets/:modset_id/modules/:mod_id", wrapper.PostComplianceModulesetModule, options.OperationMiddlewares["PostComplianceModulesetModule"]...) router.DELETE(options.BaseURL+"/compliance/modulesets/:modset_id/modulesets/:child_modset_id", wrapper.DeleteComplianceModulesetModuleset, options.OperationMiddlewares["DeleteComplianceModulesetModuleset"]...) router.POST(options.BaseURL+"/compliance/modulesets/:modset_id/modulesets/:child_modset_id", wrapper.PostComplianceModulesetModuleset, options.OperationMiddlewares["PostComplianceModulesetModuleset"]...) + router.GET(options.BaseURL+"/compliance/modulesets/:modset_id/publications", wrapper.GetComplianceModulesetPublications, options.OperationMiddlewares["GetComplianceModulesetPublications"]...) + router.DELETE(options.BaseURL+"/compliance/modulesets/:modset_id/publications/:group_id", wrapper.DeleteComplianceModulesetPublication, options.OperationMiddlewares["DeleteComplianceModulesetPublication"]...) + router.POST(options.BaseURL+"/compliance/modulesets/:modset_id/publications/:group_id", wrapper.PostComplianceModulesetPublication, options.OperationMiddlewares["PostComplianceModulesetPublication"]...) + router.GET(options.BaseURL+"/compliance/modulesets/:modset_id/responsibles", wrapper.GetComplianceModulesetResponsibles, options.OperationMiddlewares["GetComplianceModulesetResponsibles"]...) + router.DELETE(options.BaseURL+"/compliance/modulesets/:modset_id/responsibles/:group_id", wrapper.DeleteComplianceModulesetResponsible, options.OperationMiddlewares["DeleteComplianceModulesetResponsible"]...) + router.POST(options.BaseURL+"/compliance/modulesets/:modset_id/responsibles/:group_id", wrapper.PostComplianceModulesetResponsible, options.OperationMiddlewares["PostComplianceModulesetResponsible"]...) router.DELETE(options.BaseURL+"/compliance/modulesets/:modset_id/rulesets/:rset_id", wrapper.DeleteComplianceModulesetRuleset, options.OperationMiddlewares["DeleteComplianceModulesetRuleset"]...) router.POST(options.BaseURL+"/compliance/modulesets/:modset_id/rulesets/:rset_id", wrapper.PostComplianceModulesetRuleset, options.OperationMiddlewares["PostComplianceModulesetRuleset"]...) router.GET(options.BaseURL+"/compliance/modulesets/:modset_id/usage", wrapper.GetComplianceModulesetUsage, options.OperationMiddlewares["GetComplianceModulesetUsage"]...) + router.DELETE(options.BaseURL+"/compliance/modulesets_publications", wrapper.DeleteComplianceModulesetsPublications, options.OperationMiddlewares["DeleteComplianceModulesetsPublications"]...) + router.POST(options.BaseURL+"/compliance/modulesets_publications", wrapper.PostComplianceModulesetsPublications, options.OperationMiddlewares["PostComplianceModulesetsPublications"]...) + router.DELETE(options.BaseURL+"/compliance/modulesets_responsibles", wrapper.DeleteComplianceModulesetsResponsibles, options.OperationMiddlewares["DeleteComplianceModulesetsResponsibles"]...) + router.POST(options.BaseURL+"/compliance/modulesets_responsibles", wrapper.PostComplianceModulesetsResponsibles, options.OperationMiddlewares["PostComplianceModulesetsResponsibles"]...) router.DELETE(options.BaseURL+"/compliance/rulesets", wrapper.DeleteComplianceRulesets, options.OperationMiddlewares["DeleteComplianceRulesets"]...) router.GET(options.BaseURL+"/compliance/rulesets", wrapper.GetComplianceRulesets, options.OperationMiddlewares["GetComplianceRulesets"]...) router.POST(options.BaseURL+"/compliance/rulesets", wrapper.PostComplianceRulesets, options.OperationMiddlewares["PostComplianceRulesets"]...) @@ -12730,404 +13090,407 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "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", - "9pQiG12OxhejPz/9+f8HAAD//w==", + "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", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index 005e41be..a4915e95 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -2243,6 +2243,122 @@ type PostComplianceModulesetModuleJSONBody struct { ModsetModName *string `json:"modset_mod_name,omitempty"` } +// GetComplianceModulesetPublicationsParams defines parameters for GetComplianceModulesetPublications. +type GetComplianceModulesetPublicationsParams struct { + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` + + // Limit The maximum number of entries to return. 0 means no limit. + Limit *InQueryLimit `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Skip the first entries of the data cursor. + Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` + + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. + Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` + + // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. + Stats *InQueryStats `form:"stats,omitempty" json:"stats,omitempty"` + + // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). + Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` + + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). + Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` +} + +// GetComplianceModulesetResponsiblesParams defines parameters for GetComplianceModulesetResponsibles. +type GetComplianceModulesetResponsiblesParams struct { + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` + + // Limit The maximum number of entries to return. 0 means no limit. + Limit *InQueryLimit `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Skip the first entries of the data cursor. + Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` + + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. + Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` + + // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. + Stats *InQueryStats `form:"stats,omitempty" json:"stats,omitempty"` + + // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). + Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` + + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). + Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` +} + +// DeleteComplianceModulesetsPublicationsJSONBody defines parameters for DeleteComplianceModulesetsPublications. +type DeleteComplianceModulesetsPublicationsJSONBody struct { + // GroupId Group id or role + GroupId interface{} `json:"group_id"` + + // ModsetId Moduleset id or name + ModsetId interface{} `json:"modset_id"` +} + +// PostComplianceModulesetsPublicationsJSONBody defines parameters for PostComplianceModulesetsPublications. +type PostComplianceModulesetsPublicationsJSONBody struct { + // GroupId Group id or role + GroupId interface{} `json:"group_id"` + + // ModsetId Moduleset id or name + ModsetId interface{} `json:"modset_id"` +} + +// DeleteComplianceModulesetsResponsiblesJSONBody defines parameters for DeleteComplianceModulesetsResponsibles. +type DeleteComplianceModulesetsResponsiblesJSONBody struct { + // GroupId Group id or role + GroupId interface{} `json:"group_id"` + + // ModsetId Moduleset id or name + ModsetId interface{} `json:"modset_id"` +} + +// PostComplianceModulesetsResponsiblesJSONBody defines parameters for PostComplianceModulesetsResponsibles. +type PostComplianceModulesetsResponsiblesJSONBody struct { + // GroupId Group id or role + GroupId interface{} `json:"group_id"` + + // ModsetId Moduleset id or name + ModsetId interface{} `json:"modset_id"` +} + // DeleteComplianceRulesetsJSONBody defines parameters for DeleteComplianceRulesets. type DeleteComplianceRulesetsJSONBody struct { // Id Ruleset id or name @@ -6223,6 +6339,18 @@ type PostComplianceModulesetModulesJSONRequestBody PostComplianceModulesetModule // PostComplianceModulesetModuleJSONRequestBody defines body for PostComplianceModulesetModule for application/json ContentType. type PostComplianceModulesetModuleJSONRequestBody PostComplianceModulesetModuleJSONBody +// DeleteComplianceModulesetsPublicationsJSONRequestBody defines body for DeleteComplianceModulesetsPublications for application/json ContentType. +type DeleteComplianceModulesetsPublicationsJSONRequestBody DeleteComplianceModulesetsPublicationsJSONBody + +// PostComplianceModulesetsPublicationsJSONRequestBody defines body for PostComplianceModulesetsPublications for application/json ContentType. +type PostComplianceModulesetsPublicationsJSONRequestBody PostComplianceModulesetsPublicationsJSONBody + +// DeleteComplianceModulesetsResponsiblesJSONRequestBody defines body for DeleteComplianceModulesetsResponsibles for application/json ContentType. +type DeleteComplianceModulesetsResponsiblesJSONRequestBody DeleteComplianceModulesetsResponsiblesJSONBody + +// PostComplianceModulesetsResponsiblesJSONRequestBody defines body for PostComplianceModulesetsResponsibles for application/json ContentType. +type PostComplianceModulesetsResponsiblesJSONRequestBody PostComplianceModulesetsResponsiblesJSONBody + // DeleteComplianceRulesetsJSONRequestBody defines body for DeleteComplianceRulesets for application/json ContentType. type DeleteComplianceRulesetsJSONRequestBody DeleteComplianceRulesetsJSONBody diff --git a/server/handlers/compliance_teams.go b/server/handlers/compliance_teams.go index 4db3241e..672914e2 100644 --- a/server/handlers/compliance_teams.go +++ b/server/handlers/compliance_teams.go @@ -187,3 +187,79 @@ func (a *Api) PostComplianceRulesetsResponsibles(c echo.Context) error { func (a *Api) DeleteComplianceRulesetsResponsibles(c echo.Context) error { return a.rulesetsTeamBulk(c, "DeleteComplianceRulesetsResponsibles", "responsible", false) } + +// GetComplianceModulesetPublications handles GET /compliance/modulesets/{modset_id}/publications. +func (a *Api) GetComplianceModulesetPublications(c echo.Context, modsetId string, params server.GetComplianceModulesetPublicationsParams) error { + id, err := a.resolveModuleset(c.Request().Context(), modsetId) + if err != nil { + return httpProblem(c, err) + } + return a.compTeamList(c, "GetComplianceModulesetPublications", cdb.CompModulesetKind, id, "publication", + listParams(params.Props, params.Limit, params.Offset, params.Meta, params.Stats, params.Orderby, params.Groupby, params.Filter)) +} + +// GetComplianceModulesetResponsibles handles GET /compliance/modulesets/{modset_id}/responsibles. +func (a *Api) GetComplianceModulesetResponsibles(c echo.Context, modsetId string, params server.GetComplianceModulesetResponsiblesParams) error { + id, err := a.resolveModuleset(c.Request().Context(), modsetId) + if err != nil { + return httpProblem(c, err) + } + return a.compTeamList(c, "GetComplianceModulesetResponsibles", cdb.CompModulesetKind, id, "responsible", + listParams(params.Props, params.Limit, params.Offset, params.Meta, params.Stats, params.Orderby, params.Groupby, params.Filter)) +} + +func (a *Api) modulesetTeamChange(c echo.Context, name, modsetRef, groupRef, gtype string, attach bool) error { + id, err := a.resolveModuleset(c.Request().Context(), modsetRef) + if err != nil { + return httpProblem(c, err) + } + return a.compTeamChange(c, name, cdb.CompModulesetKind, id, gtype, groupRef, attach) +} + +// PostComplianceModulesetPublication handles POST /compliance/modulesets/{modset_id}/publications/{group_id}. +func (a *Api) PostComplianceModulesetPublication(c echo.Context, modsetId, groupId string) error { + return a.modulesetTeamChange(c, "PostComplianceModulesetPublication", modsetId, groupId, "publication", true) +} + +// DeleteComplianceModulesetPublication handles DELETE /compliance/modulesets/{modset_id}/publications/{group_id}. +func (a *Api) DeleteComplianceModulesetPublication(c echo.Context, modsetId, groupId string) error { + return a.modulesetTeamChange(c, "DeleteComplianceModulesetPublication", modsetId, groupId, "publication", false) +} + +// PostComplianceModulesetResponsible handles POST /compliance/modulesets/{modset_id}/responsibles/{group_id}. +func (a *Api) PostComplianceModulesetResponsible(c echo.Context, modsetId, groupId string) error { + return a.modulesetTeamChange(c, "PostComplianceModulesetResponsible", modsetId, groupId, "responsible", true) +} + +// DeleteComplianceModulesetResponsible handles DELETE /compliance/modulesets/{modset_id}/responsibles/{group_id}. +func (a *Api) DeleteComplianceModulesetResponsible(c echo.Context, modsetId, groupId string) error { + return a.modulesetTeamChange(c, "DeleteComplianceModulesetResponsible", modsetId, groupId, "responsible", false) +} + +func (a *Api) modulesetsTeamBulk(c echo.Context, name, gtype string, attach bool) error { + modset, group, err := compTeamBody(c, "modset_id") + if err != nil { + return httpProblem(c, err) + } + return a.modulesetTeamChange(c, name, modset, group, gtype, attach) +} + +// PostComplianceModulesetsPublications handles POST /compliance/modulesets_publications. +func (a *Api) PostComplianceModulesetsPublications(c echo.Context) error { + return a.modulesetsTeamBulk(c, "PostComplianceModulesetsPublications", "publication", true) +} + +// DeleteComplianceModulesetsPublications handles DELETE /compliance/modulesets_publications. +func (a *Api) DeleteComplianceModulesetsPublications(c echo.Context) error { + return a.modulesetsTeamBulk(c, "DeleteComplianceModulesetsPublications", "publication", false) +} + +// PostComplianceModulesetsResponsibles handles POST /compliance/modulesets_responsibles. +func (a *Api) PostComplianceModulesetsResponsibles(c echo.Context) error { + return a.modulesetsTeamBulk(c, "PostComplianceModulesetsResponsibles", "responsible", true) +} + +// DeleteComplianceModulesetsResponsibles handles DELETE /compliance/modulesets_responsibles. +func (a *Api) DeleteComplianceModulesetsResponsibles(c echo.Context) error { + return a.modulesetsTeamBulk(c, "DeleteComplianceModulesetsResponsibles", "responsible", false) +} From 633a8035e84f8250a45bd33739079e104b0ffcf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Mon, 28 Sep 2026 14:01:33 +0200 Subject: [PATCH 48/61] Add the compliance moduleset node and service attachment endpoints List the nodes and services a moduleset is attached to and its candidates, and attach or detach a moduleset named in the body with the bulk /compliance/modulesets_nodes and /compliance/modulesets_services forms, which delegate to the node and service compliance handlers. --- server/api.yaml | 374 +++++++ server/codegen_server_gen.go | 1222 ++++++++++++++------- server/codegen_type_gen.go | 216 ++++ server/handlers/compliance_attachments.go | 93 ++ 4 files changed, 1504 insertions(+), 401 deletions(-) diff --git a/server/api.yaml b/server/api.yaml index 57bf700f..33ad01b1 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -11869,6 +11869,380 @@ paths: - basicAuth: [ ] - bearerAuth: [ ] + /compliance/modulesets/{modset_id}/nodes: + get: + operationId: GetComplianceModulesetNodes + description: | + List the nodes a moduleset published to the user is attached to, among the nodes + the user can see. + parameters: + - in: path + name: modset_id + required: true + description: Moduleset id or name + schema: + type: string + - $ref: '#/components/parameters/inQueryProps' + - $ref: '#/components/parameters/inQueryLimit' + - $ref: '#/components/parameters/inQueryOffset' + - $ref: '#/components/parameters/inQueryMeta' + - $ref: '#/components/parameters/inQueryStats' + - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryFilter' + - $ref: '#/components/parameters/inQueryGroupby' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/NodeListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /compliance/modulesets/{modset_id}/candidate_nodes: + get: + operationId: GetComplianceModulesetCandidateNodes + description: | + List the nodes a moduleset published to the user may be attached to: the nodes + the user can see whose responsible team is one of the moduleset's publication + groups, not attached yet. + parameters: + - in: path + name: modset_id + required: true + description: Moduleset id or name + schema: + type: string + - $ref: '#/components/parameters/inQueryProps' + - $ref: '#/components/parameters/inQueryLimit' + - $ref: '#/components/parameters/inQueryOffset' + - $ref: '#/components/parameters/inQueryMeta' + - $ref: '#/components/parameters/inQueryStats' + - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryFilter' + - $ref: '#/components/parameters/inQueryGroupby' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/NodeListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /compliance/modulesets/{modset_id}/services: + get: + operationId: GetComplianceModulesetServices + description: | + List the services a moduleset published to the user is attached to, as the + service itself or, with slave, as its encapsulated service, among the services + the user can see. + parameters: + - in: path + name: modset_id + required: true + description: Moduleset id or name + schema: + type: string + - in: query + name: slave + description: With true, the encapsulated services + schema: + type: boolean + - $ref: '#/components/parameters/inQueryProps' + - $ref: '#/components/parameters/inQueryLimit' + - $ref: '#/components/parameters/inQueryOffset' + - $ref: '#/components/parameters/inQueryMeta' + - $ref: '#/components/parameters/inQueryStats' + - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryFilter' + - $ref: '#/components/parameters/inQueryGroupby' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ServiceListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /compliance/modulesets/{modset_id}/candidate_services: + get: + operationId: GetComplianceModulesetCandidateServices + description: | + List the services a moduleset published to the user may be attached to, as the + service or with slave as its encapsulated service: the services the user can see + whose app has one of the moduleset's publication groups among its responsibles, + not attached yet. + parameters: + - in: path + name: modset_id + required: true + description: Moduleset id or name + schema: + type: string + - in: query + name: slave + description: With true, the encapsulated services + schema: + type: boolean + - $ref: '#/components/parameters/inQueryProps' + - $ref: '#/components/parameters/inQueryLimit' + - $ref: '#/components/parameters/inQueryOffset' + - $ref: '#/components/parameters/inQueryMeta' + - $ref: '#/components/parameters/inQueryStats' + - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryFilter' + - $ref: '#/components/parameters/inQueryGroupby' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ServiceListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /compliance/modulesets_nodes: + post: + operationId: PostComplianceModulesetsNodes + description: | + Attach a moduleset to a node, as POST /nodes/{node_id}/compliance/modulesets/{mset_id}. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [node_id] + properties: + node_id: + type: string + modset_id: + description: Moduleset id or name + modset_name: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 409: + $ref: '#/components/responses/409' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + delete: + operationId: DeleteComplianceModulesetsNodes + description: | + Detach a moduleset from a node, as DELETE /nodes/{node_id}/compliance/modulesets/{mset_id}. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [node_id] + properties: + node_id: + type: string + modset_id: + description: Moduleset id or name + modset_name: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /compliance/modulesets_services: + post: + operationId: PostComplianceModulesetsServices + description: | + Attach a moduleset to a service, as POST /services/{svc_id}/compliance/modulesets/{mset_id}. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [svc_id] + properties: + svc_id: + type: string + modset_id: + description: Moduleset id or name + modset_name: + type: string + slave: + description: A boolean; true for the encapsulated service. encap is accepted as well. + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 409: + $ref: '#/components/responses/409' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + delete: + operationId: DeleteComplianceModulesetsServices + description: | + Detach a moduleset from a service, as DELETE /services/{svc_id}/compliance/modulesets/{mset_id}. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [svc_id] + properties: + svc_id: + type: string + modset_id: + description: Moduleset id or name + modset_name: + type: string + slave: + description: A boolean; true for the encapsulated service. encap is accepted as well. + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + components: responses: diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index f7066a60..22775804 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -153,6 +153,12 @@ type ServerInterface interface { // (GET /compliance/modulesets/{modset_id}/am_i_responsible) GetComplianceModulesetAmIResponsible(ctx echo.Context, modsetId string) error + // (GET /compliance/modulesets/{modset_id}/candidate_nodes) + GetComplianceModulesetCandidateNodes(ctx echo.Context, modsetId string, params GetComplianceModulesetCandidateNodesParams) error + + // (GET /compliance/modulesets/{modset_id}/candidate_services) + GetComplianceModulesetCandidateServices(ctx echo.Context, modsetId string, params GetComplianceModulesetCandidateServicesParams) error + // (GET /compliance/modulesets/{modset_id}/modules) GetComplianceModulesetModules(ctx echo.Context, modsetId string, params GetComplianceModulesetModulesParams) error @@ -174,6 +180,9 @@ type ServerInterface interface { // (POST /compliance/modulesets/{modset_id}/modulesets/{child_modset_id}) PostComplianceModulesetModuleset(ctx echo.Context, modsetId string, childModsetId string) error + // (GET /compliance/modulesets/{modset_id}/nodes) + GetComplianceModulesetNodes(ctx echo.Context, modsetId string, params GetComplianceModulesetNodesParams) error + // (GET /compliance/modulesets/{modset_id}/publications) GetComplianceModulesetPublications(ctx echo.Context, modsetId string, params GetComplianceModulesetPublicationsParams) error @@ -198,9 +207,18 @@ type ServerInterface interface { // (POST /compliance/modulesets/{modset_id}/rulesets/{rset_id}) PostComplianceModulesetRuleset(ctx echo.Context, modsetId string, rsetId string) error + // (GET /compliance/modulesets/{modset_id}/services) + GetComplianceModulesetServices(ctx echo.Context, modsetId string, params GetComplianceModulesetServicesParams) error + // (GET /compliance/modulesets/{modset_id}/usage) GetComplianceModulesetUsage(ctx echo.Context, modsetId string) error + // (DELETE /compliance/modulesets_nodes) + DeleteComplianceModulesetsNodes(ctx echo.Context) error + + // (POST /compliance/modulesets_nodes) + PostComplianceModulesetsNodes(ctx echo.Context) error + // (DELETE /compliance/modulesets_publications) DeleteComplianceModulesetsPublications(ctx echo.Context) error @@ -213,6 +231,12 @@ type ServerInterface interface { // (POST /compliance/modulesets_responsibles) PostComplianceModulesetsResponsibles(ctx echo.Context) error + // (DELETE /compliance/modulesets_services) + DeleteComplianceModulesetsServices(ctx echo.Context) error + + // (POST /compliance/modulesets_services) + PostComplianceModulesetsServices(ctx echo.Context) error + // (DELETE /compliance/rulesets) DeleteComplianceRulesets(ctx echo.Context) error @@ -2440,6 +2464,169 @@ func (w *ServerInterfaceWrapper) GetComplianceModulesetAmIResponsible(ctx echo.C return err } +// GetComplianceModulesetCandidateNodes converts echo context to params. +func (w *ServerInterfaceWrapper) GetComplianceModulesetCandidateNodes(ctx echo.Context) error { + var err error + // ------------- Path parameter "modset_id" ------------- + var modsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "modset_id", ctx.Param("modset_id"), &modsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter modset_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetComplianceModulesetCandidateNodesParams + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // ------------- Optional query parameter "limit" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) + } + + // ------------- Optional query parameter "offset" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) + } + + // ------------- Optional query parameter "meta" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) + } + + // ------------- Optional query parameter "stats" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) + } + + // ------------- Optional query parameter "orderby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) + } + + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + + // ------------- Optional query parameter "groupby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetComplianceModulesetCandidateNodes(ctx, modsetId, params) + return err +} + +// GetComplianceModulesetCandidateServices converts echo context to params. +func (w *ServerInterfaceWrapper) GetComplianceModulesetCandidateServices(ctx echo.Context) error { + var err error + // ------------- Path parameter "modset_id" ------------- + var modsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "modset_id", ctx.Param("modset_id"), &modsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter modset_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetComplianceModulesetCandidateServicesParams + // ------------- Optional query parameter "slave" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "slave", ctx.QueryParams(), ¶ms.Slave, runtime.BindQueryParameterOptions{Type: "boolean", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter slave: %s", err)) + } + + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // ------------- Optional query parameter "limit" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) + } + + // ------------- Optional query parameter "offset" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) + } + + // ------------- Optional query parameter "meta" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) + } + + // ------------- Optional query parameter "stats" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) + } + + // ------------- Optional query parameter "orderby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) + } + + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + + // ------------- Optional query parameter "groupby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetComplianceModulesetCandidateServices(ctx, modsetId, params) + return err +} + // GetComplianceModulesetModules converts echo context to params. func (w *ServerInterfaceWrapper) GetComplianceModulesetModules(ctx echo.Context) error { var err error @@ -2687,6 +2874,84 @@ func (w *ServerInterfaceWrapper) PostComplianceModulesetModuleset(ctx echo.Conte return err } +// GetComplianceModulesetNodes converts echo context to params. +func (w *ServerInterfaceWrapper) GetComplianceModulesetNodes(ctx echo.Context) error { + var err error + // ------------- Path parameter "modset_id" ------------- + var modsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "modset_id", ctx.Param("modset_id"), &modsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter modset_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetComplianceModulesetNodesParams + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // ------------- Optional query parameter "limit" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) + } + + // ------------- Optional query parameter "offset" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) + } + + // ------------- Optional query parameter "meta" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) + } + + // ------------- Optional query parameter "stats" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) + } + + // ------------- Optional query parameter "orderby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) + } + + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + + // ------------- Optional query parameter "groupby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetComplianceModulesetNodes(ctx, modsetId, params) + return err +} + // GetComplianceModulesetPublications converts echo context to params. func (w *ServerInterfaceWrapper) GetComplianceModulesetPublications(ctx echo.Context) error { var err error @@ -3011,6 +3276,91 @@ func (w *ServerInterfaceWrapper) PostComplianceModulesetRuleset(ctx echo.Context return err } +// GetComplianceModulesetServices converts echo context to params. +func (w *ServerInterfaceWrapper) GetComplianceModulesetServices(ctx echo.Context) error { + var err error + // ------------- Path parameter "modset_id" ------------- + var modsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "modset_id", ctx.Param("modset_id"), &modsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter modset_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetComplianceModulesetServicesParams + // ------------- Optional query parameter "slave" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "slave", ctx.QueryParams(), ¶ms.Slave, runtime.BindQueryParameterOptions{Type: "boolean", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter slave: %s", err)) + } + + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // ------------- Optional query parameter "limit" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) + } + + // ------------- Optional query parameter "offset" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) + } + + // ------------- Optional query parameter "meta" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) + } + + // ------------- Optional query parameter "stats" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) + } + + // ------------- Optional query parameter "orderby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) + } + + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + + // ------------- Optional query parameter "groupby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetComplianceModulesetServices(ctx, modsetId, params) + return err +} + // GetComplianceModulesetUsage converts echo context to params. func (w *ServerInterfaceWrapper) GetComplianceModulesetUsage(ctx echo.Context) error { var err error @@ -3031,6 +3381,32 @@ func (w *ServerInterfaceWrapper) GetComplianceModulesetUsage(ctx echo.Context) e return err } +// DeleteComplianceModulesetsNodes converts echo context to params. +func (w *ServerInterfaceWrapper) DeleteComplianceModulesetsNodes(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.DeleteComplianceModulesetsNodes(ctx) + return err +} + +// PostComplianceModulesetsNodes converts echo context to params. +func (w *ServerInterfaceWrapper) PostComplianceModulesetsNodes(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostComplianceModulesetsNodes(ctx) + return err +} + // DeleteComplianceModulesetsPublications converts echo context to params. func (w *ServerInterfaceWrapper) DeleteComplianceModulesetsPublications(ctx echo.Context) error { var err error @@ -3083,6 +3459,32 @@ func (w *ServerInterfaceWrapper) PostComplianceModulesetsResponsibles(ctx echo.C return err } +// DeleteComplianceModulesetsServices converts echo context to params. +func (w *ServerInterfaceWrapper) DeleteComplianceModulesetsServices(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.DeleteComplianceModulesetsServices(ctx) + return err +} + +// PostComplianceModulesetsServices converts echo context to params. +func (w *ServerInterfaceWrapper) PostComplianceModulesetsServices(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostComplianceModulesetsServices(ctx) + return err +} + // DeleteComplianceRulesets converts echo context to params. func (w *ServerInterfaceWrapper) DeleteComplianceRulesets(ctx echo.Context) error { var err error @@ -12833,6 +13235,8 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.POST(options.BaseURL+"/compliance/modulesets/:modset_id", wrapper.PostComplianceModuleset, options.OperationMiddlewares["PostComplianceModuleset"]...) router.PUT(options.BaseURL+"/compliance/modulesets/:modset_id", wrapper.PutComplianceModuleset, options.OperationMiddlewares["PutComplianceModuleset"]...) router.GET(options.BaseURL+"/compliance/modulesets/:modset_id/am_i_responsible", wrapper.GetComplianceModulesetAmIResponsible, options.OperationMiddlewares["GetComplianceModulesetAmIResponsible"]...) + router.GET(options.BaseURL+"/compliance/modulesets/:modset_id/candidate_nodes", wrapper.GetComplianceModulesetCandidateNodes, options.OperationMiddlewares["GetComplianceModulesetCandidateNodes"]...) + router.GET(options.BaseURL+"/compliance/modulesets/:modset_id/candidate_services", wrapper.GetComplianceModulesetCandidateServices, options.OperationMiddlewares["GetComplianceModulesetCandidateServices"]...) router.GET(options.BaseURL+"/compliance/modulesets/:modset_id/modules", wrapper.GetComplianceModulesetModules, options.OperationMiddlewares["GetComplianceModulesetModules"]...) router.POST(options.BaseURL+"/compliance/modulesets/:modset_id/modules", wrapper.PostComplianceModulesetModules, options.OperationMiddlewares["PostComplianceModulesetModules"]...) router.DELETE(options.BaseURL+"/compliance/modulesets/:modset_id/modules/:mod_id", wrapper.DeleteComplianceModulesetModule, options.OperationMiddlewares["DeleteComplianceModulesetModule"]...) @@ -12840,6 +13244,7 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.POST(options.BaseURL+"/compliance/modulesets/:modset_id/modules/:mod_id", wrapper.PostComplianceModulesetModule, options.OperationMiddlewares["PostComplianceModulesetModule"]...) router.DELETE(options.BaseURL+"/compliance/modulesets/:modset_id/modulesets/:child_modset_id", wrapper.DeleteComplianceModulesetModuleset, options.OperationMiddlewares["DeleteComplianceModulesetModuleset"]...) router.POST(options.BaseURL+"/compliance/modulesets/:modset_id/modulesets/:child_modset_id", wrapper.PostComplianceModulesetModuleset, options.OperationMiddlewares["PostComplianceModulesetModuleset"]...) + router.GET(options.BaseURL+"/compliance/modulesets/:modset_id/nodes", wrapper.GetComplianceModulesetNodes, options.OperationMiddlewares["GetComplianceModulesetNodes"]...) router.GET(options.BaseURL+"/compliance/modulesets/:modset_id/publications", wrapper.GetComplianceModulesetPublications, options.OperationMiddlewares["GetComplianceModulesetPublications"]...) router.DELETE(options.BaseURL+"/compliance/modulesets/:modset_id/publications/:group_id", wrapper.DeleteComplianceModulesetPublication, options.OperationMiddlewares["DeleteComplianceModulesetPublication"]...) router.POST(options.BaseURL+"/compliance/modulesets/:modset_id/publications/:group_id", wrapper.PostComplianceModulesetPublication, options.OperationMiddlewares["PostComplianceModulesetPublication"]...) @@ -12848,11 +13253,16 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.POST(options.BaseURL+"/compliance/modulesets/:modset_id/responsibles/:group_id", wrapper.PostComplianceModulesetResponsible, options.OperationMiddlewares["PostComplianceModulesetResponsible"]...) router.DELETE(options.BaseURL+"/compliance/modulesets/:modset_id/rulesets/:rset_id", wrapper.DeleteComplianceModulesetRuleset, options.OperationMiddlewares["DeleteComplianceModulesetRuleset"]...) router.POST(options.BaseURL+"/compliance/modulesets/:modset_id/rulesets/:rset_id", wrapper.PostComplianceModulesetRuleset, options.OperationMiddlewares["PostComplianceModulesetRuleset"]...) + router.GET(options.BaseURL+"/compliance/modulesets/:modset_id/services", wrapper.GetComplianceModulesetServices, options.OperationMiddlewares["GetComplianceModulesetServices"]...) router.GET(options.BaseURL+"/compliance/modulesets/:modset_id/usage", wrapper.GetComplianceModulesetUsage, options.OperationMiddlewares["GetComplianceModulesetUsage"]...) + router.DELETE(options.BaseURL+"/compliance/modulesets_nodes", wrapper.DeleteComplianceModulesetsNodes, options.OperationMiddlewares["DeleteComplianceModulesetsNodes"]...) + router.POST(options.BaseURL+"/compliance/modulesets_nodes", wrapper.PostComplianceModulesetsNodes, options.OperationMiddlewares["PostComplianceModulesetsNodes"]...) router.DELETE(options.BaseURL+"/compliance/modulesets_publications", wrapper.DeleteComplianceModulesetsPublications, options.OperationMiddlewares["DeleteComplianceModulesetsPublications"]...) router.POST(options.BaseURL+"/compliance/modulesets_publications", wrapper.PostComplianceModulesetsPublications, options.OperationMiddlewares["PostComplianceModulesetsPublications"]...) router.DELETE(options.BaseURL+"/compliance/modulesets_responsibles", wrapper.DeleteComplianceModulesetsResponsibles, options.OperationMiddlewares["DeleteComplianceModulesetsResponsibles"]...) router.POST(options.BaseURL+"/compliance/modulesets_responsibles", wrapper.PostComplianceModulesetsResponsibles, options.OperationMiddlewares["PostComplianceModulesetsResponsibles"]...) + router.DELETE(options.BaseURL+"/compliance/modulesets_services", wrapper.DeleteComplianceModulesetsServices, options.OperationMiddlewares["DeleteComplianceModulesetsServices"]...) + router.POST(options.BaseURL+"/compliance/modulesets_services", wrapper.PostComplianceModulesetsServices, options.OperationMiddlewares["PostComplianceModulesetsServices"]...) router.DELETE(options.BaseURL+"/compliance/rulesets", wrapper.DeleteComplianceRulesets, options.OperationMiddlewares["DeleteComplianceRulesets"]...) router.GET(options.BaseURL+"/compliance/rulesets", wrapper.GetComplianceRulesets, options.OperationMiddlewares["GetComplianceRulesets"]...) router.POST(options.BaseURL+"/compliance/rulesets", wrapper.PostComplianceRulesets, options.OperationMiddlewares["PostComplianceRulesets"]...) @@ -13090,407 +13500,417 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "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", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index a4915e95..f6f381de 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -2183,6 +2183,89 @@ type PutComplianceModulesetJSONBody struct { // PutComplianceModulesetJSONBodyAction defines parameters for PutComplianceModuleset. type PutComplianceModulesetJSONBodyAction string +// GetComplianceModulesetCandidateNodesParams defines parameters for GetComplianceModulesetCandidateNodes. +type GetComplianceModulesetCandidateNodesParams struct { + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` + + // Limit The maximum number of entries to return. 0 means no limit. + Limit *InQueryLimit `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Skip the first entries of the data cursor. + Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` + + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. + Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` + + // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. + Stats *InQueryStats `form:"stats,omitempty" json:"stats,omitempty"` + + // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). + Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` + + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). + Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` +} + +// GetComplianceModulesetCandidateServicesParams defines parameters for GetComplianceModulesetCandidateServices. +type GetComplianceModulesetCandidateServicesParams struct { + // Slave With true, the encapsulated services + Slave *bool `form:"slave,omitempty" json:"slave,omitempty"` + + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` + + // Limit The maximum number of entries to return. 0 means no limit. + Limit *InQueryLimit `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Skip the first entries of the data cursor. + Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` + + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. + Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` + + // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. + Stats *InQueryStats `form:"stats,omitempty" json:"stats,omitempty"` + + // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). + Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` + + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). + Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` +} + // GetComplianceModulesetModulesParams defines parameters for GetComplianceModulesetModules. type GetComplianceModulesetModulesParams struct { // Props A list of properties to include in each data dictionnary. @@ -2243,6 +2326,46 @@ type PostComplianceModulesetModuleJSONBody struct { ModsetModName *string `json:"modset_mod_name,omitempty"` } +// GetComplianceModulesetNodesParams defines parameters for GetComplianceModulesetNodes. +type GetComplianceModulesetNodesParams struct { + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` + + // Limit The maximum number of entries to return. 0 means no limit. + Limit *InQueryLimit `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Skip the first entries of the data cursor. + Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` + + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. + Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` + + // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. + Stats *InQueryStats `form:"stats,omitempty" json:"stats,omitempty"` + + // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). + Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` + + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). + Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` +} + // GetComplianceModulesetPublicationsParams defines parameters for GetComplianceModulesetPublications. type GetComplianceModulesetPublicationsParams struct { // Props A list of properties to include in each data dictionnary. @@ -2323,6 +2446,65 @@ type GetComplianceModulesetResponsiblesParams struct { Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` } +// GetComplianceModulesetServicesParams defines parameters for GetComplianceModulesetServices. +type GetComplianceModulesetServicesParams struct { + // Slave With true, the encapsulated services + Slave *bool `form:"slave,omitempty" json:"slave,omitempty"` + + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` + + // Limit The maximum number of entries to return. 0 means no limit. + Limit *InQueryLimit `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Skip the first entries of the data cursor. + Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` + + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. + Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` + + // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. + Stats *InQueryStats `form:"stats,omitempty" json:"stats,omitempty"` + + // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). + Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` + + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). + Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` +} + +// DeleteComplianceModulesetsNodesJSONBody defines parameters for DeleteComplianceModulesetsNodes. +type DeleteComplianceModulesetsNodesJSONBody struct { + // ModsetId Moduleset id or name + ModsetId interface{} `json:"modset_id,omitempty"` + ModsetName *string `json:"modset_name,omitempty"` + NodeId string `json:"node_id"` +} + +// PostComplianceModulesetsNodesJSONBody defines parameters for PostComplianceModulesetsNodes. +type PostComplianceModulesetsNodesJSONBody struct { + // ModsetId Moduleset id or name + ModsetId interface{} `json:"modset_id,omitempty"` + ModsetName *string `json:"modset_name,omitempty"` + NodeId string `json:"node_id"` +} + // DeleteComplianceModulesetsPublicationsJSONBody defines parameters for DeleteComplianceModulesetsPublications. type DeleteComplianceModulesetsPublicationsJSONBody struct { // GroupId Group id or role @@ -2359,6 +2541,28 @@ type PostComplianceModulesetsResponsiblesJSONBody struct { ModsetId interface{} `json:"modset_id"` } +// DeleteComplianceModulesetsServicesJSONBody defines parameters for DeleteComplianceModulesetsServices. +type DeleteComplianceModulesetsServicesJSONBody struct { + // ModsetId Moduleset id or name + ModsetId interface{} `json:"modset_id,omitempty"` + ModsetName *string `json:"modset_name,omitempty"` + + // Slave A boolean; true for the encapsulated service. encap is accepted as well. + Slave interface{} `json:"slave,omitempty"` + SvcId string `json:"svc_id"` +} + +// PostComplianceModulesetsServicesJSONBody defines parameters for PostComplianceModulesetsServices. +type PostComplianceModulesetsServicesJSONBody struct { + // ModsetId Moduleset id or name + ModsetId interface{} `json:"modset_id,omitempty"` + ModsetName *string `json:"modset_name,omitempty"` + + // Slave A boolean; true for the encapsulated service. encap is accepted as well. + Slave interface{} `json:"slave,omitempty"` + SvcId string `json:"svc_id"` +} + // DeleteComplianceRulesetsJSONBody defines parameters for DeleteComplianceRulesets. type DeleteComplianceRulesetsJSONBody struct { // Id Ruleset id or name @@ -6339,6 +6543,12 @@ type PostComplianceModulesetModulesJSONRequestBody PostComplianceModulesetModule // PostComplianceModulesetModuleJSONRequestBody defines body for PostComplianceModulesetModule for application/json ContentType. type PostComplianceModulesetModuleJSONRequestBody PostComplianceModulesetModuleJSONBody +// DeleteComplianceModulesetsNodesJSONRequestBody defines body for DeleteComplianceModulesetsNodes for application/json ContentType. +type DeleteComplianceModulesetsNodesJSONRequestBody DeleteComplianceModulesetsNodesJSONBody + +// PostComplianceModulesetsNodesJSONRequestBody defines body for PostComplianceModulesetsNodes for application/json ContentType. +type PostComplianceModulesetsNodesJSONRequestBody PostComplianceModulesetsNodesJSONBody + // DeleteComplianceModulesetsPublicationsJSONRequestBody defines body for DeleteComplianceModulesetsPublications for application/json ContentType. type DeleteComplianceModulesetsPublicationsJSONRequestBody DeleteComplianceModulesetsPublicationsJSONBody @@ -6351,6 +6561,12 @@ type DeleteComplianceModulesetsResponsiblesJSONRequestBody DeleteComplianceModul // PostComplianceModulesetsResponsiblesJSONRequestBody defines body for PostComplianceModulesetsResponsibles for application/json ContentType. type PostComplianceModulesetsResponsiblesJSONRequestBody PostComplianceModulesetsResponsiblesJSONBody +// DeleteComplianceModulesetsServicesJSONRequestBody defines body for DeleteComplianceModulesetsServices for application/json ContentType. +type DeleteComplianceModulesetsServicesJSONRequestBody DeleteComplianceModulesetsServicesJSONBody + +// PostComplianceModulesetsServicesJSONRequestBody defines body for PostComplianceModulesetsServices for application/json ContentType. +type PostComplianceModulesetsServicesJSONRequestBody PostComplianceModulesetsServicesJSONBody + // DeleteComplianceRulesetsJSONRequestBody defines body for DeleteComplianceRulesets for application/json ContentType. type DeleteComplianceRulesetsJSONRequestBody DeleteComplianceRulesetsJSONBody diff --git a/server/handlers/compliance_attachments.go b/server/handlers/compliance_attachments.go index c1b5b161..c1bf6678 100644 --- a/server/handlers/compliance_attachments.go +++ b/server/handlers/compliance_attachments.go @@ -168,3 +168,96 @@ func (a *Api) PostComplianceRulesetsServices(c echo.Context) error { func (a *Api) DeleteComplianceRulesetsServices(c echo.Context) error { return a.rulesetsServices(c, false) } + +// GetComplianceModulesetNodes handles GET /compliance/modulesets/{modset_id}/nodes. +func (a *Api) GetComplianceModulesetNodes(c echo.Context, modsetId string, params server.GetComplianceModulesetNodesParams) error { + id, err := a.publishedModuleset(c, modsetId) + if err != nil { + return httpProblem(c, err) + } + return a.compObjectNodes(c, "GetComplianceModulesetNodes", cdb.CompModulesetKind, id, false, + listParams(params.Props, params.Limit, params.Offset, params.Meta, params.Stats, params.Orderby, params.Groupby, params.Filter)) +} + +// GetComplianceModulesetCandidateNodes handles GET /compliance/modulesets/{modset_id}/candidate_nodes. +func (a *Api) GetComplianceModulesetCandidateNodes(c echo.Context, modsetId string, params server.GetComplianceModulesetCandidateNodesParams) error { + id, err := a.publishedModuleset(c, modsetId) + if err != nil { + return httpProblem(c, err) + } + return a.compObjectNodes(c, "GetComplianceModulesetCandidateNodes", cdb.CompModulesetKind, id, true, + listParams(params.Props, params.Limit, params.Offset, params.Meta, params.Stats, params.Orderby, params.Groupby, params.Filter)) +} + +// GetComplianceModulesetServices handles GET /compliance/modulesets/{modset_id}/services. +func (a *Api) GetComplianceModulesetServices(c echo.Context, modsetId string, params server.GetComplianceModulesetServicesParams) error { + id, err := a.publishedModuleset(c, modsetId) + if err != nil { + return httpProblem(c, err) + } + return a.compObjectServices(c, "GetComplianceModulesetServices", cdb.CompModulesetKind, id, params.Slave, false, + listParams(params.Props, params.Limit, params.Offset, params.Meta, params.Stats, params.Orderby, params.Groupby, params.Filter)) +} + +// GetComplianceModulesetCandidateServices handles GET /compliance/modulesets/{modset_id}/candidate_services. +func (a *Api) GetComplianceModulesetCandidateServices(c echo.Context, modsetId string, params server.GetComplianceModulesetCandidateServicesParams) error { + id, err := a.publishedModuleset(c, modsetId) + if err != nil { + return httpProblem(c, err) + } + return a.compObjectServices(c, "GetComplianceModulesetCandidateServices", cdb.CompModulesetKind, id, params.Slave, true, + listParams(params.Props, params.Limit, params.Offset, params.Meta, params.Stats, params.Orderby, params.Groupby, params.Filter)) +} + +// modulesetsNodes attaches or detaches a moduleset named in the body to a node, +// as POST and DELETE /nodes/{node_id}/compliance/modulesets/{mset_id} do. +func (a *Api) modulesetsNodes(c echo.Context, attach bool) error { + b, err := readCompAttachBody(c, "modset_id", "modset_name", "node_id") + if err != nil { + return httpProblem(c, err) + } + id, err := a.resolveModuleset(c.Request().Context(), b.obj) + if err != nil { + return httpProblem(c, err) + } + if attach { + return a.PostNodeComplianceModuleset(c, b.target, strconv.FormatInt(id, 10)) + } + return a.DeleteNodeComplianceModuleset(c, b.target, strconv.FormatInt(id, 10)) +} + +// PostComplianceModulesetsNodes handles POST /compliance/modulesets_nodes. +func (a *Api) PostComplianceModulesetsNodes(c echo.Context) error { return a.modulesetsNodes(c, true) } + +// DeleteComplianceModulesetsNodes handles DELETE /compliance/modulesets_nodes. +func (a *Api) DeleteComplianceModulesetsNodes(c echo.Context) error { + return a.modulesetsNodes(c, false) +} + +// modulesetsServices attaches or detaches a moduleset named in the body to a +// service, as POST and DELETE /services/{svc_id}/compliance/modulesets/{mset_id} do. +func (a *Api) modulesetsServices(c echo.Context, attach bool) error { + b, err := readCompAttachBody(c, "modset_id", "modset_name", "svc_id") + if err != nil { + return httpProblem(c, err) + } + id, err := a.resolveModuleset(c.Request().Context(), b.obj) + if err != nil { + return httpProblem(c, err) + } + slave := b.slave + if attach { + return a.PostServiceComplianceModuleset(c, b.target, strconv.FormatInt(id, 10), server.PostServiceComplianceModulesetParams{Slave: &slave}) + } + return a.DeleteServiceComplianceModuleset(c, b.target, strconv.FormatInt(id, 10), server.DeleteServiceComplianceModulesetParams{Slave: &slave}) +} + +// PostComplianceModulesetsServices handles POST /compliance/modulesets_services. +func (a *Api) PostComplianceModulesetsServices(c echo.Context) error { + return a.modulesetsServices(c, true) +} + +// DeleteComplianceModulesetsServices handles DELETE /compliance/modulesets_services. +func (a *Api) DeleteComplianceModulesetsServices(c echo.Context) error { + return a.modulesetsServices(c, false) +} From e20592fa771e19c1ab937a8e3cd879b8b95da049 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Mon, 28 Sep 2026 14:10:12 +0200 Subject: [PATCH 49/61] Add the compliance import and export endpoints Export rulesets and modulesets, one or all those published to the caller, with their descendants and the filtersets and rulesets they use, and import such an export, as the historical /compliance/import and /compliance/{rulesets,modulesets}/export handlers. Objects existing by name are reused and the missing relations added. Unlike the historical import, it requires the CompManager privilege, adds to an existing ruleset or moduleset only when the caller is responsible for it, refuses relations closing a loop, and runs in a transaction so that a refused import leaves nothing behind. --- cdb/db_compliance_export.go | 366 +++++++++++ cdb/db_compliance_import.go | 626 ++++++++++++++++++ server/api.yaml | 296 +++++++++ server/codegen_server_gen.go | 932 +++++++++++++++------------ server/codegen_type_gen.go | 75 +++ server/handlers/compliance_common.go | 8 +- server/handlers/compliance_import.go | 124 ++++ 7 files changed, 2014 insertions(+), 413 deletions(-) create mode 100644 cdb/db_compliance_export.go create mode 100644 cdb/db_compliance_import.go create mode 100644 server/handlers/compliance_import.go diff --git a/cdb/db_compliance_export.go b/cdb/db_compliance_export.go new file mode 100644 index 00000000..3fc338cc --- /dev/null +++ b/cdb/db_compliance_export.go @@ -0,0 +1,366 @@ +package cdb + +import ( + "context" + "database/sql" + "fmt" + "sort" + "strings" +) + +type ( + // CompExportVariable is a ruleset variable, as _export_rulesets() writes it. + CompExportVariable struct { + ID int64 `json:"id"` + VarName string `json:"var_name"` + VarValue string `json:"var_value"` + VarClass string `json:"var_class"` + VarAuthor string `json:"var_author"` + VarUpdated string `json:"var_updated"` + } + + // CompExportRuleset is a ruleset with its variables, children, filterset and + // groups, by name. + CompExportRuleset struct { + ID int64 `json:"id"` + RulesetName string `json:"ruleset_name"` + RulesetPublic string `json:"ruleset_public"` + RulesetType string `json:"ruleset_type"` + FsetName *string `json:"fset_name"` + Variables []CompExportVariable `json:"variables"` + Rulesets []string `json:"rulesets"` + Publications []string `json:"publications"` + Responsibles []string `json:"responsibles"` + } + + // CompExportModule is a moduleset module. + CompExportModule struct { + ModsetModName string `json:"modset_mod_name"` + Autofix string `json:"autofix"` + } + + // CompExportModuleset is a moduleset with its modules, children, rulesets and + // groups, by name. + CompExportModuleset struct { + ID int64 `json:"id"` + ModsetName string `json:"modset_name"` + Modules []CompExportModule `json:"modules"` + Modulesets []string `json:"modulesets"` + Rulesets []string `json:"rulesets"` + Publications []string `json:"publications"` + Responsibles []string `json:"responsibles"` + } + + // CompRulesetExport is the export of rulesets: the rulesets and their + // descendants, and the filtersets they use. + CompRulesetExport struct { + Filtersets []FiltersetExport `json:"filtersets"` + Rulesets []CompExportRuleset `json:"rulesets"` + } + + // CompModulesetExport is the export of modulesets: the modulesets and their + // descendants, with the rulesets they hold. + CompModulesetExport struct { + CompRulesetExport + Modulesets []CompExportModuleset `json:"modulesets"` + } +) + +// CompPublishedIDs returns the ids of the compliance objects published to the +// caller, as the historical export handlers select them. +func (oDb *DB) CompPublishedIDs(ctx context.Context, k CompKind, groups []string, isManager bool) ([]int64, error) { + cond, args := compObjectVisibleCond(k, groups, isManager) + return oDb.int64s(ctx, "compPublishedIDs", "SELECT "+k.Table+".id FROM "+k.Table+" WHERE "+cond+" ORDER BY "+k.Table+".id", args...) +} + +func (oDb *DB) int64s(ctx context.Context, name, query string, args ...any) ([]int64, error) { + rows, err := oDb.DB.QueryContext(ctx, query, args...) + if err != nil { + return nil, fmt.Errorf("%s: %w", name, err) + } + defer func() { _ = rows.Close() }() + var ids []int64 + for rows.Next() { + var id int64 + if err := rows.Scan(&id); err != nil { + return nil, fmt.Errorf("%s: %w", name, err) + } + ids = append(ids, id) + } + return ids, rows.Err() +} + +// compPairs reads parent-child id pairs. +func (oDb *DB) compPairs(ctx context.Context, name, query string) (map[int64][]int64, error) { + rows, err := oDb.DB.QueryContext(ctx, query) + if err != nil { + return nil, fmt.Errorf("%s: %w", name, err) + } + defer func() { _ = rows.Close() }() + pairs := map[int64][]int64{} + for rows.Next() { + var p, c int64 + if err := rows.Scan(&p, &c); err != nil { + return nil, fmt.Errorf("%s: %w", name, err) + } + pairs[p] = append(pairs[p], c) + } + return pairs, rows.Err() +} + +// withDescendants returns the ids and all the children reachable from them. +func withDescendants(ids []int64, children map[int64][]int64) []int64 { + seen := map[int64]bool{} + todo := append([]int64{}, ids...) + var all []int64 + for len(todo) > 0 { + id := todo[0] + todo = todo[1:] + if seen[id] { + continue + } + seen[id] = true + all = append(all, id) + todo = append(todo, children[id]...) + } + sort.Slice(all, func(i, j int) bool { return all[i] < all[j] }) + return all +} + +func idArgs(ids []int64) (string, []any) { + args := make([]any, len(ids)) + for i, id := range ids { + args[i] = id + } + return Placeholders(len(ids)), args +} + +// compNames returns the names of the objects of a table, by id. +func (oDb *DB) compNames(ctx context.Context, table, nameCol string) (map[int64]string, error) { + rows, err := oDb.DB.QueryContext(ctx, "SELECT id, COALESCE("+nameCol+", '') FROM "+table) + if err != nil { + return nil, fmt.Errorf("compNames %s: %w", table, err) + } + defer func() { _ = rows.Close() }() + names := map[int64]string{} + for rows.Next() { + var id int64 + var name string + if err := rows.Scan(&id, &name); err != nil { + return nil, fmt.Errorf("compNames %s: %w", table, err) + } + names[id] = name + } + return names, rows.Err() +} + +// compTeamRoles returns the roles of the publication or responsible groups of +// the given objects, by object id. +func (oDb *DB) compTeamRoles(ctx context.Context, k CompKind, gtype string, ids []int64) (map[int64][]string, error) { + table, err := k.teamTable(gtype) + if err != nil { + return nil, err + } + ph, args := idArgs(ids) + rows, err := oDb.DB.QueryContext(ctx, "SELECT t."+k.FK+", ag.role FROM "+table+" t JOIN auth_group ag ON ag.id = t.group_id"+ + " WHERE t."+k.FK+" IN ("+ph+") ORDER BY ag.role", args...) + if err != nil { + return nil, fmt.Errorf("compTeamRoles: %w", err) + } + defer func() { _ = rows.Close() }() + roles := map[int64][]string{} + for rows.Next() { + var id int64 + var role string + if err := rows.Scan(&id, &role); err != nil { + return nil, fmt.Errorf("compTeamRoles: %w", err) + } + roles[id] = append(roles[id], role) + } + return roles, rows.Err() +} + +func mapNames(ids []int64, names map[int64]string) []string { + out := make([]string, 0, len(ids)) + for _, id := range ids { + out = append(out, names[id]) + } + sort.Strings(out) + return out +} + +func orEmpty(l []string) []string { + if l == nil { + return []string{} + } + return l +} + +// ExportCompRulesets exports rulesets and their descendants, with the +// filtersets they use, in the format ImportCompliance reads, as +// _export_rulesets(). +func (oDb *DB) ExportCompRulesets(ctx context.Context, ids []int64) (CompRulesetExport, error) { + out := CompRulesetExport{Filtersets: []FiltersetExport{}, Rulesets: []CompExportRuleset{}} + if len(ids) == 0 { + return out, nil + } + children, err := oDb.compPairs(ctx, "exportCompRulesets", "SELECT parent_rset_id, child_rset_id FROM comp_rulesets_rulesets") + if err != nil { + return out, err + } + names, err := oDb.compNames(ctx, "comp_rulesets", "ruleset_name") + if err != nil { + return out, err + } + all := withDescendants(ids, children) + ph, args := idArgs(all) + + variables := map[int64][]CompExportVariable{} + rows, err := oDb.DB.QueryContext(ctx, "SELECT id, ruleset_id, COALESCE(var_name, ''), COALESCE(var_value, ''), COALESCE(var_class, ''),"+ + " COALESCE(var_author, ''), COALESCE(DATE_FORMAT(var_updated, '%Y-%m-%d %H:%i:%s'), '')"+ + " FROM comp_rulesets_variables WHERE ruleset_id IN ("+ph+") ORDER BY var_name", args...) + if err != nil { + return out, fmt.Errorf("exportCompRulesets variables: %w", err) + } + for rows.Next() { + var v CompExportVariable + var rid int64 + if err := rows.Scan(&v.ID, &rid, &v.VarName, &v.VarValue, &v.VarClass, &v.VarAuthor, &v.VarUpdated); err != nil { + _ = rows.Close() + return out, fmt.Errorf("exportCompRulesets variables: %w", err) + } + variables[rid] = append(variables[rid], v) + } + _ = rows.Close() + + publications, err := oDb.compTeamRoles(ctx, CompRulesetKind, "publication", all) + if err != nil { + return out, err + } + responsibles, err := oDb.compTeamRoles(ctx, CompRulesetKind, "responsible", all) + if err != nil { + return out, err + } + + var fsetIDs []int + rows, err = oDb.DB.QueryContext(ctx, "SELECT r.id, COALESCE(r.ruleset_name, ''), COALESCE(r.ruleset_public, ''), COALESCE(r.ruleset_type, ''), f.id, f.fset_name"+ + " FROM comp_rulesets r LEFT JOIN comp_rulesets_filtersets rf ON rf.ruleset_id = r.id LEFT JOIN gen_filtersets f ON f.id = rf.fset_id"+ + " WHERE r.id IN ("+ph+") ORDER BY r.ruleset_name", args...) + if err != nil { + return out, fmt.Errorf("exportCompRulesets: %w", err) + } + for rows.Next() { + var r CompExportRuleset + var fsetID sql.NullInt64 + var fsetName sql.NullString + if err := rows.Scan(&r.ID, &r.RulesetName, &r.RulesetPublic, &r.RulesetType, &fsetID, &fsetName); err != nil { + _ = rows.Close() + return out, fmt.Errorf("exportCompRulesets: %w", err) + } + if fsetID.Valid { + fsetIDs = append(fsetIDs, int(fsetID.Int64)) + name := fsetName.String + r.FsetName = &name + } + r.Variables = variables[r.ID] + if r.Variables == nil { + r.Variables = []CompExportVariable{} + } + r.Rulesets = mapNames(children[r.ID], names) + r.Publications = orEmpty(publications[r.ID]) + r.Responsibles = orEmpty(responsibles[r.ID]) + out.Rulesets = append(out.Rulesets, r) + } + _ = rows.Close() + + fsets, err := oDb.ExportFiltersets(ctx, fsetIDs) + if err != nil { + return out, err + } + out.Filtersets = fsets.Filtersets + return out, nil +} + +// ExportCompModulesets exports modulesets and their descendants, with the +// rulesets they hold, in the format ImportCompliance reads, as +// _export_modulesets(). +func (oDb *DB) ExportCompModulesets(ctx context.Context, ids []int64) (CompModulesetExport, error) { + out := CompModulesetExport{Modulesets: []CompExportModuleset{}} + out.Filtersets = []FiltersetExport{} + out.Rulesets = []CompExportRuleset{} + if len(ids) == 0 { + return out, nil + } + children, err := oDb.compPairs(ctx, "exportCompModulesets", "SELECT parent_modset_id, child_modset_id FROM comp_moduleset_moduleset") + if err != nil { + return out, err + } + rulesets, err := oDb.compPairs(ctx, "exportCompModulesets", "SELECT modset_id, ruleset_id FROM comp_moduleset_ruleset") + if err != nil { + return out, err + } + names, err := oDb.compNames(ctx, "comp_moduleset", "modset_name") + if err != nil { + return out, err + } + rsetNames, err := oDb.compNames(ctx, "comp_rulesets", "ruleset_name") + if err != nil { + return out, err + } + all := withDescendants(ids, children) + ph, args := idArgs(all) + + modules := map[int64][]CompExportModule{} + rows, err := oDb.DB.QueryContext(ctx, "SELECT modset_id, COALESCE(modset_mod_name, ''), COALESCE(autofix, '')"+ + " FROM comp_moduleset_modules WHERE modset_id IN ("+ph+") ORDER BY modset_mod_name", args...) + if err != nil { + return out, fmt.Errorf("exportCompModulesets modules: %w", err) + } + for rows.Next() { + var m CompExportModule + var mid int64 + if err := rows.Scan(&mid, &m.ModsetModName, &m.Autofix); err != nil { + _ = rows.Close() + return out, fmt.Errorf("exportCompModulesets modules: %w", err) + } + modules[mid] = append(modules[mid], m) + } + _ = rows.Close() + + publications, err := oDb.compTeamRoles(ctx, CompModulesetKind, "publication", all) + if err != nil { + return out, err + } + responsibles, err := oDb.compTeamRoles(ctx, CompModulesetKind, "responsible", all) + if err != nil { + return out, err + } + + var rsetIDs []int64 + for _, id := range all { + m := CompExportModuleset{ + ID: id, + ModsetName: names[id], + Modules: modules[id], + Modulesets: mapNames(children[id], names), + Rulesets: mapNames(rulesets[id], rsetNames), + Publications: orEmpty(publications[id]), + Responsibles: orEmpty(responsibles[id]), + } + if m.Modules == nil { + m.Modules = []CompExportModule{} + } + rsetIDs = append(rsetIDs, rulesets[id]...) + out.Modulesets = append(out.Modulesets, m) + } + sort.Slice(out.Modulesets, func(i, j int) bool { + return strings.ToLower(out.Modulesets[i].ModsetName) < strings.ToLower(out.Modulesets[j].ModsetName) + }) + + rsets, err := oDb.ExportCompRulesets(ctx, rsetIDs) + if err != nil { + return out, err + } + out.CompRulesetExport = rsets + return out, nil +} diff --git a/cdb/db_compliance_import.go b/cdb/db_compliance_import.go new file mode 100644 index 00000000..9454bf86 --- /dev/null +++ b/cdb/db_compliance_import.go @@ -0,0 +1,626 @@ +package cdb + +import ( + "context" + "database/sql" + "encoding/json" + "errors" + "fmt" + "strconv" + "strings" +) + +var ( + // ErrCompInvalid marks compliance designer data that cannot be used. + ErrCompInvalid = errors.New("invalid data") + + // ErrCompForbidden marks a compliance designer change the caller is not + // allowed to make. + ErrCompForbidden = errors.New("forbidden") +) + +// CompFlag is a boolean of the compliance designer, stored as "T" or "F". It +// reads a JSON boolean, number or string, as the historical exports hold either. +type CompFlag string + +func (f *CompFlag) UnmarshalJSON(b []byte) error { + var v any + if err := json.Unmarshal(b, &v); err != nil { + return err + } + switch t := v.(type) { + case bool: + *f = "F" + if t { + *f = "T" + } + return nil + case float64: + if t == 0 || t == 1 { + *f = CompFlag(map[bool]string{true: "T", false: "F"}[t == 1]) + return nil + } + case string: + switch strings.ToLower(strings.TrimSpace(t)) { + case "t", "true", "yes", "y", "1": + *f = "T" + return nil + case "f", "false", "no", "n", "0", "": + *f = "F" + return nil + } + } + return fmt.Errorf("invalid boolean %s", b) +} + +type ( + // CompImportFilter is a filter of an imported filterset. + CompImportFilter struct { + FTable *string `json:"f_table"` + FField *string `json:"f_field"` + FOp *string `json:"f_op"` + FValue *string `json:"f_value"` + } + + // CompImportFilterEntry is a filter or a filterset in an imported filterset. + CompImportFilterEntry struct { + FLogOp string `json:"f_log_op"` + FOrder int `json:"f_order"` + Filter *CompImportFilter `json:"filter"` + Filterset *string `json:"filterset"` + } + + // CompImportFilterset is an imported filterset. + CompImportFilterset struct { + FsetName *string `json:"fset_name"` + Filters []CompImportFilterEntry `json:"filters"` + } + + // CompImportVariable is a variable of an imported ruleset. + CompImportVariable struct { + VarName *string `json:"var_name"` + VarClass *string `json:"var_class"` + VarValue *string `json:"var_value"` + } + + // CompImportRuleset is an imported ruleset. + CompImportRuleset struct { + RulesetName *string `json:"ruleset_name"` + RulesetType *string `json:"ruleset_type"` + RulesetPublic *CompFlag `json:"ruleset_public"` + FsetName *string `json:"fset_name"` + Variables []CompImportVariable `json:"variables"` + Rulesets []string `json:"rulesets"` + } + + // CompImportModule is a module of an imported moduleset. + CompImportModule struct { + ModsetModName *string `json:"modset_mod_name"` + Autofix *CompFlag `json:"autofix"` + } + + // CompImportModuleset is an imported moduleset. + CompImportModuleset struct { + ModsetName *string `json:"modset_name"` + Modules []CompImportModule `json:"modules"` + Modulesets []string `json:"modulesets"` + Rulesets []string `json:"rulesets"` + } + + // CompImportData is what ExportCompRulesets and ExportCompModulesets write. + // The publications and responsibles of the export are not imported: the new + // objects get the importer's default group, as add_default_teams() gives. + CompImportData struct { + Filtersets []CompImportFilterset `json:"filtersets"` + Rulesets []CompImportRuleset `json:"rulesets"` + Modulesets []CompImportModuleset `json:"modulesets"` + } + + // CompImporter is who imports: the author recorded on the new objects, the + // group they are given, and whether the caller is responsible for an existing + // object the import adds to. + CompImporter struct { + Author string + GroupID int64 + Responsible func(ctx context.Context, k CompKind, id int64) (bool, error) + } + + compImport struct { + oDb *DB + imp CompImporter + messages []string + filters map[string]int + fsets map[string]int + rsets map[string]int64 + modsets map[string]int64 + // existing holds the objects the import found already there, which it + // may add to only when the caller is responsible for them. + existing map[string]bool + } +) + +func invalidf(format string, args ...any) error { + return fmt.Errorf("%w: "+format, append([]any{ErrCompInvalid}, args...)...) +} + +// ImportCompliance creates the filters, filtersets, rulesets and modulesets of +// an export, and their relations, as lib_compliance_import(): an object already +// there by name is reused, and the messages tell what was added and what already +// existed. Unlike the historical import, content is added to an existing +// ruleset or moduleset only when the caller is responsible for it, and a +// relation closing a loop is refused. Run it in a transaction, as it stops at +// the first error. +func (oDb *DB) ImportCompliance(ctx context.Context, data CompImportData, imp CompImporter) ([]string, error) { + ci := &compImport{ + oDb: oDb, + imp: imp, + messages: []string{}, + filters: map[string]int{}, + fsets: map[string]int{}, + rsets: map[string]int64{}, + modsets: map[string]int64{}, + existing: map[string]bool{}, + } + for _, step := range []func(context.Context, CompImportData) error{ + ci.importFilters, ci.importFiltersets, ci.importFiltersetRelations, + ci.importRulesets, ci.importRulesetFiltersets, ci.importRulesetRelations, ci.importVariables, + ci.importModulesets, ci.importModules, ci.importModulesetRelations, ci.importModulesetRulesets, + } { + if err := step(ctx, data); err != nil { + return nil, err + } + } + return ci.messages, nil +} + +func (ci *compImport) add(format string, args ...any) { + ci.messages = append(ci.messages, fmt.Sprintf(format, args...)) +} + +// mayChange refuses an addition to an existing object the caller is not +// responsible for. +func (ci *compImport) mayChange(ctx context.Context, k CompKind, name string, id int64) error { + if !ci.existing[k.Name+"/"+name] { + return nil + } + ok, err := ci.imp.Responsible(ctx, k, id) + if err != nil { + return err + } + if !ok { + return fmt.Errorf("%w: the %s %s already exists and you are not responsible for it", ErrCompForbidden, k.Name, name) + } + return nil +} + +func filterKey(f *CompImportFilter) (string, error) { + if f.FTable == nil || f.FField == nil || f.FOp == nil || f.FValue == nil { + b, _ := json.Marshal(f) + return "", invalidf("invalid filter format: %s", b) + } + return *f.FTable + "." + *f.FField + " " + *f.FOp + " " + *f.FValue, nil +} + +func (ci *compImport) importFilters(ctx context.Context, data CompImportData) error { + for _, fset := range data.Filtersets { + for _, entry := range fset.Filters { + f := entry.Filter + if f == nil { + continue + } + key, err := filterKey(f) + if err != nil { + return err + } + if _, done := ci.filters[key]; done { + continue + } + id, found, err := ci.oDb.FilterByDefinition(ctx, *f.FTable, *f.FField, *f.FOp, *f.FValue) + if err != nil { + return err + } + if found { + ci.filters[key] = id + ci.add("Filter already exists: %s", key) + continue + } + if id, err = ci.oDb.InsertFilter(ctx, *f.FTable, *f.FField, *f.FOp, *f.FValue, ci.imp.Author); err != nil { + return err + } + ci.oDb.SetChange("gen_filters") + ci.filters[key] = id + ci.add("Filter added: %s", key) + } + } + return nil +} + +func (ci *compImport) importFiltersets(ctx context.Context, data CompImportData) error { + for _, fset := range data.Filtersets { + if fset.FsetName == nil || *fset.FsetName == "" { + return invalidf("invalid filterset format: a fset_name is expected") + } + name := *fset.FsetName + id, found, err := ci.oDb.FiltersetByName(ctx, name) + if err != nil { + return err + } + if found { + ci.fsets[name] = id + ci.add("Filterset already exists: %s", name) + continue + } + if id, err = ci.oDb.InsertFilterset(ctx, name, "F", ci.imp.Author); err != nil { + return err + } + ci.oDb.SetChange("gen_filtersets") + ci.fsets[name] = id + ci.add("Filterset added: %s", name) + } + return nil +} + +// filtersetID resolves a filterset of the import, or one already there. +func (ci *compImport) filtersetID(ctx context.Context, name string) (int, error) { + if id, ok := ci.fsets[name]; ok { + return id, nil + } + id, found, err := ci.oDb.FiltersetByName(ctx, name) + if err != nil { + return 0, err + } + if !found { + return 0, invalidf("filterset %s not found", name) + } + ci.fsets[name] = id + return id, nil +} + +func (ci *compImport) importFiltersetRelations(ctx context.Context, data CompImportData) error { + for _, fset := range data.Filtersets { + fsetID := ci.fsets[*fset.FsetName] + for _, entry := range fset.Filters { + order := strconv.Itoa(entry.FOrder) + switch { + case entry.Filter != nil: + key, _ := filterKey(entry.Filter) + fID := ci.filters[key] + rel := *fset.FsetName + " -> " + entry.FLogOp + " " + key + " (" + order + ")" + if found, err := ci.oDb.exists(ctx, "importFiltersetRelations", + "SELECT 1 FROM gen_filtersets_filters WHERE fset_id = ? AND f_id = ? AND f_log_op = ? AND f_order = ?", + fsetID, fID, entry.FLogOp, entry.FOrder); err != nil { + return err + } else if found { + ci.add("Filterset relation already exists: %s", rel) + continue + } + if err := ci.oDb.InsertFiltersetFilter(ctx, fsetID, fID, entry.FOrder, entry.FLogOp); err != nil { + return err + } + ci.add("Filterset relation added: %s", rel) + case entry.Filterset != nil: + encapID, err := ci.filtersetID(ctx, *entry.Filterset) + if err != nil { + return err + } + rel := *fset.FsetName + " -> " + entry.FLogOp + " " + *entry.Filterset + " (" + order + ")" + if found, err := ci.oDb.exists(ctx, "importFiltersetRelations", + "SELECT 1 FROM gen_filtersets_filters WHERE fset_id = ? AND encap_fset_id = ? AND f_log_op = ? AND f_order = ?", + fsetID, encapID, entry.FLogOp, entry.FOrder); err != nil { + return err + } else if found { + ci.add("Filterset relation already exists: %s", rel) + continue + } + if loop, err := ci.oDb.FiltersetEncapWouldLoop(ctx, encapID, fsetID); err != nil { + return err + } else if loop || encapID == fsetID { + return invalidf("the filterset relation %s would cause an infinite recursion", rel) + } + if err := ci.oDb.InsertFiltersetEncap(ctx, fsetID, encapID, entry.FOrder, entry.FLogOp); err != nil { + return err + } + ci.add("Filterset relation added: %s", rel) + default: + continue + } + ci.oDb.SetChange("gen_filtersets_filters") + } + } + return nil +} + +// idByName returns the id of the object of a table named name. +func (ci *compImport) idByName(ctx context.Context, table, nameCol, name string) (int64, bool, error) { + var id int64 + err := ci.oDb.DB.QueryRowContext(ctx, "SELECT id FROM "+table+" WHERE "+nameCol+" = ? LIMIT 1", name).Scan(&id) + switch { + case errors.Is(err, sql.ErrNoRows): + return 0, false, nil + case err != nil: + return 0, false, fmt.Errorf("idByName %s: %w", table, err) + } + return id, true, nil +} + +func (ci *compImport) importRulesets(ctx context.Context, data CompImportData) error { + for _, rset := range data.Rulesets { + if rset.RulesetName == nil || *rset.RulesetName == "" || rset.RulesetType == nil || rset.RulesetPublic == nil { + b, _ := json.Marshal(rset) + return invalidf("invalid ruleset format: %s", b) + } + name := *rset.RulesetName + if *rset.RulesetType != "explicit" && *rset.RulesetType != "contextual" { + return invalidf("invalid ruleset_type %q of ruleset %s: expected explicit or contextual", *rset.RulesetType, name) + } + id, found, err := ci.idByName(ctx, "comp_rulesets", "ruleset_name", name) + if err != nil { + return err + } + if found { + ci.rsets[name] = id + ci.existing[CompRulesetKind.Name+"/"+name] = true + ci.add("Ruleset already exists: %s", name) + continue + } + if id, err = ci.oDb.CreateCompRuleset(ctx, name, *rset.RulesetType, string(*rset.RulesetPublic), ci.imp.GroupID); err != nil { + return err + } + ci.rsets[name] = id + ci.add("Ruleset added: %s", name) + } + return nil +} + +// rulesetID resolves a ruleset of the import, or one already there. +func (ci *compImport) rulesetID(ctx context.Context, name string) (int64, error) { + if id, ok := ci.rsets[name]; ok { + return id, nil + } + id, found, err := ci.idByName(ctx, "comp_rulesets", "ruleset_name", name) + if err != nil { + return 0, err + } + if !found { + return 0, invalidf("ruleset %s not found", name) + } + ci.rsets[name] = id + return id, nil +} + +func (ci *compImport) importRulesetFiltersets(ctx context.Context, data CompImportData) error { + for _, rset := range data.Rulesets { + if rset.FsetName == nil { + continue + } + name := *rset.RulesetName + rsetID := ci.rsets[name] + rel := name + " -> " + *rset.FsetName + fsetID, err := ci.filtersetID(ctx, *rset.FsetName) + if err != nil { + return err + } + if found, err := ci.oDb.exists(ctx, "importRulesetFiltersets", + "SELECT 1 FROM comp_rulesets_filtersets WHERE ruleset_id = ? AND fset_id = ?", rsetID, fsetID); err != nil { + return err + } else if found { + ci.add("Ruleset filterset relation already exists: %s", rel) + continue + } + if err := ci.mayChange(ctx, CompRulesetKind, name, rsetID); err != nil { + return err + } + if err := ci.oDb.SetCompRulesetFilterset(ctx, rsetID, int64(fsetID)); err != nil { + return err + } + ci.add("Ruleset filterset relation added: %s", rel) + } + return nil +} + +func (ci *compImport) importRulesetRelations(ctx context.Context, data CompImportData) error { + for _, rset := range data.Rulesets { + name := *rset.RulesetName + parent := ci.rsets[name] + for _, childName := range rset.Rulesets { + rel := name + " -> " + childName + child, err := ci.rulesetID(ctx, childName) + if err != nil { + return err + } + if found, err := ci.oDb.CompRulesetChildAttached(ctx, parent, child); err != nil { + return err + } else if found { + ci.add("Ruleset relation already exists: %s", rel) + continue + } + if err := ci.mayChange(ctx, CompRulesetKind, name, parent); err != nil { + return err + } + if loop, err := ci.oDb.CompRulesetLoop(ctx, child, parent); err != nil { + return err + } else if loop || child == parent { + return invalidf("the ruleset relation %s would cause an infinite recursion", rel) + } + if err := ci.oDb.AttachCompRulesetChild(ctx, parent, child); err != nil { + return err + } + ci.add("Ruleset relation added: %s", rel) + } + } + return nil +} + +func (ci *compImport) importVariables(ctx context.Context, data CompImportData) error { + for _, rset := range data.Rulesets { + name := *rset.RulesetName + rsetID := ci.rsets[name] + for _, v := range rset.Variables { + if v.VarName == nil || v.VarClass == nil || v.VarValue == nil { + b, _ := json.Marshal(v) + return invalidf("invalid variable format: %s", b) + } + desc := name + " :: " + *v.VarName + " (" + *v.VarClass + ")" + var id int64 + var class, value sql.NullString + err := ci.oDb.DB.QueryRowContext(ctx, "SELECT id, var_class, var_value FROM comp_rulesets_variables"+ + " WHERE ruleset_id = ? AND var_name = ? LIMIT 1", rsetID, *v.VarName).Scan(&id, &class, &value) + found := err == nil + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return fmt.Errorf("importVariables: %w", err) + } + if found && class.String == *v.VarClass && value.String == *v.VarValue { + ci.add("Variable already exists: %s", desc) + continue + } + if err := ci.mayChange(ctx, CompRulesetKind, name, rsetID); err != nil { + return err + } + fields := map[string]any{"var_class": *v.VarClass, "var_value": *v.VarValue} + if found { + err = ci.oDb.UpdateCompRulesetVariable(ctx, id, fields, ci.imp.Author) + } else { + fields["var_name"] = *v.VarName + _, err = ci.oDb.CreateCompRulesetVariable(ctx, rsetID, fields, ci.imp.Author) + } + if err != nil { + return err + } + ci.add("Variable added: %s", desc) + } + } + return nil +} + +func (ci *compImport) importModulesets(ctx context.Context, data CompImportData) error { + for _, modset := range data.Modulesets { + if modset.ModsetName == nil || *modset.ModsetName == "" { + return invalidf("invalid moduleset format: a modset_name is expected") + } + name := *modset.ModsetName + id, found, err := ci.idByName(ctx, "comp_moduleset", "modset_name", name) + if err != nil { + return err + } + if found { + ci.modsets[name] = id + ci.existing[CompModulesetKind.Name+"/"+name] = true + ci.add("Moduleset already exists: %s", name) + continue + } + if id, err = ci.oDb.CreateCompModuleset(ctx, name, ci.imp.Author, ci.imp.GroupID); err != nil { + return err + } + ci.modsets[name] = id + ci.add("Moduleset added: %s", name) + } + return nil +} + +func (ci *compImport) importModules(ctx context.Context, data CompImportData) error { + for _, modset := range data.Modulesets { + name := *modset.ModsetName + modsetID := ci.modsets[name] + for _, mod := range modset.Modules { + if mod.ModsetModName == nil || *mod.ModsetModName == "" || mod.Autofix == nil { + b, _ := json.Marshal(mod) + return invalidf("invalid module format: %s", b) + } + desc := name + " :: " + *mod.ModsetModName + " (" + string(*mod.Autofix) + ")" + var id int64 + var autofix sql.NullString + err := ci.oDb.DB.QueryRowContext(ctx, "SELECT id, autofix FROM comp_moduleset_modules"+ + " WHERE modset_id = ? AND modset_mod_name = ? LIMIT 1", modsetID, *mod.ModsetModName).Scan(&id, &autofix) + found := err == nil + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return fmt.Errorf("importModules: %w", err) + } + if stored := autofix.String == "T" || autofix.String == "1"; found && stored == (*mod.Autofix == "T") { + ci.add("Module already exists: %s", desc) + continue + } + if err := ci.mayChange(ctx, CompModulesetKind, name, modsetID); err != nil { + return err + } + fields := map[string]any{"autofix": string(*mod.Autofix)} + if found { + err = ci.oDb.UpdateCompModulesetModule(ctx, id, fields, ci.imp.Author) + } else { + fields["modset_mod_name"] = *mod.ModsetModName + _, err = ci.oDb.CreateCompModulesetModule(ctx, modsetID, fields, ci.imp.Author) + } + if err != nil { + return err + } + ci.add("Module added: %s", desc) + } + } + return nil +} + +func (ci *compImport) importModulesetRelations(ctx context.Context, data CompImportData) error { + for _, modset := range data.Modulesets { + name := *modset.ModsetName + parent := ci.modsets[name] + for _, childName := range modset.Modulesets { + rel := name + " -> " + childName + child, ok := ci.modsets[childName] + if !ok { + var found bool + var err error + if child, found, err = ci.idByName(ctx, "comp_moduleset", "modset_name", childName); err != nil { + return err + } else if !found { + return invalidf("moduleset %s not found", childName) + } + } + if found, err := ci.oDb.CompModulesetChildAttached(ctx, parent, child); err != nil { + return err + } else if found { + ci.add("Moduleset relation already exists: %s", rel) + continue + } + if err := ci.mayChange(ctx, CompModulesetKind, name, parent); err != nil { + return err + } + if loop, err := ci.oDb.CompModulesetLoop(ctx, child, parent); err != nil { + return err + } else if loop || child == parent { + return invalidf("the moduleset relation %s would cause an infinite recursion", rel) + } + if err := ci.oDb.AttachCompModulesetChild(ctx, parent, child); err != nil { + return err + } + ci.add("Moduleset relation added: %s", rel) + } + } + return nil +} + +func (ci *compImport) importModulesetRulesets(ctx context.Context, data CompImportData) error { + for _, modset := range data.Modulesets { + name := *modset.ModsetName + modsetID := ci.modsets[name] + for _, rsetName := range modset.Rulesets { + rel := name + " -> " + rsetName + rsetID, err := ci.rulesetID(ctx, rsetName) + if err != nil { + return err + } + if found, err := ci.oDb.CompModulesetRulesetAttached(ctx, modsetID, rsetID); err != nil { + return err + } else if found { + ci.add("Moduleset ruleset relation already exists: %s", rel) + continue + } + if err := ci.mayChange(ctx, CompModulesetKind, name, modsetID); err != nil { + return err + } + if err := ci.oDb.AttachCompModulesetRuleset(ctx, modsetID, rsetID); err != nil { + return err + } + ci.add("Moduleset ruleset relation added: %s", rel) + } + } + return nil +} diff --git a/server/api.yaml b/server/api.yaml index 33ad01b1..1b99147d 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -12243,6 +12243,180 @@ paths: - basicAuth: [ ] - bearerAuth: [ ] + /compliance/rulesets/export: + get: + operationId: GetComplianceRulesetsExport + description: | + Export the rulesets published to the user, with their descendants and the + filtersets they use. + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/CompRulesetExport' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /compliance/rulesets/{rset_id}/export: + get: + operationId: GetComplianceRulesetExport + description: | + Export a ruleset published to the user, with its descendants and its + filterset. + parameters: + - in: path + name: rset_id + required: true + description: Ruleset id or name + schema: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/CompRulesetExport' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /compliance/modulesets/export: + get: + operationId: GetComplianceModulesetsExport + description: | + Export the modulesets published to the user, with their descendants and the + rulesets and filtersets they use. + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/CompModulesetExport' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /compliance/modulesets/{modset_id}/export: + get: + operationId: GetComplianceModulesetExport + description: | + Export a moduleset published to the user, with its descendants and the rulesets + and filtersets they use. + parameters: + - in: path + name: modset_id + required: true + description: Moduleset id or name + schema: + type: string + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/CompModulesetExport' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + + /compliance/import: + post: + operationId: PostComplianceImport + description: | + Import the filters, filtersets, rulesets and modulesets of an export. An object + existing by name is reused, and the relations missing are added; the new objects + are given the user's default group as publication and responsible group, the + groups of the export are not imported. Requires the CompManager privilege, and + the responsibility of any existing ruleset or moduleset the import adds to. A + relation closing a loop is refused. The import applies all or nothing; the info + list tells what was added and what already existed. + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + filtersets: + type: array + items: + $ref: '#/components/schemas/FiltersetExportItem' + rulesets: + type: array + items: + $ref: '#/components/schemas/CompExportRuleset' + modulesets: + type: array + items: + $ref: '#/components/schemas/CompExportModuleset' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: array + items: + type: string + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + components: responses: @@ -13193,6 +13367,128 @@ components: meta: $ref: '#/components/schemas/ListMeta' + CompExportVariable: + type: object + properties: + id: + type: integer + var_name: + type: string + var_value: + type: string + var_class: + type: string + var_author: + type: string + var_updated: + type: string + + CompExportRuleset: + type: object + properties: + id: + type: integer + ruleset_name: + type: string + ruleset_public: + type: string + ruleset_type: + type: string + fset_name: + type: string + nullable: true + variables: + type: array + items: + $ref: '#/components/schemas/CompExportVariable' + rulesets: + description: The names of the child rulesets + type: array + items: + type: string + publications: + description: The roles of the publication groups + type: array + items: + type: string + responsibles: + description: The roles of the responsible groups + type: array + items: + type: string + + CompExportModule: + type: object + properties: + modset_mod_name: + type: string + autofix: + type: string + + CompExportModuleset: + type: object + properties: + id: + type: integer + modset_name: + type: string + modules: + type: array + items: + $ref: '#/components/schemas/CompExportModule' + modulesets: + description: The names of the child modulesets + type: array + items: + type: string + rulesets: + description: The names of the attached rulesets + type: array + items: + type: string + publications: + type: array + items: + type: string + responsibles: + type: array + items: + type: string + + CompRulesetExport: + type: object + description: | + Rulesets with their descendants and the filtersets they use, in the format + POST /compliance/import reads. + properties: + filtersets: + type: array + items: + $ref: '#/components/schemas/FiltersetExportItem' + rulesets: + type: array + items: + $ref: '#/components/schemas/CompExportRuleset' + + CompModulesetExport: + type: object + description: | + Modulesets with their descendants, and the rulesets and filtersets they use, + in the format POST /compliance/import reads. + properties: + filtersets: + type: array + items: + $ref: '#/components/schemas/FiltersetExportItem' + rulesets: + type: array + items: + $ref: '#/components/schemas/CompExportRuleset' + modulesets: + type: array + items: + $ref: '#/components/schemas/CompExportModuleset' + InstanceListResponse: type: object required: diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index 22775804..cef46e0b 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -123,6 +123,9 @@ type ServerInterface interface { // (POST /auth/node) PostAuthNode(ctx echo.Context) error + // (POST /compliance/import) + PostComplianceImport(ctx echo.Context) error + // (GET /compliance/logs) GetComplianceLogs(ctx echo.Context, params GetComplianceLogsParams) error @@ -138,6 +141,9 @@ type ServerInterface interface { // (POST /compliance/modulesets) PostComplianceModulesets(ctx echo.Context) error + // (GET /compliance/modulesets/export) + GetComplianceModulesetsExport(ctx echo.Context) error + // (DELETE /compliance/modulesets/{modset_id}) DeleteComplianceModuleset(ctx echo.Context, modsetId string) error @@ -159,6 +165,9 @@ type ServerInterface interface { // (GET /compliance/modulesets/{modset_id}/candidate_services) GetComplianceModulesetCandidateServices(ctx echo.Context, modsetId string, params GetComplianceModulesetCandidateServicesParams) error + // (GET /compliance/modulesets/{modset_id}/export) + GetComplianceModulesetExport(ctx echo.Context, modsetId string) error + // (GET /compliance/modulesets/{modset_id}/modules) GetComplianceModulesetModules(ctx echo.Context, modsetId string, params GetComplianceModulesetModulesParams) error @@ -246,6 +255,9 @@ type ServerInterface interface { // (POST /compliance/rulesets) PostComplianceRulesets(ctx echo.Context) error + // (GET /compliance/rulesets/export) + GetComplianceRulesetsExport(ctx echo.Context) error + // (DELETE /compliance/rulesets/{rset_id}) DeleteComplianceRuleset(ctx echo.Context, rsetId string) error @@ -267,6 +279,9 @@ type ServerInterface interface { // (GET /compliance/rulesets/{rset_id}/candidate_services) GetComplianceRulesetCandidateServices(ctx echo.Context, rsetId string, params GetComplianceRulesetCandidateServicesParams) error + // (GET /compliance/rulesets/{rset_id}/export) + GetComplianceRulesetExport(ctx echo.Context, rsetId string) error + // (DELETE /compliance/rulesets/{rset_id}/filtersets/{fset_id}) DeleteComplianceRulesetFilterset(ctx echo.Context, rsetId string, fsetId string) error @@ -2158,6 +2173,19 @@ func (w *ServerInterfaceWrapper) PostAuthNode(ctx echo.Context) error { return err } +// PostComplianceImport converts echo context to params. +func (w *ServerInterfaceWrapper) PostComplianceImport(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostComplianceImport(ctx) + return err +} + // GetComplianceLogs converts echo context to params. func (w *ServerInterfaceWrapper) GetComplianceLogs(ctx echo.Context) error { var err error @@ -2355,6 +2383,19 @@ func (w *ServerInterfaceWrapper) PostComplianceModulesets(ctx echo.Context) erro return err } +// GetComplianceModulesetsExport converts echo context to params. +func (w *ServerInterfaceWrapper) GetComplianceModulesetsExport(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetComplianceModulesetsExport(ctx) + return err +} + // DeleteComplianceModuleset converts echo context to params. func (w *ServerInterfaceWrapper) DeleteComplianceModuleset(ctx echo.Context) error { var err error @@ -2627,6 +2668,26 @@ func (w *ServerInterfaceWrapper) GetComplianceModulesetCandidateServices(ctx ech return err } +// GetComplianceModulesetExport converts echo context to params. +func (w *ServerInterfaceWrapper) GetComplianceModulesetExport(ctx echo.Context) error { + var err error + // ------------- Path parameter "modset_id" ------------- + var modsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "modset_id", ctx.Param("modset_id"), &modsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter modset_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetComplianceModulesetExport(ctx, modsetId) + return err +} + // GetComplianceModulesetModules converts echo context to params. func (w *ServerInterfaceWrapper) GetComplianceModulesetModules(ctx echo.Context) error { var err error @@ -3582,6 +3643,19 @@ func (w *ServerInterfaceWrapper) PostComplianceRulesets(ctx echo.Context) error return err } +// GetComplianceRulesetsExport converts echo context to params. +func (w *ServerInterfaceWrapper) GetComplianceRulesetsExport(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetComplianceRulesetsExport(ctx) + return err +} + // DeleteComplianceRuleset converts echo context to params. func (w *ServerInterfaceWrapper) DeleteComplianceRuleset(ctx echo.Context) error { var err error @@ -3854,6 +3928,26 @@ func (w *ServerInterfaceWrapper) GetComplianceRulesetCandidateServices(ctx echo. return err } +// GetComplianceRulesetExport converts echo context to params. +func (w *ServerInterfaceWrapper) GetComplianceRulesetExport(ctx echo.Context) error { + var err error + // ------------- Path parameter "rset_id" ------------- + var rsetId string + + err = runtime.BindStyledParameterWithOptions("simple", "rset_id", ctx.Param("rset_id"), &rsetId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter rset_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetComplianceRulesetExport(ctx, rsetId) + return err +} + // DeleteComplianceRulesetFilterset converts echo context to params. func (w *ServerInterfaceWrapper) DeleteComplianceRulesetFilterset(ctx echo.Context) error { var err error @@ -13225,11 +13319,13 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.POST(options.BaseURL+"/apps_responsibles", wrapper.PostAppsResponsibles, options.OperationMiddlewares["PostAppsResponsibles"]...) router.GET(options.BaseURL+"/arrays", wrapper.GetArrays, options.OperationMiddlewares["GetArrays"]...) router.POST(options.BaseURL+"/auth/node", wrapper.PostAuthNode, options.OperationMiddlewares["PostAuthNode"]...) + router.POST(options.BaseURL+"/compliance/import", wrapper.PostComplianceImport, options.OperationMiddlewares["PostComplianceImport"]...) router.GET(options.BaseURL+"/compliance/logs", wrapper.GetComplianceLogs, options.OperationMiddlewares["GetComplianceLogs"]...) router.GET(options.BaseURL+"/compliance/logs/:log_id", wrapper.GetComplianceLog, options.OperationMiddlewares["GetComplianceLog"]...) router.DELETE(options.BaseURL+"/compliance/modulesets", wrapper.DeleteComplianceModulesets, options.OperationMiddlewares["DeleteComplianceModulesets"]...) router.GET(options.BaseURL+"/compliance/modulesets", wrapper.GetComplianceModulesets, options.OperationMiddlewares["GetComplianceModulesets"]...) router.POST(options.BaseURL+"/compliance/modulesets", wrapper.PostComplianceModulesets, options.OperationMiddlewares["PostComplianceModulesets"]...) + router.GET(options.BaseURL+"/compliance/modulesets/export", wrapper.GetComplianceModulesetsExport, options.OperationMiddlewares["GetComplianceModulesetsExport"]...) router.DELETE(options.BaseURL+"/compliance/modulesets/:modset_id", wrapper.DeleteComplianceModuleset, options.OperationMiddlewares["DeleteComplianceModuleset"]...) router.GET(options.BaseURL+"/compliance/modulesets/:modset_id", wrapper.GetComplianceModuleset, options.OperationMiddlewares["GetComplianceModuleset"]...) router.POST(options.BaseURL+"/compliance/modulesets/:modset_id", wrapper.PostComplianceModuleset, options.OperationMiddlewares["PostComplianceModuleset"]...) @@ -13237,6 +13333,7 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.GET(options.BaseURL+"/compliance/modulesets/:modset_id/am_i_responsible", wrapper.GetComplianceModulesetAmIResponsible, options.OperationMiddlewares["GetComplianceModulesetAmIResponsible"]...) router.GET(options.BaseURL+"/compliance/modulesets/:modset_id/candidate_nodes", wrapper.GetComplianceModulesetCandidateNodes, options.OperationMiddlewares["GetComplianceModulesetCandidateNodes"]...) router.GET(options.BaseURL+"/compliance/modulesets/:modset_id/candidate_services", wrapper.GetComplianceModulesetCandidateServices, options.OperationMiddlewares["GetComplianceModulesetCandidateServices"]...) + router.GET(options.BaseURL+"/compliance/modulesets/:modset_id/export", wrapper.GetComplianceModulesetExport, options.OperationMiddlewares["GetComplianceModulesetExport"]...) router.GET(options.BaseURL+"/compliance/modulesets/:modset_id/modules", wrapper.GetComplianceModulesetModules, options.OperationMiddlewares["GetComplianceModulesetModules"]...) router.POST(options.BaseURL+"/compliance/modulesets/:modset_id/modules", wrapper.PostComplianceModulesetModules, options.OperationMiddlewares["PostComplianceModulesetModules"]...) router.DELETE(options.BaseURL+"/compliance/modulesets/:modset_id/modules/:mod_id", wrapper.DeleteComplianceModulesetModule, options.OperationMiddlewares["DeleteComplianceModulesetModule"]...) @@ -13266,6 +13363,7 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.DELETE(options.BaseURL+"/compliance/rulesets", wrapper.DeleteComplianceRulesets, options.OperationMiddlewares["DeleteComplianceRulesets"]...) router.GET(options.BaseURL+"/compliance/rulesets", wrapper.GetComplianceRulesets, options.OperationMiddlewares["GetComplianceRulesets"]...) router.POST(options.BaseURL+"/compliance/rulesets", wrapper.PostComplianceRulesets, options.OperationMiddlewares["PostComplianceRulesets"]...) + router.GET(options.BaseURL+"/compliance/rulesets/export", wrapper.GetComplianceRulesetsExport, options.OperationMiddlewares["GetComplianceRulesetsExport"]...) router.DELETE(options.BaseURL+"/compliance/rulesets/:rset_id", wrapper.DeleteComplianceRuleset, options.OperationMiddlewares["DeleteComplianceRuleset"]...) router.GET(options.BaseURL+"/compliance/rulesets/:rset_id", wrapper.GetComplianceRuleset, options.OperationMiddlewares["GetComplianceRuleset"]...) router.POST(options.BaseURL+"/compliance/rulesets/:rset_id", wrapper.PostComplianceRuleset, options.OperationMiddlewares["PostComplianceRuleset"]...) @@ -13273,6 +13371,7 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.GET(options.BaseURL+"/compliance/rulesets/:rset_id/am_i_responsible", wrapper.GetComplianceRulesetAmIResponsible, options.OperationMiddlewares["GetComplianceRulesetAmIResponsible"]...) router.GET(options.BaseURL+"/compliance/rulesets/:rset_id/candidate_nodes", wrapper.GetComplianceRulesetCandidateNodes, options.OperationMiddlewares["GetComplianceRulesetCandidateNodes"]...) router.GET(options.BaseURL+"/compliance/rulesets/:rset_id/candidate_services", wrapper.GetComplianceRulesetCandidateServices, options.OperationMiddlewares["GetComplianceRulesetCandidateServices"]...) + router.GET(options.BaseURL+"/compliance/rulesets/:rset_id/export", wrapper.GetComplianceRulesetExport, options.OperationMiddlewares["GetComplianceRulesetExport"]...) router.DELETE(options.BaseURL+"/compliance/rulesets/:rset_id/filtersets/:fset_id", wrapper.DeleteComplianceRulesetFilterset, options.OperationMiddlewares["DeleteComplianceRulesetFilterset"]...) router.POST(options.BaseURL+"/compliance/rulesets/:rset_id/filtersets/:fset_id", wrapper.PostComplianceRulesetFilterset, options.OperationMiddlewares["PostComplianceRulesetFilterset"]...) router.GET(options.BaseURL+"/compliance/rulesets/:rset_id/nodes", wrapper.GetComplianceRulesetNodes, options.OperationMiddlewares["GetComplianceRulesetNodes"]...) @@ -13500,417 +13599,428 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "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", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index f6f381de..eda2912d 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -456,6 +456,71 @@ type AppRow struct { Updated *string `json:"updated,omitempty"` } +// CompExportModule defines model for CompExportModule. +type CompExportModule struct { + Autofix *string `json:"autofix,omitempty"` + ModsetModName *string `json:"modset_mod_name,omitempty"` +} + +// CompExportModuleset defines model for CompExportModuleset. +type CompExportModuleset struct { + Id *int `json:"id,omitempty"` + ModsetName *string `json:"modset_name,omitempty"` + Modules *[]CompExportModule `json:"modules,omitempty"` + + // Modulesets The names of the child modulesets + Modulesets *[]string `json:"modulesets,omitempty"` + Publications *[]string `json:"publications,omitempty"` + Responsibles *[]string `json:"responsibles,omitempty"` + + // Rulesets The names of the attached rulesets + Rulesets *[]string `json:"rulesets,omitempty"` +} + +// CompExportRuleset defines model for CompExportRuleset. +type CompExportRuleset struct { + FsetName *string `json:"fset_name,omitempty"` + Id *int `json:"id,omitempty"` + + // Publications The roles of the publication groups + Publications *[]string `json:"publications,omitempty"` + + // Responsibles The roles of the responsible groups + Responsibles *[]string `json:"responsibles,omitempty"` + RulesetName *string `json:"ruleset_name,omitempty"` + RulesetPublic *string `json:"ruleset_public,omitempty"` + RulesetType *string `json:"ruleset_type,omitempty"` + + // Rulesets The names of the child rulesets + Rulesets *[]string `json:"rulesets,omitempty"` + Variables *[]CompExportVariable `json:"variables,omitempty"` +} + +// CompExportVariable defines model for CompExportVariable. +type CompExportVariable struct { + Id *int `json:"id,omitempty"` + VarAuthor *string `json:"var_author,omitempty"` + VarClass *string `json:"var_class,omitempty"` + VarName *string `json:"var_name,omitempty"` + VarUpdated *string `json:"var_updated,omitempty"` + VarValue *string `json:"var_value,omitempty"` +} + +// CompModulesetExport Modulesets with their descendants, and the rulesets and filtersets they use, +// in the format POST /compliance/import reads. +type CompModulesetExport struct { + Filtersets *[]FiltersetExportItem `json:"filtersets,omitempty"` + Modulesets *[]CompExportModuleset `json:"modulesets,omitempty"` + Rulesets *[]CompExportRuleset `json:"rulesets,omitempty"` +} + +// CompRulesetExport Rulesets with their descendants and the filtersets they use, in the format +// POST /compliance/import reads. +type CompRulesetExport struct { + Filtersets *[]FiltersetExportItem `json:"filtersets,omitempty"` + Rulesets *[]CompExportRuleset `json:"rulesets,omitempty"` +} + // ComplianceLogListResponse defines model for ComplianceLogListResponse. type ComplianceLogListResponse struct { Data ComplianceLogListResponse_Data `json:"data"` @@ -2067,6 +2132,13 @@ type PostAuthNodeJSONBody struct { Nodename string `json:"nodename"` } +// PostComplianceImportJSONBody defines parameters for PostComplianceImport. +type PostComplianceImportJSONBody struct { + Filtersets *[]FiltersetExportItem `json:"filtersets,omitempty"` + Modulesets *[]CompExportModuleset `json:"modulesets,omitempty"` + Rulesets *[]CompExportRuleset `json:"rulesets,omitempty"` +} + // GetComplianceLogsParams defines parameters for GetComplianceLogs. type GetComplianceLogsParams struct { // Props A list of properties to include in each data dictionnary. @@ -6525,6 +6597,9 @@ type PostAppsResponsiblesJSONRequestBody PostAppsResponsiblesJSONBody // PostAuthNodeJSONRequestBody defines body for PostAuthNode for application/json ContentType. type PostAuthNodeJSONRequestBody PostAuthNodeJSONBody +// PostComplianceImportJSONRequestBody defines body for PostComplianceImport for application/json ContentType. +type PostComplianceImportJSONRequestBody PostComplianceImportJSONBody + // DeleteComplianceModulesetsJSONRequestBody defines body for DeleteComplianceModulesets for application/json ContentType. type DeleteComplianceModulesetsJSONRequestBody DeleteComplianceModulesetsJSONBody diff --git a/server/handlers/compliance_common.go b/server/handlers/compliance_common.go index 31d2e1e4..cccc54e9 100644 --- a/server/handlers/compliance_common.go +++ b/server/handlers/compliance_common.go @@ -29,14 +29,18 @@ func checkCompManager(c echo.Context) error { } // compDesignerError turns the errors of the compliance designer queries into -// HTTP statuses: 404 for a missing object, 409 for a name already taken, 500 -// otherwise. +// HTTP statuses: 404 for a missing object, 409 for a name already taken, 400 +// for unusable data, 403 for a refused change, 500 otherwise. func compDesignerError(c echo.Context, name string, err error) error { switch { case errors.Is(err, cdb.ErrCompNotFound): return httpErrorf(http.StatusNotFound, "%s", err.Error()) case errors.Is(err, cdb.ErrCompConflict): return httpErrorf(http.StatusConflict, "%s", strings.TrimPrefix(err.Error(), cdb.ErrCompConflict.Error()+": ")) + case errors.Is(err, cdb.ErrCompInvalid): + return httpErrorf(http.StatusBadRequest, "%s", strings.TrimPrefix(err.Error(), cdb.ErrCompInvalid.Error()+": ")) + case errors.Is(err, cdb.ErrCompForbidden): + return httpErrorf(http.StatusForbidden, "%s", strings.TrimPrefix(err.Error(), cdb.ErrCompForbidden.Error()+": ")) } return httpInternal(echolog.GetLogHandler(c, name), "cannot "+name, err) } diff --git a/server/handlers/compliance_import.go b/server/handlers/compliance_import.go new file mode 100644 index 00000000..95a71496 --- /dev/null +++ b/server/handlers/compliance_import.go @@ -0,0 +1,124 @@ +package serverhandlers + +import ( + "context" + "database/sql" + "encoding/json" + "net/http" + + "github.com/labstack/echo/v4" + + "github.com/opensvc/oc3/cdb" + "github.com/opensvc/oc3/util/echolog" +) + +// GetComplianceRulesetsExport handles GET /compliance/rulesets/export, as the +// historical rest_get_compliance_rulesets_export: the rulesets published to the +// caller, their descendants and their filtersets, in the format of +// POST /compliance/import. +func (a *Api) GetComplianceRulesetsExport(c echo.Context) error { + ctx := c.Request().Context() + ids, err := a.ODB.CompPublishedIDs(ctx, cdb.CompRulesetKind, UserGroupsFromContext(c), IsManager(c)) + if err != nil { + return httpProblem(c, compDesignerError(c, "GetComplianceRulesetsExport", err)) + } + return a.rulesetsExport(c, "GetComplianceRulesetsExport", ids) +} + +// GetComplianceRulesetExport handles GET /compliance/rulesets/{rset_id}/export: +// a ruleset published to the caller, with its descendants and its filterset. +func (a *Api) GetComplianceRulesetExport(c echo.Context, rsetId string) error { + id, err := a.publishedRuleset(c, rsetId) + if err != nil { + return httpProblem(c, err) + } + return a.rulesetsExport(c, "GetComplianceRulesetExport", []int64{id}) +} + +func (a *Api) rulesetsExport(c echo.Context, name string, ids []int64) error { + data, err := a.ODB.ExportCompRulesets(c.Request().Context(), ids) + if err != nil { + return httpProblem(c, compDesignerError(c, name, err)) + } + return c.JSON(http.StatusOK, data) +} + +// GetComplianceModulesetsExport handles GET /compliance/modulesets/export, as +// the historical rest_get_compliance_modulesets_export: the modulesets published +// to the caller, their descendants, and the rulesets and filtersets they use. +func (a *Api) GetComplianceModulesetsExport(c echo.Context) error { + ctx := c.Request().Context() + ids, err := a.ODB.CompPublishedIDs(ctx, cdb.CompModulesetKind, UserGroupsFromContext(c), IsManager(c)) + if err != nil { + return httpProblem(c, compDesignerError(c, "GetComplianceModulesetsExport", err)) + } + return a.modulesetsExport(c, "GetComplianceModulesetsExport", ids) +} + +// GetComplianceModulesetExport handles GET /compliance/modulesets/{modset_id}/export: +// a moduleset published to the caller, with its descendants and their rulesets. +func (a *Api) GetComplianceModulesetExport(c echo.Context, modsetId string) error { + id, err := a.publishedModuleset(c, modsetId) + if err != nil { + return httpProblem(c, err) + } + return a.modulesetsExport(c, "GetComplianceModulesetExport", []int64{id}) +} + +func (a *Api) modulesetsExport(c echo.Context, name string, ids []int64) error { + data, err := a.ODB.ExportCompModulesets(c.Request().Context(), ids) + if err != nil { + return httpProblem(c, compDesignerError(c, name, err)) + } + return c.JSON(http.StatusOK, data) +} + +// PostComplianceImport handles POST /compliance/import, as the historical +// rest_post_compliance_import: the filters, filtersets, rulesets and modulesets +// of an export are created, or reused when they exist by name, and their +// relations added. Unlike the historical import, it requires the CompManager +// privilege, adds to an existing ruleset or moduleset only when the caller is +// responsible for it, and applies all or nothing. +func (a *Api) PostComplianceImport(c echo.Context) error { + const name = "PostComplianceImport" + if err := checkCompManager(c); err != nil { + return httpProblem(c, err) + } + var data cdb.CompImportData + if err := json.NewDecoder(c.Request().Body).Decode(&data); err != nil { + return httpProblem(c, httpErrorf(http.StatusBadRequest, "invalid request body: %s", err)) + } + ctx := c.Request().Context() + caller, err := a.formCaller(ctx, c) + if err != nil { + return httpProblem(c, compDesignerError(c, name, err)) + } + groupID, err := a.ODB.DefaultGroupOrManager(ctx, authUserID(c)) + if err != nil { + return httpProblem(c, compDesignerError(c, name, err)) + } + log := echolog.GetLogHandler(c, name) + tx, markSuccess, endTx, err := a.ODB.BeginTxWithControl(ctx, log, &sql.TxOptions{}) + if err != nil { + return httpProblem(c, httpInternal(log, "cannot start transaction", err)) + } + groups, isManager := UserGroupsFromContext(c), IsManager(c) + messages, err := tx.ImportCompliance(ctx, data, cdb.CompImporter{ + Author: caller.name, + GroupID: groupID, + Responsible: func(ctx context.Context, k cdb.CompKind, id int64) (bool, error) { + return tx.CompObjectResponsible(ctx, k, id, groups, isManager) + }, + }) + if err == nil { + markSuccess() + } + endTx() + if err != nil { + return httpProblem(c, compDesignerError(c, name, err)) + } + a.compLog(c, "compliance.import", "imported compliance designer data (%(n)s items)", + map[string]any{"n": len(messages)}, "", "") + a.afterRulesetChange(c, true) + return c.JSON(http.StatusOK, map[string][]string{"info": messages}) +} From a67e61c2347ae0c9b6df2a238ec761af5cbdfb21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Mon, 28 Sep 2026 16:04:54 +0200 Subject: [PATCH 50/61] Add a list of the modules of every moduleset GET /compliance/modulesets_modules lists, as the historical v_comp_modulesets view, one row per module with its moduleset and the moduleset's responsible and publication teams; a moduleset without module is listed on a row of its own, with a zero module id. The rows are restricted to the modulesets published to the caller, all of them for a manager. The teams come from derived tables whose columns are declared in cdb, so they can be filtered and sorted like the other props. --- cdb/db_compliance_modules.go | 35 + server/api.yaml | 89 +++ server/codegen_server_gen.go | 907 ++++++++++++++------------ server/codegen_type_gen.go | 143 ++++ server/handlers/compliance_modules.go | 9 + server/handlers/props_mapping.go | 23 + 6 files changed, 793 insertions(+), 413 deletions(-) diff --git a/cdb/db_compliance_modules.go b/cdb/db_compliance_modules.go index 949ec31d..8d09bb4e 100644 --- a/cdb/db_compliance_modules.go +++ b/cdb/db_compliance_modules.go @@ -7,8 +7,43 @@ import ( "fmt" "strconv" "strings" + + "github.com/opensvc/oc3/schema" +) + +// The team roles of each moduleset, as the derived tables modulesetsModulesFrom +// joins, so the lists can be filtered and sorted by them. +var ( + TModsetResponsibles = &schema.Table{Name: "modset_responsibles"} + TModsetPublications = &schema.Table{Name: "modset_publications"} + ModsetResponsibles = &schema.Col{T: TModsetResponsibles, Name: "teams", Nullable: true} + ModsetPublications = &schema.Col{T: TModsetPublications, Name: "teams", Nullable: true} ) +// modsetTeams aggregates the roles of the groups a team table gives each +// moduleset, into the derived table alias. +func modsetTeams(table, alias string) string { + return "LEFT JOIN (SELECT t.modset_id, GROUP_CONCAT(DISTINCT ag.role ORDER BY ag.role SEPARATOR ', ') AS teams" + + " FROM " + table + " t JOIN auth_group ag ON ag.id = t.group_id GROUP BY t.modset_id) " + alias + + " ON " + alias + ".modset_id = comp_moduleset.id" +} + +// modulesetsModulesFrom is the historical v_comp_modulesets view: every +// moduleset with each of its modules, a moduleset without module on a row of +// its own, and the responsible and publication teams of the moduleset. +var modulesetsModulesFrom = "comp_moduleset" + + " LEFT JOIN comp_moduleset_modules ON comp_moduleset_modules.modset_id = comp_moduleset.id " + + modsetTeams("comp_moduleset_team_responsible", TModsetResponsibles.Name) + " " + + modsetTeams("comp_moduleset_team_publication", TModsetPublications.Name) + +// GetComplianceModulesetsModules lists the modules of the modulesets visible to +// the caller, by moduleset and module name. +func (oDb *DB) GetComplianceModulesetsModules(ctx context.Context, p ListParams) ([]map[string]any, error) { + cond, args := compObjectVisibleCond(CompModulesetKind, p.Groups, p.IsManager) + return oDb.listQuery(ctx, "getComplianceModulesetsModules", modulesetsModulesFrom, []string{cond}, args, + "comp_moduleset.modset_name, comp_moduleset_modules.modset_mod_name", p) +} + // GetComplianceModulesetModules lists the modules of a moduleset, by name; one // when modID is set. func (oDb *DB) GetComplianceModulesetModules(ctx context.Context, modsetID int64, modID *int64, p ListParams) ([]map[string]any, error) { diff --git a/server/api.yaml b/server/api.yaml index 1b99147d..ddf69bf2 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -12059,6 +12059,43 @@ paths: - basicAuth: [ ] - bearerAuth: [ ] + /compliance/modulesets_modules: + get: + operationId: GetComplianceModulesetsModules + description: | + List the modules of the modulesets published to one of the user's groups, every + moduleset for a manager, as the historical v_comp_modulesets view: one row per + module, with its moduleset and the moduleset's responsible and publication + teams. A moduleset without module is listed on a row with a zero id and empty + module props. + parameters: + - $ref: '#/components/parameters/inQueryProps' + - $ref: '#/components/parameters/inQueryLimit' + - $ref: '#/components/parameters/inQueryOffset' + - $ref: '#/components/parameters/inQueryMeta' + - $ref: '#/components/parameters/inQueryStats' + - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryFilter' + - $ref: '#/components/parameters/inQueryGroupby' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ModulesetsModuleListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + /compliance/modulesets_nodes: post: operationId: PostComplianceModulesetsNodes @@ -13349,6 +13386,58 @@ components: modset_mod_updated: type: string + ModulesetsModuleRow: + type: object + description: | + A module of a compliance moduleset, with its moduleset and the moduleset's + teams. Every property is optional: the `props` query parameter selects which + columns the server returns. + properties: + id: + type: integer + description: The module id, 0 on the row of a moduleset without module. + modset_id: + type: integer + modset_name: + type: string + modset_author: + type: string + modset_updated: + type: string + modset_mod_name: + type: string + autofix: + type: string + description: T when the module is fixed without being asked, F otherwise. + modset_mod_author: + type: string + modset_mod_updated: + type: string + teams_responsible: + type: string + description: The roles of the groups responsible for the moduleset, comma separated. + teams_publication: + type: string + description: The roles of the groups the moduleset is published to, comma separated. + + ModulesetsModuleListResponse: + type: object + required: + - data + properties: + data: + oneOf: + - type: array + items: + $ref: '#/components/schemas/ModulesetsModuleRow' + - type: object + additionalProperties: + type: object + additionalProperties: + type: integer + meta: + $ref: '#/components/schemas/ListMeta' + ModulesetModuleListResponse: type: object required: diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index cef46e0b..7418d281 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -222,6 +222,9 @@ type ServerInterface interface { // (GET /compliance/modulesets/{modset_id}/usage) GetComplianceModulesetUsage(ctx echo.Context, modsetId string) error + // (GET /compliance/modulesets_modules) + GetComplianceModulesetsModules(ctx echo.Context, params GetComplianceModulesetsModulesParams) error + // (DELETE /compliance/modulesets_nodes) DeleteComplianceModulesetsNodes(ctx echo.Context) error @@ -3442,6 +3445,77 @@ func (w *ServerInterfaceWrapper) GetComplianceModulesetUsage(ctx echo.Context) e return err } +// GetComplianceModulesetsModules converts echo context to params. +func (w *ServerInterfaceWrapper) GetComplianceModulesetsModules(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetComplianceModulesetsModulesParams + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // ------------- Optional query parameter "limit" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) + } + + // ------------- Optional query parameter "offset" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) + } + + // ------------- Optional query parameter "meta" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) + } + + // ------------- Optional query parameter "stats" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) + } + + // ------------- Optional query parameter "orderby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) + } + + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + + // ------------- Optional query parameter "groupby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetComplianceModulesetsModules(ctx, params) + return err +} + // DeleteComplianceModulesetsNodes converts echo context to params. func (w *ServerInterfaceWrapper) DeleteComplianceModulesetsNodes(ctx echo.Context) error { var err error @@ -13352,6 +13426,7 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.POST(options.BaseURL+"/compliance/modulesets/:modset_id/rulesets/:rset_id", wrapper.PostComplianceModulesetRuleset, options.OperationMiddlewares["PostComplianceModulesetRuleset"]...) router.GET(options.BaseURL+"/compliance/modulesets/:modset_id/services", wrapper.GetComplianceModulesetServices, options.OperationMiddlewares["GetComplianceModulesetServices"]...) router.GET(options.BaseURL+"/compliance/modulesets/:modset_id/usage", wrapper.GetComplianceModulesetUsage, options.OperationMiddlewares["GetComplianceModulesetUsage"]...) + router.GET(options.BaseURL+"/compliance/modulesets_modules", wrapper.GetComplianceModulesetsModules, options.OperationMiddlewares["GetComplianceModulesetsModules"]...) router.DELETE(options.BaseURL+"/compliance/modulesets_nodes", wrapper.DeleteComplianceModulesetsNodes, options.OperationMiddlewares["DeleteComplianceModulesetsNodes"]...) router.POST(options.BaseURL+"/compliance/modulesets_nodes", wrapper.PostComplianceModulesetsNodes, options.OperationMiddlewares["PostComplianceModulesetsNodes"]...) router.DELETE(options.BaseURL+"/compliance/modulesets_publications", wrapper.DeleteComplianceModulesetsPublications, options.OperationMiddlewares["DeleteComplianceModulesetsPublications"]...) @@ -13599,66 +13674,66 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "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", @@ -13667,360 +13742,366 @@ var swaggerSpec = []string{ "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", + "/w==", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index eda2912d..f4580947 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -1106,6 +1106,47 @@ type ModulesetRow struct { ModsetUpdated *string `json:"modset_updated,omitempty"` } +// ModulesetsModuleListResponse defines model for ModulesetsModuleListResponse. +type ModulesetsModuleListResponse struct { + Data ModulesetsModuleListResponse_Data `json:"data"` + Meta *ListMeta `json:"meta,omitempty"` +} + +// ModulesetsModuleListResponseData0 defines model for . +type ModulesetsModuleListResponseData0 = []ModulesetsModuleRow + +// ModulesetsModuleListResponseData1 defines model for . +type ModulesetsModuleListResponseData1 map[string]map[string]int + +// ModulesetsModuleListResponse_Data defines model for ModulesetsModuleListResponse.Data. +type ModulesetsModuleListResponse_Data struct { + union json.RawMessage +} + +// ModulesetsModuleRow A module of a compliance moduleset, with its moduleset and the moduleset's +// teams. Every property is optional: the `props` query parameter selects which +// columns the server returns. +type ModulesetsModuleRow struct { + // Autofix T when the module is fixed without being asked, F otherwise. + Autofix *string `json:"autofix,omitempty"` + + // Id The module id, 0 on the row of a moduleset without module. + Id *int `json:"id,omitempty"` + ModsetAuthor *string `json:"modset_author,omitempty"` + ModsetId *int `json:"modset_id,omitempty"` + ModsetModAuthor *string `json:"modset_mod_author,omitempty"` + ModsetModName *string `json:"modset_mod_name,omitempty"` + ModsetModUpdated *string `json:"modset_mod_updated,omitempty"` + ModsetName *string `json:"modset_name,omitempty"` + ModsetUpdated *string `json:"modset_updated,omitempty"` + + // TeamsPublication The roles of the groups the moduleset is published to, comma separated. + TeamsPublication *string `json:"teams_publication,omitempty"` + + // TeamsResponsible The roles of the groups responsible for the moduleset, comma separated. + TeamsResponsible *string `json:"teams_responsible,omitempty"` +} + // NetworkListResponse defines model for NetworkListResponse. type NetworkListResponse struct { Data []NetworkRow `json:"data"` @@ -2561,6 +2602,46 @@ type GetComplianceModulesetServicesParams struct { Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` } +// GetComplianceModulesetsModulesParams defines parameters for GetComplianceModulesetsModules. +type GetComplianceModulesetsModulesParams struct { + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` + + // Limit The maximum number of entries to return. 0 means no limit. + Limit *InQueryLimit `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Skip the first entries of the data cursor. + Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` + + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. + Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` + + // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. + Stats *InQueryStats `form:"stats,omitempty" json:"stats,omitempty"` + + // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). + Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` + + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). + Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` +} + // DeleteComplianceModulesetsNodesJSONBody defines parameters for DeleteComplianceModulesetsNodes. type DeleteComplianceModulesetsNodesJSONBody struct { // ModsetId Moduleset id or name @@ -7912,6 +7993,68 @@ func (t *ModulesetModuleListResponse_Data) UnmarshalJSON(b []byte) error { return err } +// AsModulesetsModuleListResponseData0 returns the union data inside the ModulesetsModuleListResponse_Data as a ModulesetsModuleListResponseData0 +func (t ModulesetsModuleListResponse_Data) AsModulesetsModuleListResponseData0() (ModulesetsModuleListResponseData0, error) { + var body ModulesetsModuleListResponseData0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromModulesetsModuleListResponseData0 overwrites any union data inside the ModulesetsModuleListResponse_Data as the provided ModulesetsModuleListResponseData0 +func (t *ModulesetsModuleListResponse_Data) FromModulesetsModuleListResponseData0(v ModulesetsModuleListResponseData0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeModulesetsModuleListResponseData0 performs a merge with any union data inside the ModulesetsModuleListResponse_Data, using the provided ModulesetsModuleListResponseData0 +func (t *ModulesetsModuleListResponse_Data) MergeModulesetsModuleListResponseData0(v ModulesetsModuleListResponseData0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsModulesetsModuleListResponseData1 returns the union data inside the ModulesetsModuleListResponse_Data as a ModulesetsModuleListResponseData1 +func (t ModulesetsModuleListResponse_Data) AsModulesetsModuleListResponseData1() (ModulesetsModuleListResponseData1, error) { + var body ModulesetsModuleListResponseData1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromModulesetsModuleListResponseData1 overwrites any union data inside the ModulesetsModuleListResponse_Data as the provided ModulesetsModuleListResponseData1 +func (t *ModulesetsModuleListResponse_Data) FromModulesetsModuleListResponseData1(v ModulesetsModuleListResponseData1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeModulesetsModuleListResponseData1 performs a merge with any union data inside the ModulesetsModuleListResponse_Data, using the provided ModulesetsModuleListResponseData1 +func (t *ModulesetsModuleListResponse_Data) MergeModulesetsModuleListResponseData1(v ModulesetsModuleListResponseData1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t ModulesetsModuleListResponse_Data) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *ModulesetsModuleListResponse_Data) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + // AsNodeHardwareListResponseData0 returns the union data inside the NodeHardwareListResponse_Data as a NodeHardwareListResponseData0 func (t NodeHardwareListResponse_Data) AsNodeHardwareListResponseData0() (NodeHardwareListResponseData0, error) { var body NodeHardwareListResponseData0 diff --git a/server/handlers/compliance_modules.go b/server/handlers/compliance_modules.go index 4987f061..c6bbccea 100644 --- a/server/handlers/compliance_modules.go +++ b/server/handlers/compliance_modules.go @@ -67,6 +67,15 @@ func (a *Api) GetComplianceModulesetModules(c echo.Context, modsetId string, par }) } +// GetComplianceModulesetsModules handles GET /compliance/modulesets_modules. +func (a *Api) GetComplianceModulesetsModules(c echo.Context, params server.GetComplianceModulesetsModulesParams) error { + return a.handleList(c, "GetComplianceModulesetsModules", "modulesets_module", + listParams(params.Props, params.Limit, params.Offset, params.Meta, params.Stats, params.Orderby, params.Groupby, params.Filter), + func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetComplianceModulesetsModules(ctx, p) + }) +} + // GetComplianceModulesetModule handles GET /compliance/modulesets/{modset_id}/modules/{mod_id}. func (a *Api) GetComplianceModulesetModule(c echo.Context, modsetId, modId string, params server.GetComplianceModulesetModuleParams) error { ctx := c.Request().Context() diff --git a/server/handlers/props_mapping.go b/server/handlers/props_mapping.go index 8f59f436..7c4e9bcc 100644 --- a/server/handlers/props_mapping.go +++ b/server/handlers/props_mapping.go @@ -3,6 +3,7 @@ package serverhandlers import ( "fmt" + "github.com/opensvc/oc3/cdb" "github.com/opensvc/oc3/schema" ) @@ -769,6 +770,28 @@ var propsMapping = map[string]propMapping{ "modset_mod_updated": colStr(schema.CompModulesetModulesModsetModUpdated), }, }, + // Modules of every moduleset, as the historical v_comp_modulesets view: a + // moduleset without module has a row with a zero id and empty module props. + "modulesets_module": { + Available: []string{ + "id", "modset_id", "modset_name", "teams_responsible", "teams_publication", + "modset_mod_name", "autofix", "modset_mod_updated", "modset_mod_author", + "modset_author", "modset_updated", + }, + Props: map[string]propDef{ + "id": colInt(schema.CompModulesetModulesID), + "modset_id": col(schema.CompModulesetID), + "modset_name": colStr(schema.CompModulesetModsetName), + "modset_author": colStr(schema.CompModulesetModsetAuthor), + "modset_updated": colStr(schema.CompModulesetModsetUpdated), + "modset_mod_name": colStr(schema.CompModulesetModulesModsetModName), + "autofix": colStr(schema.CompModulesetModulesAutofix), + "modset_mod_author": colStr(schema.CompModulesetModulesModsetModAuthor), + "modset_mod_updated": colStr(schema.CompModulesetModulesModsetModUpdated), + "teams_responsible": colStr(cdb.ModsetResponsibles), + "teams_publication": colStr(cdb.ModsetPublications), + }, + }, // Variables of a compliance ruleset: the rules the modules apply. "ruleset_variable": { Available: []string{"id", "ruleset_id", "var_name", "var_class", "var_value", "var_author", "var_updated"}, From 6f74ffd705043756a0cc243716f637f5f7fab040 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Mon, 28 Sep 2026 16:30:48 +0200 Subject: [PATCH 51/61] Add a list of the variables of every ruleset GET /compliance/rulesets_variables lists, as the historical v_comp_rulesets view, the variables of each ruleset visible to the caller: its own, then those of each ruleset it encapsulates, found through comp_rulesets_chains and named by encap_rset and chain, with the ruleset's filterset and its responsible and publication teams. A ruleset of the chain without variable is listed on a row of its own, with a zero variable id. The team join of the modulesets list becomes compTeamsJoin, shared by both lists through their CompKind. --- cdb/db_compliance_modules.go | 17 +- cdb/db_compliance_variables.go | 42 ++ server/api.yaml | 108 +++ server/codegen_server_gen.go | 937 +++++++++++++----------- server/codegen_type_gen.go | 162 ++++ server/handlers/compliance_variables.go | 9 + server/handlers/props_mapping.go | 32 + 7 files changed, 871 insertions(+), 436 deletions(-) diff --git a/cdb/db_compliance_modules.go b/cdb/db_compliance_modules.go index 8d09bb4e..9995028b 100644 --- a/cdb/db_compliance_modules.go +++ b/cdb/db_compliance_modules.go @@ -20,12 +20,13 @@ var ( ModsetPublications = &schema.Col{T: TModsetPublications, Name: "teams", Nullable: true} ) -// modsetTeams aggregates the roles of the groups a team table gives each -// moduleset, into the derived table alias. -func modsetTeams(table, alias string) string { - return "LEFT JOIN (SELECT t.modset_id, GROUP_CONCAT(DISTINCT ag.role ORDER BY ag.role SEPARATOR ', ') AS teams" + - " FROM " + table + " t JOIN auth_group ag ON ag.id = t.group_id GROUP BY t.modset_id) " + alias + - " ON " + alias + ".modset_id = comp_moduleset.id" +// compTeamsJoin joins, under alias, the roles of the groups of gtype +// ("responsible" or "publication") of each object of kind k, comma separated in +// the teams column. +func compTeamsJoin(k CompKind, gtype, alias string) string { + return "LEFT JOIN (SELECT t." + k.FK + ", GROUP_CONCAT(DISTINCT ag.role ORDER BY ag.role SEPARATOR ', ') AS teams" + + " FROM " + k.TeamPrefix + gtype + " t JOIN auth_group ag ON ag.id = t.group_id GROUP BY t." + k.FK + ") " + alias + + " ON " + alias + "." + k.FK + " = " + k.Table + ".id" } // modulesetsModulesFrom is the historical v_comp_modulesets view: every @@ -33,8 +34,8 @@ func modsetTeams(table, alias string) string { // its own, and the responsible and publication teams of the moduleset. var modulesetsModulesFrom = "comp_moduleset" + " LEFT JOIN comp_moduleset_modules ON comp_moduleset_modules.modset_id = comp_moduleset.id " + - modsetTeams("comp_moduleset_team_responsible", TModsetResponsibles.Name) + " " + - modsetTeams("comp_moduleset_team_publication", TModsetPublications.Name) + compTeamsJoin(CompModulesetKind, "responsible", TModsetResponsibles.Name) + " " + + compTeamsJoin(CompModulesetKind, "publication", TModsetPublications.Name) // GetComplianceModulesetsModules lists the modules of the modulesets visible to // the caller, by moduleset and module name. diff --git a/cdb/db_compliance_variables.go b/cdb/db_compliance_variables.go index 0f3ecd69..2888943f 100644 --- a/cdb/db_compliance_variables.go +++ b/cdb/db_compliance_variables.go @@ -7,8 +7,50 @@ import ( "fmt" "strconv" "strings" + + "github.com/opensvc/oc3/schema" +) + +// The derived tables rulesetsVariablesFrom joins, declared as columns so the +// lists can be filtered and sorted by them: the team roles of each ruleset, and +// the chains from a ruleset to itself and to each ruleset it encapsulates. +var ( + TRsetResponsibles = &schema.Table{Name: "rset_responsibles"} + TRsetPublications = &schema.Table{Name: "rset_publications"} + TRsetChains = &schema.Table{Name: "rset_chains"} + RsetResponsibles = &schema.Col{T: TRsetResponsibles, Name: "teams", Nullable: true} + RsetPublications = &schema.Col{T: TRsetPublications, Name: "teams", Nullable: true} + RsetChainsChain = &schema.Col{T: TRsetChains, Name: "chain", Nullable: true} + RsetChainsLen = &schema.Col{T: TRsetChains, Name: "chain_len", Nullable: true} + RsetChainsEncap = &schema.Col{T: TRsetChains, Name: "encap_rset", Nullable: true} + RsetChainsEncapID = &schema.Col{T: TRsetChains, Name: "encap_rset_id", Nullable: true} ) +// rulesetsVariablesFrom is the historical v_comp_rulesets view: every ruleset +// with its filterset and teams, and the variables of the ruleset itself then of +// each ruleset it encapsulates, found through comp_rulesets_chains. On its own +// chain a ruleset names no encapsulated ruleset; a ruleset of the chain without +// variable is on a row of its own. +var rulesetsVariablesFrom = "comp_rulesets" + + " LEFT JOIN comp_rulesets_filtersets ON comp_rulesets_filtersets.ruleset_id = comp_rulesets.id" + + " LEFT JOIN gen_filtersets ON gen_filtersets.id = comp_rulesets_filtersets.fset_id " + + compTeamsJoin(CompRulesetKind, "responsible", TRsetResponsibles.Name) + " " + + compTeamsJoin(CompRulesetKind, "publication", TRsetPublications.Name) + + " LEFT JOIN (SELECT c.head_rset_id, c.tail_rset_id, c.chain, c.chain_len," + + " IF(c.tail_rset_id = c.head_rset_id, '', r.ruleset_name) AS encap_rset," + + " IF(c.tail_rset_id = c.head_rset_id, NULL, c.tail_rset_id) AS encap_rset_id" + + " FROM comp_rulesets_chains c JOIN comp_rulesets r ON r.id = c.tail_rset_id) " + TRsetChains.Name + + " ON " + TRsetChains.Name + ".head_rset_id = comp_rulesets.id" + + " LEFT JOIN comp_rulesets_variables ON comp_rulesets_variables.ruleset_id = " + TRsetChains.Name + ".tail_rset_id" + +// GetComplianceRulesetsVariables lists the variables of the rulesets visible to +// the caller, encapsulated ones included, by ruleset, chain and variable name. +func (oDb *DB) GetComplianceRulesetsVariables(ctx context.Context, p ListParams) ([]map[string]any, error) { + cond, args := compRulesetVisibleCond(p.Groups, p.IsManager) + return oDb.listQuery(ctx, "getComplianceRulesetsVariables", rulesetsVariablesFrom, []string{cond}, args, + "comp_rulesets.ruleset_name, "+RsetChainsLen.Qualified()+", "+RsetChainsEncap.Qualified()+", comp_rulesets_variables.var_name", p) +} + // CompRulesetPublished tells whether a ruleset is published to the caller: to // one of the caller's groups or to Everybody, as ruleset_publication(); always // for a manager. diff --git a/server/api.yaml b/server/api.yaml index ddf69bf2..a35ac9d5 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -9454,6 +9454,42 @@ paths: - bearerAuth: [ ] /compliance/rulesets_variables: + get: + operationId: GetComplianceRulesetsVariables + description: | + List the variables of the rulesets published to one of the user's groups, every + ruleset for a manager, as the historical v_comp_rulesets view: a ruleset lists + its own variables, then those of each ruleset it encapsulates, named by + encap_rset and chain, with the ruleset's filterset and its responsible and + publication teams. A ruleset of the chain without variable is listed on a row + with a zero id and empty variable props. + parameters: + - $ref: '#/components/parameters/inQueryProps' + - $ref: '#/components/parameters/inQueryLimit' + - $ref: '#/components/parameters/inQueryOffset' + - $ref: '#/components/parameters/inQueryMeta' + - $ref: '#/components/parameters/inQueryStats' + - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryFilter' + - $ref: '#/components/parameters/inQueryGroupby' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/RulesetsVariableListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] post: operationId: PostComplianceRulesetsVariables description: | @@ -13386,6 +13422,78 @@ components: modset_mod_updated: type: string + RulesetsVariableRow: + type: object + description: | + A variable of a compliance ruleset, own or encapsulated, with its ruleset and + the ruleset's filterset and teams. Every property is optional: the `props` + query parameter selects which columns the server returns. + properties: + id: + type: integer + description: The variable id, 0 on the row of a ruleset without variable. + ruleset_id: + type: integer + ruleset_name: + type: string + ruleset_type: + type: string + description: explicit or contextual. + ruleset_public: + type: string + description: T when the ruleset is public, F otherwise. + teams_responsible: + type: string + description: The roles of the groups responsible for the ruleset, comma separated. + teams_publication: + type: string + description: The roles of the groups the ruleset is published to, comma separated. + fset_name: + type: string + description: The filterset of a contextual ruleset. + fset_id: + type: integer + chain: + type: string + description: The path from the ruleset to the encapsulated one, as "a > b > c", empty for its own variables. + chain_len: + type: integer + description: The number of rulesets in the chain, 1 for its own variables. + encap_rset: + type: string + description: The encapsulated ruleset holding the variable, empty for its own variables. + encap_rset_id: + type: integer + description: The id of encap_rset, 0 for its own variables. + var_class: + type: string + var_name: + type: string + var_value: + type: string + var_updated: + type: string + var_author: + type: string + + RulesetsVariableListResponse: + type: object + required: + - data + properties: + data: + oneOf: + - type: array + items: + $ref: '#/components/schemas/RulesetsVariableRow' + - type: object + additionalProperties: + type: object + additionalProperties: + type: integer + meta: + $ref: '#/components/schemas/ListMeta' + ModulesetsModuleRow: type: object description: | diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index 7418d281..2b9adc60 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -366,6 +366,9 @@ type ServerInterface interface { // (POST /compliance/rulesets_services) PostComplianceRulesetsServices(ctx echo.Context) error + // (GET /compliance/rulesets_variables) + GetComplianceRulesetsVariables(ctx echo.Context, params GetComplianceRulesetsVariablesParams) error + // (POST /compliance/rulesets_variables) PostComplianceRulesetsVariables(ctx echo.Context) error @@ -4908,6 +4911,77 @@ func (w *ServerInterfaceWrapper) PostComplianceRulesetsServices(ctx echo.Context return err } +// GetComplianceRulesetsVariables converts echo context to params. +func (w *ServerInterfaceWrapper) GetComplianceRulesetsVariables(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetComplianceRulesetsVariablesParams + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // ------------- Optional query parameter "limit" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) + } + + // ------------- Optional query parameter "offset" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) + } + + // ------------- Optional query parameter "meta" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) + } + + // ------------- Optional query parameter "stats" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) + } + + // ------------- Optional query parameter "orderby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) + } + + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + + // ------------- Optional query parameter "groupby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetComplianceRulesetsVariables(ctx, params) + return err +} + // PostComplianceRulesetsVariables converts echo context to params. func (w *ServerInterfaceWrapper) PostComplianceRulesetsVariables(ctx echo.Context) error { var err error @@ -13474,6 +13548,7 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.POST(options.BaseURL+"/compliance/rulesets_responsibles", wrapper.PostComplianceRulesetsResponsibles, options.OperationMiddlewares["PostComplianceRulesetsResponsibles"]...) router.DELETE(options.BaseURL+"/compliance/rulesets_services", wrapper.DeleteComplianceRulesetsServices, options.OperationMiddlewares["DeleteComplianceRulesetsServices"]...) router.POST(options.BaseURL+"/compliance/rulesets_services", wrapper.PostComplianceRulesetsServices, options.OperationMiddlewares["PostComplianceRulesetsServices"]...) + router.GET(options.BaseURL+"/compliance/rulesets_variables", wrapper.GetComplianceRulesetsVariables, options.OperationMiddlewares["GetComplianceRulesetsVariables"]...) router.POST(options.BaseURL+"/compliance/rulesets_variables", wrapper.PostComplianceRulesetsVariables, options.OperationMiddlewares["PostComplianceRulesetsVariables"]...) router.DELETE(options.BaseURL+"/compliance/status", wrapper.DeleteComplianceStatus, options.OperationMiddlewares["DeleteComplianceStatus"]...) router.GET(options.BaseURL+"/compliance/status", wrapper.GetComplianceStatus, options.OperationMiddlewares["GetComplianceStatus"]...) @@ -13674,434 +13749,440 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "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", - "/w==", + "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", + "Ph4Pz49x0o7fZdszeFtcFhcfirvvdz8CAAD//w==", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index f4580947..b157ffec 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -1497,6 +1497,66 @@ type RulesetVariableRow struct { VarValue *string `json:"var_value,omitempty"` } +// RulesetsVariableListResponse defines model for RulesetsVariableListResponse. +type RulesetsVariableListResponse struct { + Data RulesetsVariableListResponse_Data `json:"data"` + Meta *ListMeta `json:"meta,omitempty"` +} + +// RulesetsVariableListResponseData0 defines model for . +type RulesetsVariableListResponseData0 = []RulesetsVariableRow + +// RulesetsVariableListResponseData1 defines model for . +type RulesetsVariableListResponseData1 map[string]map[string]int + +// RulesetsVariableListResponse_Data defines model for RulesetsVariableListResponse.Data. +type RulesetsVariableListResponse_Data struct { + union json.RawMessage +} + +// RulesetsVariableRow A variable of a compliance ruleset, own or encapsulated, with its ruleset and +// the ruleset's filterset and teams. Every property is optional: the `props` +// query parameter selects which columns the server returns. +type RulesetsVariableRow struct { + // Chain The path from the ruleset to the encapsulated one, as "a > b > c", empty for its own variables. + Chain *string `json:"chain,omitempty"` + + // ChainLen The number of rulesets in the chain, 1 for its own variables. + ChainLen *int `json:"chain_len,omitempty"` + + // EncapRset The encapsulated ruleset holding the variable, empty for its own variables. + EncapRset *string `json:"encap_rset,omitempty"` + + // EncapRsetId The id of encap_rset, 0 for its own variables. + EncapRsetId *int `json:"encap_rset_id,omitempty"` + FsetId *int `json:"fset_id,omitempty"` + + // FsetName The filterset of a contextual ruleset. + FsetName *string `json:"fset_name,omitempty"` + + // Id The variable id, 0 on the row of a ruleset without variable. + Id *int `json:"id,omitempty"` + RulesetId *int `json:"ruleset_id,omitempty"` + RulesetName *string `json:"ruleset_name,omitempty"` + + // RulesetPublic T when the ruleset is public, F otherwise. + RulesetPublic *string `json:"ruleset_public,omitempty"` + + // RulesetType explicit or contextual. + RulesetType *string `json:"ruleset_type,omitempty"` + + // TeamsPublication The roles of the groups the ruleset is published to, comma separated. + TeamsPublication *string `json:"teams_publication,omitempty"` + + // TeamsResponsible The roles of the groups responsible for the ruleset, comma separated. + TeamsResponsible *string `json:"teams_responsible,omitempty"` + VarAuthor *string `json:"var_author,omitempty"` + VarClass *string `json:"var_class,omitempty"` + VarName *string `json:"var_name,omitempty"` + VarUpdated *string `json:"var_updated,omitempty"` + VarValue *string `json:"var_value,omitempty"` +} + // ServiceListResponse defines model for ServiceListResponse. type ServiceListResponse struct { Data ServiceListResponse_Data `json:"data"` @@ -3199,6 +3259,46 @@ type PostComplianceRulesetsServicesJSONBody struct { SvcId string `json:"svc_id"` } +// GetComplianceRulesetsVariablesParams defines parameters for GetComplianceRulesetsVariables. +type GetComplianceRulesetsVariablesParams struct { + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` + + // Limit The maximum number of entries to return. 0 means no limit. + Limit *InQueryLimit `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Skip the first entries of the data cursor. + Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` + + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. + Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` + + // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. + Stats *InQueryStats `form:"stats,omitempty" json:"stats,omitempty"` + + // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). + Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` + + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). + Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` +} + // PostComplianceRulesetsVariablesJSONBody defines parameters for PostComplianceRulesetsVariables. type PostComplianceRulesetsVariablesJSONBody struct { RulesetId *int `json:"ruleset_id,omitempty"` @@ -8427,6 +8527,68 @@ func (t *RulesetVariableListResponse_Data) UnmarshalJSON(b []byte) error { return err } +// AsRulesetsVariableListResponseData0 returns the union data inside the RulesetsVariableListResponse_Data as a RulesetsVariableListResponseData0 +func (t RulesetsVariableListResponse_Data) AsRulesetsVariableListResponseData0() (RulesetsVariableListResponseData0, error) { + var body RulesetsVariableListResponseData0 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromRulesetsVariableListResponseData0 overwrites any union data inside the RulesetsVariableListResponse_Data as the provided RulesetsVariableListResponseData0 +func (t *RulesetsVariableListResponse_Data) FromRulesetsVariableListResponseData0(v RulesetsVariableListResponseData0) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeRulesetsVariableListResponseData0 performs a merge with any union data inside the RulesetsVariableListResponse_Data, using the provided RulesetsVariableListResponseData0 +func (t *RulesetsVariableListResponse_Data) MergeRulesetsVariableListResponseData0(v RulesetsVariableListResponseData0) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsRulesetsVariableListResponseData1 returns the union data inside the RulesetsVariableListResponse_Data as a RulesetsVariableListResponseData1 +func (t RulesetsVariableListResponse_Data) AsRulesetsVariableListResponseData1() (RulesetsVariableListResponseData1, error) { + var body RulesetsVariableListResponseData1 + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromRulesetsVariableListResponseData1 overwrites any union data inside the RulesetsVariableListResponse_Data as the provided RulesetsVariableListResponseData1 +func (t *RulesetsVariableListResponse_Data) FromRulesetsVariableListResponseData1(v RulesetsVariableListResponseData1) error { + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeRulesetsVariableListResponseData1 performs a merge with any union data inside the RulesetsVariableListResponse_Data, using the provided RulesetsVariableListResponseData1 +func (t *RulesetsVariableListResponse_Data) MergeRulesetsVariableListResponseData1(v RulesetsVariableListResponseData1) error { + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t RulesetsVariableListResponse_Data) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + return b, err +} + +func (t *RulesetsVariableListResponse_Data) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + return err +} + // AsServiceListResponseData0 returns the union data inside the ServiceListResponse_Data as a ServiceListResponseData0 func (t ServiceListResponse_Data) AsServiceListResponseData0() (ServiceListResponseData0, error) { var body ServiceListResponseData0 diff --git a/server/handlers/compliance_variables.go b/server/handlers/compliance_variables.go index 6504d060..d84fa678 100644 --- a/server/handlers/compliance_variables.go +++ b/server/handlers/compliance_variables.go @@ -138,6 +138,15 @@ func (a *Api) PostComplianceRulesetVariables(c echo.Context, rsetId string) erro } // PostComplianceRulesetsVariables handles POST /compliance/rulesets_variables, +// GetComplianceRulesetsVariables handles GET /compliance/rulesets_variables. +func (a *Api) GetComplianceRulesetsVariables(c echo.Context, params server.GetComplianceRulesetsVariablesParams) error { + return a.handleList(c, "GetComplianceRulesetsVariables", "rulesets_variable", + listParams(params.Props, params.Limit, params.Offset, params.Meta, params.Stats, params.Orderby, params.Groupby, params.Filter), + func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetComplianceRulesetsVariables(ctx, p) + }) +} + // the form naming the ruleset by ruleset_id or ruleset_name in the body. func (a *Api) PostComplianceRulesetsVariables(c echo.Context) error { entry, err := oneEntry(c) diff --git a/server/handlers/props_mapping.go b/server/handlers/props_mapping.go index 7c4e9bcc..642dba7b 100644 --- a/server/handlers/props_mapping.go +++ b/server/handlers/props_mapping.go @@ -792,6 +792,38 @@ var propsMapping = map[string]propMapping{ "teams_publication": colStr(cdb.ModsetPublications), }, }, + // Variables of every ruleset, as the historical v_comp_rulesets view: a + // ruleset lists its own variables, then those of each ruleset it + // encapsulates; a ruleset of the chain without variable has a row with a zero + // id and empty variable props. + "rulesets_variable": { + Available: []string{ + "id", "ruleset_id", "ruleset_name", "ruleset_type", "ruleset_public", + "teams_responsible", "teams_publication", "fset_name", "chain", "chain_len", + "encap_rset", "var_class", "var_name", "var_value", "var_updated", "var_author", + "encap_rset_id", "fset_id", + }, + Props: map[string]propDef{ + "id": colInt(schema.CompRulesetsVariablesID), + "ruleset_id": col(schema.CompRulesetsID), + "ruleset_name": colStr(schema.CompRulesetsRulesetName), + "ruleset_type": colStr(schema.CompRulesetsRulesetType), + "ruleset_public": colStr(schema.CompRulesetsRulesetPublic), + "teams_responsible": colStr(cdb.RsetResponsibles), + "teams_publication": colStr(cdb.RsetPublications), + "fset_name": colStr(schema.GenFiltersetsFsetName), + "chain": colStr(cdb.RsetChainsChain), + "chain_len": colInt(cdb.RsetChainsLen), + "encap_rset": colStr(cdb.RsetChainsEncap), + "var_class": colStr(schema.CompRulesetsVariablesVarClass), + "var_name": colStr(schema.CompRulesetsVariablesVarName), + "var_value": colStr(schema.CompRulesetsVariablesVarValue), + "var_updated": colStr(schema.CompRulesetsVariablesVarUpdated), + "var_author": colStr(schema.CompRulesetsVariablesVarAuthor), + "encap_rset_id": colInt(cdb.RsetChainsEncapID), + "fset_id": colInt(schema.CompRulesetsFiltersetsFsetID), + }, + }, // Variables of a compliance ruleset: the rules the modules apply. "ruleset_variable": { Available: []string{"id", "ruleset_id", "var_name", "var_class", "var_value", "var_author", "var_updated"}, From 4d97723195247dc890910086c771afac7c78b11c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Mon, 28 Sep 2026 16:43:00 +0200 Subject: [PATCH 52/61] Name the node and service of compliance runs and filter them by filterset GET /compliance/logs joins the nodes and services tables, so the nodes.* and services.* props give the names of a run's node and service, and accepts fset_id, a filterset id or name restricting the runs to the nodes it selects, as apply_filters_id() does on the node of a run. An unknown filterset is a 404. --- cdb/db_compliance_api.go | 23 +- server/api.yaml | 17 +- server/codegen_server_gen.go | 877 ++++++++++++++------------- server/codegen_type_gen.go | 27 +- server/handlers/compliance_status.go | 35 +- server/handlers/props_mapping.go | 6 + 6 files changed, 535 insertions(+), 450 deletions(-) diff --git a/cdb/db_compliance_api.go b/cdb/db_compliance_api.go index 47b3eea6..7050f51e 100644 --- a/cdb/db_compliance_api.go +++ b/cdb/db_compliance_api.go @@ -29,16 +29,33 @@ func compPublishedNodesCond(nodeCol string, groups []string, isManager bool) (st " WHERE ag.role IN (" + Placeholders(len(clean)) + "))", args } +// compLogFrom joins the node and the service of a run, for their names. +const compLogFrom = "comp_log" + + " LEFT JOIN nodes ON nodes.node_id = comp_log.node_id" + + " LEFT JOIN services ON services.svc_id = comp_log.svc_id" + // GetComplianceLogs lists the compliance module runs (check, fixable, fix) of the -// nodes the caller may see, the most recent first; one when id is set. -func (oDb *DB) GetComplianceLogs(ctx context.Context, id *int64, p ListParams) ([]map[string]any, error) { +// nodes the caller may see, the most recent first; one when id is set. A non-nil +// fsetNodeIDs restricts the runs to those nodes, the ones a filterset selects, +// as apply_filters_id() does on the node of a run. +func (oDb *DB) GetComplianceLogs(ctx context.Context, id *int64, fsetNodeIDs []string, p ListParams) ([]map[string]any, error) { cond, args := compPublishedNodesCond("comp_log.node_id", p.Groups, p.IsManager) conds := []string{cond} if id != nil { conds = append(conds, "comp_log.id = ?") args = append(args, *id) } - return oDb.listQuery(ctx, "getComplianceLogs", "comp_log", conds, args, "comp_log.id DESC", p) + if fsetNodeIDs != nil { + if len(fsetNodeIDs) == 0 { + conds = append(conds, "1=0") + } else { + conds = append(conds, "comp_log.node_id IN ("+Placeholders(len(fsetNodeIDs))+")") + for _, nodeID := range fsetNodeIDs { + args = append(args, nodeID) + } + } + } + return oDb.listQuery(ctx, "getComplianceLogs", compLogFrom, conds, args, "comp_log.id DESC", p) } // GetComplianceStatus lists the last check run of each module-node-service tuple, diff --git a/server/api.yaml b/server/api.yaml index a35ac9d5..92d3e72d 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -8794,8 +8794,15 @@ paths: description: | List the compliance modules' check, fixable and fix runs of the nodes the user can see: those whose app is published to one of the user's groups, every - node for a manager. The most recent first by default. + node for a manager. The most recent first by default. The nodes.* and + services.* props give the node and service names. parameters: + - in: query + name: fset_id + required: false + description: Restrict to the runs of the nodes this filterset selects (gen_filtersets.id or fset_name) + schema: + type: string - $ref: '#/components/parameters/inQueryProps' - $ref: '#/components/parameters/inQueryLimit' - $ref: '#/components/parameters/inQueryOffset' @@ -13300,6 +13307,14 @@ components: type: string svc_id: type: string + nodes.nodename: + type: string + nullable: true + description: The name of the node, joined. + services.svcname: + type: string + nullable: true + description: The name of the service, joined; null for a run on the node itself. ComplianceLogListResponse: type: object diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index 2b9adc60..0e5407f5 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -2202,6 +2202,13 @@ func (w *ServerInterfaceWrapper) GetComplianceLogs(ctx echo.Context) error { // Parameter object where we will unmarshal all parameters from the context var params GetComplianceLogsParams + // ------------- Optional query parameter "fset_id" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "fset_id", ctx.QueryParams(), ¶ms.FsetId, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter fset_id: %s", err)) + } + // ------------- Optional query parameter "props" ------------- err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) @@ -13749,440 +13756,442 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "7P3rktu2uiiKvgqOzjlluyaj7lzGqpV2zart5TgZniuxPdv2HDVrMKWGSEjCaBJgAFCy4squ/TT7wfaT", - "7MIHgKQkgqS61d1SN/4kbQHE9bvju3wdJTwvOCNMydHF11GBBc6JIgL+RdkHrBa/SaLepvrfKZGJoIWi", - "nI0uRm9/QnyG1IKgnKdlRiRRo2hEdVOB1WIUjRjOyehilEuiJjQdRSNB/iipIOnoQomSRCOZLEiO9dBq", - "XeiuUgnK5qO//ors5O94SronZzwl7fPqlpvOe9m7adG1ZXHDLf9nScT6Z5opInbnfs2zMmdoBs0REqQg", - "WOFpRl4iSZZE4My2SZTwfEoZQSuqFujVu5/G6A1OFmiJs5IgKmN2VQheXJAvhbiKEPzjCk0JZXOEkf4X", - "EWrtdppRqdDzf3HKSIo4IxJRlmRlStIIYRmzGReIi5SI6foFwixFVzCu7or47CJmCH2DFPmiLlCCJfmG", - "MkmYpIouCcqxShYIs/VqQQRBlMGMsM6X5sOr/1OQOflydYEEmZcZFkiPTqSknKHnl2++Q3LNFP7yItoZ", - "3Y1A2QWOplFydWHXVG2LpGYu6bqSPy6W+kQYuVheXSDyR4mzCDGuzJ+u21yZbnNFzB+Zcv83H2q0woJK", - "zmSE9AGxMp/qm9Hnk2LVmDEv1Fp/+v8xf10gxs2iIn0u5s9xzF4xVLJrxlesuqCoeVn6qnmpEEYJwEmE", - "uECYIcqWOKOpO72YNY6P6vXIFREkNaDyw/n5OGajaES+FJlGLAu1AOJ/aOCsYdzA2qgJ0lSRXLbAduR+", - "wELgdRPWfxG8LKbrNmDPc/yNJJoi6WsCIOQzt19KJFIczfXnBh2JLDOFpmv0nIznY9MyXf87LopILhO9", - "5hfjUftObN/RIOz8leZU7a73k6aD+AvNy9zetV4tYUrYpQqiSsHG6BzlBDOpbznTQ/kWBY0bS0rJDJeZ", - "Gl387Twa5ZTpuUYX59XhUqbInIjmYn8jCrcQMYO+KCcKp1hhh3aCyIIzScboDdN0JdXHaWcdo8+SoBnO", - "JNGAda63xHOqYgYcgCiMZpRk6Rh9WjRG5jOEzd0lWMBRUKWPQ+GscUyCr2TMHAQXeE4ZVoDf0POFpjNo", - "RbJM/x9WylfSnihJ0fOEl0y9iKCJz2aSqJhpRDNorg8ZgLrtmPVKh138exh49zQ/XlMDgjMqpKqu3FIZ", - "OIWkFJIL302bFbdf9eCbfm8I8E0RSXKhkWeMPggyo1+2CQv6BoiYHpmwVLMJIPgW1yzx/3fNcPWeom9w", - "UXixzfYedugfBC/k7qZeebZhGZMGaKIZHpx+ShP9GcNi7VtTAdMMWtFHhZVsO2amBM8MeMIyDIV1mGVB", - "tbEWgxvxSOoB4xG6JusIJZwpTJk+Yf2dJBlJ9K01tplSqShLlOVcCIBf+nYGo3fu7C8tpBjEh339cH6u", - "/6dXQhjAOy6KjCaAkWf/knq7Xxvj/f8EmY0uRv/fs1qUPDOt8uyD4NOM5GaWzQP7XzhFl+SPkkilGcQP", - "59/ex6yfGS7Vggv6J0nNtN/fx7Q/czGlaUqYmfOH+5jzHVfoZ14yu88f72PO15zNMprAjf7tfuDoLVNE", - "MJyhj0QsiUBvhOCGMtqP9divAOvesD9KUpJd5H3PCMLQRRMRYroZwvfh8yd0ZtoAx2pEhB0lZoQd+jQn", - "TDWGFKXmPztSkdNQdqUJLOZEgW6Dnttemu06CvuibTTRNtIlkbwUCUE0BQoJ7NDIhVJhljQ2rqlPnmNU", - "8Yq2SeQy6VqxJGJJE4Kem356zU76ahttmRsy1bX/6RoBU9G0tMhwAgK8PRMjW2OGCEtwIcsMWJxVCXdJ", - "eK2M/dNd3e9VPz79FzGQ+yojQv1Kpbq0dBFU442L14xF/58z8n42uvhnQ/btgmMY+ZKvdkXi6OsIpynV", - "a8LZh00g8/y+LQy07GTrh9//iozA07NMvXcQHbcPDbbtPTK9sRZWnWK5mHIsUoR1Ly28jdGbJRHrWsig", - "EvHCbPICOB/opPIKATuLWWWYsCxRotWCJgur60jLLIEAGF4rx+gKprvSY+s9loqkMZsJnqMrvaTJLFdX", - "Rl+Ff2rWfGXE1ysNQXJsWy1M63/XQBCzhOcEwXAY/frm50/oP96/fQdfYEEQK7MMrRbE8H+zcQVQbRbL", - "1YIIdE1ZGjM+Q+YkjZi6RWL0p7vH+vcyxwwJglMtqaOcSInnJEKCsBT0OViZ26dVO+0ux22oCK2JIID4", - "bSpc9Xl36yRP/+bvQdjS3zjLO8Z29Mrfo3NisJBQtW5HHOhifvYNUBap92ho2j5sg7630n45dgRdd9Eg", - "oy/TKd27tNcBoiWpwz6qCPYuPdxF46K4G7pXFI+S6plt7dI8hhqyDkp4Su6D4rVRj6JohT5cFJOU55gy", - "b7MiOJ9Y7WsXJZr73QMj/FjUdpGveV68+VJwoX4DE/MuPOJS8Rn90rqGnKeSqEnO04nDlhvMaXX+zWl9", - "27NTeqaDdj3khq2sCyR3DmAXg0aV9V22W6X0YipzRLKgWYoan0SDjXbRqCinDqblPua+SsGk0+3N9385", - "fG9YKZwsSIrE/pvrhoRLHxzMmrfdS4p9ULN9rrv7FDyr99nobsyc+93i9l30zNbofqPZzNH5UcJ1MLvq", - "7OJl0GJfBBA3Af8lFhRPb4a+/2W/3Rfyqu8Gk6AlFhNj42jdlG5OMiylt9V7U7qxSwrS7WCT2oPSVjTW", - "bHf3AqsO0ujjakFoZYjETMkIOUuvu1T4wb6EWXF7jUpJophZc9yMixwr9OH9x08I7i2jWrQ8o7leBEjV", - "rdy0HnQwCPzsPjEbfKtI3k/Eb8QbNIHqIaB7jnvpG9V3m5fdd3nZfZPVRbbdHdq4upgd0d3d5wmbzf7K", - "53cipm/M8BgF9p0NtpgrRMmMab4GLiswIc4QBusSPK7Cv5zBqzKncQ2nGkJ1vwt47rIWtufJgiTXEZrR", - "L5qkwx8vIuhBvlAFagJ6fiVKNpEKq1JeXaBzxK+jmH0LT9D8OkLfwV9Wu5hmxLy46zEyPu9VMuzDv9My", - "0GGUjJuov+Ah4dPY9RHUptXWZs2GvI0Zn3vb8kqTaG02J9++n71U6RrUPsKQd4ywZpLHjbP1HlvlvAxL", - "dTPsfSYr/I0ZZ4iqPdV1HyLFrNNA2UB1PUHtS/WsQRIGEIGAlAOR8icqr+8EEfXAjxH53L7azPpUXiNJ", - "CGsilpPsKr5o7OECrxFVaEoyzubwDrVaEBYbf6Zb41rMDmka0/ua4CzjicdWDO16Sx4sgg4pWXY2z/1t", - "oGX7m7uGzciSZB3Lznm60b71uVf1g1aBu6YWZO4jDdAu6Z+kY2WlJGlH85Kw1KPR9hnZvZvyUg5o8n62", - "nwnT6BB3QnPM0I+R6tQ7a6E7RpEzrpwJZ2Y3hgYZAuD4f6aJAxdIGWnb0IhaDYQXvCll5H54/WyS4SnJ", - "7JvibJJcyzK/grdC9zqJpmsjpOuDmWJpnxfBjYzMKIOdtuq2XRYfO5WnDZz2PG2wYE8bLzwNypmrWtq6", - "rEez2nZ0Q0OqH/06bBKvaoiAmyEACvVvVDV9C2SEBElKIemSZOvIOJkBz6MaoMC1jaTOB3CMXjH4e40W", - "PEslIhRefbEdX4uhyhooAWhZzDYcGapl3KdBYwtJG9P83n/Ab/RuW+zkWvrzwwycWzsRmlXO8DjLLHXc", - "Y4vWl/6v36MtqKqGbvXpfGdvRN9O+41E9eO+uWEqjVBuu4xHUR8cbx+0O6P6RAYceB0ssH3iXZh9I+z1", - "2XY78LG5PwiHcDPUpMcup55gwKYBcHe3bDrdFBsM6LbY92ad7xfQKp1T6M1J1+5RVdNWoNp9NncualRz", - "PF6ZY2OLXmZRPzUqXmG8JOqiYb5u+ApFqMhK4/lecAknEbPnVxbLr15Uhu+Mz2mCM6Q/xFp0+Rc3vsBU", - "6Zng8U+QJeWlNFSnjS8AvZrMbASSHyabRPb+5YdufnATRnEvkkfjWHeX4Ptd3+LkBjLL3aLyo0biSz1q", - "52v9jSlz97xdZAMoBGbIiYlG/zAP+XxWBe9pamDcAzcewrCKmVM4wHkMOlY+YQ/jXwRH2kU89uCdWxZd", - "49qLoLkpd/1sDmdFJWl1ZIRB9/fW68TEzxLPST8qdgnoWwEB9c3W8qWJ+tAXx2Bre+Izme3nQFMb1uun", - "c0H0OSWVMkobR298Y21Xo7RQiShDV9UtXx1s2WohiAStqWXhC5Jco7oHhIfFo2RxDS4iY/2Hs+dfZHz1", - "zYLOF/FovJ8/kEcJapzoxip3ycJgosVFfjeknov8Yak8ZTPe/liTLDCbE5RjeI5hCKOcp3Rm/Zra8PqO", - "OIY9ozaizUVuHnBr6wsEHOSTNc6zCKWCLomL+CpKJTW5Kqc5NdG15EthrNNOvOOlgl4Unqnk2IxVD67R", - "qRoeFVhIklq6HrNbWqccXTfxmgMIu15HF2HX7V3u4lt72z3g7Z1GCE8lYcoo1lShlBOjU0P7qE2D10PM", - "eLYpFG6twc99dKvzKdtcG5/+K0JJKRXXF67HR1ygOWFE0KSV6bjN3JLjQDz0nRADGPkxynzVxlpQuJRE", - "GK/FsUYTuqQZmRN4bI1Hn+KRlTGqlm/mAjPgwyayHLM0ZvHoZ9cTZDdqojfZQ/l039T3utpl+zsrz4Y6", - "7v19iu8ERP8+xY8RQO22WsBzwaVC01IinOJCmVh495KKtTBWcFG/CyA8J0xdoKvFFE9oClAMZmcgsWAv", - "oClhis4oEeg5Zoh+fP3xLXr7n+8gFwT6mU4FQa8XmDGSoX/848O7F5EZTa/5ygymBGZSz/tAz7Jmc60g", - "6lZ6K2frrufC/Z723rIZb+LAVkxpqSBCzEZmmatdCaoI6HLuCBDjSJCEi3Q3utRJT4PWYsTdO8FLN/hj", - "RM7m3lowdNu9zwC+1knhRjmrPR3gEZK0Yq8RugB97wOrbhLDaNP7gA1Nvqy/hnw/uwGNEJkr+EovH+Rd", - "Nm9D5pyzCS6KHf+dZkQMm+AlpllPH6MvpP52kziBiJ5xUiqve7pYA6rgfxI2wcrbz/Toae4cQPasZF4S", - "qbi/fTHtGYD2HT2HvFF9hy8XWJC+PrDgjE9xNjGaT3fXvuGWiTfcA9rXLOkZossGpNuXSeFzKoPmnORd", - "rR1BXrrZu/oDB4WaT7icHFEY6du7UWHePkr95a03hvTtB4TTVBApUUqUSQTT8LVzJNs8DDGiVlxcb7rZ", - "jWN2974tbb51aerRyDM8n6SkECTZws0B7yiUqVk7xuHE87u8bsczoiZTMvdEv0Kr4DhNsFTeHgnPc5vY", - "pLWdsNTbNseKrPDa2+4VXrus6dBIVOemLZR42wtBuX/qwufTqBshXrgRLXhYZz0vOd1PZq/QczeSWAsh", - "mgROCpdzanhoIORg8rovQrqmW5Ijl3LxJqvLXMq63Xl4ldSsZQ1c4azFN2YjbdtGksjdDG5RM6DLeKyT", - "9CWacREzbIwsNieZ6VnnhDOxpmP0D6oW5hFouwdMD/5yulkfcyI3/em0ZGvI0xDb2415lo93PA7+dFfB", - "Zo80xMwfWFZ7pGZ8jshyf23wZnlwTEJGY4WgEl1lfA65b0zGRePDePX/f35N1i/kFeLC/SO9MvmWFsYA", - "Lgj8q7JGQepWyuY2qyyfxQyGhjw6EcLoPz6+f2cT2+g1UZzRP0mqVWOMDLEaGz0TjFlGTQUpE7xiYwb5", - "UG1P2XC30wdng7oZN5ooF04Nf2lOraH8xqxd+0W18lul75FV/h6lp9NS8T6xNXr7HSEycDq+EBl3dIOk", - "cd2Z5JhmE2lFkH4nH/iGKbEe7BZkAcW73LnC2fWeK9iOUNgcsZREPFWlqYrivhNqW43+GGlutTnzx90e", - "oPnjCRyjh425aMrWIEtwExnI02J2yCDkRiagG78N2PQ9Pc05Txsv472T9ach2uiznz6zgdatMsd+FwSW", - "6yrr7HTt7mo8mAfarXS4DgxIktTtwtV5EPI+aIB8AkRA3ooKRFVYTP1b5edc/fJMxkwRnMv7iMHqJhrb", - "3oeVvGl3Cp5wX2yifK3k2nIJ8pqk/U6JrSlTG4OnETo3qSPMswqca31wbk7zy3gU3Qbx9iJvd0fODkAI", - "ohEAz6SREWtARitjWdgERH29MIo0Xv07uXBbb9XMvmXzGjZ7M63WzMaBNZCnf/Y2IvHOWPeG0b5BFM+O", - "2E7oOh6oB5GaxuBt8eUkybAgqbNsj9EVmGyvInRFmNMYKzvt1a7pJ2ZX9lvb2VpHr9pIgd8c3G0K7jID", - "+0zAXeZfr+m3w+y7ZfLdtNp67b1+W++WnbfJl4YYeffj3O94Sv6ORbrC4m64dnOCx8ixt/fX5mhkm1E1", - "4RBXo2cSYamJY1HKxUXMrhYr5ylkyGc92gznNFuj55qUkS84LzLNsRNq7Ek5ya/A1Wg1KbBaWE8j+7Z1", - "L+HXGx4RrTYg/ZV9UYN+MbNx4+D4YPwEN0+vLsijP2j1ZVp15NpbrCZ9nny6i6BLj03EnqavzfticvNs", - "xTZlxkDzyh1bZPanMndGXR4rVfFQk8r5p1GCTcIjzj3o/hGSHGE9fcxcTSHOsrVNVgoFRUiKZDn1xM0b", - "A60fPbwpkzUp9CYwh1Yvj55SLidLIqQP06cZTskkwVPKiEfOyEqpiPAhqG2WY9evvbBCM7BdX9sziewH", - "0Q4ZdEMap7ABAe1aGLJPHB5RiTGSqIni7c1FOUm48KGCbk5pV+tMkD+8I/tT3+hWtYDEkf6xOxLQEJZk", - "XJaCdLfKjLff7OyP1EP+l56fC84zT9MyTXwMgU/lBKoJ+B8hbK8VFh3JvDIs1WTKPbuBVi0Ut7dSqQgj", - "YuKycbS9EiQTr/+IbpyWNEv1v30dks08/1uNvHQ5KlrbZxnn/rkFTq79jZzn3sY/aeHxUdF7Z5glxOsy", - "kmNWznCiSuERBXKST6aYXfvc2XTzWpGOZg2dXmc4H+aAxOCjiNDY4SPZaPc5Sd7YW4RxVcWStUtfXE6w", - "SBa+toSzxLMoLifXRDDPkTQkmLa2AThoe3XjIJcTQTKCpbdZkrlXL+XSGlV8rR3UruArIiZTQfA1Ed/2", - "d/muo4vld9/2d+kapRBc+dxNN3q4JXX0lGVRZOsJm7ajgidIJhpJkkz+5MzXKChuBxfJOP+TTBTNPO1F", - "p9jQ4QELmjos3d/cp8hDJ30km8R6gFeW+nNPy0A06trnSsvUTK09FLJNUH4/lTyD5NIJ+UiUouxu3Fha", - "5nmM6oBnm21uq7zRFUnT1wj/mqaB0Zy5WlBQCtf5hVWurEb/FiUzvWvzBbAi9PxKE0hjiYhHi1U8emGL", - "3b7/iCxZ3OrEZTx6cShv2M5YWvSZSVJtTDRqP2KJNlxaxgiWCALJFVRl3vRvM2qVmQIO0Z6TRIq/3DoT", - "vTIubSoxGwshYxaPllSoeKSPJ3Y6QjwyAR1cmdqRJN3Hx2UIB9vo0mm/b+86ma69vTtcLXWzn/laaDAp", - "cspcQ/tiNdLsrgHwm/17eHCzR+8ud3q2b7INyT/g5BrPyU90NnsHRZm3SdcN5aQt3K/rpVff/N69Go99", - "oDA9kKXoJngqy5z3uqmNbe1spnyDDSGy5dQU0iisTLFutTDJ1IbvuLie+2U73eiFEd3oZWm60c+jvGdZ", - "Tbg5QmOZjXk7zvtOmJcd+zEyrMbWOkB0CzQre3hlA7eWcdmeEzxmt2AfDeNWzOpEoZLOtcC6pCkRV9bP", - "0WT+Mr85842kc2CP12RtagBY9hKz6ulad8Faa9SNpcu2vI8t3JQxcCagA6UZP0Jjci/NsIBScYNBI3YS", - "GknngwcaHPWsO3dxom4iFo2awDdgwg5uJYFBHOYVeovltNXPaY3psEDoqQtF07oqVJMlyYoCLKhUXEBK", - "vlcf3lYh22pB8vFepaNgWE8inI2pm6VxAPWjKluYrYM7OMPSttTQl+OoOiy33GEZjezZt5JgW7V5514U", - "+dKaindR5ph9UxU1JV+KDNv8aLIgCZ3RxOgIWm5PklII0DHMJUKKHD3fRsSHhz/DCtrWfHmHPriXj9cD", - "93KoF6K4Dx/Eeyg695f/ECBZ3O4x/GOBFSql1gqrU2gJmG+tA3aI6pMd8LFLpzwz31zR6J26u4ZflaBu", - "wcH2X+XJM+EkUNVvgzIeBFCGrNsFBnSc2o0KDfTP3QGCrmzgXZIxN8cjJmfNLbaQNVcQcscLVjyoJ3wf", - "sB955cgbiJyusOB9gL18AnAvbwn4EeIrhrjYyJ3f8AgXtT+4MXoK5w6+VY1hP9/ww6JRsrDVsXe5UYHV", - "otaU3W6s9XqjXgBnxGYnxSguz8+/J2jq/kjiUWQtwjMu4GD0sVVlZltdjmFVk4x4VtaIjnYc0xbOhA8j", - "9G3vXA1ANJlw2kskfNreqjuGmkOTavz991lPPfH5ztNU77PuGKHzfTbXmcp7I2/x7tQ1lFoMYFqhKHHW", - "lOwGBwFU6NQeBiC2ggBc9/Zt9VH5G8jG3tAIseU8n/QHQmyL1Ztja42PJlRp2lEfaofv/Y09/8UR+f2L", - "4V7/p1Tf+aORjO+EGduxHyMPbmytIyFdw/3SaSAn44HZ48roo1xajfI5Z0JbqbhU2OOqAD16Es3pPl3x", - "HKadzei8p7kTj6BbR+Zk3Z4KxjsyCZguBbOvgV3tsquD97FLt/scu3TbLCNfJklRThZ0vphUadD9F1d9", - "kPHV4P45/jLZ3kNrP8oG9VNYzH3ZbqCT31tNNy+w/9MFl8qv43eo/5OcKMEtSng7dd9kv7ub7gXpOzph", - "Gyz/knLWAZm9Hku6TzeKmeZeHFG84Bmfr70dVnhJvDdyoPqNn+UdlVTSAz9G9qX39UGQmfSnxv0EKVS5", - "ICkqBJkRsOKbVxeJl8bma+r7l5IIefZV/29C07/OdHcTzQPhPjadDiOaO+ndi0KYYinGCYYw9RJhZpUP", - "m4omJ5hphYzxmDWmtyvSOlk8grzh9sHUec/Ab4wrpFFkmpF4hHBGr1tfRR1MtF/Yhl1j32oRDm582c6t", - "UAAnZyWCqwJLueLCxUwKMqdSCSAXk2uyNqGTcIruIZqk5p14ynlGMPtGb7QSCZ5fmdwzG2TnKorZFc23", - "f0RXGU+uJ0ZhunqBtMCwthdk7++ZTcZ+BonW9cWyJWEme5iLGE9Jhs0z9x8lV7hayraDlXOteqC8h3Au", - "7WEAcGLdGXBaTnVovwkcUHt4ARVy77JH0YjmPavdvutBnTrWSfOOkLUcUgN5NwFBB/7WGgLbH8UXnJGJ", - "N04WIM4reZrWlCfXREwsZlEPrzZ9uZh31HjeQE5fnXajoFus1ijczun8R9bGIv7BxfUs46s7YXdu8MfI", - "8pp7ayHLViWyLrC2LwJNpQ64bdSNAaPPjIvcGExx9U3MTAWZMbqCeiMLglNXCEDVPLUxFGSadzNRpUk0", - "oAp8XmVdq3+CGk5gQINqt/pbUrxEV0Zig4muCsJSyuZXkIg8IwgjRr6YngivsP7YjIilpHNGiGYCScYl", - "Sa8axqEtPTVmt/PF9ThT1buK7D9MORdXhtmVbblqjwTW7Xo4IxVXyeHqXOhU9WRAN4qe34kU2rtq7NTl", - "bfqLEzaAwmPW1D3y9G/DhxvsQbVRAefGGZg2AMdP6i38Dkw7twHew/Lr6U86QmS6FBxFCjm03E/DFWsT", - "bBoNNpx+dDE6H5+Pv+11bXGftrrvSJKUgqr1R03sbOILLGnyqjSB5EAE9Tfwaz3XQqkC4lQJFkS43uZf", - "P3ORYzW6GP3HPz6NosYQ0Lo9xl/NvCFUwcZ4QZhcJo0Mmbigo8bxjL4dn4+/B1fqgjDdeDH6fnw+Ptf4", - "htUCNnJmDCbw97ztyUJT9sqApnEZApntV6jgYLayzyU2SviPkpRkjH7DDM+1QC0JiRnOMvfVS1up0Yjb", - "YAWTpB6z8uI33vm4KPTga5PfcssUbKiHKf1KOXubji5GvxD1ym5Kb9RSQOmtgl13OaPsPzXd/ADpgjWH", - "Hdb/V8gVPLz/e5NAePgHhrUO7v4RqkPusR6REjFd7/GFKxE++AMoOKWn+B0kMZCTAOi+Oz8Hkm80T5Be", - "isI9T5z9Sxp8NnLGECmkEsIAabbKy/xvjQ1/MzO2DVSt7Ex3auI+QE8D6//5u957E7P/+bvem8JzDWmN", - "oO7fIU5OtqDWbzylM62gbSCOLVIMmuQzmj4DX2XNLzFLNddb2xKmhp+DD58x0dlRXtZ25WeG5D7b0OiA", - "QsNTGLo0FNCO8o6n5M0XkmjN/TXPC/i7qn8Fs1bYRzNqXyb1PHb+OqPHJkJ+4LKBkVay+188Xe918W3+", - "GltSI8yBGqeIIJqggxNtBfoTEDFVKdFzqD2oD7I6r+oUX/Syk9aKt5udbDW+W+FCywRtAP/DEIDXnaDv", - "t0P6fmv6fj+k7/em7w9D+v7wUAhatuDnG2ZAycQ0WPbU5ufctMp8+PwJOaYK1Rit5W3KU2NQYRY2I1Nf", - "DHLAw5M8qMAvbe53kqUSFVpnZcoiexPXL2IWs2+QdS00FAEs5hc1OUFOl3F1mLbeviLox+aIs5gh09Uk", - "htZg//ybbzKe4OwFrNM9rxPJS5EQieZ0SZjWwwRNdV9B0xdjPUyTpqCKpAwiI3ZdY70zsxuEM87Izp6I", - "Fg2yxkasGGISDpk9WPdmVMkukhCGcEaXxIkrWmBF3/4N5ZSVSl/UR5ybxzgqwOYvxxuHbNfSlIDGQ/ar", - "V+HZsiWZMXuVJKTQe7CgcwH5o/RnWu6LzL/MO1mEZoKQP4m18+GVCcOx+4yZiep0l/4SPoVMK2YUKOZk", - "/iyu5/YPrJKF+dNUDYhZsiCJ7ifX0kTzREgmmMlEUs8CYC+oUSDZbiVmz42HbtRM1mff700df4NhRpOV", - "VaClDaKGUMuYvXeIgzCTKy05Ord/Q/Hd0QGC/vKmxsKzrzT9C1BRg7JN4I6Rc3xHrwwO4myF17Ia/Lvz", - "88gzg0SUxZoZY1N2nNWp4gswdc5KSVLHgRgiQnDx0mE4SulsRoRBvGwdM4tEEJZKxBzEacWNn24D6LUs", - "XOFfK5stD8BlawtVl6Bl5rH0EaTAQfas7c+2LFq/PwSL/LR9u4CbFZV+aYmKqbaBmXsQcZARsx3QQBVk", - "GJI5KyXOZAUI+upOkCn/cP7jkL4/PggD/ysabWC74eUZUS0PaT/B7w2W0qbDIqvD7lB3q9TGbG/BGAR6", - "OzqVKOPzOUlNnWvsKns3zf4mNpGqKtR8E9vNNgxG7eq5wwRjqhshHZ5LlTmC3zdRMNpFp0rsva02d8Pa", - "nX5J924Q5QEk0lZjzE9UFhleu9BWF4QKxu8q2KsfrGPWtM2gG5hmbmaQeTg4jYLp51CmnyOy5By1Ugk8", - "CbJ0QPEdr4HV4bTJ7QJ9JVJUayKaJ0j0PMVyMeVYpBPXiqcZeaElV1NNNmbWvcK9r8i6wK5x7QaVhUrn", - "huHc7hOcZUS8RLklBzHT2E6WRKzVonqc2cVmvdQ3sKtgYX38aPZwqCMHCnKAOs+nZXYNr48vjLAFThy2", - "sSq8pZldIzNEGjPyR4lBaksEVURQjJ7TNEIa68C5InIWgMhaJWyb07Aj9P/8X//3C0BDs9RUYyZgXI7X", - "homahirKwmxuk9kyQlKjUQB6Scuia1NChxRozupQttWN3bW+10EPqenEZtbIZglHd3z9DjTDchfuURfq", - "8GpkkFP3klPh0ZB8gSqecwvtDT5WMTAI5KECgoCeQbdnm5liwNC6meDAmVoEYSbHA/gfALjNchMBB/9I", - "aaK6+Fd4HTxt3gWXeGIvfq/BsUULZcZPomJe3mezw1L2KZZkCN12NRV3fC+g1Rfj4HDQ33i3TOWm3GPT", - "X83NEB7wHpa11ELgPiY9QCaf+GUZkXWVgtSZVFkpLGabYhjySWGtdjzzihGzG9vx9GS95hGQZGna4KRj", - "mr4IhrxH8wzdbSBwik7D8rcrU3nlnYeErmB+e7Sy1bE7drTKYZ83pa9nsoFTW48+XWwgZk4e0kRekI1C", - "atZYcFYZDyrJyqSvU+6xaEXVwo6kFRgq0RJnNDXpP9wzopOLdHOS4bxo5yaVzPjgvOR4xNUTlEiD4Hki", - "LBuE1KIYaqes7wQlWkDdMFm+oWANVM7v074hP8NF8SxmO16g9mEP/Mq2PELduzMuipcuEpDoWSFgBKr0", - "LzBLMxP+99ObX998eoNgH2dfcVFMaPpXh6iqt3soDLcBYlu0qSjgeIamg9H9NfEVaau/50naB4NzyL3Y", - "KCG5BZgVsQHrXdnZ/B4shScszRbFadoJW1hGu8R3ByS5rcTfJOU59hT81c1Q+oYX7TFe3XU7t8xwehH3", - "YYDrARsIvD1uIn3sXnlNoeJmUpJfDulVcpqCAbjb15JFi5pjVnmvZrMu+HvLZnyI/h3Y/62sakXRUP49", - "EsDDA9q+FrTfH5QwnqBJ6LWx3LdpaR3gYbnvkRCik2b/gdc/BkNIxevPcD6h2+k+WynxJSSeQPqKEZ1t", - "JEQUxq66nf2Tyn4hwRDuV/nby8YSTl5esOPZDFPh/awHBqsMgH4LwGYFmaFw9Q4GPjmpIFgiglv7wZGs", - "kU66B9dahav6a5vu2YNyH5rTBMwLmBcwr4l5Z18Be/rNLAonEP68jXe2jug+9pcGSh4FRm5OCXC1OSmU", - "Im+d0B3eaTpNNS4CpXDDJA1qyy2sAa+UF00U38cuH1DkCFEEq9NFkdOy+J9B9ta+7HKKCzwnKKXy2iKZ", - "+QyVEOnhoukH6mb/aaYMImIQEYOI2DCe3UA5a5reOpWzy+Y0AfMC5gXMa2LevsrZDt7dQDk7Krv3U5Y8", - "LzdzAwX97JD62S6m7KefBSw5TiwJKtq9MapmMe7eFOD7P5V9dMMHsTCIhU9VLJxsP5Idxj7fHaWx9WJ2", - "MP+gSW8Qxhb67jgDVazqYgDHM7u3fK/XbdgQhWqC30PwRzDatwiF3uDJgDcBb4KYWDOubQPiAW0X3dxr", - "y6QYsDBgYTBpDOBeAW8C3gTuNTqDogIDX55t3zYDhmsJAcAhze1dQGmpFuCmDiSllTFcQnFbUpW20Z8Q", - "puxR+DhBqRbvDB2+27ggvSR/vdwmma56tlHne6HG0agshyQBhF624uLvAyi4K95zlNG7AI/DAVRDl4XN", - "pCrlc0bzggvlh9G30G5rV2UawSP3B1GyqvYjIVNJVQXIVC5giHzRX4/RK1deJWZV8tjpGmmgMYFApWzm", - "RBIkM0q6qyULNXRwmpLUpD1hZGUHlDHTbaZqlSv1/kyilMxwmSkrbWC5YTrYKOzhhLHI5Gg23hCuopbZ", - "QFW4yJwWSbdSSb3mebGTSCoyFaJsda3mEwiczbpOo2vPUAtH1QnCuGY6vXGJFB+jVzFzR4OSjJuTQRnn", - "hTlFKE9k8hi6TzVuEQnJsTkU7F9QNjeHqLEgZlAiSZEsk2i1wAqtsDQnDacEP+FMEJzaBfvTU9UFogzQ", - "HIxC1fAGJGBIQaKf3Sdv4ALfKpK3FNoe1QA7eGRTQFEP+pv7uG1kcfNxL32jPly+m2oHO3R3yApD5tOG", - "XNCgvRmf94ixUMqhrrtmwfUZghpumhB/MSluWKr/RqJkFeWqyrmY/KcowQxJQi5swbG6BC+1tFEuTOJU", - "zqp6gpaWGpIYmfIRMQNZxRTPsuUlDMnJuVRa1SNM2Qz907Wjw5583TXJ+FWfRRDGn1RV343bH/omeDdk", - "4xhIwdnXjM+dJ9neVaIMbdAkYAiu9b3Zv00dDRAlQ8/1SicZn/szSZqln2zmiyMCxaN/9m6A7ab81JMB", - "SC1IQ77VcJNqDgGiaArFsC3ITXm6jhCWMXMZDFunPPua81QS1Z3VsL7Z3+rF3mWx6moaa+8EBAm5Cp9O", - "Wu9Kcmuow/tIWA0kmXERs1rM6iPsGxAeRKknJEpVN//ExKi+PIs7DMeyDP2PCAyuXNRsSGNjtImrYMMp", - "WWrz9+5acrw2p+e6xVmFzE8rqha8VDHjzFT5U/iasMoMhtEP5z8OMS0ZfSvRezR1KGJmqlX0m2bugAk2", - "jvQIE0AdCWY8qtyP7eKYsZV6lRdj3OpkjDUOOl9kKpAehbAUM2tkBpPGhtm5tg+a8rWlJHuwSrOu0R0r", - "F9V8drrHX0HODygNuX1I4tAaXCxcUA03WBBmisIlC5ql9ZtBZB/TIHM6eKjHzAQd5Hq3Uf9LgIzclKbd", - "MpCMsms5jlk/fW48ZLSxi2o/rtaETeJeVx3aS53p0+VbFZJWJb66l1Bh6JFVGGrIQYNUkeH086Gh75is", - "SHvLGo/EKhR5HRxAtN2g4MYXjLI5kHFbLVH/xy/4xuxmlBXZom2dZNUjHh8FUQ3SefClu1OsLVuQ9mNB", - "EoozWwlRIi0lNRHrKsk4I1co4QUlElGFsETxKC7Pz79PNJjBX2QC3eLRhpZt3CEaIr6mAXbsLV8SkOoE", - "Ybv6OKrU8ZgN18cH6dVt9KF81OTB3LL+i7AyBxDR99bwjvL55poPg0NucMjt1fKGp4z+RLIMrRYECmb5", - "hNP23NFN7j9Yet0vjfRpaVIpVu2ppe9ElTpSyEswS6Hk4mRAyujab8arMDlghBLEU1KlM0CKX9Tf13zO", - "+d1Yh5sm2CqCcw3KDTCvJn224bDovBIjcEKsplzvA+mv3UEMynB9bFpbeJA6sQcpDWWPU6Y/ekI3LO2H", - "qT1rU3/chNxFWu4HIdwOo+kECPUyw0uiW7V0T1iCC1lmWJHKIHuxOfs2rYxZ7Z24wEMIpBMMcM6tYaEZ", - "3RrF7AB0c2i6k3sgnZsT/gPeSvRXxmW95cClW8AfmgDUK4CbGkVddSgCpX7klNrCdSDW90ishz2V9lLl", - "hhGl5ZW0sqfE7NavpNUj6UnrR0f/SPsIQNv+3C98uCfWhveyX/x43vZWVatFXOjeb5ZErKc8Xb8YDtj2", - "j6APBS57P0+D5o/Abe/T/W/T9y/n6cS43LFNneIlwq0eeXfg8tHw3dv/bfJIaNbh3iBKxWf0S0sSEmT1", - "EKDw8ehTPEJnKB79HI+0eikVFyQdo39YezHkrpyb8LMv9rIsAHBmYubQDNOsFGRsoz+b8HDMz6OPmWo8", - "gvcN+zP8tqdb25B3ST9xMYbmLbeHW/qTmT+OzsxhJhwyW3Bge7QObIO0hX2l/ycE6kfpLbcfcwtibnUk", - "n433HDw7aonVlVMy8hSaZXjeRJjj8rB7mmwmyMtBXg7ycvNncPSbDA0Jsak0TcxHI1AWMtE2qVO/VG3M", - "4n5SZ0JMhtO5HoH6OHzlt+wkW8fYN+3WXQUp+7GlqO2zwyu+6c2PpUPGGuOMTnoTK5nDuFeukmdOmIrZ", - "bqozsMu9NBnmbBI1zvTockWE1L9r+EA5kRJX4bIOhW8QLBsw+CgxOPDte+bbB/ah1Ji84VAE7jsdXpTD", - "Nfvg5Rhe9YKX46PzLtiuttRNh1o8BDfthy8h9TL7xibY0SRGIs4ykw6EM2J9ZbAgkIeH5FMiEJ8Np0Nb", - "JWcCOQrk6O7IEUwSstcdkMYMrO97SXK+JP7ibluW02Evfr7c0Tc0w3rNEw0SdXTqjakf8rgLpAZ7xG4O", - "RXytsckmb2/Bql00uL29zysV5NiVrTWyQe2ISIXzQRzX3ofQn3GFpgTleLPY/q1fTQKyBtPDo5Hmt0vQ", - "dUvzu3ma7l2a3yrBFaT5IM0Haf50aMy+0ryn4uVRS/NHlM4gSPNBmm+R5nex6slK8wFZgzT/eKT56kex", - "jyuP6Hwi7Hbsidntg3GGOQb4+e2ROgZcDpxOBFeeR1pteg9HnguIIV9iQbGWk9G/uImNixn5QpISDG+E", - "LangLCdMtWXjsH8f2Mf4VcPDp+kSNMzT5wYMOWBzwOaj5bB3ktlnxwlnK6sPVZJkM8RdtgnIGRN1pfdp", - "OvK4hdzGlydk3gkGvpB5JygphyChpRYTegssQtnjUg6hnxfbFU0WPLPpzWPWcI8eTO0+wwofZSbSnczk", - "bUWS2yrs2eVRpsgc8HjvtOYDKhUHCeVG6DW5ScafW5THi9lGfby6CrETXdCCSsUFTXCGlhMoXdqYaknJ", - "6gLmEHyFCq2XmNbdjOREVYpKU9Np2i91+0aiVkVwLsfoVWMMW/XLhdZptQTqqJvM6noVMDFGfxLBNT7r", - "QUleqGqrUOx1j5oc0pshJAgUTyLJkDyG+McjIlFV3EKvNXInpFB/CpTF1aKFsc6+6v+ZxKsemeNGlWld", - "2MJBa38Mr1Lbx1ejkd12O89t1gdwHUOBgCcdRgh2xgqHPrz/+OkgGOQrahnwJ+DPEwnMm2zHwvTyNo9z", - "+lZA7x5V132u8hGacrWwWfdslr0pT9f78cKt0JnDoHT1Xn3R+95dY/NeZd6bSNxUvquZA0Y/QY64i3u7", - "ofQxM/zxXvDOx0ED1gWsO32b1LZneb8XSrur5y14o8fx9DC8ccsRPWBpwNIT9lTZwb3b8MYD4J2PNwas", - "C1h3+ryx6UWyvz209vGoTaJuxLOvcpkc3ija8P84WruO8efwZ2R8CX4iVanKNleRsfkVHHKShBS6CUu0", - "IlkG6RfN2fZbjmy/gNTB8NpEVsM/D4KqPv4YEDUgarDw3pJTi4ZTTE8NgUaRLyvYTk2sM03RNan8qbWY", - "69Ved6M2hjDnS7fIQ2F6G4pftouzAVmeRu7/OvD/Jm5CFWKAj1DMrJNQrxNNA7KD78wT8p2x9/7EXGZ6", - "C2htshf7L5CuIsC+dUEQ+aIPnaqGNxwqWUakRHO6JCyK2Qbm6m4lS20G+vYYIIvSKZnhMlPWLPQcAhNc", - "uJ/5zXnXcUZeQGp71lg1DIbN6k0gkYzAw49DAnxYXcxqeo+wIKiEqgopokwqgtOG8NzHNvujltsDlLYr", - "duoOlMmY6eUIMi1ppvrl8IPz5OZtt8rSroO585vWI2iOZKb4OiKszDWsOtAaRWYTX1SJs4bEfCyFB46C", - "euwnEJyeRDywbK5fZNiqmwsh/22Vc2N2k2K5Dv+qWrl3Wqv28mEr1R4NTAwMNrc114R7Uah8vU3Oebh5", - "U1RCkMy8fkfgtwYtVvGPWR2DKqONN33dazdBVVTH1EbNAsyQD6a21WSUXctDFIITty8DNzACNgSkPvF6", - "bK3h5T6dbCjtfEioO6bSaHuKE48kodeAMmcgsaOGwA4ZAMXhUnGJ21U3OxbqGcT/IP4/CeN5NCrKFpLx", - "sSAJxRnCCYhyNtTO4fZVknFGrlDCC01DqNLgGI/i8vz8+0SDO/xFJtAtHjWkRQ1lzpyRULXeEPBAfhQE", - "hMHIxibWYFvLnnqgShg8lHFkUP2lVgJWPlL6Ze6+SU7gPtvJR/Ndzn4Y3uXCu1ynxnmG8wltupp6LROf", - "SJahlS276ROStZzRVCHdE7QjWwNl6Ff52z3SCp6OHueSCOzmSbkLRe4IoS3BLKVaEp7sWYarOxNYjtdo", - "Spo5gC66SnCh1YLLzWTciuBcA28DsEUVLb8RHe+sIoyresL1cNh+7Y5gUHmvY9IWw3tgKO0VXFH7SduN", - "UpztS+B2k5xx0Uhu1pXb7GJz7m3qGDNDHnFRoAXuJ4mO9ZuEaXrSpvt6FLNbU8qhydPumFiGxGmBNofE", - "aSdKnoe9u/bQ4YYVZfvJlSrZeHIdSuKqd9aTVXCO/I33xKG2fm89+zob8Ehsy35oeK0+3XhfiNBqQZMF", - "WRKBqEJUtmUcW2CWZuBneJvn3J23iJjdpCqIBaCf3XaOSgioVtU73Sw8Ij+qcJVfKJTX2bWNbyGfJHoo", - "2qwJ3nTHkCbHpr5GjWU8QoIUGU6oFaULQZaUlyCFH8/bYEDGgIzHyTAPalY8fG3/yz0q+wfTX1Avg+nv", - "FIjOYSr6izuuAHq5fzX/QIICCQq1P4+Crhywiv9Duhp6tPs9SoLfq0oRqn2Gap8dtfvF4Wp9ijuv9Bkh", - "xoVuMA7I26KIlkFitmvPuKWpIGB2cKg7eUa8nYqxJ9Z/J4bqXgX8fQr8BwE/CPhBwD8KunLAwv5HKOAf", - "iTtvEPCDgL9POf8g4PcK+AGzg4B/+oy4+gkC4CZiuK9N/YhY8d8qiE6jHIM8PYNqikcd5KOR46EFsatZ", - "xzHbIzsP6knO42PmwyLsPpgli/vE+tcm/8XAKTcuOzD3x8XcHRDY6rWDkHHXry1mXfg4RiZtLdT2rz2A", - "uK04HiG1gty1XJiA2JhZ/g4JvFZsw40UYudmpSTpsBRb4E83AIvb2XbA4cDGn3Lg6x1E6ez4C21F6Bii", - "gLjzI4c4kKgrVKfpc+SWcXO3oxBHE4yQIY4maEq3IZsllPb30UyXW2u1wEqTKLlvlq0LQzEbxc4hIeuG", - "FCLRgmep8ZCO/G7VTXIcM8WHUsnPsMNHl3NgQO4fs/M7UztOGu6rHDn98kLVdePZzyMzPG9DhjrLABe6", - "d2X+ezEUiP+rWm54AQzM945zhjlgC0z4fhKaOwJjM5ovsYAEd64kXPXSsFqQjV8a4fxaibBJxXeyiaPu", - "ZOKb1pOY3TYssLZzxGzPt4ejoHIHS/al7zHJsJQtyZf0Mekmd4AOBCKkSJa58DIrNqEFX2m2IQiGwGS0", - "xFlJxqNoN/+hg53W5Ii6ET5tXxA0RQgj84U+WczW6D8+vn/n2kx+RC2VUZzRPyFV4pEkOnzcROvEjTOV", - "CHX2VQPh0NTY7rPjykPtIO2ozC5uUb2zmfMPjyOPLfl1JUT0Kyn7Kh1PBtCPMN/2vmwtyNfDc3Tvw14G", - "ugPd0vnmabKWIGwHYTsI23eQXdwB+gVKeLHWMAYuThRcGlKpJk5MeF6j9otBaYIin9eS5KVIyHalQzf9", - "RjZBQz9NTnK9rqjHyJASqSiD2aKYQd4jlJdSgf/kApIkbkhBsBycG7PK0DTjgQIfMLc5L9ajaKTvtiXD", - "eTRqQOAuQL+tttpy/w6+fHnSN8cOWdODfaLFPlHnrPYbImwN8w2XUAzvk+Dn4YoXw0hnX/X/tguY366Y", - "scsscxgUtevrrJwytOpx1FeMZQsz3dwBGZ+OBmacKTc9KRvYYyqY3hp32kuOBswJmPM02Nh2uqJebubJ", - "JdJIKjq4ML8vp0mEplwt7IOmfcec8nS9D+/bymx0GESuAoQuegOMboDaW5jb+DyqZw54/AQ54C7OAS/c", - "wLgBFb0PgW/t/DJgW8C2E3drnWzn9ejX69qD7m/ECT3B/4fghFspQAJuBtw8YV1wB+duxgkPgG/tnDBg", - "W8C2U+eEzWi4fa2bdaxabeB04519lcvksCbORhTbYYtEH8weE9nINH816ZcQ8VaVx2wLehubXyGKJUlI", - "oZuwRCuSZVBv2pxrvzXI9gvI/NTNqE00NfzyAEjazhEDigYUDfbaQ/Hmm4aeNdzM5LDoywiRJRHrmG24", - "YyCbq6qtVNRyolc8qaZZUrK6aFCejEolY+bSXTQqzSsTnMIlLIVoglWlfFBNdJORFc6n65jB75DtAZw/", - "IAGGjabfLFBZV+Cx1dk29AjIetc0sSmCczlGr6o1VEl1MGUwPi9V7S1CJeyMpLYqP1/FDBaB0Z9EcE2L", - "9LQkL9S6/kojnxzqTCs7gltCVN0TiKqTx+E0d2zhb1zYgLSG91ZDphkYVxJtBHmgKaFsXpGZJimZWEW7", - "IU6ga1L5mO1nKWii9F0IRpZrU6bIHOC6Xwza8IMNHqvBY/Xo5CCpsCrlgPgvjY8ZlgolC5JcI1GaBHzW", - "UfsbxlPyjUvFo8oCEmY2Mf6Kplcx20buXV//N19IMjTSNWZ62tsEkX002z8UwWjToN6mtbjI0HOQ6Myp", - "j2n6ovZkr+jKX0FTuQmGHksQWKUu7GILyOEdCOPUYZNxBQC8mYnqwkr0dQV5uq/qoUfe1Dt6JeYKRYKY", - "/ITE5O37f2JiciuXPPtq/j8wYnpvjtmW+2EfdogOww0vy95iMr08rSUaojq7kEbycTA6F+28P5wPYzlH", - "BYfHFIx8XLT56F9kUyqv5aAMF7onej4ts2stI+UvDC19pn+e0PQZmCao1JJTihUX66ZHgwlJNgXJjTaj", - "sJgTBYO+tCFTNVEGA+0CszQzzxrmaTdmZrVnX+2cHW+3P8G2DqW52Plasfwa0ZQwRWeUiN3I263nFjdQ", - "eG85fS0mtSC2Q6od7AWV4E5UgnuR8PUdDuMcx2ykBpJNGfwfCECbrfgOSCXOMp7of2lGgZWx3/yPH1rM", - "OZH9QAi89sQsQQe9GqEPQfj7pGTZNQQo+/7mrk8zsiRZu5Ub2r12amgVuGtsSf8k+xyVTYnX/7TvdrV1", - "xPfBegJLGSB01WLMcPEL3N682FyLPn2qwa7c0qIL1AB0fxppyKt1M2GEMCUokdZ6KQuS0BlNAFR8IsqD", - "wUjIzftYZaGj13ata84ggmv6+lXMn+1Yd/k8ZuZAgiRcpIimkJXbLAxleEqyXo0zKJtPjhfMKsDcofs1", - "zAbl9HQJsrnF01RPK7oK1kNLylIyo4yC9Q+yZE0JKhn9oyQ+/6ZD097ZZEZJ1kKAX/OszMFkP5so8KRU", - "9bJhBiKR4m0p92YTXrQNmBdYUMkZMtviWrJyaaj+fRSNfn37v9+MolFcnp9/T6o//t39lVR/6J/evmtN", - "V2UX2+Idte8ePF5W/6V/RoqjBPZjhkzMYbUNtcWV3Pqi6uTtedVT/v7Azlj7INlxsKsj96uybOnsq/lj", - "sOLrANX6Upu6OrlerIa/ytladoppfcqOFbRqdQc9nxM2saOPjSfmbAIyl+fprNpWSFj92BJWWxBsnLVX", - "tro1oB0UuoKq/Xglu9MskMtTOmugVC35GYFQEFlmirJ5UyakkNmYmlIwUEcmZokWJylnF+ia8RVDRjjT", - "TMKJVREiX6iEsYxgEiHGbbEZO/uKqoXxxofkq83FXFlif6Vn18dV6smrOtuNrp0i6nHznQOLzi3iozFS", - "tBQw12yIpMhGLv1wfv7SuspMSdZ75F3i9h2K0l3i8SCOG6TXJxFB0JBJhwu4kqheW6ORcu/a3CiJarU4", - "6t9tPudgcwxicpvNsU0Nq82OpjVYHk9dPpVEnbbx0UNrG5bFQ1LaWTMKcnNd7xo542siqzgC8ZYA8W1r", - "Nk4grWKQnkwCtO3M9o8FAel3czgqIVASq2bk+vNPeuqfXzRsk59G0ejnVhFpICtxOTKiegcIs1pKr2Zv", - "ZTBHIE4NhvsgUd2ZROXMhzasej8Bq9WIqH8TZEYEYQmRfQLYMIXOJIVp1emIqtQ6Rxc6FbsHr+IdbIp3", - "aFOEwncDzIonAnnB3vio5bnHYHLswbgNGfBkiP3BxdQeubJPJmxjDkE+O61cnV6Z64x8KbhQ3pRgb6B5", - "A+EoQ9ikXzFu7sZtQEFCrCqDFs3hOxP3JTp5oZniKchig6DeHsfx6OHd8NPwwuxOEpEsaJY6MDJxs00l", - "0Q8fXj+3IDIFkelASPdo3moHIevZ11m/vm1zv9rXVZuj2Y+xW6r1Pi+mD46zh3/GDVr+I0yDbFEBsiD7", - "EWFD6Qho8FCODBmfbzkRvHr30yjS/0Xv3mtd5/0l/Af+1e4swDXXagsVvQuVKLyAHiGntM/+3ZJt3Xcz", - "vbfNB2gD+Ei6n7zb+sAaRN4g8gYr4b4ofPYVlM+hMi/bROPa8nEzIXiA7fEDFoSppo3leOSA1029/RBL", - "c3cRBORHIiC/qbFly1C4v6gckOVQyBLE6FCZ5JS8P0xB9m5p26QLzrFKFpTNB1uQXU32IEyHZMMPK31r", - "SHz0gnezCKAfl12v/dG5URYsYHTA6IfFaAuMjx6pS4nnxIvRzhVutSBiSwmQqJQkRc9rnXrDP1hGVXGx", - "yOZVVgtB5IJnqXzRSQc+w5KC30DjNB4VCE4GZXjqfqccEoZ1+AQkB0r/ZD217jC6a1ZB8yykMg7PmvuE", - "1Bwz1jTMFluSJ59DvUkXV47+xSnT/EgtqGychFoQVAiypLyUiDPSCJ25hf1jy47FpQmJ3wgKcpnWWwJo", - "GtljA10IdOFOeG1PnPMlyflyU8BryHXtCRQ87PaQUXnGSupFim2r7CZqtCMEiJWEKf+oO3boIcNu4dnW", - "HNHWTgLehVcU84rCmrlO9uHPR49mt2PWNoZ2g18TpsT6Pjh2sv3aY1h3sUUYWjl4oC7hOeYYnmO4yCe8", - "VEWpJiZfkzz7av9w/hKtFp+PC75yBdp0ZySVKBNVCmJ9+7nIkSynOZXSIxj8QtTPXOTvYfZLM0yfOcd2", - "QwDOLTaaeulDLDT1S+Tvp14l4bg5XtmmgKYpwhZ8NEnL+BxllEH+UoQZMlDZCk0O6Fq5YHlkUHUIzpvx", - "eXt17M1DKwrCTHlUg9E01R1khP75z2yZRWiWqwilWOHfIzQej3+PULbM0DlUGtC0OULfwt9ECA5cqhqn", - "fXZaVaWDC7I3pkdYLWiy0CuB2twNQtEmAtiW1iksfOjdpSkMXa0pcnFoKU/KXHNLvQ1DisDGzEV+P+km", - "gmx8WI40JNcW9Lsw3npKrOvQw2e2gB3ISRhlVCoLpfkYfcQ5iZm9fZszwtWkQ2bus6/AFDtL0v0Mi7w5", - "dnNG3s/gpHCagkyJsw8NjDeUZQusoq8jqog5nH0+cz9A1aDRX78HBDjJtFyOzMoxeuVqWiNJiDQlr6Et", - "MjkxZd15o2x2zOq62VTYktlj6DjZzNEJP61xnmltRrYX1bXyW8gDdvce4Xs/kt/pkyMX+ROrkt2Tiwww", - "LdKcROPdgmqhB0wX1RjPJPrw/uMny2IuoH694VsVkxrHDLBOy5wbxVcjGNUYgK7JWiIsHHKbZLgSPa/w", - "NbKjaIocGTSe8SwlYjwe2zKvuFQLLqoK2y77LjJJvARBkqhIN5t0uiDabdff1x/nOCUdNbphXL3zmKVk", - "hrUUBwRns/g3AhLymyVnVf1vr30rMN7TZbwnYAtpSH/D0pEB0wXZU2segCPmslwyMosaGZHbVe/bIX/z", - "M4NRWu1xqNgtlPa6wwAye9Rcu/MnZjl53KIj2OkcnGKJfnnjmJAGMiUopO5WHDgSTS8QyQsFjlysVuxT", - "TmTMGFcmwSPo2RLpf28wBaD6OMvaK61ZcfH+ITT4YAaB9KkIpHWCNM0qQNxrFxlfbmt9O9a0mO2a0yKN", - "92DSg+INldSpVVJGVg21kUr7YkVSRFktST7Tvy8pWHGNoLy+tUD4QEzvZhLoHgLkPefFfXAsepKvcJ7X", - "kY/lNKfKIvJFVTPFVM/ACiM8x5Q1zEKIsqJ0KXBLpjE3ZsZWLtHzdBoBv4+QmSRCOaZZhFZcXM8yvrKq", - "4ZSna5TjNcKZ5GhKjDL5DWEJT0lq3g7QnC4J0+iviQOQDEMhQL6wb+ANHZh8wXkB4i8on0yuCIgPjcfD", - "mFWvh5GZ2tEYkIVxiqvkcpX8svNqSdO/xuhVzBiZY0WX8DqREknnDCuizwVp/BUMZw3iCCfn6hRuCzMx", - "M9JMhEqWESkRdna3joenkyJGW/X+scKehx5mcv1pql0BHPlSkEQZuwdmyFCtqGFyN79IZLQXKprAYu4A", - "PCEEWU5WM98bU+XWIRUp9J1StpFp3EHwODz1nORTT61wn+F8QicNjdnrfPCJZJlWUaoM+AZPjdBRfb6h", - "NgOUfo0BxuPRBQJYQFzErPHjDGeS/NWhvLzK31421heU7SMXk9ugLKWz2dnXZJBzS7LAbE6MpXO6BncF", - "I7tGlqghPZpNN4+mRK0IYSihqTGfGpst6NLGpirRnCot1ELFywXJO2DtJzqbPYiyvDnFLxQyvGphxDz3", - "W28MdxKevAW3zaTwyh5epSw06tPq89XCgJv6D61o1nPDh6O7DMgKaPTXWdPU2Z8jyzw1It97wpYKCF2U", - "EUA9FqZhMplFpQ/NtQb7U7A/HVZzfmit+cTEvCblOPsKlKHvveWzIwM1ebCRnsOfFGPW97KCXiFwMGTg", - "U3dtdVVpC1sy0IJQTqTE7fao+hmmQXCOgYXrM7JFmwQHubVlLncR9xraHNSpu7UHf9hGGwjzHI40Ro7t", - "RpqGMn4jtHFm3IA0AWkenDk1H+xvJNa2OsTcsXx72Vx0kG+DfBvk2yMhIQPl2yquumm+hC/rmumG2x6Z", - "oPug1tDAs4OgWzk+4GviJFvvI8DRibwBfQL6HAG/Mib2AfJu1XUj7q/pRATsiirz0GEdfEyUVl6odczg", - "bXjTu/DGroSX1cLDQ9wJviBUwDT0NW4L2BBWGy9ymw+8X+MRp2k8ilDsriUe/fXXAHB6Mo9uAYgPAMQ8", - "y6Y4ua5huF0+uSR1JPQ2HMP91nBc+U1irf0zsqraxjEbKMDsG0FQCSR2OwEHgmDyMLg12X5Y9unMH3FO", - "OoK3fc9MUYUHE+em4dqMq7Rxb7R+jFOern3Rel2x4VsvziFcLWDLfWjBDicasaYPihFVyGbAh4AP98I9", - "tt9vbso9PEbc++EeW+85AVsCtjw897h/jKi4R8CHgA/3xD0Gm0I3dNEqKBJyn9mIFNmVNKfDdhke08Nj", - "+uOzmU0a5l73Z3+G0S2bT4Sma/tANV2jPP3bEBTrz/5oQwzMwHn6N18WyGrVoQZUQOmA0hNgesNYZcUh", - "p+uaQUZ11sY6zmdB1mhFBDH5XpUiacx0ty5U/wgLCZw0oN2TQbuzr/C/wSy0Rj9cx0z7UcqDUVvjV0Kv", - "/zHIrTL4lAbkDci7i7xnaZkXN8bgRu65+ifNT92/0IJga5ZRmGYNPTWXfej/k17Zg5GAkJL/jsFRwEmm", - "ZwuapoRNcsLKCWFK0CGRD7o3sr2RGaF2VYZGSCQPmYltuJF1VJAxk4QgnGU2fOKlzW1aSiIk4ixbI91h", - "M75ijaYk42yOFPeBrd3P32ExvxFWvrGbCXLhXbOW0+IUD4JuBpQHJRU1+OJ9IvrFjHSorD9tiXd+sW7U", - "tuRQa9EGnhHvhzwjZ94SRQ+a5ewtm/HTyHB2VMnnK3d3lzPeEXOUYIaG0HOTAnAfgl7BeaDep0u9YZJh", - "JPzYsrpzgcrCJEX3k+QPXKoDE+SNxXzdpbxtBPvNBn4imqLnkmSQfc3ugTKptCrAZyYzO1Q53y166ZxI", - "d6d49ukZyHS44WkKs0Xo2c/PDM6vqCSPiFnsAbxPkmPUcs3AOMdNEQcclRMsE5wSZD4BTTYn+ZQIuaBF", - "hHBRSOuKIMqMSKLkWc5T++dWnBYlJv9l09FtK+YLrnQ3u2xDOdEMzS4GM6u8tLA0PRjj7JstZGjhbZBA", - "Mc9LBVksn73ROtGUp+tn9hQSDKm1p+4M0h7Rr08ld2FchCk6o0Sg57hUi4khYXV014sjCu8KEtshJbaf", - "qCwybEEX1cxlT6nN6Ok3ktqOEESDRfnRCo6nGbDsMrUDND+TDTztEjOPlfjfh+B7x8JpED5PX/g80/Ji", - "v/Va96o5W0ve4G5W6TK73tJiDTf8qihkYJeBXd6LlfxIkNTz4uTP/rigqdYaq0enOqDVvi1pHUtjo8nl", - "v+BZuqPtxayh7kEpgsRVu8z4fG6rDWCX85lxjWvmLnQfYnyRenSzAY9Pj4dfV/e3bhFv6qu6JmukOCrh", - "FluNPPXa/9kc9Pd74MBbbyFsxgeLAoETD6xaO+ytuIHNTd57R6/FJ4OtgRGH5+ojUVn/ftRcuFKRAw/2", - "8uDAgZ+SLly/kwzw56r67ibiqtJFN+uFbjLcmAHeG64re9jub/W6Ar8N/PYJKb6Mp0OcK6Hbkdin3sGS", - "A54GPH1CeCoG801xb1zzMvDMgItPEBclEUuaDGGbrucNOKdNWnJQ69JHt/CAsAFhnxDCAu70Y6tBMePr", - "59JJt9h/292UDOcchKFgZSqwlCsuUpfcfU6lMig7uSZrVxQfyuQzsiQCkS8Fl+2GJoffn2GfAbkDcj9a", - "5KYDI5a0wopogZ5Py+wagkFtQflnNH0GxkcqUY5ZihUX62YyMIOQzldd/6qwmBOFaPHSFNjVc1jrr1oQ", - "hhaYpZnJjuyS99HC1n/3Ps6+veOAqbebOK7PY0I1gr/oNbfSNJhZH2WSPT/7o4VEKVEEtELOjL2nwfYc", - "y6P+YCo9BJ9ZS9FqwSU4NRnep7nYttTbzsfehviqE2ceb4vjZh9Al/fhId5XxHc8Je257qekEQfSKPkD", - "I+o/aNG0sXQ8O8bspt4/b3s9cztZRIvsd88hGAfnD4Hmb8dj1HJSMyYDwoNqwNAqz5QgQoHsAxiXORE0", - "0TTfpqizMI3TVBApvbR9T4hcTvTyGFErLq6lBkw9Vz3PQcA0KCePk78cfbqTjM97jBJkqZfglJPqe80g", - "2vDrVz1gb2pJY/xHiuth3BQ5VsmCsjlSCyrRDNItSaLQ8zlhk+qf0toHNJxONLZVjOIPff2Neiu6A+Bh", - "wLtHYxTg89OMmsc1oBveZhyQNDxqQWrGRWKewp7Z+ojPIqvnz3CZqZhlZEky3fWZFkKeRSCZQfW4Jgpp", - "HSelMsEi9buDWRQ9jNqf8fkkpYlqyS0VQeMsV61hS7oNNtXaauTAtLVNLpP2pi0Tgpv99wcOWQrRSr0s", - "6OyrvqyupI21tLjBggzgNyRHD0/qY0m/VkM1Zb+Mz/2aiFlxEPMCuzkBOc/pL/5SfD+RJNPsAyPbdytF", - "xDvza0uSiCv7wZUxTUxtUqO3H5Y/uLGcsgRGCN0/x/L66iW6mpI5ZVcRuiIsvQKedjUVHKcJlupKs7OY", - "6fMplUnxCCwRKzzFUk+sCM6btW2uHL+Um9VSIY6Y5lis7Yv2GL1CGo2h0garVoczQXC6Rqk5i9Q8lM9K", - "SVJbxBj9cP6jj6++c2d8KN6a8Dy3n+0wwTlWZIVb3Jvh2N2GKJPUWnvsTbSF+hqC1saFzUXtTvJBkBn9", - "gjLC5kASc/yF5mU+uvj+u2iUU2b+cR7t5K+EMWEd7QvfgpfI5Ev8gvMiI+jbH78bf/s//uf42/PxuSdN", - "D29bK+UahRDOOZsjviQiw0WhFQ1W31i1gx9/7NtBsWx76/ivX1+920gK1/hiG053v34v5phRiU0dlY6C", - "3d5r3BJ+6n7uEh9aDLLocTrS0A/nPw7p++PDEXXnNzvMirz7DGml7O63yJhpstzyFqm/HvoaGTOz2rOv", - "ds6/0POtHEf/hnCZUgVS3b+1Rbq88NuZnTvuYehuQ/nYPM93YKjcMVeDPQKshNYc0YOadvjwvvm03jeZ", - "BdId/cTjTB5UhcOoCi5x+3HpFvrSTz8DpGUs64r8OVI4MXpzi5R8UFJtHiwnhnx9HRGmpbZ/jopSarG0", - "KLOsQWZrSREXRavAi6UkakLY0t/qFZanlMvJkgjpS9STZKVURPjMWvUNtLcyRhI1Uby9uSgnCRfmUHYF", - "UN2c0q7WmSB/eEfOeeqx0+lWtdBaU8fYS8JSz7YISzIuS0G6W2XG29Wg2R9p+2Evlp6fC84zT9MyTdpb", - "VhM+lROcEaEmGvC7eq2wYP5OGZZqMuWe3UCr1vraW6lUhBExKbhQ7aed8WSiVSePxTWZTEuapfrfvg4J", - "0A5fIy9dTG1r+yzj3D+3wMm1v5Hz3Nv4J21H1xzrvTPMEjIhLPX0YeUMJ6oUpH1pOcknU8yuPQAMzWtF", - "Opo1dPqavZgDRNJHaaBxJvifpAndU84zgtlWhwlWe5vQHbX2NNYyt2yfnssJFsmi9XMuJwlniWdVXE6u", - "iWCeQ+Fy4l0Wl0Ow0PbqxkIuJ4JkBEtvcwfJKviKiMlUEHxNxLf9Xb7r6JLgKWVEfdvfpWuUQnBFEtXf", - "wy2po6csiyJbT9i0HZ49WeFA7pj8yZmvUVDcfuOScf4nmSiaedqLTp4qFValbG0Cowss3d+8ZZNp76SP", - "ZJPiNjpYwWO34c/Wn43g1I6UXftcYSEwU2sPmXvorHxaqLvkq/C61W6jOVtgka7wkKqAH16/BTN4TnIu", - "1sh96EJB6hho8AW0kSARwvAjFTHDc3gJFkTDLKL2ufnKONNeNV7KUMJzUmcc+henjKRuAjzNiMeDCgT4", - "v7sNBa31yWmt7u6HWnKPvACZxdAp7nGEwllmsePn14Ci9OPrj2/RgkuFpqVEOMWFMrFPHpzRUwR8CUFJ", - "dwjGlXl9yLMAQ+8Lwj7+12tjxvHUHRAk0yKLS1U37jDB93lZeO3nnz+//WnbiN7icuFUmlNLwh8M4Zsu", - "pTbpoUlNLQuSaH0TLt9HPI8RsoI3z2kR7+EW95NMnf95wybf4RHnrPBHS63Dw0B4GAgPA+FhIDwM3NnD", - "QDD+B+N/MP4H4/+TMf4fv4f+pv3mDEhdn0nSGm5MV4/q/Mq1BgU6KNC3QnSApMcSELONbvmEbnOEVsS7", - "JKoUDGnYRtQ8ylmNlYiWxIommFlPM/YiaP72sjHxI7ShhuwY+wFjgllKtawwMV90PhrjuURYKZwsoJKu", - "4pVbJuMKrYmyrTabi/6RfEmyMiUtHpoWJF+7BXzC88A6Auu4txjoU0PUBUmuhwlptqsP4VxrwLSAaQHT", - "WjCN50VGMUtIgzsOKOXyC1Go+qBZz8U8Purx/W5Or6tJK4bYVaWlFwo+YLXQ475NRwGvHhleAa3ns1Zg", - "a2BcC0HXEtmMlyxtINtWaDRTRDCcQS53IhARgov7RzexH7KJW6LaZUC0gGhDEE08BjTrzMQGiFX1Rbrv", - "nljVnpctINITRqTXLQDlfMxPXUYcKBk25MHKSFIZUIagVRAHnyhyVRc/lF1V8PVIxMJ6G2dfc5Nqs8fp", - "WO8f4Xr/JvbEi2u1W3ELut0Dtun+v0midP9dSGq5tWpxSJZJQqSclVm2RikxF99921w0Duahr97nYvhK", - "7dxhF7V0joZHcn83cyu8wdP6d12w4ehAiIprpyuDlExxO64dNMsnybMvb8ixH4V+KSpuLfbh1uLGvPry", - "Xin95T6c+vJWfFqcCpcWN+LRD3hvD8mhLwN/HkRHaqdL/5Nnw1RlJUWUYf37giTXSJQMmVH2tGF9NFMH", - "pv2UmPb29e9h1bJA1gw3bLFvnQgrT6ns8zSALiC5DAuq/AmGDD4HAUdviaMakB6p38GwzC3Wx8eTvMWH", - "f/4kKgEFAwrefWKWU0PF/hQtBg2l4gLPyfDULO2ZWQISBiTcDwn/PsWPFPeolndnOCHDMNCVcWh85kG9", - "t80eAQEDAgbn1xbsK4ah3dsPrnBKB8IVAdMCpoUKqD5ck0QsaS+fc4nTbG9EmVSYJUQibiqnWAOMzajp", - "Q8aPbrKAkQEjA+/rwsezr6buZ3+JyG2cdHbgm2DmkSLm5iI+ug031mEOq1qGXCYdq7AVVQN1CNTh1KgD", - "ZJDxV7X8CO1QsoaZvhslxYAoGOF5HLO3M5SWhhQgKlEh+JKmJI2Q/bJkimaI8RX6t7rjczKej1E8+nYR", - "jyIUj75L49GL3cF4TpXSY1XrcE9R45h9sn+afN6mmSpJstkYfZZESFdZE2l640pwYpa2lwg0g3qf+s2Z", - "3PIZ9WCJ+twhtdBzd3yG6Oyc9PfnefPI0fucgq+DO+FxayW2HW+BUGLt9BMm7JUmoekt6GP/Ie9BYLuB", - "7XrxrSxNrtJOORw4mu45Ru9ZZv/dYFjSvJUabiYRFJ/OMr4iqTdVjsaskCDn6dF7PpU8IzIh4MlKZoJI", - "yD9ZlK0ZmqAdZKGqfgrk2zQQxyWalVkGBcAlyjR3sOVum9MgSZSibC7HMdsohP5+KneLoLeJW6V63xjP", - "rmp0bNLGI/Ja3IASd33DCiG03fxWAfyh924GbV79R7eUQ8nMbbWJ37fsAAmScJFulCX3FCUO9YifXBmG", - "VmrXxnk9sBwK2ZyuXNpypSdWjPg3ntLZ+sC0+wOX6ugpdzTaTYW9xdewspXdVguaLGzZqhyrZKHHhpSU", - "biItHM0yPJ+bcv3mMBUZo3j03//93//9zW+/ffPTT/FIC87NX9BicZHnF1LGo5f6EkheqLWz1CQZwcKc", - "vF7g2LeHjUTdB9sCRnpcAII73cPDcNA7werAR28qXp59HVxs6z5kzD7luJfWtCjE96wLn4iGc4pin7PM", - "eIBxoOx3BDAWzKBPRNw8yUpc9ymaHgvBP4RwHMTaIxFrgxD7eIXYgjBc0LG7Eysn7PD9jysNeGJ0BG9j", - "R2ChdqdZlNOMJvYoC5xc43mfp6jGNNfTuKRlGUmdM5qvnvuKKnjAiJn1QhG2AjwVSNK5JgPomqzHCBg+", - "SdHUvq9pEh65CeFfCLM0ZlgkC6oIlDvTnVMyw2W2Z3X4mPWXh//gTiUYCJ9UZXh774+kKLzD2LOUzmb9", - "CK57EUHAAZyyBppXmD8lakUIMwh/0aQKMbO1v7bIg9QIaJAeEmpgYV1WJZqWJvsMZ1CV3nTKo5hxRpDg", - "K1QQ88yNFnipSQW1iG4+r0bTEoYefk6XbmkRKrJSxqwmTqJkzMgmrqNzyY205AGU6oqwBBdX0Af+lCUU", - "DXcEA1bIJak+Rc/rCTSRShGeKSIshau86Z/F7CrnbLLMdaerF9aToP4Ws7Qe0x4WLoqapD6TaK7BX2oS", - "SHb85fRv7jgiVLKMyAY5plrqsg4K45j9TFawRMyQWnG7Aujzw/l5hMiXhBRq40AiK+apBWFIQOUgveaY", - "GZkso1L1kNGfNPz1yPiv9BZy/I0kupsiqXnU5jMDAzSVSHG3TSfy/6Epw47Xgybbe3ge+2eunLBTiVZw", - "9ZZ19C3E+CLvuY5/6DO3X0ZuAuPtbYHj2QZcurtjUhGc1qx1wSVkhWtbGHzftqyqNOZ90FcAiIeThR+E", - "GDdDcvrMrO7C/VbTRszNYdRW6z1/4XfLB68jDUV9bwh2qPAS/7Re4mUNkruKmDdELMjTj1metvd+Yq/y", - "rwXBysRbQLHbmiCj59O1C0OyEUkT2lKB7gOX6uAkuqfCvl6Lr/I/tJWKS4U9ZYB1Dy0G2XW1tqeCcZwo", - "byVj6FKAR3pPu+zq4K1IrNt9NcV12ywjXyZJUU4WdL6Awv1ywbO0vQ70xgcZXw3un+Mvk+09tPajrLff", - "dg30zf0ssLepAwZyogS3sOLt1H0JA+qn625FhhPSCTFg99FqIfGvt7d+9jKZKF7wjM/X3g4rvCTec/YU", - "ZL8PG3Gv4OHkqwRoTloTnaedu7M1YLbfO2E7ol1r1gmWCU4JMl8jqiQSxChQNqniuFvI7tNcHyJyNfjq", - "P4yQ20zD2UhQKStI8Ym+xwhEwQHhtBwQ9pKmT9Lp4PO2vN2QgDtk7KOl0IeyzAS5/onI9UF4P0Xh/cgk", - "9qP339iR7s/AY6o3P1wl1pvefmnrlesQZK4gc4XY91aMyyd00nhJ9uLeJbz4Ig3YiJrHaSvYmMfl3ewt", - "4P5nHrC6cDR/e9mYPijZgQ00ynTvlQwFa9iDdCiVnZ5xhdaNSjhgCtI/ki9JVqakxWhfg2ZVvXtIBpXA", - "RQIXebJcBIohDZbbbO8OxHMdAsYFjAsY14pxdRWzmlsOqBTuqWlW1x91THQzvWi/ZbuuVVWxza6C4gGV", - "AyoHVPajstgXkcWdofHlcSPxVjG7GaiokXHe7TiUDRfa+lxa3XgzvCQb3rI24mR0McOZJNGu92wgLoG4", - "HBtxyfi8uxJ5g5rovu5124zZ7tq/QzV+5UFVDgh59wj5ugVWGzESp4+th5DlTXbgm4sARy/Ad/H+jtMI", - "vD+QmqfF+2tkOPuaS6L6fSlt3f3qQxM/3SUObHhLthCRUxULPmC1+M2W9vfTnNScWBVlfrc0ZhcfvmvN", - "3WLvzizuNF0Tfjj/cUjfH4/Kg+2V2sGf5sOUJyfOU8Udw5/vhzvviTlOdAiYc98s67YWsNsKv4/H7BUE", - "3yD4PlXBV1Rir9hH7BW3FHovT59tX56iyHsZBN4HFnjFLcTdJ4E1RyfsXgZR94GZlCnquq+dF2VY/74g", - "yTUSJdutCbuPtPvRLCG83ASpMkiV7QibUjncx9F09mPeT7Y9oFtAt1uhmwakR4tyVfLEul7jPonT6rLp", - "zQwQiqMUy8WUY5FGSBCZcwb/p2zGTU/wP55kdEm6Fb63dvyTsBGFYpJPqjDGDg5onZhmcldO9BUPDkAe", - "WOZjZJkOoB8t26wyAwyRVCv6YLRQTR4IThaIzyBJkhnLTx3e2fYgyAasDHqjFxs3Bdj9GHeNmHvx7Xem", - "OfDsQB0CdTgV6qDn5qVIOvi3l05Un96IVFxWEweaEWhGoBmnSDO6Y3yqkpldpEMLGwQlC8zmtyQkRxwK", - "FGhJoCWBljja4QpmDLEW1IQCrOXXZH22xFlJUIGp6LITXNp5gqUg4GLARS8u9sj+Xmy05dP6rHXHLuQH", - "PAx4eER42C1Pe5FxR4beBzVDBH3AzoCdHdi5V05IE/uCB/hChiSPAe8C3u3g3aTywbqR51V/7cq31fiH", - "KpXQWcCytnglXKSIphHCEmHNoxURDCu6BBcxi9b/hmrrzm5ietd24TEpuWKZkR5xCpV4U4QzzuamtG5F", - "Djqqe/UV4vSNvbPu+8yZHypyHl9FzroUdVdtziY6hiKdT6hI535eUUfCkzYKw/lRoOrvqdiFnlca2osh", - "yBHkxCAnBi/EHtycGL+lScbn3di5y6Ccy1PG52P0BicLqLi3RlQijBTNCRKYzQlaLYggHb6MKwxDTbPO", - "EhQ1zzNRcL/yeWB+T0AHe1g82Rs7bogT+6FCwICAAXeMAc5+12tLUHiOnk/L7FpLbfkLvynBmu4OYz1Q", - "eN6qeX/Cc2TaIi2/6cVVNoRWJbsW3f7pBv09qN5Pq07wFyoVZQA4rVp3u9E5UNpAae8qUctrqDBvqOvY", - "k5jl4PQ0xQrvLuVnQaBWXI7+4+P7d0h32slYpvC8zTyqB7UlvNpK1c3LDAtEvhSCSEk5Q3wGBFtr1xKp", - "BVYowQwKgU1JozhYbT2F8nUdk/vrkW6Tfeh5H4T/EI8Sx0DrjzyTi/69jrDrzSSmwc5mEdMfdQsxLpju", - "MJjX9zrhg+27kn7q95IgBz0tOQhnmQaZb/T9W3Kb66X4RCJPUGmQi4JcdOcJ7DRpA5cRH7l2EtJxEGuD", - "TbeQsGp0DPzgEfOD05CrnLFzX9HKFZrulK6cjfNgODvcSeP+UcuuLWDW05S0nPV/gLDVQIsgbwV568Hk", - "rQ4a7kSuI6TgJy1/BSYRxK+m+PXVQMaQJIvWOAv5EmlVagIYjYZsMJBBo6xx1iOY9XlTvf0J7LeVNbjF", - "X6qC6F5/qcp7N+QmfLjchBpwLEFYe8SSBwKKfb3o7g2Ijvqy21n85yKtnppQg/57uPtDkoFDP3T1PVjt", - "+aZ059w5qGZ3xEl7cjH+QpRllcZty3FVWseveejjoLyLR0Ik71w1vC0VporksgUPKszDQuB1G16A0s1n", - "7hI3no5rYN2V3RlXaMZLlh4TmA7Nst3+tOkX8IZkIrw7UPXNY9d8JJmuD64fPUmpc5+3HZ8c8mSg9VBC", - "z5YJZADMBmPCEzImbDzqDPBz31cS8tuvn6YwFOzkTyE+vx3FNuIhb/CA6pfhPlYdjoYxGsO8m2+reN6t", - "4ymDQHdKAp0Pfq1M9zShNwh4QcC7G+5TSkCgr0NiX6DvGP2GGZ4TYR6FPksi7A/giS8JAdcF6PsScbUg", - "ImbwL8RZtoYOGk/MT3KBNQggzhwCUYG4mGNGJYAUztBcCxMyilmRlVJ3ySXJlkS2vS//QtRn2FFwgThl", - "0U7f4amG42jAjowBkSqJCkGXugGgGMUj3TyJy/Pz7xOawv9JPBqjS8MQAL6bSBUzPQDNyJyM0SuGSI5p", - "pnmOHgf4Ds4EwekaUaZ/02qWIDPIIQRrwOiH8x/H6B9ULXipYoZRgaVccZEap4Uk4SWzSC7RtISAGsYV", - "knTOEGU+Lw6HZodhTrCt1veUGRVS+V5UolGGu1rdVtsED5QRLBX6nyhZYIETBbTto+KCpJBICq3I9Lti", - "jRZYLsZtHh3FgjMyWXFx3Tq3u6D+4CKz+YeOLBqOcyG6aChjPfsK6D6kWJDu2Hhb3YvNxgz4LLoNm42Z", - "5bNoOJvtk8J1n0bqnAuES7WY6CWNaRpV67NEbbUgDFGFNDRjyvTGYxaP/o94BJ5R8UiSbBaPIPMPkK5S", - "LfTQCZRch1FhqS1yt72FkIYnyAynYBLaoh1nhSAzv5D+M1HJokYm3ZkIwhIiL9CSSjrNCEp4VuZMRvYP", - "NIPMZTJCGV1CHXoSM8LwNCMpmmV4HqEFTVPCrNhCmBKUyAiNx+OYxeySqPL/Ze9qdtuGYfCrEL5sA7Lu", - "3p1yLHZYgAHbxUPN2EwjQKZcyU7gQ999ECk5TpduPbTpuu0SwLb+TIn8PlIy40VDgdquH0EhS1V4GskW", - "A7CbDwiC4Osi2rSS0QZ3r0rjKMiWqvCRqPZGr/OLpLOWNVqb9f2kaVqJyP5m+/TcuiQSfEUE/Avu6Jxa", - "8CAr/keW3lPQ/hyIwqYxSkNWs+c6jHtHLrZ0ZFDU8CySYYEd+TX2pp0R9sMRkGE4dQD7c4e3A0Egbo6m", - "BKjeOmqiX5Vn41oM8bXmgy+ZdsSxawcItTXEmozA3LDzJM6f2zMMcnhO5f9rP0Ck8dJuwBVv3OtwAV4E", - "mnfkg1F5ngRjL8gI2BnIRU8g1Nfp0bPNY+79aQz3JA7scG2sEQVViUQHeGPd/nep3LcEyWiES7maKkLo", - "0UdDtR41hD6sWzOl+0D97kKDGSXnWuCGvhv6C1hqzGRrogkwNVpYrq4Wop1+nDqJPMKa0Kc08jyespFQ", - "xa4knFAtStarjbMN+UrcML0zYmsrQNnbdmGK/MswPUWwSf+2lt635PyCG+/aB0jLt0mM/0OXf1y63p/2", - "fT4RdTLFHXETPevDYn6b8vRF1lpbF6h5B54s9ocvhZS9vgkl94Tt4ugebAZrdUcprjhZRs5GpMt+Ozt+", - "PwUFs9t+CVVsq0pLci+/FkMPGIK5YZLIYMIy7RVFcUqeaU5ZLLW0DLUdpWRZfISqN+RDbr2WWOekr7FQ", - "YvSz2sG15JiAbKDcGRz1tUqyk7YB6yjbspgxlds4CQeqklsv5tyEeGjlUyjCNiJsbGsGomehy1l3H+t+", - "Ph4Pz49x0o7fZdszeFtcFhcfirvvdz8CAAD//w==", + "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", + "ewAAAP//", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index b157ffec..b012efcc 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -543,15 +543,21 @@ type ComplianceLogListResponse_Data struct { // 1 not ok, 2 not applicable) and its log. Every property is optional: the // `props` query parameter selects which columns the server returns. type ComplianceLogRow struct { - Id *int `json:"id,omitempty"` - NodeId *string `json:"node_id,omitempty"` - RsetMd5 *string `json:"rset_md5,omitempty"` - RunAction *string `json:"run_action,omitempty"` - RunDate *string `json:"run_date,omitempty"` - RunLog *string `json:"run_log,omitempty"` - RunModule *string `json:"run_module,omitempty"` - RunStatus *int `json:"run_status,omitempty"` - SvcId *string `json:"svc_id,omitempty"` + Id *int `json:"id,omitempty"` + NodeId *string `json:"node_id,omitempty"` + + // NodesNodename The name of the node, joined. + NodesNodename *string `json:"nodes.nodename,omitempty"` + RsetMd5 *string `json:"rset_md5,omitempty"` + RunAction *string `json:"run_action,omitempty"` + RunDate *string `json:"run_date,omitempty"` + RunLog *string `json:"run_log,omitempty"` + RunModule *string `json:"run_module,omitempty"` + RunStatus *int `json:"run_status,omitempty"` + + // ServicesSvcname The name of the service, joined; null for a run on the node itself. + ServicesSvcname *string `json:"services.svcname,omitempty"` + SvcId *string `json:"svc_id,omitempty"` } // ComplianceStatusListResponse defines model for ComplianceStatusListResponse. @@ -2242,6 +2248,9 @@ type PostComplianceImportJSONBody struct { // GetComplianceLogsParams defines parameters for GetComplianceLogs. type GetComplianceLogsParams struct { + // FsetId Restrict to the runs of the nodes this filterset selects (gen_filtersets.id or fset_name) + FsetId *string `form:"fset_id,omitempty" json:"fset_id,omitempty"` + // Props A list of properties to include in each data dictionnary. Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` diff --git a/server/handlers/compliance_status.go b/server/handlers/compliance_status.go index efe63ed3..922af022 100644 --- a/server/handlers/compliance_status.go +++ b/server/handlers/compliance_status.go @@ -25,17 +25,46 @@ func parseCompID(raw string) (int64, error) { } // GetComplianceLogs handles GET /compliance/logs, as the historical -// rest_get_compliance_logs: the runs of the nodes the caller may see. +// rest_get_compliance_logs: the runs of the nodes the caller may see, of the +// nodes of the fset_id filterset when one is given. func (a *Api) GetComplianceLogs(c echo.Context, params server.GetComplianceLogsParams) error { + var fsetNodeIDs []string + if params.FsetId != nil && *params.FsetId != "" { + ids, err := a.filtersetNodeIDs(c.Request().Context(), *params.FsetId) + if err != nil { + return httpProblem(c, err) + } + fsetNodeIDs = ids + } return a.handleList(c, "GetComplianceLogs", "comp_log", listEndpointParams{ props: params.Props, limit: params.Limit, offset: params.Offset, meta: params.Meta, stats: params.Stats, orderby: params.Orderby, groupby: params.Groupby, filter: params.Filter, }, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { - return a.ODB.GetComplianceLogs(ctx, nil, p) + return a.ODB.GetComplianceLogs(ctx, nil, fsetNodeIDs, p) }) } +// filtersetNodeIDs resolves a filterset given by id or name to the ids of the +// nodes it selects, never nil: an empty selection matches no node. +func (a *Api) filtersetNodeIDs(ctx context.Context, ref string) ([]string, error) { + fsetID, _, err := a.ODB.FiltersetByIDOrName(ctx, ref) + if err != nil { + return nil, fmt.Errorf("filtersetNodeIDs: %w", err) + } + if fsetID == 0 { + return nil, httpErrorf(http.StatusNotFound, "fset %s does not exist", ref) + } + ids, err := a.ODB.ResolveFilterset(ctx, fsetID, "node_id") + if err != nil { + return nil, fmt.Errorf("filtersetNodeIDs: %w", err) + } + if ids == nil { + ids = []string{} + } + return ids, nil +} + // GetComplianceLog handles GET /compliance/logs/{log_id}. func (a *Api) GetComplianceLog(c echo.Context, logId string, params server.GetComplianceLogParams) error { id, err := parseCompID(logId) @@ -45,7 +74,7 @@ func (a *Api) GetComplianceLog(c echo.Context, logId string, params server.GetCo return a.handleItem(c, "GetComplianceLog", "comp_log", "id", logId, listEndpointParams{ props: params.Props, }, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { - return a.ODB.GetComplianceLogs(ctx, &id, p) + return a.ODB.GetComplianceLogs(ctx, &id, nil, p) }) } diff --git a/server/handlers/props_mapping.go b/server/handlers/props_mapping.go index 642dba7b..e3e039c8 100644 --- a/server/handlers/props_mapping.go +++ b/server/handlers/props_mapping.go @@ -1058,6 +1058,12 @@ var propsMapping = map[string]propMapping{ "node_id": colStr(schema.CompLogNodeID), "svc_id": colStr(schema.CompLogSvcID), }, + // A run points at its node, and at its service when it has one, by id + // only: the names live in the joined tables. + Joins: map[string]JoinDef{ + "nodes": {MappingKey: "node"}, + "services": {MappingKey: "service"}, + }, }, "log_event": { Available: []string{ From 6d858de5c169e4876851a0949a73b454c81dce71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Tue, 29 Sep 2026 10:51:08 +0200 Subject: [PATCH 53/61] Let users change their own password POST /users/self/password takes the current password, checked as at sign in, and a new one of at least 8 characters, different from the current one. The new password is stored as a web2py hash, accepted by both collectors, and the change is logged without it. No privilege is required: knowing the current password is the proof. --- cdb/db_users.go | 23 + server/api.yaml | 45 ++ server/codegen_server_gen.go | 891 +++++++++++++------------- server/codegen_type_gen.go | 11 + server/handlers/post_user_password.go | 78 +++ xauth/w2p.go | 6 + 6 files changed, 618 insertions(+), 436 deletions(-) create mode 100644 server/handlers/post_user_password.go diff --git a/cdb/db_users.go b/cdb/db_users.go index 6678bb61..03236b6e 100644 --- a/cdb/db_users.go +++ b/cdb/db_users.go @@ -332,3 +332,26 @@ func (oDb *DB) UserDefaultGroup(ctx context.Context, userID int64) (string, bool err = oDb.DB.QueryRowContext(ctx, query, gid).Scan(&role) return checkRow(err, role.Valid, role.String) } + +// UserPasswordHash returns the stored password hash of a user, empty when the +// account has no password; false when there is no such user. +func (oDb *DB) UserPasswordHash(ctx context.Context, userID int64) (string, bool, error) { + var hash sql.NullString + err := oDb.DB.QueryRowContext(ctx, "SELECT password FROM auth_user WHERE id = ?", userID).Scan(&hash) + switch { + case errors.Is(err, sql.ErrNoRows): + return "", false, nil + case err != nil: + return "", false, fmt.Errorf("userPasswordHash: %w", err) + } + return hash.String, true, nil +} + +// SetUserPassword stores a new password hash for a user. +func (oDb *DB) SetUserPassword(ctx context.Context, userID int64, hash string) error { + if _, err := oDb.DB.ExecContext(ctx, "UPDATE auth_user SET password = ? WHERE id = ?", hash, userID); err != nil { + return fmt.Errorf("setUserPassword: %w", err) + } + oDb.SetChange("auth_user") + return nil +} diff --git a/server/api.yaml b/server/api.yaml index 92d3e72d..b6e2b741 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -8600,6 +8600,51 @@ paths: - basicAuth: [ ] - bearerAuth: [ ] + /users/self/password: + post: + operationId: PostUserSelfPassword + description: | + Change the password of the signed-in user, who gives the current one. The new + password must be at least 8 characters long and differ from the current one; + it is stored as a web2py hash, accepted by both collectors. The change is + logged, without the password. Requires user authentication, no privilege. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [current_password, new_password] + properties: + current_password: + type: string + new_password: + type: string + description: At least 8 characters. + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + type: object + properties: + info: + type: string + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + /users/{user_id}: get: operationId: GetUser diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index 0e5407f5..5c1872e1 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -930,6 +930,9 @@ type ServerInterface interface { // (POST /users) PostUsers(ctx echo.Context) error + // (POST /users/self/password) + PostUserSelfPassword(ctx echo.Context) error + // (GET /users/{user_id}) GetUser(ctx echo.Context, userId string, params GetUserParams) error @@ -13195,6 +13198,19 @@ func (w *ServerInterfaceWrapper) PostUsers(ctx echo.Context) error { return err } +// PostUserSelfPassword converts echo context to params. +func (w *ServerInterfaceWrapper) PostUserSelfPassword(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostUserSelfPassword(ctx) + return err +} + // GetUser converts echo context to params. func (w *ServerInterfaceWrapper) GetUser(ctx echo.Context) error { var err error @@ -13743,6 +13759,7 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.POST(options.BaseURL+"/tags/:tag_id/services/:svc_id", wrapper.PostTagService, options.OperationMiddlewares["PostTagService"]...) router.GET(options.BaseURL+"/users", wrapper.GetUsers, options.OperationMiddlewares["GetUsers"]...) router.POST(options.BaseURL+"/users", wrapper.PostUsers, options.OperationMiddlewares["PostUsers"]...) + router.POST(options.BaseURL+"/users/self/password", wrapper.PostUserSelfPassword, options.OperationMiddlewares["PostUserSelfPassword"]...) router.GET(options.BaseURL+"/users/:user_id", wrapper.GetUser, options.OperationMiddlewares["GetUser"]...) router.GET(options.BaseURL+"/users/:user_id/prefs", wrapper.GetUserPrefs, options.OperationMiddlewares["GetUserPrefs"]...) router.POST(options.BaseURL+"/users/:user_id/prefs", wrapper.PostUserPrefs, options.OperationMiddlewares["PostUserPrefs"]...) @@ -13756,442 +13773,444 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "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", - "ewAAAP//", + "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", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index b012efcc..6d6544b8 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -6661,6 +6661,14 @@ type PostUsersJSONBody struct { Username *string `json:"username,omitempty"` } +// PostUserSelfPasswordJSONBody defines parameters for PostUserSelfPassword. +type PostUserSelfPasswordJSONBody struct { + CurrentPassword string `json:"current_password"` + + // NewPassword At least 8 characters. + NewPassword string `json:"new_password"` +} + // GetUserParams defines parameters for GetUser. type GetUserParams struct { // Props A list of properties to include in each data dictionnary. @@ -7045,6 +7053,9 @@ type PostTagServiceJSONRequestBody PostTagServiceJSONBody // PostUsersJSONRequestBody defines body for PostUsers for application/json ContentType. type PostUsersJSONRequestBody PostUsersJSONBody +// PostUserSelfPasswordJSONRequestBody defines body for PostUserSelfPassword for application/json ContentType. +type PostUserSelfPasswordJSONRequestBody PostUserSelfPasswordJSONBody + // PostUserPrefsJSONRequestBody defines body for PostUserPrefs for application/json ContentType. type PostUserPrefsJSONRequestBody PostUserPrefsJSONBody diff --git a/server/handlers/post_user_password.go b/server/handlers/post_user_password.go new file mode 100644 index 00000000..ae6c4984 --- /dev/null +++ b/server/handlers/post_user_password.go @@ -0,0 +1,78 @@ +package serverhandlers + +import ( + "context" + "net/http" + + "github.com/labstack/echo/v4" + "github.com/spf13/viper" + + "github.com/opensvc/oc3/cdb" + "github.com/opensvc/oc3/server" + "github.com/opensvc/oc3/util/echolog" + "github.com/opensvc/oc3/util/logkey" + "github.com/opensvc/oc3/xauth" +) + +// PostUserSelfPassword handles POST /users/self/password: the caller changes +// their own password, proving they know the current one, as the change_password +// form of the historical collector does. The new one is held to the length the +// user creation requires, and stored as a web2py hash, so that both collectors +// accept it. The change is logged, without the password. +func (a *Api) PostUserSelfPassword(c echo.Context) error { + log := echolog.GetLogHandler(c, "PostUserSelfPassword") + ctx, cancel := context.WithTimeout(c.Request().Context(), a.SyncTimeout) + defer cancel() + + if !IsAuthByUser(c) { + return JSONProblemf(c, http.StatusUnauthorized, "user authentication required") + } + userID := authUserID(c) + if userID == nil { + return JSONProblemf(c, http.StatusUnauthorized, "user authentication required") + } + + var body server.PostUserSelfPasswordJSONRequestBody + if err := c.Bind(&body); err != nil { + return JSONProblem(c, http.StatusBadRequest, err.Error()) + } + if len(body.NewPassword) < minPasswordLength { + return JSONProblemf(c, http.StatusBadRequest, "the new password must be at least %d characters long", minPasswordLength) + } + if body.NewPassword == body.CurrentPassword { + return JSONProblemf(c, http.StatusBadRequest, "the new password must differ from the current one") + } + + hmacKey := viper.GetString("w2p_hmac") + stored, found, err := a.ODB.UserPasswordHash(ctx, *userID) + if err != nil { + log.Error("cannot read password", logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot read the current password") + } + if !found || !xauth.VerifyWeb2pyPassword(body.CurrentPassword, stored, hmacKey) { + return JSONProblemf(c, http.StatusForbidden, "the current password is incorrect") + } + + hash, err := xauth.HashWeb2pyPassword(body.NewPassword, hmacKey) + if err != nil { + log.Error("cannot hash password", logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot hash password") + } + if err := a.ODB.SetUserPassword(ctx, *userID, hash); err != nil { + log.Error("cannot store password", logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot store the new password") + } + + userEmail, _ := c.Get(XUserEmail).(string) + if logErr := a.ODB.Log(ctx, cdb.LogEntry{ + Action: "user.change", + User: userEmail, + Fmt: "change user %(email)s: password", + Dict: map[string]any{"email": userEmail}, + Level: "info", + }); logErr != nil { + log.Error("cannot write audit log", logkey.Error, logErr) + } + log.Info("password changed") + return c.JSON(http.StatusOK, map[string]string{"info": "password changed"}) +} diff --git a/xauth/w2p.go b/xauth/w2p.go index eaf0659d..56cac972 100644 --- a/xauth/w2p.go +++ b/xauth/w2p.go @@ -154,6 +154,12 @@ func toSHA1(b []byte) []byte { return a[:] } +// VerifyWeb2pyPassword tells whether password matches a hash stored by web2py +// or by HashWeb2pyPassword, as the sign-in does. +func VerifyWeb2pyPassword(password, storedHash, hmacKey string) bool { + return verifyWeb2pyPassword(password, storedHash, hmacKey) +} + func verifyWeb2pyPassword(password, storedHash, hmacKey string) bool { if storedHash == "" { return false From 6615a774cd431730c840dc8e9d6612a54071b015 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Tue, 29 Sep 2026 15:30:03 +0200 Subject: [PATCH 54/61] Add a list of the networks and the creation of network segments GET /networks lists the declared networks to any authenticated user, as the historical collector did. POST /networks/{net_id}/segments ports rest_post_network_segments: it requires the NetworkManager privilege and, unless the caller is a manager, membership of the network's responsible team. The range must be IPv4, lie inside the network and not overlap another segment of it (409). The caller's primary group becomes responsible for the segment, and the creation is logged as networks.segment.create. --- cdb/db_network_segments.go | 103 +++ server/api.yaml | 125 ++++ server/codegen_server_gen.go | 982 +++++++++++++++------------- server/codegen_type_gen.go | 113 ++++ server/handlers/network_segments.go | 152 +++++ server/handlers/props_mapping.go | 23 + 6 files changed, 1060 insertions(+), 438 deletions(-) create mode 100644 cdb/db_network_segments.go create mode 100644 server/handlers/network_segments.go diff --git a/cdb/db_network_segments.go b/cdb/db_network_segments.go new file mode 100644 index 00000000..c1b24cd1 --- /dev/null +++ b/cdb/db_network_segments.go @@ -0,0 +1,103 @@ +package cdb + +import ( + "context" + "database/sql" + "errors" + "fmt" +) + +// GetNetworks lists the declared networks, by name then address. Every +// authenticated user may read them, as in the historical collector. +func (oDb *DB) GetNetworks(ctx context.Context, p ListParams) ([]map[string]any, error) { + return oDb.listQuery(ctx, "getNetworks", "networks", nil, nil, "networks.name, networks.network", p) +} + +// NetworkRange is what a segment needs to know of its parent network: its +// usable range and the team responsible for it. +type NetworkRange struct { + Network string + Netmask int + Begin string + End string + TeamResponsible string +} + +// GetNetworkRange returns the range and responsible team of a declared network. +func (oDb *DB) GetNetworkRange(ctx context.Context, id int) (NetworkRange, bool, error) { + var ( + r NetworkRange + netmask sql.NullInt64 + ) + err := oDb.DB.QueryRowContext(ctx, + `SELECT COALESCE(network, ''), netmask, COALESCE(begin, ''), COALESCE(end, ''), + COALESCE(team_responsible, '') FROM networks WHERE id = ?`, id). + Scan(&r.Network, &netmask, &r.Begin, &r.End, &r.TeamResponsible) + if errors.Is(err, sql.ErrNoRows) { + return r, false, nil + } + if err != nil { + return r, false, fmt.Errorf("GetNetworkRange: %w", err) + } + r.Netmask = int(netmask.Int64) + return r, true, nil +} + +// NetworkSegmentOverlapping returns the id of a segment of the network whose +// range shares at least one address with begin–end, if any. +func (oDb *DB) NetworkSegmentOverlapping(ctx context.Context, netID int, begin, end string) (int, bool, error) { + var id int + err := oDb.DB.QueryRowContext(ctx, + `SELECT id FROM network_segments WHERE net_id = ? + AND INET_ATON(seg_begin) <= INET_ATON(?) AND INET_ATON(seg_end) >= INET_ATON(?) LIMIT 1`, + netID, end, begin).Scan(&id) + if errors.Is(err, sql.ErrNoRows) { + return 0, false, nil + } + if err != nil { + return 0, false, fmt.Errorf("NetworkSegmentOverlapping: %w", err) + } + return id, true, nil +} + +// InsertNetworkSegment creates a segment of a network and, when groupID is set, +// makes that group responsible for it. It returns the segment id. +func (oDb *DB) InsertNetworkSegment(ctx context.Context, netID int, segType, begin, end string, groupID *int64) (int, error) { + res, err := oDb.ExecContext(ctx, + "INSERT INTO network_segments (net_id, seg_type, seg_begin, seg_end) VALUES (?, ?, ?, ?)", + netID, segType, begin, end) + if err != nil { + return 0, fmt.Errorf("InsertNetworkSegment: %w", err) + } + id, err := res.LastInsertId() + if err != nil { + return 0, fmt.Errorf("InsertNetworkSegment: %w", err) + } + oDb.SetChange("network_segments") + if groupID != nil { + if _, err := oDb.ExecContext(ctx, + "INSERT INTO network_segment_responsibles (seg_id, group_id) VALUES (?, ?)", id, *groupID); err != nil { + return int(id), fmt.Errorf("InsertNetworkSegment: responsible: %w", err) + } + oDb.SetChange("network_segment_responsibles") + } + return int(id), nil +} + +// GetNetworkSegmentRow returns a network segment. +func (oDb *DB) GetNetworkSegmentRow(ctx context.Context, id int) (map[string]any, error) { + var ( + rowID, netID int + segType, begin, end string + ) + err := oDb.DB.QueryRowContext(ctx, + `SELECT id, COALESCE(net_id, 0), COALESCE(seg_type, ''), COALESCE(seg_begin, ''), COALESCE(seg_end, '') + FROM network_segments WHERE id = ?`, id).Scan(&rowID, &netID, &segType, &begin, &end) + if errors.Is(err, sql.ErrNoRows) { + return nil, nil + } + if err != nil { + return nil, fmt.Errorf("GetNetworkSegmentRow: %w", err) + } + return map[string]any{"id": rowID, "net_id": netID, "seg_type": segType, "seg_begin": begin, "seg_end": end}, nil +} diff --git a/server/api.yaml b/server/api.yaml index b6e2b741..22bc12d7 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -4613,6 +4613,39 @@ paths: - bearerAuth: [ ] /networks: + get: + operationId: GetNetworks + description: | + List the declared networks, by name then address. Every authenticated user + may read them. `begin`, `end` and `broadcast` are computed from `network` and + `netmask`. + parameters: + - $ref: '#/components/parameters/inQueryProps' + - $ref: '#/components/parameters/inQueryLimit' + - $ref: '#/components/parameters/inQueryOffset' + - $ref: '#/components/parameters/inQueryMeta' + - $ref: '#/components/parameters/inQueryStats' + - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryFilter' + - $ref: '#/components/parameters/inQueryGroupby' + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/NetworkListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] post: operationId: PostNetworks description: | @@ -4679,6 +4712,68 @@ paths: - basicAuth: [ ] - bearerAuth: [ ] + /networks/{net_id}/segments: + post: + operationId: PostNetworkSegments + description: | + Declare a segment of a network: an address range whose responsible groups + may allocate its addresses. Requires the NetworkManager privilege and, unless + the caller is a manager, membership of the network's responsible team. The + range must lie inside the network and must not overlap another segment of it + (409). The caller's primary group becomes responsible for the segment. + parameters: + - in: path + name: net_id + required: true + description: Record id of the network + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - seg_begin + - seg_end + properties: + seg_type: + type: string + enum: [static, dynamic] + default: static + description: How the addresses of the segment are allocated + seg_begin: + type: string + description: First IPv4 address of the segment + seg_end: + type: string + description: Last IPv4 address of the segment + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/NetworkSegmentListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 409: + $ref: '#/components/responses/409' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + /nodes: post: operationId: PostNodes @@ -14294,6 +14389,36 @@ components: type: array items: $ref: '#/components/schemas/NetworkRow' + meta: + $ref: '#/components/schemas/ListMeta' + info: + type: string + + NetworkSegmentRow: + type: object + description: An address range of a network, delegated to its responsible groups. + properties: + id: + type: integer + net_id: + type: integer + seg_type: + type: string + enum: [static, dynamic] + seg_begin: + type: string + seg_end: + type: string + + NetworkSegmentListResponse: + type: object + required: + - data + properties: + data: + type: array + items: + $ref: '#/components/schemas/NetworkSegmentRow' info: type: string diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index 5c1872e1..22a403e9 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -633,9 +633,15 @@ type ServerInterface interface { // (GET /logs/{log_id}) GetLog(ctx echo.Context, logId string, params GetLogParams) error + // (GET /networks) + GetNetworks(ctx echo.Context, params GetNetworksParams) error + // (POST /networks) PostNetworks(ctx echo.Context) error + // (POST /networks/{net_id}/segments) + PostNetworkSegments(ctx echo.Context, netId string) error + // (DELETE /nodes) DeleteNodes(ctx echo.Context) error @@ -8394,6 +8400,77 @@ func (w *ServerInterfaceWrapper) GetLog(ctx echo.Context) error { return err } +// GetNetworks converts echo context to params. +func (w *ServerInterfaceWrapper) GetNetworks(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetNetworksParams + // ------------- Optional query parameter "props" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "props", ctx.QueryParams(), ¶ms.Props, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter props: %s", err)) + } + + // ------------- Optional query parameter "limit" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) + } + + // ------------- Optional query parameter "offset" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "offset", ctx.QueryParams(), ¶ms.Offset, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter offset: %s", err)) + } + + // ------------- Optional query parameter "meta" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "meta", ctx.QueryParams(), ¶ms.Meta, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter meta: %s", err)) + } + + // ------------- Optional query parameter "stats" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "stats", ctx.QueryParams(), ¶ms.Stats, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter stats: %s", err)) + } + + // ------------- Optional query parameter "orderby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "orderby", ctx.QueryParams(), ¶ms.Orderby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) + } + + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + + // ------------- Optional query parameter "groupby" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetNetworks(ctx, params) + return err +} + // PostNetworks converts echo context to params. func (w *ServerInterfaceWrapper) PostNetworks(ctx echo.Context) error { var err error @@ -8407,6 +8484,26 @@ func (w *ServerInterfaceWrapper) PostNetworks(ctx echo.Context) error { return err } +// PostNetworkSegments converts echo context to params. +func (w *ServerInterfaceWrapper) PostNetworkSegments(ctx echo.Context) error { + var err error + // ------------- Path parameter "net_id" ------------- + var netId string + + err = runtime.BindStyledParameterWithOptions("simple", "net_id", ctx.Param("net_id"), &netId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter net_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostNetworkSegments(ctx, netId) + return err +} + // DeleteNodes converts echo context to params. func (w *ServerInterfaceWrapper) DeleteNodes(ctx echo.Context) error { var err error @@ -13660,7 +13757,9 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.GET(options.BaseURL+"/logs", wrapper.GetLogs, options.OperationMiddlewares["GetLogs"]...) router.POST(options.BaseURL+"/logs", wrapper.PostLogs, options.OperationMiddlewares["PostLogs"]...) router.GET(options.BaseURL+"/logs/:log_id", wrapper.GetLog, options.OperationMiddlewares["GetLog"]...) + router.GET(options.BaseURL+"/networks", wrapper.GetNetworks, options.OperationMiddlewares["GetNetworks"]...) router.POST(options.BaseURL+"/networks", wrapper.PostNetworks, options.OperationMiddlewares["PostNetworks"]...) + router.POST(options.BaseURL+"/networks/:net_id/segments", wrapper.PostNetworkSegments, options.OperationMiddlewares["PostNetworkSegments"]...) router.DELETE(options.BaseURL+"/nodes", wrapper.DeleteNodes, options.OperationMiddlewares["DeleteNodes"]...) router.GET(options.BaseURL+"/nodes", wrapper.GetNodes, options.OperationMiddlewares["GetNodes"]...) router.POST(options.BaseURL+"/nodes", wrapper.PostNodes, options.OperationMiddlewares["PostNodes"]...) @@ -13773,444 +13872,451 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "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", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index 6d6544b8..6f1a3088 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -14,6 +14,24 @@ const ( BearerAuthScopes bearerAuthContextKey = "bearerAuth.Scopes" ) +// Defines values for NetworkSegmentRowSegType. +const ( + NetworkSegmentRowSegTypeDynamic NetworkSegmentRowSegType = "dynamic" + NetworkSegmentRowSegTypeStatic NetworkSegmentRowSegType = "static" +) + +// Valid indicates whether the value is a known member of the NetworkSegmentRowSegType enum. +func (e NetworkSegmentRowSegType) Valid() bool { + switch e { + case NetworkSegmentRowSegTypeDynamic: + return true + case NetworkSegmentRowSegTypeStatic: + return true + default: + return false + } +} + // Defines values for ObsolescenceSettingRowObsType. const ( Hw ObsolescenceSettingRowObsType = "hw" @@ -314,6 +332,24 @@ func (e PostFiltersetsFiltersetsJSONBodyFLogOp) Valid() bool { } } +// Defines values for PostNetworkSegmentsJSONBodySegType. +const ( + PostNetworkSegmentsJSONBodySegTypeDynamic PostNetworkSegmentsJSONBodySegType = "dynamic" + PostNetworkSegmentsJSONBodySegTypeStatic PostNetworkSegmentsJSONBodySegType = "static" +) + +// Valid indicates whether the value is a known member of the PostNetworkSegmentsJSONBodySegType enum. +func (e PostNetworkSegmentsJSONBodySegType) Valid() bool { + switch e { + case PostNetworkSegmentsJSONBodySegTypeDynamic: + return true + case PostNetworkSegmentsJSONBodySegTypeStatic: + return true + default: + return false + } +} + // Defines values for PostNodesJSONBodyActionType. const ( PostNodesJSONBodyActionTypePull PostNodesJSONBodyActionType = "pull" @@ -1157,6 +1193,7 @@ type ModulesetsModuleRow struct { type NetworkListResponse struct { Data []NetworkRow `json:"data"` Info *string `json:"info,omitempty"` + Meta *ListMeta `json:"meta,omitempty"` } // NetworkRow A declared network. `begin`, `end` and `broadcast` are computed from @@ -1177,6 +1214,24 @@ type NetworkRow struct { Updated *string `json:"updated,omitempty"` } +// NetworkSegmentListResponse defines model for NetworkSegmentListResponse. +type NetworkSegmentListResponse struct { + Data []NetworkSegmentRow `json:"data"` + Info *string `json:"info,omitempty"` +} + +// NetworkSegmentRow An address range of a network, delegated to its responsible groups. +type NetworkSegmentRow struct { + Id *int `json:"id,omitempty"` + NetId *int `json:"net_id,omitempty"` + SegBegin *string `json:"seg_begin,omitempty"` + SegEnd *string `json:"seg_end,omitempty"` + SegType *NetworkSegmentRowSegType `json:"seg_type,omitempty"` +} + +// NetworkSegmentRowSegType defines model for NetworkSegmentRow.SegType. +type NetworkSegmentRowSegType string + // NodeHardwareListResponse defines model for NodeHardwareListResponse. type NodeHardwareListResponse struct { Data NodeHardwareListResponse_Data `json:"data"` @@ -4684,6 +4739,46 @@ type GetLogParams struct { Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` } +// GetNetworksParams defines parameters for GetNetworks. +type GetNetworksParams struct { + // Props A list of properties to include in each data dictionnary. + Props *InQueryProps `form:"props,omitempty" json:"props,omitempty"` + + // Limit The maximum number of entries to return. 0 means no limit. + Limit *InQueryLimit `form:"limit,omitempty" json:"limit,omitempty"` + + // Offset Skip the first entries of the data cursor. + Offset *InQueryOffset `form:"offset,omitempty" json:"offset,omitempty"` + + // Meta Include metadata in the response. Enabled by default. Use false or 0 to omit + // the meta field. The metadata of a list carries its total number of rows + // without pagination (total), as well as the rows returned (count), the offset + // and the limit. + Meta *InQueryMeta `form:"meta,omitempty" json:"meta,omitempty"` + + // Stats Controls the inclusion in the returned dictionnary of a "stats" key, containing the selected properties distinct values counts. + Stats *InQueryStats `form:"stats,omitempty" json:"stats,omitempty"` + + // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). + Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` + + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). + Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` +} + // PostNetworksJSONBody defines parameters for PostNetworks. type PostNetworksJSONBody struct { Comment *string `json:"comment,omitempty"` @@ -4708,6 +4803,21 @@ type PostNetworksJSONBody struct { TeamResponsible *string `json:"team_responsible,omitempty"` } +// PostNetworkSegmentsJSONBody defines parameters for PostNetworkSegments. +type PostNetworkSegmentsJSONBody struct { + // SegBegin First IPv4 address of the segment + SegBegin string `json:"seg_begin"` + + // SegEnd Last IPv4 address of the segment + SegEnd string `json:"seg_end"` + + // SegType How the addresses of the segment are allocated + SegType *PostNetworkSegmentsJSONBodySegType `json:"seg_type,omitempty"` +} + +// PostNetworkSegmentsJSONBodySegType defines parameters for PostNetworkSegments. +type PostNetworkSegmentsJSONBodySegType string + // DeleteNodesJSONBody defines parameters for DeleteNodes. type DeleteNodesJSONBody struct { // NodeId Node identifier (node_id or nodename) @@ -6984,6 +7094,9 @@ type PostLogsJSONRequestBody PostLogsJSONBody // PostNetworksJSONRequestBody defines body for PostNetworks for application/json ContentType. type PostNetworksJSONRequestBody PostNetworksJSONBody +// PostNetworkSegmentsJSONRequestBody defines body for PostNetworkSegments for application/json ContentType. +type PostNetworkSegmentsJSONRequestBody PostNetworkSegmentsJSONBody + // DeleteNodesJSONRequestBody defines body for DeleteNodes for application/json ContentType. type DeleteNodesJSONRequestBody DeleteNodesJSONBody diff --git a/server/handlers/network_segments.go b/server/handlers/network_segments.go new file mode 100644 index 00000000..6d8d9ea2 --- /dev/null +++ b/server/handlers/network_segments.go @@ -0,0 +1,152 @@ +package serverhandlers + +import ( + "context" + "fmt" + "net/http" + "net/netip" + "slices" + "strconv" + "strings" + + "github.com/labstack/echo/v4" + + "github.com/opensvc/oc3/cdb" + "github.com/opensvc/oc3/server" + "github.com/opensvc/oc3/util/echolog" + "github.com/opensvc/oc3/util/logkey" +) + +// GetNetworks handles GET /networks: the declared networks. +func (a *Api) GetNetworks(c echo.Context, params server.GetNetworksParams) error { + return a.handleList(c, "GetNetworks", "network", + listParams(params.Props, params.Limit, params.Offset, params.Meta, params.Stats, params.Orderby, params.Groupby, params.Filter), + func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetNetworks(ctx, p) + }) +} + +// PostNetworkSegments handles POST /networks/{net_id}/segments: declare an +// address range of a network, as the historical collector's +// rest_post_network_segments did. The caller's primary group becomes +// responsible for the segment. +func (a *Api) PostNetworkSegments(c echo.Context, netId string) error { + log := echolog.GetLogHandler(c, "PostNetworkSegments") + odb := a.ODB + ctx, cancel := context.WithTimeout(c.Request().Context(), a.SyncTimeout) + defer cancel() + + if err := requireNetworkManager(c); err != nil { + return err + } + netID, err := strconv.Atoi(netId) + if err != nil { + return JSONProblemf(c, http.StatusBadRequest, "network id must be an integer, got %q", netId) + } + + var body server.PostNetworkSegmentsJSONRequestBody + if err := c.Bind(&body); err != nil { + log.Error("invalid request body", logkey.Error, err) + return JSONProblem(c, http.StatusBadRequest, err.Error()) + } + + network, found, err := odb.GetNetworkRange(ctx, netID) + if err != nil { + log.Error("cannot read network", logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot read network") + } + if !found { + return JSONProblemf(c, http.StatusNotFound, "network %d not found", netID) + } + // Only the team responsible for the network carves it up, or a manager. + if !IsManager(c) && !slices.Contains(UserGroupsFromContext(c), network.TeamResponsible) { + return JSONProblemf(c, http.StatusForbidden, "not responsible for network %d", netID) + } + + segType := "static" + if body.SegType != nil && *body.SegType != "" { + segType = string(*body.SegType) + } + if segType != "static" && segType != "dynamic" { + return JSONProblemf(c, http.StatusBadRequest, "seg_type must be static or dynamic, got %q", segType) + } + + // The overlap check compares addresses with INET_ATON: IPv4 only, like networks. + netBegin, errB := netip.ParseAddr(network.Begin) + netEnd, errE := netip.ParseAddr(network.End) + if errB != nil || errE != nil { + return JSONProblemf(c, http.StatusConflict, "network %d has no usable range", netID) + } + parse := func(name, value string) (netip.Addr, error) { + addr, err := netip.ParseAddr(strings.TrimSpace(value)) + if err != nil || !addr.Is4() { + return addr, fmt.Errorf("%s must be an IPv4 address, got %q", name, value) + } + if addr.Less(netBegin) || netEnd.Less(addr) { + return addr, fmt.Errorf("%s %s is outside the network range %s - %s", name, addr, netBegin, netEnd) + } + return addr, nil + } + begin, err := parse("seg_begin", body.SegBegin) + if err != nil { + return JSONProblem(c, http.StatusBadRequest, err.Error()) + } + end, err := parse("seg_end", body.SegEnd) + if err != nil { + return JSONProblem(c, http.StatusBadRequest, err.Error()) + } + if end.Less(begin) { + return JSONProblemf(c, http.StatusBadRequest, "seg_end %s is before seg_begin %s", end, begin) + } + + otherID, taken, err := odb.NetworkSegmentOverlapping(ctx, netID, begin.String(), end.String()) + if err != nil { + log.Error("cannot check segment overlap", logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot check segment overlap") + } + if taken { + return JSONProblemf(c, http.StatusConflict, "range %s - %s overlaps segment %d", begin, end, otherID) + } + + var groupID *int64 + if userID := authUserID(c); userID != nil { + id, found, err := odb.UserPrimaryGroupID(ctx, *userID) + if err != nil { + log.Error("cannot get primary group", logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot get primary group") + } + if found { + groupID = &id + } + } + + prefix := fmt.Sprintf("%s/%d", network.Network, network.Netmask) + log.Info("called", "network", prefix, "begin", begin.String(), "end", end.String()) + + id, err := odb.InsertNetworkSegment(ctx, netID, segType, begin.String(), end.String(), groupID) + if err != nil { + log.Error("cannot create segment", logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot create segment") + } + + userEmail, _ := c.Get(XUserEmail).(string) + if logErr := odb.Log(ctx, cdb.LogEntry{ + Action: "networks.segment.create", + User: userEmail, + Fmt: "created %(type)s segment %(begin)s-%(end)s of network %(network)s", + Dict: map[string]any{"type": segType, "begin": begin.String(), "end": end.String(), "network": prefix}, + Level: "info", + }); logErr != nil { + log.Error("cannot write audit log", logkey.Error, logErr) + } + if err := odb.Session.NotifyChanges(ctx); err != nil { + log.Error("cannot notify changes", logkey.Error, err) + } + + row, err := odb.GetNetworkSegmentRow(ctx, id) + if err != nil || row == nil { + log.Error("cannot read the created segment", "id", id, logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "segment %d created but cannot be read back", id) + } + return c.JSON(http.StatusOK, map[string]any{"data": []any{row}, "info": fmt.Sprintf("segment %d created", id)}) +} diff --git a/server/handlers/props_mapping.go b/server/handlers/props_mapping.go index e3e039c8..6aca7709 100644 --- a/server/handlers/props_mapping.go +++ b/server/handlers/props_mapping.go @@ -792,6 +792,29 @@ var propsMapping = map[string]propMapping{ "teams_publication": colStr(cdb.ModsetPublications), }, }, + // Declared networks. begin, end and broadcast are generated by the database + // from network and netmask. + "network": { + Available: []string{ + "id", "name", "network", "netmask", "broadcast", "gateway", "begin", "end", + "pvid", "prio", "team_responsible", "comment", "updated", + }, + Props: map[string]propDef{ + "id": colInt(schema.NetworksID), + "name": colStr(schema.NetworksName), + "network": colStr(schema.NetworksNetwork), + "netmask": colInt(schema.NetworksNetmask), + "broadcast": colStr(schema.NetworksBroadcast), + "gateway": colStr(schema.NetworksGateway), + "begin": colStr(schema.NetworksBegin), + "end": colStr(schema.NetworksEnd), + "pvid": colInt(schema.NetworksPvid), + "prio": colInt(schema.NetworksPrio), + "team_responsible": colStr(schema.NetworksTeamResponsible), + "comment": colStr(schema.NetworksComment), + "updated": colStr(schema.NetworksUpdated), + }, + }, // Variables of every ruleset, as the historical v_comp_rulesets view: a // ruleset lists its own variables, then those of each ruleset it // encapsulates; a ruleset of the chain without variable has a row with a zero From 28c8329279013cfed7e7d32dc316d510d5c5e73f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Tue, 29 Sep 2026 15:37:21 +0200 Subject: [PATCH 55/61] Let the list of node addresses be sorted and filtered Each prop of the node_ip mapping keeps its expression and now names the v_nodenetworks column it reads, so orderby, groupby and filter accept them. GET /ips declares the filter parameter and applies its conditions. --- cdb/db_ips.go | 16 ++ server/api.yaml | 1 + server/codegen_server_gen.go | 247 ++++++++++++++++--------------- server/codegen_type_gen.go | 13 ++ server/handlers/get_ips.go | 11 +- server/handlers/props_mapping.go | 46 +++--- 6 files changed, 186 insertions(+), 148 deletions(-) diff --git a/cdb/db_ips.go b/cdb/db_ips.go index f03d7065..666d1772 100644 --- a/cdb/db_ips.go +++ b/cdb/db_ips.go @@ -6,8 +6,20 @@ import ( "errors" "fmt" "strings" + + "github.com/opensvc/oc3/schema" ) +// TNodeNetworks is the v_nodenetworks view: the addresses of the nodes, joined to +// the declared network each one belongs to. +var TNodeNetworks = &schema.Table{Name: "v_nodenetworks"} + +// NodeNetworksCol returns a column of the v_nodenetworks view, for the list +// props that sort and filter on it. +func NodeNetworksCol(name string) *schema.Col { + return &schema.Col{T: TNodeNetworks, Name: name, Nullable: true} +} + type NodeIP struct { ID int64 Addr string @@ -76,6 +88,10 @@ func buildIpsQuery(p ListParams, idCond string, idArgs []any) (string, []any, er } } + filterConds, filterArgs := p.FilterConditions() + conds = append(conds, filterConds...) + args = append(args, filterArgs...) + if len(conds) > 0 { sb.WriteString("\nWHERE " + strings.Join(conds, " AND ")) } diff --git a/server/api.yaml b/server/api.yaml index 22bc12d7..abee70dc 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -4369,6 +4369,7 @@ paths: - $ref: '#/components/parameters/inQueryMeta' - $ref: '#/components/parameters/inQueryStats' - $ref: '#/components/parameters/inQueryOrderby' + - $ref: '#/components/parameters/inQueryFilter' - $ref: '#/components/parameters/inQueryGroupby' tags: - collector diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index 22a403e9..81a01f9e 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -8142,6 +8142,13 @@ func (w *ServerInterfaceWrapper) GetIps(ctx echo.Context) error { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter orderby: %s", err)) } + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + // ------------- Optional query parameter "groupby" ------------- err = runtime.BindQueryParameterWithOptions("form", true, false, "groupby", ctx.QueryParams(), ¶ms.Groupby, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) @@ -14197,126 +14204,126 @@ var swaggerSpec = []string{ "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", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index 6f1a3088..edace25b 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -4642,6 +4642,19 @@ type GetIpsParams struct { // Orderby Comma-separated list of properties to sort by. Prefix a property with - for descending order (e.g. orderby=nodename,-app). Orderby *InQueryOrderby `form:"orderby,omitempty" json:"orderby,omitempty"` + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` + // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` } diff --git a/server/handlers/get_ips.go b/server/handlers/get_ips.go index 240e8cb4..4d60709c 100644 --- a/server/handlers/get_ips.go +++ b/server/handlers/get_ips.go @@ -11,10 +11,9 @@ import ( // GetIps handles GET /ips func (a *Api) GetIps(c echo.Context, params server.GetIpsParams) error { - return a.handleList(c, "GetIps", "node_ip", listEndpointParams{ - props: params.Props, limit: params.Limit, offset: params.Offset, - meta: params.Meta, stats: params.Stats, orderby: params.Orderby, groupby: params.Groupby, - }, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { - return a.ODB.GetIps(ctx, p) - }) + return a.handleList(c, "GetIps", "node_ip", + listParams(params.Props, params.Limit, params.Offset, params.Meta, params.Stats, params.Orderby, params.Groupby, params.Filter), + func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetIps(ctx, p) + }) } diff --git a/server/handlers/props_mapping.go b/server/handlers/props_mapping.go index 6aca7709..d9a81ef2 100644 --- a/server/handlers/props_mapping.go +++ b/server/handlers/props_mapping.go @@ -251,6 +251,8 @@ var propsMapping = map[string]propMapping{ "app_id": {SQLExpr: "COALESCE(app_id, 0) AS app_id", Kind: "int64"}, }, }, + // Addresses of the nodes, read from the v_nodenetworks view. Each prop keeps + // its expression and names the view column it reads, for sorting and filtering. "node_ip": { Available: []string{ "id", "node_id", "nodename", "intf", "mac", "type", "addr", "mask", "updated", "flag_deprecated", @@ -259,28 +261,28 @@ var propsMapping = map[string]propMapping{ }, Default: []string{"node_id", "intf", "addr", "mask", "net_name", "net_network", "net_netmask", "net_gateway"}, Props: map[string]propDef{ - "id": {SQLExpr: "id", Kind: "int64"}, - "node_id": {SQLExpr: "COALESCE(node_id, '') AS node_id", Kind: "string"}, - "nodename": {SQLExpr: "COALESCE(nodename, '') AS nodename", Kind: "string"}, - "intf": {SQLExpr: "COALESCE(intf, '') AS intf", Kind: "string"}, - "mac": {SQLExpr: "COALESCE(mac, '') AS mac", Kind: "string"}, - "type": {SQLExpr: "COALESCE(addr_type, '') AS type", Kind: "string"}, - "addr": {SQLExpr: "COALESCE(addr, '') AS addr", Kind: "string"}, - "mask": {SQLExpr: "COALESCE(mask, '') AS mask", Kind: "string"}, - "updated": {SQLExpr: "COALESCE(addr_updated, '') AS updated", Kind: "string"}, - "flag_deprecated": {SQLExpr: "COALESCE(flag_deprecated, 0) AS flag_deprecated", Kind: "int64"}, - "net_id": {SQLExpr: "net_id", Kind: "int64"}, - "net_name": {SQLExpr: "COALESCE(net_name, '') AS net_name", Kind: "string"}, - "net_network": {SQLExpr: "COALESCE(net_network, '') AS net_network", Kind: "string"}, - "net_netmask": {SQLExpr: "COALESCE(net_netmask, '') AS net_netmask", Kind: "string"}, - "net_broadcast": {SQLExpr: "COALESCE(net_broadcast, '') AS net_broadcast", Kind: "string"}, - "net_gateway": {SQLExpr: "COALESCE(net_gateway, '') AS net_gateway", Kind: "string"}, - "net_begin": {SQLExpr: "COALESCE(net_begin, '') AS net_begin", Kind: "string"}, - "net_end": {SQLExpr: "COALESCE(net_end, '') AS net_end", Kind: "string"}, - "net_pvid": {SQLExpr: "COALESCE(net_pvid, '') AS net_pvid", Kind: "string"}, - "net_prio": {SQLExpr: "COALESCE(prio, 0) AS net_prio", Kind: "int64"}, - "net_comment": {SQLExpr: "COALESCE(net_comment, '') AS net_comment", Kind: "string"}, - "net_team_responsible": {SQLExpr: "COALESCE(net_team_responsible, '') AS net_team_responsible", Kind: "string"}, + "id": {Col: cdb.NodeNetworksCol("id"), SQLExpr: "id", Kind: "int64"}, + "node_id": {Col: cdb.NodeNetworksCol("node_id"), SQLExpr: "COALESCE(node_id, '') AS node_id", Kind: "string"}, + "nodename": {Col: cdb.NodeNetworksCol("nodename"), SQLExpr: "COALESCE(nodename, '') AS nodename", Kind: "string"}, + "intf": {Col: cdb.NodeNetworksCol("intf"), SQLExpr: "COALESCE(intf, '') AS intf", Kind: "string"}, + "mac": {Col: cdb.NodeNetworksCol("mac"), SQLExpr: "COALESCE(mac, '') AS mac", Kind: "string"}, + "type": {Col: cdb.NodeNetworksCol("addr_type"), SQLExpr: "COALESCE(addr_type, '') AS type", Kind: "string"}, + "addr": {Col: cdb.NodeNetworksCol("addr"), SQLExpr: "COALESCE(addr, '') AS addr", Kind: "string"}, + "mask": {Col: cdb.NodeNetworksCol("mask"), SQLExpr: "COALESCE(mask, '') AS mask", Kind: "string"}, + "updated": {Col: cdb.NodeNetworksCol("addr_updated"), SQLExpr: "COALESCE(addr_updated, '') AS updated", Kind: "string"}, + "flag_deprecated": {Col: cdb.NodeNetworksCol("flag_deprecated"), SQLExpr: "COALESCE(flag_deprecated, 0) AS flag_deprecated", Kind: "int64"}, + "net_id": {Col: cdb.NodeNetworksCol("net_id"), SQLExpr: "net_id", Kind: "int64"}, + "net_name": {Col: cdb.NodeNetworksCol("net_name"), SQLExpr: "COALESCE(net_name, '') AS net_name", Kind: "string"}, + "net_network": {Col: cdb.NodeNetworksCol("net_network"), SQLExpr: "COALESCE(net_network, '') AS net_network", Kind: "string"}, + "net_netmask": {Col: cdb.NodeNetworksCol("net_netmask"), SQLExpr: "COALESCE(net_netmask, '') AS net_netmask", Kind: "string"}, + "net_broadcast": {Col: cdb.NodeNetworksCol("net_broadcast"), SQLExpr: "COALESCE(net_broadcast, '') AS net_broadcast", Kind: "string"}, + "net_gateway": {Col: cdb.NodeNetworksCol("net_gateway"), SQLExpr: "COALESCE(net_gateway, '') AS net_gateway", Kind: "string"}, + "net_begin": {Col: cdb.NodeNetworksCol("net_begin"), SQLExpr: "COALESCE(net_begin, '') AS net_begin", Kind: "string"}, + "net_end": {Col: cdb.NodeNetworksCol("net_end"), SQLExpr: "COALESCE(net_end, '') AS net_end", Kind: "string"}, + "net_pvid": {Col: cdb.NodeNetworksCol("net_pvid"), SQLExpr: "COALESCE(net_pvid, '') AS net_pvid", Kind: "string"}, + "net_prio": {Col: cdb.NodeNetworksCol("prio"), SQLExpr: "COALESCE(prio, 0) AS net_prio", Kind: "int64"}, + "net_comment": {Col: cdb.NodeNetworksCol("net_comment"), SQLExpr: "COALESCE(net_comment, '') AS net_comment", Kind: "string"}, + "net_team_responsible": {Col: cdb.NodeNetworksCol("net_team_responsible"), SQLExpr: "COALESCE(net_team_responsible, '') AS net_team_responsible", Kind: "string"}, }, }, "node_interface": { From 4be4c58338c30239e2aa01a88449355ce0362c0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Tue, 29 Sep 2026 15:43:36 +0200 Subject: [PATCH 56/61] Require 12 characters for a password change POST /users/self/password refuses a new password shorter than 12 characters, counted in characters rather than bytes. User creation keeps its own minimum. --- server/api.yaml | 5 ++-- server/codegen_server_gen.go | 41 ++++++++++++++------------- server/codegen_type_gen.go | 2 +- server/handlers/post_user_password.go | 16 +++++++---- 4 files changed, 36 insertions(+), 28 deletions(-) diff --git a/server/api.yaml b/server/api.yaml index abee70dc..324a8007 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -8701,7 +8701,7 @@ paths: operationId: PostUserSelfPassword description: | Change the password of the signed-in user, who gives the current one. The new - password must be at least 8 characters long and differ from the current one; + password must be at least 12 characters long and differ from the current one; it is stored as a web2py hash, accepted by both collectors. The change is logged, without the password. Requires user authentication, no privilege. requestBody: @@ -8716,7 +8716,8 @@ paths: type: string new_password: type: string - description: At least 8 characters. + minLength: 12 + description: At least 12 characters. tags: - collector responses: diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index 81a01f9e..5f29d6e7 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -14304,26 +14304,27 @@ var swaggerSpec = []string{ "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", + "//8=", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index edace25b..304cd55f 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -6788,7 +6788,7 @@ type PostUsersJSONBody struct { type PostUserSelfPasswordJSONBody struct { CurrentPassword string `json:"current_password"` - // NewPassword At least 8 characters. + // NewPassword At least 12 characters. NewPassword string `json:"new_password"` } diff --git a/server/handlers/post_user_password.go b/server/handlers/post_user_password.go index ae6c4984..e9cf1051 100644 --- a/server/handlers/post_user_password.go +++ b/server/handlers/post_user_password.go @@ -3,6 +3,7 @@ package serverhandlers import ( "context" "net/http" + "unicode/utf8" "github.com/labstack/echo/v4" "github.com/spf13/viper" @@ -14,11 +15,16 @@ import ( "github.com/opensvc/oc3/xauth" ) +// minResetPasswordLength is the shortest password accepted when a user changes +// their own, counted in characters rather than bytes. It is stricter than the +// length required at user creation. +const minResetPasswordLength = 12 + // PostUserSelfPassword handles POST /users/self/password: the caller changes // their own password, proving they know the current one, as the change_password -// form of the historical collector does. The new one is held to the length the -// user creation requires, and stored as a web2py hash, so that both collectors -// accept it. The change is logged, without the password. +// form of the historical collector does. The new one must be at least +// minResetPasswordLength characters long, and is stored as a web2py hash, so +// that both collectors accept it. The change is logged, without the password. func (a *Api) PostUserSelfPassword(c echo.Context) error { log := echolog.GetLogHandler(c, "PostUserSelfPassword") ctx, cancel := context.WithTimeout(c.Request().Context(), a.SyncTimeout) @@ -36,8 +42,8 @@ func (a *Api) PostUserSelfPassword(c echo.Context) error { if err := c.Bind(&body); err != nil { return JSONProblem(c, http.StatusBadRequest, err.Error()) } - if len(body.NewPassword) < minPasswordLength { - return JSONProblemf(c, http.StatusBadRequest, "the new password must be at least %d characters long", minPasswordLength) + if utf8.RuneCountInString(body.NewPassword) < minResetPasswordLength { + return JSONProblemf(c, http.StatusBadRequest, "the new password must be at least %d characters long", minResetPasswordLength) } if body.NewPassword == body.CurrentPassword { return JSONProblemf(c, http.StatusBadRequest, "the new password must differ from the current one") From d6c587e6b75e30d65bb02d09d65e03f54cbd19a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Tue, 29 Sep 2026 16:46:58 +0200 Subject: [PATCH 57/61] Add a global search and filters to five lists GET /search looks for the text in 14 kinds of objects, as the historical collector's search did: nodes, services, instances, applications, node addresses, disks, tags, users, teams, requests, modulesets, rulesets, filtersets and forms. Each kind is read through its own list and access control, with a case-insensitive "contains" match on its identifying props, all kinds at once. A request also matches by its number, private user groups are left out of the teams. Groups come with more set when other objects match beyond the limit, and a kind that fails reports it without failing the others. The Apps, Disks, Users, Groups and Filtersets lists now apply the column filters they were given and declare the filter parameter. --- cdb/db_apps.go | 9 +- cdb/db_auth_group.go | 5 + cdb/db_disks.go | 11 +- cdb/db_filtersets.go | 5 +- cdb/db_search.go | 27 + cdb/db_users.go | 6 +- server/api.yaml | 105 ++++ server/codegen_server_gen.go | 983 ++++++++++++++++-------------- server/codegen_type_gen.go | 166 +++++ server/handlers/get_apps.go | 1 + server/handlers/get_disks.go | 1 + server/handlers/get_filtersets.go | 1 + server/handlers/get_groups.go | 1 + server/handlers/get_users.go | 1 + server/handlers/search.go | 325 ++++++++++ 15 files changed, 1192 insertions(+), 455 deletions(-) create mode 100644 cdb/db_search.go create mode 100644 server/handlers/search.go diff --git a/cdb/db_apps.go b/cdb/db_apps.go index 8010d39e..4da766c7 100644 --- a/cdb/db_apps.go +++ b/cdb/db_apps.go @@ -62,7 +62,7 @@ func scanApps(rows *sql.Rows) ([]App, error) { return apps, nil } -func buildAppsQuery(groups []string, isManager bool, selectExprs []string) (string, []any, error) { +func buildAppsQuery(groups []string, isManager bool, selectExprs []string, filters []ColumnFilter) (string, []any, error) { q := From(schema.TApps). Distinct(). RawSelect(selectExprs...) @@ -75,6 +75,9 @@ func buildAppsQuery(groups []string, isManager bool, selectExprs []string) (stri q = q.Where(schema.AppsID, ">", 0) } + // Column filters of the request, ANDed with the access control above. + q = q.WhereFilters(filters) + query, args, err := q.Build() if err != nil { return "", nil, fmt.Errorf("buildAppsQuery: %w", err) @@ -87,11 +90,11 @@ func buildAppsQueryAll(groups []string, isManager bool) (string, []any, error) { "apps.id", "apps.app", "COALESCE(apps.updated, '')", "COALESCE(apps.app_domain, '')", "COALESCE(apps.app_team_ops, '')", "COALESCE(apps.description, '')", - }) + }, nil) } func (oDb *DB) GetApps(ctx context.Context, p ListParams) ([]map[string]any, error) { - query, args, err := buildAppsQuery(p.Groups, p.IsManager, p.SelectExprs) + query, args, err := buildAppsQuery(p.Groups, p.IsManager, p.SelectExprs, p.Filters) if err != nil { return nil, err } diff --git a/cdb/db_auth_group.go b/cdb/db_auth_group.go index 3c603d0c..9fecaad9 100644 --- a/cdb/db_auth_group.go +++ b/cdb/db_auth_group.go @@ -26,6 +26,11 @@ func (oDb *DB) GetGroups(ctx context.Context, p ListParams) ([]map[string]any, e args = append(args, stringsToAny(cleanG)...) } } + filterConds, filterArgs := p.FilterConditions() + for _, cond := range filterConds { + query += " AND " + cond + } + args = append(args, filterArgs...) if gb := p.GroupByClause(""); gb != "" { query += " " + gb } diff --git a/cdb/db_disks.go b/cdb/db_disks.go index 3d534c25..877d1117 100644 --- a/cdb/db_disks.go +++ b/cdb/db_disks.go @@ -7,7 +7,7 @@ import ( "github.com/opensvc/oc3/schema" ) -func buildDisksQuery(groups []string, isManager bool, selectExprs []string) (string, []any, error) { +func buildDisksQuery(groups []string, isManager bool, selectExprs []string, filters []ColumnFilter) (string, []any, error) { q := From(schema.TDiskinfo). LeftJoin(schema.TSvcdisks, schema.TNodes, schema.TServices, schema.TApps). RawSelect(selectExprs...) @@ -37,6 +37,9 @@ func buildDisksQuery(groups []string, isManager bool, selectExprs []string) (str q = q.Where(schema.DiskinfoID, ">", 0) } + // Column filters of the request, ANDed with the access control above. + q = q.WhereFilters(filters) + query, args, err := q.Build() if err != nil { return "", nil, fmt.Errorf("buildDisksQuery: %w", err) @@ -45,7 +48,7 @@ func buildDisksQuery(groups []string, isManager bool, selectExprs []string) (str } func (oDb *DB) GetDisk(ctx context.Context, diskID string, p ListParams) ([]map[string]any, error) { - query, args, err := buildDisksQuery(p.Groups, p.IsManager, p.SelectExprs) + query, args, err := buildDisksQuery(p.Groups, p.IsManager, p.SelectExprs, p.Filters) if err != nil { return nil, err } @@ -118,7 +121,7 @@ func (oDb *DB) GetServiceDisks(ctx context.Context, svcID string, p ListParams) } func (oDb *DB) GetNodeDisks(ctx context.Context, nodeID string, p ListParams) ([]map[string]any, error) { - query, args, err := buildDisksQuery(p.Groups, p.IsManager, p.SelectExprs) + query, args, err := buildDisksQuery(p.Groups, p.IsManager, p.SelectExprs, p.Filters) if err != nil { return nil, err } @@ -140,7 +143,7 @@ func (oDb *DB) GetNodeDisks(ctx context.Context, nodeID string, p ListParams) ([ } func (oDb *DB) GetDisks(ctx context.Context, p ListParams) ([]map[string]any, error) { - query, args, err := buildDisksQuery(p.Groups, p.IsManager, p.SelectExprs) + query, args, err := buildDisksQuery(p.Groups, p.IsManager, p.SelectExprs, p.Filters) if err != nil { return nil, err } diff --git a/cdb/db_filtersets.go b/cdb/db_filtersets.go index e714e44a..5097eef1 100644 --- a/cdb/db_filtersets.go +++ b/cdb/db_filtersets.go @@ -616,7 +616,10 @@ func (oDb *DB) GetFiltersets(ctx context.Context, p ListParams) ([]map[string]an } query := "SELECT " + strings.Join(p.SelectExprs, ", ") + " FROM gen_filtersets WHERE gen_filtersets.id > 0" - args := []any{} + filterConds, args := p.FilterConditions() + for _, cond := range filterConds { + query += " AND " + cond + } if gb := p.GroupByClause(""); gb != "" { query += " " + gb } diff --git a/cdb/db_search.go b/cdb/db_search.go new file mode 100644 index 00000000..1006b777 --- /dev/null +++ b/cdb/db_search.go @@ -0,0 +1,27 @@ +package cdb + +import ( + "context" + "fmt" +) + +// SearchTags returns the tags whose name contains the LIKE pattern, by name, up +// to limit rows. Tags are readable by every user, as in the historical search. +func (oDb *DB) SearchTags(ctx context.Context, pattern string, limit int) ([]map[string]any, error) { + rows, err := oDb.DB.QueryContext(ctx, + `SELECT COALESCE(tag_id, ''), COALESCE(tag_name, ''), COALESCE(tag_exclude, '') + FROM tags WHERE tag_name LIKE ? ORDER BY tag_name, id LIMIT ?`, pattern, limit) + if err != nil { + return nil, fmt.Errorf("searchTags: %w", err) + } + defer func() { _ = rows.Close() }() + var out []map[string]any + for rows.Next() { + var tagID, name, exclude string + if err := rows.Scan(&tagID, &name, &exclude); err != nil { + return nil, fmt.Errorf("searchTags scan: %w", err) + } + out = append(out, map[string]any{"tag_id": tagID, "tag_name": name, "tag_exclude": exclude}) + } + return out, rows.Err() +} diff --git a/cdb/db_users.go b/cdb/db_users.go index 03236b6e..b7cab321 100644 --- a/cdb/db_users.go +++ b/cdb/db_users.go @@ -49,8 +49,12 @@ func (oDb *DB) GetUsers(ctx context.Context, p ListParams) ([]map[string]any, er return nil, fmt.Errorf("getUsers: no select expressions") } authClause, args := usersAuthClause(p) + conds := []string{authClause} + filterConds, filterArgs := p.FilterConditions() + conds = append(conds, filterConds...) + args = append(args, filterArgs...) query := "SELECT " + strings.Join(p.SelectExprs, ", ") + - " FROM auth_user WHERE " + authClause + " FROM auth_user WHERE " + strings.Join(conds, " AND ") if gb := p.GroupByClause(""); gb != "" { query += " " + gb } diff --git a/server/api.yaml b/server/api.yaml index 324a8007..e7fab3fb 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -512,6 +512,7 @@ paths: - $ref: '#/components/parameters/inQueryStats' - $ref: '#/components/parameters/inQueryOrderby' - $ref: '#/components/parameters/inQueryGroupby' + - $ref: '#/components/parameters/inQueryFilter' tags: - collector responses: @@ -1435,6 +1436,7 @@ paths: - $ref: '#/components/parameters/inQueryStats' - $ref: '#/components/parameters/inQueryOrderby' - $ref: '#/components/parameters/inQueryGroupby' + - $ref: '#/components/parameters/inQueryFilter' tags: - collector responses: @@ -1815,6 +1817,7 @@ paths: - $ref: '#/components/parameters/inQueryStats' - $ref: '#/components/parameters/inQueryOrderby' - $ref: '#/components/parameters/inQueryGroupby' + - $ref: '#/components/parameters/inQueryFilter' tags: - collector responses: @@ -3768,6 +3771,7 @@ paths: - $ref: '#/components/parameters/inQueryStats' - $ref: '#/components/parameters/inQueryOrderby' - $ref: '#/components/parameters/inQueryGroupby' + - $ref: '#/components/parameters/inQueryFilter' tags: - collector responses: @@ -4613,6 +4617,59 @@ paths: - basicAuth: [ ] - bearerAuth: [ ] + /search: + get: + operationId: GetSearch + description: | + Search the main kinds of objects for the text, as the historical collector's + search: nodes, services, instances, applications, node addresses, disks, tags, + users, teams, requests, modulesets, rulesets, filtersets and forms. For each + kind, the objects whose name or another identifying prop contains the text, + case-insensitively, are read through the kind's own list and its access + control. A request also matches by its number. Groups come in that order, one + per kind, with `more` set when other objects match beyond `limit`. A kind that + cannot be searched reports it in its `error` without failing the others. A + text shorter than 2 characters returns no group. + parameters: + - in: query + name: q + required: true + description: The text to search for. + schema: + type: string + - in: query + name: kinds + description: | + Comma-separated kinds to search, all by default: node, service, instance, + app, network, disk, tag, user, group, request, moduleset, ruleset, + filterset, form. + schema: + type: string + - in: query + name: limit + description: Hits returned per kind, 5 by default, 20 at most. + schema: + type: integer + minimum: 1 + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/SearchResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + /networks: get: operationId: GetNetworks @@ -8630,6 +8687,7 @@ paths: - $ref: '#/components/parameters/inQueryStats' - $ref: '#/components/parameters/inQueryOrderby' - $ref: '#/components/parameters/inQueryGroupby' + - $ref: '#/components/parameters/inQueryFilter' tags: - collector responses: @@ -14396,6 +14454,53 @@ components: info: type: string + SearchGroup: + type: object + description: The objects of one kind matching a search. + required: + - kind + - items + - more + properties: + kind: + type: string + enum: [node, service, instance, app, network, disk, tag, user, group, request, moduleset, ruleset, filterset, form] + items: + type: array + description: | + One entry per object, with the props of its kind: node_id, nodename, app, + node_env, cluster_id, fqdn, os_name for a node; svc_id, svcname, svc_app, + svc_env, cluster_id, svc_availstatus, svc_topology for a service; svc_id, + node_id, mon_vmname, mon_availstatus, services.svcname, nodes.nodename for + an instance; id, app, app_domain, description for an application; id, addr, + mask, intf, node_id, nodename, net_name for a node address; disk_id, + disk_name, disk_size, disk_arrayid, nodename, svcname for a disk; tag_id, + tag_name, tag_exclude for a tag; id, email, first_name, last_name, username + for a user; id, role, privilege, description for a team; id, form_name, + last_form_name, status, creator, last_update for a request; id, + modset_name, modset_author for a moduleset; id, ruleset_name, ruleset_type, + ruleset_public for a ruleset; id, fset_name, fset_author for a filterset; + id, form_name, form_type, form_folder for a form. + items: + type: object + additionalProperties: true + more: + type: boolean + description: Other objects of the kind match beyond those returned. + error: + type: string + description: Set when the kind could not be searched. + + SearchResponse: + type: object + required: + - data + properties: + data: + type: array + items: + $ref: '#/components/schemas/SearchGroup' + NetworkSegmentRow: type: object description: An address range of a network, delegated to its responsible groups. diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index 5f29d6e7..cb5956cc 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -768,6 +768,9 @@ type ServerInterface interface { // (GET /packages/diff) GetPackagesDiff(ctx echo.Context, params GetPackagesDiffParams) error + // (GET /search) + GetSearch(ctx echo.Context, params GetSearchParams) error + // (DELETE /services) DeleteServices(ctx echo.Context) error @@ -1485,6 +1488,13 @@ func (w *ServerInterfaceWrapper) GetApps(ctx echo.Context) error { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + // Invoke the callback with all the unmarshaled arguments err = w.Handler.GetApps(ctx, params) return err @@ -5216,6 +5226,13 @@ func (w *ServerInterfaceWrapper) GetDisks(ctx echo.Context) error { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + // Invoke the callback with all the unmarshaled arguments err = w.Handler.GetDisks(ctx, params) return err @@ -5598,6 +5615,13 @@ func (w *ServerInterfaceWrapper) GetFiltersets(ctx echo.Context) error { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + // Invoke the callback with all the unmarshaled arguments err = w.Handler.GetFiltersets(ctx, params) return err @@ -7411,6 +7435,13 @@ func (w *ServerInterfaceWrapper) GetGroups(ctx echo.Context) error { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + // Invoke the callback with all the unmarshaled arguments err = w.Handler.GetGroups(ctx, params) return err @@ -10571,6 +10602,42 @@ func (w *ServerInterfaceWrapper) GetPackagesDiff(ctx echo.Context) error { return err } +// GetSearch converts echo context to params. +func (w *ServerInterfaceWrapper) GetSearch(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetSearchParams + // ------------- Required query parameter "q" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, true, "q", ctx.QueryParams(), ¶ms.Q, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter q: %s", err)) + } + + // ------------- Optional query parameter "kinds" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "kinds", ctx.QueryParams(), ¶ms.Kinds, runtime.BindQueryParameterOptions{Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter kinds: %s", err)) + } + + // ------------- Optional query parameter "limit" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "limit", ctx.QueryParams(), ¶ms.Limit, runtime.BindQueryParameterOptions{Type: "integer", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetSearch(ctx, params) + return err +} + // DeleteServices converts echo context to params. func (w *ServerInterfaceWrapper) DeleteServices(ctx echo.Context) error { var err error @@ -13284,6 +13351,13 @@ func (w *ServerInterfaceWrapper) GetUsers(ctx echo.Context) error { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter groupby: %s", err)) } + // ------------- Optional query parameter "filter" ------------- + + err = runtime.BindQueryParameterWithOptions("form", true, false, "filter", ctx.QueryParams(), ¶ms.Filter, runtime.BindQueryParameterOptions{Type: "array", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter filter: %s", err)) + } + // Invoke the callback with all the unmarshaled arguments err = w.Handler.GetUsers(ctx, params) return err @@ -13809,6 +13883,7 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.GET(options.BaseURL+"/openapi.json", wrapper.GetSwagger, options.OperationMiddlewares["GetSwagger"]...) router.GET(options.BaseURL+"/packages", wrapper.GetPackages, options.OperationMiddlewares["GetPackages"]...) router.GET(options.BaseURL+"/packages/diff", wrapper.GetPackagesDiff, options.OperationMiddlewares["GetPackagesDiff"]...) + router.GET(options.BaseURL+"/search", wrapper.GetSearch, options.OperationMiddlewares["GetSearch"]...) router.DELETE(options.BaseURL+"/services", wrapper.DeleteServices, options.OperationMiddlewares["DeleteServices"]...) router.GET(options.BaseURL+"/services", wrapper.GetServices, options.OperationMiddlewares["GetServices"]...) router.POST(options.BaseURL+"/services", wrapper.PostServices, options.OperationMiddlewares["PostServices"]...) @@ -13879,452 +13954,468 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "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", - "//8=", + "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", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index 304cd55f..8cffc5a9 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -50,6 +50,60 @@ func (e ObsolescenceSettingRowObsType) Valid() bool { } } +// Defines values for SearchGroupKind. +const ( + App SearchGroupKind = "app" + Disk SearchGroupKind = "disk" + Filterset SearchGroupKind = "filterset" + Form SearchGroupKind = "form" + Group SearchGroupKind = "group" + Instance SearchGroupKind = "instance" + Moduleset SearchGroupKind = "moduleset" + Network SearchGroupKind = "network" + Node SearchGroupKind = "node" + Request SearchGroupKind = "request" + Ruleset SearchGroupKind = "ruleset" + Service SearchGroupKind = "service" + Tag SearchGroupKind = "tag" + User SearchGroupKind = "user" +) + +// Valid indicates whether the value is a known member of the SearchGroupKind enum. +func (e SearchGroupKind) Valid() bool { + switch e { + case App: + return true + case Disk: + return true + case Filterset: + return true + case Form: + return true + case Group: + return true + case Instance: + return true + case Moduleset: + return true + case Network: + return true + case Node: + return true + case Request: + return true + case Ruleset: + return true + case Service: + return true + case Tag: + return true + case User: + return true + default: + return false + } +} + // Defines values for PutComplianceModulesetJSONBodyAction. const ( PutComplianceModulesetJSONBodyActionClone PutComplianceModulesetJSONBodyAction = "clone" @@ -1618,6 +1672,39 @@ type RulesetsVariableRow struct { VarValue *string `json:"var_value,omitempty"` } +// SearchGroup The objects of one kind matching a search. +type SearchGroup struct { + // Error Set when the kind could not be searched. + Error *string `json:"error,omitempty"` + + // Items One entry per object, with the props of its kind: node_id, nodename, app, + // node_env, cluster_id, fqdn, os_name for a node; svc_id, svcname, svc_app, + // svc_env, cluster_id, svc_availstatus, svc_topology for a service; svc_id, + // node_id, mon_vmname, mon_availstatus, services.svcname, nodes.nodename for + // an instance; id, app, app_domain, description for an application; id, addr, + // mask, intf, node_id, nodename, net_name for a node address; disk_id, + // disk_name, disk_size, disk_arrayid, nodename, svcname for a disk; tag_id, + // tag_name, tag_exclude for a tag; id, email, first_name, last_name, username + // for a user; id, role, privilege, description for a team; id, form_name, + // last_form_name, status, creator, last_update for a request; id, + // modset_name, modset_author for a moduleset; id, ruleset_name, ruleset_type, + // ruleset_public for a ruleset; id, fset_name, fset_author for a filterset; + // id, form_name, form_type, form_folder for a form. + Items []map[string]interface{} `json:"items"` + Kind SearchGroupKind `json:"kind"` + + // More Other objects of the kind match beyond those returned. + More bool `json:"more"` +} + +// SearchGroupKind defines model for SearchGroup.Kind. +type SearchGroupKind string + +// SearchResponse defines model for SearchResponse. +type SearchResponse struct { + Data []SearchGroup `json:"data"` +} + // ServiceListResponse defines model for ServiceListResponse. type ServiceListResponse struct { Data ServiceListResponse_Data `json:"data"` @@ -2066,6 +2153,19 @@ type GetAppsParams struct { // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` + + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` } // PostAppsJSONBody defines parameters for PostApps. @@ -3457,6 +3557,19 @@ type GetDisksParams struct { // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` + + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` } // PostDisksJSONBody defines parameters for PostDisks. @@ -3624,6 +3737,19 @@ type GetFiltersetsParams struct { // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` + + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` } // PostFiltersetsJSONBody defines parameters for PostFiltersets. @@ -4360,6 +4486,19 @@ type GetGroupsParams struct { // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` + + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` } // PostGroupsJSONBody defines parameters for PostGroups. @@ -5736,6 +5875,20 @@ type GetPackagesDiffParams struct { Encap *bool `form:"encap,omitempty" json:"encap,omitempty"` } +// GetSearchParams defines parameters for GetSearch. +type GetSearchParams struct { + // Q The text to search for. + Q string `form:"q" json:"q"` + + // Kinds Comma-separated kinds to search, all by default: node, service, instance, + // app, network, disk, tag, user, group, request, moduleset, ruleset, + // filterset, form. + Kinds *string `form:"kinds,omitempty" json:"kinds,omitempty"` + + // Limit Hits returned per kind, 5 by default, 20 at most. + Limit *int `form:"limit,omitempty" json:"limit,omitempty"` +} + // DeleteServicesJSONBody defines parameters for DeleteServices. type DeleteServicesJSONBody struct { // SvcId Service id or name @@ -6770,6 +6923,19 @@ type GetUsersParams struct { // Groupby Comma-separated list of properties to group the result by (e.g. groupby=app,svcname). Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` + + // Filter Column filter, repeatable; several filters combine with AND. Each value is + // `prop:expr`, `prop` being a property of the list (joined ones included, as + // for orderby) and `expr` one of: + // - text: case-insensitive match anywhere in the value; + // - `~regex`: regular expression (RE2 syntax), case-insensitive; + // - `in:a,b,c`: one of the listed values; + // - `eq:v`, `ne:v`: equal, not equal; + // - `gt:v`, `gte:v`, `lt:v`, `lte:v`: comparisons, for numbers and dates; + // - `empty`, `!empty`: no value, any value. + // An unknown property, a property without a column, or an invalid regular + // expression is answered with 400. + Filter *InQueryFilter `form:"filter,omitempty" json:"filter,omitempty"` } // PostUsersJSONBody defines parameters for PostUsers. diff --git a/server/handlers/get_apps.go b/server/handlers/get_apps.go index db12ee90..22687e1e 100644 --- a/server/handlers/get_apps.go +++ b/server/handlers/get_apps.go @@ -15,6 +15,7 @@ func (a *Api) GetApps(c echo.Context, params server.GetAppsParams) error { return a.handleList(c, "GetApps", "app", listEndpointParams{ props: params.Props, limit: params.Limit, offset: params.Offset, meta: params.Meta, stats: params.Stats, orderby: params.Orderby, groupby: params.Groupby, + filter: params.Filter, }, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { return odb.GetApps(ctx, p) }) diff --git a/server/handlers/get_disks.go b/server/handlers/get_disks.go index 7dd8e530..16e28b91 100644 --- a/server/handlers/get_disks.go +++ b/server/handlers/get_disks.go @@ -15,6 +15,7 @@ func (a *Api) GetDisks(c echo.Context, params server.GetDisksParams) error { return a.handleList(c, "GetDisks", "disk", listEndpointParams{ props: params.Props, limit: params.Limit, offset: params.Offset, meta: params.Meta, stats: params.Stats, orderby: params.Orderby, groupby: params.Groupby, + filter: params.Filter, }, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { return odb.GetDisks(ctx, p) }) diff --git a/server/handlers/get_filtersets.go b/server/handlers/get_filtersets.go index 030f67b3..a4b5f43a 100644 --- a/server/handlers/get_filtersets.go +++ b/server/handlers/get_filtersets.go @@ -14,6 +14,7 @@ func (a *Api) GetFiltersets(c echo.Context, params server.GetFiltersetsParams) e return a.handleList(c, "GetFiltersets", "filterset", listEndpointParams{ props: params.Props, limit: params.Limit, offset: params.Offset, meta: params.Meta, stats: params.Stats, orderby: params.Orderby, groupby: params.Groupby, + filter: params.Filter, }, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { return a.ODB.GetFiltersets(ctx, p) }) diff --git a/server/handlers/get_groups.go b/server/handlers/get_groups.go index 131645cd..66025c67 100644 --- a/server/handlers/get_groups.go +++ b/server/handlers/get_groups.go @@ -14,6 +14,7 @@ func (a *Api) GetGroups(c echo.Context, params server.GetGroupsParams) error { return a.handleList(c, "GetGroups", "auth_group", listEndpointParams{ props: params.Props, limit: params.Limit, offset: params.Offset, meta: params.Meta, stats: params.Stats, orderby: params.Orderby, groupby: params.Groupby, + filter: params.Filter, }, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { return a.ODB.GetGroups(ctx, p) }) diff --git a/server/handlers/get_users.go b/server/handlers/get_users.go index 5c058fc7..7929b78a 100644 --- a/server/handlers/get_users.go +++ b/server/handlers/get_users.go @@ -14,6 +14,7 @@ func (a *Api) GetUsers(c echo.Context, params server.GetUsersParams) error { return a.handleList(c, "GetUsers", "user", listEndpointParams{ props: params.Props, limit: params.Limit, offset: params.Offset, meta: params.Meta, stats: params.Stats, orderby: params.Orderby, groupby: params.Groupby, + filter: params.Filter, withUserID: true, }, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { return a.ODB.GetUsers(ctx, p) diff --git a/server/handlers/search.go b/server/handlers/search.go new file mode 100644 index 00000000..fda4e55e --- /dev/null +++ b/server/handlers/search.go @@ -0,0 +1,325 @@ +package serverhandlers + +import ( + "context" + "fmt" + "net/http" + "slices" + "strconv" + "strings" + "sync" + "time" + "unicode/utf8" + + "github.com/labstack/echo/v4" + + "github.com/opensvc/oc3/cdb" + "github.com/opensvc/oc3/server" + "github.com/opensvc/oc3/util/echolog" + "github.com/opensvc/oc3/util/logkey" +) + +const ( + // searchMinLength is the shortest text searched: one character matches + // almost every row and tells nothing. + searchMinLength = 2 + // searchDefaultLimit and searchMaxLimit bound the hits returned per kind. + searchDefaultLimit = 5 + searchMaxLimit = 20 + // searchTimeout bounds the whole search, all kinds together. + searchTimeout = 5 * time.Second +) + +// searchKind says how the global search looks for one kind of object: the +// list of the collector it reads, with the access control of that list, the +// props whose value may contain the text and the props returned for each hit. +type searchKind struct { + kind string + mapping string + match []string + // idProp is also compared for equality when the text is an integer: a + // request is named by its number. + idProp string + props []string + orderby string + // extra conditions, ANDed with the match. + extra []cdb.ColumnFilter + // withUserID forwards the caller's id, for the lists whose access control + // references it. + withUserID bool + fetch func(a *Api, ctx context.Context, p cdb.ListParams) ([]map[string]any, error) + // search replaces the list query for a kind without one, the tags. + search func(a *Api, ctx context.Context, pattern string, limit int) ([]map[string]any, error) +} + +// searchKinds are the searched kinds, in the order the results are returned. +var searchKinds = []searchKind{ + { + kind: "node", mapping: "node", + match: []string{"nodename", "node_id", "fqdn"}, + props: []string{"node_id", "nodename", "app", "node_env", "cluster_id", "fqdn", "os_name"}, + orderby: "nodename", + fetch: func(a *Api, ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetNodes(ctx, p) + }, + }, + { + kind: "service", mapping: "service", + match: []string{"svcname", "svc_id"}, + props: []string{"svc_id", "svcname", "svc_app", "svc_env", "cluster_id", "svc_availstatus", "svc_topology"}, + orderby: "svcname", + fetch: func(a *Api, ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetServices(ctx, p) + }, + }, + { + kind: "instance", mapping: "instance", + match: []string{"services.svcname", "mon_vmname"}, + props: []string{"svc_id", "node_id", "mon_vmname", "mon_availstatus", "services.svcname", "nodes.nodename"}, + orderby: "services.svcname,nodes.nodename", + fetch: func(a *Api, ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetServicesInstances(ctx, p) + }, + }, + { + kind: "app", mapping: "app", + match: []string{"app", "description"}, + props: []string{"id", "app", "app_domain", "description"}, + orderby: "app", + fetch: func(a *Api, ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetApps(ctx, p) + }, + }, + { + kind: "network", mapping: "node_ip", + match: []string{"addr", "mac"}, + props: []string{"id", "addr", "mask", "intf", "node_id", "nodename", "net_name"}, + orderby: "addr", + fetch: func(a *Api, ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetIps(ctx, p) + }, + }, + { + kind: "disk", mapping: "disk", + match: []string{"disk_id", "disk_name", "disk_devid"}, + props: []string{"disk_id", "disk_name", "disk_size", "disk_arrayid", "nodename", "svcname"}, + orderby: "disk_id", + fetch: func(a *Api, ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetDisks(ctx, p) + }, + }, + { + kind: "tag", + search: func(a *Api, ctx context.Context, pattern string, limit int) ([]map[string]any, error) { + return a.ODB.SearchTags(ctx, pattern, limit) + }, + }, + { + kind: "user", mapping: "user", + match: []string{"email", "first_name", "last_name", "username"}, + props: []string{"id", "email", "first_name", "last_name", "username"}, + orderby: "email", + withUserID: true, + fetch: func(a *Api, ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetUsers(ctx, p) + }, + }, + { + kind: "group", mapping: "auth_group", + match: []string{"role", "description"}, + props: []string{"id", "role", "privilege", "description"}, + orderby: "role", + // The private group of each user would drown the teams. + extra: []cdb.ColumnFilter{{Expr: `auth_group.role NOT LIKE 'user\_%'`}}, + fetch: func(a *Api, ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetGroups(ctx, p) + }, + }, + { + kind: "request", mapping: "workflow", + match: []string{"form_name", "last_form_name"}, + idProp: "id", + props: []string{"id", "form_name", "last_form_name", "status", "creator", "last_update"}, + orderby: "-id", + fetch: func(a *Api, ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetWorkflows(ctx, nil, "", p) + }, + }, + { + kind: "moduleset", mapping: "moduleset", + match: []string{"modset_name"}, + props: []string{"id", "modset_name", "modset_author"}, + orderby: "modset_name", + fetch: func(a *Api, ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetComplianceModulesets(ctx, nil, p) + }, + }, + { + kind: "ruleset", mapping: "ruleset", + match: []string{"ruleset_name"}, + props: []string{"id", "ruleset_name", "ruleset_type", "ruleset_public"}, + orderby: "ruleset_name", + fetch: func(a *Api, ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetComplianceRulesets(ctx, nil, p) + }, + }, + { + kind: "filterset", mapping: "filterset", + match: []string{"fset_name"}, + props: []string{"id", "fset_name", "fset_author"}, + orderby: "fset_name", + fetch: func(a *Api, ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetFiltersets(ctx, p) + }, + }, + { + kind: "form", mapping: "form", + match: []string{"form_name", "form_folder"}, + props: []string{"id", "form_name", "form_type", "form_folder"}, + orderby: "form_name", + fetch: func(a *Api, ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return a.ODB.GetForms(ctx, nil, p) + }, + }, +} + +// searchGroup is the result of the search for one kind. More tells that other +// objects of the kind match beyond the ones returned. +type searchGroup struct { + Kind string `json:"kind"` + Items []map[string]any `json:"items"` + More bool `json:"more"` + Error string `json:"error,omitempty"` +} + +// GetSearch handles GET /search: the objects of the main kinds whose name, or +// another identifying prop, contains the text, as the historical collector's +// search did. Each kind is read through its own list, with its access control, +// all kinds at once; a kind that fails is reported in its group without +// failing the others. +func (a *Api) GetSearch(c echo.Context, params server.GetSearchParams) error { + log := echolog.GetLogHandler(c, "GetSearch") + + text := strings.TrimSpace(params.Q) + limit := searchDefaultLimit + if params.Limit != nil { + limit = min(max(*params.Limit, 1), searchMaxLimit) + } + var wanted []string + if params.Kinds != nil && *params.Kinds != "" { + wanted = strings.Split(*params.Kinds, ",") + for _, k := range wanted { + if !slices.ContainsFunc(searchKinds, func(s searchKind) bool { return s.kind == k }) { + return JSONProblemf(c, http.StatusBadRequest, "unknown kind %q", k) + } + } + } + + groups := []searchGroup{} + if utf8.RuneCountInString(text) < searchMinLength { + return c.JSON(http.StatusOK, map[string]any{"data": groups}) + } + + ctx, cancel := context.WithTimeout(c.Request().Context(), searchTimeout) + defer cancel() + + base := cdb.ListParams{Groups: UserGroupsFromContext(c), IsManager: IsManager(c)} + userID := authUserID(c) + pattern := "%" + likeEscaper.Replace(text) + "%" + + kinds := make([]searchKind, 0, len(searchKinds)) + for _, k := range searchKinds { + if wanted == nil || slices.Contains(wanted, k.kind) { + kinds = append(kinds, k) + } + } + groups = make([]searchGroup, len(kinds)) + var wg sync.WaitGroup + for i, k := range kinds { + wg.Add(1) + go func() { + defer wg.Done() + items, err := a.searchOne(ctx, k, text, pattern, limit, base, userID) + groups[i] = searchGroup{Kind: k.kind, Items: items} + if err != nil { + log.Error("cannot search", "kind", k.kind, logkey.Error, err) + groups[i].Error = fmt.Sprintf("cannot search %s", k.kind) + groups[i].Items = []map[string]any{} + return + } + if len(items) > limit { + groups[i].Items = items[:limit] + groups[i].More = true + } + if groups[i].Items == nil { + groups[i].Items = []map[string]any{} + } + }() + } + wg.Wait() + log.Info("called", "text", text, "kinds", len(kinds), "limit", limit) + return c.JSON(http.StatusOK, map[string]any{"data": groups}) +} + +// searchOne runs the search of one kind, asking for one row more than limit +// to tell whether more match. +func (a *Api) searchOne(ctx context.Context, k searchKind, text, pattern string, limit int, base cdb.ListParams, userID *int64) ([]map[string]any, error) { + if k.search != nil { + return k.search(a, ctx, pattern, limit+1) + } + mapping := propsMapping[k.mapping] + props := strings.Join(k.props, ",") + orderby := k.orderby + fetchLimit := limit + 1 + query, err := buildListQueryParameters(&props, &fetchLimit, nil, nil, nil, &orderby, nil, mapping) + if err != nil { + return nil, err + } + selectExprs, err := buildSelectClause(query.Props, mapping) + if err != nil { + return nil, err + } + + var ( + conds []string + args []any + first *cdb.ColumnFilter + ) + for _, prop := range k.match { + col, err := resolvePropCol(prop, mapping, "search") + if err != nil { + return nil, err + } + if first == nil { + first = &cdb.ColumnFilter{Col: col} + } + conds = append(conds, col.Qualified()+" LIKE ?") + args = append(args, pattern) + } + if k.idProp != "" { + if id, err := strconv.ParseInt(text, 10, 64); err == nil { + col, err := resolvePropCol(k.idProp, mapping, "search") + if err != nil { + return nil, err + } + conds = append(conds, col.Qualified()+" = ?") + args = append(args, id) + } + } + match := cdb.ColumnFilter{Expr: "(" + strings.Join(conds, " OR ") + ")", Args: args} + if first != nil { + match.Col = first.Col + } + + p := base + p.Limit = query.Page.Limit + p.Props = query.Props + p.SelectExprs = selectExprs + p.TypeHints = buildTypeHints(query.Props, mapping) + p.OrderBy = query.OrderBy + p.Filters = append([]cdb.ColumnFilter{match}, k.extra...) + if k.withUserID { + p.UserID = userID + } + return k.fetch(a, ctx, p) +} From b0b3454ced8cfac78e88dd230c036d29e5672112 Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Tue, 29 Sep 2026 22:39:51 +0200 Subject: [PATCH 58/61] Receive the SAN switch configurations the agents inventory The om3 agents inventory the SAN switches their configuration declares, and fed them to the old collector only, through its update_brocade rpc, which stored the command outputs and parsed them into the switches, san_zone and san_zone_alias tables. oc3 had no feed for it, and will drop the rpc api. The feeder serves POST /sanswitch, taking the switch name, its type and the raw output of each command, by name: switchshow, nsshow and zoneshow for a brocade. The report is keyed by switch, as @, and not by node: a couple of nodes of the whole infrastructure inventory the switches, and the latest report of a switch is the one to parse. The sanSwitch job, on the san_switch queue, parses the outputs with a port of the old collector parser, quirks included, and replaces the rows of the switch, of the aliases of each of its configurations, and of the zones of its effective one: the rows are upserted on the unique keys of the tables, and the older rows deleted. A switchshow without its port table is refused rather than read as a switch with no port, which would delete them all. A deployment serves the feed once a worker lists san_switch in its queues. --- README.md | 1 + cachekeys/main.go | 4 + feeder/api.yaml | 48 +++ feeder/codegen_server_gen.go | 106 ++++--- feeder/codegen_type_gen.go | 34 ++ feeder/handlers/post_feed_san_switch.go | 56 ++++ worker/brocade.go | 396 ++++++++++++++++++++++++ worker/brocade_test.go | 156 ++++++++++ worker/job_feed_san_switch.go | 218 +++++++++++++ worker/metrics.go | 6 +- worker/worker.go | 9 + 11 files changed, 989 insertions(+), 45 deletions(-) create mode 100644 feeder/handlers/post_feed_san_switch.go create mode 100644 worker/brocade.go create mode 100644 worker/brocade_test.go create mode 100644 worker/job_feed_san_switch.go diff --git a/README.md b/README.md index 3c7afe39..730c6997 100644 --- a/README.md +++ b/README.md @@ -76,6 +76,7 @@ worker.fast: - "instance_action" - "node_disk" - "object_config" + - "san_switch" - "system" ``` diff --git a/cachekeys/main.go b/cachekeys/main.go index 0b8c1572..7d7646ae 100644 --- a/cachekeys/main.go +++ b/cachekeys/main.go @@ -20,6 +20,10 @@ const ( FeedNodeDiskQ = "oc3:q:feed_node_disk" FeedNodeDiskPendingH = "oc3:h:feed_node_disk_pending" + FeedSANSwitchH = "oc3:h:feed_san_switch" + FeedSANSwitchQ = "oc3:q:feed_san_switch" + FeedSANSwitchPendingH = "oc3:h:feed_san_switch_pending" + FeedObjectConfigForClusterIDH = "oc3:h:feed_object_config_for_cluster_id" FeedObjectConfigH = "oc3:h:feed_object_config" diff --git a/feeder/api.yaml b/feeder/api.yaml index 0411f2d7..4f137f84 100644 --- a/feeder/api.yaml +++ b/feeder/api.yaml @@ -367,6 +367,31 @@ paths: tags: - agent + /sanswitch: + post: + description: | + Update the configuration of a SAN switch, as the agent inventoried it: + the raw outputs of the switch commands, which the worker parses into + the switches, zones and aliases tables. A node inventories the + switches its configuration declares, on the schedule of each. + operationId: PostSANSwitch + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/SANSwitch' + responses: + 202: + description: the switch configuration will be refreshed + 400: + $ref: '#/components/responses/400' + security: + - basicAuth: [ ] + - bearerAuth: [ ] + tags: + - agent + /version: get: operationId: GetVersion @@ -608,6 +633,29 @@ components: items: $ref: '#/components/schemas/Disk' + SANSwitch: + type: object + required: + - name + - type + - data + properties: + name: + type: string + description: the name the agent reaches the switch with + type: + type: string + enum: + - brocade + description: the driver of the switch, which says how data is read + data: + type: object + additionalProperties: + type: string + description: | + the raw output of each switch command, by command name. For a + brocade: switchshow, nsshow and zoneshow. + ObjectConfig: type: object required: diff --git a/feeder/codegen_server_gen.go b/feeder/codegen_server_gen.go index a6d92d47..a3673c4d 100644 --- a/feeder/codegen_server_gen.go +++ b/feeder/codegen_server_gen.go @@ -66,6 +66,9 @@ type ServerInterface interface { // (GET /openapi.json) GetSwagger(ctx echo.Context) error + // (POST /sanswitch) + PostSANSwitch(ctx echo.Context) error + // (GET /version) GetVersion(ctx echo.Context) error } @@ -275,6 +278,19 @@ func (w *ServerInterfaceWrapper) GetSwagger(ctx echo.Context) error { return err } +// PostSANSwitch converts echo context to params. +func (w *ServerInterfaceWrapper) PostSANSwitch(ctx echo.Context) error { + var err error + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostSANSwitch(ctx) + return err +} + // GetVersion converts echo context to params. func (w *ServerInterfaceWrapper) GetVersion(ctx echo.Context) error { var err error @@ -346,6 +362,7 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.POST(options.BaseURL+"/node/system", wrapper.PostSystem, options.OperationMiddlewares["PostSystem"]...) router.POST(options.BaseURL+"/object/config", wrapper.PostObjectConfig, options.OperationMiddlewares["PostObjectConfig"]...) router.GET(options.BaseURL+"/openapi.json", wrapper.GetSwagger, options.OperationMiddlewares["GetSwagger"]...) + router.POST(options.BaseURL+"/sanswitch", wrapper.PostSANSwitch, options.OperationMiddlewares["PostSANSwitch"]...) router.GET(options.BaseURL+"/version", wrapper.GetVersion, options.OperationMiddlewares["GetVersion"]...) } @@ -355,48 +372,53 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "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", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/feeder/codegen_type_gen.go b/feeder/codegen_type_gen.go index dd3d593c..b40d5188 100644 --- a/feeder/codegen_type_gen.go +++ b/feeder/codegen_type_gen.go @@ -14,6 +14,21 @@ const ( BearerAuthScopes bearerAuthContextKey = "bearerAuth.Scopes" ) +// Defines values for SANSwitchType. +const ( + Brocade SANSwitchType = "brocade" +) + +// Valid indicates whether the value is a known member of the SANSwitchType enum. +func (e SANSwitchType) Valid() bool { + switch e { + case Brocade: + return true + default: + return false + } +} + // Action The begin or end action request type Action struct { Action string `json:"action"` @@ -194,6 +209,22 @@ type QueuedActions struct { Actions []QueuedAction `json:"actions"` } +// SANSwitch defines model for SANSwitch. +type SANSwitch struct { + // Data the raw output of each switch command, by command name. For a + // brocade: switchshow, nsshow and zoneshow. + Data map[string]string `json:"data"` + + // Name the name the agent reaches the switch with + Name string `json:"name"` + + // Type the driver of the switch, which says how data is read + Type SANSwitchType `json:"type"` +} + +// SANSwitchType the driver of the switch, which says how data is read +type SANSwitchType string + // SysReport defines model for SysReport. type SysReport struct { Deleted []string `json:"deleted"` @@ -302,3 +333,6 @@ type PostSystemJSONRequestBody = System // PostObjectConfigJSONRequestBody defines body for PostObjectConfig for application/json ContentType. type PostObjectConfigJSONRequestBody = ObjectConfig + +// PostSANSwitchJSONRequestBody defines body for PostSANSwitch for application/json ContentType. +type PostSANSwitchJSONRequestBody = SANSwitch diff --git a/feeder/handlers/post_feed_san_switch.go b/feeder/handlers/post_feed_san_switch.go new file mode 100644 index 00000000..c37a564a --- /dev/null +++ b/feeder/handlers/post_feed_san_switch.go @@ -0,0 +1,56 @@ +package feederhandlers + +import ( + "encoding/json" + "net/http" + "strings" + + "github.com/labstack/echo/v4" + + "github.com/opensvc/oc3/cachekeys" + "github.com/opensvc/oc3/feeder" + "github.com/opensvc/oc3/util/logkey" +) + +// PostSANSwitch will populate FeedSANSwitchH @ with the posted +// switch configuration, and queue its parsing. +// +// A switch is keyed by its name and not by the node reporting it: the +// switches of a fabric are inventoried by a couple of nodes of the whole +// infrastructure, and the latest report of a switch is the one to parse, +// whichever node sent it. +func (a *Api) PostSANSwitch(c echo.Context) error { + nodeID, log := getNodeIDAndLogger(c, "PostSANSwitch") + if nodeID == "" { + return JSONNodeAuthProblem(c) + } + + var payload feeder.PostSANSwitchJSONRequestBody + if err := c.Bind(&payload); err != nil { + return JSONProblem(c, http.StatusBadRequest, err.Error()) + } + switch { + case payload.Name == "", strings.Contains(payload.Name, "@"): + return JSONProblemf(c, http.StatusBadRequest, "invalid switch name: %q", payload.Name) + case !payload.Type.Valid(): + return JSONProblemf(c, http.StatusBadRequest, "unsupported switch type: %q", payload.Type) + } + b, err := json.Marshal(payload) + if err != nil { + log.Warn("Marshal", logkey.Error, err) + return JSONError(c) + } + ctx := c.Request().Context() + idx := string(payload.Type) + "@" + payload.Name + log.Debug("HSet keyH") + if err := a.Redis.HSet(ctx, cachekeys.FeedSANSwitchH, idx, b).Err(); err != nil { + log.Error("HSet keyH", logkey.Error, err) + return JSONError(c) + } + + if err := a.pushNotPending(ctx, log, cachekeys.FeedSANSwitchPendingH, cachekeys.FeedSANSwitchQ, idx); err != nil { + log.Error("pushNotPending", logkey.Error, err) + return JSONError(c) + } + return c.JSON(http.StatusAccepted, nil) +} diff --git a/worker/brocade.go b/worker/brocade.go new file mode 100644 index 00000000..bbf9aca1 --- /dev/null +++ b/worker/brocade.go @@ -0,0 +1,396 @@ +package worker + +import ( + "fmt" + "strconv" + "strings" +) + +type ( + // brocadeSwitch is what the switchshow, nsshow and zoneshow outputs of a + // brocade switch say, as the old collector read them in + // init/modules/brocade.py: the switch, its ports, the aliases of every + // zoning configuration, and the zones of the effective one. + brocadeSwitch struct { + Name string + Model string + WWN string + + // Ports are keyed by port index. + Ports map[string]*brocadePort + + // Alias is the ports of each alias, by configuration name. + Alias map[string]map[string][]string + + // Cfg is the name of the effective zoning configuration, empty when + // the switch reports none. + Cfg string + + // Zone is the ports of each zone of the effective configuration. + Zone map[string][]string + } + + brocadePort struct { + Index string + Slot string + Port string + Type string + State string + RemotePortName string + + // Speed is in Gb/s, 0 when negotiated but not yet known. Nego says + // the speed is negotiated, and is empty when the output does not + // tell. + Speed int + Nego string + + // NSE are the port names the name server reports behind the port, + // as the devices logged in through an NPIV port. + NSE []string + + trunkMaster *[2]string + } +) + +// parseBrocade reads the outputs of the switchshow, nsshow and zoneshow +// commands of a brocade switch. +func parseBrocade(switchshow, nsshow, zoneshow string) (*brocadeSwitch, error) { + s := &brocadeSwitch{ + Ports: make(map[string]*brocadePort), + Alias: make(map[string]map[string][]string), + Zone: make(map[string][]string), + } + if err := s.loadSwitchshow(switchshow); err != nil { + return nil, err + } + s.loadNsshow(nsshow) + s.loadZoneshow(zoneshow) + return s, nil +} + +// loadSwitchshow reads the switch identity and its port table: +// +// switchName: sansw1 +// switchType: 71.2 +// switchWwn: 10:00:00:05:33:a0:e6:42 +// ... +// Index Port Address Media Speed State Proto +// ================================================== +// 0 0 010000 id N8 Online FC F-Port 50:01:43:80:07:2d:f5:e6 +// 1 1 010100 id N8 Online FC E-Port 10:00:00:05:33:a0:e6:43 "sansw2" (downstream) +// +// The words past the columns of the table are a comment saying the port +// type and the name of the port at the other end. +func (s *brocadeSwitch) loadSwitchshow(buff string) error { + lines := strings.Split(buff, "\n") + if len(lines) < 2 { + return fmt.Errorf("switchshow is empty") + } + var ( + start, commentIdx int + cols []string + ) + for i, line := range lines { + switch { + case strings.HasPrefix(line, "switchName:"): + s.Name = strings.ToLower(strings.TrimSpace(afterColon(line))) + case strings.HasPrefix(line, "switchType"): + s.Model = strings.TrimSpace(afterColon(line)) + case strings.HasPrefix(line, "switchWwn"): + _, v, _ := strings.Cut(line, ":") + s.WWN = strings.TrimSpace(strings.ReplaceAll(v, ":", "")) + case strings.HasPrefix(line, "===="): + start = i + 1 + commentIdx = len(line) + if i > 0 { + cols = strings.Fields(lines[i-1]) + } + } + if start > 0 { + break + } + } + // A label with no port table says nothing of the ports: parsed as a + // switch with no port, it would have the job delete all its rows. + if start == 0 || len(cols) == 0 { + return fmt.Errorf("switchshow has no port table") + } + rindex := make(map[[2]string]string) + for _, line := range lines[start:] { + // A line shorter than the rule under the header is passed over, as + // the old collector did: an unlit port has no comment and is one, + // and the tables have never held those. + if len(line) < commentIdx { + continue + } + var comment string + if words := strings.Fields(line); len(words) >= len(cols)+1 { + comment = strings.Join(words[len(cols):], " ") + } + values := make(map[string]string) + for i, v := range strings.Fields(line[:commentIdx]) { + if i >= len(cols) { + break + } + values[cols[i]] = v + } + port := &brocadePort{ + Index: values["Index"], + Slot: "0", + Port: values["Port"], + Type: values["Type"], + State: values["State"], + } + if v, ok := values["Slot"]; ok { + port.Slot = v + } + if v, ok := values["Area"]; ok { + port.Index = v + } + if comment != "" { + switch { + case strings.Contains(comment, "E-Port"): + port.Type = "E-Port" + case strings.Contains(comment, "F-Port"): + port.Type = "F-Port" + } + words := strings.Fields(comment) + if len(words) >= 2 && strings.Contains(words[1], ":") { + port.RemotePortName = portName(words[1]) + } else if len(words) >= 3 && strings.Contains(words[2], ":") { + port.RemotePortName = portName(words[2]) + } + if strings.Contains(comment, "master is Port") { + // (Trunk port, master is Port 3 ) + parts := strings.Split(comment, "Port") + master := strings.TrimSpace(strings.Trim(parts[len(parts)-1], ") ")) + port.trunkMaster = &[2]string{port.Slot, master} + } else if strings.Contains(comment, "master is Slot") { + // (Trunk port, master is Slot 1 Port 0 ) + slot, sport := wordAfter(words, "Slot"), wordAfter(words, "Port") + port.trunkMaster = &[2]string{slot, sport} + } + } + speed := values["Speed"] + switch { + case speed == "AN": + port.Speed, port.Nego = 0, "F" + case strings.HasPrefix(speed, "N"): + port.Speed, _ = strconv.Atoi(strings.TrimPrefix(speed, "N")) + port.Nego = "T" + case strings.HasSuffix(speed, "G"): + port.Speed, _ = strconv.Atoi(strings.TrimSuffix(speed, "G")) + port.Nego = "F" + } + rindex[[2]string{port.Slot, port.Port}] = port.Index + s.Ports[port.Index] = port + } + // A slave port of a trunk takes the remote port name of its master. + for _, port := range s.Ports { + if port.trunkMaster == nil { + continue + } + if i, ok := rindex[*port.trunkMaster]; ok { + if master, ok := s.Ports[i]; ok { + port.RemotePortName = master.RemotePortName + } + } + } + return nil +} + +// loadNsshow adds to each port the port names the name server reports +// behind it: +// +// Type Pid COS PortName NodeName TTL(sec) +// N 020f01; 3;50:01:43:80:07:2d:f5:e6;50:01:43:80:07:2d:f5:e7; na +// FC4s: FCP +// Port Index: 32 +func (s *brocadeSwitch) loadNsshow(buff string) { + var name string + for _, line := range strings.Split(buff, "\n") { + if len(line) <= 2 { + continue + } + if line[1] != ' ' { + // a new entry + if fields := strings.Split(line, ";"); len(fields) == 5 { + name = strings.ReplaceAll(fields[2], ":", "") + } + continue + } + if strings.HasPrefix(strings.TrimSpace(line), "Port Index:") { + index := strings.TrimSpace(afterLastColon(line)) + if port, ok := s.Ports[index]; ok && name != "" { + port.NSE = append(port.NSE, name) + } + } + } +} + +// loadZoneshow reads the aliases of each zoning configuration, from the +// defined configurations, and the zones of the effective configuration: +// +// Defined configuration: +// cfg: PROD_CFG +// alias: DMX0197_8A0 +// 50:06:04:84:52:A4:F9:47 +// alias: Wdms01 10:00:00:00:C9:24:32:8C +// alias: EVA04 50:00:1F:E1:50:21:90:19; 50:00:1F:E1:50:21:90:1F; +// 50:00:1F:E1:50:21:90:1B; 50:00:1F:E1:50:21:90:1D +// +// Effective configuration: +// cfg: PROD_CFG +// zone: Wzzs01_DMX1370_9B1 +// 50:06:04:84:52:a6:1e:b8 +// 10:00:00:00:c9:3a:12:72 +func (s *brocadeSwitch) loadZoneshow(buff string) { + lines := strings.Split(buff, "\n") + effective := 0 + cfg := "" + haveCfg := false +firstPass: + for i, raw := range lines { + line := strings.TrimSpace(raw) + switch { + case strings.HasPrefix(line, "alias:"): + if !haveCfg { + continue + } + words := strings.Fields(line) + var alias string + var ports []string + switch len(words) { + case 2: + alias = words[1] + if i+1 < len(lines) { + ports = []string{portName(strings.TrimSpace(lines[i+1]))} + } + case 3: + alias = words[1] + ports = []string{portName(words[2])} + case 4: + alias = words[1] + ports = []string{portName(words[2]), portName(words[3])} + for j := i + 1; j < len(lines); j++ { + next := lines[j] + if strings.Contains(next, "alias") || len(next) == 0 { + break + } + for _, w := range strings.Fields(next) { + ports = append(ports, portName(w)) + } + } + default: + continue + } + s.Alias[cfg][alias] = ports + case strings.HasPrefix(line, "Effective configuration:"): + effective = i + break firstPass + case strings.HasPrefix(line, "cfg:"): + cfg = strings.TrimSpace(afterLastColon(line)) + haveCfg = true + s.Alias[cfg] = make(map[string][]string) + } + } + + lines = lines[effective:] + for i, raw := range lines { + line := strings.TrimSpace(raw) + switch { + case strings.HasPrefix(line, "zone:"): + words := strings.Fields(line) + zone := words[len(words)-1] + members := make([]string, 0) + for _, next := range lines[i+1:] { + next = strings.TrimSpace(next) + if strings.HasPrefix(next, "zone:") || len(next) == 0 { + break + } + members = append(members, strings.ToLower(strings.ReplaceAll(next, ":", ""))) + } + s.Zone[zone] = members + case strings.HasPrefix(line, "cfg:"): + s.Cfg = strings.TrimSpace(afterLastColon(line)) + } + } +} + +// portName is a port wwn as the tables store it: lower case, without its +// colons and its list separator. +func portName(s string) string { + s = strings.ReplaceAll(s, ":", "") + s = strings.ReplaceAll(s, ";", "") + return strings.ToLower(s) +} + +// afterColon returns what follows the first colon of s. +func afterColon(s string) string { + _, v, _ := strings.Cut(s, ":") + return v +} + +// afterLastColon returns what follows the last colon of s. +func afterLastColon(s string) string { + if i := strings.LastIndex(s, ":"); i >= 0 { + return s[i+1:] + } + return s +} + +// wordAfter returns the word following word in words, without the closing +// parenthesis a comment may end it with. +func wordAfter(words []string, word string) string { + for i, w := range words { + if w == word && i+1 < len(words) { + return strings.TrimSpace(strings.Trim(words[i+1], ")")) + } + } + return "" +} + +// rows are the lines of the switches table the switch fills, one per device +// the name server reports behind a port, or one for the port when it +// reports none: the column sw_portname holds the switch wwn, as the old +// collector filled it. +func (s *brocadeSwitch) rows() []any { + l := make([]any, 0, len(s.Ports)) + for _, p := range s.Ports { + row := func(rportname string) map[string]any { + return map[string]any{ + "sw_name": s.Name, + "sw_portname": s.WWN, + "sw_index": atoiOrNil(p.Index), + "sw_slot": atoiOrNil(p.Slot), + "sw_port": atoiOrNil(p.Port), + "sw_portspeed": p.Speed, + "sw_portnego": p.Nego, + "sw_portstate": p.State, + "sw_porttype": p.Type, + "sw_rportname": rportname, + } + } + n := 0 + for _, nse := range p.NSE { + if nse == p.RemotePortName { + continue + } + l = append(l, row(nse)) + n++ + } + if n == 0 { + l = append(l, row(p.RemotePortName)) + } + } + return l +} + +// atoiOrNil returns the integer s writes, or nil for a column the output +// did not fill. +func atoiOrNil(s string) any { + if i, err := strconv.Atoi(s); err == nil { + return i + } + return nil +} diff --git a/worker/brocade_test.go b/worker/brocade_test.go new file mode 100644 index 00000000..8d45fc07 --- /dev/null +++ b/worker/brocade_test.go @@ -0,0 +1,156 @@ +package worker + +import ( + "reflect" + "sort" + "testing" +) + +// The outputs of a Fabric OS switch, as the agent pushes them, in the formats +// the old collector parser was written against. +const ( + testSwitchshow = `switchName: SANSW1 +switchType: 71.2 +switchState: Online +switchMode: Native +switchRole: Principal +switchDomain: 1 +switchId: fffc01 +switchWwn: 10:00:00:05:33:a0:e6:42 +zoning: ON (PROD_CFG) +switchBeacon: OFF + +Index Port Address Media Speed State Proto +================================================== + 0 0 010000 id N8 Online FC F-Port 50:01:43:80:07:2d:f5:e6 + 1 1 010100 id N16 Online FC F-Port 1 N Port + 2 NPIV public + 2 2 010200 id 8G Online FC E-Port 10:00:00:05:33:a0:e6:43 "sansw2" (downstream) + 3 3 010300 id 8G Online FC E-Port (Trunk port, master is Port 2 ) + 4 4 010400 id AN No_Light FC +` + testNsshow = `{ + Type Pid COS PortName NodeName TTL(sec) + N 010000; 3;50:01:43:80:07:2d:f5:e6;50:01:43:80:07:2d:f5:e7; na + FC4s: FCP + Port Index: 0 + N 010100; 3;20:00:00:25:b5:00:00:01;20:00:00:25:b5:00:00:ff; na + FC4s: FCP + Port Index: 1 + N 010101; 3;20:00:00:25:b5:00:00:02;20:00:00:25:b5:00:00:ff; na + FC4s: FCP + Port Index: 1 + N 019900; 3;20:00:00:25:b5:00:00:09;20:00:00:25:b5:00:00:ff; na + Port Index: 99 +The Local Name Server has 4 entries } +` + testZoneshow = `Defined configuration: + cfg: PROD_CFG + alias: DMX0197_8A0 + 50:06:04:84:52:A4:F9:47 + alias: Wdms01 10:00:00:00:C9:24:32:8C + alias: EVA04 50:00:1F:E1:50:21:90:19; 50:00:1F:E1:50:21:90:1F; + 50:00:1F:E1:50:21:90:1B; 50:00:1F:E1:50:21:90:1D + +Effective configuration: + cfg: PROD_CFG + zone: Wzzs01_DMX1370_9B1 + 50:06:04:84:52:a6:1e:b8 + 10:00:00:00:c9:3a:12:72 + zone: Wdms01_EVA04 + 10:00:00:00:c9:24:32:8c + 50:00:1f:e1:50:21:90:19 + +` +) + +func equal(t *testing.T, what string, got, want any) { + t.Helper() + if !reflect.DeepEqual(got, want) { + t.Errorf("%s: got %#v, want %#v", what, got, want) + } +} + +func parseTestBrocade(t *testing.T) *brocadeSwitch { + t.Helper() + s, err := parseBrocade(testSwitchshow, testNsshow, testZoneshow) + if err != nil { + t.Fatalf("parse: %s", err) + } + return s +} + +func TestParseBrocadeSwitch(t *testing.T) { + s := parseTestBrocade(t) + equal(t, "name", s.Name, "sansw1") + equal(t, "model", s.Model, "71.2") + equal(t, "wwn", s.WWN, "1000000533a0e642") + equal(t, "port count, the unlit port 4 passed over as the old collector did", len(s.Ports), 4) + + p := s.Ports["0"] + equal(t, "port 0 type", p.Type, "F-Port") + equal(t, "port 0 state", p.State, "Online") + equal(t, "port 0 remote", p.RemotePortName, "5001438007"+"2df5e6") + equal(t, "port 0 speed", p.Speed, 8) + equal(t, "port 0 nego", p.Nego, "T") + + p = s.Ports["1"] + equal(t, "port 1 speed", p.Speed, 16) + equal(t, "port 1 remote, no wwn in the comment of an npiv port", p.RemotePortName, "") + equal(t, "port 1 name server entries", p.NSE, []string{"20000025b5000001", "20000025b5000002"}) + + p = s.Ports["2"] + equal(t, "port 2 type", p.Type, "E-Port") + equal(t, "port 2 speed", p.Speed, 8) + equal(t, "port 2 nego", p.Nego, "F") + equal(t, "port 2 remote", p.RemotePortName, "1000000533a0e643") + + p = s.Ports["3"] + equal(t, "port 3 type", p.Type, "E-Port") + equal(t, "port 3 remote, taken from its trunk master", p.RemotePortName, "1000000533a0e643") +} + +func TestParseBrocadeZoning(t *testing.T) { + s := parseTestBrocade(t) + equal(t, "effective cfg", s.Cfg, "PROD_CFG") + equal(t, "aliases", s.Alias["PROD_CFG"], map[string][]string{ + "DMX0197_8A0": {"5006048452a4f947"}, + "Wdms01": {"10000000c924328c"}, + "EVA04": {"50001fe150219019", "50001fe15021901f", "50001fe15021901b", "50001fe15021901d"}, + }) + equal(t, "zones", s.Zone, map[string][]string{ + "Wzzs01_DMX1370_9B1": {"5006048452a61eb8", "10000000c93a1272"}, + "Wdms01_EVA04": {"10000000c924328c", "50001fe150219019"}, + }) +} + +// A port behind which the name server reports devices gets a row per +// device, and a port with none gets one row, with the port at the other end. +func TestBrocadeRows(t *testing.T) { + s := parseTestBrocade(t) + var got []string + for _, r := range s.rows() { + m := r.(map[string]any) + equal(t, "sw_name", m["sw_name"], "sansw1") + equal(t, "sw_portname", m["sw_portname"], "1000000533a0e642") + got = append(got, m["sw_rportname"].(string)) + } + sort.Strings(got) + equal(t, "remote port names", got, []string{ + "1000000533a0e643", + "1000000533a0e643", + "20000025b5000001", + "20000025b5000002", + "50014380072df5e6", + }) +} + +// A switchshow without its port table is refused rather than read as a +// switch without ports, which would have the job delete them all. +func TestParseBrocadeRefusesATruncatedSwitchshow(t *testing.T) { + if _, err := parseBrocade("switchName: sansw1\nswitchWwn: 10:00:00:05:33:a0:e6:42\n", "", ""); err == nil { + t.Error("a switchshow without a port table is accepted") + } + if _, err := parseBrocade("", "", ""); err == nil { + t.Error("an empty switchshow is accepted") + } +} diff --git a/worker/job_feed_san_switch.go b/worker/job_feed_san_switch.go new file mode 100644 index 00000000..9e21f6cd --- /dev/null +++ b/worker/job_feed_san_switch.go @@ -0,0 +1,218 @@ +package worker + +import ( + "context" + "encoding/json" + "fmt" + "log/slog" + + "github.com/go-redis/redis/v8" + + "github.com/opensvc/oc3/cachekeys" + "github.com/opensvc/oc3/feeder" + "github.com/opensvc/oc3/mariadb" + "github.com/opensvc/oc3/util/logkey" +) + +type ( + // jobFeedSANSwitch parses the configuration of a SAN switch an agent + // reported, and stores it in the switches, san_zone and san_zone_alias + // tables, as the old collector did from the update_brocade rpc. + jobFeedSANSwitch struct { + JobBase + JobRedis + JobDB + + // idx is @, the key of the report in FeedSANSwitchH. + idx string + + data feeder.SANSwitch + brocade *brocadeSwitch + } +) + +func newSANSwitch(idx string) *jobFeedSANSwitch { + return &jobFeedSANSwitch{ + JobBase: JobBase{ + name: jtSANSwitch, + detail: "switch: " + idx, + logger: slog.With(logkey.Object, idx, logkey.JobName, jtSANSwitch), + }, + JobRedis: JobRedis{ + cachePendingH: cachekeys.FeedSANSwitchPendingH, + cachePendingIDX: idx, + }, + idx: idx, + } +} + +func (d *jobFeedSANSwitch) Operations() []operation { + return []operation{ + {name: "dropPending", do: d.dropPending}, + {name: "getData", do: d.getData}, + {name: "parse", do: d.parse}, + {name: "dbNow", do: d.dbNow}, + {name: "updateDB", do: d.updateDB}, + {name: "pushFromTableChanges", do: d.pushFromTableChanges}, + } +} + +func (d *jobFeedSANSwitch) getData(ctx context.Context) error { + result, err := d.redis.HGet(ctx, cachekeys.FeedSANSwitchH, d.idx).Result() + switch err { + case nil: + case redis.Nil: + return fmt.Errorf("HGET: no results") + default: + return fmt.Errorf("HGET: %w", err) + } + if err := json.Unmarshal([]byte(result), &d.data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + return nil +} + +// parse reads the command outputs of the switch, with the parser of its +// type. +func (d *jobFeedSANSwitch) parse(context.Context) error { + switch d.data.Type { + case feeder.Brocade: + s, err := parseBrocade(d.data.Data["switchshow"], d.data.Data["nsshow"], d.data.Data["zoneshow"]) + if err != nil { + return fmt.Errorf("parse %s: %w", d.idx, err) + } + if s.Name == "" { + // The switch did not say its name: keep the one it was + // reached by, as the old collector named it after the + // directory its report was stored in. + s.Name = d.data.Name + } + d.brocade = s + return nil + default: + return fmt.Errorf("unsupported switch type %q", d.data.Type) + } +} + +// updateDB replaces the rows of the switch, of the aliases of each of its +// configurations, and of the zones of its effective configuration, by the +// ones just parsed: the rows written now are upserted, and the older ones +// of the same switch or configuration deleted. +// +// CREATE TABLE `switches` ( +// `id` int(11) NOT NULL AUTO_INCREMENT, +// `sw_name` varchar(64) NOT NULL, +// `sw_slot` int(11) DEFAULT NULL, +// `sw_port` int(11) DEFAULT NULL, +// `sw_portspeed` int(11) DEFAULT NULL, +// `sw_portnego` varchar(1) DEFAULT '', +// `sw_porttype` varchar(16) DEFAULT '', +// `sw_portstate` varchar(16) DEFAULT '', +// `sw_portname` varchar(16) DEFAULT '', +// `sw_rportname` varchar(128) DEFAULT NULL, +// `sw_updated` datetime NOT NULL, +// `sw_fabric` varchar(128) DEFAULT NULL, +// `sw_index` int(11) DEFAULT NULL, +// PRIMARY KEY (`id`), +// UNIQUE KEY `idx1` (`sw_name`,`sw_slot`,`sw_port`,`sw_rportname`), +// KEY `idx2` (`sw_portname`,`sw_rportname`) +// ) +// +// CREATE TABLE `san_zone` ( +// `id` int(11) NOT NULL AUTO_INCREMENT, +// `cfg` varchar(128) DEFAULT '', +// `zone` varchar(128) DEFAULT '', +// `port` varchar(16) DEFAULT '', +// `updated` datetime NOT NULL, +// PRIMARY KEY (`id`), +// UNIQUE KEY `idx1` (`cfg`,`zone`,`port`) +// ) +// +// CREATE TABLE `san_zone_alias` ( +// `id` int(11) NOT NULL AUTO_INCREMENT, +// `cfg` varchar(128) DEFAULT '', +// `alias` varchar(128) DEFAULT '', +// `port` varchar(16) DEFAULT '', +// `updated` datetime NOT NULL, +// PRIMARY KEY (`id`), +// UNIQUE KEY `idx1` (`cfg`,`alias`,`port`) +// ) +func (d *jobFeedSANSwitch) updateDB(ctx context.Context) error { + s := d.brocade + now := d.now + + for cfg, aliases := range s.Alias { + rows := make([]any, 0) + for alias, ports := range aliases { + for _, port := range ports { + rows = append(rows, map[string]any{"cfg": cfg, "alias": alias, "port": port, "updated": now}) + } + } + if err := d.upsert(ctx, "san_zone_alias", []string{"cfg", "alias", "port"}, []string{"cfg", "alias", "port", "updated"}, rows); err != nil { + return err + } + if err := d.deleteOlder(ctx, "san_zone_alias", "cfg", cfg, "updated", now); err != nil { + return err + } + } + + if s.Cfg != "" { + rows := make([]any, 0) + for zone, ports := range s.Zone { + for _, port := range ports { + rows = append(rows, map[string]any{"cfg": s.Cfg, "zone": zone, "port": port, "updated": now}) + } + } + if err := d.upsert(ctx, "san_zone", []string{"cfg", "zone", "port"}, []string{"cfg", "zone", "port", "updated"}, rows); err != nil { + return err + } + if err := d.deleteOlder(ctx, "san_zone", "cfg", s.Cfg, "updated", now); err != nil { + return err + } + } + + rows := s.rows() + for _, row := range rows { + row.(map[string]any)["sw_updated"] = now + } + columns := []string{"sw_name", "sw_portname", "sw_index", "sw_slot", "sw_port", "sw_portspeed", "sw_portnego", "sw_portstate", "sw_porttype", "sw_rportname", "sw_updated"} + if err := d.upsert(ctx, "switches", []string{"sw_name", "sw_slot", "sw_port", "sw_rportname"}, columns, rows); err != nil { + return err + } + return d.deleteOlder(ctx, "switches", "sw_name", s.Name, "sw_updated", now) +} + +// upsert inserts or updates rows in table, on the unique key keys. +func (d *jobFeedSANSwitch) upsert(ctx context.Context, table string, keys, columns []string, rows []any) error { + if len(rows) == 0 { + return nil + } + mappings := make(mariadb.Mappings, len(columns)) + for i, column := range columns { + mappings[i] = mariadb.Mapping{To: column} + } + request := mariadb.InsertOrUpdate{ + Table: table, + Mappings: mappings, + Keys: keys, + Data: rows, + } + if count, err := request.ExecContextAndCountRowsAffected(ctx, d.db); err != nil { + return fmt.Errorf("upsert %s: %w", table, err) + } else if count > 0 { + d.oDb.SetChange(table) + } + return nil +} + +// deleteOlder deletes the rows of table whose column key is value, updated +// before the rows just written. +func (d *jobFeedSANSwitch) deleteOlder(ctx context.Context, table, key string, value any, updated string, now any) error { + query := fmt.Sprintf("DELETE FROM `%s` WHERE `%s` = ? AND `%s` < ?", table, key, updated) + if count, err := d.oDb.ExecContextAndCountRowsAffected(ctx, query, value, now); err != nil { + return fmt.Errorf("query %s: %w", query, err) + } else if count > 0 { + d.oDb.SetChange(table) + } + return nil +} diff --git a/worker/metrics.go b/worker/metrics.go index 942ff185..54d4c1c3 100644 --- a/worker/metrics.go +++ b/worker/metrics.go @@ -15,7 +15,7 @@ var ( Namespace: "oc3", Name: "feed_job_executions_total", Help: fmt.Sprintf("Total number of feed job executions (job_type={%s}, status={%s})", - strings.Join([]string{jtDaemonPing, jtDaemonStatus, jtNodeSystem, jtInstanceAction, jtInstanceResourceInfo, jtInstanceStatus, jtNodeDisk, jtObjectConfig}, "|"), + strings.Join([]string{jtDaemonPing, jtDaemonStatus, jtNodeSystem, jtInstanceAction, jtInstanceResourceInfo, jtInstanceStatus, jtNodeDisk, jtObjectConfig, jtSANSwitch}, "|"), strings.Join([]string{jobStatusFailed, jobStatusOk}, "|")), }, []string{"job_type", "status"}, @@ -27,7 +27,7 @@ var ( Namespace: "oc3", Name: "feed_job_duration_seconds", Help: fmt.Sprintf("Duration of entire feed job executions in seconds (job_type={%s}, status={%s})", - strings.Join([]string{jtDaemonPing, jtDaemonStatus, jtNodeSystem, jtInstanceAction, jtInstanceResourceInfo, jtInstanceStatus, jtNodeDisk, jtObjectConfig}, "|"), + strings.Join([]string{jtDaemonPing, jtDaemonStatus, jtNodeSystem, jtInstanceAction, jtInstanceResourceInfo, jtInstanceStatus, jtNodeDisk, jtObjectConfig, jtSANSwitch}, "|"), strings.Join([]string{jobStatusFailed, jobStatusOk}, "|")), Buckets: prometheus.DefBuckets, }, @@ -40,7 +40,7 @@ var ( Namespace: "oc3", Name: "feed_job_step_duration_seconds", Help: fmt.Sprintf("Duration of individual steps within feed jobs in seconds (job_type={%s}, status={%s}, job_step={main|...}})", - strings.Join([]string{jtDaemonPing, jtDaemonStatus, jtNodeSystem, jtInstanceAction, jtInstanceResourceInfo, jtInstanceStatus, jtNodeDisk, jtObjectConfig}, "|"), + strings.Join([]string{jtDaemonPing, jtDaemonStatus, jtNodeSystem, jtInstanceAction, jtInstanceResourceInfo, jtInstanceStatus, jtNodeDisk, jtObjectConfig, jtSANSwitch}, "|"), strings.Join([]string{jobStatusFailed, jobStatusOk}, "|")), Buckets: prometheus.DefBuckets, }, diff --git a/worker/worker.go b/worker/worker.go index f442d33d..effb9182 100644 --- a/worker/worker.go +++ b/worker/worker.go @@ -74,6 +74,7 @@ const ( jtNodeDisk = "nodeDisk" jtNodeSystem = "nodeSystem" jtObjectConfig = "objectConfig" + jtSANSwitch = "sanSwitch" // job or job step statuses jobStatusOk = "ok" @@ -145,6 +146,14 @@ func (w *Worker) runJob(unqueuedJob []string) error { return fmt.Errorf("invalid feed node disk index expected `nodename`@`nodeID`@`clusterID` found: %s", unqueuedJob[1]) } j = newNodeDisk(l[0], l[1], l[2]) + case cachekeys.FeedSANSwitchQ: + // expected unqueuedJob[1]: @ + if l := strings.SplitN(unqueuedJob[1], "@", 2); len(l) != 2 || l[0] == "" || l[1] == "" { + err := fmt.Errorf("invalid feed san switch index expected `type`@`name` found: %s", unqueuedJob[1]) + slog.Warn(err.Error()) + return err + } + j = newSANSwitch(unqueuedJob[1]) case cachekeys.FeedObjectConfigQ: objectName, nodeID, ClusterID, err := w.jobToInstanceAndClusterID(unqueuedJob[1]) if err != nil { From 93ffff4398b6b9865cd4d0bd4f0ea9305a9ee1a2 Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Tue, 29 Sep 2026 23:14:27 +0200 Subject: [PATCH 59/61] Confine the sysreport files to the node tree, and take full and deletions-only reports The members of a sysreport archive and the deleted files were joined to the tree of the node as given: a name climbing with ".." wrote or removed files out of it. Every path is now rooted at the tree of the node, where a ".." stops, and only the regular files of the archive are written, each closed once written rather than at the end of the request. The archive is optional: a report of the deletions of a node has none, and was refused. A full report, the full field set, holds every file and command output of the node: the files the collector holds for the node and the archive does not are removed, the git history of the tree left alone. It replaces the listing of what the collector holds, which the agent asked the old collector for to compute the deletions of a forced report. --- feeder/api.yaml | 16 +- feeder/codegen_server_gen.go | 97 ++++----- feeder/codegen_type_gen.go | 15 +- feeder/handlers/post_feed_sysreport.go | 205 +++++++++++++------- feeder/handlers/post_feed_sysreport_test.go | 161 +++++++++++++++ 5 files changed, 367 insertions(+), 127 deletions(-) create mode 100644 feeder/handlers/post_feed_sysreport_test.go diff --git a/feeder/api.yaml b/feeder/api.yaml index 4f137f84..754dca9e 100644 --- a/feeder/api.yaml +++ b/feeder/api.yaml @@ -830,17 +830,27 @@ components: SysReport: type: object - required: - - deleted - - file properties: deleted: type: array items: type: string + description: | + the tracked files deleted on the node since its last report, as + their paths on the node file: type: string format: binary + description: | + a tar of the files and command outputs changed since the last + report, each member named /file/ or + /cmd/. A report of deletions only has none. + full: + type: boolean + description: | + the archive holds every file and command output of the node: the + ones the collector holds for the node and the archive does not + are removed PostChecks: type: object diff --git a/feeder/codegen_server_gen.go b/feeder/codegen_server_gen.go index a3673c4d..9f9c7bb5 100644 --- a/feeder/codegen_server_gen.go +++ b/feeder/codegen_server_gen.go @@ -372,53 +372,56 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "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", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/feeder/codegen_type_gen.go b/feeder/codegen_type_gen.go index b40d5188..afb62737 100644 --- a/feeder/codegen_type_gen.go +++ b/feeder/codegen_type_gen.go @@ -227,8 +227,19 @@ type SANSwitchType string // SysReport defines model for SysReport. type SysReport struct { - Deleted []string `json:"deleted"` - File openapi_types.File `json:"file"` + // Deleted the tracked files deleted on the node since its last report, as + // their paths on the node + Deleted *[]string `json:"deleted,omitempty"` + + // File a tar of the files and command outputs changed since the last + // report, each member named /file/ or + // /cmd/. A report of deletions only has none. + File *openapi_types.File `json:"file,omitempty"` + + // Full the archive holds every file and command output of the node: the + // ones the collector holds for the node and the archive does not + // are removed + Full *bool `json:"full,omitempty"` } // Package defines model for package. diff --git a/feeder/handlers/post_feed_sysreport.go b/feeder/handlers/post_feed_sysreport.go index 102c5d4a..656a2fd3 100644 --- a/feeder/handlers/post_feed_sysreport.go +++ b/feeder/handlers/post_feed_sysreport.go @@ -3,18 +3,20 @@ package feederhandlers import ( "archive/tar" "encoding/json" + "fmt" "io" "io/fs" "log/slog" + "mime/multipart" "net/http" "os" "path/filepath" + "strconv" "strings" "github.com/labstack/echo/v4" "github.com/opensvc/oc3/cachekeys" - "github.com/opensvc/oc3/feeder" "github.com/opensvc/oc3/util/echolog" "github.com/opensvc/oc3/util/logkey" @@ -27,37 +29,68 @@ type sysreportData struct { NodeID string `json:"node_id"` } +// PostNodeSysReport stores the files and command outputs a node tracks, as +// the tree /sysreport//{file,cmd}/..., and queues the +// commit of the tree the scheduler versions. +// +// The form carries the tar of what changed, the tracked files deleted, and +// the full flag of a report holding everything the node tracks. A report of +// deletions only has no tar. +// +// Every path is confined to the tree of the node: a member or a deleted path +// climbing out of it with ".." lands inside it, as rooted there. func (a *Api) PostNodeSysReport(ctx echo.Context) error { log := echolog.GetLogHandler(ctx, "PostNodeSysReport") - file, err := ctx.FormFile("file") + nodeID, ok := ctx.Get(XNodeID).(string) + if !ok || nodeID == "" { + return JSONNodeAuthProblem(ctx) + } + form, err := ctx.MultipartForm() if err != nil { - return JSONProblemf(ctx, http.StatusBadRequest, "FormFile: %s", err) + return JSONProblemf(ctx, http.StatusBadRequest, "multipart form: %s", err) } - - var payload feeder.SysReport - if values, ok := ctx.Request().MultipartForm.Value["deleted"]; ok { - payload.Deleted = values + deleted := form.Value["deleted"] + full := false + if l := form.Value["full"]; len(l) > 0 { + if full, err = strconv.ParseBool(l[0]); err != nil { + return JSONProblemf(ctx, http.StatusBadRequest, "full: %s", err) + } + } + var file *multipart.FileHeader + if l := form.File["file"]; len(l) > 0 { + file = l[0] + } + if file == nil && full { + return JSONProblem(ctx, http.StatusBadRequest, "a full report needs its archive") } - payload.File.InitFromMultipart(file) uploadDir := viper.GetString("scheduler.directories.uploads") - sysreportDir := filepath.Join(uploadDir, "sysreport") - if err := os.MkdirAll(sysreportDir, 0755); err != nil { + nodeDir := filepath.Join(uploadDir, "sysreport", nodeID) + if err := os.MkdirAll(nodeDir, 0755); err != nil { log.Error("can't create sysreport dir", logkey.Error, err) return JSONProblem(ctx, http.StatusInternalServerError, "can't create sysreport dir") } - nodeID := ctx.Get(XNodeID).(string) - - needCommit := false - needCommit = sendSysreportDelete(log, payload.Deleted, sysreportDir, nodeID) || needCommit - needCommit = sendSysreportArchive(log, payload, file.Filename, sysreportDir, nodeID) || needCommit - - // TODO: Add metric PostNodeSysReport File size + needCommit := sysreportDelete(log, deleted, nodeDir) + if file != nil { + written, err := sysreportExtract(file, nodeDir) + if err != nil { + log.Error("sysreportExtract", logkey.Error, err) + return JSONProblemf(ctx, http.StatusBadRequest, "archive: %s", err) + } + if len(written) > 0 { + needCommit = true + } + if full { + if n := sysreportRemoveOthers(log, nodeDir, written); n > 0 { + needCommit = true + } + } + } v := sysreportData{ NeedCommit: needCommit, - Deleted: payload.Deleted, + Deleted: deleted, NodeID: nodeID, } if b, err := json.Marshal(v); err != nil { @@ -71,44 +104,45 @@ func (a *Api) PostNodeSysReport(ctx echo.Context) error { return ctx.JSON(http.StatusAccepted, "sysreport accepted") } -func sendSysreportDelete(l *slog.Logger, deleted []string, sysreportDir string, nodeID string) bool { +// confine returns the path rel names inside base, rel rooted at base: a rel +// climbing with ".." stops at base, and never leaves it. +func confine(base, rel string) string { + return filepath.Join(base, filepath.Clean("/"+rel)) +} + +// sysreportDelete removes the files of the node tree the node deleted, +// named by their path on the node, and says whether it was given any. +func sysreportDelete(l *slog.Logger, deleted []string, nodeDir string) bool { if len(deleted) == 0 { return false } - nodeDir := filepath.Join(sysreportDir, nodeID) + fileDir := filepath.Join(nodeDir, "file") for _, fpath := range deleted { fpath = strings.TrimSpace(fpath) - var relpath string - if filepath.IsAbs(fpath) { - relpath = "file" + fpath - } else { - relpath = filepath.Join("file", fpath) + if fpath == "" { + continue } - pathToDelete := filepath.Join(nodeDir, relpath) - if err := os.Remove(pathToDelete); err != nil && !os.IsNotExist(err) { - l.Warn("sendSysreportDelete", logkey.Error, err) + if err := os.Remove(confine(fileDir, fpath)); err != nil && !os.IsNotExist(err) { + l.Warn("sysreportDelete", logkey.Error, err) } } return true } -func sendSysreportArchive(l *slog.Logger, payload feeder.SysReport, filename string, sysreportDir string, nodeID string) bool { - if filename == "" { - return false - } - fPath := filepath.Join(sysreportDir, filename) - - if !strings.HasSuffix(fPath, ".tar") { - return false - } - - reader, err := payload.File.Reader() +// sysreportExtract writes the regular files of the archive in the node tree, +// the first component of their name, the node name, replaced by the tree, +// and returns the paths written. Each file is closed once written. +func sysreportExtract(file *multipart.FileHeader, nodeDir string) (map[string]bool, error) { + reader, err := file.Open() if err != nil { - l.Error("sendSysreportArchive", logkey.Error, err) - return false + return nil, err } defer reader.Close() + return sysreportExtractReader(reader, nodeDir) +} +func sysreportExtractReader(reader io.Reader, nodeDir string) (map[string]bool, error) { + written := make(map[string]bool) tr := tar.NewReader(reader) for { header, err := tr.Next() @@ -116,46 +150,67 @@ func sendSysreportArchive(l *slog.Logger, payload feeder.SysReport, filename str break } if err != nil { - l.Error("sendSysreportArchive", logkey.Error, err) - return false + return written, err } - idx := strings.Index(header.Name, "/") - if idx == -1 { + if header.Typeflag != tar.TypeReg { continue } - targetName := nodeID + header.Name[idx:] - targetPath := filepath.Join(sysreportDir, targetName) - - if info, err := os.Stat(targetPath); err == nil { - // enable write - _ = os.Chmod(targetPath, info.Mode()|0200) - } - - if err := os.MkdirAll(filepath.Dir(targetPath), 0755); err != nil { - l.Error("sendSysreportArchive", logkey.Error, err) - return false - } - - outFile, err := os.OpenFile(targetPath, os.O_CREATE|os.O_RDWR|os.O_TRUNC, fs.FileMode(header.Mode)) - if err != nil { - l.Error("sendSysreportArchive OpenFile", logkey.Error, err) - return false - } else { - defer func() { - _ = outFile.Close() - }() + _, rel, ok := strings.Cut(header.Name, "/") + if !ok || rel == "" { + continue } - - if _, err := io.Copy(outFile, tr); err != nil { - l.Error("sendSysreportArchive Copy", logkey.Error, err) - return false + targetPath := confine(nodeDir, rel) + if err := writeSysreportFile(targetPath, fs.FileMode(header.Mode).Perm(), tr); err != nil { + return written, err } + written[targetPath] = true + } + return written, nil +} - if info, err := os.Stat(targetPath); err == nil { - // restore read only - _ = os.Chmod(targetPath, info.Mode()|0400) - } +func writeSysreportFile(targetPath string, mode fs.FileMode, r io.Reader) error { + if info, err := os.Stat(targetPath); err == nil { + // enable write + _ = os.Chmod(targetPath, info.Mode()|0200) + } + if err := os.MkdirAll(filepath.Dir(targetPath), 0755); err != nil { + return err + } + f, err := os.OpenFile(targetPath, os.O_CREATE|os.O_RDWR|os.O_TRUNC, mode|0600) + if err != nil { + return fmt.Errorf("open %s: %w", targetPath, err) + } + if _, err := io.Copy(f, r); err != nil { + _ = f.Close() + return fmt.Errorf("write %s: %w", targetPath, err) + } + if err := f.Close(); err != nil { + return fmt.Errorf("close %s: %w", targetPath, err) + } + return os.Chmod(targetPath, mode|0400) +} +// sysreportRemoveOthers removes the files of the node tree a full report does +// not hold, and returns how many it removed. The git history of the tree is +// left alone. +func sysreportRemoveOthers(l *slog.Logger, nodeDir string, written map[string]bool) int { + n := 0 + for _, sub := range []string{"file", "cmd"} { + root := filepath.Join(nodeDir, sub) + _ = filepath.WalkDir(root, func(path string, d fs.DirEntry, err error) error { + if err != nil { + return nil + } + if d.IsDir() || written[path] { + return nil + } + if err := os.Remove(path); err != nil { + l.Warn("sysreportRemoveOthers", logkey.Error, err) + return nil + } + n++ + return nil + }) } - return true + return n } diff --git a/feeder/handlers/post_feed_sysreport_test.go b/feeder/handlers/post_feed_sysreport_test.go new file mode 100644 index 00000000..9a0e36b2 --- /dev/null +++ b/feeder/handlers/post_feed_sysreport_test.go @@ -0,0 +1,161 @@ +package feederhandlers + +import ( + "archive/tar" + "bytes" + "log/slog" + "os" + "path/filepath" + "strings" + "testing" +) + +func testTar(t *testing.T, entries map[string]string, symlinks map[string]string) *bytes.Buffer { + t.Helper() + var buf bytes.Buffer + tw := tar.NewWriter(&buf) + for name, content := range entries { + if err := tw.WriteHeader(&tar.Header{Name: name, Mode: 0644, Size: int64(len(content)), Typeflag: tar.TypeReg}); err != nil { + t.Fatal(err) + } + if _, err := tw.Write([]byte(content)); err != nil { + t.Fatal(err) + } + } + for name, target := range symlinks { + if err := tw.WriteHeader(&tar.Header{Name: name, Linkname: target, Typeflag: tar.TypeSymlink}); err != nil { + t.Fatal(err) + } + } + if err := tw.Close(); err != nil { + t.Fatal(err) + } + return &buf +} + +func readFile(t *testing.T, p string) string { + t.Helper() + b, err := os.ReadFile(p) + if err != nil { + t.Fatalf("read %s: %s", p, err) + } + return string(b) +} + +// A path climbing out of the base with ".." stops at the base. +func TestConfine(t *testing.T) { + for rel, want := range map[string]string{ + "file/etc/hosts": "/base/file/etc/hosts", + "/etc/hosts": "/base/etc/hosts", + "../../etc/passwd": "/base/etc/passwd", + "file/../../../etc/shadow": "/base/etc/shadow", + } { + if got := confine("/base", rel); got != want { + t.Errorf("%s: got %s, want %s", rel, got, want) + } + } +} + +// The members of the archive land in the node tree, the node name replaced +// by it, a member climbing with ".." included, and a symlink is not written. +func TestSysreportExtract(t *testing.T) { + root := t.TempDir() + nodeDir := filepath.Join(root, "sysreport", "node1") + archive := testTar(t, map[string]string{ + "dev2n1/file/etc/hosts": "hosts", + "dev2n1/cmd/uname": "Linux", + "dev2n1/../../../escaped": "escaped", + "dev2n1/file/../../../../outer": "outer", + }, map[string]string{ + "dev2n1/file/etc/link": "/etc/shadow", + }) + written, err := sysreportExtractReader(archive, nodeDir) + if err != nil { + t.Fatal(err) + } + if got := readFile(t, filepath.Join(nodeDir, "file/etc/hosts")); got != "hosts" { + t.Errorf("hosts: %q", got) + } + if got := readFile(t, filepath.Join(nodeDir, "cmd/uname")); got != "Linux" { + t.Errorf("uname: %q", got) + } + for _, p := range []string{filepath.Join(root, "escaped"), filepath.Join(root, "outer"), filepath.Join(filepath.Dir(root), "outer")} { + if _, err := os.Stat(p); err == nil { + t.Errorf("%s written out of the node tree", p) + } + } + if _, err := os.Lstat(filepath.Join(nodeDir, "file/etc/link")); err == nil { + t.Error("a symlink member is written") + } + for p := range written { + if !strings.HasPrefix(p, nodeDir+"/") { + t.Errorf("%s written out of the node tree", p) + } + } +} + +// The deleted files are removed from the file tree of the node, and a path +// climbing with ".." does not reach out of it. +func TestSysreportDelete(t *testing.T) { + root := t.TempDir() + nodeDir := filepath.Join(root, "sysreport", "node1") + victim := filepath.Join(root, "victim") + if err := os.WriteFile(victim, []byte("x"), 0644); err != nil { + t.Fatal(err) + } + if _, err := sysreportExtractReader(testTar(t, map[string]string{"n/file/etc/motd": "hi"}, nil), nodeDir); err != nil { + t.Fatal(err) + } + log := slog.Default() + if !sysreportDelete(log, []string{"/etc/motd", "../../../victim"}, nodeDir) { + t.Error("deletions not reported") + } + if _, err := os.Stat(filepath.Join(nodeDir, "file/etc/motd")); err == nil { + t.Error("deleted file still there") + } + if _, err := os.Stat(victim); err != nil { + t.Error("a file out of the node tree was deleted") + } + if sysreportDelete(log, nil, nodeDir) { + t.Error("no deletion reported as one") + } +} + +// A full report removes the files the node no longer holds, and leaves the +// git history alone. +func TestSysreportRemoveOthers(t *testing.T) { + nodeDir := filepath.Join(t.TempDir(), "sysreport", "node1") + if _, err := sysreportExtractReader(testTar(t, map[string]string{ + "n/file/etc/old": "old", + "n/cmd/oldcmd": "old", + }, nil), nodeDir); err != nil { + t.Fatal(err) + } + gitFile := filepath.Join(nodeDir, ".git", "HEAD") + if err := os.MkdirAll(filepath.Dir(gitFile), 0755); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(gitFile, []byte("ref"), 0644); err != nil { + t.Fatal(err) + } + written, err := sysreportExtractReader(testTar(t, map[string]string{ + "n/file/etc/new": "new", + "n/cmd/newcmd": "new", + }, nil), nodeDir) + if err != nil { + t.Fatal(err) + } + if n := sysreportRemoveOthers(slog.Default(), nodeDir, written); n != 2 { + t.Errorf("removed %d files, want 2", n) + } + for _, p := range []string{"file/etc/old", "cmd/oldcmd"} { + if _, err := os.Stat(filepath.Join(nodeDir, p)); err == nil { + t.Errorf("%s not removed", p) + } + } + for _, p := range []string{"file/etc/new", "cmd/newcmd", ".git/HEAD"} { + if _, err := os.Stat(filepath.Join(nodeDir, p)); err != nil { + t.Errorf("%s removed", p) + } + } +} From 405ff546cb38a10e8379910c8e3fc84cd3dd7d18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Tue, 29 Sep 2026 23:23:54 +0200 Subject: [PATCH 60/61] Let users change their own name and email POST /users/{user_id} changes the first name, last name or email of the signed-in user, as the profile form of the historical collector allows: only the caller's own account, without privilege. Names are trimmed and at most 128 characters; the email must be a valid address, at most 512 characters and not used by another user. The change is logged with the fields changed, and the old and new email. --- cdb/db_users.go | 33 ++++++++ server/api.yaml | 58 ++++++++++++++ server/codegen_server_gen.go | 109 ++++++++++++++++---------- server/codegen_type_gen.go | 10 +++ server/handlers/post_user.go | 146 +++++++++++++++++++++++++++++++++++ 5 files changed, 316 insertions(+), 40 deletions(-) create mode 100644 server/handlers/post_user.go diff --git a/cdb/db_users.go b/cdb/db_users.go index b7cab321..ed636011 100644 --- a/cdb/db_users.go +++ b/cdb/db_users.go @@ -359,3 +359,36 @@ func (oDb *DB) SetUserPassword(ctx context.Context, userID int64, hash string) e oDb.SetChange("auth_user") return nil } + +// UserIdentity is what a user may change about themselves: their name and email. +type UserIdentity struct { + FirstName string + LastName string + Email string +} + +// GetUserIdentity returns the name and email of a user; false when there is no +// such user. +func (oDb *DB) GetUserIdentity(ctx context.Context, userID int64) (UserIdentity, bool, error) { + var first, last, email sql.NullString + err := oDb.DB.QueryRowContext(ctx, + "SELECT first_name, last_name, email FROM auth_user WHERE id = ?", userID).Scan(&first, &last, &email) + switch { + case errors.Is(err, sql.ErrNoRows): + return UserIdentity{}, false, nil + case err != nil: + return UserIdentity{}, false, fmt.Errorf("getUserIdentity: %w", err) + } + return UserIdentity{FirstName: first.String, LastName: last.String, Email: email.String}, true, nil +} + +// SetUserIdentity stores the name and email of a user. +func (oDb *DB) SetUserIdentity(ctx context.Context, userID int64, u UserIdentity) error { + if _, err := oDb.DB.ExecContext(ctx, + "UPDATE auth_user SET first_name = ?, last_name = ?, email = ? WHERE id = ?", + u.FirstName, u.LastName, u.Email, userID); err != nil { + return fmt.Errorf("setUserIdentity: %w", err) + } + oDb.SetChange("auth_user") + return nil +} diff --git a/server/api.yaml b/server/api.yaml index e7fab3fb..41b7998c 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -8839,6 +8839,64 @@ paths: security: - basicAuth: [ ] - bearerAuth: [ ] + post: + operationId: PostUser + description: | + Change the first name, last name or email of the signed-in user, as the + profile form of the historical collector: `user_id` must designate the caller + ("self", their id or their email), another user's account is refused with a + 403. Only the keys given are changed; names are trimmed, at most 128 + characters, and may be empty. The email must be a valid address, at most 512 + characters, not used by another user (409): it is the sign-in name, so the + next requests must authenticate with it. The change is logged with the fields + changed. Requires user authentication, no privilege. Returns the user. + parameters: + - in: path + name: user_id + required: true + description: The caller, as "self", their auth_user.id or their email. + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + first_name: + type: string + maxLength: 128 + last_name: + type: string + maxLength: 128 + email: + type: string + maxLength: 512 + tags: + - collector + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/UserListResponse' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' + 409: + $ref: '#/components/responses/409' + 500: + $ref: '#/components/responses/500' + security: + - basicAuth: [ ] + - bearerAuth: [ ] /users/{user_id}/prefs: get: diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index cb5956cc..a26a4152 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -945,6 +945,9 @@ type ServerInterface interface { // (GET /users/{user_id}) GetUser(ctx echo.Context, userId string, params GetUserParams) error + // (POST /users/{user_id}) + PostUser(ctx echo.Context, userId string) error + // (GET /users/{user_id}/prefs) GetUserPrefs(ctx echo.Context, userId string) error @@ -13460,6 +13463,26 @@ func (w *ServerInterfaceWrapper) GetUser(ctx echo.Context) error { return err } +// PostUser converts echo context to params. +func (w *ServerInterfaceWrapper) PostUser(ctx echo.Context) error { + var err error + // ------------- Path parameter "user_id" ------------- + var userId string + + err = runtime.BindStyledParameterWithOptions("simple", "user_id", ctx.Param("user_id"), &userId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: ""}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter user_id: %s", err)) + } + + ctx.Set(string(BasicAuthScopes), []string{}) + + ctx.Set(string(BearerAuthScopes), []string{}) + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostUser(ctx, userId) + return err +} + // GetUserPrefs converts echo context to params. func (w *ServerInterfaceWrapper) GetUserPrefs(ctx echo.Context) error { var err error @@ -13942,6 +13965,7 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options router.POST(options.BaseURL+"/users", wrapper.PostUsers, options.OperationMiddlewares["PostUsers"]...) router.POST(options.BaseURL+"/users/self/password", wrapper.PostUserSelfPassword, options.OperationMiddlewares["PostUserSelfPassword"]...) router.GET(options.BaseURL+"/users/:user_id", wrapper.GetUser, options.OperationMiddlewares["GetUser"]...) + router.POST(options.BaseURL+"/users/:user_id", wrapper.PostUser, options.OperationMiddlewares["PostUser"]...) router.GET(options.BaseURL+"/users/:user_id/prefs", wrapper.GetUserPrefs, options.OperationMiddlewares["GetUserPrefs"]...) router.POST(options.BaseURL+"/users/:user_id/prefs", wrapper.PostUserPrefs, options.OperationMiddlewares["PostUserPrefs"]...) router.GET(options.BaseURL+"/version", wrapper.GetVersion, options.OperationMiddlewares["GetVersion"]...) @@ -14376,46 +14400,51 @@ var swaggerSpec = []string{ "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", + "8PZtHI2j5gF7KlUMrgajR4PP7z//PwAA//8=", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/codegen_type_gen.go b/server/codegen_type_gen.go index 8cffc5a9..9f427304 100644 --- a/server/codegen_type_gen.go +++ b/server/codegen_type_gen.go @@ -6985,6 +6985,13 @@ type GetUserParams struct { Groupby *InQueryGroupby `form:"groupby,omitempty" json:"groupby,omitempty"` } +// PostUserJSONBody defines parameters for PostUser. +type PostUserJSONBody struct { + Email *string `json:"email,omitempty"` + FirstName *string `json:"first_name,omitempty"` + LastName *string `json:"last_name,omitempty"` +} + // PostUserPrefsJSONBody defines parameters for PostUserPrefs. type PostUserPrefsJSONBody struct { // Data The preferences object, stored verbatim. @@ -7348,6 +7355,9 @@ type PostUsersJSONRequestBody PostUsersJSONBody // PostUserSelfPasswordJSONRequestBody defines body for PostUserSelfPassword for application/json ContentType. type PostUserSelfPasswordJSONRequestBody PostUserSelfPasswordJSONBody +// PostUserJSONRequestBody defines body for PostUser for application/json ContentType. +type PostUserJSONRequestBody PostUserJSONBody + // PostUserPrefsJSONRequestBody defines body for PostUserPrefs for application/json ContentType. type PostUserPrefsJSONRequestBody PostUserPrefsJSONBody diff --git a/server/handlers/post_user.go b/server/handlers/post_user.go new file mode 100644 index 00000000..0862bbb2 --- /dev/null +++ b/server/handlers/post_user.go @@ -0,0 +1,146 @@ +package serverhandlers + +import ( + "context" + "net/http" + "net/mail" + "strconv" + "strings" + "unicode/utf8" + + "github.com/labstack/echo/v4" + + "github.com/opensvc/oc3/cdb" + "github.com/opensvc/oc3/server" + "github.com/opensvc/oc3/util/echolog" + "github.com/opensvc/oc3/util/logkey" +) + +// The widths of the auth_user columns. +const ( + maxUserNameLength = 128 + maxUserEmailLength = 512 +) + +// PostUser handles POST /users/{user_id}: the caller changes their own first +// name, last name or email, as the profile form of the historical collector +// allows any signed-in user to. Another user's account is refused: changing it +// is the UserManager's, not ported yet. The email is the sign-in name, unique +// among users; the change is logged with the fields changed. +func (a *Api) PostUser(c echo.Context, userId string) error { + log := echolog.GetLogHandler(c, "PostUser") + ctx, cancel := context.WithTimeout(c.Request().Context(), a.SyncTimeout) + defer cancel() + odb := a.ODB + + if !IsAuthByUser(c) { + return JSONProblemf(c, http.StatusUnauthorized, "user authentication required") + } + selfID := authUserID(c) + if selfID == nil { + return JSONProblemf(c, http.StatusUnauthorized, "user authentication required") + } + callerEmail, _ := c.Get(XUserEmail).(string) + if userId != "self" && userId != strconv.FormatInt(*selfID, 10) && userId != callerEmail { + return JSONProblemf(c, http.StatusForbidden, "only your own account can be changed") + } + + var body server.PostUserJSONRequestBody + if err := c.Bind(&body); err != nil { + return JSONProblem(c, http.StatusBadRequest, err.Error()) + } + + current, found, err := odb.GetUserIdentity(ctx, *selfID) + if err != nil { + log.Error("cannot read user", logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot read the user") + } + if !found { + return JSONProblemf(c, http.StatusNotFound, "user %d not found", *selfID) + } + + next := current + var changed []string + // setName applies a name given in the body, false when it is too long. + setName := func(field string, value *string, target *string) bool { + if value == nil { + return true + } + v := strings.TrimSpace(*value) + if utf8.RuneCountInString(v) > maxUserNameLength { + return false + } + if v != *target { + *target = v + changed = append(changed, field) + } + return true + } + for _, name := range []struct { + field string + value *string + target *string + }{ + {"first_name", body.FirstName, &next.FirstName}, + {"last_name", body.LastName, &next.LastName}, + } { + if !setName(name.field, name.value, name.target) { + return JSONProblemf(c, http.StatusBadRequest, "%s must be at most %d characters long", name.field, maxUserNameLength) + } + } + if body.Email != nil { + email := strings.TrimSpace(*body.Email) + if addr, err := mail.ParseAddress(email); err != nil || addr.Address != email { + return JSONProblemf(c, http.StatusBadRequest, "email must be a valid address, got %q", *body.Email) + } + if utf8.RuneCountInString(email) > maxUserEmailLength { + return JSONProblemf(c, http.StatusBadRequest, "email must be at most %d characters long", maxUserEmailLength) + } + if !strings.EqualFold(email, current.Email) { + otherID, taken, err := odb.UserIDByEmail(ctx, email) + if err != nil { + log.Error("cannot check email", logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot check email") + } + if taken && otherID != *selfID { + return JSONProblemf(c, http.StatusConflict, "another user already has the email %s", email) + } + } + if email != current.Email { + next.Email = email + changed = append(changed, "email") + } + } + + if len(changed) > 0 { + if err := odb.SetUserIdentity(ctx, *selfID, next); err != nil { + log.Error("cannot store user", logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot store the user") + } + format := "change user %(email)s: %(fields)s" + dict := map[string]any{"email": current.Email, "fields": strings.Join(changed, ", ")} + if next.Email != current.Email { + format = "change user %(email)s: %(fields)s, email now %(new_email)s" + dict["new_email"] = next.Email + } + if logErr := odb.Log(ctx, cdb.LogEntry{ + Action: "user.change", + User: callerEmail, + Fmt: format, + Dict: dict, + Level: "info", + }); logErr != nil { + log.Error("cannot write audit log", logkey.Error, logErr) + } + if err := odb.Session.NotifyChanges(ctx); err != nil { + log.Error("cannot notify changes", logkey.Error, err) + } + log.Info("user changed", "fields", strings.Join(changed, ",")) + } + + id := strconv.FormatInt(*selfID, 10) + return a.handleItem(c, "PostUser", "user", "user_id", id, listEndpointParams{props: &userCreatedProps, withUserID: true}, + func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { + return odb.GetUser(ctx, id, p) + }) +} From 8a14f4cfec105745c2d5a4862ba8ca219fc4516b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guih=C3=A9neuf?= Date: Tue, 29 Sep 2026 23:31:27 +0200 Subject: [PATCH 61/61] Let UserManagers change other users' name and email POST /users/{user_id} now changes another user's first name, last name or email when the caller has the UserManager privilege, or is a Manager, as rest_post_user did. Other callers are refused with a 403, an unknown user with a 404. --- server/api.yaml | 14 +++--- server/codegen_server_gen.go | 90 ++++++++++++++++++------------------ server/handlers/post_user.go | 36 ++++++++++----- 3 files changed, 78 insertions(+), 62 deletions(-) diff --git a/server/api.yaml b/server/api.yaml index 41b7998c..ef92bdac 100644 --- a/server/api.yaml +++ b/server/api.yaml @@ -8842,19 +8842,21 @@ paths: post: operationId: PostUser description: | - Change the first name, last name or email of the signed-in user, as the - profile form of the historical collector: `user_id` must designate the caller - ("self", their id or their email), another user's account is refused with a - 403. Only the keys given are changed; names are trimmed, at most 128 + Change the first name, last name or email of a user. Any signed-in user may + change their own, as the profile form of the historical collector allows; + another user's requires the UserManager privilege (or Manager), else 403. + Only the keys given are changed; names are trimmed, at most 128 characters, and may be empty. The email must be a valid address, at most 512 characters, not used by another user (409): it is the sign-in name, so the next requests must authenticate with it. The change is logged with the fields - changed. Requires user authentication, no privilege. Returns the user. + changed. Requires user authentication. Returns the user. parameters: - in: path name: user_id required: true - description: The caller, as "self", their auth_user.id or their email. + description: | + User identifier: auth_user.id, the user email when it contains an + "@", or "self" for the authenticated user. schema: type: string requestBody: diff --git a/server/codegen_server_gen.go b/server/codegen_server_gen.go index a26a4152..3c260793 100644 --- a/server/codegen_server_gen.go +++ b/server/codegen_server_gen.go @@ -14400,51 +14400,51 @@ var swaggerSpec = []string{ "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", - "8PZtHI2j5gF7KlUMrgajR4PP7z//PwAA//8=", + "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", + "D9hTqWJwMRg9Hnz9+PX/AQAA//8=", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/server/handlers/post_user.go b/server/handlers/post_user.go index 0862bbb2..3f406f49 100644 --- a/server/handlers/post_user.go +++ b/server/handlers/post_user.go @@ -22,11 +22,11 @@ const ( maxUserEmailLength = 512 ) -// PostUser handles POST /users/{user_id}: the caller changes their own first -// name, last name or email, as the profile form of the historical collector -// allows any signed-in user to. Another user's account is refused: changing it -// is the UserManager's, not ported yet. The email is the sign-in name, unique -// among users; the change is logged with the fields changed. +// PostUser handles POST /users/{user_id}: the first name, last name or email of +// a user. Any signed-in user may change their own, as the profile form of the +// historical collector allows; another user's requires the UserManager +// privilege (or Manager), as rest_post_user did. The email is the sign-in name, +// unique among users; the change is logged with the fields changed. func (a *Api) PostUser(c echo.Context, userId string) error { log := echolog.GetLogHandler(c, "PostUser") ctx, cancel := context.WithTimeout(c.Request().Context(), a.SyncTimeout) @@ -41,8 +41,22 @@ func (a *Api) PostUser(c echo.Context, userId string) error { return JSONProblemf(c, http.StatusUnauthorized, "user authentication required") } callerEmail, _ := c.Get(XUserEmail).(string) + targetID := *selfID if userId != "self" && userId != strconv.FormatInt(*selfID, 10) && userId != callerEmail { - return JSONProblemf(c, http.StatusForbidden, "only your own account can be changed") + if !IsManager(c) && !HasGroup(c, "UserManager") { + return JSONProblemf(c, http.StatusForbidden, "the UserManager privilege is required to change another user") + } + id, found, err := odb.UserIDForPrefs(ctx, userId, cdb.ListParams{ + Groups: UserGroupsFromContext(c), IsManager: IsManager(c), UserID: selfID, + }) + if err != nil { + log.Error("cannot resolve user", logkey.Error, err) + return JSONProblemf(c, http.StatusInternalServerError, "cannot resolve the user") + } + if !found { + return JSONProblemf(c, http.StatusNotFound, "user %s not found", userId) + } + targetID = id } var body server.PostUserJSONRequestBody @@ -50,13 +64,13 @@ func (a *Api) PostUser(c echo.Context, userId string) error { return JSONProblem(c, http.StatusBadRequest, err.Error()) } - current, found, err := odb.GetUserIdentity(ctx, *selfID) + current, found, err := odb.GetUserIdentity(ctx, targetID) if err != nil { log.Error("cannot read user", logkey.Error, err) return JSONProblemf(c, http.StatusInternalServerError, "cannot read the user") } if !found { - return JSONProblemf(c, http.StatusNotFound, "user %d not found", *selfID) + return JSONProblemf(c, http.StatusNotFound, "user %d not found", targetID) } next := current @@ -102,7 +116,7 @@ func (a *Api) PostUser(c echo.Context, userId string) error { log.Error("cannot check email", logkey.Error, err) return JSONProblemf(c, http.StatusInternalServerError, "cannot check email") } - if taken && otherID != *selfID { + if taken && otherID != targetID { return JSONProblemf(c, http.StatusConflict, "another user already has the email %s", email) } } @@ -113,7 +127,7 @@ func (a *Api) PostUser(c echo.Context, userId string) error { } if len(changed) > 0 { - if err := odb.SetUserIdentity(ctx, *selfID, next); err != nil { + if err := odb.SetUserIdentity(ctx, targetID, next); err != nil { log.Error("cannot store user", logkey.Error, err) return JSONProblemf(c, http.StatusInternalServerError, "cannot store the user") } @@ -138,7 +152,7 @@ func (a *Api) PostUser(c echo.Context, userId string) error { log.Info("user changed", "fields", strings.Join(changed, ",")) } - id := strconv.FormatInt(*selfID, 10) + id := strconv.FormatInt(targetID, 10) return a.handleItem(c, "PostUser", "user", "user_id", id, listEndpointParams{props: &userCreatedProps, withUserID: true}, func(ctx context.Context, p cdb.ListParams) ([]map[string]any, error) { return odb.GetUser(ctx, id, p)