mirror of
https://github.com/hanzoai/base.git
synced 2026-10-21 03:41:50 +00:00
Rename / namespace: - Finish github.com/pocketbase/* → github.com/hanzoai/base (+ /dbx) sweep across all Go sources; restore the renamed root launcher (Base, base.go). - Drop the upstream-only surfaces ours doesn't ship (admin ui/, the password/OTP/oauth2/impersonate auth files, extensions) re-added by the upstream merge. - Decomplect the on-disk layout to one base_/ namespace: data/, migrations/, hooks/, types.d.ts are siblings under base_/ (default data dir base_/data). Drop the hz_ prefix everywhere; collapse migratecmd's identical JS/Go branches to one path. - Remove the accidentally-committed hz_data/ dev dir (db + iam.key) and gitignore the runtime namespace dirs. Deps / build: - kmsclient now imported from the light github.com/hanzoai/kms/sdk/go module (the root kms module zip exceeds Go's download limit); cloud/pkg/base Mount removed (lives in the fused daemon). - replicate v0.4.0 → v0.8.0; metric.Counter.Get() (no prometheus dto); network/metrics.go import fix; auth gitlab/github tidy. Tests / behavior: - Wire registerNotifyWatcherHooks; debounce notify files past the kqueue rescan window so cross-instance settings/collections reload fires. - migratecmd: exclude createdAt/updatedAt (not created/updated); regenerate Go+JS automigration goldens from canonical output. - Convert the two stale archive red-probes to assert the landed defenses (backlog cap bounds memory; forged-segment signature is rejected). IAM-native (Base = pure IAM client): - Rip the ~1k-line home-grown embedded IAM (iam_embedded*.go) and the iam-user CLI. Base no longer reinvents identity as _iam_users/_superusers rows. IAM_ENDPOINT (hanzo.id, or an in-process iam.Embed in the fused daemon) is required; Base validates IAM JWTs via JWKS only — superuser is the IAM admin claim, resolved to an ephemeral unpersisted record. - Extract the IDV reverse-proxy (/v1/idv/*) into idv_proxy.go — it was mis-colocated in the embedded onboarding file and is independent of IAM. - Bind the SQL console (/v1/sql) and test it through real IAM JWTs against a JWKS stub (no hardcoded record tokens, no persisted rows).
132 lines
3.3 KiB
Go
132 lines
3.3 KiB
Go
package core
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"html"
|
|
"html/template"
|
|
"net/mail"
|
|
|
|
"github.com/hanzoai/base/tools/mailer"
|
|
)
|
|
|
|
const systemAlertHTML = `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
|
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
|
<style>
|
|
body, html {
|
|
padding: 0;
|
|
margin: 0;
|
|
border: 0;
|
|
color: #16161a;
|
|
background: #fff;
|
|
font-size: 14px;
|
|
line-height: 20px;
|
|
font-weight: normal;
|
|
font-family: Source Sans Pro, sans-serif, emoji;
|
|
}
|
|
body {
|
|
padding: 20px 30px;
|
|
}
|
|
p {
|
|
display: block;
|
|
margin: 10px 0;
|
|
font-family: inherit;
|
|
}
|
|
small {
|
|
font-size: 12px;
|
|
line-height: 16px;
|
|
}
|
|
strong {
|
|
font-weight: bold;
|
|
}
|
|
em, i {
|
|
font-style: italic;
|
|
}
|
|
a {
|
|
color: inherit;
|
|
}
|
|
.alert {
|
|
padding: 15px;
|
|
background: #e4e8ec;
|
|
border-radius: 5px;
|
|
white-space: pre-wrap;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<p>{{.AppName}} system alert occurred:</p>
|
|
<p class="alert"><strong>{{.AlertDetails}}</strong></p>
|
|
<p>For more information you could explore the logs in the dashboard of your application.</p>
|
|
</body>
|
|
</html>`
|
|
|
|
// sendSystemAlertToAllSuperusers sends a system error alert to all superusers.
|
|
//
|
|
// note: unexported for now until there is clarity around the planned log level alerts.
|
|
func sendSystemAlertToAllSuperusers(app App, subject string, details string) error {
|
|
superusers, err := app.FindAllRecords(CollectionNameSuperusers)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var alertErrors []error
|
|
for _, superuser := range superusers {
|
|
err := sendSystemAlert(app, superuser, subject, details)
|
|
if err != nil {
|
|
alertErrors = append(alertErrors, err)
|
|
}
|
|
}
|
|
|
|
return errors.Join(alertErrors...)
|
|
}
|
|
|
|
// sendSystemAlert sends a system error alert to a single superuser.
|
|
//
|
|
// note: unexported for now until there is clarity around the planned log level alerts.
|
|
func sendSystemAlert(app App, superuser *Record, subject string, details string) error {
|
|
if !superuser.IsSuperuser() {
|
|
return errors.New("system alerts can be sent only to superusers")
|
|
}
|
|
|
|
if subject == "" || details == "" {
|
|
return errors.New("system alerts subject and details are required")
|
|
}
|
|
|
|
data := struct {
|
|
AppName string
|
|
AlertDetails string
|
|
}{
|
|
AppName: app.Settings().Meta.AppName,
|
|
AlertDetails: details,
|
|
}
|
|
|
|
tpl := template.New("system_alert")
|
|
|
|
var parseErr error
|
|
tpl, parseErr = tpl.Parse(systemAlertHTML)
|
|
if parseErr != nil {
|
|
return parseErr
|
|
}
|
|
|
|
var buff bytes.Buffer
|
|
executeErr := tpl.Execute(&buff, data)
|
|
if executeErr != nil {
|
|
return executeErr
|
|
}
|
|
|
|
message := &mailer.Message{
|
|
From: mail.Address{
|
|
Name: app.Settings().Meta.SenderName,
|
|
Address: app.Settings().Meta.SenderAddress,
|
|
},
|
|
To: []mail.Address{{Address: superuser.Email()}},
|
|
Subject: "[" + app.Settings().Meta.AppName + " system alert] " + html.EscapeString(subject),
|
|
HTML: buff.String(),
|
|
}
|
|
|
|
return app.NewMailClient().Send(message)
|
|
}
|