Skip to content

Commit

Permalink
add project creation membership
Browse files Browse the repository at this point in the history
  • Loading branch information
yujonglee committed Oct 19, 2024
1 parent de4c71b commit 7821071
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 5 deletions.
11 changes: 11 additions & 0 deletions core/lib/canary/accounts/project.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ defmodule Canary.Accounts.Project do
domain: Canary.Accounts,
data_layer: AshPostgres.DataLayer,
extensions: [AshArchival.Resource],
authorizers: [Ash.Policy.Authorizer],
simple_notifiers: [Canary.Notifiers.Discord]

require Ash.Query
Expand Down Expand Up @@ -82,6 +83,16 @@ defmodule Canary.Accounts.Project do
define :select, args: [:account_id], action: :select
end

policies do
policy action_type(:create) do
authorize_if Canary.Checks.Membership.ProjectCreate
end

policy always() do
authorize_if always()
end
end

postgres do
table "projects"
repo Canary.Repo
Expand Down
32 changes: 32 additions & 0 deletions core/lib/canary/checks/membership_project_create.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
defmodule Canary.Checks.Membership.ProjectCreate do
use Ash.Policy.SimpleCheck

def describe(_) do
"actor has correct membership to create project"
end

def match?(
%Canary.Accounts.Account{} = account,
%Ash.Policy.Authorizer{resource: Canary.Accounts.Project},
_opts
) do
with {:ok, %{billing: billing, num_projects: num_projects}} <-
Ash.load(account, [:billing, :num_projects]) do
cond do
is_nil(billing.stripe_subscription) and num_projects < 1 ->
{:ok, true}

not is_nil(billing.stripe_subscription) and num_projects < 3 ->
{:ok, true}

true ->
{:ok, false}
end
else
{:error, error} -> {:error, error}
error -> error
end
end

def match?(_, _, _), do: false
end
2 changes: 1 addition & 1 deletion core/lib/canary/checks/membership_source_create.ex
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
defmodule Canary.Checks.MembershipSourceCreate do
defmodule Canary.Checks.Membership.SourceCreate do
use Ash.Policy.SimpleCheck

def describe(_) do
Expand Down
2 changes: 1 addition & 1 deletion core/lib/canary/sources/source.ex
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ defmodule Canary.Sources.Source do

policies do
policy action_type(:create) do
authorize_if Canary.Checks.MembershipSourceCreate
authorize_if Canary.Checks.Membership.SourceCreate
end

policy always() do
Expand Down
22 changes: 19 additions & 3 deletions core/lib/canary_web/live/settings_live/create_project.ex
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ defmodule CanaryWeb.SettingsLive.CreateProject do

form =
Canary.Accounts.Project
|> AshPhoenix.Form.for_create(:create, forms: [auto?: true])
|> AshPhoenix.Form.for_create(:create,
forms: [auto?: true],
actor: socket.assigns.current_account
)
|> to_form()

{:ok, socket |> assign(:form, form)}
Expand All @@ -57,8 +60,21 @@ defmodule CanaryWeb.SettingsLive.CreateProject do
@impl true
def handle_event("submit", %{"form" => params}, socket) do
case AshPhoenix.Form.submit(socket.assigns.form, params: params) do
{:ok, _} -> {:noreply, socket |> push_navigate(to: ~p"/settings/projects")}
{:error, form} -> {:noreply, assign(socket, :form, form)}
{:ok, _} ->
{:noreply, socket |> push_navigate(to: ~p"/settings/projects")}

{:error,
%Phoenix.HTML.Form{source: %AshPhoenix.Form{source: %Ash.Changeset{errors: errors}}} = form} ->
if Enum.any?(errors, &match?(%Ash.Error.Forbidden.Policy{}, &1)) do
socket =
socket
|> push_navigate(to: ~p"/settings/projects")
|> put_flash(:error, "Please upgrade your plan.")

{:noreply, socket}
else
{:noreply, socket |> assign(:form, form)}
end
end
end
end

0 comments on commit 7821071

Please sign in to comment.