@lblod/mu-auth-sudo 0.6.0 → 1.0.0-beta.2

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.
Files changed (3) hide show
  1. package/README.md +14 -3
  2. package/dist/auth-sudo.js +130 -171
  3. package/package.json +24 -18
package/README.md CHANGED
@@ -2,12 +2,12 @@
2
2
  NPM package for a SPARQL client for mu.semte.ch that overrules access rights in queries through a mu-auth-sudo header.
3
3
 
4
4
  ## Usage
5
- ```
5
+ ```bash
6
6
  npm install @lblod/mu-auth-sudo
7
7
  ```
8
8
 
9
9
  Include the following in your code
10
- ```
10
+ ```js
11
11
  import { querySudo as query, updateSudo as update } from '@lblod/mu-auth-sudo';
12
12
 
13
13
 
@@ -26,9 +26,20 @@ await update(updateString, extraHeaders);
26
26
 
27
27
  // With custom connection options (this should be exceptional, make sure you know what you're doing)
28
28
 
29
- const connectionOptions = { sparqlEndpoint: 'http://the.custom.endpoint/sparql', mayRetry: true };
29
+ const connectionOptions = { sparqlEndpoint: 'http://the.custom.endpoint/sparql', mayRetry: true, };
30
+
31
+ await update(updateString, extraHeaders, connectionOptions);
32
+
33
+ // Authentication via digest or basic auth
34
+ const connectionOptions = {
35
+ sparqlEndpoint: 'http://the.custom.endpoint/sparql',
36
+ authUser: "dba",
37
+ authPassword: "mypass",
38
+ authType: "digest"
39
+ };
30
40
 
31
41
  await update(updateString, extraHeaders, connectionOptions);
42
+
32
43
  ```
33
44
 
34
45
  ## Logging
package/dist/auth-sudo.js CHANGED
@@ -1,187 +1,146 @@
1
- 'use strict';
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
5
17
  });
6
- exports.updateSudo = exports.querySudo = undefined;
7
-
8
- var _expressHttpContext = require('express-http-context');
9
-
10
- var _expressHttpContext2 = _interopRequireDefault(_expressHttpContext);
11
-
12
- var _sparqlClient = require('sparql-client-2');
13
-
14
- var _envVar = require('env-var');
15
-
16
- var _envVar2 = _interopRequireDefault(_envVar);
17
-
18
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
19
-
20
- var LOG_SPARQL_QUERIES = process.env.LOG_SPARQL_QUERIES != undefined ? _envVar2.default.get('LOG_SPARQL_QUERIES').asBool() : _envVar2.default.get('LOG_SPARQL_ALL').asBool();
21
- var LOG_SPARQL_UPDATES = process.env.LOG_SPARQL_UPDATES != undefined ? _envVar2.default.get('LOG_SPARQL_UPDATES').asBool() : _envVar2.default.get('LOG_SPARQL_ALL').asBool();
22
- var DEBUG_AUTH_HEADERS = _envVar2.default.get('DEBUG_AUTH_HEADERS').asBool();
23
-
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.updateSudo = exports.querySudo = void 0;
30
+ const express_http_context_1 = __importDefault(require("express-http-context"));
31
+ const env_var_1 = __importDefault(require("env-var"));
32
+ const node_fetch_1 = __importStar(require("node-fetch"));
33
+ const digest_fetch_1 = __importDefault(require("digest-fetch"));
34
+ const SPARQL_ENDPOINT = env_var_1.default.get('MU_SPARQL_ENDPOINT').required().asString();
35
+ const LOG_SPARQL_ALL = env_var_1.default.get('LOG_SPARQL_ALL').required().asString();
36
+ const LOG_SPARQL_QUERIES = env_var_1.default.get('LOG_SPARQL_QUERIES').default(LOG_SPARQL_ALL).asBool();
37
+ const LOG_SPARQL_UPDATES = env_var_1.default.get('LOG_SPARQL_UPDATES').default(LOG_SPARQL_ALL).asBool();
38
+ const DEBUG_AUTH_HEADERS = env_var_1.default.get('DEBUG_AUTH_HEADERS').required().asBool();
24
39
  // The following configuration options are considered optional, but may be overriden as a temporary workaround for issues. Thus, a last resort.
25
- var RETRY = _envVar2.default.get('SUDO_QUERY_RETRY').default('false').asBool();
26
- var RETRY_MAX_ATTEMPTS = _envVar2.default.get('SUDO_QUERY_RETRY_MAX_ATTEMPTS').default('5').asInt();
27
- var RETRY_FOR_HTTP_STATUS_CODES = _envVar2.default.get('SUDO_QUERY_RETRY_FOR_HTTP_STATUS_CODES').default('').asArray();
28
- var RETRY_FOR_CONNECTION_ERRORS = _envVar2.default.get('SUDO_QUERY_RETRY_FOR_CONNECTION_ERRORS').default('ECONNRESET,ETIMEDOUT,EAI_AGAIN').asArray();
29
- var RETRY_TIMEOUT_INCREMENT_FACTOR = _envVar2.default.get('SUDO_QUERY_RETRY_TIMEOUT_INCREMENT_FACTOR').default('0.3').asFloat();
30
-
31
- function sudoSparqlClient() {
32
- var extraHeaders = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
33
- var connectionOptions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
34
-
35
-
36
- var sparqlEndpoint = process.env.MU_SPARQL_ENDPOINT;
37
-
38
- if (connectionOptions) {
39
- sparqlEndpoint = connectionOptions.sparqlEndpoint || sparqlEndpoint;
40
- }
41
-
42
- var options = {
43
- requestDefaults: {
44
- headers: {
45
- 'mu-auth-sudo': 'true'
46
- }
40
+ const RETRY = env_var_1.default.get('SUDO_QUERY_RETRY').default('false').asBool();
41
+ const RETRY_MAX_ATTEMPTS = env_var_1.default.get('SUDO_QUERY_RETRY_MAX_ATTEMPTS').default('5').asInt();
42
+ const RETRY_FOR_HTTP_STATUS_CODES = env_var_1.default.get('SUDO_QUERY_RETRY_FOR_HTTP_STATUS_CODES').default('').asArray();
43
+ const RETRY_FOR_CONNECTION_ERRORS = env_var_1.default.get('SUDO_QUERY_RETRY_FOR_CONNECTION_ERRORS').default('ECONNRESET,ETIMEDOUT,EAI_AGAIN').asArray();
44
+ const RETRY_TIMEOUT_INCREMENT_FACTOR = env_var_1.default.get('SUDO_QUERY_RETRY_TIMEOUT_INCREMENT_FACTOR').default('0.3').asFloat();
45
+ function defaultHeaders() {
46
+ const headers = new node_fetch_1.Headers();
47
+ headers.set('content-type', 'application/x-www-form-urlencoded');
48
+ headers.set('mu-auth-sudo', 'true');
49
+ headers.set('Accept', 'application/sparql-results+json');
50
+ if (express_http_context_1.default.get('request')) {
51
+ headers.set('mu-session-id', express_http_context_1.default.get('request').get('mu-session-id'));
52
+ headers.set('mu-call-id', express_http_context_1.default.get('request').get('mu-call-id'));
53
+ }
54
+ return headers;
55
+ }
56
+ async function executeRawQuery(queryString, extraHeaders = {}, connectionOptions = {}, attempt = 0) {
57
+ const sparqlEndpoint = connectionOptions.sparqlEndpoint ?? SPARQL_ENDPOINT;
58
+ const headers = defaultHeaders();
59
+ for (const key of Object.keys(extraHeaders)) {
60
+ headers.append(key, extraHeaders[key]);
61
+ }
62
+ if (DEBUG_AUTH_HEADERS) {
63
+ const stringifiedHeaders = Array.from(headers.entries())
64
+ .filter(([key, value]) => key.startsWith('mu-'))
65
+ .map(([key, value]) => `${key}: ${value}`)
66
+ .join("\n");
67
+ console.log(`Headers set on SPARQL client: ${stringifiedHeaders}`);
47
68
  }
48
- };
49
-
50
- if (_expressHttpContext2.default.get('request')) {
51
- options.requestDefaults.headers['mu-session-id'] = _expressHttpContext2.default.get('request').get('mu-session-id');
52
- options.requestDefaults.headers['mu-call-id'] = _expressHttpContext2.default.get('request').get('mu-call-id');
53
- }
54
-
55
- if (extraHeaders) {
56
- var _iteratorNormalCompletion = true;
57
- var _didIteratorError = false;
58
- var _iteratorError = undefined;
59
-
60
69
  try {
61
- for (var _iterator = Object.keys(extraHeaders)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
62
- var key = _step.value;
63
-
64
- options.requestDefaults.headers[key] = extraHeaders[key];
65
- }
66
- } catch (err) {
67
- _didIteratorError = true;
68
- _iteratorError = err;
69
- } finally {
70
- try {
71
- if (!_iteratorNormalCompletion && _iterator.return) {
72
- _iterator.return();
70
+ // note that URLSearchParams is used because it correctly encodes for form-urlencoded
71
+ const formData = new URLSearchParams();
72
+ formData.set("query", queryString);
73
+ headers.append('Content-Length', formData.toString().length.toString());
74
+ let response;
75
+ if (connectionOptions.authUser && connectionOptions.authPassword) {
76
+ const client = new digest_fetch_1.default(connectionOptions.authUser, connectionOptions.authPassword, { basic: connectionOptions.authType === 'basic' });
77
+ response = await client.fetch(sparqlEndpoint, {
78
+ method: 'POST',
79
+ body: formData.toString(),
80
+ headers
81
+ });
73
82
  }
74
- } finally {
75
- if (_didIteratorError) {
76
- throw _iteratorError;
83
+ else {
84
+ response = await (0, node_fetch_1.default)(sparqlEndpoint, {
85
+ method: 'POST',
86
+ body: formData.toString(),
87
+ headers
88
+ });
77
89
  }
78
- }
90
+ return await response.json();
79
91
  }
80
- }
81
-
82
- if (DEBUG_AUTH_HEADERS) {
83
- console.log('Headers set on SPARQL client: ' + JSON.stringify(options));
84
- }
85
-
86
- return new _sparqlClient.SparqlClient(sparqlEndpoint, options);
87
- }
88
-
89
- async function executeRawQuery(queryString) {
90
- var extraHeaders = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
91
- var connectionOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
92
- var attempt = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
93
-
94
-
95
- if (LOG_SPARQL_QUERIES) {
96
- console.log(queryString);
97
- }
98
-
99
- try {
100
-
101
- var response = await sudoSparqlClient(extraHeaders, connectionOptions).query(queryString).executeRaw();
102
- return maybeParseJSON(response.body);
103
- } catch (ex) {
104
-
105
- if (mayRetry(ex, attempt, connectionOptions)) {
106
-
107
- attempt += 1;
108
-
109
- var sleepTime = nextAttemptTimeout(attempt);
110
- console.log('Sleeping ' + sleepTime + ' ms before next attempt');
111
- await new Promise(function (r) {
112
- return setTimeout(r, sleepTime);
113
- });
114
-
115
- return await executeRawQuery(queryString, extraHeaders, connectionOptions, attempt);
116
- } else {
117
- console.log('Failed Query:\n ' + queryString);
118
- throw ex;
92
+ catch (ex) {
93
+ if (mayRetry(ex, attempt, connectionOptions)) {
94
+ attempt += 1;
95
+ const sleepTime = nextAttemptTimeout(attempt);
96
+ console.log(`Sleeping ${sleepTime} ms before next attempt`);
97
+ await new Promise(r => setTimeout(r, sleepTime));
98
+ return await executeRawQuery(queryString, extraHeaders, connectionOptions, attempt);
99
+ }
100
+ else {
101
+ console.log(`Failed Query:
102
+ ${queryString}`);
103
+ throw ex;
104
+ }
119
105
  }
120
- }
121
106
  }
122
-
123
- function querySudo(queryString) {
124
- var extraHeaders = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
125
- var connectionOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
126
-
127
- if (LOG_SPARQL_QUERIES) {
128
- console.log(queryString);
129
- }
130
- return executeRawQuery(queryString, extraHeaders, connectionOptions);
131
- }
132
-
133
- function updateSudo(queryString) {
134
- var extraHeaders = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
135
- var connectionOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
136
-
137
- if (LOG_SPARQL_UPDATES) {
138
- console.log(queryString);
139
- }
140
- return executeRawQuery(queryString, extraHeaders, connectionOptions);
107
+ function querySudo(queryString, extraHeaders = {}, connectionOptions = {}) {
108
+ if (LOG_SPARQL_QUERIES) {
109
+ console.log(queryString);
110
+ }
111
+ return executeRawQuery(queryString, extraHeaders, connectionOptions);
141
112
  }
142
-
143
- function maybeParseJSON(body) {
144
- // Catch invalid JSON
145
- try {
146
- return JSON.parse(body);
147
- } catch (ex) {
148
- return null;
149
- }
113
+ exports.querySudo = querySudo;
114
+ function updateSudo(queryString, extraHeaders = {}, connectionOptions = {}) {
115
+ if (LOG_SPARQL_UPDATES) {
116
+ console.log(queryString);
117
+ }
118
+ return executeRawQuery(queryString, extraHeaders, connectionOptions);
150
119
  }
151
-
152
- function mayRetry(error, attempt) {
153
- var connectionOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
154
-
155
-
156
- console.log('Checking retry allowed for error: ' + error + ' and attempt: ' + attempt);
157
-
158
- var mayRetry = false;
159
-
160
- if (!(RETRY || connectionOptions.mayRetry)) {
161
- mayRetry = false;
162
- } else if (attempt < RETRY_MAX_ATTEMPTS) {
163
- if (error.code && RETRY_FOR_CONNECTION_ERRORS.includes(error.code)) {
164
- mayRetry = true;
165
- } else if (error.httpStatus && RETRY_FOR_HTTP_STATUS_CODES.includes('' + error.httpStatus)) {
166
- mayRetry = true;
120
+ exports.updateSudo = updateSudo;
121
+ function mayRetry(error, attempt, connectionOptions = {}) {
122
+ console.log(`Checking retry allowed for error: ${error} and attempt: ${attempt}`);
123
+ let mayRetry = false;
124
+ if (!(RETRY || connectionOptions.mayRetry)) {
125
+ mayRetry = false;
167
126
  }
168
- }
169
-
170
- console.log('Retry allowed? ' + mayRetry);
171
-
172
- return mayRetry;
127
+ else if (attempt < RETRY_MAX_ATTEMPTS) {
128
+ if (error.code && RETRY_FOR_CONNECTION_ERRORS.includes(error.code)) {
129
+ mayRetry = true;
130
+ }
131
+ else if (error.httpStatus && RETRY_FOR_HTTP_STATUS_CODES.includes(`${error.httpStatus}`)) {
132
+ mayRetry = true;
133
+ }
134
+ }
135
+ console.log(`Retry allowed? ${mayRetry}`);
136
+ return mayRetry;
173
137
  }
174
-
175
138
  function nextAttemptTimeout(attempt) {
176
- //expected to be milliseconds
177
- return Math.round(Math.exp(RETRY_TIMEOUT_INCREMENT_FACTOR * attempt + 10));
139
+ // expected to be milliseconds
140
+ return Math.round(Math.exp(RETRY_TIMEOUT_INCREMENT_FACTOR * attempt + 10));
178
141
  }
179
-
180
- var _exports = {
181
- querySudo: querySudo,
182
- updateSudo: updateSudo
142
+ const defaultExport = {
143
+ querySudo,
144
+ updateSudo
183
145
  };
184
-
185
- exports.default = _exports;
186
- exports.querySudo = querySudo;
187
- exports.updateSudo = updateSudo;
146
+ exports.default = defaultExport;
package/package.json CHANGED
@@ -1,12 +1,14 @@
1
1
  {
2
2
  "name": "@lblod/mu-auth-sudo",
3
- "version": "0.6.0",
3
+ "version": "1.0.0-beta.2",
4
4
  "description": "this package provides an alternative sparql client for the mu-javascript-template that has sudo rights.",
5
5
  "main": "dist/auth-sudo.js",
6
6
  "scripts": {
7
+ "build": "tsc",
8
+ "prepare": "npm run build",
9
+ "lint": "tslint -p tsconfig.json",
7
10
  "test": "echo \"Error: no test specified\" && exit 1",
8
- "prepare": "rm -rf dist && babel src --out-dir dist/",
9
- "prepublish": "rm -rf dist && babel src --out-dir dist/"
11
+ "release": "release-it"
10
12
  },
11
13
  "repository": {
12
14
  "type": "git",
@@ -22,24 +24,28 @@
22
24
  "bugs": {
23
25
  "url": "https://github.com/lblod/mu-auth-sudo/issues"
24
26
  },
25
- "babel": {
26
- "presets": [
27
- "es2015"
28
- ],
29
- "plugins": [
30
- "add-module-exports"
31
- ]
32
- },
33
27
  "homepage": "https://github.com/lblod/mu-auth-sudo#readme",
34
28
  "devDependencies": {
35
- "babel-cli": "^6.26.0",
36
- "babel-plugin-add-module-exports": "^1.0.4",
37
- "babel-preset-env": "^1.7.0",
38
- "babel-preset-es2015": "^6.24.1",
39
- "babel-register": "^6.26.0"
29
+ "@types/node-fetch": "^2.6.2",
30
+ "express-http-context": "^1.2.4",
31
+ "prettier": "^2.7.1",
32
+ "release-it": "^15.5.0",
33
+ "tslint": "^6.1.3",
34
+ "tslint-config-prettier": "^1.18.0",
35
+ "typescript": "^4.8.4"
40
36
  },
41
37
  "dependencies": {
38
+ "digest-fetch": "^1.3.0",
42
39
  "env-var": "^7.0.1",
43
- "sparql-client-2": "https://github.com/erikap/node-sparql-client.git"
44
- }
40
+ "node-fetch": "^2.6.7"
41
+ },
42
+ "peerDependencies": {
43
+ "express-http-context": "~1.2.4"
44
+ },
45
+ "volta": {
46
+ "node": "14.20.1"
47
+ },
48
+ "files": [
49
+ "dist/**/*"
50
+ ]
45
51
  }