Merge pull request from GHSA-4m48-49h7-f3c4
fix(sec): API fix duplicates ghsa-4m48-49h7-f3c4 (2.7)
This commit is contained in:
commit
ea6e9461dc
@ -112,5 +112,7 @@ libraryDependencies ++= Seq(
|
||||
"com.zaxxer" % "HikariCP" % "4.0.3",
|
||||
"commons-validator" % "commons-validator" % "1.7",
|
||||
"org.apache.tika" % "tika-core" % "2.8.0",
|
||||
"org.apache.tika" % "tika-parsers-standard-package" % "2.8.0"
|
||||
"org.apache.tika" % "tika-parsers-standard-package" % "2.8.0",
|
||||
"org.scala-lang.modules" %% "scala-xml" % "2.2.0",
|
||||
"jakarta.ws.rs" % "jakarta.ws.rs-api" % "3.1.0"
|
||||
)
|
||||
|
@ -1,6 +1,6 @@
|
||||
package org.bigbluebutton.api.model.constraint;
|
||||
|
||||
import org.bigbluebutton.api.model.validator.PostChecksumValidator;
|
||||
import org.bigbluebutton.api.model.validator.ContentTypeValidator;
|
||||
|
||||
import javax.validation.Constraint;
|
||||
import javax.validation.Payload;
|
||||
@ -10,13 +10,13 @@ import java.lang.annotation.Target;
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
@Constraint(validatedBy = PostChecksumValidator.class)
|
||||
@Constraint(validatedBy = ContentTypeValidator.class)
|
||||
@Target(TYPE)
|
||||
@Retention(RUNTIME)
|
||||
public @interface PostChecksumConstraint {
|
||||
public @interface ContentTypeConstraint {
|
||||
|
||||
String key() default "checksumError";
|
||||
String message() default "Checksums do not match";
|
||||
String key() default "unsupportedContentType";
|
||||
String message() default "POST request Content-Type is missing or unsupported";
|
||||
Class<?>[] groups() default {};
|
||||
Class<? extends Payload>[] payload() default {};
|
||||
}
|
@ -1,12 +1,16 @@
|
||||
package org.bigbluebutton.api.model.request;
|
||||
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import org.bigbluebutton.api.model.constraint.*;
|
||||
import org.bigbluebutton.api.model.shared.Checksum;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@ContentTypeConstraint
|
||||
public class CreateMeeting extends RequestWithChecksum<CreateMeeting.Params> {
|
||||
|
||||
public enum Params implements RequestParameters {
|
||||
@ -51,8 +55,8 @@ public class CreateMeeting extends RequestWithChecksum<CreateMeeting.Params> {
|
||||
private String recordString;
|
||||
private Boolean record;
|
||||
|
||||
public CreateMeeting(Checksum checksum) {
|
||||
super(checksum);
|
||||
public CreateMeeting(Checksum checksum, HttpServletRequest servletRequest) {
|
||||
super(checksum, servletRequest);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
@ -138,4 +142,9 @@ public class CreateMeeting extends RequestWithChecksum<CreateMeeting.Params> {
|
||||
isBreakoutRoom = Boolean.parseBoolean(isBreakoutRoomString);
|
||||
record = Boolean.parseBoolean(recordString);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getSupportedContentTypes() {
|
||||
return Set.of(MediaType.APPLICATION_FORM_URLENCODED, MediaType.MULTIPART_FORM_DATA, MediaType.APPLICATION_XML, MediaType.TEXT_XML);
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,16 @@
|
||||
package org.bigbluebutton.api.model.request;
|
||||
|
||||
import org.bigbluebutton.api.model.constraint.MeetingExistsConstraint;
|
||||
import org.bigbluebutton.api.model.constraint.MeetingIDConstraint;
|
||||
import org.bigbluebutton.api.model.constraint.NotEmpty;
|
||||
import org.bigbluebutton.api.model.constraint.PasswordConstraint;
|
||||
import org.bigbluebutton.api.model.constraint.*;
|
||||
import org.bigbluebutton.api.model.shared.Checksum;
|
||||
import org.bigbluebutton.api.model.shared.ModeratorPassword;
|
||||
import org.bigbluebutton.api.model.shared.Password;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@ContentTypeConstraint
|
||||
public class EndMeeting extends RequestWithChecksum<EndMeeting.Params> {
|
||||
|
||||
public enum Params implements RequestParameters {
|
||||
@ -34,8 +34,8 @@ public class EndMeeting extends RequestWithChecksum<EndMeeting.Params> {
|
||||
@Valid
|
||||
private Password moderatorPassword;
|
||||
|
||||
public EndMeeting(Checksum checksum) {
|
||||
super(checksum);
|
||||
public EndMeeting(Checksum checksum, HttpServletRequest servletRequest) {
|
||||
super(checksum, servletRequest);
|
||||
moderatorPassword = new ModeratorPassword();
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,16 @@
|
||||
package org.bigbluebutton.api.model.request;
|
||||
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import org.bigbluebutton.api.model.constraint.*;
|
||||
import org.bigbluebutton.api.service.SessionService;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class Enter implements Request<Enter.Params> {
|
||||
@ContentTypeConstraint
|
||||
public class Enter extends RequestWithSession<Enter.Params>{
|
||||
|
||||
public enum Params implements RequestParameters {
|
||||
SESSION_TOKEN("sessionToken");
|
||||
@ -27,7 +32,8 @@ public class Enter implements Request<Enter.Params> {
|
||||
|
||||
private SessionService sessionService;
|
||||
|
||||
public Enter() {
|
||||
public Enter(HttpServletRequest servletRequest) {
|
||||
super(servletRequest);
|
||||
sessionService = new SessionService();
|
||||
}
|
||||
|
||||
|
@ -2,9 +2,10 @@ package org.bigbluebutton.api.model.request;
|
||||
|
||||
import org.bigbluebutton.api.model.constraint.UserSessionConstraint;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Map;
|
||||
|
||||
public class GetJoinUrl implements Request<GetJoinUrl.Params> {
|
||||
public class GetJoinUrl extends RequestWithSession<GetJoinUrl.Params> {
|
||||
|
||||
public enum Params implements RequestParameters {
|
||||
SESSION_TOKEN("sessionToken");
|
||||
@ -19,6 +20,10 @@ public class GetJoinUrl implements Request<GetJoinUrl.Params> {
|
||||
@UserSessionConstraint
|
||||
private String sessionToken;
|
||||
|
||||
public GetJoinUrl(HttpServletRequest servletRequest) {
|
||||
super(servletRequest);
|
||||
}
|
||||
|
||||
public String getSessionToken() {
|
||||
return sessionToken;
|
||||
}
|
||||
|
@ -1,14 +1,17 @@
|
||||
package org.bigbluebutton.api.model.request;
|
||||
|
||||
import org.bigbluebutton.api.model.constraint.ContentTypeConstraint;
|
||||
import org.bigbluebutton.api.model.constraint.MeetingEndedConstraint;
|
||||
import org.bigbluebutton.api.model.constraint.MeetingExistsConstraint;
|
||||
import org.bigbluebutton.api.model.constraint.UserSessionConstraint;
|
||||
import org.bigbluebutton.api.service.SessionService;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Map;
|
||||
|
||||
public class GuestWait implements Request<GuestWait.Params> {
|
||||
@ContentTypeConstraint
|
||||
public class GuestWait extends RequestWithSession<GuestWait.Params>{
|
||||
|
||||
public enum Params implements RequestParameters {
|
||||
SESSION_TOKEN("sessionToken");
|
||||
@ -29,7 +32,8 @@ public class GuestWait implements Request<GuestWait.Params> {
|
||||
|
||||
private SessionService sessionService;
|
||||
|
||||
public GuestWait() {
|
||||
public GuestWait(HttpServletRequest servletRequest) {
|
||||
super(servletRequest);
|
||||
sessionService = new SessionService();
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,14 @@
|
||||
package org.bigbluebutton.api.model.request;
|
||||
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import org.bigbluebutton.api.model.constraint.*;
|
||||
import org.bigbluebutton.api.model.shared.Checksum;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
@ContentTypeConstraint
|
||||
public class InsertDocument extends RequestWithChecksum<InsertDocument.Params> {
|
||||
|
||||
public enum Params implements RequestParameters {
|
||||
@ -21,8 +24,8 @@ public class InsertDocument extends RequestWithChecksum<InsertDocument.Params> {
|
||||
@MeetingIDConstraint
|
||||
private String meetingID;
|
||||
|
||||
public InsertDocument(Checksum checksum) {
|
||||
super(checksum);
|
||||
public InsertDocument(Checksum checksum, HttpServletRequest servletRequest) {
|
||||
super(checksum, servletRequest);
|
||||
}
|
||||
|
||||
public String getMeetingID() {
|
||||
@ -37,4 +40,9 @@ public class InsertDocument extends RequestWithChecksum<InsertDocument.Params> {
|
||||
public void populateFromParamsMap(Map<String, String[]> params) {
|
||||
if(params.containsKey(Params.MEETING_ID.getValue())) setMeetingID(params.get(Params.MEETING_ID.getValue())[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getSupportedContentTypes() {
|
||||
return Set.of(MediaType.APPLICATION_XML, MediaType.TEXT_XML);
|
||||
}
|
||||
}
|
||||
|
@ -5,9 +5,11 @@ import org.bigbluebutton.api.model.shared.Checksum;
|
||||
import org.bigbluebutton.api.model.shared.JoinPassword;
|
||||
import org.bigbluebutton.api.model.shared.Password;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
import java.util.Map;
|
||||
|
||||
@ContentTypeConstraint
|
||||
public class JoinMeeting extends RequestWithChecksum<JoinMeeting.Params> {
|
||||
|
||||
public enum Params implements RequestParameters {
|
||||
@ -57,8 +59,8 @@ public class JoinMeeting extends RequestWithChecksum<JoinMeeting.Params> {
|
||||
@Valid
|
||||
private Password joinPassword;
|
||||
|
||||
public JoinMeeting(Checksum checksum) {
|
||||
super(checksum);
|
||||
public JoinMeeting(Checksum checksum, HttpServletRequest servletRequest) {
|
||||
super(checksum, servletRequest);
|
||||
joinPassword = new JoinPassword();
|
||||
}
|
||||
|
||||
|
@ -2,10 +2,11 @@ package org.bigbluebutton.api.model.request;
|
||||
|
||||
import org.bigbluebutton.api.model.constraint.UserSessionConstraint;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Map;
|
||||
|
||||
public class LearningDashboard implements Request<LearningDashboard.Params> {
|
||||
public class LearningDashboard extends RequestWithSession<LearningDashboard.Params> {
|
||||
|
||||
public enum Params implements RequestParameters {
|
||||
SESSION_TOKEN("sessionToken");
|
||||
@ -20,6 +21,10 @@ public class LearningDashboard implements Request<LearningDashboard.Params> {
|
||||
@UserSessionConstraint
|
||||
private String sessionToken;
|
||||
|
||||
public LearningDashboard(HttpServletRequest servletRequest) {
|
||||
super(servletRequest);
|
||||
}
|
||||
|
||||
public String getSessionToken() {
|
||||
return sessionToken;
|
||||
}
|
||||
|
@ -1,11 +1,14 @@
|
||||
package org.bigbluebutton.api.model.request;
|
||||
|
||||
import org.bigbluebutton.api.model.constraint.ContentTypeConstraint;
|
||||
import org.bigbluebutton.api.model.constraint.MeetingExistsConstraint;
|
||||
import org.bigbluebutton.api.model.constraint.MeetingIDConstraint;
|
||||
import org.bigbluebutton.api.model.shared.Checksum;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Map;
|
||||
|
||||
@ContentTypeConstraint
|
||||
public class MeetingInfo extends RequestWithChecksum<MeetingInfo.Params> {
|
||||
|
||||
public enum Params implements RequestParameters {
|
||||
@ -22,8 +25,8 @@ public class MeetingInfo extends RequestWithChecksum<MeetingInfo.Params> {
|
||||
@MeetingExistsConstraint
|
||||
private String meetingID;
|
||||
|
||||
public MeetingInfo(Checksum checksum) {
|
||||
super(checksum);
|
||||
public MeetingInfo(Checksum checksum, HttpServletRequest servletRequest) {
|
||||
super(checksum, servletRequest);
|
||||
}
|
||||
|
||||
public String getMeetingID() {
|
||||
|
@ -1,10 +1,13 @@
|
||||
package org.bigbluebutton.api.model.request;
|
||||
|
||||
import org.bigbluebutton.api.model.constraint.ContentTypeConstraint;
|
||||
import org.bigbluebutton.api.model.constraint.MeetingIDConstraint;
|
||||
import org.bigbluebutton.api.model.shared.Checksum;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Map;
|
||||
|
||||
@ContentTypeConstraint
|
||||
public class MeetingRunning extends RequestWithChecksum<MeetingRunning.Params> {
|
||||
|
||||
public enum Params implements RequestParameters {
|
||||
@ -20,8 +23,8 @@ public class MeetingRunning extends RequestWithChecksum<MeetingRunning.Params> {
|
||||
@MeetingIDConstraint
|
||||
private String meetingID;
|
||||
|
||||
public MeetingRunning(Checksum checksum) {
|
||||
super(checksum);
|
||||
public MeetingRunning(Checksum checksum, HttpServletRequest servletRequest) {
|
||||
super(checksum, servletRequest);
|
||||
}
|
||||
|
||||
public String getMeetingID() {
|
||||
|
@ -1,9 +1,13 @@
|
||||
package org.bigbluebutton.api.model.request;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public interface Request<P extends Enum<P> & RequestParameters> {
|
||||
|
||||
void populateFromParamsMap(Map<String, String[]> params);
|
||||
void convertParamsFromString();
|
||||
Set<String> getSupportedContentTypes();
|
||||
HttpServletRequest getServletRequest();
|
||||
}
|
||||
|
@ -1,17 +1,23 @@
|
||||
package org.bigbluebutton.api.model.request;
|
||||
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import org.bigbluebutton.api.model.shared.Checksum;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public abstract class RequestWithChecksum<P extends Enum<P> & RequestParameters> implements Request<P> {
|
||||
|
||||
@Valid
|
||||
protected Checksum checksum;
|
||||
|
||||
protected RequestWithChecksum(Checksum checksum) {
|
||||
protected HttpServletRequest servletRequest;
|
||||
|
||||
protected RequestWithChecksum(Checksum checksum, HttpServletRequest servletRequest) {
|
||||
this.checksum = checksum;
|
||||
this.servletRequest = servletRequest;
|
||||
}
|
||||
|
||||
public Checksum getChecksum() {
|
||||
@ -27,4 +33,14 @@ public abstract class RequestWithChecksum<P extends Enum<P> & RequestParameters>
|
||||
public void convertParamsFromString() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getSupportedContentTypes() {
|
||||
return Set.of(MediaType.APPLICATION_FORM_URLENCODED, MediaType.MULTIPART_FORM_DATA);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpServletRequest getServletRequest() {
|
||||
return servletRequest;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,25 @@
|
||||
package org.bigbluebutton.api.model.request;
|
||||
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Set;
|
||||
|
||||
public abstract class RequestWithSession<P extends Enum<P> & RequestParameters> implements Request<P> {
|
||||
|
||||
protected HttpServletRequest servletRequest;
|
||||
|
||||
protected RequestWithSession(HttpServletRequest servletRequest) {
|
||||
this.servletRequest = servletRequest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getSupportedContentTypes() {
|
||||
return Set.of(MediaType.APPLICATION_FORM_URLENCODED, MediaType.MULTIPART_FORM_DATA);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpServletRequest getServletRequest() {
|
||||
return servletRequest;
|
||||
}
|
||||
}
|
@ -2,10 +2,11 @@ package org.bigbluebutton.api.model.request;
|
||||
|
||||
import org.bigbluebutton.api.model.constraint.UserSessionConstraint;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Map;
|
||||
|
||||
public class SignOut implements Request<SignOut.Params> {
|
||||
public class SignOut extends RequestWithSession<SignOut.Params> {
|
||||
|
||||
public enum Params implements RequestParameters {
|
||||
SESSION_TOKEN("sessionToken");
|
||||
@ -20,6 +21,10 @@ public class SignOut implements Request<SignOut.Params> {
|
||||
@UserSessionConstraint
|
||||
private String sessionToken;
|
||||
|
||||
public SignOut(HttpServletRequest servletRequest) {
|
||||
super(servletRequest);
|
||||
}
|
||||
|
||||
public String getSessionToken() {
|
||||
return sessionToken;
|
||||
}
|
||||
|
@ -1,9 +1,12 @@
|
||||
package org.bigbluebutton.api.model.request;
|
||||
|
||||
import org.bigbluebutton.api.model.constraint.ContentTypeConstraint;
|
||||
import org.bigbluebutton.api.model.shared.Checksum;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Map;
|
||||
|
||||
@ContentTypeConstraint
|
||||
public class SimpleRequest extends RequestWithChecksum<SimpleRequest.Params> {
|
||||
|
||||
public enum Params implements RequestParameters {
|
||||
@ -16,8 +19,8 @@ public class SimpleRequest extends RequestWithChecksum<SimpleRequest.Params> {
|
||||
public String getValue() { return value; }
|
||||
}
|
||||
|
||||
public SimpleRequest(Checksum checksum) {
|
||||
super(checksum);
|
||||
public SimpleRequest(Checksum checksum, HttpServletRequest servletRequest) {
|
||||
super(checksum, servletRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -3,9 +3,11 @@ package org.bigbluebutton.api.model.request;
|
||||
import org.bigbluebutton.api.model.constraint.*;
|
||||
import org.bigbluebutton.api.service.SessionService;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Map;
|
||||
|
||||
public class Stuns implements Request<Stuns.Params> {
|
||||
@ContentTypeConstraint
|
||||
public class Stuns extends RequestWithSession<Stuns.Params> {
|
||||
|
||||
public enum Params implements RequestParameters {
|
||||
SESSION_TOKEN("sessionToken");
|
||||
@ -26,7 +28,10 @@ public class Stuns implements Request<Stuns.Params> {
|
||||
|
||||
private SessionService sessionService;
|
||||
|
||||
public Stuns() { sessionService = new SessionService(); }
|
||||
public Stuns(HttpServletRequest servletRequest) {
|
||||
super(servletRequest);
|
||||
sessionService = new SessionService();
|
||||
}
|
||||
|
||||
public String getSessionToken() {
|
||||
return sessionToken;
|
||||
|
@ -1,8 +1,11 @@
|
||||
package org.bigbluebutton.api.model.shared;
|
||||
|
||||
import org.bigbluebutton.api.model.constraint.ContentTypeConstraint;
|
||||
import org.bigbluebutton.api.model.constraint.NotEmpty;
|
||||
import org.bigbluebutton.api.util.ParamsUtil;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
public abstract class Checksum {
|
||||
|
||||
@NotEmpty(message = "You must provide the API call", groups = ChecksumValidationGroup.class)
|
||||
@ -13,9 +16,12 @@ public abstract class Checksum {
|
||||
|
||||
protected String queryStringWithoutChecksum;
|
||||
|
||||
public Checksum(String apiCall, String checksum) {
|
||||
protected HttpServletRequest request;
|
||||
|
||||
public Checksum(String apiCall, String checksum, HttpServletRequest request) {
|
||||
this.apiCall = ParamsUtil.sanitizeString(apiCall);
|
||||
this.checksum = ParamsUtil.sanitizeString(checksum);
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
public String getApiCall() {
|
||||
@ -41,4 +47,12 @@ public abstract class Checksum {
|
||||
public void setQueryStringWithoutChecksum(String queryStringWithoutChecksum) {
|
||||
this.queryStringWithoutChecksum = queryStringWithoutChecksum;
|
||||
}
|
||||
|
||||
public void setRequest(HttpServletRequest request) {
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
public HttpServletRequest getRequest() {
|
||||
return request;
|
||||
}
|
||||
}
|
||||
|
@ -3,16 +3,16 @@ package org.bigbluebutton.api.model.shared;
|
||||
import org.bigbluebutton.api.model.constraint.GetChecksumConstraint;
|
||||
import org.bigbluebutton.api.util.ParamsUtil;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
|
||||
@GetChecksumConstraint(groups = ChecksumValidationGroup.class)
|
||||
public class GetChecksum extends Checksum {
|
||||
|
||||
@NotEmpty(message = "You must provide the query string")
|
||||
private String queryString;
|
||||
|
||||
public GetChecksum(String apiCall, String checksum, String queryString) {
|
||||
super(apiCall, checksum);
|
||||
public GetChecksum(String apiCall, String checksum, String queryString, HttpServletRequest request) {
|
||||
super(apiCall, checksum, request);
|
||||
this.queryString = ParamsUtil.sanitizeString(queryString);
|
||||
removeChecksumFromQueryString();
|
||||
}
|
||||
|
@ -1,22 +0,0 @@
|
||||
package org.bigbluebutton.api.model.shared;
|
||||
|
||||
import org.bigbluebutton.api.model.constraint.PostChecksumConstraint;
|
||||
import org.bigbluebutton.api.service.ValidationService;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@PostChecksumConstraint(groups = ChecksumValidationGroup.class)
|
||||
public class PostChecksum extends Checksum {
|
||||
|
||||
Map<String, String[]> params;
|
||||
|
||||
public PostChecksum(String apiCall, String checksum, Map<String, String[]> params) {
|
||||
super(apiCall, checksum);
|
||||
this.params = params;
|
||||
queryStringWithoutChecksum = ValidationService.buildQueryStringFromParamsMap(params);
|
||||
}
|
||||
|
||||
public Map<String, String[]> getParams() { return params; }
|
||||
|
||||
public void setParams(Map<String, String[]> params) { this.params = params; }
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package org.bigbluebutton.api.model.validator;
|
||||
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import org.apache.commons.compress.utils.Sets;
|
||||
import org.bigbluebutton.api.model.constraint.ContentTypeConstraint;
|
||||
import org.bigbluebutton.api.model.request.Request;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.ConstraintValidator;
|
||||
import javax.validation.ConstraintValidatorContext;
|
||||
import java.util.Set;
|
||||
|
||||
public class ContentTypeValidator implements ConstraintValidator<ContentTypeConstraint, Request> {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ContentTypeValidator.class);
|
||||
|
||||
@Override
|
||||
public void initialize(ContentTypeConstraint constraintAnnotation) {}
|
||||
|
||||
@Override
|
||||
public boolean isValid(Request request, ConstraintValidatorContext context) {
|
||||
HttpServletRequest servletRequest = request.getServletRequest();
|
||||
String requestMethod = servletRequest.getMethod();
|
||||
String contentType = servletRequest.getContentType();
|
||||
String contentTypeHeader = servletRequest.getHeader("Content-Type");
|
||||
log.info("Validating {} request with content type {}", requestMethod, contentType);
|
||||
|
||||
boolean requestBodyPresent = servletRequest.getContentLength() > 0;
|
||||
if (requestBodyPresent) {
|
||||
if (contentType == null || contentTypeHeader == null) return false;
|
||||
else {
|
||||
return request.getSupportedContentTypes().contains(contentType);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,8 +1,10 @@
|
||||
package org.bigbluebutton.api.model.validator;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.ConstraintValidator;
|
||||
import javax.validation.ConstraintValidatorContext;
|
||||
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.bigbluebutton.api.model.constraint.GetChecksumConstraint;
|
||||
import org.bigbluebutton.api.model.shared.GetChecksum;
|
||||
|
@ -1,53 +0,0 @@
|
||||
package org.bigbluebutton.api.model.validator;
|
||||
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.bigbluebutton.api.model.constraint.PostChecksumConstraint;
|
||||
import org.bigbluebutton.api.model.shared.PostChecksum;
|
||||
import org.bigbluebutton.api.service.ServiceUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.validation.ConstraintValidator;
|
||||
import javax.validation.ConstraintValidatorContext;
|
||||
|
||||
public class PostChecksumValidator implements ConstraintValidator<PostChecksumConstraint, PostChecksum> {
|
||||
|
||||
private static Logger log = LoggerFactory.getLogger(PostChecksumValidator.class);
|
||||
|
||||
@Override
|
||||
public void initialize(PostChecksumConstraint constraintAnnotation) {}
|
||||
|
||||
@Override
|
||||
public boolean isValid(PostChecksum checksum, ConstraintValidatorContext context) {
|
||||
String securitySalt = ServiceUtils.getValidationService().getSecuritySalt();
|
||||
|
||||
if (securitySalt.isEmpty()) {
|
||||
log.warn("Security is disabled in this service. Make sure this is intentional.");
|
||||
return true;
|
||||
}
|
||||
|
||||
String queryStringWithoutChecksum = checksum.getQueryStringWithoutChecksum();
|
||||
log.info("query string after checksum removed: [{}]", queryStringWithoutChecksum);
|
||||
|
||||
if(queryStringWithoutChecksum == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String providedChecksum = checksum.getChecksum();
|
||||
log.info("CHECKSUM={} length={}", providedChecksum, providedChecksum.length());
|
||||
|
||||
if(providedChecksum == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String data = checksum.getApiCall() + queryStringWithoutChecksum + securitySalt;
|
||||
String createdCheckSum = DigestUtils.sha1Hex(data);
|
||||
|
||||
if (createdCheckSum == null || !createdCheckSum.equalsIgnoreCase(providedChecksum)) {
|
||||
log.info("checksumError: failed checksum. our checksum: [{}], client: [{}]", createdCheckSum, providedChecksum);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -4,11 +4,11 @@ import org.bigbluebutton.api.model.request.*;
|
||||
import org.bigbluebutton.api.model.shared.Checksum;
|
||||
import org.bigbluebutton.api.model.shared.ChecksumValidationGroup;
|
||||
import org.bigbluebutton.api.model.shared.GetChecksum;
|
||||
import org.bigbluebutton.api.model.shared.PostChecksum;
|
||||
import org.bigbluebutton.api.util.ParamsUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.Validation;
|
||||
import javax.validation.Validator;
|
||||
@ -70,11 +70,13 @@ public class ValidationService {
|
||||
validator = validatorFactory.getValidator();
|
||||
}
|
||||
|
||||
public Map<String, String> validate(ApiCall apiCall, Map<String, String[]> params, String queryString) {
|
||||
public Map<String, String> validate(ApiCall apiCall, HttpServletRequest servletRequest) {
|
||||
String queryString = servletRequest.getQueryString();
|
||||
Map<String, String[]> params = servletRequest.getParameterMap();
|
||||
log.info("Validating {} request with query string {}", apiCall.getName(), queryString);
|
||||
params = sanitizeParams(params);
|
||||
|
||||
Request request = initializeRequest(apiCall, params, queryString);
|
||||
Request request = initializeRequest(apiCall, params, queryString, servletRequest);
|
||||
Map<String,String> violations = new HashMap<>();
|
||||
|
||||
if(request == null) {
|
||||
@ -101,7 +103,7 @@ public class ValidationService {
|
||||
}
|
||||
}
|
||||
|
||||
private Request initializeRequest(ApiCall apiCall, Map<String, String[]> params, String queryString) {
|
||||
private Request initializeRequest(ApiCall apiCall, Map<String, String[]> params, String queryString, HttpServletRequest servletRequest) {
|
||||
Request request = null;
|
||||
Checksum checksum;
|
||||
|
||||
@ -110,55 +112,23 @@ public class ValidationService {
|
||||
checksumValue = params.get("checksum")[0];
|
||||
}
|
||||
|
||||
if(queryString == null || queryString.isEmpty()) {
|
||||
queryString = buildQueryStringFromParamsMap(params);
|
||||
}
|
||||
|
||||
switch(apiCall.requestType) {
|
||||
case GET:
|
||||
checksum = new GetChecksum(apiCall.getName(), checksumValue, queryString);
|
||||
switch(apiCall) {
|
||||
case CREATE:
|
||||
request = new CreateMeeting(checksum);
|
||||
break;
|
||||
case JOIN:
|
||||
request = new JoinMeeting(checksum);
|
||||
break;
|
||||
case MEETING_RUNNING:
|
||||
request = new MeetingRunning(checksum);
|
||||
break;
|
||||
case END:
|
||||
request = new EndMeeting(checksum);
|
||||
break;
|
||||
case GET_MEETING_INFO:
|
||||
request = new MeetingInfo(checksum);
|
||||
break;
|
||||
case GET_MEETINGS:
|
||||
case GET_SESSIONS:
|
||||
request = new SimpleRequest(checksum);
|
||||
break;
|
||||
case INSERT_DOCUMENT:
|
||||
request = new InsertDocument(checksum);
|
||||
break;
|
||||
case GUEST_WAIT:
|
||||
request = new GuestWait();
|
||||
break;
|
||||
case ENTER:
|
||||
request = new Enter();
|
||||
break;
|
||||
case STUNS:
|
||||
request = new Stuns();
|
||||
break;
|
||||
case SIGN_OUT:
|
||||
request = new SignOut();
|
||||
break;
|
||||
case LEARNING_DASHBOARD:
|
||||
request = new LearningDashboard();
|
||||
break;
|
||||
case GET_JOIN_URL:
|
||||
request = new GetJoinUrl();
|
||||
break;
|
||||
}
|
||||
if (Objects.requireNonNull(apiCall.requestType) == RequestType.GET) {
|
||||
checksum = new GetChecksum(apiCall.getName(), checksumValue, queryString, servletRequest);
|
||||
request = switch (apiCall) {
|
||||
case CREATE -> new CreateMeeting(checksum, servletRequest);
|
||||
case JOIN -> new JoinMeeting(checksum, servletRequest);
|
||||
case MEETING_RUNNING -> new MeetingRunning(checksum, servletRequest);
|
||||
case END -> new EndMeeting(checksum, servletRequest);
|
||||
case GET_MEETING_INFO -> new MeetingInfo(checksum, servletRequest);
|
||||
case GET_MEETINGS, GET_SESSIONS -> new SimpleRequest(checksum, servletRequest);
|
||||
case INSERT_DOCUMENT -> new InsertDocument(checksum, servletRequest);
|
||||
case GUEST_WAIT -> new GuestWait(servletRequest);
|
||||
case ENTER -> new Enter(servletRequest);
|
||||
case STUNS -> new Stuns(servletRequest);
|
||||
case SIGN_OUT -> new SignOut(servletRequest);
|
||||
case LEARNING_DASHBOARD -> new LearningDashboard(servletRequest);
|
||||
case GET_JOIN_URL -> new GetJoinUrl(servletRequest);
|
||||
};
|
||||
}
|
||||
|
||||
return request;
|
||||
|
@ -63,6 +63,26 @@ class UrlMappings {
|
||||
action = [GET: 'downloadFile']
|
||||
}
|
||||
|
||||
"/bigbluebutton/api/create"(controller: "api") {
|
||||
action = [GET: 'create', POST: 'create']
|
||||
}
|
||||
|
||||
"/bigbluebutton/api/join"(controller: "api") {
|
||||
action = [GET: 'join']
|
||||
}
|
||||
|
||||
"/bigbluebutton/api/isMeetingRunning"(controller: "api") {
|
||||
action = [GET: 'isMeetingRunning', POST: 'isMeetingRunning']
|
||||
}
|
||||
|
||||
"/bigbluebutton/api/end"(controller: "api") {
|
||||
action = [GET: 'end', POST: 'end']
|
||||
}
|
||||
|
||||
"/bigbluebutton/api/getMeetingInfo"(controller: "api") {
|
||||
action = [GET: 'getMeetingInfo', POST: 'getMeetingInfo']
|
||||
}
|
||||
|
||||
"/bigbluebutton/api/getMeetings"(controller: "api") {
|
||||
action = [GET: 'getMeetingsHandler', POST: 'getMeetingsHandler']
|
||||
}
|
||||
@ -71,6 +91,30 @@ class UrlMappings {
|
||||
action = [GET: 'getSessionsHandler', POST: 'getSessionsHandler']
|
||||
}
|
||||
|
||||
"/bigbluebutton/api/enter"(controller: "api") {
|
||||
action = [GET: 'enter', POST: 'enter']
|
||||
}
|
||||
|
||||
"/bigbluebutton/api/stuns"(controller: "api") {
|
||||
action = [GET: 'stuns', POST: 'stuns']
|
||||
}
|
||||
|
||||
"/bigbluebutton/api/signOut"(controller: "api") {
|
||||
action = [GET: 'signOut', POST: 'signOut']
|
||||
}
|
||||
|
||||
"/bigbluebutton/api/insertDocument"(controller: "api") {
|
||||
action = [GET: 'insertDocument', POST: 'insertDocument']
|
||||
}
|
||||
|
||||
"/bigbluebutton/api/getJoinUrl"(controller: "api") {
|
||||
action = [GET: 'getJoinUrl', POST: 'getJoinUrl']
|
||||
}
|
||||
|
||||
"/bigbluebutton/api/learningDashboard"(controller: "api") {
|
||||
action = [GET: 'learningDashboard', POST: 'learningDashboard']
|
||||
}
|
||||
|
||||
"/bigbluebutton/api/getRecordings"(controller: "recording") {
|
||||
action = [GET: 'getRecordingsHandler', POST: 'getRecordingsHandler']
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ import org.bigbluebutton.web.services.turn.StunServer
|
||||
import org.bigbluebutton.web.services.turn.RemoteIceCandidate
|
||||
import org.json.JSONArray
|
||||
import javax.servlet.ServletRequest
|
||||
import javax.servlet.http.HttpServletRequest
|
||||
|
||||
class ApiController {
|
||||
private static final String CONTROLLER_NAME = 'ApiController'
|
||||
@ -115,8 +116,7 @@ class ApiController {
|
||||
|
||||
Map.Entry<String, String> validationResponse = validateRequest(
|
||||
ValidationService.ApiCall.CREATE,
|
||||
request.getParameterMap(),
|
||||
request.getQueryString()
|
||||
request
|
||||
)
|
||||
|
||||
if(!(validationResponse == null)) {
|
||||
@ -208,7 +208,6 @@ class ApiController {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**********************************************
|
||||
* JOIN API
|
||||
*********************************************/
|
||||
@ -220,8 +219,7 @@ class ApiController {
|
||||
|
||||
Map.Entry<String, String> validationResponse = validateRequest(
|
||||
ValidationService.ApiCall.JOIN,
|
||||
request.getParameterMap(),
|
||||
request.getQueryString()
|
||||
request
|
||||
)
|
||||
|
||||
HashMap<String, String> roles = new HashMap<String, String>();
|
||||
@ -520,8 +518,7 @@ class ApiController {
|
||||
|
||||
Map.Entry<String, String> validationResponse = validateRequest(
|
||||
ValidationService.ApiCall.MEETING_RUNNING,
|
||||
request.getParameterMap(),
|
||||
request.getQueryString()
|
||||
request
|
||||
)
|
||||
|
||||
if(!(validationResponse == null)) {
|
||||
@ -551,8 +548,7 @@ class ApiController {
|
||||
|
||||
Map.Entry<String, String> validationResponse = validateRequest(
|
||||
ValidationService.ApiCall.END,
|
||||
request.getParameterMap(),
|
||||
request.getQueryString()
|
||||
request
|
||||
)
|
||||
|
||||
if(!(validationResponse == null)) {
|
||||
@ -595,8 +591,7 @@ class ApiController {
|
||||
|
||||
Map.Entry<String, String> validationResponse = validateRequest(
|
||||
ValidationService.ApiCall.GET_MEETING_INFO,
|
||||
request.getParameterMap(),
|
||||
request.getQueryString()
|
||||
request
|
||||
)
|
||||
|
||||
if(!(validationResponse == null)) {
|
||||
@ -604,7 +599,8 @@ class ApiController {
|
||||
return
|
||||
}
|
||||
|
||||
Meeting meeting = ServiceUtils.findMeetingFromMeetingID(params.meetingID);
|
||||
String meetingId = params.list("meetingID")[0]
|
||||
Meeting meeting = ServiceUtils.findMeetingFromMeetingID(meetingId);
|
||||
|
||||
withFormat {
|
||||
xml {
|
||||
@ -622,8 +618,7 @@ class ApiController {
|
||||
|
||||
Map.Entry<String, String> validationResponse = validateRequest(
|
||||
ValidationService.ApiCall.GET_MEETINGS,
|
||||
request.getParameterMap(),
|
||||
request.getQueryString()
|
||||
request
|
||||
)
|
||||
|
||||
if(!(validationResponse == null)) {
|
||||
@ -660,8 +655,7 @@ class ApiController {
|
||||
|
||||
Map.Entry<String, String> validationResponse = validateRequest(
|
||||
ValidationService.ApiCall.GET_SESSIONS,
|
||||
request.getParameterMap(),
|
||||
request.getQueryString()
|
||||
request
|
||||
)
|
||||
|
||||
if(!(validationResponse == null)) {
|
||||
@ -719,8 +713,7 @@ class ApiController {
|
||||
|
||||
Map.Entry<String, String> validationResponse = validateRequest(
|
||||
ValidationService.ApiCall.GUEST_WAIT,
|
||||
request.getParameterMap(),
|
||||
request.getQueryString()
|
||||
request
|
||||
)
|
||||
if(!(validationResponse == null)) {
|
||||
msgKey = validationResponse.getKey()
|
||||
@ -833,8 +826,7 @@ class ApiController {
|
||||
|
||||
Map.Entry<String, String> validationResponse = validateRequest(
|
||||
ValidationService.ApiCall.ENTER,
|
||||
request.getParameterMap(),
|
||||
request.getQueryString(),
|
||||
request
|
||||
)
|
||||
if(!(validationResponse == null)) {
|
||||
respMessage = validationResponse.getValue()
|
||||
@ -991,8 +983,7 @@ class ApiController {
|
||||
|
||||
Map.Entry<String, String> validationResponse = validateRequest(
|
||||
ValidationService.ApiCall.STUNS,
|
||||
request.getParameterMap(),
|
||||
request.getQueryString(),
|
||||
request
|
||||
)
|
||||
|
||||
if(!(validationResponse == null)) {
|
||||
@ -1068,8 +1059,7 @@ class ApiController {
|
||||
|
||||
Map.Entry<String, String> validationResponse = validateRequest(
|
||||
ValidationService.ApiCall.SIGN_OUT,
|
||||
request.getParameterMap(),
|
||||
request.getQueryString()
|
||||
request
|
||||
)
|
||||
|
||||
if(validationResponse == null) {
|
||||
@ -1113,8 +1103,7 @@ class ApiController {
|
||||
|
||||
Map.Entry<String, String> validationResponse = validateRequest(
|
||||
ValidationService.ApiCall.INSERT_DOCUMENT,
|
||||
request.getParameterMap(),
|
||||
request.getQueryString()
|
||||
request
|
||||
)
|
||||
|
||||
def externalMeetingId = params.meetingID.toString()
|
||||
@ -1166,8 +1155,7 @@ class ApiController {
|
||||
|
||||
Map.Entry<String, String> validationResponse = validateRequest(
|
||||
ValidationService.ApiCall.GET_JOIN_URL,
|
||||
request.getParameterMap(),
|
||||
request.getQueryString(),
|
||||
request
|
||||
)
|
||||
|
||||
//Validate Session
|
||||
@ -1266,8 +1254,7 @@ class ApiController {
|
||||
|
||||
Map.Entry<String, String> validationResponse = validateRequest(
|
||||
ValidationService.ApiCall.LEARNING_DASHBOARD,
|
||||
request.getParameterMap(),
|
||||
request.getQueryString(),
|
||||
request
|
||||
)
|
||||
|
||||
//Validate Session
|
||||
@ -1945,8 +1932,8 @@ class ApiController {
|
||||
redirect(url: newUri)
|
||||
}
|
||||
|
||||
private Map.Entry<String, String> validateRequest(ValidationService.ApiCall apiCall, Map<String, String[]> params, String queryString) {
|
||||
Map<String, String> violations = validationService.validate(apiCall, params, queryString)
|
||||
private Map.Entry<String, String> validateRequest(ValidationService.ApiCall apiCall, HttpServletRequest request) {
|
||||
Map<String, String> violations = validationService.validate(apiCall, request)
|
||||
Map.Entry<String, String> response = null
|
||||
|
||||
if(!violations.isEmpty()) {
|
||||
|
@ -106,7 +106,7 @@ Updated in 2.7:
|
||||
|
||||
- **create** - **Added:** `preUploadedPresentation`, `preUploadedPresentationName`, `disabledFeatures` options`cameraAsContent`, `snapshotOfCurrentSlide`, `downloadPresentationOriginalFile`, `downloadPresentationConvertedToPdf`, `timer`, `learningDashboardDownloadSessionData` (2.7.5).
|
||||
|
||||
- **join** - **Added:** `redirectErrorUrl`, `userdata-bbb_fullaudio_bridge`
|
||||
- **join** - **Added:** `redirectErrorUrl`, `userdata-bbb_fullaudio_bridge` and removed support for all HTTP request methods except GET
|
||||
|
||||
## API Data Types
|
||||
|
||||
@ -211,6 +211,8 @@ To use the security model, you must be able to create a SHA-1 checksum out of th
|
||||
|
||||
You **MUST** send this checksum with **EVERY** API call. Since end users do not know your shared secret, they can not fake calls to the server, and they can not modify any API calls since changing a single parameter name or value by only one character will completely change the checksum required to validate the call.
|
||||
|
||||
**NOTE** Checksums for POST requests must be calculated using the URL query string as well. For example, if all request parameters are in the request body then the checksum will be calculated using an empty query string.
|
||||
|
||||
Implementations of the SHA-1 functionality exist in nearly all programming languages. Here are example methods or links to example implementations for various languages:
|
||||
|
||||
- [JavaScript](http://pajhome.org.uk/crypt/md5/)
|
||||
@ -280,7 +282,7 @@ The following response parameters are standard to every call and may be returned
|
||||
| message | Sometimes | String | A message that gives additional information about the status of the call. A message parameter will always be returned if the returncode was `FAILED`. A message may also be returned in some cases where returncode was `SUCCESS` if additional information would be helpful.|
|
||||
| messageKey | Sometimes | String | Provides similar functionality to the message and follows the same rules. However, a message key will be much shorter and will generally remain the same for the life of the API whereas a message may change over time. If your third party application would like to internationalize or otherwise change the standard messages returned, you can look up your own custom messages based on this messageKey.|
|
||||
|
||||
### create
|
||||
### `GET` `POST` create
|
||||
|
||||
Creates a BigBlueButton meeting.
|
||||
|
||||
@ -466,7 +468,7 @@ The receiving endpoint should respond with one of the following HTTP codes to in
|
||||
|
||||
All other HTTP response codes will be treated as transient errors.
|
||||
|
||||
### join
|
||||
### `GET` join
|
||||
|
||||
Joins a user to the meeting specified in the meetingID parameter.
|
||||
|
||||
@ -503,7 +505,7 @@ There is a XML response for this call only when the `redirect` parameter is set
|
||||
</response>
|
||||
```
|
||||
|
||||
### insertDocument
|
||||
### `POST` insertDocument
|
||||
|
||||
This endpoint insert one or more documents into a running meeting via API call
|
||||
|
||||
@ -555,7 +557,7 @@ curl -s -X POST "https://{your-host}/bigbluebutton/api/insertDocument?meetingID=
|
||||
|
||||
There is also the possibility of passing the removable and downloadable variables inside the payload, they go in the `document` tag as already demonstrated. The way it works is exactly the same as in the [(POST) create endpoint](#pre-upload-slides)
|
||||
|
||||
### isMeetingRunning
|
||||
### `GET` `POST` isMeetingRunning
|
||||
|
||||
This call enables you to simply check on whether or not a meeting is running by looking it up with your meeting ID.
|
||||
|
||||
@ -584,7 +586,7 @@ http://yourserver.com/bigbluebutton/api/isMeetingRunning?meetingID=test01&ch
|
||||
|
||||
running can be “true” or “false” that signals whether a meeting with this ID is currently running.
|
||||
|
||||
### end
|
||||
### `GET` `POST` end
|
||||
|
||||
Use this to forcibly end a meeting and kick all participants out of the meeting.
|
||||
|
||||
@ -628,7 +630,7 @@ curl --request POST \
|
||||
|
||||
**IMPORTANT NOTE:** You should note that when you call end meeting, it is simply sending a request to the backend (Red5) server that is handling all the conference traffic. That backend server will immediately attempt to send every connected client a logout event, kicking them from the meeting. It will then disconnect them, and the meeting will be ended. However, this may take several seconds, depending on network conditions. Therefore, the end meeting call will return a success as soon as the request is sent. But to be sure that it completed, you should then check back a few seconds later by using the `getMeetingInfo` or `isMeetingRunning` calls to verify that all participants have left the meeting and that it successfully ended.
|
||||
|
||||
### getMeetingInfo
|
||||
### `GET` `POST` getMeetingInfo
|
||||
|
||||
This call will return all of a meeting's information, including the list of attendees as well as start and end times.
|
||||
|
||||
@ -728,7 +730,7 @@ If a meeting is a breakout room itself, then `getMeetingInfo` will also return a
|
||||
</response>
|
||||
```
|
||||
|
||||
### getMeetings
|
||||
### `GET` `POST` getMeetings
|
||||
|
||||
This call will return a list of all the meetings found on this server.
|
||||
|
||||
@ -781,7 +783,7 @@ http://yourserver.com/bigbluebutton/api/getMeetings?checksum=1234
|
||||
</response>
|
||||
```
|
||||
|
||||
### getRecordings
|
||||
### `GET` getRecordings
|
||||
|
||||
Retrieves the recordings that are available for playback for a given meetingID (or set of meeting IDs). Support for pagination was added in 2.6.
|
||||
|
||||
@ -896,7 +898,7 @@ Here the `getRecordings` API call returned back two recordings for the meetingID
|
||||
</response>
|
||||
```
|
||||
|
||||
### publishRecordings
|
||||
### `GET` publishRecordings
|
||||
|
||||
Publish and unpublish recordings for a given recordID (or set of record IDs).
|
||||
|
||||
@ -924,7 +926,7 @@ Publish and unpublish recordings for a given recordID (or set of record IDs).
|
||||
</response>
|
||||
```
|
||||
|
||||
### deleteRecordings
|
||||
### `GET` deleteRecordings
|
||||
|
||||
Delete one or more recordings for a given recordID (or set of record IDs).
|
||||
|
||||
@ -952,7 +954,7 @@ http://yourserver.com/bigbluebutton/api/deleteRecordings?[parameters]&checks
|
||||
</response>
|
||||
```
|
||||
|
||||
### updateRecordings
|
||||
### `GET` `POST` updateRecordings
|
||||
|
||||
Update metadata for a given recordID (or set of record IDs). Available since version 1.1
|
||||
|
||||
@ -979,7 +981,7 @@ Update metadata for a given recordID (or set of record IDs). Available since ver
|
||||
</response>
|
||||
```
|
||||
|
||||
### getRecordingTextTracks
|
||||
### `GET` `POST` getRecordingTextTracks
|
||||
|
||||
Get a list of the caption/subtitle files currently available for a recording. It will include information about the captions (language, etc.), as well as a download link. This may be useful to retrieve live or automatically transcribed subtitles from a recording for manual editing.
|
||||
|
||||
@ -1059,7 +1061,7 @@ missingParameter
|
||||
noRecordings
|
||||
: No recording was found matching the provided recording ID.
|
||||
|
||||
### putRecordingTextTrack
|
||||
### `POST` putRecordingTextTrack
|
||||
|
||||
Upload a caption or subtitle file to add it to the recording. If there is any existing track with the same values for kind and lang, it will be replaced.
|
||||
|
||||
|
@ -197,6 +197,9 @@ If `preUploadedPresentationOverrideDefault=false` (or omitted, since `false` is
|
||||
|
||||
In BigBlueButton 2.6.17/2.7.5 we added a new configuration property for bbb-apps-akka package under `services` called `checkSumAlgorithmForBreakouts`. By default the value is `"sha256"`. It controls the algorithm for checksum calculation for the breakout rooms join link. In case you overwrite bbb-web's `supportedChecksumAlgorithms` property removing sha256 you will need to set a supported algorithm here too. For example if you want to only use `sha512`, set `supportedChecksumAlgorithms=sha512` in `/etc/bigbluebutton/bbb-web.properties` and also set `checkSumAlgorithmForBreakouts="sha512"` in `/etc/bigbluebutton/bbb-apps-akka.conf` and then restart BigBlueButton.
|
||||
|
||||
#### Removed support for POST requests on `join` endpoint and Content-Type headers are now required
|
||||
|
||||
In BigBlueButton 2.6.18/2.7.8 POST requests are no longer allowed for the `join` endpoint. To ensure they are validated properly, a `Content-Type` header must also be provided for POST requests that contain data in the request body. Endpoints now support a limited set of content types that includes `text/xml`, `application/xml`, `application/x-www-form-url-encoded`, and `multipart/form-data`. By default each endpoint only supports `application/x-www-form-urlencoded` and `multipart/form-data`, but individual endpoints can override this and define their own set of supported content types. The `create` endpoint supports all of the four previously listed content types while `insertDocument` supports only `text/xml` and `application/xml`. Any requests with a content type that differs from the set supported by the target endpoint will be rejected with a new `unsupportedContentType` error.
|
||||
|
||||
### Development
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user