info:
  description: zrok client access
  title: zrok
  version: 0.3.0

basePath: /api/v1

securityDefinitions:
  key:
    type: apiKey
    in: header
    name: x-token

paths:
  #
  # account
  #
  /changePassword:
    post:
      tags:
        - account
      security:
        - key: []
      operationId: changePassword
      parameters:
        - name: body
          in: body
          schema:
            $ref: '#/definitions/changePasswordRequest'
      responses:
        200:
          description: changed password
        400:
          description: password not changed
        401:
          description: unauthorized
        422:
          description: password validation failure
          schema:
            $ref: '#/definitions/errorMessage'
        500:
          description: internal server error

  /invite:
    post:
      tags:
        - account
      operationId: invite
      parameters:
        - name: body
          in: body
          schema:
            $ref: "#/definitions/inviteRequest"
      responses:
        201:
          description: invitation created
        400:
          description: invitation not created (already exists)
          schema:
            $ref: '#/definitions/errorMessage'
        401:
          description: unauthorized
        500:
          description: internal server error

  /login:
    post:
      tags:
        - account
      operationId: login
      parameters:
        - name: body
          in: body
          schema:
            $ref: "#/definitions/loginRequest"
      responses:
        200:
          description: login successful
          schema:
            $ref: "#/definitions/loginResponse"
        401:
          description: invalid login

  /regenerateToken:
    post:
      tags:
        - account
      security:
        - key: []
      operationId: regenerateToken
      parameters:
        - name: body
          in: body
          schema:
            properties:
              emailAddress:
                type: string
      responses:
        200:
          description: regenerate account token
          schema:
            properties:
              token:
                type: string
        404:
          description: account not found
        500:
          description: internal server error

  /register:
    post:
      tags:
        - account
      operationId: register
      parameters:
        - name: body
          in: body
          schema:
            $ref: "#/definitions/registerRequest"
      responses:
        200:
          description: account created
          schema:
            $ref: "#/definitions/registerResponse"
        404:
          description: request not found
        422:
          description: password validation failure
          schema:
            $ref: '#/definitions/errorMessage'
        500:
          description: internal server error

  /resetPassword:
    post:
      tags:
        - account
      operationId: resetPassword
      parameters:
        - name: body
          in: body
          schema:
            $ref: "#/definitions/resetPasswordRequest"
      responses:
        200:
          description: password reset
        404:
          description: request not found
        422:
          description: password validation failure
          schema:
            $ref: '#/definitions/errorMessage'
        500:
          description: internal server error

  /resetPasswordRequest:
    post:
      tags:
        - account
      operationId: resetPasswordRequest
      parameters:
        - name: body
          in: body
          schema:
            properties:
              emailAddress:
                type: string
      responses:
        201:
          description: forgot password request created
        400:
          description: forgot password request not created
        500:
          description: internal server error

  /verify:
    post:
      tags:
        - account
      operationId: verify
      parameters:
        - name: body
          in: body
          schema:
            $ref: "#/definitions/verifyRequest"
      responses:
        200:
          description: token ready
          schema:
            $ref: "#/definitions/verifyResponse"
        404:
          description: token not found
        500:
          description: internal server error

  #
  # admin
  #
  /frontend:
    post:
      tags:
        - admin
      security:
        - key: []
      operationId: createFrontend
      parameters:
        - name: body
          in: body
          schema:
            $ref: "#/definitions/createFrontendRequest"
      responses:
        201:
          description: frontend created
          schema:
            $ref: "#/definitions/createFrontendResponse"
        400:
          description: bad request
        401:
          description: unauthorized
        404:
          description: not found
        500:
          description: internal server error
    patch:
      tags:
        - admin
      security:
        - key: []
      operationId: updateFrontend
      parameters:
        - name: body
          in: body
          schema:
            $ref: "#/definitions/updateFrontendRequest"
      responses:
        200:
          description: frontend updated
        401:
          description: unauthorized
        404:
          description: not found
        500:
          description: internal server error
    delete:
      tags:
        - admin
      security:
        - key: []
      operationId: deleteFrontend
      parameters:
        - name: body
          in: body
          schema:
            $ref: "#/definitions/deleteFrontendRequest"
      responses:
        200:
          description: frontend deleted
        401:
          description: unauthorized
        404:
          description: not found
        500:
          description: internal server error

  /frontends:
    get:
      tags:
        - admin
      security:
        - key: []
      operationId: listFrontends
      responses:
        200:
          description: ok
          schema:
            $ref: "#/definitions/publicFrontendList"
        401:
          description: unauthorized
        500:
          description: internal server error

  /identity:
    post:
      tags:
        - admin
      security:
        - key: []
      operationId: createIdentity
      parameters:
        - name: body
          in: body
          schema:
            properties:
              name:
                type: string
      responses:
        201:
          description: created
          schema:
            properties:
              identity:
                type: string
              cfg:
                type: string
        401:
          description: unauthorized
        500:
          description: internal server error

  /invite/token/generate:
    post:
      tags:
        - admin
      security:
        - key: []
      operationId: inviteTokenGenerate
      parameters:
        - name: body
          in: body
          schema:
            $ref: "#/definitions/inviteTokenGenerateRequest"
      responses:
        201:
          description: invitation tokens created
        400:
          description: invitation tokens not created
        401:
          description: unauthorized
        500:
          description: internal server error
  #
  # environment
  #
  /enable:
    post:
      tags:
        - environment
      security:
        - key: []
      operationId: enable
      parameters:
        - name: body
          in: body
          schema:
            $ref: "#/definitions/enableRequest"
      responses:
        201:
          description: environment enabled
          schema:
            $ref: "#/definitions/enableResponse"
        401:
          description: unauthorized
        404:
          description: account not found
        500:
          description: internal server error

  /disable:
    post:
      tags:
        - environment
      security:
        - key: []
      operationId: disable
      parameters:
        - name: body
          in: body
          schema:
            $ref: "#/definitions/disableRequest"
      responses:
        200:
          description: environment disabled
        401:
          description: invalid environment
        500:
          description: internal server error

  #
  # metadata
  #
  /configuration:
    get:
      tags:
        - metadata
      operationId: configuration
      responses:
        200:
          description: current configuration
          schema:
            $ref: "#/definitions/configuration"

  /detail/account:
    get:
      tags:
        - metadata
      security:
        - key: []
      operationId: getAccountDetail
      responses:
        200:
          description: ok
          schema:
            $ref: "#/definitions/environments"
        500:
          description: internal server error

  /detail/environment/{envZId}:
    get:
      tags:
        - metadata
      security:
        - key: []
      operationId: getEnvironmentDetail
      parameters:
        - name: envZId
          in: path
          type: string
          required: true
      responses:
        200:
          description: ok
          schema:
            $ref: "#/definitions/environmentAndResources"
        401:
          description: unauthorized
        404:
          description: not found
        500:
          description: internal server error

  /detail/frontend/{feId}:
    get:
      tags:
        - metadata
      security:
        - key: []
      operationId: getFrontendDetail
      parameters:
        - name: feId
          in: path
          type: integer
          required: true
      responses:
        200:
          description: ok
          schema:
            $ref: "#/definitions/frontend"
        401:
          description: unauthorized
        404:
          description: not found
        500:
          description: internal server error

  /detail/share/{shrToken}:
    get:
      tags:
        - metadata
      security:
        - key: []
      operationId: getShareDetail
      parameters:
        - name: shrToken
          in: path
          type: string
          required: true
      responses:
        200:
          description: ok
          schema:
            $ref: "#/definitions/share"
        401:
          description: unauthorized
        404:
          description: not found
        500:
          description: internal server error

  /overview:
    get:
      tags:
        - metadata
      security:
        - key: []
      operationId: overview
      responses:
        200:
          description: overview returned
          schema:
            $ref: "#/definitions/overview"
        500:
          description: internal server error
          schema:
            $ref: "#/definitions/errorMessage"

  /metrics/account:
    get:
      tags:
        - metadata
      security:
        - key: []
      operationId: getAccountMetrics
      parameters:
        - name: duration
          in: query
          type: string
      responses:
        200:
          description: account metrics
          schema:
            $ref: "#/definitions/metrics"
        400:
          description: bad request
        500:
          description: internal server error

  /metrics/environment/{envId}:
    get:
      tags:
        - metadata
      security:
        - key: []
      operationId: getEnvironmentMetrics
      parameters:
        - name: envId
          in: path
          type: string
          required: true
        - name: duration
          in: query
          type: string
      responses:
        200:
          description: environment metrics
          schema:
            $ref: "#/definitions/metrics"
        400:
          description: bad request
        401:
          description: unauthorized
        500:
          description: internal server error


  /metrics/share/{shrToken}:
    get:
      tags:
        - metadata
      security:
        - key: []
      operationId: getShareMetrics
      parameters:
        - name: shrToken
          in: path
          type: string
          required: true
        - name: duration
          in: query
          type: string
      responses:
        200:
          description: share metrics
          schema:
            $ref: "#/definitions/metrics"
        400:
          description: bad request
        401:
          description: unauthorized
        500:
          description: internal server error


  /version:
    get:
      tags:
        - metadata
      operationId: version
      responses:
        200:
          description: current server version
          schema:
            $ref: "#/definitions/version"

  #
  # share
  #
  /access:
    post:
      tags:
        - share
      security:
        - key: []
      operationId: access
      parameters:
        - name: body
          in: body
          schema:
            $ref: "#/definitions/accessRequest"
      responses:
        201:
          description: access created
          schema:
            $ref: "#/definitions/accessResponse"
        401:
          description: unauthorized
        404:
          description: not found
        500:
          description: internal server error

  /share:
    post:
      tags:
        - share
      security:
        - key: []
      operationId: share
      parameters:
        - name: body
          in: body
          schema:
            $ref: "#/definitions/shareRequest"
      responses:
        201:
          description: share created
          schema:
            $ref: "#/definitions/shareResponse"
        401:
          description: unauthorized
        404:
          description: not found
        409:
          description: conflict
        422:
          description: unprocessable
        500:
          description: internal server error
          schema:
            $ref: "#/definitions/errorMessage"
    patch:
      tags:
        - share
      security:
        - key: []
      operationId: updateShare
      parameters:
        - name: body
          in: body
          schema:
            $ref: "#/definitions/updateShareRequest"
      responses:
        200:
          description: share updated
        400:
          description: bad request
        401:
          description: unauthorized
        404:
          description: not found
        500:
          description: internal server error

  /unaccess:
    delete:
      tags:
        - share
      security:
        - key: []
      operationId: unaccess
      parameters:
        - name: body
          in: body
          schema:
            $ref: "#/definitions/unaccessRequest"
      responses:
        200:
          description: access removed
        401:
          description: unauthorized
        404:
          description: not found
        500:
          description: internal server error

  /unshare:
    delete:
      tags:
        - share
      security:
        - key: []
      operationId: unshare
      parameters:
        - name: body
          in: body
          schema:
            $ref: "#/definitions/unshareRequest"
      responses:
        200:
          description: share removed
        401:
          description: unauthorized
        404:
          description: not found
        500:
          description: internal server error
          schema:
            $ref: "#/definitions/errorMessage"

definitions:
  accessRequest:
    type: object
    properties:
      envZId:
        type: string
      shrToken:
        type: string

  accessResponse:
    type: object
    properties:
      frontendToken:
        type: string
      backendMode:
        type: string

  authUser:
    type: object
    properties:
      username:
        type: string
      password:
        type: string

  changePasswordRequest:
    type: object
    properties:
      email:
        type: string
      oldPassword:
        type: string
      newPassword:
         type: string

  configuration:
    type: object
    properties:
      version:
        type: string
      touLink:
        type: string
      invitesOpen:
        type: boolean
      requiresInviteToken:
        type: boolean
      inviteTokenContact:
        type: string
      passwordRequirements:
        $ref: "#/definitions/passwordRequirements"

  createFrontendRequest:
    type: object
    properties:
      zId:
        type: string
      url_template:
        type: string
      public_name:
        type: string

  createFrontendResponse:
    type: object
    properties:
      token:
        type: string

  deleteFrontendRequest:
    type: object
    properties:
      frontendToken:
        type: string

  disableRequest:
    type: object
    properties:
      identity:
        type: string

  enableRequest:
    type: object
    properties:
      description:
        type: string
      host:
        type: string

  enableResponse:
    type: object
    properties:
      identity:
        type: string
      cfg:
        type: string

  environment:
    type: object
    properties:
      description:
        type: string
      host:
        type: string
      address:
        type: string
      zId:
        type: string
      activity:
        $ref: "#/definitions/sparkData"
      limited:
        type: boolean
      createdAt:
        type: integer
      updatedAt:
        type: integer

  environments:
    type: array
    items:
      $ref: "#/definitions/environment"

  environmentAndResources:
    type: object
    properties:
      environment:
        $ref: "#/definitions/environment"
      frontends:
        $ref: "#/definitions/frontends"
      shares:
        $ref: "#/definitions/shares"

  errorMessage:
    type: string

  frontend:
    type: object
    properties:
      id:
        type: integer
      token:
        type: string
      shrToken:
        type: string
      zId:
        type: string
      createdAt:
        type: integer
      updatedAt:
        type: integer

  frontends:
    type: array
    items:
      $ref: "#/definitions/frontend"

  inviteTokenGenerateRequest:
    type: object
    properties:
      tokens:
        type: array
        items:
          type: string

  inviteRequest:
    type: object
    properties:
      email:
        type: string
      token:
        type: string

  loginRequest:
    type: object
    properties:
      email:
        type: string
      password:
        type: string

  loginResponse:
    type: string

  metrics:
    type: object
    properties:
      scope:
        type: string
      id:
        type: string
      period:
        type: number
      samples:
        type: array
        items:
          $ref: "#/definitions/metricsSample"

  metricsSample:
    type: object
    properties:
      rx:
        type: number
      tx:
        type: number
      timestamp:
        type: number

  overview:
    type: object
    properties:
      accountLimited:
        type: boolean
      environments:
        type: array
        items:
          $ref: "#/definitions/environmentAndResources"
          
  passwordRequirements:
    type: object
    properties:
      length:
        type: integer
      requireCapital:
        type: boolean
      requireNumeric:
        type: boolean
      requireSpecial:
        type: boolean
      validSpecialCharacters:
        type: string

  principal:
    type: object
    properties:
      id:
        type: integer
      email:
        type: string
      token:
        type: string
      limitless:
        type: boolean
      admin:
        type: boolean

  publicFrontend:
    type: object
    properties:
      token:
        type: string
      zId:
        type: string
      urlTemplate:
        type: string
      publicName:
        type: string
      createdAt:
        type: integer
      updatedAt:
        type: integer

  publicFrontendList:
    type: array
    items:
      $ref: "#/definitions/publicFrontend"

  registerRequest:
    type: object
    properties:
      token:
        type: string
      password:
        type: string

  registerResponse:
    type: object
    properties:
      token:
        type: string

  resetPasswordRequest:
    type: object
    properties:
      token:
        type: string
      password:
        type: string

  share:
    type: object
    properties:
      token:
        type: string
      zId:
        type: string
      shareMode:
        type: string
      backendMode:
        type: string
      frontendSelection:
        type: string
      frontendEndpoint:
        type: string
      backendProxyEndpoint:
        type: string
      reserved:
        type: boolean
      activity:
        $ref: "#/definitions/sparkData"
      limited:
        type: boolean
      createdAt:
        type: integer
      updatedAt:
        type: integer

  shares:
    type: array
    items:
      $ref: "#/definitions/share"

  shareRequest:
    type: object
    properties:
      envZId:
        type: string
      shareMode:
        type: string
        enum: ["public", "private"]
      frontendSelection:
        type: array
        items:
          type: string
      backendMode:
        type: string
        enum: ["proxy", "web", "tcpTunnel", "udpTunnel", "caddy", "drive", "socks"]
      backendProxyEndpoint:
        type: string
      authScheme:
        type: string
      authUsers:
        type: array
        items:
          $ref: "#/definitions/authUser"
      oauthProvider:
        type: string
        enum: ["github", "google"]
      oauthEmailDomains:
        type: array
        items:
          type: string
      oauthAuthorizationCheckInterval:
        type: string
      reserved:
        type: boolean
      permissionMode:
        type: string
        enum: ["open", "closed"]
      accessGrants:
        type: array
        items:
          type: string
      uniqueName:
        type: string

  shareResponse:
    type: object
    properties:
      frontendProxyEndpoints:
        type: array
        items:
          type: string
      shrToken:
        type: string

  sparkData:
    type: array
    items:
      $ref: "#/definitions/sparkDataSample"

  sparkDataSample:
    type: object
    properties:
      rx:
        type: number
      tx:
        type: number

  unaccessRequest:
    type: object
    properties:
      frontendToken:
        type: string
      envZId:
        type: string
      shrToken:
        type: string

  unshareRequest:
    type: object
    properties:
      envZId:
        type: string
      shrToken:
        type: string
      reserved:
        type: boolean

  updateFrontendRequest:
    type: object
    properties:
      frontendToken:
        type: string
      publicName:
        type: string
      urlTemplate:
        type: string

  updateShareRequest:
    type: object
    properties:
      shrToken:
        type: string
      backendProxyEndpoint:
        type: string
      addAccessGrants:
        type: array
        items:
          type: string
      removeAccessGrants:
        type: array
        items:
          type: string

  verifyRequest:
    type: object
    properties:
      token:
        type: string
  verifyResponse:
    type: object
    properties:
      email:
        type: string

  version:
    type: string

produces:
- application/zrok.v1+json
consumes:
- application/zrok.v1+json
schemes:
- http
swagger: "2.0"