feat(akka): Plugin Js relative entrypoint and refactor of pluginManifests parameter (#21485)

* [js-relative-endpoint-refactors] - Added relative js entrypoint - just the name and extension

* [js-relative-endpoint-refactors] - Changes name and references of  to  and adapt all the rest.

* [js-relative-endpoint-refactors] changes in review
This commit is contained in:
Guilherme Pereira Leme 2024-10-21 12:27:31 -03:00 committed by GitHub
parent 873b590e91
commit a9e0e872b1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 61 additions and 50 deletions

View File

@ -61,13 +61,26 @@ object PluginModel {
def getPlugins(instance: PluginModel): Map[String, Plugin] = {
instance.plugins
}
def replaceRelativeJavascriptEntrypoint(plugin: Plugin): Plugin = {
val jsEntrypoint = plugin.manifest.content.javascriptEntrypointUrl
if (jsEntrypoint.startsWith("http://") || jsEntrypoint.startsWith("https://")) {
plugin
} else {
val baseUrl = plugin.manifest.url.substring(0, plugin.manifest.url.lastIndexOf('/') + 1)
val absoluteJavascriptEntrypoint = baseUrl + jsEntrypoint
val newPluginManifestContent = plugin.manifest.content.copy(javascriptEntrypointUrl = absoluteJavascriptEntrypoint)
val newPluginManifest = plugin.manifest.copy(content = newPluginManifestContent)
plugin.copy(manifest = newPluginManifest)
}
}
def createPluginModelFromJson(json: util.Map[String, AnyRef]): PluginModel = {
val instance = new PluginModel()
var pluginsMap: Map[String, Plugin] = Map.empty[String, Plugin]
json.forEach { case (pluginName, plugin) =>
try {
val pluginObject = objectMapper.readValue(objectMapper.writeValueAsString(plugin), classOf[Plugin])
pluginsMap = pluginsMap + (pluginName -> pluginObject)
val pluginObjectWithAbsoluteJavascriptEntrypoint = replaceRelativeJavascriptEntrypoint(pluginObject)
pluginsMap = pluginsMap + (pluginName -> pluginObjectWithAbsoluteJavascriptEntrypoint)
} catch {
case err @ (_: JsonProcessingException | _: JsonMappingException) => println("Error while processing plugin " +
pluginName + ": ", err)

View File

@ -73,7 +73,7 @@ public class ApiParams {
public static final String ROLE = "role";
public static final String GROUPS = "groups";
public static final String DISABLED_FEATURES = "disabledFeatures";
public static final String PLUGINS_MANIFESTS = "pluginsManifests";
public static final String PLUGIN_MANIFESTS = "pluginManifests";
public static final String DISABLED_FEATURES_EXCLUDE = "disabledFeaturesExclude";
public static final String NOTIFY_RECORDING_IS_ON = "notifyRecordingIsOn";

View File

@ -404,10 +404,10 @@ public class MeetingService implements MessageListener {
Map<String, String> metadata = m.getMetadata();
// Fetch content for each URL and store in the map
for (PluginsManifest pluginsManifest : m.getPluginsManifests()) {
for (PluginManifest pluginManifest : m.getPluginManifests()) {
try {
String urlString = pluginsManifest.getUrl();
String urlString = pluginManifest.getUrl();
URL url = new URL(urlString);
StringBuilder content = new StringBuilder();
try (BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()))) {
@ -421,15 +421,15 @@ public class MeetingService implements MessageListener {
JsonNode jsonNode = objectMapper.readTree(content.toString());
// Validate checksum if any:
String paramChecksum = pluginsManifest.getChecksum();
String paramChecksum = pluginManifest.getChecksum();
if (!StringUtils.isEmpty(paramChecksum)) {
String hash = DigestUtils.sha256Hex(content.toString());
if (!paramChecksum.equals(hash)) {
log.info("Plugin's manifest.json checksum mismatch with that of the URL parameter for {}.",
pluginsManifest.getUrl()
pluginManifest.getUrl()
);
log.info("Plugin {} is not going to be loaded",
pluginsManifest.getUrl()
pluginManifest.getUrl()
);
continue;
}
@ -458,7 +458,7 @@ public class MeetingService implements MessageListener {
urlContents.put(pluginKey, manifestWrapper);
} catch(Exception e) {
log.error("Failed with the following plugin manifest URL: {}. Error: ",
pluginsManifest.getUrl(), e);
pluginManifest.getUrl(), e);
log.error("Therefore this plugin will not be loaded");
}
}

View File

@ -99,7 +99,7 @@ public class ParamsProcessorUtil {
private boolean defaultAllowModsToUnmuteUsers = false;
private boolean defaultAllowModsToEjectCameras = false;
private String defaultDisabledFeatures;
private String defaultPluginsManifests;
private String defaultPluginManifests;
private boolean defaultNotifyRecordingIsOn = false;
private boolean defaultKeepEvents = false;
private Boolean useDefaultLogo;
@ -428,31 +428,31 @@ public class ParamsProcessorUtil {
return groups;
}
private ArrayList<PluginsManifest> processPluginsManifests(String pluginsManifestsParam) {
ArrayList<PluginsManifest> pluginsManifests = new ArrayList<PluginsManifest>();
JsonElement pluginsManifestsJsonElement = new Gson().fromJson(pluginsManifestsParam, JsonElement.class);
private ArrayList<PluginManifest> processPluginManifests(String pluginManifestsParam) {
ArrayList<PluginManifest> pluginManifests = new ArrayList<PluginManifest>();
JsonElement pluginManifestsJsonElement = new Gson().fromJson(pluginManifestsParam, JsonElement.class);
try {
if (pluginsManifestsJsonElement != null && pluginsManifestsJsonElement.isJsonArray()) {
JsonArray pluginsManifestsJson = pluginsManifestsJsonElement.getAsJsonArray();
for (JsonElement pluginsManifestJson : pluginsManifestsJson) {
if (pluginsManifestJson.isJsonObject()) {
JsonObject pluginsManifestJsonObj = pluginsManifestJson.getAsJsonObject();
if (pluginsManifestJsonObj.has("url")) {
String url = pluginsManifestJsonObj.get("url").getAsString();
PluginsManifest newPlugin = new PluginsManifest(url);
if (pluginsManifestJsonObj.has("checksum")) {
newPlugin.setChecksum(pluginsManifestJsonObj.get("checksum").getAsString());
if (pluginManifestsJsonElement != null && pluginManifestsJsonElement.isJsonArray()) {
JsonArray pluginManifestsJson = pluginManifestsJsonElement.getAsJsonArray();
for (JsonElement pluginManifestJson : pluginManifestsJson) {
if (pluginManifestJson.isJsonObject()) {
JsonObject pluginManifestJsonObj = pluginManifestJson.getAsJsonObject();
if (pluginManifestJsonObj.has("url")) {
String url = pluginManifestJsonObj.get("url").getAsString();
PluginManifest newPlugin = new PluginManifest(url);
if (pluginManifestJsonObj.has("checksum")) {
newPlugin.setChecksum(pluginManifestJsonObj.get("checksum").getAsString());
}
pluginsManifests.add(newPlugin);
pluginManifests.add(newPlugin);
}
}
}
}
} catch(JsonSyntaxException err){
log.error("Error in pluginsManifests URL parameter's json structure.");
log.error("Error in pluginManifests URL parameter's json structure.");
}
return pluginsManifests;
return pluginManifests;
}
public Meeting processCreateParams(Map<String, String> params) {
@ -574,17 +574,17 @@ public class ParamsProcessorUtil {
}
// Parse Plugins Manifests from config and param
ArrayList<PluginsManifest> listOfPluginsManifests = new ArrayList<PluginsManifest>();
ArrayList<PluginManifest> listOfPluginManifests = new ArrayList<PluginManifest>();
//Process plugins from config
if(defaultPluginsManifests != null && !defaultPluginsManifests.isEmpty()) {
ArrayList<PluginsManifest> pluginsManifestsFromConfig = processPluginsManifests(defaultPluginsManifests);
listOfPluginsManifests.addAll(pluginsManifestsFromConfig);
if(defaultPluginManifests != null && !defaultPluginManifests.isEmpty()) {
ArrayList<PluginManifest> pluginManifestsFromConfig = processPluginManifests(defaultPluginManifests);
listOfPluginManifests.addAll(pluginManifestsFromConfig);
}
//Process plugins from /create param
String pluginsManifestsParam = params.get(ApiParams.PLUGINS_MANIFESTS);
if (!StringUtils.isEmpty(pluginsManifestsParam)) {
ArrayList<PluginsManifest> pluginsManifestsFromParam = processPluginsManifests(pluginsManifestsParam);
listOfPluginsManifests.addAll(pluginsManifestsFromParam);
String pluginManifestsParam = params.get(ApiParams.PLUGIN_MANIFESTS);
if (!StringUtils.isEmpty(pluginManifestsParam)) {
ArrayList<PluginManifest> pluginManifestsFromParam = processPluginManifests(pluginManifestsParam);
listOfPluginManifests.addAll(pluginManifestsFromParam);
}
// Check if VirtualBackgrounds is disabled
@ -827,7 +827,7 @@ public class ParamsProcessorUtil {
.withLearningDashboardCleanupDelayInMinutes(learningDashboardCleanupMins)
.withLearningDashboardAccessToken(learningDashboardAccessToken)
.withGroups(groups)
.withPluginManifests(listOfPluginsManifests)
.withPluginManifests(listOfPluginManifests)
.withDisabledFeatures(listOfDisabledFeatures)
.withNotifyRecordingIsOn(notifyRecordingIsOn)
.withPresentationUploadExternalDescription(presentationUploadExternalDescription)
@ -1620,8 +1620,8 @@ public class ParamsProcessorUtil {
this.defaultDisabledFeatures = disabledFeatures;
}
public void setPluginsManifests(String pluginsManifests) {
this.defaultPluginsManifests = pluginsManifests;
public void setPluginManifests(String pluginManifests) {
this.defaultPluginManifests = pluginManifests;
}
public void setNotifyRecordingIsOn(Boolean notifyRecordingIsOn) {

View File

@ -79,7 +79,7 @@ public class Meeting {
private String defaultAvatarURL;
private String defaultWebcamBackgroundURL;
private Map<String, Object> plugins;
private ArrayList<PluginsManifest> pluginsManifests;
private ArrayList<PluginManifest> pluginManifests;
private String guestPolicy = GuestPolicy.ASK_MODERATOR;
private String guestLobbyMessage = "";
private Map<String,String> usersWithGuestLobbyMessages;
@ -130,7 +130,7 @@ public class Meeting {
extMeetingId = builder.externalId;
intMeetingId = builder.internalId;
disabledFeatures = builder.disabledFeatures;
pluginsManifests = builder.pluginsManifests;
pluginManifests = builder.pluginManifests;
notifyRecordingIsOn = builder.notifyRecordingIsOn;
presentationUploadExternalDescription = builder.presentationUploadExternalDescription;
presentationUploadExternalUrl = builder.presentationUploadExternalUrl;
@ -452,8 +452,8 @@ public class Meeting {
plugins = p;
}
public ArrayList<PluginsManifest> getPluginsManifests() {
return pluginsManifests;
public ArrayList<PluginManifest> getPluginManifests() {
return pluginManifests;
}
public Boolean getNotifyRecordingIsOn() {
@ -943,7 +943,7 @@ public class Meeting {
private int learningDashboardCleanupDelayInMinutes;
private String learningDashboardAccessToken;
private ArrayList<String> disabledFeatures;
private ArrayList<PluginsManifest> pluginsManifests;
private ArrayList<PluginManifest> pluginManifests;
private Boolean notifyRecordingIsOn;
private String presentationUploadExternalDescription;
private String presentationUploadExternalUrl;
@ -1078,8 +1078,8 @@ public class Meeting {
return this;
}
public Builder withPluginManifests(ArrayList<PluginsManifest> map) {
this.pluginsManifests = map;
public Builder withPluginManifests(ArrayList<PluginManifest> map) {
this.pluginManifests = map;
return this;
}

View File

@ -1,18 +1,16 @@
package org.bigbluebutton.api.domain;
import java.util.Vector;
public class PluginsManifest {
public class PluginManifest {
private String url = "";
private String checksum = "";
public PluginsManifest(
public PluginManifest(
String url,
String checksum) {
this.url = url;
this.checksum = checksum;
}
public PluginsManifest(
public PluginManifest(
String url) {
this.url = url;
}

View File

@ -480,4 +480,4 @@ allowDuplicateExtUserid=true
# list of plugins manifests (json array)
# e.g: [{url: "https://plugin_manifest.json"}]
pluginsManifests=
pluginManifests=

View File

@ -201,7 +201,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
<property name="defaultKeepEvents" value="${defaultKeepEvents}"/>
<property name="allowRevealOfBBBVersion" value="${allowRevealOfBBBVersion}"/>
<property name="allowOverrideClientSettingsOnCreateCall" value="${allowOverrideClientSettingsOnCreateCall}"/>
<property name="pluginsManifests" value="${pluginsManifests}"/>
<property name="pluginManifests" value="${pluginManifests}"/>
</bean>
<bean id="presentationService" class="org.bigbluebutton.web.services.PresentationService">