(Feat): Initial Commit
This commit is contained in:
22
api/README.md
Normal file
22
api/README.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# `/api`
|
||||
|
||||
OpenAPI/Swagger specs, JSON schema files, protocol definition files.
|
||||
|
||||
Use `make swagger` do generate `/internal/types/**/*.go` from these specs. You may use `make watch-swagger` while writing these schemas to automatically execute `make swagger` every time there are changes (especially useful if you have `http://localhost:8081/` opened in your browser while mutating these specs).
|
||||
|
||||
The final `/api/swagger.yml` is auto-generated from the following specs:
|
||||
1. The skeleton spec at `/api/config/main.yml`,
|
||||
2. all path specs living within `/api/paths/*.yml` and
|
||||
3. any `/api/definitions/*.yml` referenced by in step 1 and 2.
|
||||
|
||||
Further reading:
|
||||
* [Swagger v2 specification](https://swagger.io/specification/v2/)
|
||||
* [go-swagger](https://github.com/go-swagger/go-swagger)
|
||||
* [go-swagger: Schema Generation Rules](https://github.com/go-swagger/go-swagger/blob/master/docs/use/models/schemas.md)
|
||||
|
||||
|
||||
Related examples regarding this project layout:
|
||||
|
||||
* https://github.com/golang-standards/project-layout/blob/master/api/README.md
|
||||
* https://github.com/kubernetes/kubernetes/tree/master/api
|
||||
* https://github.com/moby/moby/tree/master/api
|
||||
16
api/config/go-swagger-config.yml
Normal file
16
api/config/go-swagger-config.yml
Normal file
@@ -0,0 +1,16 @@
|
||||
layout:
|
||||
models:
|
||||
- name: definition
|
||||
source: asset:model
|
||||
target: "{{ joinFilePath .Target .ModelPackage }}"
|
||||
file_name: "{{ (snakize (pascalize .Name)) }}.go"
|
||||
operations:
|
||||
- name: parameters
|
||||
source: asset:serverParameter
|
||||
target: "{{ joinFilePath .Target .ServerPackage .Package }}"
|
||||
file_name: "{{ (snakize (pascalize .Name)) }}_parameters.go"
|
||||
application:
|
||||
- name: builder
|
||||
source: asset:serverBuilder
|
||||
target: "{{ joinFilePath .Target .ServerPackage }}"
|
||||
file_name: "spec_handlers.go"
|
||||
37
api/config/main.yml
Normal file
37
api/config/main.yml
Normal file
@@ -0,0 +1,37 @@
|
||||
# This is our base swagger file and the primary mixin target.
|
||||
# Everything in definitions|paths/*.yml will be mixed through
|
||||
# and finally flattened into the actual swagger.yml in this dir.
|
||||
consumes:
|
||||
- application/json
|
||||
produces:
|
||||
- application/json
|
||||
swagger: "2.0"
|
||||
info:
|
||||
title: allaboutapps.dev/aw/go-starter
|
||||
version: 0.1.0
|
||||
description: API documentation
|
||||
paths: {}
|
||||
securityDefinitions:
|
||||
Bearer:
|
||||
type: apiKey
|
||||
name: Authorization
|
||||
in: header
|
||||
description: |-
|
||||
Access token for application access, **must** include "Bearer " prefix.
|
||||
Example: `Bearer b4a94a42-3ea2-4af3-9699-8bcbfee6e6d2`
|
||||
x-keyPrefix: "Bearer "
|
||||
Management:
|
||||
type: apiKey
|
||||
in: query
|
||||
description: Management secret, used for monitoring and infrastructure related calls
|
||||
name: mgmt-secret
|
||||
definitions:
|
||||
# Any definitions that are not yet used within paths/*.yml are automatically removed from the resulting swagger.yml.
|
||||
# You may reference some definitions that you *always* want to be included here.
|
||||
# --
|
||||
# Always include orderDir so we can test binding it to db queries directly.
|
||||
orderDir:
|
||||
type: string
|
||||
enum:
|
||||
- asc
|
||||
- desc
|
||||
122
api/config/swagger-ui-local-translator.js
Normal file
122
api/config/swagger-ui-local-translator.js
Normal file
@@ -0,0 +1,122 @@
|
||||
// https://github.com/swagger-api/swagger-ui/blob/master/docker/configurator/translator.js
|
||||
// Based on commit in 02758b8125dbf38763cfd5d4f91c7c803e9bd0ad
|
||||
// Nov 08, 2018
|
||||
// see "AAA change" for applied changes
|
||||
|
||||
// Converts an object of environment variables into a Swagger UI config object
|
||||
const configSchema = require("./variables")
|
||||
|
||||
const defaultBaseConfig = {
|
||||
url: {
|
||||
value: "https://petstore.swagger.io/v2/swagger.json",
|
||||
schema: {
|
||||
type: "string",
|
||||
base: true
|
||||
}
|
||||
},
|
||||
dom_id: {
|
||||
value: "#swagger-ui",
|
||||
schema: {
|
||||
type: "string",
|
||||
base: true
|
||||
}
|
||||
},
|
||||
deepLinking: {
|
||||
value: "true",
|
||||
schema: {
|
||||
type: "boolean",
|
||||
base: true
|
||||
}
|
||||
},
|
||||
presets: {
|
||||
value: `[\n SwaggerUIBundle.presets.apis,\n SwaggerUIStandalonePreset\n]`,
|
||||
schema: {
|
||||
type: "array",
|
||||
base: true
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
value: `[\n SwaggerUIBundle.plugins.DownloadUrl\n]`,
|
||||
schema: {
|
||||
type: "array",
|
||||
base: true
|
||||
}
|
||||
},
|
||||
layout: {
|
||||
value: "StandaloneLayout",
|
||||
schema: {
|
||||
type: "string",
|
||||
base: true
|
||||
}
|
||||
},
|
||||
// AAA change START: interspect requests to 8081 and instead pass them to 8080 where our server runs
|
||||
requestInterceptor: {
|
||||
value: `function (request) {
|
||||
request.url = request.url.split(":8081/").join(":8080/");
|
||||
console.log("[requestInterceptor] :8080", request);
|
||||
return request;
|
||||
}`,
|
||||
schema: {
|
||||
type: "function",
|
||||
base: true
|
||||
}
|
||||
}
|
||||
// AAA change END
|
||||
}
|
||||
|
||||
function objectToKeyValueString(env, { injectBaseConfig = false, schema = configSchema, baseConfig = defaultBaseConfig } = {}) {
|
||||
let valueStorage = injectBaseConfig ? Object.assign({}, baseConfig) : {}
|
||||
const keys = Object.keys(env)
|
||||
|
||||
// Compute an intermediate representation that holds candidate values and schemas.
|
||||
//
|
||||
// This is useful for deduping between multiple env keys that set the same
|
||||
// config variable.
|
||||
|
||||
keys.forEach(key => {
|
||||
const varSchema = schema[key]
|
||||
const value = env[key]
|
||||
|
||||
if (!varSchema) return
|
||||
|
||||
if (varSchema.onFound) {
|
||||
varSchema.onFound()
|
||||
}
|
||||
|
||||
const storageContents = valueStorage[varSchema.name]
|
||||
|
||||
if (storageContents) {
|
||||
if (varSchema.legacy === true && !storageContents.schema.base) {
|
||||
// If we're looking at a legacy var, it should lose out to any already-set value
|
||||
// except for base values
|
||||
return
|
||||
}
|
||||
delete valueStorage[varSchema.name]
|
||||
}
|
||||
|
||||
valueStorage[varSchema.name] = {
|
||||
value,
|
||||
schema: varSchema
|
||||
}
|
||||
})
|
||||
|
||||
// Compute a key:value string based on valueStorage's contents.
|
||||
|
||||
let result = ""
|
||||
|
||||
Object.keys(valueStorage).forEach(key => {
|
||||
const value = valueStorage[key]
|
||||
|
||||
const escapedName = /[^a-zA-Z0-9]/.test(key) ? `"${key}"` : key
|
||||
|
||||
if (value.schema.type === "string") {
|
||||
result += `${escapedName}: "${value.value}",\n`
|
||||
} else {
|
||||
result += `${escapedName}: ${value.value === "" ? `undefined` : value.value},\n`
|
||||
}
|
||||
})
|
||||
|
||||
return result.trim()
|
||||
}
|
||||
|
||||
module.exports = objectToKeyValueString
|
||||
195
api/definitions/auth.yml
Normal file
195
api/definitions/auth.yml
Normal file
@@ -0,0 +1,195 @@
|
||||
swagger: "2.0"
|
||||
info:
|
||||
title: allaboutapps.dev/aw/go-starter
|
||||
version: 0.1.0
|
||||
paths: {}
|
||||
definitions:
|
||||
User:
|
||||
type: object
|
||||
required:
|
||||
- id
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
format: uuid4
|
||||
description: ID of user
|
||||
example: 891d37d3-c74f-493e-aea8-af73efd92016
|
||||
GetUserInfoResponse:
|
||||
type: object
|
||||
required:
|
||||
- sub
|
||||
- updated_at
|
||||
properties:
|
||||
sub:
|
||||
type: string
|
||||
description: ID of user
|
||||
example: 82ebdfad-c586-4407-a873-4cc1c33d56fc
|
||||
updated_at:
|
||||
type: integer
|
||||
description: Unix timestamp the user's info was last updated at
|
||||
example: 1591960808
|
||||
email:
|
||||
type: string
|
||||
format: email
|
||||
description: Email address of user, if available
|
||||
maxLength: 255
|
||||
example: user@example.com
|
||||
scopes:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
enum:
|
||||
- "app"
|
||||
- "cms"
|
||||
description: Auth-Scopes of the user, if available
|
||||
example: ["app"]
|
||||
PostChangePasswordPayload:
|
||||
type: object
|
||||
required:
|
||||
- currentPassword
|
||||
- newPassword
|
||||
properties:
|
||||
currentPassword:
|
||||
description: Current password of user
|
||||
type: string
|
||||
maxLength: 500
|
||||
minLength: 1
|
||||
example: correct horse battery staple
|
||||
newPassword:
|
||||
description: New password to set for user
|
||||
type: string
|
||||
maxLength: 500
|
||||
minLength: 1
|
||||
example: correct horse battery staple
|
||||
PostForgotPasswordCompletePayload:
|
||||
type: object
|
||||
required:
|
||||
- token
|
||||
- password
|
||||
properties:
|
||||
password:
|
||||
description: New password to set for user
|
||||
type: string
|
||||
maxLength: 500
|
||||
minLength: 1
|
||||
example: correct horse battery staple
|
||||
token:
|
||||
description: Password reset token sent via email
|
||||
type: string
|
||||
format: uuid4
|
||||
example: ec16f032-3c44-4148-bbcc-45557466fa74
|
||||
PostForgotPasswordPayload:
|
||||
type: object
|
||||
required:
|
||||
- username
|
||||
properties:
|
||||
username:
|
||||
description: Username to initiate password reset for
|
||||
type: string
|
||||
format: email
|
||||
maxLength: 255
|
||||
minLength: 1
|
||||
example: user@example.com
|
||||
PostLoginPayload:
|
||||
type: object
|
||||
required:
|
||||
- username
|
||||
- password
|
||||
properties:
|
||||
password:
|
||||
description: Password of user to authenticate as
|
||||
type: string
|
||||
maxLength: 500
|
||||
minLength: 1
|
||||
example: correct horse battery staple
|
||||
username:
|
||||
description: Username of user to authenticate as
|
||||
type: string
|
||||
format: email
|
||||
maxLength: 255
|
||||
minLength: 1
|
||||
example: user@example.com
|
||||
PostLoginResponse:
|
||||
type: object
|
||||
required:
|
||||
- access_token
|
||||
- token_type
|
||||
- expires_in
|
||||
- refresh_token
|
||||
properties:
|
||||
access_token:
|
||||
description: Access token required for accessing protected API endpoints
|
||||
type: string
|
||||
format: uuid4
|
||||
example: c1247d8d-0d65-41c4-bc86-ec041d2ac437
|
||||
expires_in:
|
||||
description: Access token expiry in seconds
|
||||
type: integer
|
||||
format: int64
|
||||
example: 86400
|
||||
refresh_token:
|
||||
description: Refresh token for refreshing the access token once it expires
|
||||
type: string
|
||||
format: uuid4
|
||||
example: 1dadb3bd-50d8-485d-83a3-6111392568f0
|
||||
token_type:
|
||||
description: "Type of access token, will always be `bearer`"
|
||||
type: string
|
||||
example: bearer
|
||||
RegisterResponse:
|
||||
type: object
|
||||
required:
|
||||
- requiresConfirmation
|
||||
properties:
|
||||
requiresConfirmation:
|
||||
description: Indicates whether the registration process requires email confirmation
|
||||
type: boolean
|
||||
example: true
|
||||
PostLogoutPayload:
|
||||
type: object
|
||||
properties:
|
||||
refresh_token:
|
||||
description: Optional refresh token to delete while logging out
|
||||
type: string
|
||||
format: uuid4
|
||||
example: 700ebed3-40f7-4211-bc83-a89b22b9875e
|
||||
PostRefreshPayload:
|
||||
type: object
|
||||
required:
|
||||
- refresh_token
|
||||
properties:
|
||||
refresh_token:
|
||||
description: Refresh token to use for retrieving new token set
|
||||
type: string
|
||||
format: uuid4
|
||||
example: 7503cd8a-c921-4368-a32d-6c1d01d86da9
|
||||
PostRegisterPayload:
|
||||
type: object
|
||||
required:
|
||||
- username
|
||||
- password
|
||||
properties:
|
||||
password:
|
||||
description: Password to register with
|
||||
type: string
|
||||
maxLength: 500
|
||||
minLength: 1
|
||||
example: correct horse battery staple
|
||||
username:
|
||||
description: Username to register with
|
||||
type: string
|
||||
format: email
|
||||
maxLength: 255
|
||||
minLength: 1
|
||||
example: user@example.com
|
||||
DeleteUserAccountPayload:
|
||||
type: object
|
||||
required:
|
||||
- currentPassword
|
||||
properties:
|
||||
currentPassword:
|
||||
description: Current password of user
|
||||
type: string
|
||||
maxLength: 500
|
||||
minLength: 1
|
||||
example: correct horse battery staple
|
||||
47
api/definitions/common.yml
Normal file
47
api/definitions/common.yml
Normal file
@@ -0,0 +1,47 @@
|
||||
swagger: "2.0"
|
||||
info:
|
||||
title: allaboutapps.dev/aw/go-starter
|
||||
version: 0.1.0
|
||||
paths: {}
|
||||
definitions:
|
||||
Paginatable:
|
||||
type: object
|
||||
required:
|
||||
- limit
|
||||
- offset
|
||||
- total
|
||||
properties:
|
||||
limit:
|
||||
type: integer
|
||||
description: Actual limit applied to request
|
||||
offset:
|
||||
type: integer
|
||||
description: Actual offset applied to request
|
||||
total:
|
||||
type: integer
|
||||
description: Total number of records available
|
||||
parameters:
|
||||
offsetParam:
|
||||
type: integer
|
||||
in: query
|
||||
name: offset
|
||||
description: Offset used for pagination, number of records to skip
|
||||
default: 0
|
||||
minimum: 0
|
||||
limitParam:
|
||||
type: integer
|
||||
in: query
|
||||
name: limit
|
||||
description: Limit used for pagination, number of records to retrieve
|
||||
default: 50
|
||||
minimum: 1
|
||||
maximum: 500
|
||||
orderDirParam:
|
||||
type: string
|
||||
in: query
|
||||
name: orderDir
|
||||
description: Direction of order applied, defaults to `asc` if omitted. `asc` will sort `NULL` values at the end of the list.
|
||||
enum:
|
||||
- asc
|
||||
- desc
|
||||
default: asc
|
||||
79
api/definitions/errors.yml
Normal file
79
api/definitions/errors.yml
Normal file
@@ -0,0 +1,79 @@
|
||||
swagger: "2.0"
|
||||
info:
|
||||
title: allaboutapps.dev/aw/go-starter
|
||||
version: 0.1.0
|
||||
paths: {}
|
||||
definitions:
|
||||
PublicHTTPErrorType:
|
||||
type: string
|
||||
description: Type of error returned, should be used for client-side error handling
|
||||
enum:
|
||||
- generic
|
||||
# push
|
||||
- PUSH_TOKEN_ALREADY_EXISTS
|
||||
- OLD_PUSH_TOKEN_NOT_FOUND
|
||||
# files
|
||||
- ZERO_FILE_SIZE
|
||||
# auth
|
||||
- USER_DEACTIVATED
|
||||
- INVALID_PASSWORD
|
||||
- NOT_LOCAL_USER
|
||||
- TOKEN_NOT_FOUND
|
||||
- TOKEN_EXPIRED
|
||||
- USER_ALREADY_EXISTS
|
||||
- MALFORMED_TOKEN
|
||||
- LAST_AUTHENTICATED_AT_EXCEEDED
|
||||
- MISSING_SCOPES
|
||||
PublicHTTPError:
|
||||
type: object
|
||||
required:
|
||||
- status
|
||||
- type
|
||||
- title
|
||||
properties:
|
||||
detail:
|
||||
description: "More detailed, human-readable, optional explanation of the error"
|
||||
type: string
|
||||
example: User is lacking permission to access this resource
|
||||
status:
|
||||
description: HTTP status code returned for the error
|
||||
type: integer
|
||||
format: int64
|
||||
maximum: 599
|
||||
minimum: 100
|
||||
x-go-name: Code
|
||||
example: 403
|
||||
title:
|
||||
description: "Short, human-readable description of the error"
|
||||
type: string
|
||||
example: Forbidden
|
||||
type:
|
||||
$ref: "#/definitions/PublicHTTPErrorType"
|
||||
PublicHTTPValidationError:
|
||||
allOf:
|
||||
- $ref: "#/definitions/PublicHTTPError"
|
||||
type: object
|
||||
required:
|
||||
- validationErrors
|
||||
properties:
|
||||
validationErrors:
|
||||
description: List of errors received while validating payload against schema
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/definitions/HTTPValidationErrorDetail"
|
||||
HTTPValidationErrorDetail:
|
||||
type: object
|
||||
required:
|
||||
- key
|
||||
- in
|
||||
- error
|
||||
properties:
|
||||
error:
|
||||
description: Error describing field validation failure
|
||||
type: string
|
||||
in:
|
||||
description: Indicates how the invalid field was provided
|
||||
type: string
|
||||
key:
|
||||
description: Key of field failing validation
|
||||
type: string
|
||||
28
api/definitions/push.yml
Normal file
28
api/definitions/push.yml
Normal file
@@ -0,0 +1,28 @@
|
||||
swagger: "2.0"
|
||||
info:
|
||||
title: allaboutapps.dev/aw/go-starter
|
||||
version: 0.1.0
|
||||
paths: {}
|
||||
definitions:
|
||||
PutUpdatePushTokenPayload:
|
||||
type: object
|
||||
required:
|
||||
- newToken
|
||||
- provider
|
||||
properties:
|
||||
newToken:
|
||||
description: New push token for given provider.
|
||||
type: string
|
||||
maxLength: 500
|
||||
example: 1c91e550-8167-439c-8021-dee7de2f7e96
|
||||
oldToken:
|
||||
description: Old token that can be deleted if present.
|
||||
type: string
|
||||
maxLength: 500
|
||||
example: 495179de-b771-48f0-aab2-8d23701b0f02
|
||||
x-nullable: true
|
||||
provider:
|
||||
description: Identifier of the provider the token is for (eg. "fcm", "apn"). Currently only "fcm" is supported.
|
||||
type: string
|
||||
maxLength: 500
|
||||
example: fcm
|
||||
289
api/paths/auth.yml
Normal file
289
api/paths/auth.yml
Normal file
@@ -0,0 +1,289 @@
|
||||
swagger: "2.0"
|
||||
info:
|
||||
title: allaboutapps.dev/aw/go-starter
|
||||
version: 0.1.0
|
||||
responses:
|
||||
InvalidPasswordResponse:
|
||||
description: "PublicHTTPValidationError, type `INVALID_PASSWORD`"
|
||||
schema:
|
||||
$ref: ../definitions/errors.yml#/definitions/PublicHTTPValidationError
|
||||
AuthUnauthorizedResponse:
|
||||
description: PublicHTTPError
|
||||
schema:
|
||||
$ref: ../definitions/errors.yml#/definitions/PublicHTTPError
|
||||
AuthForbiddenResponse:
|
||||
description: "PublicHTTPError, type `USER_DEACTIVATED`/`NOT_LOCAL_USER`"
|
||||
schema:
|
||||
$ref: ../definitions/errors.yml#/definitions/PublicHTTPError
|
||||
ValidationError:
|
||||
description: PublicHTTPValidationError
|
||||
schema:
|
||||
$ref: "../definitions/errors.yml#/definitions/PublicHTTPValidationError"
|
||||
parameters:
|
||||
registrationTokenParam:
|
||||
type: string
|
||||
format: uuid4
|
||||
in: path
|
||||
name: registrationToken
|
||||
description: Registration token to complete the registration process
|
||||
required: true
|
||||
paths:
|
||||
/api/v1/auth/change-password:
|
||||
post:
|
||||
security:
|
||||
- Bearer: []
|
||||
description: |-
|
||||
After successful password change, all current access and refresh tokens are
|
||||
invalidated and a new set of auth tokens is returned
|
||||
tags:
|
||||
- auth
|
||||
summary: Change local user's password
|
||||
operationId: PostChangePasswordRoute
|
||||
parameters:
|
||||
- name: Payload
|
||||
in: body
|
||||
schema:
|
||||
$ref: ../definitions/auth.yml#/definitions/PostChangePasswordPayload
|
||||
responses:
|
||||
"200":
|
||||
description: PostLoginResponse
|
||||
schema:
|
||||
$ref: ../definitions/auth.yml#/definitions/PostLoginResponse
|
||||
"400":
|
||||
$ref: "#/responses/InvalidPasswordResponse"
|
||||
"401":
|
||||
$ref: "#/responses/AuthUnauthorizedResponse"
|
||||
"403":
|
||||
$ref: "#/responses/AuthForbiddenResponse"
|
||||
|
||||
/api/v1/auth/forgot-password:
|
||||
post:
|
||||
description: |-
|
||||
Initiates a password reset for a local user, sending an email with a password
|
||||
reset link to the provided email address if a user account exists. Will always
|
||||
succeed, even if no user was found in order to prevent user enumeration
|
||||
tags:
|
||||
- auth
|
||||
summary: Initiate password reset for local user
|
||||
operationId: PostForgotPasswordRoute
|
||||
parameters:
|
||||
- name: Payload
|
||||
in: body
|
||||
schema:
|
||||
$ref: "../definitions/auth.yml#/definitions/PostForgotPasswordPayload"
|
||||
responses:
|
||||
"204":
|
||||
description: Success
|
||||
"400":
|
||||
$ref: "#/responses/ValidationError"
|
||||
/api/v1/auth/forgot-password/complete:
|
||||
post:
|
||||
description: |-
|
||||
Completes a password reset for a local user, using the password reset token sent via email
|
||||
to confirm user access, setting the new password if successful. All current access and refresh
|
||||
tokens are invalidated and a new set of auth tokens is returned
|
||||
tags:
|
||||
- auth
|
||||
summary: Completes password reset for local user
|
||||
operationId: PostForgotPasswordCompleteRoute
|
||||
parameters:
|
||||
- name: Payload
|
||||
in: body
|
||||
schema:
|
||||
$ref: "../definitions/auth.yml#/definitions/PostForgotPasswordCompletePayload"
|
||||
responses:
|
||||
"200":
|
||||
description: PostLoginResponse
|
||||
schema:
|
||||
$ref: "../definitions/auth.yml#/definitions/PostLoginResponse"
|
||||
"400":
|
||||
$ref: "#/responses/InvalidPasswordResponse"
|
||||
"403":
|
||||
$ref: "#/responses/AuthForbiddenResponse"
|
||||
"404":
|
||||
description: "PublicHTTPError, type `TOKEN_NOT_FOUND`"
|
||||
schema:
|
||||
$ref: "../definitions/errors.yml#/definitions/PublicHTTPError"
|
||||
"409":
|
||||
description: "PublicHTTPError, type `TOKEN_EXPIRED`"
|
||||
schema:
|
||||
$ref: "../definitions/errors.yml#/definitions/PublicHTTPError"
|
||||
/api/v1/auth/login:
|
||||
post:
|
||||
description: Returns an access and refresh token on successful authentication
|
||||
tags:
|
||||
- auth
|
||||
summary: Login with local user
|
||||
operationId: PostLoginRoute
|
||||
parameters:
|
||||
- name: Payload
|
||||
in: body
|
||||
schema:
|
||||
$ref: "../definitions/auth.yml#/definitions/PostLoginPayload"
|
||||
responses:
|
||||
"200":
|
||||
description: PostLoginResponse
|
||||
schema:
|
||||
$ref: "../definitions/auth.yml#/definitions/PostLoginResponse"
|
||||
"400":
|
||||
$ref: "#/responses/ValidationError"
|
||||
"401":
|
||||
$ref: "#/responses/AuthUnauthorizedResponse"
|
||||
"403":
|
||||
description: "PublicHTTPError, type `USER_DEACTIVATED`"
|
||||
schema:
|
||||
$ref: "../definitions/errors.yml#/definitions/PublicHTTPError"
|
||||
/api/v1/auth/logout:
|
||||
post:
|
||||
security:
|
||||
- Bearer: []
|
||||
description: |-
|
||||
Logs the local user out, destroying the provided access token.
|
||||
A refresh token can optionally be provided, destroying it as well if found.
|
||||
tags:
|
||||
- auth
|
||||
summary: Log out local user
|
||||
operationId: PostLogoutRoute
|
||||
parameters:
|
||||
- name: Payload
|
||||
in: body
|
||||
schema:
|
||||
$ref: "../definitions/auth.yml#/definitions/PostLogoutPayload"
|
||||
responses:
|
||||
"204":
|
||||
description: Success
|
||||
"400":
|
||||
$ref: "#/responses/ValidationError"
|
||||
"401":
|
||||
$ref: "#/responses/AuthUnauthorizedResponse"
|
||||
/api/v1/auth/refresh:
|
||||
post:
|
||||
description: |-
|
||||
Returns a fresh set of access and refresh tokens if a valid refresh token was provided.
|
||||
The old refresh token used to authenticate the request will be invalidated.
|
||||
tags:
|
||||
- auth
|
||||
summary: Refresh tokens
|
||||
operationId: PostRefreshRoute
|
||||
parameters:
|
||||
- name: Payload
|
||||
in: body
|
||||
schema:
|
||||
$ref: "../definitions/auth.yml#/definitions/PostRefreshPayload"
|
||||
responses:
|
||||
"200":
|
||||
description: PostLoginResponse
|
||||
schema:
|
||||
$ref: "../definitions/auth.yml#/definitions/PostLoginResponse"
|
||||
"400":
|
||||
$ref: "#/responses/ValidationError"
|
||||
"401":
|
||||
$ref: "#/responses/AuthUnauthorizedResponse"
|
||||
"403":
|
||||
description: "PublicHTTPError, type `USER_DEACTIVATED`"
|
||||
schema:
|
||||
$ref: "../definitions/errors.yml#/definitions/PublicHTTPError"
|
||||
/api/v1/auth/register:
|
||||
post:
|
||||
description: |
|
||||
Registers a local user. If the registration process requires a confirmation
|
||||
the status code `202` is returned without auth tokens. Afterwards the registration needs to be confirmed
|
||||
using the `POST /api/v1/auth/register/{registrationToken}` endpoint.
|
||||
tags:
|
||||
- auth
|
||||
summary: Registers a local user
|
||||
operationId: PostRegisterRoute
|
||||
parameters:
|
||||
- name: Payload
|
||||
in: body
|
||||
schema:
|
||||
$ref: "../definitions/auth.yml#/definitions/PostRegisterPayload"
|
||||
responses:
|
||||
"200":
|
||||
description: PostLoginResponse
|
||||
schema:
|
||||
$ref: "../definitions/auth.yml#/definitions/PostLoginResponse"
|
||||
"202":
|
||||
description: RegisterResponse
|
||||
schema:
|
||||
$ref: "../definitions/auth.yml#/definitions/RegisterResponse"
|
||||
"400":
|
||||
$ref: "#/responses/InvalidPasswordResponse"
|
||||
"409":
|
||||
description: "PublicHTTPError, type `USER_ALREADY_EXISTS`"
|
||||
schema:
|
||||
$ref: "../definitions/errors.yml#/definitions/PublicHTTPError"
|
||||
get:
|
||||
summary: Page to complete registration
|
||||
tags:
|
||||
- auth
|
||||
operationId: GetCompleteRegisterRoute
|
||||
parameters:
|
||||
- name: token
|
||||
in: query
|
||||
type: string
|
||||
format: uuid4
|
||||
description: Registration token to complete the registration process
|
||||
required: true
|
||||
produces:
|
||||
- text/html
|
||||
responses:
|
||||
"200":
|
||||
description: Page to complete registration
|
||||
/api/v1/auth/register/{registrationToken}:
|
||||
post:
|
||||
summary: Complete registration
|
||||
description: |-
|
||||
Completes registration for a local user
|
||||
tags:
|
||||
- auth
|
||||
operationId: PostCompleteRegisterRoute
|
||||
parameters:
|
||||
- $ref: "#/parameters/registrationTokenParam"
|
||||
responses:
|
||||
"200":
|
||||
description: PostLoginResponse
|
||||
schema:
|
||||
$ref: "../definitions/auth.yml#/definitions/PostLoginResponse"
|
||||
"401":
|
||||
description: Unauthorized
|
||||
/api/v1/auth/userinfo:
|
||||
get:
|
||||
summary: Get user info
|
||||
description: |-
|
||||
Returns user information compatible with the OpenID Connect Core 1.0 specification.
|
||||
Information returned depends on the requesting user as some data is only available if an app user profile exists.
|
||||
security:
|
||||
- Bearer: []
|
||||
operationId: GetUserInfoRoute
|
||||
tags:
|
||||
- auth
|
||||
responses:
|
||||
"200":
|
||||
description: GetUserInfoResponse
|
||||
schema:
|
||||
$ref: "../definitions/auth.yml#/definitions/GetUserInfoResponse"
|
||||
/api/v1/auth/account:
|
||||
delete:
|
||||
summary: Delete user account
|
||||
description: |-
|
||||
Completely delete the user account. This action is irreversible and therefore requires additional password authentication.
|
||||
security:
|
||||
- Bearer: []
|
||||
operationId: DeleteUserAccountRoute
|
||||
parameters:
|
||||
- name: Payload
|
||||
in: body
|
||||
schema:
|
||||
$ref: ../definitions/auth.yml#/definitions/DeleteUserAccountPayload
|
||||
tags:
|
||||
- auth
|
||||
responses:
|
||||
"204":
|
||||
description: NoContent
|
||||
"400":
|
||||
$ref: "#/responses/InvalidPasswordResponse"
|
||||
"401":
|
||||
$ref: "#/responses/AuthUnauthorizedResponse"
|
||||
"403":
|
||||
$ref: "#/responses/AuthForbiddenResponse"
|
||||
71
api/paths/common.yml
Normal file
71
api/paths/common.yml
Normal file
@@ -0,0 +1,71 @@
|
||||
swagger: "2.0"
|
||||
info:
|
||||
title: allaboutapps.dev/aw/go-starter
|
||||
version: 0.1.0
|
||||
paths:
|
||||
/swagger.yml:
|
||||
get:
|
||||
summary: Get swagger.yml
|
||||
operationId: GetSwaggerRoute
|
||||
produces:
|
||||
- text/plain
|
||||
description: |-
|
||||
OpenAPI Specification ver. 2 (fka Swagger)
|
||||
Returns our handcrafted and validated `swagger.yml`.
|
||||
tags:
|
||||
- common
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
/-/ready:
|
||||
get:
|
||||
summary: Get ready (readiness probe)
|
||||
operationId: GetReadyRoute
|
||||
produces:
|
||||
- text/plain
|
||||
description: |-
|
||||
This endpoint returns 200 when the service is ready to serve traffic.
|
||||
Does read-only probes apart from the general server ready state.
|
||||
Note that /-/ready is typically public (and not shielded by a mgmt-secret), we thus prevent information leakage here and only return `"Ready."`.
|
||||
tags:
|
||||
- common
|
||||
responses:
|
||||
"200":
|
||||
description: Ready.
|
||||
"521":
|
||||
description: Not ready.
|
||||
/-/healthy:
|
||||
get:
|
||||
security:
|
||||
- Management: []
|
||||
summary: Get healthy (liveness probe)
|
||||
operationId: GetHealthyRoute
|
||||
produces:
|
||||
- text/plain
|
||||
description: |-
|
||||
This endpoint returns 200 when the service is healthy.
|
||||
Returns an human readable string about the current service status.
|
||||
In addition to readiness probes, it performs actual write probes.
|
||||
Note that /-/healthy is private (shielded by the mgmt-secret) as it may expose sensitive information about your service.
|
||||
tags:
|
||||
- common
|
||||
responses:
|
||||
"200":
|
||||
description: Ready.
|
||||
"521":
|
||||
description: Not ready.
|
||||
/-/version:
|
||||
get:
|
||||
security:
|
||||
- Management: []
|
||||
summary: Get version
|
||||
operationId: GetVersionRoute
|
||||
produces:
|
||||
- text/plain
|
||||
description: |-
|
||||
This endpoint returns the module name, commit and build-date baked into the app binary.
|
||||
tags:
|
||||
- common
|
||||
responses:
|
||||
"200":
|
||||
description: "ModuleName @ Commit (BuildDate)"
|
||||
33
api/paths/push.yml
Normal file
33
api/paths/push.yml
Normal file
@@ -0,0 +1,33 @@
|
||||
swagger: "2.0"
|
||||
info:
|
||||
title: allaboutapps.dev/aw/go-starter
|
||||
version: 0.1.0
|
||||
paths:
|
||||
/api/v1/push/token:
|
||||
put:
|
||||
security:
|
||||
- Bearer: []
|
||||
description: |-
|
||||
Adds a push token for the given provider to the current user.
|
||||
If the oldToken is present it will be deleted.
|
||||
Currently only the provider 'fcm' is supported.
|
||||
tags:
|
||||
- push
|
||||
summary: Adds a push token to the user
|
||||
operationId: PutUpdatePushTokenRoute
|
||||
parameters:
|
||||
- name: Payload
|
||||
in: body
|
||||
schema:
|
||||
"$ref": "../definitions/push.yml#/definitions/PutUpdatePushTokenPayload"
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
"404":
|
||||
description: PublicHTTPError, type `OLD_PUSH_TOKEN_NOT_FOUND`
|
||||
schema:
|
||||
"$ref": "../definitions/errors.yml#/definitions/PublicHTTPError"
|
||||
"409":
|
||||
description: PublicHTTPError, type `PUSH_TOKEN_ALREADY_EXISTS`
|
||||
schema:
|
||||
"$ref": "../definitions/errors.yml#/definitions/PublicHTTPError"
|
||||
27
api/paths/well_known.yml
Normal file
27
api/paths/well_known.yml
Normal file
@@ -0,0 +1,27 @@
|
||||
swagger: "2.0"
|
||||
info:
|
||||
title: allaboutapps.dev/aw/go-starter
|
||||
version: 0.1.0
|
||||
paths:
|
||||
/.well-known/apple-app-site-association:
|
||||
get:
|
||||
summary: Apple App Site Association
|
||||
description: |-
|
||||
Returns the Apple App Site Association file.
|
||||
operationId: GetAppleAppSiteAssociationRoute
|
||||
tags:
|
||||
- well-known
|
||||
responses:
|
||||
"200":
|
||||
description: Apple App Site Association
|
||||
/.well-known/assetlinks.json:
|
||||
get:
|
||||
summary: Android Digital Asset Links
|
||||
description: |-
|
||||
Returns the Android Digital Asset Links file.
|
||||
operationId: GetAndroidDigitalAssetLinksRoute
|
||||
tags:
|
||||
- well-known
|
||||
responses:
|
||||
"200":
|
||||
description: Android Digital Asset Links
|
||||
738
api/swagger.yml
Normal file
738
api/swagger.yml
Normal file
@@ -0,0 +1,738 @@
|
||||
# // Code generated by "make swagger"; DO NOT EDIT.
|
||||
consumes:
|
||||
- application/json
|
||||
produces:
|
||||
- application/json
|
||||
swagger: "2.0"
|
||||
info:
|
||||
description: API documentation
|
||||
title: allaboutapps.dev/aw/go-starter
|
||||
version: 0.1.0
|
||||
paths:
|
||||
/-/healthy:
|
||||
get:
|
||||
security:
|
||||
- Management: []
|
||||
description: |-
|
||||
This endpoint returns 200 when the service is healthy.
|
||||
Returns an human readable string about the current service status.
|
||||
In addition to readiness probes, it performs actual write probes.
|
||||
Note that /-/healthy is private (shielded by the mgmt-secret) as it may expose sensitive information about your service.
|
||||
produces:
|
||||
- text/plain
|
||||
tags:
|
||||
- common
|
||||
summary: Get healthy (liveness probe)
|
||||
operationId: GetHealthyRoute
|
||||
responses:
|
||||
"200":
|
||||
description: Ready.
|
||||
"521":
|
||||
description: Not ready.
|
||||
/-/ready:
|
||||
get:
|
||||
description: |-
|
||||
This endpoint returns 200 when the service is ready to serve traffic.
|
||||
Does read-only probes apart from the general server ready state.
|
||||
Note that /-/ready is typically public (and not shielded by a mgmt-secret), we thus prevent information leakage here and only return `"Ready."`.
|
||||
produces:
|
||||
- text/plain
|
||||
tags:
|
||||
- common
|
||||
summary: Get ready (readiness probe)
|
||||
operationId: GetReadyRoute
|
||||
responses:
|
||||
"200":
|
||||
description: Ready.
|
||||
"521":
|
||||
description: Not ready.
|
||||
/-/version:
|
||||
get:
|
||||
security:
|
||||
- Management: []
|
||||
description: This endpoint returns the module name, commit and build-date baked
|
||||
into the app binary.
|
||||
produces:
|
||||
- text/plain
|
||||
tags:
|
||||
- common
|
||||
summary: Get version
|
||||
operationId: GetVersionRoute
|
||||
responses:
|
||||
"200":
|
||||
description: ModuleName @ Commit (BuildDate)
|
||||
/.well-known/apple-app-site-association:
|
||||
get:
|
||||
description: Returns the Apple App Site Association file.
|
||||
tags:
|
||||
- well-known
|
||||
summary: Apple App Site Association
|
||||
operationId: GetAppleAppSiteAssociationRoute
|
||||
responses:
|
||||
"200":
|
||||
description: Apple App Site Association
|
||||
/.well-known/assetlinks.json:
|
||||
get:
|
||||
description: Returns the Android Digital Asset Links file.
|
||||
tags:
|
||||
- well-known
|
||||
summary: Android Digital Asset Links
|
||||
operationId: GetAndroidDigitalAssetLinksRoute
|
||||
responses:
|
||||
"200":
|
||||
description: Android Digital Asset Links
|
||||
/api/v1/auth/account:
|
||||
delete:
|
||||
security:
|
||||
- Bearer: []
|
||||
description: Completely delete the user account. This action is irreversible
|
||||
and therefore requires additional password authentication.
|
||||
tags:
|
||||
- auth
|
||||
summary: Delete user account
|
||||
operationId: DeleteUserAccountRoute
|
||||
parameters:
|
||||
- name: Payload
|
||||
in: body
|
||||
schema:
|
||||
$ref: '#/definitions/deleteUserAccountPayload'
|
||||
responses:
|
||||
"204":
|
||||
description: NoContent
|
||||
"400":
|
||||
description: PublicHTTPValidationError, type `INVALID_PASSWORD`
|
||||
schema:
|
||||
$ref: '#/definitions/publicHttpValidationError'
|
||||
"401":
|
||||
description: PublicHTTPError
|
||||
schema:
|
||||
$ref: '#/definitions/publicHttpError'
|
||||
"403":
|
||||
description: PublicHTTPError, type `USER_DEACTIVATED`/`NOT_LOCAL_USER`
|
||||
schema:
|
||||
$ref: '#/definitions/publicHttpError'
|
||||
/api/v1/auth/change-password:
|
||||
post:
|
||||
security:
|
||||
- Bearer: []
|
||||
description: |-
|
||||
After successful password change, all current access and refresh tokens are
|
||||
invalidated and a new set of auth tokens is returned
|
||||
tags:
|
||||
- auth
|
||||
summary: Change local user's password
|
||||
operationId: PostChangePasswordRoute
|
||||
parameters:
|
||||
- name: Payload
|
||||
in: body
|
||||
schema:
|
||||
$ref: '#/definitions/postChangePasswordPayload'
|
||||
responses:
|
||||
"200":
|
||||
description: PostLoginResponse
|
||||
schema:
|
||||
$ref: '#/definitions/postLoginResponse'
|
||||
"400":
|
||||
description: PublicHTTPValidationError, type `INVALID_PASSWORD`
|
||||
schema:
|
||||
$ref: '#/definitions/publicHttpValidationError'
|
||||
"401":
|
||||
description: PublicHTTPError
|
||||
schema:
|
||||
$ref: '#/definitions/publicHttpError'
|
||||
"403":
|
||||
description: PublicHTTPError, type `USER_DEACTIVATED`/`NOT_LOCAL_USER`
|
||||
schema:
|
||||
$ref: '#/definitions/publicHttpError'
|
||||
/api/v1/auth/forgot-password:
|
||||
post:
|
||||
description: |-
|
||||
Initiates a password reset for a local user, sending an email with a password
|
||||
reset link to the provided email address if a user account exists. Will always
|
||||
succeed, even if no user was found in order to prevent user enumeration
|
||||
tags:
|
||||
- auth
|
||||
summary: Initiate password reset for local user
|
||||
operationId: PostForgotPasswordRoute
|
||||
parameters:
|
||||
- name: Payload
|
||||
in: body
|
||||
schema:
|
||||
$ref: '#/definitions/postForgotPasswordPayload'
|
||||
responses:
|
||||
"204":
|
||||
description: Success
|
||||
"400":
|
||||
description: PublicHTTPValidationError
|
||||
schema:
|
||||
$ref: '#/definitions/publicHttpValidationError'
|
||||
/api/v1/auth/forgot-password/complete:
|
||||
post:
|
||||
description: |-
|
||||
Completes a password reset for a local user, using the password reset token sent via email
|
||||
to confirm user access, setting the new password if successful. All current access and refresh
|
||||
tokens are invalidated and a new set of auth tokens is returned
|
||||
tags:
|
||||
- auth
|
||||
summary: Completes password reset for local user
|
||||
operationId: PostForgotPasswordCompleteRoute
|
||||
parameters:
|
||||
- name: Payload
|
||||
in: body
|
||||
schema:
|
||||
$ref: '#/definitions/postForgotPasswordCompletePayload'
|
||||
responses:
|
||||
"200":
|
||||
description: PostLoginResponse
|
||||
schema:
|
||||
$ref: '#/definitions/postLoginResponse'
|
||||
"400":
|
||||
description: PublicHTTPValidationError, type `INVALID_PASSWORD`
|
||||
schema:
|
||||
$ref: '#/definitions/publicHttpValidationError'
|
||||
"403":
|
||||
description: PublicHTTPError, type `USER_DEACTIVATED`/`NOT_LOCAL_USER`
|
||||
schema:
|
||||
$ref: '#/definitions/publicHttpError'
|
||||
"404":
|
||||
description: PublicHTTPError, type `TOKEN_NOT_FOUND`
|
||||
schema:
|
||||
$ref: '#/definitions/publicHttpError'
|
||||
"409":
|
||||
description: PublicHTTPError, type `TOKEN_EXPIRED`
|
||||
schema:
|
||||
$ref: '#/definitions/publicHttpError'
|
||||
/api/v1/auth/login:
|
||||
post:
|
||||
description: Returns an access and refresh token on successful authentication
|
||||
tags:
|
||||
- auth
|
||||
summary: Login with local user
|
||||
operationId: PostLoginRoute
|
||||
parameters:
|
||||
- name: Payload
|
||||
in: body
|
||||
schema:
|
||||
$ref: '#/definitions/postLoginPayload'
|
||||
responses:
|
||||
"200":
|
||||
description: PostLoginResponse
|
||||
schema:
|
||||
$ref: '#/definitions/postLoginResponse'
|
||||
"400":
|
||||
description: PublicHTTPValidationError
|
||||
schema:
|
||||
$ref: '#/definitions/publicHttpValidationError'
|
||||
"401":
|
||||
description: PublicHTTPError
|
||||
schema:
|
||||
$ref: '#/definitions/publicHttpError'
|
||||
"403":
|
||||
description: PublicHTTPError, type `USER_DEACTIVATED`
|
||||
schema:
|
||||
$ref: '#/definitions/publicHttpError'
|
||||
/api/v1/auth/logout:
|
||||
post:
|
||||
security:
|
||||
- Bearer: []
|
||||
description: |-
|
||||
Logs the local user out, destroying the provided access token.
|
||||
A refresh token can optionally be provided, destroying it as well if found.
|
||||
tags:
|
||||
- auth
|
||||
summary: Log out local user
|
||||
operationId: PostLogoutRoute
|
||||
parameters:
|
||||
- name: Payload
|
||||
in: body
|
||||
schema:
|
||||
$ref: '#/definitions/postLogoutPayload'
|
||||
responses:
|
||||
"204":
|
||||
description: Success
|
||||
"400":
|
||||
description: PublicHTTPValidationError
|
||||
schema:
|
||||
$ref: '#/definitions/publicHttpValidationError'
|
||||
"401":
|
||||
description: PublicHTTPError
|
||||
schema:
|
||||
$ref: '#/definitions/publicHttpError'
|
||||
/api/v1/auth/refresh:
|
||||
post:
|
||||
description: |-
|
||||
Returns a fresh set of access and refresh tokens if a valid refresh token was provided.
|
||||
The old refresh token used to authenticate the request will be invalidated.
|
||||
tags:
|
||||
- auth
|
||||
summary: Refresh tokens
|
||||
operationId: PostRefreshRoute
|
||||
parameters:
|
||||
- name: Payload
|
||||
in: body
|
||||
schema:
|
||||
$ref: '#/definitions/postRefreshPayload'
|
||||
responses:
|
||||
"200":
|
||||
description: PostLoginResponse
|
||||
schema:
|
||||
$ref: '#/definitions/postLoginResponse'
|
||||
"400":
|
||||
description: PublicHTTPValidationError
|
||||
schema:
|
||||
$ref: '#/definitions/publicHttpValidationError'
|
||||
"401":
|
||||
description: PublicHTTPError
|
||||
schema:
|
||||
$ref: '#/definitions/publicHttpError'
|
||||
"403":
|
||||
description: PublicHTTPError, type `USER_DEACTIVATED`
|
||||
schema:
|
||||
$ref: '#/definitions/publicHttpError'
|
||||
/api/v1/auth/register:
|
||||
get:
|
||||
produces:
|
||||
- text/html
|
||||
tags:
|
||||
- auth
|
||||
summary: Page to complete registration
|
||||
operationId: GetCompleteRegisterRoute
|
||||
parameters:
|
||||
- type: string
|
||||
format: uuid4
|
||||
description: Registration token to complete the registration process
|
||||
name: token
|
||||
in: query
|
||||
required: true
|
||||
responses:
|
||||
"200":
|
||||
description: Page to complete registration
|
||||
post:
|
||||
description: |
|
||||
Registers a local user. If the registration process requires a confirmation
|
||||
the status code `202` is returned without auth tokens. Afterwards the registration needs to be confirmed
|
||||
using the `POST /api/v1/auth/register/{registrationToken}` endpoint.
|
||||
tags:
|
||||
- auth
|
||||
summary: Registers a local user
|
||||
operationId: PostRegisterRoute
|
||||
parameters:
|
||||
- name: Payload
|
||||
in: body
|
||||
schema:
|
||||
$ref: '#/definitions/postRegisterPayload'
|
||||
responses:
|
||||
"200":
|
||||
description: PostLoginResponse
|
||||
schema:
|
||||
$ref: '#/definitions/postLoginResponse'
|
||||
"202":
|
||||
description: RegisterResponse
|
||||
schema:
|
||||
$ref: '#/definitions/registerResponse'
|
||||
"400":
|
||||
description: PublicHTTPValidationError, type `INVALID_PASSWORD`
|
||||
schema:
|
||||
$ref: '#/definitions/publicHttpValidationError'
|
||||
"409":
|
||||
description: PublicHTTPError, type `USER_ALREADY_EXISTS`
|
||||
schema:
|
||||
$ref: '#/definitions/publicHttpError'
|
||||
/api/v1/auth/register/{registrationToken}:
|
||||
post:
|
||||
description: Completes registration for a local user
|
||||
tags:
|
||||
- auth
|
||||
summary: Complete registration
|
||||
operationId: PostCompleteRegisterRoute
|
||||
parameters:
|
||||
- type: string
|
||||
format: uuid4
|
||||
description: Registration token to complete the registration process
|
||||
name: registrationToken
|
||||
in: path
|
||||
required: true
|
||||
responses:
|
||||
"200":
|
||||
description: PostLoginResponse
|
||||
schema:
|
||||
$ref: '#/definitions/postLoginResponse'
|
||||
"401":
|
||||
description: Unauthorized
|
||||
/api/v1/auth/userinfo:
|
||||
get:
|
||||
security:
|
||||
- Bearer: []
|
||||
description: |-
|
||||
Returns user information compatible with the OpenID Connect Core 1.0 specification.
|
||||
Information returned depends on the requesting user as some data is only available if an app user profile exists.
|
||||
tags:
|
||||
- auth
|
||||
summary: Get user info
|
||||
operationId: GetUserInfoRoute
|
||||
responses:
|
||||
"200":
|
||||
description: GetUserInfoResponse
|
||||
schema:
|
||||
$ref: '#/definitions/getUserInfoResponse'
|
||||
/api/v1/push/token:
|
||||
put:
|
||||
security:
|
||||
- Bearer: []
|
||||
description: |-
|
||||
Adds a push token for the given provider to the current user.
|
||||
If the oldToken is present it will be deleted.
|
||||
Currently only the provider 'fcm' is supported.
|
||||
tags:
|
||||
- push
|
||||
summary: Adds a push token to the user
|
||||
operationId: PutUpdatePushTokenRoute
|
||||
parameters:
|
||||
- name: Payload
|
||||
in: body
|
||||
schema:
|
||||
$ref: '#/definitions/putUpdatePushTokenPayload'
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
"404":
|
||||
description: PublicHTTPError, type `OLD_PUSH_TOKEN_NOT_FOUND`
|
||||
schema:
|
||||
$ref: '#/definitions/publicHttpError'
|
||||
"409":
|
||||
description: PublicHTTPError, type `PUSH_TOKEN_ALREADY_EXISTS`
|
||||
schema:
|
||||
$ref: '#/definitions/publicHttpError'
|
||||
/swagger.yml:
|
||||
get:
|
||||
description: |-
|
||||
OpenAPI Specification ver. 2 (fka Swagger)
|
||||
Returns our handcrafted and validated `swagger.yml`.
|
||||
produces:
|
||||
- text/plain
|
||||
tags:
|
||||
- common
|
||||
summary: Get swagger.yml
|
||||
operationId: GetSwaggerRoute
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
definitions:
|
||||
deleteUserAccountPayload:
|
||||
type: object
|
||||
required:
|
||||
- currentPassword
|
||||
properties:
|
||||
currentPassword:
|
||||
description: Current password of user
|
||||
type: string
|
||||
maxLength: 500
|
||||
minLength: 1
|
||||
example: correct horse battery staple
|
||||
getUserInfoResponse:
|
||||
type: object
|
||||
required:
|
||||
- sub
|
||||
- updated_at
|
||||
properties:
|
||||
email:
|
||||
description: Email address of user, if available
|
||||
type: string
|
||||
format: email
|
||||
maxLength: 255
|
||||
example: user@example.com
|
||||
scopes:
|
||||
description: Auth-Scopes of the user, if available
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
enum:
|
||||
- app
|
||||
- cms
|
||||
example:
|
||||
- app
|
||||
sub:
|
||||
description: ID of user
|
||||
type: string
|
||||
example: 82ebdfad-c586-4407-a873-4cc1c33d56fc
|
||||
updated_at:
|
||||
description: Unix timestamp the user's info was last updated at
|
||||
type: integer
|
||||
example: 1591960808
|
||||
httpValidationErrorDetail:
|
||||
type: object
|
||||
required:
|
||||
- key
|
||||
- in
|
||||
- error
|
||||
properties:
|
||||
error:
|
||||
description: Error describing field validation failure
|
||||
type: string
|
||||
in:
|
||||
description: Indicates how the invalid field was provided
|
||||
type: string
|
||||
key:
|
||||
description: Key of field failing validation
|
||||
type: string
|
||||
orderDir:
|
||||
type: string
|
||||
enum:
|
||||
- asc
|
||||
- desc
|
||||
postChangePasswordPayload:
|
||||
type: object
|
||||
required:
|
||||
- currentPassword
|
||||
- newPassword
|
||||
properties:
|
||||
currentPassword:
|
||||
description: Current password of user
|
||||
type: string
|
||||
maxLength: 500
|
||||
minLength: 1
|
||||
example: correct horse battery staple
|
||||
newPassword:
|
||||
description: New password to set for user
|
||||
type: string
|
||||
maxLength: 500
|
||||
minLength: 1
|
||||
example: correct horse battery staple
|
||||
postForgotPasswordCompletePayload:
|
||||
type: object
|
||||
required:
|
||||
- token
|
||||
- password
|
||||
properties:
|
||||
password:
|
||||
description: New password to set for user
|
||||
type: string
|
||||
maxLength: 500
|
||||
minLength: 1
|
||||
example: correct horse battery staple
|
||||
token:
|
||||
description: Password reset token sent via email
|
||||
type: string
|
||||
format: uuid4
|
||||
example: ec16f032-3c44-4148-bbcc-45557466fa74
|
||||
postForgotPasswordPayload:
|
||||
type: object
|
||||
required:
|
||||
- username
|
||||
properties:
|
||||
username:
|
||||
description: Username to initiate password reset for
|
||||
type: string
|
||||
format: email
|
||||
maxLength: 255
|
||||
minLength: 1
|
||||
example: user@example.com
|
||||
postLoginPayload:
|
||||
type: object
|
||||
required:
|
||||
- username
|
||||
- password
|
||||
properties:
|
||||
password:
|
||||
description: Password of user to authenticate as
|
||||
type: string
|
||||
maxLength: 500
|
||||
minLength: 1
|
||||
example: correct horse battery staple
|
||||
username:
|
||||
description: Username of user to authenticate as
|
||||
type: string
|
||||
format: email
|
||||
maxLength: 255
|
||||
minLength: 1
|
||||
example: user@example.com
|
||||
postLoginResponse:
|
||||
type: object
|
||||
required:
|
||||
- access_token
|
||||
- token_type
|
||||
- expires_in
|
||||
- refresh_token
|
||||
properties:
|
||||
access_token:
|
||||
description: Access token required for accessing protected API endpoints
|
||||
type: string
|
||||
format: uuid4
|
||||
example: c1247d8d-0d65-41c4-bc86-ec041d2ac437
|
||||
expires_in:
|
||||
description: Access token expiry in seconds
|
||||
type: integer
|
||||
format: int64
|
||||
example: 86400
|
||||
refresh_token:
|
||||
description: Refresh token for refreshing the access token once it expires
|
||||
type: string
|
||||
format: uuid4
|
||||
example: 1dadb3bd-50d8-485d-83a3-6111392568f0
|
||||
token_type:
|
||||
description: Type of access token, will always be `bearer`
|
||||
type: string
|
||||
example: bearer
|
||||
postLogoutPayload:
|
||||
type: object
|
||||
properties:
|
||||
refresh_token:
|
||||
description: Optional refresh token to delete while logging out
|
||||
type: string
|
||||
format: uuid4
|
||||
example: 700ebed3-40f7-4211-bc83-a89b22b9875e
|
||||
postRefreshPayload:
|
||||
type: object
|
||||
required:
|
||||
- refresh_token
|
||||
properties:
|
||||
refresh_token:
|
||||
description: Refresh token to use for retrieving new token set
|
||||
type: string
|
||||
format: uuid4
|
||||
example: 7503cd8a-c921-4368-a32d-6c1d01d86da9
|
||||
postRegisterPayload:
|
||||
type: object
|
||||
required:
|
||||
- username
|
||||
- password
|
||||
properties:
|
||||
password:
|
||||
description: Password to register with
|
||||
type: string
|
||||
maxLength: 500
|
||||
minLength: 1
|
||||
example: correct horse battery staple
|
||||
username:
|
||||
description: Username to register with
|
||||
type: string
|
||||
format: email
|
||||
maxLength: 255
|
||||
minLength: 1
|
||||
example: user@example.com
|
||||
publicHttpError:
|
||||
type: object
|
||||
required:
|
||||
- status
|
||||
- type
|
||||
- title
|
||||
properties:
|
||||
detail:
|
||||
description: More detailed, human-readable, optional explanation of the error
|
||||
type: string
|
||||
example: User is lacking permission to access this resource
|
||||
status:
|
||||
description: HTTP status code returned for the error
|
||||
type: integer
|
||||
format: int64
|
||||
maximum: 599
|
||||
minimum: 100
|
||||
x-go-name: Code
|
||||
example: 403
|
||||
title:
|
||||
description: Short, human-readable description of the error
|
||||
type: string
|
||||
example: Forbidden
|
||||
type:
|
||||
$ref: '#/definitions/publicHttpErrorType'
|
||||
publicHttpErrorType:
|
||||
description: Type of error returned, should be used for client-side error handling
|
||||
type: string
|
||||
enum:
|
||||
- generic
|
||||
- PUSH_TOKEN_ALREADY_EXISTS
|
||||
- OLD_PUSH_TOKEN_NOT_FOUND
|
||||
- ZERO_FILE_SIZE
|
||||
- USER_DEACTIVATED
|
||||
- INVALID_PASSWORD
|
||||
- NOT_LOCAL_USER
|
||||
- TOKEN_NOT_FOUND
|
||||
- TOKEN_EXPIRED
|
||||
- USER_ALREADY_EXISTS
|
||||
- MALFORMED_TOKEN
|
||||
- LAST_AUTHENTICATED_AT_EXCEEDED
|
||||
- MISSING_SCOPES
|
||||
publicHttpValidationError:
|
||||
type: object
|
||||
required:
|
||||
- validationErrors
|
||||
allOf:
|
||||
- $ref: '#/definitions/publicHttpError'
|
||||
properties:
|
||||
validationErrors:
|
||||
description: List of errors received while validating payload against schema
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/httpValidationErrorDetail'
|
||||
putUpdatePushTokenPayload:
|
||||
type: object
|
||||
required:
|
||||
- newToken
|
||||
- provider
|
||||
properties:
|
||||
newToken:
|
||||
description: New push token for given provider.
|
||||
type: string
|
||||
maxLength: 500
|
||||
example: 1c91e550-8167-439c-8021-dee7de2f7e96
|
||||
oldToken:
|
||||
description: Old token that can be deleted if present.
|
||||
type: string
|
||||
maxLength: 500
|
||||
x-nullable: true
|
||||
example: 495179de-b771-48f0-aab2-8d23701b0f02
|
||||
provider:
|
||||
description: Identifier of the provider the token is for (eg. "fcm", "apn").
|
||||
Currently only "fcm" is supported.
|
||||
type: string
|
||||
maxLength: 500
|
||||
example: fcm
|
||||
registerResponse:
|
||||
type: object
|
||||
required:
|
||||
- requiresConfirmation
|
||||
properties:
|
||||
requiresConfirmation:
|
||||
description: Indicates whether the registration process requires email confirmation
|
||||
type: boolean
|
||||
example: true
|
||||
parameters:
|
||||
registrationTokenParam:
|
||||
type: string
|
||||
format: uuid4
|
||||
description: Registration token to complete the registration process
|
||||
name: registrationToken
|
||||
in: path
|
||||
required: true
|
||||
responses:
|
||||
AuthForbiddenResponse:
|
||||
description: PublicHTTPError, type `USER_DEACTIVATED`/`NOT_LOCAL_USER`
|
||||
schema:
|
||||
$ref: '#/definitions/publicHttpError'
|
||||
AuthUnauthorizedResponse:
|
||||
description: PublicHTTPError
|
||||
schema:
|
||||
$ref: '#/definitions/publicHttpError'
|
||||
InvalidPasswordResponse:
|
||||
description: PublicHTTPValidationError, type `INVALID_PASSWORD`
|
||||
schema:
|
||||
$ref: '#/definitions/publicHttpValidationError'
|
||||
ValidationError:
|
||||
description: PublicHTTPValidationError
|
||||
schema:
|
||||
$ref: '#/definitions/publicHttpValidationError'
|
||||
securityDefinitions:
|
||||
Bearer:
|
||||
description: |-
|
||||
Access token for application access, **must** include "Bearer " prefix.
|
||||
Example: `Bearer b4a94a42-3ea2-4af3-9699-8bcbfee6e6d2`
|
||||
type: apiKey
|
||||
name: Authorization
|
||||
in: header
|
||||
x-keyPrefix: 'Bearer '
|
||||
Management:
|
||||
description: Management secret, used for monitoring and infrastructure related
|
||||
calls
|
||||
type: apiKey
|
||||
name: mgmt-secret
|
||||
in: query
|
||||
5
api/templates/server/builder.README
Normal file
5
api/templates/server/builder.README
Normal file
@@ -0,0 +1,5 @@
|
||||
https://raw.githubusercontent.com/go-swagger/go-swagger/master/generator/templates/server/builder.gotmpl
|
||||
Based on commit in 78f49e7e72c09ff0e39251f002bba729b861e756
|
||||
Feb 24, 2020
|
||||
|
||||
Note that our `builder.gotmpl` is minimal and only used for validating if any routes without a swagger spec exist.
|
||||
49
api/templates/server/builder.gotmpl
Normal file
49
api/templates/server/builder.gotmpl
Normal file
@@ -0,0 +1,49 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
|
||||
{{ if .Copyright -}}// {{ comment .Copyright -}}{{ end }}
|
||||
|
||||
|
||||
package types
|
||||
{{ $package := "types" }}
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
// NewSwaggerSpec creates a new SwaggerSpec instance
|
||||
func NewSwaggerSpec() *SwaggerSpec {
|
||||
|
||||
spec := &SwaggerSpec{
|
||||
Handlers: make(map[string]map[string]bool),
|
||||
}
|
||||
|
||||
if len(spec.Handlers) == 0 {
|
||||
spec.initHandlerCache()
|
||||
}
|
||||
|
||||
return spec
|
||||
}
|
||||
|
||||
/*SwaggerSpec {{ if .Info }}{{ if .Info.Description }}{{.Info.Description}}{{ else }}the {{ humanize .Name }} API{{ end }}{{ end }} */
|
||||
type SwaggerSpec struct {
|
||||
Handlers map[string]map[string]bool
|
||||
}
|
||||
|
||||
func ({{.ReceiverName}} *SwaggerSpec) initHandlerCache() {
|
||||
{{- if .Operations }}
|
||||
{{.ReceiverName}}.Handlers = make(map[string]map[string]bool)
|
||||
|
||||
// https://swagger.io/specification/v2/ fixed fields: GET, PUT, POST, DELETE, OPTIONS, HEAD, PATCH
|
||||
{{.ReceiverName}}.Handlers["GET"] = make(map[string]bool)
|
||||
{{.ReceiverName}}.Handlers["PUT"] = make(map[string]bool)
|
||||
{{.ReceiverName}}.Handlers["POST"] = make(map[string]bool)
|
||||
{{.ReceiverName}}.Handlers["DELETE"] = make(map[string]bool)
|
||||
{{.ReceiverName}}.Handlers["OPTIONS"] = make(map[string]bool)
|
||||
{{.ReceiverName}}.Handlers["HEAD"] = make(map[string]bool)
|
||||
{{.ReceiverName}}.Handlers["PATCH"] = make(map[string]bool)
|
||||
{{ range .Operations }}
|
||||
{{.ReceiverName}}.Handlers[{{ printf "%q" (upper .Method) }}][{{ if eq .Path "/" }}""{{ else }}{{ printf "%q" (cleanPath .Path) }}{{ end }}] = true
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
3
api/templates/server/parameter.README
Normal file
3
api/templates/server/parameter.README
Normal file
@@ -0,0 +1,3 @@
|
||||
https://github.com/go-swagger/go-swagger/blob/master/generator/templates/server/parameter.gotmpl
|
||||
Based on commit in b1ca570cfcd2e281d445e0049506f18fa1c2c2cc
|
||||
Jun 13, 2020
|
||||
759
api/templates/server/parameter.gotmpl
Normal file
759
api/templates/server/parameter.gotmpl
Normal file
@@ -0,0 +1,759 @@
|
||||
{{ define "bindprimitiveparam" }}{{/* an empty test definition to test template repo dependencies resolution - DO NOT CHANGE THIS */}}
|
||||
{{ end }}
|
||||
|
||||
{{ define "bodyvalidator" }}
|
||||
{{- if .HasModelBodyParams }}
|
||||
// validate body object{{/* delegate validation to model object */}}
|
||||
if err := body.Validate(route.Formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) == 0 {
|
||||
{{ .ReceiverName }}.{{ pascalize .Name }} = {{ if and (not .Schema.IsBaseType) .IsNullable }}&{{ end }}body
|
||||
}
|
||||
{{- else if and .HasSimpleBodyParams .HasModelBodyItems }}
|
||||
|
||||
{{- if or .Schema.HasSliceValidations .Schema.Items.HasValidations }}
|
||||
// validate array of body objects
|
||||
{{- end }}
|
||||
{{- if .Schema.HasSliceValidations }}
|
||||
{{ .ReceiverName }}.{{ pascalize .Name }} = {{ if and (not .Schema.IsBaseType) .IsNullable }}&{{ end }}body
|
||||
{{ template "sliceparamvalidator" . }}
|
||||
{{- end }}
|
||||
|
||||
{{- if and .Schema.Items.HasValidations (not (or .Schema.Items.IsInterface .Schema.Items.IsStream)) }}
|
||||
for {{ .IndexVar }} := range body {
|
||||
{{- if .Schema.Items.IsNullable }}
|
||||
if body[{{ .IndexVar }}] == nil {
|
||||
{{- if .Schema.Items.Required }}
|
||||
res = append(res, errors.Required({{ .Child.Path }}, {{ printf "%q" .Child.Location }}, body[{{ .IndexVar }}]))
|
||||
break
|
||||
{{- else }}
|
||||
continue
|
||||
{{- end }}
|
||||
}
|
||||
{{- end }}
|
||||
if err := body[{{ .IndexVar }}].Validate(route.Formats); err != nil {
|
||||
res = append(res, err)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
{{- if not .Schema.HasSliceValidations }}
|
||||
if len(res) == 0 {
|
||||
{{ .ReceiverName }}.{{ pascalize .Name }} = {{ if and (not .Schema.IsBaseType) .IsNullable }}&{{ end }}body
|
||||
}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
// no validation for items in this slice
|
||||
{{ .ReceiverName }}.{{ pascalize .Name }} = {{ if and (not .Schema.IsBaseType) .IsNullable }}&{{ end }}body
|
||||
{{- end }}
|
||||
|
||||
{{- else if and .HasSimpleBodyParams .HasModelBodyMap }}
|
||||
|
||||
{{- if and .Schema.HasValidations (not (or .Schema.AdditionalProperties.IsInterface .Schema.AdditionalProperties.IsStream)) }}
|
||||
// validate map of body objects
|
||||
for {{ .KeyVar }} := range body {
|
||||
{{- if .Schema.AdditionalProperties.Required }}
|
||||
if err := validate.Required({{ if .Child.Path }}{{ .Child.Path }}{{ else }}""{{ end }}, {{ printf "%q" .Child.Location }}, {{ if not .IsAnonymous }}{{ .Schema.GoType }}({{ end }}body[{{ .KeyVar }}]{{ if not .IsAnonymous }}){{ end }}); err != nil {
|
||||
return err
|
||||
}
|
||||
{{- end }}
|
||||
{{- if and .Schema.AdditionalProperties.IsNullable (not .IsMapNullOverride) }}
|
||||
if body[{{ .KeyVar }}] == nil {
|
||||
{{- if .Schema.AdditionalProperties.Required }}
|
||||
res = append(res, errors.Required({{ .Path }}, {{ printf "%q" .Location }}, body[{{ .KeyVar }}]))
|
||||
break
|
||||
{{- else }}
|
||||
continue
|
||||
{{- end }}
|
||||
}
|
||||
{{- end }}
|
||||
if val , ok :=body[{{ .KeyVar }}]; ok {
|
||||
{{- if and .IsNullable (not .IsMapNullOverride) }}
|
||||
if val != nil {
|
||||
{{- end }}
|
||||
if err := val.Validate(route.Formats); err != nil {
|
||||
res = append(res, err)
|
||||
break
|
||||
}
|
||||
{{- if and .IsNullable (not .IsMapNullOverride) }}
|
||||
}
|
||||
{{- end }}
|
||||
}
|
||||
}
|
||||
|
||||
if len(res) == 0 {
|
||||
{{ .ReceiverName }}.{{ pascalize .Name }} = {{ if and (not .Schema.IsBaseType) .IsNullable }}&{{ end }}body
|
||||
}
|
||||
{{- else }}
|
||||
// no validation for this map
|
||||
{{ .ReceiverName }}.{{ pascalize .Name }} = {{ if and (not .Schema.IsBaseType) .IsNullable }}&{{ end }}body
|
||||
{{- end }}
|
||||
{{- else if .HasSimpleBodyParams }}
|
||||
{{- if and (not .IsArray) (not .IsMap) .Schema.HasValidations }}
|
||||
// validate inline body
|
||||
{{ .ReceiverName }}.{{ pascalize .Name }} = {{ if and (not .Schema.IsBaseType) .IsNullable }}&{{ end }}body
|
||||
if err := {{ .ReceiverName }}.validate{{ pascalize .ID }}Body(route.Formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
{{- else if and (or .IsArray .IsMap) .Schema.HasValidations }}
|
||||
// validate inline body {{ if .IsArray }}array{{ else }}map{{ end }}
|
||||
{{ .ReceiverName }}.{{ pascalize .Name }} = {{ if and (not .Schema.IsBaseType) .IsNullable }}&{{ end }}body
|
||||
if err := {{ .ReceiverName }}.validate{{ pascalize .ID }}Body(route.Formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
{{- else }}
|
||||
// no validation required on inline body
|
||||
{{ .ReceiverName }}.{{ pascalize .Name }} = {{ if and (not .Schema.IsBaseType) .IsNullable }}&{{ end }}body
|
||||
{{- end}}
|
||||
{{- else }}
|
||||
{{- if .IsInterface }}
|
||||
// no validation on generic interface
|
||||
{{ .ReceiverName }}.{{ pascalize .Name }} = {{ if and (not .Schema.IsBaseType) .IsNullable }}&{{ end }}body
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{ define "sliceparamvalidator"}}
|
||||
{{ if or .MinItems .MaxItems }}
|
||||
{{ camelize .Name }}Size := int64(len({{ if and (not .IsArray) (not .HasDiscriminator) (not .IsInterface) (not .IsStream) .IsNullable }}*{{ end }}{{ if and .Child (not (hasPrefix .ValueExpression "o.")) }}{{ .Child.ValueExpression }}C{{ else }}{{ .ValueExpression }}{{ end }}))
|
||||
{{ end }}
|
||||
{{ if .MinItems }}
|
||||
// {{ .ItemsDepth }}minItems: {{ .MinItems }}
|
||||
if err := validate.MinItems({{ .Path }}, {{ printf "%q" .Location }}, {{ camelize .Name }}Size, {{ .MinItems }}); err != nil {
|
||||
return err
|
||||
}
|
||||
{{ end }}
|
||||
{{ if .MaxItems }}
|
||||
// {{ .ItemsDepth }}maxItems: {{ .MaxItems }}
|
||||
if err := validate.MaxItems({{ .Path }}, {{ printf "%q" .Location }}, {{ camelize .Name }}Size, {{.MaxItems}}); err != nil {
|
||||
return err
|
||||
}
|
||||
{{ end }}
|
||||
{{ if .UniqueItems }}
|
||||
// {{ .ItemsDepth }}uniqueItems: true
|
||||
if err := validate.UniqueItems({{ .Path }}, {{ printf "%q" .Location }}, {{ if and (not .IsArray) (not .HasDiscriminator) (not .IsInterface) (not .IsStream) .IsNullable }}*{{ end }}{{ if and .Child (not ( hasPrefix .ValueExpression "o." )) }}{{ .Child.ValueExpression }}C{{ else }}{{ .ValueExpression }}{{ end }}); err != nil {
|
||||
return err
|
||||
}
|
||||
{{ end }}
|
||||
{{ if .Enum }}
|
||||
// {{ .ItemsDepth }}Enum: {{ .Enum }}
|
||||
if err := validate.EnumCase(
|
||||
{{- .Path }}, {{ printf "%q" .Location }},
|
||||
{{- if and (not .IsArray) (not .HasDiscriminator) (not .IsInterface) (not .IsStream) .IsNullable }}*{{ end -}}
|
||||
{{- if .Child -}}
|
||||
{{- if not ( hasPrefix .ValueExpression "o." ) -}}
|
||||
{{- .Child.ValueExpression }}C{{- if .IsCustomFormatter }}.String(){{ end -}}
|
||||
{{- else -}}
|
||||
{{- .ValueExpression -}}{{- if .Child.IsCustomFormatter }}.String(){{ end -}}
|
||||
{{- end -}}
|
||||
{{- end -}},
|
||||
{{- printf "%#v" .Enum -}}, {{ if .IsEnumCI }}false{{ else }}true{{ end }}); err != nil {
|
||||
return err
|
||||
}
|
||||
{{ end }}
|
||||
{{/* BEGIN CUSTOM BY AAA */}}
|
||||
{{- if .IsArray }}{{/* slice validations */}}
|
||||
for {{ if .Child.NeedsIndex }}{{ .IndexVar }}{{ else }}_{{ end }}, {{ varname .Child.ValueExpression }}V := range {{ varname .Child.ValueExpression }}C {
|
||||
{{- if .Child.IsArray }}{{/* recursive resolution of arrays in params */}}
|
||||
{{- if not .Child.SkipParse }}
|
||||
// {{ .Child.ItemsDepth }}CollectionFormat: {{ .Child.CollectionFormat }}
|
||||
{{- end }}
|
||||
{{ .Child.Child.ValueExpression }}C := {{ if .Child.SkipParse }}{{ varname .Child.ValueExpression }}V{{ else }}swag.SplitByFormat({{ varname .Child.ValueExpression }}V, {{ printf "%q" .Child.CollectionFormat }}){{ end }}
|
||||
{{- if .Child.HasSliceValidations }}
|
||||
{{- template "sliceparamvalidator" .Child }}
|
||||
{{- end }}
|
||||
{{- else if .Child.IsMap }}{{/* simple map in items (possible with body params)*/}}
|
||||
{{ .Child.Child.ValueExpression }}C := {{ varname .Child.ValueExpression }}V
|
||||
{{- template "mapparamvalidator" .Child }}
|
||||
{{- else }}{{/* non-array && non-map type in items */}}
|
||||
{{- if and .Child.IsNullable (not .IsMapNullOverride) }}
|
||||
if {{ varname .Child.ValueExpression }}V == nil {
|
||||
{{- if .Child.Required }}
|
||||
return errors.Required({{ .Child.Path }}, {{ printf "%q" .Child.Location }}, {{ varname .Child.ValueExpression }}V)
|
||||
{{- else }}
|
||||
continue
|
||||
{{- end }}
|
||||
}
|
||||
{{- end }}
|
||||
{{- template "childvalidator" .Child }}
|
||||
{{- end }}
|
||||
}
|
||||
{{ end }}
|
||||
{{/* END CUSTOM BY AAA */}}
|
||||
{{ end }}
|
||||
|
||||
{{- define "childvalidator" }}
|
||||
{{- if .Converter }}
|
||||
{{- if ne .SwaggerFormat "" }}
|
||||
// {{ .ItemsDepth }}Format: {{ printf "%q" .SwaggerFormat }}
|
||||
{{- end }}
|
||||
{{ varname .ValueExpression }}, err := {{ .Converter }}({{ varname .ValueExpression }}V)
|
||||
if err != nil {
|
||||
return errors.InvalidType({{ .Path }}, {{ printf "%q" .Location }}, "{{ .GoType }}", {{ varname .ValueExpression }})
|
||||
}
|
||||
{{- else if and .IsCustomFormatter (not .SkipParse) }}{{/* parsing is skipped for simple body items */}}
|
||||
// {{ .ItemsDepth }}Format: {{ printf "%q" .SwaggerFormat }}
|
||||
value, err := formats.Parse({{ printf "%q" .SwaggerFormat }},{{ varname .ValueExpression }}V)
|
||||
if err != nil {
|
||||
return errors.InvalidType({{ .Path }}, {{ printf "%q" .Location }}, "{{ .GoType }}", value)
|
||||
}
|
||||
{{ varname .ValueExpression }} := *(value.(*{{.GoType}}))
|
||||
{{- else if and .IsComplexObject .HasValidations }}{{/* dedicated to nested body params */}}
|
||||
{{ varname .ValueExpression }} := {{ varname .ValueExpression }}V
|
||||
if err := {{ .ValueExpression }}.Validate(formats) ; err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName({{ .Path }})
|
||||
}
|
||||
return err
|
||||
}
|
||||
{{- else }}
|
||||
{{ varname .ValueExpression }} := {{ varname .ValueExpression }}V
|
||||
{{- end }}
|
||||
{{ template "propertyparamvalidator" . }}
|
||||
{{- end }}
|
||||
|
||||
{{- define "mapparamvalidator" }}
|
||||
{{- if and .Child.HasValidations (not (or .Child.IsInterface .Child.IsStream)) }}
|
||||
|
||||
// validations for map
|
||||
{{- else }}
|
||||
|
||||
// map has no validations: copying all elements
|
||||
{{- end }}
|
||||
{{ varname .Child.ValueExpression }}R := make({{ .GoType }},len({{ .Child.ValueExpression }}C))
|
||||
for {{ .KeyVar }}, {{ .Child.ValueExpression }}V := range {{ .Child.ValueExpression}}C {
|
||||
{{- if .Child.IsArray }}
|
||||
{{ .Child.Child.ValueExpression }}C := {{ varname .Child.ValueExpression }}V
|
||||
{{- if .Child.HasSliceValidations }}
|
||||
{{- template "sliceparamvalidator" .Child }}
|
||||
{{- end }}
|
||||
{{- template "sliceparambinder" .Child }}
|
||||
{{- else if .Child.IsMap }}
|
||||
{{ .Child.Child.ValueExpression }}C := {{ varname .Child.ValueExpression }}V
|
||||
{{ template "mapparamvalidator" .Child }}
|
||||
{{- else }}
|
||||
{{- if and .Child.IsNullable }}
|
||||
if {{ varname .Child.ValueExpression }}V == nil {
|
||||
{{- if .Child.Required }}
|
||||
return errors.Required({{ .Child.Path }}, {{ printf "%q" .Child.Location }}, {{ varname .Child.ValueExpression }}V)
|
||||
{{- else }}
|
||||
continue
|
||||
{{- end }}
|
||||
}
|
||||
{{- end }}
|
||||
{{- template "childvalidator" .Child }}
|
||||
{{- end }}
|
||||
{{ varname .Child.ValueExpression }}R[{{.KeyVar}}] = {{ varname .Child.ValueExpression }}{{ if or .Child.IsArray .Child.IsMap}}IR{{end}}
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
{{- define "propertyparamvalidator" }}
|
||||
{{/* BEGIN CUSTOM BY AAA */}}
|
||||
{{- if .IsNullable }}
|
||||
// Required: {{ if .Required }}true{{ else }}false{{ end }}
|
||||
if {{.ValueExpression}} == nil {
|
||||
{{- if .Required }}
|
||||
return errors.Required({{ printf "%q" (camelize .Name) }}, {{ printf "%q" .Location }}, "")
|
||||
{{- else }}
|
||||
return nil
|
||||
{{- end }}
|
||||
}
|
||||
{{- end }}
|
||||
{{- if .IsPrimitive }}
|
||||
{{ template "validationPrimitive" . }}
|
||||
{{- end }}
|
||||
{{- if and .IsCustomFormatter (not .IsStream) (not .IsBase64) }}
|
||||
if err := validate.FormatOf({{.Path}}, "{{.Location}}", "{{.SwaggerFormat}}", {{ if .IsNullable }}(*{{ end }}{{.ValueExpression}}{{ if .IsNullable }}){{ end }}{{ if .IsCustomFormatter }}.String(){{ end }}, formats); err != nil {
|
||||
return err
|
||||
}
|
||||
{{- end }}
|
||||
{{- if .IsArray }}{{/* slice validations */}}
|
||||
{{ varname .Child.ValueExpression }}C := {{ .ValueExpression }}
|
||||
{{/* END CUSTOM BY AAA */}}
|
||||
{{ template "sliceparamvalidator" . }}
|
||||
{{- else if .IsMap }}
|
||||
{{ .Child.ValueExpression }}C := {{ varname .Child.ValueExpression }}V
|
||||
{{ template "mapparamvalidator" . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{ define "sliceparambinder" }}
|
||||
var {{ varname .Child.ValueExpression }}R {{ .GoType }}
|
||||
for {{ if .Child.NeedsIndex }}{{ .IndexVar }}{{ else }}_{{ end }}, {{ varname .Child.ValueExpression }}V := range {{ varname .Child.ValueExpression }}C {
|
||||
{{- if .Child.IsArray }}{{/* recursive resolution of arrays in params */}}
|
||||
{{- if not .Child.SkipParse }}
|
||||
// {{ .Child.ItemsDepth }}CollectionFormat: {{ .Child.CollectionFormat }}
|
||||
{{- end }}
|
||||
{{ .Child.Child.ValueExpression }}C := {{ if .Child.SkipParse }}{{ varname .Child.ValueExpression }}V{{ else }}swag.SplitByFormat({{ varname .Child.ValueExpression }}V, {{ printf "%q" .Child.CollectionFormat }}){{ end }}
|
||||
{{- if .Child.HasSliceValidations }}
|
||||
{{- template "sliceparamvalidator" .Child }}
|
||||
{{- end }}
|
||||
if len({{ varname .Child.Child.ValueExpression }}C) > 0 {
|
||||
{{ template "sliceparambinder" .Child }}
|
||||
{{ varname .Child.ValueExpression }}R = append({{ varname .Child.ValueExpression }}R, {{ varname .Child.ValueExpression }}{{ if or .Child.IsArray .Child.IsMap }}IR{{end}})
|
||||
}
|
||||
{{- else if .Child.IsMap }}{{/* simple map in items (possible with body params)*/}}
|
||||
{{ .Child.Child.ValueExpression }}C := {{ varname .Child.ValueExpression }}V
|
||||
{{- template "mapparamvalidator" .Child }}
|
||||
{{ varname .Child.ValueExpression }}R = append({{ varname .Child.ValueExpression }}R, {{ varname .Child.ValueExpression }}{{ if or .Child.IsArray .Child.IsMap }}IR{{end}})
|
||||
{{- else }}{{/* non-array && non-map type in items */}}
|
||||
{{- if and .Child.IsNullable (not .IsMapNullOverride) }}
|
||||
if {{ varname .Child.ValueExpression }}V == nil {
|
||||
{{- if .Child.Required }}
|
||||
return errors.Required({{ .Child.Path }}, {{ printf "%q" .Child.Location }}, {{ varname .Child.ValueExpression }}V)
|
||||
{{- else }}
|
||||
continue
|
||||
{{- end }}
|
||||
}
|
||||
{{- end }}
|
||||
{{- template "childvalidator" .Child }}
|
||||
{{ varname .Child.ValueExpression }}R = append({{ varname .Child.ValueExpression }}R, {{ varname .Child.ValueExpression }}{{ if or .Child.IsArray .Child.IsMap }}IR{{end}})
|
||||
{{- end }}
|
||||
}
|
||||
{{ end }}
|
||||
|
||||
{{/* BEGIN CUSTOM BY AAA */}}
|
||||
{{- define "customsliceparamvalidator" }}
|
||||
{{- template "sliceparamvalidator" . -}}
|
||||
for _, {{ varname .Child.ValueExpression }}V := range {{ varname .Child.ValueExpression }}C {
|
||||
{{- if .Child.IsArray }}{{/* recursive resolution of arrays in params */}}
|
||||
{{ varname .Child.ValueExpression }}IC := {{ varname .Child.ValueExpression }}V
|
||||
{{- template "customsliceparamvalidator" .Child }}
|
||||
{{- else if .Child.IsCustomFormatter }}
|
||||
// Format: {{ .Child.SwaggerFormat }}
|
||||
if err := validate.FormatOf({{ .Path }}, {{ printf "%q" .Location }}, {{ printf "%q" .SwaggerFormat }}, {{ varname .Child.ValueExpression }}V.String(), formats); err != nil {
|
||||
res = append(res, errors.InvalidType({{ .Path }}, {{ printf "%q" .Location }}, {{ printf "%q" .GoType }}, {{ varname .Child.ValueExpression }}V))
|
||||
}
|
||||
{{- end -}}
|
||||
}
|
||||
{{- end }}
|
||||
{{/* END CUSTOM BY AAA */}}
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
|
||||
{{ if .Copyright -}}// {{ comment .Copyright -}}{{ end }}
|
||||
|
||||
|
||||
package {{ .Package }}
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/runtime/security"
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/go-openapi/validate"
|
||||
|
||||
{{ imports .DefaultImports }}
|
||||
{{ imports .Imports }}
|
||||
)
|
||||
|
||||
// New{{ pascalize .Name }}Params creates a new {{ pascalize .Name }}Params object
|
||||
{{ if .Params.HasSomeDefaults -}}
|
||||
// with the default values initialized.{{ else -}}
|
||||
// no default values defined in spec.
|
||||
{{- end }}
|
||||
func New{{ pascalize .Name }}Params() {{ pascalize .Name }}Params {
|
||||
{{ if .Params.HasSomeDefaults }}
|
||||
var (
|
||||
// initialize parameters with default values
|
||||
{{ range .Params }}
|
||||
{{ if .HasDefault -}}
|
||||
{{ if not .IsFileParam }}{{ varname .ID}}Default =
|
||||
{{- if and .IsPrimitive .IsCustomFormatter (not (stringContains .Zero "(\"" )) }}{{ .Zero }}{{/* strfmt type initializer requires UnmarshalText(), e.g. Date, Datetime, Duration */}}
|
||||
{{- else if and .IsPrimitive .IsCustomFormatter (stringContains .Zero "(\"" ) }}{{.GoType}}({{- printf "%#v" .Default }}){{/* strfmt type initializer takes string */}}
|
||||
{{- else if and .IsPrimitive (not .IsCustomFormatter) -}}{{.GoType}}({{- printf "%#v" .Default }}){{/* regular go primitive type initializer */}}
|
||||
{{- else if .IsArray -}}{{- /* Do not initialize from possible defaults in nested arrays */ -}}
|
||||
{{- if and .Child.IsPrimitive .Child.IsCustomFormatter }}{{ .Zero }}{{/* initialization strategy with UnmarshalText() */}}
|
||||
{{- else if .Child.IsArray -}}{{ .Zero }}{{/* initialization strategy with json.Unmarshal() */}}
|
||||
{{- else if and .Child.IsPrimitive (not .Child.IsCustomFormatter) -}}{{.GoType}}{{- arrayInitializer .Default }}{{/* regular go primitive type initializer: simple slice initializer */}}
|
||||
{{- else }}{{ printf "%#v" .Default }}{{/* all other cases (e.g. schema) [should not occur] */}}
|
||||
{{- end }}
|
||||
{{- else }}{{ printf "%#v" .Default }}{{/* case .Schema */}}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
)
|
||||
|
||||
{{ range .Params }}{{ if .HasDefault -}}{{- /* carry on UnmarshalText initialization strategy */ -}}
|
||||
{{ if and .IsPrimitive .IsCustomFormatter (not (stringContains .Zero "(\"")) }}{{ varname .ID}}Default.UnmarshalText([]byte({{ printf "%q" .Default }}))
|
||||
{{ else if .IsArray -}}
|
||||
{{ if or ( and .Child.IsPrimitive .Child.IsCustomFormatter ) .Child.IsArray -}}
|
||||
if err := json.Unmarshal([]byte(`{{printf "%s" (json .Default)}}`), &{{ varname .ID }}Default); err != nil {
|
||||
// panics if specification is invalid
|
||||
msg := fmt.Sprintf("invalid default value for parameter {{ varname .ID }}: %v",err)
|
||||
panic(msg)
|
||||
}
|
||||
{{ end -}}
|
||||
{{- end }}
|
||||
{{ end -}}
|
||||
{{- end }}
|
||||
{{ end }}
|
||||
return {{ pascalize .Name }}Params{ {{ range .Params }}{{ if .HasDefault }}
|
||||
{{ pascalize .ID}}: {{ if and (not .IsArray) (not .HasDiscriminator) (not .IsInterface) (not .IsStream) .IsNullable }}&{{ end }}{{ varname .ID }}Default,
|
||||
{{ end }}{{ end }} }
|
||||
}
|
||||
|
||||
// {{ pascalize .Name }}Params contains all the bound params for the {{ humanize .Name }} operation
|
||||
// typically these are obtained from a http.Request
|
||||
//
|
||||
// swagger:parameters {{ .Name }}
|
||||
type {{ pascalize .Name }}Params struct {
|
||||
|
||||
// HTTP Request Object
|
||||
HTTPRequest *http.Request `json:"-"`
|
||||
|
||||
{{ range .Params }}/*{{ if .Description }}{{ blockcomment .Description }}{{ end }}{{ if .Required }}
|
||||
Required: true{{ end }}{{ if .Maximum }}
|
||||
Maximum: {{ if .ExclusiveMaximum }}< {{ end }}{{ .Maximum }}{{ end }}{{ if .Minimum }}
|
||||
Minimum: {{ if .ExclusiveMinimum }}> {{ end }}{{ .Minimum }}{{ end }}{{ if .MultipleOf }}
|
||||
Multiple Of: {{ .MultipleOf }}{{ end }}{{ if .MaxLength }}
|
||||
Max Length: {{ .MaxLength }}{{ end }}{{ if .MinLength }}
|
||||
Min Length: {{ .MinLength }}{{ end }}{{ if .Pattern }}
|
||||
Pattern: {{ .Pattern }}{{ end }}{{ if .MaxItems }}
|
||||
Max Items: {{ .MaxItems }}{{ end }}{{ if .MinItems }}
|
||||
Min Items: {{ .MinItems }}{{ end }}{{ if .UniqueItems }}
|
||||
Unique: true{{ end }}{{ if .Location }}
|
||||
In: {{ .Location }}{{ end }}{{ if .CollectionFormat }}
|
||||
Collection Format: {{ .CollectionFormat }}{{ end }}{{ if .HasDefault }}
|
||||
Default: {{ printf "%#v" .Default }}{{ end }}
|
||||
*/
|
||||
{{ if not .Schema }}{{ pascalize .ID }} {{ if and (not .IsArray) (not .HasDiscriminator) (not .IsInterface) (not .IsStream) .IsNullable }}*{{ end }}{{.GoType}}{{ else }}{{ pascalize .Name }} {{ if and (not .Schema.IsBaseType) .IsNullable (not .Schema.IsStream) }}*{{ end }}{{.GoType}}{{ end }}{{/* BEGIN CUSTOM BY AAA */}}{{ if .IsQueryParam }}`query:"{{ .Name }}"`{{ else if .IsPathParam }}`param:"{{ .Name }}"`{{ else if .IsFormParam }}`form:"{{ .Name }}"`{{ end }}{{/* END CUSTOM BY AAA */}}
|
||||
{{ end}}
|
||||
}
|
||||
|
||||
// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface
|
||||
// for simple values it will use straight method calls.
|
||||
//
|
||||
// To ensure default values, the struct must have been initialized with New{{ pascalize .Name }}Params() beforehand.
|
||||
func ({{ .ReceiverName }} *{{ pascalize .Name }}Params) BindRequest(r *http.Request, route *middleware.MatchedRoute) error {
|
||||
var res []error
|
||||
|
||||
{{ .ReceiverName }}.HTTPRequest = r
|
||||
|
||||
{{ if .HasQueryParams }}qs := runtime.Values(r.URL.Query()){{ end }}
|
||||
|
||||
{{ if .HasFormParams }}if err := r.ParseMultipartForm(32 << 20); err != nil {
|
||||
if err != http.ErrNotMultipart {
|
||||
return errors.New(400,"%v",err)
|
||||
} else if err := r.ParseForm(); err != nil {
|
||||
return errors.New(400,"%v",err)
|
||||
}
|
||||
}{{ if .HasFormValueParams }}
|
||||
fds := runtime.Values(r.Form)
|
||||
{{ end }}{{ end }}
|
||||
|
||||
{{ range .Params }}
|
||||
{{ if not .IsArray -}}
|
||||
{{ if .IsQueryParam }}q{{ pascalize .Name }}, qhk{{ pascalize .Name }}, _ := qs.GetOK({{ .Path }})
|
||||
if err := {{ .ReceiverName }}.bind{{ pascalize .ID }}(q{{ pascalize .Name }}, qhk{{ pascalize .Name }}, route.Formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
{{ else if .IsPathParam }}r{{ pascalize .Name }}, rhk{{ pascalize .Name }}, _ := route.Params.GetOK({{ .Path }})
|
||||
if err := {{ .ReceiverName }}.bind{{ pascalize .ID }}(r{{ pascalize .Name }}, rhk{{ pascalize .Name }}, route.Formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
{{ else if .IsHeaderParam }}if err := {{ .ReceiverName }}.bind{{ pascalize .ID }}(r.Header[http.CanonicalHeaderKey({{ .Path }})], true, route.Formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
{{ else if .IsFormParam -}}
|
||||
{{if .IsFileParam }}{{ camelize .Name }}, {{ camelize .Name }}Header, err := r.FormFile({{ .Path }})
|
||||
if err != nil {{ if .IsNullable }}&& err != http.ErrMissingFile{{ end }}{
|
||||
res = append(res, errors.New(400, "reading file %q failed: %v", {{ printf "%q" (camelize .Name) }}, err))
|
||||
{{ if .IsNullable }}} else if err == http.ErrMissingFile {
|
||||
// no-op for missing but optional file parameter
|
||||
{{ end }}} else if err := {{ .ReceiverName }}.bind{{ pascalize .ID }}({{ camelize .Name }}, {{ camelize .Name }}Header); err != nil {
|
||||
{{ if .Required }}// Required: true{{ printf "\n" }}{{end }}res = append(res, err)
|
||||
} else {
|
||||
{{ .ReceiverName }}.{{ pascalize .Name }} = &runtime.File{Data: {{ camelize .Name }}, Header: {{ camelize .Name }}Header}
|
||||
}
|
||||
{{ else }}fd{{ pascalize .Name }}, fdhk{{ pascalize .Name }}, _ := fds.GetOK({{ .Path }})
|
||||
if err := {{ .ReceiverName }}.bind{{ pascalize .ID }}(fd{{ pascalize .Name }}, fdhk{{ pascalize .Name }}, route.Formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
{{ end }}{{/* end .FileParam */}}
|
||||
{{ end }}{{/* end not .Array */}}
|
||||
{{ else if .IsArray -}}
|
||||
{{ if .IsQueryParam }}q{{ pascalize .Name }}, qhk{{ pascalize .Name }}, _ := qs.GetOK({{ .Path }})
|
||||
if err := {{ .ReceiverName }}.bind{{ pascalize .ID }}(q{{ pascalize .Name }}, qhk{{ pascalize .Name }}, route.Formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
{{ else if .IsPathParam }}r{{ pascalize .Name }}, rhk{{ pascalize .Name }}, _ := route.Params.GetOK({{ .Path }})
|
||||
if err := {{ .ReceiverName }}.bind{{ pascalize .ID }}(r{{ pascalize .Name }}, rhk{{ pascalize .Name }}, route.Formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
{{ else if .IsHeaderParam }}if err := {{ .ReceiverName }}.bind{{ pascalize .ID }}(r.Header[http.CanonicalHeaderKey({{ .Path }})], true, route.Formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
{{ else if and .IsFormParam }}fd{{ pascalize .Name }}, fdhk{{ pascalize .Name }}, _ := fds.GetOK({{ .Path }})
|
||||
if err := {{ .ReceiverName }}.bind{{ pascalize .ID }}(fd{{ pascalize .Name }}, fdhk{{ pascalize .Name }}, route.Formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
{{ end }}{{ end }}
|
||||
{{ if and .IsBodyParam .Schema -}}
|
||||
if runtime.HasBody(r) {
|
||||
{{- if .Schema.IsStream }}
|
||||
{{ .ReceiverName }}.{{ pascalize .Name }} = r.Body
|
||||
{{- else }}
|
||||
defer r.Body.Close()
|
||||
{{- if and .Schema.IsBaseType .Schema.IsExported }}
|
||||
body, err := {{ toPackageName .ModelsPackage }}.Unmarshal{{ dropPackage .GoType }}{{ if .IsArray }}Slice{{ end }}(r.Body, route.Consumer)
|
||||
if err != nil {
|
||||
{{- if .Required }}
|
||||
if err == io.EOF {
|
||||
err = errors.Required({{ .Path }}, {{ printf "%q" .Location }}, "")
|
||||
}
|
||||
{{- end }}
|
||||
res = append(res, err)
|
||||
{{- else }}
|
||||
var body {{ .GoType }}
|
||||
if err := route.Consumer.Consume(r.Body, &body); err != nil {
|
||||
{{- if .Required }}
|
||||
if err == io.EOF {
|
||||
res = append(res, errors.Required({{ printf "%q" (camelize .Name) }}, {{ printf "%q" .Location }}, ""))
|
||||
} else {
|
||||
{{- end }}
|
||||
res = append(res, errors.NewParseError({{ printf "%q" (camelize .Name) }}, {{ printf "%q" .Location }}, "", err))
|
||||
{{- if .Required }}
|
||||
}
|
||||
{{- end -}}
|
||||
{{- end }}
|
||||
} else {
|
||||
{{- template "bodyvalidator" . }}
|
||||
}
|
||||
{{- end }}
|
||||
}
|
||||
{{- if .Required }} else {
|
||||
res = append(res, errors.Required({{ printf "%q" (camelize .Name) }}, {{ printf "%q" .Location }}, ""))
|
||||
}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
{{/* BEGIN CUSTOM BY AAA */}}
|
||||
func ({{ .ReceiverName }} *{{ pascalize .Name }}Params) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
{{ range .Params }}
|
||||
// {{ .Name }}
|
||||
// Required: {{ .Required }}
|
||||
{{ if .IsQueryParam }}// AllowEmptyValue: {{ .AllowEmptyValue }}{{ end -}}{{ if .IsPathParam }}// Parameter is provided by construction from the route{{ end -}}
|
||||
{{/* file validations */}}
|
||||
{{- if .IsFileParam }}
|
||||
{{- if or .MinLength .MaxLength }}
|
||||
size, _ := {{ .ReceiverName }}.{{ .ID }}.Seek(0, io.SeekEnd)
|
||||
file.Seek(0, io.SeekStart)
|
||||
{{- end }}
|
||||
{{- if .MinLength}}
|
||||
if size < {{.MinLength}} {
|
||||
res = append(res, errors.ExceedsMinimum({{ .Path }}, {{ printf "%q" .Location }}, {{ .MinLength }}, false))
|
||||
}
|
||||
{{- end }}
|
||||
{{- if .MaxLength}}
|
||||
if size > {{.MaxLength}} {
|
||||
res = append(res, errors.ExceedsMaximum({{ .Path }}, {{ printf "%q" .Location }}, {{ .MaxLength }}, false))
|
||||
}
|
||||
{{- end }}
|
||||
{{/* body validations, currently not used */}}
|
||||
{{- else if .IsBodyParam }}
|
||||
// body is validated in endpoint
|
||||
//if err := {{ .ReceiverName }}.{{ .ID }}.Validate(formats); err != nil {
|
||||
// res = append(res, err)
|
||||
//}
|
||||
{{/* validate for arrays */}}
|
||||
{{- else if .IsArray }}
|
||||
{{- if .HasSliceValidations }}
|
||||
if err := {{ .ReceiverName }}.validate{{ pascalize .ID }}(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
{{- else if or .Child.IsCustomFormatter .Child.IsArray }}
|
||||
{{ varname .Child.ValueExpression }}C := {{ .ValueExpression }}
|
||||
{{- template "customsliceparamvalidator" . }}
|
||||
{{- end }}
|
||||
{{/* path and query validaionts */}}
|
||||
{{- else if not .IsBodyParam }}
|
||||
{{/* if required check if exists */}}
|
||||
{{- if and (not .IsPathParam) .Required (not .AllowEmptyValue) -}}
|
||||
if err := validate.Required({{ .Path }}, {{ printf "%q" .Location }}, {{ .ReceiverName }}.{{ .ID }}); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
{{- end }}
|
||||
{{/* if a validation method exists for the property exists, call it */}}
|
||||
{{- if .HasValidations }}
|
||||
if err := {{ .ReceiverName }}.validate{{ pascalize .ID }}(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
{{- else if .IsCustomFormatter }}// Format: {{ .SwaggerFormat }}
|
||||
if err := validate.FormatOf({{ .Path }}, {{ printf "%q" .Location }}, {{ printf "%q" .SwaggerFormat }}, {{ .ReceiverName }}.{{ .ID }}, formats); err != nil {
|
||||
res = append(res, errors.InvalidType({{ .Path }}, {{ printf "%q" .Location }}, {{ printf "%q" .GoType }}, {{ .ReceiverName }}.{{ .ID }}))
|
||||
}
|
||||
{{- end }}
|
||||
{{/* in case of missing validation a TODO comment is added */}}
|
||||
{{- else }}
|
||||
// TODO add case in template
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
{{/* END CUSTOM BY AAA */}}
|
||||
|
||||
{{- $className := (pascalize .Name) }}
|
||||
{{ range .Params }}
|
||||
{{- if .IsFileParam }}
|
||||
// bind{{ pascalize .ID }} binds file parameter {{ .ID }}.
|
||||
//
|
||||
// The only supported validations on files are MinLength and MaxLength
|
||||
func ({{ .ReceiverName }} *{{ $className }}Params) bind{{ pascalize .ID }}(file multipart.File, header *multipart.FileHeader) error {
|
||||
{{- if or .MinLength .MaxLength }}
|
||||
size, _ := file.Seek(0, io.SeekEnd)
|
||||
file.Seek(0, io.SeekStart)
|
||||
{{- end }}
|
||||
{{- if .MinLength}}
|
||||
if size < {{.MinLength}} {
|
||||
return errors.ExceedsMinimum({{ .Path }}, {{ printf "%q" .Location }}, {{ .MinLength }}, false)
|
||||
}
|
||||
{{- end }}
|
||||
{{- if .MaxLength}}
|
||||
if size > {{.MaxLength}} {
|
||||
return errors.ExceedsMaximum({{ .Path }}, {{ printf "%q" .Location }}, {{ .MaxLength }}, false)
|
||||
}
|
||||
{{- end }}
|
||||
return nil
|
||||
}
|
||||
{{- else if not .IsBodyParam }}
|
||||
{{- if or .IsPrimitive .IsCustomFormatter }}
|
||||
// bind{{ pascalize .ID }} binds and validates parameter {{ .ID }} from {{ .Location }}.
|
||||
func ({{ .ReceiverName }} *{{ $className }}Params) bind{{ pascalize .ID }}(rawData []string, hasKey bool, formats strfmt.Registry) error {
|
||||
{{- if and (not .IsPathParam) .Required }}
|
||||
if !hasKey {
|
||||
return errors.Required({{ .Path }}, {{ printf "%q" .Location }}, rawData)
|
||||
}
|
||||
{{- end }}
|
||||
var raw string
|
||||
if len(rawData) > 0 {
|
||||
raw = rawData[len(rawData)-1]
|
||||
}
|
||||
|
||||
// Required: {{ .Required }}
|
||||
{{ if .IsQueryParam }}// AllowEmptyValue: {{ .AllowEmptyValue }}{{ end }}{{ if .IsPathParam }}// Parameter is provided by construction from the route{{ end }}
|
||||
{{ if and (not .IsPathParam) .Required (not .AllowEmptyValue) -}}
|
||||
if err := validate.RequiredString({{ .Path }}, {{ printf "%q" .Location }}, raw); err != nil {
|
||||
return err
|
||||
}
|
||||
{{ else if and ( not .IsPathParam ) (or (not .Required) .AllowEmptyValue) -}}
|
||||
if raw == "" { // empty values pass all other validations{{ if .HasDefault }}
|
||||
// Default values have been previously initialized by New{{ $className }}Params(){{ end }}
|
||||
return nil
|
||||
}
|
||||
{{ end }}
|
||||
{{ if .Converter }}value, err := {{ .Converter }}(raw)
|
||||
if err != nil {
|
||||
return errors.InvalidType({{ .Path }}, {{ printf "%q" .Location }}, {{ printf "%q" .GoType }}, raw)
|
||||
}
|
||||
{{ .ValueExpression }} = {{ if .IsNullable }}&{{ end }}value
|
||||
{{ else if .IsCustomFormatter }}// Format: {{ .SwaggerFormat }}
|
||||
value, err := formats.Parse({{ printf "%q" .SwaggerFormat }}, raw)
|
||||
if err != nil {
|
||||
return errors.InvalidType({{ .Path }}, {{ printf "%q" .Location }}, {{ printf "%q" .GoType }}, raw)
|
||||
}
|
||||
{{ .ValueExpression }} = {{ if or .IsArray .HasDiscriminator .IsFileParam .IsStream (not .IsNullable) }}*{{ end }}(value.(*{{ .GoType }}))
|
||||
{{else}}{{ .ValueExpression }} = {{ if .IsNullable }}&{{ end }}raw
|
||||
{{ end }}
|
||||
{{if .HasValidations }}if err := {{ .ReceiverName }}.validate{{ pascalize .ID }}(formats); err != nil {
|
||||
return err
|
||||
}
|
||||
{{ end }}
|
||||
return nil
|
||||
}
|
||||
{{- else if .IsArray }}
|
||||
// bind{{ pascalize .ID }} binds and validates array parameter {{ .ID }} from {{ .Location }}.
|
||||
//
|
||||
// Arrays are parsed according to CollectionFormat: "{{ .CollectionFormat }}" (defaults to "csv" when empty).
|
||||
func ({{ .ReceiverName }} *{{ $className }}Params) bind{{ pascalize .ID }}(rawData []string, hasKey bool, formats strfmt.Registry) error {
|
||||
{{if .Required }}if !hasKey {
|
||||
return errors.Required({{ .Path }}, {{ printf "%q" .Location }}, rawData)
|
||||
}
|
||||
{{ end }}
|
||||
{{ if eq .CollectionFormat "multi" -}}
|
||||
// CollectionFormat: {{ .CollectionFormat }}
|
||||
{{ varname .Child.ValueExpression }}C := rawData
|
||||
{{ else -}}
|
||||
var qv{{ pascalize .Name }} string
|
||||
if len(rawData) > 0 {
|
||||
qv{{ pascalize .Name }} = rawData[len(rawData) - 1]
|
||||
}
|
||||
|
||||
// CollectionFormat: {{ .CollectionFormat }}
|
||||
{{ varname .Child.ValueExpression }}C := swag.SplitByFormat(qv{{ pascalize .Name }}, {{ printf "%q" .CollectionFormat }}){{ end }}
|
||||
{{if and .Required (not .AllowEmptyValue) }}
|
||||
if len({{ varname .Child.ValueExpression }}C) == 0 {
|
||||
return errors.Required({{ .Path }}, {{ printf "%q" .Location }}, {{ varname .Child.ValueExpression }}C)
|
||||
}
|
||||
{{ else }}if len({{ varname .Child.ValueExpression }}C) == 0 { {{ if .HasDefault }}
|
||||
// Default values have been previously initialized by New{{ $className }}Params(){{ end }}
|
||||
return nil
|
||||
} {{- end }}
|
||||
{{ template "sliceparambinder" . }}
|
||||
{{ .ValueExpression }} = {{ varname .Child.ValueExpression }}R
|
||||
{{- if .HasSliceValidations }}
|
||||
if err := {{ .ReceiverName }}.validate{{ pascalize .ID }}(formats); err != nil {
|
||||
return err
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
return nil
|
||||
}
|
||||
{{ end }}
|
||||
{{ if or (and (not .IsArray) .HasValidations) (and .IsArray .HasSliceValidations) }}
|
||||
// validate{{ pascalize .ID }} carries on validations for parameter {{ .ID }}
|
||||
func ({{ .ReceiverName }} *{{ $className }}Params) validate{{ pascalize .ID }}(formats strfmt.Registry) error {
|
||||
{{ template "propertyparamvalidator" . }}
|
||||
return nil
|
||||
}
|
||||
{{ end }}
|
||||
{{- else if .IsBodyParam }}{{/* validation method for inline body parameters with validations */}}
|
||||
{{- if and .HasSimpleBodyParams (not .HasModelBodyItems) (not .HasModelBodyMap) }}
|
||||
{{- if .Schema.HasValidations }}
|
||||
// validate{{ pascalize .ID }}Body validates an inline body parameter
|
||||
func ({{ .ReceiverName }} *{{ $className }}Params) validate{{ pascalize .ID }}Body(formats strfmt.Registry) error {
|
||||
{{- if .IsArray }}
|
||||
{{- if .HasSliceValidations }}
|
||||
{{- template "sliceparamvalidator" . }}
|
||||
{{- end }}
|
||||
{{- if .Child.HasValidations }}
|
||||
{{ varname .Child.ValueExpression }}C := {{ .ValueExpression }}
|
||||
{{ template "sliceparambinder" . }}
|
||||
{{ .ValueExpression }} = {{ varname .Child.ValueExpression }}R
|
||||
{{- end }}
|
||||
{{- else if .IsMap }}
|
||||
{{ varname .Child.ValueExpression }}C := {{ .ValueExpression }}
|
||||
{{ template "mapparamvalidator" . }}
|
||||
{{ .ValueExpression }} = {{ varname .Child.ValueExpression }}R
|
||||
{{- else }}
|
||||
{{ template "propertyparamvalidator" . }}
|
||||
{{- end }}
|
||||
return nil
|
||||
}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{ end }}
|
||||
Reference in New Issue
Block a user