model: introduce ID type
Based on UUIDv7 but represented to users in a more compact base32 form,
though all of that are internal implementation details.
database: add WithReadOnlyTx
Refactor config loading and server initialization
As is, LoadConfig() does some things that are not strictly related to
the configuration, such as parsing command line arguments. This has led
to a proliferation of different ways to load the config based on various
needs and also prevents tools that need a config but are not services to
use custom command line arguments.
This commit aims to decouple config loading from everything else and
do nothing but loading the config files.
On a high level, this commit:
- renames server.NewServer() to server.New()
- moves config.Debug and config.Addr into the server package
- moves crypto.InitCrypto() call into server.New()
- moves command line parsing into server.New(), using passed-in values
rather than os.Args
The only changes required for services would be changing
cfg := config.LoadConfig(":5100")
server := server.NewServer("meta.sr.ht", cfg)
to
cfg := config.LoadConfig()
server := server.New("meta.sr.ht", ":5100", cfg, os.Args)
All other tools will be switched to just LoadConfig() and, optionally, a
call to crypto.InitCrypto(). I managed to completely remove some global
state (addr) and at least make the rest private, so that users are
forced to use the designated functions.
The config module gained support for custom FS implementation, mainly
for testing.
objects: bring back support for plain HTTP
This got lost during the transition from minio to S3 client.
client: improve user agent
config: don't log config path
This is kind of useful but it's also pretty noisy in a lot of places.
server: enable GraphQL introspection
Don't prevent suspended users from authenticating
With cookies or internal auth. The frontends already prevent users from
accessing services while suspended, and there are some complications if
we don't let the frontends access the backends at all if the
authenticated user is suspended.
auth: remove legacy OAuth support
auth/bearer: log username associated with expired token
objects: improve support for our s3 deployment
Not sure how well this generalizes but we can improve it when someone
complains.
Switch from minio to AWS SDK S3 client
Moves s3 => objects to avoid conflicting with the AWS module.
server: log GraphQL queries if running in debug mode
auth: fix remote IP determination for audit log
This is probably isolated to dev or other small environments, but I had
two issues with the remote IP determination, breaking the audit log
display in my dev env after fairly standard usage.
The gist is that the audit log is designed to contain clean IP addresses
only. However, the algorithm starts out with `r.RemoteAddr`, which may
contain a port (usually 127.0.0.1:xxxxx). The port removal is already
performed at the beginning of the function, so simply re-use the result
of this.
Furthermore, the initial value (containing the port leading to breakage)
landed in the audit log because I was using a private IP (it's my dev
evn). We correctly trust private IPs, but that means if no public IP
ever shows up in the X-Forwarded-For header, the last private IP was the
one that actually made the request.
I am not entirely sure why this showed up now. I already had a bunch of
oder audit log entries that had the correct private-but-not-localhost
addresses. But in the current state, e.g. simply updating my profile
would cause the bad IP:port notation to be written to the audit log.
server: handle CORS in server
Currently CORS is handled in nginx in front of the API. That setup is
not very suitable for Kubernetes. Instead, handle CORS here, so we do
not need any intermediaries between the ingress and the APIs.
The CORS settings are taken from sr.ht-nginx/graphql.conf [1]
[1] https://git.sr.ht/~sircmpwn/sr.ht-nginx/tree/master/item/graphql.conf
.builds/alpine.yml: upgrade to 3.22
Update ProtonMail/go-crypto to v1.3.0