1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-01-06 00:07:44 +01:00
unleash.unleash/src/lib/routes/admin-api/addon.ts

232 lines
7.8 KiB
TypeScript
Raw Normal View History

import { Request, Response } from 'express';
import Controller from '../controller';
import { IUnleashConfig, IUnleashServices } from '../../types';
import { Logger } from '../../logger';
import AddonService from '../../services/addon-service';
import { extractUsername } from '../../util/extract-user';
import {
CREATE_ADDON,
DELETE_ADDON,
NONE,
UPDATE_ADDON,
} from '../../types/permissions';
import { IAuthRequest } from '../unleash-types';
import { createRequestSchema } from '../../openapi/util/create-request-schema';
import { createResponseSchema } from '../../openapi/util/create-response-schema';
import { OpenApiService } from '../../services/openapi-service';
import { AddonSchema, addonSchema } from '../../openapi/spec/addon-schema';
import { serializeDates } from '../../types/serialize-dates';
import { AddonsSchema, addonsSchema } from '../../openapi/spec/addons-schema';
OpenAPI: addon operations (#3421) This PR updates the OpenAPI schemas for all the operations tagged with "addons". In doing so, I also uncovered a few bugs and inconsistencies. These have also been fixed. ## Changes I've added inline comments to the changed files to call out anything that I think is worth clarifying specifically. As an overall description, this PR does the following: Splits `addon-schema` into `addon-schema` and `addon-create-update-schema`. The former is used when describing addons that exist within Unleash and contain IDs and `created_at` timestamps. The latter is used when creating or updating addons. Adds examples and descriptions to all relevant schemas (and their dependencies). Updates addons operations descriptions and response codes (including the recently introduced 413 and 415). Fixes a bug where the server would crash if it didn't recognize the addon provider (test added). Fixes a bug where updating an addon wouldn't return anything, even if the API said that it would. (test added) Resolves some inconsistencies in handling of addon description. (tests added) ### Addon descriptions when creating addons, descriptions are optional. The original `addonSchema` said they could be `null | string | undefined`. This caused some inconsistencies in return values. Sometimes they were returned, other times not. I've made it so that `descriptions` are now always returned from the API. If it's not defined or if it's set to `null`, the API will return `description: null`. ### `IAddonDto` `IAddonDto`, the type we used internally to model the incoming addons (for create and update) says that `description` is required. This hasn't been true at least since we introduced OpenAPI schemas. As such, the update and insert methods that the service uses were incompatible with the **actual** data that we require. I've changed the type to reflect reality for now. Assuming the tests pass, this **should** all be good, but I'd like the reviewer(s) to give this a think too. --------- Co-authored-by: Christopher Kolstad <chriswk@getunleash.ai>
2023-04-18 12:50:34 +02:00
import {
emptyResponse,
getStandardResponses,
} from '../../openapi/util/standard-responses';
import { AddonCreateUpdateSchema } from 'lib/openapi/spec/addon-create-update-schema';
type AddonServices = Pick<IUnleashServices, 'addonService' | 'openApiService'>;
const PATH = '/';
class AddonController extends Controller {
private logger: Logger;
private addonService: AddonService;
private openApiService: OpenApiService;
constructor(
config: IUnleashConfig,
{ addonService, openApiService }: AddonServices,
) {
super(config);
this.logger = config.getLogger('/admin-api/addon.ts');
this.addonService = addonService;
this.openApiService = openApiService;
this.route({
method: 'get',
path: '',
permission: NONE,
handler: this.getAddons,
middleware: [
openApiService.validPath({
OpenAPI: addon operations (#3421) This PR updates the OpenAPI schemas for all the operations tagged with "addons". In doing so, I also uncovered a few bugs and inconsistencies. These have also been fixed. ## Changes I've added inline comments to the changed files to call out anything that I think is worth clarifying specifically. As an overall description, this PR does the following: Splits `addon-schema` into `addon-schema` and `addon-create-update-schema`. The former is used when describing addons that exist within Unleash and contain IDs and `created_at` timestamps. The latter is used when creating or updating addons. Adds examples and descriptions to all relevant schemas (and their dependencies). Updates addons operations descriptions and response codes (including the recently introduced 413 and 415). Fixes a bug where the server would crash if it didn't recognize the addon provider (test added). Fixes a bug where updating an addon wouldn't return anything, even if the API said that it would. (test added) Resolves some inconsistencies in handling of addon description. (tests added) ### Addon descriptions when creating addons, descriptions are optional. The original `addonSchema` said they could be `null | string | undefined`. This caused some inconsistencies in return values. Sometimes they were returned, other times not. I've made it so that `descriptions` are now always returned from the API. If it's not defined or if it's set to `null`, the API will return `description: null`. ### `IAddonDto` `IAddonDto`, the type we used internally to model the incoming addons (for create and update) says that `description` is required. This hasn't been true at least since we introduced OpenAPI schemas. As such, the update and insert methods that the service uses were incompatible with the **actual** data that we require. I've changed the type to reflect reality for now. Assuming the tests pass, this **should** all be good, but I'd like the reviewer(s) to give this a think too. --------- Co-authored-by: Christopher Kolstad <chriswk@getunleash.ai>
2023-04-18 12:50:34 +02:00
summary: 'Get all addons and providers',
description:
'Retrieve all addons and providers that are defined on this Unleash instance.',
tags: ['Addons'],
operationId: 'getAddons',
responses: {
OpenAPI: addon operations (#3421) This PR updates the OpenAPI schemas for all the operations tagged with "addons". In doing so, I also uncovered a few bugs and inconsistencies. These have also been fixed. ## Changes I've added inline comments to the changed files to call out anything that I think is worth clarifying specifically. As an overall description, this PR does the following: Splits `addon-schema` into `addon-schema` and `addon-create-update-schema`. The former is used when describing addons that exist within Unleash and contain IDs and `created_at` timestamps. The latter is used when creating or updating addons. Adds examples and descriptions to all relevant schemas (and their dependencies). Updates addons operations descriptions and response codes (including the recently introduced 413 and 415). Fixes a bug where the server would crash if it didn't recognize the addon provider (test added). Fixes a bug where updating an addon wouldn't return anything, even if the API said that it would. (test added) Resolves some inconsistencies in handling of addon description. (tests added) ### Addon descriptions when creating addons, descriptions are optional. The original `addonSchema` said they could be `null | string | undefined`. This caused some inconsistencies in return values. Sometimes they were returned, other times not. I've made it so that `descriptions` are now always returned from the API. If it's not defined or if it's set to `null`, the API will return `description: null`. ### `IAddonDto` `IAddonDto`, the type we used internally to model the incoming addons (for create and update) says that `description` is required. This hasn't been true at least since we introduced OpenAPI schemas. As such, the update and insert methods that the service uses were incompatible with the **actual** data that we require. I've changed the type to reflect reality for now. Assuming the tests pass, this **should** all be good, but I'd like the reviewer(s) to give this a think too. --------- Co-authored-by: Christopher Kolstad <chriswk@getunleash.ai>
2023-04-18 12:50:34 +02:00
...getStandardResponses(401),
200: createResponseSchema('addonsSchema'),
},
}),
],
});
this.route({
method: 'post',
path: '',
handler: this.createAddon,
permission: CREATE_ADDON,
middleware: [
openApiService.validPath({
OpenAPI: addon operations (#3421) This PR updates the OpenAPI schemas for all the operations tagged with "addons". In doing so, I also uncovered a few bugs and inconsistencies. These have also been fixed. ## Changes I've added inline comments to the changed files to call out anything that I think is worth clarifying specifically. As an overall description, this PR does the following: Splits `addon-schema` into `addon-schema` and `addon-create-update-schema`. The former is used when describing addons that exist within Unleash and contain IDs and `created_at` timestamps. The latter is used when creating or updating addons. Adds examples and descriptions to all relevant schemas (and their dependencies). Updates addons operations descriptions and response codes (including the recently introduced 413 and 415). Fixes a bug where the server would crash if it didn't recognize the addon provider (test added). Fixes a bug where updating an addon wouldn't return anything, even if the API said that it would. (test added) Resolves some inconsistencies in handling of addon description. (tests added) ### Addon descriptions when creating addons, descriptions are optional. The original `addonSchema` said they could be `null | string | undefined`. This caused some inconsistencies in return values. Sometimes they were returned, other times not. I've made it so that `descriptions` are now always returned from the API. If it's not defined or if it's set to `null`, the API will return `description: null`. ### `IAddonDto` `IAddonDto`, the type we used internally to model the incoming addons (for create and update) says that `description` is required. This hasn't been true at least since we introduced OpenAPI schemas. As such, the update and insert methods that the service uses were incompatible with the **actual** data that we require. I've changed the type to reflect reality for now. Assuming the tests pass, this **should** all be good, but I'd like the reviewer(s) to give this a think too. --------- Co-authored-by: Christopher Kolstad <chriswk@getunleash.ai>
2023-04-18 12:50:34 +02:00
summary: 'Create a new addon',
description:
'Create an addon instance. The addon must use one of the providers available on this Unleash instance.',
tags: ['Addons'],
operationId: 'createAddon',
OpenAPI: addon operations (#3421) This PR updates the OpenAPI schemas for all the operations tagged with "addons". In doing so, I also uncovered a few bugs and inconsistencies. These have also been fixed. ## Changes I've added inline comments to the changed files to call out anything that I think is worth clarifying specifically. As an overall description, this PR does the following: Splits `addon-schema` into `addon-schema` and `addon-create-update-schema`. The former is used when describing addons that exist within Unleash and contain IDs and `created_at` timestamps. The latter is used when creating or updating addons. Adds examples and descriptions to all relevant schemas (and their dependencies). Updates addons operations descriptions and response codes (including the recently introduced 413 and 415). Fixes a bug where the server would crash if it didn't recognize the addon provider (test added). Fixes a bug where updating an addon wouldn't return anything, even if the API said that it would. (test added) Resolves some inconsistencies in handling of addon description. (tests added) ### Addon descriptions when creating addons, descriptions are optional. The original `addonSchema` said they could be `null | string | undefined`. This caused some inconsistencies in return values. Sometimes they were returned, other times not. I've made it so that `descriptions` are now always returned from the API. If it's not defined or if it's set to `null`, the API will return `description: null`. ### `IAddonDto` `IAddonDto`, the type we used internally to model the incoming addons (for create and update) says that `description` is required. This hasn't been true at least since we introduced OpenAPI schemas. As such, the update and insert methods that the service uses were incompatible with the **actual** data that we require. I've changed the type to reflect reality for now. Assuming the tests pass, this **should** all be good, but I'd like the reviewer(s) to give this a think too. --------- Co-authored-by: Christopher Kolstad <chriswk@getunleash.ai>
2023-04-18 12:50:34 +02:00
requestBody: createRequestSchema('addonCreateUpdateSchema'),
responses: {
200: createResponseSchema('addonSchema'),
...getStandardResponses(400, 401, 403, 413, 415),
},
}),
],
});
this.route({
method: 'get',
path: `${PATH}:id`,
handler: this.getAddon,
permission: NONE,
middleware: [
openApiService.validPath({
OpenAPI: addon operations (#3421) This PR updates the OpenAPI schemas for all the operations tagged with "addons". In doing so, I also uncovered a few bugs and inconsistencies. These have also been fixed. ## Changes I've added inline comments to the changed files to call out anything that I think is worth clarifying specifically. As an overall description, this PR does the following: Splits `addon-schema` into `addon-schema` and `addon-create-update-schema`. The former is used when describing addons that exist within Unleash and contain IDs and `created_at` timestamps. The latter is used when creating or updating addons. Adds examples and descriptions to all relevant schemas (and their dependencies). Updates addons operations descriptions and response codes (including the recently introduced 413 and 415). Fixes a bug where the server would crash if it didn't recognize the addon provider (test added). Fixes a bug where updating an addon wouldn't return anything, even if the API said that it would. (test added) Resolves some inconsistencies in handling of addon description. (tests added) ### Addon descriptions when creating addons, descriptions are optional. The original `addonSchema` said they could be `null | string | undefined`. This caused some inconsistencies in return values. Sometimes they were returned, other times not. I've made it so that `descriptions` are now always returned from the API. If it's not defined or if it's set to `null`, the API will return `description: null`. ### `IAddonDto` `IAddonDto`, the type we used internally to model the incoming addons (for create and update) says that `description` is required. This hasn't been true at least since we introduced OpenAPI schemas. As such, the update and insert methods that the service uses were incompatible with the **actual** data that we require. I've changed the type to reflect reality for now. Assuming the tests pass, this **should** all be good, but I'd like the reviewer(s) to give this a think too. --------- Co-authored-by: Christopher Kolstad <chriswk@getunleash.ai>
2023-04-18 12:50:34 +02:00
summary: 'Get a specific addon',
description:
'Retrieve information about the addon whose ID matches the ID in the request URL.',
tags: ['Addons'],
operationId: 'getAddon',
OpenAPI: addon operations (#3421) This PR updates the OpenAPI schemas for all the operations tagged with "addons". In doing so, I also uncovered a few bugs and inconsistencies. These have also been fixed. ## Changes I've added inline comments to the changed files to call out anything that I think is worth clarifying specifically. As an overall description, this PR does the following: Splits `addon-schema` into `addon-schema` and `addon-create-update-schema`. The former is used when describing addons that exist within Unleash and contain IDs and `created_at` timestamps. The latter is used when creating or updating addons. Adds examples and descriptions to all relevant schemas (and their dependencies). Updates addons operations descriptions and response codes (including the recently introduced 413 and 415). Fixes a bug where the server would crash if it didn't recognize the addon provider (test added). Fixes a bug where updating an addon wouldn't return anything, even if the API said that it would. (test added) Resolves some inconsistencies in handling of addon description. (tests added) ### Addon descriptions when creating addons, descriptions are optional. The original `addonSchema` said they could be `null | string | undefined`. This caused some inconsistencies in return values. Sometimes they were returned, other times not. I've made it so that `descriptions` are now always returned from the API. If it's not defined or if it's set to `null`, the API will return `description: null`. ### `IAddonDto` `IAddonDto`, the type we used internally to model the incoming addons (for create and update) says that `description` is required. This hasn't been true at least since we introduced OpenAPI schemas. As such, the update and insert methods that the service uses were incompatible with the **actual** data that we require. I've changed the type to reflect reality for now. Assuming the tests pass, this **should** all be good, but I'd like the reviewer(s) to give this a think too. --------- Co-authored-by: Christopher Kolstad <chriswk@getunleash.ai>
2023-04-18 12:50:34 +02:00
responses: {
200: createResponseSchema('addonSchema'),
...getStandardResponses(401),
},
}),
],
});
this.route({
method: 'put',
path: `${PATH}:id`,
handler: this.updateAddon,
permission: UPDATE_ADDON,
middleware: [
openApiService.validPath({
OpenAPI: addon operations (#3421) This PR updates the OpenAPI schemas for all the operations tagged with "addons". In doing so, I also uncovered a few bugs and inconsistencies. These have also been fixed. ## Changes I've added inline comments to the changed files to call out anything that I think is worth clarifying specifically. As an overall description, this PR does the following: Splits `addon-schema` into `addon-schema` and `addon-create-update-schema`. The former is used when describing addons that exist within Unleash and contain IDs and `created_at` timestamps. The latter is used when creating or updating addons. Adds examples and descriptions to all relevant schemas (and their dependencies). Updates addons operations descriptions and response codes (including the recently introduced 413 and 415). Fixes a bug where the server would crash if it didn't recognize the addon provider (test added). Fixes a bug where updating an addon wouldn't return anything, even if the API said that it would. (test added) Resolves some inconsistencies in handling of addon description. (tests added) ### Addon descriptions when creating addons, descriptions are optional. The original `addonSchema` said they could be `null | string | undefined`. This caused some inconsistencies in return values. Sometimes they were returned, other times not. I've made it so that `descriptions` are now always returned from the API. If it's not defined or if it's set to `null`, the API will return `description: null`. ### `IAddonDto` `IAddonDto`, the type we used internally to model the incoming addons (for create and update) says that `description` is required. This hasn't been true at least since we introduced OpenAPI schemas. As such, the update and insert methods that the service uses were incompatible with the **actual** data that we require. I've changed the type to reflect reality for now. Assuming the tests pass, this **should** all be good, but I'd like the reviewer(s) to give this a think too. --------- Co-authored-by: Christopher Kolstad <chriswk@getunleash.ai>
2023-04-18 12:50:34 +02:00
summary: 'Update an addon',
description: `Update the addon with a specific ID. Any fields in the update object will be updated. Properties that are not included in the update object will not be affected. To empty a property, pass \`null\` as that property's value.
Note: passing \`null\` as a value for the description property will set it to an empty string.`,
tags: ['Addons'],
operationId: 'updateAddon',
OpenAPI: addon operations (#3421) This PR updates the OpenAPI schemas for all the operations tagged with "addons". In doing so, I also uncovered a few bugs and inconsistencies. These have also been fixed. ## Changes I've added inline comments to the changed files to call out anything that I think is worth clarifying specifically. As an overall description, this PR does the following: Splits `addon-schema` into `addon-schema` and `addon-create-update-schema`. The former is used when describing addons that exist within Unleash and contain IDs and `created_at` timestamps. The latter is used when creating or updating addons. Adds examples and descriptions to all relevant schemas (and their dependencies). Updates addons operations descriptions and response codes (including the recently introduced 413 and 415). Fixes a bug where the server would crash if it didn't recognize the addon provider (test added). Fixes a bug where updating an addon wouldn't return anything, even if the API said that it would. (test added) Resolves some inconsistencies in handling of addon description. (tests added) ### Addon descriptions when creating addons, descriptions are optional. The original `addonSchema` said they could be `null | string | undefined`. This caused some inconsistencies in return values. Sometimes they were returned, other times not. I've made it so that `descriptions` are now always returned from the API. If it's not defined or if it's set to `null`, the API will return `description: null`. ### `IAddonDto` `IAddonDto`, the type we used internally to model the incoming addons (for create and update) says that `description` is required. This hasn't been true at least since we introduced OpenAPI schemas. As such, the update and insert methods that the service uses were incompatible with the **actual** data that we require. I've changed the type to reflect reality for now. Assuming the tests pass, this **should** all be good, but I'd like the reviewer(s) to give this a think too. --------- Co-authored-by: Christopher Kolstad <chriswk@getunleash.ai>
2023-04-18 12:50:34 +02:00
requestBody: createRequestSchema('addonCreateUpdateSchema'),
responses: {
200: createResponseSchema('addonSchema'),
feat: unify error responses (#3607) This PR implements the first version of a suggested unification (and documentation) of the errors that we return from the API today. The goal is for this to be the first step towards the error type defined in this internal [linear task](https://linear.app/unleash/issue/1-629/define-the-error-type 'Define the new API error type'). ## The state of things today As things stand, we currently have no (or **very** little) documentation of the errors that are returned from the API. We mention error codes, but never what the errors may contain. Second, there is no specified format for errors, so what they return is arbitrary, and based on ... Who knows? As a result, we have multiple different errors returned by the API depending on what operation you're trying to do. What's more, with OpenAPI validation in the mix, it's absolutely possible for you to get two completely different error objects for operations to the same endpoint. Third, the errors we do return are usually pretty vague and don't really provide any real help to the user. "You don't have the right permissions". Great. Well what permissions do I need? And how would I know? "BadDataError". Sick. Why is it bad? ... You get it. ## What we want to achieve The ultimate goal is for error messages to serve both humans and machines. When the user provides bad data, we should tell them what parts of the data are bad and what they can do to fix it. When they don't have the right permissions, we should tell them what permissions they need. Additionally, it would be nice if we could provide an ID for each error instance, so that you (or an admin) can look through the logs and locate he incident. ## What's included in **this** PR? This PR does not aim to implement everything above. It's not intended to magically fix everything. Its goal is to implement the necessary **breaking** changes, so that they can be included in v5. Changing error messages is a slightly grayer area than changing APIs directly, but changing the format is definitely something I'd consider breaking. So this PR: - defines a minimal version of the error type defined in the [API error definition linear task](https://linear.app/unleash/issue/1-629/define-the-error-type). - aims to catch all errors we return today and wrap them in the error type - updates tests to match the new expectations. An important point: because we are cutting v5 very soon and because work for this wasn't started until last week, the code here isn't necessarily very polished. But it doesn't need to be. The internals can be as messy as we want, as long as the API surface is stable. That said, I'm very open to feedback about design and code completeness, etc, but this has intentionally been done quickly. Please also see my inline comments on the changes for more specific details. ### Proposed follow-ups As mentioned, this is the first step to implementing the error type. The public API error type only exposes `id`, `name`, and `message`. This is barely any more than most of the previous messages, but they are now all using the same format. Any additional properties, such as `suggestion`, `help`, `documentationLink` etc can be added as features without breaking the current format. This is an intentional limitation of this PR. Regarding additional properties: there are some error responses that must contain extra properties. Some of these are documented in the types of the new error constructor, but not all. This includes `path` and `type` properties on 401 errors, `details` on validation errors, and more. Also, because it was put together quickly, I don't yet know exactly how we (as developers) would **prefer** to use these new error messages within the code, so the internal API (the new type, name, etc), is just a suggestion. This can evolve naturally over time if (based on feedback and experience) without changing the public API. ## Returning multiple errors Most of the time when we return errors today, we only return a single error (even if many things are wrong). AJV, the OpenAPI integration we use does have a setting that allows it to return all errors in a request instead of a single one. I suggest we turn that on, but that we do it in a separate PR (because it updates a number of other snapshots). When returning errors that point to `details`, the objects in the `details` now contain a new `description` property. This "deprecates" the `message` property. Due to our general deprecation policy, this should be kept around for another full major and can be removed in v6. ```json { "name": "BadDataError", "message": "Something went wrong. Check the `details` property for more information." "details": [{ "message": "The .params property must be an object. You provided an array.", "description": "The .params property must be an object. You provided an array.", }] } ```
2023-04-25 15:40:46 +02:00
...getStandardResponses(400, 401, 403, 404, 413, 415),
OpenAPI: addon operations (#3421) This PR updates the OpenAPI schemas for all the operations tagged with "addons". In doing so, I also uncovered a few bugs and inconsistencies. These have also been fixed. ## Changes I've added inline comments to the changed files to call out anything that I think is worth clarifying specifically. As an overall description, this PR does the following: Splits `addon-schema` into `addon-schema` and `addon-create-update-schema`. The former is used when describing addons that exist within Unleash and contain IDs and `created_at` timestamps. The latter is used when creating or updating addons. Adds examples and descriptions to all relevant schemas (and their dependencies). Updates addons operations descriptions and response codes (including the recently introduced 413 and 415). Fixes a bug where the server would crash if it didn't recognize the addon provider (test added). Fixes a bug where updating an addon wouldn't return anything, even if the API said that it would. (test added) Resolves some inconsistencies in handling of addon description. (tests added) ### Addon descriptions when creating addons, descriptions are optional. The original `addonSchema` said they could be `null | string | undefined`. This caused some inconsistencies in return values. Sometimes they were returned, other times not. I've made it so that `descriptions` are now always returned from the API. If it's not defined or if it's set to `null`, the API will return `description: null`. ### `IAddonDto` `IAddonDto`, the type we used internally to model the incoming addons (for create and update) says that `description` is required. This hasn't been true at least since we introduced OpenAPI schemas. As such, the update and insert methods that the service uses were incompatible with the **actual** data that we require. I've changed the type to reflect reality for now. Assuming the tests pass, this **should** all be good, but I'd like the reviewer(s) to give this a think too. --------- Co-authored-by: Christopher Kolstad <chriswk@getunleash.ai>
2023-04-18 12:50:34 +02:00
},
}),
],
});
this.route({
method: 'delete',
path: `${PATH}:id`,
handler: this.deleteAddon,
acceptAnyContentType: true,
permission: DELETE_ADDON,
middleware: [
openApiService.validPath({
OpenAPI: addon operations (#3421) This PR updates the OpenAPI schemas for all the operations tagged with "addons". In doing so, I also uncovered a few bugs and inconsistencies. These have also been fixed. ## Changes I've added inline comments to the changed files to call out anything that I think is worth clarifying specifically. As an overall description, this PR does the following: Splits `addon-schema` into `addon-schema` and `addon-create-update-schema`. The former is used when describing addons that exist within Unleash and contain IDs and `created_at` timestamps. The latter is used when creating or updating addons. Adds examples and descriptions to all relevant schemas (and their dependencies). Updates addons operations descriptions and response codes (including the recently introduced 413 and 415). Fixes a bug where the server would crash if it didn't recognize the addon provider (test added). Fixes a bug where updating an addon wouldn't return anything, even if the API said that it would. (test added) Resolves some inconsistencies in handling of addon description. (tests added) ### Addon descriptions when creating addons, descriptions are optional. The original `addonSchema` said they could be `null | string | undefined`. This caused some inconsistencies in return values. Sometimes they were returned, other times not. I've made it so that `descriptions` are now always returned from the API. If it's not defined or if it's set to `null`, the API will return `description: null`. ### `IAddonDto` `IAddonDto`, the type we used internally to model the incoming addons (for create and update) says that `description` is required. This hasn't been true at least since we introduced OpenAPI schemas. As such, the update and insert methods that the service uses were incompatible with the **actual** data that we require. I've changed the type to reflect reality for now. Assuming the tests pass, this **should** all be good, but I'd like the reviewer(s) to give this a think too. --------- Co-authored-by: Christopher Kolstad <chriswk@getunleash.ai>
2023-04-18 12:50:34 +02:00
summary: 'Delete an addon',
description:
'Delete the addon specified by the ID in the request path.',
tags: ['Addons'],
operationId: 'deleteAddon',
OpenAPI: addon operations (#3421) This PR updates the OpenAPI schemas for all the operations tagged with "addons". In doing so, I also uncovered a few bugs and inconsistencies. These have also been fixed. ## Changes I've added inline comments to the changed files to call out anything that I think is worth clarifying specifically. As an overall description, this PR does the following: Splits `addon-schema` into `addon-schema` and `addon-create-update-schema`. The former is used when describing addons that exist within Unleash and contain IDs and `created_at` timestamps. The latter is used when creating or updating addons. Adds examples and descriptions to all relevant schemas (and their dependencies). Updates addons operations descriptions and response codes (including the recently introduced 413 and 415). Fixes a bug where the server would crash if it didn't recognize the addon provider (test added). Fixes a bug where updating an addon wouldn't return anything, even if the API said that it would. (test added) Resolves some inconsistencies in handling of addon description. (tests added) ### Addon descriptions when creating addons, descriptions are optional. The original `addonSchema` said they could be `null | string | undefined`. This caused some inconsistencies in return values. Sometimes they were returned, other times not. I've made it so that `descriptions` are now always returned from the API. If it's not defined or if it's set to `null`, the API will return `description: null`. ### `IAddonDto` `IAddonDto`, the type we used internally to model the incoming addons (for create and update) says that `description` is required. This hasn't been true at least since we introduced OpenAPI schemas. As such, the update and insert methods that the service uses were incompatible with the **actual** data that we require. I've changed the type to reflect reality for now. Assuming the tests pass, this **should** all be good, but I'd like the reviewer(s) to give this a think too. --------- Co-authored-by: Christopher Kolstad <chriswk@getunleash.ai>
2023-04-18 12:50:34 +02:00
responses: {
200: emptyResponse,
feat: unify error responses (#3607) This PR implements the first version of a suggested unification (and documentation) of the errors that we return from the API today. The goal is for this to be the first step towards the error type defined in this internal [linear task](https://linear.app/unleash/issue/1-629/define-the-error-type 'Define the new API error type'). ## The state of things today As things stand, we currently have no (or **very** little) documentation of the errors that are returned from the API. We mention error codes, but never what the errors may contain. Second, there is no specified format for errors, so what they return is arbitrary, and based on ... Who knows? As a result, we have multiple different errors returned by the API depending on what operation you're trying to do. What's more, with OpenAPI validation in the mix, it's absolutely possible for you to get two completely different error objects for operations to the same endpoint. Third, the errors we do return are usually pretty vague and don't really provide any real help to the user. "You don't have the right permissions". Great. Well what permissions do I need? And how would I know? "BadDataError". Sick. Why is it bad? ... You get it. ## What we want to achieve The ultimate goal is for error messages to serve both humans and machines. When the user provides bad data, we should tell them what parts of the data are bad and what they can do to fix it. When they don't have the right permissions, we should tell them what permissions they need. Additionally, it would be nice if we could provide an ID for each error instance, so that you (or an admin) can look through the logs and locate he incident. ## What's included in **this** PR? This PR does not aim to implement everything above. It's not intended to magically fix everything. Its goal is to implement the necessary **breaking** changes, so that they can be included in v5. Changing error messages is a slightly grayer area than changing APIs directly, but changing the format is definitely something I'd consider breaking. So this PR: - defines a minimal version of the error type defined in the [API error definition linear task](https://linear.app/unleash/issue/1-629/define-the-error-type). - aims to catch all errors we return today and wrap them in the error type - updates tests to match the new expectations. An important point: because we are cutting v5 very soon and because work for this wasn't started until last week, the code here isn't necessarily very polished. But it doesn't need to be. The internals can be as messy as we want, as long as the API surface is stable. That said, I'm very open to feedback about design and code completeness, etc, but this has intentionally been done quickly. Please also see my inline comments on the changes for more specific details. ### Proposed follow-ups As mentioned, this is the first step to implementing the error type. The public API error type only exposes `id`, `name`, and `message`. This is barely any more than most of the previous messages, but they are now all using the same format. Any additional properties, such as `suggestion`, `help`, `documentationLink` etc can be added as features without breaking the current format. This is an intentional limitation of this PR. Regarding additional properties: there are some error responses that must contain extra properties. Some of these are documented in the types of the new error constructor, but not all. This includes `path` and `type` properties on 401 errors, `details` on validation errors, and more. Also, because it was put together quickly, I don't yet know exactly how we (as developers) would **prefer** to use these new error messages within the code, so the internal API (the new type, name, etc), is just a suggestion. This can evolve naturally over time if (based on feedback and experience) without changing the public API. ## Returning multiple errors Most of the time when we return errors today, we only return a single error (even if many things are wrong). AJV, the OpenAPI integration we use does have a setting that allows it to return all errors in a request instead of a single one. I suggest we turn that on, but that we do it in a separate PR (because it updates a number of other snapshots). When returning errors that point to `details`, the objects in the `details` now contain a new `description` property. This "deprecates" the `message` property. Due to our general deprecation policy, this should be kept around for another full major and can be removed in v6. ```json { "name": "BadDataError", "message": "Something went wrong. Check the `details` property for more information." "details": [{ "message": "The .params property must be an object. You provided an array.", "description": "The .params property must be an object. You provided an array.", }] } ```
2023-04-25 15:40:46 +02:00
...getStandardResponses(401, 403, 404),
OpenAPI: addon operations (#3421) This PR updates the OpenAPI schemas for all the operations tagged with "addons". In doing so, I also uncovered a few bugs and inconsistencies. These have also been fixed. ## Changes I've added inline comments to the changed files to call out anything that I think is worth clarifying specifically. As an overall description, this PR does the following: Splits `addon-schema` into `addon-schema` and `addon-create-update-schema`. The former is used when describing addons that exist within Unleash and contain IDs and `created_at` timestamps. The latter is used when creating or updating addons. Adds examples and descriptions to all relevant schemas (and their dependencies). Updates addons operations descriptions and response codes (including the recently introduced 413 and 415). Fixes a bug where the server would crash if it didn't recognize the addon provider (test added). Fixes a bug where updating an addon wouldn't return anything, even if the API said that it would. (test added) Resolves some inconsistencies in handling of addon description. (tests added) ### Addon descriptions when creating addons, descriptions are optional. The original `addonSchema` said they could be `null | string | undefined`. This caused some inconsistencies in return values. Sometimes they were returned, other times not. I've made it so that `descriptions` are now always returned from the API. If it's not defined or if it's set to `null`, the API will return `description: null`. ### `IAddonDto` `IAddonDto`, the type we used internally to model the incoming addons (for create and update) says that `description` is required. This hasn't been true at least since we introduced OpenAPI schemas. As such, the update and insert methods that the service uses were incompatible with the **actual** data that we require. I've changed the type to reflect reality for now. Assuming the tests pass, this **should** all be good, but I'd like the reviewer(s) to give this a think too. --------- Co-authored-by: Christopher Kolstad <chriswk@getunleash.ai>
2023-04-18 12:50:34 +02:00
},
}),
],
});
}
async getAddons(req: Request, res: Response<AddonsSchema>): Promise<void> {
const addons = await this.addonService.getAddons();
const providers = this.addonService.getProviderDefinitions();
this.openApiService.respondWithValidation(200, res, addonsSchema.$id, {
addons: serializeDates(addons),
providers: serializeDates(providers),
});
}
async getAddon(
req: Request<{ id: number }, any, any, any>,
res: Response<AddonSchema>,
): Promise<void> {
const { id } = req.params;
const addon = await this.addonService.getAddon(id);
this.openApiService.respondWithValidation(
200,
res,
addonSchema.$id,
serializeDates(addon),
);
}
async updateAddon(
OpenAPI: addon operations (#3421) This PR updates the OpenAPI schemas for all the operations tagged with "addons". In doing so, I also uncovered a few bugs and inconsistencies. These have also been fixed. ## Changes I've added inline comments to the changed files to call out anything that I think is worth clarifying specifically. As an overall description, this PR does the following: Splits `addon-schema` into `addon-schema` and `addon-create-update-schema`. The former is used when describing addons that exist within Unleash and contain IDs and `created_at` timestamps. The latter is used when creating or updating addons. Adds examples and descriptions to all relevant schemas (and their dependencies). Updates addons operations descriptions and response codes (including the recently introduced 413 and 415). Fixes a bug where the server would crash if it didn't recognize the addon provider (test added). Fixes a bug where updating an addon wouldn't return anything, even if the API said that it would. (test added) Resolves some inconsistencies in handling of addon description. (tests added) ### Addon descriptions when creating addons, descriptions are optional. The original `addonSchema` said they could be `null | string | undefined`. This caused some inconsistencies in return values. Sometimes they were returned, other times not. I've made it so that `descriptions` are now always returned from the API. If it's not defined or if it's set to `null`, the API will return `description: null`. ### `IAddonDto` `IAddonDto`, the type we used internally to model the incoming addons (for create and update) says that `description` is required. This hasn't been true at least since we introduced OpenAPI schemas. As such, the update and insert methods that the service uses were incompatible with the **actual** data that we require. I've changed the type to reflect reality for now. Assuming the tests pass, this **should** all be good, but I'd like the reviewer(s) to give this a think too. --------- Co-authored-by: Christopher Kolstad <chriswk@getunleash.ai>
2023-04-18 12:50:34 +02:00
req: IAuthRequest<{ id: number }, any, AddonCreateUpdateSchema, any>,
res: Response<AddonSchema>,
): Promise<void> {
const { id } = req.params;
const createdBy = extractUsername(req);
const data = req.body;
const addon = await this.addonService.updateAddon(
id,
data,
createdBy,
req.user.id,
);
this.openApiService.respondWithValidation(
200,
res,
addonSchema.$id,
serializeDates(addon),
);
}
async createAddon(
OpenAPI: addon operations (#3421) This PR updates the OpenAPI schemas for all the operations tagged with "addons". In doing so, I also uncovered a few bugs and inconsistencies. These have also been fixed. ## Changes I've added inline comments to the changed files to call out anything that I think is worth clarifying specifically. As an overall description, this PR does the following: Splits `addon-schema` into `addon-schema` and `addon-create-update-schema`. The former is used when describing addons that exist within Unleash and contain IDs and `created_at` timestamps. The latter is used when creating or updating addons. Adds examples and descriptions to all relevant schemas (and their dependencies). Updates addons operations descriptions and response codes (including the recently introduced 413 and 415). Fixes a bug where the server would crash if it didn't recognize the addon provider (test added). Fixes a bug where updating an addon wouldn't return anything, even if the API said that it would. (test added) Resolves some inconsistencies in handling of addon description. (tests added) ### Addon descriptions when creating addons, descriptions are optional. The original `addonSchema` said they could be `null | string | undefined`. This caused some inconsistencies in return values. Sometimes they were returned, other times not. I've made it so that `descriptions` are now always returned from the API. If it's not defined or if it's set to `null`, the API will return `description: null`. ### `IAddonDto` `IAddonDto`, the type we used internally to model the incoming addons (for create and update) says that `description` is required. This hasn't been true at least since we introduced OpenAPI schemas. As such, the update and insert methods that the service uses were incompatible with the **actual** data that we require. I've changed the type to reflect reality for now. Assuming the tests pass, this **should** all be good, but I'd like the reviewer(s) to give this a think too. --------- Co-authored-by: Christopher Kolstad <chriswk@getunleash.ai>
2023-04-18 12:50:34 +02:00
req: IAuthRequest<AddonCreateUpdateSchema, any, any, any>,
res: Response<AddonSchema>,
): Promise<void> {
const createdBy = extractUsername(req);
const data = req.body;
const addon = await this.addonService.createAddon(
data,
createdBy,
req.user.id,
);
this.openApiService.respondWithValidation(
201,
res,
addonSchema.$id,
serializeDates(addon),
);
}
async deleteAddon(
req: IAuthRequest<{ id: number }, any, any, any>,
res: Response<void>,
): Promise<void> {
const { id } = req.params;
const username = extractUsername(req);
await this.addonService.removeAddon(id, username, req.user.id);
res.status(200).end();
}
}
export default AddonController;
module.exports = AddonController;