@lblod/mu-auth-sudo 1.0.0-beta.1 → 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 (2) hide show
  1. package/dist/auth-sudo.js +146 -0
  2. package/package.json +2 -2
@@ -0,0 +1,146 @@
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;
17
+ });
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();
39
+ // The following configuration options are considered optional, but may be overriden as a temporary workaround for issues. Thus, a last resort.
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}`);
68
+ }
69
+ try {
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
+ });
82
+ }
83
+ else {
84
+ response = await (0, node_fetch_1.default)(sparqlEndpoint, {
85
+ method: 'POST',
86
+ body: formData.toString(),
87
+ headers
88
+ });
89
+ }
90
+ return await response.json();
91
+ }
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
+ }
105
+ }
106
+ }
107
+ function querySudo(queryString, extraHeaders = {}, connectionOptions = {}) {
108
+ if (LOG_SPARQL_QUERIES) {
109
+ console.log(queryString);
110
+ }
111
+ return executeRawQuery(queryString, extraHeaders, connectionOptions);
112
+ }
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);
119
+ }
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;
126
+ }
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;
137
+ }
138
+ function nextAttemptTimeout(attempt) {
139
+ // expected to be milliseconds
140
+ return Math.round(Math.exp(RETRY_TIMEOUT_INCREMENT_FACTOR * attempt + 10));
141
+ }
142
+ const defaultExport = {
143
+ querySudo,
144
+ updateSudo
145
+ };
146
+ exports.default = defaultExport;
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@lblod/mu-auth-sudo",
3
- "version": "1.0.0-beta.1",
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
7
  "build": "tsc",
8
- "prepublish": "npm run build",
8
+ "prepare": "npm run build",
9
9
  "lint": "tslint -p tsconfig.json",
10
10
  "test": "echo \"Error: no test specified\" && exit 1",
11
11
  "release": "release-it"