Something went wrong. Try again.
Monorepo for Tangled
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174package xrpc
import ( "database/sql" "encoding/json" "errors" "net/http" "strings"
"tangled.org/core/api/tangled" "tangled.org/core/appview/db" "tangled.org/core/appview/email" xrpcerr "tangled.org/core/xrpc/errors")
func (x *Xrpc) AccountListEmails(w http.ResponseWriter, r *http.Request) { l := x.Logger.With("handler", "AccountListEmails")
did, ok := actorDid(r) if !ok { writeError(w, xrpcerr.MissingActorDidError, http.StatusForbidden) return }
emails, err := db.GetAllEmails(x.DB, did) if err != nil { l.Error("failed to get emails", "err", err) writeError(w, errInternal, http.StatusInternalServerError) return }
items := make([]*tangled.TempAccountListEmails_Email, 0, len(emails)) for _, e := range emails { items = append(items, &tangled.TempAccountListEmails_Email{ Address: e.Address, Verified: e.Verified, Primary: e.Primary, CreatedAt: e.CreatedAt.UTC().Format(timeFormat), }) }
x.writeJSON(w, &tangled.TempAccountListEmails_Output{Emails: items})}
func (x *Xrpc) AccountDeleteEmail(w http.ResponseWriter, r *http.Request) { l := x.Logger.With("handler", "AccountDeleteEmail")
did, ok := actorDid(r) if !ok { writeError(w, xrpcerr.MissingActorDidError, http.StatusForbidden) return }
var input tangled.TempAccountDeleteEmail_Input if err := json.NewDecoder(r.Body).Decode(&input); err != nil { writeError(w, errBadRequestBody, http.StatusBadRequest) return } addr := strings.TrimSpace(input.Email)
existing, err := db.GetEmail(x.DB, did, addr) if err != nil { if errors.Is(err, sql.ErrNoRows) { writeError(w, xrpcErrorTag("EmailNotFound", "the email address is not associated with this account"), http.StatusNotFound) return } l.Error("failed to get email", "err", err) writeError(w, errInternal, http.StatusInternalServerError) return } if existing.Primary { writeError(w, xrpcErrorTag("CannotDeletePrimary", "the primary email address cannot be deleted; set another address as primary first"), http.StatusBadRequest) return }
if err := db.DeleteEmail(x.DB, did, addr); err != nil { l.Error("failed to delete email", "err", err) writeError(w, errInternal, http.StatusInternalServerError) return }
w.WriteHeader(http.StatusOK)}
func (x *Xrpc) AccountSetPrimaryEmail(w http.ResponseWriter, r *http.Request) { l := x.Logger.With("handler", "AccountSetPrimaryEmail")
did, ok := actorDid(r) if !ok { writeError(w, xrpcerr.MissingActorDidError, http.StatusForbidden) return }
var input tangled.TempAccountSetPrimaryEmail_Input if err := json.NewDecoder(r.Body).Decode(&input); err != nil { writeError(w, errBadRequestBody, http.StatusBadRequest) return } addr := strings.TrimSpace(input.Email)
existing, err := db.GetEmail(x.DB, did, addr) if err != nil { if errors.Is(err, sql.ErrNoRows) { writeError(w, xrpcErrorTag("EmailNotFound", "the email address is not associated with this account"), http.StatusNotFound) return } l.Error("failed to get email", "err", err) writeError(w, errInternal, http.StatusInternalServerError) return } if !existing.Verified { writeError(w, xrpcErrorTag("EmailNotVerified", "the email address must be verified before it can be made primary"), http.StatusBadRequest) return }
if err := db.MakeEmailPrimary(x.DB, did, addr); err != nil { l.Error("failed to set primary email", "err", err) writeError(w, errInternal, http.StatusInternalServerError) return }
w.WriteHeader(http.StatusOK)}
func (x *Xrpc) AccountSubscribeNewsletter(w http.ResponseWriter, r *http.Request) { l := x.Logger.With("handler", "AccountSubscribeNewsletter")
did, ok := actorDid(r) if !ok { writeError(w, xrpcerr.MissingActorDidError, http.StatusForbidden) return }
primary, err := db.GetPrimaryEmail(x.DB, did) if err != nil || primary.Address == "" { writeError(w, xrpcErrorTag("NoVerifiedEmail", "a primary email address is required to subscribe"), http.StatusBadRequest) return }
if err := db.UpsertNewsletterPref(x.DB, did, db.NewsletterStatusSubscribed, primary.Address); err != nil { l.Error("failed to persist newsletter preference", "err", err) writeError(w, errInternal, http.StatusInternalServerError) return }
if x.Config.Resend.ApiKey != "" && x.Config.Resend.NewsletterSegmentId != "" { go func() { if err := email.AddNewsletterContact(x.Config.Resend.ApiKey, x.Config.Resend.NewsletterSegmentId, primary.Address); err != nil { l.Error("failed to add newsletter contact", "err", err) } }() }
w.WriteHeader(http.StatusOK)}
func (x *Xrpc) AccountDismissNewsletter(w http.ResponseWriter, r *http.Request) { l := x.Logger.With("handler", "AccountDismissNewsletter")
did, ok := actorDid(r) if !ok { writeError(w, xrpcerr.MissingActorDidError, http.StatusForbidden) return }
if err := db.UpsertNewsletterPref(x.DB, did, db.NewsletterStatusDismissed, ""); err != nil { l.Error("failed to persist newsletter dismissal", "err", err) writeError(w, errInternal, http.StatusInternalServerError) return }
w.WriteHeader(http.StatusOK)}