Skip to content
This repository was archived by the owner on Sep 5, 2025. It is now read-only.

Commit 824c0a9

Browse files
author
Paul Korzhyk
committed
Add support for alpha's auth_token and Slash API key
1 parent 30fbfe8 commit 824c0a9

File tree

11 files changed

+157
-90
lines changed

11 files changed

+157
-90
lines changed

README.md

Lines changed: 72 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -12,28 +12,28 @@ This client follows the [Dgraph Javascript gRPC client][grpcclient] closely.
1212
Before using this client, we highly recommend that you go through [docs.dgraph.io],
1313
and understand how to run and work with Dgraph.
1414

15-
[docs.dgraph.io]:https://docs.dgraph.io
15+
[docs.dgraph.io]: https://docs.dgraph.io
1616

1717
**Use [Discuss Issues](https://discuss.dgraph.io/c/issues/35) for reporting issues about this repository.**
1818

1919
## Table of contents
2020

21-
- [Install](#install)
22-
- [Supported Versions](#supported-versions)
23-
- [Quickstart](#quickstart)
24-
- [Using a client](#using-a-client)
25-
- [Create a client](#create-a-client)
26-
- [Login into Dgraph](#login-into-dgraph)
27-
- [Alter the database](#alter-the-database)
28-
- [Create a transaction](#create-a-transaction)
29-
- [Run a mutation](#run-a-mutation)
30-
- [Run a query](#run-a-query)
31-
- [Commit a transaction](#commit-a-transaction)
32-
- [Check request latency](#check-request-latency)
33-
- [Debug mode](#debug-mode)
34-
- [Development](#development)
35-
- [Building the source](#building-the-source)
36-
- [Running tests](#running-tests)
21+
- [Install](#install)
22+
- [Supported Versions](#supported-versions)
23+
- [Quickstart](#quickstart)
24+
- [Using a client](#using-a-client)
25+
- [Create a client](#create-a-client)
26+
- [Login into Dgraph](#login-into-dgraph)
27+
- [Alter the database](#alter-the-database)
28+
- [Create a transaction](#create-a-transaction)
29+
- [Run a mutation](#run-a-mutation)
30+
- [Run a query](#run-a-query)
31+
- [Commit a transaction](#commit-a-transaction)
32+
- [Check request latency](#check-request-latency)
33+
- [Debug mode](#debug-mode)
34+
- [Development](#development)
35+
- [Building the source](#building-the-source)
36+
- [Running tests](#running-tests)
3737

3838
## Install
3939

@@ -60,9 +60,9 @@ Depending on the version of Dgraph that you are connecting to, you will have to
6060
use a different version of this client.
6161

6262
| Dgraph version | dgraph-js-http version |
63-
|:--------------------:|:------------------------------:|
64-
| >= 20.03.0 | >= *20.3.0* |
65-
| >= 1.1 | >= *1.1.0* |
63+
| :------------: | :--------------------: |
64+
| >= 20.03.0 | >= _20.3.0_ |
65+
| >= 1.1 | >= _1.1.0_ |
6666

6767
## Quickstart
6868

@@ -86,10 +86,10 @@ The following code snippet shows just one connection.
8686
const dgraph = require("dgraph-js-http");
8787

8888
const clientStub = new dgraph.DgraphClientStub(
89-
// addr: optional, default: "http://localhost:8080"
90-
"http://localhost:8080",
91-
// legacyApi: optional, default: false. Set to true when connecting to Dgraph v1.0.x
92-
false,
89+
// addr: optional, default: "http://localhost:8080"
90+
"http://localhost:8080",
91+
// legacyApi: optional, default: false. Set to true when connecting to Dgraph v1.0.x
92+
false,
9393
);
9494
const dgraphClient = new dgraph.DgraphClient(clientStub);
9595
```
@@ -118,31 +118,51 @@ you need to `login` again on a periodic basis:
118118
await clientStub.login();
119119
```
120120

121+
### Configure access tokens
122+
123+
Some Dgraph configurations require extra access tokens.
124+
125+
1. Alpha servers can be configured with [Secure Alter Operations](https://dgraph.io/docs/deploy/dgraph-administration/#securing-alter-operations).
126+
In this case the token needs to be set on the client instance:
127+
128+
```js
129+
dgraphClient.setAlphaAuthToken("My secret token value");
130+
```
131+
132+
2. [Slash GraphQL](https://dgraph.io/slash-graphql) requires API key for HTTP access:
133+
134+
```js
135+
dgraphClient.setSlashApiKey("Copy the Api Key from Slash GraphQL admin page");
136+
```
137+
121138
### Create https connection
122139

123140
If your cluster is using tls/mtls you can pass a node `https.Agent` configured with you
124141
certificates as follows:
125142

126143
```js
127-
const https = require('https');
128-
const fs = require('fs');
144+
const https = require("https");
145+
const fs = require("fs");
129146
// read your certificates
130-
const cert = fs.readFileSync('./certs/client.crt', 'utf8');
131-
const ca = fs.readFileSync('./certs/ca.crt', 'utf8');
132-
const key = fs.readFileSync('./certs/client.key', 'utf8');
147+
const cert = fs.readFileSync("./certs/client.crt", "utf8");
148+
const ca = fs.readFileSync("./certs/ca.crt", "utf8");
149+
const key = fs.readFileSync("./certs/client.key", "utf8");
133150

134151
// create your https.Agent
135152
const agent = https.Agent({
136153
cert,
137154
ca,
138155
key,
139-
})
156+
});
140157

141-
const clientStub = new dgraph.DgraphClientStub('https://localhost:8080', false, {agent});
158+
const clientStub = new dgraph.DgraphClientStub(
159+
"https://localhost:8080",
160+
false,
161+
{ agent },
162+
);
142163
const dgraphClient = new dgraph.DgraphClient(clientStub);
143164
```
144165

145-
146166
### Alter the database
147167

148168
To set the schema, pass the schema to `DgraphClient#alter(Operation)` method.
@@ -180,15 +200,15 @@ and you can call `Txn#discard()` multiple times with no additional side-effects.
180200
```js
181201
const txn = dgraphClient.newTxn();
182202
try {
183-
// Do something here
184-
// ...
203+
// Do something here
204+
// ...
185205
} finally {
186-
await txn.discard();
187-
// ...
206+
await txn.discard();
207+
// ...
188208
}
189209
```
190210

191-
You can make queries read-only and best effort by passing ```options``` to ```DgraphClient#newTxn```. For example:
211+
You can make queries read-only and best effort by passing `options` to `DgraphClient#newTxn`. For example:
192212

193213
```js
194214
const options = { readOnly: true, bestEffort: true };
@@ -197,7 +217,6 @@ const res = await dgraphClient.newTxn(options).query(query);
197217

198218
Read-only transactions are useful to increase read speed because they can circumvent the usual consensus protocol. Best effort queries can also increase read speed in read bound system. Please note that best effort requires readonly.
199219

200-
201220
### Run a mutation
202221

203222
`Txn#mutate(Mutation)` runs a mutation. It takes in a `Mutation` object, which
@@ -232,7 +251,6 @@ mutation must be immediately committed.
232251
await txn.mutate({ setJson: p, commitNow: true });
233252
```
234253

235-
236254
### Run a query
237255

238256
You can run a query by calling `Txn#query(string)`. You will need to pass in a
@@ -243,7 +261,7 @@ the variables object as the second argument.
243261
The response would contain the `data` field, `Response#data`, which returns the response
244262
JSON.
245263

246-
Let’s run the following query with a variable $a:
264+
Let’s run the following query with a variable \$a:
247265

248266
```console
249267
query all($a: string) {
@@ -270,7 +288,7 @@ const ppl = res.data;
270288

271289
// Print results.
272290
console.log(`Number of people named "Alice": ${ppl.all.length}`);
273-
ppl.all.forEach((person) => console.log(person.name));
291+
ppl.all.forEach(person => console.log(person.name));
274292
```
275293

276294
This should print:
@@ -280,7 +298,6 @@ Number of people named "Alice": 1
280298
Alice
281299
```
282300

283-
284301
### Commit a transaction
285302

286303
A transaction can be committed using the `Txn#commit()` method. If your transaction
@@ -294,21 +311,21 @@ transactions when they fail.
294311
```js
295312
const txn = dgraphClient.newTxn();
296313
try {
297-
// ...
298-
// Perform any number of queries and mutations
299-
// ...
300-
// and finally...
301-
await txn.commit();
314+
// ...
315+
// Perform any number of queries and mutations
316+
// ...
317+
// and finally...
318+
await txn.commit();
302319
} catch (e) {
303-
if (e === dgraph.ERR_ABORTED) {
304-
// Retry or handle exception.
305-
} else {
306-
throw e;
307-
}
320+
if (e === dgraph.ERR_ABORTED) {
321+
// Retry or handle exception.
322+
} else {
323+
throw e;
324+
}
308325
} finally {
309-
// Clean up. Calling this after txn.commit() is a no-op
310-
// and hence safe.
311-
await txn.discard();
326+
// Clean up. Calling this after txn.commit() is a no-op
327+
// and hence safe.
328+
await txn.discard();
312329
}
313330
```
314331

lib/client.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ export declare class DgraphClient {
99
setQueryTimeout(timeout: number): DgraphClient;
1010
getQueryTimeout(): number;
1111
alter(op: Operation): Promise<Payload>;
12+
setAlphaAuthToken(authToken: string): void;
13+
setSlashApiKey(apiKey: string): void;
1214
login(userid: string, password: string): Promise<boolean>;
1315
logout(): void;
1416
newTxn(options?: TxnOptions): Txn;

lib/client.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
3636
}
3737
};
3838
Object.defineProperty(exports, "__esModule", { value: true });
39+
exports.DgraphClient = void 0;
3940
var errors_1 = require("./errors");
4041
var txn_1 = require("./txn");
4142
var util_1 = require("./util");
@@ -69,6 +70,14 @@ var DgraphClient = (function () {
6970
});
7071
});
7172
};
73+
DgraphClient.prototype.setAlphaAuthToken = function (authToken) {
74+
this.clients.forEach(function (c) {
75+
return c.setAlphaAuthToken(authToken);
76+
});
77+
};
78+
DgraphClient.prototype.setSlashApiKey = function (apiKey) {
79+
this.clients.forEach(function (c) { return c.setSlashApiKey(apiKey); });
80+
};
7281
DgraphClient.prototype.login = function (userid, password) {
7382
return __awaiter(this, void 0, void 0, function () {
7483
var c;

lib/clientStub.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ export declare class DgraphClientStub {
2828
getHealth(all?: boolean): Promise<Response>;
2929
getState(): Promise<Response>;
3030
setAutoRefresh(val: boolean): void;
31+
setAlphaAuthToken(authToken: string): void;
32+
setSlashApiKey(apiKey: string): void;
3133
private cancelRefreshTimer;
3234
private maybeStartRefreshTimer;
3335
private callAPI;

lib/clientStub.js

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,14 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
4747
}
4848
};
4949
Object.defineProperty(exports, "__esModule", { value: true });
50+
exports.DgraphClientStub = void 0;
5051
var fetch = require("isomorphic-fetch");
5152
var jwt = require("jsonwebtoken");
5253
var errors_1 = require("./errors");
5354
var AUTO_REFRESH_PREFETCH_TIME = 5000;
55+
var ACL_TOKEN_HEADER = "X-Dgraph-AccessToken";
56+
var ALPHA_AUTH_TOKEN_HEADER = "X-Dgraph-AuthToken";
57+
var SLASH_API_KEY_HEADER = "X-Auth-Token";
5458
var DgraphClientStub = (function () {
5559
function DgraphClientStub(addr, stubConfig, options) {
5660
if (stubConfig === void 0) { stubConfig = {}; }
@@ -104,7 +108,8 @@ var DgraphClientStub = (function () {
104108
return this.callAPI("alter", __assign(__assign({}, this.options), { method: "POST", body: body }));
105109
};
106110
DgraphClientStub.prototype.query = function (req) {
107-
var headers = Object.assign({}, this.options.headers !== undefined ? this.options.headers : {});
111+
var headers = this.options.headers !== undefined
112+
? __assign({}, this.options.headers) : {};
108113
if (req.vars !== undefined) {
109114
if (this.legacyApi) {
110115
headers["X-Dgraph-Vars"] = JSON.stringify(req.vars);
@@ -213,9 +218,7 @@ var DgraphClientStub = (function () {
213218
else {
214219
return Promise.reject("Mutation has no data");
215220
}
216-
var headers = Object.assign({}, this.options.headers !== undefined ? this.options.headers : {}, {
217-
"Content-Type": "application/" + (usingJSON ? "json" : "rdf"),
218-
});
221+
var headers = __assign(__assign({}, (this.options.headers !== undefined ? this.options.headers : {})), { "Content-Type": "application/" + (usingJSON ? "json" : "rdf") });
219222
if (usingJSON && this.legacyApi) {
220223
headers["X-Dgraph-MutationType"] = "json";
221224
}
@@ -253,7 +256,7 @@ var DgraphClientStub = (function () {
253256
DgraphClientStub.prototype.abort = function (ctx) {
254257
var url = !this.legacyApi
255258
? "commit?startTs=" + ctx.start_ts + "&abort=true"
256-
: "/abort/" + ctx.start_ts;
259+
: "abort/" + ctx.start_ts;
257260
return this.callAPI(url, __assign(__assign({}, this.options), { method: "POST" }));
258261
};
259262
DgraphClientStub.prototype.login = function (userid, password, refreshToken) {
@@ -279,10 +282,7 @@ var DgraphClientStub = (function () {
279282
body.userid = userid;
280283
body.password = password;
281284
}
282-
return [4, this.callAPI("login", {
283-
method: "POST",
284-
body: JSON.stringify(body),
285-
})];
285+
return [4, this.callAPI("login", __assign(__assign({}, this.options), { method: "POST", body: JSON.stringify(body) }))];
286286
case 1:
287287
res = _a.sent();
288288
this.accessToken = res.data.accessJWT;
@@ -332,6 +332,12 @@ var DgraphClientStub = (function () {
332332
this.autoRefresh = val;
333333
this.maybeStartRefreshTimer(this.accessToken);
334334
};
335+
DgraphClientStub.prototype.setAlphaAuthToken = function (authToken) {
336+
this.options.headers[ALPHA_AUTH_TOKEN_HEADER] = authToken;
337+
};
338+
DgraphClientStub.prototype.setSlashApiKey = function (apiKey) {
339+
this.options.headers[SLASH_API_KEY_HEADER] = apiKey;
340+
};
335341
DgraphClientStub.prototype.cancelRefreshTimer = function () {
336342
if (this.autoRefreshTimer !== undefined) {
337343
clearTimeout(this.autoRefreshTimer);
@@ -358,7 +364,7 @@ var DgraphClientStub = (function () {
358364
url = this.getURL(path);
359365
if (this.accessToken !== undefined && path !== "login") {
360366
config.headers = config.headers !== undefined ? config.headers : {};
361-
config.headers["X-Dgraph-AccessToken"] = this.accessToken;
367+
config.headers[ACL_TOKEN_HEADER] = this.accessToken;
362368
}
363369
return [4, fetch(url, config)];
364370
case 1:

lib/errors.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ var __extends = (this && this.__extends) || (function () {
1313
};
1414
})();
1515
Object.defineProperty(exports, "__esModule", { value: true });
16+
exports.APIError = exports.CustomError = exports.ERR_BEST_EFFORT_REQUIRED_READ_ONLY = exports.ERR_ABORTED = exports.ERR_FINISHED = exports.ERR_NO_CLIENTS = void 0;
1617
exports.ERR_NO_CLIENTS = new Error("No clients provided in DgraphClient constructor");
1718
exports.ERR_FINISHED = new Error("Transaction has already been committed or discarded");
1819
exports.ERR_ABORTED = new Error("Transaction has been aborted. Please retry");

lib/index.js

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
"use strict";
2-
function __export(m) {
3-
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
4-
}
2+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3+
if (k2 === undefined) k2 = k;
4+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5+
}) : (function(o, m, k, k2) {
6+
if (k2 === undefined) k2 = k;
7+
o[k2] = m[k];
8+
}));
9+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
10+
for (var p in m) if (p !== "default" && !exports.hasOwnProperty(p)) __createBinding(exports, m, p);
11+
};
512
Object.defineProperty(exports, "__esModule", { value: true });
6-
__export(require("./clientStub"));
7-
__export(require("./client"));
8-
__export(require("./txn"));
9-
__export(require("./errors"));
13+
__exportStar(require("./types"), exports);
14+
__exportStar(require("./clientStub"), exports);
15+
__exportStar(require("./client"), exports);
16+
__exportStar(require("./txn"), exports);
17+
__exportStar(require("./errors"), exports);

lib/txn.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
3636
}
3737
};
3838
Object.defineProperty(exports, "__esModule", { value: true });
39+
exports.Txn = void 0;
3940
var errors_1 = require("./errors");
4041
var util_1 = require("./util");
4142
var Txn = (function () {

lib/util.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"use strict";
22
Object.defineProperty(exports, "__esModule", { value: true });
3+
exports.stringifyMessage = exports.isConflictError = exports.isAbortedError = void 0;
34
var errors_1 = require("./errors");
45
function isAbortedError(error) {
56
if (!(error instanceof errors_1.APIError)) {

0 commit comments

Comments
 (0)