diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5da4fc702..857fa3bd1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,8 @@
## [Unreleased]
+### Documentation
+- Defining new API interface to fix security issue
+ [#1186](https://github.com/nextcloud/cookbook/pull/1186) @christianlupus
## 0.9.14 - 2022-08-29
diff --git a/docs/dev/api/0.1.0/index.html b/docs/dev/api/0.1.0/index.html
new file mode 100644
index 000000000..6ddcad895
--- /dev/null
+++ b/docs/dev/api/0.1.0/index.html
@@ -0,0 +1,60 @@
+
+
+
+
+
+ Public API cookbook app
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/dev/api/0.1.0/internal-cookbook.yaml b/docs/dev/api/0.1.0/internal-cookbook.yaml
new file mode 100644
index 000000000..32977d35f
--- /dev/null
+++ b/docs/dev/api/0.1.0/internal-cookbook.yaml
@@ -0,0 +1,514 @@
+openapi: 3.0.1
+info:
+ title: Nextcloud cookbook app
+ description: >-
+ This is the internal API definition of the [cookbook app](https://github.com/nextcloud/cookbook) webapp for the [nextcloud server](http://nextcloud.com).
+
+
+ The total API is separated into two parts:
+
+ - There is the public API part that can be used from 3rd party apps and scripts.
+
+ - There is the internal API that is used only by the web app of the cookbook app. This is described here.
+
+
+ The internal part is intended only to be used by the internal web app.
+ It uses session based authentication and thus requires a `requesttoken` to protect against CSRF attacks.
+ The generation and updating of these tokens is not part of the app but the regular browser capabilities and the nextcloud web frontend is used here instead.
+
+
+ In contrast, the External APIs are intended for use by external services.
+ These endpoints require the user credentials to be present in every request.
+ Thus, no session is created and no cookies or similar needs to be handled.
+ Technically, there is a CORS preflight possible but it is not required for the function of the endpoints.
+
+
+ Further contact can be found on the matrix.org server in the room [#nextcloud-cookbook:matrix.org](https://matrix.to/#/#nextcloud-cookbook:matrix.org) for general questions.
+ Additionally, there is [#nextcloud-cookbook-integration:matrix.org](https://matrix.to/#/#nextcloud-cookbook-integration:matrix.org) for questions related to the API and third party integration.
+ Further information on the different versions can be found in [the API overview page](https://nextcloud.github.io/cookbook/dev/api/index).
+ #contact:
+ #email: apiteam@swagger.io
+ license:
+ name: AGPL-3
+ url: 'http://www.gnu.org/licenses/agpl-3.0.de.html'
+ version: 0.1.0
+
+#externalDocs:
+# description: Find out more about Swagger
+# url: 'http://swagger.io'
+
+servers:
+ - url: 'http://localhost:8000/apps/cookbook'
+ - url: '{protocol}://{server}'
+ variables:
+ protocol:
+ enum:
+ - http
+ - https
+ default: https
+ server:
+ default: 'example.com'
+
+tags:
+ # - name: External API v1 - Recipes
+ # description: Querying and manipulating recipes using external APIs
+ # - name: External API v1 - Categories
+ # description: Access to the categories of recipes using external APIs
+ # - name: External API v1 - Tags
+ # description: Access to tags/keywords of recipes using external APIs
+ # - name: External API v1 - Misc
+ # description: Other API endpoints for use by external APIs
+
+ - name: Recipes
+ description: Everything related to recipes and their usage
+ - name: Categories
+ description: Access to the categories of the recipes
+ - name: Tags
+ description: Access to tags/keywords of recipes
+ - name: Misc
+ description: Other API endpoints
+
+
+
+components:
+
+ schemas:
+ Config:
+ $ref: objects.yaml#/Config
+ Error:
+ $ref: objects.yaml#/Error
+ RecipeStub:
+ $ref: objects.yaml#/RecipeStub
+ StubList:
+ $ref: objects.yaml#/StubList
+ Recipe:
+ $ref: objects.yaml#/Recipe
+
+ securitySchemes:
+ # app_password:
+ # type: http
+ # scheme: basic
+ # description: Use username and app password
+ requesttoken:
+ type: apiKey
+ name: requestkey
+ in: header
+ session:
+ type: apiKey
+ in: cookie
+ name: nc_session_id
+
+security:
+ - requesttoken: []
+ session: []
+
+paths:
+
+ /webapp/reindex:
+ post:
+ tags: [ Misc ]
+ summary: Trigger a rescan of all recipes into the caching database
+ responses:
+ 200:
+ description: The reindex process was done.
+ content:
+ application/json:
+ schema:
+ type: string
+ example: Search index rebuilt successfully
+ /webapp/config:
+ get:
+ tags: [ Misc ]
+ summary: Get the current configuration of the app
+ responses:
+ 200:
+ description: The config was read successfully
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/Config"
+ post:
+ tags: [ Misc ]
+ summary: Set the configuration for the current user
+ responses:
+ 200:
+ description: The configuration was successfully saved.
+ content:
+ application/json:
+ schema:
+ type: string
+ example: OK
+
+ /webapp/import:
+ post:
+ tags: [ Recipes ]
+ summary: Import a recipe using schema.org metadata from a website
+ requestBody:
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ url:
+ type: string
+ example: 'http://www.chefkoch.de/2345'
+ required:
+ - url
+ responses:
+ 200:
+ description: Successfully imported recipe
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/Recipe"
+ 400:
+ description: The URL to be imported was not inserted in the request or any other issue was rosen.
+ content:
+ application/json:
+ schema:
+ type: string
+ example: Field "url" is required
+ 409:
+ description: There exists a recipe with that name already. Import was aborted.
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/Error"
+ /webapp/recipes/{id}/image:
+ get:
+ tags: [ Recipes ]
+ summary: Get the main image of a recipe. If no image is stored a fallback image is delivered.
+ parameters:
+ - in: path
+ name: id
+ description: The id of the recipe to obtain the image for.
+ required: true
+ schema:
+ type: integer
+ responses:
+ 200:
+ description: Image was obtained and will be in response either as image/jpeg or image/svg+xml
+ content:
+ image/jpeg:
+ schema:
+ type: string
+ format: binary
+ image/svg+xml:
+ schema:
+ type: string
+ format: binary
+ 406:
+ description: The recipe has no image whose MIME type matches the Accept header
+ /webapp/search/{query}:
+ parameters:
+ - in: path
+ name: query
+ required: true
+ description: The search string, urlencoded, separated with spaces and/or commas
+ schema:
+ type: string
+ get:
+ tags: [ Recipes ]
+ summary: Search for recipes for keywords, tags and categories with the named search string
+ responses:
+ 200:
+ description: The recipes were obtained successfully
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/StubList"
+ 500:
+ description: An error has been thrown
+ content:
+ application/json:
+ schema:
+ type: string
+ description: The error message
+ /webapp/recipes:
+ get:
+ tags: [ Recipes ]
+ summary: Get all recipes in the database
+ responses:
+ 200:
+ description: Successfully obtained all recipes
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/StubList"
+ post:
+ tags: [ Recipes ]
+ summary: Create a new recipe
+ requestBody:
+ description: |
+ A JSON representation of the recipe to be saved.
+
+ See also the structure at https://schema.org/Recipe
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ name:
+ type: string
+ required: [ "name" ]
+ additionalProperties: true
+ example:
+ name: "Chips"
+ description: "A very delicious way of getting kids quiet"
+ ingredients:
+ - "1 pack of pre-fried chips"
+ tools: ["common oven"]
+ instructions:
+ - "Put the chips in the oven"
+ - "Wait until the are due"
+ responses:
+ 200:
+ description: Successfully created new recipe
+ content:
+ application/json:
+ schema:
+ type: integer
+ example: 2462
+ description: The id of the newly created recipe
+ 409:
+ description: A recipe with the name was already found on the server. No recipe is created.
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/Error"
+ 422:
+ description: There was no name in the request given for the recipe. Cannot save the recipe.
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/Error"
+ /webapp/recipes/{id}:
+ parameters:
+ - in: path
+ name: id
+ required: true
+ description: The id of the recipe
+ schema:
+ type: integer
+ get:
+ tags: [ Recipes ]
+ summary: Get a single recipe from the server
+ responses:
+ 200:
+ description: Recipe was sucessfully obtained
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/Recipe"
+ 404:
+ description: The given recipe id was not found
+ content:
+ application/json:
+ schema:
+ type: integer
+ example: 2345
+ description: The id of the recipe that was not found
+ put:
+ tags: [ Recipes ]
+ summary: Update a recipe
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/Recipe"
+ responses:
+ 200:
+ description: The recipe was sucessfully updated
+ content:
+ application/json:
+ schema:
+ type: integer
+ description: The id of the updated recipe
+ example: 2345
+ 422:
+ description: There was no name in the request given for the recipe. Cannot save the recipe.
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/Error"
+
+ delete:
+ tags: [ Recipes ]
+ summary: Delete an existing recipe
+ responses:
+ 200:
+ description: The recipe was deleted successfully
+ content:
+ application/json:
+ schema:
+ type: string
+ example: Recipe 2345 was deletes successfully
+ 502:
+ description: An Exception was thrown
+ content:
+ application/json:
+ schema:
+ type: string
+ example: Recipe with id 2345 was not found.
+ description: Error message
+
+ /webapp/keywords:
+ get:
+ tags: [ Tags ]
+ summary: Get all known keywords
+ responses:
+ '200':
+ description: Successfully obtained all keywords
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ type: object
+ properties:
+ name:
+ type: string
+ recipe_count:
+ type: integer
+ required:
+ - name
+ - recipe_count
+ example:
+ - name: vegetarian
+ recipe_count: 5
+ - name: sugar-free
+ recipe_count: 2
+ /webapp/tags/{keywords}:
+ get:
+ tags: [ Tags ]
+ summary: Get all recipes associated with certain keywords
+ parameters:
+ - in: path
+ name: keywords
+ required: true
+ description: Comma separated list of keywords, urlencoded
+ schema:
+ type: string
+ example: vegetarian,sweet
+ responses:
+ 200:
+ description: Recipes were successfully obtained
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/StubList"
+ 500:
+ description: An error occured
+ content:
+ application/json:
+ schema:
+ type: string
+ example: "SQLException: Something went wrong."
+
+ /webapp/categories:
+ get:
+ tags: [ Categories ]
+ summary: Get all known categories
+ responses:
+ 200:
+ description: >-
+ Sucessfully obtained all categories
+
+
+ Please note: A category name of `*` indicates the number of
+ recipes with no category associated.
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ type: object
+ properties:
+ name:
+ type: string
+ recipe_count:
+ type: integer
+ required:
+ - name
+ - recipe_count
+ example:
+ - name: Dinner
+ recipe_count: 21
+ - name: Lunch
+ recipe_count: 10
+ - name: '*'
+ recipe_count: 3
+ /webapp/category/{category}:
+ get:
+ tags: [ Categories ]
+ summary: Get all recipes of a certain category
+ parameters:
+ - in: path
+ name: category
+ required: true
+ description: >-
+ The name of the category to be queried as urlencoded string
+
+
+ Put the string `_` to obtain all recipes with no category
+ schema:
+ type: string
+ responses:
+ 200:
+ description: The filtered recipes belonging to the category
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/StubList"
+ 500:
+ description: An exception was issued.
+ content:
+ application/json:
+ schema:
+ type: string
+ description: The error message
+ example: Could not find category foo.
+ put:
+ tags: [ Categories ]
+ summary: Rename a category
+ parameters:
+ - in: path
+ name: category
+ required: true
+ description: >-
+ The name of the category to be queried as urlencoded string
+
+
+ Put the string `_` to obtain all recipes with no category
+ schema:
+ type: string
+ requestBody:
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ name:
+ type: string
+ example: Lunch
+ description: The new name to rename the category to
+ required:
+ - name
+ responses:
+ 200:
+ description: The category was renamed successfully
+ content:
+ application/json:
+ schema:
+ type: string
+ example: Lunch
+ 400:
+ description: The new category name was not included during the request.
+ 500:
+ description: The renaming did not succeed.
+ content:
+ application/json:
+ schema:
+ type: string
+ description: The error message
+ example: There exists already a category of that name.
diff --git a/docs/dev/api/0.1.0/internal.html b/docs/dev/api/0.1.0/internal.html
new file mode 100644
index 000000000..9d995803a
--- /dev/null
+++ b/docs/dev/api/0.1.0/internal.html
@@ -0,0 +1,60 @@
+
+
+
+
+
+ Internal API of cookbook app
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/dev/api/0.1.0/objects.yaml b/docs/dev/api/0.1.0/objects.yaml
new file mode 100644
index 000000000..cdbb09394
--- /dev/null
+++ b/docs/dev/api/0.1.0/objects.yaml
@@ -0,0 +1,382 @@
+Config:
+ type: object
+ description: An object describing the configuration of the web app
+ properties:
+ folder:
+ type: string
+ example: /Recipes
+ description: The folder in the user's files that contains the recipes
+ update_interval:
+ type: integer
+ example: 10
+ description: The interval between automatic rescans to rebuild the database cache in minutes
+ print_image:
+ type: boolean
+ example: true
+ description: True, if the user wished to print the recipe images with the rest of the recipes
+ required:
+ - folder
+ - update_interval
+ - print_image
+
+Error:
+ type: object
+ description: An error description
+ properties:
+ msg:
+ type: string
+ description: The error message
+ example: Recipe could not be found
+ file:
+ type: string
+ description: The file in which the exception was thrown
+ example: /var/www/custom_apps/cookbook/Service/RecipeService.php
+ line:
+ type: integer
+ description: The line where the exception is thrown
+ example: 223
+
+RecipeStubInformation:
+ type: object
+ description: The very basic information of a recipe
+ properties:
+ name:
+ type: string
+ description: The name of the recipe
+ example: Baked bananas
+ keywords:
+ type: string
+ description: A comma-separated list of recipe keywords, can be empty string
+ example: sweets,fruit
+ dateCreated:
+ type: string
+ description: The date the recipe was created in the app
+ example: "2022-01-02T16:12:41+0000"
+ dateModified:
+ type: string
+ description: The date the recipe was modified lastly in the app
+ example: "2022-01-10T10:02:52+0000"
+ imageUrl:
+ type: string
+ description: The URL of the recipe image
+ example: http://example.com/path/to/image.jpg
+ imagePlaceholderUrl:
+ type: string
+ description: The URL of the placeholder of the recipe image
+ example: http://example.com/path/to/image_thumb.jpg
+ required:
+ - "name"
+ - "keywords"
+ - "imageUrl"
+ - "imagePlaceholderUrl"
+ - "dateCreated"
+
+RecipeStub:
+ type: object
+ description: A stub of a recipe with some basic information present
+ allOf:
+ - $ref: "#/RecipeStubInformation"
+ - type: object
+ properties:
+ recipe_id:
+ type: integer
+ description: The index of the recipe
+ example: 1
+ required:
+ - "recipe_id"
+
+StubList:
+ type: array
+ items:
+ $ref: "#/RecipeStub"
+
+Tool:
+ type: string
+ example: Flat and fire-resistent bowl
+ description: A single tool for a recipe. A tool is not consumed but only used.
+
+Ingredient:
+ type: string
+ example: 100g ripe Bananas
+ description: A single ingredient for a recipe
+
+Instruction:
+ type: string
+ example: Peel the bananas
+ description: An instruction step for processing the recipe
+
+Nutrition:
+ type: object
+ properties:
+ "@type":
+ type: string
+ example: NutritionInformation
+ description: Schema.org object description
+ calories:
+ type: string
+ description: The number of calories for the given amount
+ example: 650 kcal
+ carbohydrateContent:
+ type: string
+ description: The number of grams of carbohydrates
+ example: 300 g
+ cholesterolContent:
+ type: string
+ description: The number of milligrams of cholesterol
+ example: 10 g
+ fatContent:
+ type: string
+ description: The number of grams of fat
+ example: 45 g
+ fiberContent:
+ type: string
+ description: The number of grams of fiber
+ example: 50 g
+ proteinContent:
+ type: string
+ description: The number of grams of protein
+ example: 80 g
+ saturatedFatContent:
+ type: string
+ description: The number of grams of saturated fat
+ example: 5 g
+ servingSize:
+ type: string
+ description: The serving size, in terms of the number of volume or mass
+ example: One plate, sufficient for one person as dessert
+ sodiumContent:
+ type: string
+ description: The number of milligrams of sodium
+ example: 10 mg
+ sugarContent:
+ type: string
+ description: The number of grams of sugar
+ example: 5 g
+ transFatContent:
+ type: string
+ description: The number of grams of trans fat
+ example: 10 g
+ unsaturatedFatContent:
+ type: string
+ description: The number of grams of unsaturated fat
+ example: 40 g
+ required:
+ - "@type"
+
+Recipe:
+ #type: object
+ description: A recipe according to [schema.org](http://schema.org/Recipe)
+ allOf:
+ - $ref: "#/RecipeStubInformation"
+ - type: object
+ properties:
+ "@type":
+ type: string
+ example: "Recipe"
+ description: Schema.org object type identifier
+ id:
+ type: integer
+ description: The index of the recipe
+ example: 123
+ prepTime:
+ type: string
+ nullable: true
+ description: The time required for preparation in ISO8601 format
+ example: "PT0H10M"
+ cookTime:
+ type: string
+ nullable: true
+ description: The time required for cooking in ISO8601 format
+ example: "PT1H20M"
+ totalTime:
+ type: string
+ nullable: true
+ description: The time required for the complete processing in ISO8601 format
+ example: "PT1H30M"
+ description:
+ type: string
+ example: A very easy way to make children happy
+ description: A description of the recipe or the empty string
+ url:
+ type: string
+ example: http://exmaple.com/my-recipe.html
+ description: The URL the recipe was found at or the empty string
+ image:
+ type: string
+ example: http://example.com/my-recipe-image.jpeg
+ description: The URL of the original recipe
+ recipeYield:
+ type: integer
+ example: 4
+ description: Number of servings in recipe
+ recipeCatregory:
+ type: string
+ example: Dessert
+ description: The category of the recipe
+ tools:
+ type: array
+ items:
+ $ref: "#/Tool"
+ recipeIngredients:
+ type: array
+ items:
+ $ref: "#/Ingredient"
+ recipeInstructions:
+ type: array
+ items:
+ $ref: "#/Instruction"
+ nutrition:
+ $ref: "#/Nutrition"
+ required:
+ - id
+ - prepTime
+ - cookTime
+ - totalTime
+ - description
+ - url
+ - recipeYield
+ - recipeCategory
+ - tools
+ - recipeIngredients
+ - recipeInstructions
+ - nutrition
+ additionalProperties: true
+ example:
+ name: Baked bananas
+ id: 123
+ description: A very delightful recipe of the best baked bananas ever
+ image: http://example.com/path/to/image.jpg
+ recipeYield: 5
+ prepTime: PT0H15M
+ cookTime: null
+ totalTime: PT1H20M
+ url: ''
+ tools: []
+ recipeIngredient:
+ - 3 ripe bananas
+ - 100g sugar
+ - 20 teaspoons of cinamon
+ resipeInstructions:
+ - Peel the bananas
+ - Dip the bananas in the pot of sugar
+ - Put the banans in the oven and let the cinamon soak in for 10 minutes
+ - After 5 hours of baking, they are ready
+ recipeCategory: Dessert
+ keywords: banana,cinnamon,sweet,untested recipe
+ nutrition: []
+
+RecipeList:
+ type: array
+ items:
+ $ref: "#/Recipe"
+ example:
+ - name: Baked bananas
+ description: A very delightful recipe of the best baked bananas ever
+ image: http://example.com/path/to/image.jpg
+ recipeYield: 5
+ prepTime: PT0H15M
+ recipeIngredient:
+ - 3 ripe bananas
+ - 100g sugar
+ - 20 teaspoons of cinamon
+ resipeInstructions:
+ - Peel the bananas
+ - Dip the bananas in the pot of sugar
+ - Put the banans in the oven and let the cinamon soak in for 10 minutes
+ - After 5 hours of baking, they are ready
+ recipeCategory: Dessert
+ keywords: banana,cinnamon,sweet,untested recipe
+ - name: "Homemade Apple Butter"
+ author:
+ "@type": Person
+ name: "Julie Clark"
+ description: "A simple recipe for Homemade Apple Butter that you can make in the slow cooker. Use as a spread, a syrup or in your fall recipes!"
+ datePublished: "2016-09-01T01:58:54+00:00"
+ image: "https://www.tastesoflizzyt.com/wp-content/uploads/2016/08/homemade-apple-butter-2-480x270.jpg"
+ recipeYield: 20
+ prepTime: "PT0H25M"
+ cookTime: "PT10H0M"
+ totalTime: "PT10H25M"
+ recipeIngredient:
+ - 6 1/2 pounds apples (peeled, cored and sliced)
+ - 1/2 cup granulated sugar
+ - 1/2 cup packed brown sugar
+ - 1 1/2 tablespoons ground cinnamon
+ - 1/4 teaspoon salt
+ - 1 tablespoon vanilla extract
+ recipeInstructions:
+ - Place the apples in a slow cooker.
+ - Add the sugars, cinnamon, salt and vanilla to the crockpot. Mix well.
+ - Cook in slow cooker on low for about 10 hours, stirring every couple hours. The apple butter should be thick and dark brown.
+ - If desired, use a blender to puree the apple butter until smooth.
+ - Cover and refrigerate for up to two weeks or freeze in small containers.
+ aggregateRating:
+ "@type": "AggregateRating"
+ ratingValue: "4.87"
+ ratingCount: "38"
+ recipeCategory: "Breakfast"
+ keywords: "apple butter recipes,apple recipes,fall recipes"
+ nutrition:
+ "@type": "NutritionInformation"
+ calories: "120 kcal"
+ carbohydrateContent: "31 g"
+ sodiumContent: "32 mg"
+ fiberContent: "3 g"
+ sugarContent: "25 g"
+ servingSize: "1 serving"
+ tool: []
+ url: "https://www.tastesoflizzyt.com/homemade-apple-butter/"
+ dateModified: "2021-05-23T17:10:25+0000"
+ dateCreated: "2021-05-23T17:10:25+0000"
+
+ReleaseVersion:
+ type: array
+ items:
+ type: integer
+ minItems: 3
+ maxItems: 3
+ description: The installed release of the cookbook app
+ example: [0, 9, 14]
+
+PreReleaseVersion:
+ type: array
+ items:
+ type: integer|string
+ minItems: 4
+ maxItems: 4
+ description: The installed pre-release of the cookbook app
+ example: [0, 9, 14, "-rc1"]
+
+AppVersion:
+ oneOf:
+ - $ref: "#/ReleaseVersion"
+ - $ref: "#/PreReleaseVersion"
+
+APIVersion:
+ type: object
+ properties:
+ epoch:
+ type: integer
+ description: An epoch to cope with bad API versions
+ major:
+ type: integer
+ description: The major number of the API
+ minor:
+ type: integer
+ description: The minor number of the API
+ required:
+ - "epoch"
+ - "major"
+ - "minor"
+ example:
+ epoch: 0
+ major: 1
+ minor: 3
+
+Version:
+ type: object
+ properties:
+ cookbook_version:
+ $ref: "#/AppVersion"
+ api_version:
+ $ref: "#/APIVersion"
diff --git a/docs/dev/api/0.1.0/openapi-cookbook.yaml b/docs/dev/api/0.1.0/openapi-cookbook.yaml
new file mode 100644
index 000000000..1b8bfcb88
--- /dev/null
+++ b/docs/dev/api/0.1.0/openapi-cookbook.yaml
@@ -0,0 +1,508 @@
+openapi: 3.0.1
+info:
+ title: Nextcloud cookbook app
+ description: >-
+ This is the public API definition of the [cookbook app](https://github.com/nextcloud/cookbook) for the [nextcloud server](http://nextcloud.com).
+
+
+ The total API is separated into two parts:
+
+ - There is the public API part that can be used from 3rd party apps and scripts.
+
+ - There is the internal API that is used only by the web app of the cookbook app. This is described here.
+
+
+ The internal part is intended only to be used by the internal web app.
+ It uses session based authentication and thus requires a `requesttoken` to protect against CSRF attacks.
+ The generation and updating of these tokens is not part of the app but the regular browser capabilities and the nextcloud web frontend is used here instead.
+
+
+ In contrast, the External APIs are intended for use by external services.
+ These endpoints require the user credentials to be present in every request.
+ Thus, no session is created and no cookies or similar needs to be handled.
+ Technically, there is a CORS preflight possible but it is not required for the function of the endpoints.
+
+
+ Further contact can be found on the matrix.org server in the room [#nextcloud-cookbook:matrix.org](https://matrix.to/#/#nextcloud-cookbook:matrix.org) for general questions.
+ Additionally, there is [#nextcloud-cookbook-integration:matrix.org](https://matrix.to/#/#nextcloud-cookbook-integration:matrix.org) for questions related to the API and third party integration.
+ Further information on the different versions can be found in [the API overview page](https://nextcloud.github.io/cookbook/dev/api/index).
+ #contact:
+ #email: apiteam@swagger.io
+ license:
+ name: AGPL-3
+ url: 'http://www.gnu.org/licenses/agpl-3.0.de.html'
+ version: 0.1.0
+
+#externalDocs:
+# description: Find out more about Swagger
+# url: 'http://swagger.io'
+
+servers:
+ - url: 'http://localhost:8000/apps/cookbook'
+ - url: '{protocol}://{server}'
+ variables:
+ protocol:
+ enum:
+ - http
+ - https
+ default: https
+ server:
+ default: 'example.com'
+
+tags:
+ - name: Recipes
+ description: Everything related to recipes and their usage
+ - name: Categories
+ description: Access to the categories of the recipes
+ - name: Tags
+ description: Access to tags/keywords of recipes
+ - name: Misc
+ description: Other API endpoints
+
+
+
+components:
+ schemas:
+ Config:
+ $ref: objects.yaml#/Config
+ Error:
+ $ref: objects.yaml#/Error
+ RecipeStub:
+ $ref: objects.yaml#/RecipeStub
+ StubList:
+ $ref: objects.yaml#/StubList
+ Recipe:
+ $ref: objects.yaml#/Recipe
+ Version:
+ $ref: objects.yaml#/Version
+
+ securitySchemes:
+ app_password:
+ type: http
+ scheme: basic
+ description: Use username and app password
+
+security:
+ - app_password: []
+
+paths:
+
+ /api/version:
+ get:
+ tags: [ Misc ]
+ summary: Get the version of the API endpoint
+ responses:
+ '200':
+ description: API version
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/Version"
+ /api/v1/reindex:
+ post:
+ tags: [ Misc ]
+ summary: Trigger a rescan of all recipes into the caching database
+ responses:
+ 200:
+ description: The reindex process was done.
+ content:
+ application/json:
+ schema:
+ type: string
+ example: Search index rebuilt successfully
+ /api/v1/config:
+ get:
+ tags: [ Misc ]
+ summary: Get the current configuration of the app
+ responses:
+ 200:
+ description: The config was read successfully
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/Config"
+ post:
+ tags: [ Misc ]
+ summary: Set the configuration for the current user
+ responses:
+ 200:
+ description: The configuration was successfully saved.
+ content:
+ application/json:
+ schema:
+ type: string
+ example: OK
+
+ /api/v1/import:
+ post:
+ tags: [ Recipes ]
+ summary: Import a recipe using schema.org metadata from a website
+ requestBody:
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ url:
+ type: string
+ example: 'http://www.chefkoch.de/2345'
+ required:
+ - url
+ responses:
+ 200:
+ description: Successfully imported recipe
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/Recipe"
+ 400:
+ description: The URL to be imported was not inserted in the request or any other issue was rosen.
+ content:
+ application/json:
+ schema:
+ type: string
+ example: Field "url" is required
+ 409:
+ description: There exists a recipe with that name already. Import was aborted.
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/Error"
+ /api/v1/recipes/{id}/image:
+ get:
+ tags: [ Recipes ]
+ summary: Get the main image of a recipe. If no image is stored a fallback image is delivered.
+ parameters:
+ - in: path
+ name: id
+ description: The id of the recipe to obtain the image for.
+ required: true
+ schema:
+ type: integer
+ responses:
+ 200:
+ description: Image was obtained and will be in response either as image/jpeg or image/svg+xml
+ content:
+ image/jpeg:
+ schema:
+ type: string
+ format: binary
+ image/svg+xml:
+ schema:
+ type: string
+ format: binary
+ 406:
+ description: The recipe has no image whose MIME type matches the Accept header
+ /api/v1/search/{query}:
+ parameters:
+ - in: path
+ name: query
+ required: true
+ description: The search string, urlencoded, separated with spaces and/or commas
+ schema:
+ type: string
+ get:
+ tags: [ Recipes ]
+ summary: Search for recipes for keywords, tags and categories with the named search string
+ responses:
+ 200:
+ description: The recipes were obtained successfully
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/StubList"
+ 500:
+ description: An error has been thrown
+ content:
+ application/json:
+ schema:
+ type: string
+ description: The error message
+ /api/v1/recipes:
+ get:
+ tags: [ Recipes ]
+ summary: Get all recipes in the database
+ responses:
+ 200:
+ description: Successfully obtained all recipes
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/StubList"
+ post:
+ tags: [ Recipes ]
+ summary: Create a new recipe
+ requestBody:
+ description: |
+ A JSON representation of the recipe to be saved.
+
+ See also the structure at https://schema.org/Recipe
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ name:
+ type: string
+ required: [ "name" ]
+ additionalProperties: true
+ example:
+ name: "Chips"
+ description: "A very delicious way of getting kids quiet"
+ ingredients:
+ - "1 pack of pre-fried chips"
+ tools: ["common oven"]
+ instructions:
+ - "Put the chips in the oven"
+ - "Wait until the are due"
+ responses:
+ 200:
+ description: Successfully created new recipe
+ content:
+ application/json:
+ schema:
+ type: integer
+ example: 2462
+ description: The id of the newly created recipe
+ 409:
+ description: A recipe with the name was already found on the server. No recipe is created.
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/Error"
+ 422:
+ description: There was no name in the request given for the recipe. Cannot save the recipe.
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/Error"
+ /api/v1/recipes/{id}:
+ parameters:
+ - in: path
+ name: id
+ required: true
+ description: The id of the recipe
+ schema:
+ type: integer
+ get:
+ tags: [ Recipes ]
+ summary: Get a single recipe from the server
+ responses:
+ 200:
+ description: Recipe was sucessfully obtained
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/Recipe"
+ 404:
+ description: The given recipe id was not found
+ content:
+ application/json:
+ schema:
+ type: integer
+ example: 2345
+ description: The id of the recipe that was not found
+ put:
+ tags: [ Recipes ]
+ summary: Update a recipe
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/Recipe"
+ responses:
+ 200:
+ description: The recipe was sucessfully updated
+ content:
+ application/json:
+ schema:
+ type: integer
+ description: The id of the updated recipe
+ example: 2345
+ 422:
+ description: There was no name in the request given for the recipe. Cannot save the recipe.
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/Error"
+
+ delete:
+ tags: [ Recipes ]
+ summary: Delete an existing recipe
+ responses:
+ 200:
+ description: The recipe was deleted successfully
+ content:
+ application/json:
+ schema:
+ type: string
+ example: Recipe 2345 was deletes successfully
+ 502:
+ description: An Exception was thrown
+ content:
+ application/json:
+ schema:
+ type: string
+ example: Recipe with id 2345 was not found.
+ description: Error message
+
+ /api/v1/keywords:
+ get:
+ tags: [ Tags ]
+ summary: Get all known keywords
+ responses:
+ '200':
+ description: Successfully obtained all keywords
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ type: object
+ properties:
+ name:
+ type: string
+ recipe_count:
+ type: integer
+ required:
+ - name
+ - recipe_count
+ example:
+ - name: vegetarian
+ recipe_count: 5
+ - name: sugar-free
+ recipe_count: 2
+ /api/v1/tags/{keywords}:
+ get:
+ tags: [ Tags ]
+ summary: Get all recipes associated with certain keywords
+ parameters:
+ - in: path
+ name: keywords
+ required: true
+ description: Comma separated list of keywords, urlencoded
+ schema:
+ type: string
+ example: vegetarian,sweet
+ responses:
+ 200:
+ description: Recipes were successfully obtained
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/StubList"
+ 500:
+ description: An error occured
+ content:
+ application/json:
+ schema:
+ type: string
+ example: "SQLException: Something went wrong."
+
+ /api/v1/categories:
+ get:
+ tags: [ Categories ]
+ summary: Get all known categories
+ responses:
+ 200:
+ description: >-
+ Sucessfully obtained all categories
+
+
+ Please note: A category name of `*` indicates the number of
+ recipes with no category associated.
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ type: object
+ properties:
+ name:
+ type: string
+ recipe_count:
+ type: integer
+ required:
+ - name
+ - recipe_count
+ example:
+ - name: Dinner
+ recipe_count: 21
+ - name: Lunch
+ recipe_count: 10
+ - name: '*'
+ recipe_count: 3
+ /api/v1/category/{category}:
+ get:
+ tags: [ Categories ]
+ summary: Get all recipes of a certain category
+ parameters:
+ - in: path
+ name: category
+ required: true
+ description: >-
+ The name of the category to be queried as urlencoded string
+
+
+ Put the string `_` to obtain all recipes with no category
+ schema:
+ type: string
+ responses:
+ 200:
+ description: The filtered recipes belonging to the category
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/StubList"
+ 500:
+ description: An exception was issued.
+ content:
+ application/json:
+ schema:
+ type: string
+ description: The error message
+ example: Could not find category foo.
+ put:
+ tags: [ Categories ]
+ summary: Rename a category
+ parameters:
+ - in: path
+ name: category
+ required: true
+ description: >-
+ The name of the category to be queried as urlencoded string
+
+
+ Put the string `_` to obtain all recipes with no category
+ schema:
+ type: string
+ requestBody:
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ name:
+ type: string
+ example: Lunch
+ description: The new name to rename the category to
+ required:
+ - name
+ responses:
+ 200:
+ description: The category was renamed successfully
+ content:
+ application/json:
+ schema:
+ type: string
+ example: Lunch
+ 400:
+ description: The new category name was not included during the request.
+ 500:
+ description: The renaming did not succeed.
+ content:
+ application/json:
+ schema:
+ type: string
+ description: The error message
+ example: There exists already a category of that name.
diff --git a/docs/dev/api/changelog/0.md b/docs/dev/api/changelog/0.md
index 4b0f2c3ce..a63975934 100644
--- a/docs/dev/api/changelog/0.md
+++ b/docs/dev/api/changelog/0.md
@@ -8,6 +8,16 @@ This serves only for developers to find the changes better.
## Unpublished
+### Split and rename API endpoints
+There is a security issue with the previous API version 0.4.0, see [this description](https://github.com/nextcloud/cookbook/issues/1179).
+As a result, **all** endpoints need a renaming to be able to fix the security issue.
+
+All publicly available endpoints are now located under the `/api/v1` prefix.
+Endpoints were prefixed with either `/api/v1` (if not already prefixed by `/api`) or the `/api` was replaced by `/api/v1` in all URLs.
+
+The behavior of the endpoints was not changed.
+
+
## Version 0.0.4 - cookbook v0.9.13 - 2022-07-02
See [API specification](../0.0.4/index.html)
diff --git a/docs/dev/api/index.md b/docs/dev/api/index.md
index d4d20af70..52b3a186d 100644
--- a/docs/dev/api/index.md
+++ b/docs/dev/api/index.md
@@ -5,6 +5,7 @@ This page provides an overview over the possible API endpoints provided by the a
- [Version 0.0.2](0.0.2/index.html)
- [Version 0.0.3](0.0.3/index.html)
- [Version 0.0.4](0.0.4/index.html)
+- [Version 0.1.0](0.1.0/index.html) ([internal interface](0.1.0/internal.html))
The following list provides a in depth changelog for the individual epochs:
diff --git a/docs/dev/deployment.md b/docs/dev/deployment.md
index 3e33a750f..7fadf0bf5 100644
--- a/docs/dev/deployment.md
+++ b/docs/dev/deployment.md
@@ -24,7 +24,7 @@ So you might want to create a branch `release/1.2.4` from master.
git checkout -b release/1.2.4 master
```
-### Update the changelog
+### Update the changelogs
In the release branch you will have to prepare the changelog file.
This means, you have to add a new second level heading to the unreleased changes so far.
@@ -34,6 +34,9 @@ You might need to add
```
as one of the first few lines with `YYYY-mm-dd` the current date.
+Also check if any pending API change is present.
+Update the API changelog (in `/docs/dev/api/changelog/*.md`) accordingly.
+
Commit the changes and push them to github.
### Create pull request