Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SDK-590] wrap metadata calls for node and web #592

Merged
merged 6 commits into from
Apr 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/build-typescript.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ jobs:
name: Test
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
target: [ "node", "web" ]
defaults:
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/test-golang.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,17 @@ on:
jobs:
prod-test-golang:
name: Golang - samples - prod test
runs-on: ${{ matrix.os }}
runs-on: ${{ matrix.os-artifact[0] }}
strategy:
matrix:
os: [ ubuntu-latest, windows-latest, macos-latest ]
os-artifact: [ [ubuntu-latest, linux], [windows-latest, windows-gnu] ] # , macos-latest ] disabled due to macos not allowing us to set the LD_LIBRARY_PATH as a github action
steps:
- uses: actions/checkout@v2
- name: Download ${{ matrix.os-artifact[0] }} binaries
uses: dawidd6/action-download-artifact@v2.17.0
with:
workflow: "build-libs.yml"
path: ./libs/${{ matrix.os-artifact[1] }}
path: ./samples/go
repo: trinsic-id/okapi
github_token: ${{ secrets.GITHUB_TOKEN }}
name: ${{ matrix.os-artifact[1] }}
Expand Down
6 changes: 4 additions & 2 deletions node/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ run `pwsh make.ps1`
it will take all the proto files in ../../proto and generate js files in the ./dist dir
it will also build the index.d.ts and put it into the dist
```sh
npm install -g grpc-tools
npm install -g grpc-tools prettier
grpc_tools_node_protoc --js_out=import_style=commonjs,binary:./dist --grpc_out=grpc_js:./dist --proto_path=../../proto ProviderService.proto
```

or just use the `make.ps1`
or just use the `make.ps1`

* We use [prettier](https://prettier.io/) for code formatting.
276 changes: 161 additions & 115 deletions node/src/AccountService.ts
Original file line number Diff line number Diff line change
@@ -1,136 +1,182 @@
import ServiceBase from "./ServiceBase";
import {
AccountClient,
AccountProfile,
ConfirmationMethod,
InfoRequest,
InfoResponse,
SignInRequest,
TokenProtection,
ServiceOptions,
ListDevicesRequest,
ListDevicesResponse,
RevokeDeviceRequest,
RevokeDeviceResponse,
ResponseStatus,
AccountClient,
AccountProfile,
ConfirmationMethod,
InfoRequest,
InfoResponse,
ListDevicesRequest,
ListDevicesResponse,
ResponseStatus,
RevokeDeviceRequest,
RevokeDeviceResponse,
ServiceOptions,
SignInRequest,
TokenProtection,
} from "./proto";
import {BlindOberonTokenRequest, Oberon, UnBlindOberonTokenRequest} from "@trinsic/okapi";
import {
BlindOberonTokenRequest,
Oberon,
UnBlindOberonTokenRequest,
} from "@trinsic/okapi";

export class AccountService extends ServiceBase {
client: AccountClient;

constructor(options?: ServiceOptions) {
super(options);
client: AccountClient;

this.client = new AccountClient(this.address, this.channelCredentials);
}
constructor(options?: ServiceOptions) {
super(options);

public signIn(request: SignInRequest): Promise<string> {
request.setEcosystemId(request.getEcosystemId() || this.options.getDefaultEcosystem());
this.client = new AccountClient(this.address, this.channelCredentials);
}

return new Promise((resolve, reject) => {
this.client.signIn(request, (error, response) => {
if (error || response.getStatus() != ResponseStatus.SUCCESS) {
reject(error);
} else {
const authToken = Buffer
.from(response.getProfile()!.serializeBinary())
.toString('base64url');
/**
* protect the given profile
* @param profile The profile to protect with oberon blinding
* @param securityCode must be utf-8 encoded `UInt8Array`. `string` will be decoded to utf-8.
*/
public static async protect(
profile: string | AccountProfile,
securityCode: string | Uint8Array
): Promise<string> {
securityCode = AccountService.convertToUtf8(securityCode);
profile = AccountService.convertToProfile(profile);
let cloned = profile.clone();
const request = new BlindOberonTokenRequest()
.setToken(cloned.getAuthToken())
.setBlindingList([securityCode]);
const result = await Oberon.blindToken(request);
cloned = cloned
.setAuthToken(result.getToken())
.setProtection(
new TokenProtection()
.setEnabled(true)
.setMethod(ConfirmationMethod.OTHER)
);
return Buffer.from(cloned.serializeBinary()).toString("base64url");
}

// set the auth token as active for the current service instance
this.options.setAuthToken(authToken);
/**
* unprotect the given profile
* @param profile The profile to unprotect with oberon blinding
* @param securityCode must be utf-8 encoded `UInt8Array`. `string` will be decoded to utf-8.
*/
public static async unprotect(
profile: string | AccountProfile,
securityCode: string | Uint8Array
): Promise<string> {
securityCode = AccountService.convertToUtf8(securityCode);
profile = AccountService.convertToProfile(profile);
let cloned = profile.clone();
const request = new UnBlindOberonTokenRequest()
.setToken(cloned.getAuthToken())
.setBlindingList([securityCode]);
const result = await Oberon.unblindToken(request);
cloned = cloned
.setAuthToken(result.getToken())
.setProtection(
new TokenProtection()
.setEnabled(false)
.setMethod(ConfirmationMethod.NONE)
);
return Buffer.from(cloned.serializeBinary()).toString("base64url");
}

resolve(authToken);
}
});
});
private static convertToProfile(
profile: string | AccountProfile
): AccountProfile {
if (typeof profile == "string") {
return AccountProfile.deserializeBinary(
Buffer.from(profile, "base64url")
);
}
return profile;
}

public info(): Promise<InfoResponse> {
const request = new InfoRequest();

return new Promise(async (resolve, reject) => {
try {
let metadata = await this.getMetadata(request)
this.client.info(request, metadata, (error, response) => {
if (error) {
reject(error);
} else {
resolve(response);
}
});
} catch (e) {
reject(e);
}
});
private static convertToUtf8(securityCode: string | Uint8Array): Uint8Array {
if (typeof securityCode == "string") {
return new TextEncoder().encode(securityCode);
} else {
return securityCode;
}
}

/**
* protect the given profile
* @param profile The profile to protect with oberon blinding
* @param securityCode must be utf-8 encoded `UInt8Array`. `string` will be decoded to utf-8.
*/
public static async protect(profile: string | AccountProfile, securityCode: string | Uint8Array): Promise<string> {
securityCode = AccountService.convertToUtf8(securityCode);
profile = AccountService.convertToProfile(profile);
let cloned = profile.clone();
const request = new BlindOberonTokenRequest().setToken(cloned.getAuthToken()).setBlindingList([securityCode]);
const result = await Oberon.blindToken(request);
cloned = cloned.setAuthToken(result.getToken()).setProtection(new TokenProtection().setEnabled(true).setMethod(ConfirmationMethod.OTHER));
return Buffer.from(cloned.serializeBinary()).toString('base64url');
}
public signIn(request: SignInRequest): Promise<string> {
request.setEcosystemId(
request.getEcosystemId() || this.options.getDefaultEcosystem()
);

/**
* unprotect the given profile
* @param profile The profile to unprotect with oberon blinding
* @param securityCode must be utf-8 encoded `UInt8Array`. `string` will be decoded to utf-8.
*/
public static async unprotect(profile: string | AccountProfile, securityCode: string | Uint8Array): Promise<string> {
securityCode = AccountService.convertToUtf8(securityCode);
profile = AccountService.convertToProfile(profile);
let cloned = profile.clone();
const request = new UnBlindOberonTokenRequest().setToken(cloned.getAuthToken()).setBlindingList([securityCode]);
const result = await Oberon.unblindToken(request);
cloned = cloned.setAuthToken(result.getToken()).setProtection(new TokenProtection().setEnabled(false).setMethod(ConfirmationMethod.NONE));
return Buffer.from(cloned.serializeBinary()).toString('base64url');
}
return new Promise((resolve, reject) => {
this.client.signIn(request, (error, response) => {
if (error || response.getStatus() != ResponseStatus.SUCCESS) {
reject(error);
} else {
const authToken = Buffer.from(
response.getProfile()!.serializeBinary()
).toString("base64url");

private static convertToProfile(profile: string | AccountProfile): AccountProfile {
if (typeof profile == 'string') {
return AccountProfile.deserializeBinary(Buffer.from(profile, 'base64url'));
}
return profile;
}
// set the auth token as active for the current service instance
this.options.setAuthToken(authToken);

private static convertToUtf8(securityCode: string | Uint8Array): Uint8Array {
if (typeof securityCode == 'string') {
return new TextEncoder().encode(securityCode);
} else {
return securityCode;
resolve(authToken);
}
}
});
});
}

public listDevices(request: ListDevicesRequest): Promise<ListDevicesResponse> {
return new Promise(async (resolve, reject) => {
this.client.listDevices(request, await this.getMetadata(request), (error, response) => {
if (error) {
reject(error);
} else {
resolve(response);
}
})
})
}
public info(): Promise<InfoResponse> {
const request = new InfoRequest();

public revokeDevice(request: RevokeDeviceRequest): Promise<RevokeDeviceResponse> {
return new Promise(async (resolve, reject) => {
this.client.revokeDevice(request, await this.getMetadata(request), (error, response) => {
if (error) {
reject(error);
} else {
resolve(response);
}
})
})
}
return new Promise(async (resolve, reject) => {
try {
let metadata = await this.getMetadata(request);
this.client.info(request, metadata, (error, response) => {
if (error) {
reject(error);
} else {
resolve(response);
}
});
} catch (e) {
reject(e);
}
});
}

public listDevices(
request: ListDevicesRequest
): Promise<ListDevicesResponse> {
return new Promise(async (resolve, reject) => {
try {
let metadata = await this.getMetadata(request);
this.client.listDevices(request, metadata, (error, response) => {
if (error) {
reject(error);
} else {
resolve(response);
}
});
} catch (e) {
reject(e);
}
});
}

public revokeDevice(
request: RevokeDeviceRequest
): Promise<RevokeDeviceResponse> {
return new Promise(async (resolve, reject) => {
try {
let metadata = await this.getMetadata(request);
this.client.revokeDevice(request, metadata, (error, response) => {
if (error) {
reject(error);
} else {
resolve(response);
}
});
} catch (e) {
reject(e);
}
});
}
}
Loading