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"
}
}```