diff --git a/test-app/src/main/ml-config/security/roles/rest-evaluator.json b/test-app/src/main/ml-config/security/roles/rest-evaluator.json index 476c59cb..9d315236 100644 --- a/test-app/src/main/ml-config/security/roles/rest-evaluator.json +++ b/test-app/src/main/ml-config/security/roles/rest-evaluator.json @@ -2,7 +2,8 @@ "role-name": "rest-evaluator", "description": "REST writer who can eval, invoke, or set a dynamic databases", "role": [ - "rest-writer" + "rest-writer", + "sparql-update-user" ], "privilege": [ { @@ -49,6 +50,21 @@ "privilege-name": "xdmp-get-session-field", "action": "http://marklogic.com/xdmp/privileges/xdmp-get-session-field", "kind": "execute" + }, + { + "privilege-name": "xdmp-login", + "action": "http://marklogic.com/xdmp/privileges/xdmp-login", + "kind": "execute" + }, + { + "privilege-name": "unprotected-collections", + "action": "http://marklogic.com/xdmp/privileges/unprotected-collections", + "kind": "execute" + }, + { + "privilege-name": "xdmp-xslt-invoke", + "action": "http://marklogic.com/xdmp/privileges/xslt-invoke", + "kind": "execute" } ] -} \ No newline at end of file +} diff --git a/test-app/src/main/ml-config/security/roles/rest-login.json b/test-app/src/main/ml-config/security/roles/rest-login.json new file mode 100644 index 00000000..1e6308d0 --- /dev/null +++ b/test-app/src/main/ml-config/security/roles/rest-login.json @@ -0,0 +1,11 @@ +{ + "role-name": "rest-login", + "description": "Role granting xdmp:login privilege needed for REST transform invocations with different-transaction isolation", + "privilege": [ + { + "privilege-name": "xdmp-login", + "action": "http://marklogic.com/xdmp/privileges/xdmp-login", + "kind": "execute" + } + ] +} diff --git a/test-app/src/main/ml-config/security/users/rest-admin.json b/test-app/src/main/ml-config/security/users/rest-admin.json index 1d61dd6f..6936f7df 100644 --- a/test-app/src/main/ml-config/security/users/rest-admin.json +++ b/test-app/src/main/ml-config/security/users/rest-admin.json @@ -3,6 +3,9 @@ "description": "rest-admin user", "password": "x", "role": [ - "rest-admin" + "rest-admin", + "rest-evaluator", + "rest-extension-user", + "sparql-update-user" ] -} \ No newline at end of file +} diff --git a/test-app/src/main/ml-config/security/users/rest-reader.json b/test-app/src/main/ml-config/security/users/rest-reader.json index 7cdeed28..7ca1398e 100644 --- a/test-app/src/main/ml-config/security/users/rest-reader.json +++ b/test-app/src/main/ml-config/security/users/rest-reader.json @@ -3,6 +3,8 @@ "description": "rest-reader user", "password": "x", "role": [ - "rest-reader" + "rest-reader", + "rest-extension-user", + "rest-login" ] -} \ No newline at end of file +} diff --git a/test-app/src/main/ml-config/security/users/rest-temporal-writer.json b/test-app/src/main/ml-config/security/users/rest-temporal-writer.json index aa163780..4d57bd5d 100644 --- a/test-app/src/main/ml-config/security/users/rest-temporal-writer.json +++ b/test-app/src/main/ml-config/security/users/rest-temporal-writer.json @@ -3,6 +3,7 @@ "description": "rest-writer user with temporal privileges", "password": "x", "role": [ - "rest-temporal-writer" + "rest-temporal-writer", + "rest-extension-user" ] -} \ No newline at end of file +} diff --git a/test-app/src/main/ml-config/security/users/rest-transform-user.json b/test-app/src/main/ml-config/security/users/rest-transform-user.json new file mode 100644 index 00000000..029dd5c7 --- /dev/null +++ b/test-app/src/main/ml-config/security/users/rest-transform-user.json @@ -0,0 +1,10 @@ +{ + "user-name": "rest-transform-user", + "description": "rest-transform-user user", + "password": "x", + "role": [ + "rest-transform-internal", + "rest-reader", + "rest-login" + ] +} diff --git a/test-app/src/main/ml-config/security/users/rest-writer.json b/test-app/src/main/ml-config/security/users/rest-writer.json index 3dfe87db..47469e21 100644 --- a/test-app/src/main/ml-config/security/users/rest-writer.json +++ b/test-app/src/main/ml-config/security/users/rest-writer.json @@ -5,6 +5,7 @@ "role": [ "rest-writer", "rest-evaluator", - "temporal-admin" + "temporal-admin", + "rest-extension-user" ] } diff --git a/test-basic/documents-transform.js b/test-basic/documents-transform.js index 99ea76c3..de4b1986 100644 --- a/test-basic/documents-transform.js +++ b/test-basic/documents-transform.js @@ -187,7 +187,8 @@ describe('document transform', function(){ documents.length.should.equal(1); documents[0].content.should.have.property('timestamp'); documents[0].content.should.have.property('userName'); - documents[0].content.userName.should.eql('rest-writer'); + documents[0].content.userName.should.eql('rest-transform-user', + 'As of MarkLogic 11.3.5 and 12.0.2 JavaScript transforms execute as the dedicated rest-transform-user rather than the calling user\'s identity, preventing privilege escalation via malicious transforms'); done(); }) .catch(done); @@ -202,7 +203,8 @@ describe('document transform', function(){ documents.length.should.equal(1); documents[0].content.should.have.property('timestamp'); documents[0].content.should.have.property('userName'); - documents[0].content.userName.should.eql('rest-writer'); + documents[0].content.userName.should.eql('rest-transform-user', + 'As of MarkLogic 11.3.5 and 12.0.2 JavaScript transforms execute as the dedicated rest-transform-user rather than the calling user\'s identity, preventing privilege escalation via malicious transforms'); done(); }) .catch(done); @@ -221,7 +223,8 @@ describe('document transform', function(){ documents.length.should.equal(1); documents[0].content.should.have.property('timestamp'); documents[0].content.should.have.property('userName'); - documents[0].content.userName.should.eql('rest-writer'); + documents[0].content.userName.should.eql('rest-transform-user', + 'As of MarkLogic 11.3.5 and 12.0.2 JavaScript transforms execute as the dedicated rest-transform-user rather than the calling user\'s identity, preventing privilege escalation via malicious transforms'); done(); }) .catch(done); diff --git a/test-basic/optic-fromDocs.js b/test-basic/optic-fromDocs.js index b8b78206..039f9ee8 100644 --- a/test-basic/optic-fromDocs.js +++ b/test-basic/optic-fromDocs.js @@ -20,6 +20,8 @@ let uris = []; let serverConfiguration = {}; describe('optic-update fromDocs tests', function() { + // NOTE: op.fromDocs() with op.columnBuilder() is only supported in MarkLogic 12.1.0 and later. + // Tests in this suite are skipped automatically on earlier versions. this.timeout(15000); before(function (done) { @@ -34,6 +36,10 @@ describe('optic-update fromDocs tests', function() { describe('fromDocs', function () { before(function (done) { + if (serverConfiguration.serverVersion < 12.1) { + this.skip(); + return; + } // Insert test documents const testDocs = [ { @@ -73,7 +79,7 @@ describe('optic-update fromDocs tests', function() { } }, { - // we already have a geospatial element index for 'point' in wgs84 + // we already have a geospatial element index for 'point' in wgs84 // in the test-app ml-gradle project. Use that. Use 'point' to indicate location. uri: '/test/fromDocs/location-portland.json', contentType: 'application/json', @@ -127,14 +133,14 @@ describe('optic-update fromDocs tests', function() { } } ]; - + let readable = new Stream.Readable({objectMode: true}); testDocs.forEach(doc => { readable.push(doc); uris.push(doc.uri); }); readable.push(null); - + db.documents.writeAll(readable, { onCompletion: () => done() }); @@ -252,7 +258,7 @@ describe('optic-update fromDocs tests', function() { const portlandPoint = op.cts.point(45.52, -122.68); const searchRadius = 650; // miles - // geospatial element index is defined for 'point' in wgs84 + // geospatial element index is defined for 'point' in wgs84 const plan = op.fromDocs( op.cts.collectionQuery('fromDocs'), '/location', @@ -270,7 +276,7 @@ describe('optic-update fromDocs tests', function() { ['coordinate-system=wgs84'] ) ); - + execPlan(plan).then(function (response) { const output = getResults(response); output.length.should.be.equal(3); @@ -340,4 +346,4 @@ describe('optic-update fromDocs tests', function() { }); -}); \ No newline at end of file +}); diff --git a/test-complete/nodejs-dmsdk-readall-1.js b/test-complete/nodejs-dmsdk-readall-1.js index e2b2c0a1..d94917c1 100644 --- a/test-complete/nodejs-dmsdk-readall-1.js +++ b/test-complete/nodejs-dmsdk-readall-1.js @@ -1,6 +1,6 @@ /* -* Copyright (c) 2015-2025 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved. -*/ + * Copyright (c) 2015-2026 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved. + */ var fs = require('fs'); const path = require('path'); @@ -143,6 +143,7 @@ describe('readAll-tests-one', function () { function (err, arr) { if (err) { done(err); + return; } arr.forEach(item => { setTimeout(() => { @@ -158,8 +159,8 @@ describe('readAll-tests-one', function () { for (var c of resulContents) { expect(verifyCurrentContents(c)).to.be.true; } + done(); }); - done(); }); it('readAll one document with batch options', function (done) { @@ -173,6 +174,7 @@ describe('readAll-tests-one', function () { function (err, arr) { if (err) { done(err); + return; } arr.forEach(item => { setTimeout(() => { @@ -180,8 +182,8 @@ describe('readAll-tests-one', function () { }, 3000); expect(item.uri).to.equal('dmsdk.txt'); }); + done(); }); - done(); }); //Verify no errors when readAll has no Uris to read diff --git a/test-complete/nodejs-transform-javascript.js b/test-complete/nodejs-transform-javascript.js index 9f9e16ab..0291e762 100644 --- a/test-complete/nodejs-transform-javascript.js +++ b/test-complete/nodejs-transform-javascript.js @@ -1,5 +1,5 @@ /* -* Copyright (c) 2015-2025 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved. +* Copyright (c) 2015-2026 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved. */ var should = require('should'); var fs = require('fs'); @@ -73,9 +73,11 @@ describe('Transform test with javascript', function () { result(function (response) { //console.log(JSON.stringify(response, null, 4)); response[0].content.should.have.property('timestamp'); - response[0].content.userName.should.equal('rest-reader'); + response[0].content.userName.should.equal('rest-transform-user', + 'As of MarkLogic 11.3.5 and 12.0.2 JavaScript transforms execute as the dedicated rest-transform-user rather than the calling user\'s identity, preventing privilege escalation via malicious transforms'); done(); - }, done); + }) + .catch(done); }); it('should query', function (done) { @@ -130,9 +132,11 @@ describe('Transform test with javascript', function () { result(function (response) { //console.log(JSON.stringify(response, null, 4)); response[0].content.should.have.property('timestamp'); - response[0].content.userName.should.equal('rest-reader'); + response[0].content.userName.should.equal('rest-transform-user', + 'As of MarkLogic 11.3.5 and 12.0.2 JavaScript transforms execute as the dedicated rest-transform-user rather than the calling user\'s identity, preventing privilege escalation via malicious transforms'); done(); - }, done); + }) + .catch(done); }); /*it('should modify during write', function(done){ dbWriter.documents.write({