Skip to content

Commit

Permalink
chore(rest-api): extracted duplicate code
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexanderSkrock committed Jul 11, 2024
1 parent b42b898 commit 3359aad
Show file tree
Hide file tree
Showing 9 changed files with 220 additions and 318 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ import { omit } from 'min-dash';

import classNames from 'classnames';

import { default as CamundaAPI, ApiErrors, ConnectionError, DeploymentError } from '../shared/CamundaAPI';
import { default as CamundaAPI, DeploymentError } from '../shared/CamundaAPI';
import { ConnectionError, GenericApiErrors } from '../shared/RestAPI';
import AUTH_TYPES from '../shared/AuthTypes';

import CockpitDeploymentLink from '../shared/ui/CockpitDeploymentLink';
Expand Down Expand Up @@ -541,9 +542,9 @@ export default class DeploymentTool extends PureComponent {

const { code } = result;

return (code !== ApiErrors.NO_INTERNET_CONNECTION &&
code !== ApiErrors.CONNECTION_FAILED &&
code !== ApiErrors.NOT_FOUND);
return (code !== GenericApiErrors.NO_INTERNET_CONNECTION &&
code !== GenericApiErrors.CONNECTION_FAILED &&
code !== GenericApiErrors.NOT_FOUND);
}

closeOverlay(overlayState) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ import { Config } from './../../../../app/__tests__/mocks';

import DeploymentTool from '../DeploymentTool';
import AUTH_TYPES from '../../shared/AuthTypes';
import { DeploymentError,
ConnectionError } from '../../shared/CamundaAPI';
import { DeploymentError } from '../../shared/CamundaAPI';
import { ConnectionError } from '../../shared/RestAPI';
import { Slot, SlotFillRoot } from '../../../../app/slot-fill';

const CONFIG_KEY = 'deployment-tool';
Expand Down
191 changes: 20 additions & 171 deletions client/src/plugins/camunda-plugin/shared/CamundaAPI.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,12 @@

import AUTH_TYPES from './AuthTypes';

import debug from 'debug';
import RestAPI, { ConnectionError, GenericApiErrorMessages, getNetworkErrorCode, getResponseErrorCode } from './RestAPI';

const FETCH_TIMEOUT = 5000;

const log = debug('CamundaAPI');


export default class CamundaAPI {
export default class CamundaAPI extends RestAPI {

constructor(endpoint) {

this.baseUrl = normalizeBaseURL(endpoint.url);

this.authentication = this.getAuthentication(endpoint);
super('CamundaAPI', normalizeBaseURL(endpoint.url), getAuthentication(endpoint));
}

async deployDiagram(diagram, deployment) {
Expand Down Expand Up @@ -130,152 +122,40 @@ export default class CamundaAPI {

throw new ConnectionError(response);
}
}

getAuthentication(endpoint) {

const {
authType,
username,
password,
token
} = endpoint;

switch (authType) {
case AUTH_TYPES.BASIC:
return {
username,
password
};
case AUTH_TYPES.BEARER:
return {
token
};
}
}

getHeaders() {
const headers = {
accept: 'application/json'
};

if (this.authentication) {
headers.authorization = this.getAuthHeader(this.authentication);
}

return headers;
}
function getAuthentication(endpoint) {

getAuthHeader(endpoint) {
const {
authType,
username,
password,
token
} = endpoint;

const {
token,
switch (authType) {
case AUTH_TYPES.BASIC:
return {
username,
password
} = endpoint;

if (token) {
return `Bearer ${token}`;
}

if (username && password) {
const credentials = window.btoa(`${username}:${password}`);

return `Basic ${credentials}`;
}
}

async fetch(path, options = {}) {
const url = `${this.baseUrl}${path}`;
const headers = {
...options.headers,
...this.getHeaders()
};

try {
const signal = options.signal || this.setupTimeoutSignal();

return await fetch(url, {
...options,
headers,
signal
});
} catch (error) {
log('failed to fetch', error);

return {
url,
json: () => {
return {};
}
};
}
}

setupTimeoutSignal(timeout = FETCH_TIMEOUT) {
const controller = new AbortController();

setTimeout(() => controller.abort(), timeout);

return controller.signal;
}

async parse(response) {
try {
const json = await response.json();

return json;
} catch (error) {
return {};
}
case AUTH_TYPES.BEARER:
return {
token
};
}
}

const NO_INTERNET_CONNECTION = 'NO_INTERNET_CONNECTION';
const CONNECTION_FAILED = 'CONNECTION_FAILED';
const DIAGRAM_PARSE_ERROR = 'DIAGRAM_PARSE_ERROR';
const UNAUTHORIZED = 'UNAUTHORIZED';
const FORBIDDEN = 'FORBIDDEN';
const NOT_FOUND = 'NOT_FOUND';
const INTERNAL_SERVER_ERROR = 'INTERNAL_SERVER_ERROR';
const UNAVAILABLE_ERROR = 'UNAVAILABLE_ERROR';

export const ApiErrors = {
NO_INTERNET_CONNECTION,
CONNECTION_FAILED,
DIAGRAM_PARSE_ERROR,
UNAUTHORIZED,
FORBIDDEN,
NOT_FOUND,
INTERNAL_SERVER_ERROR,
UNAVAILABLE_ERROR
};

export const ApiErrorMessages = {
[ NO_INTERNET_CONNECTION ]: 'Could not establish a network connection.',
[ CONNECTION_FAILED ]: 'Should point to a running Camunda REST API.',
[ DIAGRAM_PARSE_ERROR ]: 'Server could not parse the diagram. Please check log for errors.',
[ UNAUTHORIZED ]: 'Credentials do not match with the server.',
[ FORBIDDEN ]: 'This user is not permitted to deploy. Please use different credentials or get this user enabled to deploy.',
[ NOT_FOUND ]: 'Should point to a running Camunda REST API.',
[ INTERNAL_SERVER_ERROR ]: 'Camunda is reporting an error. Please check the server status.',
[ UNAVAILABLE_ERROR ]: 'Camunda is reporting an error. Please check the server status.'
};

export class ConnectionError extends Error {

constructor(response) {
super('Connection failed');

this.code = (
getResponseErrorCode(response) ||
getNetworkErrorCode(response)
);

this.details = ApiErrorMessages[this.code];
}
}


export class DeploymentError extends Error {

constructor(response, body) {
Expand All @@ -287,7 +167,7 @@ export class DeploymentError extends Error {
getNetworkErrorCode(response)
);

this.details = ApiErrorMessages[this.code];
this.details = ApiErrorMessages[this.code] || GenericApiErrorMessages[this.code];

this.problems = body && body.message;
}
Expand All @@ -304,7 +184,7 @@ export class StartInstanceError extends Error {
getNetworkErrorCode(response)
);

this.details = ApiErrorMessages[this.code];
this.details = ApiErrorMessages[this.code] || GenericApiErrorMessages[this.code];

this.problems = body && body.message;
}
Expand All @@ -313,29 +193,6 @@ export class StartInstanceError extends Error {

// helpers ///////////////

function getNetworkErrorCode(response) {
if (isLocalhost(response.url) || isOnline()) {
return CONNECTION_FAILED;
}

return NO_INTERNET_CONNECTION;
}

function getResponseErrorCode(response) {
switch (response.status) {
case 401:
return UNAUTHORIZED;
case 403:
return FORBIDDEN;
case 404:
return NOT_FOUND;
case 500:
return INTERNAL_SERVER_ERROR;
case 503:
return UNAVAILABLE_ERROR;
}
}

function getCamundaErrorCode(response, body) {

const PARSE_ERROR_PREFIX = 'ENGINE-09005 Could not parse BPMN process.';
Expand All @@ -345,14 +202,6 @@ function getCamundaErrorCode(response, body) {
}
}

function isLocalhost(url) {
return /^https?:\/\/(127\.0\.0\.1|localhost)/.test(url);
}

function isOnline() {
return window.navigator.onLine;
}

function normalizeBaseURL(url) {
return url.replace(/\/deployment\/create\/?/, '');
}
Loading

0 comments on commit 3359aad

Please sign in to comment.