From 457d71c980e5bdec3eb6bfa691023056e4520056 Mon Sep 17 00:00:00 2001 From: Alvin Mites Date: Wed, 30 Jun 2021 21:52:56 -0600 Subject: [PATCH 01/11] initial openapi file --- README.md | 2 +- package.json | 3 +- packages/server/docs/openapi.yaml | 195 ++++++++++++++++++++++++++++++ 3 files changed, 198 insertions(+), 2 deletions(-) create mode 100644 packages/server/docs/openapi.yaml diff --git a/README.md b/README.md index 37de15ab..b8b19279 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Make sure you have these tools installed before you begin. 1. Clone (or fork and clone) this repository and `cd` into it -2. Make sure docker is running on your machine. You can check by running `docker ps` in your terminal +2. Make sure docker is running on your machine. You can check by running `docker ps` in your terminal, also ensure you have [docker-compose](https://docs.docker.com/compose/install/) installed 3. Run `yarn start:local` diff --git a/package.json b/package.json index 0d9c1330..6ec3af76 100644 --- a/package.json +++ b/package.json @@ -83,7 +83,8 @@ "build:local-packages": "yarn workspace @upswyng/types build && yarn workspace @upswyng/common build", "build:server": "yarn build:local-packages && yarn workspace @upswyng/server build", "build:web": "yarn build:local-packages && yarn workspace @upswyng/web build", - "build:local-db": "docker compose up --build -d && mongorestore --port 27018 --username upswyng-dev-user --password upswyng123 -d upswyng-dev ./packages/server/localdb/mongodump", + "build:local-db": "docker-compose up --build -d && npm run restore:db", + "restore:db": "mongorestore --port 27018 --username upswyng-dev-user --password upswyng123 -d upswyng-dev ./packages/server/localdb/mongodump", "clean": "node clean.js", "reset": "node clean.js --reset && docker compose down -v", "heroku-postbuild": "yarn build:web && yarn build:server", diff --git a/packages/server/docs/openapi.yaml b/packages/server/docs/openapi.yaml new file mode 100644 index 00000000..168d3bc6 --- /dev/null +++ b/packages/server/docs/openapi.yaml @@ -0,0 +1,195 @@ +openapi: 3.0.0 + +info: + title: UpSwyng API v1 + description: UpSwyng API v1 + contact: + name: Code For Boulder + url: https://cfb.slack.com + version: '1.0.0' + +servers: + - url: 'http://localhost:3000' + description: Docker Compose Server + +paths: + /api/category/{category}: + parameters: + - $ref: '#/components/parameters/categoryPath' + get: + description: 'Get a single category with sub-categories.' + operationId: categoryGet + responses: + '200': + description: Single Category. + content: + application/json: + schema: + type: object + properties: + category: + allOf: + - $ref: '#/components/schemas/CategoryData' + - type: object + properties: + subcategories: + '404': + $ref: '#/components/responses/ErrorNotFound' + +components: + schemas: + # Categories + CategoryData: + type: object + properties: + _id: + type: string + example: 5d8f030ac0e6672699a500c2 + name: + type: string + stub: + type: string + color: + type: string + createdAt: + type: string + format: date-time + lastModifiedAt: + type: string + format: date-time + __v: + type: number + default: 1 + SubCategory: + allOf: + - $ref: '#/components/schemas/CategoryData' + - type: object + properties: + resources: + type: array + items: + ResourceData: + type: object + properties: + _id: + type: string + example: 5d8f030ac0e6672699a500c2 + address: + $ref: '#/components/schemas/Address' + createdAt: + type: string + format: date-date-time + deleted: + type: boolean + default: false + description: + type: string + resourceId: + type: string + example: 5d8f030ac0e6672699a500c2 + kudos: + type: number + default: 0 + lastModifiedAt: + type: string + format: date-time + latitude: + type: number + example: 40.0584971 + legacyId: + type: string + example: -KUo-cPb45EOhVRG_ul9 + name: + type: string + phone: + type: string + schedule: + type: object + properties: + alwaysOpen: + type: boolean + timezone: + type: string + _items: + type: array + items: + $ref: '#/components/schemas/Comment' + services: + type: array + items: + type: string + subcategories: + type: array + items: + $ref: '#/components/schemas/SubCategory' + website: + type: string + Address: + type: object + properties: + address1: + type: string + city: + type: string + state: + type: string + zip: + type: integer + Comment: + type: object + properties: + comment: + type: string + fromTime: + type: integer + recurrenceRule: + type: string + toTime: + type: integer + # Common + Error: + type: object + properties: + message: + type: string + description: Description of error. + example: 'Error description' + + + parameters: + categoryPath: + name: category + in: path + description: Single category index name. + example: transit + required: true + schema: + type: string + + responses: + # Errors + ErrorAlreadyExists: + description: Resource already exists and cannot be created again. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + ErrorInvalidRequest: + description: Known invalid request. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + ErrorNotFound: + description: Resource invalid or not found. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + ErrorUnknown: + description: Unknown invalid request. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + From 062e24da9c2bafdd8f75acbdd565e30a96ee44a5 Mon Sep 17 00:00:00 2001 From: Alvin Mites Date: Thu, 1 Jul 2021 14:28:53 -0600 Subject: [PATCH 02/11] fix docs --- packages/server/docs/openapi.yaml | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/server/docs/openapi.yaml b/packages/server/docs/openapi.yaml index 168d3bc6..ed115feb 100644 --- a/packages/server/docs/openapi.yaml +++ b/packages/server/docs/openapi.yaml @@ -1,16 +1,16 @@ openapi: 3.0.0 info: - title: UpSwyng API v1 - description: UpSwyng API v1 - contact: - name: Code For Boulder - url: https://cfb.slack.com - version: '1.0.0' + title: UpSwyng API v1 + description: UpSwyng API v1 + contact: + name: Code For Boulder + url: https://cfb.slack.com + version: '1.0.0' servers: - - url: 'http://localhost:3000' - description: Docker Compose Server + - url: 'http://localhost:3000' + description: Docker Compose Server paths: /api/category/{category}: @@ -33,6 +33,7 @@ paths: - type: object properties: subcategories: + $ref: '#/components/schemas/SubCategory' '404': $ref: '#/components/responses/ErrorNotFound' @@ -68,6 +69,7 @@ components: resources: type: array items: + $ref: '#/components/schemas/ResourceData' ResourceData: type: object properties: From c2243e656dbf4607a5dce68268e42274e2ea9c27 Mon Sep 17 00:00:00 2001 From: Alvin Mites Date: Thu, 1 Jul 2021 14:41:10 -0600 Subject: [PATCH 03/11] website url --- packages/server/docs/openapi.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/server/docs/openapi.yaml b/packages/server/docs/openapi.yaml index ed115feb..1d3efe57 100644 --- a/packages/server/docs/openapi.yaml +++ b/packages/server/docs/openapi.yaml @@ -5,7 +5,7 @@ info: description: UpSwyng API v1 contact: name: Code For Boulder - url: https://cfb.slack.com + url: https://www.codeforboulder.org/ version: '1.0.0' servers: From bbcfb7ca62c4b29c78c37de2c873e9fd7488b023 Mon Sep 17 00:00:00 2001 From: Alvin Mites Date: Fri, 2 Jul 2021 20:12:53 -0600 Subject: [PATCH 04/11] tweaking docs --- packages/server/docs/openapi.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/server/docs/openapi.yaml b/packages/server/docs/openapi.yaml index 1d3efe57..2d0209e6 100644 --- a/packages/server/docs/openapi.yaml +++ b/packages/server/docs/openapi.yaml @@ -5,7 +5,7 @@ info: description: UpSwyng API v1 contact: name: Code For Boulder - url: https://www.codeforboulder.org/ + url: 'https://www.codeforboulder.org/' version: '1.0.0' servers: From 0b11384e23410ba6f7f9dd587033371a0e8c074d Mon Sep 17 00:00:00 2001 From: Alvin Mites Date: Fri, 2 Jul 2021 20:43:03 -0600 Subject: [PATCH 05/11] filling in api docs --- packages/server/docs/openapi.yaml | 234 ++++++++++++++++++++++++++++-- 1 file changed, 220 insertions(+), 14 deletions(-) diff --git a/packages/server/docs/openapi.yaml b/packages/server/docs/openapi.yaml index 2d0209e6..e3434ed9 100644 --- a/packages/server/docs/openapi.yaml +++ b/packages/server/docs/openapi.yaml @@ -13,6 +13,38 @@ servers: description: Docker Compose Server paths: + /api/alert/search: + post: + description: 'Search for alerts' + operationId: alertSearchPost + requestBody: + description: Time to search for alert since. + content: + application/json: + schema: + $ref: '#/components/schemas/StartTime' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/StartTime' + responses: + '200': + description: Alerts. + # TODO: fill in alert structure + content: + application/json: + schema: + type: object + properties: + category: + allOf: + - $ref: '#/components/schemas/CategoryData' + - type: object + properties: + subcategories: + $ref: '#/components/schemas/SubCategory' + '404': + $ref: '#/components/responses/ErrorNotFound' + /api/category/{category}: parameters: - $ref: '#/components/parameters/categoryPath' @@ -37,10 +69,129 @@ paths: '404': $ref: '#/components/responses/ErrorNotFound' + /api/resources: + parameters: + - $ref: '#/components/parameters/idQueryOptional' + get: + description: 'Get one or more resources.' + operationId: resourcesGet + responses: + '200': + description: Array of resources. + content: + application/json: + schema: + type: object + properties: + resources: + type: array + items: + $ref: '#/components/schemas/ResourceDataDetail' + '404': + $ref: '#/components/responses/ErrorNotFound' + + /api/weather: + parameters: + - $ref: '#/components/parameters/latitudeQuery' + - $ref: '#/components/parameters/longitudeQuery' + get: + description: 'Get weather data for location.' + operationId: weatherGet + responses: + '200': + description: Weather data. + content: + application/json: + schema: + type: object + properties: + coord: + type: object + properties: + lon: + type: number + lat: + type: number + weather: + type: array + items: + type: object + properties: + id: + type: number + main: + type: string + description: + type: string + icon: + type: string + base: + type: string + main: + type: object + properties: + temp: + type: number + feels_like: + type: number + temp_min: + type: number + temp_max: + type: number + pressure: + type: number + humidity: + type: number + visibility: + type: number + wind: + type: object + properties: + speed: + type: number + deg: + type: number + gust: + type: number + clouds: + type: object + properties: + all: + type: number + dt: + type: number + sys: + type: object + properties: + type: + type: number + id: + type: number + country: + type: string + sunrise: + type: number + sunset: + type: number + timezone: + type: number + id: + type: number + name: + type: string + cod: + type: number + createdDate: + type: string + lifespan: + type: number + '404': + $ref: '#/components/responses/ErrorNotFound' + components: schemas: # Categories - CategoryData: + CategoryDataCore: type: object properties: _id: @@ -50,8 +201,6 @@ components: type: string stub: type: string - color: - type: string createdAt: type: string format: date-time @@ -61,6 +210,13 @@ components: __v: type: number default: 1 + CategoryData: + allOf: + - $ref: '#/components/schemas/CategoryDataCore' + - type: object + properties: + color: + type: string SubCategory: allOf: - $ref: '#/components/schemas/CategoryData' @@ -69,7 +225,19 @@ components: resources: type: array items: - $ref: '#/components/schemas/ResourceData' + $ref: '#/components/schemas/ResourceCategoryData' + ResourceCategoryData: + allOf: + - $ref: '#/components/schemas/ResourceData' + - type: object + properties: + resourceId: + type: string + example: 5d8f030ac0e6672699a500c2 + subcategories: + type: array + items: + $ref: '#/components/schemas/SubCategory' ResourceData: type: object properties: @@ -86,9 +254,6 @@ components: default: false description: type: string - resourceId: - type: string - example: 5d8f030ac0e6672699a500c2 kudos: type: number default: 0 @@ -101,6 +266,9 @@ components: legacyId: type: string example: -KUo-cPb45EOhVRG_ul9 + longitude: + type: number + example: -105.11954379999997 name: type: string phone: @@ -115,17 +283,26 @@ components: _items: type: array items: - $ref: '#/components/schemas/Comment' + $ref: '#/components/schemas/ScheduleItem' services: type: array items: type: string - subcategories: - type: array - items: - $ref: '#/components/schemas/SubCategory' + example: 'Groceries for low-income Seniors/Families' website: type: string + ResourceDataDetail: + allOf: + - $ref: '#/components/schemas/ResourceData' + - type: object + properties: + subcategories: + allOf: + - $ref: '#/components/schemas/CategoryDataCore' + - type: object + properties: + parentCategory: + $ref: '#/components/schemas/CategoryData' Address: type: object properties: @@ -137,7 +314,7 @@ components: type: string zip: type: integer - Comment: + ScheduleItem: type: object properties: comment: @@ -148,6 +325,12 @@ components: type: string toTime: type: integer + StartTime: + type: object + properties: + start: + type: string + format: date-time # Common Error: type: object @@ -157,8 +340,15 @@ components: description: Description of error. example: 'Error description' - parameters: + idQueryOptional: + name: id + in: query + description: id for a single entry. + required: false + schema: + type: string + example: 5def5cb7b831a048f2a3deed categoryPath: name: category in: path @@ -167,6 +357,22 @@ components: required: true schema: type: string + latitudeQuery: + name: latitude + in: query + description: Latitude, probably for current user + required: true + schema: + type: number + example: 40.015 + longitudeQuery: + name: longitude + in: query + description: Longitude, probably for current user + required: true + schema: + type: number + example: -105.2705 responses: # Errors From b03aa4462d1e8cc7722613ae0921596208eadc62 Mon Sep 17 00:00:00 2001 From: Alvin Mites Date: Mon, 5 Jul 2021 21:19:25 -0600 Subject: [PATCH 06/11] prototyping openapi docs --- packages/server/docs/openapi.yaml | 1181 ++++++++++++++++++++++++++--- 1 file changed, 1096 insertions(+), 85 deletions(-) diff --git a/packages/server/docs/openapi.yaml b/packages/server/docs/openapi.yaml index e3434ed9..d18fd668 100644 --- a/packages/server/docs/openapi.yaml +++ b/packages/server/docs/openapi.yaml @@ -12,20 +12,58 @@ servers: - url: 'http://localhost:3000' description: Docker Compose Server +# Paths are sorted alphabetically +# variables as part of a path are sorted as last in order. + paths: + /api/alert: + post: + description: 'Create a new alert.' + summary: 'Create alert' + security: + - requireAdmin: [] + tags: + - stub + operationId: alertPost + requestBody: + description: New Alert Payload. + content: + application/json: + schema: + $ref: '#/components/schemas/AlertPost' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/AlertPost' + responses: + '200': + description: INCOMPLETE + content: + application/json: + schema: + type: object + '400': + $ref: '#/components/responses/ErrorInvalidRequest' + '401': + $ref: '#/components/responses/ErrorAuthentication' + '500': + $ref: '#/components/responses/ErrorUnknown' + /api/alert/search: post: description: 'Search for alerts' + summary: 'Search for alerts' + tags: + - stub operationId: alertSearchPost requestBody: description: Time to search for alert since. content: application/json: schema: - $ref: '#/components/schemas/StartTime' + $ref: '#/components/schemas/StartTimeObj' application/x-www-form-urlencoded: schema: - $ref: '#/components/schemas/StartTime' + $ref: '#/components/schemas/StartTimeObj' responses: '200': description: Alerts. @@ -41,7 +79,34 @@ paths: - type: object properties: subcategories: - $ref: '#/components/schemas/SubCategory' + $ref: '#/components/schemas/SubCategoryData' + '404': + $ref: '#/components/responses/ErrorNotFound' + + /api/alert/{id}: + parameters: + - $ref: '#/components/parameters/idPath' + get: + description: 'Get an alert' + summary: 'Get an alert' + operationId: alertGet + tags: + - stub + responses: + '200': + description: Single Alert. + content: + application/json: + schema: + type: object + properties: + category: + allOf: + - $ref: '#/components/schemas/CategoryData' + - type: object + properties: + subcategories: + $ref: '#/components/schemas/SubCategoryData' '404': $ref: '#/components/responses/ErrorNotFound' @@ -49,7 +114,8 @@ paths: parameters: - $ref: '#/components/parameters/categoryPath' get: - description: 'Get a single category with sub-categories.' + description: 'Get a category with sub-categories.' + summary: 'Get a category' operationId: categoryGet responses: '200': @@ -65,15 +131,202 @@ paths: - type: object properties: subcategories: - $ref: '#/components/schemas/SubCategory' + $ref: '#/components/schemas/SubCategoryData' '404': $ref: '#/components/responses/ErrorNotFound' + /api/categories: + get: + description: 'Get an array of all categories.' + summary: 'Get all categories.' + operationId: categoriesGet + responses: + '200': + description: Categories. + content: + application/json: + schema: + type: object + properties: + categories: + type: array + items: + allOf: + - $ref: '#/components/schemas/CategoryData' + - type: object + properties: + subcategories: + type: array + items: + allOf: + - $ref: '#/components/schemas/CategoryData' + - type: object + properties: + resources: + type: array + items: + $ref: '#/components/schemas/Meta_id' + + /api/hotlines: + get: + description: 'Get an array of all hotlines.' + summary: 'Get all hotlines.' + tags: + - stub + operationId: hotlinesGet + responses: + '200': + description: Categories. + content: + application/json: + schema: + type: object + properties: + hotlines: + type: array + items: + allOf: + - $ref: '#/components/schemas/Meta_id' + '500': + $ref: '#/components/responses/ErrorUnknown' + + /api/resource: + post: + description: 'Create a new resource.' + summary: 'Create resource' + security: + - requireLoggedIn: [] + tags: + - stub + operationId: resourcePost + requestBody: + description: New Resource Payload. + content: + application/json: + schema: + $ref: '#/components/schemas/ResourcePost' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/ResourcePost' + responses: + '201': + description: INCOMPLETE + content: + application/json: + schema: + type: object + properties: + count: + type: integer + default: 12 + estimatedTotal: + type: integer + default: 29 + resourceIssues: + type: array + items: + type: object + properties: + _id: + type: string + default: '5f7a462dcd1b786bed19b4cb' + detail: + type: object + properties: + kind: + type: string + default: 'user_report' + enum: + - 'user_report' + # - 'legacy_schedule_parsing_error' + # user_report + detailExplanation: + type: string + default: 'Derp' + reportedIssues: + type: array + items: + type: string + example: 'The address is wrong.' + # # legacy schedule error + # legacyClosesSchedule: + # type: string + # description: 'Only for type legacy_schedule_parsing_error' + # legacySchedule: + # type: string + # example: '[{"day":"Thursday","fromstring":"10:00 AM","period":"First","tostring":"12:00 PM","type":"Monthly"},{"day":"Thursday","fromstring":"10:00 AM","period":"Third","tostring":"12:00 PM","type":"Monthly"}]' + # description: 'Only for type legacy_schedule_parsing_error' + kind: + type: string + default: 'user_report' + resolved: + type: boolean + default: false + resourceId: + type: string + default: '5def5cb7b831a048f2a3deed' + severity: + type: string + default: 'high' + __v: + type: integer + default: 0 + createdAt: + type: string + default: '2020-10-04T22:01:17.880Z' + lastModifiedAt: + type: string + default: '2020-10-04T22:01:17.880Z' + '401': + $ref: '#/components/responses/ErrorAuthentication' + '500': + $ref: '#/components/responses/ErrorUnknown' + + /api/resource/{id}: + parameters: + - $ref: '#/components/parameters/idPath' + get: + description: 'Get a resource.' + summary: 'Get a resource' + operationId: resourceGet + responses: + '200': + description: Single Resource. + content: + application/json: + schema: + type: object + properties: + resource: + allOf: + - $ref: '#/components/schemas/ResourceDataLatLon' + - type: object + properties: + subcategories: + allOf: + - $ref: '#/components/schemas/ResourceSubcategory' + - type: object + properties: + parentCategory: + allOf: + - $ref: '#/components/schemas/CategoryData' + - type: object + properties: + subcategories: + type: array + items: + $ref: '#/components/schemas/ResourceSubcategory' + '404': + $ref: '#/components/responses/ErrorNotFound' + '500': + $ref: '#/components/responses/ErrorUnknown' + /api/resources: parameters: - $ref: '#/components/parameters/idQueryOptional' get: - description: 'Get one or more resources.' + description: 'Get an array of resources.' + summary: 'Get resources.' operationId: resourcesGet responses: '200': @@ -86,7 +339,552 @@ paths: resources: type: array items: - $ref: '#/components/schemas/ResourceDataDetail' + allOf: + - $ref: '#/components/schemas/ResourceDataLatLon' + - type: object + properties: + subcategories: + allOf: + - $ref: '#/components/schemas/CategoryDataNoColor' + - type: object + properties: + parentCategory: + $ref: '#/components/schemas/CategoryData' + + /api/resource/draft/approve/{id}: + parameters: + - $ref: '#/components/parameters/idPath' + post: + description: 'Mark a draft resource approved.' + summary: 'Approve draft resource' + operationId: resourcesDraftApprovePost + security: + - requireAdmin: [] + requestBody: + $ref: '#/components/requestBodies/EmptyRequest' + responses: + '204': + $ref: '#/components/responses/EmptyObject' + '401': + $ref: '#/components/responses/ErrorAuthentication' + '404': + $ref: '#/components/responses/ErrorNotFound' + '500': + $ref: '#/components/responses/ErrorUnknown' + + /api/resource/draft/delete/{id}: + parameters: + - $ref: '#/components/parameters/idPath' + post: + description: 'Delete a draft resource.' + summary: 'Delete draft resource' + operationId: resourcesDraftDeletePost + security: + - requireAdmin: [] + requestBody: + $ref: '#/components/requestBodies/EmptyRequest' + responses: + '204': + $ref: '#/components/responses/EmptyObject' + '401': + $ref: '#/components/responses/ErrorAuthentication' + '404': + $ref: '#/components/responses/ErrorNotFound' + '500': + $ref: '#/components/responses/ErrorUnknown' + + /api/resource/draft/{id}: + parameters: + - $ref: '#/components/parameters/idPath' + get: + description: 'Get a resource draft.' + summary: 'Get a resource draft' + operationId: resourceDraftGet + tags: + - stub + responses: + '200': + description: Single Category. + content: + application/json: + schema: + type: object + properties: + category: + allOf: + - $ref: '#/components/schemas/CategoryData' + - type: object + properties: + subcategories: + $ref: '#/components/schemas/SubCategoryData' + '404': + $ref: '#/components/responses/ErrorNotFound' + '500': + $ref: '#/components/responses/ErrorUnknown' + + /api/resources/drafts: + parameters: + - $ref: '#/components/parameters/includeDeletedQueryOptional' + get: + description: 'Get an array of resources.' + summary: 'Get resources.' + tags: + - stub + operationId: resourcesDraftsGet + responses: + '200': + description: INCOMPLETE + content: + application/json: + schema: + type: object + properties: + draftResources: + type: array + items: + allOf: + - $ref: '#/components/schemas/ResourceDataLatLon' + - $ref: '#/components/schemas/MetaLegacyIdObj' + '401': + $ref: '#/components/responses/ErrorAuthentication' + + /api/resources/drafts/mine: + get: + description: 'Get an array of resources.' + summary: 'Get resources.' + tags: + - stub + operationId: resourcesDraftsMineGet + responses: + '200': + description: INCOMPLETE + content: + application/json: + schema: + type: object + properties: + uncategorizedResources: + type: array + items: + allOf: + - $ref: '#/components/schemas/ResourceData' + - type: object + properties: + location: + type: object + properties: + coordinates: + description: Latitude & Longitude + type: array + items: + type: number + example: [-105.13494760000003, 39.9776081] + type: + type: string + example: Point + '401': + $ref: '#/components/responses/ErrorAuthentication' + + /api/resources/issue/{id}: + parameters: + - $ref: '#/components/parameters/idPath' + get: + description: 'Get an issue by id.' + summary: 'Get an issue' + operationId: resourceIssueGet + responses: + '200': + description: Issue. + content: + application/json: + schema: + type: object + properties: + resourceIssue: + type: object + properties: + _id: + type: string + default: '5e894bc235a65b002cce1116' + detail: + type: object + properties: + detailExplanation: + type: string + default: 'The picture is incorrect. Mike ' + kind: + type: string + default: 'user_report' + reportedIssues: + type: array + items: + type: string + example: 'The address is wrong.' + kind: + type: string + default: 'user_report' + resourceId: + type: string + default: '5def5cb7b831a048f2a3deef' + severity: + type: string + default: 'high' + __v: + type: integer + default: 0 + createdAt: + type: string + default: '2020-04-05T03:08:50.948Z' + lastModifiedAt: + type: string + default: '2020-04-05T03:08:50.948Z' + + '401': + $ref: '#/components/responses/ErrorAuthentication' + '404': + $ref: '#/components/responses/ErrorNotFound' + '500': + $ref: '#/components/responses/ErrorUnknown' + + /api/resources/issues: + post: + description: 'Query for an array of issues.' + summary: 'Query issues.' + security: + - requireAdmin: [] + operationId: resourcesIssuesPost + requestBody: + description: Filter which issues to return. + content: + application/json: + schema: + $ref: '#/components/schemas/IssuesQueryPost' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/IssuesQueryPost' + responses: + '200': + description: Issues available for request. + content: + application/json: + schema: + type: object + properties: + count: + type: integer + default: 12 + estimatedTotal: + type: integer + default: 29 + resourceIssues: + type: array + items: + type: object + properties: + _id: + type: string + default: '5f7a462dcd1b786bed19b4cb' + detail: + type: object + properties: + kind: + type: string + default: 'user_report' + enum: + - 'user_report' +# - 'legacy_schedule_parsing_error' + # user_report + detailExplanation: + type: string + default: 'Derp' + reportedIssues: + type: array + items: + type: string + example: 'The address is wrong.' +# # legacy schedule error +# legacyClosesSchedule: +# type: string +# description: 'Only for type legacy_schedule_parsing_error' +# legacySchedule: +# type: string +# example: '[{"day":"Thursday","fromstring":"10:00 AM","period":"First","tostring":"12:00 PM","type":"Monthly"},{"day":"Thursday","fromstring":"10:00 AM","period":"Third","tostring":"12:00 PM","type":"Monthly"}]' +# description: 'Only for type legacy_schedule_parsing_error' + kind: + type: string + default: 'user_report' + resolved: + type: boolean + default: false + resourceId: + type: string + default: '5def5cb7b831a048f2a3deed' + severity: + type: string + default: 'high' + __v: + type: integer + default: 0 + createdAt: + type: string + default: '2020-10-04T22:01:17.880Z' + lastModifiedAt: + type: string + default: '2020-10-04T22:01:17.880Z' + '401': + $ref: '#/components/responses/ErrorAuthentication' + '500': + $ref: '#/components/responses/ErrorUnknown' + + /api/resources/issues/resolve/{id}: + parameters: + - $ref: '#/components/parameters/idPath' + post: + description: 'Mark an issue resolved' + summary: 'Resolve issue' + operationId: resourcesIssueResolvePost + security: + - requireAdmin: [] + requestBody: + $ref: '#/components/requestBodies/EmptyRequest' + responses: + '204': + $ref: '#/components/responses/EmptyObject' + '401': + $ref: '#/components/responses/ErrorAuthentication' + '404': + $ref: '#/components/responses/ErrorNotFound' + '500': + $ref: '#/components/responses/ErrorUnknown' + + /api/resources/issues/unresolve/{id}: + parameters: + - $ref: '#/components/parameters/idPath' + post: + description: 'Mark an issue unresolved' + summary: 'Unresolve issue' + operationId: resourcesIssueUnresolvePost + security: + - requireAdmin: [] + requestBody: + $ref: '#/components/requestBodies/EmptyRequest' + responses: + '204': + $ref: '#/components/responses/EmptyObject' + '401': + $ref: '#/components/responses/ErrorAuthentication' + '404': + $ref: '#/components/responses/ErrorNotFound' + '500': + $ref: '#/components/responses/ErrorUnknown' + + /api/resources/issues/user-report: + post: + description: 'Report a new issue' + summary: 'Report issue' + operationId: resourcesIssuesUserReportPost + requestBody: + description: Request body to create new issues. + content: + application/json: + schema: + type: object + required: + - resourceId + - reportedIssues + properties: + resourceId: + $ref: '#/components/schemas/Meta_id' + reportedIssues: + type: array + items: + type: object + properties: + kind: + type: string + enum: + - user_report + detailExplanation: + type: string + description: 'Text the user writes in as a detail.' + reportedIssues: + type: array + items: + type: string + description: 'Schedule Incorrect, Website Inoperable' + detailExplanation: + type: string + responses: + '201': + $ref: '#/components/responses/EmptyObject' + '401': + $ref: '#/components/responses/ErrorAuthentication' + '404': + $ref: '#/components/responses/ErrorNotFound' + '422': + $ref: '#/components/responses/ErrorInvalidRequest' + '500': + $ref: '#/components/responses/ErrorUnknown' + +# /api/resources/issues/{id}: +# parameters: +# - $ref: '#/components/parameters/idPath' +# get: +# description: 'Get issue by resource.' +# summary: 'Get issues by resource' +# operationId: resourceIssueGet +# responses: +# '200': +# description: Subcategory. +# content: +# application/json: +# schema: +# type: object +# properties: +# subcategory: +# type: object +# properties: +# _id: +# $ref: '#/components/schemas/Meta_id' +# name: +# type: string +# example: 'Food Pantries' +# stub: +# type: string +# example: 'food_pantries' +# parentCategory: +# $ref: '#/components/schemas/ParentCategory' +# resources: +# type: array +# items: +# $ref: '#/components/schemas/ResourceCategoryData' +# createdAt: +# $ref: '#/components/schemas/MetaDateTime' +# lastModifiedAt: +# $ref: '#/components/schemas/MetaDateTime' +# __v: +# type: number +# default: 1 +# '404': +# $ref: '#/components/responses/ErrorNotFound' + + /api/resources/uncategorized: + get: + description: 'Get an array of uncategorized resources.' + summary: 'Get uncategorized resources.' + tags: + - stub + operationId: resourcesUncategorizedGet + responses: + '200': + description: Array of resources. + content: + application/json: + schema: + type: object + properties: + uncategorizedResources: + type: array + items: + allOf: + - $ref: '#/components/schemas/ResourceData' + - type: object + properties: + location: + type: object + properties: + coordinates: + description: Latitude & Longitude + type: array + items: + type: number + example: [-105.13494760000003, 39.9776081] + type: + type: string + example: Point + + /api/subcategories: + get: + description: 'Get an array of all sub-categories.' + summary: 'Get sub-categories.' + operationId: subcategoriesGet + responses: + '200': + description: Subcategories. + content: + application/json: + schema: + type: object + properties: + subcategories: + type: array + items: + type: object + properties: + _id: + $ref: '#/components/schemas/Meta_id' + name: + type: string + example: 'Food Pantries' + stub: + type: string + example: 'food_pantries' + parentCategory: + allOf: + - $ref: '#/components/schemas/CategoryData' + - type: object + properties: + subcategories: + type: array + items: + $ref: '#/components/schemas/Meta_id' + createdAt: + $ref: '#/components/schemas/MetaDateTime' + lastModifiedAt: + $ref: '#/components/schemas/MetaDateTime' + __v: + type: number + default: 1 + + /api/subcategory/{subcategory}: + parameters: + - $ref: '#/components/parameters/subcategoryPath' + get: + description: 'Get a sub-category by stub name.' + summary: 'Get a sub-category' + operationId: subcategoryGet + responses: + '200': + description: Subcategory. + content: + application/json: + schema: + type: object + properties: + subcategory: + type: object + properties: + _id: + $ref: '#/components/schemas/Meta_id' + name: + type: string + example: 'Food Pantries' + stub: + type: string + example: 'food_pantries' + parentCategory: + $ref: '#/components/schemas/ParentCategory' + resources: + type: array + items: + $ref: '#/components/schemas/ResourceCategoryData' + createdAt: + $ref: '#/components/schemas/MetaDateTime' + lastModifiedAt: + $ref: '#/components/schemas/MetaDateTime' + __v: + type: number + default: 1 '404': $ref: '#/components/responses/ErrorNotFound' @@ -96,6 +894,7 @@ paths: - $ref: '#/components/parameters/longitudeQuery' get: description: 'Get weather data for location.' + summary: 'Get weather data' operationId: weatherGet responses: '200': @@ -174,7 +973,7 @@ paths: sunset: type: number timezone: - type: number + $ref: '#/components/schemas/MetaTimeZone' id: type: number name: @@ -190,130 +989,261 @@ paths: components: schemas: - # Categories - CategoryDataCore: + CategoryDataNoColor: type: object properties: _id: - type: string - example: 5d8f030ac0e6672699a500c2 + $ref: '#/components/schemas/Meta_id' name: type: string + example: Food stub: type: string + example: food createdAt: - type: string - format: date-time + $ref: '#/components/schemas/MetaDateTime' lastModifiedAt: - type: string - format: date-time + $ref: '#/components/schemas/MetaDateTime' __v: type: number default: 1 CategoryData: allOf: - - $ref: '#/components/schemas/CategoryDataCore' + - $ref: '#/components/schemas/CategoryDataNoColor' - type: object properties: color: type: string - SubCategory: + ParentCategory: allOf: - $ref: '#/components/schemas/CategoryData' - type: object properties: - resources: + subcategories: type: array items: - $ref: '#/components/schemas/ResourceCategoryData' + $ref: '#/components/schemas/Meta_id' ResourceCategoryData: allOf: - - $ref: '#/components/schemas/ResourceData' + - $ref: '#/components/schemas/ResourceDataLatLon' - type: object properties: resourceId: - type: string - example: 5d8f030ac0e6672699a500c2 - subcategories: - type: array - items: - $ref: '#/components/schemas/SubCategory' + $ref: '#/components/schemas/Meta_id' + subcategories: + type: array + items: + $ref: '#/components/schemas/SubCategoryData' ResourceData: type: object properties: _id: - type: string - example: 5d8f030ac0e6672699a500c2 + $ref: '#/components/schemas/Meta_id' address: - $ref: '#/components/schemas/Address' - createdAt: - type: string - format: date-date-time - deleted: - type: boolean - default: false + $ref: '#/components/schemas/AddressObj' description: type: string + example: 'Weekly groceries for families whose children are enrolled in the free or reduced lunch program at their school.' kudos: type: number default: 0 - lastModifiedAt: - type: string - format: date-time - latitude: - type: number - example: 40.0584971 legacyId: type: string example: -KUo-cPb45EOhVRG_ul9 - longitude: - type: number - example: -105.11954379999997 name: type: string + example: United Methodist Church phone: - type: string + $ref: '#/components/schemas/MetaPhone' schedule: - type: object - properties: - alwaysOpen: - type: boolean - timezone: - type: string - _items: - type: array - items: - $ref: '#/components/schemas/ScheduleItem' + $ref: '#/components/schemas/ScheduleObj' services: type: array items: type: string example: 'Groceries for low-income Seniors/Families' + streetViewImage: + type: string + example: 'http://media.upswyng.org/images/5def5cbab831a048f2a3df03.jpg' website: type: string - ResourceDataDetail: + deleted: + type: boolean + default: false + createdAt: + $ref: '#/components/schemas/MetaDateTime' + lastModifiedAt: + $ref: '#/components/schemas/MetaDateTime' + ResourceDataLatLon: allOf: - $ref: '#/components/schemas/ResourceData' + - $ref: '#/components/schemas/MetaLatLonObj' + ResourceSubcategory: + allOf: + - $ref: '#/components/schemas/CategoryDataNoColor' - type: object properties: + parentCategory: + $ref: '#/components/schemas/CategoryData' + SubCategoryData: + allOf: + - $ref: '#/components/schemas/CategoryData' + - type: object + properties: + resources: + type: array + items: + $ref: '#/components/schemas/ResourceCategoryData' + StartTimeObj: + type: object + properties: + start: + type: string + format: date-time + UserObj: + type: object + properties: + _id: + type: string + description: database ObjectId converted to hex string + name: + type: string + email: + type: string + format: email + providers: + type: string + enum: + - 'facebook' + - 'google' + - 'slack' + isAdmin: + type: boolean + default: false + isSuperAdmin: + type: boolean + default: false + # Post Request Bodies + AlertPost: + type: object + required: + - _id + - color + - end + - icon + - start + - title + properties: + _id: + $ref: '#/components/schemas/Meta_id' + color: + type: string + end: + $ref: '#/components/schemas/MetaDateTime' + icon: + type: string + isApproved: + type: boolean + isCancelled: + type: boolean + start: + $ref: '#/components/schemas/MetaDateTime' + title: + type: string + IssuesQueryPost: + type: object + properties: + includeResolved: + type: boolean + default: false + limit: + type: integer + default: 20 + minimumSeverity: + type: string + default: low + enum: + - low + - medium + - high + offset: + type: integer + default: 0 + ResourcePost: + type: object + properties: + draftResource: + type: object + required: + - address + - description + - latitude + - longitude + - name + - phone + - resourceId + - schedule + - services + - streetViewImage + - subcategories + - website + properties: + address: + $ref: '#/components/schemas/AddressObj' + description: + type: string + latitude: + type: number + nullable: true + default: null + longitude: + type: number + nullable: true + default: null + name: + type: string + phone: + $ref: '#/components/schemas/MetaPhone' + resourceId: + $ref: '#/components/schemas/Meta_id' + schedule: + $ref: '#/components/schemas/ScheduleObj' + services: + type: array + items: + type: string + streetViewImage: + type: string + example: 'http://media.upswyng.org/images/5def5cbab831a048f2a3df03.jpg' subcategories: - allOf: - - $ref: '#/components/schemas/CategoryDataCore' - - type: object - properties: - parentCategory: - $ref: '#/components/schemas/CategoryData' - Address: + type: array + items: + $ref: '#/components/schemas/Meta_id' + website: + type: string + # Common + AddressObj: type: object properties: address1: type: string + example: 123 Someplace Avenue city: type: string + example: Boulder state: type: string + example: CO zip: type: integer + example: 80301 + ErrorObj: + type: object + properties: + message: + type: string + description: Description of error. + example: 'Error description' ScheduleItem: type: object properties: @@ -323,40 +1253,96 @@ components: type: integer recurrenceRule: type: string + example: 'RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=WE' toTime: type: integer - StartTime: + ScheduleObj: type: object properties: - start: - type: string - format: date-time - # Common - Error: + alwaysOpen: + type: boolean + timezone: + $ref: '#/components/schemas/MetaTimeZone' + _items: + type: array + items: + $ref: '#/components/schemas/ScheduleItem' + # Meta + Meta_id: + type: string + example: 5d8f030ac0e6672699a500c2 + MetaDateTime: + type: string + format: date-time + example: '2019-09-28T06:51:53.633Z' + MetaLatLonObj: type: object properties: - message: + latitude: + type: number + example: 40.0584971 + longitude: + type: number + example: -105.11954379999997 + MetaLegacyIdObj: + type: object + properties: + legacyId: type: string - description: Description of error. - example: 'Error description' + example: -KZnRX-8rV1552vd0P7_ + MetaPhone: + type: string + example: (303) 555-0112 + MetaTimeZone: + type: string + example: 'America/Denver' + + securitySchemes: + requireAdmin: + type: http + scheme: bearer + bearerFormat: JWT + requireLoggedIn: + type: http + scheme: bearer + bearerFormat: JWT + requireSuperAdmin: + type: http + scheme: bearer + bearerFormat: JWT parameters: + categoryPath: + name: category + in: path + description: Single category stub name. + example: transit + required: true + schema: + type: string + example: food + idPath: + name: id + in: path + description: Single object _id. + required: true + schema: + $ref: '#/components/schemas/Meta_id' idQueryOptional: name: id in: query - description: id for a single entry. + description: _id for an entry required: false schema: type: string example: 5def5cb7b831a048f2a3deed - categoryPath: - name: category - in: path - description: Single category index name. - example: transit - required: true + includeDeletedQueryOptional: + name: include-deleted + in: query + description: Whether to include deleted + required: false schema: - type: string + type: boolean latitudeQuery: name: latitude in: query @@ -373,31 +1359,56 @@ components: schema: type: number example: -105.2705 + subcategoryPath: + name: subcategory + in: path + description: Single subcategory stub name. + example: food_pantry + required: true + schema: + type: string responses: + EmptyObject: + description: Empty json object. + content: + application/json: + schema: + type: object # Errors ErrorAlreadyExists: description: Resource already exists and cannot be created again. content: application/json: schema: - $ref: '#/components/schemas/Error' + $ref: '#/components/schemas/ErrorObj' + ErrorAuthentication: + description: Invalid user credentials submitted. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorObj' ErrorInvalidRequest: description: Known invalid request. content: application/json: schema: - $ref: '#/components/schemas/Error' + $ref: '#/components/schemas/ErrorObj' ErrorNotFound: description: Resource invalid or not found. content: application/json: schema: - $ref: '#/components/schemas/Error' + $ref: '#/components/schemas/ErrorObj' ErrorUnknown: description: Unknown invalid request. content: application/json: schema: - $ref: '#/components/schemas/Error' + $ref: '#/components/schemas/ErrorObj' + requestBodies: + EmptyRequest: + description: Empty request body + content: + application/json: {} From d972dddeaaeb41a389562a6a2c49585d916a8ebd Mon Sep 17 00:00:00 2001 From: Alvin Mites Date: Mon, 5 Jul 2021 21:43:11 -0600 Subject: [PATCH 07/11] restore changes --- README.md | 2 +- package.json | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b8b19279..37de15ab 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Make sure you have these tools installed before you begin. 1. Clone (or fork and clone) this repository and `cd` into it -2. Make sure docker is running on your machine. You can check by running `docker ps` in your terminal, also ensure you have [docker-compose](https://docs.docker.com/compose/install/) installed +2. Make sure docker is running on your machine. You can check by running `docker ps` in your terminal 3. Run `yarn start:local` diff --git a/package.json b/package.json index 6ec3af76..0d9c1330 100644 --- a/package.json +++ b/package.json @@ -83,8 +83,7 @@ "build:local-packages": "yarn workspace @upswyng/types build && yarn workspace @upswyng/common build", "build:server": "yarn build:local-packages && yarn workspace @upswyng/server build", "build:web": "yarn build:local-packages && yarn workspace @upswyng/web build", - "build:local-db": "docker-compose up --build -d && npm run restore:db", - "restore:db": "mongorestore --port 27018 --username upswyng-dev-user --password upswyng123 -d upswyng-dev ./packages/server/localdb/mongodump", + "build:local-db": "docker compose up --build -d && mongorestore --port 27018 --username upswyng-dev-user --password upswyng123 -d upswyng-dev ./packages/server/localdb/mongodump", "clean": "node clean.js", "reset": "node clean.js --reset && docker compose down -v", "heroku-postbuild": "yarn build:web && yarn build:server", From 40307c8f6dd6f6688a13beddddcfcea4ac13176b Mon Sep 17 00:00:00 2001 From: Alvin Mites Date: Wed, 7 Jul 2021 20:59:23 -0600 Subject: [PATCH 08/11] heavy update to openapi spec --- package.json | 3 +- packages/server/docs/openapi.yaml | 726 ++++++++++++++---- .../server/src/routes/api/bot/test-job.ts | 2 +- 3 files changed, 600 insertions(+), 131 deletions(-) diff --git a/package.json b/package.json index 0d9c1330..6ec3af76 100644 --- a/package.json +++ b/package.json @@ -83,7 +83,8 @@ "build:local-packages": "yarn workspace @upswyng/types build && yarn workspace @upswyng/common build", "build:server": "yarn build:local-packages && yarn workspace @upswyng/server build", "build:web": "yarn build:local-packages && yarn workspace @upswyng/web build", - "build:local-db": "docker compose up --build -d && mongorestore --port 27018 --username upswyng-dev-user --password upswyng123 -d upswyng-dev ./packages/server/localdb/mongodump", + "build:local-db": "docker-compose up --build -d && npm run restore:db", + "restore:db": "mongorestore --port 27018 --username upswyng-dev-user --password upswyng123 -d upswyng-dev ./packages/server/localdb/mongodump", "clean": "node clean.js", "reset": "node clean.js --reset && docker compose down -v", "heroku-postbuild": "yarn build:web && yarn build:server", diff --git a/packages/server/docs/openapi.yaml b/packages/server/docs/openapi.yaml index d18fd668..6b049660 100644 --- a/packages/server/docs/openapi.yaml +++ b/packages/server/docs/openapi.yaml @@ -23,7 +23,7 @@ paths: security: - requireAdmin: [] tags: - - stub + - alert operationId: alertPost requestBody: description: New Alert Payload. @@ -36,11 +36,14 @@ paths: $ref: '#/components/schemas/AlertPost' responses: '200': - description: INCOMPLETE + description: New Alert content: application/json: schema: type: object + properties: + alert: + $ref: '#/components/schemas/AlertData' '400': $ref: '#/components/responses/ErrorInvalidRequest' '401': @@ -50,36 +53,34 @@ paths: /api/alert/search: post: - description: 'Search for alerts' - summary: 'Search for alerts' + description: 'API endpoint to get a list of Alerts. Returns the full alert (TAlertFull with user who created) if the user is a signed-in admin. Otherwise, returns TAlert' + summary: 'API endpoint to get a list of Alerts' tags: - - stub + - alert operationId: alertSearchPost requestBody: - description: Time to search for alert since. + description: Parameters to search for alert. content: application/json: schema: - $ref: '#/components/schemas/StartTimeObj' + $ref: '#/components/schemas/AlertSearch' application/x-www-form-urlencoded: schema: - $ref: '#/components/schemas/StartTimeObj' + $ref: '#/components/schemas/AlertSearch' responses: '200': description: Alerts. - # TODO: fill in alert structure content: application/json: schema: type: object properties: - category: - allOf: - - $ref: '#/components/schemas/CategoryData' - - type: object - properties: - subcategories: - $ref: '#/components/schemas/SubCategoryData' + count: + type: integer + alerts: + type: array + items: + $ref: '#/components/schemas/AlertData' '404': $ref: '#/components/responses/ErrorNotFound' @@ -91,7 +92,7 @@ paths: summary: 'Get an alert' operationId: alertGet tags: - - stub + - alert responses: '200': description: Single Alert. @@ -100,22 +101,110 @@ paths: schema: type: object properties: - category: - allOf: - - $ref: '#/components/schemas/CategoryData' - - type: object - properties: - subcategories: - $ref: '#/components/schemas/SubCategoryData' + alert: + $ref: '#/components/schemas/AlertData' '404': $ref: '#/components/responses/ErrorNotFound' + /api/bot/check-links: + parameters: + - $ref: '#/components/parameters/slackTimestampHeader' + post: + description: "Adds a Check Links job to the queue. This job walks through all the resources in the directory and checks if their respective website URLs are valid.

Can be called from slack command `/check-links`." + summary: 'Adds a Check Links job to the queue' + tags: + - bot + operationId: botCheckLinksPost + security: + - slackSigned: [] + requestBody: + $ref: '#/components/requestBodies/SlackBotRequest' + responses: + '200': + $ref: '#/components/responses/SlackBotResponse' + '400': + $ref: '#/components/responses/ErrorInvalidRequest' + + /api/bot/destroy-all-sessions: + parameters: + - $ref: '#/components/parameters/slackTimestampHeader' + post: + description: "Adds a Destroy All Sessions job to the queue.

Can be called from slack command `/destroy-all-sessions`." + summary: 'Adds a Destroy All Sessions job to the queue' + tags: + - bot + operationId: botDestroyAllSessionsPost + security: + - slackSigned: [] + requestBody: + $ref: '#/components/requestBodies/SlackBotRequest' + responses: + '200': + $ref: '#/components/responses/SlackBotResponse' + '400': + $ref: '#/components/responses/ErrorInvalidRequest' + + /api/bot/sync-algolia: + post: + description: "Adds 'syncAlgoliaIndex' to the queue. This job ensures that our algolia index is in sync with our database.

Can be called from slack command `/sync-algolia`." + summary: "Adds 'syncAlgoliaIndex' to the queue" + tags: + - bot + operationId: botSyncAlgoliaPost + security: + - slackSigned: [] + requestBody: + $ref: '#/components/requestBodies/SlackBotRequest' + responses: + '200': + $ref: '#/components/responses/SlackBotResponse' + '400': + $ref: '#/components/responses/ErrorInvalidRequest' + + /api/bot/test-job: + post: + description: "Adds a Test Job to the Work Queue.

Can be called from slack command `/test-job`.
Command can be like `/test-job 35`, where the second part is the delay to apply to the job.

To call from the command line:
  • `curl -XPOST -d 'delay=2000&shouldFail=true' 'localhost:3000/api/bot/test-job'`
" + summary: "Adds 'syncAlgoliaIndex' to the queue" + tags: + - bot + operationId: botTestJobPost + security: + - slackSigned: [] + requestBody: + description: 'Request body from slack / command.' + content: + application/json: + schema: + $ref: '#/components/schemas/BotSlackTestJobPost' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/BotSlackTestJobPost' + responses: + '201': + description: Slack Test Job Response. + content: + application/json: + schema: + type: object + properties: + jobName: + type: string + jobId: + type: string + shouldFail: + type: boolean + default: true + '500': + $ref: '#/components/responses/ErrorUnknown' + /api/category/{category}: parameters: - $ref: '#/components/parameters/categoryPath' get: description: 'Get a category with sub-categories.' summary: 'Get a category' + tags: + - category operationId: categoryGet responses: '200': @@ -139,6 +228,8 @@ paths: get: description: 'Get an array of all categories.' summary: 'Get all categories.' + tags: + - category operationId: categoriesGet responses: '200': @@ -167,12 +258,78 @@ paths: items: $ref: '#/components/schemas/Meta_id' + /api/eventlogs: + post: + description: 'API endpoint to get a list of Event Logs. Ordered from newest to oldest.' + summary: 'API endpoint to get a list of Event Logs.' + security: + - requireAdmin: [] + tags: + - eventlogs + operationId: eventlogsPost + requestBody: + description: Which eventlogs to return. + content: + application/json: + schema: + $ref: '#/components/schemas/PaginateEventLogsPost' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/PaginateEventLogsPost' + responses: + '200': + description: Event logs + content: + application/json: + schema: + type: object + properties: + estimatedTotal: + type: integer + example: 338 + eventLogs: + type: array + items: + type: object + properties: + _id: + type: string + default: '60e650de6a3a5d1284c55546' + actor: + $ref: '#/components/schemas/UserObj' + detail: + type: object + properties: + kind: + type: string + example: "user_permission_changed" + propertyNew: + type: string + description: New value for update type events. + propertyOld: + type: string + description: Old value for update type events. + kind: + type: string + default: 'user_permission_changed' + createdAt: + $ref: '#/components/schemas/MetaDateTime' + updatedAt: + $ref: '#/components/schemas/MetaDateTime' + __v: + type: integer + default: 0 + '401': + $ref: '#/components/responses/ErrorAuthentication' + '500': + $ref: '#/components/responses/ErrorUnknown' + /api/hotlines: get: description: 'Get an array of all hotlines.' summary: 'Get all hotlines.' tags: - - stub + - hotlines operationId: hotlinesGet responses: '200': @@ -185,11 +342,41 @@ paths: hotlines: type: array items: - allOf: - - $ref: '#/components/schemas/Meta_id' + type: object + properties: + _id: + $ref: "#/components/schemas/Meta_id" + chatWebsite: + $ref: '#/components/schemas/MetaWebsite' + description: + type: string + default: 'Description of the hotline' + name: + type: string + default: 'Hotline Name' + phone: + $ref: '#/components/schemas/MetaPhone' + text: + type: string + default: 'Text for the hotline' + website: + $ref: '#/components/schemas/MetaWebsite' '500': $ref: '#/components/responses/ErrorUnknown' + /api/provider/logout: + get: + description: 'Log Out by destroying any sessions associated with request.' + summary: 'Log Out' + operationId: providerLogOutGet + responses: + '302': + description: "Actual response is a Header with `Location` set as a string. OpenAPI doesn't support that type of response yet.

`Location: /provider/?loggedout=true`" + content: + application/json: + schema: + type: object + /api/resource: post: description: 'Create a new resource.' @@ -268,15 +455,13 @@ paths: severity: type: string default: 'high' + createdAt: + $ref: '#/components/schemas/MetaDateTime' + lastModifiedAt: + $ref: '#/components/schemas/MetaDateTime' __v: type: integer default: 0 - createdAt: - type: string - default: '2020-10-04T22:01:17.880Z' - lastModifiedAt: - type: string - default: '2020-10-04T22:01:17.880Z' '401': $ref: '#/components/responses/ErrorAuthentication' '500': @@ -529,16 +714,13 @@ paths: severity: type: string default: 'high' + createdAt: + $ref: '#/components/schemas/MetaDateTime' + lastModifiedAt: + $ref: '#/components/schemas/MetaDateTime' __v: type: integer default: 0 - createdAt: - type: string - default: '2020-04-05T03:08:50.948Z' - lastModifiedAt: - type: string - default: '2020-04-05T03:08:50.948Z' - '401': $ref: '#/components/responses/ErrorAuthentication' '404': @@ -622,15 +804,13 @@ paths: severity: type: string default: 'high' + createdAt: + $ref: '#/components/schemas/MetaDateTime' + lastModifiedAt: + $ref: '#/components/schemas/MetaDateTime' __v: type: integer default: 0 - createdAt: - type: string - default: '2020-10-04T22:01:17.880Z' - lastModifiedAt: - type: string - default: '2020-10-04T22:01:17.880Z' '401': $ref: '#/components/responses/ErrorAuthentication' '500': @@ -726,48 +906,6 @@ paths: '500': $ref: '#/components/responses/ErrorUnknown' -# /api/resources/issues/{id}: -# parameters: -# - $ref: '#/components/parameters/idPath' -# get: -# description: 'Get issue by resource.' -# summary: 'Get issues by resource' -# operationId: resourceIssueGet -# responses: -# '200': -# description: Subcategory. -# content: -# application/json: -# schema: -# type: object -# properties: -# subcategory: -# type: object -# properties: -# _id: -# $ref: '#/components/schemas/Meta_id' -# name: -# type: string -# example: 'Food Pantries' -# stub: -# type: string -# example: 'food_pantries' -# parentCategory: -# $ref: '#/components/schemas/ParentCategory' -# resources: -# type: array -# items: -# $ref: '#/components/schemas/ResourceCategoryData' -# createdAt: -# $ref: '#/components/schemas/MetaDateTime' -# lastModifiedAt: -# $ref: '#/components/schemas/MetaDateTime' -# __v: -# type: number -# default: 1 -# '404': -# $ref: '#/components/responses/ErrorNotFound' - /api/resources/uncategorized: get: description: 'Get an array of uncategorized resources.' @@ -807,6 +945,8 @@ paths: get: description: 'Get an array of all sub-categories.' summary: 'Get sub-categories.' + tags: + - category operationId: subcategoriesGet responses: '200': @@ -846,12 +986,43 @@ paths: type: number default: 1 + /api/subcategory/add-resource: + post: + description: 'Add a resource to a subcategory.' + summary: 'Create a resource' + security: + - requireAdmin: [] + tags: + - category + operationId: subcategoryAddResourcePost + requestBody: + description: Add Resource Payload. + content: + application/json: + schema: + $ref: '#/components/schemas/AddResourceSubCategoryPost' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/AddResourceSubCategoryPost' + responses: + '200': + $ref: '#/components/responses/EmptyObject' + '400': + $ref: '#/components/responses/ErrorInvalidRequest' + '401': + $ref: '#/components/responses/ErrorAuthentication' + '500': + $ref: '#/components/responses/ErrorUnknown' + + /api/subcategory/{subcategory}: parameters: - $ref: '#/components/parameters/subcategoryPath' get: description: 'Get a sub-category by stub name.' summary: 'Get a sub-category' + tags: + - category operationId: subcategoryGet responses: '200': @@ -888,6 +1059,125 @@ paths: '404': $ref: '#/components/responses/ErrorNotFound' + /api/users: + post: + description: 'Get an array of all sub-categories.' + summary: 'Get users.' + tags: + - users + security: + - requireAdmin: [] + operationId: usersGet + requestBody: + description: Filter which users to return. + content: + application/json: + schema: + $ref: '#/components/schemas/PaginatePost' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/PaginatePost' + responses: + '200': + description: Subcategories. + content: + application/json: + schema: + type: object + properties: + estimatedTotal: + type: integer + example: 8 + users: + type: array + items: + type: object + properties: + _id: + $ref: '#/components/schemas/Meta_id' + email: + type: string + example: 'dev.upswyng@gmail.com' + isAdmin: + type: boolean + default: false + isSuperAdmin: + type: boolean + default: false + providers: + type: array + items: + type: string + enum: + - facebook + - google + - slack + '401': + $ref: '#/components/responses/ErrorAuthentication' + '500': + $ref: '#/components/responses/ErrorUnknown' + + /api/users/{id}: + parameters: + - $ref: '#/components/parameters/idPath' + get: + description: 'Get a user by _id.' + summary: 'Get a user' + tags: + - users + security: + - requireAdmin: [] + operationId: userIdGet + responses: + '200': + description: User. + content: + application/json: + schema: + type: object + properties: + user: + $ref: '#/components/schemas/UserObj' + '401': + $ref: '#/components/responses/ErrorAuthentication' + '404': + $ref: '#/components/responses/ErrorNotFound' + '500': + $ref: '#/components/responses/ErrorUnknown' + post: + description: 'Update user by _id' + summary: 'Update user' + tags: + - users + security: + - requireSuperAdmin: [] + operationId: userIdPost + requestBody: + description: User details to update + content: + application/json: + schema: + $ref: '#/components/schemas/UserUpdatePost' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/UserUpdatePost' + responses: + '200': + description: User. + content: + application/json: + schema: + type: object + properties: + user: + $ref: '#/components/schemas/UserObj' + '401': + $ref: '#/components/responses/ErrorAuthentication' + '404': + $ref: '#/components/responses/ErrorNotFound' + '500': + $ref: '#/components/responses/ErrorUnknown' + /api/weather: parameters: - $ref: '#/components/parameters/latitudeQuery' @@ -989,6 +1279,65 @@ paths: components: schemas: + AlertData: + type: object + properties: + _id: + $ref: '#/components/schemas/Meta_id' + category: + type: string + example: 5d8f030ac0e6672699a500c2 + nullable: true + default: null + color: + type: string + default: 'gold' + createdBy: + $ref: '#/components/schemas/UserObj' + detail: + type: string + nullable: true + end: + $ref: '#/components/schemas/MetaDateTime' + icon: + type: string + default: 'https://upload.wikimedia.org/wikipedia/commons/9/99/OOjs_UI_icon_alert-yellow.svg' + isApproved: + type: boolean + default: false + isCancelled: + type: boolean + default: false + lastModifiedBy: + $ref: '#/components/schemas/UserObj' + start: + $ref: '#/components/schemas/MetaDateTime' + title: + type: string + default: 'alert description from postman' + wasProcessed: + type: boolean + default: false + createdAt: + $ref: '#/components/schemas/MetaDateTime' + lastModifiedAt: + $ref: '#/components/schemas/MetaDateTime' + __v: + type: integer + default: 0 + AlertSearch: + allOf: + - type: object + properties: + includeCancelled: + type: boolean + nullable: true + default: true + includeUnapproved: + type: boolean + nullable: true + default: false + - $ref: '#/components/schemas/StartTimeObj' CategoryDataNoColor: type: object properties: @@ -1085,6 +1434,28 @@ components: properties: parentCategory: $ref: '#/components/schemas/CategoryData' + SlackBotResponse: + type: object + properties: + blocks: + type: array + items: + type: object + properties: + text: + type: object + properties: + text: + type: string + example: 'I found you in UpSwyng, but you have to be an administrator to tell me to run this command' + type: + $ref: '#/components/schemas/MetaSlackType' + type: + $ref: '#/components/schemas/MetaSlackType' + response_type: + type: string + enum: + - in_channel SubCategoryData: allOf: - $ref: '#/components/schemas/CategoryData' @@ -1104,26 +1475,32 @@ components: type: object properties: _id: - type: string - description: database ObjectId converted to hex string - name: - type: string + $ref: '#/components/schemas/Meta_id' email: type: string - format: email - providers: - type: string - enum: - - 'facebook' - - 'google' - - 'slack' + example: 'dev.upswyng@gmail.com' isAdmin: type: boolean default: false isSuperAdmin: type: boolean default: false + providers: + type: array + items: + type: string + enum: + - facebook + - google + - slack # Post Request Bodies + AddResourceSubCategoryPost: + type: object + properties: + subcategoryId: + $ref: '#/components/schemas/Meta_id' + resourceId: + $ref: '#/components/schemas/Meta_id' AlertPost: type: object required: @@ -1150,22 +1527,53 @@ components: $ref: '#/components/schemas/MetaDateTime' title: type: string + BotSlackJobPost: + type: object + properties: + response_url: + type: string + example: 'hooks.slack.com' + BotSlackTestJobPost: + type: object + properties: + delay: + type: integer + shouldFail: + type: string + enum: + - false + - true + response_url: + type: string + example: 'hooks.slack.com' + PaginateEventLogsPost: + allOf: + - $ref: '#/components/schemas/PaginatePost' + - type: object + properties: + resourceId: + $ref: '#/components/schemas/Meta_id' IssuesQueryPost: + allOf: + - $ref: '#/components/schemas/PaginatePost' + - type: object + properties: + includeResolved: + type: boolean + default: false + minimumSeverity: + type: string + default: low + enum: + - low + - medium + - high + PaginatePost: type: object properties: - includeResolved: - type: boolean - default: false limit: type: integer default: 20 - minimumSeverity: - type: string - default: low - enum: - - low - - medium - - high offset: type: integer default: 0 @@ -1221,6 +1629,13 @@ components: $ref: '#/components/schemas/Meta_id' website: type: string + UserUpdatePost: + type: object + properties: + isAdmin: + type: boolean + isSuperAdmin: + type: boolean # Common AddressObj: type: object @@ -1244,18 +1659,6 @@ components: type: string description: Description of error. example: 'Error description' - ScheduleItem: - type: object - properties: - comment: - type: string - fromTime: - type: integer - recurrenceRule: - type: string - example: 'RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=WE' - toTime: - type: integer ScheduleObj: type: object properties: @@ -1266,7 +1669,17 @@ components: _items: type: array items: - $ref: '#/components/schemas/ScheduleItem' + type: object + properties: + comment: + type: string + fromTime: + type: integer + recurrenceRule: + type: string + example: 'RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=WE' + toTime: + type: integer # Meta Meta_id: type: string @@ -1293,9 +1706,17 @@ components: MetaPhone: type: string example: (303) 555-0112 + MetaSlackType: + type: string + enum: + - mrkdwn + - section MetaTimeZone: type: string example: 'America/Denver' + MetaWebsite: + type: string + example: 'https://www.upswyng.org/' securitySchemes: requireAdmin: @@ -1310,6 +1731,10 @@ components: type: http scheme: bearer bearerFormat: JWT + slackSigned: + type: apiKey + in: header + name: 'X-Slack-Signature' parameters: categoryPath: @@ -1359,6 +1784,13 @@ components: schema: type: number example: -105.2705 + slackTimestampHeader: + in: header + name: X-Slack-Request-Timestamp + required: true + schema: + type: string + format: date-time subcategoryPath: name: subcategory in: path @@ -1375,13 +1807,12 @@ components: application/json: schema: type: object - # Errors - ErrorAlreadyExists: - description: Resource already exists and cannot be created again. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorObj' +# ErrorAlreadyExists: +# description: Resource already exists and cannot be created again. +# content: +# application/json: +# schema: +# $ref: '#/components/schemas/ErrorObj' ErrorAuthentication: description: Invalid user credentials submitted. content: @@ -1406,9 +1837,46 @@ components: application/json: schema: $ref: '#/components/schemas/ErrorObj' +# Redirect: +# description: Actual response is a Header with `Location` set as a string. OpenAPI doesn't support that type of response yet. +# content: +# application/json: +# schema: +# type: object + SlackBotResponse: + description: Slack Response. + content: + application/json: + schema: + $ref: '#/components/schemas/SlackBotResponse' requestBodies: EmptyRequest: description: Empty request body content: application/json: {} + SlackBotRequest: + description: 'Request body from slack / command.' + content: + application/json: + schema: + $ref: '#/components/schemas/BotSlackJobPost' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/BotSlackJobPost' + +tags: + - name: stub + description: Incomplete documentation. + - name: alert + description: 'Create and get alerts for display.' + - name: bot + description: 'Endpoints for slack bot to interact with.' + - name: category + description: 'Category & SubCategory related.' + - name: hotlines + description: 'Hotlines' + - name: resource + description: 'Resources' + - name: users + description: 'Users' diff --git a/packages/server/src/routes/api/bot/test-job.ts b/packages/server/src/routes/api/bot/test-job.ts index c572883c..2cb0a8ae 100644 --- a/packages/server/src/routes/api/bot/test-job.ts +++ b/packages/server/src/routes/api/bot/test-job.ts @@ -6,7 +6,7 @@ import mq from "../../../worker/mq"; async function makeTestJob(req, res, _next, user: TUser) { const jobName = getName("-"); - // Command can be like /testjob 35, where the second part is the delay to apply to the job + // Command can be like /test-job 35, where the second part is the delay to apply to the job let argParseFailure = false; let delay: number; const arg = req.body.text; From f3418b4bf2f49dd5acf6b6eecfc2f94e74ee20a3 Mon Sep 17 00:00:00 2001 From: Alvin Mites Date: Sat, 10 Jul 2021 12:50:27 -0600 Subject: [PATCH 09/11] finished draft of docs + minor grooming to standardize --- packages/server/docs/openapi.yaml | 250 +++++++++++------- packages/server/src/routes/api/resource.ts | 3 + .../server/src/routes/api/resources/drafts.ts | 14 + 3 files changed, 176 insertions(+), 91 deletions(-) diff --git a/packages/server/docs/openapi.yaml b/packages/server/docs/openapi.yaml index 6b049660..af85c924 100644 --- a/packages/server/docs/openapi.yaml +++ b/packages/server/docs/openapi.yaml @@ -384,7 +384,7 @@ paths: security: - requireLoggedIn: [] tags: - - stub + - resource operationId: resourcePost requestBody: description: New Resource Payload. @@ -464,6 +464,8 @@ paths: default: 0 '401': $ref: '#/components/responses/ErrorAuthentication' + '422': + $ref: '#/components/responses/ErrorAlreadyExists' '500': $ref: '#/components/responses/ErrorUnknown' @@ -522,19 +524,9 @@ paths: type: object properties: resources: - type: array - items: - allOf: - - $ref: '#/components/schemas/ResourceDataLatLon' - - type: object - properties: - subcategories: - allOf: - - $ref: '#/components/schemas/CategoryDataNoColor' - - type: object - properties: - parentCategory: - $ref: '#/components/schemas/CategoryData' + $ref: '#/components/schemas/MetaResourceArr' + '500': + $ref: '#/components/responses/ErrorUnknown' /api/resource/draft/approve/{id}: parameters: @@ -586,22 +578,17 @@ paths: summary: 'Get a resource draft' operationId: resourceDraftGet tags: - - stub + - resource responses: '200': - description: Single Category. + description: Single Resource Draft - `createdBy` only available to admin users. content: application/json: schema: type: object properties: - category: - allOf: - - $ref: '#/components/schemas/CategoryData' - - type: object - properties: - subcategories: - $ref: '#/components/schemas/SubCategoryData' + draftResource: + $ref: '#/components/schemas/DraftResource' '404': $ref: '#/components/responses/ErrorNotFound' '500': @@ -611,14 +598,14 @@ paths: parameters: - $ref: '#/components/parameters/includeDeletedQueryOptional' get: - description: 'Get an array of resources.' - summary: 'Get resources.' + description: 'Get an array of draft resources.' + summary: 'Get draft resources.' tags: - - stub + - resource operationId: resourcesDraftsGet responses: '200': - description: INCOMPLETE + description: Draft resources content: application/json: schema: @@ -627,22 +614,22 @@ paths: draftResources: type: array items: - allOf: - - $ref: '#/components/schemas/ResourceDataLatLon' - - $ref: '#/components/schemas/MetaLegacyIdObj' - '401': - $ref: '#/components/responses/ErrorAuthentication' + $ref: '#/components/schemas/DraftResource' + '500': + $ref: '#/components/responses/ErrorUnknown' /api/resources/drafts/mine: get: description: 'Get an array of resources.' summary: 'Get resources.' tags: - - stub + - resource operationId: resourcesDraftsMineGet + security: + - requireLoggedIn: [] responses: '200': - description: INCOMPLETE + description: Resource Drafts content: application/json: schema: @@ -653,22 +640,11 @@ paths: items: allOf: - $ref: '#/components/schemas/ResourceData' - - type: object - properties: - location: - type: object - properties: - coordinates: - description: Latitude & Longitude - type: array - items: - type: number - example: [-105.13494760000003, 39.9776081] - type: - type: string - example: Point + - $ref: '#/components/schemas/MetaLocationObj' '401': $ref: '#/components/responses/ErrorAuthentication' + '500': + $ref: '#/components/responses/ErrorUnknown' /api/resources/issue/{id}: parameters: @@ -911,35 +887,20 @@ paths: description: 'Get an array of uncategorized resources.' summary: 'Get uncategorized resources.' tags: - - stub + - resource operationId: resourcesUncategorizedGet responses: '200': - description: Array of resources. + description: Array of uncategorized resources. content: application/json: schema: type: object properties: uncategorizedResources: - type: array - items: - allOf: - - $ref: '#/components/schemas/ResourceData' - - type: object - properties: - location: - type: object - properties: - coordinates: - description: Latitude & Longitude - type: array - items: - type: number - example: [-105.13494760000003, 39.9776081] - type: - type: string - example: Point + $ref: '#/components/schemas/MetaResourceArr' + '500': + $ref: '#/components/responses/ErrorUnknown' /api/subcategories: get: @@ -1363,6 +1324,76 @@ components: properties: color: type: string + DraftResource: + type: object + properties: + _id: + $ref: '#/components/schemas/Meta_id' + address: + $ref: '#/components/schemas/AddressObj' + createdAt: + $ref: '#/components/schemas/MetaDateTime' + createdBy: + $ref: '#/components/schemas/UserObj' + deleted: + type: boolean + default: false + description: + type: string + example: 'Weekly groceries for families whose children are enrolled in the free or reduced lunch program at their school...' + kudos: + type: integer + default: 0 + latitude: + $ref: '#/components/schemas/MetaLatitude' + legacyId: + type: string + default: '-KUnLd_no7p7m2u77dfY' + longitude: + $ref: '#/components/schemas/MetaLongitude' + name: + type: string + default: 'Community Food Share' + phone: + type: string + default: '(303) 652-3663' + schedule: + $ref: '#/components/schemas/ScheduleObj' + services: + $ref: '#/components/schemas/MetaServicesArr' + streetViewImage: + $ref: '#/components/schemas/MetaStreetViewImage' + subcategories: + type: array + items: + type: object + properties: + _id: + $ref: '#/components/schemas/Meta_id' + name: + type: string + example: 'Food Pantries' + stub: + type: string + example: 'food_pantries' + parentCategory: + allOf: + - $ref: '#/components/schemas/CategoryData' + - type: object + properties: + subcategories: + type: array + items: + $ref: '#/components/schemas/Meta_id' + createdAt: + $ref: '#/components/schemas/MetaDateTime' + lastModifiedAt: + $ref: '#/components/schemas/MetaDateTime' + __v: + type: integer + website: + type: string + example: 'https://www.upswyng.org' ParentCategory: allOf: - $ref: '#/components/schemas/CategoryData' @@ -1407,13 +1438,9 @@ components: schedule: $ref: '#/components/schemas/ScheduleObj' services: - type: array - items: - type: string - example: 'Groceries for low-income Seniors/Families' + $ref: '#/components/schemas/MetaServicesArr' streetViewImage: - type: string - example: 'http://media.upswyng.org/images/5def5cbab831a048f2a3df03.jpg' + $ref: '#/components/schemas/MetaStreetViewImage' website: type: string deleted: @@ -1485,6 +1512,9 @@ components: isSuperAdmin: type: boolean default: false + name: + type: string + example: "Jacob Venable" providers: type: array items: @@ -1617,12 +1647,9 @@ components: schedule: $ref: '#/components/schemas/ScheduleObj' services: - type: array - items: - type: string + $ref: '#/components/schemas/MetaServicesArr' streetViewImage: - type: string - example: 'http://media.upswyng.org/images/5def5cbab831a048f2a3df03.jpg' + $ref: '#/components/schemas/MetaStreetViewImage' subcategories: type: array items: @@ -1688,29 +1715,72 @@ components: type: string format: date-time example: '2019-09-28T06:51:53.633Z' + MetaLatitude: + type: number + example: 40.0584971 + MetaLongitude: + type: number + example: -105.11954379999997 MetaLatLonObj: type: object properties: latitude: - type: number - example: 40.0584971 + $ref: '#/components/schemas/MetaLatitude' longitude: - type: number - example: -105.11954379999997 + $ref: '#/components/schemas/MetaLongitude' MetaLegacyIdObj: type: object properties: legacyId: type: string example: -KZnRX-8rV1552vd0P7_ + MetaLocation: + type: object + properties: + coordinates: + description: Latitude & Longitude + type: array + items: + type: number + example: [-105.13494760000003, 39.9776081] + type: + type: string + example: Point + MetaLocationObj: + type: object + properties: + location: + $ref: '#/components/schemas/MetaLocation' MetaPhone: type: string example: (303) 555-0112 + MetaResourceArr: + type: array + items: + allOf: + - $ref: '#/components/schemas/ResourceDataLatLon' + - type: object + properties: + subcategories: + allOf: + - $ref: '#/components/schemas/CategoryDataNoColor' + - type: object + properties: + parentCategory: + $ref: '#/components/schemas/CategoryData' + MetaServicesArr: + type: array + items: + type: string + example: 'Groceries for low-income Seniors/Families' MetaSlackType: type: string enum: - mrkdwn - section + MetaStreetViewImage: + type: string + example: 'http://media.upswyng.org/images/5def5cbab831a048f2a3df03.jpg' MetaTimeZone: type: string example: 'America/Denver' @@ -1807,12 +1877,12 @@ components: application/json: schema: type: object -# ErrorAlreadyExists: -# description: Resource already exists and cannot be created again. -# content: -# application/json: -# schema: -# $ref: '#/components/schemas/ErrorObj' + ErrorAlreadyExists: + description: Resource already exists and cannot be created again. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorObj' ErrorAuthentication: description: Invalid user credentials submitted. content: @@ -1866,8 +1936,6 @@ components: $ref: '#/components/schemas/BotSlackJobPost' tags: - - name: stub - description: Incomplete documentation. - name: alert description: 'Create and get alerts for display.' - name: bot diff --git a/packages/server/src/routes/api/resource.ts b/packages/server/src/routes/api/resource.ts index 2e782798..9e1d82c7 100644 --- a/packages/server/src/routes/api/resource.ts +++ b/packages/server/src/routes/api/resource.ts @@ -28,6 +28,9 @@ export async function post(req, res, next) { next(); return; } + + console.log(`\n user:\n\n\n\t${JSON.stringify(user)}\n\n`); + try { const { draftResource } = req.body; draftResource.createdBy = user as TUser; diff --git a/packages/server/src/routes/api/resources/drafts.ts b/packages/server/src/routes/api/resources/drafts.ts index 538bec6d..4d2af200 100644 --- a/packages/server/src/routes/api/resources/drafts.ts +++ b/packages/server/src/routes/api/resources/drafts.ts @@ -1,4 +1,5 @@ import { DraftResource } from "../../../models/Resource"; +import { isAdmin } from "../../../utility/authHelpers"; /** * Get all draft resources. Include the `include-deleted` query parameter to @@ -12,6 +13,19 @@ export async function get(req, res, _next) { "Content-Type": "application/json", }); + if (!isAdmin(req)) { + // don't allow non-admins to see who created a resource + return res.end( + JSON.stringify({ + draftResources: draftResources.map(d => { + const result = { ...d }; + delete result.createdBy; + return result; + }), + }) + ); + } + return res.end(JSON.stringify({ draftResources })); } catch (e) { console.error(e); From c5daf4790c16ee13d7fbea3e920c0fc32009e83b Mon Sep 17 00:00:00 2001 From: Alvin Mites Date: Sat, 10 Jul 2021 14:19:17 -0600 Subject: [PATCH 10/11] I think docs are ready --- packages/server/docs/openapi.yaml | 643 ++++++++++----------- packages/server/src/models/Resource.ts | 3 +- packages/server/src/routes/api/resource.ts | 2 - 3 files changed, 314 insertions(+), 334 deletions(-) diff --git a/packages/server/docs/openapi.yaml b/packages/server/docs/openapi.yaml index af85c924..2a84a3af 100644 --- a/packages/server/docs/openapi.yaml +++ b/packages/server/docs/openapi.yaml @@ -9,16 +9,16 @@ info: version: '1.0.0' servers: - - url: 'http://localhost:3000' + - url: 'http://localhost:3000/api' description: Docker Compose Server # Paths are sorted alphabetically # variables as part of a path are sorted as last in order. paths: - /api/alert: + /alert: post: - description: 'Create a new alert.' + description: 'API endpoint to create or update an alert.' summary: 'Create alert' security: - requireAdmin: [] @@ -51,7 +51,7 @@ paths: '500': $ref: '#/components/responses/ErrorUnknown' - /api/alert/search: + /alert/search: post: description: 'API endpoint to get a list of Alerts. Returns the full alert (TAlertFull with user who created) if the user is a signed-in admin. Otherwise, returns TAlert' summary: 'API endpoint to get a list of Alerts' @@ -84,11 +84,11 @@ paths: '404': $ref: '#/components/responses/ErrorNotFound' - /api/alert/{id}: + /alert/{id}: parameters: - $ref: '#/components/parameters/idPath' get: - description: 'Get an alert' + description: 'Get a single alert by ID. ex: /api/alert/5e6e9b2a8746d64922c6a412' summary: 'Get an alert' operationId: alertGet tags: @@ -103,10 +103,12 @@ paths: properties: alert: $ref: '#/components/schemas/AlertData' + '400': + $ref: '#/components/responses/ErrorInvalidRequest' '404': $ref: '#/components/responses/ErrorNotFound' - /api/bot/check-links: + /bot/check-links: parameters: - $ref: '#/components/parameters/slackTimestampHeader' post: @@ -125,7 +127,7 @@ paths: '400': $ref: '#/components/responses/ErrorInvalidRequest' - /api/bot/destroy-all-sessions: + /bot/destroy-all-sessions: parameters: - $ref: '#/components/parameters/slackTimestampHeader' post: @@ -144,7 +146,9 @@ paths: '400': $ref: '#/components/responses/ErrorInvalidRequest' - /api/bot/sync-algolia: + /bot/sync-algolia: + parameters: + - $ref: '#/components/parameters/slackTimestampHeader' post: description: "Adds 'syncAlgoliaIndex' to the queue. This job ensures that our algolia index is in sync with our database.

Can be called from slack command `/sync-algolia`." summary: "Adds 'syncAlgoliaIndex' to the queue" @@ -161,7 +165,7 @@ paths: '400': $ref: '#/components/responses/ErrorInvalidRequest' - /api/bot/test-job: + /bot/test-job: post: description: "Adds a Test Job to the Work Queue.

Can be called from slack command `/test-job`.
Command can be like `/test-job 35`, where the second part is the delay to apply to the job.

To call from the command line:
  • `curl -XPOST -d 'delay=2000&shouldFail=true' 'localhost:3000/api/bot/test-job'`
" summary: "Adds 'syncAlgoliaIndex' to the queue" @@ -197,7 +201,7 @@ paths: '500': $ref: '#/components/responses/ErrorUnknown' - /api/category/{category}: + /category/{category}: parameters: - $ref: '#/components/parameters/categoryPath' get: @@ -215,16 +219,11 @@ paths: type: object properties: category: - allOf: - - $ref: '#/components/schemas/CategoryData' - - type: object - properties: - subcategories: - $ref: '#/components/schemas/SubCategoryData' + $ref: '#/components/schemas/CategoryDocument' '404': $ref: '#/components/responses/ErrorNotFound' - /api/categories: + /categories: get: description: 'Get an array of all categories.' summary: 'Get all categories.' @@ -242,23 +241,11 @@ paths: categories: type: array items: - allOf: - - $ref: '#/components/schemas/CategoryData' - - type: object - properties: - subcategories: - type: array - items: - allOf: - - $ref: '#/components/schemas/CategoryData' - - type: object - properties: - resources: - type: array - items: - $ref: '#/components/schemas/Meta_id' + $ref: '#/components/schemas/CategoryDocument' + '500': + $ref: '#/components/responses/ErrorUnknown' - /api/eventlogs: + /eventlogs: post: description: 'API endpoint to get a list of Event Logs. Ordered from newest to oldest.' summary: 'API endpoint to get a list of Event Logs.' @@ -285,24 +272,21 @@ paths: type: object properties: estimatedTotal: - type: integer - example: 338 + $ref: '#/components/schemas/MetaCount' eventLogs: type: array items: type: object properties: _id: - type: string - default: '60e650de6a3a5d1284c55546' + $ref: '#/components/schemas/Meta_id' actor: - $ref: '#/components/schemas/UserObj' + $ref: '#/components/schemas/MetaUser' detail: type: object properties: kind: - type: string - example: "user_permission_changed" + $ref: '#/components/schemas/MetaEventKind' propertyNew: type: string description: New value for update type events. @@ -310,8 +294,7 @@ paths: type: string description: Old value for update type events. kind: - type: string - default: 'user_permission_changed' + $ref: '#/components/schemas/MetaEventKind' createdAt: $ref: '#/components/schemas/MetaDateTime' updatedAt: @@ -324,7 +307,7 @@ paths: '500': $ref: '#/components/responses/ErrorUnknown' - /api/hotlines: + /hotlines: get: description: 'Get an array of all hotlines.' summary: 'Get all hotlines.' @@ -364,7 +347,7 @@ paths: '500': $ref: '#/components/responses/ErrorUnknown' - /api/provider/logout: + /provider/logout: get: description: 'Log Out by destroying any sessions associated with request.' summary: 'Log Out' @@ -377,14 +360,15 @@ paths: schema: type: object - /api/resource: + /resource: post: - description: 'Create a new resource.' + description: 'Creates a new draft resource. Resources and updates to resources start as draft resource records. Draft resource updates are then merged into the `Resource` collection.' summary: 'Create resource' security: - requireLoggedIn: [] tags: - resource + - stub operationId: resourcePost requestBody: description: New Resource Payload. @@ -397,7 +381,7 @@ paths: $ref: '#/components/schemas/ResourcePost' responses: '201': - description: INCOMPLETE + description: New draft resource content: application/json: schema: @@ -407,8 +391,7 @@ paths: type: integer default: 12 estimatedTotal: - type: integer - default: 29 + $ref: '#/components/schemas/MetaCount' resourceIssues: type: array items: @@ -421,31 +404,9 @@ paths: type: object properties: kind: - type: string - default: 'user_report' - enum: - - 'user_report' - # - 'legacy_schedule_parsing_error' - # user_report - detailExplanation: - type: string - default: 'Derp' - reportedIssues: - type: array - items: - type: string - example: 'The address is wrong.' - # # legacy schedule error - # legacyClosesSchedule: - # type: string - # description: 'Only for type legacy_schedule_parsing_error' - # legacySchedule: - # type: string - # example: '[{"day":"Thursday","fromstring":"10:00 AM","period":"First","tostring":"12:00 PM","type":"Monthly"},{"day":"Thursday","fromstring":"10:00 AM","period":"Third","tostring":"12:00 PM","type":"Monthly"}]' - # description: 'Only for type legacy_schedule_parsing_error' + $ref: '#/components/schemas/MetaEventKindUserReport' kind: - type: string - default: 'user_report' + $ref: '#/components/schemas/MetaEventKindUserReport' resolved: type: boolean default: false @@ -469,12 +430,14 @@ paths: '500': $ref: '#/components/responses/ErrorUnknown' - /api/resource/{id}: + /resource/{id}: parameters: - $ref: '#/components/parameters/idPath' get: description: 'Get a resource.' summary: 'Get a resource' + tags: + - resource operationId: resourceGet responses: '200': @@ -485,35 +448,20 @@ paths: type: object properties: resource: - allOf: - - $ref: '#/components/schemas/ResourceDataLatLon' - - type: object - properties: - subcategories: - allOf: - - $ref: '#/components/schemas/ResourceSubcategory' - - type: object - properties: - parentCategory: - allOf: - - $ref: '#/components/schemas/CategoryData' - - type: object - properties: - subcategories: - type: array - items: - $ref: '#/components/schemas/ResourceSubcategory' + $ref: '#/components/schemas/Resource' '404': $ref: '#/components/responses/ErrorNotFound' '500': $ref: '#/components/responses/ErrorUnknown' - /api/resources: + /resources: parameters: - $ref: '#/components/parameters/idQueryOptional' get: description: 'Get an array of resources.' summary: 'Get resources.' + tags: + - resource operationId: resourcesGet responses: '200': @@ -528,12 +476,14 @@ paths: '500': $ref: '#/components/responses/ErrorUnknown' - /api/resource/draft/approve/{id}: + /resource/draft/approve/{id}: parameters: - $ref: '#/components/parameters/idPath' post: description: 'Mark a draft resource approved.' summary: 'Approve draft resource' + tags: + - resource operationId: resourcesDraftApprovePost security: - requireAdmin: [] @@ -549,12 +499,14 @@ paths: '500': $ref: '#/components/responses/ErrorUnknown' - /api/resource/draft/delete/{id}: + /resource/draft/delete/{id}: parameters: - $ref: '#/components/parameters/idPath' post: description: 'Delete a draft resource.' summary: 'Delete draft resource' + tags: + - resource operationId: resourcesDraftDeletePost security: - requireAdmin: [] @@ -570,7 +522,7 @@ paths: '500': $ref: '#/components/responses/ErrorUnknown' - /api/resource/draft/{id}: + /resource/draft/{id}: parameters: - $ref: '#/components/parameters/idPath' get: @@ -588,13 +540,13 @@ paths: type: object properties: draftResource: - $ref: '#/components/schemas/DraftResource' + $ref: '#/components/schemas/ResourceDraft' '404': $ref: '#/components/responses/ErrorNotFound' '500': $ref: '#/components/responses/ErrorUnknown' - /api/resources/drafts: + /resources/drafts: parameters: - $ref: '#/components/parameters/includeDeletedQueryOptional' get: @@ -614,11 +566,11 @@ paths: draftResources: type: array items: - $ref: '#/components/schemas/DraftResource' + $ref: '#/components/schemas/ResourceDraft' '500': $ref: '#/components/responses/ErrorUnknown' - /api/resources/drafts/mine: + /resources/drafts/mine: get: description: 'Get an array of resources.' summary: 'Get resources.' @@ -638,15 +590,13 @@ paths: uncategorizedResources: type: array items: - allOf: - - $ref: '#/components/schemas/ResourceData' - - $ref: '#/components/schemas/MetaLocationObj' + $ref: '#/components/schemas/Resource' '401': $ref: '#/components/responses/ErrorAuthentication' '500': $ref: '#/components/responses/ErrorUnknown' - /api/resources/issue/{id}: + /resources/issue/{id}: parameters: - $ref: '#/components/parameters/idPath' get: @@ -674,16 +624,14 @@ paths: type: string default: 'The picture is incorrect. Mike ' kind: - type: string - default: 'user_report' + $ref: '#/components/schemas/MetaEventKindUserReport' reportedIssues: type: array items: type: string example: 'The address is wrong.' kind: - type: string - default: 'user_report' + $ref: '#/components/schemas/MetaEventKindUserReport' resourceId: type: string default: '5def5cb7b831a048f2a3deef' @@ -704,7 +652,7 @@ paths: '500': $ref: '#/components/responses/ErrorUnknown' - /api/resources/issues: + /resources/issues: post: description: 'Query for an array of issues.' summary: 'Query issues.' @@ -732,8 +680,7 @@ paths: type: integer default: 12 estimatedTotal: - type: integer - default: 29 + $ref: '#/components/schemas/MetaCount' resourceIssues: type: array items: @@ -746,12 +693,7 @@ paths: type: object properties: kind: - type: string - default: 'user_report' - enum: - - 'user_report' -# - 'legacy_schedule_parsing_error' - # user_report + $ref: '#/components/schemas/MetaEventKindUserReport' detailExplanation: type: string default: 'Derp' @@ -760,17 +702,8 @@ paths: items: type: string example: 'The address is wrong.' -# # legacy schedule error -# legacyClosesSchedule: -# type: string -# description: 'Only for type legacy_schedule_parsing_error' -# legacySchedule: -# type: string -# example: '[{"day":"Thursday","fromstring":"10:00 AM","period":"First","tostring":"12:00 PM","type":"Monthly"},{"day":"Thursday","fromstring":"10:00 AM","period":"Third","tostring":"12:00 PM","type":"Monthly"}]' -# description: 'Only for type legacy_schedule_parsing_error' kind: - type: string - default: 'user_report' + $ref: '#/components/schemas/MetaEventKindUserReport' resolved: type: boolean default: false @@ -792,7 +725,7 @@ paths: '500': $ref: '#/components/responses/ErrorUnknown' - /api/resources/issues/resolve/{id}: + /resources/issues/resolve/{id}: parameters: - $ref: '#/components/parameters/idPath' post: @@ -813,7 +746,7 @@ paths: '500': $ref: '#/components/responses/ErrorUnknown' - /api/resources/issues/unresolve/{id}: + /resources/issues/unresolve/{id}: parameters: - $ref: '#/components/parameters/idPath' post: @@ -834,7 +767,7 @@ paths: '500': $ref: '#/components/responses/ErrorUnknown' - /api/resources/issues/user-report: + /resources/issues/user-report: post: description: 'Report a new issue' summary: 'Report issue' @@ -857,9 +790,7 @@ paths: type: object properties: kind: - type: string - enum: - - user_report + $ref: '#/components/schemas/MetaEventKindUserReport' detailExplanation: type: string description: 'Text the user writes in as a detail.' @@ -882,7 +813,7 @@ paths: '500': $ref: '#/components/responses/ErrorUnknown' - /api/resources/uncategorized: + /resources/uncategorized: get: description: 'Get an array of uncategorized resources.' summary: 'Get uncategorized resources.' @@ -902,12 +833,12 @@ paths: '500': $ref: '#/components/responses/ErrorUnknown' - /api/subcategories: + /subcategories: get: description: 'Get an array of all sub-categories.' summary: 'Get sub-categories.' tags: - - category + - sub-category operationId: subcategoriesGet responses: '200': @@ -947,14 +878,14 @@ paths: type: number default: 1 - /api/subcategory/add-resource: + /subcategory/add-resource: post: description: 'Add a resource to a subcategory.' summary: 'Create a resource' security: - requireAdmin: [] tags: - - category + - sub-category operationId: subcategoryAddResourcePost requestBody: description: Add Resource Payload. @@ -975,15 +906,14 @@ paths: '500': $ref: '#/components/responses/ErrorUnknown' - - /api/subcategory/{subcategory}: + /subcategory/{subcategory}: parameters: - $ref: '#/components/parameters/subcategoryPath' get: description: 'Get a sub-category by stub name.' summary: 'Get a sub-category' tags: - - category + - sub-category operationId: subcategoryGet responses: '200': @@ -1009,7 +939,7 @@ paths: resources: type: array items: - $ref: '#/components/schemas/ResourceCategoryData' + $ref: '#/components/schemas/Resource' createdAt: $ref: '#/components/schemas/MetaDateTime' lastModifiedAt: @@ -1020,7 +950,7 @@ paths: '404': $ref: '#/components/responses/ErrorNotFound' - /api/users: + /users: post: description: 'Get an array of all sub-categories.' summary: 'Get users.' @@ -1047,8 +977,7 @@ paths: type: object properties: estimatedTotal: - type: integer - example: 8 + $ref: '#/components/schemas/MetaCount' users: type: array items: @@ -1078,7 +1007,7 @@ paths: '500': $ref: '#/components/responses/ErrorUnknown' - /api/users/{id}: + /users/{id}: parameters: - $ref: '#/components/parameters/idPath' get: @@ -1098,7 +1027,7 @@ paths: type: object properties: user: - $ref: '#/components/schemas/UserObj' + $ref: '#/components/schemas/MetaUser' '401': $ref: '#/components/responses/ErrorAuthentication' '404': @@ -1131,7 +1060,7 @@ paths: type: object properties: user: - $ref: '#/components/schemas/UserObj' + $ref: '#/components/schemas/MetaUser' '401': $ref: '#/components/responses/ErrorAuthentication' '404': @@ -1139,7 +1068,7 @@ paths: '500': $ref: '#/components/responses/ErrorUnknown' - /api/weather: + /weather: parameters: - $ref: '#/components/parameters/latitudeQuery' - $ref: '#/components/parameters/longitudeQuery' @@ -1254,7 +1183,7 @@ components: type: string default: 'gold' createdBy: - $ref: '#/components/schemas/UserObj' + $ref: '#/components/schemas/MetaCreatedBy' detail: type: string nullable: true @@ -1270,7 +1199,7 @@ components: type: boolean default: false lastModifiedBy: - $ref: '#/components/schemas/UserObj' + $ref: '#/components/schemas/MetaUser' start: $ref: '#/components/schemas/MetaDateTime' title: @@ -1324,41 +1253,91 @@ components: properties: color: type: string - DraftResource: + ParentCategory: + allOf: + - $ref: '#/components/schemas/CategoryData' + - type: object + properties: + subcategories: + type: array + items: + $ref: '#/components/schemas/Meta_id' + Resource: type: object properties: _id: - $ref: '#/components/schemas/Meta_id' + description: 'DO NOT normally reference this, use `resourceId`' + type: string + example: '5d8f030ac0e6672699a500c2' address: - $ref: '#/components/schemas/AddressObj' + $ref: '#/components/schemas/MetaAddress' createdAt: $ref: '#/components/schemas/MetaDateTime' createdBy: - $ref: '#/components/schemas/UserObj' + $ref: '#/components/schemas/MetaCreatedBy' deleted: - type: boolean - default: false + $ref: '#/components/schemas/MetaDeleted' description: + $ref: '#/components/schemas/MetaDescription' + kudos: + type: integer + lastModifiedAt: + $ref: '#/components/schemas/MetaDateTime' + lastModifiedBy: + $ref: '#/components/schemas/MetaUser' + latitude: + $ref: '#/components/schemas/MetaLatitude' + legacyId: + $ref: '#/components/schemas/MetaLegacyId' + longitude: + $ref: '#/components/schemas/MetaLongitude' + name: type: string - example: 'Weekly groceries for families whose children are enrolled in the free or reduced lunch program at their school...' + phone: + $ref: '#/components/schemas/MetaPhone' + resourceId: + $ref: '#/components/schemas/Meta_id' + schedule: + $ref: '#/components/schemas/MetaSchedule' + services: + $ref: '#/components/schemas/MetaServicesArr' + streetViewImage: + $ref: '#/components/schemas/MetaStreetViewImage' + subcategories: + $ref: '#/components/schemas/SubCategoryWithResources' + website: + $ref: '#/components/schemas/MetaWebsite' + ResourceDraft: + type: object + properties: + _id: + $ref: '#/components/schemas/Meta_id' + address: + $ref: '#/components/schemas/MetaAddress' + createdAt: + $ref: '#/components/schemas/MetaDateTime' + createdBy: + $ref: '#/components/schemas/MetaCreatedBy' + deleted: + $ref: '#/components/schemas/MetaDeleted' + description: + $ref: '#/components/schemas/MetaDescription' kudos: type: integer default: 0 latitude: $ref: '#/components/schemas/MetaLatitude' legacyId: - type: string - default: '-KUnLd_no7p7m2u77dfY' + $ref: '#/components/schemas/MetaLegacyId' longitude: $ref: '#/components/schemas/MetaLongitude' name: type: string default: 'Community Food Share' phone: - type: string - default: '(303) 652-3663' + $ref: '#/components/schemas/MetaPhone' schedule: - $ref: '#/components/schemas/ScheduleObj' + $ref: '#/components/schemas/MetaSchedule' services: $ref: '#/components/schemas/MetaServicesArr' streetViewImage: @@ -1392,75 +1371,7 @@ components: __v: type: integer website: - type: string - example: 'https://www.upswyng.org' - ParentCategory: - allOf: - - $ref: '#/components/schemas/CategoryData' - - type: object - properties: - subcategories: - type: array - items: - $ref: '#/components/schemas/Meta_id' - ResourceCategoryData: - allOf: - - $ref: '#/components/schemas/ResourceDataLatLon' - - type: object - properties: - resourceId: - $ref: '#/components/schemas/Meta_id' - subcategories: - type: array - items: - $ref: '#/components/schemas/SubCategoryData' - ResourceData: - type: object - properties: - _id: - $ref: '#/components/schemas/Meta_id' - address: - $ref: '#/components/schemas/AddressObj' - description: - type: string - example: 'Weekly groceries for families whose children are enrolled in the free or reduced lunch program at their school.' - kudos: - type: number - default: 0 - legacyId: - type: string - example: -KUo-cPb45EOhVRG_ul9 - name: - type: string - example: United Methodist Church - phone: - $ref: '#/components/schemas/MetaPhone' - schedule: - $ref: '#/components/schemas/ScheduleObj' - services: - $ref: '#/components/schemas/MetaServicesArr' - streetViewImage: - $ref: '#/components/schemas/MetaStreetViewImage' - website: - type: string - deleted: - type: boolean - default: false - createdAt: - $ref: '#/components/schemas/MetaDateTime' - lastModifiedAt: - $ref: '#/components/schemas/MetaDateTime' - ResourceDataLatLon: - allOf: - - $ref: '#/components/schemas/ResourceData' - - $ref: '#/components/schemas/MetaLatLonObj' - ResourceSubcategory: - allOf: - - $ref: '#/components/schemas/CategoryDataNoColor' - - type: object - properties: - parentCategory: - $ref: '#/components/schemas/CategoryData' + $ref: '#/components/schemas/MetaWebsite' SlackBotResponse: type: object properties: @@ -1483,46 +1394,64 @@ components: type: string enum: - in_channel - SubCategoryData: + Subcategory: + type: object + properties: + _id: + $ref: '#/components/schemas/Meta_id' + name: + type: string + example: 'Food Pantries' + stub: + type: string + example: 'food_pantries' + parentCategory: + allOf: + - $ref: '#/components/schemas/CategoryData' + - type: object + properties: + subcategories: + type: array + items: + $ref: '#/components/schemas/Meta_id' + createdAt: + $ref: '#/components/schemas/MetaDateTime' + lastModifiedAt: + $ref: '#/components/schemas/MetaDateTime' + __v: + type: integer + SubCategoryWithResources: allOf: - - $ref: '#/components/schemas/CategoryData' + - $ref: '#/components/schemas/Subcategory' - type: object properties: resources: type: array items: - $ref: '#/components/schemas/ResourceCategoryData' + $ref: '#/components/schemas/Resource' StartTimeObj: type: object properties: start: type: string format: date-time - UserObj: - type: object - properties: - _id: - $ref: '#/components/schemas/Meta_id' - email: - type: string - example: 'dev.upswyng@gmail.com' - isAdmin: - type: boolean - default: false - isSuperAdmin: - type: boolean - default: false - name: - type: string - example: "Jacob Venable" - providers: - type: array - items: - type: string - enum: - - facebook - - google - - slack + # Document Types + CategoryDocument: + allOf: + - $ref: '#/components/schemas/CategoryData' + - type: object + properties: + subcategories: + type: array + items: + allOf: + - $ref: '#/components/schemas/CategoryData' + - type: object + properties: + resources: + type: array + items: + $ref: '#/components/schemas/Meta_id' # Post Request Bodies AddResourceSubCategoryPost: type: object @@ -1627,9 +1556,9 @@ components: - website properties: address: - $ref: '#/components/schemas/AddressObj' + $ref: '#/components/schemas/MetaAddress' description: - type: string + $ref: '#/components/schemas/MetaDescription' latitude: type: number nullable: true @@ -1645,7 +1574,7 @@ components: resourceId: $ref: '#/components/schemas/Meta_id' schedule: - $ref: '#/components/schemas/ScheduleObj' + $ref: '#/components/schemas/MetaSchedule' services: $ref: '#/components/schemas/MetaServicesArr' streetViewImage: @@ -1655,7 +1584,7 @@ components: items: $ref: '#/components/schemas/Meta_id' website: - type: string + $ref: '#/components/schemas/MetaWebsite' UserUpdatePost: type: object properties: @@ -1664,7 +1593,18 @@ components: isSuperAdmin: type: boolean # Common - AddressObj: + ErrorObj: + type: object + properties: + message: + type: string + description: Description of error. + example: 'Error description' + # Meta + Meta_id: + type: string + example: 5d8f030ac0e6672699a500c2 + MetaAddress: type: object properties: address1: @@ -1679,78 +1619,76 @@ components: zip: type: integer example: 80301 - ErrorObj: + MetaCount: + type: integer + default: 0 + example: 29 + MetaCreatedBy: + description: 'User object that only appears for admin users, otherwise field will be omitted.' type: object properties: - message: + _id: + $ref: '#/components/schemas/Meta_id' + email: type: string - description: Description of error. - example: 'Error description' - ScheduleObj: - type: object - properties: - alwaysOpen: + example: 'dev.upswyng@gmail.com' + isAdmin: type: boolean - timezone: - $ref: '#/components/schemas/MetaTimeZone' - _items: + default: false + isSuperAdmin: + type: boolean + default: false + name: + type: string + example: "Jacob Venable" + providers: type: array items: - type: object - properties: - comment: - type: string - fromTime: - type: integer - recurrenceRule: - type: string - example: 'RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=WE' - toTime: - type: integer - # Meta - Meta_id: - type: string - example: 5d8f030ac0e6672699a500c2 + type: string + enum: + - facebook + - google + - slack MetaDateTime: type: string format: date-time example: '2019-09-28T06:51:53.633Z' + MetaDeleted: + type: boolean + description: "We leave entries in the DB so they don't get resynced from Strapped, but for all intents & purposes this resource doesn't exist." + default: false + MetaDescription: + type: string + example: 'Weekly groceries for families whose children are enrolled in the free or reduced lunch program at their school.' + MetaEventKind: + type: string + enum: + - alert_live + - draft_approved + - draft_created + - draft_deleted + - resource_issue_reopened + - resource_issue_resolved + - user_permission_changed + MetaEventKindUserReport: + type: string + default: 'user_report' + example: 'user_report' + enum: + - 'user_report' MetaLatitude: type: number + nullable: true + default: null example: 40.0584971 MetaLongitude: type: number + nullable: true + default: null example: -105.11954379999997 - MetaLatLonObj: - type: object - properties: - latitude: - $ref: '#/components/schemas/MetaLatitude' - longitude: - $ref: '#/components/schemas/MetaLongitude' - MetaLegacyIdObj: - type: object - properties: - legacyId: - type: string - example: -KZnRX-8rV1552vd0P7_ - MetaLocation: - type: object - properties: - coordinates: - description: Latitude & Longitude - type: array - items: - type: number - example: [-105.13494760000003, 39.9776081] - type: - type: string - example: Point - MetaLocationObj: - type: object - properties: - location: - $ref: '#/components/schemas/MetaLocation' + MetaLegacyId: + type: string + example: -KZnRX-8rV1552vd0P7_ MetaPhone: type: string example: (303) 555-0112 @@ -1758,7 +1696,7 @@ components: type: array items: allOf: - - $ref: '#/components/schemas/ResourceDataLatLon' + - $ref: '#/components/schemas/Resource' - type: object properties: subcategories: @@ -1768,6 +1706,27 @@ components: properties: parentCategory: $ref: '#/components/schemas/CategoryData' + MetaSchedule: + type: object + properties: + alwaysOpen: + type: boolean + timezone: + $ref: '#/components/schemas/MetaTimeZone' + _items: + type: array + items: + type: object + properties: + comment: + type: string + fromTime: + type: integer + recurrenceRule: + type: string + example: 'RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=WE' + toTime: + type: integer MetaServicesArr: type: array items: @@ -1781,9 +1740,35 @@ components: MetaStreetViewImage: type: string example: 'http://media.upswyng.org/images/5def5cbab831a048f2a3df03.jpg' + nullable: true MetaTimeZone: type: string example: 'America/Denver' + MetaUser: + type: object + properties: + _id: + $ref: '#/components/schemas/Meta_id' + email: + type: string + example: 'dev.upswyng@gmail.com' + isAdmin: + type: boolean + default: false + isSuperAdmin: + type: boolean + default: false + name: + type: string + example: "Jacob Venable" + providers: + type: array + items: + type: string + enum: + - facebook + - google + - slack MetaWebsite: type: string example: 'https://www.upswyng.org/' @@ -1907,12 +1892,6 @@ components: application/json: schema: $ref: '#/components/schemas/ErrorObj' -# Redirect: -# description: Actual response is a Header with `Location` set as a string. OpenAPI doesn't support that type of response yet. -# content: -# application/json: -# schema: -# type: object SlackBotResponse: description: Slack Response. content: @@ -1941,7 +1920,11 @@ tags: - name: bot description: 'Endpoints for slack bot to interact with.' - name: category - description: 'Category & SubCategory related.' + description: 'Categories' + - name: sub-category + description: 'SubCategories' + - name: eventlogs + description: 'Event logs' - name: hotlines description: 'Hotlines' - name: resource diff --git a/packages/server/src/models/Resource.ts b/packages/server/src/models/Resource.ts index 0cdc447f..20e7e1d7 100644 --- a/packages/server/src/models/Resource.ts +++ b/packages/server/src/models/Resource.ts @@ -4,7 +4,6 @@ import { TLegacyResource, TResource, TResourceScheduleData, - TSubcategory, } from "@upswyng/types"; import { TSubcategoryDocument, @@ -49,7 +48,7 @@ export interface TResourceDocument extends Document { /** * Convert a resource document from the database into our `TResource` type. - * Explicity enumerate keys so we make TypeScript happy. + * Explicitly enumerate keys so we make TypeScript happy. */ export const resourceDocumentToResource = async ( r: TResourceDocument diff --git a/packages/server/src/routes/api/resource.ts b/packages/server/src/routes/api/resource.ts index 9e1d82c7..04278db6 100644 --- a/packages/server/src/routes/api/resource.ts +++ b/packages/server/src/routes/api/resource.ts @@ -29,8 +29,6 @@ export async function post(req, res, next) { return; } - console.log(`\n user:\n\n\n\t${JSON.stringify(user)}\n\n`); - try { const { draftResource } = req.body; draftResource.createdBy = user as TUser; From 13778e43055df2bf50d146829db2687507113ffd Mon Sep 17 00:00:00 2001 From: Alvin Mites Date: Wed, 21 Jul 2021 19:46:24 -0600 Subject: [PATCH 11/11] updates from code review --- packages/server/docs/openapi.yaml | 176 +++++++++++++++--------------- 1 file changed, 85 insertions(+), 91 deletions(-) diff --git a/packages/server/docs/openapi.yaml b/packages/server/docs/openapi.yaml index 2a84a3af..88632a58 100644 --- a/packages/server/docs/openapi.yaml +++ b/packages/server/docs/openapi.yaml @@ -83,6 +83,8 @@ paths: $ref: '#/components/schemas/AlertData' '404': $ref: '#/components/responses/ErrorNotFound' + '500': + $ref: '#/components/responses/ErrorUnknown' /alert/{id}: parameters: @@ -307,45 +309,45 @@ paths: '500': $ref: '#/components/responses/ErrorUnknown' - /hotlines: - get: - description: 'Get an array of all hotlines.' - summary: 'Get all hotlines.' - tags: - - hotlines - operationId: hotlinesGet - responses: - '200': - description: Categories. - content: - application/json: - schema: - type: object - properties: - hotlines: - type: array - items: - type: object - properties: - _id: - $ref: "#/components/schemas/Meta_id" - chatWebsite: - $ref: '#/components/schemas/MetaWebsite' - description: - type: string - default: 'Description of the hotline' - name: - type: string - default: 'Hotline Name' - phone: - $ref: '#/components/schemas/MetaPhone' - text: - type: string - default: 'Text for the hotline' - website: - $ref: '#/components/schemas/MetaWebsite' - '500': - $ref: '#/components/responses/ErrorUnknown' +# /hotlines: +# get: +# description: 'Get an array of all hotlines.' +# summary: 'Get all hotlines.' +# tags: +# - hotlines +# operationId: hotlinesGet +# responses: +# '200': +# description: Categories. +# content: +# application/json: +# schema: +# type: object +# properties: +# hotlines: +# type: array +# items: +# type: object +# properties: +# _id: +# $ref: "#/components/schemas/Meta_id" +# chatWebsite: +# $ref: '#/components/schemas/MetaWebsite' +# description: +# type: string +# default: 'Description of the hotline' +# name: +# type: string +# default: 'Hotline Name' +# phone: +# $ref: '#/components/schemas/MetaPhone' +# text: +# type: string +# default: 'Text for the hotline' +# website: +# $ref: '#/components/schemas/MetaWebsite' +# '500': +# $ref: '#/components/responses/ErrorUnknown' /provider/logout: get: @@ -368,7 +370,6 @@ paths: - requireLoggedIn: [] tags: - resource - - stub operationId: resourcePost requestBody: description: New Resource Payload. @@ -387,42 +388,8 @@ paths: schema: type: object properties: - count: - type: integer - default: 12 - estimatedTotal: - $ref: '#/components/schemas/MetaCount' - resourceIssues: - type: array - items: - type: object - properties: - _id: - type: string - default: '5f7a462dcd1b786bed19b4cb' - detail: - type: object - properties: - kind: - $ref: '#/components/schemas/MetaEventKindUserReport' - kind: - $ref: '#/components/schemas/MetaEventKindUserReport' - resolved: - type: boolean - default: false - resourceId: - type: string - default: '5def5cb7b831a048f2a3deed' - severity: - type: string - default: 'high' - createdAt: - $ref: '#/components/schemas/MetaDateTime' - lastModifiedAt: - $ref: '#/components/schemas/MetaDateTime' - __v: - type: integer - default: 0 + draftResource: + $ref: '#/components/schemas/ResourceDraft' '401': $ref: '#/components/responses/ErrorAuthentication' '422': @@ -455,14 +422,14 @@ paths: $ref: '#/components/responses/ErrorUnknown' /resources: - parameters: - - $ref: '#/components/parameters/idQueryOptional' get: description: 'Get an array of resources.' summary: 'Get resources.' tags: - resource operationId: resourcesGet + parameters: + - $ref: '#/components/parameters/idQueryMultipleOptional' responses: '200': description: Array of resources. @@ -548,7 +515,7 @@ paths: /resources/drafts: parameters: - - $ref: '#/components/parameters/includeDeletedQueryOptional' + - $ref: '#/components/parameters/includeDeletedDraftsQueryOptional' get: description: 'Get an array of draft resources.' summary: 'Get draft resources.' @@ -572,8 +539,8 @@ paths: /resources/drafts/mine: get: - description: 'Get an array of resources.' - summary: 'Get resources.' + description: 'Get an array of drafts the current user created.' + summary: 'Get draft resources for current user.' tags: - resource operationId: resourcesDraftsMineGet @@ -590,7 +557,7 @@ paths: uncategorizedResources: type: array items: - $ref: '#/components/schemas/Resource' + $ref: '#/components/schemas/ResourceDraft' '401': $ref: '#/components/responses/ErrorAuthentication' '500': @@ -602,6 +569,8 @@ paths: get: description: 'Get an issue by id.' summary: 'Get an issue' + tags: + - issues operationId: resourceIssueGet responses: '200': @@ -656,9 +625,11 @@ paths: post: description: 'Query for an array of issues.' summary: 'Query issues.' + tags: + - issues + operationId: resourcesIssuesPost security: - requireAdmin: [] - operationId: resourcesIssuesPost requestBody: description: Filter which issues to return. content: @@ -731,6 +702,8 @@ paths: post: description: 'Mark an issue resolved' summary: 'Resolve issue' + tags: + - issues operationId: resourcesIssueResolvePost security: - requireAdmin: [] @@ -752,6 +725,8 @@ paths: post: description: 'Mark an issue unresolved' summary: 'Unresolve issue' + tags: + - issues operationId: resourcesIssueUnresolvePost security: - requireAdmin: [] @@ -771,6 +746,8 @@ paths: post: description: 'Report a new issue' summary: 'Report issue' + tags: + - issues operationId: resourcesIssuesUserReportPost requestBody: description: Request body to create new issues. @@ -1217,6 +1194,7 @@ components: default: 0 AlertSearch: allOf: + - $ref: '#/components/schemas/EndTimeObj' - type: object properties: includeCancelled: @@ -1253,6 +1231,12 @@ components: properties: color: type: string + EndTimeObj: + type: object + properties: + end: + type: string + format: date-time ParentCategory: allOf: - $ref: '#/components/schemas/CategoryData' @@ -1385,7 +1369,7 @@ components: properties: text: type: string - example: 'I found you in UpSwyng, but you have to be an administrator to tell me to run this command' + example: 'Tell upswyngbot /COMMAND to run the job' type: $ref: '#/components/schemas/MetaSlackType' type: @@ -1451,7 +1435,7 @@ components: resources: type: array items: - $ref: '#/components/schemas/Meta_id' + $ref: '#/components/schemas/Resource' # Post Request Bodies AddResourceSubCategoryPost: type: object @@ -1640,7 +1624,7 @@ components: default: false name: type: string - example: "Jacob Venable" + example: "Ursella UpSwyng" providers: type: array items: @@ -1760,7 +1744,7 @@ components: default: false name: type: string - example: "Jacob Venable" + example: "Ursella UpSwyng" providers: type: array items: @@ -1816,10 +1800,18 @@ components: schema: type: string example: 5def5cb7b831a048f2a3deed - includeDeletedQueryOptional: + idQueryMultipleOptional: + name: id + in: query + description: 'Single `_id` or multiple comma separated `_id,_id,_id` for one or more entries.' + required: false + schema: + type: string + example: 5def5cb7b831a048f2a3deed + includeDeletedDraftsQueryOptional: name: include-deleted in: query - description: Whether to include deleted + description: Whether to include drafts for resources that are already deleted required: false schema: type: boolean @@ -1925,8 +1917,10 @@ tags: description: 'SubCategories' - name: eventlogs description: 'Event logs' - - name: hotlines - description: 'Hotlines' +# - name: hotlines +# description: 'Hotlines' + - name: issues + description: 'Endpoints for issues reported on resources' - name: resource description: 'Resources' - name: users