renamed account interface

This commit is contained in:
balzack 2024-08-28 18:11:42 -07:00
parent 5de105ed89
commit 5c3b491f82
17 changed files with 122 additions and 187 deletions

View File

@ -1,5 +1,5 @@
import { EventEmitter } from 'eventemitter3'; import { EventEmitter } from 'eventemitter3';
import type { Alias, Account } from '../src/api'; import type { Alias } from '../src/api';
import type { Group } from '../src/types'; import type { Group } from '../src/types';
export class MockAliasModule implements Alias { export class MockAliasModule implements Alias {

View File

@ -1,5 +1,5 @@
import { EventEmitter } from 'eventemitter3'; import { EventEmitter } from 'eventemitter3';
import type { Attribute, Account } from '../src/api'; import type { Attribute } from '../src/api';
import type { Article } from '../src/types'; import type { Article } from '../src/types';
export class MockAttributeModule implements Attribute { export class MockAttributeModule implements Attribute {

View File

@ -1,5 +1,5 @@
import { EventEmitter } from 'eventemitter3'; import { EventEmitter } from 'eventemitter3';
import type { Content, Account } from '../src/api'; import type { Content } from '../src/api';
import type { Channel, Topic, Asset, Tag, Repeater } from '../src/types'; import type { Channel, Topic, Asset, Tag, Repeater } from '../src/types';
export class MockContentModule implements Content { export class MockContentModule implements Content {

View File

@ -1,8 +1,8 @@
import { EventEmitter } from 'eventemitter3'; import { EventEmitter } from 'eventemitter3';
import { type Account } from '../src/api'; import { type Settings } from '../src/api';
import type { AccountStatus } from '../src/types'; import type { Config } from '../src/types';
export class MockAccountModule implements Account { export class MockSettingsModule implements Settings {
public revision: number; public revision: number;
private emitter: EventEmitter; private emitter: EventEmitter;
@ -12,11 +12,11 @@ export class MockAccountModule implements Account {
this.emitter = new EventEmitter(); this.emitter = new EventEmitter();
} }
public addStatusListener(ev: (status: AccountStatus) => void): void { public addStatusListener(ev: (status: Config) => void): void {
this.emitter.on('status', ev); this.emitter.on('status', ev);
} }
public removeStatusListener(ev: (status: AccountStatus) => void): void { public removeStatusListener(ev: (status: Config) => void): void {
this.emitter.off('status', ev); this.emitter.off('status', ev);
} }

View File

@ -2,7 +2,7 @@ import { DatabagSDK } from '../src/index';
import { type SessionParams } from '../src/types'; import { type SessionParams } from '../src/types';
import { MockConnection } from '../__mocks__/connection'; import { MockConnection } from '../__mocks__/connection';
import { MockAccountModule } from '../__mocks__/account'; import { MockSettingsModule } from '../__mocks__/settings';
import { MockIdentityModule } from '../__mocks__/identity'; import { MockIdentityModule } from '../__mocks__/identity';
import { MockAliasModule } from '../__mocks__/alias'; import { MockAliasModule } from '../__mocks__/alias';
import { MockContentModule } from '../__mocks__/content'; import { MockContentModule } from '../__mocks__/content';
@ -29,11 +29,11 @@ jest.mock('../src/connection', () => {
} }
}) })
const mockAccount = new MockAccountModule(); const mockSettings = new MockSettingsModule();
jest.mock('../src/account', () => { jest.mock('../src/settings', () => {
return { return {
AccountModule: jest.fn().mockImplementation(() => { SettingsModule: jest.fn().mockImplementation(() => {
return mockAccount; return mockSettings;
}) })
} }
}) })
@ -99,14 +99,14 @@ test('allocates session correctly', async () => {
const params: SessionParams = { topicBatch: 0, tagBatch: 0, channelTypes: [], pushType: '', deviceToken: '', notifications: [], deviceId: '', version: '', appName: '' }; 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); const session = await sdk.login('handle', 'password', 'jest.test', true, null, params);
session.addStatusListener((ev: string) => { status = ev; }); session.addStatusListener((ev: string) => { status = ev; });
const account = session.getAccount(); const settings = session.getSettings();
account.enableNotifications(); settings.enableNotifications();
mockConnection.emitStatus('connected'); mockConnection.emitStatus('connected');
mockConnection.emitRevision({ account: 3, profile: 3, article: 3, group: 3, channel: 3, card: 3}); mockConnection.emitRevision({ account: 3, profile: 3, article: 3, group: 3, channel: 3, card: 3});
mockConnection.emitRing({ cardId: '', callId: 'test', calleeToken: '', ice: []}); mockConnection.emitRing({ cardId: '', callId: 'test', calleeToken: '', ice: []});
await waitFor(() => (status === 'connected')); await waitFor(() => (status === 'connected'));
await waitFor(() => (mockRing.call?.callId === 'test')); await waitFor(() => (mockRing.call?.callId === 'test'));
await waitFor(() => (mockAccount.revision == 3)); await waitFor(() => (mockSettings.revision == 3));
await waitFor(() => (mockIdentity.revision == 3)); await waitFor(() => (mockIdentity.revision == 3));
await waitFor(() => (mockContent.revision == 3)); await waitFor(() => (mockContent.revision == 3));
await waitFor(() => (mockContact.revision == 3)); await waitFor(() => (mockContact.revision == 3));

View File

@ -1,13 +1,13 @@
import { AccountModule } from '../src/account'; import { SettingsModule } from '../src/settings';
import { NoStore } from '../src/store'; import { NoStore } from '../src/store';
import { Crypto } from '../src/crypto'; import { Crypto } from '../src/crypto';
import { ConsoleLogging } from '../src/logging'; import { ConsoleLogging } from '../src/logging';
import { defaultAccountEntity } from '../src/entities'; import { defaultConfigEntity } from '../src/entities';
import { AccountStatus } from '../src/types'; import { Config } from '../src/types';
import { waitFor } from '../__mocks__/waitFor'; import { waitFor } from '../__mocks__/waitFor';
import axios from 'redaxios'; import axios from 'redaxios';
const testStatus = JSON.parse(JSON.stringify(defaultAccountEntity)); const testStatus = JSON.parse(JSON.stringify(defaultConfigEntity));
jest.mock('redaxios', () => { jest.mock('redaxios', () => {
return { return {
@ -76,29 +76,29 @@ class TestStore extends NoStore {
} }
test('allocates session correctly', async () => { test('allocates session correctly', async () => {
let status: AccountStatus | null = null; let status: Config | null = null;
const log = new ConsoleLogging(); const log = new ConsoleLogging();
const store = new TestStore(); const store = new TestStore();
const crypto = new TestCrypto(); const crypto = new TestCrypto();
const account = new AccountModule(log, store, crypto, 'test_guid', 'test_token', 'test_url', false); const settings = new SettingsModule(log, store, crypto, 'test_guid', 'test_token', 'test_url', false);
account.addStatusListener((ev: AccountStatus) => { status = ev }); settings.addStatusListener((ev: Config) => { status = ev });
account.setRevision(5); settings.setRevision(5);
await waitFor(() => (status?.storageUsed == 2)); await waitFor(() => (status?.storageUsed == 2));
account.enableRegistry(); settings.enableRegistry();
account.setRevision(6); settings.setRevision(6);
await waitFor(() => Boolean(status?.searchable)); await waitFor(() => Boolean(status?.searchable));
account.disableRegistry(); settings.disableRegistry();
account.setRevision(7); settings.setRevision(7);
await waitFor(() => !Boolean(status?.searchable)); await waitFor(() => !Boolean(status?.searchable));
account.enableNotifications(); settings.enableNotifications();
account.setRevision(8); settings.setRevision(8);
await waitFor(() => Boolean(status?.pushEnabled)); await waitFor(() => Boolean(status?.pushEnabled));
account.disableNotifications(); settings.disableNotifications();
account.setRevision(9); settings.setRevision(9);
await waitFor(() => !Boolean(status?.pushEnabled)); await waitFor(() => !Boolean(status?.pushEnabled));
account.setSeal('password'); settings.setSeal('password');
account.setRevision(10); settings.setRevision(10);
await waitFor(() => Boolean(status?.sealSet)); await waitFor(() => Boolean(status?.sealSet));
}); });

View File

@ -1,5 +1,5 @@
import { EventEmitter } from 'eventemitter3'; import { EventEmitter } from 'eventemitter3';
import type { Alias, Account, Logging } from './api'; import type { Alias, Settings, Logging } from './api';
import type { Group } from './types'; import type { Group } from './types';
import { Store } from './store'; import { Store } from './store';
@ -10,16 +10,16 @@ export class AliasModule implements Alias {
private token: string; private token: string;
private node: string; private node: string;
private secure: boolean; private secure: boolean;
private account: Account; private settings: Settings;
private emitter: EventEmitter; private emitter: EventEmitter;
constructor(log: Logging, account: Account, store: Store, guid: string, token: string, node: string, secure: boolean) { constructor(log: Logging, settings: Settings, store: Store, guid: string, token: string, node: string, secure: boolean) {
this.guid = guid; this.guid = guid;
this.token = token; this.token = token;
this.node = node; this.node = node;
this.secure = secure; this.secure = secure;
this.log = log; this.log = log;
this.account = account; this.settings = settings;
this.emitter = new EventEmitter(); this.emitter = new EventEmitter();
} }

View File

@ -4,54 +4,10 @@
// formaize delete vs block remote channel // formaize delete vs block remote channel
// articles share by cards now // articles share by cards now
import type { Channel, Topic, Asset, Tag, Article, Group, Card, Profile, Call, AccountStatus, NodeConfig, NodeAccount, Repeater } from './types'; import type { Channel, Topic, Asset, Tag, Article, Group, Card, Profile, Call, Config, NodeConfig, NodeAccount, Repeater } from './types';
export interface SqlStore {
set(stmt: string, params?: (string | number | null)[]): Promise<void>;
get(stmt: string, params?: (string | number | null)[]): Promise<any[]>;
}
export interface WebStore {
getValue(key: string): Promise<string>;
setValue(key: string, value: string): Promise<void>;
clearValue(key: string): Promise<void>;
clearAll(): Promise<void>;
}
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 }
}
export interface Session { export interface Session {
close(): Promise<{ node: string, secure: boolean, token: string }>; getSettings(): Settings;
getAccount(): Account;
getIdentity(): Identity; getIdentity(): Identity;
getContact(): Contact; getContact(): Contact;
getAlias(): Alias; getAlias(): Alias;
@ -63,8 +19,6 @@ export interface Session {
addFocus(cardId: string | null, channelId: string): Focus; addFocus(cardId: string | null, channelId: string): Focus;
removeFocus(focus: Focus): void; removeFocus(focus: Focus): void;
resync(): void;
addStatusListener(ev: (status: string) => void): void; addStatusListener(ev: (status: string) => void): void;
removeStatusListener(ev: (status: string) => void): void; removeStatusListener(ev: (status: string) => void): void;
} }
@ -82,7 +36,7 @@ export interface Ring {
decline(callId: string): void; decline(callId: string): void;
} }
export interface Account { export interface Settings {
setLogin(username: string, password: string): Promise<void>; setLogin(username: string, password: string): Promise<void>;
enableNotifications(): Promise<void>; enableNotifications(): Promise<void>;
disableNotifications(): Promise<void>; disableNotifications(): Promise<void>;
@ -96,8 +50,8 @@ export interface Account {
unlockSeal(password: string): Promise<void>; unlockSeal(password: string): Promise<void>;
forgetSeal(): Promise<void>; forgetSeal(): Promise<void>;
addStatusListener(ev: (status: AccountStatus) => void): void; addStatusListener(ev: (config: Config) => void): void;
removeStatusListener(ev: (status: AccountStatus) => void): void; removeStatusListener(ev: (config: Config) => void): void;
} }
export interface Identity { export interface Identity {

View File

@ -1,5 +1,5 @@
import { EventEmitter } from 'eventemitter3'; import { EventEmitter } from 'eventemitter3';
import type { Attribute, Account, Logging } from './api'; import type { Attribute, Settings, Logging } from './api';
import type { Article } from './types'; import type { Article } from './types';
import { Store } from './store'; import { Store } from './store';
@ -10,16 +10,16 @@ export class AttributeModule implements Attribute {
private token: string; private token: string;
private node: string; private node: string;
private secure: boolean; private secure: boolean;
private account: Account; private settings: Settings;
private emitter: EventEmitter; private emitter: EventEmitter;
constructor(log: Logging, account: Account, store: Store, guid: string, token: string, node: string, secure: boolean) { constructor(log: Logging, settings: Settings, store: Store, guid: string, token: string, node: string, secure: boolean) {
this.guid = guid; this.guid = guid;
this.token = token; this.token = token;
this.node = node; this.node = node;
this.secure = secure; this.secure = secure;
this.log = log; this.log = log;
this.account = account; this.settings = settings;
this.emitter = new EventEmitter(); this.emitter = new EventEmitter();
} }

View File

@ -1,5 +1,5 @@
import { EventEmitter } from 'eventemitter3'; import { EventEmitter } from 'eventemitter3';
import type { Content, Account, Logging } from './api'; import type { Content, Settings, Logging } from './api';
import type { Channel, Topic, Asset, Tag, Repeater } from './types'; import type { Channel, Topic, Asset, Tag, Repeater } from './types';
import { Store } from './store'; import { Store } from './store';
@ -10,16 +10,16 @@ export class ContentModule implements Content {
private token: string; private token: string;
private node: string; private node: string;
private secure: boolean; private secure: boolean;
private account: Account; private settings: Settings;
private emitter: EventEmitter; private emitter: EventEmitter;
constructor(log: Logging, account: Account, store: Store, guid: string, token: string, node: string, secure: boolean) { constructor(log: Logging, settings: Settings, store: Store, guid: string, token: string, node: string, secure: boolean) {
this.guid = guid; this.guid = guid;
this.token = token; this.token = token;
this.node = node; this.node = node;
this.secure = secure; this.secure = secure;
this.log = log; this.log = log;
this.account = account; this.settings = settings;
this.emitter = new EventEmitter(); this.emitter = new EventEmitter();
} }

View File

@ -149,7 +149,7 @@ export type SealEntity = {
publicKey: string, publicKey: string,
} }
export type AccountEntity = { export type ConfigEntity = {
disabled: boolean, disabled: boolean,
storageUsed: number, storageUsed: number,
storageAvailable: number, storageAvailable: number,
@ -164,7 +164,7 @@ export type AccountEntity = {
webPushKey: string, webPushKey: string,
} }
export const defaultAccountEntity = { export const defaultConfigEntity = {
disabled: false, disabled: false,
storageUsed: 0, storageUsed: 0,
storageAvailable: 0, storageAvailable: 0,

View File

@ -10,13 +10,16 @@ import { addAccount } from './net/addAccount';
import { setAdmin } from './net/setAdmin'; import { setAdmin } from './net/setAdmin';
import { getAvailable } from './net/getAvailable'; import { getAvailable } from './net/getAvailable';
import { getUsername } from './net/getUsername'; import { getUsername } from './net/getUsername';
import type { Session, Node, Bot, SqlStore, WebStore } from './api'; import type { Session, Node, Bot } from './api';
import type { SessionParams } from './types'; import type { SessionParams } from './types';
import type { Login } from './entities'; import type { Login } from './entities';
import type { Crypto } from './crypto'; import type { Crypto } from './crypto';
import type { WebStore, SqlStore } from './store';
export * from './api'; export * from './api';
export * from './types'; export * from './types';
export { WebStore, SqlStore } from './store';
export { Crypto } from './crypto';
export class DatabagSDK { export class DatabagSDK {
@ -77,7 +80,8 @@ export class DatabagSDK {
} }
public async logout(session: Session, all: boolean): Promise<void> { public async logout(session: Session, all: boolean): Promise<void> {
const params = await session.close(); const sessionModule = session as SessionModule;
const params = await sessionModule.close();
try { try {
const { node, secure, token } = params; const { node, secure, token } = params;
await clearLogin(node, secure, token, all); await clearLogin(node, secure, token, all);

View File

@ -1,7 +1,7 @@
import axios from 'redaxios'; import axios from 'redaxios';
import { AccountEntity } from '../entities'; import { ConfigEntity } from '../entities';
export async function getAccountStatus(node: string, secure: boolean, token: string): Promise<AccountEntity> { export async function getAccountStatus(node: string, secure: boolean, token: string): Promise<ConfigEntity> {
const endpoint = `http${secure ? 's' : ''}://${node}/account/status?agent=${token}`; const endpoint = `http${secure ? 's' : ''}://${node}/account/status?agent=${token}`;
const response = await axios.get(endpoint); const response = await axios.get(endpoint);
if (response.status >= 400 && response.status < 600) { if (response.status >= 400 && response.status < 600) {

View File

@ -1,6 +1,6 @@
import { EventEmitter } from 'eventemitter3'; import { EventEmitter } from 'eventemitter3';
import { AccountModule } from './account'; import { SettingsModule } from './settings';
import { IdentityModule } from './identity'; import { IdentityModule } from './identity';
import { ContactModule } from './contact'; import { ContactModule } from './contact';
import { AliasModule } from './alias'; import { AliasModule } from './alias';
@ -12,7 +12,7 @@ import { RingModule } from './ring';
import { Connection } from './connection'; import { Connection } from './connection';
import type { Session, Account, Identity, Contact, Ring, Alias, Attribute, Content, Stream, Focus } from './api'; import type { Session, Settings, Identity, Contact, Ring, Alias, Attribute, Content, Stream, Focus } from './api';
import { Revision } from './entities'; import { Revision } from './entities';
import { Call } from './types'; import { Call } from './types';
import { Store } from './store'; import { Store } from './store';
@ -30,9 +30,8 @@ export class SessionModule implements Session {
private node: string; private node: string;
private secure: boolean; private secure: boolean;
private loginTimestamp: number; private loginTimestamp: number;
private syncRevision: Revision | null;
private status: string; private status: string;
private account: AccountModule; private settings: SettingsModule;
private identity: IdentityModule; private identity: IdentityModule;
private contact: ContactModule; private contact: ContactModule;
private alias: AliasModule; private alias: AliasModule;
@ -54,16 +53,15 @@ export class SessionModule implements Session {
this.node = node; this.node = node;
this.secure = secure; this.secure = secure;
this.loginTimestamp = loginTimestamp; this.loginTimestamp = loginTimestamp;
this.syncRevision = null;
this.status = 'connecting' this.status = 'connecting'
this.emitter = new EventEmitter(); this.emitter = new EventEmitter();
this.identity = new IdentityModule(log, this.store, guid, token, node, secure); this.identity = new IdentityModule(log, this.store, guid, token, node, secure);
this.account = new AccountModule(log, this.store, this.crypto, guid, token, node, secure); this.settings = new SettingsModule(log, this.store, this.crypto, guid, token, node, secure);
this.contact = new ContactModule(log, this.store, guid, token, node, secure); this.contact = new ContactModule(log, this.store, guid, token, node, secure);
this.alias = new AliasModule(log, this.account, this.store, guid, token, node, secure); this.alias = new AliasModule(log, this.settings, this.store, guid, token, node, secure);
this.attribute = new AttributeModule(log, this.account, this.store, guid, token, node, secure); this.attribute = new AttributeModule(log, this.settings, this.store, guid, token, node, secure);
this.content = new ContentModule(log, this.account, this.store, guid, token, node, secure); this.content = new ContentModule(log, this.settings, this.store, guid, token, node, secure);
this.stream = new StreamModule(log, this.contact, this.content, this.store, guid); this.stream = new StreamModule(log, this.contact, this.content, this.store, guid);
this.ring = new RingModule(log); this.ring = new RingModule(log);
this.connection = new Connection(log, token, node, secure); this.connection = new Connection(log, token, node, secure);
@ -74,23 +72,12 @@ export class SessionModule implements Session {
} }
const onRevision = async (ev: Revision) => { const onRevision = async (ev: Revision) => {
try { await this.identity.setRevision(ev.profile);
await this.identity.setRevision(ev.profile); await this.settings.setRevision(ev.account);
await this.account.setRevision(ev.account); await this.contact.setRevision(ev.card);
await this.contact.setRevision(ev.card); await this.attribute.setRevision(ev.article);
await this.attribute.setRevision(ev.article); await this.alias.setRevision(ev.group);
await this.alias.setRevision(ev.group); await this.content.setRevision(ev.channel);
await this.content.setRevision(ev.channel);
if (this.syncRevision) {
this.syncRevision = null
this.emitter.emit('status', this.getStatus());
}
}
catch(err) {
this.log.warn(err);
this.syncRevision = ev;
this.emitter.emit('status', this.getStatus());
}
} }
const onRing = (ev: Call) => { const onRing = (ev: Call) => {
@ -111,45 +98,24 @@ export class SessionModule implements Session {
} }
private getStatus(): string { private getStatus(): string {
if (this.status === 'connected' && this.syncRevision) {
return 'offsync';
}
return this.status; return this.status;
} }
public async resync() {
if (this.syncRevision) {
try {
await this.identity.setRevision(this.syncRevision.profile);
await this.account.setRevision(this.syncRevision.account);
await this.contact.setRevision(this.syncRevision.card);
await this.attribute.setRevision(this.syncRevision.article);
await this.alias.setRevision(this.syncRevision.group);
await this.content.setRevision(this.syncRevision.channel);
this.syncRevision = null
this.emitter.emit('status', this.getStatus());
}
catch(err) {
this.log.warn(err);
}
}
}
public async close(): Promise<{ node: string, secure: boolean, token: string }> { public async close(): Promise<{ node: string, secure: boolean, token: string }> {
await this.content.close(); await this.content.close();
await this.attribute.close(); await this.attribute.close();
await this.alias.close(); await this.alias.close();
await this.contact.close(); await this.contact.close();
await this.identity.close(); await this.identity.close();
await this.account.close(); await this.settings.close();
await this.stream.close(); await this.stream.close();
this.connection.close(); this.connection.close();
const { node, secure, token } = this; const { node, secure, token } = this;
return { node: node, secure: secure, token: token }; return { node: node, secure: secure, token: token };
} }
public getAccount(): Account { public getSettings(): Settings {
return this.account; return this.settings;
} }
public getIdentity(): Identity { public getIdentity(): Identity {

View File

@ -1,10 +1,10 @@
import { EventEmitter } from 'eventemitter3'; import { EventEmitter } from 'eventemitter3';
import type { Account } from './api'; import type { Settings } from './api';
import type { AccountStatus } from './types'; import type { Config } from './types';
import { Store } from './store'; import { Store } from './store';
import { Crypto } from './crypto'; import { Crypto } from './crypto';
import { Logging } from './logging'; import { Logging } from './logging';
import { defaultAccountEntity, AccountEntity } from './entities'; import { defaultConfigEntity, ConfigEntity } from './entities';
import { getAccountStatus } from './net/getAccountStatus'; import { getAccountStatus } from './net/getAccountStatus';
import { addAccountMFAuth } from './net/addAccountMFAuth'; import { addAccountMFAuth } from './net/addAccountMFAuth';
import { setAccountMFAuth } from './net/setAccountMFAuth'; import { setAccountMFAuth } from './net/setAccountMFAuth';
@ -18,7 +18,7 @@ import { clearAccountSeal } from './net/clearAccountSeal';
const CLOSE_POLL_MS = 100; const CLOSE_POLL_MS = 100;
const RETRY_POLL_MS = 2000; const RETRY_POLL_MS = 2000;
export class AccountModule implements Account { export class SettingsModule implements Settings {
private emitter: EventEmitter; private emitter: EventEmitter;
private guid: string; private guid: string;
@ -32,7 +32,7 @@ export class AccountModule implements Account {
private closing: boolean; private closing: boolean;
private revision: number; private revision: number;
private nextRevision: number | null; private nextRevision: number | null;
private entity: AccountEntity; private entity: ConfigEntity;
private sealKey: { privateKey: string, publicKey: string } | null; private sealKey: { privateKey: string, publicKey: string } | null;
constructor(log: Logging, store: Store, crypto: Crypto | null, guid: string, token: string, node: string, secure: boolean) { constructor(log: Logging, store: Store, crypto: Crypto | null, guid: string, token: string, node: string, secure: boolean) {
@ -46,7 +46,7 @@ export class AccountModule implements Account {
this.sealKey = null; this.sealKey = null;
this.secure = secure; this.secure = secure;
this.revision = 0; this.revision = 0;
this.entity = defaultAccountEntity; this.entity = defaultConfigEntity;
this.syncing = true; this.syncing = true;
this.closing = false; this.closing = false;
this.nextRevision = null; this.nextRevision = null;
@ -54,8 +54,8 @@ export class AccountModule implements Account {
} }
private async init() { private async init() {
this.revision = await this.store.getAccountRevision(this.guid); this.revision = await this.store.getSettingsRevision(this.guid);
this.entity = await this.store.getAccountData(this.guid); this.entity = await this.store.getSettingsData(this.guid);
this.sealKey = await this.store.getSeal(this.guid); this.sealKey = await this.store.getSeal(this.guid);
this.syncing = false; this.syncing = false;
await this.sync(); await this.sync();
@ -73,8 +73,8 @@ export class AccountModule implements Account {
try { try {
const { guid, node, secure, token } = this; const { guid, node, secure, token } = this;
const status = await getAccountStatus(node, secure, token); const status = await getAccountStatus(node, secure, token);
await this.store.setAccountData(guid, status); await this.store.setSettingsData(guid, status);
await this.store.setAccountRevision(guid, nextRev); await this.store.setSettingsRevision(guid, nextRev);
this.entity = status; this.entity = status;
this.emitter.emit('status', this.getStatus()); this.emitter.emit('status', this.getStatus());
this.revision = nextRev; this.revision = nextRev;
@ -101,12 +101,12 @@ export class AccountModule implements Account {
return { storageUsed, storageAvailable, forwardingAddress, searchable, allowUnsealed, pushEnabled, sealable, sealSet, sealUnlocked, enableIce, multiFactorAuth, webPushKey }; return { storageUsed, storageAvailable, forwardingAddress, searchable, allowUnsealed, pushEnabled, sealable, sealSet, sealUnlocked, enableIce, multiFactorAuth, webPushKey };
} }
public addStatusListener(ev: (status: AccountStatus) => void): void { public addStatusListener(ev: (status: Config) => void): void {
this.emitter.on('status', ev); this.emitter.on('status', ev);
this.emitter.emit('status', this.getStatus()); this.emitter.emit('status', this.getStatus());
} }
public removeStatusListener(ev: (status: AccountStatus) => void): void { public removeStatusListener(ev: (status: Config) => void): void {
this.emitter.off('status', ev); this.emitter.off('status', ev);
} }

View File

@ -1,5 +1,4 @@
import { WebStore, SqlStore } from './api'; import { Login, ProfileEntity, defaultProfileEntity, ConfigEntity, defaultConfigEntity } from './entities';
import { Login, ProfileEntity, defaultProfileEntity, AccountEntity, defaultAccountEntity } from './entities';
import type { Logging } from './logging'; import type { Logging } from './logging';
export interface Store { export interface Store {
@ -15,10 +14,22 @@ export interface Store {
getProfileData(guid: string): Promise<ProfileEntity>; getProfileData(guid: string): Promise<ProfileEntity>;
setProfileData(guid: string, data: ProfileEntity): Promise<void>; setProfileData(guid: string, data: ProfileEntity): Promise<void>;
getAccountRevision(guid: string): Promise<number>; getSettingsRevision(guid: string): Promise<number>;
setAccountRevision(guid: string, revision: number): Promise<void>; setSettingsRevision(guid: string, revision: number): Promise<void>;
getAccountData(guid: string): Promise<AccountEntity>; getSettingsData(guid: string): Promise<ConfigEntity>;
setAccountData(guid: string, data: AccountEntity): Promise<void>; setSettingsData(guid: string, data: ConfigEntity): Promise<void>;
}
export interface SqlStore {
set(stmt: string, params?: (string | number | null)[]): Promise<void>;
get(stmt: string, params?: (string | number | null)[]): Promise<any[]>;
}
export interface WebStore {
getValue(key: string): Promise<string>;
setValue(key: string, value: string): Promise<void>;
clearValue(key: string): Promise<void>;
clearAll(): Promise<void>;
} }
export class OfflineStore implements Store { export class OfflineStore implements Store {
@ -102,19 +113,19 @@ export class OfflineStore implements Store {
await this.setAppValue(guid, 'profile_data', JSON.stringify(data)); await this.setAppValue(guid, 'profile_data', JSON.stringify(data));
} }
public async getAccountRevision(guid: string): Promise<number> { public async getSettingsRevision(guid: string): Promise<number> {
return await this.getAppValue(guid, 'account_revision', 0) as number; return await this.getAppValue(guid, 'account_revision', 0) as number;
} }
public async setAccountRevision(guid: string, revision: number): Promise<void> { public async setSettingsRevision(guid: string, revision: number): Promise<void> {
await this.setAppValue(guid, 'account_revision', revision.toString()); await this.setAppValue(guid, 'account_revision', revision.toString());
} }
public async getAccountData(guid: string): Promise<AccountEntity> { public async getSettingsData(guid: string): Promise<ConfigEntity> {
return await this.getAppValue(guid, 'account_data', defaultAccountEntity) as AccountEntity; return await this.getAppValue(guid, 'account_data', defaultConfigEntity) as ConfigEntity;
} }
public async setAccountData(guid: string, data: AccountEntity): Promise<void> { public async setSettingsData(guid: string, data: ConfigEntity): Promise<void> {
await this.setAppValue(guid, 'account_data', JSON.stringify(data)); await this.setAppValue(guid, 'account_data', JSON.stringify(data));
} }
@ -184,18 +195,18 @@ export class OnlineStore implements Store {
public async setProfileData(guid: string, data: ProfileEntity): Promise<void> { public async setProfileData(guid: string, data: ProfileEntity): Promise<void> {
} }
public async getAccountRevision(guid: string): Promise<number> { public async getSettingsRevision(guid: string): Promise<number> {
return 0; return 0;
} }
public async setAccountRevision(guid: string, revision: number): Promise<void> { public async setSettingsRevision(guid: string, revision: number): Promise<void> {
} }
public async getAccountData(guid: string): Promise<AccountEntity> { public async getSettingsData(guid: string): Promise<ConfigEntity> {
return defaultAccountEntity; return defaultConfigEntity;
} }
public async setAccountData(guid: string, data: AccountEntity): Promise<void> { public async setSettingsData(guid: string, data: ConfigEntity): Promise<void> {
} }
} }
@ -238,18 +249,18 @@ export class NoStore implements Store {
public async setProfileData(guid: string, data: ProfileEntity): Promise<void> { public async setProfileData(guid: string, data: ProfileEntity): Promise<void> {
} }
public async getAccountRevision(guid: string): Promise<number> { public async getSettingsRevision(guid: string): Promise<number> {
return 0; return 0;
} }
public async setAccountRevision(guid: string, revision: number): Promise<void> { public async setSettingsRevision(guid: string, revision: number): Promise<void> {
} }
public async getAccountData(guid: string): Promise<AccountEntity> { public async getSettingsData(guid: string): Promise<ConfigEntity> {
return defaultAccountEntity; return defaultConfigEntity;
} }
public async setAccountData(guid: string, data: AccountEntity): Promise<void> { public async setSettingsData(guid: string, data: ConfigEntity): Promise<void> {
} }
} }

View File

@ -135,7 +135,7 @@ export type Repeater = {
server: string, server: string,
} }
export type AccountStatus = { export type Config = {
disabled: boolean, disabled: boolean,
storageUsed: number, storageUsed: number,
storageAvailable: number, storageAvailable: number,