oracledb 7.0.0 → 26.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -6
- package/build/Release/oracledb-26.0.0-darwin-arm64.node +0 -0
- package/build/Release/oracledb-26.0.0-darwin-arm64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-26.0.0-js-buildinfo.txt +1 -0
- package/build/Release/oracledb-26.0.0-linux-arm64.node +0 -0
- package/build/Release/oracledb-26.0.0-linux-arm64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-26.0.0-linux-x64.node +0 -0
- package/build/Release/oracledb-26.0.0-linux-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-26.0.0-win32-x64.node +0 -0
- package/build/Release/oracledb-26.0.0-win32-x64.node-buildinfo.txt +1 -0
- package/lib/aqDeqOptions.js +4 -4
- package/lib/aqEnqOptions.js +2 -2
- package/lib/aqQueue.js +11 -6
- package/lib/connection.js +73 -18
- package/lib/constants.js +4 -0
- package/lib/endUserSecurityContext.js +30 -25
- package/lib/errors.js +92 -5
- package/lib/impl/connection.js +36 -0
- package/lib/impl/datahandlers/buffer.js +91 -18
- package/lib/impl/datahandlers/oson.js +3 -2
- package/lib/impl/parserHelpers.js +6 -2
- package/lib/impl/resultset.js +32 -11
- package/lib/oracledb.js +34 -0
- package/lib/pool.js +6 -2
- package/lib/queryStream.js +13 -5
- package/lib/resultset.js +10 -3
- package/lib/securityContextProvider.js +206 -0
- package/lib/thin/aq.js +2 -3
- package/lib/thin/connection.js +380 -24
- package/lib/thin/dbObject.js +20 -11
- package/lib/thin/pool.js +4 -3
- package/lib/thin/protocol/capabilities.js +37 -4
- package/lib/thin/protocol/constants.js +49 -1
- package/lib/thin/protocol/messages/aqArray.js +2 -2
- package/lib/thin/protocol/messages/aqBase.js +2 -2
- package/lib/thin/protocol/messages/auth.js +17 -6
- package/lib/thin/protocol/messages/base.js +75 -17
- package/lib/thin/protocol/messages/dataType.js +46 -0
- package/lib/thin/protocol/messages/directPathLoadStream.js +3 -2
- package/lib/thin/protocol/messages/execute.js +10 -4
- package/lib/thin/protocol/messages/index.js +4 -0
- package/lib/thin/protocol/messages/notification.js +281 -0
- package/lib/thin/protocol/messages/subscribe.js +181 -0
- package/lib/thin/protocol/messages/withData.js +23 -10
- package/lib/thin/protocol/packet.js +2 -4
- package/lib/thin/protocol/protocol.js +7 -4
- package/lib/thin/resultSet.js +40 -20
- package/lib/thin/sqlnet/ezConnectResolver.js +9 -2
- package/lib/thin/sqlnet/navNodes.js +7 -5
- package/lib/thin/sqlnet/networkSession.js +17 -11
- package/lib/thin/sqlnet/ntTcp.js +24 -8
- package/lib/thin/sqlnet/packet.js +24 -4
- package/lib/thin/sqlnet/sessionAtts.js +2 -2
- package/lib/thin/statement.js +6 -1
- package/lib/thin/statementCache.js +34 -6
- package/lib/thin/subscr.js +363 -0
- package/lib/transformer.js +60 -17
- package/lib/util.js +46 -8
- package/lib/version.js +1 -1
- package/package.json +1 -1
- package/plugins/configProviders/gcpstorage/index.js +121 -0
- package/plugins/configProviders/ociobject/index.js +1 -1
- package/plugins/token/cache.js +154 -0
- package/plugins/token/endUserSecurityProvider/index.js +377 -0
- package/plugins/token/extensionAzure/index.js +160 -28
- package/plugins/token/extensionOci/index.js +221 -16
- package/plugins/vectorsdk/OracleVecDB.js +346 -0
- package/plugins/vectorsdk/index.js +49 -0
- package/plugins/vectorsdk/utils.js +370 -0
- package/plugins/vectorsdk/vectorEmbedding.js +223 -0
- package/plugins/vectorsdk/vectorIndex.js +177 -0
- package/plugins/vectorsdk/vectorRecords.js +406 -0
- package/plugins/vectorsdk/vectorSchema.js +408 -0
- package/plugins/vectorsdk/vectorSearch.js +538 -0
- package/build/Release/oracledb-7.0.0-darwin-arm64.node +0 -0
- package/build/Release/oracledb-7.0.0-darwin-arm64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-7.0.0-js-buildinfo.txt +0 -1
- package/build/Release/oracledb-7.0.0-linux-arm64.node +0 -0
- package/build/Release/oracledb-7.0.0-linux-arm64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-7.0.0-linux-x64.node +0 -0
- package/build/Release/oracledb-7.0.0-linux-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-7.0.0-win32-x64.node +0 -0
- package/build/Release/oracledb-7.0.0-win32-x64.node-buildinfo.txt +0 -1
- package/eslint.config.js +0 -39
package/README.md
CHANGED
|
@@ -1,22 +1,30 @@
|
|
|
1
|
-
# node-oracledb version
|
|
1
|
+
# node-oracledb version 26.0.0 <img src="https://img.shields.io/npm/v/oracledb.svg" alt="oracledb"/> <img src="https://img.shields.io/npm/dm/oracledb.svg" alt="oracledb"/>
|
|
2
2
|
|
|
3
3
|
The node-oracledb add-on for Node.js powers high performance Oracle Database
|
|
4
4
|
applications. Applications can be written in TypeScript, or directly in
|
|
5
5
|
JavaScript.
|
|
6
6
|
|
|
7
|
-
Use node-oracledb
|
|
7
|
+
Use node-oracledb 26.0.0 to connect Node.js 14.17, or later, to Oracle
|
|
8
8
|
Database. Older versions of node-oracledb may work with older versions of
|
|
9
9
|
Node.js.
|
|
10
10
|
|
|
11
11
|
Node-oracledb supports basic and advanced features of Oracle Database
|
|
12
|
-
and Oracle Client. See the [homepage][4] for a list.
|
|
12
|
+
and Oracle Client. See the [homepage][4] for a list. It is used by many
|
|
13
|
+
JavaScript and TypeScript frameworks, SQL generators, ORMs, and libraries.
|
|
14
|
+
|
|
15
|
+
Node-oracledb has a rich feature set which is easy to use. It gives you
|
|
16
|
+
control over SQL and PL/SQL statement execution, fast data ingestion, support
|
|
17
|
+
for calling NoSQL-style document APIs, message queueing,database notifications
|
|
18
|
+
and for starting and stopping the database.
|
|
19
|
+
It also has high availability and security features. Database operations
|
|
20
|
+
can optionally be [pipelined][16].
|
|
13
21
|
|
|
14
22
|
The node-oracledb module is open source and maintained by Oracle Corp.
|
|
15
23
|
It is stable, well documented, and has a comprehensive test suite.
|
|
16
24
|
|
|
17
25
|
## Installation
|
|
18
26
|
|
|
19
|
-
Run `npm install oracledb
|
|
27
|
+
Run `npm install oracledb`.
|
|
20
28
|
|
|
21
29
|
See [Getting Started with Node-oracledb][1] and [Quick Start Node-oracledb Installation][2].
|
|
22
30
|
|
|
@@ -40,7 +48,8 @@ See [Getting Started with Node-oracledb][1] and [Quick Start Node-oracledb Insta
|
|
|
40
48
|
available when optional Oracle Client libraries are loaded by
|
|
41
49
|
node-oracledb. Libraries are available in the free [Oracle Instant
|
|
42
50
|
Client][15] packages. Node-oracledb can use Oracle Client libraries version
|
|
43
|
-
19
|
|
51
|
+
19 or later. Older node-oracledb versions supported older Client
|
|
52
|
+
versions.
|
|
44
53
|
|
|
45
54
|
- Oracle Database
|
|
46
55
|
|
|
@@ -118,4 +127,5 @@ limitations under the License.
|
|
|
118
127
|
[12]: https://github.com/oracle/node-oracledb/blob/main/CONTRIBUTING.md
|
|
119
128
|
[13]: https://github.com/oracle/node-oracledb/blob/main/SECURITY.md
|
|
120
129
|
[14]: https://www.npmjs.com/package/oracledb
|
|
121
|
-
[15]: https://www.oracle.com/database/technologies/instant-client.html
|
|
130
|
+
[15]: https://www.oracle.com/database/technologies/instant-client.html
|
|
131
|
+
[16]: https://node-oracledb.readthedocs.io/en/latest/user_guide/pipeline.html
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
oracledb-26.0.0-darwin-arm64.node v24.11.1 fdba9345f92e83a5f0e66f01a5953ecfc358e053 1c8cabceb27b2e7a64737fb3de66f3d0014eed5f Mon, 28 Sep 2026 10:55:10 GMT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
fdba9345f92e83a5f0e66f01a5953ecfc358e053
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
oracledb-26.0.0-linux-arm64.node v24.19.0 fdba9345f92e83a5f0e66f01a5953ecfc358e053 1c8cabceb27b2e7a64737fb3de66f3d0014eed5f Mon, 28 Sep 2026 10:49:51 GMT
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
oracledb-26.0.0-linux-x64.node v22.19.0 fdba9345f92e83a5f0e66f01a5953ecfc358e053 1c8cabceb27b2e7a64737fb3de66f3d0014eed5f Mon, 28 Sep 2026 10:48:56 GMT
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
oracledb-26.0.0-win32-x64.node v22.17.1 fdba9345f92e83a5f0e66f01a5953ecfc358e053 1c8cabceb27b2e7a64737fb3de66f3d0014eed5f Mon, 28 Sep 2026 10:54:04 GMT
|
package/lib/aqDeqOptions.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright (c) 2019,
|
|
1
|
+
// Copyright (c) 2019, 2026, Oracle and/or its affiliates.
|
|
2
2
|
|
|
3
3
|
//-----------------------------------------------------------------------------
|
|
4
4
|
//
|
|
@@ -56,7 +56,7 @@ class AqDeqOptions {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
set consumerName(value) {
|
|
59
|
-
errors.
|
|
59
|
+
errors.assertPropLength(value, "string", 128, "consumerName");
|
|
60
60
|
this._impl.setConsumerName(value);
|
|
61
61
|
}
|
|
62
62
|
|
|
@@ -70,7 +70,7 @@ class AqDeqOptions {
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
set correlation(value) {
|
|
73
|
-
errors.
|
|
73
|
+
errors.assertPropLength(value, "string", 128, "correlation");
|
|
74
74
|
this._impl.setCorrelation(value);
|
|
75
75
|
}
|
|
76
76
|
|
|
@@ -148,7 +148,7 @@ class AqDeqOptions {
|
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
set transformation(value) {
|
|
151
|
-
errors.
|
|
151
|
+
errors.assertPropLength(value, "string", 128, "transformation");
|
|
152
152
|
this._impl.setTransformation(value);
|
|
153
153
|
}
|
|
154
154
|
|
package/lib/aqEnqOptions.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright (c) 2019,
|
|
1
|
+
// Copyright (c) 2019, 2026, Oracle and/or its affiliates.
|
|
2
2
|
|
|
3
3
|
//-----------------------------------------------------------------------------
|
|
4
4
|
//
|
|
@@ -57,7 +57,7 @@ class AqEnqOptions {
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
set transformation(value) {
|
|
60
|
-
errors.
|
|
60
|
+
errors.assertPropLength(value, "string", 128, "transformation");
|
|
61
61
|
this._impl.setTransformation(value);
|
|
62
62
|
}
|
|
63
63
|
|
package/lib/aqQueue.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright (c) 2019,
|
|
1
|
+
// Copyright (c) 2019, 2026, Oracle and/or its affiliates.
|
|
2
2
|
|
|
3
3
|
//-----------------------------------------------------------------------------
|
|
4
4
|
//
|
|
@@ -104,15 +104,15 @@ class AqQueue {
|
|
|
104
104
|
|
|
105
105
|
// validate options, if applicable
|
|
106
106
|
if (message.correlation !== undefined) {
|
|
107
|
-
errors.
|
|
107
|
+
errors.assertPropLength(message.correlation, "string", 128,
|
|
108
108
|
"correlation");
|
|
109
109
|
}
|
|
110
110
|
if (message.delay !== undefined) {
|
|
111
111
|
errors.assertParamPropValue(Number.isInteger(message.delay), 1, "delay");
|
|
112
112
|
}
|
|
113
113
|
if (message.exceptionQueue !== undefined) {
|
|
114
|
-
errors.
|
|
115
|
-
|
|
114
|
+
errors.assertPropLength(message.exceptionQueue, "string", 128,
|
|
115
|
+
"exceptionQueue");
|
|
116
116
|
}
|
|
117
117
|
if (message.expiration !== undefined) {
|
|
118
118
|
errors.assertParamPropValue(Number.isInteger(message.expiration), 1,
|
|
@@ -123,8 +123,13 @@ class AqQueue {
|
|
|
123
123
|
"priority");
|
|
124
124
|
}
|
|
125
125
|
if (message.recipients !== undefined) {
|
|
126
|
-
|
|
127
|
-
|
|
126
|
+
// Check recipients length and type
|
|
127
|
+
errors.assertPropLength(message.recipients, "array", 1024, "recipients");
|
|
128
|
+
// Check value and length of each recipient
|
|
129
|
+
message.recipients.forEach((recipient, index) => {
|
|
130
|
+
errors.assertPropLength(recipient, "string", 128,
|
|
131
|
+
`recipient at index ${index}`);
|
|
132
|
+
});
|
|
128
133
|
}
|
|
129
134
|
|
|
130
135
|
return message;
|
package/lib/connection.js
CHANGED
|
@@ -55,6 +55,19 @@ const APP_CONTEXT_VALUE_MAX_BYTES = 4 * 1000;
|
|
|
55
55
|
// and destroyed with another!
|
|
56
56
|
const _subscriptions = new Map();
|
|
57
57
|
|
|
58
|
+
//---------------------------------------------------------------------------
|
|
59
|
+
// _removeSubscription()
|
|
60
|
+
//
|
|
61
|
+
// Remove a subscription only when it is still the subscription currently
|
|
62
|
+
// registered for the name. A terminal old subscription must not remove a newer
|
|
63
|
+
// subscription that reused the same name.
|
|
64
|
+
//---------------------------------------------------------------------------
|
|
65
|
+
function _removeSubscription(name, subscription) {
|
|
66
|
+
if (_subscriptions.get(name) === subscription) {
|
|
67
|
+
_subscriptions.delete(name);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
58
71
|
// default closure for NUMBER type.
|
|
59
72
|
const defaultNumberConverter = (v) => (v === null) ? null : parseFloat(v);
|
|
60
73
|
|
|
@@ -83,9 +96,8 @@ function _determineDbObjTypeConverter(metadata, options) {
|
|
|
83
96
|
}
|
|
84
97
|
if ([types.DB_TYPE_CLOB, types.DB_TYPE_NCLOB, types.DB_TYPE_BLOB,
|
|
85
98
|
types.DB_TYPE_BFILE].includes(metadata.type)) {
|
|
86
|
-
// converters for
|
|
87
|
-
return errors.
|
|
88
|
-
'DbObjConverter for LOBs');
|
|
99
|
+
// converters for LOBs are not supported.
|
|
100
|
+
return errors.throwNotImplemented('DbObjConverter for LOBs');
|
|
89
101
|
}
|
|
90
102
|
metadata.converter = result.converter;
|
|
91
103
|
}
|
|
@@ -905,6 +917,23 @@ class Connection extends EventEmitter {
|
|
|
905
917
|
this._impl.setCurrentSchema(value);
|
|
906
918
|
}
|
|
907
919
|
|
|
920
|
+
//---------------------------------------------------------------------------
|
|
921
|
+
// databaseOpenTelemetryTracing
|
|
922
|
+
//
|
|
923
|
+
// Property for enabling database OpenTelemetry trace propagation.
|
|
924
|
+
//---------------------------------------------------------------------------
|
|
925
|
+
get databaseOpenTelemetryTracing() {
|
|
926
|
+
if (this._impl)
|
|
927
|
+
return this._impl.getDatabaseOpenTelemetryTracing();
|
|
928
|
+
return undefined;
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
set databaseOpenTelemetryTracing(value) {
|
|
932
|
+
errors.assertPropValue(typeof value === 'boolean', "databaseOpenTelemetryTracing");
|
|
933
|
+
errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
|
|
934
|
+
this._impl.setDatabaseOpenTelemetryTracing(value);
|
|
935
|
+
}
|
|
936
|
+
|
|
908
937
|
//---------------------------------------------------------------------------
|
|
909
938
|
// dbOp
|
|
910
939
|
//
|
|
@@ -1406,7 +1435,7 @@ class Connection extends EventEmitter {
|
|
|
1406
1435
|
errors.assertArgCount(arguments, 1, 1);
|
|
1407
1436
|
errors.assertParamValue(typeof sql === 'string', 1);
|
|
1408
1437
|
errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
|
|
1409
|
-
const info = await this._impl.getStatementInfo(sql);
|
|
1438
|
+
const info = await this._impl.getStatementInfo(sql, { connection: this });
|
|
1410
1439
|
if (info.metaData) {
|
|
1411
1440
|
for (let i = 0; i < info.metaData.length; i++) {
|
|
1412
1441
|
const m = info.metaData[i];
|
|
@@ -1564,6 +1593,21 @@ class Connection extends EventEmitter {
|
|
|
1564
1593
|
return this._impl && this._impl.getTransactionInProgress();
|
|
1565
1594
|
}
|
|
1566
1595
|
|
|
1596
|
+
//---------------------------------------------------------------------------
|
|
1597
|
+
// txnPriority
|
|
1598
|
+
//
|
|
1599
|
+
// Property for transaction priority associated with the connection.
|
|
1600
|
+
//---------------------------------------------------------------------------
|
|
1601
|
+
get txnPriority() {
|
|
1602
|
+
return this._impl && this._impl.getTxnPriority();
|
|
1603
|
+
}
|
|
1604
|
+
|
|
1605
|
+
set txnPriority(value) {
|
|
1606
|
+
errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
|
|
1607
|
+
errors.assertTxnPriority(value);
|
|
1608
|
+
this._impl.setTxnPriority(value);
|
|
1609
|
+
}
|
|
1610
|
+
|
|
1567
1611
|
//---------------------------------------------------------------------------
|
|
1568
1612
|
// ping()
|
|
1569
1613
|
//
|
|
@@ -1590,9 +1634,11 @@ class Connection extends EventEmitter {
|
|
|
1590
1634
|
} else {
|
|
1591
1635
|
options = {};
|
|
1592
1636
|
}
|
|
1637
|
+
errors.assertParamPropUnsignedIntNonZero(options, 3, "rowsPerDataEvent");
|
|
1638
|
+
const rowsPerDataEvent = options.rowsPerDataEvent;
|
|
1593
1639
|
options.resultSet = true;
|
|
1594
1640
|
|
|
1595
|
-
const stream = new QueryStream();
|
|
1641
|
+
const stream = new QueryStream(undefined, rowsPerDataEvent);
|
|
1596
1642
|
|
|
1597
1643
|
// calling execute() via nextTick to ensure that handlers are registered
|
|
1598
1644
|
// prior to the events being emitted
|
|
@@ -1732,15 +1778,22 @@ class Connection extends EventEmitter {
|
|
|
1732
1778
|
errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
|
|
1733
1779
|
|
|
1734
1780
|
const inSubscr = _subscriptions.get(name);
|
|
1781
|
+
if (this.thin) {
|
|
1782
|
+
options._onRetire = (subscription) =>
|
|
1783
|
+
_removeSubscription(name, subscription);
|
|
1784
|
+
}
|
|
1735
1785
|
const outValue = await this._impl.subscribe(inSubscr, options);
|
|
1736
1786
|
let subscription;
|
|
1737
1787
|
if (options.namespace === constants.SUBSCR_NAMESPACE_DBCHANGE) {
|
|
1738
1788
|
subscription = outValue.subscription;
|
|
1739
1789
|
delete outValue.subscription;
|
|
1790
|
+
outValue.regId = Number(outValue.regId);
|
|
1740
1791
|
} else {
|
|
1741
1792
|
subscription = outValue;
|
|
1742
1793
|
}
|
|
1743
|
-
|
|
1794
|
+
if (!this.thin || subscription._registered) {
|
|
1795
|
+
_subscriptions.set(name, subscription);
|
|
1796
|
+
}
|
|
1744
1797
|
return outValue;
|
|
1745
1798
|
}
|
|
1746
1799
|
|
|
@@ -1988,11 +2041,14 @@ class Connection extends EventEmitter {
|
|
|
1988
2041
|
|
|
1989
2042
|
// Force a ResultSet and then fetch rows according to the requested
|
|
1990
2043
|
// fetch variant in non-pipeline flow.
|
|
1991
|
-
|
|
1992
|
-
|
|
2044
|
+
const execOptions = {
|
|
2045
|
+
...op.options,
|
|
2046
|
+
resultSet: true,
|
|
2047
|
+
fetchTypeHandler: this._createFetchTypeHandler(op.fetchLobs)
|
|
2048
|
+
};
|
|
1993
2049
|
let shouldClose = false;
|
|
1994
2050
|
try {
|
|
1995
|
-
res = await this._execute(op.statement, op.parameters,
|
|
2051
|
+
res = await this._execute(op.statement, op.parameters, execOptions);
|
|
1996
2052
|
if (opType === 'fetchOne') {
|
|
1997
2053
|
const row = await res.resultSet._getRow();
|
|
1998
2054
|
res.rows = row ? [row] : [];
|
|
@@ -2095,12 +2151,18 @@ class Connection extends EventEmitter {
|
|
|
2095
2151
|
errors.assertParamValue(typeof name === 'string', 1);
|
|
2096
2152
|
errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
|
|
2097
2153
|
errors.assert(_subscriptions.has(name), errors.ERR_INVALID_SUBSCR);
|
|
2098
|
-
|
|
2154
|
+
const subscription = _subscriptions.get(name);
|
|
2155
|
+
await this._impl.unsubscribe(subscription);
|
|
2156
|
+
|
|
2157
|
+
if (this.thin) {
|
|
2158
|
+
_removeSubscription(name, subscription);
|
|
2159
|
+
return;
|
|
2160
|
+
}
|
|
2099
2161
|
|
|
2100
2162
|
// Delay decreasing the reference count
|
|
2101
2163
|
// as NJS layer starts cleanup (uv_close) of async handle asynchronously.
|
|
2102
2164
|
setTimeout(() => {
|
|
2103
|
-
|
|
2165
|
+
_removeSubscription(name, subscription);
|
|
2104
2166
|
}, 0);
|
|
2105
2167
|
}
|
|
2106
2168
|
|
|
@@ -2116,13 +2178,6 @@ class Connection extends EventEmitter {
|
|
|
2116
2178
|
errors.throwErr(errors.ERR_APP_CONTEXT_EMPTY_NAMESPACE);
|
|
2117
2179
|
}
|
|
2118
2180
|
|
|
2119
|
-
// Passing null/undefined/[] currently leaves existing entries intact in
|
|
2120
|
-
// thick mode and triggers an error in thin mode.
|
|
2121
|
-
// It does not clear the context; use clearAppContext() explicitly
|
|
2122
|
-
// when you need to remove keys.
|
|
2123
|
-
if (keyValues === null || keyValues === undefined) {
|
|
2124
|
-
keyValues = [];
|
|
2125
|
-
}
|
|
2126
2181
|
errors.assertParamValue(Array.isArray(keyValues), 2);
|
|
2127
2182
|
|
|
2128
2183
|
for (const entry of keyValues) {
|
package/lib/constants.js
CHANGED
|
@@ -40,16 +40,17 @@ function hasNonEmptyText(value) {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
/*
|
|
43
|
-
Represents
|
|
43
|
+
Represents a Deep Data Security credential set for an end user or, for direct
|
|
44
|
+
application logon, the application identity encoded by its database token.
|
|
44
45
|
|
|
45
46
|
Required properties
|
|
46
47
|
- databaseAccessToken: non-empty string accepted by the database driver.
|
|
47
|
-
- endUserToken or endUserName:
|
|
48
|
-
-
|
|
48
|
+
- endUserToken or endUserName: exactly one must be supplied as a string for an
|
|
49
|
+
end-user context. Neither is supplied for direct application logon.
|
|
49
50
|
|
|
50
51
|
Optional properties
|
|
51
52
|
- key: look-up identifier the database maps to stored context attributes; may be
|
|
52
|
-
|
|
53
|
+
supplied only with endUserName.
|
|
53
54
|
- dataRoles: data roles enabled/disabled by the application logic, rather
|
|
54
55
|
than a database security policy.
|
|
55
56
|
- attributes: Attributes are contained in JSON objects conforming
|
|
@@ -72,29 +73,31 @@ class EndUserSecurityContext {
|
|
|
72
73
|
dataRoles,
|
|
73
74
|
attributes
|
|
74
75
|
} = options;
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
76
|
+
const hasEndUserToken = endUserToken !== undefined && endUserToken !== null;
|
|
77
|
+
const hasEndUserName = endUserName !== undefined && endUserName !== null;
|
|
78
|
+
const hasKey = key !== undefined && key !== null;
|
|
79
|
+
|
|
80
|
+
// The database access token is always required. An end-user context has
|
|
81
|
+
// exactly one identity mechanism. A context with neither token nor name
|
|
82
|
+
// is an application-direct logon: the database maps the client identity
|
|
83
|
+
// in databaseAccessToken to its registered application identity.
|
|
78
84
|
errors.assertParamValue(hasNonEmptyText(databaseAccessToken), 1);
|
|
79
85
|
errors.assertParamValue(
|
|
80
|
-
(
|
|
81
|
-
(
|
|
82
|
-
1
|
|
83
|
-
);
|
|
86
|
+
(hasEndUserToken && !hasEndUserName && !hasKey) ||
|
|
87
|
+
(!hasEndUserToken && hasEndUserName) ||
|
|
88
|
+
(!hasEndUserToken && !hasEndUserName && !hasKey), 1);
|
|
84
89
|
|
|
85
90
|
// When supplied, token/name/key values must contain non-whitespace text.
|
|
86
|
-
if (
|
|
91
|
+
if (hasEndUserToken) {
|
|
87
92
|
errors.assertParamValue(hasNonEmptyText(endUserToken), 1);
|
|
88
93
|
}
|
|
89
94
|
|
|
90
|
-
|
|
91
|
-
// end user context attributes.
|
|
92
|
-
if (endUserName !== undefined && endUserName !== null) {
|
|
95
|
+
if (hasEndUserName) {
|
|
93
96
|
errors.assertParamValue(hasNonEmptyText(endUserName), 1);
|
|
94
|
-
errors.assertParamValue(key !== undefined && key !== null, 1);
|
|
95
97
|
}
|
|
96
98
|
|
|
97
|
-
if (
|
|
99
|
+
if (hasKey) {
|
|
100
|
+
errors.assertParamValue(hasEndUserName, 1);
|
|
98
101
|
errors.assertParamValue(hasNonEmptyText(key), 1);
|
|
99
102
|
}
|
|
100
103
|
|
|
@@ -117,7 +120,10 @@ class EndUserSecurityContext {
|
|
|
117
120
|
|
|
118
121
|
// Data roles are optional, but must be passed as an array when present.
|
|
119
122
|
if (dataRoles != null) {
|
|
120
|
-
errors.assertParamValue(
|
|
123
|
+
errors.assertParamValue(
|
|
124
|
+
Array.isArray(dataRoles) && dataRoles.every(hasNonEmptyText),
|
|
125
|
+
1
|
|
126
|
+
);
|
|
121
127
|
payload.data_roles = Array.from(dataRoles);
|
|
122
128
|
}
|
|
123
129
|
|
|
@@ -128,17 +134,21 @@ class EndUserSecurityContext {
|
|
|
128
134
|
1
|
|
129
135
|
);
|
|
130
136
|
payload.attributes = Object.entries(attributes).map(
|
|
131
|
-
([name, values]) => ({ name, values }));
|
|
137
|
+
([name, values]) => ({ name, values: values ?? null }));
|
|
132
138
|
}
|
|
133
139
|
|
|
134
140
|
this._payloadStore = new ObfuscatedValue();
|
|
135
141
|
this._encodeAndStorePayload(payload);
|
|
136
142
|
}
|
|
137
143
|
|
|
144
|
+
// Encode EUSC payloads with strict validation of unsupported JSON values and
|
|
145
|
+
// field names.
|
|
138
146
|
_encodePayload(value) {
|
|
139
147
|
const encoder = new oson.OsonEncoder();
|
|
140
148
|
return encoder.encode(
|
|
141
|
-
transformer.transformJsonValue(value
|
|
149
|
+
transformer.transformJsonValue(value, {
|
|
150
|
+
rejectUnsupportedTypes: true
|
|
151
|
+
}),
|
|
142
152
|
DEFAULT_MAX_FIELD_NAME_SIZE
|
|
143
153
|
);
|
|
144
154
|
}
|
|
@@ -159,7 +169,6 @@ class EndUserSecurityContext {
|
|
|
159
169
|
payloadLength
|
|
160
170
|
);
|
|
161
171
|
}
|
|
162
|
-
this.clearEncodedPayload();
|
|
163
172
|
this._payloadStore.set(encodedPayload, { returnBuffer: true });
|
|
164
173
|
encodedPayload.fill(0);
|
|
165
174
|
}
|
|
@@ -167,10 +176,6 @@ class EndUserSecurityContext {
|
|
|
167
176
|
getDeobfuscatedValue() {
|
|
168
177
|
return this._payloadStore.get({ returnBuffer: true });
|
|
169
178
|
}
|
|
170
|
-
|
|
171
|
-
clearEncodedPayload() {
|
|
172
|
-
this._payloadStore.clear();
|
|
173
|
-
}
|
|
174
179
|
}
|
|
175
180
|
|
|
176
181
|
module.exports = EndUserSecurityContext;
|