"authenticationOptions" : {
"authenticationMethod": "JWT",
"jwtAuthenticationOptions" : {
"tokenExpirationTime" : 3600,
"signatureSecret" : "secret",
"keystorePath": "keystore.jceks"
}
}
This documentation provides information on the structure and functionality of the Mesh server and its API endpoints.
Mesh is a API-Centric CMS Server written in Java which enables you to store and retrieve JSON documents and binaries via REST. Mesh will also provide you a lot of powerful tools build around and for those documents.
Document level permission system
Search API
Webroot API for easy integration with modern routing frameworks
Image Manipulation API
Tagging system
Schema system for documents
Clustering (in development)
Versioning of your documents (in development)
The Mesh REST API provides endpoints which enable you to invoke CRUD operations on any Mesh element. There are many things you can do with the REST API. For example:
You can create new users.
You can create nodes and tag them with tags.
Binary data can be added to nodes.
You can find nodes which match your search parameters.
All REST API responses are only available in JSON.
The Postman chrome extension can be used to build and invoke requests from your browser to Mesh.
Mesh currently supports two ways of authentication: Basic
and Json Web Token (JWT)
. A user can be authenticated by setting the Authentication HTTP header in a request.
Edit the mesh configuration file (mesh.json
) to set your prefered authentication method.
Here is an example:
"authenticationOptions" : {
"authenticationMethod": "JWT",
"jwtAuthenticationOptions" : {
"tokenExpirationTime" : 3600,
"signatureSecret" : "secret",
"keystorePath": "keystore.jceks"
}
}
authenticationOptions.authenticationMethod
can be set to either "Basic"
or "JWT"
.
To use basic auth, set the authenticationOptions.authenticationMethod
to "Basic"
.
When using basic auth, set the authorization header according to RFC 1945 to authorize a user. This will also create a session for this user and set a session id cookie. For following requests, you can choose to either send the authorization header again or send the cookie back. Both ways will work to authorize the user.
For performance reasons, we recommend using the cookie whenever possible.
To destroy the session and the cookie you can call GET on the /api/v1/auth/logout
endpoint.
To use basic auth, set the authenticationOptions.authenticationMethod
to "JWT"
. You also have to set the keystore secret and the path to the keystore file. See above for an example.
Before using JWT you have to create a keystore which holds the secret to generate the signature for the token.
Currently only the HS256 algorithm is supported. You can use the java keytool
to create a new keystore.
Here is an example on how to create a keystore:
keytool -genseckey -keystore keystore.jceks -storetype jceks -storepass secret -keyalg HMacSHA256 -keysize 2048 -alias HS256 -keypass secret
After creating the keystore, set the file path of the keystore and the password to access the keystore in the mesh.json
configuration file.
To retrieve a token, call POST on the /api/v1/auth/login
endpoint with a json object containing these fields:
username
The username of the user
password
The password of the user
If the authentication was successful, the server will respond with a json object containing a single field:
token
The token to be sent on every subsequent request.
To authenticate the user for other requests, set Authorization
header to "Bearer <Token>"
, where <Token>
is the token you received from the login.
The token only lasts a certain amount of time (which can be configured in the mesh.json
file), so it might be necessary to refresh the token. You can call GET on the /api/v1/auth/refresh
endpoint with your still valid token to receive a new token which has a refreshed expire time.
When calling the login endpoint via JWT, the server also sets a cookie containing the token. Sending the cookie back can be used instead of the HTTP header to authenticate a user. This is useful for embedding binary image nodes directly in HTML.
Mesh expects and returns UTF-8 encoded data. Sending data in any other encoding format will result in encoding issues.
It is important to set the
when sending JSON data and to also set the Content-Type: application/json
header in order to signal Mesh that your client is accepting JSON.Accept
Content-Type: application/json
Accept: application/json
A request which is not well formatted may fail. Mesh will do its best to identify the issue and return a meaningful error response in those cases.
The paging query parameters are
and perPage
. It is important to note that page
is 1-based and page
can be set to perPage
in order to just retrieve a count of elements.0
Binary data can be attached to node binary fields which have been created using a schema that lists one or more binary fields. The
endpoint can be used to POST binary data and thus update the stored binary field. This endpoint is accepting only /api/v1/nodes/:uuid/languages/:languageTag/fields/:fieldName
.multipart/form-data
Create a new node
It is mandatory to specify the
, parentNodeUuid
and language
field when creating a node. It is possible specify the schema uuid instead of the name. At least one property within the schema
object must be set.schema
POST /api/v1/demo/nodes/2f2de9297c8143e8ade9297c8193e8fc HTTP/1.1
Host: localhost:8080
Cookie: mesh.session=61ac7969-e5ad-4c28-bc0f-0869a04e4db1
Content-Type: application/json
Accept: application/json
{
"schema" : {
"name" : "vehicle"
},
"published" : false,
"language" : "en",
"fields" : {
"name" : "DeLorean DMC-12",
"description" : "The DeLorean DMC-12 is a sports car manufactured by John DeLorean's DeLorean Motor Company for the American market from 1981–83."
},
"parentNodeUuid" : "91ca3e3517af41e48a3e3517afd1e4a5"
}
Update an existing node
The created node can be updated via a
request. You may only include those field which should be updated.PUT
PUT /api/v1/demo/nodes/5af8d0e077e34361b8d0e077e353619e HTTP/1.1
Host: localhost:8080
Cookie: mesh.session=61ac7969-e5ad-4c28-bc0f-0869a04e4db1
Content-Type: application/json
Accept: application/json
{
"schema" : {
"name" : "vehicle"
},
"published" : false,
"language" : "en",
"fields" : {
"weight" : 1230
}
}
Add a tag to a node
Tagging nodes requires just a simple
request.PUT
PUT /api/v1/demo/nodes/5af8d0e077e34361b8d0e077e353619e/tags/ba2edcdb1234489daedcdb1234289d38 HTTP/1.1
Host: localhost:8080
Cookie: mesh.session=61ac7969-e5ad-4c28-bc0f-0869a04e4db1
Accept: application/json
Mesh provides a various building blocks which can be used in order to setup your content structure. Below are elements which can be used to create your project datastructure.
Users can log into Mesh in order to interact with other elements.
Endpoint: /api/v1/users
Property | Description |
---|---|
uuid |
Uuid of the user |
lastname |
Lastname of the user |
firstname |
Firstname of the user |
username |
Username of the user (mandatory) |
emailAddress |
Email Address of the user |
nodeReference |
Node reference which can be used to store additional user data. It is also possible to expand this field using the |
enabled |
Enabled flag. Disabled users can no longer log into mash. A deleted user will not be completely removed. Instead the user will just be disabled. |
groups |
List of group references of the user |
creator |
User reference of the creator |
created |
Epoch creation date |
editor |
User reference of the last editor |
edited |
Epoch last edited date |
rolePerms |
Role permissions on the element |
permissions |
User permissions on the element |
Response Sample
{
"uuid" : "e63c84cf9b80457bbc84cf9b80257b21",
"creator" : {
"name" : "jdoe42",
"uuid" : "107defd0e6d24f00bdefd0e6d2ff00b2"
},
"created" : 1457951862854,
"editor" : {
"name" : "jdoe42",
"uuid" : "ea037d3a9338485a837d3a9338885a02"
},
"edited" : 1457951862854,
"permissions" : [ "READ", "UPDATE", "DELETE", "CREATE" ],
"lastname" : "Doe",
"firstname" : "Joe",
"username" : "jdoe42",
"emailAddress" : "j.doe@nowhere.com",
"nodeReference" : {
"projectName" : "dummy",
"uuid" : "1bf4c6f72c4d49e9b4c6f72c4d39e906"
},
"enabled" : true,
"groups" : [ {
"name" : "editors",
"uuid" : "885e79ee1b974b489e79ee1b97eb4899"
} ]
}
Groups are used to organize users. Roles can be assigned to groups. A user in a group with roles inherits those roles and the permissions that are bound to those roles. Groups can’t be nested.
Endpoint: /api/v1/groups
Property | Description |
---|---|
uuid |
Uuid of the group |
name |
Name of the group |
roles |
List of role references (name/uuid) |
creator |
User reference of the creator |
created |
Epoch creation date |
editor |
User reference of the last editor |
edited |
Epoch last edited date |
rolePerms |
Role permissions on the element |
permissions |
User permissions on the element |
Response Sample
{
"uuid" : "3429927e5e024d2ba9927e5e02ad2bd7",
"creator" : {
"name" : "jdoe42",
"uuid" : "ae29a94f7af74cafa9a94f7af7acaf5c"
},
"created" : 1457951862942,
"editor" : {
"name" : "jdoe42",
"uuid" : "a5dd492b3eef49979d492b3eefb9979f"
},
"edited" : 1457951862942,
"permissions" : [ "READ", "UPDATE", "DELETE", "CREATE" ],
"name" : "Admin Group",
"roles" : [ {
"name" : "admin",
"uuid" : "7db01267c1474617b01267c14776178b"
} ]
}
Roles are used to assign permissions to objects. A role can be assigned to multiple groups. Users can only assign permissions to roles to which they have access. Roles can’t be nested.
Endpoint: /api/v1/roles
Property | Description |
---|---|
uuid |
Uuid of the role |
name |
Name of the role |
groups |
List of group references of the role |
creator |
User reference of the creator |
created |
Epoch creation date |
editor |
User reference of the last editor |
edited |
Epoch last edited date |
rolePerms |
Role permissions on the element |
permissions |
User permissions on the element |
Response Sample
{
"uuid" : "12210e43b9604362a10e43b960f362d8",
"creator" : {
"name" : "jdoe42",
"uuid" : "fc3bb59078584537bbb5907858d53779"
},
"created" : 1457951862952,
"editor" : {
"name" : "jdoe42",
"uuid" : "21f17f8706064464b17f87060654646c"
},
"edited" : 1457951862952,
"permissions" : [ "READ", "UPDATE", "DELETE", "CREATE" ],
"name" : "Admin role",
"groups" : [ {
"name" : "editors",
"uuid" : "39a20267671a48cda20267671ac8cded"
}, {
"name" : "guests",
"uuid" : "c09404ccd6304fe89404ccd6307fe8fb"
} ]
}
A project is the base element your content structure which includes tagfamilies and your node tree. Schemas can be assigned to projects in order to allow creation of nodes which use one of the assigned schemas.
Endpoint: /api/v1/projects
Property | Description |
---|---|
uuid |
Uuid of the project |
name |
Name of the project |
rootNodeUuid |
Uuid of the project root node |
creator |
User reference of the creator |
created |
Epoch creation date |
editor |
User reference of the last editor |
edited |
Epoch last edited date |
rolePerms |
Role permissions on the element |
permissions |
User permissions on the element |
Response Sample
{
"uuid" : "6ebf225b63b1471dbf225b63b1e71dfb",
"creator" : {
"name" : "jdoe42",
"uuid" : "be39717b793440c4b9717b793450c41d"
},
"created" : 1457951863077,
"editor" : {
"name" : "jdoe42",
"uuid" : "961b40bbaa4e479d9b40bbaa4e479de5"
},
"edited" : 1457951863077,
"permissions" : [ "READ", "UPDATE", "DELETE", "CREATE" ],
"name" : "Dummy Project",
"rootNodeUuid" : "44e5a75f14c74931a5a75f14c789311f"
}
Tag families are base elements for tags which are bound to single project. Tag families can’t be nested.
Endpoint: /api/v1/:YOURPROJECT/tagfamilies
Property | Description |
---|---|
uuid |
Uuid of the tag family |
name |
Name of the tag family |
creator |
User reference of the creator |
created |
Epoch creation date |
editor |
User reference of the last editor |
edited |
Epoch last edited date |
rolePerms |
Role permissions on the element |
permissions |
User permissions on the element |
Response Sample
{
"creator" : {
"name" : "jdoe42",
"uuid" : "110b342a809a4dab8b342a809aadabf3"
},
"created" : 1457951863002,
"editor" : {
"name" : "jdoe42",
"uuid" : "f6c1a7081dbe4d8b81a7081dbedd8be3"
},
"edited" : 1457951863002,
"permissions" : [ "READ", "CREATE", "UPDATE" ],
"name" : "Colors"
}
Tags can be added to nodes. Tags can not be hierarchically structured.
Endpoint: /api/v1/:YOUR_PROJECT/tagFamilies/:uuid/tags
Property | Description |
---|---|
uuid |
Uuid of the tag |
fields |
Tag fields which provide the tag name |
tagFamily |
Tag family reference of the tag |
creator |
User reference of the creator |
created |
Epoch creation date |
editor |
User reference of the last editor |
edited |
Epoch last edited date |
rolePerms |
Role permissions on the element |
permissions |
User permissions on the element |
Response Sample
{
"uuid" : "e1fbd0d37e654560bbd0d37e65b56071",
"creator" : {
"name" : "jdoe42",
"uuid" : "d600c0e084ba4d3280c0e084babd3211"
},
"created" : 1457951862997,
"editor" : {
"name" : "jdoe42",
"uuid" : "657146f7a032472db146f7a032b72d76"
},
"edited" : 1457951862997,
"permissions" : [ "READ", "UPDATE", "DELETE", "CREATE" ],
"tagFamily" : {
"name" : "colors",
"uuid" : "ab87547e858c4d8687547e858c9d8666"
},
"fields" : {
"name" : "tagName"
}
}
Nodes are the main structural building blocks for your content. You may create different schemas to create multiple types of nodes. Nodes can be hierarchically structured if the schema is allowing this. The type of a node is always defined by the assigned schema. Nodes can be tagged by any number of tags.
Endpoint: /api/v1/:YOURPROJECT/nodes
Property | Description |
---|---|
uuid |
Uuid of the node |
fields |
Node fields of the current language |
parentNode |
Node reference to the parent node. The project basenode has no parent node. |
language |
Language tag of the current language |
availableLanguages |
List of available languages |
languagePaths |
Map with languages and the corresponding webroot path. Note that the field will only be added when a |
tags |
List of tags that were used to tag the node |
project |
Project reference |
schema |
Schema reference of the node |
isContainer |
Flag that indicates that the node is a container and may contain children |
childrenInfo |
JSON structure which contains information on the amount and type of child elements |
published |
Published flag |
displayField |
Key of the field that will be used to retrieve the display name value. (eg. "title" for blogpost nodes and "filename" for binary nodes) |
segmentField |
Key of the field that will be used to build a path segment of this node. The path segments create the webroot path to the element. |
creator |
User reference of the creator |
created |
Epoch creation date |
editor |
User reference of the last editor |
edited |
Epoch last edited date |
rolePerms |
Role permissions on the element |
permissions |
User permissions on the element |
Response Sample
{
"uuid" : "7a2382b54f6c4c44a382b54f6ccc442b",
"creator" : {
"name" : "jdoe42",
"uuid" : "d13a166d4099418bba166d4099a18b56"
},
"created" : 1457951862960,
"edited" : 1457951862960,
"permissions" : [ "READ", "UPDATE", "DELETE", "CREATE" ],
"availableLanguages" : [ "en", "de" ],
"languagePaths" : {
"de" : "/api/v1/yourProject/webroot/Bilder",
"en" : "/api/v1/yourProject/webroot/Images"
},
"parentNode" : {
"uuid" : "71d142efa6e94aed9142efa6e92aed98",
"displayName" : "parentNodeDisplayName"
},
"tags" : { },
"childrenInfo" : {
"folder" : {
"schemaUuid" : "2fb39ab31d1e4947b39ab31d1e894714",
"count" : 5
},
"blogpost" : {
"schemaUuid" : "643f7f317d084577bf7f317d08d5772d",
"count" : 1
}
},
"schema" : {
"name" : "content",
"uuid" : "c92f658cffed4461af658cffed44613f",
"version" : 1
},
"published" : true,
"fields" : {
"content-htmlField" : "Content for language tag de-DE",
"names-stringListField" : [ "Jack", "Joe", "Mary", "Tom" ],
"categories-nodeListField" : [ {
"uuid" : "27b4037ff40f4470b4037ff40f247024"
}, {
"uuid" : "e9a7a86d14cd4897a7a86d14cdf8972e"
}, {
"uuid" : "7dca4b525f3d474f8a4b525f3d474f1c"
} ],
"locations-micronodeListField" : [ {
"uuid" : "c4b3bba9c0b442d3b3bba9c0b4c2d336",
"microschema" : {
"name" : "geolocation",
"uuid" : "78c53b6f3e094a6f853b6f3e094a6fc4"
},
"fields" : {
"latitude" : 48.208330230278,
"longitude" : 16.373063840833
},
"type" : "micronode"
}, {
"uuid" : "c6b60e1897474ae5b60e1897474ae518",
"microschema" : {
"name" : "geolocation",
"uuid" : "e951f6806578475d91f6806578475d9e"
},
"fields" : {
"latitude" : 48.137222,
"longitude" : 11.575556
},
"type" : "micronode"
} ],
"enabled-booleanField" : true,
"price-numberField" : 100.1,
"filename-stringField" : "dummy-content.de.html",
"teaser-stringField" : "Dummy teaser for de-DE",
"location-micronodeField" : {
"uuid" : "a73680a14d54422eb680a14d54a22e19",
"microschema" : {
"name" : "geolocation",
"uuid" : "9b71f7c241744fe8b1f7c241747fe807"
},
"fields" : {
"latitude" : 48.208330230278,
"longitude" : 16.373063840833
},
"type" : "micronode"
},
"relatedProduct-nodeField" : {
"uuid" : "cac34b2d5f1d4a0e834b2d5f1d6a0e92"
},
"name-stringField" : "Name for language tag de-DE",
"release-dateField" : 1457951862,
"categoryIds-numberListField" : [ 1, 42, 133, 7 ],
"binary-binaryField" : {
"fileName" : "flower.jpg",
"width" : 800,
"height" : 600,
"sha512sum" : "ec582eb760034dd91d5fd33656c0b56f082b7365d32e2a139dd9c87ebc192bff3525f32ff4c4137463a31cad020ac19e6e356508db2b90e32d737b6d725e14c1",
"fileSize" : 95365,
"mimeType" : "image/jpeg",
"dpi" : 200,
"type" : "binary"
}
},
"path" : "/api/v1/yourProject/webroot/Images",
"breadcrumb" : [ ],
"container" : false
}
Name | Description |
---|---|
lang |
The lang query parameter can be used to retrieve a node in a particular language. |
role |
The role query parameter may be used in order to add permission information related to the specified role to the response.
This may be useful when you are logged in as admin but you want to retrieve the editor role permissions on a given node. When used, the response will include the |
expand |
A comma separated list of fields to expand on the node. When not set various fields may only contain element references. It is possible to expand node fields. |
expandAll |
The |
It is mandatory to set the
and language
parameter within the JSON request when sending a create request via POST to the nodes endpoint.parentNodeUuid
Depending on the used schema it may also be mandatory to add fields to the request which are flagged as mandatory.
{
"schema" : {
"name" : "content",
"uuid" : "7726dc580eb94a24a6dc580eb9fa2423",
"version" : 1
},
"published" : true,
"language" : "en",
"fields" : {
"names-stringListField" : [ "Jack", "Joe", "Mary", "Tom" ],
"categories-nodeListField" : [ {
"uuid" : "4a11eccc9e6640a591eccc9e66c0a540"
}, {
"uuid" : "953ffc0180c0479bbffc0180c0479bce"
}, {
"uuid" : "023ae71de1894c1bbae71de1895c1ba9"
} ],
"locations-micronodeListField" : [ {
"microschema" : {
"name" : "geolocation",
"uuid" : "8121da32e7a04e89a1da32e7a09e894e"
},
"fields" : {
"latitude" : 48.208330230278,
"longitude" : 16.373063840833
},
"type" : "micronode"
}, {
"microschema" : {
"name" : "geolocation",
"uuid" : "5749abadcbc34e9e89abadcbc3be9eb8"
},
"fields" : {
"latitude" : 48.137222,
"longitude" : 11.575556
},
"type" : "micronode"
} ],
"enabled-booleanField" : true,
"price-numberField" : 100.1,
"title" : "English title",
"content" : "English content",
"filename" : "index.en.html",
"location-micronodeField" : {
"microschema" : {
"name" : "geolocation",
"uuid" : "5c50f44264474a3a90f4426447fa3a45"
},
"fields" : {
"latitude" : 48.208330230278,
"longitude" : 16.373063840833
},
"type" : "micronode"
},
"relatedProduct-nodeField" : {
"uuid" : "9f5e74bf2e1445879e74bf2e147587ba"
},
"name" : "English name",
"release-dateField" : 1457951862,
"categoryIds-numberListField" : [ 1, 42, 133, 7 ],
"teaser" : "English teaser"
},
"parentNodeUuid" : "d3c652dc313d4b338652dc313dab33fc"
}
A schema defines the type and name of each field for a node. You can think of a schema as a blueprint for new nodes.
Endpoint: /api/v1/schemas
Unresolved directive in index.asciidoc - include::../raml/json/SchemaResponse.example.json[]
The following configuration properties may be specified:
binary
Set to true
to mark the schema as a binary schema. This will cause a file upload input to appear
when creating/editing a node using this schema, and also add additional binary-specific properties to the response object
of such nodes.
container
Set to true
to indicate that this schema can contain child nodes. This will cause the response
object for such nodes to have a childrenInfo
property.
displayField
Used to specify which field (as defined in the "fields" list) should be considered the title for
the purpose of displaying a list of nodes. The value must be a string which corresponds to the name of one of the
schema’s fields, and additionally that field must not be of type "list", "node".
A field is defined by an object which must have the following properties:
name
A unique name to identify the field
type
The type of data to be stored in this field.
The following optional properties may be applied to any type of field:
required
If true
, this field may not be left empty.
label
A human-readable label for the field to be used as a form label in the admin UI. If not defined, the "name" field would be used.
In addition to the above, certain types expose additional properties with which to configure the field. Such additional properties are defined in the [Types](#types) section.
Name | Type Key | Description |
---|---|---|
String |
|
A string field type may have an |
HTML |
|
A html field type does not have any special configuration settings at this point of time. |
Number |
|
A number field type has three optional config properties: "min" is the lowest permitted value, "max" is the greatest permitted value, and "step" is the size of the permitted increment in value. For example: |
Date |
|
The date field type stores a date in a epoch date format. |
Boolean |
|
A boolean field type does not have any special config settings. |
Binary |
|
The binary field type stores binary and binary related meta data (e.g: filename, sha512sum, image width and height, mimetype..). Binary fields within nodes can be updated using the fields API. |
Node |
|
A node field type must have an |
Micronode |
|
A micronode field type stores a single micronode. A micronode is similar to a node but it is directly bound to the node and thus is not accessible within the project node tree structure. Typical usecases for micronodes are galleries, location boxes, vcards. |
List |
|
A list field must be typed via the |
Binary schemas should be able to specify which media types (aka MIME type or Content-type) they may contain. This would be done by means of a whitelist which is an array of multiple regular expressions.
Since the JSON standard does not have a special regex type, it would need to be specified as a string, but would actually be converted to and interpreted as a regex by Mesh.
Component | Type | Version |
---|---|---|
Graph Database |
2.1.x |
|
OGM |
2.2.x |
|
Search Engine |
1.7.x |
|
Core Framework |
3.1.x |
|
In-Memory Data Grid |
3.5.x |
There is no dedicated installation procedure for mesh. You just download the mesh jar file and start it using java.
java -jar mesh-demo-0.6.0.jar
Alternatively you can start mesh using docker via:
The mesh-demo image contains mesh which provides the demo data and demo application.
docker run -p 8080:8080 gentics/mesh-demo
or
docker run -v /opt/data/:/mesh/data -p 8080:8080 gentics/mesh-demo
The mesh image contains an empty mesh server without any demo content.
docker run -p 8080:8080 gentics/mesh
or
docker run -v /opt/data/:/mesh/data -p 8080:8080 gentics/mesh
Oracle Java Runtime (JRE) 8u60+
The max open file limit on linux has to be raised on most linux systems since the embedded graph database and elasticsearch server often exceed the amount of concurrent open files.
Edit /etc/security/limits.conf and add these two lines:
Mesh soft nofile 60000
Mesh hard nofile 60000
Edit /etc/pam.d/su and uncomment or add the following line:
session required pam_limits.so
Please note that this change may require a logout and login after it is being applied.
The main
configuration file contains various settings to configure the graph database and various file system paths.mesh.json
{
"clusterMode" : false,
"defaultPageSize" : 25,
"defaultMaxDepth" : 10,
"defaultLanguage" : "en",
"updateCheck" : true,
"verticles" : { },
"mailServerOptions" : {
"hostname" : "localhost",
"port" : 25,
"starttls" : "OPTIONAL",
"login" : "NONE",
"ssl" : false,
"trustAll" : false,
"maxPoolSize" : 10,
"keepAlive" : true,
"allowRcptErrors" : false
},
"httpServerOptions" : {
"port" : 8080,
"ssl" : false,
"corsAllowedOriginPattern" : "NOT_SET",
"enableCors" : false
},
"storageOptions" : {
"directory" : "data/mesh-graphdb",
"backupDirectory" : "data/mesh-backup",
"exportDirectory" : "data/mesh-export",
"startServer" : false
},
"searchOptions" : {
"directory" : "data/mesh-searchindex",
"httpEnabled" : false
},
"uploadOptions" : {
"byteLimit" : 262144000,
"directory" : "data/binaryFiles",
"tempDirectory" : "/opt/mesh/data/tmp/temp-uploads"
},
"authenticationOptions" : {
"authenticationMethod" : "BASIC_AUTH",
"jwtAuthenticationOptions" : {
"tokenExpirationTime" : 3600,
"keystorePath" : "keystore.jceks"
}
},
"imageOptions" : {
"imageCacheDirectory" : "data/binaryImageCache",
"maxWidth" : 2048,
"maxHeight" : 2048
},
"tempDirectory" : "/opt/mesh/data/tmp"
}
Configuration | Type | Description |
---|---|---|
|
Flag |
The internal hazelcast in-memory data grid will be enabled if this flag is set to true. |
|
Flag |
A update check to the mesh update server will be invoked during startup if this flag is set to true. |
|
Number |
Default page size. |
|
String |
Default language which is used as a fallback when no language was specified. |
|
List |
List of vert.x java verticle classes which will be loaded during startup. |
|
Path |
Path to the main temporary filesystem directory. |
To enable https you have to specify the server key and the server certificate within the Mesh configuration.
You can create a snakeoil certificate for testing purposes this way:
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 90 -nodes
Configuration | Type | Description |
---|---|---|
|
Number |
Http Port number |
|
Boolean |
Enable or disable SSL support |
|
RegEx |
Regex which will validate the origin CORS header |
|
Boolean |
Enable CORS support |
|
Path |
SSL certificate path |
|
Path |
SSL key path |
By default all specified directories are relative to the current working directory.
Configuration | Type | Description |
---|---|---|
|
Path |
Path to the graph database storage location. |
|
Path |
Backup directory |
|
Path |
Export directory |
|
Boolean |
Flag that indicated whether the graph database server component should be started. By default only an embedded graph database is used which does not start a graph server. |
|
JSON |
Additional JSON parameters that will be passed on to the used graph database implementation. |
Configuration | Type | Description |
---|---|---|
|
Number |
Upload limit in bytes |
|
Path |
Filesystem directory for uploaded binary data |
|
Path |
Temporary directory for uploaded binary data. Finished files will be moved to the upload directory. |
Mesh does not manage any cache structure but it is possible to tweak the underlying graph database cache settings.
Permissions exist between roles and other elements (including other roles). Most responses within Mesh will contain a list of permissions which may indicate that CRUD operations on the returned element is restricted in a way.
The
endpoint can be used to assign or revoke permissions to/from a role. This endpoint can also be used to apply recursive permissions.
It is important to note that permissions can be applied to individual elements and onto the set of elements which is identified by the endpoint name (e.g: /groups)./api/v1/roles/:roleUuid/permissions
For newly created objects CRUD permissions are assigned to those roles that would be able to also create the object in the first place. By this we ensure that roles that would also be able to create the object are now able to invoke CRUD on the newly created object.
Example:
User John is assigned to Role A. Role A grants him to create a new child Node in a parent Node.
User Mary is assigned to Role B. Role B grants her to also create a new child Node in the same parent Node.
When John creates a new Node the permission system identifies Role B as a role that would also be able to create the object. Therefore CRUD permissions are assigned in between Role A and B and the newly created object.
Recursive permission changes on
will also affect all listed users./users
Element | Permission | Description |
---|---|---|
|
Create |
New users can be created. |
|
Read |
Not used |
|
Update |
Not used |
|
Delete |
Not used |
Recursive permission changes on
have no effect on referenced elements./users/:uuid
Element | Permission | Description |
---|---|---|
|
Create |
Not used |
|
Read |
User can be read. |
|
Update |
User can be updated. |
|
Delete |
User can be deleted. |
Recursive permission changes on
will affect all groups./groups
Element | Permission | Description |
---|---|---|
|
Create |
New roles can be created. |
|
Read |
Not used |
|
Update |
Not used |
|
Delete |
Not used |
Recursive permission changes on
will also affect users of the group but not roles that are linked to the group./groups/:uuid
Element | Permission | Description |
---|---|---|
|
Create |
Not used |
|
Read |
Group can be read. |
|
Update |
Group can be updated. |
|
Delete |
Group can be deleted. |
Element | Permission | Description |
---|---|---|
|
Create |
New roles can be created. |
|
Read |
Not used |
|
Update |
Not used |
|
Delete |
Not used |
Recursive permission changes on
have no effect./roles/:uuid
Element | Permission | Description |
---|---|---|
|
Create |
Not used |
|
Read |
Role can be read. |
|
Update |
Role can be updated. |
|
Delete |
Role can be deleted. |
Recursive permission changes on
will also affect schemas./schemas
Element | Permission | Description |
---|---|---|
|
Create |
New schemas can be created. |
|
Read |
Not used |
|
Update |
Not used |
|
Delete |
Not used |
Recursive permission changes on
have no effect on referenced elements./schemas/:uuid
Element | Permission | Description |
---|---|---|
|
Create |
Not used |
|
Read |
The schema can be read. Read permission on the schema is also needed to be able to create new nodes that are based upon the schema. |
|
Update |
The schema can be updated. |
|
Delete |
The schema can be deleted. |
Recursive permission changes on
will also affect all projects and those elements./projects
Element | Permission | Description |
---|---|---|
|
Create |
Create new projects. |
|
Read |
Not used |
|
Update |
Not used |
|
Delete |
Not used |
Recursive permission changes on
will also affect schemas, tagfamilies (and tags), nodes and subnodes./projects/:uuid
Element | Permission | Description |
---|---|---|
|
Create |
Not used |
|
Read |
Project can be read. |
|
Update |
Project can be updated. |
|
Delete |
Project can be deleted. |
Recursive permission changes on
will also all tagfamiles and those tags./project/:uuid/tagFamilies
Element | Permission | Description |
---|---|---|
|
Create |
Create new tag families. |
|
Read |
Not used |
|
Update |
Not used |
|
Delete |
Not used |
Recursive permission changes on
will also affect tags./project/:uuid/tagFamilies/:uuid
Element | Permission | Description |
---|---|---|
|
Create |
Tags can be created within the tag family. |
|
Read |
Tag family can be read. |
|
Update |
Tag family can be updated. |
|
Delete |
Tag family can be deleted. |
Recursive permission on
changes have no effect./api/v1/projects/:uuid/tagFamilies/:uuid/tags
Element | Permission | Description |
---|---|---|
|
Create |
Create new tags. |
|
Read |
Not used |
|
Update |
Not used |
|
Delete |
Not used |
Recursive permission changes on
have no effect./projects/:uuid/tagFamilies/:uuid/tags/:uuid
Element | Permission | Description |
---|---|---|
|
Create |
Not used |
|
Read |
Tag can be read. |
|
Update |
Tag can be updated. |
|
Delete |
Tag can be deleted. |
Recursive permission changes on
will also affect children of the node./:YOUR_PROJECT/nodes/:uuid
Element | Permission | Description |
---|---|---|
|
Create |
Not used |
|
Read |
Not used |
|
Update |
Not used |
|
Delete |
Not used |
Recursive permission changes on
will also affect children of the node./:YOUR_PROJECT/nodes/:uuid
Element | Permission | Description |
---|---|---|
|
Create |
Create new nodes within the node |
|
Read |
Node can be read. |
|
Update |
Node can be updated. |
|
Delete |
Node can be deleted. |
The
endpoint can be used to access nodes via a regular web path instead of using uuids./api/v1/:YOUR_PROJECT/webroot/:path
Example: /api/v1/demo/webroot/Vehicle%20Images/ford-gt.jpg?width=1000
This makes it possible to integrate mesh with many known routing frameworks.
Framework | Language |
---|---|
PHP |
|
JS |
|
Java,JS,Ceylon |
|
Ruby |
A webroot path consists of multiple path segments. Each segment of the url must be URL encoded. A list of segments can be provided by a single node. The segmentField
information from the schema is used to determine the segment field value which the node provides. Each language of the node must provide different path segment.
The Ford GT Image
node for example provides the path segment ford-gt.jpg
since the used schema vehicleImage
points to the binary field image
. The binary field contains the filename ford-gt.jpg
.
The segmentField
parameter within the schema is therefore used to map in between fields and the path segment.
ford-gt.jpg
→ /api/v1/demo/webroot/Vehicle%20Images/ford-gt.jpg
The binary data will be returned if the path targets a node in which the binary fileName
property provides the segment.
It is possible to differentiate between a mesh binary response and a normal JSON response by checking whether the Content-Disposition
header parameter is set. The header value will only be set when binary data is returned.
The router implementation can use this in order to be able to to decide whether to handle the JSON data or whether the binary data should just be passed through to the requestor.
There are two ways of generating a nested navigation response within mesh. You can either use
or /api/v1/:YOUR_PROJECT/nodes/:uuid/navigation
endpoints./api/v1/:YOUR_PROJECT/navroot/:path
Each endpoint will return a navigation response which contains the nested navigation tree structure. The
parameter may be used to limit the navigation depth (default: 10).maxDepth
Mesh will try to resolve any found mesh link within any text field of a node if the resolveLinks query parameter has been set to either short
, medium
or full
.
Example:
will be transformed into {{mesh.link("2f2de9297c8143e8ade9297c8193e8fc", "en")}}
when using the /api/v1/demo/webroot/Vehicle%20Images/ford-gt.jpg
?resolveLinks=full
Valid Links:
{{mesh.link("2f2de9297c8143e8ade9297c8193e8fc", "en")}}
{{mesh.link('2f2de9297c8143e8ade9297c8193e8fc', 'en')}}
{{mesh.link(\"2f2de9297c8143e8ade9297c8193e8fc\", \"en\")}}
(Link to default language){{mesh.link("2f2de9297c8143e8ade9297c8193e8fc")}}
The
endpoint can be used to resolve mesh links within the posted text data. This is useful when resolving links for a preview page./api/v1/utilities/linkResolver
Mesh provides a changelog like system in order to apply and keep track of schema changes. A schema change may be a single change that adds a new field to the schema or a change which updates the schema properties.
Mesh supports the following change operations:
Properties | Description |
---|---|
after |
Name of the field after which the new field should be inserted |
field |
Name of the field that should be added |
type |
Type of the field |
listType |
Optional list type |
{
"operation" : "ADDFIELD",
"properties" : {
"field" : "fieldToBeAdded",
"after" : "firstField",
"type" : "list",
"listType" : "html"
}
}
Properties | Description |
---|---|
field |
Name of the field to be removed |
{
"operation" : "REMOVEFIELD",
"properties" : {
"field" : "fieldToBeRemoved"
}
}
Properties | Description |
---|---|
field |
Name of the field to be modified |
type |
New field type |
listType |
(Only applies for lists) New list type |
{
"operation" : "CHANGEFIELDTYPE",
"properties" : {
"field" : "fieldToBeChanged",
"type" : "html"
}
}
Properties | Description |
---|---|
field |
Field to be updated |
label |
New field label |
{
"operation" : "UPDATEFIELD",
"properties" : {
"field" : "fieldToBeUpdated",
"name" : "newName"
}
}
Properties | Description |
---|---|
description |
New schema description |
order |
Array of strings that contains the field order |
displayFieldname |
New displayFieldname value of the schema |
segmentFieldname |
New segmentFieldname value of the schema |
container |
New container flag of the schema |
{
"operation" : "UPDATESCHEMA",
"properties" : {
"container" : "true",
"segmentFieldname" : "newSegmentField",
"displayFieldname" : "newSegmentField",
"description" : "new description",
"label" : "new label"
}
}
Properties | Description |
---|---|
description |
New microschema description |
{
"operation" : "UPDATEMICROSCHEMA",
"properties" : {
"description" : "new description",
"label" : "new label"
}
}
Each change may also provide a migration script. The migration script can be used to modify nodes that were affected by the migration.
Typical usecases for migration scripts are for example dynamic field removal or even custom reformatting of field data. It is also possible to split a single field value into values for two new fields.
The
and /api/v1/schemas/:uuid/diff
endpoints can be used to generate a list of changes by comparing the stored and posted schema./api/v1/microschemas/:uuid/diff
This list of changes can be modified and posted to
for schemas or /api/v1/schemas/:uuid/changes
for microschemas.
The posted list of changes will be validated and stored when valid. A schema migration process will be stared which runs in the background./api/v1/microschemas/:uuid/changes
The SockJS compliant
endpoint can be used to register to migration specific messages./api/v1/eventbus
Additionally to websocket it is possible to query mesh whether a migration is running via the
endpoint./api/v1/admin/migrationStatus
Sending a schema to
using the /api/v1/schemas:uuid
method will conveniently combine the diff generation and invocation of the schema migration.PUT
Please note that by default conflicting data will be removed and this action can only be avoided by specifying a custom migration script.
The
endpoint allows clients to access the mesh eventbus. This may be useful if you want to react on specific mesh events.
Currently only schema migration specific events are handled via this endpoint but more will follow./api/v1/eventbus
The endpoint is SockJS compliant. It is also possible to access the websocket directly via:
./api/v1/eventbus/websocket
Eventname | Description |
---|---|
mesh.migration |
Receive node and micronode migration specific events |
Images can be resized by appending the image manipulation query parameters on the binary node endpoint:
Endpoint: /api/v1/:YOUR_PROJECT/nodes/:uuid/languages/:languageTag/fields/:fieldname?width=220
It is also possible to use the image manipulation in combination with the webroot endpoint:
Endpoint: /api/v1/:YOUR_PROJECT/webroot/:path?width=220
It is mandatory to specify all four crop parameters when cropping an image.
Parameter | Description |
---|---|
|
Target image width. |
|
Target image height. |
|
Crop area start x coordinate. |
|
Crop area start y coordinate. |
|
Crop area width. |
|
Crop area height. |
Nodes are translated into different languages. Requests for nodes should contain the requested languages (as comma separated list) as query parameter:
Endpoint: /api/v1/:YOUR_PROJECT/nodes/:uuid?lang=en,de
If the requested node is available in any of the languages, the response will contain the fields in that language (first language found). Otherwise, the node will still be returned, but without fields.
If requested nodes contain fields of type node
or list of nodes
, and the fields are expanded, the expanded versions of the referenced nodes will be in the
same language as the node (if possible), otherwise the normal language fallback is done.
Search requests are handled by the /search endpoints.
Elasticsearch is used in order to provide the search functionality. This way elasticsearch queries can be posted to the search endpoints.
The JSON format of stored documents within the elasticsearch differ from the JSON format that is returned via regular Mesh endpoints. Thus it is important to know the elasticsearch document format when building an elasticsearch query. Below is a list of various example documents.
Endpoint: /api/v1/search/users
{
"created" : 1457951867551,
"creator.uuid" : "38bda5af937849a9bda5af937809a971",
"edited" : 1457951867551,
"editor.uuid" : "38bda5af937849a9bda5af937809a971",
"emailadress" : "joe1@nowhere.tld",
"firstname" : "Joe",
"groups.name" : [ "editors", "superEditors" ],
"groups.uuid" : [ "f00e2aaedadc48db8e2aaedadc38db9b", "df168a00b6b54c33968a00b6b50c33d2" ],
"lastname" : "Doe",
"username" : "joe1",
"uuid" : "35459263394240a8859263394280a8f5"
}
Endpoint: /api/v1/search/groups
{
"created" : 1457951867548,
"creator.uuid" : "eafd178922234761bd17892223076170",
"edited" : 1457951867548,
"editor.uuid" : "eafd178922234761bd17892223076170",
"name" : "adminGroup",
"uuid" : "c1de0197735c46069e0197735cd606da"
}
Endpoint: /api/v1/search/roles
{
"created" : 1457951867570,
"creator.uuid" : "74145c9295d84c11945c9295d82c110a",
"edited" : 1457951867570,
"editor.uuid" : "74145c9295d84c11945c9295d82c110a",
"name" : "adminRole",
"uuid" : "1430d3919e3444a7b0d3919e3424a71d"
}
Endpoint: /api/v1/search/nodes
{
"created" : 0,
"creator.uuid" : "065c11b1882745249c11b1882745245d",
"displayField.key" : "string",
"edited" : 0,
"editor.uuid" : "065c11b1882745249c11b1882745245d",
"fields.boolean" : true,
"fields.booleanList" : [ "true", "true", "true" ],
"fields.date" : 1457951867,
"fields.dateList" : [ 1457951867, 1457951867, 1457951867 ],
"fields.html" : "some<b>html",
"fields.htmlList" : [ "some<b>html", "some<b>html", "some<b>html" ],
"fields.micronode.fields.latitude" : 16.373063840833,
"fields.micronode.fields.longitude" : 16.373063840833,
"fields.micronode.microschema.name" : null,
"fields.micronode.microschema.uuid" : null,
"fields.node" : "c5ccbd240e964f278cbd240e963f2790",
"fields.nodeList" : [ "c5ccbd240e964f278cbd240e963f2790", "c5ccbd240e964f278cbd240e963f2790", "c5ccbd240e964f278cbd240e963f2790" ],
"fields.number" : 0.146,
"fields.numberList" : [ 0.146, 0.146, 0.146 ],
"fields.string" : "The name value",
"fields.stringList" : [ "The name value", "The name value", "The name value" ],
"language" : "de",
"parentNode.uuid" : "505f9062984e4f3e9f9062984e5f3e27",
"project.name" : "dummyProject",
"project.uuid" : "2ddb303cb6fd4ead9b303cb6fd8ead51",
"schema.name" : null,
"schema.uuid" : "71a2f74432544cc3a2f74432541cc33f",
"schema.version" : "0",
"tags.name" : [ "green", "red" ],
"tags.uuid" : [ "19f04b852be241bbb04b852be261bbe9", "651b601756754c5c9b601756759c5c62" ],
"uuid" : "698747b078b34e058747b078b32e05f0"
}
Search nodes by schema name
Listed below is an example search query which can be posted to
in order to find all nodes across all projects which were created using the content schema.
The found nodes will be sorted ascending by creator./api/v1/search/nodes
{
"sort" : {
"created" : { "order" : "asc" }
},
"query":{
"bool" : {
"must" : {
"term" : { "schema.name" : "content" }
}
}
}
}
Search nodes by micronode field values
Find all nodes which have a micronode list field (vcardlist) that contain at least one micronode which contains the two string fields (firstName, lastName) with the values ("Joe", "Doe"):
{
"query": {
"nested": {
"path": "fields.vcardlist",
"query": {
"bool": {
"must": [
{
"match": {
"fields.vcardlist.fields.firstName": "Joe"
}
},
{
"match": {
"fields.vcardlist.fields.lastName": "Doe"
}
}
]
}
}
}
}
}
/api/v1/search/projects
{
"created" : 1457951867574,
"creator.uuid" : "a2fd6316427746bfbd6316427786bf11",
"edited" : 1457951867574,
"editor.uuid" : "a2fd6316427746bfbd6316427786bf11",
"name" : "dummyProject",
"uuid" : "d64f2bf744ee46d58f2bf744ee26d5e6"
}
Endpoint: /api/v1/search/tags
{
"created" : 1457951867528,
"creator.uuid" : "09243adc0371437ea43adc0371637e8a",
"edited" : 1457951867528,
"editor.uuid" : "09243adc0371437ea43adc0371637e8a",
"fields.name" : "red",
"project.name" : "dummyProject",
"project.uuid" : "859903d70ab347c19903d70ab3b7c166",
"tagFamily.name" : "colors",
"tagFamily.uuid" : "b086889b29b14c7886889b29b1ac78b9",
"uuid" : "7f70f1f6c8314828b0f1f6c8316828ef"
}
Endpoint: /api/v1/search/tagFamilies
{
"created" : 1457951867577,
"creator.uuid" : "aa59f08df238428299f08df2385282c9",
"edited" : 1457951867577,
"editor.uuid" : "aa59f08df238428299f08df2385282c9",
"name" : "colors",
"project.name" : "dummyProject",
"project.uuid" : "6b3a16bee0784471ba16bee078a471ec",
"tags.name" : [ "red", "green" ],
"tags.uuid" : [ "6128aeae1ec34f4fa8aeae1ec31f4f56", "db163879dcbe4958963879dcbe695827" ],
"uuid" : "c2934d4d4f534c56934d4d4f533c56d0"
}
Endpoint: /api/v1/search/schemas
{
"created" : 1457951867582,
"creator.uuid" : "c4db6aae97ae440f9b6aae97ae140fd0",
"description" : "Content schema",
"edited" : 1457951867583,
"editor.uuid" : "c4db6aae97ae440f9b6aae97ae140fd0",
"name" : "content",
"uuid" : "ce2f7b047f3240bfaf7b047f3290bff9"
}
Endpoint: /api/v1/search/microschemas
{
"created" : 1457951867587,
"creator.uuid" : "d2ac5c3f52f34ab4ac5c3f52f3fab483",
"edited" : 1457951867587,
"editor.uuid" : "d2ac5c3f52f34ab4ac5c3f52f3fab483",
"name" : "geolocation",
"uuid" : "b2e3c0cb4b3147ffa3c0cb4b3157ff11"
}
Clustering support is still in development.
It will be possible to use master/master replication for OrientDB. Clustering for the elasticsearch nodes and the vertx event message bus.
The Mesh Administration UI is an AngularJS single page application which uses the REST API to interface with Mesh. By default it can be reached via
.http://localhost:8080/mesh-ui/
The mesh ui can be configured using the meshConfig.json file.
(function(window, document) {
/**
* Settings which can be configured per app instance, without requiring the app be re-built from
* source.
*
* @name meshConfig
*/
var meshConfig = {
// The URL to the Mesh API
apiUrl: '/api/v1/'
};
window.meshConfig = meshConfig;
})(window, document);
The mesh ui will provide a preview button when editing nodes. A post request to a configureable url is being dispatchen when the button will be triggered. The post request will contain the node JSON data of the current editing state. This way a preview page can be easily rendered by custom frontend implementations.
Gentics Mesh is published under a commercial license. This license can be obtained from sales@gentics.com.