<feed xmlns='http://www.w3.org/2005/Atom'>
<title>finserv, branch auth</title>
<subtitle>Personal finances server</subtitle>
<id>https://cgit.xengineering.eu/finserv/atom/?h=auth</id>
<link rel='self' href='https://cgit.xengineering.eu/finserv/atom/?h=auth'/>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/finserv/'/>
<updated>2026-06-27T19:52:31Z</updated>
<entry>
<title>Add NewToken()</title>
<updated>2026-06-27T19:52:31Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2026-06-27T19:47:51Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/finserv/commit/?id=94f5bcd677c5c3c6032e3d2973b416644df55e42'/>
<id>urn:sha1:94f5bcd677c5c3c6032e3d2973b416644df55e42</id>
<content type='text'>
This creates a new token for session management.
</content>
</entry>
<entry>
<title>Switch Register() and Authenticate() to sql.Tx</title>
<updated>2026-06-27T19:21:45Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2026-06-27T19:21:45Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/finserv/commit/?id=132990e985751e40c263224a62983c8013409a36'/>
<id>urn:sha1:132990e985751e40c263224a62983c8013409a36</id>
<content type='text'>
Using sql.Tx (database transactions) instead of a plain database has the
advantage that the caller can wrap multiple library calls into one
transaction.

This guarantees that no database entries change between the library
calls which is critical to prevent race conditions.
</content>
</entry>
<entry>
<title>Add core functionality of /api/authenticate</title>
<updated>2026-06-27T18:47:36Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2026-06-27T18:47:36Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/finserv/commit/?id=ea4bd88963724c13f7b906d856af2d1c715fc056'/>
<id>urn:sha1:ea4bd88963724c13f7b906d856af2d1c715fc056</id>
<content type='text'>
This handler now actually validates the username and password and
returns a matching HTTP response code.
</content>
</entry>
<entry>
<title>Harmonize function names further</title>
<updated>2026-06-22T18:11:39Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2026-06-22T18:11:39Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/finserv/commit/?id=485fb6556eed127c59e52915ec2984ee84c8210b'/>
<id>urn:sha1:485fb6556eed127c59e52915ec2984ee84c8210b</id>
<content type='text'>
</content>
</entry>
<entry>
<title>sql: migrations: Add 0003.sqlite3</title>
<updated>2026-06-22T18:10:50Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2026-06-22T18:09:08Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/finserv/commit/?id=56dd6588503908d9a562445c1cb6a99c2a7aa415'/>
<id>urn:sha1:56dd6588503908d9a562445c1cb6a99c2a7aa415</id>
<content type='text'>
This adds persistence for tokens.
</content>
</entry>
<entry>
<title>Remove registration handler</title>
<updated>2026-06-22T18:10:43Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2026-06-22T17:57:20Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/finserv/commit/?id=a4535e0aa3e103f87bae6c3f1a1527588e60208c'/>
<id>urn:sha1:a4535e0aa3e103f87bae6c3f1a1527588e60208c</id>
<content type='text'>
This should be an admin-only task which should maybe be done via command
line on the server.
</content>
</entry>
<entry>
<title>Remove wrong auth call</title>
<updated>2026-06-22T17:56:41Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2026-06-22T17:56:41Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/finserv/commit/?id=188d40cc52329e55afbb3a55be2b94057bedb339'/>
<id>urn:sha1:188d40cc52329e55afbb3a55be2b94057bedb339</id>
<content type='text'>
</content>
</entry>
<entry>
<title>Use only string-based input output for HTTP tests</title>
<updated>2026-06-21T12:36:47Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2026-06-21T12:36:47Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/finserv/commit/?id=2009b9726e2aac595a186063deb729df0d7cd850'/>
<id>urn:sha1:2009b9726e2aac595a186063deb729df0d7cd850</id>
<content type='text'>
The API should only communicate via UTF-8 encoded text. Requiring by
default makes test case notation easier and improves scalability.
</content>
</entry>
<entry>
<title>Name HTTP handlers based on intended paths</title>
<updated>2026-06-21T12:33:43Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2026-06-21T12:33:43Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/finserv/commit/?id=20f56806b405f3d33f3db2f419e02a3361d99296'/>
<id>urn:sha1:20f56806b405f3d33f3db2f419e02a3361d99296</id>
<content type='text'>
</content>
</entry>
<entry>
<title>Add authenticate HTTP handler</title>
<updated>2026-06-21T12:33:19Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2026-06-21T11:30:06Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/finserv/commit/?id=97516f00e4206823f8c4485449f0080823ac5e35'/>
<id>urn:sha1:97516f00e4206823f8c4485449f0080823ac5e35</id>
<content type='text'>
</content>
</entry>
<entry>
<title>Add `register` HTTP handler</title>
<updated>2026-06-21T09:55:44Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2026-06-21T09:49:42Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/finserv/commit/?id=7ab03af3f662c90b1868f5ef14e70f443b2d91cd'/>
<id>urn:sha1:7ab03af3f662c90b1868f5ef14e70f443b2d91cd</id>
<content type='text'>
This allows users to register.
</content>
</entry>
<entry>
<title>Fix wrong error message</title>
<updated>2026-06-21T08:53:35Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2026-06-21T08:53:35Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/finserv/commit/?id=383cf7a521f7bfcdf552cd18ea9919930af2e9cf'/>
<id>urn:sha1:383cf7a521f7bfcdf552cd18ea9919930af2e9cf</id>
<content type='text'>
</content>
</entry>
<entry>
<title>Do not use init for HTTP handler registration</title>
<updated>2026-06-21T08:49:11Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2026-06-21T08:49:11Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/finserv/commit/?id=2dc210a7ee7272f241f6d159ccca01c4da4228d2'/>
<id>urn:sha1:2dc210a7ee7272f241f6d159ccca01c4da4228d2</id>
<content type='text'>
This does not allow to use a *sql.DB which is initialized in main()
inside to pass it to handlers with DB access.
</content>
</entry>
<entry>
<title>Add TestHTTPVersion</title>
<updated>2026-06-20T20:30:36Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2026-06-20T20:30:36Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/finserv/commit/?id=b4950dfa73802afb63009f3ef501463baf5c30e2'/>
<id>urn:sha1:b4950dfa73802afb63009f3ef501463baf5c30e2</id>
<content type='text'>
This introduces the first HTTP test.
</content>
</entry>
<entry>
<title>Add integration test TestRegisterAuthenticate</title>
<updated>2026-06-20T15:12:18Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2026-06-20T15:10:09Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/finserv/commit/?id=bbf9efa82e96761f93b591e1a159ef7afb1f05c0'/>
<id>urn:sha1:bbf9efa82e96761f93b591e1a159ef7afb1f05c0</id>
<content type='text'>
This makes sure the implementations of Register() and Authenticate() are
compatible.
</content>
</entry>
<entry>
<title>Add Authenticate()</title>
<updated>2026-06-20T15:12:18Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2026-06-20T15:07:47Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/finserv/commit/?id=a5c8467bbb14731847cdf8c37cbde0c91827022a'/>
<id>urn:sha1:a5c8467bbb14731847cdf8c37cbde0c91827022a</id>
<content type='text'>
This function validates a username and password against the database.
</content>
</entry>
<entry>
<title>Format password.go</title>
<updated>2026-06-20T15:12:14Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2026-06-20T15:01:36Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/finserv/commit/?id=6c0aaac6975bdee1596df5b72c1e47e6a923c79f'/>
<id>urn:sha1:6c0aaac6975bdee1596df5b72c1e47e6a923c79f</id>
<content type='text'>
</content>
</entry>
<entry>
<title>Add Register()</title>
<updated>2026-06-20T15:10:39Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2026-06-05T20:45:01Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/finserv/commit/?id=0143b6e4cb7c31abee7d71a2dbd713abcc98936d'/>
<id>urn:sha1:0143b6e4cb7c31abee7d71a2dbd713abcc98936d</id>
<content type='text'>
This function creates a new user and sets the username and bcrypt-hashed
password.
</content>
</entry>
<entry>
<title>sql: migrations: Add 0002.sqlite3</title>
<updated>2026-06-20T12:08:03Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2026-06-05T20:39:17Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/finserv/commit/?id=3934137fa15737145094ec4607de82e5b3dbf063'/>
<id>urn:sha1:3934137fa15737145094ec4607de82e5b3dbf063</id>
<content type='text'>
This migrations adds a `users` table with id, username and
password_bcrypt.

This allows basic user management and authentication.
</content>
</entry>
<entry>
<title>go.mod: Use braces</title>
<updated>2026-06-20T12:08:03Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2026-06-20T11:57:13Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/finserv/commit/?id=5d581f1526437b4dde8d16600883958cb47eec73'/>
<id>urn:sha1:5d581f1526437b4dde8d16600883958cb47eec73</id>
<content type='text'>
This makes the file less repetitive and diffs more readable.
</content>
</entry>
<entry>
<title>Add golang.org/x/crypto</title>
<updated>2026-06-05T20:30:01Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2026-06-05T20:29:50Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/finserv/commit/?id=4ec2d77a60dd5242c428537c0d3e719954a3bb45'/>
<id>urn:sha1:4ec2d77a60dd5242c428537c0d3e719954a3bb45</id>
<content type='text'>
This is required to have bcrypt hashing to hash passwords.
</content>
</entry>
<entry>
<title>Add global db variable and open connection to it</title>
<updated>2026-06-05T19:01:52Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2026-06-05T18:59:27Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/finserv/commit/?id=3395bc1cd32698897385596022e0c855765b48f2'/>
<id>urn:sha1:3395bc1cd32698897385596022e0c855765b48f2</id>
<content type='text'>
This allows any handler to access the database via a global variable.
The connection is closed when the run function finishes.
</content>
</entry>
<entry>
<title>Add TestTransaction</title>
<updated>2026-06-02T18:27:05Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2026-06-02T18:27:05Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/finserv/commit/?id=3ad3565c64ed1ce692c0509d8fe5a7530f8fb7e3'/>
<id>urn:sha1:3ad3565c64ed1ce692c0509d8fe5a7530f8fb7e3</id>
<content type='text'>
This makes sure the assumption is correct that everything inside a
transaction is rolled back if the transaction fails.
</content>
</entry>
<entry>
<title>Add TestUserVersion</title>
<updated>2026-06-02T18:20:17Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2026-06-02T18:20:17Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/finserv/commit/?id=a3009e165c4cdbf94eb23a071d5e6c39425539e8'/>
<id>urn:sha1:a3009e165c4cdbf94eb23a071d5e6c39425539e8</id>
<content type='text'>
This is partially redundant to MigrateToLatest. Nevertheless a layered
testing approach is useful to detect low-level problems in test
functions which are simple.
</content>
</entry>
<entry>
<title>Name tests like functions to test</title>
<updated>2026-06-02T18:12:53Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2026-06-02T18:12:53Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/finserv/commit/?id=975349b50e3d2c76564fef686a2a33b01212b6d3'/>
<id>urn:sha1:975349b50e3d2c76564fef686a2a33b01212b6d3</id>
<content type='text'>
This enforces a similar structure of test functions named `TestFooBar`
if they test the function `FooBar`.
</content>
</entry>
<entry>
<title>Add MigrateToLatest</title>
<updated>2026-06-02T17:52:18Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2026-06-02T17:52:18Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/finserv/commit/?id=a750aa4ecf7ecab519b53d7f3ac082425ba50686'/>
<id>urn:sha1:a750aa4ecf7ecab519b53d7f3ac082425ba50686</id>
<content type='text'>
This function will be used most by the production software to update
the database schema to the latest known version.
</content>
</entry>
<entry>
<title>Remove success logging in tests</title>
<updated>2026-06-02T17:40:55Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2026-06-02T17:40:55Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/finserv/commit/?id=bd1ead99fd53ad8c3c016b59d67f5bf58ade5095'/>
<id>urn:sha1:bd1ead99fd53ad8c3c016b59d67f5bf58ade5095</id>
<content type='text'>
In case the test succeeds it is not required to log anything. This only
adds noise to the output.
</content>
</entry>
<entry>
<title>Add UserVersion()</title>
<updated>2026-05-31T19:37:16Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2026-05-31T19:34:44Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/finserv/commit/?id=29ae857b5ca13fa12f1d07d4a30597ff9ce28767'/>
<id>urn:sha1:29ae857b5ca13fa12f1d07d4a30597ff9ce28767</id>
<content type='text'>
This function gets the user_version SQLite3 field describing which
migration was the last executed one.

A test checking this before applying any migrations and after each
migration is included.
</content>
</entry>
<entry>
<title>Add migration execution</title>
<updated>2026-05-31T19:37:13Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2026-05-31T19:20:48Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/finserv/commit/?id=efb324070827bd1fe713b93f80c601551d246579'/>
<id>urn:sha1:efb324070827bd1fe713b93f80c601551d246579</id>
<content type='text'>
This adds the execution of the embedded migrations and adds a suitable
unit test.
</content>
</entry>
<entry>
<title>Add migration reading</title>
<updated>2026-05-31T18:48:51Z</updated>
<author>
<name>xengineering</name>
<email>me@xengineering.eu</email>
</author>
<published>2026-05-31T16:13:15Z</published>
<link rel='alternate' type='text/html' href='https://cgit.xengineering.eu/finserv/commit/?id=4cb6a5952f341741ef2728fb39acb7f19de61ba9'/>
<id>urn:sha1:4cb6a5952f341741ef2728fb39acb7f19de61ba9</id>
<content type='text'>
This prepares the infrastructure to place migration SQL code in the
source repository with paths formatted as `sql/migrations/%04d.sqlite3`.
The numbers need to be counting up from 1.

They are embedded with Go's embed package and are parsed into a slice of
strings where the migration number minus one is the slice index and the
value is the migrations file as string.

This makes handling of migrations in code as easy as possible.

This commit adds also tests for this functionality.
</content>
</entry>
</feed>
