From e274313f236dc6067e648b03f567b789b5fe2f08 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Wed, 28 Apr 2021 11:49:41 +1000 Subject: [PATCH] add and remove Moderatos opengroupv2 (not yet working server side) --- js/background.js | 32 ------- ts/components/conversation/Message.tsx | 52 +----------- .../conversation/ModeratorsRemoveDialog.tsx | 16 +++- ts/interactions/message.ts | 85 +++++++++++++++++++ ts/opengroup/opengroupV2/OpenGroupAPIV2.ts | 37 ++++++++ ts/session/utils/Toast.tsx | 2 +- 6 files changed, 139 insertions(+), 85 deletions(-) diff --git a/js/background.js b/js/background.js index 297093796..eb8bcef04 100644 --- a/js/background.js +++ b/js/background.js @@ -607,38 +607,6 @@ } }); - Whisper.events.on('publicChatInvitationAccepted', async (serverAddress, channelId) => { - // To some degree this has been copy-pasted - // form connection_to_server_dialog_view.js: - const rawServerUrl = serverAddress.replace(/^https?:\/\//i, '').replace(/[/\\]+$/i, ''); - const sslServerUrl = `https://${rawServerUrl}`; - const conversationId = `publicChat:${channelId}@${rawServerUrl}`; - - const conversationExists = window.getConversationController().get(conversationId); - if (conversationExists) { - window.log.warn('We are already a member of this public chat'); - window.libsession.Utils.ToastUtils.pushAlreadyMemberOpenGroup(); - - return; - } - - const conversation = await window - .getConversationController() - .getOrCreateAndWait(conversationId, 'group'); - await conversation.setPublicSource(sslServerUrl, channelId); - - const channelAPI = await window.lokiPublicChatAPI.findOrCreateChannel( - sslServerUrl, - channelId, - conversationId - ); - if (!channelAPI) { - window.log.warn(`Could not connect to ${serverAddress}`); - return; - } - window.inboxStore.dispatch(window.actionsCreators.openConversationExternal(conversationId)); - }); - Whisper.events.on('leaveGroup', async groupConvo => { if (appView) { appView.showLeaveGroupDialog(groupConvo); diff --git a/ts/components/conversation/Message.tsx b/ts/components/conversation/Message.tsx index 9d31b7e80..45c78243b 100644 --- a/ts/components/conversation/Message.tsx +++ b/ts/components/conversation/Message.tsx @@ -74,6 +74,7 @@ import { ToastUtils, UserUtils } from '../../session/utils'; import { ConversationController } from '../../session/conversations'; import { MessageRegularProps } from '../../models/messageType'; import { useEncryptedFileFetch } from '../../hooks/useEncryptedFileFetch'; +import { addSenderAsModerator, removeSenderFromModerator } from '../../interactions/message'; // Same as MIN_WIDTH in ImageGrid.tsx const MINIMUM_LINK_PREVIEW_IMAGE_WIDTH = 200; @@ -899,58 +900,11 @@ class MessageInner extends React.PureComponent { } private async onAddModerator() { - const { authorPhoneNumber: pubkey, convoId } = this.props; - try { - const convo = ConversationController.getInstance().getOrThrow(convoId); - const channelAPI = await convo.getPublicSendData(); - if (!channelAPI) { - throw new Error('No channelAPI'); - } - if (!channelAPI.serverAPI) { - throw new Error('No serverAPI'); - } - const res = await channelAPI.serverAPI.addModerator([pubkey]); - if (!res) { - window.log.warn('failed to add moderators:', res); - - ToastUtils.pushUserNeedsToHaveJoined(); - } else { - window.log.info(`${pubkey} added as moderator...`); - // refresh the moderator list. Will trigger a refresh - const modPubKeys = await channelAPI.getModerators(); - await convo.updateGroupAdmins(modPubKeys); - - ToastUtils.pushUserAddedToModerators(); - } - } catch (e) { - window.log.error('Got error while adding moderator:', e); - } + await addSenderAsModerator(this.props.authorPhoneNumber, this.props.convoId); } private async onRemoveFromModerator() { - const { authorPhoneNumber: pubkey, convoId } = this.props; - try { - const convo = ConversationController.getInstance().getOrThrow(convoId); - const channelAPI = await convo.getPublicSendData(); - if (!channelAPI) { - throw new Error('No channelAPI'); - } - const res = await channelAPI.serverAPI.removeModerators([pubkey]); - if (!res) { - window.log.warn('failed to remove moderators:', res); - - ToastUtils.pushErrorHappenedWhileRemovingModerator(); - } else { - // refresh the moderator list. Will trigger a refresh - const modPubKeys = await channelAPI.getModerators(); - await convo.updateGroupAdmins(modPubKeys); - - window.log.info(`${pubkey} removed from moderators...`); - ToastUtils.pushUserRemovedToModerators(); - } - } catch (e) { - window.log.error('Got error while removing moderator:', e); - } + await removeSenderFromModerator(this.props.authorPhoneNumber, this.props.convoId); } } diff --git a/ts/components/conversation/ModeratorsRemoveDialog.tsx b/ts/components/conversation/ModeratorsRemoveDialog.tsx index faec7d87d..a8ce6d0d5 100644 --- a/ts/components/conversation/ModeratorsRemoveDialog.tsx +++ b/ts/components/conversation/ModeratorsRemoveDialog.tsx @@ -1,13 +1,16 @@ import React from 'react'; import { DefaultTheme } from 'styled-components'; import { ConversationModel } from '../../models/conversation'; +import { ApiV2 } from '../../opengroup/opengroupV2'; import { ConversationController } from '../../session/conversations'; +import { PubKey } from '../../session/types'; import { ToastUtils } from '../../session/utils'; import { Flex } from '../session/Flex'; import { SessionButton, SessionButtonColor, SessionButtonType } from '../session/SessionButton'; import { ContactType, SessionMemberListItem } from '../session/SessionMemberListItem'; import { SessionModal } from '../session/SessionModal'; import { SessionSpinner } from '../session/SessionSpinner'; +import _ from 'lodash'; interface Props { convo: ConversationModel; onClose: any; @@ -197,8 +200,15 @@ export class RemoveModeratorsDialog extends React.Component { if (this.props.convo.isOpenGroupV1()) { res = await this.channelAPI.serverAPI.removeModerators(removedMods); } else if (this.props.convo.isOpenGroupV2()) { - // FIXME audric removeModerators opengroupv2 - throw new Error('removeModerators opengroupv2 TODO'); + const roomInfos = this.props.convo.toOpenGroupV2(); + const modsToRemove = _.compact(removedMods.map(m => PubKey.from(m))); + res = await Promise.all( + modsToRemove.map(async m => { + return ApiV2.removeModerator(m, roomInfos); + }) + ); + // all moderators are removed means all promise resolved with bool= true + res = res.every(r => !!r); } if (!res) { window.log.warn('failed to remove moderators:', res); @@ -206,7 +216,7 @@ export class RemoveModeratorsDialog extends React.Component { ToastUtils.pushUserNeedsToHaveJoined(); } else { window.log.info(`${removedMods} removed from moderators...`); - ToastUtils.pushUserRemovedToModerators(); + ToastUtils.pushUserRemovedFromModerators(); } } catch (e) { window.log.error('Got error while adding moderator:', e); diff --git a/ts/interactions/message.ts b/ts/interactions/message.ts index 350cfbcaa..1b06c0641 100644 --- a/ts/interactions/message.ts +++ b/ts/interactions/message.ts @@ -3,6 +3,7 @@ import { getV2OpenGroupRoom } from '../data/opengroups'; import { ConversationModel } from '../models/conversation'; import { ApiV2 } from '../opengroup/opengroupV2'; import { isOpenGroupV2 } from '../opengroup/utils/OpenGroupUtils'; +import { ConversationController } from '../session/conversations'; import { PubKey } from '../session/types'; import { ToastUtils } from '../session/utils'; @@ -105,3 +106,87 @@ export function copyPubKey(sender: string) { ToastUtils.pushCopiedToClipBoard(); } + +export async function removeSenderFromModerator(sender: string, convoId: string) { + try { + const pubKeyToRemove = PubKey.cast(sender); + const convo = ConversationController.getInstance().getOrThrow(convoId); + if (convo.isOpenGroupV1()) { + const channelAPI = await convo.getPublicSendData(); + if (!channelAPI) { + throw new Error('No channelAPI'); + } + const res = await channelAPI.serverAPI.removeModerators([pubKeyToRemove.key]); + if (!res) { + window.log.warn('failed to remove moderators:', res); + + ToastUtils.pushErrorHappenedWhileRemovingModerator(); + } else { + // refresh the moderator list. Will trigger a refresh + const modPubKeys = await channelAPI.getModerators(); + await convo.updateGroupAdmins(modPubKeys); + + window.log.info(`${pubKeyToRemove.key} removed from moderators...`); + ToastUtils.pushUserRemovedFromModerators(); + } + } else if (convo.isOpenGroupV2()) { + // FXIME audric removeModerator not working serverside + const roomInfo = convo.toOpenGroupV2(); + const res = await ApiV2.removeModerator(pubKeyToRemove, roomInfo); + if (!res) { + window.log.warn('failed to remove moderator:', res); + + ToastUtils.pushErrorHappenedWhileRemovingModerator(); + } else { + window.log.info(`${pubKeyToRemove.key} removed from moderators...`); + ToastUtils.pushUserRemovedFromModerators(); + } + } + } catch (e) { + window.log.error('Got error while removing moderator:', e); + } +} + +export async function addSenderAsModerator(sender: string, convoId: string) { + try { + const pubKeyToRemove = PubKey.cast(sender); + + const convo = ConversationController.getInstance().getOrThrow(convoId); + if (convo.isOpenGroupV1()) { + const channelAPI = await convo.getPublicSendData(); + if (!channelAPI) { + throw new Error('No channelAPI'); + } + if (!channelAPI.serverAPI) { + throw new Error('No serverAPI'); + } + const res = await channelAPI.serverAPI.addModerator([pubKeyToRemove.key]); + if (!res) { + window.log.warn('failed to add moderators:', res); + + ToastUtils.pushUserNeedsToHaveJoined(); + } else { + window.log.info(`${pubKeyToRemove.key} added as moderator...`); + // refresh the moderator list. Will trigger a refresh + const modPubKeys = await channelAPI.getModerators(); + await convo.updateGroupAdmins(modPubKeys); + + ToastUtils.pushUserAddedToModerators(); + } + } else if (convo.isOpenGroupV2()) { + // FXIME audric addModerator not working serverside + const roomInfo = convo.toOpenGroupV2(); + const res = await ApiV2.addModerator(pubKeyToRemove, roomInfo); + if (!res) { + window.log.warn('failed to add moderator:', res); + + ToastUtils.pushUserNeedsToHaveJoined(); + } else { + window.log.info(`${pubKeyToRemove.key} removed from moderators...`); + ToastUtils.pushUserAddedToModerators(); + } + } + } catch (e) { + window.log.error('Got error while adding moderator:', e); + } +} diff --git a/ts/opengroup/opengroupV2/OpenGroupAPIV2.ts b/ts/opengroup/opengroupV2/OpenGroupAPIV2.ts index 0aa0310e2..13e136eb4 100644 --- a/ts/opengroup/opengroupV2/OpenGroupAPIV2.ts +++ b/ts/opengroup/opengroupV2/OpenGroupAPIV2.ts @@ -630,3 +630,40 @@ export const uploadImageForRoomOpenGroupV2 = async ( fileUrl, }; }; + +/** MODERATORS ADD/REMOVE */ + +export const addModerator = async ( + userToAddAsMods: PubKey, + roomInfos: OpenGroupRequestCommonType +): Promise => { + const request: OpenGroupV2Request = { + method: 'POST', + room: roomInfos.roomId, + server: roomInfos.serverUrl, + isAuthRequired: true, + queryParams: { public_key: userToAddAsMods.key }, + endpoint: 'moderators', + }; + const addModResult = await sendOpenGroupV2Request(request); + const isOk = parseStatusCodeFromOnionRequest(addModResult) === 200; + console.warn('addModResult', addModResult); + return isOk; +}; + +export const removeModerator = async ( + userToAddAsMods: PubKey, + roomInfos: OpenGroupRequestCommonType +): Promise => { + const request: OpenGroupV2Request = { + method: 'DELETE', + room: roomInfos.roomId, + server: roomInfos.serverUrl, + isAuthRequired: true, + endpoint: `moderators/${userToAddAsMods.key}`, + }; + const removeModResult = await sendOpenGroupV2Request(request); + const isOk = parseStatusCodeFromOnionRequest(removeModResult) === 200; + console.warn('removeModResult', removeModResult); + return isOk; +}; diff --git a/ts/session/utils/Toast.tsx b/ts/session/utils/Toast.tsx index 14cfcadd7..520ed8099 100644 --- a/ts/session/utils/Toast.tsx +++ b/ts/session/utils/Toast.tsx @@ -195,7 +195,7 @@ export function pushUserAddedToModerators() { pushToastSuccess('userAddedToModerators', window.i18n('userAddedToModerators')); } -export function pushUserRemovedToModerators() { +export function pushUserRemovedFromModerators() { pushToastSuccess('userRemovedFromModerators', window.i18n('userRemovedFromModerators')); }