Part of 5.0 and used by the GenUIne adminCentral
REST design considerations
About HTTP Methods:
- GET and POST are supported by all browsers, the rest are quirky to say the least
- PUT would be nice for create
- DELETE would be nice for delete
- IPSecurity filter blocks all but GET and POST
- Some frameworks simluate methods using a query param named _method
...
- Reading resources are done using GET and a path (GET <resource path>)
- Performing an action on a resource is done using POST and a trailing action name (POST <resource path>/<action name>)
REST Module infrastructure
RestEndpointManager is an ObservedManager that observes changes in /modules/<modules/rest-endpoints and discovers them runtime. They're exposed to the outside world at .magnolia/rest/*
...
The endpoints are not accessible unless the session is logged in. A 401 is sent by SecurityFilter (with the login page).
AdminCentral Endpoint (.magnolia/rest/admincentral)
status: started, menu returned is /modules/adminInterface/config/menu
overall stuff like menu config, login and module manager ui
- get menu
- method: GET
- path: .magnolia/rest/admincentral/menu
- arguments: none
- returns: MenuConfiguration
Tree Endpoint (.magnolia/rest/tree/<treeName>)
status: proof of concept
Generic endpoint for tree views. A client fetches the tree configuration to build the view, subsequent calls to fetch nodes return data for each column. Each tree is served by a TreeHandler. The TreeHandler can provide functionality that is specific for its tree.
...
to be decided: searching the repository is a very special kind of function bar item, how can it be represented?
Endpoint interface
- get child nodes
- method: GET
- path: .magnolia/rest/tree/<treeName>/<path>
- arguments: treeName and path in uri
- returns: TreeNodeListTreeNodeWithChildren
- get tree configuration
- method: POST
- path: .magnolia/rest/tree/<treeName>/config
- arguments: treeName in uri
- returns: JsonTreeConfiguration
- execute command
- method: POST
- path: .magnolia/rest/tree/<treeName>/<path>/<command>
- arguments: treeName, path and the name of the command in uri, rest of parameters are used by the actual command
- returns: depends on the command, must be able to also output a message (AlertUtil-style)TreeCommandExecutionResult
Commands
Commands are configured in the repository, arguments to a command are set using node data and mapped in using C2B. Parameters in the request are mapped onto the command using reflection before execution. A command is a use-once object (fresh instance created for every request). Commands include:
- create content
- arguments: optional name (defaults to 'untitled'), itemType
- returns: a TreeNodeList with only TreeNodeWithChildren of the newly created TreeNodenodes parent
- note:
- if the new name is already taken a unique name will be generated
- for the website tree the command must also set the default template (CreateWebsiteNodeCommand performs this)
- for the users tree the command must also add the newly added user to UserManager
- delete content
- arguments: none other than the path
- returns: a TreeNodeList TreeNodeWithChildren of the deleted nodes parent
- note: must also deactivate the deleted node
- rename content
- arguments: the new name
- returns: a TreeNodeList TreeNodeWithChildren of parent of the node that changed name
- note:
- if the new name is already taken a unique name will be generated
- for the users tree the command must update ACLs after rename
- move content
- arguments: new path, name of node to place before/after
- returns: a TreeNodeList TreeNodeWithChildren of the parent that the node was moved to and the previous parent
- note:
- if the new name is already taken a unique name will be generated
- copy content
- arguments: new path, name of node to place before/after
- returns: a TreeNodeList TreeNodeWithChildren of the parent that the node was copied to
- note:
- the new content must be deactivated
- if the new name is already taken a unique name will be generated
- activate
- activate incl subnodes
- add nodedata
- arguments: name, value and type (type and value optional defaults to empty string)
- returns: a TreeNodeList TreeNodeWithChildren of the node where nodedata was added
- note: if the name is already taken a unique name will be generated
- set nodedata
- arguments: name and value
- returns: a TreeNodeList TreeNodeWithChildren of the node where nodedata was changed
- remove nodedata
- arguments: name of nodedata to remove
- returns: a TreeNodeList TreeNodeWithChildren of the node where nodedata was removed
- rename nodedata
- arguments: name of nodedata to rename, new name
- returns: a TreeNodeList TreeNodeWithChildren of the node where nodedata was renamed
- note: what if the new name already exists? create unique or fail?
- list versions
- revert to version
- import and export
- note: does this even make sense to do with REST? (there's certainly nothing to return as JSON)
- search
- arguments: search query
- returns: search result
- set metadata property
- arguments: name, value and type
Command return values
Update: Commands return TreeCommandExecutionResult that contains all the changed nodes
To be decided: After invoking the command its up to the handler to return a good response. Depending on the command we need to return very different things:
- Create, we need to return the new nodes parent so that the client sees how the new node is ordered among its siblings
- Move, we need to return the parent that the node moves to, see above, and we need to let the client know that it is no longer where it used to be.
- and so on...
Website Endpoint (.magnolia/rest/website)
replaced by the tree endpoint
- get child pages
- method: GET
- path: .magnolia/rest/website/<path>
- arguments: path in uri
- returns: WebsitePageList
- create page
- method: PUT
- path: .magnolia/rest/website/<path>
- arguments: path in uri
- returns WebsitePage
- delete page
- method: DELETE
- path: .magnolia/rest/website/<path>
- arguments: path in uri
- update page (name, title, template)
- method: POST
- path: .magnolia/rest/website/<path>/update
- arguments: WebsitePage (only name, title and template sticks)
- search pages
- activate page
- method: POST
- path: .magnolia/rest/website/<path>/activate
- deactivate page
- method: POST
- path: .magnolia/rest/website/<path>/deactivate
- move page
- method: POST
- path: .magnolia/rest/website/<path>/move
- arguments: to=<website path>
- copy page
- method: POST
- path: .magnolia/rest/website/<path>/copy
- arguments: to=<website path>
- edit page using dialog (page properties)
- method: POST
- path: .magnolia/rest/website/<path>/edit
- arguments: dialog=<dialogName>
- returns: a dialog structure with values from the repository
- save page using dialog (page properties)
- method: POST
- path: .magnolia/rest/website/<path>/save
- arguments: dialog=<dialogName> and a whole bunch of parameters needed to represent the values
- returns: OK or a validation error structure
- list versions
- method: POST
- path: .magnolia/rest/website/<path>/versions
- returns: ?
- revert to version
- method: POST
- path: .magnolia/rest/website/<path>/revert/<version>
- import + export
- transport is already defined as an XML document
Templating Endpoint (.magnolia/rest/templating ?)
status: not implemented
- get paragraph definitions (for select paragraph dialog)
- method GET
- path .magnolia/rest/templating/paragraphs
- arguments
- paragraphs - comma seperated list of paragraphs
- returns ParagraphDefinitionList
- add paragraph using dialog
- method POST
- path .magnolia/rest/templating
- today sends in repository, path, nodeCollection and node=mgnlNew
- edit paragraph using dialog
- today sends in paragraphName, is this necessary, can we send in a dialogName instead?
- move paragraph (within node collection)
- delete paragraph
Dialogs Endpoint (.magnolia/rest/dialogs/)
status: proof of concept - has tabs, validation, supports only edit and date controls
...
- load dialog
- method GET
- path .magnolia/rest/dialogs/<dialogName>
- arguments
- mgnlRepository
- mgnlPath
- mgnlNodeCollectionName
- mgnlNode
- returns
- Dialog populated from repository
- example /.magnolia/rest/dialogs/howTo?mgnlRepository=website&mgnlPath=/howTo-jsp/main/0
- create node with dialog
- method POST
- path .magnolia/rest/dialogs/<dialogName>/create
- arguments
- mgnlRepository
- mgnlPath
- mgnlNodeCollectionName
- mgnlNode
- returns
- ValidationResult
- example /.magnolia/rest/dialogs/howTo/create?mgnlRepository=website&mgnlPath=/howTo-jsp&mgnlNodeCollectionName=main&title=ASDFGH12345
- update node with dialog
- method POST
- path .magnolia/rest/dialogs/<dialogName>/update
- arguments
- mgnlRepository
- mgnlPath
- mgnlNodeCollectionName
- mgnlNode
- returns
- ValidationResult
- example /.magnolia/rest/dialogs/howTo/update?mgnlRepository=website&mgnlPath=/howTo-jsp/main/0&title=ASDFGH12345
Repository Endpoint (.magnolia/rest/repository/<repositoryName>/)
CRUD for supported item types
...
Should be able to share commands with tree endpoint
Module Store (.magnolia/rest/modulestore ?)
list installed modules
list available modules
get module info
Workflow
Data Module
DMS
+ Tools