diff --git a/app/controllers/help_controller.rb b/app/controllers/help_controller.rb
new file mode 100644
index 0000000..301d4e9
--- /dev/null
+++ b/app/controllers/help_controller.rb
@@ -0,0 +1,7 @@
+class HelpController < ApplicationController
+ before_action :authenticate_user!
+
+ def api
+ render layout: false
+ end
+end
diff --git a/app/views/help/api.html.erb b/app/views/help/api.html.erb
new file mode 100644
index 0000000..a9b6988
--- /dev/null
+++ b/app/views/help/api.html.erb
@@ -0,0 +1,104 @@
+
WebDNS API
+
WebDNS API
+
General
+
To access WebDNS API you must have an API token. If you are a WebDNS user you can generate your token by clicking on the API Token link in the navigation bar.
+
+
All API request should be routed under the /api/ prefix.
+
The API token needs to be present as a ?token URL parameter in all requests.
+
When sending data (POST/PUT) make sure to correctly set the content encoding header (Content-Enconding: application/json).
The bulk API allows multiple operations to be perfomed as a single transactional operation. There a three supported operations and they are applied in the following order:
+
+
deletes
+
upserts
+
additions
+
+
additions is an array of hashes. Each hash represents a record to be added.
+name, type, content and prio fields are supported.
+
deletes is an array of hashes. Each hash represents a single record to be deleted. The fields musts match exactly one record.
+
upserts is an array of hashes. Each hash represents a records to be added, just like an addition. What’s different about upserts is that, before adding the records, all records matching the hash’s name and type are deleted.
+
Fields
+
+
name: Record name. Should be expanded to contain the full domain name.
+
type: Capitilized record type ('A', 'AAAA', etc)
+
prio: Record priority, if supported.
+
content: Record content. When this is a CNANE do not include the trailing dot.
+
+
\ No newline at end of file
diff --git a/app/views/help/api.md b/app/views/help/api.md
new file mode 100644
index 0000000..fef7ee0
--- /dev/null
+++ b/app/views/help/api.md
@@ -0,0 +1,115 @@
+# WebDNS API
+
+## General
+
+To access WebDNS API you must have an API `token`. If you are a WebDNS user you can generate your token by clicking on the `API Token` link in the navigation bar.
+
+ * All API request should be routed under the `/api/` prefix.
+ * The API token needs to be present as a `?token` URL parameter in all requests.
+ * When sending data (POST/PUT) make sure to correctly set the content encoding header (`Content-Enconding: application/json`).
+
+## Debug API
+
+### GET `/ping`
+```bash
+curl -X GET https://webdns/api/ping
+{
+ "ok": true,
+ "response": "pong"
+}
+```
+
+### GET `/whoami`
+```bash
+curl -X GET https://webdns/api/whoami
+{
+ "ok": true,
+ "response": {
+ "id": 1,
+ "email": "user@example.com"
+ }
+}
+```
+
+## Records API
+
+### GET `/domain//list`
+```bash
+curl -X GET https://webdns/api/domain/example.com/list
+
+{
+ "ok": true,
+ "response": [
+ {
+ "name": "example.com",
+ "content": "ns1.example.com webdns@example.com 2016050301 10800 3600 604800 3600",
+ "type": "SOA",
+ "ttl": null,
+ "prio": null,
+ "disabled": false
+ },
+ {
+ "name": "example.com",
+ "content": "ns1.example.com",
+ "type": "NS",
+ "ttl": null,
+ "prio": null,
+ "disabled": false
+ },
+ {
+ "name": "www.example.com",
+ "content": "192.0.0.1",
+ "type": "A",
+ "ttl": null,
+ "prio": null,
+ "disabled": false
+ },
+ {
+ "name": "www.example.com",
+ "content": "2001:db8::1",
+ "type": "AAAA",
+ "ttl": null,
+ "prio": null,
+ "disabled": false
+ }
+```
+
+### POST `/domain//bulk`
+
+The `bulk` API allows multiple operations to be perfomed as a single transactional operation. There a three supported operations and they are applied in the following order:
+
+ * `deletes`
+ * `upserts`
+ * `additions`
+
+`additions` is an array of hashes. Each hash represents a record to be added.
+`name`, `type`, `content` and `prio` fields are supported.
+
+`deletes` is an array of hashes. Each hash represents a single record to be deleted. The fields musts match **exactly one** record.
+
+`upserts` is an array of hashes. Each hash represents a records to be added, just like an `addition`. What's different about `upserts` is that, before adding the records, all records matching the hash's `name` and `type` are deleted.
+
+#### Fields
+ * `name`: Record name. Should be expanded to contain the full domain name.
+ * `type`: Capitilized record type (`'A'`, `'AAAA'`, etc)
+ * `prio`: Record priority, if supported.
+ * `content`: Record content. When this is a CNANE **do not** include the trailing dot.
+
+```bash
+curl -X POST https://webdns/api/domain/example.com/bulk -H 'Content-Type: application/json' -d '{
+ "upserts": [
+ {
+ "name": "mail.example.com",
+ "type": "A",
+ "content": "1.2.3.4"
+ }
+ ],
+ "additions": [
+ {
+ "name": "www.example.com",
+ "type": "A",
+ "content": "1.2.3.4"
+ }
+ ]
+}'
+```
\ No newline at end of file
diff --git a/app/views/shared/_nav.html.erb b/app/views/shared/_nav.html.erb
index 2c7b7ff..98af7f0 100644
--- a/app/views/shared/_nav.html.erb
+++ b/app/views/shared/_nav.html.erb
@@ -1,56 +1,57 @@
diff --git a/config/routes.rb b/config/routes.rb
index 80b5e24..c76f3ab 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,77 +1,79 @@
Rails.application.routes.draw do
# Override devise user removal
devise_scope :users do
delete :users, to: redirect('/')
end
devise_for :users
get '/auth/saml', to: 'auth#saml'
root to: redirect('/domains')
resources :users, only: [] do
get :token, to: 'users#token', on: :member
post :generate_token, to: 'users#generate_token', on: :member
end
resources :groups, only: [:show] do
get :search_member,
to: 'groups#search_member', on: :member
post :members,
to: 'groups#create_member', as: :create_member, on: :member
delete 'member/:user_id',
to: 'groups#destroy_member', as: :destroy_member, on: :member
end
resources :domains do
get :edit_dnssec, to: 'domains#edit_dnssec', on: :member
delete :full_destroy, to: 'domains#full_destroy', on: :member
resources :records, except: [:index, :show] do
# Reuse records#update instead of introducing new controller actions
#
# rubocop:disable Style/AlignHash
put :disable, to: 'records#update', on: :member,
defaults: { record: { disabled: true } }
put :enable, to: 'records#update', on: :member,
defaults: { record: { disabled: false } }
put :editable, to: 'records#editable', on: :collection
post :valid, to: 'records#valid', on: :collection
post :bulk, to: 'records#bulk', on: :collection
# rubocop:enable Style/AlignHash
end
end
get '/records/search', to: 'records#search'
# Admin
namespace :admin do
root to: redirect('/admin/groups')
resources :groups, except: [:show]
resources :jobs, only: [:index, :destroy] do
put :done, to: 'jobs#update', on: :member,
defaults: { job: { status: 1 } }
put :pending, to: 'jobs#update', on: :member,
defaults: { job: { status: 0 } }
end
resources :users, only: [:destroy] do
get :orphans, to: 'users#orphans', on: :collection
put :update_groups, to: 'users#update_groups', on: :collection
end
end
# API
scope '/api' do
get :ping, to: 'api#ping'
get :whoami, to: 'api#whoami'
get '/domain/:domain/list', to: 'api#list', constraints: { domain: /[^\/]+/}
post '/domain/:domain/bulk', to: 'api#bulk', constraints: { domain: /[^\/]+/}
end if WebDNS.settings[:api]
# Private
put 'private/replace_ds', to: 'private#replace_ds'
put 'private/trigger_event', to: 'private#trigger_event'
get 'private/zones', to: 'private#zones'
+
+ get 'help/api', to: 'help#api'
end