mirror of https://gitee.com/bigwinds/arangodb
Add SyntheticRequest#auth (#8750)
* Add SyntheticRequest#auth * Fix tests
This commit is contained in:
parent
3007c928aa
commit
b76f8adc0f
|
@ -1,6 +1,8 @@
|
||||||
devel
|
devel
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
* added req.auth property to Foxx
|
||||||
|
|
||||||
* added collection.documentId method to derive document id from key
|
* added collection.documentId method to derive document id from key
|
||||||
|
|
||||||
* fixed internal issue #536: ArangoSearch may crash server during term lookup
|
* fixed internal issue #536: ArangoSearch may crash server during term lookup
|
||||||
|
|
|
@ -19,6 +19,18 @@ The request object specifies the following properties:
|
||||||
of the ArangoDB server (e.g. `30102` for version 3.1.2) if no valid header
|
of the ArangoDB server (e.g. `30102` for version 3.1.2) if no valid header
|
||||||
was provided.
|
was provided.
|
||||||
|
|
||||||
|
* **auth**: `object | null`
|
||||||
|
|
||||||
|
The credentials supplied in the `authorization` header if any.
|
||||||
|
|
||||||
|
If the request uses basic authentication, the value is an object like
|
||||||
|
`{basic: {username: string}}` or
|
||||||
|
`{basic: {username: string, password: string}}` or
|
||||||
|
`{basic: {}}` (if the credentials were malformed or empty).
|
||||||
|
|
||||||
|
If the request uses bearer authentication, the value is an object like
|
||||||
|
`{bearer: string}`.
|
||||||
|
|
||||||
* **baseUrl**: `string`
|
* **baseUrl**: `string`
|
||||||
|
|
||||||
Root-relative base URL of the service, i.e. the prefix `"/_db/"` followed
|
Root-relative base URL of the service, i.e. the prefix `"/_db/"` followed
|
||||||
|
|
|
@ -448,3 +448,19 @@ The bundled JEMalloc memory allocator used in ArangoDB release packages has been
|
||||||
upgraded from version 5.0.1 to version 5.2.0.
|
upgraded from version 5.0.1 to version 5.2.0.
|
||||||
|
|
||||||
The bundled version of the RocksDB library has been upgraded from 5.16 to 6.0.
|
The bundled version of the RocksDB library has been upgraded from 5.16 to 6.0.
|
||||||
|
|
||||||
|
|
||||||
|
Foxx
|
||||||
|
----
|
||||||
|
|
||||||
|
Request credentials are now exposed via the `auth` property:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const tokens = context.collection("tokens");
|
||||||
|
router.get("/authorized", (req, res) => {
|
||||||
|
if (!req.auth || !req.auth.bearer || !tokens.exists(req.auth.bearer)) {
|
||||||
|
res.throw(403, "Not authenticated");
|
||||||
|
}
|
||||||
|
// ...
|
||||||
|
});
|
||||||
|
```
|
|
@ -202,6 +202,33 @@ module.exports =
|
||||||
return this._raw.compatibility;
|
return this._raw.compatibility;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get auth () {
|
||||||
|
const header = this.get("authorization") || "";
|
||||||
|
let match = header.match(/^Bearer (.*)$/);
|
||||||
|
if (match) {
|
||||||
|
return {bearer: match[1]};
|
||||||
|
}
|
||||||
|
match = header.match(/^Basic (.*)$/);
|
||||||
|
if (match) {
|
||||||
|
let credentials = "";
|
||||||
|
try {
|
||||||
|
credentials = new Buffer(match[1], "base64").toString("utf-8");
|
||||||
|
} catch (e) {}
|
||||||
|
if (!credentials) return {basic: {}};
|
||||||
|
const i = credentials.indexOf(":");
|
||||||
|
if (i === -1) {
|
||||||
|
return {basic: {username: credentials}};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
basic: {
|
||||||
|
username: credentials.slice(0, i),
|
||||||
|
password: credentials.slice(i + 1)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
get database () {
|
get database () {
|
||||||
return this._raw.database;
|
return this._raw.database;
|
||||||
}
|
}
|
||||||
|
|
|
@ -273,14 +273,71 @@ describe('SyntheticRequest', function () {
|
||||||
describe('headers', function () {
|
describe('headers', function () {
|
||||||
it('exposes the headers of the native request', function () {
|
it('exposes the headers of the native request', function () {
|
||||||
const headers = {};
|
const headers = {};
|
||||||
const rawReq = createNativeRequest({
|
const rawReq = createNativeRequest({ headers });
|
||||||
headers: headers
|
|
||||||
});
|
|
||||||
const req = new SyntheticRequest(rawReq, {});
|
const req = new SyntheticRequest(rawReq, {});
|
||||||
expect(req.headers).to.equal(headers);
|
expect(req.headers).to.equal(headers);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('auth', function () {
|
||||||
|
function btoa (str) {
|
||||||
|
return new Buffer(str).toString("base64");
|
||||||
|
}
|
||||||
|
it('recognizes no auth', function () {
|
||||||
|
const rawReq = createNativeRequest({ headers: {} });
|
||||||
|
const req = new SyntheticRequest(rawReq, {});
|
||||||
|
expect(req.auth).to.eql(null);
|
||||||
|
});
|
||||||
|
it('recognizes bearer auth', function () {
|
||||||
|
const headers = {authorization: "Bearer deadbeef"};
|
||||||
|
const rawReq = createNativeRequest({ headers });
|
||||||
|
const req = new SyntheticRequest(rawReq, {});
|
||||||
|
expect(req.auth).to.eql({bearer: "deadbeef"});
|
||||||
|
});
|
||||||
|
it('recognizes empty basic auth', function () {
|
||||||
|
const headers = {authorization: `Basic ${btoa("")}`};
|
||||||
|
const rawReq = createNativeRequest({ headers });
|
||||||
|
const req = new SyntheticRequest(rawReq, {});
|
||||||
|
expect(req.auth).to.eql({basic: {}});
|
||||||
|
});
|
||||||
|
it('recognizes malformed basic auth', function () {
|
||||||
|
const headers = {authorization: `Basic \x00\x01`};
|
||||||
|
const rawReq = createNativeRequest({ headers });
|
||||||
|
const req = new SyntheticRequest(rawReq, {});
|
||||||
|
expect(req.auth).to.eql({basic: {}});
|
||||||
|
});
|
||||||
|
it('recognizes basic with no password', function () {
|
||||||
|
const username = "hello";
|
||||||
|
const headers = {authorization: `Basic ${btoa(username)}`};
|
||||||
|
const rawReq = createNativeRequest({ headers });
|
||||||
|
const req = new SyntheticRequest(rawReq, {});
|
||||||
|
expect(req.auth).to.eql({basic: {username}});
|
||||||
|
});
|
||||||
|
it('recognizes basic with empty password', function () {
|
||||||
|
const username = "hello";
|
||||||
|
const headers = {authorization: `Basic ${btoa(`${username}:`)}`};
|
||||||
|
const rawReq = createNativeRequest({ headers });
|
||||||
|
const req = new SyntheticRequest(rawReq, {});
|
||||||
|
expect(req.auth).to.eql({basic: {username, password: ""}});
|
||||||
|
});
|
||||||
|
it('recognizes basic with password', function () {
|
||||||
|
const username = "hello";
|
||||||
|
const password = "world";
|
||||||
|
const headers = {authorization: `Basic ${btoa(`${username}:${password}`)}`};
|
||||||
|
const rawReq = createNativeRequest({ headers });
|
||||||
|
const req = new SyntheticRequest(rawReq, {});
|
||||||
|
expect(req.auth).to.eql({basic: {username, password}});
|
||||||
|
});
|
||||||
|
it('recognizes basic with colons in password', function () {
|
||||||
|
const username = "hello";
|
||||||
|
const password = "w:o:r:l:d";
|
||||||
|
const headers = {authorization: `Basic ${btoa(`${username}:${password}`)}`};
|
||||||
|
const rawReq = createNativeRequest({ headers });
|
||||||
|
const req = new SyntheticRequest(rawReq, {});
|
||||||
|
expect(req.auth).to.eql({basic: {username, password}});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('method', function () {
|
describe('method', function () {
|
||||||
it('exposes the method of the native request', function () {
|
it('exposes the method of the native request', function () {
|
||||||
const rawReq = createNativeRequest({
|
const rawReq = createNativeRequest({
|
||||||
|
|
Loading…
Reference in New Issue