Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restricted routes should work without can permissions #777

Open
Tal-Shavit opened this issue Jan 16, 2025 · 2 comments
Open

Restricted routes should work without can permissions #777

Tal-Shavit opened this issue Jan 16, 2025 · 2 comments

Comments

@Tal-Shavit
Copy link

Tal-Shavit commented Jan 16, 2025

Describe the bug
When I add only: [:index] in the router, I get an error no match of right hand side value: nil.
To fix this, I need to add can to allow only the index action, or not allow the new action. But it shouldn’t be like that. Once I allow the route for index only, I shouldn’t need to add can, it should directly create the route for index only.

To Reproduce
Steps to reproduce the behavior:

  1. Configurer live_resources route with only: [:index] or use except: [:new].
  2. Visit index page.
  3. See the error.

Expected behavior
When using only: [:index] in the router, the index action should work without requiring explicit can permissions.

Please complete the following information:
OS: MacOS
Browser Checked on Chrome, Safari, Firefox
Elixir Version 1.17.2
Backpex Version 0.10.0

Code example

Mix.install([
  {:phoenix_playground, "~> 0.1.6"},
  {:backpex, "~> 0.10.0"},
  {:phoenix_pubsub, "~> 2.1"}
])

defmodule CustomAdapter do
  use Backpex.Adapter
  require Logger

  @impl Backpex.Adapter
  def get(_id, _assigns, _live_resource) do
    raise "not implemented yet"
  end

  @impl Backpex.Adapter
  def get!(id, _assigns, _live_resource) do
    %{id: "1", name: "Ido"}
  end

  @impl Backpex.Adapter
  def list(_fields, assigns, _config, criteria) do
    [%{id: "1", name: "Ido"}]
  end

  @impl Backpex.Adapter
  def count(_fields, _assigns, _config, _criteria) do
    100
  end

  @impl Backpex.Adapter
  def delete_all(_items, _live_resource) do
    raise "not implemented yet"
  end

  @impl Backpex.Adapter
  def insert(_item, _config) do
    raise "not implemented yet"
  end

  @impl Backpex.Adapter
  def update(_item, _config) do
    raise "not implemented yet"
  end

  @impl Backpex.Adapter
  def update_all(_items, _updates, _config) do
    raise "not implemented yet"
  end

  @impl Backpex.Adapter
  def change(_item, _attrs, _fields, _assigns, _config, _opts) do
    raise "not implemented yet"
  end
end

defmodule BackpexDemoLive do
  use Phoenix.LiveView

  use Backpex.LiveResource,
    adapter: CustomAdapter,
    adapter_config: [],
    layout: {BackpexDemoLive, :layout},
    pubsub: [
      name: :pubsub,
      topic: "admin:brands",
      event_prefix: "brands_"
    ]

  @impl Backpex.LiveResource
  def singular_name, do: "Brand"

  @impl Backpex.LiveResource
  def plural_name, do: "Brands"

  @impl Backpex.LiveResource
  def item_actions(default_actions) do
    default_actions
    |> Keyword.drop([:delete])
    |> Keyword.drop([:edit])
  end

  @impl Backpex.LiveResource

  # def can?(_assigns, :index, _item), do: true

  # def can?(_assigns, _action, _item), do: false

  @impl Backpex.LiveResource
  def fields do
    [
      id: %{
        module: Backpex.Fields.Text,
        label: "Id",
        only: [:index]
      },
      name: %{
        module: Backpex.Fields.Text,
        label: "Name",
        only: [:index]
      }
    ]
  end

  def layout(assigns) do
    assigns = assign(assigns, :current_url, "/")

    ~H"""
    <Backpex.HTML.Layout.app_shell fluid={@fluid?}>
      <:topbar>
        <Backpex.HTML.Layout.topbar_branding />

        <Backpex.HTML.Layout.topbar_dropdown>
          <:label>
            <label tabindex="0" class="btn btn-square btn-ghost">
              label
            </label>
          </:label>
          <li>
            <.link navigate="/" class="flex justify-between text-red-600 hover:bg-gray-100">
              <p>Logout</p>
            </.link>
          </li>
        </Backpex.HTML.Layout.topbar_dropdown>
      </:topbar>
      <:sidebar></:sidebar>
      <Backpex.HTML.Layout.flash_messages flash={@flash} />
      {@inner_content}
    </Backpex.HTML.Layout.app_shell>
    """
  end
end

defmodule DemoRouter do
  use Phoenix.Router
  import Phoenix.LiveView.Router
  import Backpex.Router

  pipeline :browser do
    plug :accepts, ["html"]
    plug :fetch_session
    plug :put_root_layout, html: {PhoenixPlayground.Layout, :root}
    plug :put_secure_browser_headers
  end

  scope "/demo" do
    pipe_through :browser

    backpex_routes()

    live_session :default, on_mount: Backpex.InitAssigns do
      live_resources("/", BackpexDemoLive, only: [:index])
    end
  end
end

children = [
  {Phoenix.PubSub, name: :pubsub}
]

Supervisor.start_link(children, strategy: :one_for_one)

PhoenixPlayground.start(plug: DemoRouter)

Note: To fix the issue, remove can from the comment.

@clifinger
Copy link

clifinger commented Jan 17, 2025

You can add also ->

# in your live resource

@impl Backpex.LiveResource
def can?(_assigns, :new, _item) do
  false
end

@Tal-Shavit Tal-Shavit changed the title New button appears even when it is not supposed to be displayed Restricted routes should work without can permissions Feb 2, 2025
@Tal-Shavit
Copy link
Author

Tal-Shavit commented Feb 2, 2025

@clifinger
Hi, thank you very much for the response!
I’ve updated the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants