This is the Go-equivalent to
https://lists.sr.ht/~sircmpwn/sr.ht-dev/patches/47657
This commit enables spreading the config in /etc/sr.ht - and, crucially,
_only_ in /etc/sr.ht - over multiple .ini files.
If a file config.ini is found (either in current or parent directory, or
/etc/sr.ht) it (and only it) is loaded and any other ini files are
ignored. To utilize multiple configs, they must be in /etc/sr.ht, and
none of them must be called config.ini.
Spreading the config over multiple files will make it much easier to
create containerized versions, where e.g. different secrets can be made
available in different files, but rendering it all into one big file
would require some preprocessing.
583d0b1bcb ("client/graphql: handle GraphQL errors") changed
Execute behavior by wrapping the result into a struct with "data"
and "errors" fields. This is a breaking change, but it's hard to
spot when upgrading core-go because it won't cause a compilation
error.
Rename Execute to Do to break the build and force callers to update
accordingly.
Services other than meta.sr.ht don't really have a use for the
private PGP key.
Add a CanPGPSign method so that meta.sr.ht can emit a warning or
error when the PGP key is missing.
The documentation states [1]:
> When the original authentication method becomes invalid (such as the
> expiration of or revocation of an OAuth 2.0 bearer token), the
> webhook is disabled.
However, this is currently not the case. Expired webhooks are indeed
filtered out in virtually all GraphQL queries (by means of core-go's
FilterWebhooks [2]), so users cannot see or delete them. They are _not_
filtered out upon scheduling, however. This commit fixes that.
The symptoms of this are that active webhooks may simply not be run - if
a user has both an expired and a valid, active webhook for some event,
the scheduling will retrieve both, fail on the expired one, and stop
processing, without any feedback to the user who scheduled the hooks.
This is a problem across all services, so core-go seems like the best
place to fix this.
[1]: https://man.sr.ht/graphql.md#webhook-authentication
[2]: https://git.sr.ht/~sircmpwn/core-go/tree/master/item/webhooks/config.go#L74,81
Checking context.Cancelled is not enough, I also see the same issue
with context.DeadlineExceeded:
panic: Transaction error: driver: bad connection
Closure error: context deadline exceeded
goroutine 66664 [running]:
git.sr.ht/~sircmpwn/core-go/database.WithTx({0x5578e1847a58, 0xc0002c44e0}, 0x50?, 0xc000285f38)
git.sr.ht/~sircmpwn/core-go@v0.0.0-20231129165057-e7b8e02696a1/database/middleware.go:74 +0x2ce
git.sr.ht/~sircmpwn/builds.sr.ht/api/loaders.fetchUsersByID.func1({0xc0002cf190, 0x1, 0x1})
git.sr.ht/~sircmpwn/builds.sr.ht/api/loaders/middleware.go:34 +0x118
git.sr.ht/~sircmpwn/builds.sr.ht/api/loaders.(*usersByIDLoaderBatch).end(...)
git.sr.ht/~sircmpwn/builds.sr.ht/api/loaders/usersbyidloader_gen.go:222
git.sr.ht/~sircmpwn/builds.sr.ht/api/loaders.(*usersByIDLoaderBatch).startTimer(0xc00044a360, 0xc00042d380)
git.sr.ht/~sircmpwn/builds.sr.ht/api/loaders/usersbyidloader_gen.go:218 +0xe7
created by git.sr.ht/~sircmpwn/builds.sr.ht/api/loaders.(*usersByIDLoaderBatch).keyIndex
git.sr.ht/~sircmpwn/builds.sr.ht/api/loaders/usersbyidloader_gen.go:191 +0x119
Newer versions of the graphql package add new fields to this struct.
This results in errors:
database/ql.go:40:4: too few values in struct literal of type graphql.CollectedField
database/ql.go:71:4: too few values in struct literal of type graphql.CollectedField
Sometimes we're panic'ing like so:
panic: driver: bad connection
goroutine 9333 [running]:
git.sr.ht/~sircmpwn/core-go/database.WithTx({0x561c2e623478, 0xc0002b6ed0}, 0x50?, 0xc00025ff38)
git.sr.ht/~sircmpwn/core-go@v0.0.0-20230816134313-65b1657b30a1/database/middleware.go:57 +0x1fc
git.sr.ht/~sircmpwn/builds.sr.ht/api/loaders.fetchUsersByID.func1({0xc0002d80f0, 0x1, 0x1})
git.sr.ht/~sircmpwn/builds.sr.ht/api/loaders/middleware.go:34 +0x118
git.sr.ht/~sircmpwn/builds.sr.ht/api/loaders.(*usersByIDLoaderBatch).end(...)
git.sr.ht/~sircmpwn/builds.sr.ht/api/loaders/usersbyidloader_gen.go:222
git.sr.ht/~sircmpwn/builds.sr.ht/api/loaders.(*usersByIDLoaderBatch).startTimer(0xc0004e5380, 0xc0000e5140)
git.sr.ht/~sircmpwn/builds.sr.ht/api/loaders/usersbyidloader_gen.go:218 +0xe7
created by git.sr.ht/~sircmpwn/builds.sr.ht/api/loaders.(*usersByIDLoaderBatch).keyIndex
git.sr.ht/~sircmpwn/builds.sr.ht/api/loaders/usersbyidloader_gen.go:191 +0x119
I believe this is a pq bug, see the linked bug report. Stop
panic'ing in that case.
Same logic as server.Access, but lower-level. Useful to check for
a permission not covered by the GraphQL schema @access directives
(such as builds.sr.ht secrets).
Log a message when mail::error-to is unset, just in case the admin
forgot to set it. Don't try to parse an email address if error-to
is set to the empty string (the default value in the default config
file).
The error returned when a token is missing a required grant would
be "Access denied for invalid auth method" which is confusing.
Fix this with a more accurate error message.
defer always runs after a panic. There is no need to recover and
re-panic, we can just unconditionally tx.Rollback() (it will
silently error out if the transaction has already been committed or
rolled back).
This fixes the stack trace of the panic being incorrect. It points
to this function instead of the real culprit.
Fixes the following error when running `go test`:
../../go/pkg/mod/github.com/prometheus/client_golang@v1.14.0/prometheus/internal/metric.go:19:2: missing go.sum entry for module providing package github.com/prometheus/client_model/go (imported by github.com/prometheus/client_golang/prometheus); to add:
go get github.com/prometheus/client_golang/prometheus@v1.14.0
The email has already been parsed according to the headers, but they are
still present. However, signing or encrypting the email will change the
content format, so remove any such headers before continuing.
The current solution of fetching columns based on the GraphQL context
has some limits. While probably not the solution for all use-cases, it
sometimes can be desirable to simply fetch all columns from the database
when retrieving objects.
This commit adds two simple functions doing just that. They can be used
when building SQL queries, like
query := database.SelectAll(new(model.Email))
and
rows.Scan(database.ScanAll(&email)...)