Skip to content

Commit

Permalink
feat: implement accept and remove in the AuthorizationRequest Entity
Browse files Browse the repository at this point in the history
  • Loading branch information
monitz87 committed Apr 2, 2020
1 parent 27ef2d9 commit ebf68fb
Show file tree
Hide file tree
Showing 8 changed files with 135 additions and 7 deletions.
29 changes: 26 additions & 3 deletions src/api/entities/AuthorizationRequest.ts
@@ -1,6 +1,7 @@
import BigNumber from 'bignumber.js';

import { Entity } from '~/base';
import { consumeAuthorizationRequests } from '~/api/procedures';
import { Entity, TransactionQueue } from '~/base';
import { Context } from '~/context';
import { Authorization } from '~/types';

Expand Down Expand Up @@ -64,10 +65,9 @@ export class AuthorizationRequest extends Entity<UniqueIdentifiers> {
public expiry: Date | null;

/**
* @hidden
* internal identifier for the request (used to accept/reject/cancel)
*/
private authId: BigNumber;
public authId: BigNumber;

/**
* @hidden
Expand All @@ -85,4 +85,27 @@ export class AuthorizationRequest extends Entity<UniqueIdentifiers> {
this.expiry = expiry;
this.data = data;
}

/**
* Accept the authorization request. You must be the target of the request to be able to accept it
*/
public accept(): Promise<TransactionQueue> {
return consumeAuthorizationRequests.prepare(
{ authRequests: [this], accept: true },
this.context
);
}

/**
* Remove the authorization request
*
* - If you are the request issuer, this will cancel the authorization
* - If you are the request target, this will reject the authorization
*/
public remove(): Promise<TransactionQueue> {
return consumeAuthorizationRequests.prepare(
{ authRequests: [this], accept: false },
this.context
);
}
}
2 changes: 1 addition & 1 deletion src/api/procedures/__tests__/createSecurityToken.ts
Expand Up @@ -287,7 +287,7 @@ describe('createSecurityToken procedure', () => {

const result = await prepareCreateSecurityToken.call(proc, { ...args, documents });

sinon.assert.calledWith(addTransactionStub, tx, {}, rawTicker, rawDocuments);
sinon.assert.calledWith(addTransactionStub, tx, { isCritical: false }, rawTicker, rawDocuments);

expect(result).toMatchObject(new SecurityToken({ ticker }, mockContext));
});
Expand Down
66 changes: 66 additions & 0 deletions src/api/procedures/consumeAuthorizationRequests.ts
@@ -0,0 +1,66 @@
import { AuthorizationRequest } from '~/api/entities';
import { Procedure } from '~/base';
import { authTargetToAuthIdentifier, numberToU64 } from '~/utils';

export interface ConsumeParams {
accept: boolean;
}

export type ConsumeAuthorizationRequestsParams = ConsumeParams & {
authRequests: AuthorizationRequest[];
};

const isLive = ({ expiry }: AuthorizationRequest): boolean =>
expiry === null || expiry > new Date();

/**
* @hidden
*/
export async function prepareConsumeAuthorizationRequests(
this: Procedure<ConsumeAuthorizationRequestsParams>,
args: ConsumeAuthorizationRequestsParams
): Promise<void> {
const {
context: {
polymeshApi: { tx },
},
context,
} = this;
const { accept, authRequests } = args;

const liveRequests = authRequests.filter(isLive);

if (accept) {
const requestIds = liveRequests.map(({ authId }) => numberToU64(authId, context));
this.addTransaction(tx.identity.batchAcceptAuthorization, {}, requestIds);
} else {
const authIdentifiers = liveRequests.map(({ authId, targetDid }) =>
authTargetToAuthIdentifier({ authId, did: targetDid }, context)
);
this.addTransaction(tx.identity.batchRemoveAuthorization, {}, authIdentifiers);
}
}

/**
* @hidden
*/
export function isAuthorized(
this: Procedure<ConsumeAuthorizationRequestsParams>,
{ authRequests, accept }: ConsumeAuthorizationRequestsParams
): boolean {
const { did } = this.context.getCurrentIdentity();

return authRequests.filter(isLive).every(({ targetDid, issuerDid }) => {
let condition = did === targetDid;
if (!accept) {
condition = condition || did === issuerDid;
}

return condition;
});
}

export const consumeAuthorizationRequests = new Procedure(
prepareConsumeAuthorizationRequests,
isAuthorized
);
2 changes: 1 addition & 1 deletion src/api/procedures/createSecurityToken.ts
Expand Up @@ -126,7 +126,7 @@ export async function prepareCreateSecurityToken(
if (documents) {
const rawDocuments = documents.map(document => tokenDocumentToDocument(document, context));

this.addTransaction(tx.asset.addDocuments, {}, rawTicker, rawDocuments);
this.addTransaction(tx.asset.addDocuments, { isCritical: false }, rawTicker, rawDocuments);
}

return new SecurityToken({ ticker }, context);
Expand Down
1 change: 1 addition & 0 deletions src/api/procedures/index.ts
Expand Up @@ -4,3 +4,4 @@ export { toggleFreezeTransfers, ToggleFreezeTransfersParams } from './toggleFree
export { createSecurityToken, CreateSecurityTokenParams } from './createSecurityToken';
export { setTokenDocuments, SetTokenDocumentsParams } from './setTokenDocuments';
export { transferTokenOwnership, TransferTokenOwnershipParams } from './transferTokenOwnership';
export { consumeAuthorizationRequests, ConsumeParams } from './consumeAuthorizationRequests';
7 changes: 5 additions & 2 deletions src/base/Procedure.ts
Expand Up @@ -26,7 +26,10 @@ export class Procedure<Args extends unknown = void, ReturnValue extends unknown
args: Args
) => Promise<MaybePostTransactionValue<ReturnValue>>;

private checkRoles: (this: Procedure<Args, ReturnValue>, args: Args) => Promise<boolean> | Role[];
private checkRoles: (
this: Procedure<Args, ReturnValue>,
args: Args
) => Promise<boolean> | boolean | Role[];

private transactions: TransactionSpec[] = [];

Expand All @@ -50,7 +53,7 @@ export class Procedure<Args extends unknown = void, ReturnValue extends unknown
| ((
this: Procedure<Args, ReturnValue>,
args: Args
) => Promise<boolean> | Role[]) = async (): Promise<boolean> => true
) => Promise<boolean> | boolean | Role[]) = async (): Promise<boolean> => true
) {
this.prepareTransactions = prepareTransactions;

Expand Down
6 changes: 6 additions & 0 deletions src/types/internal.ts
Expand Up @@ -6,6 +6,7 @@ import {
SubmittableExtrinsics,
} from '@polkadot/api/types';
import { ISubmittableResult } from '@polkadot/types/types';
import BigNumber from 'bignumber.js';

import { PostTransactionValue } from '~/base';

Expand Down Expand Up @@ -98,3 +99,8 @@ export interface Signer {
type: SignerType;
value: string;
}

export interface AuthTarget {
did: string;
authId: BigNumber;
}
29 changes: 29 additions & 0 deletions src/utils/index.ts
Expand Up @@ -10,6 +10,7 @@ import {
AccountKey,
AssetIdentifier,
AssetType,
AuthIdentifier,
AuthorizationData,
Document,
DocumentHash,
Expand All @@ -35,6 +36,7 @@ import {
TokenType,
} from '~/types';
import {
AuthTarget,
Extrinsics,
MapMaybePostTransactionValue,
MaybePostTransactionValue,
Expand Down Expand Up @@ -483,6 +485,33 @@ export function documentToTokenDocument(
};
}

/**
* @hidden
*/
export function authTargetToAuthIdentifier(
{ did, authId }: AuthTarget,
context: Context
): AuthIdentifier {
return createType<'AuthIdentifier'>(context.polymeshApi.registry, 'AuthIdentifier', {
// eslint-disable-next-line @typescript-eslint/camelcase
auth_id: numberToU64(authId, context),
signatory: signerToSignatory({ type: SignerType.Identity, value: did }, context),
});
}

/**
* @hidden
*/
export function authIdentifierToAuthTarget({
auth_id: authId,
signatory,
}: AuthIdentifier): AuthTarget {
return {
authId: u64ToBigNumber(authId),
did: signatoryToSigner(signatory).value,
};
}

/**
* Unwrap a Post Transaction Value
*/
Expand Down

0 comments on commit ebf68fb

Please sign in to comment.