mirror of
https://github.com/outbackdingo/firezone.git
synced 2026-01-27 10:18:54 +00:00
Generate API docs from tests and Phoenix Controller docs (#1286)
1. The test data is taken from tests, you can override attributes by adding keyword params to `doc` macro; 2. Additionally, you can add a section title using a `@moduledoc` in a controller and a controller action title using `@doc` on a controller function. (It will be added to all instances of its usage). 3. To make parameters nice a helper was added to build it using `DocHelper`, you can find an example in UserController. Overall, the code is messy, I'll need to revisit it, but was doing it in a rush so hope it's good enough for v0. Results you can see at https://firezone.docs.apiary.io/. To generate it locally run `DOC=1 mix test test/fz_http_web/controllers/json`. Co-authored-by: Jamil Bou Kheir <jamilbk@users.noreply.github.com>
This commit is contained in:
@@ -1,3 +1,3 @@
|
||||
[codespell]
|
||||
skip = ./erl_crash.dump,./apps/fz_http/erl_crash.dump,./cover,./vendor,./omnibus,*.json,yarn.lock,seeds.exs,./**/node_modules,./deps,./priv/static,./priv/plts,./**/priv/static,./.git,./docs/build,./_build
|
||||
skip = ./docs/docs/reference/api/*.mdx,./erl_crash.dump,./apps/fz_http/erl_crash.dump,./cover,./vendor,./omnibus,*.json,yarn.lock,seeds.exs,./**/node_modules,./deps,./priv/static,./priv/plts,./**/priv/static,./.git,./docs/build,./_build
|
||||
ignore-words-list = keypair,keypairs,iif,statics,wee
|
||||
|
||||
5
.github/workflows/publish_docs.yml
vendored
5
.github/workflows/publish_docs.yml
vendored
@@ -17,13 +17,10 @@ jobs:
|
||||
node-version: 16
|
||||
cache: 'yarn'
|
||||
cache-dependency-path: docs/yarn.lock
|
||||
# XXX: Add API docs generation here
|
||||
- run: |
|
||||
cd docs/
|
||||
yarn install --frozen-lockfile
|
||||
|
||||
# Uncomment below when REST API docs are done
|
||||
# yarn run docusaurus gen-api-docs rest_api
|
||||
|
||||
yarn build
|
||||
- name: Publish Latest Docs
|
||||
uses: JamesIves/github-pages-deploy-action@v4.4.1
|
||||
|
||||
@@ -25,6 +25,7 @@ defmodule FzHttpWeb do
|
||||
import FzHttpWeb.Gettext
|
||||
import Phoenix.LiveView.Controller
|
||||
import FzHttpWeb.ControllerHelpers
|
||||
import FzHttpWeb.DocHelpers
|
||||
|
||||
unquote(verified_routes())
|
||||
end
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
defmodule FzHttpWeb.JSON.ConfigurationController do
|
||||
@moduledoc api_doc: [title: "Configurations", group: "Configuration"]
|
||||
@moduledoc """
|
||||
This endpoint allows an administrator to manage Configurations.
|
||||
"""
|
||||
use FzHttpWeb, :controller
|
||||
|
||||
alias FzHttp.{Configurations.Configuration, Configurations}
|
||||
|
||||
action_fallback FzHttpWeb.JSON.FallbackController
|
||||
action_fallback(FzHttpWeb.JSON.FallbackController)
|
||||
|
||||
@doc api_doc: [summary: "Get Configuration"]
|
||||
def show(conn, _params) do
|
||||
configuration = Configurations.get_configuration!()
|
||||
render(conn, "show.json", configuration: configuration)
|
||||
end
|
||||
|
||||
@doc api_doc: [summary: "Update Configuration"]
|
||||
def update(conn, %{"configuration" => params}) do
|
||||
configuration = Configurations.get_configuration!()
|
||||
|
||||
|
||||
@@ -1,19 +1,22 @@
|
||||
defmodule FzHttpWeb.JSON.DeviceController do
|
||||
@moduledoc api_doc: [title: "Devices", group: "Devices"]
|
||||
@moduledoc """
|
||||
REST API Controller for Devices.
|
||||
This endpoint allows an administrator to manage Devices.
|
||||
"""
|
||||
|
||||
use FzHttpWeb, :controller
|
||||
|
||||
action_fallback FzHttpWeb.JSON.FallbackController
|
||||
action_fallback(FzHttpWeb.JSON.FallbackController)
|
||||
|
||||
alias FzHttp.Devices
|
||||
|
||||
@doc api_doc: [summary: "List all Devices"]
|
||||
def index(conn, _params) do
|
||||
devices = Devices.list_devices()
|
||||
render(conn, "index.json", devices: devices)
|
||||
end
|
||||
|
||||
@doc api_doc: [summary: "Create a Device"]
|
||||
def create(conn, %{"device" => device_params}) do
|
||||
with {:ok, device} <- Devices.create_device(device_params) do
|
||||
conn
|
||||
@@ -23,11 +26,13 @@ defmodule FzHttpWeb.JSON.DeviceController do
|
||||
end
|
||||
end
|
||||
|
||||
@doc api_doc: [summary: "Get Device by ID"]
|
||||
def show(conn, %{"id" => id}) do
|
||||
device = Devices.get_device!(id)
|
||||
render(conn, "show.json", device: device)
|
||||
end
|
||||
|
||||
@doc api_doc: [summary: "Update a Device"]
|
||||
def update(conn, %{"id" => id, "device" => device_params}) do
|
||||
device = Devices.get_device!(id)
|
||||
|
||||
@@ -36,6 +41,7 @@ defmodule FzHttpWeb.JSON.DeviceController do
|
||||
end
|
||||
end
|
||||
|
||||
@doc api_doc: [summary: "Delete a Device"]
|
||||
def delete(conn, %{"id" => id}) do
|
||||
device = Devices.get_device!(id)
|
||||
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
defmodule FzHttpWeb.JSON.RuleController do
|
||||
@moduledoc api_doc: [title: "Rules", group: "Rules"]
|
||||
@moduledoc """
|
||||
REST API Controller for Rules.
|
||||
This endpoint allows an adminisrator to manage Rules.
|
||||
"""
|
||||
|
||||
use FzHttpWeb, :controller
|
||||
|
||||
action_fallback FzHttpWeb.JSON.FallbackController
|
||||
action_fallback(FzHttpWeb.JSON.FallbackController)
|
||||
|
||||
alias FzHttp.Rules
|
||||
|
||||
@doc api_doc: [summary: "List all Rules"]
|
||||
def index(conn, _params) do
|
||||
# XXX: Add user-scoped rules
|
||||
rules = Rules.list_rules()
|
||||
render(conn, "index.json", rules: rules)
|
||||
end
|
||||
|
||||
@doc api_doc: [summary: "Create a Rule"]
|
||||
def create(conn, %{"rule" => rule_params}) do
|
||||
with {:ok, rule} <- Rules.create_rule(rule_params) do
|
||||
conn
|
||||
@@ -24,11 +26,13 @@ defmodule FzHttpWeb.JSON.RuleController do
|
||||
end
|
||||
end
|
||||
|
||||
@doc api_doc: [summary: "Get Rule by ID"]
|
||||
def show(conn, %{"id" => id}) do
|
||||
rule = Rules.get_rule!(id)
|
||||
render(conn, "show.json", rule: rule)
|
||||
end
|
||||
|
||||
@doc api_doc: [summary: "Update a Rule"]
|
||||
def update(conn, %{"id" => id, "rule" => rule_params}) do
|
||||
rule = Rules.get_rule!(id)
|
||||
|
||||
@@ -37,6 +41,7 @@ defmodule FzHttpWeb.JSON.RuleController do
|
||||
end
|
||||
end
|
||||
|
||||
@doc api_doc: [summary: "Delete a Rule"]
|
||||
def delete(conn, %{"id" => id}) do
|
||||
rule = Rules.get_rule!(id)
|
||||
|
||||
|
||||
@@ -1,16 +1,54 @@
|
||||
defmodule FzHttpWeb.JSON.UserController do
|
||||
use FzHttpWeb, :controller
|
||||
@moduledoc api_doc: [title: "Users", sidebar_position: 2, toc_max_heading_level: 4]
|
||||
@moduledoc """
|
||||
This endpoint allows an administrator to manage Users.
|
||||
|
||||
## Auto-Create Users from OpenID or SAML providers
|
||||
|
||||
You can set Configuration option `auto_create_users` to `true` to automatically create users
|
||||
from OpenID or SAML providers. Use it with care as anyone with access to the provider will be
|
||||
able to log-in to Firezone.
|
||||
|
||||
If `auto_create_users` is `false`, then you need to provision users with `password` attribute,
|
||||
otherwise they will have no means to log in.
|
||||
"""
|
||||
use FzHttpWeb, :controller
|
||||
alias FzHttp.Users
|
||||
alias FzHttp.Users.User
|
||||
|
||||
action_fallback FzHttpWeb.JSON.FallbackController
|
||||
action_fallback(FzHttpWeb.JSON.FallbackController)
|
||||
|
||||
@doc api_doc: [action: "List all Users"]
|
||||
def index(conn, _params) do
|
||||
users = Users.list_users()
|
||||
render(conn, "index.json", users: users)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Create a new User.
|
||||
|
||||
This endpoint is useful in two cases:
|
||||
|
||||
1. When [Local Authentication](/authenticate/local-auth/) is enabled (discouraged in
|
||||
production deployments), it allows an administrator to provision users with their passwords;
|
||||
2. When `auto_create_users` in the associated OpenID or SAML configuration is disabled,
|
||||
it allows an administrator to provision users with their emails beforehand, effectively
|
||||
whitelisting specific users for authentication.
|
||||
|
||||
If `auto_create_users` is `true` in the associated OpenID or SAML configuration, there is no need
|
||||
to provision users; they will be created automatically when they log in for the first time using
|
||||
the associated OpenID or SAML provider.
|
||||
|
||||
#### User Attributes
|
||||
|
||||
| Attribute | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `role` | `admin` or `unprivileged` (default) | No | User role. |
|
||||
| `email` | `string` | Yes | Email which will be used to identify the user. |
|
||||
| `password` | `string` | No | A password that can be used for login-password authentication. |
|
||||
| `password_confirmation` | `string` | -> | Is required when the `password` is set. |
|
||||
"""
|
||||
@doc api_doc: [action: "Create a User"]
|
||||
def create(conn, %{"user" => %{"role" => "admin"} = user_params}) do
|
||||
with {:ok, %User{} = user} <- Users.create_admin_user(user_params) do
|
||||
conn
|
||||
@@ -29,11 +67,16 @@ defmodule FzHttpWeb.JSON.UserController do
|
||||
end
|
||||
end
|
||||
|
||||
@doc api_doc: [summary: "Get User by ID or Email"]
|
||||
def show(conn, %{"id" => id_or_email}) do
|
||||
user = get_user_by_id_or_email(id_or_email)
|
||||
render(conn, "show.json", user: user)
|
||||
end
|
||||
|
||||
@doc """
|
||||
For details please see [Create a User](#create-a-user-post-v0users) section.
|
||||
"""
|
||||
@doc api_doc: [action: "Update a User"]
|
||||
def update(conn, %{"id" => id_or_email, "user" => user_params}) do
|
||||
user = get_user_by_id_or_email(id_or_email)
|
||||
|
||||
@@ -42,6 +85,7 @@ defmodule FzHttpWeb.JSON.UserController do
|
||||
end
|
||||
end
|
||||
|
||||
@doc api_doc: [summary: "Delete a User"]
|
||||
def delete(conn, %{"id" => id_or_email}) do
|
||||
user = get_user_by_id_or_email(id_or_email)
|
||||
|
||||
|
||||
17
apps/fz_http/lib/fz_http_web/doc_helpers.ex
Normal file
17
apps/fz_http/lib/fz_http_web/doc_helpers.ex
Normal file
@@ -0,0 +1,17 @@
|
||||
defmodule FzHttpWeb.DocHelpers do
|
||||
def group(name, children) do
|
||||
{:group, {name, children}}
|
||||
end
|
||||
|
||||
def attr(name, type, opts) do
|
||||
required? = Keyword.get(opts, :required?, false)
|
||||
description = Keyword.get(opts, :description)
|
||||
{:attr, {name, type, required?, description}}
|
||||
end
|
||||
|
||||
def type(type), do: {:type, type}
|
||||
def type(type, example), do: {:type, {type, example}}
|
||||
|
||||
def enum_type(type, values, example \\ nil),
|
||||
do: {:type, {:enum, type, values, example || List.first(values)}}
|
||||
end
|
||||
@@ -95,7 +95,8 @@ defmodule FzHttp.MixProject do
|
||||
{:telemetry, "~> 1.0"},
|
||||
{:plug_cowboy, "~> 2.5"},
|
||||
{:credo, "~> 1.5", only: [:dev, :test], runtime: false},
|
||||
{:remote_ip, "~> 1.0"}
|
||||
{:remote_ip, "~> 1.0"},
|
||||
{:bureaucrat, "~> 0.2.9", only: :test}
|
||||
]
|
||||
end
|
||||
|
||||
|
||||
@@ -4,7 +4,10 @@ defmodule FzHttpWeb.JSON.ConfigurationControllerTest do
|
||||
|
||||
describe "GET /v0/configuration" do
|
||||
test "renders configuration" do
|
||||
conn = get(authed_conn(), ~p"/v0/configuration")
|
||||
conn =
|
||||
get(authed_conn(), ~p"/v0/configuration")
|
||||
|> doc()
|
||||
|
||||
assert json_response(conn, 200)["data"]
|
||||
end
|
||||
|
||||
@@ -98,7 +101,10 @@ defmodule FzHttpWeb.JSON.ConfigurationControllerTest do
|
||||
}
|
||||
|
||||
test "updates fields when data is valid" do
|
||||
conn = put(authed_conn(), ~p"/v0/configuration", configuration: @first_config)
|
||||
conn =
|
||||
put(authed_conn(), ~p"/v0/configuration", configuration: @first_config)
|
||||
|> doc()
|
||||
|
||||
assert @first_config = json_response(conn, 200)["data"]
|
||||
|
||||
conn = put(authed_conn(), ~p"/v0/configuration", configuration: @second_config)
|
||||
|
||||
@@ -25,14 +25,18 @@ defmodule FzHttpWeb.JSON.DeviceControllerTest do
|
||||
describe "GET /v0/devices/:id" do
|
||||
test "shows device" do
|
||||
id = device().id
|
||||
conn = get(authed_conn(), ~p"/v0/devices/#{id}")
|
||||
|
||||
conn =
|
||||
get(authed_conn(), ~p"/v0/devices/#{id}")
|
||||
|> doc()
|
||||
|
||||
assert %{"id" => ^id} = json_response(conn, 200)["data"]
|
||||
end
|
||||
|
||||
test "renders 404 for device not found" do
|
||||
assert_error_sent 404, fn ->
|
||||
assert_error_sent(404, fn ->
|
||||
get(authed_conn(), ~p"/v0/devices/003da73d-2dd9-4492-8136-3282843545e8")
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
test "renders 401 for missing authorization header" do
|
||||
@@ -52,6 +56,7 @@ defmodule FzHttpWeb.JSON.DeviceControllerTest do
|
||||
post(authed_conn(), ~p"/v0/devices",
|
||||
device: Map.merge(@params, %{"user_id" => unprivileged_user.id})
|
||||
)
|
||||
|> doc()
|
||||
|
||||
assert @params = json_response(conn, 201)["data"]
|
||||
end
|
||||
@@ -84,11 +89,14 @@ defmodule FzHttpWeb.JSON.DeviceControllerTest do
|
||||
end
|
||||
end
|
||||
|
||||
describe "[authed] PUT /v0/devices/:id" do
|
||||
describe "PUT /v0/devices/:id" do
|
||||
test "updates device" do
|
||||
device = device()
|
||||
|
||||
conn = put(authed_conn(), ~p"/v0/devices/#{device}", device: @params)
|
||||
conn =
|
||||
put(authed_conn(), ~p"/v0/devices/#{device}", device: @params)
|
||||
|> doc()
|
||||
|
||||
assert @params = json_response(conn, 200)["data"]
|
||||
|
||||
conn = get(conn, ~p"/v0/devices/#{device}")
|
||||
@@ -96,9 +104,9 @@ defmodule FzHttpWeb.JSON.DeviceControllerTest do
|
||||
end
|
||||
|
||||
test "renders 404 for device not found" do
|
||||
assert_error_sent 404, fn ->
|
||||
assert_error_sent(404, fn ->
|
||||
put(authed_conn(), ~p"/v0/devices/003da73d-2dd9-4492-8136-3282843545e8", device: %{})
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
test "renders 401 for missing authorization header" do
|
||||
@@ -111,7 +119,9 @@ defmodule FzHttpWeb.JSON.DeviceControllerTest do
|
||||
test "lists all devices" do
|
||||
devices = for _i <- 1..5, do: device()
|
||||
|
||||
conn = get(authed_conn(), ~p"/v0/devices")
|
||||
conn =
|
||||
get(authed_conn(), ~p"/v0/devices")
|
||||
|> doc()
|
||||
|
||||
assert json_response(conn, 200)["data"]
|
||||
|> Enum.map(& &1["id"])
|
||||
@@ -131,18 +141,21 @@ defmodule FzHttpWeb.JSON.DeviceControllerTest do
|
||||
test "deletes device" do
|
||||
device = device()
|
||||
|
||||
conn = delete(authed_conn(), ~p"/v0/devices/#{device}")
|
||||
conn =
|
||||
delete(authed_conn(), ~p"/v0/devices/#{device}")
|
||||
|> doc()
|
||||
|
||||
assert response(conn, 204)
|
||||
|
||||
assert_error_sent 404, fn ->
|
||||
assert_error_sent(404, fn ->
|
||||
get(conn, ~p"/v0/devices/#{device}")
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
test "renders 404 for device not found" do
|
||||
assert_error_sent 404, fn ->
|
||||
assert_error_sent(404, fn ->
|
||||
delete(authed_conn(), ~p"/v0/devices/003da73d-2dd9-4492-8136-3282843545e8")
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
test "renders 401 for missing authorization header" do
|
||||
|
||||
@@ -22,14 +22,18 @@ defmodule FzHttpWeb.JSON.RuleControllerTest do
|
||||
describe "GET /v0/rules/:id" do
|
||||
test "shows rule" do
|
||||
id = rule().id
|
||||
conn = get(authed_conn(), ~p"/v0/rules/#{id}")
|
||||
|
||||
conn =
|
||||
get(authed_conn(), ~p"/v0/rules/#{id}")
|
||||
|> doc()
|
||||
|
||||
assert %{"id" => ^id} = json_response(conn, 200)["data"]
|
||||
end
|
||||
|
||||
test "renders 404 for rule not found" do
|
||||
assert_error_sent 404, fn ->
|
||||
assert_error_sent(404, fn ->
|
||||
get(authed_conn(), ~p"/v0/rules/003da73d-2dd9-4492-8136-3282843545e8")
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
test "renders 401 for missing authorization header" do
|
||||
@@ -46,6 +50,7 @@ defmodule FzHttpWeb.JSON.RuleControllerTest do
|
||||
|
||||
conn =
|
||||
post(conn, ~p"/v0/rules", rule: Map.merge(@accept_rule_params, %{"user_id" => user.id}))
|
||||
|> doc()
|
||||
|
||||
assert @accept_rule_params = json_response(conn, 201)["data"]
|
||||
end
|
||||
@@ -79,7 +84,11 @@ defmodule FzHttpWeb.JSON.RuleControllerTest do
|
||||
describe "PUT /v0/rules/:id" do
|
||||
test "updates accept rule when valid" do
|
||||
rule = rule()
|
||||
conn = put(authed_conn(), ~p"/v0/rules/#{rule}", rule: @accept_rule_params)
|
||||
|
||||
conn =
|
||||
put(authed_conn(), ~p"/v0/rules/#{rule}", rule: @accept_rule_params)
|
||||
|> doc()
|
||||
|
||||
assert @accept_rule_params = json_response(conn, 200)["data"]
|
||||
|
||||
conn = get(conn, ~p"/v0/rules/#{rule}")
|
||||
@@ -103,9 +112,9 @@ defmodule FzHttpWeb.JSON.RuleControllerTest do
|
||||
end
|
||||
|
||||
test "renders 404 for rule not found" do
|
||||
assert_error_sent 404, fn ->
|
||||
assert_error_sent(404, fn ->
|
||||
put(authed_conn(), ~p"/v0/rules/003da73d-2dd9-4492-8136-3282843545e8", rule: %{})
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
test "renders 401 for missing authorization header" do
|
||||
@@ -117,7 +126,10 @@ defmodule FzHttpWeb.JSON.RuleControllerTest do
|
||||
describe "GET /v0/rules" do
|
||||
test "lists rules" do
|
||||
for i <- 1..5, do: rule(%{destination: "10.3.2.#{i}"})
|
||||
conn = get(authed_conn(), ~p"/v0/rules")
|
||||
|
||||
conn =
|
||||
get(authed_conn(), ~p"/v0/rules")
|
||||
|> doc()
|
||||
|
||||
actual =
|
||||
Rules.list_rules()
|
||||
@@ -141,18 +153,22 @@ defmodule FzHttpWeb.JSON.RuleControllerTest do
|
||||
describe "DELETE /v0/rules/:id" do
|
||||
test "deletes rule" do
|
||||
rule = rule()
|
||||
conn = delete(authed_conn(), ~p"/v0/rules/#{rule}")
|
||||
|
||||
conn =
|
||||
delete(authed_conn(), ~p"/v0/rules/#{rule}")
|
||||
|> doc()
|
||||
|
||||
assert response(conn, 204)
|
||||
|
||||
assert_error_sent 404, fn ->
|
||||
assert_error_sent(404, fn ->
|
||||
get(authed_conn(), ~p"/v0/rules/#{rule}")
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
test "renders 404 for rule not found" do
|
||||
assert_error_sent 404, fn ->
|
||||
assert_error_sent(404, fn ->
|
||||
delete(authed_conn(), ~p"/v0/rules/003da73d-2dd9-4492-8136-3282843545e8")
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
test "renders 401 for missing authorization header" do
|
||||
|
||||
@@ -20,9 +20,11 @@ defmodule FzHttpWeb.JSON.UserControllerTest do
|
||||
|
||||
describe "GET /v0/users" do
|
||||
test "lists all users" do
|
||||
for _i <- 1..5, do: user()
|
||||
for _i <- 1..3, do: user()
|
||||
|
||||
conn = get(authed_conn(), ~p"/v0/users")
|
||||
conn =
|
||||
get(authed_conn(), ~p"/v0/users")
|
||||
|> doc()
|
||||
|
||||
actual =
|
||||
Users.list_users()
|
||||
@@ -39,20 +41,44 @@ defmodule FzHttpWeb.JSON.UserControllerTest do
|
||||
|
||||
test "renders 401 for missing authorization header" do
|
||||
conn = get(unauthed_conn(), ~p"/v0/users")
|
||||
|
||||
assert json_response(conn, 401)["errors"] == %{"auth" => "unauthenticated"}
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST /v0/users" do
|
||||
test "can create unprivileged user with password" do
|
||||
params = %{
|
||||
"email" => "new-user@test",
|
||||
"role" => "unprivileged",
|
||||
"password" => "test1234test",
|
||||
"password_confirmation" => "test1234test"
|
||||
}
|
||||
|
||||
conn =
|
||||
post(authed_conn(), ~p"/v0/users", user: params)
|
||||
|> doc()
|
||||
|
||||
assert json_response(conn, 201)["data"]["role"] == "unprivileged"
|
||||
end
|
||||
|
||||
test "can create unprivileged user" do
|
||||
params = %{"email" => "new-user@test", "role" => "unprivileged"}
|
||||
conn = post(authed_conn(), ~p"/v0/users", user: params)
|
||||
|
||||
conn =
|
||||
post(authed_conn(), ~p"/v0/users", user: params)
|
||||
|> doc(example_description: "Provision an unprivileged OpenID User")
|
||||
|
||||
assert json_response(conn, 201)["data"]["role"] == "unprivileged"
|
||||
end
|
||||
|
||||
test "can create admin user" do
|
||||
params = %{"email" => "new-user@test", "role" => "admin"}
|
||||
conn = post(authed_conn(), ~p"/v0/users", user: params)
|
||||
|
||||
conn =
|
||||
post(authed_conn(), ~p"/v0/users", user: params)
|
||||
|> doc(example_description: "Provision an admin OpenID User")
|
||||
|
||||
assert json_response(conn, 201)["data"]["role"] == "admin"
|
||||
end
|
||||
|
||||
@@ -68,7 +94,9 @@ defmodule FzHttpWeb.JSON.UserControllerTest do
|
||||
end
|
||||
|
||||
test "renders errors when data is invalid" do
|
||||
conn = post(authed_conn(), ~p"/v0/users", user: @invalid_attrs)
|
||||
conn =
|
||||
post(authed_conn(), ~p"/v0/users", user: @invalid_attrs)
|
||||
|> doc(example_description: "Error due to invalid parameters")
|
||||
|
||||
assert json_response(conn, 422)["errors"] == %{
|
||||
"password" => [
|
||||
@@ -84,16 +112,24 @@ defmodule FzHttpWeb.JSON.UserControllerTest do
|
||||
end
|
||||
end
|
||||
|
||||
describe "PUT /v0/users/:id" do
|
||||
describe "PUT /v0/users/:id_or_email" do
|
||||
test "returns user that was updated via email" do
|
||||
user = user(%{role: :unprivileged})
|
||||
conn = put(authed_conn(), ~p"/v0/users/#{user.email}", user: %{})
|
||||
|
||||
conn =
|
||||
put(authed_conn(), ~p"/v0/users/#{user.email}", user: %{})
|
||||
|> doc(example_description: "Update by email")
|
||||
|
||||
assert json_response(conn, 200)["data"]["id"] == user.id
|
||||
end
|
||||
|
||||
test "returns user that was updated via id" do
|
||||
user = user(%{role: :unprivileged})
|
||||
conn = put(authed_conn(), ~p"/v0/users/#{user}", user: %{})
|
||||
|
||||
conn =
|
||||
put(authed_conn(), ~p"/v0/users/#{user}", user: %{})
|
||||
|> doc(example_description: "Update by ID")
|
||||
|
||||
assert json_response(conn, 200)["data"]["id"] == user.id
|
||||
end
|
||||
|
||||
@@ -149,7 +185,9 @@ defmodule FzHttpWeb.JSON.UserControllerTest do
|
||||
test "can update own role" do
|
||||
conn = authed_conn()
|
||||
user = conn.private.guardian_default_resource
|
||||
|
||||
conn = put(conn, ~p"/v0/users/#{user}", user: %{role: :unprivileged})
|
||||
|
||||
assert json_response(conn, 200)["data"]["role"] == "unprivileged"
|
||||
end
|
||||
|
||||
@@ -174,9 +212,9 @@ defmodule FzHttpWeb.JSON.UserControllerTest do
|
||||
end
|
||||
|
||||
test "renders 404 for user not found" do
|
||||
assert_error_sent 404, fn ->
|
||||
assert_error_sent(404, fn ->
|
||||
put(authed_conn(), ~p"/v0/users/003da73d-2dd9-4492-8136-3282843545e8", user: %{})
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
test "renders 401 for missing authorization header" do
|
||||
@@ -189,21 +227,27 @@ defmodule FzHttpWeb.JSON.UserControllerTest do
|
||||
test "gets user by id" do
|
||||
conn = authed_conn()
|
||||
user = conn.private.guardian_default_resource
|
||||
|
||||
conn = get(conn, ~p"/v0/users/#{user}")
|
||||
|
||||
assert json_response(conn, 200)["data"]["id"] == user.id
|
||||
end
|
||||
|
||||
test "gets user by email" do
|
||||
conn = authed_conn()
|
||||
user = conn.private.guardian_default_resource
|
||||
conn = get(conn, ~p"/v0/users/#{user.email}")
|
||||
|
||||
conn =
|
||||
get(conn, ~p"/v0/users/#{user.email}")
|
||||
|> doc(example_description: "An email can be used instead of ID.")
|
||||
|
||||
assert json_response(conn, 200)["data"]["id"] == user.id
|
||||
end
|
||||
|
||||
test "renders 404 for user not found" do
|
||||
assert_error_sent 404, fn ->
|
||||
assert_error_sent(404, fn ->
|
||||
get(authed_conn(), ~p"/v0/users/003da73d-2dd9-4492-8136-3282843545e8")
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
test "renders 401 for missing authorization header" do
|
||||
@@ -215,28 +259,36 @@ defmodule FzHttpWeb.JSON.UserControllerTest do
|
||||
describe "DELETE /v0/users/:id" do
|
||||
test "deletes user by id" do
|
||||
user = user(%{role: :unprivileged})
|
||||
conn = delete(authed_conn(), ~p"/v0/users/#{user}")
|
||||
|
||||
conn =
|
||||
delete(authed_conn(), ~p"/v0/users/#{user}")
|
||||
|> doc()
|
||||
|
||||
assert response(conn, 204)
|
||||
|
||||
assert_error_sent 404, fn ->
|
||||
assert_error_sent(404, fn ->
|
||||
get(conn, ~p"/v0/users/#{user}")
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
test "deletes user by email" do
|
||||
user = user(%{role: :unprivileged})
|
||||
conn = delete(authed_conn(), ~p"/v0/users/#{user.email}")
|
||||
|
||||
conn =
|
||||
delete(authed_conn(), ~p"/v0/users/#{user.email}")
|
||||
|> doc(example_description: "An email can be used instead of ID.")
|
||||
|
||||
assert response(conn, 204)
|
||||
|
||||
assert_error_sent 404, fn ->
|
||||
assert_error_sent(404, fn ->
|
||||
get(conn, ~p"/v0/users/#{user}")
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
test "renders 404 for user not found" do
|
||||
assert_error_sent 404, fn ->
|
||||
assert_error_sent(404, fn ->
|
||||
delete(authed_conn(), ~p"/v0/users/003da73d-2dd9-4492-8136-3282843545e8")
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
test "renders 401 for missing authorization header" do
|
||||
|
||||
@@ -28,6 +28,7 @@ defmodule FzHttpWeb.ApiCase do
|
||||
import Plug.Conn
|
||||
import Phoenix.ConnTest
|
||||
import FzHttp.TestHelpers
|
||||
import Bureaucrat.Helpers
|
||||
|
||||
use FzHttpWeb, :verified_routes
|
||||
|
||||
|
||||
223
apps/fz_http/test/support/api_doc_formatter.ex
Normal file
223
apps/fz_http/test/support/api_doc_formatter.ex
Normal file
@@ -0,0 +1,223 @@
|
||||
defmodule Firezone.DocusaurusWriter do
|
||||
@keep_req_headers ["authorization"]
|
||||
@keep_resp_headers ["content-type", "location"]
|
||||
|
||||
def write(conns, path) do
|
||||
File.mkdir_p!(path)
|
||||
routes = Phoenix.Router.routes(List.first(conns).private.phoenix_router)
|
||||
|
||||
conns
|
||||
|> Enum.group_by(& &1.private.phoenix_controller)
|
||||
|> Enum.map(fn {controller, conns} ->
|
||||
{module_doc, module_assigns, function_docs} = fetch_module_docs!(controller)
|
||||
|
||||
title =
|
||||
Keyword.get_lazy(module_assigns, :title, fn ->
|
||||
controller
|
||||
|> to_string()
|
||||
|> String.split(".")
|
||||
|> List.last()
|
||||
|> String.replace_trailing("Controller", "")
|
||||
end)
|
||||
|
||||
path = Path.join(path, "#{String.downcase(title)}.mdx")
|
||||
file = File.open!(path, [:write, :utf8])
|
||||
|
||||
w!(file, "---")
|
||||
w!(file, docusaurus_header(module_assigns))
|
||||
w!(file, "---")
|
||||
w!(file, "\n")
|
||||
w!(file, module_doc)
|
||||
w!(file, "## API Documentation")
|
||||
|
||||
conns
|
||||
|> Enum.group_by(& &1.private.phoenix_action)
|
||||
# We order actions nicely
|
||||
|> Enum.sort_by(fn
|
||||
{:index, _} -> 1
|
||||
{:show, _} -> 3
|
||||
{:create, _} -> 2
|
||||
{:update, _} -> 4
|
||||
{:delete, _} -> 5
|
||||
{_other, _} -> 1000
|
||||
end)
|
||||
|> Enum.map(fn {action, conns} ->
|
||||
{path, verb} = fetch_route!(routes, controller, action)
|
||||
{function_doc, function_assigns} = get_function_docs(function_docs, action)
|
||||
|
||||
title = maybe_wrap(function_assigns[:action], "#{verb} #{path}")
|
||||
|
||||
w!(file, "### #{title}")
|
||||
w!(file, "\n")
|
||||
w!(file, function_doc)
|
||||
|
||||
uri_params = build_uri_params(path)
|
||||
|
||||
write_examples(file, conns, path, uri_params)
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
defp maybe_wrap(nil, title), do: title
|
||||
defp maybe_wrap(action_assign, title), do: "#{action_assign} [`#{title}`]"
|
||||
|
||||
defp docusaurus_header(assigns) do
|
||||
assigns
|
||||
|> Enum.map_join("\n", fn {key, value} ->
|
||||
"#{key}: #{value}"
|
||||
end)
|
||||
end
|
||||
|
||||
defp fetch_route!(routes, controller, controller_action) do
|
||||
%{path: path, verb: verb} =
|
||||
Enum.find(routes, fn
|
||||
%{plug: ^controller, plug_opts: ^controller_action} -> true
|
||||
_other -> false
|
||||
end)
|
||||
|
||||
path = String.replace(path, ~r|:([^/]*)|, "{\\1}")
|
||||
verb = verb |> to_string() |> String.upcase()
|
||||
|
||||
{path, verb}
|
||||
end
|
||||
|
||||
defp fetch_module_docs!(controller) do
|
||||
case Code.fetch_docs(controller) do
|
||||
{:docs_v1, _, _, _, module_doc, %{api_doc: module_assigns}, function_docs} ->
|
||||
{get_doc(module_doc), module_assigns, function_docs}
|
||||
|
||||
{:error, :module_not_found} ->
|
||||
raise "No module #{controller}"
|
||||
end
|
||||
end
|
||||
|
||||
defp get_doc(md) when is_map(md), do: Map.get(md, "en")
|
||||
defp get_doc(_md), do: nil
|
||||
|
||||
defp get_function_docs(function_docs, function) do
|
||||
function_docs
|
||||
|> Enum.find(fn
|
||||
{{:function, ^function, _}, _, _, _, _} -> true
|
||||
{{:function, _function, _}, _, _, _, _} -> false
|
||||
end)
|
||||
|> case do
|
||||
{_, _, _, :none, %{api_doc: function_assigns}} ->
|
||||
{nil, function_assigns}
|
||||
|
||||
{_, _, _, doc, %{api_doc: function_assigns}} ->
|
||||
{get_doc(doc), function_assigns}
|
||||
|
||||
{_, _, _, doc, _chunks} ->
|
||||
{get_doc(doc), %{}}
|
||||
|
||||
_other ->
|
||||
{nil, %{}}
|
||||
end
|
||||
end
|
||||
|
||||
defp build_uri_params(path) do
|
||||
Regex.scan(~r/{([^}]*)}/, path)
|
||||
|> Enum.map(fn [_, param] ->
|
||||
param
|
||||
end)
|
||||
end
|
||||
|
||||
defp write_examples(file, conns, path, uri_params) do
|
||||
conns
|
||||
|> Enum.sort_by(& &1.status)
|
||||
|> Enum.each(fn conn ->
|
||||
example_description = conn.assigns.bureaucrat_opts[:example_description] || "Example"
|
||||
w!(file, "#### #{example_description}")
|
||||
|
||||
w_req_uri_params!(file, conn, uri_params)
|
||||
|
||||
w!(
|
||||
file,
|
||||
"""
|
||||
```bash
|
||||
$ curl -i \\
|
||||
-X #{conn.method} "https://{firezone_host}#{path}" \\
|
||||
-H 'Content-Type: application/json' \\
|
||||
"""
|
||||
|> String.trim_trailing()
|
||||
)
|
||||
|
||||
maybe_w!(file, b_req_headers(conn))
|
||||
maybe_w!(file, b_req_body(conn.body_params))
|
||||
|
||||
w!(file, "")
|
||||
|
||||
w!(file, "HTTP/1.1 #{conn.status}")
|
||||
maybe_w!(file, b_resp_headers(conn))
|
||||
maybe_w!(file, b_resp_body(conn.resp_body))
|
||||
w!(file, "```")
|
||||
end)
|
||||
end
|
||||
|
||||
defp w_req_uri_params!(_file, _conn, []), do: :ok
|
||||
|
||||
defp w_req_uri_params!(file, conn, params) do
|
||||
w!(file, "**URI Parameters:**\n")
|
||||
|
||||
Enum.each(params, fn param ->
|
||||
w!(file, i(1, "- `#{param}`: `#{conn.params[param]}`"))
|
||||
end)
|
||||
end
|
||||
|
||||
defp b_req_headers(conn) do
|
||||
for {key, value} <- conn.req_headers, key in @keep_req_headers do
|
||||
case {key, value} do
|
||||
{"authorization", "bearer " <> _} ->
|
||||
i(1, "-H 'Authorization: Bearer {api_token}' \\")
|
||||
|
||||
{key, value} ->
|
||||
i(1, "-H '#{camelize_header_key(key)}: #{value}' \\")
|
||||
end
|
||||
end
|
||||
|> Enum.join("\n")
|
||||
end
|
||||
|
||||
defp b_req_body(params) when params == %{}, do: ""
|
||||
|
||||
defp b_req_body(params) do
|
||||
i(1, "--data-binary @- << EOF\n#{Jason.encode!(params, pretty: true)}'\nEOF")
|
||||
end
|
||||
|
||||
defp b_resp_headers(conn) do
|
||||
for {key, value} <- conn.resp_headers, key in @keep_resp_headers do
|
||||
"#{camelize_header_key(key)}: #{value}"
|
||||
end
|
||||
|> Enum.join("\n")
|
||||
end
|
||||
|
||||
defp b_resp_body(resp_body) do
|
||||
case Jason.decode(resp_body) do
|
||||
{:ok, map} ->
|
||||
"\n" <> Jason.encode!(map, pretty: true)
|
||||
|
||||
_error ->
|
||||
resp_body
|
||||
end
|
||||
end
|
||||
|
||||
defp camelize_header_key(key) do
|
||||
key
|
||||
|> String.split("-")
|
||||
|> Enum.map_join("-", fn
|
||||
<<first::utf8, rest::binary>> -> String.upcase(<<first::utf8>>) <> rest
|
||||
other -> other
|
||||
end)
|
||||
end
|
||||
|
||||
defp i(level, text) do
|
||||
String.duplicate(" ", level) <> text
|
||||
end
|
||||
|
||||
defp maybe_w!(_file, ""), do: :ok
|
||||
defp maybe_w!(_file, nil), do: :ok
|
||||
defp maybe_w!(file, text), do: w!(file, text)
|
||||
|
||||
defp w!(file, content) do
|
||||
IO.puts(file, content)
|
||||
end
|
||||
end
|
||||
@@ -1,4 +1,9 @@
|
||||
Ecto.Adapters.SQL.Sandbox.mode(FzHttp.Repo, :manual)
|
||||
Mox.defmock(OpenIDConnect.Mock, for: OpenIDConnect.MockBehaviour)
|
||||
|
||||
ExUnit.start()
|
||||
Ecto.Adapters.SQL.Sandbox.mode(FzHttp.Repo, :manual)
|
||||
Bureaucrat.start(
|
||||
writer: Firezone.DocusaurusWriter,
|
||||
default_path: "../../docs/docs/reference/api"
|
||||
)
|
||||
|
||||
ExUnit.start(formatters: [ExUnit.CLIFormatter, Bureaucrat.Formatter])
|
||||
|
||||
@@ -64,3 +64,5 @@ config :fz_vpn,
|
||||
wg_adapter: FzVpn.Interface.WGAdapter.Sandbox
|
||||
|
||||
config :argon2_elixir, t_cost: 1, m_cost: 8
|
||||
|
||||
config :bureaucrat, :json_library, Jason
|
||||
|
||||
4
docs/docs/reference/api/README.md
Normal file
4
docs/docs/reference/api/README.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: REST API
|
||||
sidebar_position: 10
|
||||
---
|
||||
145
docs/docs/reference/api/configurations.mdx
Normal file
145
docs/docs/reference/api/configurations.mdx
Normal file
@@ -0,0 +1,145 @@
|
||||
---
|
||||
title: Configurations
|
||||
group: Configuration
|
||||
---
|
||||
|
||||
|
||||
This endpoint allows an administrator to manage Configurations.
|
||||
|
||||
## API Documentation
|
||||
### GET /v0/configuration
|
||||
|
||||
|
||||
|
||||
#### Example
|
||||
```bash
|
||||
$ curl -i \
|
||||
-X GET "https://{firezone_host}/v0/configuration" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Authorization: Bearer {api_token}' \
|
||||
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json; charset=utf-8
|
||||
|
||||
{
|
||||
"data": {
|
||||
"allow_unprivileged_device_configuration": true,
|
||||
"allow_unprivileged_device_management": true,
|
||||
"default_client_allowed_ips": "0.0.0.0/0,::/0",
|
||||
"default_client_dns": "1.1.1.1,1.0.0.1",
|
||||
"default_client_endpoint": "localhost:51820",
|
||||
"default_client_mtu": 1280,
|
||||
"default_client_persistent_keepalive": 25,
|
||||
"disable_vpn_on_oidc_error": false,
|
||||
"id": "8f17e873-de8a-4264-8567-39e450870306",
|
||||
"inserted_at": "2023-01-13T06:00:43.178729Z",
|
||||
"local_auth_enabled": true,
|
||||
"logo": null,
|
||||
"openid_connect_providers": [],
|
||||
"saml_identity_providers": [],
|
||||
"updated_at": "2023-01-13T06:00:43.178729Z",
|
||||
"vpn_session_duration": 0
|
||||
}
|
||||
}
|
||||
```
|
||||
### PATCH /v0/configuration
|
||||
|
||||
|
||||
|
||||
#### Example
|
||||
```bash
|
||||
$ curl -i \
|
||||
-X PUT "https://{firezone_host}/v0/configuration" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Authorization: Bearer {api_token}' \
|
||||
--data-binary @- << EOF
|
||||
{
|
||||
"configuration": {
|
||||
"allow_unprivileged_device_configuration": false,
|
||||
"allow_unprivileged_device_management": false,
|
||||
"default_client_allowed_ips": "1.1.1.1,2.2.2.2",
|
||||
"default_client_dns": "1.1.1.1",
|
||||
"default_client_endpoint": "new-endpoint",
|
||||
"default_client_mtu": 1100,
|
||||
"default_client_persistent_keepalive": 1,
|
||||
"disable_vpn_on_oidc_error": true,
|
||||
"local_auth_enabled": false,
|
||||
"openid_connect_providers": [
|
||||
{
|
||||
"auto_create_users": false,
|
||||
"client_id": "test-id",
|
||||
"client_secret": "test-secret",
|
||||
"discovery_document_uri": "https://accounts.google.com/.well-known/openid-configuration",
|
||||
"id": "google",
|
||||
"label": "google",
|
||||
"redirect_uri": "https://invalid",
|
||||
"response_type": "response-type",
|
||||
"scope": "test-scope"
|
||||
}
|
||||
],
|
||||
"saml_identity_providers": [
|
||||
{
|
||||
"auto_create_users": false,
|
||||
"base_url": "https://saml",
|
||||
"id": "okta",
|
||||
"label": "okta",
|
||||
"metadata": "<?xml version=\"1.0\"?>\n<md:EntityDescriptor xmlns=\"urn:oasis:names:tc:SAML:2.0:metadata\" xmlns:md=\"urn:oasis:names:tc:SAML:2.0:metadata\" xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\" entityID=\"http://localhost:8080/realms/firezone\">\n <md:IDPSSODescriptor WantAuthnRequestsSigned=\"true\" protocolSupportEnumeration=\"urn:oasis:names:tc:SAML:2.0:protocol\">\n <md:KeyDescriptor use=\"signing\">\n <ds:KeyInfo>\n <ds:KeyName>pdSMtx2s3RVVhxg_qJOjHhlZhwZk6JiBMiSm5PEgjkA</ds:KeyName>\n <ds:X509Data>\n <ds:X509Certificate>MIICnzCCAYcCBgGD18ZU8TANBgkqhkiG9w0BAQsFADATMREwDwYDVQQDDAhmaXJlem9uZTAeFw0yMjEwMTQxODMyMjJaFw0zMjEwMTQxODM0MDJaMBMxETAPBgNVBAMMCGZpcmV6b25lMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAur5Cb0jrDJbMwr96WWE+z9CjDg0A/uRkaB4loRqkmu3A2fQGsS6CP7F7lQWMJmpzvBgkNtB69toO2sgx1u1fhpIJBZ0uSHF5gnzQAivgVxInvkMKRTRSkpMbhObiDHZnEGI2+Ly+8iV8IvprdrbDgm52u4conam0H1PewUKkHulrVQ+ImFuEWAjKCRSqpUG2F1eRkA0YpqB09x0CZAOOoucwTsBYj/ZAz3dUXhYIENAF7v0ykvzGOCAyOZIn1uYQc7jvWpwoI8qQdL45phj2FLoFlght3tlZV8IG5hsXrE6rg7Ufqvv8xyGltrOMKj/jEFEunagZOUjkypDp36b8cwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQBEZKLLr66GB3NxqXGTMl0PvTDNB9GdyShQHaJYjeeUQnEXixjlAVrOq/txEBKjhGUcqyFELoNuwcxxV1iHA5oXhCoqYmnp9T/ftmXPDT3c49PBABHgLJaFOKYTpVx1YjP7mA44X1ijLZmgboIeeFNerVNHIzR9BsxcloQlB0r9QfC14rsuXo6QD3QnaVI8wDgWXQHqpcwLFqvehXdNvMFniRvX2qBNU8E0FPoMaZ1C3n2nssLcVZ+C4ghq6YoAG+wLGY7XE8+v5rnYGDpGpfgr2wdefn6tryFq3PyGqA8ThjARESRRQG9kI/RlNX7qCnP/8/7JQ4wLdfz5C25uhakP</ds:X509Certificate>\n </ds:X509Data>\n </ds:KeyInfo>\n </md:KeyDescriptor>\n <md:ArtifactResolutionService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:SOAP\" Location=\"http://localhost:8080/realms/firezone/protocol/saml/resolve\" index=\"0\"/>\n <md:SingleLogoutService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST\" Location=\"http://localhost:8080/realms/firezone/protocol/saml\"/>\n <md:SingleLogoutService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect\" Location=\"http://localhost:8080/realms/firezone/protocol/saml\"/>\n <md:SingleLogoutService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact\" Location=\"http://localhost:8080/realms/firezone/protocol/saml\"/>\n <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat>\n <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</md:NameIDFormat>\n <md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</md:NameIDFormat>\n <md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</md:NameIDFormat>\n <md:SingleSignOnService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST\" Location=\"http://localhost:8080/realms/firezone/protocol/saml\"/>\n <md:SingleSignOnService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect\" Location=\"http://localhost:8080/realms/firezone/protocol/saml\"/>\n <md:SingleSignOnService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:SOAP\" Location=\"http://localhost:8080/realms/firezone/protocol/saml\"/>\n <md:SingleSignOnService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact\" Location=\"http://localhost:8080/realms/firezone/protocol/saml\"/>\n </md:IDPSSODescriptor>\n</md:EntityDescriptor>\n",
|
||||
"sign_metadata": false,
|
||||
"sign_requests": false,
|
||||
"signed_assertion_in_resp": false,
|
||||
"signed_envelopes_in_resp": false
|
||||
}
|
||||
],
|
||||
"vpn_session_duration": 100
|
||||
}
|
||||
}'
|
||||
EOF
|
||||
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json; charset=utf-8
|
||||
|
||||
{
|
||||
"data": {
|
||||
"allow_unprivileged_device_configuration": false,
|
||||
"allow_unprivileged_device_management": false,
|
||||
"default_client_allowed_ips": "1.1.1.1,2.2.2.2",
|
||||
"default_client_dns": "1.1.1.1",
|
||||
"default_client_endpoint": "new-endpoint",
|
||||
"default_client_mtu": 1100,
|
||||
"default_client_persistent_keepalive": 1,
|
||||
"disable_vpn_on_oidc_error": true,
|
||||
"id": "8f17e873-de8a-4264-8567-39e450870306",
|
||||
"inserted_at": "2023-01-13T06:00:43.178729Z",
|
||||
"local_auth_enabled": false,
|
||||
"logo": null,
|
||||
"openid_connect_providers": [
|
||||
{
|
||||
"auto_create_users": false,
|
||||
"client_id": "test-id",
|
||||
"client_secret": "test-secret",
|
||||
"discovery_document_uri": "https://accounts.google.com/.well-known/openid-configuration",
|
||||
"id": "google",
|
||||
"label": "google",
|
||||
"redirect_uri": "https://invalid",
|
||||
"response_type": "response-type",
|
||||
"scope": "test-scope"
|
||||
}
|
||||
],
|
||||
"saml_identity_providers": [
|
||||
{
|
||||
"auto_create_users": false,
|
||||
"base_url": "https://saml",
|
||||
"id": "okta",
|
||||
"label": "okta",
|
||||
"metadata": "<?xml version=\"1.0\"?>\n<md:EntityDescriptor xmlns=\"urn:oasis:names:tc:SAML:2.0:metadata\" xmlns:md=\"urn:oasis:names:tc:SAML:2.0:metadata\" xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\" entityID=\"http://localhost:8080/realms/firezone\">\n <md:IDPSSODescriptor WantAuthnRequestsSigned=\"true\" protocolSupportEnumeration=\"urn:oasis:names:tc:SAML:2.0:protocol\">\n <md:KeyDescriptor use=\"signing\">\n <ds:KeyInfo>\n <ds:KeyName>pdSMtx2s3RVVhxg_qJOjHhlZhwZk6JiBMiSm5PEgjkA</ds:KeyName>\n <ds:X509Data>\n <ds:X509Certificate>MIICnzCCAYcCBgGD18ZU8TANBgkqhkiG9w0BAQsFADATMREwDwYDVQQDDAhmaXJlem9uZTAeFw0yMjEwMTQxODMyMjJaFw0zMjEwMTQxODM0MDJaMBMxETAPBgNVBAMMCGZpcmV6b25lMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAur5Cb0jrDJbMwr96WWE+z9CjDg0A/uRkaB4loRqkmu3A2fQGsS6CP7F7lQWMJmpzvBgkNtB69toO2sgx1u1fhpIJBZ0uSHF5gnzQAivgVxInvkMKRTRSkpMbhObiDHZnEGI2+Ly+8iV8IvprdrbDgm52u4conam0H1PewUKkHulrVQ+ImFuEWAjKCRSqpUG2F1eRkA0YpqB09x0CZAOOoucwTsBYj/ZAz3dUXhYIENAF7v0ykvzGOCAyOZIn1uYQc7jvWpwoI8qQdL45phj2FLoFlght3tlZV8IG5hsXrE6rg7Ufqvv8xyGltrOMKj/jEFEunagZOUjkypDp36b8cwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQBEZKLLr66GB3NxqXGTMl0PvTDNB9GdyShQHaJYjeeUQnEXixjlAVrOq/txEBKjhGUcqyFELoNuwcxxV1iHA5oXhCoqYmnp9T/ftmXPDT3c49PBABHgLJaFOKYTpVx1YjP7mA44X1ijLZmgboIeeFNerVNHIzR9BsxcloQlB0r9QfC14rsuXo6QD3QnaVI8wDgWXQHqpcwLFqvehXdNvMFniRvX2qBNU8E0FPoMaZ1C3n2nssLcVZ+C4ghq6YoAG+wLGY7XE8+v5rnYGDpGpfgr2wdefn6tryFq3PyGqA8ThjARESRRQG9kI/RlNX7qCnP/8/7JQ4wLdfz5C25uhakP</ds:X509Certificate>\n </ds:X509Data>\n </ds:KeyInfo>\n </md:KeyDescriptor>\n <md:ArtifactResolutionService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:SOAP\" Location=\"http://localhost:8080/realms/firezone/protocol/saml/resolve\" index=\"0\"/>\n <md:SingleLogoutService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST\" Location=\"http://localhost:8080/realms/firezone/protocol/saml\"/>\n <md:SingleLogoutService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect\" Location=\"http://localhost:8080/realms/firezone/protocol/saml\"/>\n <md:SingleLogoutService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact\" Location=\"http://localhost:8080/realms/firezone/protocol/saml\"/>\n <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat>\n <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</md:NameIDFormat>\n <md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</md:NameIDFormat>\n <md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</md:NameIDFormat>\n <md:SingleSignOnService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST\" Location=\"http://localhost:8080/realms/firezone/protocol/saml\"/>\n <md:SingleSignOnService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect\" Location=\"http://localhost:8080/realms/firezone/protocol/saml\"/>\n <md:SingleSignOnService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:SOAP\" Location=\"http://localhost:8080/realms/firezone/protocol/saml\"/>\n <md:SingleSignOnService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact\" Location=\"http://localhost:8080/realms/firezone/protocol/saml\"/>\n </md:IDPSSODescriptor>\n</md:EntityDescriptor>\n",
|
||||
"sign_metadata": false,
|
||||
"sign_requests": false,
|
||||
"signed_assertion_in_resp": false,
|
||||
"signed_envelopes_in_resp": false
|
||||
}
|
||||
],
|
||||
"updated_at": "2023-01-13T06:30:47.529652Z",
|
||||
"vpn_session_duration": 100
|
||||
}
|
||||
}
|
||||
```
|
||||
363
docs/docs/reference/api/devices.mdx
Normal file
363
docs/docs/reference/api/devices.mdx
Normal file
@@ -0,0 +1,363 @@
|
||||
---
|
||||
title: Devices
|
||||
group: Devices
|
||||
---
|
||||
|
||||
|
||||
This endpoint allows an administrator to manage Devices.
|
||||
|
||||
## API Documentation
|
||||
### GET /v0/devices
|
||||
|
||||
|
||||
|
||||
#### Example
|
||||
```bash
|
||||
$ curl -i \
|
||||
-X GET "https://{firezone_host}/v0/devices" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Authorization: Bearer {api_token}' \
|
||||
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json; charset=utf-8
|
||||
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"allowed_ips": "0.0.0.0/0,::/0",
|
||||
"description": "factory description",
|
||||
"dns": "1.1.1.1,1.0.0.1",
|
||||
"endpoint": "localhost:51820",
|
||||
"id": "9fc9b189-b740-4676-a7c2-c135b97d951d",
|
||||
"inserted_at": "2023-01-13T06:30:47.092141Z",
|
||||
"ipv4": "100.99.95.137",
|
||||
"ipv6": "fd00::2a:3f6d",
|
||||
"latest_handshake": null,
|
||||
"mtu": 1280,
|
||||
"name": "factory 3175",
|
||||
"persistent_keepalive": 25,
|
||||
"preshared_key": "Fj2iQKy5R5lLi8GIMI96FIfgWs/8saEYj4q6mLtgpg8=",
|
||||
"public_key": "cVAdAno+PbyPBg5ubwxPe86QahSZ3AwhsKHfkFNw0nc=",
|
||||
"remote_ip": null,
|
||||
"rx_bytes": null,
|
||||
"server_public_key": "is+0ov0/SZ9I+qyDD+adVoH9LreWHa85QQgpt6RUtA4=",
|
||||
"tx_bytes": null,
|
||||
"updated_at": "2023-01-13T06:30:47.092141Z",
|
||||
"use_default_allowed_ips": true,
|
||||
"use_default_dns": true,
|
||||
"use_default_endpoint": true,
|
||||
"use_default_mtu": true,
|
||||
"use_default_persistent_keepalive": true,
|
||||
"user_id": "4b195eb9-d675-4143-8de0-64e68c5a6d86"
|
||||
},
|
||||
{
|
||||
"allowed_ips": "0.0.0.0/0,::/0",
|
||||
"description": "factory description",
|
||||
"dns": "1.1.1.1,1.0.0.1",
|
||||
"endpoint": "localhost:51820",
|
||||
"id": "85243eb4-8c30-4bce-bb40-b4b9650e7ffa",
|
||||
"inserted_at": "2023-01-13T06:30:47.101527Z",
|
||||
"ipv4": "100.106.156.151",
|
||||
"ipv6": "fd00::3e:876d",
|
||||
"latest_handshake": null,
|
||||
"mtu": 1280,
|
||||
"name": "factory 2820",
|
||||
"persistent_keepalive": 25,
|
||||
"preshared_key": "NXiX1/xSyDfEl+S3O7VaaVTJKUu2kZo91pCycuZG3mk=",
|
||||
"public_key": "e8e8+NBCAyHPycu2VJIRK9NQCR5Bz5Oo6aFbuOmUMhc=",
|
||||
"remote_ip": null,
|
||||
"rx_bytes": null,
|
||||
"server_public_key": "is+0ov0/SZ9I+qyDD+adVoH9LreWHa85QQgpt6RUtA4=",
|
||||
"tx_bytes": null,
|
||||
"updated_at": "2023-01-13T06:30:47.101527Z",
|
||||
"use_default_allowed_ips": true,
|
||||
"use_default_dns": true,
|
||||
"use_default_endpoint": true,
|
||||
"use_default_mtu": true,
|
||||
"use_default_persistent_keepalive": true,
|
||||
"user_id": "1949803a-bb74-429c-ac99-fae4ce09ca08"
|
||||
},
|
||||
{
|
||||
"allowed_ips": "0.0.0.0/0,::/0",
|
||||
"description": "factory description",
|
||||
"dns": "1.1.1.1,1.0.0.1",
|
||||
"endpoint": "localhost:51820",
|
||||
"id": "7898b569-7c59-4596-b002-e1717c6fe5df",
|
||||
"inserted_at": "2023-01-13T06:30:47.108829Z",
|
||||
"ipv4": "100.120.62.86",
|
||||
"ipv6": "fd00::38:7ee5",
|
||||
"latest_handshake": null,
|
||||
"mtu": 1280,
|
||||
"name": "factory 2978",
|
||||
"persistent_keepalive": 25,
|
||||
"preshared_key": "i6kyqjysbWGEWMO9FNUDMxE1OhrYJsgjuIfgnJNApyE=",
|
||||
"public_key": "ulryM87WfDob8foWZtIiaW+cH+ugh4t/31vSO2YNRtA=",
|
||||
"remote_ip": null,
|
||||
"rx_bytes": null,
|
||||
"server_public_key": "is+0ov0/SZ9I+qyDD+adVoH9LreWHa85QQgpt6RUtA4=",
|
||||
"tx_bytes": null,
|
||||
"updated_at": "2023-01-13T06:30:47.108829Z",
|
||||
"use_default_allowed_ips": true,
|
||||
"use_default_dns": true,
|
||||
"use_default_endpoint": true,
|
||||
"use_default_mtu": true,
|
||||
"use_default_persistent_keepalive": true,
|
||||
"user_id": "a1ebe3b2-3843-47ee-baf4-077740bfcd35"
|
||||
},
|
||||
{
|
||||
"allowed_ips": "0.0.0.0/0,::/0",
|
||||
"description": "factory description",
|
||||
"dns": "1.1.1.1,1.0.0.1",
|
||||
"endpoint": "localhost:51820",
|
||||
"id": "3113df9e-29a4-4062-8a7d-7bf67612c61c",
|
||||
"inserted_at": "2023-01-13T06:30:47.115812Z",
|
||||
"ipv4": "100.64.196.12",
|
||||
"ipv6": "fd00::1e:b441",
|
||||
"latest_handshake": null,
|
||||
"mtu": 1280,
|
||||
"name": "factory 1577",
|
||||
"persistent_keepalive": 25,
|
||||
"preshared_key": "oZsi27RP/myoPFDTdxv29KVAxb2D1PTN+ojhUHsuM9I=",
|
||||
"public_key": "ZZrmY3JKOLJc9JZO+JTBJ9toM+x3hZBikcEAAxhdnWY=",
|
||||
"remote_ip": null,
|
||||
"rx_bytes": null,
|
||||
"server_public_key": "is+0ov0/SZ9I+qyDD+adVoH9LreWHa85QQgpt6RUtA4=",
|
||||
"tx_bytes": null,
|
||||
"updated_at": "2023-01-13T06:30:47.115812Z",
|
||||
"use_default_allowed_ips": true,
|
||||
"use_default_dns": true,
|
||||
"use_default_endpoint": true,
|
||||
"use_default_mtu": true,
|
||||
"use_default_persistent_keepalive": true,
|
||||
"user_id": "634c7a8b-95c3-4c2f-9566-78be4d768cde"
|
||||
},
|
||||
{
|
||||
"allowed_ips": "0.0.0.0/0,::/0",
|
||||
"description": "factory description",
|
||||
"dns": "1.1.1.1,1.0.0.1",
|
||||
"endpoint": "localhost:51820",
|
||||
"id": "44c8dd33-ad63-47cf-93ae-ff5ffcb16f52",
|
||||
"inserted_at": "2023-01-13T06:30:47.123039Z",
|
||||
"ipv4": "100.93.227.124",
|
||||
"ipv6": "fd00::3:b1dd",
|
||||
"latest_handshake": null,
|
||||
"mtu": 1280,
|
||||
"name": "factory 1673",
|
||||
"persistent_keepalive": 25,
|
||||
"preshared_key": "G0XAE7HCOArcB+RH09g/HIsDJM3SfYk9WKa1WYo6hv4=",
|
||||
"public_key": "RBr9GYzFGuoltoIt2iTeqSb0CHaiPAcwxxxxSYlX4tg=",
|
||||
"remote_ip": null,
|
||||
"rx_bytes": null,
|
||||
"server_public_key": "is+0ov0/SZ9I+qyDD+adVoH9LreWHa85QQgpt6RUtA4=",
|
||||
"tx_bytes": null,
|
||||
"updated_at": "2023-01-13T06:30:47.123039Z",
|
||||
"use_default_allowed_ips": true,
|
||||
"use_default_dns": true,
|
||||
"use_default_endpoint": true,
|
||||
"use_default_mtu": true,
|
||||
"use_default_persistent_keepalive": true,
|
||||
"user_id": "b61a4d7a-34a6-4d37-9871-a024fb97fe60"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
### POST /v0/devices
|
||||
|
||||
|
||||
|
||||
#### Example
|
||||
```bash
|
||||
$ curl -i \
|
||||
-X POST "https://{firezone_host}/v0/devices" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Authorization: Bearer {api_token}' \
|
||||
--data-binary @- << EOF
|
||||
{
|
||||
"device": {
|
||||
"allowed_ips": "0.0.0.0/0, ::/0, 1.1.1.1",
|
||||
"description": "create-description",
|
||||
"dns": "9.9.9.8",
|
||||
"endpoint": "9.9.9.9",
|
||||
"ipv4": "100.64.0.2",
|
||||
"ipv6": "fd00::2",
|
||||
"mtu": 999,
|
||||
"name": "create-name",
|
||||
"persistent_keepalive": 9,
|
||||
"preshared_key": "CHqFuS+iL3FTog5F4Ceumqlk0CU4Cl/dyUP/9F9NDnI=",
|
||||
"public_key": "CHqFuS+iL3FTog5F4Ceumqlk0CU4Cl/dyUP/9F9NDnI=",
|
||||
"use_default_allowed_ips": false,
|
||||
"use_default_dns": false,
|
||||
"use_default_endpoint": false,
|
||||
"use_default_mtu": false,
|
||||
"use_default_persistent_keepalive": false,
|
||||
"user_id": "57afecab-c92c-45b8-8764-017a7cb5276b"
|
||||
}
|
||||
}'
|
||||
EOF
|
||||
|
||||
HTTP/1.1 201
|
||||
Content-Type: application/json; charset=utf-8
|
||||
Location: /v0/devices/0f71030e-b872-494f-af2b-c31730f119e0
|
||||
|
||||
{
|
||||
"data": {
|
||||
"allowed_ips": "0.0.0.0/0, ::/0, 1.1.1.1",
|
||||
"description": "create-description",
|
||||
"dns": "9.9.9.8",
|
||||
"endpoint": "9.9.9.9",
|
||||
"id": "0f71030e-b872-494f-af2b-c31730f119e0",
|
||||
"inserted_at": "2023-01-13T06:30:47.204640Z",
|
||||
"ipv4": "100.64.0.2",
|
||||
"ipv6": "fd00::2",
|
||||
"latest_handshake": null,
|
||||
"mtu": 999,
|
||||
"name": "create-name",
|
||||
"persistent_keepalive": 9,
|
||||
"preshared_key": "CHqFuS+iL3FTog5F4Ceumqlk0CU4Cl/dyUP/9F9NDnI=",
|
||||
"public_key": "CHqFuS+iL3FTog5F4Ceumqlk0CU4Cl/dyUP/9F9NDnI=",
|
||||
"remote_ip": null,
|
||||
"rx_bytes": null,
|
||||
"server_public_key": "is+0ov0/SZ9I+qyDD+adVoH9LreWHa85QQgpt6RUtA4=",
|
||||
"tx_bytes": null,
|
||||
"updated_at": "2023-01-13T06:30:47.204640Z",
|
||||
"use_default_allowed_ips": false,
|
||||
"use_default_dns": false,
|
||||
"use_default_endpoint": false,
|
||||
"use_default_mtu": false,
|
||||
"use_default_persistent_keepalive": false,
|
||||
"user_id": "57afecab-c92c-45b8-8764-017a7cb5276b"
|
||||
}
|
||||
}
|
||||
```
|
||||
### GET /v0/devices/{id}
|
||||
|
||||
|
||||
|
||||
#### Example
|
||||
**URI Parameters:**
|
||||
|
||||
- `id`: `904fbe05-86a5-4edb-afb2-6b728755a210`
|
||||
```bash
|
||||
$ curl -i \
|
||||
-X GET "https://{firezone_host}/v0/devices/{id}" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Authorization: Bearer {api_token}' \
|
||||
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json; charset=utf-8
|
||||
|
||||
{
|
||||
"data": {
|
||||
"allowed_ips": "0.0.0.0/0,::/0",
|
||||
"description": "factory description",
|
||||
"dns": "1.1.1.1,1.0.0.1",
|
||||
"endpoint": "localhost:51820",
|
||||
"id": "904fbe05-86a5-4edb-afb2-6b728755a210",
|
||||
"inserted_at": "2023-01-13T06:30:47.048145Z",
|
||||
"ipv4": "100.74.213.26",
|
||||
"ipv6": "fd00::5:110a",
|
||||
"latest_handshake": null,
|
||||
"mtu": 1280,
|
||||
"name": "factory 2403",
|
||||
"persistent_keepalive": 25,
|
||||
"preshared_key": "fue0i7cIahPPlWr6UCSerJNu3NRDrETv3YW+Xjc3qU4=",
|
||||
"public_key": "6KYOCkP8off66kidQOXpwQlwKix8ELfXm/kR5cwsnug=",
|
||||
"remote_ip": null,
|
||||
"rx_bytes": null,
|
||||
"server_public_key": "is+0ov0/SZ9I+qyDD+adVoH9LreWHa85QQgpt6RUtA4=",
|
||||
"tx_bytes": null,
|
||||
"updated_at": "2023-01-13T06:30:47.048145Z",
|
||||
"use_default_allowed_ips": true,
|
||||
"use_default_dns": true,
|
||||
"use_default_endpoint": true,
|
||||
"use_default_mtu": true,
|
||||
"use_default_persistent_keepalive": true,
|
||||
"user_id": "bc22e5c4-853c-4e0d-bf93-85111707e66f"
|
||||
}
|
||||
}
|
||||
```
|
||||
### PATCH /v0/devices/{id}
|
||||
|
||||
|
||||
|
||||
#### Example
|
||||
**URI Parameters:**
|
||||
|
||||
- `id`: `ef1da923-caf4-47f3-ab6a-7ab0908d7f0e`
|
||||
```bash
|
||||
$ curl -i \
|
||||
-X PUT "https://{firezone_host}/v0/devices/{id}" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Authorization: Bearer {api_token}' \
|
||||
--data-binary @- << EOF
|
||||
{
|
||||
"device": {
|
||||
"allowed_ips": "0.0.0.0/0, ::/0, 1.1.1.1",
|
||||
"description": "create-description",
|
||||
"dns": "9.9.9.8",
|
||||
"endpoint": "9.9.9.9",
|
||||
"ipv4": "100.64.0.2",
|
||||
"ipv6": "fd00::2",
|
||||
"mtu": 999,
|
||||
"name": "create-name",
|
||||
"persistent_keepalive": 9,
|
||||
"preshared_key": "CHqFuS+iL3FTog5F4Ceumqlk0CU4Cl/dyUP/9F9NDnI=",
|
||||
"public_key": "CHqFuS+iL3FTog5F4Ceumqlk0CU4Cl/dyUP/9F9NDnI=",
|
||||
"use_default_allowed_ips": false,
|
||||
"use_default_dns": false,
|
||||
"use_default_endpoint": false,
|
||||
"use_default_mtu": false,
|
||||
"use_default_persistent_keepalive": false
|
||||
}
|
||||
}'
|
||||
EOF
|
||||
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json; charset=utf-8
|
||||
|
||||
{
|
||||
"data": {
|
||||
"allowed_ips": "0.0.0.0/0, ::/0, 1.1.1.1",
|
||||
"description": "create-description",
|
||||
"dns": "9.9.9.8",
|
||||
"endpoint": "9.9.9.9",
|
||||
"id": "ef1da923-caf4-47f3-ab6a-7ab0908d7f0e",
|
||||
"inserted_at": "2023-01-13T06:30:47.264719Z",
|
||||
"ipv4": "100.64.0.2",
|
||||
"ipv6": "fd00::2",
|
||||
"latest_handshake": null,
|
||||
"mtu": 999,
|
||||
"name": "create-name",
|
||||
"persistent_keepalive": 9,
|
||||
"preshared_key": "CHqFuS+iL3FTog5F4Ceumqlk0CU4Cl/dyUP/9F9NDnI=",
|
||||
"public_key": "CHqFuS+iL3FTog5F4Ceumqlk0CU4Cl/dyUP/9F9NDnI=",
|
||||
"remote_ip": null,
|
||||
"rx_bytes": null,
|
||||
"server_public_key": "is+0ov0/SZ9I+qyDD+adVoH9LreWHa85QQgpt6RUtA4=",
|
||||
"tx_bytes": null,
|
||||
"updated_at": "2023-01-13T06:30:47.279141Z",
|
||||
"use_default_allowed_ips": false,
|
||||
"use_default_dns": false,
|
||||
"use_default_endpoint": false,
|
||||
"use_default_mtu": false,
|
||||
"use_default_persistent_keepalive": false,
|
||||
"user_id": "ae05e328-3a67-4101-9d6b-48dcd9cdddf8"
|
||||
}
|
||||
}
|
||||
```
|
||||
### DELETE /v0/devices/{id}
|
||||
|
||||
|
||||
|
||||
#### Example
|
||||
**URI Parameters:**
|
||||
|
||||
- `id`: `5b8cf677-ae60-4eca-b038-9abcd410904f`
|
||||
```bash
|
||||
$ curl -i \
|
||||
-X DELETE "https://{firezone_host}/v0/devices/{id}" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Authorization: Bearer {api_token}' \
|
||||
|
||||
HTTP/1.1 204
|
||||
```
|
||||
203
docs/docs/reference/api/rules.mdx
Normal file
203
docs/docs/reference/api/rules.mdx
Normal file
@@ -0,0 +1,203 @@
|
||||
---
|
||||
title: Rules
|
||||
group: Rules
|
||||
---
|
||||
|
||||
|
||||
This endpoint allows an adminisrator to manage Rules.
|
||||
|
||||
## API Documentation
|
||||
### GET /v0/rules
|
||||
|
||||
|
||||
|
||||
#### Example
|
||||
```bash
|
||||
$ curl -i \
|
||||
-X GET "https://{firezone_host}/v0/rules" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Authorization: Bearer {api_token}' \
|
||||
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json; charset=utf-8
|
||||
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"action": "drop",
|
||||
"destination": "10.3.2.1",
|
||||
"id": "fdcf2ca8-1871-4aac-bc01-591b3e18578e",
|
||||
"inserted_at": "2023-01-13T06:30:46.079209Z",
|
||||
"port_range": null,
|
||||
"port_type": null,
|
||||
"updated_at": "2023-01-13T06:30:46.079209Z",
|
||||
"user_id": null
|
||||
},
|
||||
{
|
||||
"action": "drop",
|
||||
"destination": "10.3.2.2",
|
||||
"id": "2e544ab0-0ca5-432e-9a31-b5feb982f50a",
|
||||
"inserted_at": "2023-01-13T06:30:46.087033Z",
|
||||
"port_range": null,
|
||||
"port_type": null,
|
||||
"updated_at": "2023-01-13T06:30:46.087033Z",
|
||||
"user_id": null
|
||||
},
|
||||
{
|
||||
"action": "drop",
|
||||
"destination": "10.3.2.3",
|
||||
"id": "02df6455-65f1-406b-a3dd-7c223af04f9b",
|
||||
"inserted_at": "2023-01-13T06:30:46.088443Z",
|
||||
"port_range": null,
|
||||
"port_type": null,
|
||||
"updated_at": "2023-01-13T06:30:46.088443Z",
|
||||
"user_id": null
|
||||
},
|
||||
{
|
||||
"action": "drop",
|
||||
"destination": "10.3.2.4",
|
||||
"id": "e0c4e652-e3a2-4a69-a8f3-265e07515938",
|
||||
"inserted_at": "2023-01-13T06:30:46.090111Z",
|
||||
"port_range": null,
|
||||
"port_type": null,
|
||||
"updated_at": "2023-01-13T06:30:46.090111Z",
|
||||
"user_id": null
|
||||
},
|
||||
{
|
||||
"action": "drop",
|
||||
"destination": "10.3.2.5",
|
||||
"id": "a7c2bfb2-3e09-48d8-b038-c69c84b777b1",
|
||||
"inserted_at": "2023-01-13T06:30:46.091623Z",
|
||||
"port_range": null,
|
||||
"port_type": null,
|
||||
"updated_at": "2023-01-13T06:30:46.091623Z",
|
||||
"user_id": null
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
### POST /v0/rules
|
||||
|
||||
|
||||
|
||||
#### Example
|
||||
```bash
|
||||
$ curl -i \
|
||||
-X POST "https://{firezone_host}/v0/rules" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Authorization: Bearer {api_token}' \
|
||||
--data-binary @- << EOF
|
||||
{
|
||||
"rule": {
|
||||
"action": "accept",
|
||||
"destination": "1.1.1.1/24",
|
||||
"port_range": "1 - 2",
|
||||
"port_type": "udp",
|
||||
"user_id": "9f4d207a-90d8-4cc9-800c-accefe9f90cf"
|
||||
}
|
||||
}'
|
||||
EOF
|
||||
|
||||
HTTP/1.1 201
|
||||
Content-Type: application/json; charset=utf-8
|
||||
Location: /v0/rules/cc374f84-b003-4858-8772-516ea3f098a1
|
||||
|
||||
{
|
||||
"data": {
|
||||
"action": "accept",
|
||||
"destination": "1.1.1.1/24",
|
||||
"id": "cc374f84-b003-4858-8772-516ea3f098a1",
|
||||
"inserted_at": "2023-01-13T06:30:47.193190Z",
|
||||
"port_range": "1 - 2",
|
||||
"port_type": "udp",
|
||||
"updated_at": "2023-01-13T06:30:47.193190Z",
|
||||
"user_id": "9f4d207a-90d8-4cc9-800c-accefe9f90cf"
|
||||
}
|
||||
}
|
||||
```
|
||||
### GET /v0/rules/{id}
|
||||
|
||||
|
||||
|
||||
#### Example
|
||||
**URI Parameters:**
|
||||
|
||||
- `id`: `49a9ae27-74f2-45dd-a324-d47a7581205c`
|
||||
```bash
|
||||
$ curl -i \
|
||||
-X GET "https://{firezone_host}/v0/rules/{id}" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Authorization: Bearer {api_token}' \
|
||||
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json; charset=utf-8
|
||||
|
||||
{
|
||||
"data": {
|
||||
"action": "drop",
|
||||
"destination": "10.10.10.0/24",
|
||||
"id": "49a9ae27-74f2-45dd-a324-d47a7581205c",
|
||||
"inserted_at": "2023-01-13T06:30:46.993421Z",
|
||||
"port_range": null,
|
||||
"port_type": null,
|
||||
"updated_at": "2023-01-13T06:30:46.993421Z",
|
||||
"user_id": null
|
||||
}
|
||||
}
|
||||
```
|
||||
### PATCH /v0/rules/{id}
|
||||
|
||||
|
||||
|
||||
#### Example
|
||||
**URI Parameters:**
|
||||
|
||||
- `id`: `b8231fa6-1df2-4b1b-8687-61a72a8031b1`
|
||||
```bash
|
||||
$ curl -i \
|
||||
-X PUT "https://{firezone_host}/v0/rules/{id}" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Authorization: Bearer {api_token}' \
|
||||
--data-binary @- << EOF
|
||||
{
|
||||
"rule": {
|
||||
"action": "accept",
|
||||
"destination": "1.1.1.1/24",
|
||||
"port_range": "1 - 2",
|
||||
"port_type": "udp"
|
||||
}
|
||||
}'
|
||||
EOF
|
||||
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json; charset=utf-8
|
||||
|
||||
{
|
||||
"data": {
|
||||
"action": "accept",
|
||||
"destination": "1.1.1.1/24",
|
||||
"id": "b8231fa6-1df2-4b1b-8687-61a72a8031b1",
|
||||
"inserted_at": "2023-01-13T06:30:47.244050Z",
|
||||
"port_range": "1 - 2",
|
||||
"port_type": "udp",
|
||||
"updated_at": "2023-01-13T06:30:47.254788Z",
|
||||
"user_id": null
|
||||
}
|
||||
}
|
||||
```
|
||||
### DELETE /v0/rules/{id}
|
||||
|
||||
|
||||
|
||||
#### Example
|
||||
**URI Parameters:**
|
||||
|
||||
- `id`: `05c0342c-984c-43df-855b-32e88ea8ee08`
|
||||
```bash
|
||||
$ curl -i \
|
||||
-X DELETE "https://{firezone_host}/v0/rules/{id}" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Authorization: Bearer {api_token}' \
|
||||
|
||||
HTTP/1.1 204
|
||||
```
|
||||
354
docs/docs/reference/api/users.mdx
Normal file
354
docs/docs/reference/api/users.mdx
Normal file
@@ -0,0 +1,354 @@
|
||||
---
|
||||
title: Users
|
||||
sidebar_position: 2
|
||||
toc_max_heading_level: 4
|
||||
---
|
||||
|
||||
|
||||
This endpoint allows an administrator to manage Users.
|
||||
|
||||
## Auto-Create Users from OpenID or SAML providers
|
||||
|
||||
You can set Configuration option `auto_create_users` to `true` to automatically create users
|
||||
from OpenID or SAML providers. Use it with care as anyone with access to the provider will be
|
||||
able to log-in to Firezone.
|
||||
|
||||
If `auto_create_users` is `false`, then you need to provision users with `password` attribute,
|
||||
otherwise they will have no means to log in.
|
||||
|
||||
## API Documentation
|
||||
### List all Users [`GET /v0/users`]
|
||||
|
||||
|
||||
|
||||
#### Example
|
||||
```bash
|
||||
$ curl -i \
|
||||
-X GET "https://{firezone_host}/v0/users" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Authorization: Bearer {api_token}' \
|
||||
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json; charset=utf-8
|
||||
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"disabled_at": null,
|
||||
"email": "test-2886@test",
|
||||
"id": "9f0ce70d-d9e6-4610-ad3b-e5758318c016",
|
||||
"inserted_at": "2023-01-13T06:30:47.076850Z",
|
||||
"last_signed_in_at": null,
|
||||
"last_signed_in_method": null,
|
||||
"role": "admin",
|
||||
"updated_at": "2023-01-13T06:30:47.076850Z"
|
||||
},
|
||||
{
|
||||
"disabled_at": null,
|
||||
"email": "test-2918@test",
|
||||
"id": "36479416-7099-46f9-b9b9-3ad4411eef7d",
|
||||
"inserted_at": "2023-01-13T06:30:47.079115Z",
|
||||
"last_signed_in_at": null,
|
||||
"last_signed_in_method": null,
|
||||
"role": "admin",
|
||||
"updated_at": "2023-01-13T06:30:47.079115Z"
|
||||
},
|
||||
{
|
||||
"disabled_at": null,
|
||||
"email": "test-3045@test",
|
||||
"id": "232c2358-5132-4fc7-8e42-cd8464fcae02",
|
||||
"inserted_at": "2023-01-13T06:30:47.081138Z",
|
||||
"last_signed_in_at": null,
|
||||
"last_signed_in_method": null,
|
||||
"role": "admin",
|
||||
"updated_at": "2023-01-13T06:30:47.081138Z"
|
||||
},
|
||||
{
|
||||
"disabled_at": null,
|
||||
"email": "test-2950@test",
|
||||
"id": "b15b274b-751e-4ca6-9c3e-3a798299ec86",
|
||||
"inserted_at": "2023-01-13T06:30:47.083059Z",
|
||||
"last_signed_in_at": null,
|
||||
"last_signed_in_method": null,
|
||||
"role": "admin",
|
||||
"updated_at": "2023-01-13T06:30:47.083059Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
### Create a User [`POST /v0/users`]
|
||||
|
||||
|
||||
Create a new User.
|
||||
|
||||
This endpoint is useful in two cases:
|
||||
|
||||
1. When [Local Authentication](/authenticate/local-auth/) is enabled (discouraged in
|
||||
production deployments), it allows an administrator to provision users with their passwords;
|
||||
2. When `auto_create_users` in the associated OpenID or SAML configuration is disabled,
|
||||
it allows an administrator to provision users with their emails beforehand, effectively
|
||||
whitelisting specific users for authentication.
|
||||
|
||||
If `auto_create_users` is `true` in the associated OpenID or SAML configuration, there is no need
|
||||
to provision users; they will be created automatically when they log in for the first time using
|
||||
the associated OpenID or SAML provider.
|
||||
|
||||
#### User Attributes
|
||||
|
||||
| Attribute | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `role` | `admin` or `unprivileged` (default) | No | User role. |
|
||||
| `email` | `string` | Yes | Email which will be used to identify the user. |
|
||||
| `password` | `string` | No | A password that can be used for login-password authentication. |
|
||||
| `password_confirmation` | `string` | -> | Is required when the `password` is set. |
|
||||
|
||||
#### Example
|
||||
```bash
|
||||
$ curl -i \
|
||||
-X POST "https://{firezone_host}/v0/users" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Authorization: Bearer {api_token}' \
|
||||
--data-binary @- << EOF
|
||||
{
|
||||
"user": {
|
||||
"email": "new-user@test",
|
||||
"password": "test1234test",
|
||||
"password_confirmation": "test1234test",
|
||||
"role": "unprivileged"
|
||||
}
|
||||
}'
|
||||
EOF
|
||||
|
||||
HTTP/1.1 201
|
||||
Content-Type: application/json; charset=utf-8
|
||||
Location: /v0/users/86616e3e-13f0-4177-bc8e-1a0e588f0be8
|
||||
|
||||
{
|
||||
"data": {
|
||||
"disabled_at": null,
|
||||
"email": "new-user@test",
|
||||
"id": "86616e3e-13f0-4177-bc8e-1a0e588f0be8",
|
||||
"inserted_at": "2023-01-13T06:30:47.047550Z",
|
||||
"last_signed_in_at": null,
|
||||
"last_signed_in_method": null,
|
||||
"role": "unprivileged",
|
||||
"updated_at": "2023-01-13T06:30:47.047550Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
#### Provision an unprivileged OpenID User
|
||||
```bash
|
||||
$ curl -i \
|
||||
-X POST "https://{firezone_host}/v0/users" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Authorization: Bearer {api_token}' \
|
||||
--data-binary @- << EOF
|
||||
{
|
||||
"user": {
|
||||
"email": "new-user@test",
|
||||
"role": "unprivileged"
|
||||
}
|
||||
}'
|
||||
EOF
|
||||
|
||||
HTTP/1.1 201
|
||||
Content-Type: application/json; charset=utf-8
|
||||
Location: /v0/users/6e7962a7-c183-4afb-8569-9001bdfd0d87
|
||||
|
||||
{
|
||||
"data": {
|
||||
"disabled_at": null,
|
||||
"email": "new-user@test",
|
||||
"id": "6e7962a7-c183-4afb-8569-9001bdfd0d87",
|
||||
"inserted_at": "2023-01-13T06:30:47.282412Z",
|
||||
"last_signed_in_at": null,
|
||||
"last_signed_in_method": null,
|
||||
"role": "unprivileged",
|
||||
"updated_at": "2023-01-13T06:30:47.282412Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
#### Provision an admin OpenID User
|
||||
```bash
|
||||
$ curl -i \
|
||||
-X POST "https://{firezone_host}/v0/users" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Authorization: Bearer {api_token}' \
|
||||
--data-binary @- << EOF
|
||||
{
|
||||
"user": {
|
||||
"email": "new-user@test",
|
||||
"role": "admin"
|
||||
}
|
||||
}'
|
||||
EOF
|
||||
|
||||
HTTP/1.1 201
|
||||
Content-Type: application/json; charset=utf-8
|
||||
Location: /v0/users/dedc4dcc-0f65-4110-ad7f-9c354e36e5e5
|
||||
|
||||
{
|
||||
"data": {
|
||||
"disabled_at": null,
|
||||
"email": "new-user@test",
|
||||
"id": "dedc4dcc-0f65-4110-ad7f-9c354e36e5e5",
|
||||
"inserted_at": "2023-01-13T06:30:47.166645Z",
|
||||
"last_signed_in_at": null,
|
||||
"last_signed_in_method": null,
|
||||
"role": "admin",
|
||||
"updated_at": "2023-01-13T06:30:47.166645Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
#### Error due to invalid parameters
|
||||
```bash
|
||||
$ curl -i \
|
||||
-X POST "https://{firezone_host}/v0/users" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Authorization: Bearer {api_token}' \
|
||||
--data-binary @- << EOF
|
||||
{
|
||||
"user": {
|
||||
"email": "test@test.com",
|
||||
"password": "test1234"
|
||||
}
|
||||
}'
|
||||
EOF
|
||||
|
||||
HTTP/1.1 422
|
||||
Content-Type: application/json; charset=utf-8
|
||||
|
||||
{
|
||||
"errors": {
|
||||
"password": [
|
||||
"should be at least 12 character(s)",
|
||||
"does not match password confirmation."
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
### GET /v0/users/{id}
|
||||
|
||||
|
||||
|
||||
#### An email can be used instead of ID.
|
||||
**URI Parameters:**
|
||||
|
||||
- `id`: `test-1481@test`
|
||||
```bash
|
||||
$ curl -i \
|
||||
-X GET "https://{firezone_host}/v0/users/{id}" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Authorization: Bearer {api_token}' \
|
||||
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json; charset=utf-8
|
||||
|
||||
{
|
||||
"data": {
|
||||
"disabled_at": null,
|
||||
"email": "test-1481@test",
|
||||
"id": "b19a929d-fd84-4f11-a799-23416c8efaf8",
|
||||
"inserted_at": "2023-01-13T06:30:47.050304Z",
|
||||
"last_signed_in_at": null,
|
||||
"last_signed_in_method": null,
|
||||
"role": "admin",
|
||||
"updated_at": "2023-01-13T06:30:47.050304Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
### Update a User [`PATCH /v0/users/{id}`]
|
||||
|
||||
|
||||
For details please see [Create a User](#create-a-user-post-v0users) section.
|
||||
|
||||
#### Update by email
|
||||
**URI Parameters:**
|
||||
|
||||
- `id`: `test-3618@test`
|
||||
```bash
|
||||
$ curl -i \
|
||||
-X PUT "https://{firezone_host}/v0/users/{id}" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Authorization: Bearer {api_token}' \
|
||||
--data-binary @- << EOF
|
||||
{
|
||||
"user": {}
|
||||
}'
|
||||
EOF
|
||||
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json; charset=utf-8
|
||||
|
||||
{
|
||||
"data": {
|
||||
"disabled_at": null,
|
||||
"email": "test-3618@test",
|
||||
"id": "54d4de57-21f3-4adc-a9a9-a3ee642da76e",
|
||||
"inserted_at": "2023-01-13T06:30:47.285730Z",
|
||||
"last_signed_in_at": null,
|
||||
"last_signed_in_method": null,
|
||||
"role": "unprivileged",
|
||||
"updated_at": "2023-01-13T06:30:47.285730Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
#### Update by ID
|
||||
**URI Parameters:**
|
||||
|
||||
- `id`: `8dd4eff5-3d2f-4868-94cd-73abb6f130dc`
|
||||
```bash
|
||||
$ curl -i \
|
||||
-X PUT "https://{firezone_host}/v0/users/{id}" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Authorization: Bearer {api_token}' \
|
||||
--data-binary @- << EOF
|
||||
{
|
||||
"user": {}
|
||||
}'
|
||||
EOF
|
||||
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json; charset=utf-8
|
||||
|
||||
{
|
||||
"data": {
|
||||
"disabled_at": null,
|
||||
"email": "test-3235@test",
|
||||
"id": "8dd4eff5-3d2f-4868-94cd-73abb6f130dc",
|
||||
"inserted_at": "2023-01-13T06:30:47.265280Z",
|
||||
"last_signed_in_at": null,
|
||||
"last_signed_in_method": null,
|
||||
"role": "unprivileged",
|
||||
"updated_at": "2023-01-13T06:30:47.265280Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
### DELETE /v0/users/{id}
|
||||
|
||||
|
||||
|
||||
#### Example
|
||||
**URI Parameters:**
|
||||
|
||||
- `id`: `fc0b513f-bd4b-4015-ac71-29b59c678a20`
|
||||
```bash
|
||||
$ curl -i \
|
||||
-X DELETE "https://{firezone_host}/v0/users/{id}" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Authorization: Bearer {api_token}' \
|
||||
|
||||
HTTP/1.1 204
|
||||
```
|
||||
#### An email can be used instead of ID.
|
||||
**URI Parameters:**
|
||||
|
||||
- `id`: `test-3816@test`
|
||||
```bash
|
||||
$ curl -i \
|
||||
-X DELETE "https://{firezone_host}/v0/users/{id}" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Authorization: Bearer {api_token}' \
|
||||
|
||||
HTTP/1.1 204
|
||||
```
|
||||
@@ -43,28 +43,9 @@ const config = {
|
||||
}
|
||||
],
|
||||
|
||||
plugins: [
|
||||
[
|
||||
'docusaurus-plugin-openapi-docs',
|
||||
{
|
||||
id: "apiDocs",
|
||||
docsPluginId: "classic",
|
||||
config: {
|
||||
rest_api: {
|
||||
specPath: "openapi.yaml",
|
||||
outputDir: "docs/reference/REST API",
|
||||
sidebarOptions: {
|
||||
groupPathsBy: "tag",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
plugins: [],
|
||||
|
||||
themes: [
|
||||
"docusaurus-theme-openapi-docs",
|
||||
],
|
||||
themes: [],
|
||||
|
||||
presets: [
|
||||
[
|
||||
@@ -75,8 +56,7 @@ const config = {
|
||||
routeBasePath: '/',
|
||||
sidebarPath: require.resolve('./sidebars.js'),
|
||||
editUrl: 'https://github.com/firezone/firezone/tree/master/docs',
|
||||
docLayoutComponent: "@theme/DocPage",
|
||||
docItemComponent: "@theme/ApiItem",
|
||||
docLayoutComponent: "@theme/DocPage"
|
||||
},
|
||||
theme: {
|
||||
customCss: require.resolve('./src/css/custom.css'),
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
openapi: "3.0.0"
|
||||
info:
|
||||
version: 1.0.0
|
||||
title: Swagger Petstore
|
||||
license:
|
||||
name: MIT
|
||||
servers:
|
||||
- url: http://petstore.swagger.io/v1
|
||||
paths:
|
||||
/pets:
|
||||
get:
|
||||
summary: List all pets
|
||||
operationId: listPets
|
||||
tags:
|
||||
- pets
|
||||
parameters:
|
||||
- name: limit
|
||||
in: query
|
||||
description: How many items to return at one time (max 100)
|
||||
required: false
|
||||
schema:
|
||||
type: integer
|
||||
format: int32
|
||||
responses:
|
||||
'200':
|
||||
description: A paged array of pets
|
||||
headers:
|
||||
x-next:
|
||||
description: A link to the next page of responses
|
||||
schema:
|
||||
type: string
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Pets"
|
||||
default:
|
||||
description: unexpected error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
post:
|
||||
summary: Create a pet
|
||||
operationId: createPets
|
||||
tags:
|
||||
- pets
|
||||
responses:
|
||||
'201':
|
||||
description: Null response
|
||||
default:
|
||||
description: unexpected error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
/pets/{petId}:
|
||||
get:
|
||||
summary: Info for a specific pet
|
||||
operationId: showPetById
|
||||
tags:
|
||||
- pets
|
||||
parameters:
|
||||
- name: petId
|
||||
in: path
|
||||
required: true
|
||||
description: The id of the pet to retrieve
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: Expected response to a valid request
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Pet"
|
||||
default:
|
||||
description: unexpected error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
components:
|
||||
schemas:
|
||||
Pet:
|
||||
type: object
|
||||
required:
|
||||
- id
|
||||
- name
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
format: int64
|
||||
name:
|
||||
type: string
|
||||
tag:
|
||||
type: string
|
||||
Pets:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/Pet"
|
||||
Error:
|
||||
type: object
|
||||
required:
|
||||
- code
|
||||
- message
|
||||
properties:
|
||||
code:
|
||||
type: integer
|
||||
format: int32
|
||||
message:
|
||||
type: string
|
||||
@@ -19,8 +19,6 @@
|
||||
"@docusaurus/theme-search-algolia": "^2.1.0",
|
||||
"@mdx-js/react": "^1.6.22",
|
||||
"clsx": "^1.1.1",
|
||||
"docusaurus-plugin-openapi-docs": "^1.2.2",
|
||||
"docusaurus-theme-openapi-docs": "^1.2.2",
|
||||
"markdownlint-cli": "^0.31.1",
|
||||
"prism-react-renderer": "^1.3.3",
|
||||
"react": "^17.0.2",
|
||||
|
||||
1635
docs/yarn.lock
1635
docs/yarn.lock
File diff suppressed because it is too large
Load Diff
1
mix.lock
1
mix.lock
@@ -1,6 +1,7 @@
|
||||
%{
|
||||
"argon2_elixir": {:hex, :argon2_elixir, "2.4.1", "edb27bdd326bc738f3e4614eddc2f73507be6fedc9533c6bcc6f15bbac9c85cc", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "0e21f52a373739d00bdfd5fe6da2f04eea623cb4f66899f7526dd9db03903d9f"},
|
||||
"bunt": {:hex, :bunt, "0.2.1", "e2d4792f7bc0ced7583ab54922808919518d0e57ee162901a16a1b6664ef3b14", [:mix], [], "hexpm", "a330bfb4245239787b15005e66ae6845c9cd524a288f0d141c148b02603777a5"},
|
||||
"bureaucrat": {:hex, :bureaucrat, "0.2.9", "d98e4d2b9bdbf22e4a45c2113ce8b38b5b63278506c6ff918e3b943a4355d85b", [:mix], [{:inflex, ">= 1.10.0", [hex: :inflex, repo: "hexpm", optional: false]}, {:phoenix, ">= 1.2.0", [hex: :phoenix, repo: "hexpm", optional: true]}, {:plug, ">= 1.0.0", [hex: :plug, repo: "hexpm", optional: false]}, {:poison, "~> 1.5 or ~> 2.0 or ~> 3.0 or ~> 4.0", [hex: :poison, repo: "hexpm", optional: true]}], "hexpm", "111c8dd84382a62e1026ae011d592ceee918553e5203fe8448d9ba6ccbdfff7d"},
|
||||
"bypass": {:hex, :bypass, "2.1.0", "909782781bf8e20ee86a9cabde36b259d44af8b9f38756173e8f5e2e1fabb9b1", [:mix], [{:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: false]}, {:ranch, "~> 1.3", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "d9b5df8fa5b7a6efa08384e9bbecfe4ce61c77d28a4282f79e02f1ef78d96b80"},
|
||||
"castore": {:hex, :castore, "0.1.20", "62a0126cbb7cb3e259257827b9190f88316eb7aa3fdac01fd6f2dfd64e7f46e9", [:mix], [], "hexpm", "a020b7650529c986c454a4035b6b13a328e288466986307bea3aadb4c95ac98a"},
|
||||
"certifi": {:hex, :certifi, "2.9.0", "6f2a475689dd47f19fb74334859d460a2dc4e3252a3324bd2111b8f0429e7e21", [:rebar3], [], "hexpm", "266da46bdb06d6c6d35fde799bcb28d36d985d424ad7c08b5bb48f5b5cdd4641"},
|
||||
|
||||
Reference in New Issue
Block a user