snapshot of https://github.com/ory/keto.git (master, 2026-09-16; blobs > 131072B omitted)
Some checks failed
CI / Run lints and checks (push) Failing after 47s
CI / Run tests (push) Failing after 1s
CI / Run race tests (push) Failing after 5s
CI / Build CLI docs (push) Has been skipped
CI / Run buf actions (push) Failing after 5s
CodeQL / Analyze (go) (push) Failing after 3s
CodeQL / Analyze (javascript) (push) Failing after 2s
Docker Image Scanners / scanners (push) Failing after 3s
Format / format (push) Failing after 3s
Synchronize Issue Labels / Synchronize Issue Labels (push) Has been skipped
CI / Generate release (push) Has been skipped
CI / Draft newsletter (push) Has been skipped
CI / Pending approval Slack notification (push) Has been skipped
CI / Send newsletter (push) Has been skipped
Some checks failed
CI / Run lints and checks (push) Failing after 47s
CI / Run tests (push) Failing after 1s
CI / Run race tests (push) Failing after 5s
CI / Build CLI docs (push) Has been skipped
CI / Run buf actions (push) Failing after 5s
CodeQL / Analyze (go) (push) Failing after 3s
CodeQL / Analyze (javascript) (push) Failing after 2s
Docker Image Scanners / scanners (push) Failing after 3s
Format / format (push) Failing after 3s
Synchronize Issue Labels / Synchronize Issue Labels (push) Has been skipped
CI / Generate release (push) Has been skipped
CI / Draft newsletter (push) Has been skipped
CI / Pending approval Slack notification (push) Has been skipped
CI / Send newsletter (push) Has been skipped
This commit is contained in:
5
.schema/README.md
Normal file
5
.schema/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
The schemas in this directory are meant for external and public use.
|
||||
|
||||
The config schema is generated from the internal one at
|
||||
`embedx/config.schema.json`, so in case of changes to the config schema, please
|
||||
edit that internal schema instead.
|
||||
508
.schema/config.schema.json
Normal file
508
.schema/config.schema.json
Normal file
@@ -0,0 +1,508 @@
|
||||
{
|
||||
"$id": "https://raw.githubusercontent.com/ory/keto/master/.schema/config.schema.json",
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "ORY Keto Configuration",
|
||||
"type": "object",
|
||||
"definitions": {
|
||||
"$schema": {
|
||||
"type": "string",
|
||||
"format": "uri-reference",
|
||||
"description": "Add this to allow defining the schema, useful for IDE integration"
|
||||
},
|
||||
"namespace": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"$schema": {
|
||||
"$ref": "#/definitions/$schema"
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"title": "The name of the namespace.",
|
||||
"examples": ["videos", "groups", "files"]
|
||||
},
|
||||
"id": {
|
||||
"type": "integer",
|
||||
"title": "The unique ID of the namespace. Can not be changed once set.",
|
||||
"minimum": 0,
|
||||
"maximum": 2147483647
|
||||
},
|
||||
"config": {
|
||||
"type": "object",
|
||||
"title": "The configuration of the namespace.",
|
||||
"description": "To be defined."
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": ["name"]
|
||||
},
|
||||
"tlsxSource": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"path": {
|
||||
"title": "Path to PEM-encoded Fle",
|
||||
"type": "string",
|
||||
"examples": ["path/to/file.pem"]
|
||||
},
|
||||
"base64": {
|
||||
"title": "Base64 Encoded Inline",
|
||||
"description": "The base64 string of the PEM-encoded file content. Can be generated using for example `base64 -i path/to/file.pem`.",
|
||||
"type": "string",
|
||||
"examples": [
|
||||
"LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tXG5NSUlEWlRDQ0FrMmdBd0lCQWdJRVY1eE90REFOQmdr..."
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"tlsx": {
|
||||
"title": "HTTPS",
|
||||
"description": "Configure HTTP over TLS (HTTPS). All options can also be set using environment variables by replacing dots (`.`) with underscores (`_`) and uppercasing the key. For example, `some.prefix.tls.key.path` becomes `export SOME_PREFIX_TLS_KEY_PATH`. If all keys are left undefined, TLS will be disabled.",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"key": {
|
||||
"title": "Private Key (PEM)",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/tlsxSource"
|
||||
}
|
||||
]
|
||||
},
|
||||
"cert": {
|
||||
"title": "TLS Certificate (PEM)",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/tlsxSource"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"cors": {
|
||||
"title": "Cross Origin Resource Sharing (CORS)",
|
||||
"description": "Configure [Cross Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/) using the following options.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"title": "Enable CORS",
|
||||
"description": "If set to true, CORS will be enabled and preflight-requests (OPTION) will be answered."
|
||||
},
|
||||
"allowed_origins": {
|
||||
"title": "Allowed Origins",
|
||||
"description": "A list of origins a cross-domain request can be executed from. If the special * value is present in the list, all origins will be allowed. An origin may contain a wildcard (*) to replace 0 or more characters (i.e.: http://*.domain.com). Usage of wildcards implies a small performance penality. Only one wildcard can be used per origin.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"default": ["*"],
|
||||
"uniqueItems": true,
|
||||
"examples": [
|
||||
[
|
||||
"https://example.com",
|
||||
"https://*.example.com",
|
||||
"https://*.foo.example.com"
|
||||
]
|
||||
]
|
||||
},
|
||||
"allowed_methods": {
|
||||
"type": "array",
|
||||
"title": "Allowed HTTP Methods",
|
||||
"description": "A list of methods the client is allowed to use with cross-domain requests.",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"GET",
|
||||
"HEAD",
|
||||
"POST",
|
||||
"PUT",
|
||||
"DELETE",
|
||||
"CONNECT",
|
||||
"TRACE",
|
||||
"PATCH"
|
||||
]
|
||||
},
|
||||
"uniqueItems": true,
|
||||
"default": ["GET", "POST", "PUT", "PATCH", "DELETE"]
|
||||
},
|
||||
"allowed_headers": {
|
||||
"description": "A list of non simple headers the client is allowed to use with cross-domain requests.",
|
||||
"title": "Allowed Request HTTP Headers",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"minLength": 1,
|
||||
"uniqueItems": true,
|
||||
"default": ["Authorization", "Content-Type"]
|
||||
},
|
||||
"exposed_headers": {
|
||||
"description": "Indicates which headers are safe to expose to the API of a CORS API specification",
|
||||
"title": "Allowed Response HTTP Headers",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"minLength": 1,
|
||||
"uniqueItems": true,
|
||||
"default": ["Content-Type"]
|
||||
},
|
||||
"allow_credentials": {
|
||||
"type": "boolean",
|
||||
"title": "Allow HTTP Credentials",
|
||||
"default": false,
|
||||
"description": "Indicates whether the request can include user credentials like cookies, HTTP authentication or client side SSL certificates."
|
||||
},
|
||||
"max_age": {
|
||||
"type": "integer",
|
||||
"default": 0,
|
||||
"title": "Maximum Age",
|
||||
"description": "Indicates how long (in seconds) the results of a preflight request can be cached. The default is 0 which stands for no max age."
|
||||
},
|
||||
"debug": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"title": "Enable Debugging",
|
||||
"description": "Set to true to debug server side CORS issues."
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"required": ["dsn"],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"$schema": {
|
||||
"$ref": "#/definitions/$schema"
|
||||
},
|
||||
"dsn": {
|
||||
"title": "Data Source Name",
|
||||
"type": "string",
|
||||
"description": "Sets the data source name. This configures the backend where ORY Keto persists data. If dsn is \"memory\", data will be written to memory and is lost when you restart this instance. ORY Hydra supports popular SQL databases. For more detailed configuration information go to: https://www.ory.com/docs/hydra/dependencies-environment#sql",
|
||||
"examples": [
|
||||
"postgres://user:password@host:123/database",
|
||||
"mysql://user:password@tcp(host:123)/database",
|
||||
"memory"
|
||||
]
|
||||
},
|
||||
"serve": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"read": {
|
||||
"type": "object",
|
||||
"title": "Read API (http and gRPC)",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"port": {
|
||||
"type": "integer",
|
||||
"default": 4466,
|
||||
"title": "Port",
|
||||
"description": "The port to listen on.",
|
||||
"minimum": 0,
|
||||
"maximum": 65535
|
||||
},
|
||||
"host": {
|
||||
"type": "string",
|
||||
"default": "",
|
||||
"examples": ["localhost", "127.0.0.1"],
|
||||
"title": "Host",
|
||||
"description": "The network interface to listen on."
|
||||
},
|
||||
"write_listen_file": {
|
||||
"type": "string",
|
||||
"title": "Read Listen File",
|
||||
"description": "The path to a file that will be created when the read API is ready to accept connections. The content of the file is the host:port of the read API. Use this to get the actual port when using port 0. The service might not yet be ready to accept connections when the file is created.",
|
||||
"format": "uri",
|
||||
"examples": ["file:///tmp/keto-read-api"]
|
||||
},
|
||||
"cors": {
|
||||
"$ref": "#/definitions/cors"
|
||||
},
|
||||
"tls": {
|
||||
"$ref": "#/definitions/tlsx"
|
||||
}
|
||||
}
|
||||
},
|
||||
"write": {
|
||||
"type": "object",
|
||||
"title": "Write API (http and gRPC)",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"port": {
|
||||
"type": "integer",
|
||||
"default": 4467,
|
||||
"title": "Port",
|
||||
"description": "The port to listen on.",
|
||||
"minimum": 0,
|
||||
"maximum": 65535
|
||||
},
|
||||
"host": {
|
||||
"type": "string",
|
||||
"default": "",
|
||||
"examples": ["localhost", "127.0.0.1"],
|
||||
"title": "Host",
|
||||
"description": "The network interface to listen on."
|
||||
},
|
||||
"write_listen_file": {
|
||||
"type": "string",
|
||||
"title": "Write Listen File",
|
||||
"description": "The path to a file that will be created when the write API is ready to accept connections. The content of the file is the host:port of the write API. Use this to get the actual port when using port 0. The service might not yet be ready to accept connections when the file is created.",
|
||||
"format": "uri",
|
||||
"examples": ["file:///tmp/keto-write-api"]
|
||||
},
|
||||
"cors": {
|
||||
"$ref": "#/definitions/cors"
|
||||
},
|
||||
"tls": {
|
||||
"$ref": "#/definitions/tlsx"
|
||||
}
|
||||
}
|
||||
},
|
||||
"metrics": {
|
||||
"type": "object",
|
||||
"title": "Metrics API (http only)",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"port": {
|
||||
"type": "integer",
|
||||
"default": 4468,
|
||||
"title": "Port",
|
||||
"description": "The port to listen on.",
|
||||
"minimum": 0,
|
||||
"maximum": 65535
|
||||
},
|
||||
"host": {
|
||||
"type": "string",
|
||||
"default": "",
|
||||
"examples": ["localhost", "127.0.0.1"],
|
||||
"title": "Host",
|
||||
"description": "The network interface to listen on."
|
||||
},
|
||||
"write_listen_file": {
|
||||
"type": "string",
|
||||
"title": "Metrics Listen File",
|
||||
"description": "The path to a file that will be created when the metrics API is ready to accept connections. The content of the file is the host:port of the metrics API. Use this to get the actual port when using port 0. The service might not yet be ready to accept connections when the file is created.",
|
||||
"format": "uri",
|
||||
"examples": ["file:///tmp/keto-metrics-api"]
|
||||
},
|
||||
"cors": {
|
||||
"$ref": "#/definitions/cors"
|
||||
},
|
||||
"tls": {
|
||||
"$ref": "#/definitions/tlsx"
|
||||
}
|
||||
}
|
||||
},
|
||||
"opl": {
|
||||
"type": "object",
|
||||
"title": "Ory Permission Language Syntax API (http and gRPC)",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"port": {
|
||||
"type": "integer",
|
||||
"default": 4469,
|
||||
"title": "Port",
|
||||
"description": "The port to listen on.",
|
||||
"minimum": 0,
|
||||
"maximum": 65535
|
||||
},
|
||||
"host": {
|
||||
"type": "string",
|
||||
"default": "",
|
||||
"examples": ["localhost", "127.0.0.1"],
|
||||
"title": "Host",
|
||||
"description": "The network interface to listen on."
|
||||
},
|
||||
"write_listen_file": {
|
||||
"type": "string",
|
||||
"title": "OPL Listen File",
|
||||
"description": "The path to a file that will be created when the OPL API is ready to accept connections. The content of the file is the host:port of the OPL API. Use this to get the actual port when using port 0. The service might not yet be ready to accept connections when the file is created.",
|
||||
"format": "uri",
|
||||
"examples": ["file:///tmp/keto-opl-api"]
|
||||
},
|
||||
"cors": {
|
||||
"$ref": "#/definitions/cors"
|
||||
},
|
||||
"tls": {
|
||||
"$ref": "#/definitions/tlsx"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"profiling": {
|
||||
"title": "Profiling",
|
||||
"description": "Enables CPU or memory profiling if set. For more details on profiling Go programs read [Profiling Go Programs](https://blog.golang.org/profiling-go-programs).",
|
||||
"type": "string",
|
||||
"enum": ["cpu", "mem", ""]
|
||||
},
|
||||
"log": {
|
||||
"$ref": "https://raw.githubusercontent.com/ory/keto/6e32173d/oryx/logrusx/config.schema.json"
|
||||
},
|
||||
"tracing": {
|
||||
"$ref": "https://raw.githubusercontent.com/ory/keto/6e32173d/oryx/otelx/config.schema.json"
|
||||
},
|
||||
"namespaces": {
|
||||
"description": "Namespace configuration or it's location.",
|
||||
"default": "file://./keto_namespaces",
|
||||
"oneOf": [
|
||||
{
|
||||
"title": "Legacy namespace Repo URI",
|
||||
"description": "A URI that points to a directory of namespace files, or a single file with all namespaces",
|
||||
"type": "string",
|
||||
"format": "uri"
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"title": "Legacy namespace configuration",
|
||||
"items": {
|
||||
"$ref": "#/definitions/namespace"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"title": "Namespace configuration",
|
||||
"properties": {
|
||||
"location": {
|
||||
"type": "string",
|
||||
"title": "Ory Permission Language config file URI",
|
||||
"description": "A URI that points to a directory of namespace files, or a single file with all namespaces",
|
||||
"format": "uri",
|
||||
"examples": [
|
||||
"file://./keto_namespaces.ts",
|
||||
"file:///etc/configs/keto_namespaces.ts"
|
||||
]
|
||||
},
|
||||
"experimental_strict_mode": {
|
||||
"type": "boolean",
|
||||
"title": "Strict permission checking mode (deprecated)",
|
||||
"description": "Deprecated: use feature_flags.strict_mode instead. If strict mode is enabled, then relation tuples for permits are not checked directly (but the rewrites are applied). Similarly, subject sets are only expanded if they were declared with SubjectSet<...>. These stricter rules result in much faster checks with fewer queries to the underlying database."
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": ["location"]
|
||||
}
|
||||
]
|
||||
},
|
||||
"limit": {
|
||||
"type": "object",
|
||||
"title": "Limits",
|
||||
"description": "Limits aiming to control the resource consumption. These limits are not a sufficient replacement for rate-limiting.",
|
||||
"properties": {
|
||||
"max_read_depth": {
|
||||
"type": "integer",
|
||||
"default": 5,
|
||||
"title": "Global maximum read depth",
|
||||
"description": "The global maximum depth on all read operations. Note that this does not affect how deeply nested the tuples can be. This value can be decreased for a request by a value specified on the request, only if the request-specific value is greater than 1 and less than the global maximum depth.",
|
||||
"minimum": 1,
|
||||
"maximum": 65535
|
||||
},
|
||||
"max_read_width": {
|
||||
"type": "integer",
|
||||
"default": 100,
|
||||
"title": "Global maximum read width",
|
||||
"description": "The global maximum width on all read operations. Note that this does not affect how deeply nested the tuples can be. This value can be decreased for a request by a value specified on the request, only if the request-specific value is greater than 1 and less than the global maximum width.",
|
||||
"minimum": 1,
|
||||
"maximum": 65535
|
||||
},
|
||||
"max_batch_check_size": {
|
||||
"type": "integer",
|
||||
"default": 10,
|
||||
"title": "Maximum batch check size",
|
||||
"description": "The maximum number of tuples that will be accepted by the batch check endpoint.",
|
||||
"minimum": 1,
|
||||
"maximum": 65535
|
||||
},
|
||||
"batch_check_max_parallelization": {
|
||||
"type": "integer",
|
||||
"default": 5,
|
||||
"title": "Max concurrent checks during batch check",
|
||||
"description": "The limit for the number of tuples that will be checked concurrently during a batch check.",
|
||||
"minimum": 1,
|
||||
"maximum": 65535
|
||||
},
|
||||
"max_expand_size": {
|
||||
"type": "integer",
|
||||
"default": 4000,
|
||||
"title": "Maximum tuples during expand",
|
||||
"description": "The maximum total number of relation tuples the expand engine will return in a single BuildTree call. Once the limit is reached, further nodes are returned as truncated.",
|
||||
"minimum": 0,
|
||||
"maximum": 65535
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"clients": {
|
||||
"title": "Global outgoing network settings",
|
||||
"description": "Configure how outgoing network calls behave.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"http": {
|
||||
"title": "Global HTTP client configuration",
|
||||
"description": "Configure how outgoing HTTP calls behave.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"disallow_private_ip_ranges": {
|
||||
"title": "Disallow private IP ranges",
|
||||
"description": "Disallow all outgoing HTTP calls to private IP ranges. This feature can help protect against SSRF attacks.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"secrets": {
|
||||
"title": "Secrets for signing and encryption",
|
||||
"description": "Make sure to use unique and random secrets for production deployments. Horizontally scaled deployments have to use the same secrets across all instances.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pagination": {
|
||||
"description": "Pagination secrets are used to encrypt pagination tokens. The first secret is used for encryption, while all others are used for decryption. This allows you to rotate the encryption key without invalidating all existing pagination tokens.",
|
||||
"type": "array",
|
||||
"minLength": 1,
|
||||
"items": {
|
||||
"type": "string",
|
||||
"minLength": 16
|
||||
},
|
||||
"examples": [
|
||||
[
|
||||
"secret used for encryption",
|
||||
"old secret kept for decryption",
|
||||
"another old secret kept for decryption"
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"feature_flags": {
|
||||
"title": "Feature flags",
|
||||
"description": "Opt in to features that are still being refined. Behavior may change in future releases.",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"expand_rewrites": {
|
||||
"type": "boolean",
|
||||
"title": "Expand OPL rewrite rules",
|
||||
"description": "If enabled, the expand API follows OPL rewrite rules when building permission trees.",
|
||||
"default": false
|
||||
},
|
||||
"strict_mode": {
|
||||
"type": "boolean",
|
||||
"title": "Strict permission checking mode",
|
||||
"description": "If strict mode is enabled, then relation tuples for permits are not checked directly (but the rewrites are applied). Similarly, subject sets are only expanded if they were declared with SubjectSet<...>. These stricter rules result in much faster checks with fewer queries to the underlying database.",
|
||||
"default": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"title": "The Keto version this config is written for.",
|
||||
"description": "SemVer according to https://semver.org/ prefixed with `v` as in our releases.",
|
||||
"pattern": "^v(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$"
|
||||
}
|
||||
}
|
||||
}
|
||||
5
.schema/namespace.schema.json
Normal file
5
.schema/namespace.schema.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"$ref": "./config.schema.json#/definitions/namespace",
|
||||
"description": "This schema is just to work around the limitation of some IDEs to support json schema paths."
|
||||
}
|
||||
6
.schema/openapi/gen.go.yml
Normal file
6
.schema/openapi/gen.go.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
disallowAdditionalPropertiesIfNotPresent: true
|
||||
packageName: client
|
||||
generateInterfaces: true
|
||||
isGoSubmodule: false
|
||||
structPrefix: true
|
||||
enumClassPrefix: true
|
||||
7
.schema/openapi/gen.typescript.yml
Normal file
7
.schema/openapi/gen.typescript.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
npmName: "@ory/kratos-client"
|
||||
npmVersion: 0.0.0
|
||||
# typescriptThreePlus: true
|
||||
#npmRepository: https://github.com/ory/sdk.git
|
||||
supportsES6: true
|
||||
ensureUniqueParams: true
|
||||
modelPropertyNaming: original
|
||||
94
.schema/openapi/patches/health.yaml
Normal file
94
.schema/openapi/patches/health.yaml
Normal file
@@ -0,0 +1,94 @@
|
||||
- op: replace
|
||||
path: /paths/~1health~1alive
|
||||
value:
|
||||
get:
|
||||
description: |-
|
||||
This endpoint returns a HTTP 200 status code when {{.ProjectHumanName}} is accepting incoming
|
||||
HTTP requests. This status does currently not include checks whether the database connection is working.
|
||||
|
||||
If the service supports TLS Edge Termination, this endpoint does not require the
|
||||
`X-Forwarded-Proto` header to be set.
|
||||
|
||||
Be aware that if you are running multiple nodes of this service, the health status will never
|
||||
refer to the cluster state, only to a single instance.
|
||||
operationId: isAlive
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/healthStatus"
|
||||
description: {{.ProjectHumanName}} is ready to accept connections.
|
||||
'500':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/genericError"
|
||||
description: genericError
|
||||
summary: Check HTTP Server Status
|
||||
tags: {{ .HealthPathTags | toJson }}
|
||||
- op: replace
|
||||
path: /paths/~1health~1ready
|
||||
value:
|
||||
get:
|
||||
operationId: isReady
|
||||
description: |-
|
||||
This endpoint returns a HTTP 200 status code when {{.ProjectHumanName}} is up running and the environment dependencies (e.g.
|
||||
the database) are responsive as well.
|
||||
|
||||
If the service supports TLS Edge Termination, this endpoint does not require the
|
||||
`X-Forwarded-Proto` header to be set.
|
||||
|
||||
Be aware that if you are running multiple nodes of {{.ProjectHumanName}}, the health status will never
|
||||
refer to the cluster state, only to a single instance.
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
description: Always "ok".
|
||||
type: string
|
||||
description: {{.ProjectHumanName}} is ready to accept requests.
|
||||
'503':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
properties:
|
||||
errors:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: Errors contains a list of errors that caused the not ready status.
|
||||
type: object
|
||||
type: object
|
||||
description: Ory Kratos is not yet ready to accept requests.
|
||||
summary: Check HTTP Server and Database Status
|
||||
tags: {{ .HealthPathTags | toJson }}
|
||||
- op: replace
|
||||
path: /paths/~1version
|
||||
value:
|
||||
get:
|
||||
description: |-
|
||||
This endpoint returns the version of {{.ProjectHumanName}}.
|
||||
|
||||
If the service supports TLS Edge Termination, this endpoint does not require the
|
||||
`X-Forwarded-Proto` header to be set.
|
||||
|
||||
Be aware that if you are running multiple nodes of this service, the version will never
|
||||
refer to the cluster state, only to a single instance.
|
||||
operationId: getVersion
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
version:
|
||||
description: The version of {{.ProjectHumanName}}.
|
||||
type: string
|
||||
description: Returns the {{.ProjectHumanName}} version.
|
||||
summary: Return Running Software Version.
|
||||
tags: {{ .HealthPathTags | toJson }}
|
||||
12
.schema/openapi/patches/meta.yaml
Normal file
12
.schema/openapi/patches/meta.yaml
Normal file
@@ -0,0 +1,12 @@
|
||||
- op: replace
|
||||
path: /info
|
||||
value:
|
||||
title: Ory Keto API
|
||||
description: |
|
||||
Documentation for all of Ory Keto's REST APIs. gRPC is documented separately.
|
||||
version: >-
|
||||
{{ getenv "CIRCLE_TAG" }}
|
||||
license:
|
||||
name: Apache 2.0
|
||||
contact:
|
||||
email: "hi@ory.sh"
|
||||
7
.schema/openapi/templates/go/.travis.yml
Normal file
7
.schema/openapi/templates/go/.travis.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
language: go
|
||||
|
||||
install:
|
||||
- go get -d -v .
|
||||
|
||||
script:
|
||||
- go build -v ./
|
||||
221
.schema/openapi/templates/go/README.mustache
Normal file
221
.schema/openapi/templates/go/README.mustache
Normal file
@@ -0,0 +1,221 @@
|
||||
# Go API client for {{packageName}}
|
||||
|
||||
{{#appDescriptionWithNewLines}}
|
||||
{{{appDescriptionWithNewLines}}}
|
||||
{{/appDescriptionWithNewLines}}
|
||||
|
||||
## Overview
|
||||
This API client was generated by the [OpenAPI Generator](https://openapi-generator.tech) project. By using the [OpenAPI-spec](https://www.openapis.org/) from a remote server, you can easily generate an API client.
|
||||
|
||||
- API version: {{appVersion}}
|
||||
- Package version: {{packageVersion}}
|
||||
{{^hideGenerationTimestamp}}
|
||||
- Build date: {{generatedDate}}
|
||||
{{/hideGenerationTimestamp}}
|
||||
- Build package: {{generatorClass}}
|
||||
{{#infoUrl}}
|
||||
For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}})
|
||||
{{/infoUrl}}
|
||||
|
||||
## Installation
|
||||
|
||||
Install the following dependencies:
|
||||
|
||||
```shell
|
||||
go get github.com/stretchr/testify/assert
|
||||
go get golang.org/x/oauth2
|
||||
go get golang.org/x/net/context
|
||||
```
|
||||
|
||||
Put the package under your project folder and add the following in import:
|
||||
|
||||
```golang
|
||||
import {{packageName}} "{{gitHost}}/{{gitUserId}}/{{gitRepoId}}{{#isGoSubmodule}}/{{packageName}}{{/isGoSubmodule}}"
|
||||
```
|
||||
|
||||
To use a proxy, set the environment variable `HTTP_PROXY`:
|
||||
|
||||
```golang
|
||||
os.Setenv("HTTP_PROXY", "http://proxy_name:proxy_port")
|
||||
```
|
||||
|
||||
## Configuration of Server URL
|
||||
|
||||
Default configuration comes with `Servers` field that contains server objects as defined in the OpenAPI specification.
|
||||
|
||||
### Select Server Configuration
|
||||
|
||||
For using other server than the one defined on index 0 set context value `sw.ContextServerIndex` of type `int`.
|
||||
|
||||
```golang
|
||||
ctx := context.WithValue(context.Background(), {{packageName}}.ContextServerIndex, 1)
|
||||
```
|
||||
|
||||
### Templated Server URL
|
||||
|
||||
Templated server URL is formatted using default variables from configuration or from context value `sw.ContextServerVariables` of type `map[string]string`.
|
||||
|
||||
```golang
|
||||
ctx := context.WithValue(context.Background(), {{packageName}}.ContextServerVariables, map[string]string{
|
||||
"basePath": "v2",
|
||||
})
|
||||
```
|
||||
|
||||
Note, enum values are always validated and all unused variables are silently ignored.
|
||||
|
||||
### URLs Configuration per Operation
|
||||
|
||||
Each operation can use different server URL defined using `OperationServers` map in the `Configuration`.
|
||||
An operation is uniquely identifield by `"{classname}Service.{nickname}"` string.
|
||||
Similar rules for overriding default operation server index and variables applies by using `sw.ContextOperationServerIndices` and `sw.ContextOperationServerVariables` context maps.
|
||||
|
||||
```
|
||||
ctx := context.WithValue(context.Background(), {{packageName}}.ContextOperationServerIndices, map[string]int{
|
||||
"{classname}Service.{nickname}": 2,
|
||||
})
|
||||
ctx = context.WithValue(context.Background(), {{packageName}}.ContextOperationServerVariables, map[string]map[string]string{
|
||||
"{classname}Service.{nickname}": {
|
||||
"port": "8443",
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
## Documentation for API Endpoints
|
||||
|
||||
All URIs are relative to *{{basePath}}*
|
||||
|
||||
Class | Method | HTTP request | Description
|
||||
------------ | ------------- | ------------- | -------------
|
||||
{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationIdLowerCase}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}}
|
||||
{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
|
||||
|
||||
## Documentation For Models
|
||||
|
||||
{{#models}}{{#model}} - [{{{classname}}}]({{modelDocPath}}{{{classname}}}.md)
|
||||
{{/model}}{{/models}}
|
||||
|
||||
## Documentation For Authorization
|
||||
|
||||
{{^authMethods}} Endpoints do not require authorization.
|
||||
{{/authMethods}}{{#authMethods}}{{#last}} Authentication schemes defined for the API:{{/last}}{{/authMethods}}
|
||||
{{#authMethods}}
|
||||
|
||||
### {{{name}}}
|
||||
|
||||
{{#isApiKey}}
|
||||
- **Type**: API key
|
||||
- **API key parameter name**: {{{keyParamName}}}
|
||||
- **Location**: {{#isKeyInQuery}}URL query string{{/isKeyInQuery}}{{#isKeyInHeader}}HTTP header{{/isKeyInHeader}}
|
||||
|
||||
Note, each API key must be added to a map of `map[string]APIKey` where the key is: {{keyParamName}} and passed in as the auth context for each request.
|
||||
|
||||
{{/isApiKey}}
|
||||
{{#isBasic}}
|
||||
{{#isBasicBearer}}
|
||||
- **Type**: HTTP Bearer token authentication
|
||||
|
||||
Example
|
||||
|
||||
```golang
|
||||
auth := context.WithValue(context.Background(), sw.ContextAccessToken, "BEARER_TOKEN_STRING")
|
||||
r, err := client.Service.Operation(auth, args)
|
||||
```
|
||||
|
||||
{{/isBasicBearer}}
|
||||
{{#isBasicBasic}}
|
||||
- **Type**: HTTP basic authentication
|
||||
|
||||
Example
|
||||
|
||||
```golang
|
||||
auth := context.WithValue(context.Background(), sw.ContextBasicAuth, sw.BasicAuth{
|
||||
UserName: "username",
|
||||
Password: "password",
|
||||
})
|
||||
r, err := client.Service.Operation(auth, args)
|
||||
```
|
||||
|
||||
{{/isBasicBasic}}
|
||||
{{#isHttpSignature}}
|
||||
- **Type**: HTTP signature authentication
|
||||
|
||||
Example
|
||||
|
||||
```golang
|
||||
authConfig := client.HttpSignatureAuth{
|
||||
KeyId: "my-key-id",
|
||||
PrivateKeyPath: "rsa.pem",
|
||||
Passphrase: "my-passphrase",
|
||||
SigningScheme: sw.HttpSigningSchemeHs2019,
|
||||
SignedHeaders: []string{
|
||||
sw.HttpSignatureParameterRequestTarget, // The special (request-target) parameter expresses the HTTP request target.
|
||||
sw.HttpSignatureParameterCreated, // Time when request was signed, formatted as a Unix timestamp integer value.
|
||||
"Host", // The Host request header specifies the domain name of the server, and optionally the TCP port number.
|
||||
"Date", // The date and time at which the message was originated.
|
||||
"Content-Type", // The Media type of the body of the request.
|
||||
"Digest", // A cryptographic digest of the request body.
|
||||
},
|
||||
SigningAlgorithm: sw.HttpSigningAlgorithmRsaPSS,
|
||||
SignatureMaxValidity: 5 * time.Minute,
|
||||
}
|
||||
var authCtx context.Context
|
||||
var err error
|
||||
if authCtx, err = authConfig.ContextWithValue(context.Background()); err != nil {
|
||||
// Process error
|
||||
}
|
||||
r, err = client.Service.Operation(auth, args)
|
||||
|
||||
```
|
||||
{{/isHttpSignature}}
|
||||
{{/isBasic}}
|
||||
{{#isOAuth}}
|
||||
|
||||
- **Type**: OAuth
|
||||
- **Flow**: {{{flow}}}
|
||||
- **Authorization URL**: {{{authorizationUrl}}}
|
||||
- **Scopes**: {{^scopes}}N/A{{/scopes}}
|
||||
{{#scopes}} - **{{{scope}}}**: {{{description}}}
|
||||
{{/scopes}}
|
||||
|
||||
Example
|
||||
|
||||
```golang
|
||||
auth := context.WithValue(context.Background(), sw.ContextAccessToken, "ACCESSTOKENSTRING")
|
||||
r, err := client.Service.Operation(auth, args)
|
||||
```
|
||||
|
||||
Or via OAuth2 module to automatically refresh tokens and perform user authentication.
|
||||
|
||||
```golang
|
||||
import "golang.org/x/oauth2"
|
||||
|
||||
/* Perform OAuth2 round trip request and obtain a token */
|
||||
|
||||
tokenSource := oauth2cfg.TokenSource(createContext(httpClient), &token)
|
||||
auth := context.WithValue(oauth2.NoContext, sw.ContextOAuth2, tokenSource)
|
||||
r, err := client.Service.Operation(auth, args)
|
||||
```
|
||||
|
||||
{{/isOAuth}}
|
||||
{{/authMethods}}
|
||||
|
||||
## Documentation for Utility Methods
|
||||
|
||||
Due to the fact that model structure members are all pointers, this package contains
|
||||
a number of utility functions to easily obtain pointers to values of basic types.
|
||||
Each of these functions takes a value of the given basic type and returns a pointer to it:
|
||||
|
||||
* `PtrBool`
|
||||
* `PtrInt`
|
||||
* `PtrInt32`
|
||||
* `PtrInt64`
|
||||
* `PtrFloat`
|
||||
* `PtrFloat32`
|
||||
* `PtrFloat64`
|
||||
* `PtrString`
|
||||
* `PtrTime`
|
||||
|
||||
## Author
|
||||
|
||||
{{#apiInfo}}{{#apis}}{{#-last}}{{infoEmail}}
|
||||
{{/-last}}{{/apis}}{{/apiInfo}}
|
||||
377
.schema/openapi/templates/go/api.mustache
Normal file
377
.schema/openapi/templates/go/api.mustache
Normal file
@@ -0,0 +1,377 @@
|
||||
{{>partial_header}}
|
||||
package {{packageName}}
|
||||
|
||||
{{#operations}}
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
{{#imports}} "{{import}}"
|
||||
{{/imports}}
|
||||
)
|
||||
|
||||
// Linger please
|
||||
var (
|
||||
_ context.Context
|
||||
)
|
||||
{{#generateInterfaces}}
|
||||
|
||||
type {{classname}} interface {
|
||||
{{#operation}}
|
||||
|
||||
/*
|
||||
* {{operationId}}{{#summary}} {{{.}}}{{/summary}}{{^summary}} Method for {{operationId}}{{/summary}}
|
||||
{{#notes}}
|
||||
* {{{unescapedNotes}}}
|
||||
{{/notes}}
|
||||
* @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background().{{#pathParams}}
|
||||
* @param {{paramName}}{{#description}} {{{.}}}{{/description}}{{/pathParams}}
|
||||
* @return {{#structPrefix}}{{&classname}}{{/structPrefix}}Api{{operationId}}Request
|
||||
*/
|
||||
{{{nickname}}}(ctx context.Context{{#pathParams}}, {{paramName}} {{{dataType}}}{{/pathParams}}) {{#structPrefix}}{{&classname}}{{/structPrefix}}Api{{operationId}}Request
|
||||
|
||||
/*
|
||||
* {{nickname}}Execute executes the request{{#returnType}}
|
||||
* @return {{{.}}}{{/returnType}}
|
||||
*/
|
||||
{{nickname}}Execute(r {{#structPrefix}}{{&classname}}{{/structPrefix}}Api{{operationId}}Request) ({{#returnType}}{{^isArray}}{{^returnTypeIsPrimitive}}*{{/returnTypeIsPrimitive}}{{/isArray}}{{{.}}}, {{/returnType}}*http.Response, error)
|
||||
{{/operation}}
|
||||
}
|
||||
{{/generateInterfaces}}
|
||||
|
||||
// {{classname}}Service {{classname}} service
|
||||
type {{classname}}Service service
|
||||
{{#operation}}
|
||||
|
||||
type {{#structPrefix}}{{&classname}}{{/structPrefix}}Api{{operationId}}Request struct {
|
||||
ctx context.Context{{#generateInterfaces}}
|
||||
ApiService {{classname}}
|
||||
{{/generateInterfaces}}{{^generateInterfaces}}
|
||||
ApiService *{{classname}}Service
|
||||
{{/generateInterfaces}}
|
||||
{{#allParams}}
|
||||
{{paramName}} {{^isPathParam}}*{{/isPathParam}}{{{dataType}}}
|
||||
{{/allParams}}
|
||||
}
|
||||
{{#allParams}}{{^isPathParam}}
|
||||
func (r {{#structPrefix}}{{&classname}}{{/structPrefix}}Api{{operationId}}Request) {{vendorExtensions.x-export-param-name}}({{paramName}} {{{dataType}}}) {{#structPrefix}}{{&classname}}{{/structPrefix}}Api{{operationId}}Request {
|
||||
r.{{paramName}} = &{{paramName}}
|
||||
return r
|
||||
}{{/isPathParam}}{{/allParams}}
|
||||
|
||||
func (r {{#structPrefix}}{{&classname}}{{/structPrefix}}Api{{operationId}}Request) Execute() ({{#returnType}}{{^isArray}}{{^returnTypeIsPrimitive}}*{{/returnTypeIsPrimitive}}{{/isArray}}{{{.}}}, {{/returnType}}*http.Response, error) {
|
||||
return r.ApiService.{{nickname}}Execute(r)
|
||||
}
|
||||
|
||||
/*
|
||||
* {{operationId}}{{#summary}} {{{.}}}{{/summary}}{{^summary}} Method for {{operationId}}{{/summary}}
|
||||
{{#notes}}
|
||||
* {{{unescapedNotes}}}
|
||||
{{/notes}}
|
||||
* @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background().{{#pathParams}}
|
||||
* @param {{paramName}}{{#description}} {{{.}}}{{/description}}{{/pathParams}}
|
||||
* @return {{#structPrefix}}{{&classname}}{{/structPrefix}}Api{{operationId}}Request
|
||||
*/
|
||||
func (a *{{{classname}}}Service) {{{nickname}}}(ctx context.Context{{#pathParams}}, {{paramName}} {{{dataType}}}{{/pathParams}}) {{#structPrefix}}{{&classname}}{{/structPrefix}}Api{{operationId}}Request {
|
||||
return {{#structPrefix}}{{&classname}}{{/structPrefix}}Api{{operationId}}Request{
|
||||
ApiService: a,
|
||||
ctx: ctx,{{#pathParams}}
|
||||
{{paramName}}: {{paramName}},{{/pathParams}}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute executes the request{{#returnType}}
|
||||
* @return {{{.}}}{{/returnType}}
|
||||
*/
|
||||
func (a *{{{classname}}}Service) {{nickname}}Execute(r {{#structPrefix}}{{&classname}}{{/structPrefix}}Api{{operationId}}Request) ({{#returnType}}{{^isArray}}{{^returnTypeIsPrimitive}}*{{/returnTypeIsPrimitive}}{{/isArray}}{{{.}}}, {{/returnType}}*http.Response, error) {
|
||||
var (
|
||||
localVarHTTPMethod = http.Method{{httpMethod}}
|
||||
localVarPostBody interface{}
|
||||
localVarFormFileName string
|
||||
localVarFileName string
|
||||
localVarFileBytes []byte
|
||||
{{#returnType}}
|
||||
localVarReturnValue {{^isArray}}{{^returnTypeIsPrimitive}}*{{/returnTypeIsPrimitive}}{{/isArray}}{{{.}}}
|
||||
{{/returnType}}
|
||||
)
|
||||
|
||||
localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "{{{classname}}}Service.{{{nickname}}}")
|
||||
if err != nil {
|
||||
return {{#returnType}}localVarReturnValue, {{/returnType}}nil, &GenericOpenAPIError{error: err.Error()}
|
||||
}
|
||||
|
||||
localVarPath := localBasePath + "{{{path}}}"{{#pathParams}}
|
||||
localVarPath = strings.Replace(localVarPath, "{"+"{{baseName}}"+"}", url.PathEscape(parameterToString(r.{{paramName}}, "{{#collectionFormat}}{{collectionFormat}}{{/collectionFormat}}")), -1){{/pathParams}}
|
||||
|
||||
localVarHeaderParams := make(map[string]string)
|
||||
localVarQueryParams := url.Values{}
|
||||
localVarFormParams := url.Values{}
|
||||
{{#allParams}}
|
||||
{{#required}}
|
||||
{{^isPathParam}}
|
||||
if r.{{paramName}} == nil {
|
||||
return {{#returnType}}localVarReturnValue, {{/returnType}}nil, reportError("{{paramName}} is required and must be specified")
|
||||
}
|
||||
{{/isPathParam}}
|
||||
{{#minItems}}
|
||||
if len({{^isPathParam}}*{{/isPathParam}}r.{{paramName}}) < {{minItems}} {
|
||||
return {{#returnType}}localVarReturnValue, {{/returnType}}nil, reportError("{{paramName}} must have at least {{minItems}} elements")
|
||||
}
|
||||
{{/minItems}}
|
||||
{{#maxItems}}
|
||||
if len({{^isPathParam}}*{{/isPathParam}}r.{{paramName}}) > {{maxItems}} {
|
||||
return {{#returnType}}localVarReturnValue, {{/returnType}}nil, reportError("{{paramName}} must have less than {{maxItems}} elements")
|
||||
}
|
||||
{{/maxItems}}
|
||||
{{#minLength}}
|
||||
if strlen({{^isPathParam}}*{{/isPathParam}}r.{{paramName}}) < {{minLength}} {
|
||||
return {{#returnType}}localVarReturnValue, {{/returnType}}nil, reportError("{{paramName}} must have at least {{minLength}} elements")
|
||||
}
|
||||
{{/minLength}}
|
||||
{{#maxLength}}
|
||||
if strlen({{^isPathParam}}*{{/isPathParam}}r.{{paramName}}) > {{maxLength}} {
|
||||
return {{#returnType}}localVarReturnValue, {{/returnType}}nil, reportError("{{paramName}} must have less than {{maxLength}} elements")
|
||||
}
|
||||
{{/maxLength}}
|
||||
{{#minimum}}
|
||||
{{#isString}}
|
||||
{{paramName}}Txt, err := atoi({{^isPathParam}}*{{/isPathParam}}r.{{paramName}})
|
||||
if {{paramName}}Txt < {{minimum}} {
|
||||
{{/isString}}
|
||||
{{^isString}}
|
||||
if {{^isPathParam}}*{{/isPathParam}}r.{{paramName}} < {{minimum}} {
|
||||
{{/isString}}
|
||||
return {{#returnType}}localVarReturnValue, {{/returnType}}nil, reportError("{{paramName}} must be greater than {{minimum}}")
|
||||
}
|
||||
{{/minimum}}
|
||||
{{#maximum}}
|
||||
{{#isString}}
|
||||
{{paramName}}Txt, err := atoi({{^isPathParam}}*{{/isPathParam}}r.{{paramName}})
|
||||
if {{paramName}}Txt > {{maximum}} {
|
||||
{{/isString}}
|
||||
{{^isString}}
|
||||
if {{^isPathParam}}*{{/isPathParam}}r.{{paramName}} > {{maximum}} {
|
||||
{{/isString}}
|
||||
return {{#returnType}}localVarReturnValue, {{/returnType}}nil, reportError("{{paramName}} must be less than {{maximum}}")
|
||||
}
|
||||
{{/maximum}}
|
||||
{{/required}}
|
||||
{{/allParams}}
|
||||
|
||||
{{#queryParams}}
|
||||
{{#required}}
|
||||
{{#isCollectionFormatMulti}}
|
||||
{
|
||||
t := *r.{{paramName}}
|
||||
if reflect.TypeOf(t).Kind() == reflect.Slice {
|
||||
s := reflect.ValueOf(t)
|
||||
for i := 0; i < s.Len(); i++ {
|
||||
localVarQueryParams.Add("{{baseName}}", parameterToString(s.Index(i), "{{#collectionFormat}}{{collectionFormat}}{{/collectionFormat}}"))
|
||||
}
|
||||
} else {
|
||||
localVarQueryParams.Add("{{baseName}}", parameterToString(t, "{{#collectionFormat}}{{collectionFormat}}{{/collectionFormat}}"))
|
||||
}
|
||||
}
|
||||
{{/isCollectionFormatMulti}}
|
||||
{{^isCollectionFormatMulti}}
|
||||
localVarQueryParams.Add("{{baseName}}", parameterToString(*r.{{paramName}}, "{{#collectionFormat}}{{collectionFormat}}{{/collectionFormat}}"))
|
||||
{{/isCollectionFormatMulti}}
|
||||
{{/required}}
|
||||
{{^required}}
|
||||
if r.{{paramName}} != nil {
|
||||
{{#isCollectionFormatMulti}}
|
||||
t := *r.{{paramName}}
|
||||
if reflect.TypeOf(t).Kind() == reflect.Slice {
|
||||
s := reflect.ValueOf(t)
|
||||
for i := 0; i < s.Len(); i++ {
|
||||
localVarQueryParams.Add("{{baseName}}", parameterToString(s.Index(i), "{{#collectionFormat}}{{collectionFormat}}{{/collectionFormat}}"))
|
||||
}
|
||||
} else {
|
||||
localVarQueryParams.Add("{{baseName}}", parameterToString(t, "{{#collectionFormat}}{{collectionFormat}}{{/collectionFormat}}"))
|
||||
}
|
||||
{{/isCollectionFormatMulti}}
|
||||
{{^isCollectionFormatMulti}}
|
||||
localVarQueryParams.Add("{{baseName}}", parameterToString(*r.{{paramName}}, "{{#collectionFormat}}{{collectionFormat}}{{/collectionFormat}}"))
|
||||
{{/isCollectionFormatMulti}}
|
||||
}
|
||||
{{/required}}
|
||||
{{/queryParams}}
|
||||
// to determine the Content-Type header
|
||||
{{=<% %>=}}
|
||||
localVarHTTPContentTypes := []string{<%#consumes%>"<%&mediaType%>"<%^-last%>, <%/-last%><%/consumes%>}
|
||||
<%={{ }}=%>
|
||||
|
||||
// set Content-Type header
|
||||
localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes)
|
||||
if localVarHTTPContentType != "" {
|
||||
localVarHeaderParams["Content-Type"] = localVarHTTPContentType
|
||||
}
|
||||
|
||||
// to determine the Accept header
|
||||
{{=<% %>=}}
|
||||
localVarHTTPHeaderAccepts := []string{<%#produces%>"<%&mediaType%>"<%^-last%>, <%/-last%><%/produces%>}
|
||||
<%={{ }}=%>
|
||||
|
||||
// set Accept header
|
||||
localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts)
|
||||
if localVarHTTPHeaderAccept != "" {
|
||||
localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept
|
||||
}
|
||||
{{#headerParams}}
|
||||
{{#required}}
|
||||
localVarHeaderParams["{{baseName}}"] = parameterToString(*r.{{paramName}}, "{{#collectionFormat}}{{collectionFormat}}{{/collectionFormat}}")
|
||||
{{/required}}
|
||||
{{^required}}
|
||||
if r.{{paramName}} != nil {
|
||||
localVarHeaderParams["{{baseName}}"] = parameterToString(*r.{{paramName}}, "{{#collectionFormat}}{{collectionFormat}}{{/collectionFormat}}")
|
||||
}
|
||||
{{/required}}
|
||||
{{/headerParams}}
|
||||
{{#formParams}}
|
||||
{{#isFile}}
|
||||
localVarFormFileName = "{{baseName}}"
|
||||
{{#required}}
|
||||
localVarFile := *r.{{paramName}}
|
||||
{{/required}}
|
||||
{{^required}}
|
||||
var localVarFile {{dataType}}
|
||||
if r.{{paramName}} != nil {
|
||||
localVarFile = *r.{{paramName}}
|
||||
}
|
||||
{{/required}}
|
||||
if localVarFile != nil {
|
||||
fbs, _ := io.ReadAll(localVarFile)
|
||||
localVarFileBytes = fbs
|
||||
localVarFileName = localVarFile.Name()
|
||||
localVarFile.Close()
|
||||
}
|
||||
{{/isFile}}
|
||||
{{^isFile}}
|
||||
{{#required}}
|
||||
localVarFormParams.Add("{{baseName}}", parameterToString(*r.{{paramName}}, "{{#collectionFormat}}{{collectionFormat}}{{/collectionFormat}}"))
|
||||
{{/required}}
|
||||
{{^required}}
|
||||
{{#isModel}}
|
||||
if r.{{paramName}} != nil {
|
||||
paramJson, err := parameterToJson(*r.{{paramName}})
|
||||
if err != nil {
|
||||
return {{#returnType}}localVarReturnValue, {{/returnType}}nil, err
|
||||
}
|
||||
localVarFormParams.Add("{{baseName}}", paramJson)
|
||||
}
|
||||
{{/isModel}}
|
||||
{{^isModel}}
|
||||
if r.{{paramName}} != nil {
|
||||
localVarFormParams.Add("{{baseName}}", parameterToString(*r.{{paramName}}, "{{#collectionFormat}}{{collectionFormat}}{{/collectionFormat}}"))
|
||||
}
|
||||
{{/isModel}}
|
||||
{{/required}}
|
||||
{{/isFile}}
|
||||
{{/formParams}}
|
||||
{{#bodyParams}}
|
||||
// body params
|
||||
localVarPostBody = r.{{paramName}}
|
||||
{{/bodyParams}}
|
||||
{{#authMethods}}
|
||||
{{#isApiKey}}
|
||||
{{^isKeyInCookie}}
|
||||
if r.ctx != nil {
|
||||
// API Key Authentication
|
||||
if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok {
|
||||
{{#vendorExtensions.x-auth-id-alias}}
|
||||
if apiKey, ok := auth["{{.}}"]; ok {
|
||||
var key string
|
||||
if prefix, ok := auth["{{name}}"]; ok && prefix.Prefix != "" {
|
||||
key = prefix.Prefix + " " + apiKey.Key
|
||||
} else {
|
||||
key = apiKey.Key
|
||||
}
|
||||
{{/vendorExtensions.x-auth-id-alias}}
|
||||
{{^vendorExtensions.x-auth-id-alias}}
|
||||
if apiKey, ok := auth["{{name}}"]; ok {
|
||||
var key string
|
||||
if apiKey.Prefix != "" {
|
||||
key = apiKey.Prefix + " " + apiKey.Key
|
||||
} else {
|
||||
key = apiKey.Key
|
||||
}
|
||||
{{/vendorExtensions.x-auth-id-alias}}
|
||||
{{#isKeyInHeader}}
|
||||
localVarHeaderParams["{{keyParamName}}"] = key
|
||||
{{/isKeyInHeader}}
|
||||
{{#isKeyInQuery}}
|
||||
localVarQueryParams.Add("{{keyParamName}}", key)
|
||||
{{/isKeyInQuery}}
|
||||
}
|
||||
}
|
||||
}
|
||||
{{/isKeyInCookie}}
|
||||
{{/isApiKey}}
|
||||
{{/authMethods}}
|
||||
req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFormFileName, localVarFileName, localVarFileBytes)
|
||||
if err != nil {
|
||||
return {{#returnType}}localVarReturnValue, {{/returnType}}nil, err
|
||||
}
|
||||
|
||||
localVarHTTPResponse, err := a.client.callAPI(req)
|
||||
if err != nil || localVarHTTPResponse == nil {
|
||||
return {{#returnType}}localVarReturnValue, {{/returnType}}localVarHTTPResponse, err
|
||||
}
|
||||
|
||||
localVarBody, err := io.ReadAll(localVarHTTPResponse.Body)
|
||||
localVarHTTPResponse.Body.Close()
|
||||
localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody))
|
||||
if err != nil {
|
||||
return {{#returnType}}localVarReturnValue, {{/returnType}}localVarHTTPResponse, err
|
||||
}
|
||||
|
||||
if localVarHTTPResponse.StatusCode >= 300 {
|
||||
newErr := &GenericOpenAPIError{
|
||||
body: localVarBody,
|
||||
error: localVarHTTPResponse.Status,
|
||||
}
|
||||
{{#responses}}
|
||||
{{#dataType}}
|
||||
{{^is1xx}}
|
||||
{{^is2xx}}
|
||||
{{^wildcard}}
|
||||
if localVarHTTPResponse.StatusCode == {{{code}}} {
|
||||
{{/wildcard}}
|
||||
var v {{{dataType}}}
|
||||
err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type"))
|
||||
if err != nil {
|
||||
newErr.error = err.Error()
|
||||
return {{#returnType}}localVarReturnValue, {{/returnType}}localVarHTTPResponse, newErr
|
||||
}
|
||||
newErr.model = v
|
||||
{{^-last}}
|
||||
return {{#returnType}}localVarReturnValue, {{/returnType}}localVarHTTPResponse, newErr
|
||||
{{/-last}}
|
||||
{{^wildcard}}
|
||||
}
|
||||
{{/wildcard}}
|
||||
{{/is2xx}}
|
||||
{{/is1xx}}
|
||||
{{/dataType}}
|
||||
{{/responses}}
|
||||
return {{#returnType}}localVarReturnValue, {{/returnType}}localVarHTTPResponse, newErr
|
||||
}
|
||||
|
||||
{{#returnType}}
|
||||
err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type"))
|
||||
if err != nil {
|
||||
newErr := &GenericOpenAPIError{
|
||||
body: localVarBody,
|
||||
error: err.Error(),
|
||||
}
|
||||
return {{#returnType}}localVarReturnValue, {{/returnType}}localVarHTTPResponse, newErr
|
||||
}
|
||||
|
||||
{{/returnType}}
|
||||
return {{#returnType}}localVarReturnValue, {{/returnType}}localVarHTTPResponse, nil
|
||||
}
|
||||
{{/operation}}
|
||||
{{/operations}}
|
||||
92
.schema/openapi/templates/go/api_doc.mustache
Normal file
92
.schema/openapi/templates/go/api_doc.mustache
Normal file
@@ -0,0 +1,92 @@
|
||||
# {{invokerPackage}}\{{classname}}{{#description}}
|
||||
|
||||
{{description}}{{/description}}
|
||||
|
||||
All URIs are relative to *{{basePath}}*
|
||||
|
||||
Method | HTTP request | Description
|
||||
------------- | ------------- | -------------
|
||||
{{#operations}}{{#operation}}[**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}}
|
||||
{{/operation}}{{/operations}}
|
||||
|
||||
{{#operations}}
|
||||
{{#operation}}
|
||||
|
||||
## {{{operationId}}}
|
||||
|
||||
> {{#returnType}}{{{.}}} {{/returnType}}{{{operationId}}}(ctx{{#pathParams}}, {{paramName}}{{/pathParams}}){{#allParams}}{{^isPathParam}}.{{vendorExtensions.x-export-param-name}}({{paramName}}){{/isPathParam}}{{/allParams}}.Execute()
|
||||
|
||||
{{{summary}}}{{#notes}}
|
||||
|
||||
{{{unespacedNotes}}}{{/notes}}
|
||||
|
||||
### Example
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
{{#vendorExtensions.x-go-import}}
|
||||
{{{vendorExtensions.x-go-import}}}
|
||||
{{/vendorExtensions.x-go-import}}
|
||||
{{goImportAlias}} "./openapi"
|
||||
)
|
||||
|
||||
func main() {
|
||||
{{#allParams}}
|
||||
{{paramName}} := {{{vendorExtensions.x-go-example}}} // {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}}
|
||||
{{/allParams}}
|
||||
|
||||
configuration := {{goImportAlias}}.NewConfiguration()
|
||||
apiClient := {{goImportAlias}}.NewAPIClient(configuration)
|
||||
resp, r, err := apiClient.{{classname}}.{{operationId}}(context.Background(){{#pathParams}}, {{paramName}}{{/pathParams}}){{#allParams}}{{^isPathParam}}.{{vendorExtensions.x-export-param-name}}({{paramName}}){{/isPathParam}}{{/allParams}}.Execute()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error when calling `{{classname}}.{{operationId}}``: %v\n", err)
|
||||
fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r)
|
||||
}
|
||||
{{#returnType}}
|
||||
// response from `{{operationId}}`: {{{.}}}
|
||||
fmt.Fprintf(os.Stdout, "Response from `{{classname}}.{{operationId}}`: %v\n", resp)
|
||||
{{/returnType}}
|
||||
}
|
||||
```
|
||||
|
||||
### Path Parameters
|
||||
|
||||
{{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{#pathParams}}{{#-last}}
|
||||
Name | Type | Description | Notes
|
||||
------------- | ------------- | ------------- | -------------
|
||||
**ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc.{{/-last}}{{/pathParams}}{{#pathParams}}
|
||||
**{{paramName}}** | {{^isPrimitiveType}}{{^isFile}}[{{/isFile}}{{/isPrimitiveType}}**{{dataType}}**{{^isPrimitiveType}}{{^isFile}}]({{baseType}}.md){{/isFile}}{{/isPrimitiveType}} | {{description}} | {{#defaultValue}}[default to {{defaultValue}}]{{/defaultValue}}{{/pathParams}}
|
||||
|
||||
### Other Parameters
|
||||
|
||||
Other parameters are passed through a pointer to a api{{{nickname}}}Request struct via the builder pattern
|
||||
{{#allParams}}{{#-last}}
|
||||
|
||||
Name | Type | Description | Notes
|
||||
------------- | ------------- | ------------- | -------------{{/-last}}{{/allParams}}{{#allParams}}
|
||||
{{^isPathParam}} **{{paramName}}** | {{#isContainer}}{{#isArray}}{{#items}}{{^isPrimitiveType}}{{^isFile}}[{{/isFile}}{{/isPrimitiveType}}**[]{{dataType}}**{{^isPrimitiveType}}{{^isFile}}]({{^baseType}}{{dataType}}{{/baseType}}{{baseType}}.md){{/isFile}}{{/isPrimitiveType}}{{/items}}{{/isArray}}{{#isMap}}{{#items}}{{^isPrimitiveType}}{{^isFile}}[{{/isFile}}{{/isPrimitiveType}}**map[string]{{dataType}}**{{^isPrimitiveType}}{{^isFile}}]({{^baseType}}{{dataType}}{{/baseType}}{{baseType}}.md){{/isFile}}{{/isPrimitiveType}}{{/items}}{{/isMap}}{{/isContainer}}{{^isContainer}}{{^isPrimitiveType}}{{^isFile}}[{{/isFile}}{{/isPrimitiveType}}**{{dataType}}**{{^isPrimitiveType}}{{^isFile}}]({{^baseType}}{{dataType}}{{/baseType}}{{baseType}}.md){{/isFile}}{{/isPrimitiveType}}{{/isContainer}} | {{description}} | {{#defaultValue}}[default to {{defaultValue}}]{{/defaultValue}}{{/isPathParam}}{{/allParams}}
|
||||
|
||||
### Return type
|
||||
|
||||
{{#returnType}}{{#returnTypeIsPrimitive}}**{{{returnType}}}**{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}[**{{{returnType}}}**]({{returnBaseType}}.md){{/returnTypeIsPrimitive}}{{/returnType}}{{^returnType}} (empty response body){{/returnType}}
|
||||
|
||||
### Authorization
|
||||
|
||||
{{^authMethods}}No authorization required{{/authMethods}}{{#authMethods}}[{{{name}}}](../README.md#{{{name}}}){{^-last}}, {{/-last}}{{/authMethods}}
|
||||
|
||||
### HTTP request headers
|
||||
|
||||
- **Content-Type**: {{#consumes}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/consumes}}{{^consumes}}Not defined{{/consumes}}
|
||||
- **Accept**: {{#produces}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/produces}}{{^produces}}Not defined{{/produces}}
|
||||
|
||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints)
|
||||
[[Back to Model list]](../README.md#documentation-for-models)
|
||||
[[Back to README]](../README.md)
|
||||
|
||||
{{/operation}}
|
||||
{{/operations}}
|
||||
583
.schema/openapi/templates/go/client.mustache
Normal file
583
.schema/openapi/templates/go/client.mustache
Normal file
@@ -0,0 +1,583 @@
|
||||
{{>partial_header}}
|
||||
package {{packageName}}
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
{{#withAWSV4Signature}}
|
||||
awsv4 "github.com/aws/aws-sdk-go/aws/signer/v4"
|
||||
awscredentials "github.com/aws/aws-sdk-go/aws/credentials"
|
||||
{{/withAWSV4Signature}}
|
||||
)
|
||||
|
||||
var (
|
||||
jsonCheck = regexp.MustCompile(`(?i:(?:application|text)/(?:vnd\.[^;]+\+)?json)`)
|
||||
xmlCheck = regexp.MustCompile(`(?i:(?:application|text)/xml)`)
|
||||
)
|
||||
|
||||
// APIClient manages communication with the {{appName}} API v{{version}}
|
||||
// In most cases there should be only one, shared, APIClient.
|
||||
type APIClient struct {
|
||||
cfg *Configuration
|
||||
common service // Reuse a single struct instead of allocating one for each service on the heap.
|
||||
|
||||
// API Services
|
||||
{{#apiInfo}}
|
||||
{{#apis}}
|
||||
{{#operations}}
|
||||
|
||||
{{#generateInterfaces}}
|
||||
{{classname}} {{classname}}
|
||||
{{/generateInterfaces}}
|
||||
{{^generateInterfaces}}
|
||||
{{classname}} *{{classname}}Service
|
||||
{{/generateInterfaces}}
|
||||
{{/operations}}
|
||||
{{/apis}}
|
||||
{{/apiInfo}}
|
||||
}
|
||||
|
||||
type service struct {
|
||||
client *APIClient
|
||||
}
|
||||
|
||||
// NewAPIClient creates a new API client. Requires a userAgent string describing your application.
|
||||
// optionally a custom http.Client to allow for advanced features such as caching.
|
||||
func NewAPIClient(cfg *Configuration) *APIClient {
|
||||
if cfg.HTTPClient == nil {
|
||||
cfg.HTTPClient = http.DefaultClient
|
||||
}
|
||||
|
||||
c := &APIClient{}
|
||||
c.cfg = cfg
|
||||
c.common.client = c
|
||||
|
||||
{{#apiInfo}}
|
||||
// API Services
|
||||
{{#apis}}
|
||||
{{#operations}}
|
||||
c.{{classname}} = (*{{classname}}Service)(&c.common)
|
||||
{{/operations}}
|
||||
{{/apis}}
|
||||
{{/apiInfo}}
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
func atoi(in string) (int, error) {
|
||||
return strconv.Atoi(in)
|
||||
}
|
||||
|
||||
// selectHeaderContentType select a content type from the available list.
|
||||
func selectHeaderContentType(contentTypes []string) string {
|
||||
if len(contentTypes) == 0 {
|
||||
return ""
|
||||
}
|
||||
if contains(contentTypes, "application/json") {
|
||||
return "application/json"
|
||||
}
|
||||
return contentTypes[0] // use the first content type specified in 'consumes'
|
||||
}
|
||||
|
||||
// selectHeaderAccept join all accept types and return
|
||||
func selectHeaderAccept(accepts []string) string {
|
||||
if len(accepts) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
if contains(accepts, "application/json") {
|
||||
return "application/json"
|
||||
}
|
||||
|
||||
return strings.Join(accepts, ",")
|
||||
}
|
||||
|
||||
// contains is a case insenstive match, finding needle in a haystack
|
||||
func contains(haystack []string, needle string) bool {
|
||||
for _, a := range haystack {
|
||||
if strings.ToLower(a) == strings.ToLower(needle) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Verify optional parameters are of the correct type.
|
||||
func typeCheckParameter(obj interface{}, expected string, name string) error {
|
||||
// Make sure there is an object.
|
||||
if obj == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check the type is as expected.
|
||||
if reflect.TypeOf(obj).String() != expected {
|
||||
return fmt.Errorf("Expected %s to be of type %s but received %s.", name, expected, reflect.TypeOf(obj).String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// parameterToString convert interface{} parameters to string, using a delimiter if format is provided.
|
||||
func parameterToString(obj interface{}, collectionFormat string) string {
|
||||
var delimiter string
|
||||
|
||||
switch collectionFormat {
|
||||
case "pipes":
|
||||
delimiter = "|"
|
||||
case "ssv":
|
||||
delimiter = " "
|
||||
case "tsv":
|
||||
delimiter = "\t"
|
||||
case "csv":
|
||||
delimiter = ","
|
||||
}
|
||||
|
||||
if reflect.TypeOf(obj).Kind() == reflect.Slice {
|
||||
return strings.Trim(strings.Replace(fmt.Sprint(obj), " ", delimiter, -1), "[]")
|
||||
} else if t, ok := obj.(time.Time); ok {
|
||||
return t.Format(time.RFC3339)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%v", obj)
|
||||
}
|
||||
|
||||
// helper for converting interface{} parameters to json strings
|
||||
func parameterToJson(obj interface{}) (string, error) {
|
||||
jsonBuf, err := json.Marshal(obj)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(jsonBuf), err
|
||||
}
|
||||
|
||||
|
||||
// callAPI do the request.
|
||||
func (c *APIClient) callAPI(request *http.Request) (*http.Response, error) {
|
||||
if c.cfg.Debug {
|
||||
dump, err := httputil.DumpRequestOut(request, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Printf("\n%s\n", string(dump))
|
||||
}
|
||||
|
||||
resp, err := c.cfg.HTTPClient.Do(request)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
|
||||
if c.cfg.Debug {
|
||||
dump, err := httputil.DumpResponse(resp, true)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
log.Printf("\n%s\n", string(dump))
|
||||
}
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// Allow modification of underlying config for alternate implementations and testing
|
||||
// Caution: modifying the configuration while live can cause data races and potentially unwanted behavior
|
||||
func (c *APIClient) GetConfig() *Configuration {
|
||||
return c.cfg
|
||||
}
|
||||
|
||||
// prepareRequest build the request
|
||||
func (c *APIClient) prepareRequest(
|
||||
ctx context.Context,
|
||||
path string, method string,
|
||||
postBody interface{},
|
||||
headerParams map[string]string,
|
||||
queryParams url.Values,
|
||||
formParams url.Values,
|
||||
formFileName string,
|
||||
fileName string,
|
||||
fileBytes []byte) (localVarRequest *http.Request, err error) {
|
||||
|
||||
var body *bytes.Buffer
|
||||
|
||||
// Detect postBody type and post.
|
||||
if postBody != nil {
|
||||
contentType := headerParams["Content-Type"]
|
||||
if contentType == "" {
|
||||
contentType = detectContentType(postBody)
|
||||
headerParams["Content-Type"] = contentType
|
||||
}
|
||||
|
||||
body, err = setBody(postBody, contentType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// add form parameters and file if available.
|
||||
if strings.HasPrefix(headerParams["Content-Type"], "multipart/form-data") && len(formParams) > 0 || (len(fileBytes) > 0 && fileName != "") {
|
||||
if body != nil {
|
||||
return nil, errors.New("Cannot specify postBody and multipart form at the same time.")
|
||||
}
|
||||
body = &bytes.Buffer{}
|
||||
w := multipart.NewWriter(body)
|
||||
|
||||
for k, v := range formParams {
|
||||
for _, iv := range v {
|
||||
if strings.HasPrefix(k, "@") { // file
|
||||
err = addFile(w, k[1:], iv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else { // form value
|
||||
w.WriteField(k, iv)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(fileBytes) > 0 && fileName != "" {
|
||||
w.Boundary()
|
||||
//_, fileNm := filepath.Split(fileName)
|
||||
part, err := w.CreateFormFile(formFileName, filepath.Base(fileName))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = part.Write(fileBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Set the Boundary in the Content-Type
|
||||
headerParams["Content-Type"] = w.FormDataContentType()
|
||||
|
||||
// Set Content-Length
|
||||
headerParams["Content-Length"] = fmt.Sprintf("%d", body.Len())
|
||||
w.Close()
|
||||
}
|
||||
|
||||
if strings.HasPrefix(headerParams["Content-Type"], "application/x-www-form-urlencoded") && len(formParams) > 0 {
|
||||
if body != nil {
|
||||
return nil, errors.New("Cannot specify postBody and x-www-form-urlencoded form at the same time.")
|
||||
}
|
||||
body = &bytes.Buffer{}
|
||||
body.WriteString(formParams.Encode())
|
||||
// Set Content-Length
|
||||
headerParams["Content-Length"] = fmt.Sprintf("%d", body.Len())
|
||||
}
|
||||
|
||||
// Setup path and query parameters
|
||||
url, err := url.Parse(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Override request host, if applicable
|
||||
if c.cfg.Host != "" {
|
||||
url.Host = c.cfg.Host
|
||||
}
|
||||
|
||||
// Override request scheme, if applicable
|
||||
if c.cfg.Scheme != "" {
|
||||
url.Scheme = c.cfg.Scheme
|
||||
}
|
||||
|
||||
// Adding Query Param
|
||||
query := url.Query()
|
||||
for k, v := range queryParams {
|
||||
for _, iv := range v {
|
||||
query.Add(k, iv)
|
||||
}
|
||||
}
|
||||
|
||||
// Encode the parameters.
|
||||
url.RawQuery = query.Encode()
|
||||
|
||||
// Generate a new request
|
||||
if body != nil {
|
||||
localVarRequest, err = http.NewRequest(method, url.String(), body)
|
||||
} else {
|
||||
localVarRequest, err = http.NewRequest(method, url.String(), nil)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// add header parameters, if any
|
||||
if len(headerParams) > 0 {
|
||||
headers := http.Header{}
|
||||
for h, v := range headerParams {
|
||||
headers.Set(h, v)
|
||||
}
|
||||
localVarRequest.Header = headers
|
||||
}
|
||||
|
||||
// Add the user agent to the request.
|
||||
localVarRequest.Header.Add("User-Agent", c.cfg.UserAgent)
|
||||
|
||||
if ctx != nil {
|
||||
// add context to the request
|
||||
localVarRequest = localVarRequest.WithContext(ctx)
|
||||
|
||||
// Walk through any authentication.
|
||||
|
||||
// OAuth2 authentication
|
||||
if tok, ok := ctx.Value(ContextOAuth2).(oauth2.TokenSource); ok {
|
||||
// We were able to grab an oauth2 token from the context
|
||||
var latestToken *oauth2.Token
|
||||
if latestToken, err = tok.Token(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
latestToken.SetAuthHeader(localVarRequest)
|
||||
}
|
||||
|
||||
// Basic HTTP Authentication
|
||||
if auth, ok := ctx.Value(ContextBasicAuth).(BasicAuth); ok {
|
||||
localVarRequest.SetBasicAuth(auth.UserName, auth.Password)
|
||||
}
|
||||
|
||||
// AccessToken Authentication
|
||||
if auth, ok := ctx.Value(ContextAccessToken).(string); ok {
|
||||
localVarRequest.Header.Add("Authorization", "Bearer "+auth)
|
||||
}
|
||||
|
||||
{{#withAWSV4Signature}}
|
||||
// AWS Signature v4 Authentication
|
||||
if auth, ok := ctx.Value(ContextAWSv4).(AWSv4); ok {
|
||||
creds := awscredentials.NewStaticCredentials(auth.AccessKey, auth.SecretKey, "")
|
||||
signer := awsv4.NewSigner(creds)
|
||||
var reader *strings.Reader
|
||||
if body == nil {
|
||||
reader = strings.NewReader("")
|
||||
} else {
|
||||
reader = strings.NewReader(body.String())
|
||||
}
|
||||
timestamp := time.Now()
|
||||
_, err := signer.Sign(localVarRequest, reader, "oapi", "eu-west-2", timestamp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
{{/withAWSV4Signature}}
|
||||
}
|
||||
|
||||
for header, value := range c.cfg.DefaultHeader {
|
||||
localVarRequest.Header.Add(header, value)
|
||||
}
|
||||
{{#hasHttpSignatureMethods}}
|
||||
if ctx != nil {
|
||||
// HTTP Signature Authentication. All request headers must be set (including default headers)
|
||||
// because the headers may be included in the signature.
|
||||
if auth, ok := ctx.Value(ContextHttpSignatureAuth).(HttpSignatureAuth); ok {
|
||||
err = SignRequest(ctx, localVarRequest, auth)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
{{/hasHttpSignatureMethods}}
|
||||
return localVarRequest, nil
|
||||
}
|
||||
|
||||
func (c *APIClient) decode(v interface{}, b []byte, contentType string) (err error) {
|
||||
if len(b) == 0 {
|
||||
return nil
|
||||
}
|
||||
if s, ok := v.(*string); ok {
|
||||
*s = string(b)
|
||||
return nil
|
||||
}
|
||||
if xmlCheck.MatchString(contentType) {
|
||||
if err = xml.Unmarshal(b, v); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if jsonCheck.MatchString(contentType) {
|
||||
if actualObj, ok := v.(interface{GetActualInstance() interface{}}); ok { // oneOf, anyOf schemas
|
||||
if unmarshalObj, ok := actualObj.(interface{UnmarshalJSON([]byte) error}); ok { // make sure it has UnmarshalJSON defined
|
||||
if err = unmarshalObj.UnmarshalJSON(b); err!= nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return errors.New("Unknown type with GetActualInstance but no unmarshalObj.UnmarshalJSON defined")
|
||||
}
|
||||
} else if err = json.Unmarshal(b, v); err != nil { // simple model
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return errors.New("undefined response type")
|
||||
}
|
||||
|
||||
// Add a file to the multipart request
|
||||
func addFile(w *multipart.Writer, fieldName, path string) error {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
part, err := w.CreateFormFile(fieldName, filepath.Base(path))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = io.Copy(part, file)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Prevent trying to import "fmt"
|
||||
func reportError(format string, a ...interface{}) error {
|
||||
return fmt.Errorf(format, a...)
|
||||
}
|
||||
|
||||
// Prevent trying to import "bytes"
|
||||
func newStrictDecoder(data []byte) *json.Decoder {
|
||||
dec := json.NewDecoder(bytes.NewBuffer(data))
|
||||
dec.DisallowUnknownFields()
|
||||
return dec
|
||||
}
|
||||
|
||||
// Set request body from an interface{}
|
||||
func setBody(body interface{}, contentType string) (bodyBuf *bytes.Buffer, err error) {
|
||||
if bodyBuf == nil {
|
||||
bodyBuf = &bytes.Buffer{}
|
||||
}
|
||||
|
||||
if reader, ok := body.(io.Reader); ok {
|
||||
_, err = bodyBuf.ReadFrom(reader)
|
||||
} else if b, ok := body.([]byte); ok {
|
||||
_, err = bodyBuf.Write(b)
|
||||
} else if s, ok := body.(string); ok {
|
||||
_, err = bodyBuf.WriteString(s)
|
||||
} else if s, ok := body.(*string); ok {
|
||||
_, err = bodyBuf.WriteString(*s)
|
||||
} else if jsonCheck.MatchString(contentType) {
|
||||
err = json.NewEncoder(bodyBuf).Encode(body)
|
||||
} else if xmlCheck.MatchString(contentType) {
|
||||
err = xml.NewEncoder(bodyBuf).Encode(body)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if bodyBuf.Len() == 0 {
|
||||
err = fmt.Errorf("Invalid body type %s\n", contentType)
|
||||
return nil, err
|
||||
}
|
||||
return bodyBuf, nil
|
||||
}
|
||||
|
||||
// detectContentType method is used to figure out `Request.Body` content type for request header
|
||||
func detectContentType(body interface{}) string {
|
||||
contentType := "text/plain; charset=utf-8"
|
||||
kind := reflect.TypeOf(body).Kind()
|
||||
|
||||
switch kind {
|
||||
case reflect.Struct, reflect.Map, reflect.Ptr:
|
||||
contentType = "application/json; charset=utf-8"
|
||||
case reflect.String:
|
||||
contentType = "text/plain; charset=utf-8"
|
||||
default:
|
||||
if b, ok := body.([]byte); ok {
|
||||
contentType = http.DetectContentType(b)
|
||||
} else if kind == reflect.Slice {
|
||||
contentType = "application/json; charset=utf-8"
|
||||
}
|
||||
}
|
||||
|
||||
return contentType
|
||||
}
|
||||
|
||||
// Ripped from https://github.com/gregjones/httpcache/blob/master/httpcache.go
|
||||
type cacheControl map[string]string
|
||||
|
||||
func parseCacheControl(headers http.Header) cacheControl {
|
||||
cc := cacheControl{}
|
||||
ccHeader := headers.Get("Cache-Control")
|
||||
for _, part := range strings.Split(ccHeader, ",") {
|
||||
part = strings.Trim(part, " ")
|
||||
if part == "" {
|
||||
continue
|
||||
}
|
||||
if strings.ContainsRune(part, '=') {
|
||||
keyval := strings.Split(part, "=")
|
||||
cc[strings.Trim(keyval[0], " ")] = strings.Trim(keyval[1], ",")
|
||||
} else {
|
||||
cc[part] = ""
|
||||
}
|
||||
}
|
||||
return cc
|
||||
}
|
||||
|
||||
// CacheExpires helper function to determine remaining time before repeating a request.
|
||||
func CacheExpires(r *http.Response) time.Time {
|
||||
// Figure out when the cache expires.
|
||||
var expires time.Time
|
||||
now, err := time.Parse(time.RFC1123, r.Header.Get("date"))
|
||||
if err != nil {
|
||||
return time.Now()
|
||||
}
|
||||
respCacheControl := parseCacheControl(r.Header)
|
||||
|
||||
if maxAge, ok := respCacheControl["max-age"]; ok {
|
||||
lifetime, err := time.ParseDuration(maxAge + "s")
|
||||
if err != nil {
|
||||
expires = now
|
||||
} else {
|
||||
expires = now.Add(lifetime)
|
||||
}
|
||||
} else {
|
||||
expiresHeader := r.Header.Get("Expires")
|
||||
if expiresHeader != "" {
|
||||
expires, err = time.Parse(time.RFC1123, expiresHeader)
|
||||
if err != nil {
|
||||
expires = now
|
||||
}
|
||||
}
|
||||
}
|
||||
return expires
|
||||
}
|
||||
|
||||
func strlen(s string) int {
|
||||
return utf8.RuneCountInString(s)
|
||||
}
|
||||
|
||||
// GenericOpenAPIError Provides access to the body, error and model on returned errors.
|
||||
type GenericOpenAPIError struct {
|
||||
body []byte
|
||||
error string
|
||||
model interface{}
|
||||
}
|
||||
|
||||
// Error returns non-empty string if there was an error.
|
||||
func (e GenericOpenAPIError) Error() string {
|
||||
return e.error
|
||||
}
|
||||
|
||||
// Body returns the raw bytes of the response
|
||||
func (e GenericOpenAPIError) Body() []byte {
|
||||
return e.body
|
||||
}
|
||||
|
||||
// Model returns the unpacked model of the error
|
||||
func (e GenericOpenAPIError) Model() interface{} {
|
||||
return e.model
|
||||
}
|
||||
303
.schema/openapi/templates/go/configuration.mustache
Normal file
303
.schema/openapi/templates/go/configuration.mustache
Normal file
@@ -0,0 +1,303 @@
|
||||
{{>partial_header}}
|
||||
package {{packageName}}
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// contextKeys are used to identify the type of value in the context.
|
||||
// Since these are string, it is possible to get a short description of the
|
||||
// context key for logging and debugging using key.String().
|
||||
|
||||
type contextKey string
|
||||
|
||||
func (c contextKey) String() string {
|
||||
return "auth " + string(c)
|
||||
}
|
||||
|
||||
var (
|
||||
// ContextOAuth2 takes an oauth2.TokenSource as authentication for the request.
|
||||
ContextOAuth2 = contextKey("token")
|
||||
|
||||
// ContextBasicAuth takes BasicAuth as authentication for the request.
|
||||
ContextBasicAuth = contextKey("basic")
|
||||
|
||||
// ContextAccessToken takes a string oauth2 access token as authentication for the request.
|
||||
ContextAccessToken = contextKey("accesstoken")
|
||||
|
||||
// ContextAPIKeys takes a string apikey as authentication for the request
|
||||
ContextAPIKeys = contextKey("apiKeys")
|
||||
|
||||
{{#withAWSV4Signature}}
|
||||
// ContextAWSv4 takes an Access Key and a Secret Key for signing AWS Signature v4
|
||||
ContextAWSv4 = contextKey("awsv4")
|
||||
|
||||
{{/withAWSV4Signature}}
|
||||
// ContextHttpSignatureAuth takes HttpSignatureAuth as authentication for the request.
|
||||
ContextHttpSignatureAuth = contextKey("httpsignature")
|
||||
|
||||
// ContextServerIndex uses a server configuration from the index.
|
||||
ContextServerIndex = contextKey("serverIndex")
|
||||
|
||||
// ContextOperationServerIndices uses a server configuration from the index mapping.
|
||||
ContextOperationServerIndices = contextKey("serverOperationIndices")
|
||||
|
||||
// ContextServerVariables overrides a server configuration variables.
|
||||
ContextServerVariables = contextKey("serverVariables")
|
||||
|
||||
// ContextOperationServerVariables overrides a server configuration variables using operation specific values.
|
||||
ContextOperationServerVariables = contextKey("serverOperationVariables")
|
||||
)
|
||||
|
||||
// BasicAuth provides basic http authentication to a request passed via context using ContextBasicAuth
|
||||
type BasicAuth struct {
|
||||
UserName string `json:"userName,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
}
|
||||
|
||||
// APIKey provides API key based authentication to a request passed via context using ContextAPIKey
|
||||
type APIKey struct {
|
||||
Key string
|
||||
Prefix string
|
||||
}
|
||||
|
||||
{{#withAWSV4Signature}}
|
||||
// AWSv4 provides AWS Signature to a request passed via context using ContextAWSv4
|
||||
// https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html
|
||||
type AWSv4 struct {
|
||||
AccessKey string
|
||||
SecretKey string
|
||||
}
|
||||
|
||||
{{/withAWSV4Signature}}
|
||||
// ServerVariable stores the information about a server variable
|
||||
type ServerVariable struct {
|
||||
Description string
|
||||
DefaultValue string
|
||||
EnumValues []string
|
||||
}
|
||||
|
||||
// ServerConfiguration stores the information about a server
|
||||
type ServerConfiguration struct {
|
||||
URL string
|
||||
Description string
|
||||
Variables map[string]ServerVariable
|
||||
}
|
||||
|
||||
// ServerConfigurations stores multiple ServerConfiguration items
|
||||
type ServerConfigurations []ServerConfiguration
|
||||
|
||||
// Configuration stores the configuration of the API client
|
||||
type Configuration struct {
|
||||
Host string `json:"host,omitempty"`
|
||||
Scheme string `json:"scheme,omitempty"`
|
||||
DefaultHeader map[string]string `json:"defaultHeader,omitempty"`
|
||||
UserAgent string `json:"userAgent,omitempty"`
|
||||
Debug bool `json:"debug,omitempty"`
|
||||
Servers ServerConfigurations
|
||||
OperationServers map[string]ServerConfigurations
|
||||
HTTPClient *http.Client
|
||||
}
|
||||
|
||||
// NewConfiguration returns a new Configuration object
|
||||
func NewConfiguration() *Configuration {
|
||||
cfg := &Configuration{
|
||||
DefaultHeader: make(map[string]string),
|
||||
UserAgent: "{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{packageVersion}}}/go{{/httpUserAgent}}",
|
||||
Debug: false,
|
||||
{{#servers}}
|
||||
{{#-first}}
|
||||
Servers: ServerConfigurations{
|
||||
{{/-first}}
|
||||
{
|
||||
URL: "{{{url}}}",
|
||||
Description: "{{{description}}}{{^description}}No description provided{{/description}}",
|
||||
{{#variables}}
|
||||
{{#-first}}
|
||||
Variables: map[string]ServerVariable{
|
||||
{{/-first}}
|
||||
"{{{name}}}": ServerVariable{
|
||||
Description: "{{{description}}}{{^description}}No description provided{{/description}}",
|
||||
DefaultValue: "{{{defaultValue}}}",
|
||||
{{#enumValues}}
|
||||
{{#-first}}
|
||||
EnumValues: []string{
|
||||
{{/-first}}
|
||||
"{{{.}}}",
|
||||
{{#-last}}
|
||||
},
|
||||
{{/-last}}
|
||||
{{/enumValues}}
|
||||
},
|
||||
{{#-last}}
|
||||
},
|
||||
{{/-last}}
|
||||
{{/variables}}
|
||||
},
|
||||
{{#-last}}
|
||||
},
|
||||
{{/-last}}
|
||||
{{/servers}}
|
||||
{{#apiInfo}}
|
||||
OperationServers: map[string]ServerConfigurations{
|
||||
{{#apis}}
|
||||
{{#operations}}
|
||||
{{#operation}}
|
||||
{{#servers}}
|
||||
{{#-first}}
|
||||
"{{{classname}}}Service.{{{nickname}}}": {
|
||||
{{/-first}}
|
||||
{
|
||||
URL: "{{{url}}}",
|
||||
Description: "{{{description}}}{{^description}}No description provided{{/description}}",
|
||||
{{#variables}}
|
||||
{{#-first}}
|
||||
Variables: map[string]ServerVariable{
|
||||
{{/-first}}
|
||||
"{{{name}}}": ServerVariable{
|
||||
Description: "{{{description}}}{{^description}}No description provided{{/description}}",
|
||||
DefaultValue: "{{{defaultValue}}}",
|
||||
{{#enumValues}}
|
||||
{{#-first}}
|
||||
EnumValues: []string{
|
||||
{{/-first}}
|
||||
"{{{.}}}",
|
||||
{{#-last}}
|
||||
},
|
||||
{{/-last}}
|
||||
{{/enumValues}}
|
||||
},
|
||||
{{#-last}}
|
||||
},
|
||||
{{/-last}}
|
||||
{{/variables}}
|
||||
},
|
||||
{{#-last}}
|
||||
},
|
||||
{{/-last}}
|
||||
{{/servers}}
|
||||
{{/operation}}
|
||||
{{/operations}}
|
||||
{{/apis}}
|
||||
},
|
||||
{{/apiInfo}}
|
||||
}
|
||||
return cfg
|
||||
}
|
||||
|
||||
// AddDefaultHeader adds a new HTTP header to the default header in the request
|
||||
func (c *Configuration) AddDefaultHeader(key string, value string) {
|
||||
c.DefaultHeader[key] = value
|
||||
}
|
||||
|
||||
// URL formats template on a index using given variables
|
||||
func (sc ServerConfigurations) URL(index int, variables map[string]string) (string, error) {
|
||||
if index < 0 || len(sc) <= index {
|
||||
return "", fmt.Errorf("Index %v out of range %v", index, len(sc)-1)
|
||||
}
|
||||
server := sc[index]
|
||||
url := server.URL
|
||||
|
||||
// go through variables and replace placeholders
|
||||
for name, variable := range server.Variables {
|
||||
if value, ok := variables[name]; ok {
|
||||
found := bool(len(variable.EnumValues) == 0)
|
||||
for _, enumValue := range variable.EnumValues {
|
||||
if value == enumValue {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return "", fmt.Errorf("The variable %s in the server URL has invalid value %v. Must be %v", name, value, variable.EnumValues)
|
||||
}
|
||||
url = strings.Replace(url, "{"+name+"}", value, -1)
|
||||
} else {
|
||||
url = strings.Replace(url, "{"+name+"}", variable.DefaultValue, -1)
|
||||
}
|
||||
}
|
||||
return url, nil
|
||||
}
|
||||
|
||||
// ServerURL returns URL based on server settings
|
||||
func (c *Configuration) ServerURL(index int, variables map[string]string) (string, error) {
|
||||
return c.Servers.URL(index, variables)
|
||||
}
|
||||
|
||||
func getServerIndex(ctx context.Context) (int, error) {
|
||||
si := ctx.Value(ContextServerIndex)
|
||||
if si != nil {
|
||||
if index, ok := si.(int); ok {
|
||||
return index, nil
|
||||
}
|
||||
return 0, reportError("Invalid type %T should be int", si)
|
||||
}
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func getServerOperationIndex(ctx context.Context, endpoint string) (int, error) {
|
||||
osi := ctx.Value(ContextOperationServerIndices)
|
||||
if osi != nil {
|
||||
if operationIndices, ok := osi.(map[string]int); !ok {
|
||||
return 0, reportError("Invalid type %T should be map[string]int", osi)
|
||||
} else {
|
||||
index, ok := operationIndices[endpoint]
|
||||
if ok {
|
||||
return index, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return getServerIndex(ctx)
|
||||
}
|
||||
|
||||
func getServerVariables(ctx context.Context) (map[string]string, error) {
|
||||
sv := ctx.Value(ContextServerVariables)
|
||||
if sv != nil {
|
||||
if variables, ok := sv.(map[string]string); ok {
|
||||
return variables, nil
|
||||
}
|
||||
return nil, reportError("ctx value of ContextServerVariables has invalid type %T should be map[string]string", sv)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func getServerOperationVariables(ctx context.Context, endpoint string) (map[string]string, error) {
|
||||
osv := ctx.Value(ContextOperationServerVariables)
|
||||
if osv != nil {
|
||||
if operationVariables, ok := osv.(map[string]map[string]string); !ok {
|
||||
return nil, reportError("ctx value of ContextOperationServerVariables has invalid type %T should be map[string]map[string]string", osv)
|
||||
} else {
|
||||
variables, ok := operationVariables[endpoint]
|
||||
if ok {
|
||||
return variables, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return getServerVariables(ctx)
|
||||
}
|
||||
|
||||
// ServerURLWithContext returns a new server URL given an endpoint
|
||||
func (c *Configuration) ServerURLWithContext(ctx context.Context, endpoint string) (string, error) {
|
||||
sc, ok := c.OperationServers[endpoint]
|
||||
if !ok {
|
||||
sc = c.Servers
|
||||
}
|
||||
|
||||
if ctx == nil {
|
||||
return sc.URL(0, nil)
|
||||
}
|
||||
|
||||
index, err := getServerOperationIndex(ctx, endpoint)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
variables, err := getServerOperationVariables(ctx, endpoint)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return sc.URL(index, variables)
|
||||
}
|
||||
58
.schema/openapi/templates/go/git_push.sh.mustache
Executable file
58
.schema/openapi/templates/go/git_push.sh.mustache
Executable file
@@ -0,0 +1,58 @@
|
||||
#!/bin/sh
|
||||
# ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/
|
||||
#
|
||||
# Usage example: /bin/sh ./git_push.sh wing328 openapi-pestore-perl "minor update" "gitlab.com"
|
||||
|
||||
git_user_id=$1
|
||||
git_repo_id=$2
|
||||
release_note=$3
|
||||
git_host=$4
|
||||
|
||||
if [ "$git_host" = "" ]; then
|
||||
git_host="{{{gitHost}}}"
|
||||
echo "[INFO] No command line input provided. Set \$git_host to $git_host"
|
||||
fi
|
||||
|
||||
if [ "$git_user_id" = "" ]; then
|
||||
git_user_id="{{{gitUserId}}}"
|
||||
echo "[INFO] No command line input provided. Set \$git_user_id to $git_user_id"
|
||||
fi
|
||||
|
||||
if [ "$git_repo_id" = "" ]; then
|
||||
git_repo_id="{{{gitRepoId}}}"
|
||||
echo "[INFO] No command line input provided. Set \$git_repo_id to $git_repo_id"
|
||||
fi
|
||||
|
||||
if [ "$release_note" = "" ]; then
|
||||
release_note="{{{releaseNote}}}"
|
||||
echo "[INFO] No command line input provided. Set \$release_note to $release_note"
|
||||
fi
|
||||
|
||||
# Initialize the local directory as a Git repository
|
||||
git init
|
||||
|
||||
# Adds the files in the local repository and stages them for commit.
|
||||
git add .
|
||||
|
||||
# Commits the tracked changes and prepares them to be pushed to a remote repository.
|
||||
git commit -m "$release_note"
|
||||
|
||||
# Sets the new remote
|
||||
git_remote=`git remote`
|
||||
if [ "$git_remote" = "" ]; then # git remote not defined
|
||||
|
||||
if [ "$GIT_TOKEN" = "" ]; then
|
||||
echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git credential in your environment."
|
||||
git remote add origin https://${git_host}/${git_user_id}/${git_repo_id}.git
|
||||
else
|
||||
git remote add origin https://${git_user_id}:${GIT_TOKEN}@${git_host}/${git_user_id}/${git_repo_id}.git
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
git pull origin master
|
||||
|
||||
# Pushes (Forces) the changes in the local repository up to the remote repository
|
||||
echo "Git pushing to https://${git_host}/${git_user_id}/${git_repo_id}.git"
|
||||
git push origin master 2>&1 | grep -v 'To https'
|
||||
|
||||
24
.schema/openapi/templates/go/gitignore.mustache
Normal file
24
.schema/openapi/templates/go/gitignore.mustache
Normal file
@@ -0,0 +1,24 @@
|
||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
*.test
|
||||
*.prof
|
||||
20
.schema/openapi/templates/go/model.mustache
Normal file
20
.schema/openapi/templates/go/model.mustache
Normal file
@@ -0,0 +1,20 @@
|
||||
{{>partial_header}}
|
||||
package {{packageName}}
|
||||
|
||||
{{#models}}
|
||||
import (
|
||||
"encoding/json"
|
||||
{{#imports}}
|
||||
"{{import}}"
|
||||
{{/imports}}
|
||||
)
|
||||
|
||||
{{#model}}
|
||||
{{#isEnum}}
|
||||
{{>model_enum}}
|
||||
{{/isEnum}}
|
||||
{{^isEnum}}
|
||||
{{#oneOf}}{{#-first}}{{>model_oneof}}{{/-first}}{{/oneOf}}{{^oneOf}}{{#anyOf}}{{#-first}}{{>model_anyof}}{{/-first}}{{/anyOf}}{{^anyOf}}{{>model_simple}}{{/anyOf}}{{/oneOf}}
|
||||
{{/isEnum}}
|
||||
{{/model}}
|
||||
{{/models}}
|
||||
76
.schema/openapi/templates/go/model_anyof.mustache
Normal file
76
.schema/openapi/templates/go/model_anyof.mustache
Normal file
@@ -0,0 +1,76 @@
|
||||
// {{classname}}{{#description}} {{{description}}}{{/description}}{{^description}} struct for {{{classname}}}{{/description}}
|
||||
type {{classname}} struct {
|
||||
{{#anyOf}}
|
||||
{{{.}}} *{{{.}}}
|
||||
{{/anyOf}}
|
||||
}
|
||||
|
||||
// Unmarshal JSON data into any of the pointers in the struct
|
||||
func (dst *{{classname}}) UnmarshalJSON(data []byte) error {
|
||||
var err error
|
||||
{{#isNullable}}
|
||||
// this object is nullable so check if the payload is null or empty string
|
||||
if string(data) == "" || string(data) == "{}" {
|
||||
return nil
|
||||
}
|
||||
|
||||
{{/isNullable}}
|
||||
{{#discriminator}}
|
||||
{{#mappedModels}}
|
||||
{{#-first}}
|
||||
// use discriminator value to speed up the lookup
|
||||
var jsonDict map[string]interface{}
|
||||
err := json.Unmarshal(data, &jsonDict)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to unmarshal JSON into map for the discrimintor lookup.")
|
||||
}
|
||||
|
||||
{{/-first}}
|
||||
// check if the discriminator value is '{{{mappingName}}}'
|
||||
if jsonDict["{{{propertyBaseName}}}"] == "{{{mappingName}}}" {
|
||||
// try to unmarshal JSON data into {{{modelName}}}
|
||||
err = json.Unmarshal(data, &dst.{{{modelName}}});
|
||||
if err == nil {
|
||||
json{{{modelName}}}, _ := json.Marshal(dst.{{{modelName}}})
|
||||
if string(json{{{modelName}}}) == "{}" { // empty struct
|
||||
dst.{{{modelName}}} = nil
|
||||
} else {
|
||||
return nil // data stored in dst.{{{modelName}}}, return on the first match
|
||||
}
|
||||
} else {
|
||||
dst.{{{modelName}}} = nil
|
||||
}
|
||||
}
|
||||
|
||||
{{/mappedModels}}
|
||||
{{/discriminator}}
|
||||
{{#anyOf}}
|
||||
// try to unmarshal JSON data into {{{.}}}
|
||||
err = json.Unmarshal(data, &dst.{{{.}}});
|
||||
if err == nil {
|
||||
json{{{.}}}, _ := json.Marshal(dst.{{{.}}})
|
||||
if string(json{{{.}}}) == "{}" { // empty struct
|
||||
dst.{{{.}}} = nil
|
||||
} else {
|
||||
return nil // data stored in dst.{{{.}}}, return on the first match
|
||||
}
|
||||
} else {
|
||||
dst.{{{.}}} = nil
|
||||
}
|
||||
|
||||
{{/anyOf}}
|
||||
return fmt.Errorf("Data failed to match schemas in anyOf({{classname}})")
|
||||
}
|
||||
|
||||
// Marshal data from the first non-nil pointers in the struct to JSON
|
||||
func (src *{{classname}}) MarshalJSON() ([]byte, error) {
|
||||
{{#anyOf}}
|
||||
if src.{{{.}}} != nil {
|
||||
return json.Marshal(&src.{{{.}}})
|
||||
}
|
||||
|
||||
{{/anyOf}}
|
||||
return nil, nil // no data in anyOf schemas
|
||||
}
|
||||
|
||||
{{>nullable_model}}
|
||||
97
.schema/openapi/templates/go/model_doc.mustache
Normal file
97
.schema/openapi/templates/go/model_doc.mustache
Normal file
@@ -0,0 +1,97 @@
|
||||
{{#models}}{{#model}}# {{classname}}
|
||||
|
||||
{{^isEnum}}
|
||||
## Properties
|
||||
|
||||
Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
{{#vendorExtensions.x-is-one-of-interface}}
|
||||
**{{classname}}Interface** | **interface { {{#discriminator}}{{propertyGetter}}() {{propertyType}}{{/discriminator}} }** | An interface that can hold any of the proper implementing types |
|
||||
{{/vendorExtensions.x-is-one-of-interface}}
|
||||
{{^vendorExtensions.x-is-one-of-interface}}
|
||||
{{#vars}}**{{name}}** | {{^required}}Pointer to {{/required}}{{#isContainer}}{{#isArray}}{{#items}}{{^isPrimitiveType}}{{^isFile}}[{{/isFile}}{{/isPrimitiveType}}**[]{{dataType}}**{{^isPrimitiveType}}{{^isFile}}]({{dataType}}.md){{/isFile}}{{/isPrimitiveType}}{{/items}}{{/isArray}}{{#isMap}}{{#items}}{{^isPrimitiveType}}{{^isFile}}[{{/isFile}}{{/isPrimitiveType}}**map[string]{{dataType}}**{{^isPrimitiveType}}{{^isFile}}]({{^baseType}}{{dataType}}{{/baseType}}{{baseType}}.md){{/isFile}}{{/isPrimitiveType}}{{/items}}{{/isMap}}{{/isContainer}}{{^isContainer}}{{^isPrimitiveType}}{{^isFile}}{{^isDateTime}}[{{/isDateTime}}{{/isFile}}{{/isPrimitiveType}}**{{dataType}}**{{^isPrimitiveType}}{{^isFile}}{{^isDateTime}}]({{^baseType}}{{dataType}}{{/baseType}}{{baseType}}.md){{/isDateTime}}{{/isFile}}{{/isPrimitiveType}}{{/isContainer}} | {{description}} | {{^required}}[optional] {{/required}}{{#isReadOnly}}[readonly] {{/isReadOnly}}{{#defaultValue}}[default to {{{.}}}]{{/defaultValue}}
|
||||
{{/vars}}
|
||||
{{/vendorExtensions.x-is-one-of-interface}}
|
||||
|
||||
## Methods
|
||||
|
||||
{{^vendorExtensions.x-is-one-of-interface}}
|
||||
### New{{classname}}
|
||||
|
||||
`func New{{classname}}({{#vars}}{{#required}}{{nameInCamelCase}} {{dataType}}, {{/required}}{{/vars}}) *{{classname}}`
|
||||
|
||||
New{{classname}} instantiates a new {{classname}} object
|
||||
This constructor will assign default values to properties that have it defined,
|
||||
and makes sure properties required by API are set, but the set of arguments
|
||||
will change when the set of required properties is changed
|
||||
|
||||
### New{{classname}}WithDefaults
|
||||
|
||||
`func New{{classname}}WithDefaults() *{{classname}}`
|
||||
|
||||
New{{classname}}WithDefaults instantiates a new {{classname}} object
|
||||
This constructor will only assign default values to properties that have it defined,
|
||||
but it doesn't guarantee that properties required by API are set
|
||||
|
||||
{{#vars}}
|
||||
### Get{{name}}
|
||||
|
||||
`func (o *{{classname}}) Get{{name}}() {{vendorExtensions.x-go-base-type}}`
|
||||
|
||||
Get{{name}} returns the {{name}} field if non-nil, zero value otherwise.
|
||||
|
||||
### Get{{name}}Ok
|
||||
|
||||
`func (o *{{classname}}) Get{{name}}Ok() (*{{vendorExtensions.x-go-base-type}}, bool)`
|
||||
|
||||
Get{{name}}Ok returns a tuple with the {{name}} field if it's non-nil, zero value otherwise
|
||||
and a boolean to check if the value has been set.
|
||||
|
||||
### Set{{name}}
|
||||
|
||||
`func (o *{{classname}}) Set{{name}}(v {{vendorExtensions.x-go-base-type}})`
|
||||
|
||||
Set{{name}} sets {{name}} field to given value.
|
||||
|
||||
{{^required}}
|
||||
### Has{{name}}
|
||||
|
||||
`func (o *{{classname}}) Has{{name}}() bool`
|
||||
|
||||
Has{{name}} returns a boolean if a field has been set.
|
||||
{{/required}}
|
||||
|
||||
{{#isNullable}}
|
||||
### Set{{name}}Nil
|
||||
|
||||
`func (o *{{classname}}) Set{{name}}Nil(b bool)`
|
||||
|
||||
Set{{name}}Nil sets the value for {{name}} to be an explicit nil
|
||||
|
||||
### Unset{{name}}
|
||||
`func (o *{{classname}}) Unset{{name}}()`
|
||||
|
||||
Unset{{name}} ensures that no value is present for {{name}}, not even an explicit nil
|
||||
{{/isNullable}}
|
||||
{{/vars}}
|
||||
{{#vendorExtensions.x-implements}}
|
||||
|
||||
### As{{{.}}}
|
||||
|
||||
`func (s *{{classname}}) As{{{.}}}() {{{.}}}`
|
||||
|
||||
Convenience method to wrap this instance of {{classname}} in {{{.}}}
|
||||
{{/vendorExtensions.x-implements}}
|
||||
{{/vendorExtensions.x-is-one-of-interface}}
|
||||
{{/isEnum}}
|
||||
{{#isEnum}}
|
||||
## Enum
|
||||
|
||||
{{#allowableValues}}{{#enumVars}}
|
||||
* `{{name}}` (value: `{{{value}}}`)
|
||||
{{/enumVars}}{{/allowableValues}}
|
||||
{{/isEnum}}
|
||||
|
||||
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||
|
||||
{{/model}}{{/models}}
|
||||
71
.schema/openapi/templates/go/model_enum.mustache
Normal file
71
.schema/openapi/templates/go/model_enum.mustache
Normal file
@@ -0,0 +1,71 @@
|
||||
// {{{classname}}} {{#description}}{{{.}}}{{/description}}{{^description}}the model '{{{classname}}}'{{/description}}
|
||||
type {{{classname}}} {{^format}}{{dataType}}{{/format}}{{#format}}{{{format}}}{{/format}}
|
||||
|
||||
// List of {{{name}}}
|
||||
const (
|
||||
{{#allowableValues}}
|
||||
{{#enumVars}}
|
||||
{{^-first}}
|
||||
{{/-first}}
|
||||
{{#enumClassPrefix}}{{{classname.toUpperCase}}}_{{/enumClassPrefix}}{{name}} {{{classname}}} = {{{value}}}
|
||||
{{/enumVars}}
|
||||
{{/allowableValues}}
|
||||
)
|
||||
|
||||
func (v *{{{classname}}}) UnmarshalJSON(src []byte) error {
|
||||
var value {{^format}}{{dataType}}{{/format}}{{#format}}{{{format}}}{{/format}}
|
||||
err := json.Unmarshal(src, &value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
enumTypeValue := {{{classname}}}(value)
|
||||
for _, existing := range []{{classname}}{ {{#allowableValues}}{{#enumVars}}{{{value}}}, {{/enumVars}} {{/allowableValues}} } {
|
||||
if existing == enumTypeValue {
|
||||
*v = enumTypeValue
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("%+v is not a valid {{classname}}", value)
|
||||
}
|
||||
|
||||
// Ptr returns reference to {{{name}}} value
|
||||
func (v {{{classname}}}) Ptr() *{{{classname}}} {
|
||||
return &v
|
||||
}
|
||||
|
||||
type Nullable{{{classname}}} struct {
|
||||
value *{{{classname}}}
|
||||
isSet bool
|
||||
}
|
||||
|
||||
func (v Nullable{{classname}}) Get() *{{classname}} {
|
||||
return v.value
|
||||
}
|
||||
|
||||
func (v *Nullable{{classname}}) Set(val *{{classname}}) {
|
||||
v.value = val
|
||||
v.isSet = true
|
||||
}
|
||||
|
||||
func (v Nullable{{classname}}) IsSet() bool {
|
||||
return v.isSet
|
||||
}
|
||||
|
||||
func (v *Nullable{{classname}}) Unset() {
|
||||
v.value = nil
|
||||
v.isSet = false
|
||||
}
|
||||
|
||||
func NewNullable{{classname}}(val *{{classname}}) *Nullable{{classname}} {
|
||||
return &Nullable{{classname}}{value: val, isSet: true}
|
||||
}
|
||||
|
||||
func (v Nullable{{{classname}}}) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(v.value)
|
||||
}
|
||||
|
||||
func (v *Nullable{{{classname}}}) UnmarshalJSON(src []byte) error {
|
||||
v.isSet = true
|
||||
return json.Unmarshal(src, &v.value)
|
||||
}
|
||||
114
.schema/openapi/templates/go/model_oneof.mustache
Normal file
114
.schema/openapi/templates/go/model_oneof.mustache
Normal file
@@ -0,0 +1,114 @@
|
||||
// {{classname}} - {{#description}}{{{description}}}{{/description}}{{^description}}struct for {{{classname}}}{{/description}}
|
||||
type {{classname}} struct {
|
||||
{{#oneOf}}
|
||||
{{#lambda.titlecase}}{{{.}}}{{/lambda.titlecase}} *{{{.}}}
|
||||
{{/oneOf}}
|
||||
}
|
||||
|
||||
{{#oneOf}}
|
||||
// {{{.}}}As{{classname}} is a convenience function that returns {{{.}}} wrapped in {{classname}}
|
||||
func {{#lambda.titlecase}}{{{.}}}{{/lambda.titlecase}}As{{classname}}(v *{{{.}}}) {{classname}} {
|
||||
return {{classname}}{
|
||||
{{#lambda.titlecase}}{{{.}}}{{/lambda.titlecase}}: v,
|
||||
}
|
||||
}
|
||||
|
||||
{{/oneOf}}
|
||||
|
||||
// Unmarshal JSON data into one of the pointers in the struct
|
||||
func (dst *{{classname}}) UnmarshalJSON(data []byte) error {
|
||||
var err error
|
||||
{{#isNullable}}
|
||||
// this object is nullable so check if the payload is null or empty string
|
||||
if string(data) == "" || string(data) == "{}" {
|
||||
return nil
|
||||
}
|
||||
|
||||
{{/isNullable}}
|
||||
{{#useOneOfDiscriminatorLookup}}
|
||||
{{#discriminator}}
|
||||
{{#mappedModels}}
|
||||
{{#-first}}
|
||||
// use discriminator value to speed up the lookup
|
||||
var jsonDict map[string]interface{}
|
||||
err = newStrictDecoder(data).Decode(&jsonDict)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to unmarshal JSON into map for the discrimintor lookup.")
|
||||
}
|
||||
|
||||
{{/-first}}
|
||||
// check if the discriminator value is '{{{mappingName}}}'
|
||||
if jsonDict["{{{propertyBaseName}}}"] == "{{{mappingName}}}" {
|
||||
// try to unmarshal JSON data into {{{modelName}}}
|
||||
err = json.Unmarshal(data, &dst.{{{modelName}}})
|
||||
if err == nil {
|
||||
return nil // data stored in dst.{{{modelName}}}, return on the first match
|
||||
} else {
|
||||
dst.{{{modelName}}} = nil
|
||||
return fmt.Errorf("Failed to unmarshal {{classname}} as {{{modelName}}}: %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
{{/mappedModels}}
|
||||
{{/discriminator}}
|
||||
return nil
|
||||
{{/useOneOfDiscriminatorLookup}}
|
||||
{{^useOneOfDiscriminatorLookup}}
|
||||
match := 0
|
||||
{{#oneOf}}
|
||||
// try to unmarshal data into {{#lambda.titlecase}}{{{.}}}{{/lambda.titlecase}}
|
||||
err = newStrictDecoder(data).Decode(&dst.{{#lambda.titlecase}}{{{.}}}{{/lambda.titlecase}})
|
||||
if err == nil {
|
||||
json{{#lambda.titlecase}}{{{.}}}{{/lambda.titlecase}}, _ := json.Marshal(dst.{{#lambda.titlecase}}{{{.}}}{{/lambda.titlecase}})
|
||||
if string(json{{#lambda.titlecase}}{{{.}}}{{/lambda.titlecase}}) == "{}" { // empty struct
|
||||
dst.{{#lambda.titlecase}}{{{.}}}{{/lambda.titlecase}} = nil
|
||||
} else {
|
||||
match++
|
||||
}
|
||||
} else {
|
||||
dst.{{#lambda.titlecase}}{{{.}}}{{/lambda.titlecase}} = nil
|
||||
}
|
||||
|
||||
{{/oneOf}}
|
||||
if match > 1 { // more than 1 match
|
||||
// reset to nil
|
||||
{{#oneOf}}
|
||||
dst.{{#lambda.titlecase}}{{{.}}}{{/lambda.titlecase}} = nil
|
||||
{{/oneOf}}
|
||||
|
||||
return fmt.Errorf("Data matches more than one schema in oneOf({{classname}})")
|
||||
} else if match == 1 {
|
||||
return nil // exactly one match
|
||||
} else { // no match
|
||||
return fmt.Errorf("Data failed to match schemas in oneOf({{classname}})")
|
||||
}
|
||||
{{/useOneOfDiscriminatorLookup}}
|
||||
}
|
||||
|
||||
// Marshal data from the first non-nil pointers in the struct to JSON
|
||||
func (src {{classname}}) MarshalJSON() ([]byte, error) {
|
||||
{{#oneOf}}
|
||||
if src.{{#lambda.titlecase}}{{{.}}}{{/lambda.titlecase}} != nil {
|
||||
return json.Marshal(&src.{{#lambda.titlecase}}{{{.}}}{{/lambda.titlecase}})
|
||||
}
|
||||
|
||||
{{/oneOf}}
|
||||
return nil, nil // no data in oneOf schemas
|
||||
}
|
||||
|
||||
// Get the actual instance
|
||||
func (obj *{{classname}}) GetActualInstance() (interface{}) {
|
||||
if obj == nil {
|
||||
return nil
|
||||
}
|
||||
{{#oneOf}}
|
||||
if obj.{{#lambda.titlecase}}{{{.}}}{{/lambda.titlecase}} != nil {
|
||||
return obj.{{#lambda.titlecase}}{{{.}}}{{/lambda.titlecase}}
|
||||
}
|
||||
|
||||
{{/oneOf}}
|
||||
// all schemas are nil
|
||||
return nil
|
||||
}
|
||||
|
||||
{{>nullable_model}}
|
||||
391
.schema/openapi/templates/go/model_simple.mustache
Normal file
391
.schema/openapi/templates/go/model_simple.mustache
Normal file
@@ -0,0 +1,391 @@
|
||||
// {{classname}}{{#description}} {{{description}}}{{/description}}{{^description}} struct for {{{classname}}}{{/description}}
|
||||
type {{classname}} struct {
|
||||
{{#parent}}
|
||||
{{^isMap}}
|
||||
{{^isArray}}
|
||||
{{{parent}}}
|
||||
{{/isArray}}
|
||||
{{/isMap}}
|
||||
{{#isArray}}
|
||||
Items {{{parent}}}
|
||||
{{/isArray}}
|
||||
{{/parent}}
|
||||
{{#vars}}
|
||||
{{^-first}}
|
||||
{{/-first}}
|
||||
{{#description}}
|
||||
// {{{description}}}
|
||||
{{/description}}
|
||||
{{name}} {{^required}}{{^isNullable}}{{^isArray}}{{^isFreeFormObject}}*{{/isFreeFormObject}}{{/isArray}}{{/isNullable}}{{/required}}{{{dataType}}} `json:"{{baseName}}{{^required}},omitempty{{/required}}"{{#withXml}} xml:"{{baseName}}{{#isXmlAttribute}},attr{{/isXmlAttribute}}"{{/withXml}}{{#vendorExtensions.x-go-custom-tag}} {{{.}}}{{/vendorExtensions.x-go-custom-tag}}`
|
||||
{{/vars}}
|
||||
{{#isAdditionalPropertiesTrue}}
|
||||
AdditionalProperties map[string]interface{}
|
||||
{{/isAdditionalPropertiesTrue}}
|
||||
}
|
||||
|
||||
{{#isAdditionalPropertiesTrue}}
|
||||
type _{{{classname}}} {{{classname}}}
|
||||
|
||||
{{/isAdditionalPropertiesTrue}}
|
||||
// New{{classname}} instantiates a new {{classname}} object
|
||||
// This constructor will assign default values to properties that have it defined,
|
||||
// and makes sure properties required by API are set, but the set of arguments
|
||||
// will change when the set of required properties is changed
|
||||
func New{{classname}}({{#vars}}{{#required}}{{nameInCamelCase}} {{dataType}}, {{/required}}{{/vars}}) *{{classname}} {
|
||||
this := {{classname}}{}
|
||||
{{#vars}}
|
||||
{{#required}}
|
||||
this.{{name}} = {{nameInCamelCase}}
|
||||
{{/required}}
|
||||
{{^required}}
|
||||
{{#defaultValue}}
|
||||
{{^vendorExtensions.x-golang-is-container}}
|
||||
{{#isNullable}}
|
||||
var {{nameInCamelCase}} {{{datatypeWithEnum}}} = {{{.}}}
|
||||
this.{{name}} = *New{{{dataType}}}(&{{nameInCamelCase}})
|
||||
{{/isNullable}}
|
||||
{{^isNullable}}
|
||||
var {{nameInCamelCase}} {{{dataType}}} = {{{.}}}
|
||||
this.{{name}} = &{{nameInCamelCase}}
|
||||
{{/isNullable}}
|
||||
{{/vendorExtensions.x-golang-is-container}}
|
||||
{{/defaultValue}}
|
||||
{{/required}}
|
||||
{{/vars}}
|
||||
return &this
|
||||
}
|
||||
|
||||
// New{{classname}}WithDefaults instantiates a new {{classname}} object
|
||||
// This constructor will only assign default values to properties that have it defined,
|
||||
// but it doesn't guarantee that properties required by API are set
|
||||
func New{{classname}}WithDefaults() *{{classname}} {
|
||||
this := {{classname}}{}
|
||||
{{#vars}}
|
||||
{{#defaultValue}}
|
||||
{{^vendorExtensions.x-golang-is-container}}
|
||||
{{#isNullable}}
|
||||
{{!we use datatypeWithEnum here, since it will represent the non-nullable name of the datatype, e.g. int64 for NullableInt64}}
|
||||
var {{nameInCamelCase}} {{{datatypeWithEnum}}} = {{{.}}}
|
||||
this.{{name}} = *New{{{dataType}}}(&{{nameInCamelCase}})
|
||||
{{/isNullable}}
|
||||
{{^isNullable}}
|
||||
var {{nameInCamelCase}} {{{dataType}}} = {{{.}}}
|
||||
this.{{name}} = {{^required}}&{{/required}}{{nameInCamelCase}}
|
||||
{{/isNullable}}
|
||||
{{/vendorExtensions.x-golang-is-container}}
|
||||
{{/defaultValue}}
|
||||
{{/vars}}
|
||||
return &this
|
||||
}
|
||||
|
||||
{{#vars}}
|
||||
{{#required}}
|
||||
// Get{{name}} returns the {{name}} field value
|
||||
{{#isNullable}}
|
||||
// If the value is explicit nil, the zero value for {{vendorExtensions.x-go-base-type}} will be returned
|
||||
{{/isNullable}}
|
||||
func (o *{{classname}}) Get{{name}}() {{vendorExtensions.x-go-base-type}} {
|
||||
if o == nil {{#isNullable}}{{^vendorExtensions.x-golang-is-container}}|| o.{{name}}.Get() == nil{{/vendorExtensions.x-golang-is-container}}{{/isNullable}} {
|
||||
var ret {{vendorExtensions.x-go-base-type}}
|
||||
return ret
|
||||
}
|
||||
|
||||
{{#isNullable}}
|
||||
{{#vendorExtensions.x-golang-is-container}}
|
||||
return o.{{name}}
|
||||
{{/vendorExtensions.x-golang-is-container}}
|
||||
{{^vendorExtensions.x-golang-is-container}}
|
||||
return *o.{{name}}.Get()
|
||||
{{/vendorExtensions.x-golang-is-container}}
|
||||
{{/isNullable}}
|
||||
{{^isNullable}}
|
||||
return o.{{name}}
|
||||
{{/isNullable}}
|
||||
}
|
||||
|
||||
// Get{{name}}Ok returns a tuple with the {{name}} field value
|
||||
// and a boolean to check if the value has been set.
|
||||
{{#isNullable}}
|
||||
// NOTE: If the value is an explicit nil, `nil, true` will be returned
|
||||
{{/isNullable}}
|
||||
func (o *{{classname}}) Get{{name}}Ok() ({{^isArray}}{{^isFreeFormObject}}*{{/isFreeFormObject}}{{/isArray}}{{vendorExtensions.x-go-base-type}}, bool) {
|
||||
if o == nil {{#isNullable}}{{#vendorExtensions.x-golang-is-container}}|| o.{{name}} == nil{{/vendorExtensions.x-golang-is-container}}{{/isNullable}} {
|
||||
return nil, false
|
||||
}
|
||||
{{#isNullable}}
|
||||
{{#vendorExtensions.x-golang-is-container}}
|
||||
return {{^isArray}}{{^isFreeFormObject}}&{{/isFreeFormObject}}{{/isArray}}o.{{name}}, true
|
||||
{{/vendorExtensions.x-golang-is-container}}
|
||||
{{^vendorExtensions.x-golang-is-container}}
|
||||
return o.{{name}}.Get(), o.{{name}}.IsSet()
|
||||
{{/vendorExtensions.x-golang-is-container}}
|
||||
{{/isNullable}}
|
||||
{{^isNullable}}
|
||||
return {{^isArray}}{{^isFreeFormObject}}&{{/isFreeFormObject}}{{/isArray}}o.{{name}}, true
|
||||
{{/isNullable}}
|
||||
}
|
||||
|
||||
// Set{{name}} sets field value
|
||||
func (o *{{classname}}) Set{{name}}(v {{vendorExtensions.x-go-base-type}}) {
|
||||
{{#isNullable}}
|
||||
{{#vendorExtensions.x-golang-is-container}}
|
||||
o.{{name}} = v
|
||||
{{/vendorExtensions.x-golang-is-container}}
|
||||
{{^vendorExtensions.x-golang-is-container}}
|
||||
o.{{name}}.Set(&v)
|
||||
{{/vendorExtensions.x-golang-is-container}}
|
||||
{{/isNullable}}
|
||||
{{^isNullable}}
|
||||
o.{{name}} = v
|
||||
{{/isNullable}}
|
||||
}
|
||||
|
||||
{{/required}}
|
||||
{{^required}}
|
||||
// Get{{name}} returns the {{name}} field value if set, zero value otherwise{{#isNullable}} (both if not set or set to explicit null){{/isNullable}}.
|
||||
func (o *{{classname}}) Get{{name}}() {{vendorExtensions.x-go-base-type}} {
|
||||
if o == nil {{^isNullable}}|| o.{{name}} == nil{{/isNullable}}{{#isNullable}}{{^vendorExtensions.x-golang-is-container}}|| o.{{name}}.Get() == nil{{/vendorExtensions.x-golang-is-container}}{{/isNullable}} {
|
||||
var ret {{vendorExtensions.x-go-base-type}}
|
||||
return ret
|
||||
}
|
||||
{{#isNullable}}
|
||||
{{#vendorExtensions.x-golang-is-container}}
|
||||
return o.{{name}}
|
||||
{{/vendorExtensions.x-golang-is-container}}
|
||||
{{^vendorExtensions.x-golang-is-container}}
|
||||
return *o.{{name}}.Get()
|
||||
{{/vendorExtensions.x-golang-is-container}}
|
||||
{{/isNullable}}
|
||||
{{^isNullable}}
|
||||
return {{^isArray}}{{^isFreeFormObject}}*{{/isFreeFormObject}}{{/isArray}}o.{{name}}
|
||||
{{/isNullable}}
|
||||
}
|
||||
|
||||
// Get{{name}}Ok returns a tuple with the {{name}} field value if set, nil otherwise
|
||||
// and a boolean to check if the value has been set.
|
||||
{{#isNullable}}
|
||||
// NOTE: If the value is an explicit nil, `nil, true` will be returned
|
||||
{{/isNullable}}
|
||||
func (o *{{classname}}) Get{{name}}Ok() ({{^isArray}}{{^isFreeFormObject}}*{{/isFreeFormObject}}{{/isArray}}{{vendorExtensions.x-go-base-type}}, bool) {
|
||||
if o == nil {{^isNullable}}|| o.{{name}} == nil{{/isNullable}}{{#isNullable}}{{#vendorExtensions.x-golang-is-container}}|| o.{{name}} == nil{{/vendorExtensions.x-golang-is-container}}{{/isNullable}} {
|
||||
return nil, false
|
||||
}
|
||||
{{#isNullable}}
|
||||
{{#vendorExtensions.x-golang-is-container}}
|
||||
return {{^isArray}}{{^isFreeFormObject}}&{{/isFreeFormObject}}{{/isArray}}o.{{name}}, true
|
||||
{{/vendorExtensions.x-golang-is-container}}
|
||||
{{^vendorExtensions.x-golang-is-container}}
|
||||
return o.{{name}}.Get(), o.{{name}}.IsSet()
|
||||
{{/vendorExtensions.x-golang-is-container}}
|
||||
{{/isNullable}}
|
||||
{{^isNullable}}
|
||||
return o.{{name}}, true
|
||||
{{/isNullable}}
|
||||
}
|
||||
|
||||
// Has{{name}} returns a boolean if a field has been set.
|
||||
func (o *{{classname}}) Has{{name}}() bool {
|
||||
if o != nil && {{^isNullable}}o.{{name}} != nil{{/isNullable}}{{#isNullable}}{{#vendorExtensions.x-golang-is-container}}o.{{name}} != nil{{/vendorExtensions.x-golang-is-container}}{{^vendorExtensions.x-golang-is-container}}o.{{name}}.IsSet(){{/vendorExtensions.x-golang-is-container}}{{/isNullable}} {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// Set{{name}} gets a reference to the given {{dataType}} and assigns it to the {{name}} field.
|
||||
func (o *{{classname}}) Set{{name}}(v {{vendorExtensions.x-go-base-type}}) {
|
||||
{{#isNullable}}
|
||||
{{#vendorExtensions.x-golang-is-container}}
|
||||
o.{{name}} = v
|
||||
{{/vendorExtensions.x-golang-is-container}}
|
||||
{{^vendorExtensions.x-golang-is-container}}
|
||||
o.{{name}}.Set({{^isArray}}{{^isFreeFormObject}}&{{/isFreeFormObject}}{{/isArray}}v)
|
||||
{{/vendorExtensions.x-golang-is-container}}
|
||||
{{/isNullable}}
|
||||
{{^isNullable}}
|
||||
o.{{name}} = {{^isArray}}{{^isFreeFormObject}}&{{/isFreeFormObject}}{{/isArray}}v
|
||||
{{/isNullable}}
|
||||
}
|
||||
{{#isNullable}}
|
||||
{{^vendorExtensions.x-golang-is-container}}
|
||||
// Set{{name}}Nil sets the value for {{name}} to be an explicit nil
|
||||
func (o *{{classname}}) Set{{name}}Nil() {
|
||||
o.{{name}}.Set(nil)
|
||||
}
|
||||
|
||||
// Unset{{name}} ensures that no value is present for {{name}}, not even an explicit nil
|
||||
func (o *{{classname}}) Unset{{name}}() {
|
||||
o.{{name}}.Unset()
|
||||
}
|
||||
{{/vendorExtensions.x-golang-is-container}}
|
||||
{{/isNullable}}
|
||||
|
||||
{{/required}}
|
||||
{{/vars}}
|
||||
func (o {{classname}}) MarshalJSON() ([]byte, error) {
|
||||
toSerialize := {{#isArray}}make([]interface{}, len(o.Items)){{/isArray}}{{^isArray}}map[string]interface{}{}{{/isArray}}
|
||||
{{#parent}}
|
||||
{{^isMap}}
|
||||
{{^isArray}}
|
||||
serialized{{parent}}, err{{parent}} := json.Marshal(o.{{parent}})
|
||||
if err{{parent}} != nil {
|
||||
return []byte{}, err{{parent}}
|
||||
}
|
||||
err{{parent}} = json.Unmarshal([]byte(serialized{{parent}}), &toSerialize)
|
||||
if err{{parent}} != nil {
|
||||
return []byte{}, err{{parent}}
|
||||
}
|
||||
{{/isArray}}
|
||||
{{/isMap}}
|
||||
{{#isArray}}
|
||||
for i, item := range o.Items {
|
||||
toSerialize[i] = item
|
||||
}
|
||||
{{/isArray}}
|
||||
{{/parent}}
|
||||
{{#vars}}
|
||||
{{! if argument is nullable, only serialize it if it is set}}
|
||||
{{#isNullable}}
|
||||
{{#vendorExtensions.x-golang-is-container}}
|
||||
{{! support for container fields is not ideal at this point because of lack of Nullable* types}}
|
||||
if o.{{name}} != nil {
|
||||
toSerialize["{{baseName}}"] = o.{{name}}
|
||||
}
|
||||
{{/vendorExtensions.x-golang-is-container}}
|
||||
{{^vendorExtensions.x-golang-is-container}}
|
||||
if {{#required}}true{{/required}}{{^required}}o.{{name}}.IsSet(){{/required}} {
|
||||
toSerialize["{{baseName}}"] = o.{{name}}.Get()
|
||||
}
|
||||
{{/vendorExtensions.x-golang-is-container}}
|
||||
{{/isNullable}}
|
||||
{{! if argument is not nullable, don't set it if it is nil}}
|
||||
{{^isNullable}}
|
||||
if {{#required}}true{{/required}}{{^required}}o.{{name}} != nil{{/required}} {
|
||||
toSerialize["{{baseName}}"] = o.{{name}}
|
||||
}
|
||||
{{/isNullable}}
|
||||
{{/vars}}
|
||||
{{#isAdditionalPropertiesTrue}}
|
||||
|
||||
for key, value := range o.AdditionalProperties {
|
||||
toSerialize[key] = value
|
||||
}
|
||||
|
||||
{{/isAdditionalPropertiesTrue}}
|
||||
return json.Marshal(toSerialize)
|
||||
}
|
||||
|
||||
{{#isAdditionalPropertiesTrue}}
|
||||
func (o *{{{classname}}}) UnmarshalJSON(bytes []byte) (err error) {
|
||||
{{#parent}}
|
||||
{{^isMap}}
|
||||
type {{classname}}WithoutEmbeddedStruct struct {
|
||||
{{#vars}}
|
||||
{{^-first}}
|
||||
{{/-first}}
|
||||
{{#description}}
|
||||
// {{{description}}}
|
||||
{{/description}}
|
||||
{{name}} {{^required}}{{^isNullable}}*{{/isNullable}}{{/required}}{{{dataType}}} `json:"{{baseName}}{{^required}},omitempty{{/required}}"{{#withXml}} xml:"{{baseName}}{{#isXmlAttribute}},attr{{/isXmlAttribute}}"{{/withXml}}{{#vendorExtensions.x-go-custom-tag}} {{{.}}}{{/vendorExtensions.x-go-custom-tag}}`
|
||||
{{/vars}}
|
||||
}
|
||||
|
||||
var{{{classname}}}WithoutEmbeddedStruct := {{{classname}}}WithoutEmbeddedStruct{}
|
||||
|
||||
err = json.Unmarshal(bytes, &var{{{classname}}}WithoutEmbeddedStruct)
|
||||
if err == nil {
|
||||
var{{{classname}}} := _{{{classname}}}{}
|
||||
{{#vars}}
|
||||
var{{{classname}}}.{{{name}}} = var{{{classname}}}WithoutEmbeddedStruct.{{{name}}}
|
||||
{{/vars}}
|
||||
*o = {{{classname}}}(var{{{classname}}})
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
|
||||
var{{{classname}}} := _{{{classname}}}{}
|
||||
|
||||
err = json.Unmarshal(bytes, &var{{{classname}}})
|
||||
if err == nil {
|
||||
o.{{{parent}}} = var{{{classname}}}.{{{parent}}}
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
|
||||
additionalProperties := make(map[string]interface{})
|
||||
|
||||
if err = json.Unmarshal(bytes, &additionalProperties); err == nil {
|
||||
{{#vars}}
|
||||
delete(additionalProperties, "{{{baseName}}}")
|
||||
{{/vars}}
|
||||
|
||||
// remove fields from embedded structs
|
||||
reflect{{{parent}}} := reflect.ValueOf(o.{{{parent}}})
|
||||
for i := 0; i < reflect{{{parent}}}.Type().NumField(); i++ {
|
||||
t := reflect{{{parent}}}.Type().Field(i)
|
||||
|
||||
if jsonTag := t.Tag.Get("json"); jsonTag != "" {
|
||||
fieldName := ""
|
||||
if commaIdx := strings.Index(jsonTag, ","); commaIdx > 0 {
|
||||
fieldName = jsonTag[:commaIdx]
|
||||
} else {
|
||||
fieldName = jsonTag
|
||||
}
|
||||
if fieldName != "AdditionalProperties" {
|
||||
delete(additionalProperties, fieldName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
o.AdditionalProperties = additionalProperties
|
||||
}
|
||||
|
||||
return err
|
||||
{{/isMap}}
|
||||
{{#isMap}}
|
||||
var{{{classname}}} := _{{{classname}}}{}
|
||||
|
||||
if err = json.Unmarshal(bytes, &var{{{classname}}}); err == nil {
|
||||
*o = {{{classname}}}(var{{{classname}}})
|
||||
}
|
||||
|
||||
additionalProperties := make(map[string]interface{})
|
||||
|
||||
if err = json.Unmarshal(bytes, &additionalProperties); err == nil {
|
||||
{{#vars}}
|
||||
delete(additionalProperties, "{{{baseName}}}")
|
||||
{{/vars}}
|
||||
o.AdditionalProperties = additionalProperties
|
||||
}
|
||||
|
||||
return err
|
||||
{{/isMap}}
|
||||
{{/parent}}
|
||||
{{^parent}}
|
||||
var{{{classname}}} := _{{{classname}}}{}
|
||||
|
||||
if err = json.Unmarshal(bytes, &var{{{classname}}}); err == nil {
|
||||
*o = {{{classname}}}(var{{{classname}}})
|
||||
}
|
||||
|
||||
additionalProperties := make(map[string]interface{})
|
||||
|
||||
if err = json.Unmarshal(bytes, &additionalProperties); err == nil {
|
||||
{{#vars}}
|
||||
delete(additionalProperties, "{{{baseName}}}")
|
||||
{{/vars}}
|
||||
o.AdditionalProperties = additionalProperties
|
||||
}
|
||||
|
||||
return err
|
||||
{{/parent}}
|
||||
}
|
||||
|
||||
{{/isAdditionalPropertiesTrue}}
|
||||
{{#isArray}}
|
||||
func (o *{{{classname}}}) UnmarshalJSON(bytes []byte) (err error) {
|
||||
return json.Unmarshal(bytes, &o.Items)
|
||||
}
|
||||
|
||||
{{/isArray}}
|
||||
{{>nullable_model}}
|
||||
35
.schema/openapi/templates/go/nullable_model.mustache
Normal file
35
.schema/openapi/templates/go/nullable_model.mustache
Normal file
@@ -0,0 +1,35 @@
|
||||
type Nullable{{{classname}}} struct {
|
||||
value {{^isArray}}{{^isFreeFormObject}}*{{/isFreeFormObject}}{{/isArray}}{{{classname}}}
|
||||
isSet bool
|
||||
}
|
||||
|
||||
func (v Nullable{{classname}}) Get() {{^isArray}}{{^isFreeFormObject}}*{{/isFreeFormObject}}{{/isArray}}{{classname}} {
|
||||
return v.value
|
||||
}
|
||||
|
||||
func (v *Nullable{{classname}}) Set(val {{^isArray}}{{^isFreeFormObject}}*{{/isFreeFormObject}}{{/isArray}}{{classname}}) {
|
||||
v.value = val
|
||||
v.isSet = true
|
||||
}
|
||||
|
||||
func (v Nullable{{classname}}) IsSet() bool {
|
||||
return v.isSet
|
||||
}
|
||||
|
||||
func (v *Nullable{{classname}}) Unset() {
|
||||
v.value = nil
|
||||
v.isSet = false
|
||||
}
|
||||
|
||||
func NewNullable{{classname}}(val {{^isArray}}{{^isFreeFormObject}}*{{/isFreeFormObject}}{{/isArray}}{{classname}}) *Nullable{{classname}} {
|
||||
return &Nullable{{classname}}{value: val, isSet: true}
|
||||
}
|
||||
|
||||
func (v Nullable{{{classname}}}) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(v.value)
|
||||
}
|
||||
|
||||
func (v *Nullable{{{classname}}}) UnmarshalJSON(src []byte) error {
|
||||
v.isSet = true
|
||||
return json.Unmarshal(src, &v.value)
|
||||
}
|
||||
1
.schema/openapi/templates/go/openapi.mustache
Normal file
1
.schema/openapi/templates/go/openapi.mustache
Normal file
@@ -0,0 +1 @@
|
||||
{{{openapi-yaml}}}
|
||||
18
.schema/openapi/templates/go/partial_header.mustache
Normal file
18
.schema/openapi/templates/go/partial_header.mustache
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
{{#appName}}
|
||||
* {{{appName}}}
|
||||
*
|
||||
{{/appName}}
|
||||
{{#appDescription}}
|
||||
* {{{appDescription}}}
|
||||
*
|
||||
{{/appDescription}}
|
||||
{{#version}}
|
||||
* API version: {{{version}}}
|
||||
{{/version}}
|
||||
{{#infoEmail}}
|
||||
* Contact: {{{infoEmail}}}
|
||||
{{/infoEmail}}
|
||||
*/
|
||||
|
||||
// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT.
|
||||
38
.schema/openapi/templates/go/response.mustache
Normal file
38
.schema/openapi/templates/go/response.mustache
Normal file
@@ -0,0 +1,38 @@
|
||||
{{>partial_header}}
|
||||
package {{packageName}}
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// APIResponse stores the API response returned by the server.
|
||||
type APIResponse struct {
|
||||
*http.Response `json:"-"`
|
||||
Message string `json:"message,omitempty"`
|
||||
// Operation is the name of the OpenAPI operation.
|
||||
Operation string `json:"operation,omitempty"`
|
||||
// RequestURL is the request URL. This value is always available, even if the
|
||||
// embedded *http.Response is nil.
|
||||
RequestURL string `json:"url,omitempty"`
|
||||
// Method is the HTTP method used for the request. This value is always
|
||||
// available, even if the embedded *http.Response is nil.
|
||||
Method string `json:"method,omitempty"`
|
||||
// Payload holds the contents of the response body (which may be nil or empty).
|
||||
// This is provided here as the raw response.Body() reader will have already
|
||||
// been drained.
|
||||
Payload []byte `json:"-"`
|
||||
}
|
||||
|
||||
// NewAPIResponse returns a new APIResonse object.
|
||||
func NewAPIResponse(r *http.Response) *APIResponse {
|
||||
|
||||
response := &APIResponse{Response: r}
|
||||
return response
|
||||
}
|
||||
|
||||
// NewAPIResponseWithError returns a new APIResponse object with the provided error message.
|
||||
func NewAPIResponseWithError(errorMessage string) *APIResponse {
|
||||
|
||||
response := &APIResponse{Message: errorMessage}
|
||||
return response
|
||||
}
|
||||
414
.schema/openapi/templates/go/signing.mustache
Normal file
414
.schema/openapi/templates/go/signing.mustache
Normal file
@@ -0,0 +1,414 @@
|
||||
{{>partial_header}}
|
||||
package {{packageName}}
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/ed25519"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/textproto"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
// Constants for HTTP signature parameters.
|
||||
// The '(request-target)' parameter concatenates the lowercased :method, an
|
||||
// ASCII space, and the :path pseudo-headers.
|
||||
HttpSignatureParameterRequestTarget string = "(request-target)"
|
||||
// The '(created)' parameter expresses when the signature was
|
||||
// created. The value MUST be a Unix timestamp integer value.
|
||||
HttpSignatureParameterCreated string = "(created)"
|
||||
// The '(expires)' parameter expresses when the signature ceases to
|
||||
// be valid. The value MUST be a Unix timestamp integer value.
|
||||
HttpSignatureParameterExpires string = "(expires)"
|
||||
)
|
||||
|
||||
const (
|
||||
// Constants for HTTP headers.
|
||||
// The 'Host' header, as defined in RFC 2616, section 14.23.
|
||||
HttpHeaderHost string = "Host"
|
||||
// The 'Date' header.
|
||||
HttpHeaderDate string = "Date"
|
||||
// The digest header, as defined in RFC 3230, section 4.3.2.
|
||||
HttpHeaderDigest string = "Digest"
|
||||
// The HTTP Authorization header, as defined in RFC 7235, section 4.2.
|
||||
HttpHeaderAuthorization string = "Authorization"
|
||||
)
|
||||
|
||||
const (
|
||||
// Specifies the Digital Signature Algorithm is derived from metadata
|
||||
// associated with 'keyId'. Supported DSA algorithms are RSASSA-PKCS1-v1_5,
|
||||
// RSASSA-PSS, and ECDSA.
|
||||
// The hash is SHA-512.
|
||||
// This is the default value.
|
||||
HttpSigningSchemeHs2019 string = "hs2019"
|
||||
// Use RSASSA-PKCS1-v1_5 with SHA-512 hash. Deprecated.
|
||||
HttpSigningSchemeRsaSha512 string = "rsa-sha512"
|
||||
// Use RSASSA-PKCS1-v1_5 with SHA-256 hash. Deprecated.
|
||||
HttpSigningSchemeRsaSha256 string = "rsa-sha256"
|
||||
|
||||
// RFC 8017 section 7.2
|
||||
// Calculate the message signature using RSASSA-PKCS1-V1_5-SIGN from RSA PKCS#1 v1.5.
|
||||
// PKCSV1_5 is deterministic. The same message and key will produce an identical
|
||||
// signature value each time.
|
||||
HttpSigningAlgorithmRsaPKCS1v15 string = "RSASSA-PKCS1-v1_5"
|
||||
// Calculate the message signature using probabilistic signature scheme RSASSA-PSS.
|
||||
// PSS is randomized and will produce a different signature value each time.
|
||||
HttpSigningAlgorithmRsaPSS string = "RSASSA-PSS"
|
||||
)
|
||||
|
||||
var supportedSigningSchemes = map[string]bool{
|
||||
HttpSigningSchemeHs2019: true,
|
||||
HttpSigningSchemeRsaSha512: true,
|
||||
HttpSigningSchemeRsaSha256: true,
|
||||
}
|
||||
|
||||
|
||||
// HttpSignatureAuth provides HTTP signature authentication to a request passed
|
||||
// via context using ContextHttpSignatureAuth.
|
||||
// An 'Authorization' header is calculated by creating a hash of select headers,
|
||||
// and optionally the body of the HTTP request, then signing the hash value using
|
||||
// a private key which is available to the client.
|
||||
//
|
||||
// SignedHeaders specifies the list of HTTP headers that are included when generating
|
||||
// the message signature.
|
||||
// The two special signature headers '(request-target)' and '(created)' SHOULD be
|
||||
// included in SignedHeaders.
|
||||
// The '(created)' header expresses when the signature was created.
|
||||
// The '(request-target)' header is a concatenation of the lowercased :method, an
|
||||
// ASCII space, and the :path pseudo-headers.
|
||||
//
|
||||
// For example, SignedHeaders can be set to:
|
||||
// (request-target) (created) date host digest
|
||||
//
|
||||
// When SignedHeaders is not specified, the client defaults to a single value, '(created)',
|
||||
// in the list of HTTP headers.
|
||||
// When SignedHeaders contains the 'Digest' value, the client performs the following operations:
|
||||
// 1. Calculate a digest of request body, as specified in RFC3230, section 4.3.2.
|
||||
// 2. Set the 'Digest' header in the request body.
|
||||
// 3. Include the 'Digest' header and value in the HTTP signature.
|
||||
type HttpSignatureAuth struct {
|
||||
KeyId string // A key identifier.
|
||||
PrivateKeyPath string // The path to the private key.
|
||||
Passphrase string // The passphrase to decrypt the private key, if the key is encrypted.
|
||||
SigningScheme string // The signature scheme, when signing HTTP requests. Supported value is 'hs2019'.
|
||||
// The signature algorithm, when signing HTTP requests.
|
||||
// Supported values are RSASSA-PKCS1-v1_5, RSASSA-PSS.
|
||||
SigningAlgorithm string
|
||||
SignedHeaders []string // A list of HTTP headers included when generating the signature for the message.
|
||||
// SignatureMaxValidity specifies the maximum duration of the signature validity.
|
||||
// The value is used to set the '(expires)' signature parameter in the HTTP request.
|
||||
// '(expires)' is set to '(created)' plus the value of the SignatureMaxValidity field.
|
||||
// To specify the '(expires)' signature parameter, set 'SignatureMaxValidity' and add '(expires)' to 'SignedHeaders'.
|
||||
SignatureMaxValidity time.Duration
|
||||
privateKey crypto.PrivateKey // The private key used to sign HTTP requests.
|
||||
}
|
||||
|
||||
// ContextWithValue validates the HttpSignatureAuth configuration parameters and returns a context
|
||||
// suitable for HTTP signature. An error is returned if the HttpSignatureAuth configuration parameters
|
||||
// are invalid.
|
||||
func (h *HttpSignatureAuth) ContextWithValue(ctx context.Context) (context.Context, error) {
|
||||
if h.KeyId == "" {
|
||||
return nil, fmt.Errorf("Key ID must be specified")
|
||||
}
|
||||
if h.PrivateKeyPath == "" {
|
||||
return nil, fmt.Errorf("Private key path must be specified")
|
||||
}
|
||||
if _, ok := supportedSigningSchemes[h.SigningScheme]; !ok {
|
||||
return nil, fmt.Errorf("Invalid signing scheme: '%v'", h.SigningScheme)
|
||||
}
|
||||
m := make(map[string]bool)
|
||||
for _, h := range h.SignedHeaders {
|
||||
if strings.ToLower(h) == strings.ToLower(HttpHeaderAuthorization) {
|
||||
return nil, fmt.Errorf("Signed headers cannot include the 'Authorization' header")
|
||||
}
|
||||
m[h] = true
|
||||
}
|
||||
if len(m) != len(h.SignedHeaders) {
|
||||
return nil, fmt.Errorf("List of signed headers cannot have duplicate names")
|
||||
}
|
||||
if h.SignatureMaxValidity < 0 {
|
||||
return nil, fmt.Errorf("Signature max validity must be a positive value")
|
||||
}
|
||||
if err := h.loadPrivateKey(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return context.WithValue(ctx, ContextHttpSignatureAuth, *h), nil
|
||||
}
|
||||
|
||||
// GetPublicKey returns the public key associated with this HTTP signature configuration.
|
||||
func (h *HttpSignatureAuth) GetPublicKey() (crypto.PublicKey, error) {
|
||||
if h.privateKey == nil {
|
||||
if err := h.loadPrivateKey(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
switch key := h.privateKey.(type) {
|
||||
case *rsa.PrivateKey:
|
||||
return key.Public(), nil
|
||||
case *ecdsa.PrivateKey:
|
||||
return key.Public(), nil
|
||||
default:
|
||||
// Do not change '%T' to anything else such as '%v'!
|
||||
// The value of the private key must not be returned.
|
||||
return nil, fmt.Errorf("Unsupported key: %T", h.privateKey)
|
||||
}
|
||||
}
|
||||
|
||||
// loadPrivateKey reads the private key from the file specified in the HttpSignatureAuth.
|
||||
func (h *HttpSignatureAuth) loadPrivateKey() (err error) {
|
||||
var file *os.File
|
||||
file, err = os.Open(h.PrivateKeyPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Cannot load private key '%s'. Error: %v", h.PrivateKeyPath, err)
|
||||
}
|
||||
defer func() {
|
||||
err = file.Close()
|
||||
}()
|
||||
var priv []byte
|
||||
priv, err = io.ReadAll(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pemBlock, _ := pem.Decode(priv)
|
||||
if pemBlock == nil {
|
||||
// No PEM data has been found.
|
||||
return fmt.Errorf("File '%s' does not contain PEM data", h.PrivateKeyPath)
|
||||
}
|
||||
var privKey []byte
|
||||
if x509.IsEncryptedPEMBlock(pemBlock) {
|
||||
// The PEM data is encrypted.
|
||||
privKey, err = x509.DecryptPEMBlock(pemBlock, []byte(h.Passphrase))
|
||||
if err != nil {
|
||||
// Failed to decrypt PEM block. Because of deficiencies in the encrypted-PEM format,
|
||||
// it's not always possibleto detect an incorrect password.
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
privKey = pemBlock.Bytes
|
||||
}
|
||||
switch pemBlock.Type {
|
||||
case "RSA PRIVATE KEY":
|
||||
if h.privateKey, err = x509.ParsePKCS1PrivateKey(privKey); err != nil {
|
||||
return err
|
||||
}
|
||||
case "EC PRIVATE KEY", "PRIVATE KEY":
|
||||
// https://tools.ietf.org/html/rfc5915 section 4.
|
||||
if h.privateKey, err = x509.ParsePKCS8PrivateKey(privKey); err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("Key '%s' is not supported", pemBlock.Type)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SignRequest signs the request using HTTP signature.
|
||||
// See https://datatracker.ietf.org/doc/draft-cavage-http-signatures/
|
||||
//
|
||||
// Do not add, remove or change headers that are included in the SignedHeaders
|
||||
// after SignRequest has been invoked; this is because the header values are
|
||||
// included in the signature. Any subsequent alteration will cause a signature
|
||||
// verification failure.
|
||||
// If there are multiple instances of the same header field, all
|
||||
// header field values associated with the header field MUST be
|
||||
// concatenated, separated by a ASCII comma and an ASCII space
|
||||
// ', ', and used in the order in which they will appear in the
|
||||
// transmitted HTTP message.
|
||||
func SignRequest(
|
||||
ctx context.Context,
|
||||
r *http.Request,
|
||||
auth HttpSignatureAuth) error {
|
||||
|
||||
if auth.privateKey == nil {
|
||||
return fmt.Errorf("Private key is not set")
|
||||
}
|
||||
now := time.Now()
|
||||
date := now.UTC().Format(http.TimeFormat)
|
||||
// The 'created' field expresses when the signature was created.
|
||||
// The value MUST be a Unix timestamp integer value. See 'HTTP signature' section 2.1.4.
|
||||
created := now.Unix()
|
||||
|
||||
var h crypto.Hash
|
||||
var err error
|
||||
var prefix string
|
||||
var expiresUnix float64
|
||||
|
||||
if auth.SignatureMaxValidity < 0 {
|
||||
return fmt.Errorf("Signature validity must be a positive value")
|
||||
}
|
||||
if auth.SignatureMaxValidity > 0 {
|
||||
e := now.Add(auth.SignatureMaxValidity)
|
||||
expiresUnix = float64(e.Unix()) + float64(e.Nanosecond()) / float64(time.Second)
|
||||
}
|
||||
// Determine the cryptographic hash to be used for the signature and the body digest.
|
||||
switch auth.SigningScheme {
|
||||
case HttpSigningSchemeRsaSha512, HttpSigningSchemeHs2019:
|
||||
h = crypto.SHA512
|
||||
prefix = "SHA-512="
|
||||
case HttpSigningSchemeRsaSha256:
|
||||
// This is deprecated and should no longer be used.
|
||||
h = crypto.SHA256
|
||||
prefix = "SHA-256="
|
||||
default:
|
||||
return fmt.Errorf("Unsupported signature scheme: %v", auth.SigningScheme)
|
||||
}
|
||||
if !h.Available() {
|
||||
return fmt.Errorf("Hash '%v' is not available", h)
|
||||
}
|
||||
|
||||
// Build the "(request-target)" signature header.
|
||||
var sb bytes.Buffer
|
||||
fmt.Fprintf(&sb, "%s %s", strings.ToLower(r.Method), r.URL.EscapedPath())
|
||||
if r.URL.RawQuery != "" {
|
||||
// The ":path" pseudo-header field includes the path and query parts
|
||||
// of the target URI (the "path-absolute" production and optionally a
|
||||
// '?' character followed by the "query" production (see Sections 3.3
|
||||
// and 3.4 of [RFC3986]
|
||||
fmt.Fprintf(&sb, "?%s", r.URL.RawQuery)
|
||||
}
|
||||
requestTarget := sb.String()
|
||||
sb.Reset()
|
||||
|
||||
// Build the string to be signed.
|
||||
signedHeaders := auth.SignedHeaders
|
||||
if len(signedHeaders) == 0 {
|
||||
signedHeaders = []string{HttpSignatureParameterCreated}
|
||||
}
|
||||
// Validate the list of signed headers has no duplicates.
|
||||
m := make(map[string]bool)
|
||||
for _, h := range signedHeaders {
|
||||
m[h] = true
|
||||
}
|
||||
if len(m) != len(signedHeaders) {
|
||||
return fmt.Errorf("List of signed headers must not have any duplicates")
|
||||
}
|
||||
hasCreatedParameter := false
|
||||
hasExpiresParameter := false
|
||||
for i, header := range signedHeaders {
|
||||
header = strings.ToLower(header)
|
||||
var value string
|
||||
switch header {
|
||||
case strings.ToLower(HttpHeaderAuthorization):
|
||||
return fmt.Errorf("Cannot include the 'Authorization' header as a signed header.")
|
||||
case HttpSignatureParameterRequestTarget:
|
||||
value = requestTarget
|
||||
case HttpSignatureParameterCreated:
|
||||
value = fmt.Sprintf("%d", created)
|
||||
hasCreatedParameter = true
|
||||
case HttpSignatureParameterExpires:
|
||||
if auth.SignatureMaxValidity.Nanoseconds() == 0 {
|
||||
return fmt.Errorf("Cannot set '(expires)' signature parameter. SignatureMaxValidity is not configured.")
|
||||
}
|
||||
value = fmt.Sprintf("%.3f", expiresUnix)
|
||||
hasExpiresParameter = true
|
||||
case "date":
|
||||
value = date
|
||||
r.Header.Set(HttpHeaderDate, date)
|
||||
case "digest":
|
||||
// Calculate the digest of the HTTP request body.
|
||||
// Calculate body digest per RFC 3230 section 4.3.2
|
||||
bodyHash := h.New()
|
||||
if r.Body != nil {
|
||||
// Make a copy of the body io.Reader so that we can read the body to calculate the hash,
|
||||
// then one more time when marshaling the request.
|
||||
var body io.Reader
|
||||
body, err = r.GetBody()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = io.Copy(bodyHash, body); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
d := bodyHash.Sum(nil)
|
||||
value = prefix + base64.StdEncoding.EncodeToString(d)
|
||||
r.Header.Set(HttpHeaderDigest, value)
|
||||
case "host":
|
||||
value = r.Host
|
||||
r.Header.Set(HttpHeaderHost, r.Host)
|
||||
default:
|
||||
var ok bool
|
||||
var v []string
|
||||
canonicalHeader := textproto.CanonicalMIMEHeaderKey(header)
|
||||
if v, ok = r.Header[canonicalHeader]; !ok {
|
||||
// If a header specified in the headers parameter cannot be matched with
|
||||
// a provided header in the message, the implementation MUST produce an error.
|
||||
return fmt.Errorf("Header '%s' does not exist in the request", canonicalHeader)
|
||||
}
|
||||
// If there are multiple instances of the same header field, all
|
||||
// header field values associated with the header field MUST be
|
||||
// concatenated, separated by a ASCII comma and an ASCII space
|
||||
// `, `, and used in the order in which they will appear in the
|
||||
// transmitted HTTP message.
|
||||
value = strings.Join(v, ", ")
|
||||
}
|
||||
if i > 0 {
|
||||
fmt.Fprintf(&sb, "\n")
|
||||
}
|
||||
fmt.Fprintf(&sb, "%s: %s", header, value)
|
||||
}
|
||||
if expiresUnix != 0 && !hasExpiresParameter {
|
||||
return fmt.Errorf("SignatureMaxValidity is specified, but '(expired)' parameter is not present")
|
||||
}
|
||||
msg := []byte(sb.String())
|
||||
msgHash := h.New()
|
||||
if _, err = msgHash.Write(msg); err != nil {
|
||||
return err
|
||||
}
|
||||
d := msgHash.Sum(nil)
|
||||
|
||||
var signature []byte
|
||||
switch key := auth.privateKey.(type) {
|
||||
case *rsa.PrivateKey:
|
||||
switch auth.SigningAlgorithm {
|
||||
case HttpSigningAlgorithmRsaPKCS1v15:
|
||||
signature, err = rsa.SignPKCS1v15(rand.Reader, key, h, d)
|
||||
case "", HttpSigningAlgorithmRsaPSS:
|
||||
signature, err = rsa.SignPSS(rand.Reader, key, h, d, nil)
|
||||
default:
|
||||
return fmt.Errorf("Unsupported signing algorithm: '%s'", auth.SigningAlgorithm)
|
||||
}
|
||||
case *ecdsa.PrivateKey:
|
||||
signature, err = key.Sign(rand.Reader, d, h)
|
||||
case ed25519.PrivateKey: // requires go 1.13
|
||||
signature, err = key.Sign(rand.Reader, msg, crypto.Hash(0))
|
||||
default:
|
||||
return fmt.Errorf("Unsupported private key")
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sb.Reset()
|
||||
for i, header := range signedHeaders {
|
||||
if i > 0 {
|
||||
sb.WriteRune(' ')
|
||||
}
|
||||
sb.WriteString(strings.ToLower(header))
|
||||
}
|
||||
headers_list := sb.String()
|
||||
sb.Reset()
|
||||
fmt.Fprintf(&sb, `Signature keyId="%s",algorithm="%s",`, auth.KeyId, auth.SigningScheme)
|
||||
if hasCreatedParameter {
|
||||
fmt.Fprintf(&sb, "created=%d,", created)
|
||||
}
|
||||
if hasExpiresParameter {
|
||||
fmt.Fprintf(&sb, "expires=%.3f,", expiresUnix)
|
||||
}
|
||||
fmt.Fprintf(&sb, `headers="%s",signature="%s"`, headers_list, base64.StdEncoding.EncodeToString(signature))
|
||||
authStr := sb.String()
|
||||
r.Header.Set(HttpHeaderAuthorization, authStr)
|
||||
return nil
|
||||
}
|
||||
326
.schema/openapi/templates/go/utils.mustache
Normal file
326
.schema/openapi/templates/go/utils.mustache
Normal file
@@ -0,0 +1,326 @@
|
||||
{{>partial_header}}
|
||||
package {{packageName}}
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
)
|
||||
|
||||
// PtrBool is a helper routine that returns a pointer to given boolean value.
|
||||
func PtrBool(v bool) *bool { return &v }
|
||||
|
||||
// PtrInt is a helper routine that returns a pointer to given integer value.
|
||||
func PtrInt(v int) *int { return &v }
|
||||
|
||||
// PtrInt32 is a helper routine that returns a pointer to given integer value.
|
||||
func PtrInt32(v int32) *int32 { return &v }
|
||||
|
||||
// PtrInt64 is a helper routine that returns a pointer to given integer value.
|
||||
func PtrInt64(v int64) *int64 { return &v }
|
||||
|
||||
// PtrFloat32 is a helper routine that returns a pointer to given float value.
|
||||
func PtrFloat32(v float32) *float32 { return &v }
|
||||
|
||||
// PtrFloat64 is a helper routine that returns a pointer to given float value.
|
||||
func PtrFloat64(v float64) *float64 { return &v }
|
||||
|
||||
// PtrString is a helper routine that returns a pointer to given string value.
|
||||
func PtrString(v string) *string { return &v }
|
||||
|
||||
// PtrTime is helper routine that returns a pointer to given Time value.
|
||||
func PtrTime(v time.Time) *time.Time { return &v }
|
||||
|
||||
type NullableBool struct {
|
||||
value *bool
|
||||
isSet bool
|
||||
}
|
||||
|
||||
func (v NullableBool) Get() *bool {
|
||||
return v.value
|
||||
}
|
||||
|
||||
func (v *NullableBool) Set(val *bool) {
|
||||
v.value = val
|
||||
v.isSet = true
|
||||
}
|
||||
|
||||
func (v NullableBool) IsSet() bool {
|
||||
return v.isSet
|
||||
}
|
||||
|
||||
func (v *NullableBool) Unset() {
|
||||
v.value = nil
|
||||
v.isSet = false
|
||||
}
|
||||
|
||||
func NewNullableBool(val *bool) *NullableBool {
|
||||
return &NullableBool{value: val, isSet: true}
|
||||
}
|
||||
|
||||
func (v NullableBool) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(v.value)
|
||||
}
|
||||
|
||||
func (v *NullableBool) UnmarshalJSON(src []byte) error {
|
||||
v.isSet = true
|
||||
return json.Unmarshal(src, &v.value)
|
||||
}
|
||||
|
||||
|
||||
type NullableInt struct {
|
||||
value *int
|
||||
isSet bool
|
||||
}
|
||||
|
||||
func (v NullableInt) Get() *int {
|
||||
return v.value
|
||||
}
|
||||
|
||||
func (v *NullableInt) Set(val *int) {
|
||||
v.value = val
|
||||
v.isSet = true
|
||||
}
|
||||
|
||||
func (v NullableInt) IsSet() bool {
|
||||
return v.isSet
|
||||
}
|
||||
|
||||
func (v *NullableInt) Unset() {
|
||||
v.value = nil
|
||||
v.isSet = false
|
||||
}
|
||||
|
||||
func NewNullableInt(val *int) *NullableInt {
|
||||
return &NullableInt{value: val, isSet: true}
|
||||
}
|
||||
|
||||
func (v NullableInt) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(v.value)
|
||||
}
|
||||
|
||||
func (v *NullableInt) UnmarshalJSON(src []byte) error {
|
||||
v.isSet = true
|
||||
return json.Unmarshal(src, &v.value)
|
||||
}
|
||||
|
||||
|
||||
type NullableInt32 struct {
|
||||
value *int32
|
||||
isSet bool
|
||||
}
|
||||
|
||||
func (v NullableInt32) Get() *int32 {
|
||||
return v.value
|
||||
}
|
||||
|
||||
func (v *NullableInt32) Set(val *int32) {
|
||||
v.value = val
|
||||
v.isSet = true
|
||||
}
|
||||
|
||||
func (v NullableInt32) IsSet() bool {
|
||||
return v.isSet
|
||||
}
|
||||
|
||||
func (v *NullableInt32) Unset() {
|
||||
v.value = nil
|
||||
v.isSet = false
|
||||
}
|
||||
|
||||
func NewNullableInt32(val *int32) *NullableInt32 {
|
||||
return &NullableInt32{value: val, isSet: true}
|
||||
}
|
||||
|
||||
func (v NullableInt32) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(v.value)
|
||||
}
|
||||
|
||||
func (v *NullableInt32) UnmarshalJSON(src []byte) error {
|
||||
v.isSet = true
|
||||
return json.Unmarshal(src, &v.value)
|
||||
}
|
||||
|
||||
|
||||
type NullableInt64 struct {
|
||||
value *int64
|
||||
isSet bool
|
||||
}
|
||||
|
||||
func (v NullableInt64) Get() *int64 {
|
||||
return v.value
|
||||
}
|
||||
|
||||
func (v *NullableInt64) Set(val *int64) {
|
||||
v.value = val
|
||||
v.isSet = true
|
||||
}
|
||||
|
||||
func (v NullableInt64) IsSet() bool {
|
||||
return v.isSet
|
||||
}
|
||||
|
||||
func (v *NullableInt64) Unset() {
|
||||
v.value = nil
|
||||
v.isSet = false
|
||||
}
|
||||
|
||||
func NewNullableInt64(val *int64) *NullableInt64 {
|
||||
return &NullableInt64{value: val, isSet: true}
|
||||
}
|
||||
|
||||
func (v NullableInt64) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(v.value)
|
||||
}
|
||||
|
||||
func (v *NullableInt64) UnmarshalJSON(src []byte) error {
|
||||
v.isSet = true
|
||||
return json.Unmarshal(src, &v.value)
|
||||
}
|
||||
|
||||
|
||||
type NullableFloat32 struct {
|
||||
value *float32
|
||||
isSet bool
|
||||
}
|
||||
|
||||
func (v NullableFloat32) Get() *float32 {
|
||||
return v.value
|
||||
}
|
||||
|
||||
func (v *NullableFloat32) Set(val *float32) {
|
||||
v.value = val
|
||||
v.isSet = true
|
||||
}
|
||||
|
||||
func (v NullableFloat32) IsSet() bool {
|
||||
return v.isSet
|
||||
}
|
||||
|
||||
func (v *NullableFloat32) Unset() {
|
||||
v.value = nil
|
||||
v.isSet = false
|
||||
}
|
||||
|
||||
func NewNullableFloat32(val *float32) *NullableFloat32 {
|
||||
return &NullableFloat32{value: val, isSet: true}
|
||||
}
|
||||
|
||||
func (v NullableFloat32) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(v.value)
|
||||
}
|
||||
|
||||
func (v *NullableFloat32) UnmarshalJSON(src []byte) error {
|
||||
v.isSet = true
|
||||
return json.Unmarshal(src, &v.value)
|
||||
}
|
||||
|
||||
|
||||
type NullableFloat64 struct {
|
||||
value *float64
|
||||
isSet bool
|
||||
}
|
||||
|
||||
func (v NullableFloat64) Get() *float64 {
|
||||
return v.value
|
||||
}
|
||||
|
||||
func (v *NullableFloat64) Set(val *float64) {
|
||||
v.value = val
|
||||
v.isSet = true
|
||||
}
|
||||
|
||||
func (v NullableFloat64) IsSet() bool {
|
||||
return v.isSet
|
||||
}
|
||||
|
||||
func (v *NullableFloat64) Unset() {
|
||||
v.value = nil
|
||||
v.isSet = false
|
||||
}
|
||||
|
||||
func NewNullableFloat64(val *float64) *NullableFloat64 {
|
||||
return &NullableFloat64{value: val, isSet: true}
|
||||
}
|
||||
|
||||
func (v NullableFloat64) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(v.value)
|
||||
}
|
||||
|
||||
func (v *NullableFloat64) UnmarshalJSON(src []byte) error {
|
||||
v.isSet = true
|
||||
return json.Unmarshal(src, &v.value)
|
||||
}
|
||||
|
||||
|
||||
type NullableString struct {
|
||||
value *string
|
||||
isSet bool
|
||||
}
|
||||
|
||||
func (v NullableString) Get() *string {
|
||||
return v.value
|
||||
}
|
||||
|
||||
func (v *NullableString) Set(val *string) {
|
||||
v.value = val
|
||||
v.isSet = true
|
||||
}
|
||||
|
||||
func (v NullableString) IsSet() bool {
|
||||
return v.isSet
|
||||
}
|
||||
|
||||
func (v *NullableString) Unset() {
|
||||
v.value = nil
|
||||
v.isSet = false
|
||||
}
|
||||
|
||||
func NewNullableString(val *string) *NullableString {
|
||||
return &NullableString{value: val, isSet: true}
|
||||
}
|
||||
|
||||
func (v NullableString) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(v.value)
|
||||
}
|
||||
|
||||
func (v *NullableString) UnmarshalJSON(src []byte) error {
|
||||
v.isSet = true
|
||||
return json.Unmarshal(src, &v.value)
|
||||
}
|
||||
|
||||
|
||||
type NullableTime struct {
|
||||
value *time.Time
|
||||
isSet bool
|
||||
}
|
||||
|
||||
func (v NullableTime) Get() *time.Time {
|
||||
return v.value
|
||||
}
|
||||
|
||||
func (v *NullableTime) Set(val *time.Time) {
|
||||
v.value = val
|
||||
v.isSet = true
|
||||
}
|
||||
|
||||
func (v NullableTime) IsSet() bool {
|
||||
return v.isSet
|
||||
}
|
||||
|
||||
func (v *NullableTime) Unset() {
|
||||
v.value = nil
|
||||
v.isSet = false
|
||||
}
|
||||
|
||||
func NewNullableTime(val *time.Time) *NullableTime {
|
||||
return &NullableTime{value: val, isSet: true}
|
||||
}
|
||||
|
||||
func (v NullableTime) MarshalJSON() ([]byte, error) {
|
||||
return v.value.MarshalJSON()
|
||||
}
|
||||
|
||||
func (v *NullableTime) UnmarshalJSON(src []byte) error {
|
||||
v.isSet = true
|
||||
return json.Unmarshal(src, &v.value)
|
||||
}
|
||||
67
.schema/relation_tuple.schema.json
Normal file
67
.schema/relation_tuple.schema.json
Normal file
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"allOf": [
|
||||
{
|
||||
"required": ["namespace", "relation", "object"],
|
||||
"properties": {
|
||||
"$schema": {
|
||||
"type": "string",
|
||||
"format": "uri-reference",
|
||||
"description": "Add this to allow defining the schema, useful for IDE integration"
|
||||
},
|
||||
"namespace": {
|
||||
"type": "string",
|
||||
"description": "The namespace of the object and relation in this tuple."
|
||||
},
|
||||
"object": {
|
||||
"type": "string",
|
||||
"description": "The object affected by this relation."
|
||||
},
|
||||
"relation": {
|
||||
"type": "string",
|
||||
"description": "The relation of the object and subject."
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"oneOf": [
|
||||
{
|
||||
"required": ["subject_id"],
|
||||
"properties": {
|
||||
"subject_id": {
|
||||
"type": "string",
|
||||
"description": "The subject ID affected by this relation."
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"required": ["subject_set"],
|
||||
"properties": {
|
||||
"subject_set": {
|
||||
"type": "object",
|
||||
"description": "The subject set affected by this relation.",
|
||||
"properties": {
|
||||
"namespace": {
|
||||
"type": "string",
|
||||
"description": "The namespace of the object and relation in this subject set."
|
||||
},
|
||||
"object": {
|
||||
"type": "string",
|
||||
"description": "The object referenced in this subject set."
|
||||
},
|
||||
"relation": {
|
||||
"type": "string",
|
||||
"description": "The relation of this subject set."
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": ["namespace", "relation", "object"]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
216
.schema/version.schema.json
Normal file
216
.schema/version.schema.json
Normal file
@@ -0,0 +1,216 @@
|
||||
{
|
||||
"$id": "https://github.com/ory/keto/.schema/versions.config.schema.json",
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"oneOf": [
|
||||
{
|
||||
"allOf": [
|
||||
{
|
||||
"properties": {
|
||||
"version": {
|
||||
"const": "v0.14.0"
|
||||
}
|
||||
},
|
||||
"required": ["version"]
|
||||
},
|
||||
{
|
||||
"$ref": "https://raw.githubusercontent.com/ory/keto/v0.14.0/.schema/config.schema.json"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"allOf": [
|
||||
{
|
||||
"properties": {
|
||||
"version": {
|
||||
"const": "v0.12.0-alpha.0"
|
||||
}
|
||||
},
|
||||
"required": ["version"]
|
||||
},
|
||||
{
|
||||
"$ref": "https://raw.githubusercontent.com/ory/keto/v0.12.0-alpha.0/.schema/config.schema.json"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"allOf": [
|
||||
{
|
||||
"properties": {
|
||||
"version": {
|
||||
"const": "v0.11.1-alpha.0"
|
||||
}
|
||||
},
|
||||
"required": ["version"]
|
||||
},
|
||||
{
|
||||
"$ref": "https://raw.githubusercontent.com/ory/keto/v0.11.1-alpha.0/.schema/config.schema.json"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"allOf": [
|
||||
{
|
||||
"properties": {
|
||||
"version": {
|
||||
"const": "v0.11.0-alpha.0"
|
||||
}
|
||||
},
|
||||
"required": ["version"]
|
||||
},
|
||||
{
|
||||
"$ref": "https://raw.githubusercontent.com/ory/keto/v0.11.0-alpha.0/.schema/config.schema.json"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"allOf": [
|
||||
{
|
||||
"properties": {
|
||||
"version": {
|
||||
"const": "v0.10.0-alpha.0"
|
||||
}
|
||||
},
|
||||
"required": ["version"]
|
||||
},
|
||||
{
|
||||
"$ref": "https://raw.githubusercontent.com/ory/keto/v0.10.0-alpha.0/.schema/config.schema.json"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"allOf": [
|
||||
{
|
||||
"properties": {
|
||||
"version": {
|
||||
"const": "v0.9.0-alpha.0"
|
||||
}
|
||||
},
|
||||
"required": ["version"]
|
||||
},
|
||||
{
|
||||
"$ref": "https://raw.githubusercontent.com/ory/keto/v0.9.0-alpha.0/.schema/config.schema.json"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"allOf": [
|
||||
{
|
||||
"properties": {
|
||||
"version": {
|
||||
"const": "v0.8.0-alpha.2"
|
||||
}
|
||||
},
|
||||
"required": ["version"]
|
||||
},
|
||||
{
|
||||
"$ref": "https://raw.githubusercontent.com/ory/keto/v0.8.0-alpha.2/.schema/config.schema.json"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"allOf": [
|
||||
{
|
||||
"properties": {
|
||||
"version": {
|
||||
"const": "v0.6.0-alpha.1"
|
||||
}
|
||||
},
|
||||
"required": ["version"]
|
||||
},
|
||||
{
|
||||
"$ref": "https://raw.githubusercontent.com/ory/keto/v0.6.0-alpha.1/internal/driver/config/config.schema.json"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"allOf": [
|
||||
{
|
||||
"properties": {
|
||||
"version": {
|
||||
"const": "v0.6.0-alpha.3"
|
||||
}
|
||||
},
|
||||
"required": ["version"]
|
||||
},
|
||||
{
|
||||
"$ref": "https://raw.githubusercontent.com/ory/keto/v0.6.0-alpha.3/internal/driver/config/config.schema.json"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"allOf": [
|
||||
{
|
||||
"properties": {
|
||||
"version": {
|
||||
"const": "v0.7.0-alpha.0"
|
||||
}
|
||||
},
|
||||
"required": ["version"]
|
||||
},
|
||||
{
|
||||
"$ref": "https://raw.githubusercontent.com/ory/keto/v0.7.0-alpha.0/.schema/config.schema.json"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"allOf": [
|
||||
{
|
||||
"properties": {
|
||||
"version": {
|
||||
"const": "v0.7.0-alpha.1"
|
||||
}
|
||||
},
|
||||
"required": ["version"]
|
||||
},
|
||||
{
|
||||
"$ref": "https://raw.githubusercontent.com/ory/keto/v0.7.0-alpha.1/.schema/config.schema.json"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"allOf": [
|
||||
{
|
||||
"properties": {
|
||||
"version": {
|
||||
"const": "v0.8.0-alpha.1"
|
||||
}
|
||||
},
|
||||
"required": ["version"]
|
||||
},
|
||||
{
|
||||
"$ref": "https://raw.githubusercontent.com/ory/keto/v0.8.0-alpha.1/.schema/config.schema.json"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"allOf": [
|
||||
{
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"version": {
|
||||
"type": "string",
|
||||
"maxLength": 0
|
||||
}
|
||||
},
|
||||
"required": ["version"]
|
||||
},
|
||||
{
|
||||
"not": {
|
||||
"properties": {
|
||||
"version": {}
|
||||
},
|
||||
"required": ["version"]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"$ref": "#/oneOf/0/allOf/1"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"title": "All Versions of the ORY Keto Configuration",
|
||||
"type": "object"
|
||||
}
|
||||
Reference in New Issue
Block a user