diff --git a/VERSION b/VERSION index b7fd43df7..b068c030e 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.5.12 \ No newline at end of file +1.5.13 \ No newline at end of file diff --git a/lib/logflare/billing.ex b/lib/logflare/billing.ex index bff3e8265..1005ebac7 100644 --- a/lib/logflare/billing.ex +++ b/lib/logflare/billing.ex @@ -14,6 +14,7 @@ defmodule Logflare.Billing do Billing.PaymentMethod } + alias Logflare.Partners alias Logflare.SingleTenant require Protocol @@ -329,6 +330,9 @@ defmodule Logflare.Billing do SingleTenant.single_tenant?() -> get_plan_by(name: "Enterprise") + Partners.user_upgraded?(user) -> + get_plan_by(name: "Enterprise") + user.billing_enabled == false -> legacy_plan() diff --git a/lib/logflare/partners.ex b/lib/logflare/partners.ex index 2dbdbf2b3..4ef57d814 100644 --- a/lib/logflare/partners.ex +++ b/lib/logflare/partners.ex @@ -116,4 +116,27 @@ defmodule Logflare.Partners do |> Multi.delete_all(:delete, query) |> Repo.transaction() end + + def user_upgraded?(%User{id: id}) do + query = + from(pu in PartnerUser, where: pu.user_id == ^id, select: pu.upgraded) + + Repo.one(query) || false + end + + def upgrade_user(p, u), do: do_upgrade_downgrade(p, u, true) + def downgrade_user(p, u), do: do_upgrade_downgrade(p, u, false) + + def do_upgrade_downgrade(%Partner{id: partner_id}, %User{id: user_id}, value) do + query = + from(pu in PartnerUser, + where: pu.partner_id == ^partner_id and pu.user_id == ^user_id, + select: pu + ) + + case Repo.update_all(query, set: [upgraded: value]) do + {1, [partner_user]} -> {:ok, partner_user} + _ -> {:error, :not_found} + end + end end diff --git a/lib/logflare/partners/partner_user.ex b/lib/logflare/partners/partner_user.ex index b893557ae..912020ddb 100644 --- a/lib/logflare/partners/partner_user.ex +++ b/lib/logflare/partners/partner_user.ex @@ -8,6 +8,7 @@ defmodule Logflare.Partners.PartnerUser do schema "partner_users" do belongs_to :partner, Logflare.Partners.Partner belongs_to :user, Logflare.User + field :upgraded, :boolean, default: false end def changeset(partner_user, params) do diff --git a/lib/logflare_web/controllers/api/partner/user_controller.ex b/lib/logflare_web/controllers/api/partner/user_controller.ex index f862b2653..aa6aea5d8 100644 --- a/lib/logflare_web/controllers/api/partner/user_controller.ex +++ b/lib/logflare_web/controllers/api/partner/user_controller.ex @@ -61,6 +61,20 @@ defmodule LogflareWeb.Api.Partner.UserController do end end + def upgrade(%{assigns: %{partner: partner}} = conn, %{"user_token" => user_token}) do + with user when not is_nil(user) <- Partners.get_user_by_token(partner, user_token), + {:ok, %_{}} <- Partners.upgrade_user(partner, user) do + json(conn, %{tier: "metered"}) + end + end + + def downgrade(%{assigns: %{partner: partner}} = conn, %{"user_token" => user_token}) do + with user when not is_nil(user) <- Partners.get_user_by_token(partner, user_token), + {:ok, %_{}} <- Partners.downgrade_user(partner, user) do + json(conn, %{tier: "free"}) + end + end + defp sanitize_response(user) do Enum.reduce(@allowed_fields, %{}, fn key, acc -> Map.put(acc, key, Map.get(user, key)) end) end diff --git a/lib/logflare_web/router.ex b/lib/logflare_web/router.ex index eaf71feee..37511bb7d 100644 --- a/lib/logflare_web/router.ex +++ b/lib/logflare_web/router.ex @@ -391,6 +391,8 @@ defmodule LogflareWeb.Router do get("/users", Api.Partner.UserController, :index) post("/users", Api.Partner.UserController, :create) + put("/users/:user_token/upgrade", Api.Partner.UserController, :upgrade) + put("/users/:user_token/downgrade", Api.Partner.UserController, :downgrade) get("/users/:user_token", Api.Partner.UserController, :get_user) get("/users/:user_token/usage", Api.Partner.UserController, :get_user_usage) diff --git a/priv/repo/migrations/20231213013433_add_upgraded_column_to_partner_users_table.exs b/priv/repo/migrations/20231213013433_add_upgraded_column_to_partner_users_table.exs new file mode 100644 index 000000000..da16b1847 --- /dev/null +++ b/priv/repo/migrations/20231213013433_add_upgraded_column_to_partner_users_table.exs @@ -0,0 +1,17 @@ +defmodule Logflare.Repo.Migrations.AddUpgradedColumnToPartnerUsersTable do + use Ecto.Migration + + def up do + + alter table(:partner_users) do + add :upgraded, :boolean, default: false, null: false + end + end + + def down do + + alter table(:partner_users) do + remove :upgraded + end + end +end diff --git a/test/logflare/billing_test.exs b/test/logflare/billing_test.exs index 7e3193fa9..e45830f51 100644 --- a/test/logflare/billing_test.exs +++ b/test/logflare/billing_test.exs @@ -2,6 +2,8 @@ defmodule Logflare.BillingTest do use Logflare.DataCase alias Logflare.{User, Billing, Billing.BillingAccount, Billing.PaymentMethod, Billing.Plan} + alias Logflare.Partners + describe "billing accounts" do @valid_attrs %{stripe_customer: "some stripe id"} @update_attrs %{stripe_customer: "some stripe other id"} @@ -216,6 +218,19 @@ defmodule Logflare.BillingTest do assert %Plan{name: "Custom"} = Billing.get_plan_by_user(ba.user) end + test "get_plan_by_user/1 with partner upgrade/downgrade" do + insert(:plan, name: "Free") + insert(:plan, name: "Enterprise") + user = insert(:user) + partner = insert(:partner, users: [user]) + assert %Plan{name: "Free"} = Billing.get_plan_by_user(user) + # upgrade user + Partners.upgrade_user(partner,user ) + assert %Plan{name: "Enterprise"} = Billing.get_plan_by_user(user) + + + end + test "change_plan/1 returns changeset" do plan = insert(:plan) assert %Ecto.Changeset{} = Billing.change_plan(plan) diff --git a/test/logflare/partners_test.exs b/test/logflare/partners_test.exs index fc3227556..4149246a5 100644 --- a/test/logflare/partners_test.exs +++ b/test/logflare/partners_test.exs @@ -2,6 +2,7 @@ defmodule Logflare.PartnerTest do use Logflare.DataCase alias Logflare.Partners + alias Logflare.Partners.PartnerUser alias Logflare.Repo alias Logflare.User @@ -102,4 +103,19 @@ defmodule Logflare.PartnerTest do assert {:error, :not_found} = Partners.delete_user(partner, user) end end + + test "upgrade_user/2, downgrade_user/2, user_upgraded?/1" do + user = insert(:user) + partner = insert(:partner, users: [user]) + assert Partners.user_upgraded?(user) == false + assert {:ok, %PartnerUser{upgraded: true}} = Partners.upgrade_user(partner, user) + assert Partners.user_upgraded?(user) + assert {:ok, %PartnerUser{upgraded: false}} = Partners.downgrade_user(partner, user) + assert Partners.user_upgraded?(user) == false + + assert Partners.user_upgraded?(insert(:user)) == false + + assert {:error, :not_found} = Partners.upgrade_user(partner, insert(:user)) + end + end diff --git a/test/logflare_web/controllers/api/partner/user_controller_test.exs b/test/logflare_web/controllers/api/partner/user_controller_test.exs index f7b20167f..ad738eb21 100644 --- a/test/logflare_web/controllers/api/partner/user_controller_test.exs +++ b/test/logflare_web/controllers/api/partner/user_controller_test.exs @@ -134,6 +134,29 @@ defmodule LogflareWeb.Api.Partner.UserControllerTest do end end + describe "PUT user tiers" do + test "upgrade/downgrade", %{conn: conn} do + user = insert(:user) + partner = insert(:partner, users: [user]) + + # upgrade + assert %{"tier"=> "metered"} = + conn + |> add_partner_access_token(partner) + |> put(~p"/api/partner/users/#{user.token}/upgrade") + |> json_response(200) + + # downgrade + assert %{"tier"=> "free"} = + conn + |> recycle() + |> add_partner_access_token(partner) + |> put(~p"/api/partner/users/#{user.token}/downgrade") + |> json_response(200) + + end + end + describe "GET user usage" do test "returns 200 and the usage for a given user", %{ conn: conn,