diff --git a/backend/config/config.exs b/backend/config/config.exs index 6245155c0..441dbb106 100644 --- a/backend/config/config.exs +++ b/backend/config/config.exs @@ -28,8 +28,8 @@ config :azimutt, azimutt_github_issues_new: "https://github.com/azimuttapp/azimutt/issues/new", environment: config_env(), # TODO: find an automated process to build it - version: "2.1.7", - version_date: "2024-09-30T00:00:00.000Z", + version: "2.1.8", + version_date: "2024-10-03T00:00:00.000Z", commit_hash: System.cmd("git", ["log", "-1", "--pretty=format:%h"]) |> elem(0) |> String.trim(), commit_message: System.cmd("git", ["log", "-1", "--pretty=format:%s"]) |> elem(0) |> String.trim(), commit_date: System.cmd("git", ["log", "-1", "--pretty=format:%aI"]) |> elem(0) |> String.trim(), diff --git a/backend/lib/azimutt_web/components/icon.ex b/backend/lib/azimutt_web/components/icon.ex index 31a989bcd..1acce96c1 100644 --- a/backend/lib/azimutt_web/components/icon.ex +++ b/backend/lib/azimutt_web/components/icon.ex @@ -48,6 +48,7 @@ defmodule AzimuttWeb.Components.Icon do "ellipsis-vertical" -> ellipsis_vertical(assigns) "exclamation-triangle" -> exclamation_triangle(assigns) "eye" -> eye(assigns) + "finger-print" -> finger_print(assigns) "folder" -> folder(assigns) "funnel" -> funnel(assigns) "globe" -> globe(assigns) @@ -56,6 +57,8 @@ defmodule AzimuttWeb.Components.Icon do "home" -> home(assigns) "inbox" -> inbox(assigns) "key" -> key(assigns) + "lock-closed" -> lock_closed(assigns) + "lock-open" -> lock_open(assigns) "magnifying-glass" -> magnifying_glass(assigns) "magnifying-glass-circle" -> magnifying_glass_circle(assigns) "map" -> map(assigns) @@ -942,6 +945,27 @@ defmodule AzimuttWeb.Components.Icon do end end + def finger_print(assigns) do + classes = if assigns[:class], do: " #{assigns[:class]}", else: "" + + case assigns[:kind] do + "outline" -> + ~H""" + <.outline classes={classes}> + """ + + "solid" -> + ~H""" + <.solid classes={classes}> + """ + + _ -> + ~H""" + <.mini classes={classes}> + """ + end + end + def folder(assigns) do classes = if assigns[:class], do: " #{assigns[:class]}", else: "" @@ -1120,6 +1144,48 @@ defmodule AzimuttWeb.Components.Icon do end end + def lock_closed(assigns) do + classes = if assigns[:class], do: " #{assigns[:class]}", else: "" + + case assigns[:kind] do + "outline" -> + ~H""" + <.outline classes={classes}> + """ + + "solid" -> + ~H""" + <.solid classes={classes}> + """ + + _ -> + ~H""" + <.mini classes={classes}> + """ + end + end + + def lock_open(assigns) do + classes = if assigns[:class], do: " #{assigns[:class]}", else: "" + + case assigns[:kind] do + "outline" -> + ~H""" + <.outline classes={classes}> + """ + + "solid" -> + ~H""" + <.solid classes={classes}> + """ + + _ -> + ~H""" + <.mini classes={classes}> + """ + end + end + def magnifying_glass(assigns) do classes = if assigns[:class], do: " #{assigns[:class]}", else: "" diff --git a/backend/lib/azimutt_web/controllers/website_controller.ex b/backend/lib/azimutt_web/controllers/website_controller.ex index 19184bdf1..9b478d4b7 100644 --- a/backend/lib/azimutt_web/controllers/website_controller.ex +++ b/backend/lib/azimutt_web/controllers/website_controller.ex @@ -45,6 +45,9 @@ defmodule AzimuttWeb.WebsiteController do |> Result.map(fn {from, to} -> conn |> render("convert.html", from: from, to: to) end) end + def portal(conn, _params), do: conn |> render("portal.html") + def portal_subscribed(conn, _params), do: conn |> render("portal-subscribed.html") + def last(conn, _params) do case conn |> last_used_project do {:ok, p} -> conn |> redirect(to: Routes.elm_path(conn, :project_show, p.organization_id, p.id)) diff --git a/backend/lib/azimutt_web/router.ex b/backend/lib/azimutt_web/router.ex index dcc30267e..8a56f4768 100644 --- a/backend/lib/azimutt_web/router.ex +++ b/backend/lib/azimutt_web/router.ex @@ -43,6 +43,8 @@ defmodule AzimuttWeb.Router do pipe_through([:browser, :website_root_layout]) get("/", WebsiteController, :index) get("/aml", WebsiteController, :aml) + get("/portal", WebsiteController, :portal) + get("/portal/subscribed", WebsiteController, :portal_subscribed) # get("/cli", WebsiteController, :cli) # get("/analyze", WebsiteController, :analyze) # get("/analyze/rules", WebsiteController, :analyze_rules) diff --git a/backend/lib/azimutt_web/templates/website/portal-subscribed.html.heex b/backend/lib/azimutt_web/templates/website/portal-subscribed.html.heex new file mode 100644 index 000000000..0eadb4cda --- /dev/null +++ b/backend/lib/azimutt_web/templates/website/portal-subscribed.html.heex @@ -0,0 +1,10 @@ +
+
+

Success 🎉

+

Thank you for subscribing!

+

We're glad you want to know more about Azimutt portal, and are looking to get back to you soon!

+ +
+
diff --git a/backend/lib/azimutt_web/templates/website/portal.html.heex b/backend/lib/azimutt_web/templates/website/portal.html.heex new file mode 100644 index 000000000..29581bc09 --- /dev/null +++ b/backend/lib/azimutt_web/templates/website/portal.html.heex @@ -0,0 +1,191 @@ +
+ +
+ +
+

Your PostgreSQL database, without incidents.

+

Get insights from your database to fix issues before the become production incidents.

+
+ +
+ + + +
+
+
+
+ +
+ + + +
+
+

Databases are critical.

+

+ In fact, they are the most critical part of the infrastructure as they are the hardest to scale and replicate. + Yet, many companies prefer scaling them up and spending more on infrastructure rather than making sure they are used correctly. + Essentially because the existing tooling is made for specialists and require a lot of expertise. +

+

+ Database monitoring is mostly done as a side effect. Either from the server monitoring (CPU, memory, disk, network...) or from the code (query duration, timeouts...). + This allows to spot and act on incidents, but it has no way to anticipate and prevent them. +

+

+ There is a better way... +

+
+
+ +
+
+
+

Proactive monitoring and alerting turned into insights

+
    +
  • + + Not only monitor slow queries, but identify degradations, fast and slow. +
  • +
  • + + Not only trigger thresholds alerts, but search unusual values and patterns. +
  • +
  • + + Not only react on sudden events, but also warn on long term drift. +
  • +
  • + + Not only monitor a database, but inspect all your clusters. +
  • +
+

Watch internals for weak signal: dead rows, analyze and vacuum delays.

+
+
+
+ + + +
+
+
+

Work safer

+

Human in production make errors.

+

+ Yet they may be required for many reasons depending on the business. + The less, the better, but still you need to manage some access. + Now with Azimutt portal: +

+
+
+
+
+
+
+ Fine-grained access rights +
+
+ Allowing see schema, run query plan, read access or write access for any table/column. + All with history, temporary access, query approval and urgency escalation. +
+
+
+
+
+ Query safeguard +
+
+ For queries using large tables, run a query plan to check usage index and warn/block if excessive. + Adds default timeout on user queries. + Less fat finger in production. +
+
+
+
+
+ Full audit log +
+
+ Production access is critical, knowing who done what and when improves safety a lot. + Keeping queries with parameters as well as impacted rows. +
+
+
+
+
+ Malicious activity identification +
+
+ Watch malicious patterns such as data extraction or weired access pattern, making sure database access is used well. +
+
+
+
+
+
+ + + +
+
+

Monitoring without graphs.

+

+ Current products show you a lot of data and graphs, allowing you to dig into issues. + This is good. But only if you have the skills, the time or the necessity to dig in.
+ Azimutt portal mainly provides alerts and insights. It's meant for teams who want their databases on autopilot. + This is not a replacement of other tools, it's an addition with expert knowledge backed in.
+ Or more probably, your first step into taking better care or your database. +

+
+
+ + + +
+
+

Everything API driven.

+

+ Offering seamless integration in your current tech stack and tools! +

+
+
+ + + +
+
+
+

Does it resonate with you?

+

Join The Waitlist.

+
+
+ +
+ + + +
+
+
+
+ + + +<%= render "_footer.html", conn: @conn %>