diff --git a/lib/schema_web/controllers/schema_controller.ex b/lib/schema_web/controllers/schema_controller.ex index 07bf69c..8d8eadc 100644 --- a/lib/schema_web/controllers/schema_controller.ex +++ b/lib/schema_web/controllers/schema_controller.ex @@ -43,6 +43,32 @@ defmodule SchemaWeb.SchemaController do version: "1.0.0" }) end, + Versions: + swagger_schema do + title("Versions") + description("Schema versions, using Semantic Versioning Specification (SemVer) format.") + + properties do + versions(:string, "Version numbers", required: true) + end + + example(%{ + default: %{ + version: "1.0.0", + url: "https://schema.example.com:443/api" + }, + versions: [ + %{ + version: "1.1.0-dev", + url: "https://schema.example.com:443/1.1.0-dev/api" + }, + %{ + version: "1.0.0", + url: "https://schema.example.com:443/1.0.0/api" + } + ] + }) + end, ClassDesc: swagger_schema do title("Class Descriptor") @@ -122,6 +148,50 @@ defmodule SchemaWeb.SchemaController do send_json_resp(conn, version) end + @doc """ + Get available OCSF schema versions. + """ + swagger_path :versions do + get("/api/versions") + summary("Versions") + description("Get available OCSF schema versions.") + produces("application/json") + tag("Schema") + response(200, "Success", :Versions) + end + + @spec versions(Plug.Conn.t(), any) :: Plug.Conn.t() + def versions(conn, _params) do + + url = Application.get_env(:schema_server, SchemaWeb.Endpoint)[:url] + + # The :url key is meant to be set for production, but isn't set for local development + base_url = if url == nil do + "#{conn.scheme}://#{conn.host}:#{conn.port}" + else + "#{conn.scheme}://#{Keyword.fetch!(url, :host)}:#{Keyword.fetch!(url, :port)}" + end + + available_versions = Schemas.versions() + |> Enum.map(fn {version, _} -> version end) + + default_version = %{:version => Schema.version(), :url => "#{base_url}/#{Schema.version()}/api"} + + versions_response = case available_versions do + [] -> + # If there is no response, we only provide a single schema + %{:versions => [default_version], :default => default_version} + + [_head | _tail] -> + available_versions_objects = available_versions + |> Enum.map(fn version -> %{:version => version, :url => "#{base_url}/#{version}/api"} end) + %{:versions => available_versions_objects, :default => default_version} + + end + + send_json_resp(conn, versions_response) + end + @doc """ Get the schema data types. """ diff --git a/lib/schema_web/router.ex b/lib/schema_web/router.ex index 71bc110..fc49a87 100644 --- a/lib/schema_web/router.ex +++ b/lib/schema_web/router.ex @@ -38,7 +38,7 @@ defmodule SchemaWeb.Router do get "/classes", PageController, :classes get "/classes/:id", PageController, :classes get "/classes/:extension/:id", PageController, :classes - + get "/class/graph/:id", PageController, :class_graph get "/class/graph/:extension/:id", PageController, :class_graph @@ -51,7 +51,7 @@ defmodule SchemaWeb.Router do get "/object/graph/:id", PageController, :object_graph get "/object/graph/:extension/:id", PageController, :object_graph - + get "/data_types", PageController, :data_types get "/guidelines", PageController, :guidelines end @@ -61,6 +61,8 @@ defmodule SchemaWeb.Router do pipe_through :api get "/version", SchemaController, :version + get "/versions", SchemaController, :versions + get "/profiles", SchemaController, :profiles get "/extensions", SchemaController, :extensions @@ -94,7 +96,7 @@ defmodule SchemaWeb.Router do get "/classes/:id", SchemaController, :json_class get "/classes/:extension/:id", SchemaController, :json_class - + get "/objects/:id", SchemaController, :json_object get "/objects/:extension/:id", SchemaController, :json_object end