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:
parent
db66a885fb
commit
f545b3353e
4 changed files with 42 additions and 1 deletions
35
email.go
35
email.go
|
@ -11,6 +11,7 @@
|
||||||
package writefreely
|
package writefreely
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -180,6 +181,40 @@ func handleCreateEmailSubscription(app *App, w http.ResponseWriter, r *http.Requ
|
||||||
return impart.WriteSuccess(w, "", http.StatusAccepted)
|
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 {
|
func handleDeleteEmailSubscription(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
alias := collectionAliasFromReq(r)
|
alias := collectionAliasFromReq(r)
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ var (
|
||||||
ErrNotLoggedIn = impart.HTTPError{http.StatusUnauthorized, "Not logged in."}
|
ErrNotLoggedIn = impart.HTTPError{http.StatusUnauthorized, "Not logged in."}
|
||||||
|
|
||||||
ErrForbiddenCollection = impart.HTTPError{http.StatusForbidden, "You don't have permission to add to this collection."}
|
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."}
|
ErrForbiddenEditPost = impart.HTTPError{http.StatusForbidden, "You don't have permission to update this post."}
|
||||||
ErrUnauthorizedEditPost = impart.HTTPError{http.StatusUnauthorized, "Invalid editing credentials."}
|
ErrUnauthorizedEditPost = impart.HTTPError{http.StatusUnauthorized, "Invalid editing credentials."}
|
||||||
ErrUnauthorizedGeneral = impart.HTTPError{http.StatusUnauthorized, "You don't have permission to do that."}
|
ErrUnauthorizedGeneral = impart.HTTPError{http.StatusUnauthorized, "You don't have permission to do that."}
|
||||||
|
|
|
@ -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}/collect", handler.All(addPost)).Methods("POST")
|
||||||
apiColls.HandleFunc("/{alias}/pin", handler.All(pinPost)).Methods("POST")
|
apiColls.HandleFunc("/{alias}/pin", handler.All(pinPost)).Methods("POST")
|
||||||
apiColls.HandleFunc("/{alias}/unpin", 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(handleCreateEmailSubscription)).Methods("POST")
|
||||||
apiColls.HandleFunc("/{alias}/email/subscribe", handler.All(handleDeleteEmailSubscription)).Methods("DELETE")
|
apiColls.HandleFunc("/{alias}/email/subscribe", handler.All(handleDeleteEmailSubscription)).Methods("DELETE")
|
||||||
apiColls.HandleFunc("/{collection}/email/unsubscribe", handler.All(handleDeleteEmailSubscription)).Methods("GET")
|
apiColls.HandleFunc("/{collection}/email/unsubscribe", handler.All(handleDeleteEmailSubscription)).Methods("GET")
|
||||||
|
|
|
@ -63,7 +63,11 @@
|
||||||
<p><strong>Email subscriptions are disabled on this server</strong>, so no new emails will be sent out.</p>
|
<p><strong>Email subscriptions are disabled on this server</strong>, so no new emails will be sent out.</p>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{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">
|
<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>
|
<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>
|
</div>
|
||||||
|
|
Loading…
Add table
Reference in a new issue