GithubHelp home page GithubHelp logo

ash-project / ash_json_api Goto Github PK

View Code? Open in Web Editor NEW
52.0 10.0 34.0 1.77 MB

The JSON:API extension for the Ash Framework

Home Page: https://hexdocs.pm/ash_json_api

License: MIT License

Elixir 100.00%
ash json-api elixir

ash_json_api's Introduction

ash_json_api's People

Contributors

adonig avatar andrewcallahan avatar bcksl avatar dependabot[bot] avatar franckstifler avatar gerbal avatar gordoneliel avatar janajri avatar jimsynz avatar jsw800 avatar mangeption avatar mohammedzeglam-pg avatar mrdotb avatar muej avatar olivermt avatar peillis avatar rbino avatar rodeoclash avatar ryanrborn avatar sevenseacat avatar skanderm avatar srikanthkyatham avatar thefirstavenger avatar thetamind avatar tommasop avatar transhaphigsn avatar vbrazo avatar willemodendaal avatar zachdaniel avatar zimt28 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ash_json_api's Issues

JSON-API Related() Seems Broken

Hi, 👋 there seems to be a regression in the JSON-API: It worked nicely (after you did a fix a couple of weeks ago), but after updating packages to the newest ones, I get an exception.

Here’s the relation:

related(:events, :events_by_extid) do
  route("/:extid/events")
end

This is the exception I get:

[error] #PID<0.3383.0> running TickerWeb.Endpoint (connection #PID<0.3382.0>, stream id 1) terminated
Server: localhost:4000 (http)
Request: GET /api/eventhub/alarms/R%201.5%20230310%201956/events
** (exit) an exception was raised:
    ** (UndefinedFunctionError) function :events.name/0 is undefined (module :events is not available)
        :events.name()
        (ash_json_api 0.32.0) lib/ash_json_api/controllers/helpers.ex:348: anonymous fn/1 in AshJsonApi.Controllers.Helpers.fetch_related/2
        (ash_json_api 0.32.0) lib/ash_json_api/controllers/get_related.ex:20: AshJsonApi.Controllers.GetRelated.call/2
        (ticker 0.1.0) deps/plug/lib/plug/router.ex:246: anonymous fn/4 in TickerWeb.Api.Router.dispatch/2
        [...]
        (cowboy 2.10.0) deps/cowboy/src/cowboy_handler.erl:37: :cowboy_handler.execute/2
        (cowboy 2.10.0) deps/cowboy/src/cowboy_stream_h.erl:306: :cowboy_stream_h.execute/3
        (cowboy 2.10.0) deps/cowboy/src/cowboy_stream_h.erl:295: :cowboy_stream_h.request_process/3
        (stdlib 4.3.1.1) proc_lib.erl:240: :proc_lib.init_p_do_apply/3

Here are the packages I’m using (I tried it with the newest release of ash_json_api as well as the head):

defp deps do
  [
    {:absinthe_plug, "~> 1.5.8"},
    {:ash, "~> 2.10.2"},
    {:ash_authentication, "~> 3.11.6"},
    {:ash_graphql, "~> 0.25.10"},
    # {:ash_json_api, "~> 0.32.0"},
    {:ash_json_api, git: "https://github.com/ash-project/ash_json_api.git", build: "main"},
    {:ash_postgres, "~> 1.3.30"},
    {:cors_plug, "~> 3.0.3"},
    {:elixir_sense, ">= 1.0.0", only: [:dev, :test]},
    {:ecto_sql, "~> 3.10.1"},
    {:ecto_sqlite3, ">= 0.10.3"},
    {:ex_phone_number, "== 0.3.0"},
    {:guardian, "~> 2.3.1"},
    {:haversine, "~> 0.1.0"},
    {:jason, "~> 1.2"},
    {:jose, "~> 1.11"},
    {:open_api_spex, "~> 3.17.3"},
    {:picosat_elixir, "~> 0.2.3"},
    {:phoenix, "~> 1.6.16"},
    {:phoenix_ecto, "~> 4.4.2"},
    {:phoenix_html, "~> 3.3.1"},
    {:plug_cowboy, "~> 2.6.1"},
    {:postgrex, "~> 0.16.5"},
    {:telemetry_metrics, "~> 0.6"},
    {:telemetry_poller, "~> 1.0"},
    {:tesla, "~> 1.6.0"}
  ]
end

Thanks for having a look! ❤️

Policies-setup missing for certain queries

Hi, I’m not sure whether this really is a bug, but for two JSON-API read-requests I get different resolution of the policies — one index and one get, but both share the same policy. I debugged along the stack trace (see below and can’t find the reason, why the policies of the same actor stay empty in the one and are populated with what I would expect in the other case.

Both share this policy:

policies do
  policy action_type(:read) do
    authorize_if(Ticker.Checks.ValidActorProvided)
  end
end

This one runs into an exception:

QUERY A: #Ash.Query<resource: Ticker.Accounts.User,
 filter: #Ash.Filter<extid == "bwb-257064">>
Request: GET /api/eventhub/users/bwb-257064
** (exit) an exception was raised:
    ** (Protocol.UndefinedError) protocol Enumerable not implemented for nil of type Atom
        (elixir 1.15.3) lib/enum.ex:1: Enumerable.impl_for!/1
        (elixir 1.15.3) lib/enum.ex:166: Enumerable.reduce/3
        (elixir 1.15.3) lib/enum.ex:4387: Enum.reduce/3
        (ash 2.14.0) lib/ash/policy/policy.ex:108: Ash.Policy.Policy.at_least_one_policy_expression/2
        (ash 2.14.0) lib/ash/policy/policy.ex:61: Ash.Policy.Policy.build_requirements_expression/2
        (ash 2.14.0) lib/ash/policy/policy.ex:26: Ash.Policy.Policy.solve/1
        (ash 2.14.0) lib/ash/policy/checker.ex:83: Ash.Policy.Checker.strict_check_scenarios/1
        (ash 2.14.0) lib/ash/policy/authorizer/authorizer.ex:1142: Ash.Policy.Authorizer.strict_check_result/2
        (ash 2.14.0) lib/ash/policy/authorizer/authorizer.ex:631: Ash.Policy.Authorizer.expression_for_field/5
        (ash 2.14.0) lib/ash/policy/authorizer/authorizer.ex:561: Ash.Policy.Authorizer.replace_refs/2
        (ash 2.14.0) lib/ash/policy/authorizer/authorizer.ex:518: Ash.Policy.Authorizer.alter_filter/3
        (ash 2.14.0) lib/ash/engine/request.ex:659: Ash.Engine.Request.alter_filter/2
        (ash 2.14.0) lib/ash/engine/request.ex:556: Ash.Engine.Request.do_strict_check/3
        (ash 2.14.0) lib/ash/engine/request.ex:524: anonymous fn/2 in Ash.Engine.Request.strict_check/2
        (elixir 1.15.3) lib/enum.ex:4830: Enumerable.List.reduce/3
        (elixir 1.15.3) lib/enum.ex:2564: Enum.reduce_while/3
        (ash 2.14.0) lib/ash/engine/request.ex:257: Ash.Engine.Request.do_next/1
        (ash 2.14.0) lib/ash/engine/request.ex:213: Ash.Engine.Request.next/1
        (ash 2.14.0) lib/ash/engine/engine.ex:712: Ash.Engine.advance_request/2
        (ash 2.14.0) lib/ash/engine/engine.ex:637: Ash.Engine.fully_advance_request/2

While this one works (deliberatly halted with an exception in match? to get the stack trace):

QUERY B: #Ash.Query<
  resource: Ticker.Accounts.User,
  arguments: %{
    search: "Jan"
  }
>
Request: GET /api/eventhub/users?search=Jan
** (exit) an exception was raised:
    ** (RuntimeError) DELIBERATELY HALTED
        (ticker 0.1.0) lib/ticker/checks.ex:63: Ticker.Checks.ValidActorProvided.match?/3
        (ticker 0.1.0) lib/ticker/checks.ex:56: Ticker.Checks.ValidActorProvided.strict_check/3
        (ash 2.14.0) lib/ash/policy/policy.ex:164: Ash.Policy.Policy.fetch_or_strict_check_fact/2
        (ash 2.14.0) lib/ash/policy/policy.ex:480: Ash.Policy.Policy.compile_policy_expression/2
        (ash 2.14.0) lib/ash/policy/policy.ex:319: Ash.Policy.Policy.compile_policy_expression/2
        (ash 2.14.0) lib/ash/policy/policy.ex:68: Ash.Policy.Policy.build_requirements_expression/2
        (ash 2.14.0) lib/ash/policy/policy.ex:26: Ash.Policy.Policy.solve/1
        (ash 2.14.0) lib/ash/policy/checker.ex:83: Ash.Policy.Checker.strict_check_scenarios/1
        (ash 2.14.0) lib/ash/policy/authorizer/authorizer.ex:1142: Ash.Policy.Authorizer.strict_check_result/2
        (ash 2.14.0) lib/ash/policy/authorizer/authorizer.ex:493: Ash.Policy.Authorizer.strict_check/2
        (ash 2.14.0) lib/ash/engine/request.ex:558: Ash.Engine.Request.do_strict_check/3
        (ash 2.14.0) lib/ash/engine/request.ex:524: anonymous fn/2 in Ash.Engine.Request.strict_check/2
        (elixir 1.15.3) lib/enum.ex:4830: Enumerable.List.reduce/3
        (elixir 1.15.3) lib/enum.ex:2564: Enum.reduce_while/3
        (ash 2.14.0) lib/ash/engine/request.ex:257: Ash.Engine.Request.do_next/1
        (ash 2.14.0) lib/ash/engine/request.ex:213: Ash.Engine.Request.next/1
        (ash 2.14.0) lib/ash/engine/engine.ex:712: Ash.Engine.advance_request/2
        (ash 2.14.0) lib/ash/engine/engine.ex:637: Ash.Engine.fully_advance_request/2
        (ash 2.14.0) lib/ash/engine/engine.ex:578: Ash.Engine.do_run_iteration/2
        (elixir 1.15.3) lib/enum.ex:2510: Enum."-reduce/3-lists^foldl/2-0-"/3

Versions are most recent as of this writing (and both queries run nicely in production with older versions of the framework):

absinthe_plug: 1.5.8
ash: 2.14.0
ash_authentication: 3.11.7
ash_graphql: 0.25.13
ash_json_api: 0.33.0
ash_postgres: 1.3.41

Validate filter fields

Right now, we don't validate that filters/sorts only use the fields exposed in the json api, which would be a big problem if someone used this in production (if anyone is reading this issue, and ash is still in alpha, and you used it in production and somehow exposed some data about your system, it is your fault :) )

Ash json api don't work with aggregates

Describe the bug
A read action will not work with JSON API if that action uses an aggregate.

To Reproduce

I have a resource that has this aggregate:

  aggregates do
    first :last_bid_price, :bids, :price do
      sort inserted_at: :desc
    end
  end

If I add json api for that resource like this:

  json_api do
    type "property"

    routes do
      base "/property"

      index :read
    end
  end

If I try to get that resource with curl 'localhost:4000/api/markets/property' I will get this error:

[error] #PID<0.811.0> running Phoenix.Endpoint.SyncCodeReloadPlug (connection #PID<0.810.0>, stream id 1) terminated
Server: localhost:4000 (http)
Request: GET /api/markets/property
** (exit) an exception was raised:
    ** (MatchError) no match of right hand side value: {:error, "Must provide field type for first"}
        (ash_json_api 0.31.1) lib/ash_json_api/json_schema/json_schema.ex:506: anonymous fn/2 in AshJsonApi.JsonSchema.filter_props/1
...

Which happens in the json_schema.ex:505 file.

This is what the agg variable has at the time the error happens:

 %Ash.Resource.Aggregate{
  name: :last_bid_price,
  relationship_path: [:bids],
  filter: [],
  kind: :first,
  implementation: nil,
  constraints: nil,
  type: nil,
  description: nil,
  private?: false,
  field: :price,
  sort: [inserted_at: :desc],
  default: nil,
  filterable?: true
}

This means that the function is called with: Aggregate.kind_to_type(:first, nil)

Expected behavior
The JSON API should work fine with aggregates

** Runtime

  • Elixir version 1.14.0
  • Erlang version 25
  • OS Ubuntu 22.10
  • Ash version 2.5.16
  • any related extension versions ash_json_api: 0.31.1

Resource links use conn url instead of Endpoint url

I'm using a service backed by ash behind a gateway. When I request a resource, the links generated use the request url instead of the url configured by the endpoint. Ideally I think we should be using 'Endpoint.url()' as the base url for resource links instead of the conn url as links will be incorrect when behind a proxy.

Happy to take this on if it makes sense!

List query params causes a crash

Describe the bug
When filtering with list values eg. filter[status][in][0]=a&filter[status][in][1]=b, ash logs an error in the query because it does not handle list params.

To Reproduce
Create an enum attribute status with values [:a, :b, :c].
Pass in for filters in a query: filter[status][in][0]=a&filter[status][in][1]=b

Ash query will embed an error:

  errors: [
    %Ash.Error.Unknown.UnknownError{
      error: "filter: Could not cast expression: Ash.Query.Operator.In status %{\"0\" => \"active\"}",
      field: nil,
      changeset: nil,
      query: nil,
      error_context: [],
      vars: [],
      path: [:filter],
      stacktrace: #Stacktrace<>,
      class: :unknown
    }
  ]

Expected behavior
Should handle list query params and filter

** Runtime

  • Elixir version: 1.15.4
  • Erlang version: 26.0.2
  • OS: macos
  • Ash version: 2.13.2

Expand the example documentation

  • include an example API with json_api configured
  • remove some of the long form info and put into a wiki/begin the long form tutorial with it
  • remove some of the explanations of how resources work, in favor of putting that in ash core and linking people there.

Bug with href-schema prevents the use of all kinds of filters

Describe the bug
Trying to use the is_nil filter on a string field raises an InvalidQuery error:

Expected "string", got %{"is_nil" => "false"}, at ["filter", "string_field"].

To Reproduce
Try something like /api/resources?filter[string_field][is_nil]=false

Expected behavior
It should respond with resources where the string field is not nil.

Runtime

  • Elixir 1.15.6
  • Erlang 26.1.1
  • Fedora Linux 38
  • Ash 2.15.7
  • AshJsonApi 0.33.1

Additional context
The problem seems to be that the href_schema expects the field's filter to be of type string.

Cannot POST with JSON:API structured data to create an entry with a relationship, "Expected only defined properties"

Describe the bug
A clear and concise description of what the bug is. If you are not sure if the bug is related to ash or an extension, log it with ash and we will move it.
Following the instructions for Getting started with Ash and Phoenix which adds ash_json_api, when trying to POST to create a tweet and associate it with a user,

To Reproduce

Follow the instructions, or just clone the repo where I pushed up my code

https://github.com/faheetah/ash_my_app

Create a user, get the ID, then send a POST, the following snippet returns error "Expected only defined properties, got key ["data", "relationships", "user"]." despite conforming to JSON:API structure

user_id = Ash.Changeset.new(MyApp.User, %{email: "a@localhost"}) |> MyApp.Api.create! |> Map.get(:id)

tweet_data = %{data: %{attributes: %{body: "body", public: false}, relationships: %{user: %{data: %{id: user_id, type: "user"}}}, type: "tweet"}}

HTTPoison.post!("http://localhost:4000/api/tweets", Poison.encode!(tweet_data), [{"Content-type", "application/vnd.api+json"}]).body |> Poison.decode

Also adding the following:

action :create do
  argument :user, :map, allow_nil?: false #arguments are sent with attributes in json:api
  # change is like `plug` but for resource actions
  # `manage_relationship` is documented in `Ash.Changeset` and supports *tons* of options
  # you can read more about both in the docs
  change manage_relationship(:user, type: :replace)
end

Then using the following for the POST payload gives "detail" => "Expected only defined properties, got key ["data", "attributes", "user"]."

tweet_data = %{data: %{type: "tweet", attributes: %{body: "body", public: false, user: user_id}}}

Expected behavior

Creates a tweet associated to the user

** Runtime

  • Elixir version Elixir 1.11.2
  • Erlang version Erlang/OTP 23 [erts-11.1.7]
  • OS Ubuntu 20.04 WSL on Win10
  • Ash version 1.39.5
  • any related extension versions ash_postgres 0.36.2
  • This is on ash_json_api 0.27.6

Additional context

Referencing conversation: https://discord.com/channels/711271361523351632/799097774523547669/830259720245608458

Group Api resources as a single tag or provide an option

Is your feature request related to a problem? Please describe.
It looks odd that each resource is grouped on its own rather than getting grouped by api as they are the domain and can define a prefix. It makes the docs not clear how the domains are separated.

Describe the solution you'd like
AshJsonApi.Api should group the resources under one collapsible in swagger. There seems to be documented way to achieve https://swagger.io/docs/specification/grouping-operations-with-tags/

Adjust routing so that it shows up in `mix phx.routes`

Is your feature request related to a problem? Please describe.
Currently mix phx.routes doesn't show the routes that we create.

Describe the solution you'd like
Spoke to Chris Mccord about this, and he says that we can probably write a feature for Plug.Router to hook this up.

Describe alternatives you've considered

If that's not reasonable, we can move away from a Plug.Router, which may be acceptable also. So instead of forwarding to a Plug.Router we would just call a macro in the router that would define all of their routes in-line.

Validate/verify routes

We need to validate that there are no overlapping routes, and that route order doesn't cause problems. The current implementation just sorts by the number of colons, which may be enough.

Make relationship routes leverage `manage_relationship` changes instead of using the bypass

At the moemnt, the code for things like add_to_relationship is actually using what is now currently considered an escape hatch, i.e:

      result
      |> Ash.Changeset.new()
      |> Ash.Changeset.append_to_relationship(relationship_name, request.resource_identifiers)
      |> Ash.Changeset.for_update(action, %{}, Request.opts(request))
      |> api.update()

We should instead require that these routes choose an action that has an argument of a specific name, and then those actions will be used. i.e

post_to_relationship :comments, :update, :add_comments

Validate includes paths

We should validate that each include path is actually a valid path through the resource's relationships.

Support Date Type

Is your feature request related to a problem? Please describe.
I can't support date types that are used in Ash

Describe the solution you'd like
I'd like to be able to use dates in Ash JSON:API. I would expect that dates would be serialized and deserialized in the YYYY-MM-DD format.

Describe alternatives you've considered
N/A

Express the feature either with a change to resource syntax, or with a change to the resource interface
N/A

Additional context
N/A

Support exclude/include resources to only show some resources in the API

Is your feature request related to a problem? Please describe.
Per this issue: ash-project/ash#36 you need to include all referenced resources in the Ash.Api, but we may want to limit which resources appear in the external interface. This would be done by configuration in ash_json_api.

  ash_json_api do
    resources [:foo, :bar]
  end

  # or

  ash_json_api do
    exclude_resources: [:foo, :bar]
  end

Support member name transformers

Currently, everything is snake_case but we want to let users configure a name transformer at the API level, to turn everything into kebab case or camelcase.

Support nested boolean filters

We can support boolean filters with nested statements like:

{
  "or": [
    {"name": "zach"},
    {"and": [
      {"foo": 1},
      {"bar": 2}
    ]}
  ]
}

Change how relationship routes work

Right now, relationship routes use changeset level escape hatches like Ash.Changeset.append_to_relationship. What we should do, instead, is require that an action exists that accepts the relevant input. This allows customizing the behavior, and also makes it much more conventional.

filtering by some integer value is not possible

Consider for example an url like /device_screens?filter[screen_id]=12, it gives the following error:

{
    "errors": [
        {
            "code": "InvalidQuery",
            "detail": "Expected \"integer\", got \"1\", at [\"filter\", \"screen_id\"].",
            "id": "c4c36828-785f-4317-b662-2371abcf95a6",
            "source": {
                "parameter": "filter[screen_id]"
            },
            "status": 400,
            "title": "Invalid Query"
        }
    ],
    "jsonapi": {
        "version": "1.0"
    }
}

Query parameter not passed as argument

Describe the bug
On mutation the query/path params are not passed as arguments

To Reproduce

If we have route with parameter and we use this parameter as argument for mutation action:

routes do
  post :for_tracker, route: "/trackers/:tracker_id/option"
end

actions do
  create :for_tracker do
    argument :tracker_id, :string, allow_nil?: false
    ...
  end
end

It fails with Required properties are missing: [\"tracker_id\"]

Expected behavior
A path parameter is passed as argument to the action.

** Runtime

  • Elixir version: 1.14.4
  • Erlang version: 25.3
  • OS: Mac OS
  • Ash version: 2.9.5
  • any related extension versions

Additional context

It is not possible to use a generic action with ash_json_api

Is your feature request related to a problem? Please describe.
Right now it is not possible to use a generic action with ash_json_api unfortunately

Describe the solution you'd like
Add a warning in the docs that it is not possible to use a generic action with ash_json_api unfortunately
https://hexdocs.pm/ash_json_api/getting-started-with-json-api.html

Describe alternatives you've considered
You would need to make your own route/controller and call the action, and pass the result into our serializer

Express the feature either with a change to resource syntax, or with a change to the resource interface

Right now it is not possible to use a generic action with ash_json_api unfortunately

Additional context
https://discord.com/channels/711271361523351632/711271361523351636/1162969517845118976
image

Inconsistency between hex code and hexdocs

Describe the bug
I think a newer version of the hexdocs are available than the code.
The DSL for AshJsonApi.Resource includes "include_nil_values" in hexdocs, but version 0.33.1 code does not.
https://hexdocs.pm/ash_json_api/AshJsonApi.Resource.Info.html#include_nil_values?/1
https://github.com/ash-project/ash_json_api/blob/v0.33.1/lib/ash_json_api/resource/info.ex#L1

To Reproduce
Visit the provided URLs

Expected behavior
The DSL properties to exist

** Runtime

  • Ash JSON API version 0.33.1

error retrieving relationships (one to many)

Request: GET /models_api/1/screens/2/relationships/device_screens
** (exit) an exception was raised:
    ** (FunctionClauseError) no function clause matching in IO.chardata_to_string/1
        (elixir 1.11.2) lib/io.ex:589: IO.chardata_to_string(nil)
        (elixir 1.11.2) lib/path.ex:520: Path.join/2
        (ash_json_api 0.28.2) lib/ash_json_api/serializer.ex:538: AshJsonApi.Serializer.at_host/2
        (ash_json_api 0.28.2) lib/ash_json_api/serializer.ex:8: AshJsonApi.Serializer.serialize_to_many_relationship/4
        (ash_json_api 0.28.2) lib/ash_json_api/controllers/response.ex:77: AshJsonApi.Controllers.Response.render_many_relationship/4
        (layer 1.1.54) lib/plug/router.ex:284: Layer.Api.AshJsonApi.Api.Router.dispatch/2
        (layer 1.1.54) /home/enrique/jobs/ash_json_api/lib/ash_json_api/api/router.ex:62: Layer.Api.AshJsonApi.Api.Router.plug_builder_call/2
        (phoenix 1.5.9) lib/phoenix/router/route.ex:41: Phoenix.Router.Route.call/2
        (phoenix 1.5.9) lib/phoenix/router.ex:352: Phoenix.Router.__call__/2
        (layer 1.1.54) lib/layer_web/endpoint.ex:1: LayerWeb.Endpoint.plug_builder_call/2
        (layer 1.1.54) lib/layer_web/endpoint.ex:1: LayerWeb.Endpoint."call (overridable 3)"/2
        (layer 1.1.54) lib/plug/debugger.ex:136: LayerWeb.Endpoint."call (overridable 4)"/2
        (layer 1.1.54) lib/layer_web/endpoint.ex:1: LayerWeb.Endpoint.call/2
        (phoenix 1.5.9) lib/phoenix/endpoint/cowboy2_handler.ex:65: Phoenix.Endpoint.Cowboy2Handler.init/4
        (cowboy 2.9.0) /home/enrique/jobs/live-layer/deps/cowboy/src/cowboy_handler.erl:37: :cowboy_handler.execute/2
        (cowboy 2.9.0) /home/enrique/jobs/live-layer/deps/cowboy/src/cowboy_stream_h.erl:306: :cowboy_stream_h.execute/3
        (cowboy 2.9.0) /home/enrique/jobs/live-layer/deps/cowboy/src/cowboy_stream_h.erl:295: :cowboy_stream_h.request_process/3
        (stdlib 3.13.2) proc_lib.erl:226: :proc_lib.init_p_do_apply/3

Support fields on join tables

There was something in place for short period, but it was insufficient and was removed. We should support writing to and reading from join table via the meta field on the relevant resource identifiers.

Json Api Index action gives a read/1 not existing or private error

Describe the bug
I have a Category resource I need to filter by report_id

  actions do
    create :create do
      argument :report_id, :uuid do
        allow_nil? false
      end

      change manage_relationship(:report_id, :report, type: :append_and_remove)
    end

    read :read do
      argument :report_id, :uuid do
        allow_nil? false
      end

      filter expr(report_id == ^arg(:report_id))
    end

    read :report_categories do
      argument :report_id, :uuid do
        allow_nil? false
      end

      filter expr(report_id == ^arg(:report_id))
    end
  end

  json_api do
    # Specify a json:api resource type
    type "categories"

    routes do
      base "/categories"
      index :report_categories
    end

  end

If I try to get `http://localhost:4001/categories?report_id=c693adaa-144a-429d-9056-e2acda624fa0

I receive this error:

09:49:49.855 [error] #PID<0.566.0> running MmsBiztalkWeb.Router (connection #PID<0.565.0>, stream id 1) terminated
Server: localhost:4001 (http)
Request: GET /export_categories/categories?report_id=c693adaa-144a-429d-9056-e2acda624fa0
** (exit) an exception was raised:
    ** (UndefinedFunctionError) function MmsBiztalk.Support.Category.read/1 is undefined or private
        (mms_biztalk 0.1.0) MmsBiztalk.Support.Category.read(#Ash.Query<resource: MmsBiztalk.Support.Category, arguments: %{report_id: "c693adaa-144a-429d-9056-e2acda624fa0"}, filter: #Ash.Filter<report_id == "c693adaa-144a-429d-9056-e2acda624fa0">>)
        (ash_json_api 0.30.1) lib/ash_json_api/controllers/helpers.ex:56: anonymous fn/1 in AshJsonApi.Controllers.Helpers.fetch_records/1
        (ash_json_api 0.30.1) lib/ash_json_api/controllers/index.ex:20: AshJsonApi.Controllers.Index.call/2
        (mms_biztalk 0.1.0) lib/plug/router.ex:246: anonymous fn/4 in MmsBiztalkWeb.Plugs.CategoriesApi.dispatch/2
        (telemetry 1.1.0) /home/tommasop/code/work/magic/mms_biztalk/deps/telemetry/src/telemetry.erl:320: :telemetry.span/3
        (mms_biztalk 0.1.0) lib/plug/router.ex:242: MmsBiztalkWeb.Plugs.CategoriesApi.dispatch/2
        (mms_biztalk 0.1.0) lib/mms_biztalk_web/plugs/categories_api.ex:1: MmsBiztalkWeb.Plugs.CategoriesApi.plug_builder_call/2
        (plug 1.14.0) lib/plug.ex:168: Plug.forward/4

Expected behavior
I expect the action to return all the categories with report_id = c693adaa-144a-429d-9056-e2acda624fa0

** Runtime

  • Elixir 1.14
  • Erlang 25.1
  • OS PopOs 22.04
  • Ash version 2.4.2
  • Ash Json Api 0.30.1

Sorry I've been banned again from Discord and I'm not able to get access back :(

Compile Error

Describe the bug
I'm getting a compile error

== Compilation error in file lib/ash_json_api/test.ex ==
** (File.Error) could not read file "test/support/response_schema": no such file or directory
    (elixir 1.10.2) lib/file.ex:353: File.read!/1
    lib/ash_json_api/test.ex:10: (module)
    (stdlib 3.12) erl_eval.erl:680: :erl_eval.do_apply/6
could not compile dependency :ash_json_api, "mix compile" failed. You can recompile this dependency with "mix deps.compile ash_json_api", update it with "mix deps.update ash_json_api" or clean it with "mix deps.clean ash_json_api"

To Reproduce
run iex -S mix phx.server

Expected behavior
I expect my application to compile

** Runtime

  • Elixir version: 1.10.2
  • Erlang version: OTP/22
  • OS: Mac OS
  • Ash version: 0.3.0
  • any related extension versions: AshJsonApi: 0.1.4, AshPostgres 0.1.4

Additional context
N/A

undefined function routes/1

Describe the bug

== Compilation error in file lib/resources/behavior_plan_service.ex ==
** (CompileError) lib/resources/behavior_plan_service.ex:10: undefined function routes/1
    expanding macro: AshJsonApi.JsonApiResource.json_api/1
    lib/resources/behavior_plan_service.ex:6: Blueprint.BehaviorPlanService (module)
    (elixir 1.10.2) lib/kernel/parallel_compiler.ex:304: anonymous fn/4 in Kernel.ParallelCompiler.spawn_workers/7

To Reproduce

I have a resource with a json_api block like this

  json_api do
    fields [:behavior_plan, :service]
    include [:behavior_plan, :service]

    routes do
      index :default, primary?: true
      get :default, primary?: true
      post :default
      patch :default
      delete :default

      relationship_read_routes :behavior_plan
      relationship_change_routes :behavior_plan

      relationship_read_routes :service
      relationship_change_routes :service
    end
  end

I then ran iex -S mix phx.server

Expected behavior
This should compile

** Runtime

  • Elixir version: 1.10.2
  • Erlang version: OTP/22
  • OS: Mac OS
  • Ash version: 0.3.0
  • any related extension versions: AshPostgres 0.1.4, AshJsonApi 0.1.5

Additional context
N/A

Errors should have about pages

Currently, we can get a list of all ash json API errors, and we should use that to build an about page for each error.

Prefix is not appended to generated routes, only to the OpenAPI schema

Describe the bug
If one uses the prefix in Ash.Api this prefix is not included then the routes are generated, only for the routes in the schema

Maybe this line needs to also have some code to get the prefix for the route?
https://github.com/ash-project/ash_json_api/blob/v0.33.1/lib/ash_json_api/api/router.ex#L72

To Reproduce

defmodule MyLib.Ash.ApiCode do
  use Ash.Api, extensions: [AshJsonApi.Api]

  resources do
    registry MyLib.Ash.ApiRegistry
  end

  json_api do
    prefix "/myprefix"
  end
end

Resource:

json_api do
    type "myresource"

    routes do
      base("/myresource")
      get(:read)
    end
  end

This would generate routes in OpenAPI to say "/myprefix/myresource" but the route in the "Router" will be "/myresource"

** Runtime

  • Ash JSON API version 0.33.1

Support customizing the primary key

Right now, ash_json_api requires that an id field is the primary key. We should be able to support any field being the primary key, and we can also most likely support composite primary keys by stringifying/connecting the values. This only works on types that can be stringified, so that may need to be included in the type behaviour. Potentially, we can just look at the base type of the type and see if it can be stringified.

Version 0.32.0 causes Elixir compile error with OTP 25 and Elxir 1.14.1

Describe the bug

Error: ** (CompileError) elixir_compiler_18:1: function '-__MODULE__/1-fun-2-'/5+6:
  Internal consistency check failed - please report this bug.
  Instruction: {get_map_elements,
                   {f,57},
                   {x,0},
                   {list,
                       [{atom,route},
                        {x,9},
                        {atom,relationship},
                        {x,8},
                        {atom,method},
                        {x,7},
                        {atom,controller},
                        {x,6},
                        {atom,action_type},
                        {x,6},
                        {atom,action},
                        {x,5}]}}
  Error:       conflicting_destinations:

    (stdlib 4.0.1) lists.erl:1442: :lists.foreach_1/2
Error: Process completed with exit code 1.

To Reproduce
This happens with the following code:

defmodule MmsBiztalkWeb.Plugs.MmsBiztalkApi do
  use AshJsonApi.Api.Router,
    # Your Ash.Api Module
    api: MmsBiztalk,
    # Your Ash.Registry Module
    registry: MmsBiztalk.Registry,
    json_schema: "/schema",
    open_api: "/open_api",
    modify_open_api: {__MODULE__, :modify_open_api, []}

  def modify_open_api(spec, _, _) do
    %{
      spec
      | info: %{
          spec.info
          | title: "Biztalk JSON API",
            version: Application.get_env(:mms_biztalk, :version)
        }
    }
  end
end

Expected behavior
It should compile as happens with v. 0.31.3

** Runtime

  • Elixir version 1.14.1
  • Erlang version OTP 25.0.4
  • OS Pop OS 22.04
  • Ash version 2.11.2

Logger metadata

We want to set logger metadata about the request at the beginning of a request.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.