summaryrefslogtreecommitdiff
path: root/docs/REST.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/REST.md')
-rw-r--r--docs/REST.md245
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.