email: allow sending raw emails
The current email.Enqueue() function only allows sending messages with
the server's default settings.
In order to support sending any arbitrary message, we need to expose
a lower level API taking a raw message.Entity pointer. This new API will
be reused in a future reimplementation of the lists.sr.ht ingress agent
to forward messages to subscribers.
Add email.EnqueueRaw() that calls email.SendRaw(). Retry sending 10
times in the case of failure.
Signed-off-by: Robin Jarry <robin@jarry.cc>
email: keep smtp client connection alive
Instead of connecting and disconnecting each and every time we need to
send an email, keep the SMTP connection alive attached to a context
variable.
Before sending an email, check if the connection is still valid and
reconnect if it is not.
Signed-off-by: Robin Jarry <robin@jarry.cc>
treewide: update to new multi worker dowork api
The work.Queue() implementation has changed and now allows scheduling
tasks from multiple goroutines in parallel. Also, it requires a new
argument for limiting the queue buffer size in order to apply back
pressure.
Define new configuration variables to allow tuning the queue sizes and
number of workers per service:
[mail]
# Maximum size of the outgoing email queue (default 512).
egress-queue-size = 512
[$service_name]
# Number of parallel workers per queue (default 1).
# There are multiple queues (for egress email, webhooks, etc.).
# This setting is applied on a per-queue basis.
queue-workers = 1
[webhooks]
# Maximum size of the webhooks queue (default 512).
queue-size = 512
Use these new settings to configure the queues and workers accordingly.
Fix unit tests as well.
Link: https://git.sr.ht/~sircmpwn/dowork/commit/95719cfc0118
Signed-off-by: Robin Jarry <robin@jarry.cc>
webhooks: do not crash when expire is NULL
This is currently not possible to create a webhook without an expiry
date. But the SQL database schema does not forbid it. If in the future
we would like to allow webhooks to be created without an expiry date, we
shouldn't crash when fetching them.
Check for the validity of the Expiry field before checking its value. If
it is nil, assume that the webhooks has no expiry date.
Signed-off-by: Robin Jarry <robin@jarry.cc>
auth: reduce scope of user_type
auth: grant scoped access to anon internal auth
Internal auth is granted access to everything, whereas anonymous
internal auth is pretty restricted. This is mostly to avoid accidentally
hitting resolvers that require a logged-in user, however. Given that all
anon internal use cases are hard-coded and tested, this seems like a
pretty low risk. Allowing this will have the huge benefit of making much
more information available to anon internal queries, which will unlock
removing a bunch of awkward work-arounds we put in place.
Note, however, that this is also a work-around. It saves us from adding
yet more work-arounds to the GQL schema, and in the meantime a redesign
of the schema (especially the directives) is being worked on.
config: decouple file loading from crypto init
Now that the algorithm for loading the config is non-trivial, the code
for it should be re-used everywhere. However, it is currently coupled
with a call to `InitCrypto()`, which requires certain things like
webhook keys to be configured. This is not suitable for many components
that still need the configuration.
This commit introduces `config.LoadFiles()` to do only the file loading.
`LoadConfig()` uses it, and so can any components that do not care about
crypto initialization.
email: set Content-Type to format=flowed
This allows us to start sending emails in flowed format. It does not
actually change anything, until the templates in the services get
updated.
As format=flowed is designed to be backwards-compatible, it also doesn't
break anything. All emails will still look like before, with static line
breaks. However, changing the templates to flowed will now produce
emails that render as flowed successfully. Tested on plain (signed) and
encrypted mails.
See https://www.ietf.org/rfc/rfc2646.txt
auth/middleware: fix user_type on new users
Upgrade Go, `go mod tidy`, build on Alpine 3.20
.builds/alpine.yml: upgrade to Alpine 3.20
server: add AnonRouter function
To expose anonymous (unauthenticated) routing to downstream core-go
users.
auth/middleware: convert user types to uppercase
server: fix playground on config.Debug
A recent change made it so that the playground required authentication
to access in debug mode; this moves it under the other auth-free
endpoints.
auth: add Grants.IsSubset
This is a little bit hacky. Previously DecodeGrants would only store the
list of grants associated with the current service. This minimizes API
breakage by storing all grants as $service/$grant in the map key and
stores the local service name in the grant object, and updates
Grants.Has() to accept "$grant" and infer that it refers to a local
service or accept the fully qualified "$service/$grant" to test against
grants for any service -- which IsSubset makes use of to test that one
Grant object is a subset of another with respect to all services it has
grants for.
server: use routing groups
Instead of hardcoding some exceptions in the auth middleware, use a
different routing group for routes that do not require auth. Makes the
auth middleware more generic and also removes a lot of unneccessary
middleware processing from routes that don't need it.
For now, the added group is not accessible from outside the module, but
if the need arises, this might be an option.
config: print loaded config(s) to log
email: update StartTLS usage per go-smtp changes