From ba74a41fd27e17a6560df6f0f88e198ada82b72f Mon Sep 17 00:00:00 2001 From: Guilherme Leme Date: Mon, 10 Jun 2024 11:32:48 -0300 Subject: [PATCH 1/5] [update-data-channel-function] - (WIP) Initial work --- ...PluginDataChannelReplaceEntryMsgHdlr.scala | 55 +++++++++++++++++++ .../core/apps/plugin/PluginHdlrs.scala | 1 + .../core/db/PluginDataChannelEntryDAO.scala | 41 +++++++++++++- .../senders/ReceivedJsonMsgHandlerActor.scala | 3 + .../core/running/MeetingActor.scala | 1 + .../common2/msgs/PluginMsgs.scala | 28 +++++++--- .../actions/pluginDataChannelDeleteEntry.ts | 2 +- .../actions/pluginDataChannelReplaceEntry.ts | 38 +++++++++++++ bbb-graphql-server/metadata/actions.graphql | 10 ++++ bbb-graphql-server/metadata/actions.yaml | 6 ++ .../channel-manager/writer-manager.tsx | 40 +++++++++++--- .../plugins-engine/data-channel/mutations.ts | 14 +++++ 12 files changed, 218 insertions(+), 21 deletions(-) create mode 100755 akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/plugin/PluginDataChannelReplaceEntryMsgHdlr.scala create mode 100644 bbb-graphql-actions/src/actions/pluginDataChannelReplaceEntry.ts diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/plugin/PluginDataChannelReplaceEntryMsgHdlr.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/plugin/PluginDataChannelReplaceEntryMsgHdlr.scala new file mode 100755 index 0000000000..e82d5b069f --- /dev/null +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/plugin/PluginDataChannelReplaceEntryMsgHdlr.scala @@ -0,0 +1,55 @@ +package org.bigbluebutton.core.apps.plugin + +import org.bigbluebutton.ClientSettings +import org.bigbluebutton.common2.msgs.PluginDataChannelReplaceEntryMsg +import org.bigbluebutton.core.db.{JsonUtils, PluginDataChannelEntryDAO} +import org.bigbluebutton.core.domain.MeetingState2x +import org.bigbluebutton.core.models.{Roles, Users2x} +import org.bigbluebutton.core.running.{HandlerHelpers, LiveMeeting} + +trait PluginDataChannelReplaceEntryMsgHdlr extends HandlerHelpers { + + def handle(msg: PluginDataChannelReplaceEntryMsg, state: MeetingState2x, liveMeeting: LiveMeeting): Unit = { + val pluginsDisabled: Boolean = liveMeeting.props.meetingProp.disabledFeatures.contains("plugins") + val meetingId = liveMeeting.props.meetingProp.intId + + for { + _ <- if (!pluginsDisabled) Some(()) else None + user <- Users2x.findWithIntId(liveMeeting.users2x, msg.header.userId) + } yield { + val pluginsConfig = ClientSettings.getPluginsFromConfig(ClientSettings.clientSettingsFromFile) + + if (!pluginsConfig.contains(msg.body.pluginName)) { + println(s"Plugin '${msg.body.pluginName}' not found.") + } else if (!pluginsConfig(msg.body.pluginName).dataChannels.contains(msg.body.channelName)) { + println(s"Data channel '${msg.body.channelName}' not found in plugin '${msg.body.pluginName}'.") + } else { + val hasPermission = for { + writePermission <- pluginsConfig(msg.body.pluginName).dataChannels(msg.body.channelName).writePermission + } yield { + writePermission.toLowerCase match { + case "all" => true + case "moderator" => user.role == Roles.MODERATOR_ROLE + case "presenter" => user.presenter + case _ => false + } + } + + println(s"\n\n\n\n\n teste ---> ${msg.body.payloadJson}") + + if (!hasPermission.contains(true)) { + println(s"No permission to write in plugin: '${msg.body.pluginName}', data channel: '${msg.body.channelName}'.") + } else { + PluginDataChannelEntryDAO.replace( + msg.header.meetingId, + msg.body.pluginName, + msg.body.channelName, + msg.body.subChannelName, + msg.body.entryId, + JsonUtils.mapToJson(msg.body.payloadJson), + ) + } + } + } + } +} diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/plugin/PluginHdlrs.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/plugin/PluginHdlrs.scala index d9f8bb78f8..d1dbf285fc 100644 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/plugin/PluginHdlrs.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/plugin/PluginHdlrs.scala @@ -6,6 +6,7 @@ import org.bigbluebutton.common2.msgs.PluginDataChannelDeleteEntryMsgBody class PluginHdlrs(implicit val context: ActorContext) extends PluginDataChannelPushEntryMsgHdlr + with PluginDataChannelReplaceEntryMsgHdlr with PluginDataChannelDeleteEntryMsgHdlr with PluginDataChannelResetMsgHdlr { diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/db/PluginDataChannelEntryDAO.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/db/PluginDataChannelEntryDAO.scala index 424b91ea17..4a57d260ef 100644 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/db/PluginDataChannelEntryDAO.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/db/PluginDataChannelEntryDAO.scala @@ -2,6 +2,7 @@ package org.bigbluebutton.core.db import PostgresProfile.api._ import org.bigbluebutton.core.db.DatabaseConnection.{db, logger} +import org.bigbluebutton.core.util.RandomStringGenerator import spray.json.JsValue import scala.concurrent.ExecutionContext.Implicits.global @@ -18,7 +19,7 @@ case class PluginDataChannelEntryDbModel( pluginName: String, channelName: String, subChannelName: String, -// entryId: Option[String] = None, + entryId: Option[String] = None, payloadJson: JsValue, fromUserId: String, toRoles: Option[List[String]], @@ -32,14 +33,14 @@ class PluginDataChannelEntryDbTableDef(tag: Tag) extends Table[PluginDataChannel val pluginName = column[String]("pluginName", O.PrimaryKey) val channelName = column[String]("channelName", O.PrimaryKey) val subChannelName = column[String]("subChannelName") -// val entryId = column[Option[String]]("messageId", O.PrimaryKey) //// The messageId is generated by the database + val entryId = column[Option[String]]("entryId", O.PrimaryKey) val payloadJson = column[JsValue]("payloadJson") val fromUserId = column[String]("fromUserId") val toRoles = column[Option[List[String]]]("toRoles") val toUserIds = column[Option[List[String]]]("toUserIds") val createdAt = column[java.sql.Timestamp]("createdAt") val deletedAt = column[Option[java.sql.Timestamp]]("deletedAt") - override def * = (meetingId, pluginName, channelName, subChannelName, payloadJson, fromUserId, toRoles, toUserIds, createdAt, deletedAt) <> (PluginDataChannelEntryDbModel.tupled, PluginDataChannelEntryDbModel.unapply) + override def * = (meetingId, pluginName, channelName, subChannelName, entryId, payloadJson, fromUserId, toRoles, toUserIds, createdAt, deletedAt) <> (PluginDataChannelEntryDbModel.tupled, PluginDataChannelEntryDbModel.unapply) } object PluginDataChannelEntryDAO { @@ -48,6 +49,7 @@ object PluginDataChannelEntryDAO { DatabaseConnection.db.run( TableQuery[PluginDataChannelEntryDbTableDef].forceInsert( PluginDataChannelEntryDbModel( + entryId = Some(RandomStringGenerator.randomAlphanumericString(50)), meetingId = meetingId, pluginName = pluginName, channelName = channelName, @@ -123,4 +125,37 @@ object PluginDataChannelEntryDAO { } } + def replace(meetingId: String, pluginName: String, channelName: String, + subChannelName: String, entryId: String, payloadJson: JsValue) = { + + DatabaseConnection.db.run( + TableQuery[PluginDataChannelEntryDbTableDef] + .filter(_.meetingId === meetingId) + .filter(_.pluginName === pluginName) + .filter(_.channelName === channelName) + .filter(_.subChannelName === subChannelName) + .filter(_.entryId === entryId) + .filter(_.deletedAt.isEmpty) + .map(_.payloadJson) + .update(payloadJson) + ).onComplete { + case Success(rowsAffected) => DatabaseConnection.logger.debug(s"$rowsAffected row(s) updated with new payloadJson on pluginDataChannelEntry table!") + case Failure(e) => DatabaseConnection.logger.debug(s"Error updating with new payloadJson for table pluginDataChannelEntry: $e") + } + +// DatabaseConnection.db.run( +// sqlu"""UPDATE "pluginDataChannelEntry" SET +// "payloadJson" = payloadJson +// WHERE "deletedAt" is null +// AND "meetingId" = ${meetingId} +// AND "pluginName" = ${pluginName} +// AND "channelName" = ${channelName} +// AND "subChannelName" = ${subChannelName} +// AND "entryId" = ${entryId}""" +// ).onComplete { +// case Success(rowsAffected) => DatabaseConnection.logger.debug(s"$rowsAffected row(s) updated with new payloadJson on pluginDataChannelEntry table!") +// case Failure(e) => DatabaseConnection.logger.debug(s"Error updating with new payloadJson for table pluginDataChannelEntry: $e") +// } + } + } \ No newline at end of file diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala index 035897c4d8..702c5642bc 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala @@ -418,6 +418,9 @@ class ReceivedJsonMsgHandlerActor( case PluginDataChannelPushEntryMsg.NAME => routeGenericMsg[PluginDataChannelPushEntryMsg](envelope, jsonNode) + case PluginDataChannelReplaceEntryMsg.NAME => + routeGenericMsg[PluginDataChannelReplaceEntryMsg](envelope, jsonNode) + case PluginDataChannelDeleteEntryMsg.NAME => routeGenericMsg[PluginDataChannelDeleteEntryMsg](envelope, jsonNode) diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala index ac8aee1f3b..7dfc9dd9d5 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala @@ -643,6 +643,7 @@ class MeetingActor( // Plugin case m: PluginDataChannelPushEntryMsg => pluginHdlrs.handle(m, state, liveMeeting) + case m: PluginDataChannelReplaceEntryMsg => pluginHdlrs.handle(m, state, liveMeeting) case m: PluginDataChannelDeleteEntryMsg => pluginHdlrs.handle(m, state, liveMeeting) case m: PluginDataChannelResetMsg => pluginHdlrs.handle(m, state, liveMeeting) diff --git a/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/PluginMsgs.scala b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/PluginMsgs.scala index 9e4aef15b6..e4ba5e601b 100755 --- a/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/PluginMsgs.scala +++ b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/PluginMsgs.scala @@ -16,20 +16,30 @@ case class PluginDataChannelPushEntryMsgBody( toUserIds: List[String], ) +object PluginDataChannelReplaceEntryMsg { val NAME = "PluginDataChannelReplaceEntryMsg" } +case class PluginDataChannelReplaceEntryMsg(header: BbbClientMsgHeader, body: PluginDataChannelReplaceEntryMsgBody) extends StandardMsg +case class PluginDataChannelReplaceEntryMsgBody( + pluginName: String, + channelName: String, + subChannelName: String, + payloadJson: Map[String, Any], + entryId: String, + ) + object PluginDataChannelDeleteEntryMsg { val NAME = "PluginDataChannelDeleteEntryMsg" } case class PluginDataChannelDeleteEntryMsg(header: BbbClientMsgHeader, body: PluginDataChannelDeleteEntryMsgBody) extends StandardMsg case class PluginDataChannelDeleteEntryMsgBody( - pluginName: String, - subChannelName: String, - channelName: String, - entryId: String - ) + pluginName: String, + subChannelName: String, + channelName: String, + entryId: String + ) object PluginDataChannelResetMsg { val NAME = "PluginDataChannelResetMsg" } case class PluginDataChannelResetMsg(header: BbbClientMsgHeader, body: PluginDataChannelResetMsgBody) extends StandardMsg case class PluginDataChannelResetMsgBody( - pluginName: String, - subChannelName: String, - channelName: String - ) + pluginName: String, + subChannelName: String, + channelName: String + ) diff --git a/bbb-graphql-actions/src/actions/pluginDataChannelDeleteEntry.ts b/bbb-graphql-actions/src/actions/pluginDataChannelDeleteEntry.ts index 71e4c5ba40..5aae2a066e 100644 --- a/bbb-graphql-actions/src/actions/pluginDataChannelDeleteEntry.ts +++ b/bbb-graphql-actions/src/actions/pluginDataChannelDeleteEntry.ts @@ -11,7 +11,7 @@ export default function buildRedisMessage(sessionVariables: Record, input: Record): RedisMessage { + throwErrorIfInvalidInput(input, + [ + {name: 'pluginName', type: 'string', required: true}, + {name: 'subChannelName', type: 'string', required: true}, + {name: 'channelName', type: 'string', required: true}, + {name: 'payloadJson', type: 'json', required: true}, + {name: 'entryId', type: 'string', required: true}, + ] + ) + + const eventName = `PluginDataChannelReplaceEntryMsg`; + + const routing = { + meetingId: sessionVariables['x-hasura-meetingid'] as String, + userId: sessionVariables['x-hasura-userid'] as String + }; + + const header = { + name: eventName, + meetingId: routing.meetingId, + userId: routing.userId + }; + + const body = { + pluginName: input.pluginName, + channelName: input.channelName, + subChannelName: input.subChannelName, + payloadJson: input.payloadJson, + entryId: input.entryId, + }; + + return { eventName, routing, header, body }; +} diff --git a/bbb-graphql-server/metadata/actions.graphql b/bbb-graphql-server/metadata/actions.graphql index f1d232c9a9..17b3ba45cc 100644 --- a/bbb-graphql-server/metadata/actions.graphql +++ b/bbb-graphql-server/metadata/actions.graphql @@ -227,6 +227,16 @@ type Mutation { ): Boolean } +type Mutation { + pluginDataChannelReplaceEntry( + pluginName: String! + subChannelName: String! + channelName: String! + entryId: String! + payloadJson: String! + ): Boolean +} + type Mutation { pluginDataChannelReset( pluginName: String! diff --git a/bbb-graphql-server/metadata/actions.yaml b/bbb-graphql-server/metadata/actions.yaml index 36a41463ce..bf6bb5980d 100644 --- a/bbb-graphql-server/metadata/actions.yaml +++ b/bbb-graphql-server/metadata/actions.yaml @@ -197,6 +197,12 @@ actions: handler: '{{HASURA_BBB_GRAPHQL_ACTIONS_ADAPTER_URL}}' permissions: - role: bbb_client + - name: pluginDataChannelReplaceEntry + definition: + kind: synchronous + handler: '{{HASURA_BBB_GRAPHQL_ACTIONS_ADAPTER_URL}}' + permissions: + - role: bbb_client - name: pluginDataChannelReset definition: kind: synchronous diff --git a/bigbluebutton-html5/imports/ui/components/plugins-engine/data-channel/channel-manager/writer-manager.tsx b/bigbluebutton-html5/imports/ui/components/plugins-engine/data-channel/channel-manager/writer-manager.tsx index 7fd8c65c86..a67a1f6e76 100644 --- a/bigbluebutton-html5/imports/ui/components/plugins-engine/data-channel/channel-manager/writer-manager.tsx +++ b/bigbluebutton-html5/imports/ui/components/plugins-engine/data-channel/channel-manager/writer-manager.tsx @@ -5,12 +5,16 @@ import * as PluginSdk from 'bigbluebutton-html-plugin-sdk'; import { DataChannelArguments, PushEntryFunction, ObjectTo, ToRole, ToUserId, + ReplaceEntryFunctionArguments, } from 'bigbluebutton-html-plugin-sdk/dist/cjs/data-channel/types'; import { DataChannelHooks } from 'bigbluebutton-html-plugin-sdk/dist/cjs/data-channel/enums'; import { HookEvents } from 'bigbluebutton-html-plugin-sdk/dist/cjs/core/enum'; import { HookEventWrapper, UpdatedEventDetails } from 'bigbluebutton-html-plugin-sdk/dist/cjs/core/types'; -import { PLUGIN_DATA_CHANNEL_DELETE_MUTATION, PLUGIN_DATA_CHANNEL_PUSH_MUTATION, PLUGIN_DATA_CHANNEL_RESET_MUTATION } from '../mutations'; +import { + PLUGIN_DATA_CHANNEL_DELETE_MUTATION, PLUGIN_DATA_CHANNEL_PUSH_MUTATION, + PLUGIN_DATA_CHANNEL_REPLACE_MUTATION, PLUGIN_DATA_CHANNEL_RESET_MUTATION, +} from '../mutations'; export interface DataChannelItemManagerWriterProps { pluginName: string; @@ -46,9 +50,10 @@ const DataChannelItemManagerWriter: React.ElementType { const argumentsOfPushEntryFunction = { @@ -82,7 +87,7 @@ const DataChannelItemManagerWriter: React.ElementType 0) argumentsOfPushEntryFunction.variables.toRoles = rolesTo; if (usersTo.length > 0) argumentsOfPushEntryFunction.variables.toUserIds = usersTo; } - pushEntryFunctionPluginDataChannelMessage(argumentsOfPushEntryFunction); + pushEntryFunctionPluginDataChannel(argumentsOfPushEntryFunction); }) as PushEntryFunction; pluginApi.mapOfPushEntryFunctions[dataChannelIdentifier] = useDataChannelHandlerFunction; @@ -93,18 +98,18 @@ const DataChannelItemManagerWriter: React.ElementType; const hookArguments = eventDetails?.hookArguments as DataChannelArguments | undefined; - deleteEntryFunctionPluginDataChannelMessage({ + deleteEntryFunctionPluginDataChannel({ variables: { pluginName: hookArguments?.pluginName, channelName: hookArguments?.channelName, - messageId: eventDetails.data, + entryId: eventDetails.data, subChannelName, }, }); } else if (event.detail.hook === DataChannelHooks.DATA_CHANNEL_RESET) { const eventDetails = event.detail as UpdatedEventDetails; const hookArguments = eventDetails?.hookArguments as DataChannelArguments | undefined; - resetFunctionPluginDataChannelMessage({ + resetFunctionPluginDataChannel({ variables: { pluginName: hookArguments?.pluginName, channelName: hookArguments?.channelName, @@ -114,10 +119,29 @@ const DataChannelItemManagerWriter: React.ElementType) => { + if (event.detail.hook === DataChannelHooks.DATA_CHANNEL_REPLACE) { + const eventDetails = event.detail as UpdatedEventDetails>; + const hookArguments = eventDetails?.hookArguments as DataChannelArguments | undefined; + replaceEntryFunctionPluginDataChannel({ + variables: { + pluginName: hookArguments?.pluginName, + channelName: hookArguments?.channelName, + subChannelName: hookArguments?.subChannelName, + entryId: eventDetails.data.entryId, + payloadJson: eventDetails.data.payloadJson, + }, + }); + } + }) as EventListener; + useEffect(() => { window.addEventListener(HookEvents.UPDATED, deleteOrResetHandler); + window.addEventListener(HookEvents.UPDATED, replaceEntryHandler); return () => { window.removeEventListener(HookEvents.UPDATED, deleteOrResetHandler); + window.removeEventListener(HookEvents.UPDATED, replaceEntryHandler); }; }, []); return null; diff --git a/bigbluebutton-html5/imports/ui/components/plugins-engine/data-channel/mutations.ts b/bigbluebutton-html5/imports/ui/components/plugins-engine/data-channel/mutations.ts index d93a0aa137..8a4f562cd6 100644 --- a/bigbluebutton-html5/imports/ui/components/plugins-engine/data-channel/mutations.ts +++ b/bigbluebutton-html5/imports/ui/components/plugins-engine/data-channel/mutations.ts @@ -36,3 +36,17 @@ export const PLUGIN_DATA_CHANNEL_DELETE_MUTATION = gql` ) } `; + +export const PLUGIN_DATA_CHANNEL_REPLACE_MUTATION = gql` + mutation PluginDataChannelReplaceEntry($pluginName: String!, + $subChannelName: String!, $channelName: String!, + $payloadJson: json!, $entryId: String!) { + pluginDataChannelReplaceEntry( + entryId: $entryId, + pluginName: $pluginName, + channelName: $channelName, + subChannelName: $subChannelName, + payloadJson: $payloadJson + ) + } +`; From 59d08a26552b98a3a55d5f4958bd1f1d27b3d353 Mon Sep 17 00:00:00 2001 From: Guilherme Leme Date: Mon, 10 Jun 2024 17:45:14 -0300 Subject: [PATCH 2/5] [update-data-channel-function] - remove debbuging logs --- .../PluginDataChannelReplaceEntryMsgHdlr.scala | 2 -- .../core/db/PluginDataChannelEntryDAO.scala | 14 -------------- 2 files changed, 16 deletions(-) diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/plugin/PluginDataChannelReplaceEntryMsgHdlr.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/plugin/PluginDataChannelReplaceEntryMsgHdlr.scala index e82d5b069f..b9b6bb430f 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/plugin/PluginDataChannelReplaceEntryMsgHdlr.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/plugin/PluginDataChannelReplaceEntryMsgHdlr.scala @@ -35,8 +35,6 @@ trait PluginDataChannelReplaceEntryMsgHdlr extends HandlerHelpers { } } - println(s"\n\n\n\n\n teste ---> ${msg.body.payloadJson}") - if (!hasPermission.contains(true)) { println(s"No permission to write in plugin: '${msg.body.pluginName}', data channel: '${msg.body.channelName}'.") } else { diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/db/PluginDataChannelEntryDAO.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/db/PluginDataChannelEntryDAO.scala index 4a57d260ef..1e48a8d6e0 100644 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/db/PluginDataChannelEntryDAO.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/db/PluginDataChannelEntryDAO.scala @@ -142,20 +142,6 @@ object PluginDataChannelEntryDAO { case Success(rowsAffected) => DatabaseConnection.logger.debug(s"$rowsAffected row(s) updated with new payloadJson on pluginDataChannelEntry table!") case Failure(e) => DatabaseConnection.logger.debug(s"Error updating with new payloadJson for table pluginDataChannelEntry: $e") } - -// DatabaseConnection.db.run( -// sqlu"""UPDATE "pluginDataChannelEntry" SET -// "payloadJson" = payloadJson -// WHERE "deletedAt" is null -// AND "meetingId" = ${meetingId} -// AND "pluginName" = ${pluginName} -// AND "channelName" = ${channelName} -// AND "subChannelName" = ${subChannelName} -// AND "entryId" = ${entryId}""" -// ).onComplete { -// case Success(rowsAffected) => DatabaseConnection.logger.debug(s"$rowsAffected row(s) updated with new payloadJson on pluginDataChannelEntry table!") -// case Failure(e) => DatabaseConnection.logger.debug(s"Error updating with new payloadJson for table pluginDataChannelEntry: $e") -// } } } \ No newline at end of file From 6e4e015d28968e4493474bb49d0e41978b3bd57b Mon Sep 17 00:00:00 2001 From: Guilherme Leme Date: Tue, 11 Jun 2024 11:53:28 -0300 Subject: [PATCH 3/5] [update-data-channel-function] update plugin SDK --- bigbluebutton-html5/package-lock.json | 6 +++--- bigbluebutton-html5/package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bigbluebutton-html5/package-lock.json b/bigbluebutton-html5/package-lock.json index 820241a428..6f67fdb694 100644 --- a/bigbluebutton-html5/package-lock.json +++ b/bigbluebutton-html5/package-lock.json @@ -3322,9 +3322,9 @@ "dev": true }, "bigbluebutton-html-plugin-sdk": { - "version": "0.0.48", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.48.tgz", - "integrity": "sha512-t6z8zc5NkXKWXDVRqddxMCVOuIHVfDnPlpehW/JyskSJXED6ET0dVaRi3heiRh8PfsKP729xpnusqpg9/QE2RA==", + "version": "0.0.50", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.50.tgz", + "integrity": "sha512-LTyEBATF1e4Ky96EYvdrEZXsIqXUu3IZm5AntRKP+5Xk/KsXhm13vRZolLZNvg6CQBTUUNSTM0mfbRqj5stK7g==", "requires": { "@apollo/client": "^3.8.7", "@browser-bunyan/console-formatted-stream": "^1.8.0", diff --git a/bigbluebutton-html5/package.json b/bigbluebutton-html5/package.json index 37a1e2b12c..2c668ecfd2 100644 --- a/bigbluebutton-html5/package.json +++ b/bigbluebutton-html5/package.json @@ -47,7 +47,7 @@ "autoprefixer": "^10.4.4", "axios": "^1.6.4", "babel-runtime": "~6.26.0", - "bigbluebutton-html-plugin-sdk": "0.0.48", + "bigbluebutton-html-plugin-sdk": "0.0.50", "bowser": "^2.11.0", "browser-bunyan": "^1.8.0", "classnames": "^2.2.6", From 8464fca7da047157f894578be8a91cc505c6b09c Mon Sep 17 00:00:00 2001 From: Guilherme Leme Date: Tue, 18 Jun 2024 11:24:49 -0300 Subject: [PATCH 4/5] [update-data-channel-function] - changes permissioning name --- .../org/bigbluebutton/ClientSettings.scala | 22 +++++++++---------- .../PluginDataChannelDeleteEntryMsgHdlr.scala | 4 ++-- .../PluginDataChannelPushEntryMsgHdlr.scala | 4 ++-- ...PluginDataChannelReplaceEntryMsgHdlr.scala | 16 +++++++++++--- .../PluginDataChannelResetMsgHdlr.scala | 4 ++-- 5 files changed, 30 insertions(+), 20 deletions(-) diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/ClientSettings.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/ClientSettings.scala index bec18e1f6a..afee8869b3 100644 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/ClientSettings.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/ClientSettings.scala @@ -140,26 +140,26 @@ object ClientSettings extends SystemConfiguration { } yield { if (dataChannel.contains("name")) { val channelName = dataChannel("name").toString - val writePermission = { - if (dataChannel.contains("writePermission")) { - dataChannel("writePermission") match { + val pushPermission = { + if (dataChannel.contains("pushPermission")) { + dataChannel("pushPermission") match { case wPerm: List[String] => wPerm case _ => { - logger.warn(s"Invalid writePermission for channel $channelName in plugin $pluginName") + logger.warn(s"Invalid pushPermission for channel $channelName in plugin $pluginName") List() } } } else { - logger.warn(s"Missing config writePermission for channel $channelName in plugin $pluginName") + logger.warn(s"Missing config pushPermission for channel $channelName in plugin $pluginName") List() } } - val deletePermission = { - if (dataChannel.contains("deletePermission")) { - dataChannel("deletePermission") match { + val replaceOrDeletePermission = { + if (dataChannel.contains("replaceOrDeletePermission")) { + dataChannel("replaceOrDeletePermission") match { case dPerm: List[String] => dPerm case _ => { - logger.warn(s"Invalid deletePermission for channel $channelName in plugin $pluginName") + logger.warn(s"Invalid replaceOrDeletePermission for channel $channelName in plugin $pluginName") List() } } @@ -168,7 +168,7 @@ object ClientSettings extends SystemConfiguration { } } - pluginDataChannels += (channelName -> DataChannel(channelName, writePermission, deletePermission)) + pluginDataChannels += (channelName -> DataChannel(channelName, pushPermission, replaceOrDeletePermission)) } } case _ => logger.warn(s"Plugin $pluginName has an invalid dataChannels format") @@ -184,7 +184,7 @@ object ClientSettings extends SystemConfiguration { pluginsFromConfig } - case class DataChannel(name: String, writePermission: List[String], deletePermission: List[String]) + case class DataChannel(name: String, pushPermission: List[String], replaceOrDeletePermission: List[String]) case class Plugin(name: String, url: String, dataChannels: Map[String, DataChannel]) } diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/plugin/PluginDataChannelDeleteEntryMsgHdlr.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/plugin/PluginDataChannelDeleteEntryMsgHdlr.scala index 17c8ca7e78..69480297ca 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/plugin/PluginDataChannelDeleteEntryMsgHdlr.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/plugin/PluginDataChannelDeleteEntryMsgHdlr.scala @@ -25,9 +25,9 @@ trait PluginDataChannelDeleteEntryMsgHdlr extends HandlerHelpers { println(s"Data channel '${msg.body.channelName}' not found in plugin '${msg.body.pluginName}'.") } else { val hasPermission = for { - deletePermission <- pluginsConfig(msg.body.pluginName).dataChannels(msg.body.channelName).deletePermission + replaceOrDeletePermission <- pluginsConfig(msg.body.pluginName).dataChannels(msg.body.channelName).replaceOrDeletePermission } yield { - deletePermission.toLowerCase match { + replaceOrDeletePermission.toLowerCase match { case "all" => true case "moderator" => user.role == Roles.MODERATOR_ROLE case "presenter" => user.presenter diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/plugin/PluginDataChannelPushEntryMsgHdlr.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/plugin/PluginDataChannelPushEntryMsgHdlr.scala index 32b0b52604..fc6b8c4c45 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/plugin/PluginDataChannelPushEntryMsgHdlr.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/plugin/PluginDataChannelPushEntryMsgHdlr.scala @@ -25,9 +25,9 @@ trait PluginDataChannelPushEntryMsgHdlr extends HandlerHelpers { println(s"Data channel '${msg.body.channelName}' not found in plugin '${msg.body.pluginName}'.") } else { val hasPermission = for { - writePermission <- pluginsConfig(msg.body.pluginName).dataChannels(msg.body.channelName).writePermission + pushPermission <- pluginsConfig(msg.body.pluginName).dataChannels(msg.body.channelName).pushPermission } yield { - writePermission.toLowerCase match { + pushPermission.toLowerCase match { case "all" => true case "moderator" => user.role == Roles.MODERATOR_ROLE case "presenter" => user.presenter diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/plugin/PluginDataChannelReplaceEntryMsgHdlr.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/plugin/PluginDataChannelReplaceEntryMsgHdlr.scala index b9b6bb430f..883fb55284 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/plugin/PluginDataChannelReplaceEntryMsgHdlr.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/plugin/PluginDataChannelReplaceEntryMsgHdlr.scala @@ -25,13 +25,23 @@ trait PluginDataChannelReplaceEntryMsgHdlr extends HandlerHelpers { println(s"Data channel '${msg.body.channelName}' not found in plugin '${msg.body.pluginName}'.") } else { val hasPermission = for { - writePermission <- pluginsConfig(msg.body.pluginName).dataChannels(msg.body.channelName).writePermission + replaceOrDeletePermission <- pluginsConfig(msg.body.pluginName).dataChannels(msg.body.channelName).replaceOrDeletePermission } yield { - writePermission.toLowerCase match { + replaceOrDeletePermission.toLowerCase match { case "all" => true case "moderator" => user.role == Roles.MODERATOR_ROLE case "presenter" => user.presenter - case _ => false + case "sender" => { + val senderUserId = PluginDataChannelEntryDAO.getMessageSender( + meetingId, + msg.body.pluginName, + msg.body.channelName, + msg.body.subChannelName, + msg.body.entryId + ) + senderUserId == msg.header.userId + } + case _ => false } } diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/plugin/PluginDataChannelResetMsgHdlr.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/plugin/PluginDataChannelResetMsgHdlr.scala index 16ac38b0ae..32a403f862 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/plugin/PluginDataChannelResetMsgHdlr.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/plugin/PluginDataChannelResetMsgHdlr.scala @@ -25,9 +25,9 @@ trait PluginDataChannelResetMsgHdlr extends HandlerHelpers { println(s"Data channel '${msg.body.channelName}' not found in plugin '${msg.body.pluginName}'.") } else { val hasPermission = for { - deletePermission <- pluginsConfig(msg.body.pluginName).dataChannels(msg.body.channelName).deletePermission + replaceOrDeletePermission <- pluginsConfig(msg.body.pluginName).dataChannels(msg.body.channelName).replaceOrDeletePermission } yield { - deletePermission.toLowerCase match { + replaceOrDeletePermission.toLowerCase match { case "all" => true case "moderator" => user.role == Roles.MODERATOR_ROLE case "presenter" => user.presenter From 1d9b28133e71fba6007f1abc5d0562714279cc42 Mon Sep 17 00:00:00 2001 From: Guilherme Leme Date: Tue, 18 Jun 2024 17:46:17 -0300 Subject: [PATCH 5/5] [update-data-channel-function] - change sender to creator naming in data-channel --- .../PluginDataChannelDeleteEntryMsgHdlr.scala | 6 +++--- .../PluginDataChannelReplaceEntryMsgHdlr.scala | 6 +++--- .../core/db/PluginDataChannelEntryDAO.scala | 16 ++++++++-------- bbb-graphql-server/bbb_schema.sql | 6 +++--- .../tables/public_v_pluginDataChannelEntry.yaml | 6 +++--- .../plugins-engine/data-channel/subscriptions.ts | 6 +++--- 6 files changed, 23 insertions(+), 23 deletions(-) diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/plugin/PluginDataChannelDeleteEntryMsgHdlr.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/plugin/PluginDataChannelDeleteEntryMsgHdlr.scala index 69480297ca..2cc9f5104c 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/plugin/PluginDataChannelDeleteEntryMsgHdlr.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/plugin/PluginDataChannelDeleteEntryMsgHdlr.scala @@ -31,15 +31,15 @@ trait PluginDataChannelDeleteEntryMsgHdlr extends HandlerHelpers { case "all" => true case "moderator" => user.role == Roles.MODERATOR_ROLE case "presenter" => user.presenter - case "sender" => { - val senderUserId = PluginDataChannelEntryDAO.getMessageSender( + case "creator" => { + val creatorUserId = PluginDataChannelEntryDAO.getEntryCreator( meetingId, msg.body.pluginName, msg.body.channelName, msg.body.subChannelName, msg.body.entryId ) - senderUserId == msg.header.userId + creatorUserId == msg.header.userId } case _ => false } diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/plugin/PluginDataChannelReplaceEntryMsgHdlr.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/plugin/PluginDataChannelReplaceEntryMsgHdlr.scala index 883fb55284..453f64587d 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/plugin/PluginDataChannelReplaceEntryMsgHdlr.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/plugin/PluginDataChannelReplaceEntryMsgHdlr.scala @@ -31,15 +31,15 @@ trait PluginDataChannelReplaceEntryMsgHdlr extends HandlerHelpers { case "all" => true case "moderator" => user.role == Roles.MODERATOR_ROLE case "presenter" => user.presenter - case "sender" => { - val senderUserId = PluginDataChannelEntryDAO.getMessageSender( + case "creator" => { + val creatorUserId = PluginDataChannelEntryDAO.getEntryCreator( meetingId, msg.body.pluginName, msg.body.channelName, msg.body.subChannelName, msg.body.entryId ) - senderUserId == msg.header.userId + creatorUserId == msg.header.userId } case _ => false } diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/db/PluginDataChannelEntryDAO.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/db/PluginDataChannelEntryDAO.scala index 1e48a8d6e0..e53d924aa2 100644 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/db/PluginDataChannelEntryDAO.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/db/PluginDataChannelEntryDAO.scala @@ -21,7 +21,7 @@ case class PluginDataChannelEntryDbModel( subChannelName: String, entryId: Option[String] = None, payloadJson: JsValue, - fromUserId: String, + createdBy: String, toRoles: Option[List[String]], toUserIds: Option[List[String]], createdAt: java.sql.Timestamp, @@ -35,16 +35,16 @@ class PluginDataChannelEntryDbTableDef(tag: Tag) extends Table[PluginDataChannel val subChannelName = column[String]("subChannelName") val entryId = column[Option[String]]("entryId", O.PrimaryKey) val payloadJson = column[JsValue]("payloadJson") - val fromUserId = column[String]("fromUserId") + val createdBy = column[String]("createdBy") val toRoles = column[Option[List[String]]]("toRoles") val toUserIds = column[Option[List[String]]]("toUserIds") val createdAt = column[java.sql.Timestamp]("createdAt") val deletedAt = column[Option[java.sql.Timestamp]]("deletedAt") - override def * = (meetingId, pluginName, channelName, subChannelName, entryId, payloadJson, fromUserId, toRoles, toUserIds, createdAt, deletedAt) <> (PluginDataChannelEntryDbModel.tupled, PluginDataChannelEntryDbModel.unapply) + override def * = (meetingId, pluginName, channelName, subChannelName, entryId, payloadJson, createdBy, toRoles, toUserIds, createdAt, deletedAt) <> (PluginDataChannelEntryDbModel.tupled, PluginDataChannelEntryDbModel.unapply) } object PluginDataChannelEntryDAO { - def insert(meetingId: String, pluginName: String, channelName: String, subChannelName: String, senderUserId: String, + def insert(meetingId: String, pluginName: String, channelName: String, subChannelName: String, createdBy: String, payloadJson: Map[String, Any], toRoles: List[String], toUserIds: List[String]) = { DatabaseConnection.db.run( TableQuery[PluginDataChannelEntryDbTableDef].forceInsert( @@ -55,7 +55,7 @@ object PluginDataChannelEntryDAO { channelName = channelName, subChannelName = subChannelName, payloadJson = JsonUtils.mapToJson(payloadJson), - fromUserId = senderUserId, + createdBy = createdBy, toRoles = toRoles.map(_.toUpperCase).filter(Permission.allowedRoles.contains) match { case Nil => None case filtered => Some(filtered) @@ -88,9 +88,9 @@ object PluginDataChannelEntryDAO { } } - def getMessageSender(meetingId: String, pluginName: String, channelName: String, - subChannelName: String, entryId: String): String = { - val query = sql"""SELECT "fromUserId" + def getEntryCreator(meetingId: String, pluginName: String, channelName: String, + subChannelName: String, entryId: String): String = { + val query = sql"""SELECT "createdBy" FROM "pluginDataChannelEntry" WHERE "deletedAt" is null AND "meetingId" = ${meetingId} diff --git a/bbb-graphql-server/bbb_schema.sql b/bbb-graphql-server/bbb_schema.sql index f4c4ada2f4..f301a6eb8d 100644 --- a/bbb-graphql-server/bbb_schema.sql +++ b/bbb-graphql-server/bbb_schema.sql @@ -2029,13 +2029,13 @@ CREATE TABLE "pluginDataChannelEntry" ( "entryId" varchar(50) DEFAULT uuid_generate_v4(), "subChannelName" varchar(255), "payloadJson" jsonb, - "fromUserId" varchar(50), + "createdBy" varchar(50), "toRoles" varchar[], --MODERATOR, VIEWER, PRESENTER "toUserIds" varchar[], "createdAt" timestamp with time zone DEFAULT current_timestamp, "deletedAt" timestamp with time zone, CONSTRAINT "pluginDataChannel_pkey" PRIMARY KEY ("meetingId","pluginName","channelName","entryId", "subChannelName"), - FOREIGN KEY ("meetingId", "fromUserId") REFERENCES "user"("meetingId","userId") ON DELETE CASCADE + FOREIGN KEY ("meetingId", "createdBy") REFERENCES "user"("meetingId","userId") ON DELETE CASCADE ); create index "idx_pluginDataChannelEntry_pk_reverse" on "pluginDataChannelEntry"("pluginName", "meetingId", "channelName", "subChannelName"); create index "idx_pluginDataChannelEntry_pk_reverse_b" on "pluginDataChannelEntry"("channelName", "pluginName", "meetingId", "subChannelName"); @@ -2044,7 +2044,7 @@ create index "idx_pluginDataChannelEntry_channelName" on "pluginDataChannelEntry create index "idx_pluginDataChannelEntry_roles" on "pluginDataChannelEntry"("meetingId", "toRoles", "toUserIds", "createdAt") where "deletedAt" is null; CREATE OR REPLACE VIEW "v_pluginDataChannelEntry" AS -SELECT u."meetingId", u."userId", m."pluginName", m."channelName", m."subChannelName", m."entryId", m."payloadJson", m."fromUserId", m."toRoles", m."createdAt" +SELECT u."meetingId", u."userId", m."pluginName", m."channelName", m."subChannelName", m."entryId", m."payloadJson", m."createdBy", m."toRoles", m."createdAt" FROM "user" u JOIN "pluginDataChannelEntry" m ON m."meetingId" = u."meetingId" AND ((m."toRoles" IS NULL AND m."toUserIds" IS NULL) diff --git a/bbb-graphql-server/metadata/databases/BigBlueButton/tables/public_v_pluginDataChannelEntry.yaml b/bbb-graphql-server/metadata/databases/BigBlueButton/tables/public_v_pluginDataChannelEntry.yaml index 50723d0084..c21c618b72 100644 --- a/bbb-graphql-server/metadata/databases/BigBlueButton/tables/public_v_pluginDataChannelEntry.yaml +++ b/bbb-graphql-server/metadata/databases/BigBlueButton/tables/public_v_pluginDataChannelEntry.yaml @@ -7,11 +7,11 @@ configuration: custom_name: pluginDataChannelEntry custom_root_fields: {} object_relationships: - - name: sender + - name: creator using: manual_configuration: column_mapping: - fromUserId: userId + createdBy: userId meetingId: meetingId insertion_order: null remote_table: @@ -27,7 +27,7 @@ select_permissions: - channelName - entryId - payloadJson - - fromUserId + - createdBy - toRoles filter: _and: diff --git a/bigbluebutton-html5/imports/ui/components/plugins-engine/data-channel/subscriptions.ts b/bigbluebutton-html5/imports/ui/components/plugins-engine/data-channel/subscriptions.ts index f2af9c8215..dbae7c7ef4 100644 --- a/bigbluebutton-html5/imports/ui/components/plugins-engine/data-channel/subscriptions.ts +++ b/bigbluebutton-html5/imports/ui/components/plugins-engine/data-channel/subscriptions.ts @@ -16,7 +16,7 @@ const PLUGIN_DATA_CHANNEL_NEW_ITEMS = gql` subChannelName, entryId, payloadJson, - fromUserId, + createdBy, pluginName, toRoles, } @@ -40,7 +40,7 @@ const PLUGIN_DATA_CHANNEL_All_ITEMS = gql` subChannelName, entryId, payloadJson, - fromUserId, + createdBy, pluginName, toRoles, } @@ -65,7 +65,7 @@ const PLUGIN_DATA_CHANNEL_LATEST_ITEM = gql` subChannelName, entryId, payloadJson, - fromUserId, + createdBy, pluginName, toRoles, }