New users being created in test environment have their IDs continually incrementing using Wallaby/Phoenix - postgresql

I'm new to Elixir/Phoenix so I'm not sure if this is working as expected or an issue I should address.
I have a Phoenix app that I just started adding integration tests to. Having done this for a few days of setting up and testing the User registration feature, I'm now onto testing the login.
I'm using Wallaby:
test.exs:
config :happy_app, :sql_sandbox, true
config :wallaby,
driver: Wallaby.Experimental.Chrome,
chrome: [headless: true],
screenshot_on_failure: true
test_helper.exs:
ExUnit.start()
Ecto.Adapters.SQL.Sandbox.mode(HappyApp.Repo, :manual)
{:ok, _} = Application.ensure_all_started(:wallaby)
Application.put_env(:wallaby, :base_url, HappyAppWeb.Endpoint.url())
My test looks like this:
defmodule HappyAppWeb.UserLoginTest do
use HappyAppWeb.IntegrationCase, async: true
alias HappyApp.Accounts
import HappyAppWeb.IntegrationSteps
#tag integration: true
test "user can login", %{session: session} do
email = "test-user#example.com"
password = "12345678"
# seed user into db
user = Accounts.create_user(%{email: email, password: password})
IO.inspect user
# logging in with the user's email and password
# asserting the view is correct
end
end
When I inspect the user: IO.inspect user I get:
IO.inspect user
=>
{:ok,
%HappyApp.Accounts.User{
__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
email: "test-user#example.com",
id: 449,
inserted_at: ~N[2019-11-24 13:20:33],
password: nil,
password_hash: "shhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
updated_at: ~N[2019-11-24 13:20:33]
}}
Notice the id: 449,. Is that correct? Shouldn't that reset between tests back to 1?
Manually looking into postgres I see that happy_app_test db is indeed empty. Is the data elsewhere?

This thing is related to the database engine. I cannot find information that confirms it for sure, however I suspect that rollback is deleting the rows that were previously inserted.
When you delete rows, the id counter is not reset, it continues to increment. Basically you need to delete/update the table to reset the counter, or you can reset it manually if you really need to.
If you restart the tests, you will notice that the first test that inserts the record will start from 1 and others will continue the counter, since before the tests you run migration and create a new table, with a new serial counter.
If you are interested to find more about auto increment of the id you can read here.

Take a look on Phoenix 1.4.17 Testing Document. The reason happy_app_test db is empty:
The default test helper file, test/test_helper.exs, creates and migrates our test database for us. It also starts a transaction for each test to run in. This will "clean" the database by rolling back the transaction as each test completes.
And Why the id doesn't start from 1 is the database keep AUTO_INCREMENT the id unless you reset the database or specify postgres database.
Update: check out mix.exs file
defp aliases do
[
"ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"],
"ecto.reset": ["ecto.drop", "ecto.setup"],
test: ["ecto.create --quiet", "ecto.migrate", "test"]
]
end
When you run mix test, it actually calls 3 commands: "ecto.create --quiet", "ecto.migrate", "test". This why database is clean after each test.

Related

How can I submit unsubmitted Moodle attempt via SQL

Hello I ma trying to submit unsubmitted quiz attempts so I can grade them. So far I have set the timefinish column in mdl_quiz_attempts which changes the attempt status to "Not yet graded", then setting fraction to 0 from NULL and state to "gradewrong" from "complete" in mdl_question_attempt_steps to simulate submission but this seems to break the site. What am I missing?
You're going to have to trace through the code for the process_finish() function in mod/quiz/attemptlib.php ( https://github.com/moodle/moodle/blob/master/mod/quiz/attemptlib.php#L2171 ) and figure out how that all works.
This is a complex process and will require a lot of DB queries / updates in order to achieve it manually.
I would strongly recommend that you write a PHP script to do this, instead of trying to handle it manually (that way you can create an instance of 'quiz_attempt' for each user's attempt, then call $attempt->process_finish() on each, in order to close the attempt properly).
Thanks. The trick is to set the timefinish column in mdl_quiz_attempts which changes the attempt status to "Not yet graded", then setting the state to "gradewrong" from "complete" in mdl_question_attempt_steps for unsubmitted responses to simulate submission. Then set a fake 0 grade to sumgrades where grades are NULL in mdl_quiz_attempts and then running a regrade in the admin panel.

Using QCMDEXC to call QEZSNDMG via DB2 stored procedure

Working on a side project where I use a set of views to identify contention of records within an iSeries set of physical files.
What I would like to do once identified is pull the user profile locking the record, and then send a break message to their terminal as an informational break message.
What I have found is the QEZSNDMG API. Simple enough to use interactively, but I'm trying to put together a command that would be used in conjunction with QCMDEXC API to issue the call to QEZSNDMG and alert the user that they are locking a record.
Reviewing the IBM documentation of the QEZSNDMG API, I see that there are two sets of option parameters, but nothing as required (which seems odd to me, but another topic for another day). But I continue to receive the error "Parameters passed on CALL do not match those required."
Here are some examples that I have tried from the command line so far:
CALL PGM(QEZSNDMG) PARM('*INFO' '*BREAK' 'TEST' '4' 'DOUGLAS' '1' '1' '-4')
CALL PGM(QEZSNDMG) PARM('*INFO' '*BREAK' 'TEST' '4' 'DOUGLAS')
CALL PGM(QEZSNDMG) PARM('*INFO' '*BREAK' 'TEST' '4' 'DOUGLAS' '1')
Note: I would like to avoid using a CL or RPG program if possible but understand it may come to that using one of many examples I found before posting. Just want to exhaust this option before going down that road.
Update
While logged in, I used WRKMSGQ to see the message queues assigned to my station. There were two: QSYS/DOUGLAS and QUSRSYS/DOUGLAS. I then issued SNDBRKMSG with no affect on my workstation (IE, the message didn't break my session):
SNDBRKMSG MSG(TESTING) TOMSGQ(QSYS/DOUGLAS)
SNDBRKMSG MSG(TESTING) TOMSGQ(QUSRSYS/DOUGLAS)
I realized if I provide the workstation session name in the TOMSG parameter it worked:
SNDBRKMSG MSG(TESTING) TOMSGQ(*LIBL/QPADEV0003)
Using SNDBRKMSG was what I was looking for.
Some nudging in the right direction lead me to realize that the workstation session ID is located within QSYS2.RCD_LOCK in field JOB_NAME (job number/username/workstation).
Extracting the workstation ID allowed me to create a correctly formatted SNDBRKMSG command to QCMDEXC and alert the user that they are locking a record needed by another process.

Get update db (in postgres) notifications in phoenix

I need to now when a row changed in my db. I'm using phoenix 1.2.4. I already have the triggers using postgres, but actually I don't know if I need them.
Do you know how could I solve my problem?
NOTE: The data base isn't necessarily changed from the controllers, rather I have a cron that update some parts.
I saw this tutorial (Publish/subscribe with PostgreSQL and Phoenix Framework) a few days ago and it seems like it contains exactly what you want.
It sets up the notification from the DB and then broadcast it. In your case, you just need the notification part and should be all good.
I hope that helps :)
Postgrex.Notifications is the module which will use postgresql listen/notify to deliver messages to an elixir process.
A simple example:
defmodule MyListener do
use GenServer
def start_link(), do: GenServer.start_link(__MODULE__, [])
def init(_arg) do
{:ok, pid} = Postgrex.Notifications.start_link(MyRepo.config())
Postgrex.Notifications.listen(pid, "my_table")
{:ok, []}
end
def handle_info({:notification, _connection_pid, _ref, _channel, payload}, state) do
# ... do something with payload ...
{:noreply, state}
end
end

expect command in Solaris 11

New to expect command, In Solaris 11 the expect package is included, and I understand from Linux it's very useful for automation.
Am trying to create around 10 users and set password for the users by a script.
#!/usr/bin/expect
spawn /usr/bin/passwd user1
expect "New password: \n"
send "Userpass123$\r"
expect "Re-enter new Password: \n"
send "Userpass123$\r"
The password is being set correctly, but its taking almost 20 seconds to set the password for a single user,
Find the output below
JUDI-DEV-01# time /tmp/123
spawn /usr/bin/passwd user1
New Password:
Re-enter new Password:
real 0m20.023s
user 0m0.005s
sys 0m0.005s
JUDI-DEV-01#
Please help me in fetching the user id , UID , GID , home dir, from a file and to create the user accounts
example file data is /tmp/userlist
user1:150:20:App User1:/export/home/user1:/bin/ksh
user2:151:20:App User2:/export/home/user2:/bin/ksh
user3:152:20:App User3:/export/home/user3:/bin/ksh
dbuser1:201:30:db user1:/export/home/dbuser1:/usr/bin/ksh
dbuser2:202:30:db user1:/export/home/dbuser2:/usr/bin/ksh
I know to separate the values to different variable in shell script, not sure how it works in expect
After sending the password for the second time, add expect eof. This will ensure the completion of the program.
send "Userpass123$\r"
expect eof
To split the values, you can use split command
% split "dbuser1:201:30:db user1:/export/home/dbuser1:/usr/bin/ksh" :
dbuser1 201 30 {db user1} /export/home/dbuser1 /usr/bin/ksh
%

Elixir's comeonin does not seem to be checking hashes correctly

So I recently decided I wanted to learn Elixir for the new year, and have been going through the Phoenix framework's book on how web development works in Elixir.
So far I am really enjoying it, and am already starting to love the language. I've come across a few issues with the Come-on-in package though.
One was compiling it, which is fine. But I am wondering if it is causing problems, the issue is I am having trouble figuring out how to debug this issue.
defmodule Rumbl.Auth do
import Plug.Conn
def init(opts) do
Keyword.fetch!(opts, :repo)
end
def call(conn, repo) do
user_id = get_session(conn, :user_id)
user = user_id && repo.get(Rumbl.User, user_id)
assign(conn, :current_user, user)
end
def login(conn, user) do
conn
|> assign(:current_user, user)
|> put_session(:user_id, user.id)
|> configure_session(renew: true)
end
def logout(conn) do
configure_session(conn, drop: true)
end
import Comeonin.Bcrypt, only: [checkpw: 2, dummy_checkpw: 0]
def login_by_username_and_pass(conn, username, given_pass, opts) do
repo = Keyword.fetch!(opts, :repo)
user = repo.get_by(Rumbl.User, username: username)
cond do
user && checkpw(given_pass, user.password_hash) ->
{:ok, login(conn, user)}
user ->
{:error, :unauthorized, conn}
true ->
dummy_checkpw()
{:error, :not_found, conn}
end
end
end
That is the code, and everything is compiling and I can see it's being sent through correctly. But for some reason the password is never being resolved. I made another user with the password "password" and even did something like this:
checkpw("password", "$2b$12$aa4dos3r4YwX7HKgj.JiL.bEzg42QjxBvWwm5M")
Just to see if it was how I was passing the information, obviously that is the hash in my database, and that also does not work. I am at a loss to what I am doing wrong, or since this is my first time using Bcrypt and am not 100% sure how the salting works if it's how I am using the library itself.
I am hashing the passwords with this:
defp put_pass_hash(changeset) do
case changeset do
%Ecto.Changeset{valid?: true, changes: %{password: pass}} ->
put_change(changeset, :password_hash, Comeonin.Bcrypt.hashpwsalt(pass))
_ ->
changeset
end
end
I've looked over everything I can think of, and it all looks correct, but for some reason Comeonin is not comparing the passwords correctly. Any help would be much appreciated, thanks!
The issue I was having was not anything to do with Elixir or the Comeonin library!
I had only allowed a Varchar of 45 for my passwords, and it was truncating the response. I am just going to leave this here in case anyone does something as silly as this in the future!