From b92d2a546f19b95046258e2a1312cd66184d67d5 Mon Sep 17 00:00:00 2001
From: Rushiraj Nenuji <19696935+rushirajnenuji@users.noreply.github.com>
Date: Mon, 18 Dec 2023 19:34:07 +0530
Subject: [PATCH 1/3] Return serialized XML objects instead of String
Return serialized XML objects instead of String
Reference: https://github.com/NCEAS/metacatui/issues/2235
---
src/js/collections/AccessPolicy.js | 35 ++++++++-------
src/js/models/AccessRule.js | 69 ++++++++++++++----------------
2 files changed, 49 insertions(+), 55 deletions(-)
diff --git a/src/js/collections/AccessPolicy.js b/src/js/collections/AccessPolicy.js
index 7efe4703c..93222e1b4 100644
--- a/src/js/collections/AccessPolicy.js
+++ b/src/js/collections/AccessPolicy.js
@@ -124,28 +124,27 @@ define(["jquery", "underscore", "backbone", "models/AccessRule"],
},
/**
- * Creates an access policy XML from the values set on the member
- * AccessRule models.
- * @return {string} A string of the access policy XML
- */
- serialize: function(){
-
- if( this.length == 0 )
- return "";
+ * Creates an access policy XML from the values set on the member
+ * AccessRule models.
+ * @returns {object} A XML object of the access policy or null if empty
+ */
+ serialize: function() {
+ if (this.length === 0) {
+ return null;
+ }
- //Create the access policy node which will contain all the rules
- var xml = "\n";
+ // Create the access policy node which will contain all the rules
+ var accessPolicyElement = document.createElement('accesspolicy');
- //Serialize each AccessRule member model and add to the policy DOM
- this.each(function(accessRule){
- xml += accessRule.serialize();
+ // Serialize each AccessRule member model and add to the policy DOM
+ this.each(function(accessRule) {
+ var accessRuleNode = accessRule.serialize();
+ if (accessRuleNode) {
+ accessPolicyElement.appendChild(accessRuleNode);
+ }
});
- xml += "\n"
-
- //Convert the access policy DOM to a string and return it
- return xml;
-
+ return accessPolicyElement;
},
/**
diff --git a/src/js/models/AccessRule.js b/src/js/models/AccessRule.js
index 2bb6ade4c..108a2bd5d 100644
--- a/src/js/models/AccessRule.js
+++ b/src/js/models/AccessRule.js
@@ -53,46 +53,41 @@ define(['jquery', 'underscore', 'backbone'],
},
/**
- * Takes the values set on this model's attributes and creates an XML string
- * to be inserted into a DataONEObject's system metadata access policy.
- * @return {string} The access rule XML string
- */
- serialize: function(){
-
- var xml = "";
-
- //Serialize the allow rules
- if( this.get("read") || this.get("write") || this.get("changePermission") ){
-
- //Start the "allow" node
- xml += '\t\n';
-
- //Add the subject
- xml += '\t\t' + this.get("subject") + '\n';
-
- //Add the read permission
- if( this.get("read") ){
- xml += '\t\tread\n';
- }
-
- //Add the write permission
- if( this.get("write") ){
- xml += '\t\twrite\n';
- }
-
- //Add the changePermission permission
- if( this.get("changePermission") ){
- xml += '\t\tchangePermission\n';
- }
-
- //Close the "allow" node
- xml += '\t\n';
+ * Takes the values set on this model's attributes and creates an XML string
+ * to be inserted into a DataONEObject's system metadata access policy.
+ * @returns {object} The access rule XML object or null if not created
+ */
+ serialize: function() {
+ // Serialize the allow rules
+ if (this.get("read") || this.get("write") || this.get("changePermission")) {
+ // Create the element
+ var allowElement = document.createElement('allow');
+
+ // Create the element and set its text content
+ var subjectElement = document.createElement('subject');
+ subjectElement.textContent = this.get("subject");
+
+ // Append the and elements to
+ allowElement.appendChild(subjectElement);
+
+ // Create the elements and set their text content
+ var permissions = ['read', 'write', 'changePermission'];
+ for (var i = 0; i < permissions.length; i++) {
+ if (this.get(permissions[i])) {
+ var permissionElement = document.createElement('permission');
+ permissionElement.textContent = permissions[i];
+ allowElement.appendChild(permissionElement);
+ }
+ }
- }
+ // Return the element
+ return allowElement;
+ }
- return xml;
+ // If no access rule is created, return null
+ return null;
+ },
- },
/**
* Gets and sets the subject info for the subjects in this access policy.
From 7b4c7d9177fa80518663426b260669dadc1e8dc0 Mon Sep 17 00:00:00 2001
From: Rushiraj Nenuji <19696935+rushirajnenuji@users.noreply.github.com>
Date: Tue, 19 Dec 2023 19:38:26 +0530
Subject: [PATCH 2/3] Update AccessRule model
Update AccessRule model to parse garbled XML
Reference #2235
---
src/js/models/AccessRule.js | 65 +++++++++++++++++++++++++++----------
1 file changed, 47 insertions(+), 18 deletions(-)
diff --git a/src/js/models/AccessRule.js b/src/js/models/AccessRule.js
index 108a2bd5d..f443b008d 100644
--- a/src/js/models/AccessRule.js
+++ b/src/js/models/AccessRule.js
@@ -28,29 +28,58 @@ define(['jquery', 'underscore', 'backbone'],
},
/**
- * Translates the access rule XML DOM into a JSON object to be set on the model.
- * @param {Element} accessRuleXML An DOM element that contains a single access rule
- * @return {JSON} The Access Rule values to be set on this model
- */
- parse: function( accessRuleXML ){
- //If there is no access policy, do not attempt to parse anything
- if( typeof accessRuleXML == "undefined" || !accessRuleXML)
- return {};
+ * Translates the access rule XML DOM into a JSON object to be set on the model.
+ * @param {Element} accessRuleXML An DOM element that contains a single access rule
+ * @return {JSON} The Access Rule values to be set on this model
+ */
+ parse: function(accessRuleXML) {
+ // If there is no access policy, do not attempt to parse anything
+ if (typeof accessRuleXML === "undefined" || !accessRuleXML) {
+ return {};
+ }
- accessRuleXML = $(accessRuleXML);
+ var accessRuleXMLObj = $(accessRuleXML);
- //Start an access rule object with the given subject
- var parsedAccessRule = {
- subject: accessRuleXML.find("subject").text()
- }
+ // Start an access rule object with the given subject
+ var parsedAccessRule = {
+ subject: accessRuleXMLObj.find("subject").text()
+ };
- _.each( accessRuleXML.find("permission"), function( permissionNode ){
- parsedAccessRule[ $(permissionNode).text() ] = true;
- });
+ _.each(accessRuleXMLObj.find("permission"), function(permissionNode, idx) {
+ let permissionText = $(permissionNode).text().trim();
- return parsedAccessRule;
+ // Check if the permission text is not empty
+ if (permissionText.length) {
+ // Save the parsed permission
+ parsedAccessRule[permissionText] = true;
+ } else {
+ // This is added as a workaround for malformed permission XML
+ // introduced by Chromium 120.X
+ // See https://github.com/NCEAS/metacatui/issues/2235
- },
+ // Define the regular expression
+ let globalPermRegex = /<\/permission>(.*)/g;
+ // Define the regular expression
+ let permRegex = /<\/permission>(.*)/;
+
+ let accessRoleStr = accessRuleXMLObj.html();
+
+ let matches = accessRoleStr.match(globalPermRegex);
+
+ // Check if matches exist and have a length
+ if (matches && matches.length && idx < matches.length) {
+ let permMatch = matches[idx].match(permRegex);
+
+ // Check if permMatch exists and has a length
+ if (permMatch && permMatch.length) {
+ parsedAccessRule[permMatch[1]] = true;
+ }
+ }
+ }
+ });
+
+ return parsedAccessRule;
+ },
/**
* Takes the values set on this model's attributes and creates an XML string
From 758ff8e3710637d9fdf406a9c2383e56ff5be877 Mon Sep 17 00:00:00 2001
From: Robyn Thiessen-Bock
Date: Tue, 19 Dec 2023 14:21:56 -0500
Subject: [PATCH 3/3] Update version to 2.27.1 and rebuild docs
---
README.md | 2 +-
docs/_config.yml | 2 +-
docs/docs/AccessPolicy.html | 22 +--
docs/docs/AccessRule.html | 12 +-
.../src_js_collections_AccessPolicy.js.html | 35 +++--
docs/docs/src_js_models_AccessRule.js.html | 126 +++++++++++-------
docs/index.md | 2 +-
package.json | 2 +-
src/index.html | 2 +-
9 files changed, 114 insertions(+), 91 deletions(-)
diff --git a/README.md b/README.md
index af37378e1..cae39c75e 100644
--- a/README.md
+++ b/README.md
@@ -17,7 +17,7 @@ MetacatUI is an open source, community project. We [welcome contributions](http
Cite this software as:
-> Matthew B. Jones, Chris Jones, Lauren Walker, Robyn Thiessen-Bock, Ben Leinfelder, Peter Slaughter, Bryce Mecum, Rushiraj Nenuji, Hesham Elbashandy, Val Hendrix. 2022. MetacatUI: A client-side web interface for DataONE data repositories (version 2.27.0). Arctic Data Center. [doi:10.18739/A25M6282K](https://doi.org/10.18739/A25M6282K)
+> Matthew B. Jones, Chris Jones, Lauren Walker, Robyn Thiessen-Bock, Ben Leinfelder, Peter Slaughter, Bryce Mecum, Rushiraj Nenuji, Hesham Elbashandy, Val Hendrix. 2023. MetacatUI: A client-side web interface for DataONE data repositories (version 2.27.1). Arctic Data Center. [doi:10.18739/A25M6282K](https://doi.org/10.18739/A25M6282K)
## Screenshots
diff --git a/docs/_config.yml b/docs/_config.yml
index f0b94ecb6..72dd93506 100644
--- a/docs/_config.yml
+++ b/docs/_config.yml
@@ -1,3 +1,3 @@
url: "/metacatui"
highlighter: "rouge"
-version: "2.27.0"
+version: "2.27.1"
diff --git a/docs/docs/AccessPolicy.html b/docs/docs/AccessPolicy.html
index d25c63484..b1c57e29e 100644
--- a/docs/docs/AccessPolicy.html
+++ b/docs/docs/AccessPolicy.html
@@ -564,7 +564,7 @@
},
/**
- * Creates an access policy XML from the values set on the member
- * AccessRule models.
- * @return {string} A string of the access policy XML
- */
- serialize: function(){
-
- if( this.length == 0 )
- return "";
+ * Creates an access policy XML from the values set on the member
+ * AccessRule models.
+ * @returns {object} A XML object of the access policy or null if empty
+ */
+ serialize: function() {
+ if (this.length === 0) {
+ return null;
+ }
- //Create the access policy node which will contain all the rules
- var xml = "<accessPolicy>\n";
+ // Create the access policy node which will contain all the rules
+ var accessPolicyElement = document.createElement('accesspolicy');
- //Serialize each AccessRule member model and add to the policy DOM
- this.each(function(accessRule){
- xml += accessRule.serialize();
+ // Serialize each AccessRule member model and add to the policy DOM
+ this.each(function(accessRule) {
+ var accessRuleNode = accessRule.serialize();
+ if (accessRuleNode) {
+ accessPolicyElement.appendChild(accessRuleNode);
+ }
});
- xml += "\n</accessPolicy>"
-
- //Convert the access policy DOM to a string and return it
- return xml;
-
+ return accessPolicyElement;
},
/**
diff --git a/docs/docs/src_js_models_AccessRule.js.html b/docs/docs/src_js_models_AccessRule.js.html
index 3a08e29c8..e7c040418 100644
--- a/docs/docs/src_js_models_AccessRule.js.html
+++ b/docs/docs/src_js_models_AccessRule.js.html
@@ -74,71 +74,95 @@
Source: src/js/models/AccessRule.js
},
/**
- * Translates the access rule XML DOM into a JSON object to be set on the model.
- * @param {Element} accessRuleXML An <allow> DOM element that contains a single access rule
- * @return {JSON} The Access Rule values to be set on this model
- */
- parse: function( accessRuleXML ){
- //If there is no access policy, do not attempt to parse anything
- if( typeof accessRuleXML == "undefined" || !accessRuleXML)
- return {};
-
- accessRuleXML = $(accessRuleXML);
-
- //Start an access rule object with the given subject
- var parsedAccessRule = {
- subject: accessRuleXML.find("subject").text()
- }
-
- _.each( accessRuleXML.find("permission"), function( permissionNode ){
- parsedAccessRule[ $(permissionNode).text() ] = true;
- });
+ * Translates the access rule XML DOM into a JSON object to be set on the model.
+ * @param {Element} accessRuleXML An <allow> DOM element that contains a single access rule
+ * @return {JSON} The Access Rule values to be set on this model
+ */
+ parse: function(accessRuleXML) {
+ // If there is no access policy, do not attempt to parse anything
+ if (typeof accessRuleXML === "undefined" || !accessRuleXML) {
+ return {};
+ }
- return parsedAccessRule;
+ var accessRuleXMLObj = $(accessRuleXML);
- },
+ // Start an access rule object with the given subject
+ var parsedAccessRule = {
+ subject: accessRuleXMLObj.find("subject").text()
+ };
- /**
- * Takes the values set on this model's attributes and creates an XML string
- * to be inserted into a DataONEObject's system metadata access policy.
- * @return {string} The access rule XML string
- */
- serialize: function(){
+ _.each(accessRuleXMLObj.find("permission"), function(permissionNode, idx) {
+ let permissionText = $(permissionNode).text().trim();
- var xml = "";
+ // Check if the permission text is not empty
+ if (permissionText.length) {
+ // Save the parsed permission
+ parsedAccessRule[permissionText] = true;
+ } else {
+ // This is added as a workaround for malformed permission XML
+ // introduced by Chromium 120.X
+ // See https://github.com/NCEAS/metacatui/issues/2235
- //Serialize the allow rules
- if( this.get("read") || this.get("write") || this.get("changePermission") ){
+ // Define the regular expression
+ let globalPermRegex = /<permission><\/permission>(.*)/g;
+ // Define the regular expression
+ let permRegex = /<permission><\/permission>(.*)/;
- //Start the "allow" node
- xml += '\t<allow>\n';
+ let accessRoleStr = accessRuleXMLObj.html();
- //Add the subject
- xml += '\t\t<subject>' + this.get("subject") + '</subject>\n';
+ let matches = accessRoleStr.match(globalPermRegex);
- //Add the read permission
- if( this.get("read") ){
- xml += '\t\t<permission>read</permission>\n';
- }
+ // Check if matches exist and have a length
+ if (matches && matches.length && idx < matches.length) {
+ let permMatch = matches[idx].match(permRegex);
- //Add the write permission
- if( this.get("write") ){
- xml += '\t\t<permission>write</permission>\n';
- }
+ // Check if permMatch exists and has a length
+ if (permMatch && permMatch.length) {
+ parsedAccessRule[permMatch[1]] = true;
+ }
+ }
+ }
+ });
- //Add the changePermission permission
- if( this.get("changePermission") ){
- xml += '\t\t<permission>changePermission</permission>\n';
- }
+ return parsedAccessRule;
+ },
- //Close the "allow" node
- xml += '\t</allow>\n';
+ /**
+ * Takes the values set on this model's attributes and creates an XML string
+ * to be inserted into a DataONEObject's system metadata access policy.
+ * @returns {object} The access rule XML object or null if not created
+ */
+ serialize: function() {
+ // Serialize the allow rules
+ if (this.get("read") || this.get("write") || this.get("changePermission")) {
+ // Create the <allow> element
+ var allowElement = document.createElement('allow');
+
+ // Create the <subject> element and set its text content
+ var subjectElement = document.createElement('subject');
+ subjectElement.textContent = this.get("subject");
+
+ // Append the <subject> and <permission> elements to <allow>
+ allowElement.appendChild(subjectElement);
+
+ // Create the <permission> elements and set their text content
+ var permissions = ['read', 'write', 'changePermission'];
+ for (var i = 0; i < permissions.length; i++) {
+ if (this.get(permissions[i])) {
+ var permissionElement = document.createElement('permission');
+ permissionElement.textContent = permissions[i];
+ allowElement.appendChild(permissionElement);
+ }
+ }
- }
+ // Return the <allow> element
+ return allowElement;
+ }
- return xml;
+ // If no access rule is created, return null
+ return null;
+ },
- },
/**
* Gets and sets the subject info for the subjects in this access policy.
diff --git a/docs/index.md b/docs/index.md
index cc3a44a34..8f99ba8c0 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -22,7 +22,7 @@ MetacatUI is an open source, community project. We [welcome contributions](http
Cite this software as:
-> Matthew B. Jones, Chris Jones, Lauren Walker, Robyn Thiessen-Bock, Ben Leinfelder, Peter Slaughter, Bryce Mecum, Rushiraj Nenuji, Hesham Elbashandy, Val Hendrix. 2022. MetacatUI: A client-side web interface for DataONE data repositories (version 2.24.0). Arctic Data Center. [doi:10.18739/A25M6282K](https://doi.org/10.18739/A25M6282K)
+> Matthew B. Jones, Chris Jones, Lauren Walker, Robyn Thiessen-Bock, Ben Leinfelder, Peter Slaughter, Bryce Mecum, Rushiraj Nenuji, Hesham Elbashandy, Val Hendrix. 2023. MetacatUI: A client-side web interface for DataONE data repositories (version 2.27.1). Arctic Data Center. [doi:10.18739/A25M6282K](https://doi.org/10.18739/A25M6282K)
## Related Projects
diff --git a/package.json b/package.json
index a48ee0062..59a498086 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "metacatui",
- "version": "2.27.0",
+ "version": "2.27.1",
"description": "MetacatUI: A client-side web interface for DataONE data repositories",
"main": "server.js",
"dependencies": {
diff --git a/src/index.html b/src/index.html
index 1e01d7c0a..e28552077 100644
--- a/src/index.html
+++ b/src/index.html
@@ -44,7 +44,7 @@
//Create the MetacatUI object
var MetacatUI = {};
- MetacatUI.metacatUIVersion = "2.27.0";
+ MetacatUI.metacatUIVersion = "2.27.1";
//Catch errors when the config or loader file fails to load.
// These are mainly helpful for developers/operators installing MetacatUI