mirror of
https://github.com/balzack/databag.git
synced 2025-02-14 12:39:17 +00:00
support updating subject on sealed channels in webapp
This commit is contained in:
parent
fd086e2333
commit
40dc395dff
@ -1,8 +1,7 @@
|
|||||||
import { checkResponse, fetchWithTimeout } from './fetchUtil';
|
import { checkResponse, fetchWithTimeout } from './fetchUtil';
|
||||||
|
|
||||||
export async function setChannelSubject(token, channelId, subject ) {
|
export async function setChannelSubject(token, channelId, dataType, data ) {
|
||||||
let data = { subject };
|
let params = { dataType, data: JSON.stringify(data) };
|
||||||
let params = { dataType: 'superbasic', data: JSON.stringify(data) };
|
|
||||||
let channel = await fetchWithTimeout(`/content/channels/${channelId}/subject?agent=${token}`, { method: 'PUT', body: JSON.stringify(params)} );
|
let channel = await fetchWithTimeout(`/content/channels/${channelId}/subject?agent=${token}`, { method: 'PUT', body: JSON.stringify(params)} );
|
||||||
checkResponse(channel);
|
checkResponse(channel);
|
||||||
return await channel.json();
|
return await channel.json();
|
||||||
|
@ -48,7 +48,7 @@ export function useChannelContext() {
|
|||||||
else {
|
else {
|
||||||
let detail = await getChannelDetail(access.current, channel.id);
|
let detail = await getChannelDetail(access.current, channel.id);
|
||||||
cur.data.channelDetail = detail;
|
cur.data.channelDetail = detail;
|
||||||
cur.data.unsealedSubject = null;
|
cur.data.unsealedChannel = null;
|
||||||
}
|
}
|
||||||
cur.data.detailRevision = channel.data.detailRevision;
|
cur.data.detailRevision = channel.data.detailRevision;
|
||||||
}
|
}
|
||||||
@ -151,7 +151,27 @@ export function useChannelContext() {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
setChannelSubject: async (channelId, subject) => {
|
setChannelSubject: async (channelId, subject) => {
|
||||||
return await setChannelSubject(access.current, channelId, subject);
|
return await setChannelSubject(access.current, channelId, 'superbasic', { subject });
|
||||||
|
},
|
||||||
|
setChannelSealedSubject: async (channelId, subject, sealKey) => {
|
||||||
|
const channel = channels.current.get(channelId);
|
||||||
|
|
||||||
|
let { seals, subjectEncrypted, subjectIv } = JSON.parse(channel.data.channelDetail.data);
|
||||||
|
seals.forEach(seal => {
|
||||||
|
if (seal.publicKey === sealKey.public) {
|
||||||
|
let crypto = new JSEncrypt();
|
||||||
|
crypto.setPrivateKey(sealKey.private);
|
||||||
|
const unsealedKey = crypto.decrypt(seal.sealedKey);
|
||||||
|
const key = CryptoJS.enc.Hex.parse(unsealedKey);
|
||||||
|
|
||||||
|
const iv = CryptoJS.lib.WordArray.random(128 / 8);
|
||||||
|
const encrypted = CryptoJS.AES.encrypt(JSON.stringify({ subject }), key, { iv: iv });
|
||||||
|
subjectEncrypted = encrypted.ciphertext.toString(CryptoJS.enc.Base64)
|
||||||
|
subjectIv = iv.toString();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const data = { subjectEncrypted, subjectIv, seals };
|
||||||
|
return await setChannelSubject(access.current, channelId, 'sealed', data);
|
||||||
},
|
},
|
||||||
setChannelCard: async (channelId, cardId) => {
|
setChannelCard: async (channelId, cardId) => {
|
||||||
return await setChannelCard(access.current, channelId, cardId);
|
return await setChannelCard(access.current, channelId, cardId);
|
||||||
|
@ -7,6 +7,7 @@ import { EditOutlined, ExclamationCircleOutlined } from '@ant-design/icons';
|
|||||||
import { CardSelect } from '../cardSelect/CardSelect';
|
import { CardSelect } from '../cardSelect/CardSelect';
|
||||||
import { EditSubject } from './editSubject/EditSubject';
|
import { EditSubject } from './editSubject/EditSubject';
|
||||||
import { EditMembers } from './editMembers/EditMembers';
|
import { EditMembers } from './editMembers/EditMembers';
|
||||||
|
import { UnlockOutlined, LockFilled } from '@ant-design/icons';
|
||||||
|
|
||||||
export function Details({ cardId, channelId, closeDetails, closeConversation, openContact }) {
|
export function Details({ cardId, channelId, closeDetails, closeConversation, openContact }) {
|
||||||
|
|
||||||
@ -117,15 +118,31 @@ export function Details({ cardId, channelId, closeDetails, closeConversation, op
|
|||||||
</div>
|
</div>
|
||||||
<div class="stats">
|
<div class="stats">
|
||||||
{ state.host && (
|
{ state.host && (
|
||||||
<div class="subject edit" onClick={actions.setEditSubject}>
|
<div class="subject" onClick={actions.setEditSubject}>
|
||||||
<Space>
|
{ state.locked && !state.unlocked && (
|
||||||
<div>{ state.subject }</div>
|
<LockFilled style={{ paddingRight: 4 }} />
|
||||||
<EditOutlined />
|
)}
|
||||||
</Space>
|
{ state.locked && state.unlocked && (
|
||||||
|
<UnlockOutlined style={{ paddingRight: 4 }} />
|
||||||
|
)}
|
||||||
|
<span>{ state.subject }</span>
|
||||||
|
{ state.editable && (
|
||||||
|
<span class="edit" onClick={actions.setEditSubject}>
|
||||||
|
<EditOutlined style={{ paddingLeft: 4 }}/>
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{ !state.host && (
|
{ !state.host && (
|
||||||
<div class="subject">{ state.subject }</div>
|
<div class="subject">
|
||||||
|
{ state.locked && !state.unlocked && (
|
||||||
|
<LockFilled style={{ paddingRight: 4 }} />
|
||||||
|
)}
|
||||||
|
{ state.locked && state.unlocked && (
|
||||||
|
<UnlockOutlined style={{ paddingRight: 4 }} />
|
||||||
|
)}
|
||||||
|
<span>{ state.subject }</span>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
{ state.host && (
|
{ state.host && (
|
||||||
<div class="host">host</div>
|
<div class="host">host</div>
|
||||||
@ -139,7 +156,7 @@ export function Details({ cardId, channelId, closeDetails, closeConversation, op
|
|||||||
{ state.host && (
|
{ state.host && (
|
||||||
<div class="button" onClick={deleteChannel}>Delete Topic</div>
|
<div class="button" onClick={deleteChannel}>Delete Topic</div>
|
||||||
)}
|
)}
|
||||||
{ state.host && (
|
{ state.host && !state.locked && (
|
||||||
<div class="button" onClick={actions.setEditMembers}>Edit Membership</div>
|
<div class="button" onClick={actions.setEditMembers}>Edit Membership</div>
|
||||||
)}
|
)}
|
||||||
{ !state.host && (
|
{ !state.host && (
|
||||||
|
@ -90,9 +90,6 @@ export const DetailsWrapper = styled.div`
|
|||||||
padding-left: 16px;
|
padding-left: 16px;
|
||||||
|
|
||||||
.edit {
|
.edit {
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { useContext, useState, useEffect } from 'react';
|
import { useContext, useState, useEffect } from 'react';
|
||||||
import { CardContext } from 'context/CardContext';
|
import { CardContext } from 'context/CardContext';
|
||||||
import { ChannelContext } from 'context/ChannelContext';
|
import { ChannelContext } from 'context/ChannelContext';
|
||||||
|
import { AccountContext } from 'context/AccountContext';
|
||||||
import { ViewportContext } from 'context/ViewportContext';
|
import { ViewportContext } from 'context/ViewportContext';
|
||||||
|
|
||||||
export function useDetails(cardId, channelId) {
|
export function useDetails(cardId, channelId) {
|
||||||
@ -20,9 +21,13 @@ export function useDetails(cardId, channelId) {
|
|||||||
subjectUpdate: null,
|
subjectUpdate: null,
|
||||||
unknown: 0,
|
unknown: 0,
|
||||||
display: null,
|
display: null,
|
||||||
|
locked: false,
|
||||||
|
unlocked: false,
|
||||||
|
editable: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const card = useContext(CardContext);
|
const card = useContext(CardContext);
|
||||||
|
const account = useContext(AccountContext);
|
||||||
const channel = useContext(ChannelContext);
|
const channel = useContext(ChannelContext);
|
||||||
const viewport = useContext(ViewportContext);
|
const viewport = useContext(ViewportContext);
|
||||||
|
|
||||||
@ -35,7 +40,7 @@ export function useDetails(cardId, channelId) {
|
|||||||
}, [viewport]);
|
}, [viewport]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let img, subject, subjectUpdate, host, started, contacts
|
let img, subject, subjectUpdate, host, started, contacts, locked, unlocked, editable;
|
||||||
let chan;
|
let chan;
|
||||||
if (cardId) {
|
if (cardId) {
|
||||||
const cardChan = card.state.cards.get(cardId);
|
const cardChan = card.state.cards.get(cardId);
|
||||||
@ -60,10 +65,34 @@ export function useDetails(cardId, channelId) {
|
|||||||
img = 'team';
|
img = 'team';
|
||||||
subject = 'Conversation'
|
subject = 'Conversation'
|
||||||
}
|
}
|
||||||
const parsed = JSON.parse(chan.data.channelDetail.data);
|
if (chan.data.channelDetail.dataType === 'sealed') {
|
||||||
if (parsed.subject) {
|
editable = false;
|
||||||
subject = parsed.subject;
|
try {
|
||||||
subjectUpdate = subject;
|
const seals = JSON.parse(chan.data.channelDetail.data).seals;
|
||||||
|
seals.forEach(seal => {
|
||||||
|
if (account.state.sealKey.public === seal.publicKey) {
|
||||||
|
editable = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
locked = true;
|
||||||
|
unlocked = chan.data.unsealedChannel != null;
|
||||||
|
if (chan.data.unsealedChannel?.subject) {
|
||||||
|
subject = chan.data.unsealedChannel.subject;
|
||||||
|
subjectUpdate = subject;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
locked = false;
|
||||||
|
editable = (chan.cardId == null);
|
||||||
|
const parsed = JSON.parse(chan.data.channelDetail.data);
|
||||||
|
if (parsed.subject) {
|
||||||
|
subject = parsed.subject;
|
||||||
|
subjectUpdate = subject;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const date = new Date(chan.data.channelDetail.created * 1000);
|
const date = new Date(chan.data.channelDetail.created * 1000);
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
@ -96,8 +125,8 @@ export function useDetails(cardId, channelId) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
updateState({ img, subject, host, started, contacts, members, unknown, subjectUpdate });
|
updateState({ img, subject, host, started, contacts, members, unknown, subjectUpdate, locked, unlocked, editable });
|
||||||
}, [cardId, channelId, card, channel]);
|
}, [cardId, channelId, card, channel, account]);
|
||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
setEditSubject: () => {
|
setEditSubject: () => {
|
||||||
@ -113,7 +142,12 @@ export function useDetails(cardId, channelId) {
|
|||||||
if (!state.busy) {
|
if (!state.busy) {
|
||||||
try {
|
try {
|
||||||
updateState({ busy: true });
|
updateState({ busy: true });
|
||||||
channel.actions.setChannelSubject(channelId, state.subjectUpdate);
|
if (state.locked) {
|
||||||
|
channel.actions.setChannelSealedSubject(channelId, state.subjectUpdate, account.state.sealKey);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
channel.actions.setChannelSubject(channelId, state.subjectUpdate);
|
||||||
|
}
|
||||||
updateState({ busy: false });
|
updateState({ busy: false });
|
||||||
}
|
}
|
||||||
catch(err) {
|
catch(err) {
|
||||||
|
Loading…
Reference in New Issue
Block a user