openapi: 3.0.0
info:
  version: v1
  title: FarmStall API
  description: |-

    An API for writing reviews about your favourite (or worst) farm stalls.

    ![Picture of produce](https://farmstall.ponelat.com/img/produce-banner.jpg)

    ---

    # Auth

    To create **Reviews** without being _anonymous_. You need to add a **MyUserToken** to the `Authorization` header.

    To get a **MyUserToken**:
    1. Create a **User** with [POST /users](#Users/post_users)
    1. Get a **MyUserToken** by calling [POST /tokens](#Users/post_tokens) with your **User** credentials.

    # Reviews
    Reviews are the heart of this API. <br/>
    Registered **Users** and anonymous users can both write reviews based on their experience at farm stalls. <br/>

    Each review comes with a rating of between one and five stars inclusive.

    - One star being the worst experience
    - Five stars being the best


    ### Example Reviews

      "A wonderful time!" &mdash; Bob McNally
      <br/>
      ![5 stars](https://farmstall.ponelat.com/img/rating-5.png)

      "An awful place" &mdash; _Anonymous_
      <br/>
      ![1 star](https://farmstall.ponelat.com/img/rating-1.png)

      "A totally average place." &mdash; Jane Fair
      <br/>
      ![3 stars](https://farmstall.ponelat.com/img/rating-3.png)

  contact:
    name: Josh Ponelat
    email: jponelat@gmail.com
    url: https://ponelat.com/contact

  license:
    url: https://www.apache.org/licenses/LICENSE-2.0
    name: Apache 2.0

externalDocs:
  url: https://app.swaggerhub.com/apis/designing-apis/part-one
  description: SwaggerHub

tags:
  - name: Reviews
    description: Reviews of your favourite/worst farm stalls

  - name: Users
    description: Users and authentication

servers:
- url: 'https://farmstall.ponelat.com/v1'

paths:
  /reviews:
    get:
      tags:
        - Reviews
      description: Get a list of reviews
      parameters:
      - name: maxRating
        in: query
        schema:
          type: number
      responses:
        '200':
          description: A bunch of reviews
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    rating:
                      type: integer
                      minimum: 1
                      maximum: 5
                    message:
                      type: string
                    uuid:
                      type: string
                      pattern: '^[0-9a-fA-F\-]{36}$'
                    userId:
                      type: string
                      pattern: '^[0-9a-fA-F\-]{36}$'
                      nullable: true

    post:
      tags:
      - Reviews
      description: Create a new Review
      security:
      - MyUserToken: []
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                message:
                  type: string
                  example: An awesome time for the whole family.
                rating:
                  type: integer
                  minimum: 1
                  maximum: 5
                  example: 5
      responses:
        '201':
          description: Successfully created a new Review
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: An awesome time for the whole family.
                  rating:
                    type: integer
                    minimum: 1
                    maximum: 5
                    example: 5
                  userId:
                    type: string
                    nullable: true
                    pattern: '[a-zA-Z-.0-9]{36}'
                    example: f7f680a8-d111-421f-b6b3-493ebf905078
                  uuid:
                    type: string
                    pattern: '[a-zA-Z-.0-9]{36}'
                    example: f7f680a8-d111-421f-b6b3-493ebf905078


  /reviews/{reviewId}:
    get:
      tags:
      - Reviews
      description: Get a single review
      parameters:
      - name: reviewId
        in: path
        required: true
        schema:
          type: string
          minLength: 36
          maxLength: 36
          pattern: '[a-zA-Z0-9-]+'
      responses:
        '200':
          description: A single review
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: An awesome time for the whole family.
                  rating:
                    type: integer
                    minimum: 1
                    maximum: 5
                    example: 5
                  userId:
                    minLength: 36
                    maxLength: 36
                    pattern: '^[a-zA-Z0-9-]+$'
                    nullable: true
                    example: f7f680a8-d111-421f-b6b3-493ebf905078
                  uuid:
                    minLength: 36
                    maxLength: 36
                    pattern: '^[a-zA-Z0-9-]+$'
                    example: f7f680a8-d111-421f-b6b3-493ebf905078
        '404':
          description: Review not found



  /users:
    post:
      tags:
      - Users
      description: Create a new user
      requestBody:
        description: User details
        content:
          application/json:
            schema:
              type: object
              properties:
                username:
                  type: string
                  example: ponelat
                password:
                  type: string
                  format: password
                fullName:
                  type: string
                  example: Josh Ponelat
      responses:
        '201':
          description: Successfully created a new user
          content:
            application/json:
              schema:
                type: object
                properties:
                  username:
                    type: string
                    example: ponelat
                  uuid:
                    type: string
                    example: f7f680a8-d111-421f-b6b3-493ebf905078


  /tokens:
    post:
      tags:
      - Users
      description: Create a new token
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                username:
                  type: string
                  example: ponelat
                password:
                  type: string
                  format: password

      responses:
        '201':
          description: Create a new token for gaining authenticated access to resources
          content:
            application/json:
              schema:
                type: object
                properties:
                  token:
                    type: string


components:
  securitySchemes:
    MyUserToken:
      name: Authorization
      type: apiKey
      in: header
