Support exporting email subscribers list

This adds a new /api/collections/{alias} endpoint that downloads all
collection subscribers as a CSV file.

Ref T828
This commit is contained in:
Matt Baer 2025-02-18 18:42:46 -05:00
parent db66a885fb
commit f545b3353e
4 changed files with 42 additions and 1 deletions

View file

@ -11,6 +11,7 @@
package writefreely
import (
"bytes"
"database/sql"
"encoding/json"
"fmt"
@ -180,6 +181,40 @@ func handleCreateEmailSubscription(app *App, w http.ResponseWriter, r *http.Requ
return impart.WriteSuccess(w, "", http.StatusAccepted)
}
func handleExportEmailSubscriptions(app *App, w http.ResponseWriter, r *http.Request) ([]byte, string, error) {
vars := mux.Vars(r)
var err error
alias := vars["alias"]
filename := ""
u := getUserSession(app, r)
if u == nil {
return nil, filename, ErrNotLoggedIn
}
c, err := app.db.GetCollection(alias)
if err != nil {
return nil, filename, err
}
// Verify permissions / ownership
if u.ID != c.OwnerID {
return nil, filename, ErrForbiddenCollectionAccess
}
filename = "subscribers-" + alias + "-" + time.Now().Truncate(time.Second).UTC().Format("200601021504")
subs, err := app.db.GetEmailSubscribers(c.ID, true)
if err != nil {
return nil, filename, err
}
var data []byte
for _, sub := range subs {
data = append(data, []byte(sub.Email.String+"\n")...)
}
data = bytes.TrimRight(data, "\n")
return data, filename, err
}
func handleDeleteEmailSubscription(app *App, w http.ResponseWriter, r *http.Request) error {
alias := collectionAliasFromReq(r)

View file

@ -26,6 +26,7 @@ var (
ErrNotLoggedIn = impart.HTTPError{http.StatusUnauthorized, "Not logged in."}
ErrForbiddenCollection = impart.HTTPError{http.StatusForbidden, "You don't have permission to add to this collection."}
ErrForbiddenCollectionAccess = impart.HTTPError{http.StatusForbidden, "You don't have permission to access this collection."}
ErrForbiddenEditPost = impart.HTTPError{http.StatusForbidden, "You don't have permission to update this post."}
ErrUnauthorizedEditPost = impart.HTTPError{http.StatusUnauthorized, "Invalid editing credentials."}
ErrUnauthorizedGeneral = impart.HTTPError{http.StatusUnauthorized, "You don't have permission to do that."}

View file

@ -148,6 +148,7 @@ func InitRoutes(apper Apper, r *mux.Router) *mux.Router {
apiColls.HandleFunc("/{alias}/collect", handler.All(addPost)).Methods("POST")
apiColls.HandleFunc("/{alias}/pin", handler.All(pinPost)).Methods("POST")
apiColls.HandleFunc("/{alias}/unpin", handler.All(pinPost)).Methods("POST")
apiColls.HandleFunc("/{alias}/email/subscribers/export.csv", handler.Download(handleExportEmailSubscriptions, UserLevelUser)).Methods("GET")
apiColls.HandleFunc("/{alias}/email/subscribe", handler.All(handleCreateEmailSubscription)).Methods("POST")
apiColls.HandleFunc("/{alias}/email/subscribe", handler.All(handleDeleteEmailSubscription)).Methods("DELETE")
apiColls.HandleFunc("/{collection}/email/unsubscribe", handler.All(handleDeleteEmailSubscription)).Methods("GET")

View file

@ -63,7 +63,11 @@
<p><strong>Email subscriptions are disabled on this server</strong>, so no new emails will be sent out.</p>
</div>
{{end}}
{{if not .EmailSubsEnabled}}
{{if .EmailSubsEnabled}}
<div class="row toolbar ends">
<a href="/api/collections/{{.Collection.Alias}}/email/subscribers/export.csv">Export list</a>
</div>
{{else}}
<div class="alert info">
<p><strong>Email subscriptions are disabled</strong>. {{if .EmailSubs}}No new emails will be sent out.{{end}} To enable email subscriptions, turn the option on from your blog's <a href="/me/c/{{.Collection.Alias}}#updates">Customize</a> page.</p>
</div>