- join and create api have unit tests
This commit is contained in:
parent
c40976dab5
commit
78adae0696
@ -49,7 +49,7 @@ maxConversionTime=5
|
||||
maxNumPages=100
|
||||
|
||||
# Default number of digits for voice conference users joining through the PSTN.
|
||||
defaulNumDigitsForTelVoice=5
|
||||
defaultNumDigitsForTelVoice=5
|
||||
|
||||
#----------------------------------------------------
|
||||
# Default dial access number
|
||||
@ -76,6 +76,10 @@ bigbluebutton.web.serverURL=http://192.168.0.166
|
||||
# If blank, it returns to bigbluebutton.web.serverURL
|
||||
bigbluebutton.web.logoutURL=
|
||||
|
||||
# The url of the BigBlueButton client. User's will be redirected here when
|
||||
# successfully joining the meeting.
|
||||
defaultClientUrl=${bigbluebutton.web.serverURL}/client/BigBlueButton.html
|
||||
|
||||
#------------------------------------------------------
|
||||
# These properties are used to test the conversion process.
|
||||
# Conference name folder in ${presentationDir} (see above)
|
||||
@ -109,4 +113,5 @@ beans.dynamicConferenceService.defaultDialAccessNumber=${defaultDialAccessNumber
|
||||
beans.dynamicConferenceService.defaultMaxUsers=${defaultMaxUsers}
|
||||
beans.dynamicConferenceService.defaultLogoutUrl=${bigbluebutton.web.logoutURL}
|
||||
beans.dynamicConferenceService.defaultServerUrl=${bigbluebutton.web.serverURL}
|
||||
beans.dynamicConferenceService.defaulNumDigitsForTelVoice=${defaulNumDigitsForTelVoice}
|
||||
beans.dynamicConferenceService.defaultNumDigitsForTelVoice=${defaultNumDigitsForTelVoice}
|
||||
beans.dynamicConferenceService.defaultClientUrl=${defaultClientUrl}
|
||||
|
@ -159,6 +159,8 @@ class ApiController {
|
||||
.withMaxUsers(maxUsers).withModeratorPass(modPass).withViewerPass(viewerPass).withRecording(record)
|
||||
.withLogoutUrl(logoutUrl).withTelVoice(telVoice).withWebVoice(webVoice).withDialNumber(dialNumber)
|
||||
.withMetadata(meetingInfo).withWelcomeMessage(welcomeMessage).build()
|
||||
|
||||
log.info("Storing meeting ${meeting.getInternalId()}")
|
||||
dynamicConferenceService.createConference(meeting);
|
||||
|
||||
// See if the request came with pre-uploading of presentation.
|
||||
@ -173,45 +175,55 @@ class ApiController {
|
||||
def join = {
|
||||
log.debug CONTROLLER_NAME + "#join"
|
||||
|
||||
// Do we have a checksum? If none, complain.
|
||||
if (StringUtils.isEmpty(params.checksum)) {
|
||||
invalid("missingParamChecksum", "You must pass a checksum and query string.");
|
||||
return
|
||||
}
|
||||
|
||||
if (! dynamicConferenceService.isChecksumSame("create", params.checksum, request.getQueryString())) {
|
||||
invalidChecksum(); return;
|
||||
}
|
||||
|
||||
// Do we have a name for the user joining? If none, complain.
|
||||
String fullName = params.fullName
|
||||
if (StringUtils.isEmpty(fullName)) {
|
||||
invalid("missingParamFullName", "You must specify a name for the attendee who will be joining the meeting.");
|
||||
return
|
||||
}
|
||||
|
||||
// Do we have a meeting id? If none, complain.
|
||||
String externalMeetingId = params.meetingID
|
||||
if (StringUtils.isEmpty(externalMeetingId)) {
|
||||
invalid("missingParamMeetingID", "You must specify a meeting ID for the meeting.");
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// Do we have a password? If not, complain.
|
||||
String attPW = params.password
|
||||
if (StringUtils.isEmpty(attPW)) {
|
||||
invalid("missingParamPassword", "You must specify a password for the meeting.");
|
||||
return
|
||||
}
|
||||
|
||||
String internalMeetingId = dynamicConferenceService.getInternalMeetingId(externalMeetingId);
|
||||
|
||||
// Do we agree on the checksum? If not, complain.
|
||||
if (! dynamicConferenceService.isChecksumSame("join", params.checksum, request.getQueryString())) {
|
||||
invalidChecksum(); return;
|
||||
}
|
||||
|
||||
// Everything is good so far. Translate the external meeting id to an internal meeting id. If
|
||||
// we can't find the meeting, complain.
|
||||
String internalMeetingId = dynamicConferenceService.getInternalMeetingId(externalMeetingId);
|
||||
log.info("Retrieving meeting ${internalMeetingId}")
|
||||
Meeting meeting = dynamicConferenceService.getMeeting(internalMeetingId);
|
||||
if (meeting == null) {
|
||||
invalid("invalidMeetingIdentifier", "The meeting ID that you supplied did not match any existing meetings");
|
||||
return;
|
||||
}
|
||||
|
||||
// Is this user joining a meeting that has been ended. If so, complain.
|
||||
if (meeting.isForciblyEnded()) {
|
||||
invalid("meetingForciblyEnded", "You can not re-join a meeting that has already been forcibly ended. However, once the meeting is removed from memory (according to the timeout configured on this server, you will be able to once again create a meeting with the same meeting ID");
|
||||
return;
|
||||
}
|
||||
|
||||
// Now determine if this user is a moderator or a viewer.
|
||||
String role = null;
|
||||
if (meeting.getModeratorPassword().equals(attPW)) {
|
||||
role = ROLE_MODERATOR;
|
||||
@ -222,37 +234,33 @@ class ApiController {
|
||||
if (role == null) {
|
||||
invalidPassword("You either did not supply a password or the password supplied is neither the attendee or moderator password for this conference."); return;
|
||||
}
|
||||
|
||||
String webVoice = params.webVoiceConf
|
||||
|
||||
String webVoice = StringUtils.isEmpty(params.webVoiceConf) ? meeting.getTelVoice() : params.webVoiceConf
|
||||
|
||||
boolean redirectImm = parseBoolean(params.redirectImmediately)
|
||||
|
||||
String externUserID = params.userID
|
||||
if (StringUtils.isEmpty(externUserID)) {
|
||||
externUserID = RandomStringUtils.randomAlphanumeric(12).toLowerCase()
|
||||
}
|
||||
meeting.setWebVoiceConf(StringUtils.isEmpty(webVoice) ? conf.voiceBridge : webVoice)
|
||||
|
||||
log.debug "join successful - setting session parameters and redirecting to join"
|
||||
session["conferencename"] = conf.meetingID
|
||||
session["meetingID"] = conf.meetingID
|
||||
session["conferencename"] = meeting.getName()
|
||||
session["meetingID"] = meeting.getInternalId()
|
||||
session["externUserID"] = externUserID
|
||||
session["fullname"] = fullName
|
||||
session["role"] = role
|
||||
session["conference"] = conf.getMeetingToken()
|
||||
session["room"] = conf.getMeetingToken()
|
||||
session["voicebridge"] = conf.getVoiceBridge()
|
||||
session["webvoiceconf"] = conf.getWebVoiceConf()
|
||||
session["conference"] = meeting.getInternalId()
|
||||
session["room"] = meeting.getInternalId()
|
||||
session["voicebridge"] = meeting.getTelVoice()
|
||||
session["webvoiceconf"] = meeting.getWebVoice()
|
||||
session["mode"] = "LIVE"
|
||||
session["record"] = conf.record
|
||||
session['welcome'] = conf.welcome
|
||||
session["record"] = meeting.isRecord()
|
||||
session['welcome'] = meeting.getWelcomeMessage()
|
||||
|
||||
session.setMaxInactiveInterval(SESSION_TIMEOUT);
|
||||
|
||||
def config = ConfigurationHolder.config
|
||||
def hostURL = config.bigbluebutton.web.serverURL
|
||||
def redirectUrl = "${hostURL}/client/BigBlueButton.html";
|
||||
log.debug("join done, redirecting to ${redirectUrl}");
|
||||
redirect(url:redirectUrl)
|
||||
log.info("Successfully joined. Redirecting to ${dynamicConferenceService.defaultClientUrl}");
|
||||
redirect(url: dynamicConferenceService.defaultClientUrl)
|
||||
}
|
||||
|
||||
def isMeetingRunning = {
|
||||
|
@ -49,38 +49,23 @@ public class DynamicConferenceService {
|
||||
def recordStatusDir
|
||||
def defaultLogoutUrl
|
||||
def defaultServerUrl
|
||||
def defaulNumDigitsForTelVoice
|
||||
|
||||
def defaultNumDigitsForTelVoice
|
||||
def defaultClientUrl
|
||||
|
||||
private MeetingService meetingService
|
||||
|
||||
public Collection<Meeting> getAllMeetings() {
|
||||
return confsByMtgID.isEmpty() ? Collections.emptySet() : Collections.unmodifiableCollection(confsByMtgID.values());
|
||||
}
|
||||
|
||||
public void createConference(Meeting conf) {
|
||||
/* conf.setStoredTime(new Date());
|
||||
confsByMtgID.put(conf.getMeetingID(), conf);
|
||||
tokenMap.put(conf.getMeetingToken(), conf.getMeetingID());
|
||||
if (conf.isRecord()) {
|
||||
createConferenceRecord(conf);
|
||||
}
|
||||
*/ }
|
||||
public void createConference(Meeting meeting) {
|
||||
meetingService.storeMeeting(meeting)
|
||||
}
|
||||
|
||||
public Meeting getMeeting(String meetingID) {
|
||||
return meetingService.getMeeting(meetingID);
|
||||
}
|
||||
|
||||
private Meeting getConferenceByToken(String token) {
|
||||
if (token == null) {
|
||||
return null;
|
||||
}
|
||||
String mtgID = tokenMap.get(token);
|
||||
if (mtgID == null) {
|
||||
return null;
|
||||
}
|
||||
return confsByMtgID.get(mtgID);
|
||||
}
|
||||
|
||||
|
||||
public boolean isMeetingWithVoiceBridgeExist(String voiceBridge) {
|
||||
Collection<Meeting> confs = confsByMtgID.values()
|
||||
for (Meeting c : confs) {
|
||||
@ -142,7 +127,7 @@ public class DynamicConferenceService {
|
||||
}
|
||||
|
||||
public String processTelVoice(String telNum) {
|
||||
return StringUtils.isEmpty(telNum) ? RandomStringUtils.randomNumeric(defaulNumDigitsForTelVoice) : telNum;
|
||||
return StringUtils.isEmpty(telNum) ? RandomStringUtils.randomNumeric(defaultNumDigitsForTelVoice) : telNum;
|
||||
}
|
||||
|
||||
public String processDialNumber(String dial) {
|
||||
@ -233,6 +218,7 @@ public class DynamicConferenceService {
|
||||
log.debug "our checksum: " + cs
|
||||
if (cs == null || cs.equals(checksum) == false) {
|
||||
log.info("checksumError: request did not pass the checksum security check")
|
||||
log.info("salt: ${securitySalt} checksum: ${cs} client: ${checksum} query: ${queryString}")
|
||||
return false;
|
||||
}
|
||||
log.debug("checksum ok: request passed the checksum security check")
|
||||
|
@ -6,7 +6,7 @@ import org.bigbluebutton.api.domain.Meeting;
|
||||
public interface MeetingService {
|
||||
public void cleanupOldMeetings();
|
||||
public Collection<Meeting> getAllMeetings();
|
||||
public void storeMeeting(Meeting conf);
|
||||
public void storeMeeting(Meeting m);
|
||||
public Meeting getMeeting(String meetingID);
|
||||
public boolean isMeetingWithVoiceBridgeExist(String voiceBridge);
|
||||
}
|
||||
|
@ -58,14 +58,9 @@ public class MeetingServiceImp implements MeetingService {
|
||||
return meetings.isEmpty() ? Collections.emptySet() : Collections.unmodifiableCollection(meetings.values());
|
||||
}
|
||||
|
||||
public void storeMeeting(Meeting conf) {
|
||||
/* conf.setStoredTime(new Date());
|
||||
meetings.put(conf.getMeetingID(), conf);
|
||||
if (conf.isRecord()) {
|
||||
// createMeetingRecord(conf);
|
||||
}
|
||||
*/ }
|
||||
|
||||
public void storeMeeting(Meeting m) {
|
||||
meetings.put(m.getInternalId(), m);
|
||||
}
|
||||
|
||||
public Meeting getMeeting(String meetingID) {
|
||||
if (meetingID == null) {
|
||||
@ -121,6 +116,6 @@ public class MeetingServiceImp implements MeetingService {
|
||||
|
||||
public void setDynamicConferenceService(IDynamicConferenceService s) {
|
||||
dynConfService = s;
|
||||
s.setMeetingService(this);
|
||||
s.setMeetingService((MeetingService) this);
|
||||
}
|
||||
}
|
@ -3,5 +3,5 @@ package org.bigbluebutton.web.services;
|
||||
import org.bigbluebutton.api.MeetingService;
|
||||
|
||||
public interface IDynamicConferenceService {
|
||||
void setMeetingService(MeetingService s);
|
||||
public void setMeetingService(MeetingService s);
|
||||
}
|
||||
|
@ -6,8 +6,26 @@ import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.bigbluebutton.api.*;
|
||||
|
||||
class ApiControllerTests extends ControllerUnitTestCase {
|
||||
String SALT = 'ab56fda9fc1c2bde2d65ff76134b47ad'
|
||||
String MEETING_ID = "CULB"
|
||||
String MEETING_NAME = "CULB"
|
||||
String MOD_PASS = "testm"
|
||||
String VIEW_PASS = "testa"
|
||||
String CLIENT_URL = "http://localhost/client/BigBlueButton.html"
|
||||
|
||||
|
||||
def service
|
||||
|
||||
protected void setUp() {
|
||||
super.setUp()
|
||||
mockLogging(DynamicConferenceService)
|
||||
service = new DynamicConferenceService()
|
||||
service.setMeetingService(new MeetingServiceImp())
|
||||
service.apiVersion = "0.7"
|
||||
service.securitySalt = SALT
|
||||
service.defaultNumDigitsForTelVoice = 5
|
||||
service.defaultNumDigitsForTelVoice = 5
|
||||
service.defaultClientUrl = CLIENT_URL
|
||||
}
|
||||
|
||||
protected void tearDown() {
|
||||
@ -23,34 +41,70 @@ class ApiControllerTests extends ControllerUnitTestCase {
|
||||
println "controller response = " + controller.response.contentAsString
|
||||
}
|
||||
|
||||
void testCreateAPI() {
|
||||
String securitySalt = 'ab56fda9fc1c2bde2d65ff76134b47ad'
|
||||
String mId = "CULB"
|
||||
String mName = "CULB"
|
||||
String modPass = "testm"
|
||||
String viewPass = "testa"
|
||||
|
||||
String queryString = "meetingID=${mId}&name=${mName}&moderatorPW=${modPass}&attendeePW=${viewPass}"
|
||||
String checksum = DigestUtils.shaHex("create" + queryString + securitySalt)
|
||||
void testCreateAPI() {
|
||||
String queryString = "meetingID=${MEETING_ID}&name=${MEETING_NAME}&moderatorPW=${MOD_PASS}&attendeePW=${VIEW_PASS}"
|
||||
String checksum = DigestUtils.shaHex("create" + queryString + SALT)
|
||||
queryString += "&checksum=${checksum}"
|
||||
|
||||
mockParams.meetingID = mId
|
||||
mockParams.meetingID = MEETING_ID
|
||||
mockParams.checksum = checksum
|
||||
mockParams.name = mName
|
||||
mockParams.moderatorPW = modPass
|
||||
mockParams.attendeePW = viewPass
|
||||
mockParams.name = MEETING_NAME
|
||||
mockParams.moderatorPW = MOD_PASS
|
||||
mockParams.attendeePW = VIEW_PASS
|
||||
mockRequest.queryString = queryString
|
||||
|
||||
ApiController controller = new ApiController()
|
||||
mockLogging(DynamicConferenceService)
|
||||
def service = new DynamicConferenceService()
|
||||
service.setMeetingService(new MeetingServiceImp())
|
||||
service.apiVersion = "0.7"
|
||||
service.securitySalt = 'ab56fda9fc1c2bde2d65ff76134b47ad'
|
||||
|
||||
mockLogging(ApiController)
|
||||
|
||||
controller.setDynamicConferenceService(service)
|
||||
controller.create()
|
||||
println "controller response = " + controller.response.contentAsString
|
||||
}
|
||||
|
||||
|
||||
void testJoinAPI() {
|
||||
|
||||
/** Create the meeting to set things up */
|
||||
String queryString = "meetingID=${MEETING_ID}&name=${MEETING_NAME}&moderatorPW=${MOD_PASS}&attendeePW=${VIEW_PASS}"
|
||||
String checksum = DigestUtils.shaHex("create" + queryString + SALT)
|
||||
queryString += "&checksum=${checksum}"
|
||||
|
||||
mockParams.meetingID = MEETING_ID
|
||||
mockParams.checksum = checksum
|
||||
mockParams.name = MEETING_NAME
|
||||
mockParams.moderatorPW = MOD_PASS
|
||||
mockParams.attendeePW = VIEW_PASS
|
||||
mockRequest.queryString = queryString
|
||||
|
||||
ApiController controller = new ApiController()
|
||||
mockLogging(ApiController)
|
||||
controller.setDynamicConferenceService(service)
|
||||
controller.create()
|
||||
|
||||
String username = "Richard"
|
||||
String modPass = "testm"
|
||||
|
||||
queryString = "meetingID=${MEETING_ID}&fullName=${username}&password=${MOD_PASS}"
|
||||
checksum = DigestUtils.shaHex("join" + queryString + SALT)
|
||||
queryString += "&checksum=${checksum}"
|
||||
|
||||
mockParams.fullName = username
|
||||
mockParams.meetingID = MEETING_ID
|
||||
mockParams.password = MOD_PASS
|
||||
mockParams.checksum = checksum
|
||||
mockRequest.queryString = queryString
|
||||
|
||||
ApiController controller2 = new ApiController()
|
||||
mockLogging(ApiController)
|
||||
controller2.setDynamicConferenceService(service)
|
||||
controller2.join()
|
||||
|
||||
/**
|
||||
* Need to use controller2.redirectArgs['url'] instead of controller2.response.redirectedUrl as
|
||||
* shown in the grails doc because it is returning null for me.
|
||||
*
|
||||
* see http://kousenit.wordpress.com/2010/11/10/unit-testing-grails-controllers-revisited/
|
||||
*/
|
||||
assertEquals CLIENT_URL, controller2.redirectArgs['url']
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user