- join and create api have unit tests

This commit is contained in:
Richard Alam 2011-05-31 15:23:44 -04:00
parent c40976dab5
commit 78adae0696
7 changed files with 127 additions and 79 deletions

View File

@ -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}

View File

@ -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 = {

View File

@ -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")

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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']
}
}