@@ -22,7 +22,7 @@
-
+
diff --git a/public/api/schema/assigned-category.json b/public/api/schema/assigned-category.json
index b8ec66eb..8be281a5 100644
--- a/public/api/schema/assigned-category.json
+++ b/public/api/schema/assigned-category.json
@@ -1,4 +1,5 @@
{
+ "$id": "https://api.costs-to-expect.com/v2/api/schema/assigned-category.json",
"type": "object",
"properties": {
"id": {
diff --git a/public/api/schema/assigned-subcategory.json b/public/api/schema/assigned-subcategory.json
index 727f08a6..d13a249a 100644
--- a/public/api/schema/assigned-subcategory.json
+++ b/public/api/schema/assigned-subcategory.json
@@ -1,4 +1,5 @@
{
+ "$id": "https://api.costs-to-expect.com/v2/api/schema/assigned-subcategory.json",
"type": "object",
"properties": {
"id": {
diff --git a/public/api/schema/auth/options/create-password.json b/public/api/schema/auth/options/create-password.json
index 69d3166c..f08f72b7 100644
--- a/public/api/schema/auth/options/create-password.json
+++ b/public/api/schema/auth/options/create-password.json
@@ -1,4 +1,5 @@
{
+ "$id": "https://api.costs-to-expect.com/v2/api/schema/auth/options/create-password.json",
"type": "object",
"properties": {
"POST": {
diff --git a/public/api/schema/auth/options/register.json b/public/api/schema/auth/options/register.json
index 045c08eb..c20052b9 100644
--- a/public/api/schema/auth/options/register.json
+++ b/public/api/schema/auth/options/register.json
@@ -1,4 +1,5 @@
{
+ "$id": "https://api.costs-to-expect.com/v2/api/schema/auth/options/register.json",
"type": "object",
"properties": {
"POST": {
diff --git a/public/api/schema/category.json b/public/api/schema/category.json
index d089021b..2fa39b25 100644
--- a/public/api/schema/category.json
+++ b/public/api/schema/category.json
@@ -1,4 +1,5 @@
{
+ "$id": "https://api.costs-to-expect.com/v2/api/schema/category.json",
"type": "object",
"properties": {
"id": {
diff --git a/public/api/schema/currency.json b/public/api/schema/currency.json
index 616f374c..0e85e6ca 100644
--- a/public/api/schema/currency.json
+++ b/public/api/schema/currency.json
@@ -1,4 +1,5 @@
{
+ "$id": "https://api.costs-to-expect.com/v2/api/schema/category.json",
"type": "object",
"properties": {
"id": {
diff --git a/public/api/schema/error-log.json b/public/api/schema/error-log.json
index 10887a2c..3378639f 100644
--- a/public/api/schema/error-log.json
+++ b/public/api/schema/error-log.json
@@ -1,4 +1,5 @@
{
+ "$id": "https://api.costs-to-expect.com/v2/api/schema/error-log.json",
"type": "object",
"properties": {
"method": {
diff --git a/public/api/schema/item-allocated-expense.json b/public/api/schema/item-allocated-expense.json
index 570c094d..9f4554cf 100644
--- a/public/api/schema/item-allocated-expense.json
+++ b/public/api/schema/item-allocated-expense.json
@@ -1,4 +1,5 @@
{
+ "$id": "https://api.costs-to-expect.com/v2/api/schema/item-allocated-expense.json",
"type": "object",
"properties": {
"id": {
diff --git a/public/api/schema/item-category.json b/public/api/schema/item-category.json
index a3c13d60..59130e04 100644
--- a/public/api/schema/item-category.json
+++ b/public/api/schema/item-category.json
@@ -1,4 +1,5 @@
{
+ "$id": "https://api.costs-to-expect.com/v2/api/schema/item-category.json",
"type": "object",
"properties": {
"id": {
diff --git a/public/api/schema/item-game.json b/public/api/schema/item-game.json
index e1636df6..6ae5744a 100644
--- a/public/api/schema/item-game.json
+++ b/public/api/schema/item-game.json
@@ -1,4 +1,5 @@
{
+ "$id": "https://api.costs-to-expect.com/v2/api/schema/item-game.json",
"type": "object",
"properties": {
"id": {
diff --git a/public/api/schema/item-simple-expense.json b/public/api/schema/item-simple-expense.json
index 1a473c5d..98477587 100644
--- a/public/api/schema/item-simple-expense.json
+++ b/public/api/schema/item-simple-expense.json
@@ -1,4 +1,5 @@
{
+ "$id": "https://api.costs-to-expect.com/v2/api/schema/item-simple-expense.json",
"type": "object",
"properties": {
"id": {
diff --git a/public/api/schema/item-simple-item.json b/public/api/schema/item-simple-item.json
index f5e0b29c..2e316977 100644
--- a/public/api/schema/item-simple-item.json
+++ b/public/api/schema/item-simple-item.json
@@ -1,4 +1,5 @@
{
+ "$id": "https://api.costs-to-expect.com/v2/api/schema/item-simple-item.json",
"type": "object",
"properties": {
"id": {
diff --git a/public/api/schema/item-subcategory.json b/public/api/schema/item-subcategory.json
index b0bbfb7e..2d82d179 100644
--- a/public/api/schema/item-subcategory.json
+++ b/public/api/schema/item-subcategory.json
@@ -1,4 +1,5 @@
{
+ "$id": "https://api.costs-to-expect.com/v2/api/schema/item-subcategory.json",
"type": "object",
"properties": {
"id": {
diff --git a/public/api/schema/item-subtype.json b/public/api/schema/item-subtype.json
index 991d0f42..b0512c2c 100644
--- a/public/api/schema/item-subtype.json
+++ b/public/api/schema/item-subtype.json
@@ -1,4 +1,5 @@
{
+ "$id": "https://api.costs-to-expect.com/v2/api/schema/item-subtype.json",
"type": "object",
"properties": {
"id": {
diff --git a/public/api/schema/item-type.json b/public/api/schema/item-type.json
index 50adc08f..98ab33e6 100644
--- a/public/api/schema/item-type.json
+++ b/public/api/schema/item-type.json
@@ -1,4 +1,5 @@
{
+ "$id": "https://api.costs-to-expect.com/v2/api/schema/item-type.json",
"type": "object",
"properties": {
"id": {
@@ -18,14 +19,14 @@
},
"created": {
"type": "string"
- },
- "required": [
- "id",
- "name",
- "friendly_name",
- "description",
- "example",
- "created"
- ]
- }
+ }
+ },
+ "required": [
+ "id",
+ "name",
+ "friendly_name",
+ "description",
+ "example",
+ "created"
+ ]
}
diff --git a/public/api/schema/options/resource-type-collection.json b/public/api/schema/options/resource-type-collection.json
new file mode 100644
index 00000000..188ba745
--- /dev/null
+++ b/public/api/schema/options/resource-type-collection.json
@@ -0,0 +1,537 @@
+{
+ "$id": "https://api.costs-to-expect.com/v2/api/schema/options/resource-type-collection.json",
+ "type": "object",
+ "properties": {
+ "GET": {
+ "type": "object",
+ "properties": {
+ "description": {
+ "type": "string"
+ },
+ "authentication": {
+ "type": "object",
+ "properties": {
+ "required": {
+ "type": "boolean"
+ },
+ "authenticated": {
+ "type": "boolean"
+ }
+ },
+ "required": [
+ "required",
+ "authenticated"
+ ]
+ },
+ "sortable": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "searchable": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string"
+ }
+ }
+ },
+ "description": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "required": [
+ "name",
+ "description"
+ ]
+ },
+ "filterable": {
+ "type": [
+ "array"
+ ]
+ },
+ "parameters": {
+ "type":"object",
+ "properties": {
+ "offset": {
+ "type": "object",
+ "properties": {
+ "parameter": {
+ "type": "string"
+ },
+ "title": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "default": {
+ "type": "integer"
+ },
+ "type": {
+ "type": "string"
+ },
+ "required": {
+ "type": "boolean"
+ }
+ },
+ "required": [
+ "parameter",
+ "title",
+ "description",
+ "default",
+ "type",
+ "required"
+ ]
+ },
+ "limit": {
+ "type": "object",
+ "properties": {
+ "parameter": {
+ "type": "string"
+ },
+ "title": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "default": {
+ "type": "integer"
+ },
+ "type": {
+ "type": "string"
+ },
+ "required": {
+ "type": "boolean"
+ }
+ },
+ "required": [
+ "parameter",
+ "title",
+ "description",
+ "default",
+ "type",
+ "required"
+ ]
+ },
+ "collection": {
+ "type": "object",
+ "properties": {
+ "parameter": {
+ "type": "string"
+ },
+ "title": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "default": {
+ "type": "boolean"
+ },
+ "type": {
+ "type": "string"
+ },
+ "required": {
+ "type": "boolean"
+ }
+ },
+ "required": [
+ "parameter",
+ "title",
+ "description",
+ "default",
+ "type",
+ "required"
+ ]
+ },
+ "sort": {
+ "type": "object",
+ "properties": {
+ "parameter": {
+ "type": "string"
+ },
+ "title": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "default": {
+ "type": "null"
+ },
+ "type": {
+ "type": "string"
+ },
+ "required": {
+ "type": "boolean"
+ }
+ },
+ "required": [
+ "parameter",
+ "title",
+ "description",
+ "default",
+ "type",
+ "required"
+ ]
+ },
+ "search": {
+ "type": "object",
+ "properties": {
+ "parameter": {
+ "type": "string"
+ },
+ "title": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "default": {
+ "type": "null"
+ },
+ "type": {
+ "type": "string"
+ },
+ "required": {
+ "type": "boolean"
+ }
+ },
+ "required": [
+ "parameter",
+ "title",
+ "description",
+ "default",
+ "type",
+ "required"
+ ]
+ }
+ },
+ "required": [
+ "offset",
+ "limit",
+ "collection",
+ "sort",
+ "search"
+ ]
+ }
+ },
+ "required": [
+ "description",
+ "authentication",
+ "sortable",
+ "searchable",
+ "filterable",
+ "parameters"
+ ]
+ },
+ "POST": {
+ "type": "object",
+ "properties": {
+ "description": {
+ "type": "string"
+ },
+ "authentication": {
+ "type": "object",
+ "properties": {
+ "required": {
+ "type": "boolean"
+ },
+ "authenticated": {
+ "type": "boolean"
+ }
+ },
+ "required": [
+ "required",
+ "authenticated"
+ ]
+ },
+ "fields": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "object",
+ "properties": {
+ "field": {
+ "type": "string"
+ },
+ "title": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "type": {
+ "type": "string"
+ },
+ "validation": {
+ "type": "object",
+ "properties": {
+ "max-length": {
+ "type": "integer"
+ }
+ },
+ "required": [
+ "max-length"
+ ]
+ },
+ "required": {
+ "type": "boolean"
+ }
+ },
+ "required": [
+ "field",
+ "title",
+ "description",
+ "type",
+ "validation",
+ "required"
+ ]
+ },
+ "description": {
+ "type": "object",
+ "properties": {
+ "field": {
+ "type": "string"
+ },
+ "title": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "type": {
+ "type": "string"
+ },
+ "required": {
+ "type": "boolean"
+ }
+ },
+ "required": [
+ "field",
+ "title",
+ "description",
+ "type",
+ "required"
+ ]
+ },
+ "data": {
+ "type": "object",
+ "properties": {
+ "field": {
+ "type": "string"
+ },
+ "title": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "type": {
+ "type": "string"
+ },
+ "required": {
+ "type": "boolean"
+ }
+ },
+ "required": [
+ "field",
+ "title",
+ "description",
+ "type",
+ "required"
+ ]
+ },
+ "item_type_id": {
+ "type": "object",
+ "properties": {
+ "field": {
+ "type": "string"
+ },
+ "title": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "type": {
+ "type": "string"
+ },
+ "validation": {
+ "type": "object",
+ "properties": {
+ "length": {
+ "type": "integer"
+ }
+ },
+ "required": [
+ "length"
+ ]
+ },
+ "required": {
+ "type": "boolean"
+ },
+ "allowed_values": {
+ "type": "object",
+ "properties": {
+ "OqZwKX16bW": {
+ "type": "object",
+ "properties": {
+ "value": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "value",
+ "name",
+ "description"
+ ]
+ },
+ "gjp4P71YJe": {
+ "type": "object",
+ "properties": {
+ "value": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "value",
+ "name",
+ "description"
+ ]
+ },
+ "QxO1VLyM86": {
+ "type": "object",
+ "properties": {
+ "value": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "value",
+ "name",
+ "description"
+ ]
+ },
+ "2AP1axw6L7": {
+ "type": "object",
+ "properties": {
+ "value": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "value",
+ "name",
+ "description"
+ ]
+ }
+ },
+ "required": [
+ "OqZwKX16bW",
+ "gjp4P71YJe",
+ "QxO1VLyM86",
+ "2AP1axw6L7"
+ ]
+ }
+ },
+ "required": [
+ "field",
+ "title",
+ "description",
+ "type",
+ "validation",
+ "required"
+ ]
+ },
+ "public": {
+ "type": "object",
+ "properties": {
+ "field": {
+ "type": "string"
+ },
+ "title": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "type": {
+ "type": "string"
+ },
+ "required": {
+ "type": "boolean"
+ }
+ },
+ "required": [
+ "field",
+ "title",
+ "description",
+ "type",
+ "required"
+ ]
+ }
+ },
+ "required": [
+ "name",
+ "description",
+ "data",
+ "item_type_id",
+ "public"
+ ]
+ },
+ "parameters": {
+ "type": [
+ "object",
+ "array"
+ ]
+ }
+ },
+ "required": [
+ "description",
+ "authentication",
+ "fields",
+ "parameters"
+ ]
+ }
+ },
+ "required": [
+ "GET",
+ "POST"
+ ]
+}
diff --git a/public/api/schema/options/resource-type.json b/public/api/schema/options/resource-type.json
new file mode 100644
index 00000000..f8d0a28a
--- /dev/null
+++ b/public/api/schema/options/resource-type.json
@@ -0,0 +1,299 @@
+{
+ "$id": "https://api.costs-to-expect.com/v2/api/schema/options/resource-type-collection.json",
+ "type": "object",
+ "properties": {
+ "DELETE": {
+ "type": "object",
+ "properties": {
+ "description": {
+ "type": "string"
+ },
+ "authentication": {
+ "type": "object",
+ "properties": {
+ "required": {
+ "type": "boolean"
+ },
+ "authenticated": {
+ "type": "boolean"
+ }
+ },
+ "required": [
+ "required",
+ "authenticated"
+ ]
+ }
+ },
+ "required": [
+ "description",
+ "authentication"
+ ]
+ },
+ "GET" : {
+ "type": "object",
+ "properties": {
+ "description": {
+ "type": "string"
+ },
+ "authentication": {
+ "type": "object",
+ "properties": {
+ "required": {
+ "type": "boolean"
+ },
+ "authenticated": {
+ "type": "boolean"
+ }
+ },
+ "required": [
+ "required",
+ "authenticated"
+ ]
+ },
+ "sortable": {
+ "type": "array"
+ },
+ "searchable": {
+ "type": "array"
+ },
+ "filterable": {
+ "type": "array"
+ },
+ "parameters": {
+ "type": "object",
+ "properties": {
+ "include-resources": {
+ "type": "object",
+ "properties": {
+ "field": {
+ "type": "string"
+ },
+ "title": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "type": {
+ "type": "string"
+ },
+ "required": {
+ "type": "boolean"
+ }
+ },
+ "required": [
+ "field",
+ "title",
+ "description",
+ "type",
+ "required"
+ ]
+ },
+ "include-permitted-users": {
+ "type": "object",
+ "properties": {
+ "field": {
+ "type": "string"
+ },
+ "title": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "type": {
+ "type": "string"
+ },
+ "required": {
+ "type": "boolean"
+ }
+ },
+ "required": [
+ "field",
+ "title",
+ "description",
+ "type",
+ "required"
+ ]
+ }
+ },
+ "required": [
+ "include-resources",
+ "include-permitted-users"
+ ]
+ }
+ },
+ "required": [
+ "description",
+ "authentication",
+ "sortable",
+ "searchable",
+ "filterable"
+ ]
+ },
+ "PATCH": {
+ "type": "object",
+ "properties": {
+ "description": {
+ "type": "string"
+ },
+ "authentication": {
+ "type": "object",
+ "properties": {
+ "required": {
+ "type": "boolean"
+ },
+ "authenticated": {
+ "type": "boolean"
+ }
+ },
+ "required": [
+ "required",
+ "authenticated"
+ ]
+ },
+ "fields": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "object",
+ "properties": {
+ "field": {
+ "type": "string"
+ },
+ "title": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "type": {
+ "type": "string"
+ },
+ "validation": {
+ "type": "object",
+ "properties": {
+ "max-length": {
+ "type": "integer"
+ }
+ },
+ "required": [
+ "max-length"
+ ]
+ },
+ "required": {
+ "type": "boolean"
+ }
+ },
+ "required": [
+ "field",
+ "title",
+ "description",
+ "type",
+ "validation",
+ "required"
+ ]
+ },
+ "description": {
+ "type": "object",
+ "properties": {
+ "field": {
+ "type": "string"
+ },
+ "title": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "type": {
+ "type": "string"
+ },
+ "required": {
+ "type": "boolean"
+ }
+ },
+ "required": [
+ "field",
+ "title",
+ "description",
+ "type",
+ "required"
+ ]
+ },
+ "data": {
+ "type": "object",
+ "properties": {
+ "field": {
+ "type": "string"
+ },
+ "title": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "type": {
+ "type": "string"
+ },
+ "required": {
+ "type": "boolean"
+ }
+ },
+ "required": [
+ "field",
+ "title",
+ "description",
+ "type",
+ "required"
+ ]
+ },
+ "public": {
+ "type": "object",
+ "properties": {
+ "field": {
+ "type": "string"
+ },
+ "title": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "type": {
+ "type": "string"
+ },
+ "required": {
+ "type": "boolean"
+ }
+ },
+ "required": [
+ "field",
+ "title",
+ "description",
+ "type",
+ "required"
+ ]
+ }
+ },
+ "required": [
+ "name",
+ "description",
+ "data",
+ "public"
+ ]
+ }
+ },
+ "required": [
+ "description",
+ "authentication",
+ "fields"
+ ]
+ }
+ },
+ "required": [
+ "DELETE",
+ "GET",
+ "DELETE"
+ ]
+}
\ No newline at end of file
diff --git a/public/api/schema/partial-transfer.json b/public/api/schema/partial-transfer.json
index 3f738095..5df17707 100644
--- a/public/api/schema/partial-transfer.json
+++ b/public/api/schema/partial-transfer.json
@@ -1,4 +1,5 @@
{
+ "$id": "https://api.costs-to-expect.com/v2/api/schema/partial-transfer.json",
"type": "object",
"properties": {
"id": {
diff --git a/public/api/schema/permitted-user.json b/public/api/schema/permitted-user.json
index f43efe08..f4ce168e 100644
--- a/public/api/schema/permitted-user.json
+++ b/public/api/schema/permitted-user.json
@@ -1,4 +1,5 @@
{
+ "$id": "https://api.costs-to-expect.com/v2/api/schema/permitted-user.json",
"type": "object",
"properties": {
"id": {
diff --git a/public/api/schema/resource-type-include-permitted-users.json b/public/api/schema/resource-type-include-permitted-users.json
new file mode 100644
index 00000000..78edc530
--- /dev/null
+++ b/public/api/schema/resource-type-include-permitted-users.json
@@ -0,0 +1,114 @@
+{
+ "$id": "https://api.costs-to-expect.com/v2/api/schema/resource-type-include-permitted-users.json",
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "data": {
+ "type": ["object", "null"]
+ },
+ "created": {
+ "type": "string"
+ },
+ "public": {
+ "type": "boolean"
+ },
+ "item_type": {
+ "type": "object",
+ "properties": {
+ "uri": {
+ "type": "string"
+ },
+ "id": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "friendly_name": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "uri",
+ "id",
+ "name",
+ "friendly_name",
+ "description"
+ ]
+ },
+ "resources": {
+ "type": "object",
+ "properties": {
+ "uri": {
+ "type": "string"
+ },
+ "count": {
+ "type": "integer"
+ }
+ },
+ "required": [
+ "uri",
+ "count"
+ ]
+ },
+ "permitted_users": {
+ "type": "object",
+ "properties": {
+ "uri": {
+ "type": "string"
+ },
+ "count": {
+ "type": "integer"
+ },
+ "collection": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "email": {
+ "type": "string"
+ },
+ "created": {
+ "type": "string"
+ }
+ },
+ "required": []
+ }
+ }
+ },
+ "required": [
+ "uri",
+ "count",
+ "collection"
+ ]
+ }
+ },
+ "required": [
+ "id",
+ "name",
+ "description",
+ "data",
+ "created",
+ "public",
+ "item_type",
+ "resources",
+ "permitted_users"
+ ]
+}
diff --git a/public/api/schema/resource-type-include-resources.json b/public/api/schema/resource-type-include-resources.json
new file mode 100644
index 00000000..1370fd48
--- /dev/null
+++ b/public/api/schema/resource-type-include-resources.json
@@ -0,0 +1,133 @@
+{
+ "$id": "https://api.costs-to-expect.com/v2/api/schema/resource-type-include-resources.json",
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "data": {
+ "type": ["object", "null"]
+ },
+ "created": {
+ "type": "string"
+ },
+ "public": {
+ "type": "boolean"
+ },
+ "item_type": {
+ "type": "object",
+ "properties": {
+ "uri": {
+ "type": "string"
+ },
+ "id": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "friendly_name": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "uri",
+ "id",
+ "name",
+ "friendly_name",
+ "description"
+ ]
+ },
+ "resources": {
+ "type": "object",
+ "properties": {
+ "uri": {
+ "type": "string"
+ },
+ "count": {
+ "type": "integer"
+ },
+ "collection": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "data": {
+ "type": [
+ "object",
+ "null"
+ ]
+ },
+ "created": {
+ "type": "string"
+ },
+ "item_subtype": {
+ "type": "object",
+ "properties": {
+ "uri": {
+ "type": "string"
+ },
+ "id": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "uri",
+ "id",
+ "name",
+ "description"
+ ]
+ }
+ },
+ "required": [
+ "id",
+ "name",
+ "description",
+ "data",
+ "created"
+ ]
+ }
+ }
+ },
+ "required": [
+ "uri",
+ "count",
+ "collection"
+ ]
+ }
+ },
+ "required": [
+ "id",
+ "name",
+ "description",
+ "data",
+ "created",
+ "public",
+ "item_type",
+ "resources"
+ ]
+}
diff --git a/public/api/schema/resource-type-item-allocated-expense.json b/public/api/schema/resource-type-item-allocated-expense.json
index eebf66c4..fe585aed 100644
--- a/public/api/schema/resource-type-item-allocated-expense.json
+++ b/public/api/schema/resource-type-item-allocated-expense.json
@@ -1,4 +1,5 @@
{
+ "$id": "https://api.costs-to-expect.com/v2/api/schema/resource-type-item-allocated-expense.json",
"type": "object",
"properties": {
"id": {
diff --git a/public/api/schema/resource-type-item-game.json b/public/api/schema/resource-type-item-game.json
index fa2e7574..33118d3b 100644
--- a/public/api/schema/resource-type-item-game.json
+++ b/public/api/schema/resource-type-item-game.json
@@ -1,4 +1,5 @@
{
+ "$id": "https://api.costs-to-expect.com/v2/api/schema/resource-type-item-game.json",
"type": "object",
"properties": {
"id": {
diff --git a/public/api/schema/resource-type-item-simple-expense.json b/public/api/schema/resource-type-item-simple-expense.json
index a64bee98..5cf564eb 100644
--- a/public/api/schema/resource-type-item-simple-expense.json
+++ b/public/api/schema/resource-type-item-simple-expense.json
@@ -1,4 +1,5 @@
{
+ "$id": "https://api.costs-to-expect.com/v2/api/schema/resource-type-item-simple-expense.json",
"type": "object",
"properties": {
"id": {
diff --git a/public/api/schema/resource-type-item-simple-item.json b/public/api/schema/resource-type-item-simple-item.json
index 6aae2ec6..083c31e6 100644
--- a/public/api/schema/resource-type-item-simple-item.json
+++ b/public/api/schema/resource-type-item-simple-item.json
@@ -1,4 +1,5 @@
{
+ "$id": "https://api.costs-to-expect.com/v2/api/schema/resource-type-item-simple-item.json",
"type": "object",
"properties": {
"id": {
diff --git a/public/api/schema/resource-type.json b/public/api/schema/resource-type.json
index e905e0d9..d775ce6f 100644
--- a/public/api/schema/resource-type.json
+++ b/public/api/schema/resource-type.json
@@ -1,4 +1,5 @@
{
+ "$id": "https://api.costs-to-expect.com/v2/api/schema/resource-type.json",
"type": "object",
"properties": {
"id": {
@@ -22,6 +23,9 @@
"item_type": {
"type": "object",
"properties": {
+ "uri": {
+ "type": "string"
+ },
"id": {
"type": "string"
},
@@ -36,6 +40,7 @@
}
},
"required": [
+ "uri",
"id",
"name",
"friendly_name",
@@ -45,23 +50,17 @@
"resources": {
"type": "object",
"properties": {
+ "uri": {
+ "type": "string"
+ },
"count": {
"type": "integer"
}
},
"required": [
+ "uri",
"count"
]
-
- },
- "permitted_users": {
- "type": "object",
- "properties": {
- "count": {
- "type": "integer"
- }
- }
-
}
},
"required": [
diff --git a/public/api/schema/resource.json b/public/api/schema/resource.json
index fafe26ed..c08229c0 100644
--- a/public/api/schema/resource.json
+++ b/public/api/schema/resource.json
@@ -1,4 +1,5 @@
{
+ "$id": "https://api.costs-to-expect.com/v2/api/schema/resource.json",
"type": "object",
"properties": {
"id": {
@@ -13,25 +14,6 @@
"data": {
"type": ["object", "null"]
},
- "item_subtype": {
- "type": "object",
- "properties": {
- "id": {
- "type": "string"
- },
- "name": {
- "type": "string"
- },
- "description": {
- "type": "string"
- }
- },
- "required": [
- "id",
- "name",
- "description"
- ]
- },
"created": {
"type": "string"
}
@@ -41,7 +23,6 @@
"name",
"description",
"data",
- "item_subtype",
"created"
]
}
diff --git a/public/api/schema/subcategory.json b/public/api/schema/subcategory.json
index 25a5c5f8..5b010163 100644
--- a/public/api/schema/subcategory.json
+++ b/public/api/schema/subcategory.json
@@ -1,4 +1,5 @@
{
+ "$id": "https://api.costs-to-expect.com/v2/api/schema/subcategory.json",
"type": "object",
"properties": {
"id": {
diff --git a/public/api/schema/transfer.json b/public/api/schema/transfer.json
index 2052d4c5..f8217d7c 100644
--- a/public/api/schema/transfer.json
+++ b/public/api/schema/transfer.json
@@ -1,4 +1,5 @@
{
+ "$id": "https://api.costs-to-expect.com/v2/api/schema/transfer.json",
"type": "object",
"properties": {
"id": {
diff --git a/resources/lang/en/responses.php b/resources/lang/en/responses.php
index cf9198fd..fc316a96 100644
--- a/resources/lang/en/responses.php
+++ b/resources/lang/en/responses.php
@@ -8,6 +8,7 @@
'not-found-or-not-accessible-entity' => 'The requested `:type` does not exist or is not accessible with your permissions.',
'not-supported' => 'The requested route is not supported for the item type',
'constraint' => 'Unable to handle your request, dependent data exists or foreign key error.',
+ 'constraint-category' => 'Unable to handle your request, category data exists for the item, delete the category first.',
'model-select-failure' => 'Unable to handle your request, an error occurred when selecting the data to complete your request.',
'model-save-failure-update' => 'Unable to handle your request, an error occurred when processing your update request.',
'model-save-failure-create' => 'Unable to handle your request, an error occurred when processing your create request.',
@@ -20,4 +21,5 @@
'error' => 'Sorry, there has been an error, please try again later.',
'category-limit' => 'Unable to handle your request, the number of allowable category assignments reached',
'subcategory-limit' => 'Unable to handle your request, the number of allowable subcategory assignments reached',
+ 'invalid-route' => 'The requested route is invalid, please visit the index of the API to see all the valid routes https://api.costs-to-expect.com/v2'
];
diff --git a/resources/lang/en/route-descriptions.php b/resources/lang/en/route-descriptions.php
index 12fe6d7e..27eb9055 100644
--- a/resources/lang/en/route-descriptions.php
+++ b/resources/lang/en/route-descriptions.php
@@ -66,8 +66,8 @@
'item_category_GET_index' => 'Return the category assigned to the selected item',
'item_category_GET_show' => 'Return the category assigned to the selected item',
- 'item_category_POST_allocated-expense' => 'Assign a maximum of one category to the selected allocated-expense',
- 'item_category_POST_simple-expense' => 'Assign a maximum of one category to the selected simple-expense',
+ 'item_category_POST_allocated_expense' => 'Assign a maximum of one category to the selected allocated-expense',
+ 'item_category_POST_simple_expense' => 'Assign a maximum of one category to the selected simple-expense',
'item_category_POST_game' => 'Assign the categories (players) to the selected game',
'item_category_PATCH' => 'Update the category assigned to the selected item',
@@ -76,8 +76,8 @@
'item_sub_category_GET_index' => 'Return the subcategory assigned to the selected item',
'item_sub_category_GET_show' => 'Return the subcategory assigned to the selected item',
- 'item_sub_category_POST_allocated-expense' => 'Assign a maximum of one subcategory to the selected allocated-expense',
- 'item_sub_category_POST_simple-expense' => 'Assign a maximum of one subcategory to the selected simple-expense',
+ 'item_sub_category_POST_allocated_expense' => 'Assign a maximum of one subcategory to the selected allocated-expense',
+ 'item_sub_category_POST_simple_expense' => 'Assign a maximum of one subcategory to the selected simple-expense',
'item_sub_category_PATCH' => 'Update the subcategory assigned to the selected item',
'item_sub_category_DELETE' => 'Delete the subcategory assigned to the selected item',
@@ -96,7 +96,7 @@
'permitted_user_POST' => 'Assign a permitted user',
'permitted_user_DELETE' => 'Delete the selected permitted user',
- 'request_GET_error-log' => 'Return the error log',
+ 'request_GET_error_log' => 'Return the error log',
'request_GET_cache' => 'Return the number of cached keys for the authenticated user',
'request_DELETE_cache' => 'Attempt to delete the cached keys for the authenticated user',
'request_POST' => 'Create an error log report',
@@ -104,10 +104,9 @@
'summary_category_GET_index' => 'Return a summary of the categories',
'summary_subcategory_GET_index' => 'Return a summary of the subcategories',
- 'summary-resource-type-GET-index' => 'Return a summary of the resource types',
- 'summary-resource-GET-index' => 'Return a summary of the resources',
+ 'summary_resource_type_GET_index' => 'Return a summary of the resource types',
+ 'summary_resource_GET_index' => 'Return a summary of the resources',
- 'summary_GET_resource-type_resource_items' => 'Return the TCO (Total cost of ownership, sum of items) for the selected resource',
-
- 'summary-resource-type-item-GET-index' => 'Return a summary of the items for all the resources matching this resource type',
+ 'summary_items_GET_index'=> 'Return the "item" summary for the selected resource, review summary filters for all summary options',
+ 'summary_resource_type_items_GET_index'=> 'Return the "item" summary for the selected resource type, items for all resources are summarised, review summary filters for all summary options',
];
diff --git a/resources/views/welcome.blade.php b/resources/views/welcome.blade.php
index 0ab15b7a..fb35665c 100644
--- a/resources/views/welcome.blade.php
+++ b/resources/views/welcome.blade.php
@@ -214,7 +214,7 @@ function gtag(){dataLayer.push(arguments);}
- Latest release {{ $version }}
+ {{ $version }}
The latest release of the Costs to Expect API is
{{ $version }}; we released it on the {{ date('jS M Y', strtotime($date)) }}.
@@ -225,34 +225,34 @@ function gtag(){dataLayer.push(arguments);}
Added
- - We have added our first schema files for OPTIONS responses and started working on the tests.
- - We have added tests for category management, found one bug when creating the tests.
+ - We allow the `collection` parameter for `simple-item` item-type collections.
+ - We have added tests for subcategory management, found another bug, whoopee!
+ - We have added tests for item type responses.
+ - We have added an option response tests for the resource types collection and a resource type.
+ - We have added additional resource type tests and created/updated the json-schema files as necessary.
+ - We have added a catch-all route for non-matching routes.
Changed
- - We have updated our response class for OPTIONS responses, we now allow parameters to be defined for POST requests. One example of where we need this is the create password POST request, `password` and `password_confirmation` are required fields, however, `token` and `email` are required parameters. Before this update, you had to parse the returned error of read the OPTIONS request description.
- - We have started splitting config files, a config file should be for one purpose.
- - We have spent quite a bit of time reviewing the API structure and refactoring. We have removed unnecessary complexity, renamed classes and methods to describe intent more clearly and removed pointless base classes.
- - We have reworked how allowed values are generated for the different item types, allowed values for fields and parameters have been split, and we have removed all abstraction.
- - We have removed some route validation files which didn't do anything useful after all the item type work.
- - We have reworked the responses class, removed exception parameters when not necessary, pass in an exception if thrown and now delegated responsibility to the responses class to decide if the exception should be returned in the response.
- - We have upgraded the API to Laravel 9 and PHP 8.1.
+ - We have renamed the tests directory and corrected the namespaces.
+ - We are continuing to update out routes to named routes.
+ - We have moved additional responses to the response class.
+ - We have updated more response, if a collection is included in a response a `uri` field will contain the relative URI to the relevant collection.
+ - We have adjusted the layout of the test section in the README and added a note explaining the meaning of 'Non yet'.
+ - We have updated the response when attempting to delete an item with category assignments, rather than return a generic foreign key error, we specifically mention that there are category assignments that need to be removed first.
+ - We have cleaned up the response description lang file.
Fixed
- - Options request incorrect for the `auth.register` endpoint (Test added).
- - Options requests returning response twice.
- - Type corrected in OPTIONS response, authentication status/requirements now a boolean, not a string.
- - Minor correction to the description of two POST endpoints.
- - Corrected a type in the OPTIONS response for the month parameter.
- - Corrected the `partial-transfer` JSON schema file.
- - Allowed values not showing for `category` on GET endpoints.
- - Inconsistent usage of the responses helper.
- - Category validator allowed duplicate names due to incorrect params, caught by model.
+ - Removed an output in a test.
+ - Updated the route middleware, invalid decodes should return a 403 for the route.
+ - Added a unique validation rule for emails, don't leave the check to the database.
+ - Corrected the descriptions in the OPTIONS requests for `item` summaries.
+ - The allowed values for `winner_id` should be a category assigned to the item, not all the categories assigned to the resource type.
Removed
diff --git a/routes/api.php b/routes/api.php
index fffb3ed1..8a45f76e 100644
--- a/routes/api.php
+++ b/routes/api.php
@@ -4,3 +4,9 @@
require('api/private-routes.php');
require('api/public-routes.php');
require('api/public-summary-routes.php');
+
+Route::fallback(function () {
+ return response()->json(
+ ['message' => trans('responses.invalid-route')]
+ );
+});
diff --git a/routes/api/private-routes.php b/routes/api/private-routes.php
index 02f2b484..e895cc7c 100644
--- a/routes/api/private-routes.php
+++ b/routes/api/private-routes.php
@@ -4,6 +4,7 @@
use App\Http\Controllers\PermittedUserManage;
use App\Http\Controllers\ResourceManage;
use App\Http\Controllers\ResourceTypeManage;
+use App\Http\Controllers\SubcategoryManage;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Route;
@@ -33,8 +34,8 @@ static function () {
Route::post(
'resource-types/{resource_type_id}/categories/{category_id}/subcategories',
- 'SubcategoryManage@create'
- );
+ [SubcategoryManage::class, 'create']
+ )->name('subcategory.create');
Route::post(
'resource-types/{resource_type_id}/permitted-users',
@@ -88,8 +89,8 @@ static function () {
Route::delete(
'resource-types/{resource_type_id}/categories/{category_id}/subcategories/{subcategory_id}',
- 'SubcategoryManage@delete'
- );
+ [SubcategoryManage::class, 'delete']
+ )->name('subcategory.delete');
Route::delete(
'resource-types/{resource_type_id}/partial-transfers/{item_partial_transfer_id}',
@@ -128,8 +129,8 @@ static function () {
Route::patch(
'resource-types/{resource_type_id}/categories/{category_id}/subcategories/{subcategory_id}',
- 'SubcategoryManage@update'
- );
+ [SubcategoryManage::class, 'update']
+ )->name('subcategory.update');
Route::patch(
'resource-types/{resource_type_id}/resources/{resource_id}',
diff --git a/routes/api/public-routes.php b/routes/api/public-routes.php
index 31d5c2c8..b8cd4bda 100644
--- a/routes/api/public-routes.php
+++ b/routes/api/public-routes.php
@@ -59,8 +59,8 @@ static function () {
Route::get(
'item-types',
- 'ItemTypeView@index'
- );
+ [\App\Http\Controllers\ItemTypeView::class, 'index']
+ )->name('item-type.list');
Route::options(
'item-types',
@@ -89,8 +89,8 @@ static function () {
Route::get(
'item-types/{item_type_id}/item-subtypes/{item_subtype_id}',
- 'ItemSubtypeView@show'
- );
+ [\App\Http\Controllers\ItemSubtypeView::class, 'show']
+ )->name('item-subtype.show');
Route::options(
'item-types/{item_type_id}/item-subtypes/{item_subtype_id}',
diff --git a/tests/View/Http/Controllers/ResourceTypeViewTest.php b/tests/View/Http/Controllers/ResourceTypeViewTest.php
deleted file mode 100644
index aeed0597..00000000
--- a/tests/View/Http/Controllers/ResourceTypeViewTest.php
+++ /dev/null
@@ -1,67 +0,0 @@
-actingAs(User::find(1));
-
- $response = $this->getResourceTypes();
-
- $response->assertStatus(200);
-
- foreach ($response->json() as $item) {
- try {
- $json = json_encode($item, JSON_THROW_ON_ERROR);
- } catch (\JsonException $e) {
- $this->fail('Unable to encode the JSON string');
- }
-
- $this->assertJsonIsResourceType($json);
- }
- }
-
- /** @test */
- public function collection_pagination(): void
- {
- $this->actingAs(User::find(1));
-
- $response = $this->getResourceTypes(['offset'=>1, 'limit'=> 1]);
-
- $response->assertStatus(200);
- $response->assertHeader('X-Offset', 1);
- $response->assertHeader('X-Limit', 1);
-
- foreach ($response->json() as $item) {
- try {
- $json = json_encode($item, JSON_THROW_ON_ERROR);
- } catch (\JsonException $e) {
- $this->fail('Unable to encode the JSON string');
- }
-
- $this->assertJsonIsResourceType($json);
- }
- }
-
- /** @test */
- public function item(): void
- {
- $this->actingAs(User::find(1));
-
- $response = $this->getResourceTypes(['offset'=>0, 'limit'=> 1]);
- $response->assertStatus(200);
-
- $resource_type_id = $response->json()[0]['id'];
-
- $response = $this->getResourceType(['resource_type_id'=> $resource_type_id]);
- $response->assertStatus(200);
-
- $this->assertJsonIsResourceType($response->content());
- }
-}