Merge pull request #1002 from theseyi/urn-to-id

converts a dataset id to urn using urntoid endpoint. refactors a chec…
This commit is contained in:
Seyi Adebajo 2018-02-28 17:05:32 -08:00 committed by GitHub
commit 14a1e4bdea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 33 additions and 96 deletions

View File

@ -11,15 +11,14 @@ import { IDatasetView } from 'wherehows-web/typings/api/datasets/dataset';
import { IDatasetSchema } from 'wherehows-web/typings/api/datasets/schema';
import { IComplianceDataType } from 'wherehows-web/typings/api/list/compliance-datatypes';
import {
ApiResponseStatus,
IReadComplianceResult,
notFoundApiError,
readDatasetComplianceByUrn,
readDatasetComplianceSuggestionByUrn,
saveDatasetComplianceByUrn
} from 'wherehows-web/utils/api';
import { columnDataTypesAndFieldNames } from 'wherehows-web/utils/api/datasets/columns';
import { readDatasetSchemaByUrn } from 'wherehows-web/utils/api/datasets/schema';
import { ApiError } from 'wherehows-web/utils/api/errors/errors';
import { readComplianceDataTypes } from 'wherehows-web/utils/api/list/compliance-datatypes';
import { compliancePolicyStrings, removeReadonlyAttr, filterEditableEntities } from 'wherehows-web/constants';
@ -160,7 +159,7 @@ export default class DatasetComplianceContainer extends Component {
setProperties(this, { schemaFieldNamesMappedToDataTypes, schemaless });
} catch (e) {
// If this schema is missing, silence exception, otherwise propagate
if (!(e instanceof ApiError && e.status === ApiResponseStatus.NotFound)) {
if (!notFoundApiError(e)) {
throw e;
}
}

View File

@ -1,9 +1,9 @@
import Controller from '@ember/controller';
import { computed, set, get, setProperties, getProperties, getWithDefault } from '@ember/object';
import { debug } from '@ember/debug';
import $ from 'jquery';
import { inject as service } from '@ember/service';
import { run, scheduleOnce } from '@ember/runloop';
import $ from 'jquery';
import {
datasetComplianceUrlById,
createDatasetComment,
@ -13,7 +13,6 @@ import {
} from 'wherehows-web/utils/api';
import { encodeUrn } from 'wherehows-web/utils/validators/urn';
import { updateDatasetDeprecation } from 'wherehows-web/utils/api/datasets/properties';
import { readDatasetView } from 'wherehows-web/utils/api/datasets/dataset';
import { readDatasetOwners, updateDatasetOwners } from 'wherehows-web/utils/api/datasets/owners';
import { Tabs } from 'wherehows-web/constants/datasets/shared';
import { action } from 'ember-decorators/object';

View File

@ -3,7 +3,7 @@ import { set, get, setProperties } from '@ember/object';
import { inject } from '@ember/service';
import { makeUrnBreadcrumbs } from 'wherehows-web/utils/entities';
import { isRequiredMinOwnersNotConfirmed } from 'wherehows-web/constants/datasets/owner';
import { readDatasetById, readDatasetByUrn } from 'wherehows-web/utils/api/datasets/dataset';
import { datasetIdToUrn, readDatasetByUrn } from 'wherehows-web/utils/api/datasets/dataset';
import isUrn, { isWhUrn, isLiUrn, convertWhUrnToLiUrn, encodeUrn, decodeUrn } from 'wherehows-web/utils/validators/urn';
import { checkAclAccess } from 'wherehows-web/utils/api/datasets/acl-access';
@ -48,7 +48,8 @@ export default Route.extend({
});
}
return await readDatasetById(identifier);
// recurse with dataset urn from id
return this.model({ dataset_id: await datasetIdToUrn(identifier) });
},
/**

View File

@ -1,6 +1,5 @@
import { assert } from '@ember/debug';
import { ApiResponseStatus } from 'wherehows-web/utils/api';
import { ApiError } from 'wherehows-web/utils/api/errors/errors';
import { notFoundApiError } from 'wherehows-web/utils/api';
import { createInitialComplianceInfo } from 'wherehows-web/utils/datasets/compliance-policy';
import { datasetUrlById, datasetUrlByUrn } from 'wherehows-web/utils/api/datasets/shared';
import { ApiStatus } from 'wherehows-web/utils/api/shared';
@ -98,7 +97,7 @@ const readDatasetComplianceByUrn = async (urn: string): Promise<IReadComplianceR
url: datasetComplianceUrlByUrn(urn)
}));
} catch (e) {
if (e instanceof ApiError && e.status === ApiResponseStatus.NotFound) {
if (notFoundApiError(e)) {
complianceInfo = createInitialComplianceInfo(urn);
isNewComplianceInfo = true;
} else {

View File

@ -1,7 +1,4 @@
import { warn } from '@ember/debug';
import {
IDataset,
IDatasetGetResponse,
IDatasetsGetResponse,
IDatasetView,
IDatasetViewGetResponse,
@ -12,44 +9,10 @@ import {
datasetsCountUrl,
datasetsUrl,
datasetsUrlRoot,
datasetUrlById,
datasetUrlByUrn
} from 'wherehows-web/utils/api/datasets/shared';
import { ApiStatus } from 'wherehows-web/utils/api';
import { encodeUrn } from 'wherehows-web/utils/validators/urn';
// TODO: DSS-6122 Create and move to Error module
const datasetApiException = 'An error occurred with the dataset api';
const datasetIdException = 'Dataset reference in unexpected format. Expected a urn or dataset id.';
/**
* Constructs the dataset view endpoint url from the dataset id
* @param {number} id the dataset id
*/
const datasetViewUrlById = (id: number) => `${datasetUrlById(id)}/view`;
/**
* Reads the dataset object from the get endpoint for the given dataset id
* @param {number} id the id of the dataset
* @return {Promise<IDataset>}
*/
const readDatasetById = async (id: number | string): Promise<IDataset> => {
id = parseInt(id + '', 10);
// if id is less than or equal 0, throw illegal dataset error
if (id <= 0 || !Number.isInteger(id)) {
throw new TypeError(datasetIdException);
}
const { status, dataset, message } = await getJSON<IDatasetGetResponse>({ url: datasetUrlById(id) });
let errorMessage = message || datasetApiException;
if (status === ApiStatus.OK && dataset) {
return dataset;
}
throw new Error(errorMessage);
};
/**
* Reads a dataset by urn, in the li format
* @param {string} urn
@ -61,54 +24,20 @@ const readDatasetByUrn = async (urn: string = ''): Promise<IDatasetView> => {
};
/**
* Reads the response from the datasetView endpoint for the provided dataset id
* Constructs a url to get a dataset urn given a dataset id
* @param {number} id
* @returns {Promise<IDatasetView>}
*/
const readDatasetView = async (id: number): Promise<IDatasetView> => {
const { status, dataset } = await getJSON<IDatasetViewGetResponse>({ url: datasetViewUrlById(id) });
if (status === ApiStatus.OK && dataset) {
return dataset;
}
throw new Error(datasetApiException);
};
/**
* Constructs a url to get a dataset id given a dataset urn
* @param {string} urn
* @return {string}
*/
const datasetIdTranslationUrlByUrn = (urn: string): string => {
return `${datasetsUrlRoot('v1')}/urntoid/${encodeURIComponent(urn)}`;
};
const datasetUrnTranslationUrlByUrn = (id: number): string => `${datasetsUrlRoot('v2')}/idtourn/${id}`;
/**
* Translates a dataset urn string to a dataset id, using the endpoint at datasetIdTranslationUrlByUrn()
* if a dataset id is not found
* or an exception occurs, the value returned is zero, which is an illegal dataset id
* and should be treated as an exception.
* @param {string} urn
* @return {Promise<number>}
* Translates a dataset id to a dataset urn, using the endpoint at datasetIdTranslationUrlByUrn()
* @param {number} id
* @return {Promise<string>}
*/
const datasetUrnToId = async (urn: string): Promise<number> => {
let datasetId = 0;
try {
// The headers object is a Header
const headers = await getHeaders({ url: datasetIdTranslationUrlByUrn(urn) });
const stringId = headers.get('datasetid');
// If stringId is not falsey, parse as int and return, otherwise use default
if (stringId) {
datasetId = parseInt(stringId, 10);
}
} catch (e) {
warn(`Exception occurred translating datasetUrn: ${e.message}`);
}
return datasetId;
const datasetIdToUrn = async (id: number) => {
const headers = await getHeaders({ url: datasetUrnTranslationUrlByUrn(id) });
return headers.get('whUrn');
};
/**
@ -140,4 +69,4 @@ const readDatasetsCount = async ({ platform, prefix }: Partial<IReadDatasetsOpti
return await getJSON<number>({ url });
};
export { readDatasetById, datasetUrnToId, readDatasetView, readDatasets, readDatasetsCount, readDatasetByUrn };
export { readDatasets, readDatasetsCount, readDatasetByUrn, datasetIdToUrn };

View File

@ -10,9 +10,8 @@ import {
IPartyProps,
IUserEntityMap
} from 'wherehows-web/typings/api/datasets/party-entities';
import { ApiResponseStatus } from 'wherehows-web/utils/api';
import { notFoundApiError } from 'wherehows-web/utils/api';
import { datasetUrlById, datasetUrlByUrn } from 'wherehows-web/utils/api/datasets/shared';
import { ApiError } from 'wherehows-web/utils/api/errors/errors';
import { getJSON, postJSON } from 'wherehows-web/utils/api/fetcher';
import { getApiRoot, ApiStatus } from 'wherehows-web/utils/api/shared';
import { arrayFilter, arrayMap } from 'wherehows-web/utils/array';
@ -128,7 +127,7 @@ const readDatasetOwnersByUrn = async (urn: string): Promise<Array<IOwner>> => {
({ owners = [] } = await getJSON<Pick<IOwnerResponse, 'owners'>>({ url: datasetOwnersUrlByUrn(urn) }));
return ownersWithModifiedTimeAsDate(owners);
} catch (e) {
if (e instanceof ApiError && e.status === ApiResponseStatus.NotFound) {
if (notFoundApiError(e)) {
return owners;
} else {
throw e;

View File

@ -1,5 +1,6 @@
import fetch from 'fetch';
import { throwIfApiError } from 'wherehows-web/utils/api/errors/errors';
import { apiErrorStatusMessage } from 'wherehows-web/constants/errors/errors';
import { ApiError, throwIfApiError } from 'wherehows-web/utils/api/errors/errors';
/**
* Describes the attributes on the fetch configuration object
@ -112,13 +113,14 @@ const getHeaders = async (config: FetchConfig): Promise<Headers> => {
...withBaseFetchHeaders(config.headers),
method: 'HEAD'
};
const { ok, headers, statusText } = await fetch(config.url, fetchConfig);
const response = await fetch(config.url, fetchConfig);
const { ok, headers, status } = response;
if (ok) {
return headers;
}
throw new Error(statusText);
throw new ApiError(status, apiErrorStatusMessage(status));
};
export { getJSON, postJSON, deleteJSON, putJSON, getHeaders };

View File

@ -1,6 +1,8 @@
/**
* Defines available api version types
*/
import { ApiError } from 'wherehows-web/utils/api/errors/errors';
export type ApiVersion = 'v1' | 'v2';
/**
@ -31,3 +33,10 @@ export enum ApiResponseStatus {
UnAuthorized = 401,
InternalServerError = 500
}
/**
* Convenience function to ascertain if an api error is a not found code
* @param {Error} e
* @return {boolean}
*/
export const notFoundApiError = (e: Error) => e instanceof ApiError && e.status === ApiResponseStatus.NotFound;