Skip to content

Commit

Permalink
feat: validate printable ASCII
Browse files Browse the repository at this point in the history
  • Loading branch information
shuffledex committed Jan 13, 2021
1 parent b28337f commit 55b44eb
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 9 deletions.
9 changes: 8 additions & 1 deletion src/Polymesh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ import {
tickerToString,
u32ToBigNumber,
} from '~/utils/conversion';
import { createProcedureMethod, getDid, stringIsClean } from '~/utils/internal';
import { createProcedureMethod, getDid, isPrintableASCII, stringIsClean } from '~/utils/internal';

import { Claims } from './Claims';
// import { Governance } from './Governance';
Expand Down Expand Up @@ -345,6 +345,13 @@ export class Polymesh {
args: { ticker: string },
callback?: SubCallback<boolean>
): Promise<boolean | UnsubCallback> {
if (!isPrintableASCII(args.ticker)) {
throw new PolymeshError({
code: ErrorCode.ValidationError,
message: 'Only printable ASCII is alowed as ticker name',
});
}

const reservation = new TickerReservation(args, this.context);

if (callback) {
Expand Down
17 changes: 17 additions & 0 deletions src/__tests__/Polymesh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,23 @@ describe('Polymesh Class', () => {
entityMockUtils.cleanup();
});

test('should throw if ticker reservation does not exist', async () => {
entityMockUtils.getTickerReservationDetailsStub().resolves({
owner: entityMockUtils.getIdentityInstance(),
expiryDate: new Date(),
status: TickerReservationStatus.Free,
});

const polymesh = await Polymesh.connect({
nodeUrl: 'wss://some.url',
accountUri: '//uri',
});

return expect(
polymesh.isTickerAvailable({ ticker: String.fromCharCode(10000000) })
).rejects.toThrow('Only printable ASCII is alowed as ticker name');
});

test('should return true if ticker is available to reserve it', async () => {
entityMockUtils.getTickerReservationDetailsStub().resolves({
owner: entityMockUtils.getIdentityInstance(),
Expand Down
8 changes: 8 additions & 0 deletions src/api/procedures/__tests__/reserveTicker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,14 @@ describe('reserveTicker procedure', () => {

let error;

try {
await prepareReserveTicker.call(proc, { ticker: String.fromCharCode(10000000) });
} catch (err) {
error = err;
}

expect(error.message).toBe('Only printable ASCII is alowed as ticker name');

try {
await prepareReserveTicker.call(proc, { ticker: '' });
} catch (err) {
Expand Down
9 changes: 8 additions & 1 deletion src/api/procedures/reserveTicker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
import { ErrorCode, RoleType, TickerReservationStatus } from '~/types';
import { ProcedureAuthorization } from '~/types/internal';
import { stringToTicker, tickerToString } from '~/utils/conversion';
import { findEventRecord } from '~/utils/internal';
import { findEventRecord, isPrintableASCII } from '~/utils/internal';

export interface ReserveTickerParams {
ticker: string;
Expand Down Expand Up @@ -47,6 +47,13 @@ export async function prepareReserveTicker(
} = this;
const { ticker, extendPeriod = false } = args;

if (!isPrintableASCII(ticker)) {
throw new PolymeshError({
code: ErrorCode.ValidationError,
message: 'Only printable ASCII is alowed as ticker name',
});
}

if (ticker.length < 1 || ticker.length > 12 || ticker !== ticker.toUpperCase()) {
throw new PolymeshError({
code: ErrorCode.ValidationError,
Expand Down
25 changes: 18 additions & 7 deletions src/utils/__tests__/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
delay,
findEventRecord,
getDid,
isPrintableASCII,
padString,
removePadding,
requestAtBlock,
Expand Down Expand Up @@ -424,15 +425,25 @@ describe('calculateNextKey', () => {

expect(nextKey).toEqual(30);
});
});

describe('stringIsClean', () => {
test('should return false if the string contains charcode 65533', () => {
expect(stringIsClean(String.fromCharCode(65533))).toBe(false);
});
describe('stringIsClean', () => {
test('should return false if the string contains charcode 65533', () => {
expect(stringIsClean(String.fromCharCode(65533))).toBe(false);
});

test("should return true if the string doesn't contain any forbidden characters", () => {
expect(stringIsClean('Clean String')).toBe(true);
});
test("should return true if the string doesn't contain any forbidden characters", () => {
expect(stringIsClean('Clean String')).toBe(true);
});
});

describe('isPrintableASCII', () => {
test('should return true if the string contains printable ASCII', () => {
expect(isPrintableASCII('TICKET')).toBe(true);
});

test("should return false if the string doesn't contain printable ASCII", () => {
expect(isPrintableASCII(String.fromCharCode(10000000))).toBe(false);
});
});

Expand Down
9 changes: 9 additions & 0 deletions src/utils/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,15 @@ export function stringIsClean(value: string): boolean {
return !range(value.length).some(index => forbiddenCharCodes.includes(value.charCodeAt(index)));
}

/**
* @hidden
*
* Return whether the string is fully printable ASCII
*/
export function isPrintableASCII(value: string): boolean {
return new RegExp('^[\\\x00-\\\x7F]*$').test(value);
}

/**
* @hidden
*
Expand Down

0 comments on commit 55b44eb

Please sign in to comment.