Skip to content

Commit

Permalink
prevent free plan to access ask endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
yujonglee committed Oct 28, 2024
1 parent 7e6ae39 commit 8ad75c2
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 3 deletions.
45 changes: 43 additions & 2 deletions core/lib/canary/interface/controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ defmodule CanaryWeb.Interface.Controller do

@canary_id_header "x-canary-operation-id"

plug :rate_limit when action in [:search, :ask]
plug :set_operation_id when action in [:search, :ask]
plug :find_project when action in [:search, :ask]
plug :rate_limit when action in [:search, :ask]
plug :prevent_free_plan when action in [:ask]

defp set_operation_id(conn, _opts) do
conn |> put_resp_header(@canary_id_header, Ecto.UUID.generate())
Expand All @@ -26,19 +27,59 @@ defmodule CanaryWeb.Interface.Controller do
end

defp find_project(conn, _opts) do
err_msg = "no client found with the given key"
action = Phoenix.Controller.action_name(conn)

err_msg = "no project found with the given key"

with {:ok, token} <- get_token_from_header(conn),
{:ok, project} <-
Canary.Accounts.Project
|> Ash.Query.filter(public_key == ^token)
|> wrap_project_query(action)
|> Ash.read_one(not_found_error?: true) do
conn |> assign(:project, project)
else
_ -> conn |> send_resp(401, err_msg) |> halt()
end
end

defp prevent_free_plan(conn, _opts) do
err_msg = "can not access this with free plan"

cond do
Application.get_env(:canary, :env) != :prod ->
conn

conn.host == "cloud.getcanary.dev" ->
conn

not Canary.Membership.can_use_ask?(conn.assigns.project.account) ->
conn |> send_resp(403, err_msg) |> halt()

true ->
conn |> send_resp(403, err_msg) |> halt()
end
end

defp wrap_project_query(query, action) do
if action == :search do
query
else
billing_query =
Canary.Accounts.Billing
|> Ash.Query.select([:id])
|> Ash.Query.load(:membership)

account_query =
Canary.Accounts.Account
|> Ash.Query.select([:id])
|> Ash.Query.load(billing: billing_query)

query
|> Ash.Query.load(account: account_query)
end
end

defp get_token_from_header(conn) do
case get_req_header(conn, "authorization") do
["Bearer " <> token] -> {:ok, token}
Expand Down
11 changes: 11 additions & 0 deletions core/lib/canary/membership.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,17 @@ defmodule Canary.Membership do
end
end

def can_use_ask?(%Canary.Accounts.Account{} = account) do
account = ensure_membership(account)

case account.billing.membership.tier do
:free -> false
:starter -> true
:admin -> true
_ -> false
end
end

def max_sources(%Canary.Accounts.Account{} = account) do
account = ensure_membership(account)

Expand Down
9 changes: 8 additions & 1 deletion core/lib/canary_web/live/example_live/example.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,14 @@ defmodule CanaryWeb.ExampleLive.Example do
~H"""
<div class="border border-gray-200 py-4 px-6 rounded-md">
<h2><%= @example.name %></h2>
<p :if={@example[:description]} class="italic mb-4"><%= @example.description %></p>
<div class="flex flex-col mb-4 italic">
<p :if={@example[:description]} class="italic"><%= @example.description %></p>
<span :if={@example[:paid]} class="text-red-700">
This is not available in the free plan.
</span>
</div>
<div class="flex flex-col gap-0 mt-2">
<div class="text-md mb-2">
Expand Down
3 changes: 3 additions & 0 deletions core/lib/canary_web/live/example_live/examples.ex
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ defmodule CanaryWeb.ExampleLive.Examples do
has_webpage and has_github and tags != "" ->
%{
name: "Search with Ask AI",
paid: true,
description: "Type longer question, and press tab to run 'Ask AI'.",
code: """
<canary-root query="why use #{assigns.current_project.name}?">
Expand All @@ -164,6 +165,7 @@ defmodule CanaryWeb.ExampleLive.Examples do
has_webpage and has_github and tags == "" ->
%{
name: "Search with Ask AI",
paid: true,
description: "Type longer question, and press tab to run 'Ask AI'.",
code: """
<canary-root query="why use #{assigns.current_project.name}?">
Expand All @@ -189,6 +191,7 @@ defmodule CanaryWeb.ExampleLive.Examples do
true ->
%{
name: "Search with Ask AI",
paid: true,
description: "Type longer question, and press tab to run 'Ask AI'.",
code: """
<canary-root query="why use #{assigns.current_project.name}?">
Expand Down

0 comments on commit 8ad75c2

Please sign in to comment.