mirror of
https://github.com/balzack/databag.git
synced 2025-04-24 02:25:26 +00:00
implemented channel management methods
This commit is contained in:
parent
3e16002b16
commit
a733a2246f
@ -750,7 +750,11 @@ export class ContactModule implements Contact {
|
||||
public async setBlockedCard(cardId: string, blocked: boolean): Promise<void> {
|
||||
const entry = this.cardEntries.get(cardId);
|
||||
if (entry) {
|
||||
await this.setCardBlocked(cardId);
|
||||
if (blocked) {
|
||||
await this.setCardBlocked(cardId);
|
||||
} else {
|
||||
await this.clearCardBlocked(cardId);
|
||||
}
|
||||
entry.card = this.setCard(cardId, entry.item);
|
||||
this.emitCards();
|
||||
}
|
||||
@ -761,7 +765,11 @@ export class ContactModule implements Contact {
|
||||
if (entries) {
|
||||
const entry = entries.get(channelId);
|
||||
if (entry) {
|
||||
await this.setChannelBlocked(cardId, channelId);
|
||||
if (blocked) {
|
||||
await this.setChannelBlocked(cardId, channelId);
|
||||
} else {
|
||||
await this.clearChannelBlocked(cardId, channelId);
|
||||
}
|
||||
entry.channel = this.setChannel(cardId, channelId, entry.item);
|
||||
this.emitChannels(cardId);
|
||||
}
|
||||
@ -773,7 +781,11 @@ export class ContactModule implements Contact {
|
||||
if (entries) {
|
||||
const entry = entries.get(articleId);
|
||||
if (entry) {
|
||||
await this.setArticleBlocked(cardId, articleId);
|
||||
if (blocked) {
|
||||
await this.setArticleBlocked(cardId, articleId);
|
||||
} else {
|
||||
await this.clearArticleBlocked(cardId, articleId);
|
||||
}
|
||||
entry.article = this.setArticle(cardId, articleId, entry.item);
|
||||
this.emitArticles(cardId);
|
||||
}
|
||||
@ -937,6 +949,23 @@ export class ContactModule implements Contact {
|
||||
await this.sync();
|
||||
}
|
||||
|
||||
public async getSeal(cardId: string, keyData: string): Promise<{ publicKey: string, sealedKey: string }> {
|
||||
if (!this.crypto) {
|
||||
throw new Error('crypto not set');
|
||||
}
|
||||
const card = this.cardEntries.get(cardId);
|
||||
if (!card) {
|
||||
throw new Error('specified card not found');
|
||||
}
|
||||
const publicKey = card.item.profile.seal;
|
||||
if (!publicKey) {
|
||||
throw new Error('seal key not set for card');
|
||||
}
|
||||
const sealed = await this.crypto.rsaEncrypt(keyData, publicKey);
|
||||
const sealedKey = sealed.encryptedDataB64;
|
||||
return { publicKey, sealedKey };
|
||||
}
|
||||
|
||||
private async getChannelKey(seals: [{ publicKey: string; sealedKey: string }]): Promise<string | null> {
|
||||
const seal = seals.find(({ publicKey }) => this.seal && publicKey === this.seal.publicKey);
|
||||
if (seal && this.crypto && this.seal) {
|
||||
|
@ -3,20 +3,37 @@ import type { Channel } from './types';
|
||||
import { ContactModule } from './contact';
|
||||
import { StreamModule } from './stream';
|
||||
import { Logging } from './logging';
|
||||
import { Crypto } from './crypto';
|
||||
|
||||
export class ContentModule implements Content {
|
||||
private crypto: Crypto | null;
|
||||
private log: Logging;
|
||||
private contact: ContactModule;
|
||||
private stream: StreamModule;
|
||||
|
||||
constructor(log: Logging, contact: ContactModule, stream: StreamModule) {
|
||||
constructor(log: Logging, crypto: Crypto | null, contact: ContactModule, stream: StreamModule) {
|
||||
this.contact = contact;
|
||||
this.stream = stream;
|
||||
this.log = log;
|
||||
this.crypto = crypto;
|
||||
}
|
||||
|
||||
public async addChannel(sealed: boolean, type: string, subject: string, cardIds: string[]): Promise<string> {
|
||||
return await this.stream.addChannel(sealed, type, subject, cardIds);
|
||||
if (sealed) {
|
||||
if (!this.crypto) {
|
||||
throw new Error('crypto not set');
|
||||
}
|
||||
const { aesKeyHex } = await this.crypto.aesKey();
|
||||
const seals = [];
|
||||
for (let cardId of cardIds) {
|
||||
const seal = await this.contact.getSeal(cardId, aesKeyHex);
|
||||
seals.push(seal);
|
||||
}
|
||||
return await this.stream.addSealedChannel(type, subject, cardIds, aesKeyHex, seals);
|
||||
}
|
||||
else {
|
||||
return await this.stream.addUnsealedChannel(type, subject, cardIds);
|
||||
}
|
||||
}
|
||||
|
||||
public async removeChannel(channelId: string): Promise<void> {
|
||||
|
12
app/sdk/src/net/addChannel.ts
Normal file
12
app/sdk/src/net/addChannel.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { checkResponse, fetchWithTimeout } from './fetchUtil';
|
||||
|
||||
export async function addChannel(node: string, secure: boolean, token: string, type: string, data: any, cards: string[]) {
|
||||
const params = { dataType: type, data: JSON.stringify(data), groups: [], cards };
|
||||
const endpoint = `http${secure ? 's' : ''}://${node}/content/channels?agent=${token}`;
|
||||
const channel = await fetchWithTimeout(endpoint, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
checkResponse(channel.status);
|
||||
return await channel.json();
|
||||
}
|
7
app/sdk/src/net/clearChannelCard.ts
Normal file
7
app/sdk/src/net/clearChannelCard.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { checkResponse, fetchWithTimeout } from './fetchUtil';
|
||||
|
||||
export async function clearChannelCard(node: string, secure: boolean, token: string, channelId: string, cardId: string): Promise<void> {
|
||||
const endpoint = `http${secure ? 's' : ''}://${node}/content/channels/${channelId}/cards/${cardId}?agent=${token}`;
|
||||
const { status } = await fetchWithTimeout(endpoint, { method: 'DELETE' });
|
||||
checkResponse(status);
|
||||
}
|
9
app/sdk/src/net/getChannelNotifications.ts
Normal file
9
app/sdk/src/net/getChannelNotifications.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { checkResponse, fetchWithTimeout } from './fetchUtil';
|
||||
|
||||
export async function getChannelNotifications(node: string, secure: boolean, token: string, channelId: string) {
|
||||
const endpoint = `http${secure ? 's' : ''}://${node}/content/channels/${channelId}/notification?agent=${token}`;
|
||||
const notify = await fetchWithTimeout(endpoint, { method: 'GET' });
|
||||
checkResponse(notify.status);
|
||||
return await notify.json();
|
||||
}
|
||||
|
7
app/sdk/src/net/removeChannel.ts
Normal file
7
app/sdk/src/net/removeChannel.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { checkResponse, fetchWithTimeout } from './fetchUtil';
|
||||
|
||||
export async function removeChannel(node: string, secure: boolean, token: string, channelId: string): Promise<void> {
|
||||
const endpoint = `http${secure ? 's' : ''}://${node}/content/channels/${channelId}?agent=${token}`;
|
||||
const { status } = await fetchWithTimeout(endpoint, { method: 'DELETE' });
|
||||
checkResponse(status);
|
||||
}
|
7
app/sdk/src/net/setChannelCard.ts
Normal file
7
app/sdk/src/net/setChannelCard.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { checkResponse, fetchWithTimeout } from './fetchUtil';
|
||||
|
||||
export async function setChannelCard(node: string, secure: boolean, token: string, channelId: string, cardId: string): Promise<void> {
|
||||
const endpoint = `http${secure ? 's' : ''}://${node}/content/channels/${channelId}/cards/${cardId}?agent=${token}`;
|
||||
const { status } = await fetchWithTimeout(endpoint, { method: 'PUT' });
|
||||
checkResponse(status);
|
||||
}
|
7
app/sdk/src/net/setChannelNotifications.ts
Normal file
7
app/sdk/src/net/setChannelNotifications.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { checkResponse, fetchWithTimeout } from './fetchUtil';
|
||||
|
||||
export async function setChannelNotifications(node: string, secure: boolean, token: string, channelId: string, flag: boolean) {
|
||||
const endpoint = `http${secure ? 's' : ''}://${node}/content/channels/${channelId}/notification?agent=${token}`;
|
||||
const { status } = await fetchWithTimeout(endpoint, { method: 'PUT', body: JSON.stringify(notify) });
|
||||
checkResponse(status);
|
||||
}
|
12
app/sdk/src/net/setChannelSubject.ts
Normal file
12
app/sdk/src/net/setChannelSubject.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { checkResponse, fetchWithTimeout } from './fetchUtil';
|
||||
|
||||
export async function setChannelSubject(node: string, secure: boolean, token: string, channelId: string, type: string, data: any): Promise<void> {
|
||||
const params = { dataType: type, data: JSON.stringify(data) };
|
||||
const endpoint = `http${secure ? 's' : ''}://${node}/content/channels/${channelId}/subject?agent=${token}`;
|
||||
const { status } = await fetchWithTimeout(endpoint, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
checkResponse(status);
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ console.log(">>> ", channelTypes);
|
||||
this.alias = new AliasModule(log, this.settings, this.store, guid, token, node, secure);
|
||||
this.attribute = new AttributeModule(log, this.settings, this.store, guid, token, node, secure);
|
||||
this.stream = new StreamModule(log, this.store, this.crypto, guid, token, node, secure, channelTypes);
|
||||
this.content = new ContentModule(log, this.contact, this.stream);
|
||||
this.content = new ContentModule(log, this.crypto, this.contact, this.stream);
|
||||
this.ring = new RingModule(log);
|
||||
this.connection = new Connection(log, token, node, secure);
|
||||
|
||||
|
@ -6,10 +6,18 @@ import type { ChannelItem } from './items';
|
||||
import type { Channel, Topic, Asset, Tag, Participant } from './types';
|
||||
import { Store } from './store';
|
||||
import { Crypto } from './crypto';
|
||||
import { addChannel } from './net/addChannel';
|
||||
import { removeChannel } from './net/removeChannel';
|
||||
import { getChannels } from './net/getChannels';
|
||||
import { getChannelDetail } from './net/getChannelDetail';
|
||||
import { getChannelSummary } from './net/getChannelSummary';
|
||||
import { defaultChannelItem } from './items';
|
||||
import { setChannelSubject } from './net/setChannelSubject';
|
||||
import { setChannelCard } from './net/setChannelCard';
|
||||
import { clearChannelCard } from './net/clearChannelCard';
|
||||
import { getChannelNotifications } from './net/getChannelNotifications';
|
||||
import { setChannelNotifications } from './net/setChannelNotifications';
|
||||
import { addFlag } from './net/addFlag';
|
||||
|
||||
const CLOSE_POLL_MS = 100;
|
||||
const RETRY_POLL_MS = 2000;
|
||||
@ -193,7 +201,6 @@ export class StreamModule {
|
||||
public addChannelListener(ev: (arg: { channels: Channel[], cardId: string | null }) => void): void {
|
||||
this.emitter.on('channel', ev);
|
||||
const channels = Array.from(this.channelEntries, ([channelId, entry]) => entry.channel);
|
||||
console.log("EMIT ON ADD", channels.length);
|
||||
ev({ channels, cardId: null });
|
||||
}
|
||||
|
||||
@ -203,7 +210,6 @@ console.log("EMIT ON ADD", channels.length);
|
||||
|
||||
private emitChannels() {
|
||||
const channels = Array.from(this.channelEntries, ([channelId, entry]) => entry.channel);
|
||||
console.log("EMIT", channels.length);
|
||||
this.emitter.emit('channel', { channels, cardId: null });
|
||||
}
|
||||
|
||||
@ -219,33 +225,114 @@ console.log("EMIT", channels.length);
|
||||
await this.sync();
|
||||
}
|
||||
|
||||
public async addChannel(sealed: boolean, type: string, subject: string, cardIds: string[]): Promise<string> {
|
||||
return '';
|
||||
public async addSealedChannel(type: string, subject: string, cardIds: string[], aesKeyHex: string, seals: { publicKey: string, sealedKey: string}[]): Promise<string> {
|
||||
const { node, secure, token, crypto, seal } = this;
|
||||
if (!crypto) {
|
||||
throw new Error('crypto not set');
|
||||
}
|
||||
if (!seal) {
|
||||
throw new Error('seal not set');
|
||||
}
|
||||
const sealKey = await this.crypto.rsaEncrypt(aesKeyHex, seal.publicKey);
|
||||
const { ivHex } = await crypto.aesIv();
|
||||
const { encryptedDataB64 } = await crypto.aesEncrypt(subject, ivHex, aesKeyHex);
|
||||
const sealedSubject = { subjectEncrypted: encryptedDataB64, subjectIv: ivHex, seals: [ ...seals, sealKey ] };
|
||||
return await addChannel(node, secure, token, type, sealedSubject, cardIds);
|
||||
}
|
||||
|
||||
public async removeChannel(channelId: string): Promise<void> { }
|
||||
public async addUnsealedChannel(type: string, subject: string, cardIds: string[]): Promise<string> {
|
||||
const { node, secure, token } = this;
|
||||
return await addChannel(node, secure, token, type, { subject }, cardIds);
|
||||
}
|
||||
|
||||
public async setChannelSubject(channelId: string, subject: string): Promise<void> { }
|
||||
public async removeChannel(channelId: string): Promise<void> {
|
||||
const { node, secure, token } = this;
|
||||
return await removeChannel(node, secure, token);
|
||||
}
|
||||
|
||||
public async setChannelCard(channelId: string, cardId: string): Promise<void> { }
|
||||
public async setChannelSubject(channelId: string, subject: string): Promise<void> {
|
||||
const channel = this.channelEntries.get(channelId);
|
||||
if (!channel) {
|
||||
throw new Error('channel not found');
|
||||
}
|
||||
const { item } = channel;
|
||||
const { node, secure, token, crypto, seal } = this;
|
||||
if (item.sealed) {
|
||||
if (!crypto) {
|
||||
throw new Error('crypto not set');
|
||||
}
|
||||
if (!seal) {
|
||||
throw new Error('seal not set');
|
||||
}
|
||||
const { subjectIv, seals } = JSON.parse(item.detail.data);
|
||||
if (!item.channelKey) {
|
||||
item.channelKey = await this.getChannelKey(seals);
|
||||
}
|
||||
const { encryptedDataB64 } = await crypto.aesEncrypt(subject, subjectIv, item.channelKey);
|
||||
const sealedSubject = { subjectEncrypted, encryptedDataB64, subjectIv, seals };
|
||||
await setChannelSubject(node, secure, token, channelId, item.dataType, sealedSubject);
|
||||
}
|
||||
else {
|
||||
await setChannelSubject(node, secure, token, channelId, item.dataType, { subject });
|
||||
}
|
||||
}
|
||||
|
||||
public async clearChannelCard(channelId: string, cardId: string): Promise<void> { }
|
||||
public async setChannelCard(channelId: string, cardId: string): Promise<void> {
|
||||
const { node, secure, token } = this;
|
||||
await setChannelCard(node, secure, token, channelId, cardId);
|
||||
}
|
||||
|
||||
public async setBlockedChannel(channelId: string, blocked: boolean): Promise<void> { }
|
||||
public async clearChannelCard(channelId: string, cardId: string): Promise<void> {
|
||||
const { node, secure, token } = this;
|
||||
await clearChannelCard(node, secure, token, channelid, cardId);
|
||||
}
|
||||
|
||||
public async setBlockedChannel(channelId: string, blocked: boolean): Promise<void> {
|
||||
const entry = this.channelEntries.get(channelId);
|
||||
if (entry) {
|
||||
if (blocked) {
|
||||
await this.setChannelBlocked(channelId);
|
||||
} else {
|
||||
await this.clearChannelBlocked(channelId);
|
||||
}
|
||||
entry.card = this.setChannel(cardId, entry.item);
|
||||
this.emitChannels();
|
||||
}
|
||||
}
|
||||
|
||||
public async getBlockedChannels(): Promise<Channel[]> {
|
||||
return [];
|
||||
return Array.from(this.channelEntries.entries())
|
||||
.filter(([key, value]) => this.isChannelBlocked(key))
|
||||
.map(([key, value]) => value.card);
|
||||
}
|
||||
|
||||
public async flagChannel(channelId: string): Promise<void> { }
|
||||
public async flagChannel(channelId: string): Promise<void> {
|
||||
const { node, secure, guid } = this;
|
||||
await addFlag(node, secure, guid, { channelId });
|
||||
}
|
||||
|
||||
public async getChannelNotifications(channelId: string): Promise<boolean> {
|
||||
return false;
|
||||
const { node, secure, token } = this;
|
||||
await getChannelNotifications(node, secure, token, channelId);
|
||||
}
|
||||
|
||||
public async setChannelNotifications(channelId: string, enabled: boolean): Promise<void> { }
|
||||
public async setChannelNotifications(channelId: string, enabled: boolean): Promise<void> {
|
||||
const { node, secure, token } = this;
|
||||
await setChannelNotifications(node, secure, token, channelId, enabled);
|
||||
}
|
||||
|
||||
public async setUnreadChannel(channelId: string, unread: boolean): Promise<void> { }
|
||||
public async setUnreadChannel(channelId: string, unread: boolean): Promise<void> {
|
||||
const entry = this.channelEntries.get(channelId);
|
||||
if (entry) {
|
||||
if (unread) {
|
||||
await this.setChannelUnread(channelId);
|
||||
} else {
|
||||
await this.clearChannelUnread(channelId);
|
||||
}
|
||||
entry.card = this.setChannel(cardId, entry.item);
|
||||
this.emitChannels();
|
||||
}
|
||||
}
|
||||
|
||||
public async setFocus(channelId: string): Promise<Focus> {
|
||||
const { node, secure, token, focus } = this;
|
||||
|
Loading…
x
Reference in New Issue
Block a user