How to properly send JSON data to a phx phoenix API - json

I am working on a Phoenix / phx API written using Elixir, and I am trying to test the functionality of the JSON API using Postman. I'm sending JSON data to the API to hopefully create a new user, but phx is giving me the following error.
Phoenix.ActionClauseError at POST /api/users
Not sure where the problem lies exactly, so I'll post the router and the controller for the phx project.
router.ex
defmodule KegCopRAPI.Web.Router do
use KegCopRAPI.Web, :router
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_flash
plug :protect_from_forgery
plug :put_secure_browser_headers
end
pipeline :api do
plug :accepts, ["json"]
plug Guardian.Plug.VerifyHeader, realm: "Bearer"
plug Guardian.Plug.LoadResource
end
scope "/", KegCopRAPI.Web do
pipe_through :browser # Use the default browser stack
get "/", PageController, :index
end
# Other scopes may use custom stacks.
scope "/api", KegCopRAPI.Web do
pipe_through :api
post "/sessions", SessionController, :create
delete "/sessions", SessionController, :delete
post "/sessions/refresh", SessionController, :refresh
resources "/users", UserController, except: [:show, :index, :new, :edit]
end
end
user_controller.ex
def create(conn, %{"user" => user_params}) do
# with {:ok, %User{} = user} <- Accounts.create_user(user_params) do
changeset = User.registration_changeset(%User{}, user_params)
case Repo.insert(changeset) do
{:ok, user} ->
new_conn = Guardian.Plug.api_sign_in(conn, user, :access)
jwt = Guardian.Plug.current_token(new_conn)
# conn
# |> put_status(:created)
# |> put_resp_header("location", user_path(conn, :show, user))
# |> render("show.json", user: user)
new_conn
|> put_status(:created)
|> render(KegCopRAPI.SessionView, "show.json", user: user, jwt: jwt)
{:error, changeset} ->
conn
|> put_status(:unprocessable_entity)
|> render(KegCopRAPI.ChangesetView, "error.json", changeset: changeset)
end
end
The entire project can be found here
Any and all help would greatly be appreciated.
I'm sending data to the API with the following Postman settings,
The complete error message below,
[info] POST /api/users
[debug] Processing with KegCopRAPI.Web.UserController.create/2
Parameters: %{"email" => "foo#example.com", "password" => "[FILTERED]", "username" => "foo"}
Pipelines: [:api]
[info] Sent 400 in 10ms
[debug] ** (Phoenix.ActionClauseError) could not find a matching KegCopRAPI.Web.UserController.create clause
to process request. This typically happens when there is a
parameter mismatch but may also happen when any of the other
action arguments do not match. The request parameters are:
%{"email" => "foo#example.com", "password" => "password", "username" => "foo"}
(kegcopr_api) lib/kegcopr_api/web/controllers/user_controller.ex:14: KegCopRAPI.Web.UserController.create(%Plug.Conn{adapter: {Plug.Adapters.Cowboy.Conn, :...}, assigns: %{}, before_send: [#Function<1.33581574/1 in Plug.Logger.call/2>, #Function<0.72433304/1 in Phoenix.LiveReloader.before_send_inject_reloader/2>], body_params: %{"email" => "foo#example.com", "password" => "password", "username" => "foo"}, cookies: %Plug.Conn.Unfetched{aspect: :cookies}, halted: false, host: "localhost", method: "POST", owner: #PID<0.2357.0>, params: %{"email" => "foo#example.com", "password" => "password", "username" => "foo"}, path_info: ["api", "users"], path_params: %{}, peer: {{127, 0, 0, 1}, 59852}, port: 4000, private: %{KegCopRAPI.Web.Router => {[], %{}}, :guardian_default_resource => nil, :phoenix_action => :create, :phoenix_controller => KegCopRAPI.Web.UserController, :phoenix_endpoint => KegCopRAPI.Web.Endpoint, :phoenix_format => "json", :phoenix_layout => {KegCopRAPI.Web.LayoutView, :app}, :phoenix_pipelines => [:api], :phoenix_router => KegCopRAPI.Web.Router, :phoenix_view => KegCopRAPI.Web.UserView, :plug_session_fetch => #Function<1.131660147/1 in Plug.Session.fetch_session/1>}, query_params: %{}, query_string: "", remote_ip: {127, 0, 0, 1}, req_cookies: %Plug.Conn.Unfetched{aspect: :cookies}, req_headers: [{"cache-control", "no-cache"}, {"postman-token", "da608739-758b-40d7-bdef-23b3c2a63bed"}, {"content-type", "application/json"}, {"user-agent", "PostmanRuntime/3.0.11-hotfix.2"}, {"accept", "*/*"}, {"host", "localhost:4000"}, {"accept-encoding", "gzip, deflate"}, {"content-length", "76"}, {"connection", "keep-alive"}], request_path: "/api/users", resp_body: nil, resp_cookies: %{}, resp_headers: [{"cache-control", "max-age=0, private, must-revalidate"}, {"x-request-id", "slfdhshckenp3dinlqr22m5nlakhoaq4"}, {"access-control-allow-origin", "*"}, {"access-control-expose-headers", ""}, {"access-control-allow-credentials", "true"}, {"vary", ""}], scheme: :http, script_name: [], secret_key_base: "fIEpvi5ujSQEKgmkRpt83KiLPq068sSmvFKlWFZyNpi3nkNmUtYO24Em6cXIUblZ", state: :unset, status: nil}, %{"email" => "foo#example.com", "password" => "password", "username" => "foo"})
(kegcopr_api) lib/kegcopr_api/web/controllers/user_controller.ex:1: KegCopRAPI.Web.UserController.action/2
(kegcopr_api) lib/kegcopr_api/web/controllers/user_controller.ex:1: KegCopRAPI.Web.UserController.phoenix_controller_pipeline/2
(kegcopr_api) lib/kegcopr_api/web/endpoint.ex:1: KegCopRAPI.Web.Endpoint.instrument/4
(phoenix) lib/phoenix/router.ex:277: Phoenix.Router.__call__/1
(kegcopr_api) lib/kegcopr_api/web/endpoint.ex:1: KegCopRAPI.Web.Endpoint.plug_builder_call/2
(kegcopr_api) lib/plug/debugger.ex:123: KegCopRAPI.Web.Endpoint."call (overridable 3)"/2
(kegcopr_api) lib/kegcopr_api/web/endpoint.ex:1: KegCopRAPI.Web.Endpoint.call/2
(plug) lib/plug/adapters/cowboy/handler.ex:15: Plug.Adapters.Cowboy.Handler.upgrade/4
(cowboy) /opt/elixir/kegcopr_api/deps/cowboy/src/cowboy_protocol.erl:442: :cowboy_protocol.execute/4

Since you're using the data from the map inside the "user" key, you need to put all the fields under the "user" key in the request, like this:
{
"user": {
"username": "foo",
"email": "foo#example.com",
"password": "password"
}
}

In your controller you are pattern-matching
"user" => user_params
So, you have to put the user params under the user key:
"user": {
"email": "foo#bar.com",
...
}

Related

Wildfly json log formatter dynamic configuration not applied

Wildfly 20 is connected with a Logstash instance listening on tcp port 5300:
logstash.conf:
input {
tcp {
codec => json
port => "5300"
}
}
output {
stdout {}
}
Making use of its built-in json logging capabilities with socket connection, as outpointed in wildfly-logstash does not send logs to logstash, Wildfly is configured on the Wildfly CLI, entering the following sequence of statements (that end up in standalone.xml automatically):
/subsystem=logging/json-formatter=LOG-STASH:add(key-overrides={timestamp=#timestamp,message=#message,logger-name=#source,host-name=#source_host}, exception-output-type=formatted)
/socket-binding-group=standard-sockets/remote-destination-outbound-socket-binding=log-stash:add(host=localhost, port=8000)
/subsystem=logging/socket-handler=LOGSTASH-SOCKET:add(named-formatter=LOG-STASH, outbound-socket-binding-ref=log-stash, level=DEBUG)
/subsystem=logging/async-handler=LOGSTASH-ASYNC:add(queue-length=512, subhandlers=[LOGSTASH-SOCKET])
/subsystem=logging/root-logger=ROOT:add-handler(name=LOGSTASH-ASYNC)
It produces log statements on standard out of the logstash node, as e.g.:
{
"level" => "DEBUG",
"host" => "gateway",
"processId" => 14972,
"sequence" => 34696,
"#version" => "1",
"#source" => "com.myapplication.TaskService",
"#source_host" => "device-01",
"threadName" => "EJB default - 6",
"threadId" => 215,
"loggerClassName" => "org.slf4j.impl.Slf4jLogger",
"mdc" => {},
"ndc" => "",
"port" => 64210,
"processName" => "jboss-modules.jar",
"#timestamp" => 2021-03-31T14:10:19.869Z,
"#message" => "task execution successfull: MailDaemon"
}
That is only half way to the goal, required is another set of attribute names (of the individual json log message) to fit in our enterprise logstash instances.
Especially, neither "host-name" nor "logger-name" are written, although configured; instead "#source_host" and #source are logged.
Further adaption of the log-formatter LOG-STASH partially succeeds.
1) /subsystem=logging/json-formatter=LOG-STASH:write-attribute(name="meta-data",value={service="myapplication-api", serviceversion="1.1.0", instanceId="myapplication-api-1.1.0"})
2) /subsystem=logging/json-formatter=LOG-STASH:write-attribute(name="key-overrides",value=[severity=level,timestamp=#timestamp,message=msg,logger-name=#source,host-name=#source_host])
Further simplifaction results in attribute stored, but not applied:
3) /subsystem=logging/json-formatter=LOG-STASH:write-attribute(name="key-overrides",value={"level"="severity"})
4) /subsystem=logging/json-formatter=LOG-STASH:read-attribute(name="key-overrides")
works and meta data are added. 2. and 3. bring no results. 4. prints out like
INFO [org.jboss.as.cli.CommandContext] {
"outcome" => "success",
"result" => {"level" => "severity"}
}
{
"outcome" => "success",
"result" => {"level" => "severity"}
}
With the above setup the following Wildfly CLI command sucessfully renames the wanted keys' default values:
/subsystem=logging/json-formatter=LOG-STASH:write-attribute(name="key-overrides",value={"level"="severity","sequence"="trace","thread-id"="pid","logger-class-name"="class","thread-name"="thread"})
These settings end up in standalone.xml and logging.properties in the same folder on disk.
During my work there was a discrepancy between configured keys in both files.
Be aware that camel case key names like threadId produce a configuration error. You have to use thread-id instead. I found this by inspection of the JBoss logging library, i.e. looking on the Java source code.
The produced logging output is e.g.
{
"pid" => 212,
"message" => "Synchronizaing finished in 0ms",
"#version" => "1",
"loggerName" => "com.myapp.Cache",
"#timestamp" => 2021-04-08T13:49:00.178Z,
"port" => 59182,
"processName" => "jboss-modules.jar",
"trace" => 4245,
"host" => "gateway",
"severity" => "DEBUG",
"processId" => 10536,
"mdc" => {},
"hostName" => "host-alpha",
"timestamp" => "2021-04-08T15:49:00.176+02:00",
"class" => "org.slf4j.impl.Slf4jLogger",
"ndc" => "",
"thread" => "EJB default - 7"
}
What would be nice still, is to have fields mdc and ndc deprived of the output.

LDAP on local domain with Mediawiki on Debian 10

I have a MediaWiki (1.34) running on a Debian 10 linux VM on our local network. We have a local domain (abc.local) managed by Win Server 2008 R2. I am trying to implement LDAP so only abc.local domain users can use our wiki. I installed all the necessary extensions and everything seems to work when i use this test ldapprovider.json to test. I don't know credentials for this test domain so i get this:
This seems to tell me that LDAP is working though and tried to authenticate based on the bogus user creds i supplied. So, now i tried to modify the ldapprovider.json for my local domain. All i tried at first attempt was to change "server", "user", and "pass". The 5.5.5.5 is our internal local domain controller.
{
"LDAP": {
"connection": {
"server": "5.5.5.5",
"user": "cn=Administrator,dc=example,dc=com",
"pass": "XXXXXXXXXX",
"options": {
"LDAP_OPT_DEREF": 1
},
"basedn": "dc=example,dc=com",
"groupbasedn": "dc=example,dc=com",
"userbasedn": "dc=example,dc=com",
"searchattribute": "uid",
"searchstring": "uid=USER-NAME,dc=example,dc=com",
"usernameattribute": "uid",
"realnameattribute": "cn",
"emailattribute": "mail"
},
"userinfo": {
"attributes-map": {
"email": "mail",
"realname": "cn",
"nickname": "uid",
"language": "preferredlanguage"
}
},
"groupsync": {
"mapping": {
"mathematicians": "ou=mathematicians,dc=example,dc=com",
"scientists": "ou=scientists,dc=example,dc=com"
}
}
}
}
This time when i enter user credentials i get the following error:
[f66f7d40890c442c71165a80] /index.php/Special:PluggableAuthLogin MWException from line 157 of /var/www/html/mediawiki/extensions/LDAPProvider/src/Client.php: Could not bind to LDAP: (49) Invalid credentials
Backtrace:
#0 /var/www/html/mediawiki/extensions/LDAPProvider/src/Client.php(80): MediaWiki\Extension\LDAPProvider\Client->establishBinding()
#1 /var/www/html/mediawiki/extensions/LDAPProvider/src/Client.php(313): MediaWiki\Extension\LDAPProvider\Client->init()
#2 /var/www/html/mediawiki/extensions/LDAPAuthentication2/src/PluggableAuth.php(76): MediaWiki\Extension\LDAPProvider\Client->canBindAs(string, string)
#3 /var/www/html/mediawiki/extensions/PluggableAuth/includes/PluggableAuthLogin.php(30): MediaWiki\Extension\LDAPAuthentication2\PluggableAuth->authenticate(NULL, string, NULL, NULL, NULL)
#4 /var/www/html/mediawiki/includes/specialpage/SpecialPage.php(575): PluggableAuthLogin->execute(NULL)
#5 /var/www/html/mediawiki/includes/specialpage/SpecialPageFactory.php(611): SpecialPage->run(NULL)
#6 /var/www/html/mediawiki/includes/MediaWiki.php(296): MediaWiki\Special\SpecialPageFactory->executePath(Title, RequestContext)
#7 /var/www/html/mediawiki/includes/MediaWiki.php(900): MediaWiki->performRequest()
#8 /var/www/html/mediawiki/includes/MediaWiki.php(527): MediaWiki->main()
#9 /var/www/html/mediawiki/index.php(44): MediaWiki->run()
#10 {main}
I do not know how to modify the ldapprovider.json for my local domain abc.local. Don't know if this helps, but when i join computers to the domain i use "abc.local" and when users login the use "abc\username".
p.s. I've only made it this far because of serious help/tutoring i received from this question. Just hate to give up...
EDIT1: I joined my linux machine to the windows domain and have the following results to the realm discover, realm join, and id commands. Working fine - can id a user rjsmith (he is user and also in engineers group).
root#mediawiki-linux:/etc# realm discover abc.local
abc.local
type: kerberos
realm-name: abc.local
domain-name: abc.local
configured: no
server-software: active-directory
client-software: sssd
required-package: sssd-tools
required-package: sssd
required-package: libnss-sss
required-package: libpam-sss
required-package: adcli
required-package: samba-common-bin
root#mediawiki-linux:/etc# realm join abc.local
Password for Administrator:
root#mediawiki-linux:/etc#
root#mediawiki-linux:/etc# realm discover abc.local
abc.local
type: kerberos
realm-name: abc.local
domain-name: abc.local
configured: kerberos-member
server-software: active-directory
client-software: sssd
required-package: sssd-tools
required-package: sssd
required-package: libnss-sss
required-package: libpam-sss
required-package: adcli
required-package: samba-common-bin
login-formats: %U#abc.local
login-policy: allow-realm-logins
root#mediawiki-linux:/etc# id rjsmith#abc.local
uid=521401112(rjsmith#abc.local) gid=521400513(domain users#abc.local) groups=521400513(domain users#abc.local),521401111(engineers#abc.local)
EDIT2: This is my LDAPProviderDomainConfigProvider function in my LocalSettings.php file. Still getting the Could not bind to LDAP: (49) Invalid credentials. error.
$LDAPProviderDomainConfigProvider = function() {
$config = [
'LDAP' => [
'connection' => [
"server" => "5.5.5.5"
"user" => "cn=Administrator#abc.local,dc=abc,dc=local",
"pass" => 'password',
"options" => [
"LDAP_OPT_DEREF" => 1
],
"basedn" => "dc=abc,dc=local",
"groupbasedn" => "dc=abc,dc=local",
"userbasedn" => "dc=abc,dc=local",
"searchattribute" => "uid",
"searchstring" => "uid=USER-NAME,dc=abc,dc=local",
"usernameattribute" => "uid",
"realnameattribute" => "cn",
"emailattribute" => "mail"
]
]
];
return new \MediaWiki\Extension\LDAPProvider\DomainConfigProvider\InlinePHPArray( $config );
};
Based on the comments, your error looks to be that the username, you need to bind the ldap connection to, is not cn=Administrator#abc.local,dc=abc,dc=local but rather Administrator#abc.local.
So, changing that in your ldap configuration for the extension to something like that:
$LDAPProviderDomainConfigProvider = function() {
$config = [
'LDAP' => [
'connection' => [
"server" => "5.5.5.5"
"user" => "Administrator#abc.local",
"pass" => 'password',
"options" => [
"LDAP_OPT_DEREF" => 1
],
"basedn" => "dc=abc,dc=local",
"groupbasedn" => "dc=abc,dc=local",
"userbasedn" => "dc=abc,dc=local",
"searchattribute" => "uid",
"searchstring" => "uid=USER-NAME,dc=abc,dc=local",
"usernameattribute" => "uid",
"realnameattribute" => "cn",
"emailattribute" => "mail"
]
]
];
return new \MediaWiki\Extension\LDAPProvider\DomainConfigProvider\InlinePHPArray( $config );
};
should do the trick (take a look to the changed user property) for retrieving user information from the LDAP on login.

Chef Creating dynamic Json File

I got a problem in generate a json file using a template inside a chef template.
I need to generate a json file like below, called plugin.json:
{
"agents": [
{
"name" : "sqlhost",
"host" : "localhost",
"metrics" : "status,newrelic",
"user" : "root",
"passwd" : "mysecret"
}
]
}
This file will be used by the Newrelic plugin
Template File plugin.json.erb:
<%= Chef::JSONCompat.to_json_pretty(#name) %>
I've created a recipe like this one:
mysql-plugin.rb
# Default Variables
newrelic = decrypt_databag('newrelic')
node.default['newrelic_npi']['license_key'] = newrelic['license_key']
plugin = 'com.newrelic.plugins.mysql.instance'
plugin_json_path = "/opt/newrelic-npi/plugins/com.newrelic.plugins.mysql.instance/newrelic_mysql_plugin-2.0.0/config/plugin.json"
node.default['newrelic_npi']['name'] = "localhost1"
execute 'fetch' do
cwd node['newrelic_npi']['install_path']
user node['newrelic_npi']['user']
command "./npi fetch #{plugin} -y"
not_if do
::File.exist? "#{node['newrelic_npi']['install_path']}/plugins/#{plugin}"
end
end
execute 'prepare' do
cwd node['newrelic_npi']['install_path']
user node['newrelic_npi']['user']
command "./npi prepare #{plugin}"
end
template "#{plugin_json_path}" do
source 'plugin.json.erb'
owner "root"
group "root"
mode "0644"
variables :name => node['newrelic_npi']['name']
action :create
end
execute 'add-service' do
cwd node['newrelic_npi']['install_path']
user node['newrelic_npi']['user']
command "sudo ./npi add-service #{plugin} --start" # needs root privileges
not_if do
::File.exist? "/etc/init.d/newrelic_plugin_#{plugin}"
end
end
At the Template block what should I do to make a Json file like plugin.json?
template "#{plugin_json_path}" do
source 'plugin.json.erb'
owner "root"
group "root"
mode "0644"
variables :name => node['newrelic_npi']['name']
action :create
end
Thanks in Advance.
First. You should be setting any default node variables inside default.rb in your attributes folder. Like this:
default['newrelic_npi']['license_key'] = newrelic['license_key']
default['newrelic_npi']['name'] = "localhost1"
Node attributes are reset before compilation and will pull from that file as well as Ohai. Setting node attributes inside the recipe means they aren't going to be available for your template (you should review this Chef Client Overview).
Next, if you just need to set the hostname or another specific portion of the template file you can do this inside your erb file:
{
"agents": [
{
"name" : "sqlhost",
"host" : "<%= #name %>",
"metrics" : "status,newrelic",
"user" : "root",
"passwd" : "mysecret"
}
]
}
Your current erb file is trying to convert #name (which you try to set to localhost1) to json, not set the whole file like your example.
To generate a correct plugin.json:
{
"agents": [
{
"name" : <%= Chef::JSONCompat.to_json_pretty(#name) %>,
"host" : <%= Chef::JSONCompat.to_json_pretty(#host) %>,
"metrics" : <%= Chef::JSONCompat.to_json_pretty(#metrics) %>,
"user" : <%= Chef::JSONCompat.to_json_pretty(#user) %>,
"passwd" : <%= Chef::JSONCompat.to_json_pretty(#passwd) %>
}
]
}
At the template Block I did like:
template node['newrelic_npi']['plugin_json_path'] do
source 'plugin.json.erb'
owner 'root'
group 'root'
mode '0644'
variables(
:name => node['newrelic_npi']['name'],
:host => node['newrelic_npi']['host'],
:metrics => node['newrelic_npi']['metrics'],
:user => node['newrelic_npi']['user'],
:passwd => node['newrelic_npi']['myql_admin_password']
)
action :create
end

Run Codeception API Test with Yii2

I have been fighting with this problem for hours and cannot get through. I want to run API tests with Yii2 and (of course) Codeception. Here is my api.suite.yml
class_name: ApiTester
modules:
enabled:
- REST:
url: /mobile
depends: Yii2
part: Json
- \Helper\Api
config:
Yii2:
entryUrl: http://localhost:8080/index-test.php
and my test file UserLoginCept.php
<?php
$I = new ApiTester($scenario);
$I->wantTo('Test User Login');
$I->sendPOST('mobile/login', ['username' => 'uname', 'password' => '123456']);
$I->seeResponseCodeIs(\Codeception\Util\HttpCode::OK);
$I->seeResponseContainsJson(['success'=>true]);
Results are logged below. The problem is the Test is calling site/index which is in the root project not mobile module. I can sense that it is picking wrong URL somewhere as I cannot see any trace of the module being called. If I try URL on Browser it works fine
http://localhost:8080/index.php/mobile/api/login
{
"success": false,
"token": ""
}
can someone help me spot what am doing wrong? I have read as much as I could could not find the issue.
Codeception Results
$~ codecept --debug run api
Codeception PHP Testing Framework v2.2.10
Powered by PHPUnit 4.8.35 by Sebastian Bergmann and contributors.
Rebuilding ApiTester...
Api Tests (1) -----------------------------------------------------------------------------------------------------------------------------------------------------------------------
Modules: REST, Yii2, \Helper\Api
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
UserLoginCept: Test User Login
Signature: UserLoginCept
Test: tests/api/UserLoginCept.php
Scenario --
I send post "/mobile/api/login",{"username":"uname","password":"123456"}
[Request] POST /mobile/mobile/api/login {"username":"uname","password":"123456"}
[Request Headers] []
[yii\db\Connection::open] 'Opening DB connection: mysql:host=localhost;dbname=database_name'
ERROR
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1) UserLoginCept: Test user login
Test tests/api/UserLoginCept.php
[Error] Call to a member function isAdmin() on null
Scenario Steps:
1. $I->sendPOST("/mobile/api/login",{"username":"uname","password":"123456"}) at tests/api/UserLoginCept.php:4
#1 /Users/hosanna/Projects/Volcano/WebApp/vendor/yiisoft/yii2/base/View.php:328
#2 /Users/hosanna/Projects/Volcano/WebApp/vendor/yiisoft/yii2/base/View.php:250
#3 /Users/hosanna/Projects/Volcano/WebApp/vendor/yiisoft/yii2/base/Controller.php:396
#4 /Users/hosanna/Projects/Volcano/WebApp/vendor/yiisoft/yii2/base/Controller.php:382
#5 /Users/hosanna/Projects/Volcano/WebApp/controllers/SiteController.php:74
#6 app\controllers\SiteController->actionIndex
#7 /Users/hosanna/Projects/Volcano/WebApp/vendor/yiisoft/yii2/base/InlineAction.php:57
#8 /Users/hosanna/Projects/Volcano/WebApp/vendor/yiisoft/yii2/base/Controller.php:156
#9 /Users/hosanna/Projects/Volcano/WebApp/vendor/yiisoft/yii2/base/Module.php:523
#10 /Users/hosanna/Projects/Volcano/WebApp/vendor/yiisoft/yii2/web/Application.php:102
<!DOCTYPE html>
<html lang="en-US">
..... rest of HTML.....
So here is how I solved it:
changed suite.api.yaml to use test-index.php
class_name: ApiTester
modules:
enabled:
- Yii2
- REST:
url: http://localhost:8080/index-test.php/mobile/
depends: Yii2
part: Json
configFile: 'config/test.php'
- \Helper\Api
config:
Yii2:
I then changed the config file referred by text-index (config/test.php) to include pretty URLs:
<?php
$params = require(__DIR__ . '/params.php');
$dbParams = require(__DIR__ . '/test_db.php');
/**
* Application configuration shared by all test types
*/
return [
'id' => 'basic-tests',
'basePath' => dirname(__DIR__),
'language' => 'en-US',
'modules' => [
'mobile' => [
'class' => 'app\modules\mobile\Module',
],
],
'components' => [
'db' => $dbParams,
'mailer' => [
'useFileTransport' => true,
],
'assetManager' => [
'basePath' => __DIR__ . '/../web/assets',
],
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => false,
'showScriptName' => true,
'rules' => [
['class' => 'yii\rest\UrlRule', 'controller' => 'mobile/api'],
],
],
'user' => [
'identityClass' => 'app\modules\mobile\models\User',
],
'request' => [
'cookieValidationKey' => 'test',
'enableCsrfValidation' => false,
// but if you absolutely need it set cookie domain to localhost
/*
'csrfCookie' => [
'domain' => 'localhost',
],
*/
],
],
'params' => $params,
];
After that tests were running fine!

exception_notification: smtp not working

I am using Rails 3.2.5 and exception_notification gem. In production mode, I am generally sending emails using PostMarkApp's postmark-rails gem.
Initially, I got a View error from exception_notification gem stating
ActionView::Template::Error (code converter not found (UTF-8 to UTF-16))
so based on exception_notification gem raises ActionView::Template::Error (code converter not found (UTF-8 to UTF-16)) only on Heroku production mode, I moved to
gem 'exception_notification', git: 'git://github.com/alanjds/exception_notification.git'
This solved that bug. Now, I want the gem to send emails from my gmail account instead of using PostMarkApp credits, so I added the following to my production.rb, yet Exception Notification attempts to send email only from Post Mark App. Why is this setting not working?
config.middleware.use ExceptionNotifier,
sender_address: 'noreply#mydomain.com',
exception_recipients: 'myemail#mydomain.com',
sections: %w{current_user} + ExceptionNotifier::Notifier.default_sections,
ignore_crawlers: %w{Googlebot bingbot},
email_format: true,
normalize_subject: true,
smtp_settings: {
:address => "smtp.gmail.com",
:port => "587",
:domain => "www.gmail.com",
:user_name => "myemail#gmail.com",
:password => "mypassword",
:authentication => "plain",
:enable_starttls_auto => true,
:openssl_verify_mode => 'none'
}
config.action_mailer.delivery_method = :postmark
config.action_mailer.postmark_settings = { :api_key => "_____" }
For some reason it appears that SMTP delivery does NOT work in the development environment. I tried a number of different settings and was never able to get this to work. It DOES however work in my other environments. Older posts seem to indicate this as well:
http://www.ruby-forum.com/topic/64776
http://www.devchix.com/2008/12/09/how-to-see-exception_notification-plugin-work-in-development-mode/
In development, I am using the following in my development.rb:
config.action_mailer.delivery_method = :letter_opener
config.middleware.use ExceptionNotifier,
:sender_address => 'test#test.com',
:exception_recipients => 'recipient#test.com'
In my "staging" environment, I am using the following in my staging.rb:
config.action_mailer.delivery_method = :smtp
config.middleware.use ExceptionNotifier,
:sender_address => 'test#test.com',
:exception_recipients => 'recipient#test.com'
The staging.rb acquires it's SMTP settings from an initializer I have the uses SendGrid for SMTP:
ActionMailer::Base.smtp_settings = {
:address => "smtp.sendgrid.net",
:port => 25,
:domain => "test.com",
:user_name => "user_name",
:password => "password",
:authentication => "plain"
}
Try the suggestion at http://www.scottw.com/multiple-smtp-servers-with-action-mailer
or at Rails ActionMailer with multiple SMTP servers