Included unmuteViewers param on create

This commit is contained in:
Pedro Beschorner Marin 2019-04-10 17:55:24 -03:00
parent caa6b9a85e
commit 5f011f2e2e
15 changed files with 54 additions and 7 deletions

View File

@ -14,7 +14,8 @@ trait MuteUserCmdMsgHdlr extends RightsManagementTrait {
val outGW: OutMsgRouter val outGW: OutMsgRouter
def handleMuteUserCmdMsg(msg: MuteUserCmdMsg) { def handleMuteUserCmdMsg(msg: MuteUserCmdMsg) {
if (msg.body.userId != msg.header.userId && (msg.body.mute == false || permissionFailed( val unmuteDisabled = !liveMeeting.props.usersProp.unmuteViewers && msg.body.mute == false
if (msg.body.userId != msg.header.userId && (unmuteDisabled || permissionFailed(
PermissionCheck.MOD_LEVEL, PermissionCheck.MOD_LEVEL,
PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId PermissionCheck.VIEWER_LEVEL, liveMeeting.users2x, msg.header.userId
))) { ))) {

View File

@ -40,6 +40,7 @@ trait AppsTestFixtures {
val dialNumber = "613-555-1234" val dialNumber = "613-555-1234"
val maxUsers = 25 val maxUsers = 25
val guestPolicy = "ALWAYS_ASK" val guestPolicy = "ALWAYS_ASK"
val unmuteViewers = false
val red5DeskShareIPTestFixture = "127.0.0.1" val red5DeskShareIPTestFixture = "127.0.0.1"
val red5DeskShareAppTestFixtures = "red5App" val red5DeskShareAppTestFixtures = "red5App"
@ -59,7 +60,7 @@ trait AppsTestFixtures {
modOnlyMessage = modOnlyMessage) modOnlyMessage = modOnlyMessage)
val voiceProp = VoiceProp(telVoice = voiceConfId, voiceConf = voiceConfId, dialNumber = dialNumber, muteOnStart = muteOnStart) val voiceProp = VoiceProp(telVoice = voiceConfId, voiceConf = voiceConfId, dialNumber = dialNumber, muteOnStart = muteOnStart)
val usersProp = UsersProp(maxUsers = maxUsers, webcamsOnlyForModerator = webcamsOnlyForModerator, val usersProp = UsersProp(maxUsers = maxUsers, webcamsOnlyForModerator = webcamsOnlyForModerator,
guestPolicy = guestPolicy) guestPolicy = guestPolicy, unmuteViewers = unmuteViewers)
val metadataProp = new MetadataProp(metadata) val metadataProp = new MetadataProp(metadata)
val defaultProps = DefaultProps(meetingProp, breakoutProps, durationProps, password, recordProp, welcomeProp, voiceProp, val defaultProps = DefaultProps(meetingProp, breakoutProps, durationProps, password, recordProp, welcomeProp, voiceProp,

View File

@ -19,7 +19,7 @@ case class WelcomeProp(welcomeMsgTemplate: String, welcomeMsg: String, modOnlyMe
case class VoiceProp(telVoice: String, voiceConf: String, dialNumber: String, muteOnStart: Boolean) case class VoiceProp(telVoice: String, voiceConf: String, dialNumber: String, muteOnStart: Boolean)
case class UsersProp(maxUsers: Int, webcamsOnlyForModerator: Boolean, guestPolicy: String) case class UsersProp(maxUsers: Int, webcamsOnlyForModerator: Boolean, guestPolicy: String, unmuteViewers: Boolean)
case class MetadataProp(metadata: collection.immutable.Map[String, String]) case class MetadataProp(metadata: collection.immutable.Map[String, String])

View File

@ -34,6 +34,7 @@ trait TestFixtures {
val dialNumber = "613-555-1234" val dialNumber = "613-555-1234"
val maxUsers = 25 val maxUsers = 25
val muteOnStart = false val muteOnStart = false
val unmuteViewers = false
val keepEvents = false val keepEvents = false
val guestPolicy = "ALWAYS_ASK" val guestPolicy = "ALWAYS_ASK"
val metadata: collection.immutable.Map[String, String] = Map("foo" -> "bar", "bar" -> "baz", "baz" -> "foo") val metadata: collection.immutable.Map[String, String] = Map("foo" -> "bar", "bar" -> "baz", "baz" -> "foo")
@ -52,7 +53,7 @@ trait TestFixtures {
modOnlyMessage = modOnlyMessage) modOnlyMessage = modOnlyMessage)
val voiceProp = VoiceProp(telVoice = voiceConfId, voiceConf = voiceConfId, dialNumber = dialNumber, muteOnStart = muteOnStart) val voiceProp = VoiceProp(telVoice = voiceConfId, voiceConf = voiceConfId, dialNumber = dialNumber, muteOnStart = muteOnStart)
val usersProp = UsersProp(maxUsers = maxUsers, webcamsOnlyForModerator = webcamsOnlyForModerator, val usersProp = UsersProp(maxUsers = maxUsers, webcamsOnlyForModerator = webcamsOnlyForModerator,
guestPolicy = guestPolicy) guestPolicy = guestPolicy, unmuteViewers = unmuteViewers)
val metadataProp = new MetadataProp(metadata) val metadataProp = new MetadataProp(metadata)
val screenshareProps = ScreenshareProps(screenshareConf = "FixMe!", red5ScreenshareIp = "fixMe!", val screenshareProps = ScreenshareProps(screenshareConf = "FixMe!", red5ScreenshareIp = "fixMe!",
red5ScreenshareApp = "fixMe!") red5ScreenshareApp = "fixMe!")

View File

@ -43,6 +43,7 @@ public class ApiParams {
public static final String MODERATOR_ONLY_MESSAGE = "moderatorOnlyMessage"; public static final String MODERATOR_ONLY_MESSAGE = "moderatorOnlyMessage";
public static final String MODERATOR_PW = "moderatorPW"; public static final String MODERATOR_PW = "moderatorPW";
public static final String MUTE_ON_START = "muteOnStart"; public static final String MUTE_ON_START = "muteOnStart";
public static final String UNMUTE_VIEWERS = "unmuteViewers";
public static final String NAME = "name"; public static final String NAME = "name";
public static final String PARENT_MEETING_ID = "parentMeetingID"; public static final String PARENT_MEETING_ID = "parentMeetingID";
public static final String PASSWORD = "password"; public static final String PASSWORD = "password";

View File

@ -315,7 +315,7 @@ public class MeetingService implements MessageListener {
m.getDialNumber(), m.getMaxUsers(), m.getMaxInactivityTimeoutMinutes(), m.getWarnMinutesBeforeMax(), m.getDialNumber(), m.getMaxUsers(), m.getMaxInactivityTimeoutMinutes(), m.getWarnMinutesBeforeMax(),
m.getMeetingExpireIfNoUserJoinedInMinutes(), m.getmeetingExpireWhenLastUserLeftInMinutes(), m.getMeetingExpireIfNoUserJoinedInMinutes(), m.getmeetingExpireWhenLastUserLeftInMinutes(),
m.getUserInactivityInspectTimerInMinutes(), m.getUserInactivityThresholdInMinutes(), m.getUserInactivityInspectTimerInMinutes(), m.getUserInactivityThresholdInMinutes(),
m.getUserActivitySignResponseDelayInMinutes(), m.getMuteOnStart(), keepEvents); m.getUserActivitySignResponseDelayInMinutes(), m.getMuteOnStart(), m.getUnmuteViewers(), keepEvents);
} }
private String formatPrettyDate(Long timestamp) { private String formatPrettyDate(Long timestamp) {

View File

@ -90,6 +90,7 @@ public class ParamsProcessorUtil {
private boolean allowStartStopRecording; private boolean allowStartStopRecording;
private boolean webcamsOnlyForModerator; private boolean webcamsOnlyForModerator;
private boolean defaultMuteOnStart = false; private boolean defaultMuteOnStart = false;
private boolean defaultUnmuteViewers = false;
private String defaultConfigXML = null; private String defaultConfigXML = null;
@ -391,6 +392,13 @@ public class ParamsProcessorUtil {
} }
meeting.setMuteOnStart(muteOnStart); meeting.setMuteOnStart(muteOnStart);
Boolean unmuteViewers = defaultUnmuteViewers;
if (!StringUtils.isEmpty(params.get(ApiParams.UNMUTE_VIEWERS))) {
unmuteViewers = Boolean.parseBoolean(params.get(ApiParams.UNMUTE_VIEWERS));
}
meeting.setUnmuteViewers(unmuteViewers);
return meeting; return meeting;
} }
@ -888,6 +896,13 @@ public class ParamsProcessorUtil {
return defaultMuteOnStart; return defaultMuteOnStart;
} }
public void setUnmuteViewers(Boolean value) {
defaultUnmuteViewers = value;
}
public Boolean getUnmuteViewers() {
return defaultUnmuteViewers;
}
public List<String> decodeIds(String encodeid) { public List<String> decodeIds(String encodeid) {
ArrayList<String> ids=new ArrayList<>(); ArrayList<String> ids=new ArrayList<>();

View File

@ -78,6 +78,7 @@ public class Meeting {
private String customLogoURL = ""; private String customLogoURL = "";
private String customCopyright = ""; private String customCopyright = "";
private Boolean muteOnStart = false; private Boolean muteOnStart = false;
private Boolean unmuteViewers = false;
private Integer maxInactivityTimeoutMinutes = 120; private Integer maxInactivityTimeoutMinutes = 120;
private Integer warnMinutesBeforeMax = 5; private Integer warnMinutesBeforeMax = 5;
@ -424,6 +425,14 @@ public class Meeting {
return muteOnStart; return muteOnStart;
} }
public void setUnmuteViewers(Boolean value) {
unmuteViewers = value;
}
public Boolean getUnmuteViewers() {
return unmuteViewers;
}
public void userJoined(User user) { public void userJoined(User user) {
userHasJoined = true; userHasJoined = true;
this.users.put(user.getInternalUserId(), user); this.users.put(user.getInternalUserId(), user);

View File

@ -26,6 +26,7 @@ public interface IBbbWebApiGWApp {
Integer userInactivityThresholdInMinutes, Integer userInactivityThresholdInMinutes,
Integer userActivitySignResponseDelayInMinutes, Integer userActivitySignResponseDelayInMinutes,
Boolean muteOnStart, Boolean muteOnStart,
Boolean unmuteViewers,
Boolean keepEvents); Boolean keepEvents);
void registerUser(String meetingID, String internalUserId, String fullname, String role, void registerUser(String meetingID, String internalUserId, String fullname, String role,

View File

@ -97,6 +97,7 @@ class BbbWebApiGWApp(
userInactivityThresholdInMinutes: java.lang.Integer, userInactivityThresholdInMinutes: java.lang.Integer,
userActivitySignResponseDelayInMinutes: java.lang.Integer, userActivitySignResponseDelayInMinutes: java.lang.Integer,
muteOnStart: java.lang.Boolean, muteOnStart: java.lang.Boolean,
unmuteViewers: java.lang.Boolean,
keepEvents: java.lang.Boolean): Unit = { keepEvents: java.lang.Boolean): Unit = {
val meetingProp = MeetingProp(name = meetingName, extId = extMeetingId, intId = meetingId, val meetingProp = MeetingProp(name = meetingName, extId = extMeetingId, intId = meetingId,
@ -121,7 +122,7 @@ class BbbWebApiGWApp(
modOnlyMessage = modOnlyMessage) modOnlyMessage = modOnlyMessage)
val voiceProp = VoiceProp(telVoice = voiceBridge, voiceConf = voiceBridge, dialNumber = dialNumber, muteOnStart = muteOnStart.booleanValue()) val voiceProp = VoiceProp(telVoice = voiceBridge, voiceConf = voiceBridge, dialNumber = dialNumber, muteOnStart = muteOnStart.booleanValue())
val usersProp = UsersProp(maxUsers = maxUsers.intValue(), webcamsOnlyForModerator = webcamsOnlyForModerator.booleanValue(), val usersProp = UsersProp(maxUsers = maxUsers.intValue(), webcamsOnlyForModerator = webcamsOnlyForModerator.booleanValue(),
guestPolicy = guestPolicy) guestPolicy = guestPolicy, unmuteViewers = unmuteViewers.booleanValue())
val metadataProp = MetadataProp(mapAsScalaMap(metadata).toMap) val metadataProp = MetadataProp(mapAsScalaMap(metadata).toMap)
val screenshareProps = ScreenshareProps( val screenshareProps = ScreenshareProps(
screenshareConf = voiceBridge + screenshareConfSuffix, screenshareConf = voiceBridge + screenshareConfSuffix,

View File

@ -24,6 +24,7 @@ export default function addMeeting(meeting) {
webcamsOnlyForModerator: Boolean, webcamsOnlyForModerator: Boolean,
guestPolicy: String, guestPolicy: String,
maxUsers: Number, maxUsers: Number,
unmuteViewers: Boolean,
}, },
durationProps: { durationProps: {
createdTime: Number, createdTime: Number,

View File

@ -281,11 +281,21 @@ const isMeetingLocked = (id) => {
return isLocked; return isLocked;
}; };
const areViewersUnmutable = () => {
const meeting = Meetings.findOne({ meetingId: Auth.meetingID });
if (meeting.usersProp) {
return meeting.usersProp.unmuteViewers;
}
return false;
}
const getAvailableActions = (currentUser, user, isBreakoutRoom) => { const getAvailableActions = (currentUser, user, isBreakoutRoom) => {
const isDialInUser = isVoiceOnlyUser(user.id) || user.isPhoneUser; const isDialInUser = isVoiceOnlyUser(user.id) || user.isPhoneUser;
const hasAuthority = currentUser.isModerator || user.isCurrent; const hasAuthority = currentUser.isModerator || user.isCurrent;
const unmuteViewer = !user.isModerator && areViewersUnmutable();
const allowedToChatPrivately = !user.isCurrent && !isDialInUser; const allowedToChatPrivately = !user.isCurrent && !isDialInUser;
const allowedToMuteAudio = hasAuthority const allowedToMuteAudio = hasAuthority
@ -297,7 +307,7 @@ const getAvailableActions = (currentUser, user, isBreakoutRoom) => {
&& user.isVoiceUser && user.isVoiceUser
&& !user.isListenOnly && !user.isListenOnly
&& user.isMuted && user.isMuted
&& user.isCurrent; && (user.isCurrent || unmuteViewer);
const allowedToResetStatus = hasAuthority const allowedToResetStatus = hasAuthority
&& user.emoji.status !== EMOJI_STATUSES.none && user.emoji.status !== EMOJI_STATUSES.none

View File

@ -191,6 +191,10 @@ webcamsOnlyForModerator=false
# Mute the meeting on start # Mute the meeting on start
muteOnStart=false muteOnStart=false
# Unmute users
# Gives moderators permisson to unmute other users
unmuteViewers=false
# Saves meeting events even if the meeting is not recorded # Saves meeting events even if the meeting is not recorded
keepEvents=false keepEvents=false

View File

@ -131,6 +131,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
<property name="maxPresentationFileUpload" value="${maxFileSizeUpload}"/> <property name="maxPresentationFileUpload" value="${maxFileSizeUpload}"/>
<property name="clientLogoutTimerInMinutes" value="${clientLogoutTimerInMinutes}"/> <property name="clientLogoutTimerInMinutes" value="${clientLogoutTimerInMinutes}"/>
<property name="muteOnStart" value="${muteOnStart}"/> <property name="muteOnStart" value="${muteOnStart}"/>
<property name="unmuteViewers" value="${unmuteViewers}"/>
</bean> </bean>
<import resource="doc-conversion.xml"/> <import resource="doc-conversion.xml"/>

View File

@ -1514,6 +1514,7 @@ class ApiController {
customLogoURL meeting.getCustomLogoURL() customLogoURL meeting.getCustomLogoURL()
customCopyright meeting.getCustomCopyright() customCopyright meeting.getCustomCopyright()
muteOnStart meeting.getMuteOnStart() muteOnStart meeting.getMuteOnStart()
unmuteViewers meeting.getUnmuteViewers()
logoutUrl us.logoutUrl logoutUrl us.logoutUrl
defaultLayout us.defaultLayout defaultLayout us.defaultLayout
avatarURL us.avatarURL avatarURL us.avatarURL