diff --git a/pkg/api/oas_client_gen.go b/pkg/api/oas_client_gen.go index 386cacd..7df265d 100644 --- a/pkg/api/oas_client_gen.go +++ b/pkg/api/oas_client_gen.go @@ -88,7 +88,7 @@ type Invoker interface { // // Delete the specified script policy by ID. // - // DELETE /script-policy/id/{ScriptPolicyID} + // DELETE /script-policy/{ScriptPolicyID} DeleteScriptPolicy(ctx context.Context, params DeleteScriptPolicyParams) error // GetScript invokes getScript operation. // @@ -100,14 +100,8 @@ type Invoker interface { // // Get the specified script policy by ID. // - // GET /script-policy/id/{ScriptPolicyID} + // GET /script-policy/{ScriptPolicyID} GetScriptPolicy(ctx context.Context, params GetScriptPolicyParams) (*ScriptPolicy, error) - // GetScriptPolicyFromHash invokes getScriptPolicyFromHash operation. - // - // Get the policy for the given hash of script source code. - // - // GET /script-policy/hash/{FromScriptHash} - GetScriptPolicyFromHash(ctx context.Context, params GetScriptPolicyFromHashParams) (*ScriptPolicy, error) // GetSubmission invokes getSubmission operation. // // Retrieve map with ID. @@ -120,6 +114,12 @@ type Invoker interface { // // GET /script-policy ListScriptPolicy(ctx context.Context, params ListScriptPolicyParams) ([]ScriptPolicy, error) + // ListScripts invokes listScripts operation. + // + // Get list of scripts. + // + // GET /scripts + ListScripts(ctx context.Context, params ListScriptsParams) ([]Script, error) // ListSubmissions invokes listSubmissions operation. // // Get list of submissions. @@ -142,7 +142,7 @@ type Invoker interface { // // Update the specified script policy by ID. // - // POST /script-policy/id/{ScriptPolicyID} + // POST /script-policy/{ScriptPolicyID} UpdateScriptPolicy(ctx context.Context, request *ScriptPolicyUpdate, params UpdateScriptPolicyParams) error // UpdateSubmissionModel invokes updateSubmissionModel operation. // @@ -1401,7 +1401,7 @@ func (c *Client) sendDeleteScript(ctx context.Context, params DeleteScriptParams // // Delete the specified script policy by ID. // -// DELETE /script-policy/id/{ScriptPolicyID} +// DELETE /script-policy/{ScriptPolicyID} func (c *Client) DeleteScriptPolicy(ctx context.Context, params DeleteScriptPolicyParams) error { _, err := c.sendDeleteScriptPolicy(ctx, params) return err @@ -1411,7 +1411,7 @@ func (c *Client) sendDeleteScriptPolicy(ctx context.Context, params DeleteScript otelAttrs := []attribute.KeyValue{ otelogen.OperationID("deleteScriptPolicy"), semconv.HTTPRequestMethodKey.String("DELETE"), - semconv.HTTPRouteKey.String("/script-policy/id/{ScriptPolicyID}"), + semconv.HTTPRouteKey.String("/script-policy/{ScriptPolicyID}"), } // Run stopwatch. @@ -1444,7 +1444,7 @@ func (c *Client) sendDeleteScriptPolicy(ctx context.Context, params DeleteScript stage = "BuildURL" u := uri.Clone(c.requestURL(ctx)) var pathParts [2]string - pathParts[0] = "/script-policy/id/" + pathParts[0] = "/script-policy/" { // Encode "ScriptPolicyID" parameter. e := uri.NewPathEncoder(uri.PathEncoderConfig{ @@ -1647,7 +1647,7 @@ func (c *Client) sendGetScript(ctx context.Context, params GetScriptParams) (res // // Get the specified script policy by ID. // -// GET /script-policy/id/{ScriptPolicyID} +// GET /script-policy/{ScriptPolicyID} func (c *Client) GetScriptPolicy(ctx context.Context, params GetScriptPolicyParams) (*ScriptPolicy, error) { res, err := c.sendGetScriptPolicy(ctx, params) return res, err @@ -1657,7 +1657,7 @@ func (c *Client) sendGetScriptPolicy(ctx context.Context, params GetScriptPolicy otelAttrs := []attribute.KeyValue{ otelogen.OperationID("getScriptPolicy"), semconv.HTTPRequestMethodKey.String("GET"), - semconv.HTTPRouteKey.String("/script-policy/id/{ScriptPolicyID}"), + semconv.HTTPRouteKey.String("/script-policy/{ScriptPolicyID}"), } // Run stopwatch. @@ -1690,7 +1690,7 @@ func (c *Client) sendGetScriptPolicy(ctx context.Context, params GetScriptPolicy stage = "BuildURL" u := uri.Clone(c.requestURL(ctx)) var pathParts [2]string - pathParts[0] = "/script-policy/id/" + pathParts[0] = "/script-policy/" { // Encode "ScriptPolicyID" parameter. e := uri.NewPathEncoder(uri.PathEncoderConfig{ @@ -1766,129 +1766,6 @@ func (c *Client) sendGetScriptPolicy(ctx context.Context, params GetScriptPolicy return result, nil } -// GetScriptPolicyFromHash invokes getScriptPolicyFromHash operation. -// -// Get the policy for the given hash of script source code. -// -// GET /script-policy/hash/{FromScriptHash} -func (c *Client) GetScriptPolicyFromHash(ctx context.Context, params GetScriptPolicyFromHashParams) (*ScriptPolicy, error) { - res, err := c.sendGetScriptPolicyFromHash(ctx, params) - return res, err -} - -func (c *Client) sendGetScriptPolicyFromHash(ctx context.Context, params GetScriptPolicyFromHashParams) (res *ScriptPolicy, err error) { - otelAttrs := []attribute.KeyValue{ - otelogen.OperationID("getScriptPolicyFromHash"), - semconv.HTTPRequestMethodKey.String("GET"), - semconv.HTTPRouteKey.String("/script-policy/hash/{FromScriptHash}"), - } - - // Run stopwatch. - startTime := time.Now() - defer func() { - // Use floating point division here for higher precision (instead of Millisecond method). - elapsedDuration := time.Since(startTime) - c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...)) - }() - - // Increment request counter. - c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) - - // Start a span for this request. - ctx, span := c.cfg.Tracer.Start(ctx, GetScriptPolicyFromHashOperation, - trace.WithAttributes(otelAttrs...), - clientSpanKind, - ) - // Track stage for error reporting. - var stage string - defer func() { - if err != nil { - span.RecordError(err) - span.SetStatus(codes.Error, stage) - c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) - } - span.End() - }() - - stage = "BuildURL" - u := uri.Clone(c.requestURL(ctx)) - var pathParts [2]string - pathParts[0] = "/script-policy/hash/" - { - // Encode "FromScriptHash" parameter. - e := uri.NewPathEncoder(uri.PathEncoderConfig{ - Param: "FromScriptHash", - Style: uri.PathStyleSimple, - Explode: false, - }) - if err := func() error { - return e.EncodeValue(conv.StringToString(params.FromScriptHash)) - }(); err != nil { - return res, errors.Wrap(err, "encode path") - } - encoded, err := e.Result() - if err != nil { - return res, errors.Wrap(err, "encode path") - } - pathParts[1] = encoded - } - uri.AddPathParts(u, pathParts[:]...) - - stage = "EncodeRequest" - r, err := ht.NewRequest(ctx, "GET", u) - if err != nil { - return res, errors.Wrap(err, "create request") - } - - { - type bitset = [1]uint8 - var satisfied bitset - { - stage = "Security:CookieAuth" - switch err := c.securityCookieAuth(ctx, GetScriptPolicyFromHashOperation, r); { - case err == nil: // if NO error - satisfied[0] |= 1 << 0 - case errors.Is(err, ogenerrors.ErrSkipClientSecurity): - // Skip this security. - default: - return res, errors.Wrap(err, "security \"CookieAuth\"") - } - } - - if ok := func() bool { - nextRequirement: - for _, requirement := range []bitset{ - {0b00000001}, - } { - for i, mask := range requirement { - if satisfied[i]&mask != mask { - continue nextRequirement - } - } - return true - } - return false - }(); !ok { - return res, ogenerrors.ErrSecurityRequirementIsNotSatisfied - } - } - - stage = "SendRequest" - resp, err := c.cfg.Client.Do(r) - if err != nil { - return res, errors.Wrap(err, "do request") - } - defer resp.Body.Close() - - stage = "DecodeResponse" - result, err := decodeGetScriptPolicyFromHashResponse(resp) - if err != nil { - return res, errors.Wrap(err, "decode response") - } - - return result, nil -} - // GetSubmission invokes getSubmission operation. // // Retrieve map with ID. @@ -2200,6 +2077,211 @@ func (c *Client) sendListScriptPolicy(ctx context.Context, params ListScriptPoli return result, nil } +// ListScripts invokes listScripts operation. +// +// Get list of scripts. +// +// GET /scripts +func (c *Client) ListScripts(ctx context.Context, params ListScriptsParams) ([]Script, error) { + res, err := c.sendListScripts(ctx, params) + return res, err +} + +func (c *Client) sendListScripts(ctx context.Context, params ListScriptsParams) (res []Script, err error) { + otelAttrs := []attribute.KeyValue{ + otelogen.OperationID("listScripts"), + semconv.HTTPRequestMethodKey.String("GET"), + semconv.HTTPRouteKey.String("/scripts"), + } + + // Run stopwatch. + startTime := time.Now() + defer func() { + // Use floating point division here for higher precision (instead of Millisecond method). + elapsedDuration := time.Since(startTime) + c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...)) + }() + + // Increment request counter. + c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) + + // Start a span for this request. + ctx, span := c.cfg.Tracer.Start(ctx, ListScriptsOperation, + trace.WithAttributes(otelAttrs...), + clientSpanKind, + ) + // Track stage for error reporting. + var stage string + defer func() { + if err != nil { + span.RecordError(err) + span.SetStatus(codes.Error, stage) + c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) + } + span.End() + }() + + stage = "BuildURL" + u := uri.Clone(c.requestURL(ctx)) + var pathParts [1]string + pathParts[0] = "/scripts" + uri.AddPathParts(u, pathParts[:]...) + + stage = "EncodeQueryParams" + q := uri.NewQueryEncoder() + { + // Encode "Page" parameter. + cfg := uri.QueryParameterEncodingConfig{ + Name: "Page", + Style: uri.QueryStyleForm, + Explode: true, + } + + if err := q.EncodeParam(cfg, func(e uri.Encoder) error { + return e.EncodeValue(conv.Int32ToString(params.Page)) + }); err != nil { + return res, errors.Wrap(err, "encode query") + } + } + { + // Encode "Limit" parameter. + cfg := uri.QueryParameterEncodingConfig{ + Name: "Limit", + Style: uri.QueryStyleForm, + Explode: true, + } + + if err := q.EncodeParam(cfg, func(e uri.Encoder) error { + return e.EncodeValue(conv.Int32ToString(params.Limit)) + }); err != nil { + return res, errors.Wrap(err, "encode query") + } + } + { + // Encode "Hash" parameter. + cfg := uri.QueryParameterEncodingConfig{ + Name: "Hash", + Style: uri.QueryStyleForm, + Explode: true, + } + + if err := q.EncodeParam(cfg, func(e uri.Encoder) error { + if val, ok := params.Hash.Get(); ok { + return e.EncodeValue(conv.StringToString(val)) + } + return nil + }); err != nil { + return res, errors.Wrap(err, "encode query") + } + } + { + // Encode "Name" parameter. + cfg := uri.QueryParameterEncodingConfig{ + Name: "Name", + Style: uri.QueryStyleForm, + Explode: true, + } + + if err := q.EncodeParam(cfg, func(e uri.Encoder) error { + if val, ok := params.Name.Get(); ok { + return e.EncodeValue(conv.StringToString(val)) + } + return nil + }); err != nil { + return res, errors.Wrap(err, "encode query") + } + } + { + // Encode "Source" parameter. + cfg := uri.QueryParameterEncodingConfig{ + Name: "Source", + Style: uri.QueryStyleForm, + Explode: true, + } + + if err := q.EncodeParam(cfg, func(e uri.Encoder) error { + if val, ok := params.Source.Get(); ok { + return e.EncodeValue(conv.StringToString(val)) + } + return nil + }); err != nil { + return res, errors.Wrap(err, "encode query") + } + } + { + // Encode "SubmissionID" parameter. + cfg := uri.QueryParameterEncodingConfig{ + Name: "SubmissionID", + Style: uri.QueryStyleForm, + Explode: true, + } + + if err := q.EncodeParam(cfg, func(e uri.Encoder) error { + if val, ok := params.SubmissionID.Get(); ok { + return e.EncodeValue(conv.Int64ToString(val)) + } + return nil + }); err != nil { + return res, errors.Wrap(err, "encode query") + } + } + u.RawQuery = q.Values().Encode() + + stage = "EncodeRequest" + r, err := ht.NewRequest(ctx, "GET", u) + if err != nil { + return res, errors.Wrap(err, "create request") + } + + { + type bitset = [1]uint8 + var satisfied bitset + { + stage = "Security:CookieAuth" + switch err := c.securityCookieAuth(ctx, ListScriptsOperation, r); { + case err == nil: // if NO error + satisfied[0] |= 1 << 0 + case errors.Is(err, ogenerrors.ErrSkipClientSecurity): + // Skip this security. + default: + return res, errors.Wrap(err, "security \"CookieAuth\"") + } + } + + if ok := func() bool { + nextRequirement: + for _, requirement := range []bitset{ + {0b00000001}, + } { + for i, mask := range requirement { + if satisfied[i]&mask != mask { + continue nextRequirement + } + } + return true + } + return false + }(); !ok { + return res, ogenerrors.ErrSecurityRequirementIsNotSatisfied + } + } + + stage = "SendRequest" + resp, err := c.cfg.Client.Do(r) + if err != nil { + return res, errors.Wrap(err, "do request") + } + defer resp.Body.Close() + + stage = "DecodeResponse" + result, err := decodeListScriptsResponse(resp) + if err != nil { + return res, errors.Wrap(err, "decode response") + } + + return result, nil +} + // ListSubmissions invokes listSubmissions operation. // // Get list of submissions. @@ -2642,7 +2724,7 @@ func (c *Client) sendUpdateScript(ctx context.Context, request *ScriptUpdate, pa // // Update the specified script policy by ID. // -// POST /script-policy/id/{ScriptPolicyID} +// POST /script-policy/{ScriptPolicyID} func (c *Client) UpdateScriptPolicy(ctx context.Context, request *ScriptPolicyUpdate, params UpdateScriptPolicyParams) error { _, err := c.sendUpdateScriptPolicy(ctx, request, params) return err @@ -2652,7 +2734,7 @@ func (c *Client) sendUpdateScriptPolicy(ctx context.Context, request *ScriptPoli otelAttrs := []attribute.KeyValue{ otelogen.OperationID("updateScriptPolicy"), semconv.HTTPRequestMethodKey.String("POST"), - semconv.HTTPRouteKey.String("/script-policy/id/{ScriptPolicyID}"), + semconv.HTTPRouteKey.String("/script-policy/{ScriptPolicyID}"), } // Run stopwatch. @@ -2685,7 +2767,7 @@ func (c *Client) sendUpdateScriptPolicy(ctx context.Context, request *ScriptPoli stage = "BuildURL" u := uri.Clone(c.requestURL(ctx)) var pathParts [2]string - pathParts[0] = "/script-policy/id/" + pathParts[0] = "/script-policy/" { // Encode "ScriptPolicyID" parameter. e := uri.NewPathEncoder(uri.PathEncoderConfig{ diff --git a/pkg/api/oas_handlers_gen.go b/pkg/api/oas_handlers_gen.go index 3752b66..7b89376 100644 --- a/pkg/api/oas_handlers_gen.go +++ b/pkg/api/oas_handlers_gen.go @@ -1984,14 +1984,14 @@ func (s *Server) handleDeleteScriptRequest(args [1]string, argsEscaped bool, w h // // Delete the specified script policy by ID. // -// DELETE /script-policy/id/{ScriptPolicyID} +// DELETE /script-policy/{ScriptPolicyID} func (s *Server) handleDeleteScriptPolicyRequest(args [1]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) { statusWriter := &codeRecorder{ResponseWriter: w} w = statusWriter otelAttrs := []attribute.KeyValue{ otelogen.OperationID("deleteScriptPolicy"), semconv.HTTPRequestMethodKey.String("DELETE"), - semconv.HTTPRouteKey.String("/script-policy/id/{ScriptPolicyID}"), + semconv.HTTPRouteKey.String("/script-policy/{ScriptPolicyID}"), } // Start a span for this request. @@ -2374,14 +2374,14 @@ func (s *Server) handleGetScriptRequest(args [1]string, argsEscaped bool, w http // // Get the specified script policy by ID. // -// GET /script-policy/id/{ScriptPolicyID} +// GET /script-policy/{ScriptPolicyID} func (s *Server) handleGetScriptPolicyRequest(args [1]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) { statusWriter := &codeRecorder{ResponseWriter: w} w = statusWriter otelAttrs := []attribute.KeyValue{ otelogen.OperationID("getScriptPolicy"), semconv.HTTPRequestMethodKey.String("GET"), - semconv.HTTPRouteKey.String("/script-policy/id/{ScriptPolicyID}"), + semconv.HTTPRouteKey.String("/script-policy/{ScriptPolicyID}"), } // Start a span for this request. @@ -2565,201 +2565,6 @@ func (s *Server) handleGetScriptPolicyRequest(args [1]string, argsEscaped bool, } } -// handleGetScriptPolicyFromHashRequest handles getScriptPolicyFromHash operation. -// -// Get the policy for the given hash of script source code. -// -// GET /script-policy/hash/{FromScriptHash} -func (s *Server) handleGetScriptPolicyFromHashRequest(args [1]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) { - statusWriter := &codeRecorder{ResponseWriter: w} - w = statusWriter - otelAttrs := []attribute.KeyValue{ - otelogen.OperationID("getScriptPolicyFromHash"), - semconv.HTTPRequestMethodKey.String("GET"), - semconv.HTTPRouteKey.String("/script-policy/hash/{FromScriptHash}"), - } - - // Start a span for this request. - ctx, span := s.cfg.Tracer.Start(r.Context(), GetScriptPolicyFromHashOperation, - trace.WithAttributes(otelAttrs...), - serverSpanKind, - ) - defer span.End() - - // Add Labeler to context. - labeler := &Labeler{attrs: otelAttrs} - ctx = contextWithLabeler(ctx, labeler) - - // Run stopwatch. - startTime := time.Now() - defer func() { - elapsedDuration := time.Since(startTime) - - attrSet := labeler.AttributeSet() - attrs := attrSet.ToSlice() - code := statusWriter.status - if code != 0 { - codeAttr := semconv.HTTPResponseStatusCode(code) - attrs = append(attrs, codeAttr) - span.SetAttributes(codeAttr) - } - attrOpt := metric.WithAttributes(attrs...) - - // Increment request counter. - s.requests.Add(ctx, 1, attrOpt) - - // Use floating point division here for higher precision (instead of Millisecond method). - s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt) - }() - - var ( - recordError = func(stage string, err error) { - span.RecordError(err) - - // https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status - // Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges, - // unless there was another error (e.g., network error receiving the response body; or 3xx codes with - // max redirects exceeded), in which case status MUST be set to Error. - code := statusWriter.status - if code >= 100 && code < 500 { - span.SetStatus(codes.Error, stage) - } - - attrSet := labeler.AttributeSet() - attrs := attrSet.ToSlice() - if code != 0 { - attrs = append(attrs, semconv.HTTPResponseStatusCode(code)) - } - - s.errors.Add(ctx, 1, metric.WithAttributes(attrs...)) - } - err error - opErrContext = ogenerrors.OperationContext{ - Name: GetScriptPolicyFromHashOperation, - ID: "getScriptPolicyFromHash", - } - ) - { - type bitset = [1]uint8 - var satisfied bitset - { - sctx, ok, err := s.securityCookieAuth(ctx, GetScriptPolicyFromHashOperation, r) - if err != nil { - err = &ogenerrors.SecurityError{ - OperationContext: opErrContext, - Security: "CookieAuth", - Err: err, - } - if encodeErr := encodeErrorResponse(s.h.NewError(ctx, err), w, span); encodeErr != nil { - defer recordError("Security:CookieAuth", err) - } - return - } - if ok { - satisfied[0] |= 1 << 0 - ctx = sctx - } - } - - if ok := func() bool { - nextRequirement: - for _, requirement := range []bitset{ - {0b00000001}, - } { - for i, mask := range requirement { - if satisfied[i]&mask != mask { - continue nextRequirement - } - } - return true - } - return false - }(); !ok { - err = &ogenerrors.SecurityError{ - OperationContext: opErrContext, - Err: ogenerrors.ErrSecurityRequirementIsNotSatisfied, - } - if encodeErr := encodeErrorResponse(s.h.NewError(ctx, err), w, span); encodeErr != nil { - defer recordError("Security", err) - } - return - } - } - params, err := decodeGetScriptPolicyFromHashParams(args, argsEscaped, r) - if err != nil { - err = &ogenerrors.DecodeParamsError{ - OperationContext: opErrContext, - Err: err, - } - defer recordError("DecodeParams", err) - s.cfg.ErrorHandler(ctx, w, r, err) - return - } - - var response *ScriptPolicy - if m := s.cfg.Middleware; m != nil { - mreq := middleware.Request{ - Context: ctx, - OperationName: GetScriptPolicyFromHashOperation, - OperationSummary: "Get the policy for the given hash of script source code", - OperationID: "getScriptPolicyFromHash", - Body: nil, - Params: middleware.Parameters{ - { - Name: "FromScriptHash", - In: "path", - }: params.FromScriptHash, - }, - Raw: r, - } - - type ( - Request = struct{} - Params = GetScriptPolicyFromHashParams - Response = *ScriptPolicy - ) - response, err = middleware.HookMiddleware[ - Request, - Params, - Response, - ]( - m, - mreq, - unpackGetScriptPolicyFromHashParams, - func(ctx context.Context, request Request, params Params) (response Response, err error) { - response, err = s.h.GetScriptPolicyFromHash(ctx, params) - return response, err - }, - ) - } else { - response, err = s.h.GetScriptPolicyFromHash(ctx, params) - } - if err != nil { - if errRes, ok := errors.Into[*ErrorStatusCode](err); ok { - if err := encodeErrorResponse(errRes, w, span); err != nil { - defer recordError("Internal", err) - } - return - } - if errors.Is(err, ht.ErrNotImplemented) { - s.cfg.ErrorHandler(ctx, w, r, err) - return - } - if err := encodeErrorResponse(s.h.NewError(ctx, err), w, span); err != nil { - defer recordError("Internal", err) - } - return - } - - if err := encodeGetScriptPolicyFromHashResponse(response, w, span); err != nil { - defer recordError("EncodeResponse", err) - if !errors.Is(err, ht.ErrInternalServerErrorResponse) { - s.cfg.ErrorHandler(ctx, w, r, err) - } - return - } -} - // handleGetSubmissionRequest handles getSubmission operation. // // Retrieve map with ID. @@ -3166,6 +2971,221 @@ func (s *Server) handleListScriptPolicyRequest(args [0]string, argsEscaped bool, } } +// handleListScriptsRequest handles listScripts operation. +// +// Get list of scripts. +// +// GET /scripts +func (s *Server) handleListScriptsRequest(args [0]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) { + statusWriter := &codeRecorder{ResponseWriter: w} + w = statusWriter + otelAttrs := []attribute.KeyValue{ + otelogen.OperationID("listScripts"), + semconv.HTTPRequestMethodKey.String("GET"), + semconv.HTTPRouteKey.String("/scripts"), + } + + // Start a span for this request. + ctx, span := s.cfg.Tracer.Start(r.Context(), ListScriptsOperation, + trace.WithAttributes(otelAttrs...), + serverSpanKind, + ) + defer span.End() + + // Add Labeler to context. + labeler := &Labeler{attrs: otelAttrs} + ctx = contextWithLabeler(ctx, labeler) + + // Run stopwatch. + startTime := time.Now() + defer func() { + elapsedDuration := time.Since(startTime) + + attrSet := labeler.AttributeSet() + attrs := attrSet.ToSlice() + code := statusWriter.status + if code != 0 { + codeAttr := semconv.HTTPResponseStatusCode(code) + attrs = append(attrs, codeAttr) + span.SetAttributes(codeAttr) + } + attrOpt := metric.WithAttributes(attrs...) + + // Increment request counter. + s.requests.Add(ctx, 1, attrOpt) + + // Use floating point division here for higher precision (instead of Millisecond method). + s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt) + }() + + var ( + recordError = func(stage string, err error) { + span.RecordError(err) + + // https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status + // Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges, + // unless there was another error (e.g., network error receiving the response body; or 3xx codes with + // max redirects exceeded), in which case status MUST be set to Error. + code := statusWriter.status + if code >= 100 && code < 500 { + span.SetStatus(codes.Error, stage) + } + + attrSet := labeler.AttributeSet() + attrs := attrSet.ToSlice() + if code != 0 { + attrs = append(attrs, semconv.HTTPResponseStatusCode(code)) + } + + s.errors.Add(ctx, 1, metric.WithAttributes(attrs...)) + } + err error + opErrContext = ogenerrors.OperationContext{ + Name: ListScriptsOperation, + ID: "listScripts", + } + ) + { + type bitset = [1]uint8 + var satisfied bitset + { + sctx, ok, err := s.securityCookieAuth(ctx, ListScriptsOperation, r) + if err != nil { + err = &ogenerrors.SecurityError{ + OperationContext: opErrContext, + Security: "CookieAuth", + Err: err, + } + if encodeErr := encodeErrorResponse(s.h.NewError(ctx, err), w, span); encodeErr != nil { + defer recordError("Security:CookieAuth", err) + } + return + } + if ok { + satisfied[0] |= 1 << 0 + ctx = sctx + } + } + + if ok := func() bool { + nextRequirement: + for _, requirement := range []bitset{ + {0b00000001}, + } { + for i, mask := range requirement { + if satisfied[i]&mask != mask { + continue nextRequirement + } + } + return true + } + return false + }(); !ok { + err = &ogenerrors.SecurityError{ + OperationContext: opErrContext, + Err: ogenerrors.ErrSecurityRequirementIsNotSatisfied, + } + if encodeErr := encodeErrorResponse(s.h.NewError(ctx, err), w, span); encodeErr != nil { + defer recordError("Security", err) + } + return + } + } + params, err := decodeListScriptsParams(args, argsEscaped, r) + if err != nil { + err = &ogenerrors.DecodeParamsError{ + OperationContext: opErrContext, + Err: err, + } + defer recordError("DecodeParams", err) + s.cfg.ErrorHandler(ctx, w, r, err) + return + } + + var response []Script + if m := s.cfg.Middleware; m != nil { + mreq := middleware.Request{ + Context: ctx, + OperationName: ListScriptsOperation, + OperationSummary: "Get list of scripts", + OperationID: "listScripts", + Body: nil, + Params: middleware.Parameters{ + { + Name: "Page", + In: "query", + }: params.Page, + { + Name: "Limit", + In: "query", + }: params.Limit, + { + Name: "Hash", + In: "query", + }: params.Hash, + { + Name: "Name", + In: "query", + }: params.Name, + { + Name: "Source", + In: "query", + }: params.Source, + { + Name: "SubmissionID", + In: "query", + }: params.SubmissionID, + }, + Raw: r, + } + + type ( + Request = struct{} + Params = ListScriptsParams + Response = []Script + ) + response, err = middleware.HookMiddleware[ + Request, + Params, + Response, + ]( + m, + mreq, + unpackListScriptsParams, + func(ctx context.Context, request Request, params Params) (response Response, err error) { + response, err = s.h.ListScripts(ctx, params) + return response, err + }, + ) + } else { + response, err = s.h.ListScripts(ctx, params) + } + if err != nil { + if errRes, ok := errors.Into[*ErrorStatusCode](err); ok { + if err := encodeErrorResponse(errRes, w, span); err != nil { + defer recordError("Internal", err) + } + return + } + if errors.Is(err, ht.ErrNotImplemented) { + s.cfg.ErrorHandler(ctx, w, r, err) + return + } + if err := encodeErrorResponse(s.h.NewError(ctx, err), w, span); err != nil { + defer recordError("Internal", err) + } + return + } + + if err := encodeListScriptsResponse(response, w, span); err != nil { + defer recordError("EncodeResponse", err) + if !errors.Is(err, ht.ErrInternalServerErrorResponse) { + s.cfg.ErrorHandler(ctx, w, r, err) + } + return + } +} + // handleListSubmissionsRequest handles listSubmissions operation. // // Get list of submissions. @@ -3786,14 +3806,14 @@ func (s *Server) handleUpdateScriptRequest(args [1]string, argsEscaped bool, w h // // Update the specified script policy by ID. // -// POST /script-policy/id/{ScriptPolicyID} +// POST /script-policy/{ScriptPolicyID} func (s *Server) handleUpdateScriptPolicyRequest(args [1]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) { statusWriter := &codeRecorder{ResponseWriter: w} w = statusWriter otelAttrs := []attribute.KeyValue{ otelogen.OperationID("updateScriptPolicy"), semconv.HTTPRequestMethodKey.String("POST"), - semconv.HTTPRouteKey.String("/script-policy/id/{ScriptPolicyID}"), + semconv.HTTPRouteKey.String("/script-policy/{ScriptPolicyID}"), } // Start a span for this request. diff --git a/pkg/api/oas_operations_gen.go b/pkg/api/oas_operations_gen.go index 89bf5d3..4b63be0 100644 --- a/pkg/api/oas_operations_gen.go +++ b/pkg/api/oas_operations_gen.go @@ -19,9 +19,9 @@ const ( DeleteScriptPolicyOperation OperationName = "DeleteScriptPolicy" GetScriptOperation OperationName = "GetScript" GetScriptPolicyOperation OperationName = "GetScriptPolicy" - GetScriptPolicyFromHashOperation OperationName = "GetScriptPolicyFromHash" GetSubmissionOperation OperationName = "GetSubmission" ListScriptPolicyOperation OperationName = "ListScriptPolicy" + ListScriptsOperation OperationName = "ListScripts" ListSubmissionsOperation OperationName = "ListSubmissions" SetSubmissionCompletedOperation OperationName = "SetSubmissionCompleted" UpdateScriptOperation OperationName = "UpdateScript" diff --git a/pkg/api/oas_parameters_gen.go b/pkg/api/oas_parameters_gen.go index 4f9b718..9fa84db 100644 --- a/pkg/api/oas_parameters_gen.go +++ b/pkg/api/oas_parameters_gen.go @@ -675,87 +675,6 @@ func decodeGetScriptPolicyParams(args [1]string, argsEscaped bool, r *http.Reque return params, nil } -// GetScriptPolicyFromHashParams is parameters of getScriptPolicyFromHash operation. -type GetScriptPolicyFromHashParams struct { - FromScriptHash string -} - -func unpackGetScriptPolicyFromHashParams(packed middleware.Parameters) (params GetScriptPolicyFromHashParams) { - { - key := middleware.ParameterKey{ - Name: "FromScriptHash", - In: "path", - } - params.FromScriptHash = packed[key].(string) - } - return params -} - -func decodeGetScriptPolicyFromHashParams(args [1]string, argsEscaped bool, r *http.Request) (params GetScriptPolicyFromHashParams, _ error) { - // Decode path: FromScriptHash. - if err := func() error { - param := args[0] - if argsEscaped { - unescaped, err := url.PathUnescape(args[0]) - if err != nil { - return errors.Wrap(err, "unescape path") - } - param = unescaped - } - if len(param) > 0 { - d := uri.NewPathDecoder(uri.PathDecoderConfig{ - Param: "FromScriptHash", - Value: param, - Style: uri.PathStyleSimple, - Explode: false, - }) - - if err := func() error { - val, err := d.DecodeValue() - if err != nil { - return err - } - - c, err := conv.ToString(val) - if err != nil { - return err - } - - params.FromScriptHash = c - return nil - }(); err != nil { - return err - } - if err := func() error { - if err := (validate.String{ - MinLength: 16, - MinLengthSet: true, - MaxLength: 16, - MaxLengthSet: true, - Email: false, - Hostname: false, - Regex: nil, - }).Validate(string(params.FromScriptHash)); err != nil { - return errors.Wrap(err, "string") - } - return nil - }(); err != nil { - return err - } - } else { - return validate.ErrFieldRequired - } - return nil - }(); err != nil { - return params, &ogenerrors.DecodeParamError{ - Name: "FromScriptHash", - In: "path", - Err: err, - } - } - return params, nil -} - // GetSubmissionParams is parameters of getSubmission operation. type GetSubmissionParams struct { // The unique identifier for a submission. @@ -1133,6 +1052,414 @@ func decodeListScriptPolicyParams(args [0]string, argsEscaped bool, r *http.Requ return params, nil } +// ListScriptsParams is parameters of listScripts operation. +type ListScriptsParams struct { + Page int32 + Limit int32 + Hash OptString + Name OptString + Source OptString + SubmissionID OptInt64 +} + +func unpackListScriptsParams(packed middleware.Parameters) (params ListScriptsParams) { + { + key := middleware.ParameterKey{ + Name: "Page", + In: "query", + } + params.Page = packed[key].(int32) + } + { + key := middleware.ParameterKey{ + Name: "Limit", + In: "query", + } + params.Limit = packed[key].(int32) + } + { + key := middleware.ParameterKey{ + Name: "Hash", + In: "query", + } + if v, ok := packed[key]; ok { + params.Hash = v.(OptString) + } + } + { + key := middleware.ParameterKey{ + Name: "Name", + In: "query", + } + if v, ok := packed[key]; ok { + params.Name = v.(OptString) + } + } + { + key := middleware.ParameterKey{ + Name: "Source", + In: "query", + } + if v, ok := packed[key]; ok { + params.Source = v.(OptString) + } + } + { + key := middleware.ParameterKey{ + Name: "SubmissionID", + In: "query", + } + if v, ok := packed[key]; ok { + params.SubmissionID = v.(OptInt64) + } + } + return params +} + +func decodeListScriptsParams(args [0]string, argsEscaped bool, r *http.Request) (params ListScriptsParams, _ error) { + q := uri.NewQueryDecoder(r.URL.Query()) + // Decode query: Page. + if err := func() error { + cfg := uri.QueryParameterDecodingConfig{ + Name: "Page", + Style: uri.QueryStyleForm, + Explode: true, + } + + if err := q.HasParam(cfg); err == nil { + if err := q.DecodeParam(cfg, func(d uri.Decoder) error { + val, err := d.DecodeValue() + if err != nil { + return err + } + + c, err := conv.ToInt32(val) + if err != nil { + return err + } + + params.Page = c + return nil + }); err != nil { + return err + } + if err := func() error { + if err := (validate.Int{ + MinSet: true, + Min: 1, + MaxSet: false, + Max: 0, + MinExclusive: false, + MaxExclusive: false, + MultipleOfSet: false, + MultipleOf: 0, + }).Validate(int64(params.Page)); err != nil { + return errors.Wrap(err, "int") + } + return nil + }(); err != nil { + return err + } + } else { + return validate.ErrFieldRequired + } + return nil + }(); err != nil { + return params, &ogenerrors.DecodeParamError{ + Name: "Page", + In: "query", + Err: err, + } + } + // Decode query: Limit. + if err := func() error { + cfg := uri.QueryParameterDecodingConfig{ + Name: "Limit", + Style: uri.QueryStyleForm, + Explode: true, + } + + if err := q.HasParam(cfg); err == nil { + if err := q.DecodeParam(cfg, func(d uri.Decoder) error { + val, err := d.DecodeValue() + if err != nil { + return err + } + + c, err := conv.ToInt32(val) + if err != nil { + return err + } + + params.Limit = c + return nil + }); err != nil { + return err + } + if err := func() error { + if err := (validate.Int{ + MinSet: true, + Min: 1, + MaxSet: true, + Max: 100, + MinExclusive: false, + MaxExclusive: false, + MultipleOfSet: false, + MultipleOf: 0, + }).Validate(int64(params.Limit)); err != nil { + return errors.Wrap(err, "int") + } + return nil + }(); err != nil { + return err + } + } else { + return validate.ErrFieldRequired + } + return nil + }(); err != nil { + return params, &ogenerrors.DecodeParamError{ + Name: "Limit", + In: "query", + Err: err, + } + } + // Decode query: Hash. + if err := func() error { + cfg := uri.QueryParameterDecodingConfig{ + Name: "Hash", + Style: uri.QueryStyleForm, + Explode: true, + } + + if err := q.HasParam(cfg); err == nil { + if err := q.DecodeParam(cfg, func(d uri.Decoder) error { + var paramsDotHashVal string + if err := func() error { + val, err := d.DecodeValue() + if err != nil { + return err + } + + c, err := conv.ToString(val) + if err != nil { + return err + } + + paramsDotHashVal = c + return nil + }(); err != nil { + return err + } + params.Hash.SetTo(paramsDotHashVal) + return nil + }); err != nil { + return err + } + if err := func() error { + if value, ok := params.Hash.Get(); ok { + if err := func() error { + if err := (validate.String{ + MinLength: 16, + MinLengthSet: true, + MaxLength: 16, + MaxLengthSet: true, + Email: false, + Hostname: false, + Regex: nil, + }).Validate(string(value)); err != nil { + return errors.Wrap(err, "string") + } + return nil + }(); err != nil { + return err + } + } + return nil + }(); err != nil { + return err + } + } + return nil + }(); err != nil { + return params, &ogenerrors.DecodeParamError{ + Name: "Hash", + In: "query", + Err: err, + } + } + // Decode query: Name. + if err := func() error { + cfg := uri.QueryParameterDecodingConfig{ + Name: "Name", + Style: uri.QueryStyleForm, + Explode: true, + } + + if err := q.HasParam(cfg); err == nil { + if err := q.DecodeParam(cfg, func(d uri.Decoder) error { + var paramsDotNameVal string + if err := func() error { + val, err := d.DecodeValue() + if err != nil { + return err + } + + c, err := conv.ToString(val) + if err != nil { + return err + } + + paramsDotNameVal = c + return nil + }(); err != nil { + return err + } + params.Name.SetTo(paramsDotNameVal) + return nil + }); err != nil { + return err + } + if err := func() error { + if value, ok := params.Name.Get(); ok { + if err := func() error { + if err := (validate.String{ + MinLength: 0, + MinLengthSet: false, + MaxLength: 128, + MaxLengthSet: true, + Email: false, + Hostname: false, + Regex: nil, + }).Validate(string(value)); err != nil { + return errors.Wrap(err, "string") + } + return nil + }(); err != nil { + return err + } + } + return nil + }(); err != nil { + return err + } + } + return nil + }(); err != nil { + return params, &ogenerrors.DecodeParamError{ + Name: "Name", + In: "query", + Err: err, + } + } + // Decode query: Source. + if err := func() error { + cfg := uri.QueryParameterDecodingConfig{ + Name: "Source", + Style: uri.QueryStyleForm, + Explode: true, + } + + if err := q.HasParam(cfg); err == nil { + if err := q.DecodeParam(cfg, func(d uri.Decoder) error { + var paramsDotSourceVal string + if err := func() error { + val, err := d.DecodeValue() + if err != nil { + return err + } + + c, err := conv.ToString(val) + if err != nil { + return err + } + + paramsDotSourceVal = c + return nil + }(); err != nil { + return err + } + params.Source.SetTo(paramsDotSourceVal) + return nil + }); err != nil { + return err + } + if err := func() error { + if value, ok := params.Source.Get(); ok { + if err := func() error { + if err := (validate.String{ + MinLength: 0, + MinLengthSet: false, + MaxLength: 1048576, + MaxLengthSet: true, + Email: false, + Hostname: false, + Regex: nil, + }).Validate(string(value)); err != nil { + return errors.Wrap(err, "string") + } + return nil + }(); err != nil { + return err + } + } + return nil + }(); err != nil { + return err + } + } + return nil + }(); err != nil { + return params, &ogenerrors.DecodeParamError{ + Name: "Source", + In: "query", + Err: err, + } + } + // Decode query: SubmissionID. + if err := func() error { + cfg := uri.QueryParameterDecodingConfig{ + Name: "SubmissionID", + Style: uri.QueryStyleForm, + Explode: true, + } + + if err := q.HasParam(cfg); err == nil { + if err := q.DecodeParam(cfg, func(d uri.Decoder) error { + var paramsDotSubmissionIDVal int64 + if err := func() error { + val, err := d.DecodeValue() + if err != nil { + return err + } + + c, err := conv.ToInt64(val) + if err != nil { + return err + } + + paramsDotSubmissionIDVal = c + return nil + }(); err != nil { + return err + } + params.SubmissionID.SetTo(paramsDotSubmissionIDVal) + return nil + }); err != nil { + return err + } + } + return nil + }(); err != nil { + return params, &ogenerrors.DecodeParamError{ + Name: "SubmissionID", + In: "query", + Err: err, + } + } + return params, nil +} + // ListSubmissionsParams is parameters of listSubmissions operation. type ListSubmissionsParams struct { Page int32 diff --git a/pkg/api/oas_response_decoders_gen.go b/pkg/api/oas_response_decoders_gen.go index 4743df9..eb652d4 100644 --- a/pkg/api/oas_response_decoders_gen.go +++ b/pkg/api/oas_response_decoders_gen.go @@ -856,98 +856,6 @@ func decodeGetScriptPolicyResponse(resp *http.Response) (res *ScriptPolicy, _ er return res, errors.Wrap(defRes, "error") } -func decodeGetScriptPolicyFromHashResponse(resp *http.Response) (res *ScriptPolicy, _ error) { - switch resp.StatusCode { - case 200: - // Code 200. - ct, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type")) - if err != nil { - return res, errors.Wrap(err, "parse media type") - } - switch { - case ct == "application/json": - buf, err := io.ReadAll(resp.Body) - if err != nil { - return res, err - } - d := jx.DecodeBytes(buf) - - var response ScriptPolicy - if err := func() error { - if err := response.Decode(d); err != nil { - return err - } - if err := d.Skip(); err != io.EOF { - return errors.New("unexpected trailing data") - } - return nil - }(); err != nil { - err = &ogenerrors.DecodeBodyError{ - ContentType: ct, - Body: buf, - Err: err, - } - return res, err - } - // Validate response. - if err := func() error { - if err := response.Validate(); err != nil { - return err - } - return nil - }(); err != nil { - return res, errors.Wrap(err, "validate") - } - return &response, nil - default: - return res, validate.InvalidContentType(ct) - } - } - // Convenient error response. - defRes, err := func() (res *ErrorStatusCode, err error) { - ct, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type")) - if err != nil { - return res, errors.Wrap(err, "parse media type") - } - switch { - case ct == "application/json": - buf, err := io.ReadAll(resp.Body) - if err != nil { - return res, err - } - d := jx.DecodeBytes(buf) - - var response Error - if err := func() error { - if err := response.Decode(d); err != nil { - return err - } - if err := d.Skip(); err != io.EOF { - return errors.New("unexpected trailing data") - } - return nil - }(); err != nil { - err = &ogenerrors.DecodeBodyError{ - ContentType: ct, - Body: buf, - Err: err, - } - return res, err - } - return &ErrorStatusCode{ - StatusCode: resp.StatusCode, - Response: response, - }, nil - default: - return res, validate.InvalidContentType(ct) - } - }() - if err != nil { - return res, errors.Wrapf(err, "default (code %d)", resp.StatusCode) - } - return res, errors.Wrap(defRes, "error") -} - func decodeGetSubmissionResponse(resp *http.Response) (res *Submission, _ error) { switch resp.StatusCode { case 200: @@ -1157,6 +1065,123 @@ func decodeListScriptPolicyResponse(resp *http.Response) (res []ScriptPolicy, _ return res, errors.Wrap(defRes, "error") } +func decodeListScriptsResponse(resp *http.Response) (res []Script, _ error) { + switch resp.StatusCode { + case 200: + // Code 200. + ct, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type")) + if err != nil { + return res, errors.Wrap(err, "parse media type") + } + switch { + case ct == "application/json": + buf, err := io.ReadAll(resp.Body) + if err != nil { + return res, err + } + d := jx.DecodeBytes(buf) + + var response []Script + if err := func() error { + response = make([]Script, 0) + if err := d.Arr(func(d *jx.Decoder) error { + var elem Script + if err := elem.Decode(d); err != nil { + return err + } + response = append(response, elem) + return nil + }); err != nil { + return err + } + if err := d.Skip(); err != io.EOF { + return errors.New("unexpected trailing data") + } + return nil + }(); err != nil { + err = &ogenerrors.DecodeBodyError{ + ContentType: ct, + Body: buf, + Err: err, + } + return res, err + } + // Validate response. + if err := func() error { + if response == nil { + return errors.New("nil is invalid value") + } + var failures []validate.FieldError + for i, elem := range response { + if err := func() error { + if err := elem.Validate(); err != nil { + return err + } + return nil + }(); err != nil { + failures = append(failures, validate.FieldError{ + Name: fmt.Sprintf("[%d]", i), + Error: err, + }) + } + } + if len(failures) > 0 { + return &validate.Error{Fields: failures} + } + return nil + }(); err != nil { + return res, errors.Wrap(err, "validate") + } + return response, nil + default: + return res, validate.InvalidContentType(ct) + } + } + // Convenient error response. + defRes, err := func() (res *ErrorStatusCode, err error) { + ct, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type")) + if err != nil { + return res, errors.Wrap(err, "parse media type") + } + switch { + case ct == "application/json": + buf, err := io.ReadAll(resp.Body) + if err != nil { + return res, err + } + d := jx.DecodeBytes(buf) + + var response Error + if err := func() error { + if err := response.Decode(d); err != nil { + return err + } + if err := d.Skip(); err != io.EOF { + return errors.New("unexpected trailing data") + } + return nil + }(); err != nil { + err = &ogenerrors.DecodeBodyError{ + ContentType: ct, + Body: buf, + Err: err, + } + return res, err + } + return &ErrorStatusCode{ + StatusCode: resp.StatusCode, + Response: response, + }, nil + default: + return res, validate.InvalidContentType(ct) + } + }() + if err != nil { + return res, errors.Wrapf(err, "default (code %d)", resp.StatusCode) + } + return res, errors.Wrap(defRes, "error") +} + func decodeListSubmissionsResponse(resp *http.Response) (res []Submission, _ error) { switch resp.StatusCode { case 200: diff --git a/pkg/api/oas_response_encoders_gen.go b/pkg/api/oas_response_encoders_gen.go index f27d572..29fa98a 100644 --- a/pkg/api/oas_response_encoders_gen.go +++ b/pkg/api/oas_response_encoders_gen.go @@ -139,20 +139,6 @@ func encodeGetScriptPolicyResponse(response *ScriptPolicy, w http.ResponseWriter return nil } -func encodeGetScriptPolicyFromHashResponse(response *ScriptPolicy, w http.ResponseWriter, span trace.Span) error { - w.Header().Set("Content-Type", "application/json; charset=utf-8") - w.WriteHeader(200) - span.SetStatus(codes.Ok, http.StatusText(200)) - - e := new(jx.Encoder) - response.Encode(e) - if _, err := e.WriteTo(w); err != nil { - return errors.Wrap(err, "write") - } - - return nil -} - func encodeGetSubmissionResponse(response *Submission, w http.ResponseWriter, span trace.Span) error { w.Header().Set("Content-Type", "application/json; charset=utf-8") w.WriteHeader(200) @@ -185,6 +171,24 @@ func encodeListScriptPolicyResponse(response []ScriptPolicy, w http.ResponseWrit return nil } +func encodeListScriptsResponse(response []Script, w http.ResponseWriter, span trace.Span) error { + w.Header().Set("Content-Type", "application/json; charset=utf-8") + w.WriteHeader(200) + span.SetStatus(codes.Ok, http.StatusText(200)) + + e := new(jx.Encoder) + e.ArrStart() + for _, elem := range response { + elem.Encode(e) + } + e.ArrEnd() + if _, err := e.WriteTo(w); err != nil { + return errors.Wrap(err, "write") + } + + return nil +} + func encodeListSubmissionsResponse(response []Submission, w http.ResponseWriter, span trace.Span) error { w.Header().Set("Content-Type", "application/json; charset=utf-8") w.WriteHeader(200) diff --git a/pkg/api/oas_router_gen.go b/pkg/api/oas_router_gen.go index b8fdfb2..ac26a08 100644 --- a/pkg/api/oas_router_gen.go +++ b/pkg/api/oas_router_gen.go @@ -102,74 +102,31 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { break } + // Param: "ScriptPolicyID" + // Leaf parameter + args[0] = elem + elem = "" + if len(elem) == 0 { - break - } - switch elem[0] { - case 'h': // Prefix: "hash/" - origElem := elem - if l := len("hash/"); len(elem) >= l && elem[0:l] == "hash/" { - elem = elem[l:] - } else { - break + // Leaf node. + switch r.Method { + case "DELETE": + s.handleDeleteScriptPolicyRequest([1]string{ + args[0], + }, elemIsEscaped, w, r) + case "GET": + s.handleGetScriptPolicyRequest([1]string{ + args[0], + }, elemIsEscaped, w, r) + case "POST": + s.handleUpdateScriptPolicyRequest([1]string{ + args[0], + }, elemIsEscaped, w, r) + default: + s.notAllowed(w, r, "DELETE,GET,POST") } - // Param: "FromScriptHash" - // Leaf parameter - args[0] = elem - elem = "" - - if len(elem) == 0 { - // Leaf node. - switch r.Method { - case "GET": - s.handleGetScriptPolicyFromHashRequest([1]string{ - args[0], - }, elemIsEscaped, w, r) - default: - s.notAllowed(w, r, "GET") - } - - return - } - - elem = origElem - case 'i': // Prefix: "id/" - origElem := elem - if l := len("id/"); len(elem) >= l && elem[0:l] == "id/" { - elem = elem[l:] - } else { - break - } - - // Param: "ScriptPolicyID" - // Leaf parameter - args[0] = elem - elem = "" - - if len(elem) == 0 { - // Leaf node. - switch r.Method { - case "DELETE": - s.handleDeleteScriptPolicyRequest([1]string{ - args[0], - }, elemIsEscaped, w, r) - case "GET": - s.handleGetScriptPolicyRequest([1]string{ - args[0], - }, elemIsEscaped, w, r) - case "POST": - s.handleUpdateScriptPolicyRequest([1]string{ - args[0], - }, elemIsEscaped, w, r) - default: - s.notAllowed(w, r, "DELETE,GET,POST") - } - - return - } - - elem = origElem + return } elem = origElem @@ -186,10 +143,12 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { if len(elem) == 0 { switch r.Method { + case "GET": + s.handleListScriptsRequest([0]string{}, elemIsEscaped, w, r) case "POST": s.handleCreateScriptRequest([0]string{}, elemIsEscaped, w, r) default: - s.notAllowed(w, r, "POST") + s.notAllowed(w, r, "GET,POST") } return @@ -684,86 +643,41 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) { break } + // Param: "ScriptPolicyID" + // Leaf parameter + args[0] = elem + elem = "" + if len(elem) == 0 { - break - } - switch elem[0] { - case 'h': // Prefix: "hash/" - origElem := elem - if l := len("hash/"); len(elem) >= l && elem[0:l] == "hash/" { - elem = elem[l:] - } else { - break + // Leaf node. + switch method { + case "DELETE": + r.name = DeleteScriptPolicyOperation + r.summary = "Delete the specified script policy by ID" + r.operationID = "deleteScriptPolicy" + r.pathPattern = "/script-policy/{ScriptPolicyID}" + r.args = args + r.count = 1 + return r, true + case "GET": + r.name = GetScriptPolicyOperation + r.summary = "Get the specified script policy by ID" + r.operationID = "getScriptPolicy" + r.pathPattern = "/script-policy/{ScriptPolicyID}" + r.args = args + r.count = 1 + return r, true + case "POST": + r.name = UpdateScriptPolicyOperation + r.summary = "Update the specified script policy by ID" + r.operationID = "updateScriptPolicy" + r.pathPattern = "/script-policy/{ScriptPolicyID}" + r.args = args + r.count = 1 + return r, true + default: + return } - - // Param: "FromScriptHash" - // Leaf parameter - args[0] = elem - elem = "" - - if len(elem) == 0 { - // Leaf node. - switch method { - case "GET": - r.name = GetScriptPolicyFromHashOperation - r.summary = "Get the policy for the given hash of script source code" - r.operationID = "getScriptPolicyFromHash" - r.pathPattern = "/script-policy/hash/{FromScriptHash}" - r.args = args - r.count = 1 - return r, true - default: - return - } - } - - elem = origElem - case 'i': // Prefix: "id/" - origElem := elem - if l := len("id/"); len(elem) >= l && elem[0:l] == "id/" { - elem = elem[l:] - } else { - break - } - - // Param: "ScriptPolicyID" - // Leaf parameter - args[0] = elem - elem = "" - - if len(elem) == 0 { - // Leaf node. - switch method { - case "DELETE": - r.name = DeleteScriptPolicyOperation - r.summary = "Delete the specified script policy by ID" - r.operationID = "deleteScriptPolicy" - r.pathPattern = "/script-policy/id/{ScriptPolicyID}" - r.args = args - r.count = 1 - return r, true - case "GET": - r.name = GetScriptPolicyOperation - r.summary = "Get the specified script policy by ID" - r.operationID = "getScriptPolicy" - r.pathPattern = "/script-policy/id/{ScriptPolicyID}" - r.args = args - r.count = 1 - return r, true - case "POST": - r.name = UpdateScriptPolicyOperation - r.summary = "Update the specified script policy by ID" - r.operationID = "updateScriptPolicy" - r.pathPattern = "/script-policy/id/{ScriptPolicyID}" - r.args = args - r.count = 1 - return r, true - default: - return - } - } - - elem = origElem } elem = origElem @@ -780,6 +694,14 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) { if len(elem) == 0 { switch method { + case "GET": + r.name = ListScriptsOperation + r.summary = "Get list of scripts" + r.operationID = "listScripts" + r.pathPattern = "/scripts" + r.args = args + r.count = 0 + return r, true case "POST": r.name = CreateScriptOperation r.summary = "Create a new script" diff --git a/pkg/api/oas_server_gen.go b/pkg/api/oas_server_gen.go index 08ff08e..ac66414 100644 --- a/pkg/api/oas_server_gen.go +++ b/pkg/api/oas_server_gen.go @@ -72,7 +72,7 @@ type Handler interface { // // Delete the specified script policy by ID. // - // DELETE /script-policy/id/{ScriptPolicyID} + // DELETE /script-policy/{ScriptPolicyID} DeleteScriptPolicy(ctx context.Context, params DeleteScriptPolicyParams) error // GetScript implements getScript operation. // @@ -84,14 +84,8 @@ type Handler interface { // // Get the specified script policy by ID. // - // GET /script-policy/id/{ScriptPolicyID} + // GET /script-policy/{ScriptPolicyID} GetScriptPolicy(ctx context.Context, params GetScriptPolicyParams) (*ScriptPolicy, error) - // GetScriptPolicyFromHash implements getScriptPolicyFromHash operation. - // - // Get the policy for the given hash of script source code. - // - // GET /script-policy/hash/{FromScriptHash} - GetScriptPolicyFromHash(ctx context.Context, params GetScriptPolicyFromHashParams) (*ScriptPolicy, error) // GetSubmission implements getSubmission operation. // // Retrieve map with ID. @@ -104,6 +98,12 @@ type Handler interface { // // GET /script-policy ListScriptPolicy(ctx context.Context, params ListScriptPolicyParams) ([]ScriptPolicy, error) + // ListScripts implements listScripts operation. + // + // Get list of scripts. + // + // GET /scripts + ListScripts(ctx context.Context, params ListScriptsParams) ([]Script, error) // ListSubmissions implements listSubmissions operation. // // Get list of submissions. @@ -126,7 +126,7 @@ type Handler interface { // // Update the specified script policy by ID. // - // POST /script-policy/id/{ScriptPolicyID} + // POST /script-policy/{ScriptPolicyID} UpdateScriptPolicy(ctx context.Context, req *ScriptPolicyUpdate, params UpdateScriptPolicyParams) error // UpdateSubmissionModel implements updateSubmissionModel operation. // diff --git a/pkg/api/oas_unimplemented_gen.go b/pkg/api/oas_unimplemented_gen.go index 6d6e6fa..b080398 100644 --- a/pkg/api/oas_unimplemented_gen.go +++ b/pkg/api/oas_unimplemented_gen.go @@ -107,7 +107,7 @@ func (UnimplementedHandler) DeleteScript(ctx context.Context, params DeleteScrip // // Delete the specified script policy by ID. // -// DELETE /script-policy/id/{ScriptPolicyID} +// DELETE /script-policy/{ScriptPolicyID} func (UnimplementedHandler) DeleteScriptPolicy(ctx context.Context, params DeleteScriptPolicyParams) error { return ht.ErrNotImplemented } @@ -125,20 +125,11 @@ func (UnimplementedHandler) GetScript(ctx context.Context, params GetScriptParam // // Get the specified script policy by ID. // -// GET /script-policy/id/{ScriptPolicyID} +// GET /script-policy/{ScriptPolicyID} func (UnimplementedHandler) GetScriptPolicy(ctx context.Context, params GetScriptPolicyParams) (r *ScriptPolicy, _ error) { return r, ht.ErrNotImplemented } -// GetScriptPolicyFromHash implements getScriptPolicyFromHash operation. -// -// Get the policy for the given hash of script source code. -// -// GET /script-policy/hash/{FromScriptHash} -func (UnimplementedHandler) GetScriptPolicyFromHash(ctx context.Context, params GetScriptPolicyFromHashParams) (r *ScriptPolicy, _ error) { - return r, ht.ErrNotImplemented -} - // GetSubmission implements getSubmission operation. // // Retrieve map with ID. @@ -157,6 +148,15 @@ func (UnimplementedHandler) ListScriptPolicy(ctx context.Context, params ListScr return r, ht.ErrNotImplemented } +// ListScripts implements listScripts operation. +// +// Get list of scripts. +// +// GET /scripts +func (UnimplementedHandler) ListScripts(ctx context.Context, params ListScriptsParams) (r []Script, _ error) { + return r, ht.ErrNotImplemented +} + // ListSubmissions implements listSubmissions operation. // // Get list of submissions. @@ -188,7 +188,7 @@ func (UnimplementedHandler) UpdateScript(ctx context.Context, req *ScriptUpdate, // // Update the specified script policy by ID. // -// POST /script-policy/id/{ScriptPolicyID} +// POST /script-policy/{ScriptPolicyID} func (UnimplementedHandler) UpdateScriptPolicy(ctx context.Context, req *ScriptPolicyUpdate, params UpdateScriptPolicyParams) error { return ht.ErrNotImplemented } diff --git a/pkg/internal/oas_client_gen.go b/pkg/internal/oas_client_gen.go index 20e9d2e..f279873 100644 --- a/pkg/internal/oas_client_gen.go +++ b/pkg/internal/oas_client_gen.go @@ -65,12 +65,18 @@ type Invoker interface { // // GET /scripts/{ScriptID} GetScript(ctx context.Context, params GetScriptParams) (*Script, error) - // GetScriptPolicyFromHash invokes getScriptPolicyFromHash operation. + // ListScriptPolicy invokes listScriptPolicy operation. // - // Get the policy for the given hash of script source code. + // Get list of script policies. // - // GET /script-policy/hash/{FromScriptHash} - GetScriptPolicyFromHash(ctx context.Context, params GetScriptPolicyFromHashParams) (*ScriptPolicy, error) + // GET /script-policy + ListScriptPolicy(ctx context.Context, params ListScriptPolicyParams) ([]ScriptPolicy, error) + // ListScripts invokes listScripts operation. + // + // Get list of scripts. + // + // GET /scripts + ListScripts(ctx context.Context, params ListScriptsParams) ([]Script, error) // UpdateSubmissionModel invokes updateSubmissionModel operation. // // Update model following role restrictions. @@ -756,21 +762,21 @@ func (c *Client) sendGetScript(ctx context.Context, params GetScriptParams) (res return result, nil } -// GetScriptPolicyFromHash invokes getScriptPolicyFromHash operation. +// ListScriptPolicy invokes listScriptPolicy operation. // -// Get the policy for the given hash of script source code. +// Get list of script policies. // -// GET /script-policy/hash/{FromScriptHash} -func (c *Client) GetScriptPolicyFromHash(ctx context.Context, params GetScriptPolicyFromHashParams) (*ScriptPolicy, error) { - res, err := c.sendGetScriptPolicyFromHash(ctx, params) +// GET /script-policy +func (c *Client) ListScriptPolicy(ctx context.Context, params ListScriptPolicyParams) ([]ScriptPolicy, error) { + res, err := c.sendListScriptPolicy(ctx, params) return res, err } -func (c *Client) sendGetScriptPolicyFromHash(ctx context.Context, params GetScriptPolicyFromHashParams) (res *ScriptPolicy, err error) { +func (c *Client) sendListScriptPolicy(ctx context.Context, params ListScriptPolicyParams) (res []ScriptPolicy, err error) { otelAttrs := []attribute.KeyValue{ - otelogen.OperationID("getScriptPolicyFromHash"), + otelogen.OperationID("listScriptPolicy"), semconv.HTTPRequestMethodKey.String("GET"), - semconv.HTTPRouteKey.String("/script-policy/hash/{FromScriptHash}"), + semconv.HTTPRouteKey.String("/script-policy"), } // Run stopwatch. @@ -785,7 +791,7 @@ func (c *Client) sendGetScriptPolicyFromHash(ctx context.Context, params GetScri c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) // Start a span for this request. - ctx, span := c.cfg.Tracer.Start(ctx, GetScriptPolicyFromHashOperation, + ctx, span := c.cfg.Tracer.Start(ctx, ListScriptPolicyOperation, trace.WithAttributes(otelAttrs...), clientSpanKind, ) @@ -802,27 +808,92 @@ func (c *Client) sendGetScriptPolicyFromHash(ctx context.Context, params GetScri stage = "BuildURL" u := uri.Clone(c.requestURL(ctx)) - var pathParts [2]string - pathParts[0] = "/script-policy/hash/" + var pathParts [1]string + pathParts[0] = "/script-policy" + uri.AddPathParts(u, pathParts[:]...) + + stage = "EncodeQueryParams" + q := uri.NewQueryEncoder() + { + // Encode "Page" parameter. + cfg := uri.QueryParameterEncodingConfig{ + Name: "Page", + Style: uri.QueryStyleForm, + Explode: true, + } + + if err := q.EncodeParam(cfg, func(e uri.Encoder) error { + return e.EncodeValue(conv.Int32ToString(params.Page)) + }); err != nil { + return res, errors.Wrap(err, "encode query") + } + } + { + // Encode "Limit" parameter. + cfg := uri.QueryParameterEncodingConfig{ + Name: "Limit", + Style: uri.QueryStyleForm, + Explode: true, + } + + if err := q.EncodeParam(cfg, func(e uri.Encoder) error { + return e.EncodeValue(conv.Int32ToString(params.Limit)) + }); err != nil { + return res, errors.Wrap(err, "encode query") + } + } { // Encode "FromScriptHash" parameter. - e := uri.NewPathEncoder(uri.PathEncoderConfig{ - Param: "FromScriptHash", - Style: uri.PathStyleSimple, - Explode: false, - }) - if err := func() error { - return e.EncodeValue(conv.StringToString(params.FromScriptHash)) - }(); err != nil { - return res, errors.Wrap(err, "encode path") + cfg := uri.QueryParameterEncodingConfig{ + Name: "FromScriptHash", + Style: uri.QueryStyleForm, + Explode: true, } - encoded, err := e.Result() - if err != nil { - return res, errors.Wrap(err, "encode path") + + if err := q.EncodeParam(cfg, func(e uri.Encoder) error { + if val, ok := params.FromScriptHash.Get(); ok { + return e.EncodeValue(conv.StringToString(val)) + } + return nil + }); err != nil { + return res, errors.Wrap(err, "encode query") } - pathParts[1] = encoded } - uri.AddPathParts(u, pathParts[:]...) + { + // Encode "ToScriptID" parameter. + cfg := uri.QueryParameterEncodingConfig{ + Name: "ToScriptID", + Style: uri.QueryStyleForm, + Explode: true, + } + + if err := q.EncodeParam(cfg, func(e uri.Encoder) error { + if val, ok := params.ToScriptID.Get(); ok { + return e.EncodeValue(conv.Int64ToString(val)) + } + return nil + }); err != nil { + return res, errors.Wrap(err, "encode query") + } + } + { + // Encode "Policy" parameter. + cfg := uri.QueryParameterEncodingConfig{ + Name: "Policy", + Style: uri.QueryStyleForm, + Explode: true, + } + + if err := q.EncodeParam(cfg, func(e uri.Encoder) error { + if val, ok := params.Policy.Get(); ok { + return e.EncodeValue(conv.Int32ToString(val)) + } + return nil + }); err != nil { + return res, errors.Wrap(err, "encode query") + } + } + u.RawQuery = q.Values().Encode() stage = "EncodeRequest" r, err := ht.NewRequest(ctx, "GET", u) @@ -838,7 +909,179 @@ func (c *Client) sendGetScriptPolicyFromHash(ctx context.Context, params GetScri defer resp.Body.Close() stage = "DecodeResponse" - result, err := decodeGetScriptPolicyFromHashResponse(resp) + result, err := decodeListScriptPolicyResponse(resp) + if err != nil { + return res, errors.Wrap(err, "decode response") + } + + return result, nil +} + +// ListScripts invokes listScripts operation. +// +// Get list of scripts. +// +// GET /scripts +func (c *Client) ListScripts(ctx context.Context, params ListScriptsParams) ([]Script, error) { + res, err := c.sendListScripts(ctx, params) + return res, err +} + +func (c *Client) sendListScripts(ctx context.Context, params ListScriptsParams) (res []Script, err error) { + otelAttrs := []attribute.KeyValue{ + otelogen.OperationID("listScripts"), + semconv.HTTPRequestMethodKey.String("GET"), + semconv.HTTPRouteKey.String("/scripts"), + } + + // Run stopwatch. + startTime := time.Now() + defer func() { + // Use floating point division here for higher precision (instead of Millisecond method). + elapsedDuration := time.Since(startTime) + c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...)) + }() + + // Increment request counter. + c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) + + // Start a span for this request. + ctx, span := c.cfg.Tracer.Start(ctx, ListScriptsOperation, + trace.WithAttributes(otelAttrs...), + clientSpanKind, + ) + // Track stage for error reporting. + var stage string + defer func() { + if err != nil { + span.RecordError(err) + span.SetStatus(codes.Error, stage) + c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) + } + span.End() + }() + + stage = "BuildURL" + u := uri.Clone(c.requestURL(ctx)) + var pathParts [1]string + pathParts[0] = "/scripts" + uri.AddPathParts(u, pathParts[:]...) + + stage = "EncodeQueryParams" + q := uri.NewQueryEncoder() + { + // Encode "Page" parameter. + cfg := uri.QueryParameterEncodingConfig{ + Name: "Page", + Style: uri.QueryStyleForm, + Explode: true, + } + + if err := q.EncodeParam(cfg, func(e uri.Encoder) error { + return e.EncodeValue(conv.Int32ToString(params.Page)) + }); err != nil { + return res, errors.Wrap(err, "encode query") + } + } + { + // Encode "Limit" parameter. + cfg := uri.QueryParameterEncodingConfig{ + Name: "Limit", + Style: uri.QueryStyleForm, + Explode: true, + } + + if err := q.EncodeParam(cfg, func(e uri.Encoder) error { + return e.EncodeValue(conv.Int32ToString(params.Limit)) + }); err != nil { + return res, errors.Wrap(err, "encode query") + } + } + { + // Encode "Hash" parameter. + cfg := uri.QueryParameterEncodingConfig{ + Name: "Hash", + Style: uri.QueryStyleForm, + Explode: true, + } + + if err := q.EncodeParam(cfg, func(e uri.Encoder) error { + if val, ok := params.Hash.Get(); ok { + return e.EncodeValue(conv.StringToString(val)) + } + return nil + }); err != nil { + return res, errors.Wrap(err, "encode query") + } + } + { + // Encode "Name" parameter. + cfg := uri.QueryParameterEncodingConfig{ + Name: "Name", + Style: uri.QueryStyleForm, + Explode: true, + } + + if err := q.EncodeParam(cfg, func(e uri.Encoder) error { + if val, ok := params.Name.Get(); ok { + return e.EncodeValue(conv.StringToString(val)) + } + return nil + }); err != nil { + return res, errors.Wrap(err, "encode query") + } + } + { + // Encode "Source" parameter. + cfg := uri.QueryParameterEncodingConfig{ + Name: "Source", + Style: uri.QueryStyleForm, + Explode: true, + } + + if err := q.EncodeParam(cfg, func(e uri.Encoder) error { + if val, ok := params.Source.Get(); ok { + return e.EncodeValue(conv.StringToString(val)) + } + return nil + }); err != nil { + return res, errors.Wrap(err, "encode query") + } + } + { + // Encode "SubmissionID" parameter. + cfg := uri.QueryParameterEncodingConfig{ + Name: "SubmissionID", + Style: uri.QueryStyleForm, + Explode: true, + } + + if err := q.EncodeParam(cfg, func(e uri.Encoder) error { + if val, ok := params.SubmissionID.Get(); ok { + return e.EncodeValue(conv.Int64ToString(val)) + } + return nil + }); err != nil { + return res, errors.Wrap(err, "encode query") + } + } + u.RawQuery = q.Values().Encode() + + stage = "EncodeRequest" + r, err := ht.NewRequest(ctx, "GET", u) + if err != nil { + return res, errors.Wrap(err, "create request") + } + + stage = "SendRequest" + resp, err := c.cfg.Client.Do(r) + if err != nil { + return res, errors.Wrap(err, "do request") + } + defer resp.Body.Close() + + stage = "DecodeResponse" + result, err := decodeListScriptsResponse(resp) if err != nil { return res, errors.Wrap(err, "decode response") } diff --git a/pkg/internal/oas_handlers_gen.go b/pkg/internal/oas_handlers_gen.go index c072c08..14b104a 100644 --- a/pkg/internal/oas_handlers_gen.go +++ b/pkg/internal/oas_handlers_gen.go @@ -1077,22 +1077,22 @@ func (s *Server) handleGetScriptRequest(args [1]string, argsEscaped bool, w http } } -// handleGetScriptPolicyFromHashRequest handles getScriptPolicyFromHash operation. +// handleListScriptPolicyRequest handles listScriptPolicy operation. // -// Get the policy for the given hash of script source code. +// Get list of script policies. // -// GET /script-policy/hash/{FromScriptHash} -func (s *Server) handleGetScriptPolicyFromHashRequest(args [1]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) { +// GET /script-policy +func (s *Server) handleListScriptPolicyRequest(args [0]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) { statusWriter := &codeRecorder{ResponseWriter: w} w = statusWriter otelAttrs := []attribute.KeyValue{ - otelogen.OperationID("getScriptPolicyFromHash"), + otelogen.OperationID("listScriptPolicy"), semconv.HTTPRequestMethodKey.String("GET"), - semconv.HTTPRouteKey.String("/script-policy/hash/{FromScriptHash}"), + semconv.HTTPRouteKey.String("/script-policy"), } // Start a span for this request. - ctx, span := s.cfg.Tracer.Start(r.Context(), GetScriptPolicyFromHashOperation, + ctx, span := s.cfg.Tracer.Start(r.Context(), ListScriptPolicyOperation, trace.WithAttributes(otelAttrs...), serverSpanKind, ) @@ -1147,11 +1147,11 @@ func (s *Server) handleGetScriptPolicyFromHashRequest(args [1]string, argsEscape } err error opErrContext = ogenerrors.OperationContext{ - Name: GetScriptPolicyFromHashOperation, - ID: "getScriptPolicyFromHash", + Name: ListScriptPolicyOperation, + ID: "listScriptPolicy", } ) - params, err := decodeGetScriptPolicyFromHashParams(args, argsEscaped, r) + params, err := decodeListScriptPolicyParams(args, argsEscaped, r) if err != nil { err = &ogenerrors.DecodeParamsError{ OperationContext: opErrContext, @@ -1162,27 +1162,43 @@ func (s *Server) handleGetScriptPolicyFromHashRequest(args [1]string, argsEscape return } - var response *ScriptPolicy + var response []ScriptPolicy if m := s.cfg.Middleware; m != nil { mreq := middleware.Request{ Context: ctx, - OperationName: GetScriptPolicyFromHashOperation, - OperationSummary: "Get the policy for the given hash of script source code", - OperationID: "getScriptPolicyFromHash", + OperationName: ListScriptPolicyOperation, + OperationSummary: "Get list of script policies", + OperationID: "listScriptPolicy", Body: nil, Params: middleware.Parameters{ + { + Name: "Page", + In: "query", + }: params.Page, + { + Name: "Limit", + In: "query", + }: params.Limit, { Name: "FromScriptHash", - In: "path", + In: "query", }: params.FromScriptHash, + { + Name: "ToScriptID", + In: "query", + }: params.ToScriptID, + { + Name: "Policy", + In: "query", + }: params.Policy, }, Raw: r, } type ( Request = struct{} - Params = GetScriptPolicyFromHashParams - Response = *ScriptPolicy + Params = ListScriptPolicyParams + Response = []ScriptPolicy ) response, err = middleware.HookMiddleware[ Request, @@ -1191,14 +1207,14 @@ func (s *Server) handleGetScriptPolicyFromHashRequest(args [1]string, argsEscape ]( m, mreq, - unpackGetScriptPolicyFromHashParams, + unpackListScriptPolicyParams, func(ctx context.Context, request Request, params Params) (response Response, err error) { - response, err = s.h.GetScriptPolicyFromHash(ctx, params) + response, err = s.h.ListScriptPolicy(ctx, params) return response, err }, ) } else { - response, err = s.h.GetScriptPolicyFromHash(ctx, params) + response, err = s.h.ListScriptPolicy(ctx, params) } if err != nil { if errRes, ok := errors.Into[*ErrorStatusCode](err); ok { @@ -1217,7 +1233,176 @@ func (s *Server) handleGetScriptPolicyFromHashRequest(args [1]string, argsEscape return } - if err := encodeGetScriptPolicyFromHashResponse(response, w, span); err != nil { + if err := encodeListScriptPolicyResponse(response, w, span); err != nil { + defer recordError("EncodeResponse", err) + if !errors.Is(err, ht.ErrInternalServerErrorResponse) { + s.cfg.ErrorHandler(ctx, w, r, err) + } + return + } +} + +// handleListScriptsRequest handles listScripts operation. +// +// Get list of scripts. +// +// GET /scripts +func (s *Server) handleListScriptsRequest(args [0]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) { + statusWriter := &codeRecorder{ResponseWriter: w} + w = statusWriter + otelAttrs := []attribute.KeyValue{ + otelogen.OperationID("listScripts"), + semconv.HTTPRequestMethodKey.String("GET"), + semconv.HTTPRouteKey.String("/scripts"), + } + + // Start a span for this request. + ctx, span := s.cfg.Tracer.Start(r.Context(), ListScriptsOperation, + trace.WithAttributes(otelAttrs...), + serverSpanKind, + ) + defer span.End() + + // Add Labeler to context. + labeler := &Labeler{attrs: otelAttrs} + ctx = contextWithLabeler(ctx, labeler) + + // Run stopwatch. + startTime := time.Now() + defer func() { + elapsedDuration := time.Since(startTime) + + attrSet := labeler.AttributeSet() + attrs := attrSet.ToSlice() + code := statusWriter.status + if code != 0 { + codeAttr := semconv.HTTPResponseStatusCode(code) + attrs = append(attrs, codeAttr) + span.SetAttributes(codeAttr) + } + attrOpt := metric.WithAttributes(attrs...) + + // Increment request counter. + s.requests.Add(ctx, 1, attrOpt) + + // Use floating point division here for higher precision (instead of Millisecond method). + s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt) + }() + + var ( + recordError = func(stage string, err error) { + span.RecordError(err) + + // https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status + // Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges, + // unless there was another error (e.g., network error receiving the response body; or 3xx codes with + // max redirects exceeded), in which case status MUST be set to Error. + code := statusWriter.status + if code >= 100 && code < 500 { + span.SetStatus(codes.Error, stage) + } + + attrSet := labeler.AttributeSet() + attrs := attrSet.ToSlice() + if code != 0 { + attrs = append(attrs, semconv.HTTPResponseStatusCode(code)) + } + + s.errors.Add(ctx, 1, metric.WithAttributes(attrs...)) + } + err error + opErrContext = ogenerrors.OperationContext{ + Name: ListScriptsOperation, + ID: "listScripts", + } + ) + params, err := decodeListScriptsParams(args, argsEscaped, r) + if err != nil { + err = &ogenerrors.DecodeParamsError{ + OperationContext: opErrContext, + Err: err, + } + defer recordError("DecodeParams", err) + s.cfg.ErrorHandler(ctx, w, r, err) + return + } + + var response []Script + if m := s.cfg.Middleware; m != nil { + mreq := middleware.Request{ + Context: ctx, + OperationName: ListScriptsOperation, + OperationSummary: "Get list of scripts", + OperationID: "listScripts", + Body: nil, + Params: middleware.Parameters{ + { + Name: "Page", + In: "query", + }: params.Page, + { + Name: "Limit", + In: "query", + }: params.Limit, + { + Name: "Hash", + In: "query", + }: params.Hash, + { + Name: "Name", + In: "query", + }: params.Name, + { + Name: "Source", + In: "query", + }: params.Source, + { + Name: "SubmissionID", + In: "query", + }: params.SubmissionID, + }, + Raw: r, + } + + type ( + Request = struct{} + Params = ListScriptsParams + Response = []Script + ) + response, err = middleware.HookMiddleware[ + Request, + Params, + Response, + ]( + m, + mreq, + unpackListScriptsParams, + func(ctx context.Context, request Request, params Params) (response Response, err error) { + response, err = s.h.ListScripts(ctx, params) + return response, err + }, + ) + } else { + response, err = s.h.ListScripts(ctx, params) + } + if err != nil { + if errRes, ok := errors.Into[*ErrorStatusCode](err); ok { + if err := encodeErrorResponse(errRes, w, span); err != nil { + defer recordError("Internal", err) + } + return + } + if errors.Is(err, ht.ErrNotImplemented) { + s.cfg.ErrorHandler(ctx, w, r, err) + return + } + if err := encodeErrorResponse(s.h.NewError(ctx, err), w, span); err != nil { + defer recordError("Internal", err) + } + return + } + + if err := encodeListScriptsResponse(response, w, span); err != nil { defer recordError("EncodeResponse", err) if !errors.Is(err, ht.ErrInternalServerErrorResponse) { s.cfg.ErrorHandler(ctx, w, r, err) diff --git a/pkg/internal/oas_operations_gen.go b/pkg/internal/oas_operations_gen.go index 31c7a14..ad092f8 100644 --- a/pkg/internal/oas_operations_gen.go +++ b/pkg/internal/oas_operations_gen.go @@ -13,6 +13,7 @@ const ( CreateScriptOperation OperationName = "CreateScript" CreateScriptPolicyOperation OperationName = "CreateScriptPolicy" GetScriptOperation OperationName = "GetScript" - GetScriptPolicyFromHashOperation OperationName = "GetScriptPolicyFromHash" + ListScriptPolicyOperation OperationName = "ListScriptPolicy" + ListScriptsOperation OperationName = "ListScripts" UpdateSubmissionModelOperation OperationName = "UpdateSubmissionModel" ) diff --git a/pkg/internal/oas_parameters_gen.go b/pkg/internal/oas_parameters_gen.go index d75b26c..ebab54c 100644 --- a/pkg/internal/oas_parameters_gen.go +++ b/pkg/internal/oas_parameters_gen.go @@ -397,68 +397,99 @@ func decodeGetScriptParams(args [1]string, argsEscaped bool, r *http.Request) (p return params, nil } -// GetScriptPolicyFromHashParams is parameters of getScriptPolicyFromHash operation. -type GetScriptPolicyFromHashParams struct { - FromScriptHash string +// ListScriptPolicyParams is parameters of listScriptPolicy operation. +type ListScriptPolicyParams struct { + Page int32 + Limit int32 + FromScriptHash OptString + ToScriptID OptInt64 + Policy OptInt32 } -func unpackGetScriptPolicyFromHashParams(packed middleware.Parameters) (params GetScriptPolicyFromHashParams) { +func unpackListScriptPolicyParams(packed middleware.Parameters) (params ListScriptPolicyParams) { + { + key := middleware.ParameterKey{ + Name: "Page", + In: "query", + } + params.Page = packed[key].(int32) + } + { + key := middleware.ParameterKey{ + Name: "Limit", + In: "query", + } + params.Limit = packed[key].(int32) + } { key := middleware.ParameterKey{ Name: "FromScriptHash", - In: "path", + In: "query", + } + if v, ok := packed[key]; ok { + params.FromScriptHash = v.(OptString) + } + } + { + key := middleware.ParameterKey{ + Name: "ToScriptID", + In: "query", + } + if v, ok := packed[key]; ok { + params.ToScriptID = v.(OptInt64) + } + } + { + key := middleware.ParameterKey{ + Name: "Policy", + In: "query", + } + if v, ok := packed[key]; ok { + params.Policy = v.(OptInt32) } - params.FromScriptHash = packed[key].(string) } return params } -func decodeGetScriptPolicyFromHashParams(args [1]string, argsEscaped bool, r *http.Request) (params GetScriptPolicyFromHashParams, _ error) { - // Decode path: FromScriptHash. +func decodeListScriptPolicyParams(args [0]string, argsEscaped bool, r *http.Request) (params ListScriptPolicyParams, _ error) { + q := uri.NewQueryDecoder(r.URL.Query()) + // Decode query: Page. if err := func() error { - param := args[0] - if argsEscaped { - unescaped, err := url.PathUnescape(args[0]) - if err != nil { - return errors.Wrap(err, "unescape path") - } - param = unescaped + cfg := uri.QueryParameterDecodingConfig{ + Name: "Page", + Style: uri.QueryStyleForm, + Explode: true, } - if len(param) > 0 { - d := uri.NewPathDecoder(uri.PathDecoderConfig{ - Param: "FromScriptHash", - Value: param, - Style: uri.PathStyleSimple, - Explode: false, - }) - if err := func() error { + if err := q.HasParam(cfg); err == nil { + if err := q.DecodeParam(cfg, func(d uri.Decoder) error { val, err := d.DecodeValue() if err != nil { return err } - c, err := conv.ToString(val) + c, err := conv.ToInt32(val) if err != nil { return err } - params.FromScriptHash = c + params.Page = c return nil - }(); err != nil { + }); err != nil { return err } if err := func() error { - if err := (validate.String{ - MinLength: 16, - MinLengthSet: true, - MaxLength: 16, - MaxLengthSet: true, - Email: false, - Hostname: false, - Regex: nil, - }).Validate(string(params.FromScriptHash)); err != nil { - return errors.Wrap(err, "string") + if err := (validate.Int{ + MinSet: true, + Min: 1, + MaxSet: false, + Max: 0, + MinExclusive: false, + MaxExclusive: false, + MultipleOfSet: false, + MultipleOf: 0, + }).Validate(int64(params.Page)); err != nil { + return errors.Wrap(err, "int") } return nil }(); err != nil { @@ -468,10 +499,617 @@ func decodeGetScriptPolicyFromHashParams(args [1]string, argsEscaped bool, r *ht return validate.ErrFieldRequired } return nil + }(); err != nil { + return params, &ogenerrors.DecodeParamError{ + Name: "Page", + In: "query", + Err: err, + } + } + // Decode query: Limit. + if err := func() error { + cfg := uri.QueryParameterDecodingConfig{ + Name: "Limit", + Style: uri.QueryStyleForm, + Explode: true, + } + + if err := q.HasParam(cfg); err == nil { + if err := q.DecodeParam(cfg, func(d uri.Decoder) error { + val, err := d.DecodeValue() + if err != nil { + return err + } + + c, err := conv.ToInt32(val) + if err != nil { + return err + } + + params.Limit = c + return nil + }); err != nil { + return err + } + if err := func() error { + if err := (validate.Int{ + MinSet: true, + Min: 1, + MaxSet: true, + Max: 100, + MinExclusive: false, + MaxExclusive: false, + MultipleOfSet: false, + MultipleOf: 0, + }).Validate(int64(params.Limit)); err != nil { + return errors.Wrap(err, "int") + } + return nil + }(); err != nil { + return err + } + } else { + return validate.ErrFieldRequired + } + return nil + }(); err != nil { + return params, &ogenerrors.DecodeParamError{ + Name: "Limit", + In: "query", + Err: err, + } + } + // Decode query: FromScriptHash. + if err := func() error { + cfg := uri.QueryParameterDecodingConfig{ + Name: "FromScriptHash", + Style: uri.QueryStyleForm, + Explode: true, + } + + if err := q.HasParam(cfg); err == nil { + if err := q.DecodeParam(cfg, func(d uri.Decoder) error { + var paramsDotFromScriptHashVal string + if err := func() error { + val, err := d.DecodeValue() + if err != nil { + return err + } + + c, err := conv.ToString(val) + if err != nil { + return err + } + + paramsDotFromScriptHashVal = c + return nil + }(); err != nil { + return err + } + params.FromScriptHash.SetTo(paramsDotFromScriptHashVal) + return nil + }); err != nil { + return err + } + if err := func() error { + if value, ok := params.FromScriptHash.Get(); ok { + if err := func() error { + if err := (validate.String{ + MinLength: 16, + MinLengthSet: true, + MaxLength: 16, + MaxLengthSet: true, + Email: false, + Hostname: false, + Regex: nil, + }).Validate(string(value)); err != nil { + return errors.Wrap(err, "string") + } + return nil + }(); err != nil { + return err + } + } + return nil + }(); err != nil { + return err + } + } + return nil }(); err != nil { return params, &ogenerrors.DecodeParamError{ Name: "FromScriptHash", - In: "path", + In: "query", + Err: err, + } + } + // Decode query: ToScriptID. + if err := func() error { + cfg := uri.QueryParameterDecodingConfig{ + Name: "ToScriptID", + Style: uri.QueryStyleForm, + Explode: true, + } + + if err := q.HasParam(cfg); err == nil { + if err := q.DecodeParam(cfg, func(d uri.Decoder) error { + var paramsDotToScriptIDVal int64 + if err := func() error { + val, err := d.DecodeValue() + if err != nil { + return err + } + + c, err := conv.ToInt64(val) + if err != nil { + return err + } + + paramsDotToScriptIDVal = c + return nil + }(); err != nil { + return err + } + params.ToScriptID.SetTo(paramsDotToScriptIDVal) + return nil + }); err != nil { + return err + } + } + return nil + }(); err != nil { + return params, &ogenerrors.DecodeParamError{ + Name: "ToScriptID", + In: "query", + Err: err, + } + } + // Decode query: Policy. + if err := func() error { + cfg := uri.QueryParameterDecodingConfig{ + Name: "Policy", + Style: uri.QueryStyleForm, + Explode: true, + } + + if err := q.HasParam(cfg); err == nil { + if err := q.DecodeParam(cfg, func(d uri.Decoder) error { + var paramsDotPolicyVal int32 + if err := func() error { + val, err := d.DecodeValue() + if err != nil { + return err + } + + c, err := conv.ToInt32(val) + if err != nil { + return err + } + + paramsDotPolicyVal = c + return nil + }(); err != nil { + return err + } + params.Policy.SetTo(paramsDotPolicyVal) + return nil + }); err != nil { + return err + } + } + return nil + }(); err != nil { + return params, &ogenerrors.DecodeParamError{ + Name: "Policy", + In: "query", + Err: err, + } + } + return params, nil +} + +// ListScriptsParams is parameters of listScripts operation. +type ListScriptsParams struct { + Page int32 + Limit int32 + Hash OptString + Name OptString + Source OptString + SubmissionID OptInt64 +} + +func unpackListScriptsParams(packed middleware.Parameters) (params ListScriptsParams) { + { + key := middleware.ParameterKey{ + Name: "Page", + In: "query", + } + params.Page = packed[key].(int32) + } + { + key := middleware.ParameterKey{ + Name: "Limit", + In: "query", + } + params.Limit = packed[key].(int32) + } + { + key := middleware.ParameterKey{ + Name: "Hash", + In: "query", + } + if v, ok := packed[key]; ok { + params.Hash = v.(OptString) + } + } + { + key := middleware.ParameterKey{ + Name: "Name", + In: "query", + } + if v, ok := packed[key]; ok { + params.Name = v.(OptString) + } + } + { + key := middleware.ParameterKey{ + Name: "Source", + In: "query", + } + if v, ok := packed[key]; ok { + params.Source = v.(OptString) + } + } + { + key := middleware.ParameterKey{ + Name: "SubmissionID", + In: "query", + } + if v, ok := packed[key]; ok { + params.SubmissionID = v.(OptInt64) + } + } + return params +} + +func decodeListScriptsParams(args [0]string, argsEscaped bool, r *http.Request) (params ListScriptsParams, _ error) { + q := uri.NewQueryDecoder(r.URL.Query()) + // Decode query: Page. + if err := func() error { + cfg := uri.QueryParameterDecodingConfig{ + Name: "Page", + Style: uri.QueryStyleForm, + Explode: true, + } + + if err := q.HasParam(cfg); err == nil { + if err := q.DecodeParam(cfg, func(d uri.Decoder) error { + val, err := d.DecodeValue() + if err != nil { + return err + } + + c, err := conv.ToInt32(val) + if err != nil { + return err + } + + params.Page = c + return nil + }); err != nil { + return err + } + if err := func() error { + if err := (validate.Int{ + MinSet: true, + Min: 1, + MaxSet: false, + Max: 0, + MinExclusive: false, + MaxExclusive: false, + MultipleOfSet: false, + MultipleOf: 0, + }).Validate(int64(params.Page)); err != nil { + return errors.Wrap(err, "int") + } + return nil + }(); err != nil { + return err + } + } else { + return validate.ErrFieldRequired + } + return nil + }(); err != nil { + return params, &ogenerrors.DecodeParamError{ + Name: "Page", + In: "query", + Err: err, + } + } + // Decode query: Limit. + if err := func() error { + cfg := uri.QueryParameterDecodingConfig{ + Name: "Limit", + Style: uri.QueryStyleForm, + Explode: true, + } + + if err := q.HasParam(cfg); err == nil { + if err := q.DecodeParam(cfg, func(d uri.Decoder) error { + val, err := d.DecodeValue() + if err != nil { + return err + } + + c, err := conv.ToInt32(val) + if err != nil { + return err + } + + params.Limit = c + return nil + }); err != nil { + return err + } + if err := func() error { + if err := (validate.Int{ + MinSet: true, + Min: 1, + MaxSet: true, + Max: 100, + MinExclusive: false, + MaxExclusive: false, + MultipleOfSet: false, + MultipleOf: 0, + }).Validate(int64(params.Limit)); err != nil { + return errors.Wrap(err, "int") + } + return nil + }(); err != nil { + return err + } + } else { + return validate.ErrFieldRequired + } + return nil + }(); err != nil { + return params, &ogenerrors.DecodeParamError{ + Name: "Limit", + In: "query", + Err: err, + } + } + // Decode query: Hash. + if err := func() error { + cfg := uri.QueryParameterDecodingConfig{ + Name: "Hash", + Style: uri.QueryStyleForm, + Explode: true, + } + + if err := q.HasParam(cfg); err == nil { + if err := q.DecodeParam(cfg, func(d uri.Decoder) error { + var paramsDotHashVal string + if err := func() error { + val, err := d.DecodeValue() + if err != nil { + return err + } + + c, err := conv.ToString(val) + if err != nil { + return err + } + + paramsDotHashVal = c + return nil + }(); err != nil { + return err + } + params.Hash.SetTo(paramsDotHashVal) + return nil + }); err != nil { + return err + } + if err := func() error { + if value, ok := params.Hash.Get(); ok { + if err := func() error { + if err := (validate.String{ + MinLength: 16, + MinLengthSet: true, + MaxLength: 16, + MaxLengthSet: true, + Email: false, + Hostname: false, + Regex: nil, + }).Validate(string(value)); err != nil { + return errors.Wrap(err, "string") + } + return nil + }(); err != nil { + return err + } + } + return nil + }(); err != nil { + return err + } + } + return nil + }(); err != nil { + return params, &ogenerrors.DecodeParamError{ + Name: "Hash", + In: "query", + Err: err, + } + } + // Decode query: Name. + if err := func() error { + cfg := uri.QueryParameterDecodingConfig{ + Name: "Name", + Style: uri.QueryStyleForm, + Explode: true, + } + + if err := q.HasParam(cfg); err == nil { + if err := q.DecodeParam(cfg, func(d uri.Decoder) error { + var paramsDotNameVal string + if err := func() error { + val, err := d.DecodeValue() + if err != nil { + return err + } + + c, err := conv.ToString(val) + if err != nil { + return err + } + + paramsDotNameVal = c + return nil + }(); err != nil { + return err + } + params.Name.SetTo(paramsDotNameVal) + return nil + }); err != nil { + return err + } + if err := func() error { + if value, ok := params.Name.Get(); ok { + if err := func() error { + if err := (validate.String{ + MinLength: 0, + MinLengthSet: false, + MaxLength: 128, + MaxLengthSet: true, + Email: false, + Hostname: false, + Regex: nil, + }).Validate(string(value)); err != nil { + return errors.Wrap(err, "string") + } + return nil + }(); err != nil { + return err + } + } + return nil + }(); err != nil { + return err + } + } + return nil + }(); err != nil { + return params, &ogenerrors.DecodeParamError{ + Name: "Name", + In: "query", + Err: err, + } + } + // Decode query: Source. + if err := func() error { + cfg := uri.QueryParameterDecodingConfig{ + Name: "Source", + Style: uri.QueryStyleForm, + Explode: true, + } + + if err := q.HasParam(cfg); err == nil { + if err := q.DecodeParam(cfg, func(d uri.Decoder) error { + var paramsDotSourceVal string + if err := func() error { + val, err := d.DecodeValue() + if err != nil { + return err + } + + c, err := conv.ToString(val) + if err != nil { + return err + } + + paramsDotSourceVal = c + return nil + }(); err != nil { + return err + } + params.Source.SetTo(paramsDotSourceVal) + return nil + }); err != nil { + return err + } + if err := func() error { + if value, ok := params.Source.Get(); ok { + if err := func() error { + if err := (validate.String{ + MinLength: 0, + MinLengthSet: false, + MaxLength: 1048576, + MaxLengthSet: true, + Email: false, + Hostname: false, + Regex: nil, + }).Validate(string(value)); err != nil { + return errors.Wrap(err, "string") + } + return nil + }(); err != nil { + return err + } + } + return nil + }(); err != nil { + return err + } + } + return nil + }(); err != nil { + return params, &ogenerrors.DecodeParamError{ + Name: "Source", + In: "query", + Err: err, + } + } + // Decode query: SubmissionID. + if err := func() error { + cfg := uri.QueryParameterDecodingConfig{ + Name: "SubmissionID", + Style: uri.QueryStyleForm, + Explode: true, + } + + if err := q.HasParam(cfg); err == nil { + if err := q.DecodeParam(cfg, func(d uri.Decoder) error { + var paramsDotSubmissionIDVal int64 + if err := func() error { + val, err := d.DecodeValue() + if err != nil { + return err + } + + c, err := conv.ToInt64(val) + if err != nil { + return err + } + + paramsDotSubmissionIDVal = c + return nil + }(); err != nil { + return err + } + params.SubmissionID.SetTo(paramsDotSubmissionIDVal) + return nil + }); err != nil { + return err + } + } + return nil + }(); err != nil { + return params, &ogenerrors.DecodeParamError{ + Name: "SubmissionID", + In: "query", Err: err, } } diff --git a/pkg/internal/oas_response_decoders_gen.go b/pkg/internal/oas_response_decoders_gen.go index 6594497..b1abc6f 100644 --- a/pkg/internal/oas_response_decoders_gen.go +++ b/pkg/internal/oas_response_decoders_gen.go @@ -3,6 +3,7 @@ package api import ( + "fmt" "io" "mime" "net/http" @@ -476,7 +477,7 @@ func decodeGetScriptResponse(resp *http.Response) (res *Script, _ error) { return res, errors.Wrap(defRes, "error") } -func decodeGetScriptPolicyFromHashResponse(resp *http.Response) (res *ScriptPolicy, _ error) { +func decodeListScriptPolicyResponse(resp *http.Response) (res []ScriptPolicy, _ error) { switch resp.StatusCode { case 200: // Code 200. @@ -492,9 +493,17 @@ func decodeGetScriptPolicyFromHashResponse(resp *http.Response) (res *ScriptPoli } d := jx.DecodeBytes(buf) - var response ScriptPolicy + var response []ScriptPolicy if err := func() error { - if err := response.Decode(d); err != nil { + response = make([]ScriptPolicy, 0) + if err := d.Arr(func(d *jx.Decoder) error { + var elem ScriptPolicy + if err := elem.Decode(d); err != nil { + return err + } + response = append(response, elem) + return nil + }); err != nil { return err } if err := d.Skip(); err != io.EOF { @@ -511,14 +520,148 @@ func decodeGetScriptPolicyFromHashResponse(resp *http.Response) (res *ScriptPoli } // Validate response. if err := func() error { - if err := response.Validate(); err != nil { - return err + if response == nil { + return errors.New("nil is invalid value") + } + var failures []validate.FieldError + for i, elem := range response { + if err := func() error { + if err := elem.Validate(); err != nil { + return err + } + return nil + }(); err != nil { + failures = append(failures, validate.FieldError{ + Name: fmt.Sprintf("[%d]", i), + Error: err, + }) + } + } + if len(failures) > 0 { + return &validate.Error{Fields: failures} } return nil }(); err != nil { return res, errors.Wrap(err, "validate") } - return &response, nil + return response, nil + default: + return res, validate.InvalidContentType(ct) + } + } + // Convenient error response. + defRes, err := func() (res *ErrorStatusCode, err error) { + ct, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type")) + if err != nil { + return res, errors.Wrap(err, "parse media type") + } + switch { + case ct == "application/json": + buf, err := io.ReadAll(resp.Body) + if err != nil { + return res, err + } + d := jx.DecodeBytes(buf) + + var response Error + if err := func() error { + if err := response.Decode(d); err != nil { + return err + } + if err := d.Skip(); err != io.EOF { + return errors.New("unexpected trailing data") + } + return nil + }(); err != nil { + err = &ogenerrors.DecodeBodyError{ + ContentType: ct, + Body: buf, + Err: err, + } + return res, err + } + return &ErrorStatusCode{ + StatusCode: resp.StatusCode, + Response: response, + }, nil + default: + return res, validate.InvalidContentType(ct) + } + }() + if err != nil { + return res, errors.Wrapf(err, "default (code %d)", resp.StatusCode) + } + return res, errors.Wrap(defRes, "error") +} + +func decodeListScriptsResponse(resp *http.Response) (res []Script, _ error) { + switch resp.StatusCode { + case 200: + // Code 200. + ct, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type")) + if err != nil { + return res, errors.Wrap(err, "parse media type") + } + switch { + case ct == "application/json": + buf, err := io.ReadAll(resp.Body) + if err != nil { + return res, err + } + d := jx.DecodeBytes(buf) + + var response []Script + if err := func() error { + response = make([]Script, 0) + if err := d.Arr(func(d *jx.Decoder) error { + var elem Script + if err := elem.Decode(d); err != nil { + return err + } + response = append(response, elem) + return nil + }); err != nil { + return err + } + if err := d.Skip(); err != io.EOF { + return errors.New("unexpected trailing data") + } + return nil + }(); err != nil { + err = &ogenerrors.DecodeBodyError{ + ContentType: ct, + Body: buf, + Err: err, + } + return res, err + } + // Validate response. + if err := func() error { + if response == nil { + return errors.New("nil is invalid value") + } + var failures []validate.FieldError + for i, elem := range response { + if err := func() error { + if err := elem.Validate(); err != nil { + return err + } + return nil + }(); err != nil { + failures = append(failures, validate.FieldError{ + Name: fmt.Sprintf("[%d]", i), + Error: err, + }) + } + } + if len(failures) > 0 { + return &validate.Error{Fields: failures} + } + return nil + }(); err != nil { + return res, errors.Wrap(err, "validate") + } + return response, nil default: return res, validate.InvalidContentType(ct) } diff --git a/pkg/internal/oas_response_encoders_gen.go b/pkg/internal/oas_response_encoders_gen.go index 1c2c959..345b8f5 100644 --- a/pkg/internal/oas_response_encoders_gen.go +++ b/pkg/internal/oas_response_encoders_gen.go @@ -83,13 +83,35 @@ func encodeGetScriptResponse(response *Script, w http.ResponseWriter, span trace return nil } -func encodeGetScriptPolicyFromHashResponse(response *ScriptPolicy, w http.ResponseWriter, span trace.Span) error { +func encodeListScriptPolicyResponse(response []ScriptPolicy, w http.ResponseWriter, span trace.Span) error { w.Header().Set("Content-Type", "application/json; charset=utf-8") w.WriteHeader(200) span.SetStatus(codes.Ok, http.StatusText(200)) e := new(jx.Encoder) - response.Encode(e) + e.ArrStart() + for _, elem := range response { + elem.Encode(e) + } + e.ArrEnd() + if _, err := e.WriteTo(w); err != nil { + return errors.Wrap(err, "write") + } + + return nil +} + +func encodeListScriptsResponse(response []Script, w http.ResponseWriter, span trace.Span) error { + w.Header().Set("Content-Type", "application/json; charset=utf-8") + w.WriteHeader(200) + span.SetStatus(codes.Ok, http.StatusText(200)) + + e := new(jx.Encoder) + e.ArrStart() + for _, elem := range response { + elem.Encode(e) + } + e.ArrEnd() if _, err := e.WriteTo(w); err != nil { return errors.Wrap(err, "write") } diff --git a/pkg/internal/oas_router_gen.go b/pkg/internal/oas_router_gen.go index e8907bb..11c3fcc 100644 --- a/pkg/internal/oas_router_gen.go +++ b/pkg/internal/oas_router_gen.go @@ -82,45 +82,18 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { } if len(elem) == 0 { + // Leaf node. switch r.Method { + case "GET": + s.handleListScriptPolicyRequest([0]string{}, elemIsEscaped, w, r) case "POST": s.handleCreateScriptPolicyRequest([0]string{}, elemIsEscaped, w, r) default: - s.notAllowed(w, r, "POST") + s.notAllowed(w, r, "GET,POST") } return } - switch elem[0] { - case '/': // Prefix: "/hash/" - origElem := elem - if l := len("/hash/"); len(elem) >= l && elem[0:l] == "/hash/" { - elem = elem[l:] - } else { - break - } - - // Param: "FromScriptHash" - // Leaf parameter - args[0] = elem - elem = "" - - if len(elem) == 0 { - // Leaf node. - switch r.Method { - case "GET": - s.handleGetScriptPolicyFromHashRequest([1]string{ - args[0], - }, elemIsEscaped, w, r) - default: - s.notAllowed(w, r, "GET") - } - - return - } - - elem = origElem - } elem = origElem case 's': // Prefix: "s" @@ -133,10 +106,12 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { if len(elem) == 0 { switch r.Method { + case "GET": + s.handleListScriptsRequest([0]string{}, elemIsEscaped, w, r) case "POST": s.handleCreateScriptRequest([0]string{}, elemIsEscaped, w, r) default: - s.notAllowed(w, r, "POST") + s.notAllowed(w, r, "GET,POST") } return @@ -476,7 +451,16 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) { } if len(elem) == 0 { + // Leaf node. switch method { + case "GET": + r.name = ListScriptPolicyOperation + r.summary = "Get list of script policies" + r.operationID = "listScriptPolicy" + r.pathPattern = "/script-policy" + r.args = args + r.count = 0 + return r, true case "POST": r.name = CreateScriptPolicyOperation r.summary = "Create a new script policy" @@ -489,38 +473,6 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) { return } } - switch elem[0] { - case '/': // Prefix: "/hash/" - origElem := elem - if l := len("/hash/"); len(elem) >= l && elem[0:l] == "/hash/" { - elem = elem[l:] - } else { - break - } - - // Param: "FromScriptHash" - // Leaf parameter - args[0] = elem - elem = "" - - if len(elem) == 0 { - // Leaf node. - switch method { - case "GET": - r.name = GetScriptPolicyFromHashOperation - r.summary = "Get the policy for the given hash of script source code" - r.operationID = "getScriptPolicyFromHash" - r.pathPattern = "/script-policy/hash/{FromScriptHash}" - r.args = args - r.count = 1 - return r, true - default: - return - } - } - - elem = origElem - } elem = origElem case 's': // Prefix: "s" @@ -533,6 +485,14 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) { if len(elem) == 0 { switch method { + case "GET": + r.name = ListScriptsOperation + r.summary = "Get list of scripts" + r.operationID = "listScripts" + r.pathPattern = "/scripts" + r.args = args + r.count = 0 + return r, true case "POST": r.name = CreateScriptOperation r.summary = "Create a new script" diff --git a/pkg/internal/oas_schemas_gen.go b/pkg/internal/oas_schemas_gen.go index e3106c3..2b4a6c5 100644 --- a/pkg/internal/oas_schemas_gen.go +++ b/pkg/internal/oas_schemas_gen.go @@ -90,6 +90,52 @@ func (s *ID) SetID(val int64) { s.ID = val } +// NewOptInt32 returns new OptInt32 with value set to v. +func NewOptInt32(v int32) OptInt32 { + return OptInt32{ + Value: v, + Set: true, + } +} + +// OptInt32 is optional int32. +type OptInt32 struct { + Value int32 + Set bool +} + +// IsSet returns true if OptInt32 was set. +func (o OptInt32) IsSet() bool { return o.Set } + +// Reset unsets value. +func (o *OptInt32) Reset() { + var v int32 + o.Value = v + o.Set = false +} + +// SetTo sets value to v. +func (o *OptInt32) SetTo(v int32) { + o.Set = true + o.Value = v +} + +// Get returns value and boolean that denotes whether value was set. +func (o OptInt32) Get() (v int32, ok bool) { + if !o.Set { + return v, false + } + return o.Value, true +} + +// Or returns value if set, or given parameter if does not. +func (o OptInt32) Or(d int32) int32 { + if v, ok := o.Get(); ok { + return v + } + return d +} + // NewOptInt64 returns new OptInt64 with value set to v. func NewOptInt64(v int64) OptInt64 { return OptInt64{ @@ -136,6 +182,52 @@ func (o OptInt64) Or(d int64) int64 { return d } +// NewOptString returns new OptString with value set to v. +func NewOptString(v string) OptString { + return OptString{ + Value: v, + Set: true, + } +} + +// OptString is optional string. +type OptString struct { + Value string + Set bool +} + +// IsSet returns true if OptString was set. +func (o OptString) IsSet() bool { return o.Set } + +// Reset unsets value. +func (o *OptString) Reset() { + var v string + o.Value = v + o.Set = false +} + +// SetTo sets value to v. +func (o *OptString) SetTo(v string) { + o.Set = true + o.Value = v +} + +// Get returns value and boolean that denotes whether value was set. +func (o OptString) Get() (v string, ok bool) { + if !o.Set { + return v, false + } + return o.Value, true +} + +// Or returns value if set, or given parameter if does not. +func (o OptString) Or(d string) string { + if v, ok := o.Get(); ok { + return v + } + return d +} + // Ref: #/components/schemas/Script type Script struct { ID int64 `json:"ID"` diff --git a/pkg/internal/oas_server_gen.go b/pkg/internal/oas_server_gen.go index f266fc6..6b6d9f3 100644 --- a/pkg/internal/oas_server_gen.go +++ b/pkg/internal/oas_server_gen.go @@ -50,12 +50,18 @@ type Handler interface { // // GET /scripts/{ScriptID} GetScript(ctx context.Context, params GetScriptParams) (*Script, error) - // GetScriptPolicyFromHash implements getScriptPolicyFromHash operation. + // ListScriptPolicy implements listScriptPolicy operation. // - // Get the policy for the given hash of script source code. + // Get list of script policies. // - // GET /script-policy/hash/{FromScriptHash} - GetScriptPolicyFromHash(ctx context.Context, params GetScriptPolicyFromHashParams) (*ScriptPolicy, error) + // GET /script-policy + ListScriptPolicy(ctx context.Context, params ListScriptPolicyParams) ([]ScriptPolicy, error) + // ListScripts implements listScripts operation. + // + // Get list of scripts. + // + // GET /scripts + ListScripts(ctx context.Context, params ListScriptsParams) ([]Script, error) // UpdateSubmissionModel implements updateSubmissionModel operation. // // Update model following role restrictions. diff --git a/pkg/internal/oas_unimplemented_gen.go b/pkg/internal/oas_unimplemented_gen.go index 898a52c..9228c85 100644 --- a/pkg/internal/oas_unimplemented_gen.go +++ b/pkg/internal/oas_unimplemented_gen.go @@ -76,12 +76,21 @@ func (UnimplementedHandler) GetScript(ctx context.Context, params GetScriptParam return r, ht.ErrNotImplemented } -// GetScriptPolicyFromHash implements getScriptPolicyFromHash operation. +// ListScriptPolicy implements listScriptPolicy operation. // -// Get the policy for the given hash of script source code. +// Get list of script policies. // -// GET /script-policy/hash/{FromScriptHash} -func (UnimplementedHandler) GetScriptPolicyFromHash(ctx context.Context, params GetScriptPolicyFromHashParams) (r *ScriptPolicy, _ error) { +// GET /script-policy +func (UnimplementedHandler) ListScriptPolicy(ctx context.Context, params ListScriptPolicyParams) (r []ScriptPolicy, _ error) { + return r, ht.ErrNotImplemented +} + +// ListScripts implements listScripts operation. +// +// Get list of scripts. +// +// GET /scripts +func (UnimplementedHandler) ListScripts(ctx context.Context, params ListScriptsParams) (r []Script, _ error) { return r, ht.ErrNotImplemented }