From b697667364569f5e151ab212fa42cbf0124ada19 Mon Sep 17 00:00:00 2001 From: Paul Trudel <35616208+paultrudel@users.noreply.github.com> Date: Wed, 26 Jun 2024 11:39:39 -0400 Subject: [PATCH] feat(events): Add user custom data to events.xml (#20566) * Send custom user data to akka apps * Add user custom data to registered user * Add user custom data to user join event * Store user custom data in Redis * Rename userCustomData to customParameters * Rename xml tag to userdata --- .../apps/users/RegisterUserReqMsgHdlr.scala | 8 ++++ .../core/models/RegisteredUsers.scala | 9 ++++- .../bigbluebutton/core/models/Users2x.scala | 11 +++--- .../events/ParticipantJoinRecordEvent.scala | 12 ++++++ .../core/running/HandlerHelpers.scala | 3 +- .../UserJoinedMeetingEvtMsgBuilder.scala | 2 +- .../endpoint/redis/RedisRecorderActor.scala | 1 + .../common2/msgs/UsersMsgs.scala | 38 ++++++++++--------- .../org/bigbluebutton/api/MeetingService.java | 11 +++++- .../bigbluebutton/api2/IBbbWebApiGWApp.java | 2 +- .../bigbluebutton/api2/BbbWebApiGWApp.scala | 6 ++- .../org/bigbluebutton/api2/MsgBuilder.scala | 2 +- .../api2/meeting/MeetingsManagerActor.scala | 2 +- .../api2/meeting/ToAkkaAppsSendersTrait.scala | 2 +- .../api/users/server/modifiers/addUser.js | 5 ++- 15 files changed, 80 insertions(+), 34 deletions(-) diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/users/RegisterUserReqMsgHdlr.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/users/RegisterUserReqMsgHdlr.scala index d9e8be96f3..eca545182d 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/users/RegisterUserReqMsgHdlr.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/users/RegisterUserReqMsgHdlr.scala @@ -63,6 +63,14 @@ trait RegisterUserReqMsgHdlr { RegisteredUsers.add(liveMeeting.registeredUsers, regUser) + val userCustomData: Map[String, String] = msg.body.userCustomData.map { + case (k, v) => k -> v.toString + } + + if (userCustomData.nonEmpty) { + RegisteredUsers.updateUserCustomData(liveMeeting.registeredUsers, regUser, userCustomData) + } + log.info("Register user success. meetingId=" + liveMeeting.props.meetingProp.intId + " userId=" + msg.body.extUserId + " user=" + regUser) diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/RegisteredUsers.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/RegisteredUsers.scala index c63402b739..96ec1dca19 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/RegisteredUsers.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/RegisteredUsers.scala @@ -164,6 +164,12 @@ object RegisteredUsers { u } + def updateUserCustomData(users: RegisteredUsers, user: RegisteredUser, userCustomData: Map[String, String]): RegisteredUser = { + val u = user.modify(_.userCustomData).setTo(userCustomData) + users.save(u) + u + } + } class RegisteredUsers { @@ -202,6 +208,7 @@ case class RegisteredUser( joined: Boolean, banned: Boolean, loggedOut: Boolean, - lastBreakoutRoom: BreakoutRoom2x = null + lastBreakoutRoom: BreakoutRoom2x = null, + userCustomData: Map[String, String] = Map.empty ) diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/Users2x.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/Users2x.scala index 039499520c..5a3b661bfb 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/Users2x.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/Users2x.scala @@ -407,20 +407,21 @@ case class UserState( guestStatus: String, emoji: String, reactionEmoji: String, - reactionChangedOn: Long = 0, + reactionChangedOn: Long = 0, raiseHand: Boolean, away: Boolean, locked: Boolean, presenter: Boolean, avatar: String, color: String, - roleChangedOn: Long = System.currentTimeMillis(), - lastActivityTime: Long = System.currentTimeMillis(), - lastInactivityInspect: Long = 0, + roleChangedOn: Long = System.currentTimeMillis(), + lastActivityTime: Long = System.currentTimeMillis(), + lastInactivityInspect: Long = 0, clientType: String, pickExempted: Boolean, userLeftFlag: UserLeftFlag, - speechLocale: String = "" + speechLocale: String = "", + userCustomData: Map[String, String] = Map.empty ) case class UserIdAndName(id: String, name: String) diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/record/events/ParticipantJoinRecordEvent.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/record/events/ParticipantJoinRecordEvent.scala index 230bd38103..c81622aa13 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/record/events/ParticipantJoinRecordEvent.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/record/events/ParticipantJoinRecordEvent.scala @@ -19,8 +19,11 @@ package org.bigbluebutton.core.record.events +import spray.json._ + class ParticipantJoinRecordEvent extends AbstractParticipantRecordEvent { import ParticipantJoinRecordEvent._ + import ParticipantJoinRecordEventJsonProtocol._ setEvent("ParticipantJoinEvent") @@ -43,6 +46,10 @@ class ParticipantJoinRecordEvent extends AbstractParticipantRecordEvent { def setRole(role: String) { eventMap.put(ROLE, role) } + + def setUserdata(userCustomData: Map[String, String]): Unit = { + eventMap.put(USER_DATA, userCustomData.toJson.compactPrint) + } } object ParticipantJoinRecordEvent { @@ -50,4 +57,9 @@ object ParticipantJoinRecordEvent { protected final val EXT_USER_ID = "externalUserId" protected final val NAME = "name" protected final val ROLE = "role" + protected final val USER_DATA = "userdata" +} + +object ParticipantJoinRecordEventJsonProtocol extends DefaultJsonProtocol { + } \ No newline at end of file diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/HandlerHelpers.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/HandlerHelpers.scala index 12e661d118..980431d48b 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/HandlerHelpers.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/HandlerHelpers.scala @@ -73,7 +73,8 @@ trait HandlerHelpers extends SystemConfiguration { color = regUser.color, clientType = clientType, pickExempted = false, - userLeftFlag = UserLeftFlag(false, 0) + userLeftFlag = UserLeftFlag(false, 0), + userCustomData = regUser.userCustomData ) } diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/senders/UserJoinedMeetingEvtMsgBuilder.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/senders/UserJoinedMeetingEvtMsgBuilder.scala index 4301e11fc3..24268a1525 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/senders/UserJoinedMeetingEvtMsgBuilder.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/senders/UserJoinedMeetingEvtMsgBuilder.scala @@ -17,7 +17,7 @@ object UserJoinedMeetingEvtMsgBuilder { away = userState.away, pin = userState.pin, presenter = userState.presenter, locked = userState.locked, avatar = userState.avatar, color = userState.color, - clientType = userState.clientType) + clientType = userState.clientType, userCustomData = userState.userCustomData) val event = UserJoinedMeetingEvtMsg(meetingId, userState.intId, body) diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/endpoint/redis/RedisRecorderActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/endpoint/redis/RedisRecorderActor.scala index cbd31cc437..5b643a17f7 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/endpoint/redis/RedisRecorderActor.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/endpoint/redis/RedisRecorderActor.scala @@ -357,6 +357,7 @@ class RedisRecorderActor( ev.setExternalUserId(msg.body.extId) ev.setName(msg.body.name) ev.setRole(msg.body.role) + ev.setUserdata(msg.body.userCustomData) record(msg.header.meetingId, ev.toMap.asJava) } diff --git a/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/UsersMsgs.scala b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/UsersMsgs.scala index 4ac35f033f..a72b8806ed 100755 --- a/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/UsersMsgs.scala +++ b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/UsersMsgs.scala @@ -7,7 +7,8 @@ case class RegisterUserReqMsg( ) extends BbbCoreMsg case class RegisterUserReqMsgBody(meetingId: String, intUserId: String, name: String, role: String, extUserId: String, authToken: String, avatarURL: String, - guest: Boolean, authed: Boolean, guestStatus: String, excludeFromDashboard: Boolean) + guest: Boolean, authed: Boolean, guestStatus: String, excludeFromDashboard: Boolean, + userCustomData: Map[String, AnyRef]) object UserRegisteredRespMsg { val NAME = "UserRegisteredRespMsg" } case class UserRegisteredRespMsg( @@ -89,23 +90,24 @@ case class UserJoinedMeetingEvtMsg( body: UserJoinedMeetingEvtMsgBody ) extends BbbCoreMsg case class UserJoinedMeetingEvtMsgBody( - intId: String, - extId: String, - name: String, - role: String, - guest: Boolean, - authed: Boolean, - guestStatus: String, - emoji: String, - reactionEmoji: String, - raiseHand: Boolean, - away: Boolean, - pin: Boolean, - presenter: Boolean, - locked: Boolean, - avatar: String, - color: String, - clientType: String + intId: String, + extId: String, + name: String, + role: String, + guest: Boolean, + authed: Boolean, + guestStatus: String, + emoji: String, + reactionEmoji: String, + raiseHand: Boolean, + away: Boolean, + pin: Boolean, + presenter: Boolean, + locked: Boolean, + avatar: String, + color: String, + clientType: String, + userCustomData: Map[String, String] ) /** diff --git a/bbb-common-web/src/main/java/org/bigbluebutton/api/MeetingService.java b/bbb-common-web/src/main/java/org/bigbluebutton/api/MeetingService.java index 62883aaf6b..07b2a5d5b8 100755 --- a/bbb-common-web/src/main/java/org/bigbluebutton/api/MeetingService.java +++ b/bbb-common-web/src/main/java/org/bigbluebutton/api/MeetingService.java @@ -426,10 +426,19 @@ public class MeetingService implements MessageListener { } private void processRegisterUser(RegisterUser message) { + Map userCustomData = null; + Meeting meeting = meetings.get(message.meetingID); + if (meeting != null) { + userCustomData = meeting.getUserCustomData(message.externUserID); + } + if (userCustomData == null) { + userCustomData = new HashMap<>(); + } + gw.registerUser(message.meetingID, message.internalUserId, message.fullname, message.role, message.externUserID, message.authToken, message.avatarURL, message.guest, - message.authed, message.guestStatus, message.excludeFromDashboard); + message.authed, message.guestStatus, message.excludeFromDashboard, userCustomData); } public Meeting getMeeting(String meetingId) { diff --git a/bbb-common-web/src/main/java/org/bigbluebutton/api2/IBbbWebApiGWApp.java b/bbb-common-web/src/main/java/org/bigbluebutton/api2/IBbbWebApiGWApp.java index 54852b2a68..bd20ff5c84 100755 --- a/bbb-common-web/src/main/java/org/bigbluebutton/api2/IBbbWebApiGWApp.java +++ b/bbb-common-web/src/main/java/org/bigbluebutton/api2/IBbbWebApiGWApp.java @@ -51,7 +51,7 @@ public interface IBbbWebApiGWApp { void registerUser(String meetingID, String internalUserId, String fullname, String role, String externUserID, String authToken, String avatarURL, - Boolean guest, Boolean authed, String guestStatus, Boolean excludeFromDashboard); + Boolean guest, Boolean authed, String guestStatus, Boolean excludeFromDashboard, Map userCustomData); void guestWaitingLeft(String meetingID, String internalUserId); void destroyMeeting(DestroyMeetingMessage msg); diff --git a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/BbbWebApiGWApp.scala b/bbb-common-web/src/main/scala/org/bigbluebutton/api2/BbbWebApiGWApp.scala index a359709154..b8ed63892c 100755 --- a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/BbbWebApiGWApp.scala +++ b/bbb-common-web/src/main/scala/org/bigbluebutton/api2/BbbWebApiGWApp.scala @@ -263,16 +263,18 @@ class BbbWebApiGWApp( def registerUser(meetingId: String, intUserId: String, name: String, role: String, extUserId: String, authToken: String, avatarURL: String, guest: java.lang.Boolean, authed: java.lang.Boolean, - guestStatus: String, excludeFromDashboard: java.lang.Boolean): Unit = { + guestStatus: String, excludeFromDashboard: java.lang.Boolean, userCustomData: java.util.Map[String, AnyRef]): Unit = { // meetingManagerActorRef ! new RegisterUser(meetingId = meetingId, intUserId = intUserId, name = name, // role = role, extUserId = extUserId, authToken = authToken, avatarURL = avatarURL, // guest = guest, authed = authed) + val ucd = userCustomData.asScala.toMap + val regUser = new RegisterUser(meetingId = meetingId, intUserId = intUserId, name = name, role = role, extUserId = extUserId, authToken = authToken, avatarURL = avatarURL, guest = guest.booleanValue(), authed = authed.booleanValue(), guestStatus = guestStatus, - excludeFromDashboard = excludeFromDashboard) + excludeFromDashboard = excludeFromDashboard, ucd) val event = MsgBuilder.buildRegisterUserRequestToAkkaApps(regUser) msgToAkkaAppsEventBus.publish(MsgToAkkaApps(toAkkaAppsChannel, event)) diff --git a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/MsgBuilder.scala b/bbb-common-web/src/main/scala/org/bigbluebutton/api2/MsgBuilder.scala index 6101178543..2150248b6a 100755 --- a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/MsgBuilder.scala +++ b/bbb-common-web/src/main/scala/org/bigbluebutton/api2/MsgBuilder.scala @@ -41,7 +41,7 @@ object MsgBuilder { val body = RegisterUserReqMsgBody(meetingId = msg.meetingId, intUserId = msg.intUserId, name = msg.name, role = msg.role, extUserId = msg.extUserId, authToken = msg.authToken, avatarURL = msg.avatarURL, guest = msg.guest, authed = msg.authed, guestStatus = msg.guestStatus, - excludeFromDashboard = msg.excludeFromDashboard) + excludeFromDashboard = msg.excludeFromDashboard, msg.userCustomData) val req = RegisterUserReqMsg(header, body) BbbCommonEnvCoreMsg(envelope, req) } diff --git a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/meeting/MeetingsManagerActor.scala b/bbb-common-web/src/main/scala/org/bigbluebutton/api2/meeting/MeetingsManagerActor.scala index f784263e72..a1cb6352cd 100755 --- a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/meeting/MeetingsManagerActor.scala +++ b/bbb-common-web/src/main/scala/org/bigbluebutton/api2/meeting/MeetingsManagerActor.scala @@ -17,7 +17,7 @@ case class CreateBreakoutRoomMsg(meetingId: String, parentMeetingId: String, case class AddUserSession(token: String, session: UserSession) case class RegisterUser(meetingId: String, intUserId: String, name: String, role: String, extUserId: String, authToken: String, avatarURL: String, - guest: Boolean, authed: Boolean, guestStatus: String, excludeFromDashboard: Boolean) + guest: Boolean, authed: Boolean, guestStatus: String, excludeFromDashboard: Boolean, userCustomData: Map[String, AnyRef]) case class CreateMeetingMsg(defaultProps: DefaultProps) diff --git a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/meeting/ToAkkaAppsSendersTrait.scala b/bbb-common-web/src/main/scala/org/bigbluebutton/api2/meeting/ToAkkaAppsSendersTrait.scala index 366494aaec..1ab9a9dd35 100755 --- a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/meeting/ToAkkaAppsSendersTrait.scala +++ b/bbb-common-web/src/main/scala/org/bigbluebutton/api2/meeting/ToAkkaAppsSendersTrait.scala @@ -29,7 +29,7 @@ trait ToAkkaAppsSendersTrait extends SystemConfiguration { val body = RegisterUserReqMsgBody(meetingId = msg.meetingId, intUserId = msg.intUserId, name = msg.name, role = msg.role, extUserId = msg.extUserId, authToken = msg.authToken, avatarURL = msg.avatarURL, guest = msg.guest, authed = msg.authed, guestStatus = msg.guestStatus, - excludeFromDashboard = msg.excludeFromDashboard) + excludeFromDashboard = msg.excludeFromDashboard, msg.userCustomData) val req = RegisterUserReqMsg(header, body) val message = BbbCommonEnvCoreMsg(envelope, req) sendToBus(message) diff --git a/bigbluebutton-html5/imports/api/users/server/modifiers/addUser.js b/bigbluebutton-html5/imports/api/users/server/modifiers/addUser.js index 6945110ce2..a2a922b0b8 100755 --- a/bigbluebutton-html5/imports/api/users/server/modifiers/addUser.js +++ b/bigbluebutton-html5/imports/api/users/server/modifiers/addUser.js @@ -33,6 +33,7 @@ export default async function addUser(meetingId, userData) { color: String, pin: Boolean, clientType: String, + userCustomData: Match.Optional(Match.Any), }); const userId = user.intId; @@ -43,6 +44,8 @@ export default async function addUser(meetingId, userData) { }; const Meeting = await Meetings.findOneAsync({ meetingId }); + const { userCustomData, ...restOfUser } = user; + const userInfos = { meetingId, sortName: lowercaseTrim(user.name), @@ -57,7 +60,7 @@ export default async function addUser(meetingId, userData) { responseDelay: 0, loggedOut: false, left: false, - ...flat(user), + ...flat(restOfUser), }; const modifier = {