Skip to content
You are viewing docs for v0.1.0. Switch to latest

Admin Login App REST API Example

This document demonstrates sample data based on the deql deql-lang/examples/admin-login-app/admin-login-demo.deql

Terminal window
/api/health
{"status":"ok"}
/api/info
{"concept_counts":{"aggregates":1,"commands":3,"decisions":3,"events":4,"eventstores":0,"projections":2,"templates":0},"readonly":false,"version":"0.1.0"}
/api/dereg/aggregates
rowname
0AdminAccount
/api/dereg/commands
rownamefield_countaggregate
0BootstrapAdmin3AdminAccount
1ChangePassword3AdminAccount
2LoginAdmin2AdminAccount
/api/dereg/events
rownamefield_countaggregate
0AdminBootstrapped2AdminAccount
1AdminLoginFailed2AdminAccount
2AdminLoginSucceeded2AdminAccount
3PasswordChanged1AdminAccount
/api/dereg/decisions
rownameaggregatecommandhas_guardemitted_eventsguard_sqlstate_as_sql
0BootstrapAdminDecisionAdminAccountBootstrapAdmintrueAdminBootstrappedexisting_flag IS NULLsql SELECT 1 AS existing_flag FROM DeReg."AdminAccount$Events" WHERE stream_id = :user_id AND event_type = 'AdminBootstrapped' LIMIT 1
1ChangePasswordDecisionAdminAccountChangePasswordtruePasswordChangedencode(digest(:old_password,‘sha256’),‘hex’) = current_hash AND encode(digest(:new_password,‘sha256’),‘hex’) <> current_hashsql SELECT COALESCE(LAST(CASE WHEN event_type = 'PasswordChanged' THEN data.new_password_hash END), LAST(CASE WHEN event_type = 'AdminBootstrapped' THEN data.password_hash END)) AS current_hash FROM DeReg."AdminAccount$Events" WHERE stream_id = :user_id
2LoginAdminDecisionAdminAccountLoginAdmintrueAdminLoginSucceeded, AdminLoginFailedNonesql SELECT COALESCE(LAST(CASE WHEN event_type = 'PasswordChanged' THEN data.new_password_hash END), LAST(CASE WHEN event_type = 'AdminBootstrapped' THEN data.password_hash END)) AS current_hash FROM DeReg."AdminAccount$Events" WHERE stream_id = :user_id

Full SQL row 0

CREATE DECISION BootstrapAdminDecision
FOR AdminAccount
ON COMMAND BootstrapAdmin
STATE AS
SELECT 1 AS existing_flag
FROM DeReg."AdminAccount$Events"
WHERE stream_id = :user_id
AND event_type = 'AdminBootstrapped'
LIMIT 1
EMIT AS
SELECT EVENT AdminBootstrapped (
username := :username,
password_hash := :password_hash
)
WHERE existing_flag IS NULL;

Full sql row 1

CREATE DECISION ChangePasswordDecision
FOR AdminAccount
ON COMMAND ChangePassword
STATE AS
SELECT COALESCE(
LAST(CASE WHEN event_type = 'PasswordChanged' THEN data.new_password_hash END),
LAST(CASE WHEN event_type = 'AdminBootstrapped' THEN data.password_hash END)
) AS current_hash
FROM DeReg."AdminAccount$Events"
WHERE stream_id = :user_id
EMIT AS
SELECT EVENT PasswordChanged (
new_password_hash := encode(digest(:new_password,'sha256'),'hex')
)
WHERE encode(digest(:old_password,'sha256'),'hex') = current_hash
AND encode(digest(:new_password,'sha256'),'hex') <> current_hash;

FUll sql row 2

CREATE DECISION LoginAdminDecision
FOR AdminAccount
ON COMMAND LoginAdmin
STATE AS
SELECT COALESCE(
LAST(CASE WHEN event_type = 'PasswordChanged' THEN data.new_password_hash END),
LAST(CASE WHEN event_type = 'AdminBootstrapped' THEN data.password_hash END)
) AS current_hash
FROM DeReg."AdminAccount$Events"
WHERE stream_id = :user_id
EMIT AS
BRANCH PasswordMatch
SELECT EVENT AdminLoginSucceeded (
session_token := encode(digest(CAST(random() AS VARCHAR),'sha256'),'hex'),
login_at := ARROW_CAST(CAST(CURRENT_TIMESTAMP AS VARCHAR),'Utf8')
)
WHERE current_hash IS NOT NULL
AND encode(digest(:password,'sha256'),'hex') = current_hash
UNION ALL
BRANCH PasswordMismatch
SELECT EVENT AdminLoginFailed (
attempted_at :=
/api/dereg/decisions/ChangePasswordDecision
rownameaggregatecommandhas_guardemitted_eventsguard_sqlstate_as_sql
0ChangePasswordDecisionAdminAccountChangePasswordTruePasswordChangedencode(digest(:old_password,‘sha256’),‘hex’) = current_hash AND encode(digest(:new_password,‘sha256’),‘hex’) <> current_hashSELECT COALESCE(LAST(CASE WHEN event_type = ‘PasswordChanged’ THEN data.new_password_hash END), LAST(CASE WHEN event_type = ‘AdminBootstrapped’ THEN data.password_hash END)) AS current_hash FROM DeReg.”AdminAccount$Events” WHERE stream_id = :user_id

Full SQL

CREATE DECISION ChangePasswordDecision
FOR AdminAccount
ON COMMAND ChangePassword
STATE AS
SELECT COALESCE (
LAST ( CASE WHEN event_type = 'PasswordChanged' THEN data . new_password_hash END ) ,
LAST ( CASE WHEN event_type = 'AdminBootstrapped' THEN data . password_hash END )
) AS current_hash
FROM DeReg . "AdminAccount$Events"
WHERE stream_id = :user_id
EMIT AS
SELECT EVENT PasswordChanged (
new_password_hash := encode ( digest ( :new_password , 'sha256' ) , 'hex' )
)
WHERE encode ( digest ( :old_password , 'sha256' ) , 'hex' ) = current_hash
AND encode ( digest ( :new_password , 'sha256' ) , 'hex' ) <> current_hash;
/api/dereg/projections
rownamequery_sql
0FailedLoginReportsql SELECT stream_id AS user_id, seq, data.attempted_at AS attempted_at, data.reason AS reason FROM DeReg."AdminAccount$Events" WHERE event_type = 'AdminLoginFailed' ORDER BY stream_id, seq
1LoginMetricssql SELECT stream_id AS user_id, COUNT(*) FILTER (WHERE event_type = 'AdminLoginSucceeded') AS success_count, COUNT(*) FILTER (WHERE event_type = 'AdminLoginFailed') AS failure_count, LAST(CASE WHEN event_type = 'AdminLoginSucceeded' THEN data.login_at END) AS last_login_at, LAST(CASE WHEN event_type = 'AdminLoginFailed' THEN data.attempted_at END) AS last_failure_at FROM DeReg."AdminAccount$Events" GROUP BY stream_id
/api/dereg/templates
Empty DataFrame
Columns: [name, param_count]
Index: []
/api/dereg/eventstores
Empty DataFrame
Columns: [name]
Index: []
/api/dereg/aggregates/AdminAccount
rowname
0AdminAccount
/api/dereg/commands/LoginAdmin
rownamefield_countaggregate
0LoginAdmin2AdminAccount
/api/dereg/decisions/LoginAdminDecision
rownameaggregatecommandhas_guardemitted_eventsguard_sqlstate_as_sql
0LoginAdminDecisionAdminAccountLoginAdminTrueAdminLoginSucceeded, AdminLoginFailedNoneSELECT COALESCE(LAST(CASE WHEN event_type = ‘PasswordChanged’ THEN data.new_password_hash END), LAST(CASE WHEN event_type = ‘AdminBootstrapped’ THEN data.password_hash END)) AS current_hash FROM DeReg.”AdminAccount$Events” WHERE stream_id = :user_id
/api/dereg/projections/LoginMetrics
rownamequery_sql
0LoginMetricssql SELECT stream_id AS user_id, COUNT(*) FILTER (WHERE event_type = 'AdminLoginSucceeded') AS success_count, COUNT(*) FILTER (WHERE event_type = 'AdminLoginFailed') AS failure_count, LAST(CASE WHEN event_type = 'AdminLoginSucceeded' THEN data.login_at END) AS last_login_at, LAST(CASE WHEN event_type = 'AdminLoginFailed' THEN data.attempted_at END) AS last_failure_at FROM DeReg."AdminAccount$Events" GROUP BY stream_id
/api/dereg/aggregates/AdminAccount/fields
Empty DataFrame
Columns: []
Index: []
/api/dereg/commands/LoginAdmin/fields
rowcommand_namefield_namefield_typeis_keyordinal
0LoginAdminuser_idSTRINGFalse0
1LoginAdminpasswordSTRINGFalse1
/api/dereg/commands/BootstrapAdmin/fields
rowcommand_namefield_namefield_typeis_keyordinal
0BootstrapAdminuser_idSTRINGFalse0
1BootstrapAdminusernameSTRINGFalse1
2BootstrapAdminpassword_hashSTRINGFalse2
/api/dereg/commands/ChangePassword/fields
rowcommand_namefield_namefield_typeis_keyordinal
0ChangePassworduser_idSTRINGFalse0
1ChangePasswordold_passwordSTRINGFalse1
2ChangePasswordnew_passwordSTRINGFalse2
/api/dereg/decisions/BootstrapAdminDecision/emits
rowdecision_nameevent_name
0BootstrapAdminDecisionAdminBootstrapped
/api/dereg/decisions/LoginAdminDecision/emits
rowdecision_nameevent_name
0LoginAdminDecisionAdminLoginSucceeded
1LoginAdminDecisionAdminLoginFailed
/api/dereg/decisions/ChangePasswordDecision/emits
rowdecision_nameevent_name
0ChangePasswordDecisionPasswordChanged
/api/aggregates/AdminAccount
rowaggregate_idattempted_atlogin_atnew_password_hashpassword_hashreasonsession_tokenusername
0ADMIN-9992026-04-23T04:34:13.932324NoneNoneNoneaccount_not_foundNoneNone
1ADMIN-0012026-04-23T04:34:14.0068322026-04-23T04:34:13.980024d4e276b8043bc4592cf7ec3b4120e2801f14fd0bc42c704a79d4e48acf3f5e4d1ec1c26b50d5d3c58d9583181af8076655fe00756bf7285940ba3670f99fcba0invalid_passwordNonealice

Re-Hydrated events in an aggregate by aggregate id

Section titled “Re-Hydrated events in an aggregate by aggregate id”
/api/aggregates/AdminAccount/ADMIN-001
rowaggregate_idattempted_atlogin_atnew_password_hashpassword_hashreasonsession_tokenusername
0ADMIN-0012026-04-23T04:34:14.0068322026-04-23T04:34:13.980024d4e276b8043bc4592cf7ec3b4120e2801f14fd0bc42c704a79d4e48acf3f5e4d1ec1c26b50d5d3c58d9583181af8076655fe00756bf7285940ba3670f99fcba0invalid_passwordNonealice
/api/aggregates/AdminAccount/events
rowevent_idstream_typestream_idseqevent_typeoccurred_atdata
01AdminAccountADMIN-0011AdminBootstrapped2026-04-23 04:34:13.863002+00:00{“attempted_at”: null, “login_at”: null, “new_password_hash”: null, “password_hash”: “1ec1c26b50d5d3c58d9583181af8076655fe00756bf7285940ba3670f99fcba0”, “reason”: null, “session_token”: null, “username”: “alice”}
12AdminAccountADMIN-0012AdminLoginFailed2026-04-23 04:34:13.908317+00:00{“attempted_at”: “2026-04-23T04:34:13.906731”, “login_at”: null, “new_password_hash”: null, “password_hash”: null, “reason”: “invalid_password”, “session_token”: null, “username”: null}
23AdminAccountADMIN-9991AdminLoginFailed2026-04-23 04:34:13.933797+00:00{“attempted_at”: “2026-04-23T04:34:13.932324”, “login_at”: null, “new_password_hash”: null, “password_hash”: null, “reason”: “account_not_found”, “session_token”: null, “username”: null}
34AdminAccountADMIN-0013PasswordChanged2026-04-23 04:34:13.957300+00:00{“attempted_at”: null, “login_at”: null, “new_password_hash”: “d4e276b8043bc4592cf7ec3b4120e2801f14fd0bc42c704a79d4e48acf3f5e4d”, “password_hash”: null, “reason”: null, “session_token”: null, “username”: null}
45AdminAccountADMIN-0014AdminLoginSucceeded2026-04-23 04:34:13.983364+00:00{“attempted_at”: null, “login_at”: “2026-04-23T04:34:13.980024”, “new_password_hash”: null, “password_hash”: null, “reason”: null, “session_token”: null, “username”: null}
56AdminAccountADMIN-0015AdminLoginFailed2026-04-23 04:34:14.008298+00:00{“attempted_at”: “2026-04-23T04:34:14.006832”, “login_at”: null, “new_password_hash”: null, “password_hash”: null, “reason”: “invalid_password”, “session_token”: null, “username”: null}
/api/aggregates/AdminAccount/events/ADMIN-001
rowevent_idstream_typestream_idseqevent_typeoccurred_atdata
01AdminAccountADMIN-0011AdminBootstrapped2026-04-23 04:34:13.863002+00:00{“attempted_at”: null, “login_at”: null, “new_password_hash”: null, “password_hash”: “1ec1c26b50d5d3c58d9583181af8076655fe00756bf7285940ba3670f99fcba0”, “reason”: null, “session_token”: null, “username”: “alice”}
12AdminAccountADMIN-0012AdminLoginFailed2026-04-23 04:34:13.908317+00:00{“attempted_at”: “2026-04-23T04:34:13.906731”, “login_at”: null, “new_password_hash”: null, “password_hash”: null, “reason”: “invalid_password”, “session_token”: null, “username”: null}
24AdminAccountADMIN-0013PasswordChanged2026-04-23 04:34:13.957300+00:00{“attempted_at”: null, “login_at”: null, “new_password_hash”: “d4e276b8043bc4592cf7ec3b4120e2801f14fd0bc42c704a79d4e48acf3f5e4d”, “password_hash”: null, “reason”: null, “session_token”: null, “username”: null}
35AdminAccountADMIN-0014AdminLoginSucceeded2026-04-23 04:34:13.983364+00:00{“attempted_at”: null, “login_at”: “2026-04-23T04:34:13.980024”, “new_password_hash”: null, “password_hash”: null, “reason”: null, “session_token”: null, “username”: null}
46AdminAccountADMIN-0015AdminLoginFailed2026-04-23 04:34:14.008298+00:00{“attempted_at”: “2026-04-23T04:34:14.006832”, “login_at”: null, “new_password_hash”: null, “password_hash”: null, “reason”: “invalid_password”, “session_token”: null, “username”: null}
/api/aggregates/AdminAccount/inspect/input/test_logins
rowcolumn1column2
0ADMIN-001N3wP@ss!
1ADMIN-001wrong
2ADMIN-999anything
/api/aggregates/AdminAccount/inspect/output/simulated_login_events
rowevent_idstream_typestream_idseqevent_typeoccurred_atdata
0019db89d-f9b9-7512-8297-e3f9d3a6b233AdminAccountADMIN-0011AdminLoginSucceeded2026-04-23 04:34:14.073096+00:00{“attempted_at”: null, “login_at”: “2026-04-23T04:34:14.071490”, “reason”: null, “session_token”: “6cccf00982d094b7761381c021788822b22d4cea2c5378bbdf8d60f224005c6b”}
1019db89d-f9d4-7762-a8d0-cb7b1be08ee7AdminAccountADMIN-0012AdminLoginFailed2026-04-23 04:34:14.100901+00:00{“attempted_at”: “2026-04-23T04:34:14.099677”, “login_at”: null, “reason”: “invalid_password”, “session_token”: null}
2019db89d-f9ee-7ee2-b67c-e9aada3c907eAdminAccountADMIN-9991AdminLoginFailed2026-04-23 04:34:14.126643+00:00{“attempted_at”: “2026-04-23T04:34:14.124955”, “login_at”: null, “reason”: “account_not_found”, “session_token”: null}

Inspect decision output branches table by name

Section titled “Inspect decision output branches table by name”
/api/aggregates/AdminAccount/inspect/output/simulated_login_events__branches
rowinspect_row_indexdecision_namebranch_idbranch_indexbranch_rule_namebranch_guardbranch_statusevent_typestream_id
00LoginAdminDecisionb_e05bcdb22827fa2e1PasswordMatchcurrent_hash IS NOT NULL AND encode(digest(:password,‘sha256’),‘hex’) = current_hashemittedAdminLoginSucceededADMIN-001
10LoginAdminDecisionb_b510cb20ff7184322PasswordMismatchcurrent_hash IS NULL OR encode(digest(:password,‘sha256’),‘hex’) <> current_hashguard_failedNoneADMIN-001
21LoginAdminDecisionb_e05bcdb22827fa2e1PasswordMatchcurrent_hash IS NOT NULL AND encode(digest(:password,‘sha256’),‘hex’) = current_hashguard_failedNoneADMIN-001
31LoginAdminDecisionb_b510cb20ff7184322PasswordMismatchcurrent_hash IS NULL OR encode(digest(:password,‘sha256’),‘hex’) <> current_hashemittedAdminLoginFailedADMIN-001
42LoginAdminDecisionb_e05bcdb22827fa2e1PasswordMatchcurrent_hash IS NOT NULL AND encode(digest(:password,‘sha256’),‘hex’) = current_hashguard_failedNoneADMIN-999
52LoginAdminDecisionb_b510cb20ff7184322PasswordMismatchcurrent_hash IS NULL OR encode(digest(:password,‘sha256’),‘hex’) <> current_hashemittedAdminLoginFailedADMIN-999
/api/dereg/inspections
rownametypeinput_tableoutput_table
0simulated_login_eventsDecisiontest_loginssimulated_login_events

Full sql INSPECT DECISION LoginAdminDecision FROM test_logins INTO simulated_login_events;

/api/dereg/inspections/simulated_login_events
rownametypeinput_tableoutput_table
0simulated_login_eventsDecisiontest_loginssimulated_login_events

Full sql INSPECT DECISION LoginAdminDecision FROM test_logins INTO simulated_login_events;

Execute command using http post json LoginAdmin

Section titled “Execute command using http post json LoginAdmin”
/api/aggregates/AdminAccount/execute/LoginAdmin '{"params": {"user_id": "ADMIN-001", "password": "s3cret"}}'
Terminal window
curl -X POST 'http://localhost:8080/api/aggregates/AdminAccount/execute/LoginAdmin' \
-H 'Content-Type: application/json' \
-d '{
"params": {
"user_id": "ADMIN-001",
"password": "s3cret"
}
}'
rowevent_typestream_idseqstatusfields
0AdminLoginFailedADMIN-0018success{“attempted_at”:“2026-04-23T08:28:39.351318”,“reason”:“invalid_password”}

Execute command using http post json LoginAdmin success

Section titled “Execute command using http post json LoginAdmin success”
/api/aggregates/AdminAccount/execute/LoginAdmin '{"params": {"user_id": "ADMIN-001", "password": "N3wP@ss!"}}'
Terminal window
curl -X POST 'http://localhost:8080/api/aggregates/AdminAccount/execute/LoginAdmin' \
-H 'Content-Type: application/json' \
-d '{
"params": {
"user_id": "ADMIN-001",
"password": "N3wP@ss!"
}
}'
rowevent_typestream_idseqstatusfields
0AdminLoginSucceededADMIN-0019success{“login_at”:“2026-04-23T08:34:47.169076”,“session_token”:“57952c631c6a5c303d0dd530244f8759b3200bbd809eb6b40acd11e002beab48”}
/api/projections/LoginMetrics/query
rowuser_idsuccess_countfailure_countlast_login_atlast_failure_at
0ADMIN-99901None2026-04-23T04:34:13.932324
1ADMIN-001252026-04-23T08:34:47.1690762026-04-23T08:28:39.351318

Query projections by name FailedLoginReport

Section titled “Query projections by name FailedLoginReport”
/api/projections/FailedLoginReport/query
rowuser_idseqattempted_atreason
0ADMIN-00122026-04-23T04:34:13.906731invalid_password
1ADMIN-00152026-04-23T04:34:14.006832invalid_password
2ADMIN-00162026-04-23T08:21:06.826926invalid_password
3ADMIN-00172026-04-23T08:27:01.967859invalid_password
4ADMIN-00182026-04-23T08:28:39.351318invalid_password
5ADMIN-99912026-04-23T04:34:13.932324account_not_found