@lblod/mu-auth-sudo 0.4.0 → 0.6.0-rc.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 +31 -1
- package/dist/auth-sudo.js +80 -22
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# mu-auth-sudo
|
|
2
|
-
NPM package for a
|
|
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
|
```
|
|
@@ -9,6 +9,26 @@ npm install @lblod/mu-auth-sudo
|
|
|
9
9
|
Include the following in your code
|
|
10
10
|
```
|
|
11
11
|
import { querySudo as query, updateSudo as update } from '@lblod/mu-auth-sudo';
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
//Examples
|
|
15
|
+
|
|
16
|
+
// To run a regular query
|
|
17
|
+
|
|
18
|
+
const queryString = `SELECT * FROM { GRAPH ?g { ?s ?p ?o. } } LIMIT 1`;
|
|
19
|
+
await query(queryString);
|
|
20
|
+
|
|
21
|
+
// To pass extra headers
|
|
22
|
+
|
|
23
|
+
const updateString = `INSERT DATA { GRAPH <http://foo> { <http://bar> <http://baz> <http://boom>. } }`;
|
|
24
|
+
const extraHeaders = { 'mu-call-scope-id': 'http://foo/bar', 'other-info'; 'hello' };
|
|
25
|
+
await update(updateString, extraHeaders);
|
|
26
|
+
|
|
27
|
+
// With custom connection options (this should be exceptional, make sure you know what you're doing)
|
|
28
|
+
|
|
29
|
+
const connectionOptions = { sparqlEndpoint: 'http://the.custom.endpoint/sparql', mayRetry: true };
|
|
30
|
+
|
|
31
|
+
await update(updateString, extraHeaders, connectionOptions);
|
|
12
32
|
```
|
|
13
33
|
|
|
14
34
|
## Logging
|
|
@@ -21,3 +41,13 @@ The verbosity of logging can be configured as in the [javascript template](https
|
|
|
21
41
|
- `DEBUG_AUTH_HEADERS`: Debugging of [mu-authorization](https://github.com/mu-semtech/mu-authorization) access-control related headers (default `true`)
|
|
22
42
|
|
|
23
43
|
Following values are considered true: [`"true"`, `"TRUE"`, `"1"`].
|
|
44
|
+
|
|
45
|
+
## Retrying
|
|
46
|
+
You can tweak system-wide retry parameters. These should be considered internal, but tweaking them may help in extreme scenarios. Use with extreme caution.
|
|
47
|
+
|
|
48
|
+
- `SUDO_QUERY_RETRY`: System-wide configuration to enable the retry-mechanism (default `'false'`).
|
|
49
|
+
Warning: this overules eventual source-code specifications (i.e. `connectionOptions = { mayRetry: false }`), so make sure you know what you're doing.
|
|
50
|
+
- `SUDO_QUERY_RETRY_MAX_ATTEMPTS`: Specfiy the number of max retry attempts (default: 5)
|
|
51
|
+
- `SUDO_QUERY_RETRY_FOR_HTTP_STATUS_CODES`: Specify what returned HTTP status from the database are allowed for retry. (default: `''`). Overriding this list should be considered case by case.
|
|
52
|
+
- `SUDO_QUERY_RETRY_FOR_CONNECTION_ERRORS`: Specify what connection errors are allowed for retry. (default: `'ECONNRESET,ETIMEDOUT,EAI_AGAIN'`)
|
|
53
|
+
- `SUDO_QUERY_RETRY_TIMEOUT_INCREMENT_FACTOR`: Specify the factor applied to the timeout before the next attempt. Check implementation to see how it is calculated. (default: `'0.3'`)
|
package/dist/auth-sudo.js
CHANGED
|
@@ -21,9 +21,23 @@ var LOG_SPARQL_QUERIES = process.env.LOG_SPARQL_QUERIES != undefined ? _envVar2.
|
|
|
21
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
22
|
var DEBUG_AUTH_HEADERS = _envVar2.default.get('DEBUG_AUTH_HEADERS').asBool();
|
|
23
23
|
|
|
24
|
+
// 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
|
+
|
|
24
31
|
function sudoSparqlClient() {
|
|
25
32
|
var extraHeaders = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
26
|
-
var
|
|
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
|
+
}
|
|
27
41
|
|
|
28
42
|
var options = {
|
|
29
43
|
requestDefaults: {
|
|
@@ -72,42 +86,86 @@ function sudoSparqlClient() {
|
|
|
72
86
|
return new _sparqlClient.SparqlClient(sparqlEndpoint, options);
|
|
73
87
|
}
|
|
74
88
|
|
|
75
|
-
function executeRawQuery(queryString) {
|
|
89
|
+
async function executeRawQuery(queryString) {
|
|
76
90
|
var extraHeaders = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
77
|
-
var
|
|
91
|
+
var connectionOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
92
|
+
var attempt = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
|
|
78
93
|
|
|
79
|
-
return sudoSparqlClient(extraHeaders, sparqlEndpoint).query(queryString).executeRaw().then(function (response) {
|
|
80
|
-
function maybeParseJSON(body) {
|
|
81
|
-
// Catch invalid JSON
|
|
82
|
-
try {
|
|
83
|
-
return JSON.parse(body);
|
|
84
|
-
} catch (ex) {
|
|
85
|
-
return null;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
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();
|
|
89
102
|
return maybeParseJSON(response.body);
|
|
90
|
-
})
|
|
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 throw ex;
|
|
117
|
+
}
|
|
91
118
|
}
|
|
92
119
|
|
|
93
120
|
function querySudo(queryString) {
|
|
94
121
|
var extraHeaders = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
95
|
-
var
|
|
122
|
+
var connectionOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
96
123
|
|
|
97
|
-
|
|
98
|
-
console.log(queryString);
|
|
99
|
-
}
|
|
100
|
-
return executeRawQuery(queryString, extraHeaders, sparqlEndpoint);
|
|
124
|
+
return executeRawQuery(queryString, extraHeaders, connectionOptions);
|
|
101
125
|
}
|
|
102
126
|
|
|
103
127
|
function updateSudo(queryString) {
|
|
104
128
|
var extraHeaders = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
105
|
-
var
|
|
129
|
+
var connectionOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
106
130
|
|
|
107
|
-
|
|
108
|
-
|
|
131
|
+
return executeRawQuery(queryString, extraHeaders, connectionOptions);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function maybeParseJSON(body) {
|
|
135
|
+
// Catch invalid JSON
|
|
136
|
+
try {
|
|
137
|
+
return JSON.parse(body);
|
|
138
|
+
} catch (ex) {
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function mayRetry(error, attempt) {
|
|
144
|
+
var connectionOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
console.log('Checking retry allowed for error: ' + error + ' and attempt: ' + attempt);
|
|
148
|
+
|
|
149
|
+
var mayRetry = false;
|
|
150
|
+
|
|
151
|
+
if (!(RETRY || connectionOptions.mayRetry)) {
|
|
152
|
+
mayRetry = false;
|
|
153
|
+
} else if (attempt < RETRY_MAX_ATTEMPTS) {
|
|
154
|
+
if (error.code && RETRY_FOR_CONNECTION_ERRORS.includes(error.code)) {
|
|
155
|
+
mayRetry = true;
|
|
156
|
+
} else if (error.httpStatus && RETRY_FOR_HTTP_STATUS_CODES.includes('' + error.httpStatus)) {
|
|
157
|
+
mayRetry = true;
|
|
158
|
+
}
|
|
109
159
|
}
|
|
110
|
-
|
|
160
|
+
|
|
161
|
+
console.log('Retry allowed? ' + mayRetry);
|
|
162
|
+
|
|
163
|
+
return mayRetry;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function nextAttemptTimeout(attempt) {
|
|
167
|
+
//expected to be milliseconds
|
|
168
|
+
return Math.round(Math.exp(RETRY_TIMEOUT_INCREMENT_FACTOR * attempt + 10));
|
|
111
169
|
}
|
|
112
170
|
|
|
113
171
|
var _exports = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lblod/mu-auth-sudo",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0-rc.0",
|
|
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": {
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
"homepage": "https://github.com/lblod/mu-auth-sudo#readme",
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"babel-cli": "^6.26.0",
|
|
36
|
+
"babel-plugin-add-module-exports": "^1.0.4",
|
|
36
37
|
"babel-preset-env": "^1.7.0",
|
|
37
|
-
"babel-plugin-add-module-exports": "^1.0.0",
|
|
38
38
|
"babel-preset-es2015": "^6.24.1",
|
|
39
39
|
"babel-register": "^6.26.0"
|
|
40
40
|
},
|