1
0
Fork 0

Merge branch 'devel' of github.com:arangodb/arangodb into devel

This commit is contained in:
Andreas Streichardt 2016-05-20 17:37:00 +02:00
commit bca08d012f
21 changed files with 351 additions and 180 deletions

View File

@ -7,8 +7,9 @@ newVersionNumber = $(shell cat ../../VERSION)
################################################################################
# per book targets
check-summary:
@echo "##### checking summary for $(NAME)"
@find ppbooks/$(NAME) -name \*.md |sed -e "s;ppbooks/$(NAME)/;;" |grep -vf SummaryBlacklist.txt |sort > /tmp/is_md.txt
@cat $(NAME)/SUMMARY.md |grep '(' |sed -e "s;.*(;;" -e "s;).*;;" |sort |grep -v '# Summary' > /tmp/is_summary.txt
@cat $(NAME)/SUMMARY.md |grep -v '^ *# '|grep '(' |sed -e "s;.*(;;" -e "s;).*;;" |sort > /tmp/is_summary.txt
@if test "`comm -3 /tmp/is_md.txt /tmp/is_summary.txt|wc -l`" -ne 0; then \
echo "not all files are mapped to the summary!"; \
echo " files found | files in summary"; \
@ -17,6 +18,7 @@ check-summary:
fi
book-check-leftover-docublocks:
@echo "##### checking for left over docublocks in $(NAME)"
@if test "`grep -r \"@startDocuBlock\" --include \"*.md\" ppbooks/$(NAME) | wc -l`" -ne 0; then \
echo ; \
echo "@startDocuBlock markers still found in generated output files:"; \
@ -25,6 +27,7 @@ book-check-leftover-docublocks:
fi
book-check-restheader-leftovers:
@echo "##### checking for restheader leftovers in $(NAME)"
@if test "`find ppbooks/$(NAME) -name '*.md' -exec grep -- '^@[A-Z]*' {} \; -print | wc -l`" -gt 0; then \
echo "found these unconverted Swagger Restapi tags: "; \
find ppbooks/$(NAME) -name '*.md' -exec grep '^@[A-Z]*' {} \; -print; \
@ -33,6 +36,7 @@ book-check-restheader-leftovers:
# Check for all lines starting with exclamation marks, except image links which are exclamation mar + bracket
book-check-mdpp-leftovers:
@echo "##### checking for mdpp leftovers for $(NAME)"
@if test "`find ppbooks/$(NAME) -name '*.md' -exec grep -- '^![^\[]' {} \; -print | wc -l`" -gt 0; then \
echo "found these unconverted Markdown-PP tags: "; \
find ppbooks/$(NAME) -name '*.md' -exec grep '^![^\[]' {} \; -print; \
@ -40,6 +44,7 @@ book-check-mdpp-leftovers:
fi
ppbook-precheck-bad-code-sections:
@echo "##### checking for bad code sections in $(NAME)"
@if grep -qR '^``` *.* ' $(NAME); then \
echo "tripple tics with blanks afterwards found: "; \
grep -R '^``` *.* ' $(NAME); \
@ -47,6 +52,7 @@ ppbook-precheck-bad-code-sections:
fi
ppbook-check-html-link:
@echo "##### checking for invalid HTML links in $(NAME)"
@if test "`egrep -r '\[.*\]\(.*\)' ppbooks/$(NAME) |grep '\.md:' |grep html |grep -v http://|grep -v https:// |grep -v header.css |wc -l`" -gt 0; then \
echo "Found links to .html files inside of the document! use <foo>.md instead!"; \
echo; \
@ -55,6 +61,7 @@ ppbook-check-html-link:
fi
ppbook-check-directory-link:
@echo "##### checking for invalid md links in $(NAME)"
@if test "`egrep -r '\[.*\]\(.*\)' ppbooks/$(NAME) | grep '\.md:' |grep -v html |grep -v http://|grep -v https:// |grep -v header.css |grep -v node_modules |grep -v node_modules | grep -v '\.md' | wc -l`" -gt 0; then \
echo "Found director links! use ../<directory>/README.md instead!"; \
echo; \
@ -63,6 +70,7 @@ ppbook-check-directory-link:
fi
book-check-markdown-leftovers:
@echo "##### checking for remaining markdown snippets in the HTML output of $(NAME)"
@if test "`find books/$(NAME) -name '*.html' -exec grep -- '##' {} \; -print | wc -l`" -gt 0; then \
echo "found these unconverted markdown titles: "; \
find books/$(NAME) -name '*.html' -exec grep '##' {} \; -print; \
@ -80,6 +88,7 @@ book-check-markdown-leftovers:
fi
book-check-dangling-anchors:
@echo "##### checking for dangling anchors in $(NAME)"
@grep -R "a href.*#" books/$(NAME) | \
egrep -v "(styles/header\.js|/app\.js|class=\"navigation|https*://|href=\"#\")" | \
sed 's;\(.*\.html\):.*a href="\(.*\)#\(.*\)">.*</a>.*;\1,\2,\3;' | grep -v " " > /tmp/anchorlist.txt
@ -110,7 +119,7 @@ book-check-dangling-anchors:
fi
build-book-symlinks:
echo "generate backwards compatibility symlinks:"
echo "##### generate backwards compatibility symlinks for $(NAME)"
cd books/$(NAME); pwd; \
find . -name "README.mdpp" |\
sed -e 's:README\.mdpp$$::' |\
@ -118,6 +127,7 @@ build-book-symlinks:
bash
build-book:
@echo "##### Generating book $(NAME)"
make ppbook-precheck-bad-code-sections $(NAME)
if test ! -d ppbooks/$(NAME); then \
mkdir -p ppbooks/$(NAME); \
@ -147,18 +157,17 @@ build-book:
test -d books/$(NAME) || mkdir -p books/$(NAME)
#make check-summary
#make book-check-leftover-docublocks
#make book-check-restheader-leftovers
#make book-check-mdpp-leftovers
#make ppbook-check-html-link
#make ppbook-check-directory-link
make check-summary
make book-check-leftover-docublocks
make book-check-restheader-leftovers
make book-check-mdpp-leftovers
make ppbook-check-directory-link
cd ppbooks/$(NAME) && gitbook install
cd ppbooks/$(NAME) && gitbook build ./ ./../../books/$(NAME)
python ../Scripts/deprecated.py
#make book-check-markdown-leftovers
make book-check-markdown-leftovers
clean-book:
@rm -rvf books/$(NAME)
@ -254,4 +263,10 @@ build-books:
make build-books-keep-md NAME=Users
make build-books-keep-md NAME=AQL
make build-books-keep-md NAME=HTTP
make ppbook-check-html-link NAME=Users
make ppbook-check-html-link NAME=AQL
make ppbook-check-html-link NAME=HTTP
make check-docublocks

View File

@ -1,3 +1,48 @@
!CHAPTER Static file assets
TODO
The most flexible way to serve files in your Foxx service is to simply pass them through in your router using [the context object's `fileName` method][CONTEXT] and [the response object's `sendFile` method][RESPONSE]:
```js
router.get('/some/filename.png', function (req, res) {
const filePath = module.context.fileName('some-local-filename.png');
res.sendFile(filePath);
});
```
While allowing for greater control of how the file should be sent to the client and who should be able to access it, doing this for all your static assets can get tedious.
Alternatively you can specify file assets that should be served by your Foxx service directly in the [service manifest][MANIFEST] using the `files` attribute:
```json
"files": {
"/some/filename.png": {
"path": "some-local-filename.png",
"type": "image/png",
"gzip": false
},
"/favicon.ico": "bookmark.ico",
"/static": "my-assets-folder"
}
```
Each entry in the `files` attribute can represent either a single file or a directory. When serving entire directories, the key acts as a prefix and requests to that prefix will be resolved within the given directory.
**Options**
* **path**: `string`
The relative path of the file or folder within the service.
* **type**: `string` (optional)
The MIME content type of the file. Defaults to an intelligent guess based on the filename's extension.
* **gzip**: `boolean` (Default: `false`)
If set to `true` the file will be served with gzip-encoding if supported by the client. This can be useful when serving text files like client-side JavaScript, CSS or HTML.
If a string is provided instead of an object, it will be interpreted as the *path* option.
[CONTEXT]: './Context.md'
[MANIFEST]: './Manifest.md'
[RESPONSE]: './Response.md'

View File

@ -106,7 +106,54 @@ router.get('/hello/:name', function (req, res) {
The first line imports the [`joi` module from npm][JOI] which comes bundled with ArangoDB. Joi is a validation library that is used throughout Foxx to define schemas and parameter types.
**Note**: You can bundle your own modules from npm by installing them in your service folder and making sure the `node_modules` folder is included in your zip archive. For more information see [the chapter on modules][MODULES].
**Note**: You can bundle your own modules from npm by installing them in your service folder and making sure the `node_modules` folder is included in your zip archive. For more information see [the section on module dependencies in the chapter on dependencies][DEPENDENCIES].
The `pathParam` method allows us to specify parameters we are expecting in the path. The first argument corresponds to the parameter name in the path, the second argument is a joi schema the parameter is expected to match and the final argument serves to describe the parameter in the API documentation.
The path parameters are accessible from the `pathParams` property of the request object. We're using a template string to generate the server's response containing the parameter's value.
Note that routes with path parameters that fail to validate for the request URL will be skipped as if they wouldn't exist. This allows you to define multiple routes that are only distinguished by the schemas of their path parameters (e.g. a route taking only numeric parameters and one taking any string as a fallback).
![Screenshot of the API docs after a request to /hello/world]()
Let's take this further and create a route that takes a JSON request body:
```js
const requestSchema = joi.object({
values: joi.array().items(joi.number().required()).required()
}).required();
const responseSchema = joi.object({
result: joi.number().required()
}).required();
router.post('/sum', function (req, res) {
const values = req.body.values;
res.send({
result: values.reduce(function (a, b) {
return a + b;
}, 0)
});
})
.body(requestSchema, 'Values to add together.')
.response(responseSchema, 'Sum of the input values.')
.summary('Add up numbers')
.description('Calculates the sum of an array of number values.');
```
Note that we used `post` to define this route instead of `get` (which does not support request bodies). Trying to send a GET request to this route's URL (in the absence of a `get` route for the same path) will result in Foxx responding with an appropriate error response, indicating the supported HTTP methods.
As this route not only expects a JSON object as input but also responds with a JSON object as output we need to define two schemas. We don't strictly need a response schema but it helps documenting what the route should be expected to respond with and will show up in the API documentation.
Because we're passing a schema to the `response` method we don't need to explicitly tell Foxx we are sending a JSON response. The presence of a schema in the absence of a content type always implies we want JSON. Though we could just add `["application/json"]` as an additional argument after the schema if we wanted to make this more explicit.
The `body` method works the same way as the `response` method except the schema will be used to validate the request body. If the request body can't be parsed as JSON or doesn't match the schema, Foxx will reject the request with an appropriate error response.
![Screenshot of the API docs after a request with an array of numbers]()
!SECTION Using the database
TODO
!SECTION Next steps
TODO
@ -117,4 +164,4 @@ TODO
[REQUEST]: ./Router/Request.md
[RESPONSE]: ./Router/Response.md
[ROUTES]: ./Router/Endpoints.md
[MODULES]: ./Modules.md
[DEPENDENCIES]: ./Dependencies.md

View File

@ -1,3 +1,3 @@
!CHAPTER Other Foxx modules
!CHAPTER Related modules
TODO

View File

@ -16,6 +16,16 @@ While Foxx is primarily designed to be used to access the database itself, Arang
Finally [Scripts][SCRIPTS] can be used to perform one-off tasks, which can also be scheduled to be performed asynchronously using the built-in job queue.
!SECTION Development mode
TODO
!SECTION Foxx store
TODO
!SECTION Cluster-Foxx
TODO
[CONTEXT]: ./Context.md

View File

@ -1,4 +1,4 @@
!CHAPTER Router Module
!CHAPTER Routers
`const createRouter = require('@arangodb/foxx/router');`
@ -6,6 +6,74 @@ TODO
Routers need to be mounted to expose their HTTP routes. See [service context][CONTEXT].
!SECTION Creating a router
`createRouter(): Router`
This returns a new, clean Router object that has not yet been mounted in the service and can be exported like any other object.
!SECTION Request handlers
`router.get([path], handler, [name]): Endpoint`
`router.post([path], handler, [name]): Endpoint`
`router.put([path], handler, [name]): Endpoint`
`router.patch([path], handler, [name]): Endpoint`
`router.delete([path], handler, [name]): Endpoint`
`router.all([path], handler, [name]): Endpoint`
TODO
**Arguments**
* **path**: `string` (Default: `"/"`)
The path of the request handler relative to the base path the Router is mounted at. If omitted, the request handler will handle requests to the base path of the Router. For information on defining dynamic routes see the section on path parameters in the [chapter on router endpoints][ENDPOINTS].
* **handler**: `Function`
A function that takes the following arguments:
* **req**: `Request`
An incoming server request object.
* **res**: `Response`
An outgoing server response.
* **name**: `string` (optional)
A name that can be used to generate URLs for the endpoint. For more information see the `reverse` method of the [request object][REQUEST].
TODO
!SECTION Mounting child routers and middleware
`router.use([path], handler, [name]): Endpoint`
TODO
**Arguments**
* **path**: `string` (optional)
TODO
* **handler**: `Router | Middleware`
TODO
* **name**: `string` (optional)
A name that can be used to generate URLs for endpoints of this router. For more information see the `reverse` method of the [request object][REQUEST]. Has no effect if *handler* is a Middleware.
TODO
[CONTEXT]: ../Context.md
[ENDPOINTS]: ./Endpoints.md
[REQUEST]: ./Request.md

View File

@ -1,76 +0,0 @@
!CHAPTER Routers
`const createRouter = require('@arangodb/foxx/router');`
TODO
!SECTION Creating a router
`createRouter(): Router`
This returns a new, clean Router object that has not yet been mounted in the service and can be exported like any other object.
!SECTION Request handlers
`router.get([path], handler, [name]): Endpoint`
`router.post([path], handler, [name]): Endpoint`
`router.put([path], handler, [name]): Endpoint`
`router.patch([path], handler, [name]): Endpoint`
`router.delete([path], handler, [name]): Endpoint`
`router.all([path], handler, [name]): Endpoint`
TODO
**Arguments**
* **path**: `string` (Default: `"/"`)
The path of the request handler relative to the base path the Router is mounted at. If omitted, the request handler will handle requests to the base path of the Router. For information on defining dynamic routes see the section on path parameters in the [chapter on router endpoints][ENDPOINTS].
* **handler**: `Function`
A function that takes the following arguments:
* **req**: `Request`
An incoming server request object.
* **res**: `Response`
An outgoing server response.
* **name**: `string` (optional)
A name that can be used to generate URLs for the endpoint. For more information see the `reverse` method of the [request object][REQUEST].
TODO
!SECTION Mounting child routers and middleware
`router.use([path], handler, [name]): Endpoint`
TODO
**Arguments**
* **path**: `string` (optional)
TODO
* **handler**: `Router | Middleware`
TODO
* **name**: `string` (optional)
A name that can be used to generate URLs for endpoints of this router. For more information see the `reverse` method of the [request object][REQUEST]. Has no effect if *handler* is a Middleware.
TODO
[ENDPOINTS]: ./Endpoints.md
[REQUEST]: ./Request.md

View File

@ -4,26 +4,57 @@
The JWT session storage converts sessions to and from [JSON Web Tokens](https://jwt.io/).
**Examples**
```js
// Pass in a secure secret from the Foxx configuration
const secret = module.context.configuration.jwtSecret;
const sessions = sessionsMiddleware({
storage: jwtStorage(secret),
transport: 'header'
});
module.context.use(sessions);
```
!SECTION Creating a storage
`jwtStorage(options): Storage`
Creates a [Storage][STORAGES] that can be used in the sessions middleware.
**Note:** while the "none" algorithm (i.e. no signature) is supported this dummy algorithm provides no security and allows clients to make arbitrary modifications to the payload and should not be used unless you are certain you specifically need it.
**Arguments**
* **options**: `Object`
An object with the following properties:
* **algorithm**: `string`
* **algorithm**: `string` (Default: `"HS512"`)
TODO
The algorithm to use for signing the token.
Supported values:
* `"HS256"` (HMAC-SHA256)
* `"HS384"` (HMAC-SHA384)
* `"HS512"` (HMAC-SHA512)
* `"none"` (no signature)
* **secret**: `string`
TODO
The secret to use for signing the token.
TODO
This field is forbidden when using the "none" algorithm but required otherwise.
* **ttl**: `number` (Default: `3600`)
The maximum lifetime of the token in seconds. You may want to keep this short as a new token is generated on every request allowing clients to refresh tokens automatically.
* **verify**: `boolean` (Default: `true`)
If set to `false` the signature will not be verified but still generated (unless using the "none" algorithm).
If a string is passed instead of an options object it will be interpreted as the *secret* option.
[STORAGES]: ./README.md

View File

@ -38,7 +38,7 @@ new() {
`storage.fromClient(sid): Session | null`
TODO
Resolves or deserializes a session identifier to a session object.
**Arguments**
@ -60,7 +60,7 @@ fromClient(sid) {
`storage.forClient(session): string | null`
TODO
Derives a session identifier from the given session object.
**Arguments**

View File

@ -2,7 +2,24 @@
`const cookieTransport = require('@arangodb/foxx/sessions/transports/cookie');`
TODO
The cookie transport stores session identifiers in cookies on the request and response object.
**Examples**
```js
// Pass in a secure secret from the Foxx configuration
const secret = module.context.configuration.cookieSecret;
const sessions = sessionsMiddleware({
storage: module.context.collection('sessions'),
transport: cookieTransport({
name: 'FOXXSESSID',
ttl: 60 * 60 * 24 * 7, // one week in seconds
algorithm: 'sha256',
secret: secret
})
});
module.context.use(sessions);
```
!SECTION Creating a transport
@ -18,20 +35,21 @@ Creates a [Transport][TRANSPORT] that can be used in the sessions middleware.
* **name**: `string` (Default: `"sid"`)
TODO
The name of the cookie.
* **ttl**: `number` (optional)
TODO
* **secret**: `string` (optional)
TODO
Cookie lifetime in seconds.
* **algorithm**: `string` (optional)
TODO
The algorithm used to sign and verify the cookie. If no algorithm is specified, the cookie will not be signed or verified. See the [cookie method on the response object][RESPONSE].
* **secret**: `string` (optional)
Secret to use for the signed cookie. Will be ignored if no algorithm is provided.
If a string is passed instead of an options object, it will be interpreted as the *name* option.
[RESPONSE]: ../../Router/Response.md
[TRANSPORT]: ./README.md

View File

@ -2,7 +2,17 @@
`const headerTransport = require('@arangodb/foxx/sessions/transports/header');`
TODO
The header transport stores session identifiers in headers on the request and response objects.
**Examples**
```js
const sessions = sessionsMiddleware({
storage: module.context.collection('sessions'),
transport: headerTransport('X-FOXXSESSID')
});
module.context.use(sessions);
```
!SECTION Creating a transport
@ -18,7 +28,7 @@ Creates a [Transport][TRANSPORT] that can be used in the sessions middleware.
* **name**: `string` (Default: `X-Session-Id`)
TODO
Name of the header that contains the session identifier (not case sensitive).
If a string is passed instead of an options object, it will be interpreted as the *name* option.

View File

@ -613,7 +613,6 @@ collection names, e.g.
}
}
```
This result structure was redundant, and therefore has been simplified to just
```
@ -624,6 +623,7 @@ This result structure was redundant, and therefore has been simplified to just
...
]
}
```
in ArangoDB 3.0.

View File

@ -1,11 +1,11 @@
#
# Summary
#
#* [First Steps](FirstSteps/README.md)
# * [Getting Familiar](FirstSteps/GettingFamiliar.md)
# * [First Steps](FirstSteps/README.md) #TODO
# * [Getting Familiar](FirstSteps/GettingFamiliar.md) #TODO
* [Getting Started](GettingStarted/README.md)
# move to administration (command line options)?
#* [Install and run the server](FirstSteps/Arangod.md)
# * [Install and run the server](FirstSteps/Arangod.md) #TODO
* [Installing](GettingStarted/Installing/README.md)
* [Linux](GettingStarted/Installing/Linux.md)
* [Mac OS X](GettingStarted/Installing/MacOSX.md)
@ -15,13 +15,13 @@
* [Cluster setup](GettingStarted/Installing/Cluster.md)
* [Using the Web Interface](GettingStarted/WebInterface.md)
* [Coming from SQL](GettingStarted/ComingFromSql.md)
#* [Coming from MongoDB](GettingStarted/ComingFromMongoDb.md)
# * [Coming from MongoDB](GettingStarted/ComingFromMongoDb.md) #TODO
#
* [Scalability](Scalability/README.md)
# * [Joins](Scalability/Joins.md)
#
* [Data model & modeling](DataModeling/README.md)
#* [Collections](FirstSteps/CollectionsAndDocuments.md)
# * [Collections](FirstSteps/CollectionsAndDocuments.md) #TODO
* [Concepts](DataModeling/Concepts.md)
* [Databases](DataModeling/Databases/README.md)
* [Working with Databases](DataModeling/Databases/WorkingWith.md)
@ -67,8 +67,7 @@
* [Service context](Foxx/Context.md)
* [Configuration](Foxx/Configuration.md)
* [Dependencies](Foxx/Dependencies.md)
* [Routing](Foxx/Router/README.md)
* [Routers](Foxx/Router/Routers.md)
* [Routers](Foxx/Router/README.md)
* [Endpoints](Foxx/Router/Endpoints.md)
* [Middleware](Foxx/Router/Middleware.md)
* [Request](Foxx/Router/Request.md)
@ -84,6 +83,7 @@
* [Writing tests](Foxx/Testing.md)
* [Scripts and queued jobs](Foxx/Scripts.md)
* [Legacy mode for 2.x](Foxx/LegacyMode.md)
* [User management](Foxx/Users.md)
* [Related modules](Foxx/Modules.md)
* [Authentication](Foxx/Auth.md)
* [OAuth 2.0](Foxx/OAuth2.md)

View File

@ -195,9 +195,9 @@ Illegal document
@END_EXAMPLE_ARANGOSH_RUN
Insert multiple documents:
TODO, make this example work.
###!TODO, make this example work.
@ EXAMPLE_ARANGOSH_RUN{RestDocumentHandlerPostMulti}
EXAMPLE_ARANGOSH_RUN{RestDocumentHandlerPostMulti}
var cn = "products";
db._drop(cn);
@ -209,12 +209,12 @@ TODO, make this example work.
assert(response.code === 200);
logJsonResponse(response);
@ END_EXAMPLE_ARANGOSH_RUN
ND_EXAMPLE_ARANGOSH_RUN
Use of returnNew:
TODO, make this example work.
###!TODO, make this example work.
@ EXAMPLE_ARANGOSH_RUN{RestDocumentHandlerPostMulti}
EXAMPLE_ARANGOSH_RUN{RestDocumentHandlerPostMulti}
var cn = "products";
db._drop(cn);
@ -226,6 +226,6 @@ TODO, make this example work.
assert(response.code === 200);
logJsonResponse(response);
@ END_EXAMPLE_ARANGOSH_RUN
END_EXAMPLE_ARANGOSH_RUN
@endDocuBlock

File diff suppressed because one or more lines are too long

View File

@ -124,6 +124,12 @@
initFinished: false,
initialize: function () {
//check frontend config for global conf settings
if (frontendConfig.isCluster === true) {
this.isCluster = true;
}
// This should be the only global object
window.modalView = new window.ModalView();
@ -143,7 +149,6 @@
var callback = function(error, isCoordinator) {
self = this;
if (isCoordinator === true) {
self.isCluster = true;
self.coordinatorCollection.fetch({
success: function() {
@ -151,9 +156,6 @@
}
});
}
else {
self.isCluster = false;
}
}.bind(this);
window.isCoordinator(callback);

View File

@ -34,6 +34,7 @@ module.exports = function jwtStorage(cfg) {
}
assert(cfg.algorithm === 'none' || cfg.secret, `Must pass a JWT secret for "${cfg.algorithm}" algorithm`);
assert(cfg.algorithm !== 'none' || !cfg.secret, 'Must NOT pass a JWT secret for "none" algorithm');
const algorithm = cfg.algorithm || 'HS512';
const ttl = (cfg.ttl || 60 * 60) * 1000;
return {
fromClient(sid) {
@ -54,7 +55,7 @@ module.exports = function jwtStorage(cfg) {
payload: session.data,
exp: Date.now() + ttl
};
return crypto.jwtEncode(cfg.secret, token, cfg.algorithm);
return crypto.jwtEncode(cfg.secret, token, algorithm);
},
new() {
return {