bigbluebutton-web: Added filter parameter to getRecordings for filtering queries based on the state of the recording [published|unpublished|deleted]

This commit is contained in:
jfederico 2016-01-22 11:38:33 -05:00
parent 3265709455
commit 6b911820e0
4 changed files with 149 additions and 81 deletions

View File

@ -19,9 +19,11 @@
package org.bigbluebutton.web.controllers
import javax.servlet.ServletRequest;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.Collections;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.codec.binary.Base64;
@ -38,14 +40,18 @@ import org.bigbluebutton.web.services.turn.StunTurnService;
import org.bigbluebutton.web.services.turn.TurnEntry;
import org.bigbluebutton.presentation.PresentationUrlDownloadService;
import org.bigbluebutton.presentation.UploadedPresentation
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import org.bigbluebutton.api.ApiErrors;
import org.bigbluebutton.api.ClientConfigService;
import org.bigbluebutton.api.ParamsProcessorUtil;
import java.util.HashMap;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.Map;
import java.text.DateFormat;
class ApiController {
@ -1705,10 +1711,11 @@ class ApiController {
internalRecordIds = paramsProcessorUtil.decodeIds(params.recordID)
}
ArrayList<String> filters = new ArrayList<String>()
Map<String, Object> filters = new LinkedHashMap<String, Object>()
if (!StringUtils.isEmpty(params.filter)) {
filters = paramsProcessorUtil.decodeIds(params.filter)
filters = paramsProcessorUtil.decodeFilters(params.filter)
}
log.debug(new groovy.json.JsonBuilder( filters ).toPrettyString())
// Everything is good so far.
if ( internalRecordIds.size() == 0 ) {
@ -1716,7 +1723,7 @@ class ApiController {
// Translate the external meeting ids to an internal meeting ids.
internalRecordIds = paramsProcessorUtil.convertToInternalMeetingId(externalMeetingIds);
}
HashMap<String,Recording> recs = meetingService.getRecordings(internalRecordIds);
HashMap<String,Recording> recs = meetingService.getRecordings(internalRecordIds, filters);
recs = meetingService.filterRecordingsByMetadata(recs, ParamsProcessorUtil.processMetaParam(params));
if (recs.isEmpty()) {

View File

@ -339,9 +339,9 @@ public class MeetingService implements MessageListener {
return null;
}
public HashMap<String,Recording> getRecordings(ArrayList<String> idList) {
public HashMap<String,Recording> getRecordings(ArrayList<String> idList, Map<String, Object> filters) {
//TODO: this method shouldn't be used
HashMap<String,Recording> recs= reorderRecordings(recordingService.getRecordings(idList));
HashMap<String,Recording> recs= reorderRecordings(recordingService.getRecordings(idList, filters));
return recs;
}

View File

@ -27,6 +27,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;
@ -42,69 +43,70 @@ import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.*;
public class ParamsProcessorUtil {
private static Logger log = LoggerFactory.getLogger(ParamsProcessorUtil.class);
private static Logger log = LoggerFactory.getLogger(ParamsProcessorUtil.class);
private final String URLDECODER_SEPARATOR=",";
private final String URLDECODER_SEPARATOR=",";
private final String FILTERDECODER_SEPARATOR_ELEMENTS=":";
private final String FILTERDECODER_SEPARATOR_OPERATORS="\\|";
private String apiVersion;
private boolean serviceEnabled = false;
private String securitySalt;
private int defaultMaxUsers = 20;
private String defaultWelcomeMessage;
private String defaultWelcomeMessageFooter;
private String defaultDialAccessNumber;
private String testVoiceBridge;
private String testConferenceMock;
private String defaultLogoutUrl;
private String defaultServerUrl;
private int defaultNumDigitsForTelVoice;
private String defaultClientUrl;
private String defaultAvatarURL;
private String defaultConfigURL;
private int defaultMeetingDuration;
private boolean disableRecordingDefault;
private boolean autoStartRecording;
private boolean allowStartStopRecording;
private String apiVersion;
private boolean serviceEnabled = false;
private String securitySalt;
private int defaultMaxUsers = 20;
private String defaultWelcomeMessage;
private String defaultWelcomeMessageFooter;
private String defaultDialAccessNumber;
private String testVoiceBridge;
private String testConferenceMock;
private String defaultLogoutUrl;
private String defaultServerUrl;
private int defaultNumDigitsForTelVoice;
private String defaultClientUrl;
private String defaultAvatarURL;
private String defaultConfigURL;
private int defaultMeetingDuration;
private boolean disableRecordingDefault;
private boolean autoStartRecording;
private boolean allowStartStopRecording;
private String defaultConfigXML = null;
private String defaultConfigXML = null;
private String substituteKeywords(String message, String dialNumber, String telVoice, String meetingName) {
String welcomeMessage = message;
private String substituteKeywords(String message, String dialNumber, String telVoice, String meetingName) {
String welcomeMessage = message;
String DIAL_NUM = "%%DIALNUM%%";
String CONF_NUM = "%%CONFNUM%%";
String CONF_NAME = "%%CONFNAME%%";
ArrayList<String> keywordList = new ArrayList<String>();
keywordList.add(DIAL_NUM);keywordList.add(CONF_NUM);keywordList.add(CONF_NAME);
String DIAL_NUM = "%%DIALNUM%%";
String CONF_NUM = "%%CONFNUM%%";
String CONF_NAME = "%%CONFNAME%%";
ArrayList<String> keywordList = new ArrayList<String>();
keywordList.add(DIAL_NUM);keywordList.add(CONF_NUM);keywordList.add(CONF_NAME);
Iterator<String> itr = keywordList.iterator();
while(itr.hasNext()) {
String keyword = (String) itr.next();
if (keyword.equals(DIAL_NUM)) {
welcomeMessage = welcomeMessage.replaceAll(DIAL_NUM, dialNumber);
} else if (keyword.equals(CONF_NUM)) {
welcomeMessage = welcomeMessage.replaceAll(CONF_NUM, telVoice);
} else if (keyword.equals(CONF_NAME)) {
welcomeMessage = welcomeMessage.replaceAll(CONF_NAME, meetingName);
}
}
return welcomeMessage;
}
Iterator<String> itr = keywordList.iterator();
while(itr.hasNext()) {
String keyword = (String) itr.next();
if (keyword.equals(DIAL_NUM)) {
welcomeMessage = welcomeMessage.replaceAll(DIAL_NUM, dialNumber);
} else if (keyword.equals(CONF_NUM)) {
welcomeMessage = welcomeMessage.replaceAll(CONF_NUM, telVoice);
} else if (keyword.equals(CONF_NAME)) {
welcomeMessage = welcomeMessage.replaceAll(CONF_NAME, meetingName);
}
}
return welcomeMessage;
}
public void processRequiredCreateParams(Map<String, String> params, ApiErrors errors) {
// Do we have a checksum? If not, complain.
public void processRequiredCreateParams(Map<String, String> params, ApiErrors errors) {
// Do we have a checksum? If not, complain.
if (StringUtils.isEmpty(params.get("checksum"))) {
errors.missingParamError("checksum");
errors.missingParamError("checksum");
}
// Do we have a meeting id? If not, complain.
if(!StringUtils.isEmpty(params.get("meetingID"))) {
if (StringUtils.isEmpty(StringUtils.strip(params.get("meetingID")))) {
errors.missingParamError("meetingID");
}
if (StringUtils.isEmpty(StringUtils.strip(params.get("meetingID")))) {
errors.missingParamError("meetingID");
}
} else {
errors.missingParamError("meetingID");
errors.missingParamError("meetingID");
}
}
@ -703,7 +705,7 @@ public class ParamsProcessorUtil {
this.defaultAvatarURL = url;
}
public ArrayList<String> decodeIds(String encodeid){
public ArrayList<String> decodeIds(String encodeid) {
ArrayList<String> ids=new ArrayList<String>();
try {
ids.addAll(Arrays.asList(URLDecoder.decode(encodeid,"UTF-8").split(URLDECODER_SEPARATOR)));
@ -722,7 +724,7 @@ public class ParamsProcessorUtil {
return internalMeetingIds;
}
public Map<String,String> getUserCustomData(Map<String,String> params){
public Map<String,String> getUserCustomData(Map<String,String> params) {
Map<String,String> resp = new HashMap<String, String>();
for (String key: params.keySet()) {
@ -737,4 +739,25 @@ public class ParamsProcessorUtil {
return resp;
}
public Map<String, Object> decodeFilters(String encodedFilters) {
Map<String, Object> filters = new LinkedHashMap<String, Object>();
try {
String[] sFilters = encodedFilters.split(URLDECODER_SEPARATOR);
for( String sFilter: sFilters) {
String[] filterElements = sFilter.split(FILTERDECODER_SEPARATOR_ELEMENTS, 3);
Map<String, Object> filter = new LinkedHashMap<String, Object>();
filter.put("op", filterElements[1]);
String[] fValues = filterElements[2].split(FILTERDECODER_SEPARATOR_OPERATORS);
filter.put("values", fValues );
filters.put(filterElements[0], filter);
}
} catch (Exception e) {
log.error("Couldn't decode the filters");
}
return filters;
}
}

View File

@ -22,6 +22,7 @@ package org.bigbluebutton.api;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
@ -56,29 +57,66 @@ public class RecordingService {
}
}
public ArrayList<Recording> getRecordings(ArrayList<String> meetingIds) {
private boolean shouldIncludeDir( Map<String, Object> filters, String type ) {
boolean r = false;
if( filters.containsKey("state") ) {
Map<String, Object> filter = (Map<String, Object>)filters.get("state");
String[] values = (String[])filter.get("values");
if ( Arrays.asList(values).contains("any") ) {
r = true;
} else {
if ( type.equals(Recording.STATE_PUBLISHED) && Arrays.asList(values).contains(Recording.STATE_PUBLISHED) ) {
r = true;
} else if ( type.equals(Recording.STATE_UNPUBLISHED) && Arrays.asList(values).contains(Recording.STATE_UNPUBLISHED) ) {
r = true;
} else if ( type.equals(Recording.STATE_DELETED) && Arrays.asList(values).contains(Recording.STATE_DELETED) ) {
r = true;
}
}
} else {
if ( type.equals(Recording.STATE_PUBLISHED) || type.equals(Recording.STATE_UNPUBLISHED) ) {
r = true;
}
}
return r;
}
public ArrayList<Recording> getRecordings(ArrayList<String> meetingIds, Map<String, Object> filters) {
ArrayList<Recording> recs = new ArrayList<Recording>();
if(meetingIds.isEmpty()){
meetingIds.addAll(getAllRecordingIds(publishedDir));
meetingIds.addAll(getAllRecordingIds(unpublishedDir));
meetingIds.addAll(getAllRecordingIds(deletedDir));
if ( shouldIncludeDir(filters, Recording.STATE_PUBLISHED) )
meetingIds.addAll(getAllRecordingIds(publishedDir));
if ( shouldIncludeDir(filters, Recording.STATE_UNPUBLISHED) )
meetingIds.addAll(getAllRecordingIds(unpublishedDir));
if ( shouldIncludeDir(filters, Recording.STATE_DELETED) )
meetingIds.addAll(getAllRecordingIds(deletedDir));
}
for(String meetingId : meetingIds){
ArrayList<Recording> published = getRecordingsForPath(meetingId, publishedDir);
if (!published.isEmpty()) {
recs.addAll(published);
if ( shouldIncludeDir(filters, Recording.STATE_PUBLISHED) ) {
ArrayList<Recording> published = getRecordingsForPath(meetingId, publishedDir);
if (!published.isEmpty()) {
recs.addAll(published);
}
}
ArrayList<Recording> unpublished = getRecordingsForPath(meetingId, unpublishedDir);
if (!unpublished.isEmpty()) {
recs.addAll(unpublished);
if ( shouldIncludeDir(filters, Recording.STATE_UNPUBLISHED) ) {
ArrayList<Recording> unpublished = getRecordingsForPath(meetingId, unpublishedDir);
if (!unpublished.isEmpty()) {
recs.addAll(unpublished);
}
}
ArrayList<Recording> deleted = getRecordingsForPath(meetingId, deletedDir);
if (!deleted.isEmpty()) {
recs.addAll(deleted);
if ( shouldIncludeDir(filters, Recording.STATE_DELETED) ) {
ArrayList<Recording> deleted = getRecordingsForPath(meetingId, deletedDir);
if (!deleted.isEmpty()) {
recs.addAll(deleted);
}
}
}