From 8847448ab7feb1c221580639c4f38d539ad3e2eb Mon Sep 17 00:00:00 2001 From: balzack Date: Mon, 26 Aug 2024 15:27:45 -0700 Subject: [PATCH] interface cleanup --- app/sdk/__tests__/session.tests.ts | 2 +- app/sdk/src/api.ts | 31 ++++++++++++++++++++++----- app/sdk/src/bot.ts | 8 +++++-- app/sdk/src/crypto.ts | 29 +++++++++++++++++++++++++ app/sdk/src/focus.ts | 3 ++- app/sdk/src/identity.ts | 3 ++- app/sdk/src/index.ts | 11 +++++----- app/sdk/src/logging.ts | 6 +++++- app/sdk/src/net/getProfile.ts | 12 +++++++++++ app/sdk/src/net/getProfileImageUrl.ts | 4 ++++ app/sdk/src/net/setProfileData.ts | 11 ++++++++++ app/sdk/src/net/setProfileImage.ts | 10 +++++++++ app/sdk/src/node.ts | 3 ++- app/sdk/src/session.ts | 4 +++- app/sdk/src/store.ts | 3 ++- app/sdk/src/stream.ts | 3 ++- 16 files changed, 123 insertions(+), 20 deletions(-) create mode 100644 app/sdk/src/crypto.ts create mode 100644 app/sdk/src/net/getProfile.ts create mode 100644 app/sdk/src/net/getProfileImageUrl.ts create mode 100644 app/sdk/src/net/setProfileData.ts create mode 100644 app/sdk/src/net/setProfileImage.ts diff --git a/app/sdk/__tests__/session.tests.ts b/app/sdk/__tests__/session.tests.ts index 17946d98..12caf10f 100644 --- a/app/sdk/__tests__/session.tests.ts +++ b/app/sdk/__tests__/session.tests.ts @@ -95,7 +95,7 @@ jest.mock('../src/ring', () => { test('allocates session correctly', async () => { let status: string = ''; - const sdk = new DatabagSDK(null); + const sdk = new DatabagSDK(); const params: SessionParams = { topicBatch: 0, tagBatch: 0, channelTypes: [], pushType: '', deviceToken: '', notifications: [], deviceId: '', version: '', appName: '' }; const session = await sdk.login('handle', 'password', 'jest.test', true, null, params); session.addStatusListener((ev: string) => { status = ev; }); diff --git a/app/sdk/src/api.ts b/app/sdk/src/api.ts index c3572056..85317c91 100644 --- a/app/sdk/src/api.ts +++ b/app/sdk/src/api.ts @@ -19,12 +19,33 @@ export interface WebStore { } export interface Crypto { -} -export interface Logging { - error(m: any): void; - warn(m: any): void; - info(m: any): void; + // generate salt for pbk function + pkdkfSalt(): { saltHex: string }; + + // generate aes key with pbkdf2 + pbkdfKey(saltHex: string, password: string): { aesKeyHex: string }; + + // generate random aes key + aesKey(): { aesKeyHex: string }; + + // generate iv to use to aes function + aesIv(): { ivHex: string }; + + // encrypt data with aes key and iv + aesEncrypt(data: string, ivHex: string, aesKeyHex: string): { encryptedDataB64: string }; + + // decrypt data with aes key and iv + aesDecrypt(encryptedDataB64: string, ivHex: string, aesKeyHex: string): { data: string }; + + // generate rsa key + rsaKey(): { publicKeyB64: string, privateKeyB64: string }; + + // encrypt data with public rsa key + rsaEncrypt(data: string, publicKeyB64: string): { encryptedDataB64: string } + + // decrypt data with private rsa key + rsaDecrypt(encryptedDataB64: string, privateKeyB64: string): { data: string } } export interface Session { diff --git a/app/sdk/src/bot.ts b/app/sdk/src/bot.ts index 29aa2f11..21421394 100644 --- a/app/sdk/src/bot.ts +++ b/app/sdk/src/bot.ts @@ -1,15 +1,19 @@ -import type { Bot, Logging } from './api'; +import type { Bot } from './api'; import type { Asset } from './types'; +import type { Crypto } from './crypto'; +import type { Logging } from './logging'; export class BotModule implements Bot { private log: Logging; + private crypto: Crypto | null; private node: string; private secure: boolean; private token: string; - constructor(log: Logging, node: string, secure: boolean, token: string) { + constructor(log: Logging, crypto: Crypto | null, node: string, secure: boolean, token: string) { this.log = log; + this.crypto = crypto; this.node = node; this.secure = secure; this.token = token; diff --git a/app/sdk/src/crypto.ts b/app/sdk/src/crypto.ts new file mode 100644 index 00000000..f35d2388 --- /dev/null +++ b/app/sdk/src/crypto.ts @@ -0,0 +1,29 @@ +export interface Crypto { + + // generate salt for pbk function + pkdkfSalt(): { saltHex: string }; + + // generate aes key with pbkdf2 + pbkdfKey(saltHex: string, password: string): { aesKeyHex: string }; + + // generate random aes key + aesKey(): { aesKeyHex: string }; + + // generate iv to use to aes function + aesIv(): { ivHex: string }; + + // encrypt data with aes key and iv + aesEncrypt(data: string, ivHex: string, aesKeyHex: string): { encryptedDataB64: string }; + + // decrypt data with aes key and iv + aesDecrypt(encryptedDataB64: string, ivHex: string, aesKeyHex: string): { data: string }; + + // generate rsa key + rsaKey(): { publicKeyB64: string, privateKeyB64: string }; + + // encrypt data with public rsa key + rsaEncrypt(data: string, publicKeyB64: string): { encryptedDataB64: string } + + // decrypt data with private rsa key + rsaDecrypt(encryptedDataB64: string, privateKeyB64: string): { data: string } +} diff --git a/app/sdk/src/focus.ts b/app/sdk/src/focus.ts index 9b32dfb1..0d97249f 100644 --- a/app/sdk/src/focus.ts +++ b/app/sdk/src/focus.ts @@ -1,6 +1,7 @@ import { EventEmitter } from 'eventemitter3'; -import type { Identity, Contact, Content, Focus, Logging } from './api'; +import type { Identity, Contact, Content, Focus } from './api'; import type { Topic, Asset, Repeater } from './types'; +import type { Logging } from './logging'; import { Store } from './store'; export class FocusModule implements Focus { diff --git a/app/sdk/src/identity.ts b/app/sdk/src/identity.ts index 0a66da3f..2ecda929 100644 --- a/app/sdk/src/identity.ts +++ b/app/sdk/src/identity.ts @@ -1,5 +1,6 @@ import { EventEmitter } from 'eventemitter3'; -import type { Identity, Logging } from './api'; +import type { Identity } from './api'; +import type { Logging } from './logging'; import type { Profile } from './types'; import { Store } from './store'; import { getProfile } from './net/getProfile'; diff --git a/app/sdk/src/index.ts b/app/sdk/src/index.ts index b7883675..5d9d6501 100644 --- a/app/sdk/src/index.ts +++ b/app/sdk/src/index.ts @@ -1,7 +1,7 @@ import { SessionModule } from './session'; import { NodeModule } from './node'; import { BotModule } from './bot'; -import { ConsoleLogging } from './logging'; +import { type Logging, ConsoleLogging } from './logging'; import { type Store, OfflineStore, OnlineStore, NoStore } from './store'; import { setLogin } from './net/setLogin'; import { clearLogin } from './net/clearLogin'; @@ -10,9 +10,10 @@ import { addAccount } from './net/addAccount'; import { setAdmin } from './net/setAdmin'; import { getAvailable } from './net/getAvailable'; import { getUsername } from './net/getUsername'; -import type { Session, Node, Bot, SqlStore, WebStore, Crypto, Logging } from './api'; +import type { Session, Node, Bot, SqlStore, WebStore } from './api'; import type { SessionParams } from './types'; import type { Login } from './entities'; +import type { Crypto } from './crypto'; export * from './api'; export * from './types'; @@ -23,9 +24,9 @@ export class DatabagSDK { private crypto: Crypto | null; private store: Store; - constructor(crypto: Crypto | null, log?: Logging) { - this.crypto = crypto; + constructor(crypto?: Crypto, log?: Logging) { this.store = new NoStore(); + this.crypto = crypto ? crypto : null; this.log = log ? log : new ConsoleLogging(); this.log.info("databag sdk"); } @@ -98,6 +99,6 @@ export class DatabagSDK { } public async automate(node: string, secure: boolean, token: string): Promise { - return new BotModule(this.log, node, secure, token); + return new BotModule(this.log, this.crypto, node, secure, token); } } diff --git a/app/sdk/src/logging.ts b/app/sdk/src/logging.ts index b7e3294d..5641af84 100644 --- a/app/sdk/src/logging.ts +++ b/app/sdk/src/logging.ts @@ -1,4 +1,8 @@ -import { Logging } from './api'; +export interface Logging { + error(m: any): void; + warn(m: any): void; + info(m: any): void; +} export class ConsoleLogging implements Logging { public error(m: any): void { diff --git a/app/sdk/src/net/getProfile.ts b/app/sdk/src/net/getProfile.ts new file mode 100644 index 00000000..da4ec79e --- /dev/null +++ b/app/sdk/src/net/getProfile.ts @@ -0,0 +1,12 @@ +import axios from 'redaxios'; +import { ProfileEntity } from '../entities'; + +export async function getProfile(node: string, secure: boolean, token: string): Promise { + const endpoint = `http${secure ? 's' : ''}://${node}/profile?agent=${token}`; + const response = await axios.get(endpoint); + if (response.status >= 400 && response.status < 600) { + throw new Error('getProfile failed'); + } + return response.data; +} + diff --git a/app/sdk/src/net/getProfileImageUrl.ts b/app/sdk/src/net/getProfileImageUrl.ts new file mode 100644 index 00000000..d7d597a2 --- /dev/null +++ b/app/sdk/src/net/getProfileImageUrl.ts @@ -0,0 +1,4 @@ +export function getProfileImageUrl(node: string, secure: boolean, token: string, revision: number) { + return `http${secure ? 's' : ''}://${node}/profile/image?agent=${token}&revision=${revision}`; +} + diff --git a/app/sdk/src/net/setProfileData.ts b/app/sdk/src/net/setProfileData.ts new file mode 100644 index 00000000..86fe07ed --- /dev/null +++ b/app/sdk/src/net/setProfileData.ts @@ -0,0 +1,11 @@ +import axios from 'redaxios'; + +export async function setProfileData(node: string, secure: boolean, token: string, name: string, location: string, description: string): Promise { + const data = { name: name, location: location, description: description }; + const endpoint = `http${secure ? 's' : ''}://${node}/profile/data?agent=${token}`; + const response = await axios.put(endpoint, data); + if (response.status >= 400 && response.status < 600) { + throw new Error('setProfileData failed'); + } +} + diff --git a/app/sdk/src/net/setProfileImage.ts b/app/sdk/src/net/setProfileImage.ts new file mode 100644 index 00000000..373ad80e --- /dev/null +++ b/app/sdk/src/net/setProfileImage.ts @@ -0,0 +1,10 @@ +import axios from 'redaxios'; + +export async function setProfileImage(node: string, secure: boolean, token: string, image: string) { + const endpoint = `http${secure ? 's' : ''}://${node}/profile/image?agent=${token}`; + const response = await axios.put(endpoint, image); + if (response.status >= 400 && response.status < 600) { + throw new Error('setProfileImage failed'); + } +} + diff --git a/app/sdk/src/node.ts b/app/sdk/src/node.ts index aee34a79..474f231e 100644 --- a/app/sdk/src/node.ts +++ b/app/sdk/src/node.ts @@ -1,5 +1,6 @@ -import type { Node, Logging } from './api'; +import type { Node } from './api'; import type { NodeAccount, NodeConfig } from './types'; +import type { Logging } from './logging'; export class NodeModule implements Node { diff --git a/app/sdk/src/session.ts b/app/sdk/src/session.ts index 1d751250..94870f4b 100644 --- a/app/sdk/src/session.ts +++ b/app/sdk/src/session.ts @@ -12,10 +12,12 @@ import { RingModule } from './ring'; import { Connection } from './connection'; -import type { Session, Account, Identity, Contact, Ring, Alias, Attribute, Content, Stream, Focus, Crypto, Logging } from './api'; +import type { Session, Account, Identity, Contact, Ring, Alias, Attribute, Content, Stream, Focus } from './api'; import { Revision } from './entities'; import { Call } from './types'; import { Store } from './store'; +import type { Logging } from './logging'; +import type { Crypto } from './crypto'; export class SessionModule implements Session { diff --git a/app/sdk/src/store.ts b/app/sdk/src/store.ts index 35c1cb53..ed08c89f 100644 --- a/app/sdk/src/store.ts +++ b/app/sdk/src/store.ts @@ -1,5 +1,6 @@ -import { WebStore, SqlStore, Logging } from './api'; +import { WebStore, SqlStore } from './api'; import { Login, ProfileEntity, defaultProfileEntity } from './entities'; +import type { Logging } from './logging'; export interface Store { init(): Promise; diff --git a/app/sdk/src/stream.ts b/app/sdk/src/stream.ts index 161d0db7..5578e236 100644 --- a/app/sdk/src/stream.ts +++ b/app/sdk/src/stream.ts @@ -1,7 +1,8 @@ import { EventEmitter } from 'eventemitter3'; -import type { Contact, Content, Stream, Logging } from './api'; +import type { Contact, Content, Stream } from './api'; import type { Channel } from './types'; import { Store } from './store'; +import { Logging } from './logging'; export class StreamModule implements Stream {