Use the same code paths to render the browser version of emails

This commit is contained in:
Eli Ribble 2026-01-19 21:21:02 +00:00
parent 1232a7c0ec
commit 42caa77b3e
No known key found for this signature in database
6 changed files with 41 additions and 11 deletions

View file

@ -9,17 +9,17 @@ import (
"net/http"
"github.com/Gleipnir-Technology/nidus-sync/config"
"github.com/Gleipnir-Technology/nidus-sync/htmlpage"
"github.com/rs/zerolog/log"
)
func RenderEmailReportConfirmation(w http.ResponseWriter, report_id string) {
content := contentEmailSubscriptionConfirmation(report_id)
renderOrError(w, reportConfirmationT, content)
}
func SendEmailReportConfirmation(to string, report_id string) error {
report_id_str := publicReportID(report_id)
content := contentEmailReportConfirmation{
URLLogo: "https://dev-sync.nidus.cloud/static/img/nidus-logo-no-lettering-64.png",
URLReportStatus: fmt.Sprintf("https://dev-sync.nidus.cloud/report/%s", report_id),
URLReportUnsubscribe: fmt.Sprintf("https://dev-sync.nidus.cloud/report/%s/unsubscribe", report_id),
URLViewInBrowser: fmt.Sprintf("https://dev-sync.nidus.cloud/report/%s/subscribe-confirmation", report_id),
}
content := contentEmailSubscriptionConfirmation(report_id)
text, html, err := renderEmailTemplates(reportConfirmationT, content)
if err != nil {
return fmt.Errorf("Failed to render template %s: %w", reportConfirmationT.name, err)
@ -104,6 +104,15 @@ type emailResponse struct {
Message string `json:"message"`
}
func contentEmailSubscriptionConfirmation(report_id string) contentEmailReportConfirmation {
return contentEmailReportConfirmation{
URLLogo: "https://dev-sync.nidus.cloud/static/img/nidus-logo-no-lettering-64.png",
URLReportStatus: fmt.Sprintf("https://dev-sync.nidus.cloud/report/%s", report_id),
URLReportUnsubscribe: fmt.Sprintf("https://dev-sync.nidus.cloud/report/%s/unsubscribe", report_id),
URLViewInBrowser: fmt.Sprintf("https://dev-sync.nidus.cloud/email/report/%s/subscription-confirmation", report_id),
}
}
func publicReportID(s string) string {
if len(s) != 12 {
return s
@ -111,6 +120,17 @@ func publicReportID(s string) string {
return s[0:4] + "-" + s[4:8] + "-" + s[8:12]
}
func renderOrError(w http.ResponseWriter, template *builtTemplate, context interface{}) {
buf := &bytes.Buffer{}
err := template.executeTemplateHTML(buf, context)
if err != nil {
log.Error().Err(err).Str("name", template.name).Msg("Failed to render template")
htmlpage.RespondError(w, "Failed to render template", err, http.StatusInternalServerError)
return
}
buf.WriteTo(w)
}
func sendEmail(email emailRequest) (response emailResponse, err error) {
url := "https://api.forwardemail.net/v1/emails"

View file

@ -54,7 +54,7 @@ func FileServer(r chi.Router, path string, root http.FileSystem, embeddedFS embe
// Try to open from local filesystem for development
fileToServe, err = root.Open(requestedPath)
if err != nil {
respondError(w, "Failed to open file", err, http.StatusNotFound)
RespondError(w, "Failed to open file", err, http.StatusNotFound)
return
}
}

View file

@ -85,7 +85,7 @@ func RenderOrError(w http.ResponseWriter, template *BuiltTemplate, context inter
err := template.executeTemplate(buf, context)
if err != nil {
log.Error().Err(err).Strs("files", template.files).Msg("Failed to render template")
respondError(w, "Failed to render template", err, http.StatusInternalServerError)
RespondError(w, "Failed to render template", err, http.StatusInternalServerError)
return
}
buf.WriteTo(w)

View file

@ -34,7 +34,7 @@ func (crw *customResponseWriter) Write(b []byte) (int, error) {
}
// Respond with an error that is visible to the user
func respondError(w http.ResponseWriter, m string, e error, s int) {
func RespondError(w http.ResponseWriter, m string, e error, s int) {
log.Warn().Int("status", s).Err(e).Str("user message", m).Msg("Responding with an error")
http.Error(w, m, s)
}

View file

@ -4,14 +4,18 @@ import (
"crypto/rand"
"fmt"
"math/big"
"net/http"
"strings"
"github.com/Gleipnir-Technology/nidus-sync/comms"
"github.com/go-chi/chi/v5"
)
// GenerateReportID creates a 12-character random string using only unambiguous
// capital letters and numbers
func GenerateReportID() (string, error) {
// Define character set (no O, I, Z to avoid confusion)
const charset = "ABCDEFGHJKLMNPQRSTUVWXY0123456789"
// Define character set (no O/0, I/l/1, 2/Z to avoid confusion)
const charset = "ABCDEFGHJKLMNPQRSTUVWXY3456789"
const length = 12
var builder strings.Builder
@ -31,3 +35,8 @@ func GenerateReportID() (string, error) {
return builder.String(), nil
}
func getEmailReportSubscriptionConfirmation(w http.ResponseWriter, r *http.Request) {
report_id := chi.URLParam(r, "report_id")
comms.RenderEmailReportConfirmation(w, report_id)
}

View file

@ -8,6 +8,7 @@ import (
func Router() chi.Router {
r := chi.NewRouter()
r.Get("/", getRoot)
r.Get("/email/report/{report_id}/subscription-confirmation", getEmailReportSubscriptionConfirmation)
r.Get("/nuisance", getNuisance)
r.Post("/nuisance-submit", postNuisance)
r.Get("/nuisance-submit-complete", getNuisanceSubmitComplete)