mirror of
https://github.com/DeBrosOfficial/orama.git
synced 2026-06-16 23:14:13 +00:00
Migration 028: namespace_push_credentials
- Per-(namespace, provider) AES-256-GCM encrypted credential blob.
- Generic schema — apns/ntfy/expo/future plug in with zero migration.
- Separated from migration 026's namespace_push_config (preferences vs
credentials, different access patterns).
pkg/push/credentials
- Manager + Registry + RQLite store; HKDF purpose "namespace-push-credentials"
via pkg/secrets. Provider Validator interface for per-provider schema.
pkg/push/providers/apns
- Apple Push Notification service direct provider (no Expo proxy).
- Validator + dispatcher; credentials are p8 signing key + key_id + team_id.
pkg/push/providers/ntfy/credentials.go
- ntfy credential schema (auth_token + default topic). Used both with
the public ntfy.sh and our self-hosted instance.
pkg/environments/production/installers/ntfy.go
- Self-hosted ntfy server installer. Binary, system user, hardened
/etc/ntfy/server.yml, systemd unit. Listens on 127.0.0.1:NtfyListenPort
only — Caddy is the only public path.
pkg/environments/production/installers/caddy.go
- Emit reverse_proxy block for push.<dnsZone> -> 127.0.0.1:NtfyListenPort
when operator enables ntfy on a node.
CLI: install/upgrade orchestrators learn a new "ntfy" install/preserve
phase; flag gating in install/flags.go + upgrade/flags.go.
Gateway handlers/push/credentials_handler.go
- GET/PUT/DELETE /v1/namespace/push-credentials/{provider}.
- PUT validates against provider Validator before encrypting and storing.
- GET returns a redacted view (booleans + non-secret fields only).
Push manager: provider resolution now also consults
namespace_push_credentials before falling back to YAML defaults.
Docs: core/docs/PUSH_NOTIFICATIONS.md walks through end-to-end setup.
VERSION bumped to 0.122.14.
89 lines
3.0 KiB
Go
89 lines
3.0 KiB
Go
package credentials
|
|
|
|
import "sync"
|
|
|
|
// registry is the package-level map of provider name → Validator.
|
|
//
|
|
// Provider packages (pkg/push/providers/apns, .../ntfy, .../fcm, …)
|
|
// export a Validator implementation; the gateway dependency wiring
|
|
// calls Register at startup for each provider it wants to support on
|
|
// this gateway. Anyone-can-register-anything is intentional — operators
|
|
// who want to disable a provider simply don't register its Validator,
|
|
// and PUT/GET for that provider return 400 ErrUnknownProvider.
|
|
//
|
|
// Safe for concurrent reads; mutations should happen at gateway
|
|
// startup before request serving begins.
|
|
var (
|
|
registryMu sync.RWMutex
|
|
registry = map[string]Validator{}
|
|
)
|
|
|
|
// Register makes a Validator available for the provider name. Calling
|
|
// Register with the same name twice replaces the previous one — useful
|
|
// in tests; in production it indicates a wiring bug and is logged by
|
|
// the gateway startup path.
|
|
//
|
|
// Panics if v is nil or v.Provider() is empty: these are programmer
|
|
// errors that should fail loud at gateway startup, not mysteriously at
|
|
// first PUT.
|
|
func Register(v Validator) {
|
|
if v == nil {
|
|
panic("credentials: Register called with nil Validator")
|
|
}
|
|
name := v.Provider()
|
|
if name == "" {
|
|
panic("credentials: Validator.Provider() returned empty string")
|
|
}
|
|
registryMu.Lock()
|
|
defer registryMu.Unlock()
|
|
registry[name] = v
|
|
}
|
|
|
|
// LookupValidator returns the Validator for provider, or (nil, false)
|
|
// if no Validator is registered. Used by the PUT/GET handlers to
|
|
// reject unknown providers with a 400 + clear error.
|
|
func LookupValidator(provider string) (Validator, bool) {
|
|
registryMu.RLock()
|
|
defer registryMu.RUnlock()
|
|
v, ok := registry[provider]
|
|
return v, ok
|
|
}
|
|
|
|
// RegisteredProviders returns the names of all currently-registered
|
|
// providers. Used by the "what providers does this gateway support"
|
|
// summary endpoint and by tests. Order is unspecified.
|
|
func RegisteredProviders() []string {
|
|
registryMu.RLock()
|
|
defer registryMu.RUnlock()
|
|
out := make([]string, 0, len(registry))
|
|
for name := range registry {
|
|
out = append(out, name)
|
|
}
|
|
return out
|
|
}
|
|
|
|
// resetRegistry clears the registry. Used internally by the package's
|
|
// own tests; the exported ResetRegistryForTest wrapper makes it
|
|
// callable from tests in OTHER packages (which can't reach
|
|
// package-internal symbols).
|
|
//
|
|
// Not safe to call while requests are in flight; intended for test
|
|
// setup/teardown ONLY.
|
|
func resetRegistry() {
|
|
registryMu.Lock()
|
|
defer registryMu.Unlock()
|
|
registry = map[string]Validator{}
|
|
}
|
|
|
|
// ResetRegistryForTest clears the global Validator registry. Tests in
|
|
// other packages (e.g. the HTTP handler tests) that register
|
|
// Validators should defer this so they don't leak state into other
|
|
// tests in the same binary.
|
|
//
|
|
// Exposed as a regular exported function (not _test.go-gated) because
|
|
// test files in other packages cannot reach _test.go-only exports of
|
|
// THIS package. Safe to call at runtime but pointless outside tests.
|
|
func ResetRegistryForTest() {
|
|
resetRegistry()
|
|
}
|