diff options
Diffstat (limited to 'docs/REST.md')
-rw-r--r-- | docs/REST.md | 245 |
1 files changed, 245 insertions, 0 deletions
diff --git a/docs/REST.md b/docs/REST.md new file mode 100644 index 000000000..f8e6adf08 --- /dev/null +++ b/docs/REST.md @@ -0,0 +1,245 @@ +# Anope REST API + +Anope provides a RESTful HTTP API through the rest and httpd modules which +expose basic CRUD operations on all of Anope's internal data structures. + +The type names and data structures are the same as is used in the SQL/RDBMS +databaes support, but it otherwise currently not documented. + +The RESTful API documented here is relatively low level and allows you to +construct things that aren't normally possible in Anope, such as creating +nickless accounts or having an accounts display not matched a grouped nicks +name. This would produce weird behavior and not work as expected. It is +your responsibility to not do this. + +As an alternative you may execute commands remotely using the xmlrpc_main +module, which uses Anope's normal command system and is less subject to misuse. + +# Example usage + +## Getting available object types + +``` +$ curl localhost:8080/rest/types +{ + "types": [ + "botinfo", + "xline", + "oper", + "badword", + "channel", + "level", + "mlockmode", + "accesschanaccess", + "akick", + "entrymsg", + "flagschanaccess", + "logsetting", + "modelock", + "csmiscdata", + "cssuspendinfo", + "xopchanaccess", + "vhost", + "hostrequest", + "memoinfo", + "memo", + "memoignore", + "nick", + "account", + "mode", + "nsaccess", + "autojoin", + "nsmiscdata", + "nssuspendinfo", + "forbid", + "ignore", + "operinfo", + "newsitem", + "exception", + "stats" + ] +} +``` + +The types are subject to change, as several are dynamically added via modules, +including third party modules. + +## Listing objects of a type + +Send a GET to /rest/{object type} to return a list of all objects of that type. +For example, to fetch a list of all accounts. + +``` +$ curl localhost:8080/rest/account +{ + "account": [ + { + "display": "Adam", + "pass": "sha256:55ad6396a287df38967de578cbf92788faea8c94cd7d0e4f55eb45257921d75b:3df6978927389fb71a560a232572e5871bd072752eca27f159dc1fdc2462411c", + "email": "adam@sigterm.info", + "id": "10" + }, + { + "display": "Adam2", + "pass": "sha256:4cbb6ec03a8e7401342ee8832f5e4bd2abeb8fc7a007e66e2ac02e0c14f694f0:041167d04d70381e4218781e06b2b57b08165a987aced63f0a8ca8d25ac8ee51", + "email": "adam@anope.org", + "id": "95" + } + ] +} +``` + +## Searching for objects + +You may search for objects by the value of one of their fields, if it is unique. +This is most useful for looking up nicks, accounts, and channels. + +If the field you are searching for is not something commonly looked up by Anope, +which is mostly anything other than nick, account, and channel names, it will +likely cause the SQL database backend to on-the-fly index the field. + +Send a GET request to /rest/{object type}/{field name}/{search} + +``` +$ curl localhost:8080/rest/account/display/Adam +{ + "display": "Adam", + "pass": "sha256:55ad6396a287df38967de578cbf92788faea8c94cd7d0e4f55eb45257921d75b:3df6978927389fb71a560a232572e5871bd072752eca27f159dc1fdc2462411c", + "email": "adam@sigterm.info", + "id": "10" +} +``` + +Which will return the entire object. If it is not found, a non-200 status code is returned, +along with an error message. Error messages are never JSON formatted, but are simple strings. + +## Getting objects + +If you have an object ID, you can also fetch the object by id. + +Send a GET request to /rest/{object type}/{id} + +``` +$ curl localhost:8080/rest/account/10 +{ + "display": "Adam", + "pass": "sha256:55ad6396a287df38967de578cbf92788faea8c94cd7d0e4f55eb45257921d75b:3df6978927389fb71a560a232572e5871bd072752eca27f159dc1fdc2462411c", + "email": "adam@sigterm.info", + "id": "10" +} +``` + +## Updating the value of a field of an existing object + +You may PUT to /rest/{object type}/{id}/{field} data to update the value of a field. + +``` +$ curl -D - -X PUT localhost:8080/rest/account/10/email -d 'adam@anope.org' +HTTP/1.1 200 OK +Date: Sun, 30 Oct 2016 17:17:05 EDT +Server: Anope-2.1 +Content-Type: application/json +Content-Length: 0 +Connection: Close + +``` + +Again, a 200 status code is okay, anything else is an error, and a description is provided in the reply content. +You can now fetch the object back and notice the changed email address. + +## Creating objects + +You can create new objects by POSTing to /rest/{object type} + +``` +$ curl -D - -X POST localhost:8080/rest/account -d '{"display": "Adam3", "email": "Adam@anope.org"}' +HTTP/1.1 201 Created +Date: Sun, 30 Oct 2016 17:39:56 EDT +Server: Anope-2.1 +Content-Type: application/json +Content-Length: 3 +Connection: Close + +126 +``` + +This will return a 201 Ceated, with the body being the object's new id. + +## Deleting objects + +Similarly you can delete objects by sending DELETE to /rest/{object type}/{id}. + +``` +$ curl -D - -X DELETE localhost:8080/rest/account/126 +HTTP/1.1 200 OK +Date: Sun, 30 Oct 2016 17:42:40 EDT +Server: Anope-2.1 +Content-Type: application/json +Content-Length: 0 +Connection: Close +``` + +Due to the way Anope stores its data, deleting any object at any time should be safe, and will not leak +other (perhaps now unreachable) objects. + +# Object References and Relationships + +Object references are represented in the REST API by {type}:{id} + +``` +$ curl localhost:8080/rest/nsaccess/13 +{ + "account": "account:10", + "mask": "Adam@*.gvd.168.192.IP", + "id": "13" +} +``` + +Such as the value of "account" here for this nickserv access entry. Even though object ids within Anope +are global and not specific to the type. As such, if you submit a POST or PUT operation which creates a +field that is a reference, it is expected you supply both the type and id, in this format. + +It is possible to search for object references of a specific type to a given object. This is how all +one-to-many relationships are looked up within Anope. Objects never contain lists of other objects. +There are no join tables, and the objects within the C++ API do not contain collections of other +objects. + +For example: + +``` +$ curl localhost:8080/rest/account/10?refs=nsaccess +{ + "account": [ + { + "account": "account:10", + "mask": "Adam@*.gvd.168.192.IP", + "id": "13" + }, + { + "account": "account:10", + "mask": "adam@anope.org", + "id": "126" + } + ] +} +``` + +This fetches all objects of type nsaccess which have a reference to an account with id 10. Because +the type nsaccess only has one field that is a reference, the result is effectively the account's +NickServ access list. + +Because searching by refs searches object references and not at a field level, in cases of searching +for objects with mutltiple references, you would have to inspect the resulting objects to see if it +is what you want. For example, if you wanted to find all channels owned by a user, you may perform +something like GET /rest/account/10?refs=channel. The channels returned have a reference to the +given account, whether that is the channels founder or something else, like successor, or any other +field possible (that may have even been added by a 3rd party module), is unknown. + +Relationships defined within Anope, that is, the fields on objects which are object references, can +optionally depend on the existance of the object to which they reference. These fields can be seen +within the SQL schema as having foreign keys with ON CASCADE DELETE. When an object is deleted, all +references to it automatically get either NULLed, or the objects which reference it get recursively +deleted too. This is why it is generally safe to delete any object at any time. + +The field "account" on "nsaccess" is one that will cascade delete, which is why if you delete an +account, the access entries for it are automatically also cleaned up. |