I’m working on an email API service, Already got the Ash action to send email working in iex.
My send_email action is a custom action that will perfom some non standard CRUD. Got 2 create actions and the calls to api ask for attributes from wrong create action. As for now just trying to get the Ok atom
My resource
defmodule Eppa.Accounts.Servicios do use Ash.Resource, otp_app: :eppa, domain: Eppa.Accounts, data_layer: AshPostgres.DataLayer, extensions: [AshJsonApi.Resource] json_api do type "servicios" end postgres do table "servicios" repo Eppa.Repo references do reference :user, index?: true, on_delete: :delete end end actions do defaults [:read, :destroy] create :create do primary? true accept [:tipo, :creditos_disponibles, :vigencia] change relate_actor(:created_by, allow_nil?: true) change relate_actor(:updated_by, allow_nil?: true) end update :update do primary? true accept [:creditos_disponibles, :vigencia] change relate_actor(:updated_by, allow_nil?: true) end create :send_email do # Definición de argumentos que se esperan recibir vía JSON argument :user_email, :ci_string, allow_nil?: false argument :destinatario, :ci_string, allow_nil?: false argument :cc, {:array, :ci_string}, default: [] argument :asunto, :string, allow_nil?: false argument :contenido_html, :ci_string, allow_nil?: false argument :attachments, {:array, :map}, default: [] argument :plantilla_id, :ci_string, allow_nil?: true # Testing - " {:ok, "ok"} end end attributes do uuid_v7_primary_key :id attribute :tipo, :atom do constraints one_of: [:correos, :sms] allow_nil? false public? true end attribute :creditos_disponibles, :integer do allow_nil? false default 0 public? true end attribute :vigencia, :datetime do allow_nil? false public? true end attribute :user_id, :uuid do end create_timestamp :inserted_at update_timestamp :updated_at end relationships do belongs_to :created_by, Eppa.Accounts.User belongs_to :updated_by, Eppa.Accounts.User belongs_to :user, Eppa.Accounts.User do allow_nil? false end end end
My domain
defmodule Eppa.Accounts do use Ash.Domain, otp_app: :eppa, extensions: [AshJsonApi.Domain] json_api do routes do base_route "/servicios", Eppa.Accounts.Servicios do post :send_email end end end resources do resource Eppa.Accounts.Token resource Eppa.Accounts.User do define :create_user, action: :register_with_password define :update_user, action: :update_user define :get_users, action: :read define :get_user_by_id, action: :read, get_by: :id define :get_user_by_email, action: :read, get_by: :email define :get_users_with_services, action: :read end resource Eppa.Accounts.Servicios do define :get_servicios, action: :read define :create_servicio, action: :create define :send_email, action: :send_email define :get_servicio_by_id, action: :read, get_by: :id end resource Eppa.Accounts.Profile do define :create_perfil, action: :create define :update_perfil, action: :update define :get_profiles, action: :read define :get_perfil_by_id, action: :read, get_by: :id end end authorization do # disable using the authorize?: false flag when calling actions authorize :always end end
Router
defmodule EppaWeb.Router do use EppaWeb, :router use AshAuthentication.Phoenix.Router import AshAuthentication.Plug.Helpers pipeline :browser do plug :accepts, ["html"] plug :fetch_session plug :fetch_live_flash plug :put_root_layout, html: {EppaWeb.Layouts, :root} plug :protect_from_forgery plug :put_secure_browser_headers plug :load_from_session end pipeline :api do plug :accepts, ["json"] plug :load_from_bearer plug :set_actor, :user end scope "/api/json" do pipe_through [:api] forward "/swaggerui", OpenApiSpex.Plug.SwaggerUI, path: "/api/json/open_api", default_model_expand_depth: 4 forward "/", EppaWeb.AshJsonApiRouter end scope "/", EppaWeb do pipe_through :browser ash_authentication_live_session :authenticated_routes do live "/dashboard", DashboardLive, :index live "/users", UserLive.Index, :index live "/users/new", UserLive.Index, :new live "/users/:id/edit", UserLive.Index, :edit live "/users/:id", UserLive.Show, :show live "/users/:id/show/edit", UserLive.Show, :edit live "/users/:id/assign_profile", UserLive.Index, :assign_profile live "/users/:id/servicios", EppaWeb.UserLive.Servicios, :index live "/profiles", ProfileLive.Index, :index live "/profiles/new", ProfileLive.Index, :new live "/profiles/:id/edit", ProfileLive.Index, :edit live "/profiles/:id", ProfileLive.Show, :show live "/profiles/:id/show/edit", ProfileLive.Show, :edit # live "/services", ServiceAssignmentLive.Index, :index # live "/services/new", ServiceAssignmentLive.Index, :new live "/services", ServicesLive.Index, :index live "/services/:id/creditos", ServiceLive.Creditos, :creditos # in each liveview, add one of the following at the top of the module: # # If an authenticated user must be present: # on_mount {EppaWeb.LiveUserAuth, :live_user_required} # # If an authenticated user *may* be present: # on_mount {EppaWeb.LiveUserAuth, :live_user_optional} # # If an authenticated user must *not* be present: # on_mount {EppaWeb.LiveUserAuth, :live_no_user} end end scope "/", EppaWeb do pipe_through :browser # live "/sign-in", SignInLive, :index get "/", RedirectController, :to_sign_in # get "/", PageController, :home auth_routes AuthController, Eppa.Accounts.User, path: "/auth" sign_out_route AuthController # Remove these if you'd like to use your own authentication views sign_in_route register_path: "/register", reset_path: "/reset", auth_routes_prefix: "/auth", on_mount: [{EppaWeb.LiveUserAuth, :live_no_user}], overrides: [EppaWeb.AuthOverrides, AshAuthentication.Phoenix.Overrides.Default] # Remove this if you do not want to use the reset password feature reset_route auth_routes_prefix: "/auth", overrides: [EppaWeb.AuthOverrides, AshAuthentication.Phoenix.Overrides.Default] end # Other scopes may use custom stacks. # scope "/api", EppaWeb do # pipe_through :api # end # Enable LiveDashboard and Swoosh mailbox preview in development if Application.compile_env(:eppa, :dev_routes) do # If you want to use the LiveDashboard in production, you should put # it behind authentication and allow only admins to access it. # If your application does not have an admins-only section yet, # you can use Plug.BasicAuth to set up some basic authentication # as long as you are also using SSL (which you should anyway). import Phoenix.LiveDashboard.Router scope "/dev" do pipe_through :browser live_dashboard "/dashboard", metrics: EppaWeb.Telemetry forward "/mailbox", Plug.Swoosh.MailboxPreview end end end
API CALL
{ "data":{ "type":"servicios", "attributes": { "user_email": "knd_rt@hotmail.com", "destinatario": "blitzlepe@gmail.com" , "cc":[ "cande.lepe@agustindeiturbide.com" ], "asunto":"Prueba desde Insomnia", "contenido_html":"Su pinche madre, si jalo !!!", "attachments":[] } } }
Response
{ "errors": [ { "code": "required", "id": "c5e78bdc-fc81-421e-a9b9-cf71c85256bb", "meta": {}, "status": "400", "title": "Required", "source": { "pointer": "/data/attributes/tipo" }, "detail": "is required" }, { "code": "required", "id": "c6c953b2-0925-4ada-9c8f-fd682c248b99", "meta": {}, "status": "400", "title": "Required", "source": { "pointer": "/data/attributes/vigencia" }, "detail": "is required" } ], "jsonapi": { "version": "1.0" } }```