Make App struct public
This commit is contained in:
parent
9023d4eb3f
commit
d8937e89a8
52
account.go
52
account.go
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2018 A Bunch Tell LLC.
|
* Copyright © 2018-2019 A Bunch Tell LLC.
|
||||||
*
|
*
|
||||||
* This file is part of WriteFreely.
|
* This file is part of WriteFreely.
|
||||||
*
|
*
|
||||||
|
@ -49,7 +49,7 @@ type (
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewUserPage(app *app, r *http.Request, u *User, title string, flashes []string) *UserPage {
|
func NewUserPage(app *App, r *http.Request, u *User, title string, flashes []string) *UserPage {
|
||||||
up := &UserPage{
|
up := &UserPage{
|
||||||
StaticPage: pageForReq(app, r),
|
StaticPage: pageForReq(app, r),
|
||||||
PageTitle: title,
|
PageTitle: title,
|
||||||
|
@ -73,12 +73,12 @@ const (
|
||||||
|
|
||||||
var actuallyUsernameReg = regexp.MustCompile("username is actually ([a-z0-9\\-]+)\\. Please try that, instead")
|
var actuallyUsernameReg = regexp.MustCompile("username is actually ([a-z0-9\\-]+)\\. Please try that, instead")
|
||||||
|
|
||||||
func apiSignup(app *app, w http.ResponseWriter, r *http.Request) error {
|
func apiSignup(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
_, err := signup(app, w, r)
|
_, err := signup(app, w, r)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func signup(app *app, w http.ResponseWriter, r *http.Request) (*AuthUser, error) {
|
func signup(app *App, w http.ResponseWriter, r *http.Request) (*AuthUser, error) {
|
||||||
reqJSON := IsJSON(r.Header.Get("Content-Type"))
|
reqJSON := IsJSON(r.Header.Get("Content-Type"))
|
||||||
|
|
||||||
// Get params
|
// Get params
|
||||||
|
@ -113,7 +113,7 @@ func signup(app *app, w http.ResponseWriter, r *http.Request) (*AuthUser, error)
|
||||||
return signupWithRegistration(app, ur, w, r)
|
return signupWithRegistration(app, ur, w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func signupWithRegistration(app *app, signup userRegistration, w http.ResponseWriter, r *http.Request) (*AuthUser, error) {
|
func signupWithRegistration(app *App, signup userRegistration, w http.ResponseWriter, r *http.Request) (*AuthUser, error) {
|
||||||
reqJSON := IsJSON(r.Header.Get("Content-Type"))
|
reqJSON := IsJSON(r.Header.Get("Content-Type"))
|
||||||
|
|
||||||
// Validate required params (alias)
|
// Validate required params (alias)
|
||||||
|
@ -229,7 +229,7 @@ func signupWithRegistration(app *app, signup userRegistration, w http.ResponseWr
|
||||||
return resUser, nil
|
return resUser, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func viewLogout(app *app, w http.ResponseWriter, r *http.Request) error {
|
func viewLogout(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
session, err := app.sessionStore.Get(r, cookieName)
|
session, err := app.sessionStore.Get(r, cookieName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ErrInternalCookieSession
|
return ErrInternalCookieSession
|
||||||
|
@ -268,7 +268,7 @@ func viewLogout(app *app, w http.ResponseWriter, r *http.Request) error {
|
||||||
return impart.HTTPError{http.StatusFound, "/"}
|
return impart.HTTPError{http.StatusFound, "/"}
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleAPILogout(app *app, w http.ResponseWriter, r *http.Request) error {
|
func handleAPILogout(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
accessToken := r.Header.Get("Authorization")
|
accessToken := r.Header.Get("Authorization")
|
||||||
if accessToken == "" {
|
if accessToken == "" {
|
||||||
return ErrNoAccessToken
|
return ErrNoAccessToken
|
||||||
|
@ -284,7 +284,7 @@ func handleAPILogout(app *app, w http.ResponseWriter, r *http.Request) error {
|
||||||
return impart.HTTPError{Status: http.StatusNoContent}
|
return impart.HTTPError{Status: http.StatusNoContent}
|
||||||
}
|
}
|
||||||
|
|
||||||
func viewLogin(app *app, w http.ResponseWriter, r *http.Request) error {
|
func viewLogin(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
var earlyError string
|
var earlyError string
|
||||||
oneTimeToken := r.FormValue("with")
|
oneTimeToken := r.FormValue("with")
|
||||||
if oneTimeToken != "" {
|
if oneTimeToken != "" {
|
||||||
|
@ -333,7 +333,7 @@ func viewLogin(app *app, w http.ResponseWriter, r *http.Request) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func webLogin(app *app, w http.ResponseWriter, r *http.Request) error {
|
func webLogin(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
err := login(app, w, r)
|
err := login(app, w, r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
username := r.FormValue("alias")
|
username := r.FormValue("alias")
|
||||||
|
@ -370,7 +370,7 @@ func webLogin(app *app, w http.ResponseWriter, r *http.Request) error {
|
||||||
|
|
||||||
var loginAttemptUsers = sync.Map{}
|
var loginAttemptUsers = sync.Map{}
|
||||||
|
|
||||||
func login(app *app, w http.ResponseWriter, r *http.Request) error {
|
func login(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
reqJSON := IsJSON(r.Header.Get("Content-Type"))
|
reqJSON := IsJSON(r.Header.Get("Content-Type"))
|
||||||
oneTimeToken := r.FormValue("with")
|
oneTimeToken := r.FormValue("with")
|
||||||
verbose := r.FormValue("all") == "true" || r.FormValue("verbose") == "1" || r.FormValue("verbose") == "true" || (reqJSON && oneTimeToken != "")
|
verbose := r.FormValue("all") == "true" || r.FormValue("verbose") == "1" || r.FormValue("verbose") == "true" || (reqJSON && oneTimeToken != "")
|
||||||
|
@ -534,7 +534,7 @@ func login(app *app, w http.ResponseWriter, r *http.Request) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getVerboseAuthUser(app *app, token string, u *User, verbose bool) *AuthUser {
|
func getVerboseAuthUser(app *App, token string, u *User, verbose bool) *AuthUser {
|
||||||
resUser := &AuthUser{
|
resUser := &AuthUser{
|
||||||
AccessToken: token,
|
AccessToken: token,
|
||||||
User: u,
|
User: u,
|
||||||
|
@ -563,7 +563,7 @@ func getVerboseAuthUser(app *app, token string, u *User, verbose bool) *AuthUser
|
||||||
return resUser
|
return resUser
|
||||||
}
|
}
|
||||||
|
|
||||||
func viewExportOptions(app *app, u *User, w http.ResponseWriter, r *http.Request) error {
|
func viewExportOptions(app *App, u *User, w http.ResponseWriter, r *http.Request) error {
|
||||||
// Fetch extra user data
|
// Fetch extra user data
|
||||||
p := NewUserPage(app, r, u, "Export", nil)
|
p := NewUserPage(app, r, u, "Export", nil)
|
||||||
|
|
||||||
|
@ -571,7 +571,7 @@ func viewExportOptions(app *app, u *User, w http.ResponseWriter, r *http.Request
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func viewExportPosts(app *app, w http.ResponseWriter, r *http.Request) ([]byte, string, error) {
|
func viewExportPosts(app *App, w http.ResponseWriter, r *http.Request) ([]byte, string, error) {
|
||||||
var filename string
|
var filename string
|
||||||
var u = &User{}
|
var u = &User{}
|
||||||
reqJSON := IsJSON(r.Header.Get("Content-Type"))
|
reqJSON := IsJSON(r.Header.Get("Content-Type"))
|
||||||
|
@ -635,7 +635,7 @@ func viewExportPosts(app *app, w http.ResponseWriter, r *http.Request) ([]byte,
|
||||||
return data, filename, err
|
return data, filename, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func viewExportFull(app *app, w http.ResponseWriter, r *http.Request) ([]byte, string, error) {
|
func viewExportFull(app *App, w http.ResponseWriter, r *http.Request) ([]byte, string, error) {
|
||||||
var err error
|
var err error
|
||||||
filename := ""
|
filename := ""
|
||||||
u := getUserSession(app, r)
|
u := getUserSession(app, r)
|
||||||
|
@ -655,7 +655,7 @@ func viewExportFull(app *app, w http.ResponseWriter, r *http.Request) ([]byte, s
|
||||||
return data, filename, err
|
return data, filename, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func viewMeAPI(app *app, w http.ResponseWriter, r *http.Request) error {
|
func viewMeAPI(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
reqJSON := IsJSON(r.Header.Get("Content-Type"))
|
reqJSON := IsJSON(r.Header.Get("Content-Type"))
|
||||||
uObj := struct {
|
uObj := struct {
|
||||||
ID int64 `json:"id,omitempty"`
|
ID int64 `json:"id,omitempty"`
|
||||||
|
@ -679,7 +679,7 @@ func viewMeAPI(app *app, w http.ResponseWriter, r *http.Request) error {
|
||||||
return impart.WriteSuccess(w, uObj, http.StatusOK)
|
return impart.WriteSuccess(w, uObj, http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
func viewMyPostsAPI(app *app, u *User, w http.ResponseWriter, r *http.Request) error {
|
func viewMyPostsAPI(app *App, u *User, w http.ResponseWriter, r *http.Request) error {
|
||||||
reqJSON := IsJSON(r.Header.Get("Content-Type"))
|
reqJSON := IsJSON(r.Header.Get("Content-Type"))
|
||||||
if !reqJSON {
|
if !reqJSON {
|
||||||
return ErrBadRequestedType
|
return ErrBadRequestedType
|
||||||
|
@ -710,7 +710,7 @@ func viewMyPostsAPI(app *app, u *User, w http.ResponseWriter, r *http.Request) e
|
||||||
return impart.WriteSuccess(w, p, http.StatusOK)
|
return impart.WriteSuccess(w, p, http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
func viewMyCollectionsAPI(app *app, u *User, w http.ResponseWriter, r *http.Request) error {
|
func viewMyCollectionsAPI(app *App, u *User, w http.ResponseWriter, r *http.Request) error {
|
||||||
reqJSON := IsJSON(r.Header.Get("Content-Type"))
|
reqJSON := IsJSON(r.Header.Get("Content-Type"))
|
||||||
if !reqJSON {
|
if !reqJSON {
|
||||||
return ErrBadRequestedType
|
return ErrBadRequestedType
|
||||||
|
@ -724,7 +724,7 @@ func viewMyCollectionsAPI(app *app, u *User, w http.ResponseWriter, r *http.Requ
|
||||||
return impart.WriteSuccess(w, p, http.StatusOK)
|
return impart.WriteSuccess(w, p, http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
func viewArticles(app *app, u *User, w http.ResponseWriter, r *http.Request) error {
|
func viewArticles(app *App, u *User, w http.ResponseWriter, r *http.Request) error {
|
||||||
p, err := app.db.GetAnonymousPosts(u)
|
p, err := app.db.GetAnonymousPosts(u)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("unable to fetch anon posts: %v", err)
|
log.Error("unable to fetch anon posts: %v", err)
|
||||||
|
@ -761,7 +761,7 @@ func viewArticles(app *app, u *User, w http.ResponseWriter, r *http.Request) err
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func viewCollections(app *app, u *User, w http.ResponseWriter, r *http.Request) error {
|
func viewCollections(app *App, u *User, w http.ResponseWriter, r *http.Request) error {
|
||||||
c, err := app.db.GetCollections(u)
|
c, err := app.db.GetCollections(u)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("unable to fetch collections: %v", err)
|
log.Error("unable to fetch collections: %v", err)
|
||||||
|
@ -792,7 +792,7 @@ func viewCollections(app *app, u *User, w http.ResponseWriter, r *http.Request)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func viewEditCollection(app *app, u *User, w http.ResponseWriter, r *http.Request) error {
|
func viewEditCollection(app *App, u *User, w http.ResponseWriter, r *http.Request) error {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
c, err := app.db.GetCollection(vars["collection"])
|
c, err := app.db.GetCollection(vars["collection"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -815,7 +815,7 @@ func viewEditCollection(app *app, u *User, w http.ResponseWriter, r *http.Reques
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateSettings(app *app, w http.ResponseWriter, r *http.Request) error {
|
func updateSettings(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
reqJSON := IsJSON(r.Header.Get("Content-Type"))
|
reqJSON := IsJSON(r.Header.Get("Content-Type"))
|
||||||
|
|
||||||
var s userSettings
|
var s userSettings
|
||||||
|
@ -904,7 +904,7 @@ func updateSettings(app *app, w http.ResponseWriter, r *http.Request) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func updatePassphrase(app *app, w http.ResponseWriter, r *http.Request) error {
|
func updatePassphrase(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
accessToken := r.Header.Get("Authorization")
|
accessToken := r.Header.Get("Authorization")
|
||||||
if accessToken == "" {
|
if accessToken == "" {
|
||||||
return ErrNoAccessToken
|
return ErrNoAccessToken
|
||||||
|
@ -943,7 +943,7 @@ func updatePassphrase(app *app, w http.ResponseWriter, r *http.Request) error {
|
||||||
return impart.WriteSuccess(w, struct{}{}, http.StatusOK)
|
return impart.WriteSuccess(w, struct{}{}, http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
func viewStats(app *app, u *User, w http.ResponseWriter, r *http.Request) error {
|
func viewStats(app *App, u *User, w http.ResponseWriter, r *http.Request) error {
|
||||||
var c *Collection
|
var c *Collection
|
||||||
var err error
|
var err error
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
|
@ -994,7 +994,7 @@ func viewStats(app *app, u *User, w http.ResponseWriter, r *http.Request) error
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func viewSettings(app *app, u *User, w http.ResponseWriter, r *http.Request) error {
|
func viewSettings(app *App, u *User, w http.ResponseWriter, r *http.Request) error {
|
||||||
fullUser, err := app.db.GetUserByID(u.ID)
|
fullUser, err := app.db.GetUserByID(u.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Unable to get user for settings: %s", err)
|
log.Error("Unable to get user for settings: %s", err)
|
||||||
|
@ -1025,7 +1025,7 @@ func viewSettings(app *app, u *User, w http.ResponseWriter, r *http.Request) err
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func saveTempInfo(app *app, key, val string, r *http.Request, w http.ResponseWriter) error {
|
func saveTempInfo(app *App, key, val string, r *http.Request, w http.ResponseWriter) error {
|
||||||
session, err := app.sessionStore.Get(r, "t")
|
session, err := app.sessionStore.Get(r, "t")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ErrInternalCookieSession
|
return ErrInternalCookieSession
|
||||||
|
@ -1039,7 +1039,7 @@ func saveTempInfo(app *app, key, val string, r *http.Request, w http.ResponseWri
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func getTempInfo(app *app, key string, r *http.Request, w http.ResponseWriter) string {
|
func getTempInfo(app *App, key string, r *http.Request, w http.ResponseWriter) string {
|
||||||
session, err := app.sessionStore.Get(r, "t")
|
session, err := app.sessionStore.Get(r, "t")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2018 A Bunch Tell LLC.
|
* Copyright © 2018-2019 A Bunch Tell LLC.
|
||||||
*
|
*
|
||||||
* This file is part of WriteFreely.
|
* This file is part of WriteFreely.
|
||||||
*
|
*
|
||||||
|
@ -62,7 +62,7 @@ func (ru *RemoteUser) AsPerson() *activitystreams.Person {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleFetchCollectionActivities(app *app, w http.ResponseWriter, r *http.Request) error {
|
func handleFetchCollectionActivities(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
w.Header().Set("Server", serverSoftware)
|
w.Header().Set("Server", serverSoftware)
|
||||||
|
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
|
@ -86,7 +86,7 @@ func handleFetchCollectionActivities(app *app, w http.ResponseWriter, r *http.Re
|
||||||
return impart.RenderActivityJSON(w, p, http.StatusOK)
|
return impart.RenderActivityJSON(w, p, http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleFetchCollectionOutbox(app *app, w http.ResponseWriter, r *http.Request) error {
|
func handleFetchCollectionOutbox(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
w.Header().Set("Server", serverSoftware)
|
w.Header().Set("Server", serverSoftware)
|
||||||
|
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
|
@ -138,7 +138,7 @@ func handleFetchCollectionOutbox(app *app, w http.ResponseWriter, r *http.Reques
|
||||||
return impart.RenderActivityJSON(w, ocp, http.StatusOK)
|
return impart.RenderActivityJSON(w, ocp, http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleFetchCollectionFollowers(app *app, w http.ResponseWriter, r *http.Request) error {
|
func handleFetchCollectionFollowers(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
w.Header().Set("Server", serverSoftware)
|
w.Header().Set("Server", serverSoftware)
|
||||||
|
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
|
@ -183,7 +183,7 @@ func handleFetchCollectionFollowers(app *app, w http.ResponseWriter, r *http.Req
|
||||||
return impart.RenderActivityJSON(w, ocp, http.StatusOK)
|
return impart.RenderActivityJSON(w, ocp, http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleFetchCollectionFollowing(app *app, w http.ResponseWriter, r *http.Request) error {
|
func handleFetchCollectionFollowing(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
w.Header().Set("Server", serverSoftware)
|
w.Header().Set("Server", serverSoftware)
|
||||||
|
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
|
@ -218,7 +218,7 @@ func handleFetchCollectionFollowing(app *app, w http.ResponseWriter, r *http.Req
|
||||||
return impart.RenderActivityJSON(w, ocp, http.StatusOK)
|
return impart.RenderActivityJSON(w, ocp, http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleFetchCollectionInbox(app *app, w http.ResponseWriter, r *http.Request) error {
|
func handleFetchCollectionInbox(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
w.Header().Set("Server", serverSoftware)
|
w.Header().Set("Server", serverSoftware)
|
||||||
|
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
|
@ -531,7 +531,7 @@ func resolveIRI(url string) ([]byte, error) {
|
||||||
return body, nil
|
return body, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteFederatedPost(app *app, p *PublicPost, collID int64) error {
|
func deleteFederatedPost(app *App, p *PublicPost, collID int64) error {
|
||||||
if debugging {
|
if debugging {
|
||||||
log.Info("Deleting federated post!")
|
log.Info("Deleting federated post!")
|
||||||
}
|
}
|
||||||
|
@ -569,7 +569,7 @@ func deleteFederatedPost(app *app, p *PublicPost, collID int64) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func federatePost(app *app, p *PublicPost, collID int64, isUpdate bool) error {
|
func federatePost(app *App, p *PublicPost, collID int64, isUpdate bool) error {
|
||||||
if debugging {
|
if debugging {
|
||||||
if isUpdate {
|
if isUpdate {
|
||||||
log.Info("Federating updated post!")
|
log.Info("Federating updated post!")
|
||||||
|
@ -619,7 +619,7 @@ func federatePost(app *app, p *PublicPost, collID int64, isUpdate bool) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getRemoteUser(app *app, actorID string) (*RemoteUser, error) {
|
func getRemoteUser(app *App, actorID string) (*RemoteUser, error) {
|
||||||
u := RemoteUser{ActorID: actorID}
|
u := RemoteUser{ActorID: actorID}
|
||||||
err := app.db.QueryRow("SELECT id, inbox, shared_inbox FROM remoteusers WHERE actor_id = ?", actorID).Scan(&u.ID, &u.Inbox, &u.SharedInbox)
|
err := app.db.QueryRow("SELECT id, inbox, shared_inbox FROM remoteusers WHERE actor_id = ?", actorID).Scan(&u.ID, &u.Inbox, &u.SharedInbox)
|
||||||
switch {
|
switch {
|
||||||
|
@ -633,7 +633,7 @@ func getRemoteUser(app *app, actorID string) (*RemoteUser, error) {
|
||||||
return &u, nil
|
return &u, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getActor(app *app, actorIRI string) (*activitystreams.Person, *RemoteUser, error) {
|
func getActor(app *App, actorIRI string) (*activitystreams.Person, *RemoteUser, error) {
|
||||||
log.Info("Fetching actor %s locally", actorIRI)
|
log.Info("Fetching actor %s locally", actorIRI)
|
||||||
actor := &activitystreams.Person{}
|
actor := &activitystreams.Person{}
|
||||||
remoteUser, err := getRemoteUser(app, actorIRI)
|
remoteUser, err := getRemoteUser(app, actorIRI)
|
||||||
|
|
18
admin.go
18
admin.go
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2018 A Bunch Tell LLC.
|
* Copyright © 2018-2019 A Bunch Tell LLC.
|
||||||
*
|
*
|
||||||
* This file is part of WriteFreely.
|
* This file is part of WriteFreely.
|
||||||
*
|
*
|
||||||
|
@ -96,7 +96,7 @@ func (c instanceContent) UpdatedFriendly() string {
|
||||||
return c.Updated.Format("January 2, 2006, 3:04 PM")
|
return c.Updated.Format("January 2, 2006, 3:04 PM")
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleViewAdminDash(app *app, u *User, w http.ResponseWriter, r *http.Request) error {
|
func handleViewAdminDash(app *App, u *User, w http.ResponseWriter, r *http.Request) error {
|
||||||
updateAppStats()
|
updateAppStats()
|
||||||
p := struct {
|
p := struct {
|
||||||
*UserPage
|
*UserPage
|
||||||
|
@ -117,7 +117,7 @@ func handleViewAdminDash(app *app, u *User, w http.ResponseWriter, r *http.Reque
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleViewAdminUsers(app *app, u *User, w http.ResponseWriter, r *http.Request) error {
|
func handleViewAdminUsers(app *App, u *User, w http.ResponseWriter, r *http.Request) error {
|
||||||
p := struct {
|
p := struct {
|
||||||
*UserPage
|
*UserPage
|
||||||
Config config.AppCfg
|
Config config.AppCfg
|
||||||
|
@ -157,7 +157,7 @@ func handleViewAdminUsers(app *app, u *User, w http.ResponseWriter, r *http.Requ
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleViewAdminUser(app *app, u *User, w http.ResponseWriter, r *http.Request) error {
|
func handleViewAdminUser(app *App, u *User, w http.ResponseWriter, r *http.Request) error {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
username := vars["username"]
|
username := vars["username"]
|
||||||
if username == "" {
|
if username == "" {
|
||||||
|
@ -229,7 +229,7 @@ func handleViewAdminUser(app *app, u *User, w http.ResponseWriter, r *http.Reque
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleViewAdminPages(app *app, u *User, w http.ResponseWriter, r *http.Request) error {
|
func handleViewAdminPages(app *App, u *User, w http.ResponseWriter, r *http.Request) error {
|
||||||
p := struct {
|
p := struct {
|
||||||
*UserPage
|
*UserPage
|
||||||
Config config.AppCfg
|
Config config.AppCfg
|
||||||
|
@ -287,7 +287,7 @@ func handleViewAdminPages(app *app, u *User, w http.ResponseWriter, r *http.Requ
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleViewAdminPage(app *app, u *User, w http.ResponseWriter, r *http.Request) error {
|
func handleViewAdminPage(app *App, u *User, w http.ResponseWriter, r *http.Request) error {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
slug := vars["slug"]
|
slug := vars["slug"]
|
||||||
if slug == "" {
|
if slug == "" {
|
||||||
|
@ -329,7 +329,7 @@ func handleViewAdminPage(app *app, u *User, w http.ResponseWriter, r *http.Reque
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleAdminUpdateSite(app *app, u *User, w http.ResponseWriter, r *http.Request) error {
|
func handleAdminUpdateSite(app *App, u *User, w http.ResponseWriter, r *http.Request) error {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
id := vars["page"]
|
id := vars["page"]
|
||||||
|
|
||||||
|
@ -347,7 +347,7 @@ func handleAdminUpdateSite(app *app, u *User, w http.ResponseWriter, r *http.Req
|
||||||
return impart.HTTPError{http.StatusFound, "/admin/page/" + id + m}
|
return impart.HTTPError{http.StatusFound, "/admin/page/" + id + m}
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleAdminUpdateConfig(app *app, u *User, w http.ResponseWriter, r *http.Request) error {
|
func handleAdminUpdateConfig(app *App, u *User, w http.ResponseWriter, r *http.Request) error {
|
||||||
app.cfg.App.SiteName = r.FormValue("site_name")
|
app.cfg.App.SiteName = r.FormValue("site_name")
|
||||||
app.cfg.App.SiteDesc = r.FormValue("site_desc")
|
app.cfg.App.SiteDesc = r.FormValue("site_desc")
|
||||||
app.cfg.App.OpenRegistration = r.FormValue("open_registration") == "on"
|
app.cfg.App.OpenRegistration = r.FormValue("open_registration") == "on"
|
||||||
|
@ -418,7 +418,7 @@ func updateAppStats() {
|
||||||
sysStatus.NumGC = m.NumGC
|
sysStatus.NumGC = m.NumGC
|
||||||
}
|
}
|
||||||
|
|
||||||
func adminResetPassword(app *app, u *User, newPass string) error {
|
func adminResetPassword(app *App, u *User, newPass string) error {
|
||||||
hashedPass, err := auth.HashPass([]byte(newPass))
|
hashedPass, err := auth.HashPass([]byte(newPass))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return impart.HTTPError{http.StatusInternalServerError, fmt.Sprintf("Could not create password hash: %v", err)}
|
return impart.HTTPError{http.StatusInternalServerError, fmt.Sprintf("Could not create password hash: %v", err)}
|
||||||
|
|
39
app.go
39
app.go
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2018 A Bunch Tell LLC.
|
* Copyright © 2018-2019 A Bunch Tell LLC.
|
||||||
*
|
*
|
||||||
* This file is part of WriteFreely.
|
* This file is part of WriteFreely.
|
||||||
*
|
*
|
||||||
|
@ -62,7 +62,8 @@ var (
|
||||||
isSingleUser bool
|
isSingleUser bool
|
||||||
)
|
)
|
||||||
|
|
||||||
type app struct {
|
// App holds data and configuration for an individual WriteFreely instance.
|
||||||
|
type App struct {
|
||||||
router *mux.Router
|
router *mux.Router
|
||||||
db *datastore
|
db *datastore
|
||||||
cfg *config.Config
|
cfg *config.Config
|
||||||
|
@ -76,7 +77,7 @@ type app struct {
|
||||||
|
|
||||||
// handleViewHome shows page at root path. Will be the Pad if logged in and the
|
// handleViewHome shows page at root path. Will be the Pad if logged in and the
|
||||||
// catch-all landing page otherwise.
|
// catch-all landing page otherwise.
|
||||||
func handleViewHome(app *app, w http.ResponseWriter, r *http.Request) error {
|
func handleViewHome(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
if app.cfg.App.SingleUser {
|
if app.cfg.App.SingleUser {
|
||||||
// Render blog index
|
// Render blog index
|
||||||
return handleViewCollection(app, w, r)
|
return handleViewCollection(app, w, r)
|
||||||
|
@ -111,7 +112,7 @@ func handleViewHome(app *app, w http.ResponseWriter, r *http.Request) error {
|
||||||
return renderPage(w, "landing.tmpl", p)
|
return renderPage(w, "landing.tmpl", p)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleTemplatedPage(app *app, w http.ResponseWriter, r *http.Request, t *template.Template) error {
|
func handleTemplatedPage(app *App, w http.ResponseWriter, r *http.Request, t *template.Template) error {
|
||||||
p := struct {
|
p := struct {
|
||||||
page.StaticPage
|
page.StaticPage
|
||||||
ContentTitle string
|
ContentTitle string
|
||||||
|
@ -157,7 +158,7 @@ func handleTemplatedPage(app *app, w http.ResponseWriter, r *http.Request, t *te
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func pageForReq(app *app, r *http.Request) page.StaticPage {
|
func pageForReq(app *App, r *http.Request) page.StaticPage {
|
||||||
p := page.StaticPage{
|
p := page.StaticPage{
|
||||||
AppCfg: app.cfg.App,
|
AppCfg: app.cfg.App,
|
||||||
Path: r.URL.Path,
|
Path: r.URL.Path,
|
||||||
|
@ -189,7 +190,7 @@ func pageForReq(app *app, r *http.Request) page.StaticPage {
|
||||||
var shttp = http.NewServeMux()
|
var shttp = http.NewServeMux()
|
||||||
var fileRegex = regexp.MustCompile("/([^/]*\\.[^/]*)$")
|
var fileRegex = regexp.MustCompile("/([^/]*\\.[^/]*)$")
|
||||||
|
|
||||||
func Serve(app *app, debug bool) {
|
func Serve(app *App, debug bool) {
|
||||||
debugging = debug
|
debugging = debug
|
||||||
|
|
||||||
log.Info("Initializing...")
|
log.Info("Initializing...")
|
||||||
|
@ -317,14 +318,14 @@ func OutputVersion() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewApp creates a new app instance.
|
// NewApp creates a new app instance.
|
||||||
func NewApp(cfgFile string) *app {
|
func NewApp(cfgFile string) *App {
|
||||||
return &app{
|
return &App{
|
||||||
cfgFile: cfgFile,
|
cfgFile: cfgFile,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateConfig creates a default configuration and saves it to the app's cfgFile.
|
// CreateConfig creates a default configuration and saves it to the app's cfgFile.
|
||||||
func CreateConfig(app *app) error {
|
func CreateConfig(app *App) error {
|
||||||
log.Info("Creating configuration...")
|
log.Info("Creating configuration...")
|
||||||
c := config.New()
|
c := config.New()
|
||||||
log.Info("Saving configuration %s...", app.cfgFile)
|
log.Info("Saving configuration %s...", app.cfgFile)
|
||||||
|
@ -336,7 +337,7 @@ func CreateConfig(app *app) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// DoConfig runs the interactive configuration process.
|
// DoConfig runs the interactive configuration process.
|
||||||
func DoConfig(app *app) {
|
func DoConfig(app *App) {
|
||||||
d, err := config.Configure(app.cfgFile)
|
d, err := config.Configure(app.cfgFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Unable to configure: %v", err)
|
log.Error("Unable to configure: %v", err)
|
||||||
|
@ -374,7 +375,7 @@ func DoConfig(app *app) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenerateKeys creates app encryption keys and saves them into the configured KeysParentDir.
|
// GenerateKeys creates app encryption keys and saves them into the configured KeysParentDir.
|
||||||
func GenerateKeys(app *app) error {
|
func GenerateKeys(app *App) error {
|
||||||
// Read keys path from config
|
// Read keys path from config
|
||||||
loadConfig(app)
|
loadConfig(app)
|
||||||
|
|
||||||
|
@ -407,7 +408,7 @@ func GenerateKeys(app *app) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateSchema creates all database tables needed for the application.
|
// CreateSchema creates all database tables needed for the application.
|
||||||
func CreateSchema(app *app) error {
|
func CreateSchema(app *App) error {
|
||||||
loadConfig(app)
|
loadConfig(app)
|
||||||
connectToDatabase(app)
|
connectToDatabase(app)
|
||||||
defer shutdown(app)
|
defer shutdown(app)
|
||||||
|
@ -419,7 +420,7 @@ func CreateSchema(app *app) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Migrate runs all necessary database migrations.
|
// Migrate runs all necessary database migrations.
|
||||||
func Migrate(app *app) error {
|
func Migrate(app *App) error {
|
||||||
loadConfig(app)
|
loadConfig(app)
|
||||||
connectToDatabase(app)
|
connectToDatabase(app)
|
||||||
defer shutdown(app)
|
defer shutdown(app)
|
||||||
|
@ -432,7 +433,7 @@ func Migrate(app *app) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResetPassword runs the interactive password reset process.
|
// ResetPassword runs the interactive password reset process.
|
||||||
func ResetPassword(app *app, username string) error {
|
func ResetPassword(app *App, username string) error {
|
||||||
// Connect to the database
|
// Connect to the database
|
||||||
loadConfig(app)
|
loadConfig(app)
|
||||||
connectToDatabase(app)
|
connectToDatabase(app)
|
||||||
|
@ -470,7 +471,7 @@ func ResetPassword(app *app, username string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadConfig(app *app) {
|
func loadConfig(app *App) {
|
||||||
log.Info("Loading %s configuration...", app.cfgFile)
|
log.Info("Loading %s configuration...", app.cfgFile)
|
||||||
cfg, err := config.Load(app.cfgFile)
|
cfg, err := config.Load(app.cfgFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -480,7 +481,7 @@ func loadConfig(app *app) {
|
||||||
app.cfg = cfg
|
app.cfg = cfg
|
||||||
}
|
}
|
||||||
|
|
||||||
func connectToDatabase(app *app) {
|
func connectToDatabase(app *App) {
|
||||||
log.Info("Connecting to %s database...", app.cfg.Database.Type)
|
log.Info("Connecting to %s database...", app.cfg.Database.Type)
|
||||||
|
|
||||||
var db *sql.DB
|
var db *sql.DB
|
||||||
|
@ -510,13 +511,13 @@ func connectToDatabase(app *app) {
|
||||||
app.db = &datastore{db, app.cfg.Database.Type}
|
app.db = &datastore{db, app.cfg.Database.Type}
|
||||||
}
|
}
|
||||||
|
|
||||||
func shutdown(app *app) {
|
func shutdown(app *App) {
|
||||||
log.Info("Closing database connection...")
|
log.Info("Closing database connection...")
|
||||||
app.db.Close()
|
app.db.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateUser creates a new admin or normal user from the given username:password string.
|
// CreateUser creates a new admin or normal user from the given username:password string.
|
||||||
func CreateUser(app *app, credStr string, isAdmin bool) error {
|
func CreateUser(app *App, credStr string, isAdmin bool) error {
|
||||||
// Create an admin user with --create-admin
|
// Create an admin user with --create-admin
|
||||||
creds := strings.Split(credStr, ":")
|
creds := strings.Split(credStr, ":")
|
||||||
if len(creds) != 2 {
|
if len(creds) != 2 {
|
||||||
|
@ -587,7 +588,7 @@ func CreateUser(app *app, credStr string, isAdmin bool) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func adminInitDatabase(app *app) error {
|
func adminInitDatabase(app *App) error {
|
||||||
schemaFileName := "schema.sql"
|
schemaFileName := "schema.sql"
|
||||||
if app.cfg.Database.Type == driverSQLite {
|
if app.cfg.Database.Type == driverSQLite {
|
||||||
schemaFileName = "sqlite.sql"
|
schemaFileName = "sqlite.sql"
|
||||||
|
|
|
@ -316,7 +316,7 @@ func (c *Collection) RenderMathJax() bool {
|
||||||
return c.db.CollectionHasAttribute(c.ID, "render_mathjax")
|
return c.db.CollectionHasAttribute(c.ID, "render_mathjax")
|
||||||
}
|
}
|
||||||
|
|
||||||
func newCollection(app *app, w http.ResponseWriter, r *http.Request) error {
|
func newCollection(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
reqJSON := IsJSON(r.Header.Get("Content-Type"))
|
reqJSON := IsJSON(r.Header.Get("Content-Type"))
|
||||||
alias := r.FormValue("alias")
|
alias := r.FormValue("alias")
|
||||||
title := r.FormValue("title")
|
title := r.FormValue("title")
|
||||||
|
@ -399,7 +399,7 @@ func newCollection(app *app, w http.ResponseWriter, r *http.Request) error {
|
||||||
return impart.HTTPError{http.StatusFound, redirectTo}
|
return impart.HTTPError{http.StatusFound, redirectTo}
|
||||||
}
|
}
|
||||||
|
|
||||||
func apiCheckCollectionPermissions(app *app, r *http.Request, c *Collection) (int64, error) {
|
func apiCheckCollectionPermissions(app *App, r *http.Request, c *Collection) (int64, error) {
|
||||||
accessToken := r.Header.Get("Authorization")
|
accessToken := r.Header.Get("Authorization")
|
||||||
var userID int64 = -1
|
var userID int64 = -1
|
||||||
if accessToken != "" {
|
if accessToken != "" {
|
||||||
|
@ -419,7 +419,7 @@ func apiCheckCollectionPermissions(app *app, r *http.Request, c *Collection) (in
|
||||||
}
|
}
|
||||||
|
|
||||||
// fetchCollection handles the API endpoint for retrieving collection data.
|
// fetchCollection handles the API endpoint for retrieving collection data.
|
||||||
func fetchCollection(app *app, w http.ResponseWriter, r *http.Request) error {
|
func fetchCollection(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
accept := r.Header.Get("Accept")
|
accept := r.Header.Get("Accept")
|
||||||
if strings.Contains(accept, "application/activity+json") {
|
if strings.Contains(accept, "application/activity+json") {
|
||||||
return handleFetchCollectionActivities(app, w, r)
|
return handleFetchCollectionActivities(app, w, r)
|
||||||
|
@ -467,7 +467,7 @@ func fetchCollection(app *app, w http.ResponseWriter, r *http.Request) error {
|
||||||
|
|
||||||
// fetchCollectionPosts handles an API endpoint for retrieving a collection's
|
// fetchCollectionPosts handles an API endpoint for retrieving a collection's
|
||||||
// posts.
|
// posts.
|
||||||
func fetchCollectionPosts(app *app, w http.ResponseWriter, r *http.Request) error {
|
func fetchCollectionPosts(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
alias := vars["alias"]
|
alias := vars["alias"]
|
||||||
|
|
||||||
|
@ -563,7 +563,7 @@ func processCollectionRequest(cr *collectionReq, vars map[string]string, w http.
|
||||||
// domain that doesn't yet have a collection associated, or if a collection
|
// domain that doesn't yet have a collection associated, or if a collection
|
||||||
// requires a password. In either case, this will return nil, nil -- thus both
|
// requires a password. In either case, this will return nil, nil -- thus both
|
||||||
// values should ALWAYS be checked to determine whether or not to continue.
|
// values should ALWAYS be checked to determine whether or not to continue.
|
||||||
func processCollectionPermissions(app *app, cr *collectionReq, u *User, w http.ResponseWriter, r *http.Request) (*Collection, error) {
|
func processCollectionPermissions(app *App, cr *collectionReq, u *User, w http.ResponseWriter, r *http.Request) (*Collection, error) {
|
||||||
// Display collection if this is a collection
|
// Display collection if this is a collection
|
||||||
var c *Collection
|
var c *Collection
|
||||||
var err error
|
var err error
|
||||||
|
@ -654,7 +654,7 @@ func processCollectionPermissions(app *app, cr *collectionReq, u *User, w http.R
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkUserForCollection(app *app, cr *collectionReq, r *http.Request, isPostReq bool) (*User, error) {
|
func checkUserForCollection(app *App, cr *collectionReq, r *http.Request, isPostReq bool) (*User, error) {
|
||||||
u := getUserSession(app, r)
|
u := getUserSession(app, r)
|
||||||
return u, nil
|
return u, nil
|
||||||
}
|
}
|
||||||
|
@ -682,7 +682,7 @@ func getCollectionPage(vars map[string]string) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleViewCollection displays the requested Collection
|
// handleViewCollection displays the requested Collection
|
||||||
func handleViewCollection(app *app, w http.ResponseWriter, r *http.Request) error {
|
func handleViewCollection(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
cr := &collectionReq{}
|
cr := &collectionReq{}
|
||||||
|
|
||||||
|
@ -788,7 +788,7 @@ func handleViewCollection(app *app, w http.ResponseWriter, r *http.Request) erro
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleViewCollectionTag(app *app, w http.ResponseWriter, r *http.Request) error {
|
func handleViewCollectionTag(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
tag := vars["tag"]
|
tag := vars["tag"]
|
||||||
|
|
||||||
|
@ -867,7 +867,7 @@ func handleViewCollectionTag(app *app, w http.ResponseWriter, r *http.Request) e
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleCollectionPostRedirect(app *app, w http.ResponseWriter, r *http.Request) error {
|
func handleCollectionPostRedirect(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
slug := vars["slug"]
|
slug := vars["slug"]
|
||||||
|
|
||||||
|
@ -885,7 +885,7 @@ func handleCollectionPostRedirect(app *app, w http.ResponseWriter, r *http.Reque
|
||||||
return impart.HTTPError{http.StatusFound, loc}
|
return impart.HTTPError{http.StatusFound, loc}
|
||||||
}
|
}
|
||||||
|
|
||||||
func existingCollection(app *app, w http.ResponseWriter, r *http.Request) error {
|
func existingCollection(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
reqJSON := IsJSON(r.Header.Get("Content-Type"))
|
reqJSON := IsJSON(r.Header.Get("Content-Type"))
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
collAlias := vars["alias"]
|
collAlias := vars["alias"]
|
||||||
|
@ -980,7 +980,7 @@ func collectionAliasFromReq(r *http.Request) string {
|
||||||
return alias
|
return alias
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleWebCollectionUnlock(app *app, w http.ResponseWriter, r *http.Request) error {
|
func handleWebCollectionUnlock(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
var readReq struct {
|
var readReq struct {
|
||||||
Alias string `schema:"alias" json:"alias"`
|
Alias string `schema:"alias" json:"alias"`
|
||||||
Pass string `schema:"password" json:"password"`
|
Pass string `schema:"password" json:"password"`
|
||||||
|
@ -1047,7 +1047,7 @@ func handleWebCollectionUnlock(app *app, w http.ResponseWriter, r *http.Request)
|
||||||
return impart.HTTPError{http.StatusFound, next}
|
return impart.HTTPError{http.StatusFound, next}
|
||||||
}
|
}
|
||||||
|
|
||||||
func isAuthorizedForCollection(app *app, alias string, r *http.Request) bool {
|
func isAuthorizedForCollection(app *App, alias string, r *http.Request) bool {
|
||||||
authd := false
|
authd := false
|
||||||
session, err := app.sessionStore.Get(r, blogPassCookieName)
|
session, err := app.sessionStore.Get(r, blogPassCookieName)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
|
|
@ -60,7 +60,7 @@ type writestore interface {
|
||||||
GetTemporaryAccessToken(userID int64, validSecs int) (string, error)
|
GetTemporaryAccessToken(userID int64, validSecs int) (string, error)
|
||||||
GetTemporaryOneTimeAccessToken(userID int64, validSecs int, oneTime bool) (string, error)
|
GetTemporaryOneTimeAccessToken(userID int64, validSecs int, oneTime bool) (string, error)
|
||||||
DeleteAccount(userID int64) (l *string, err error)
|
DeleteAccount(userID int64) (l *string, err error)
|
||||||
ChangeSettings(app *app, u *User, s *userSettings) error
|
ChangeSettings(app *App, u *User, s *userSettings) error
|
||||||
ChangePassphrase(userID int64, sudo bool, curPass string, hashedPass []byte) error
|
ChangePassphrase(userID int64, sudo bool, curPass string, hashedPass []byte) error
|
||||||
|
|
||||||
GetCollections(u *User) (*[]Collection, error)
|
GetCollections(u *User) (*[]Collection, error)
|
||||||
|
@ -1774,7 +1774,7 @@ func (db *datastore) GetUserPostsCount(userID int64) int64 {
|
||||||
|
|
||||||
// ChangeSettings takes a User and applies the changes in the given
|
// ChangeSettings takes a User and applies the changes in the given
|
||||||
// userSettings, MODIFYING THE USER with successful changes.
|
// userSettings, MODIFYING THE USER with successful changes.
|
||||||
func (db *datastore) ChangeSettings(app *app, u *User, s *userSettings) error {
|
func (db *datastore) ChangeSettings(app *App, u *User, s *userSettings) error {
|
||||||
var errPass error
|
var errPass error
|
||||||
q := query.NewUpdate()
|
q := query.NewUpdate()
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2018 A Bunch Tell LLC.
|
* Copyright © 2018-2019 A Bunch Tell LLC.
|
||||||
*
|
*
|
||||||
* This file is part of WriteFreely.
|
* This file is part of WriteFreely.
|
||||||
*
|
*
|
||||||
|
@ -92,7 +92,7 @@ func exportPostsZip(u *User, posts *[]PublicPost) []byte {
|
||||||
return b.Bytes()
|
return b.Bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
func compileFullExport(app *app, u *User) *ExportUser {
|
func compileFullExport(app *App, u *User) *ExportUser {
|
||||||
exportUser := &ExportUser{
|
exportUser := &ExportUser{
|
||||||
User: u,
|
User: u,
|
||||||
}
|
}
|
||||||
|
|
4
feed.go
4
feed.go
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2018 A Bunch Tell LLC.
|
* Copyright © 2018-2019 A Bunch Tell LLC.
|
||||||
*
|
*
|
||||||
* This file is part of WriteFreely.
|
* This file is part of WriteFreely.
|
||||||
*
|
*
|
||||||
|
@ -20,7 +20,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ViewFeed(app *app, w http.ResponseWriter, req *http.Request) error {
|
func ViewFeed(app *App, w http.ResponseWriter, req *http.Request) error {
|
||||||
alias := collectionAliasFromReq(req)
|
alias := collectionAliasFromReq(req)
|
||||||
|
|
||||||
// Display collection if this is a collection
|
// Display collection if this is a collection
|
||||||
|
|
18
handle.go
18
handle.go
|
@ -36,16 +36,16 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
handlerFunc func(app *app, w http.ResponseWriter, r *http.Request) error
|
handlerFunc func(app *App, w http.ResponseWriter, r *http.Request) error
|
||||||
userHandlerFunc func(app *app, u *User, w http.ResponseWriter, r *http.Request) error
|
userHandlerFunc func(app *App, u *User, w http.ResponseWriter, r *http.Request) error
|
||||||
dataHandlerFunc func(app *app, w http.ResponseWriter, r *http.Request) ([]byte, string, error)
|
dataHandlerFunc func(app *App, w http.ResponseWriter, r *http.Request) ([]byte, string, error)
|
||||||
authFunc func(app *app, r *http.Request) (*User, error)
|
authFunc func(app *App, r *http.Request) (*User, error)
|
||||||
)
|
)
|
||||||
|
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
errors *ErrorPages
|
errors *ErrorPages
|
||||||
sessionStore *sessions.CookieStore
|
sessionStore *sessions.CookieStore
|
||||||
app *app
|
app *App
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrorPages hold template HTML error pages for displaying errors to the user.
|
// ErrorPages hold template HTML error pages for displaying errors to the user.
|
||||||
|
@ -59,7 +59,7 @@ type ErrorPages struct {
|
||||||
|
|
||||||
// NewHandler returns a new Handler instance, using the given StaticPage data,
|
// NewHandler returns a new Handler instance, using the given StaticPage data,
|
||||||
// and saving alias to the application's CookieStore.
|
// and saving alias to the application's CookieStore.
|
||||||
func NewHandler(app *app) *Handler {
|
func NewHandler(app *App) *Handler {
|
||||||
h := &Handler{
|
h := &Handler{
|
||||||
errors: &ErrorPages{
|
errors: &ErrorPages{
|
||||||
NotFound: template.Must(template.New("").Parse("{{define \"base\"}}<html><head><title>404</title></head><body><p>Not found.</p></body></html>{{end}}")),
|
NotFound: template.Must(template.New("").Parse("{{define \"base\"}}<html><head><title>404</title></head><body><p>Not found.</p></body></html>{{end}}")),
|
||||||
|
@ -160,7 +160,7 @@ func (h *Handler) Admin(f userHandlerFunc) http.HandlerFunc {
|
||||||
// UserAPI handles requests made in the API by the authenticated user.
|
// UserAPI handles requests made in the API by the authenticated user.
|
||||||
// This provides user-friendly HTML pages and actions that work in the browser.
|
// This provides user-friendly HTML pages and actions that work in the browser.
|
||||||
func (h *Handler) UserAPI(f userHandlerFunc) http.HandlerFunc {
|
func (h *Handler) UserAPI(f userHandlerFunc) http.HandlerFunc {
|
||||||
return h.UserAll(false, f, func(app *app, r *http.Request) (*User, error) {
|
return h.UserAll(false, f, func(app *App, r *http.Request) (*User, error) {
|
||||||
// Authorize user from Authorization header
|
// Authorize user from Authorization header
|
||||||
t := r.Header.Get("Authorization")
|
t := r.Header.Get("Authorization")
|
||||||
if t == "" {
|
if t == "" {
|
||||||
|
@ -222,7 +222,7 @@ func (h *Handler) UserAll(web bool, f userHandlerFunc, a authFunc) http.HandlerF
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) RedirectOnErr(f handlerFunc, loc string) handlerFunc {
|
func (h *Handler) RedirectOnErr(f handlerFunc, loc string) handlerFunc {
|
||||||
return func(app *app, w http.ResponseWriter, r *http.Request) error {
|
return func(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
err := f(app, w, r)
|
err := f(app, w, r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if ie, ok := err.(impart.HTTPError); ok {
|
if ie, ok := err.(impart.HTTPError); ok {
|
||||||
|
@ -239,7 +239,7 @@ func (h *Handler) RedirectOnErr(f handlerFunc, loc string) handlerFunc {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) Page(n string) http.HandlerFunc {
|
func (h *Handler) Page(n string) http.HandlerFunc {
|
||||||
return h.Web(func(app *app, w http.ResponseWriter, r *http.Request) error {
|
return h.Web(func(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
t, ok := pages[n]
|
t, ok := pages[n]
|
||||||
if !ok {
|
if !ok {
|
||||||
return impart.HTTPError{http.StatusNotFound, "Page not found."}
|
return impart.HTTPError{http.StatusNotFound, "Page not found."}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2018 A Bunch Tell LLC.
|
* Copyright © 2018-2019 A Bunch Tell LLC.
|
||||||
*
|
*
|
||||||
* This file is part of WriteFreely.
|
* This file is part of WriteFreely.
|
||||||
*
|
*
|
||||||
|
@ -15,7 +15,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
func handleViewHostMeta(app *app, w http.ResponseWriter, r *http.Request) error {
|
func handleViewHostMeta(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
w.Header().Set("Server", serverSoftware)
|
w.Header().Set("Server", serverSoftware)
|
||||||
w.Header().Set("Content-Type", "application/xrd+xml; charset=utf-8")
|
w.Header().Set("Content-Type", "application/xrd+xml; charset=utf-8")
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ func (i Invite) ExpiresFriendly() string {
|
||||||
return i.Expires.Format("January 2, 2006, 3:04 PM")
|
return i.Expires.Format("January 2, 2006, 3:04 PM")
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleViewUserInvites(app *app, u *User, w http.ResponseWriter, r *http.Request) error {
|
func handleViewUserInvites(app *App, u *User, w http.ResponseWriter, r *http.Request) error {
|
||||||
// Don't show page if instance doesn't allow it
|
// Don't show page if instance doesn't allow it
|
||||||
if !(app.cfg.App.UserInvites != "" && (u.IsAdmin() || app.cfg.App.UserInvites != "admin")) {
|
if !(app.cfg.App.UserInvites != "" && (u.IsAdmin() || app.cfg.App.UserInvites != "admin")) {
|
||||||
return impart.HTTPError{http.StatusNotFound, ""}
|
return impart.HTTPError{http.StatusNotFound, ""}
|
||||||
|
@ -73,7 +73,7 @@ func handleViewUserInvites(app *app, u *User, w http.ResponseWriter, r *http.Req
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleCreateUserInvite(app *app, u *User, w http.ResponseWriter, r *http.Request) error {
|
func handleCreateUserInvite(app *App, u *User, w http.ResponseWriter, r *http.Request) error {
|
||||||
muVal := r.FormValue("uses")
|
muVal := r.FormValue("uses")
|
||||||
expVal := r.FormValue("expires")
|
expVal := r.FormValue("expires")
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ func handleCreateUserInvite(app *app, u *User, w http.ResponseWriter, r *http.Re
|
||||||
return impart.HTTPError{http.StatusFound, "/me/invites"}
|
return impart.HTTPError{http.StatusFound, "/me/invites"}
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleViewInvite(app *app, w http.ResponseWriter, r *http.Request) error {
|
func handleViewInvite(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
inviteCode := mux.Vars(r)["code"]
|
inviteCode := mux.Vars(r)["code"]
|
||||||
|
|
||||||
i, err := app.db.GetUserInvite(inviteCode)
|
i, err := app.db.GetUserInvite(inviteCode)
|
||||||
|
|
6
keys.go
6
keys.go
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2018 A Bunch Tell LLC.
|
* Copyright © 2018-2019 A Bunch Tell LLC.
|
||||||
*
|
*
|
||||||
* This file is part of WriteFreely.
|
* This file is part of WriteFreely.
|
||||||
*
|
*
|
||||||
|
@ -34,13 +34,13 @@ type keychain struct {
|
||||||
emailKey, cookieAuthKey, cookieKey []byte
|
emailKey, cookieAuthKey, cookieKey []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func initKeyPaths(app *app) {
|
func initKeyPaths(app *App) {
|
||||||
emailKeyPath = filepath.Join(app.cfg.Server.KeysParentDir, emailKeyPath)
|
emailKeyPath = filepath.Join(app.cfg.Server.KeysParentDir, emailKeyPath)
|
||||||
cookieAuthKeyPath = filepath.Join(app.cfg.Server.KeysParentDir, cookieAuthKeyPath)
|
cookieAuthKeyPath = filepath.Join(app.cfg.Server.KeysParentDir, cookieAuthKeyPath)
|
||||||
cookieKeyPath = filepath.Join(app.cfg.Server.KeysParentDir, cookieKeyPath)
|
cookieKeyPath = filepath.Join(app.cfg.Server.KeysParentDir, cookieKeyPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
func initKeys(app *app) error {
|
func initKeys(app *App) error {
|
||||||
var err error
|
var err error
|
||||||
app.keys = &keychain{}
|
app.keys = &keychain{}
|
||||||
|
|
||||||
|
|
6
pad.go
6
pad.go
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2018 A Bunch Tell LLC.
|
* Copyright © 2018-2019 A Bunch Tell LLC.
|
||||||
*
|
*
|
||||||
* This file is part of WriteFreely.
|
* This file is part of WriteFreely.
|
||||||
*
|
*
|
||||||
|
@ -19,7 +19,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func handleViewPad(app *app, w http.ResponseWriter, r *http.Request) error {
|
func handleViewPad(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
action := vars["action"]
|
action := vars["action"]
|
||||||
slug := vars["slug"]
|
slug := vars["slug"]
|
||||||
|
@ -102,7 +102,7 @@ func handleViewPad(app *app, w http.ResponseWriter, r *http.Request) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleViewMeta(app *app, w http.ResponseWriter, r *http.Request) error {
|
func handleViewMeta(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
action := vars["action"]
|
action := vars["action"]
|
||||||
slug := vars["slug"]
|
slug := vars["slug"]
|
||||||
|
|
6
pages.go
6
pages.go
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2018 A Bunch Tell LLC.
|
* Copyright © 2018-2019 A Bunch Tell LLC.
|
||||||
*
|
*
|
||||||
* This file is part of WriteFreely.
|
* This file is part of WriteFreely.
|
||||||
*
|
*
|
||||||
|
@ -18,7 +18,7 @@ import (
|
||||||
|
|
||||||
var defaultPageUpdatedTime = time.Date(2018, 11, 8, 12, 0, 0, 0, time.Local)
|
var defaultPageUpdatedTime = time.Date(2018, 11, 8, 12, 0, 0, 0, time.Local)
|
||||||
|
|
||||||
func getAboutPage(app *app) (*instanceContent, error) {
|
func getAboutPage(app *App) (*instanceContent, error) {
|
||||||
c, err := app.db.GetDynamicContent("about")
|
c, err := app.db.GetDynamicContent("about")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -40,7 +40,7 @@ func defaultAboutTitle(cfg *config.Config) sql.NullString {
|
||||||
return sql.NullString{String: "About " + cfg.App.SiteName, Valid: true}
|
return sql.NullString{String: "About " + cfg.App.SiteName, Valid: true}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getPrivacyPage(app *app) (*instanceContent, error) {
|
func getPrivacyPage(app *App) (*instanceContent, error) {
|
||||||
c, err := app.db.GetDynamicContent("privacy")
|
c, err := app.db.GetDynamicContent("privacy")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
26
posts.go
26
posts.go
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2018 A Bunch Tell LLC.
|
* Copyright © 2018-2019 A Bunch Tell LLC.
|
||||||
*
|
*
|
||||||
* This file is part of WriteFreely.
|
* This file is part of WriteFreely.
|
||||||
*
|
*
|
||||||
|
@ -260,7 +260,7 @@ func (p *Post) HasTitleLink() bool {
|
||||||
return hasLink
|
return hasLink
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleViewPost(app *app, w http.ResponseWriter, r *http.Request) error {
|
func handleViewPost(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
friendlyID := vars["post"]
|
friendlyID := vars["post"]
|
||||||
|
|
||||||
|
@ -466,7 +466,7 @@ func handleViewPost(app *app, w http.ResponseWriter, r *http.Request) error {
|
||||||
// /posts
|
// /posts
|
||||||
// /posts?collection={alias}
|
// /posts?collection={alias}
|
||||||
// ? /collections/{alias}/posts
|
// ? /collections/{alias}/posts
|
||||||
func newPost(app *app, w http.ResponseWriter, r *http.Request) error {
|
func newPost(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
reqJSON := IsJSON(r.Header.Get("Content-Type"))
|
reqJSON := IsJSON(r.Header.Get("Content-Type"))
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
collAlias := vars["alias"]
|
collAlias := vars["alias"]
|
||||||
|
@ -591,7 +591,7 @@ func newPost(app *app, w http.ResponseWriter, r *http.Request) error {
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
func existingPost(app *app, w http.ResponseWriter, r *http.Request) error {
|
func existingPost(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
reqJSON := IsJSON(r.Header.Get("Content-Type"))
|
reqJSON := IsJSON(r.Header.Get("Content-Type"))
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
postID := vars["post"]
|
postID := vars["post"]
|
||||||
|
@ -711,7 +711,7 @@ func existingPost(app *app, w http.ResponseWriter, r *http.Request) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func deletePost(app *app, w http.ResponseWriter, r *http.Request) error {
|
func deletePost(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
friendlyID := vars["post"]
|
friendlyID := vars["post"]
|
||||||
editToken := r.FormValue("token")
|
editToken := r.FormValue("token")
|
||||||
|
@ -830,7 +830,7 @@ func deletePost(app *app, w http.ResponseWriter, r *http.Request) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// addPost associates a post with the authenticated user.
|
// addPost associates a post with the authenticated user.
|
||||||
func addPost(app *app, w http.ResponseWriter, r *http.Request) error {
|
func addPost(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
var ownerID int64
|
var ownerID int64
|
||||||
|
|
||||||
// Authenticate user
|
// Authenticate user
|
||||||
|
@ -879,7 +879,7 @@ func addPost(app *app, w http.ResponseWriter, r *http.Request) error {
|
||||||
return impart.WriteSuccess(w, res, http.StatusOK)
|
return impart.WriteSuccess(w, res, http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
func dispersePost(app *app, w http.ResponseWriter, r *http.Request) error {
|
func dispersePost(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
var ownerID int64
|
var ownerID int64
|
||||||
|
|
||||||
// Authenticate user
|
// Authenticate user
|
||||||
|
@ -923,7 +923,7 @@ type (
|
||||||
)
|
)
|
||||||
|
|
||||||
// pinPost pins a post to a blog
|
// pinPost pins a post to a blog
|
||||||
func pinPost(app *app, w http.ResponseWriter, r *http.Request) error {
|
func pinPost(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
var userID int64
|
var userID int64
|
||||||
|
|
||||||
// Authenticate user
|
// Authenticate user
|
||||||
|
@ -981,7 +981,7 @@ func pinPost(app *app, w http.ResponseWriter, r *http.Request) error {
|
||||||
return impart.WriteSuccess(w, res, http.StatusOK)
|
return impart.WriteSuccess(w, res, http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchPost(app *app, w http.ResponseWriter, r *http.Request) error {
|
func fetchPost(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
var collID int64
|
var collID int64
|
||||||
var coll *Collection
|
var coll *Collection
|
||||||
var err error
|
var err error
|
||||||
|
@ -1030,7 +1030,7 @@ func fetchPost(app *app, w http.ResponseWriter, r *http.Request) error {
|
||||||
return impart.WriteSuccess(w, p, http.StatusOK)
|
return impart.WriteSuccess(w, p, http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchPostProperty(app *app, w http.ResponseWriter, r *http.Request) error {
|
func fetchPostProperty(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
p, err := app.db.GetPostProperty(vars["post"], 0, vars["property"])
|
p, err := app.db.GetPostProperty(vars["post"], 0, vars["property"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1128,7 +1128,7 @@ func (p *SubmittedPost) isFontValid() bool {
|
||||||
return valid
|
return valid
|
||||||
}
|
}
|
||||||
|
|
||||||
func getRawPost(app *app, friendlyID string) *RawPost {
|
func getRawPost(app *App, friendlyID string) *RawPost {
|
||||||
var content, font, title string
|
var content, font, title string
|
||||||
var isRTL sql.NullBool
|
var isRTL sql.NullBool
|
||||||
var lang sql.NullString
|
var lang sql.NullString
|
||||||
|
@ -1148,7 +1148,7 @@ func getRawPost(app *app, friendlyID string) *RawPost {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO; return a Post!
|
// TODO; return a Post!
|
||||||
func getRawCollectionPost(app *app, slug, collAlias string) *RawPost {
|
func getRawCollectionPost(app *App, slug, collAlias string) *RawPost {
|
||||||
var id, title, content, font string
|
var id, title, content, font string
|
||||||
var isRTL sql.NullBool
|
var isRTL sql.NullBool
|
||||||
var lang sql.NullString
|
var lang sql.NullString
|
||||||
|
@ -1185,7 +1185,7 @@ func getRawCollectionPost(app *app, slug, collAlias string) *RawPost {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func viewCollectionPost(app *app, w http.ResponseWriter, r *http.Request) error {
|
func viewCollectionPost(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
slug := vars["slug"]
|
slug := vars["slug"]
|
||||||
|
|
||||||
|
|
14
read.go
14
read.go
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2018 A Bunch Tell LLC.
|
* Copyright © 2018-2019 A Bunch Tell LLC.
|
||||||
*
|
*
|
||||||
* This file is part of WriteFreely.
|
* This file is part of WriteFreely.
|
||||||
*
|
*
|
||||||
|
@ -49,7 +49,7 @@ type readPublication struct {
|
||||||
TotalPages int
|
TotalPages int
|
||||||
}
|
}
|
||||||
|
|
||||||
func initLocalTimeline(app *app) {
|
func initLocalTimeline(app *App) {
|
||||||
app.timeline = &localTimeline{
|
app.timeline = &localTimeline{
|
||||||
postsPerPage: tlPostsPerPage,
|
postsPerPage: tlPostsPerPage,
|
||||||
m: memo.New(app.db.FetchPublicPosts, 10*time.Minute),
|
m: memo.New(app.db.FetchPublicPosts, 10*time.Minute),
|
||||||
|
@ -108,7 +108,7 @@ func (db *datastore) FetchPublicPosts() (interface{}, error) {
|
||||||
return posts, nil
|
return posts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func viewLocalTimelineAPI(app *app, w http.ResponseWriter, r *http.Request) error {
|
func viewLocalTimelineAPI(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
updateTimelineCache(app.timeline)
|
updateTimelineCache(app.timeline)
|
||||||
|
|
||||||
skip, _ := strconv.Atoi(r.FormValue("skip"))
|
skip, _ := strconv.Atoi(r.FormValue("skip"))
|
||||||
|
@ -121,7 +121,7 @@ func viewLocalTimelineAPI(app *app, w http.ResponseWriter, r *http.Request) erro
|
||||||
return impart.WriteSuccess(w, posts, http.StatusOK)
|
return impart.WriteSuccess(w, posts, http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
func viewLocalTimeline(app *app, w http.ResponseWriter, r *http.Request) error {
|
func viewLocalTimeline(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
if !app.cfg.App.LocalTimeline {
|
if !app.cfg.App.LocalTimeline {
|
||||||
return impart.HTTPError{http.StatusNotFound, "Page doesn't exist."}
|
return impart.HTTPError{http.StatusNotFound, "Page doesn't exist."}
|
||||||
}
|
}
|
||||||
|
@ -153,7 +153,7 @@ func updateTimelineCache(tl *localTimeline) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func showLocalTimeline(app *app, w http.ResponseWriter, r *http.Request, page int, author, tag string) error {
|
func showLocalTimeline(app *App, w http.ResponseWriter, r *http.Request, page int, author, tag string) error {
|
||||||
updateTimelineCache(app.timeline)
|
updateTimelineCache(app.timeline)
|
||||||
|
|
||||||
pl := len(*(app.timeline.posts))
|
pl := len(*(app.timeline.posts))
|
||||||
|
@ -226,7 +226,7 @@ func (c *readPublication) PrevPageURL(n int) string {
|
||||||
|
|
||||||
// handlePostIDRedirect handles a route where a post ID is given and redirects
|
// handlePostIDRedirect handles a route where a post ID is given and redirects
|
||||||
// the user to the canonical post URL.
|
// the user to the canonical post URL.
|
||||||
func handlePostIDRedirect(app *app, w http.ResponseWriter, r *http.Request) error {
|
func handlePostIDRedirect(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
postID := vars["post"]
|
postID := vars["post"]
|
||||||
p, err := app.db.GetPost(postID, 0)
|
p, err := app.db.GetPost(postID, 0)
|
||||||
|
@ -249,7 +249,7 @@ func handlePostIDRedirect(app *app, w http.ResponseWriter, r *http.Request) erro
|
||||||
return impart.HTTPError{http.StatusFound, c.CanonicalURL() + p.Slug.String}
|
return impart.HTTPError{http.StatusFound, c.CanonicalURL() + p.Slug.String}
|
||||||
}
|
}
|
||||||
|
|
||||||
func viewLocalTimelineFeed(app *app, w http.ResponseWriter, req *http.Request) error {
|
func viewLocalTimelineFeed(app *App, w http.ResponseWriter, req *http.Request) error {
|
||||||
if !app.cfg.App.LocalTimeline {
|
if !app.cfg.App.LocalTimeline {
|
||||||
return impart.HTTPError{http.StatusNotFound, "Page doesn't exist."}
|
return impart.HTTPError{http.StatusNotFound, "Page doesn't exist."}
|
||||||
}
|
}
|
||||||
|
|
16
session.go
16
session.go
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2018 A Bunch Tell LLC.
|
* Copyright © 2018-2019 A Bunch Tell LLC.
|
||||||
*
|
*
|
||||||
* This file is part of WriteFreely.
|
* This file is part of WriteFreely.
|
||||||
*
|
*
|
||||||
|
@ -29,7 +29,7 @@ const (
|
||||||
|
|
||||||
// initSession creates the cookie store. It depends on the keychain already
|
// initSession creates the cookie store. It depends on the keychain already
|
||||||
// being loaded.
|
// being loaded.
|
||||||
func initSession(app *app) *sessions.CookieStore {
|
func initSession(app *App) *sessions.CookieStore {
|
||||||
// Register complex data types we'll be storing in cookies
|
// Register complex data types we'll be storing in cookies
|
||||||
gob.Register(&User{})
|
gob.Register(&User{})
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ func initSession(app *app) *sessions.CookieStore {
|
||||||
return store
|
return store
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSessionFlashes(app *app, w http.ResponseWriter, r *http.Request, session *sessions.Session) ([]string, error) {
|
func getSessionFlashes(app *App, w http.ResponseWriter, r *http.Request, session *sessions.Session) ([]string, error) {
|
||||||
var err error
|
var err error
|
||||||
if session == nil {
|
if session == nil {
|
||||||
session, err = app.sessionStore.Get(r, cookieName)
|
session, err = app.sessionStore.Get(r, cookieName)
|
||||||
|
@ -66,7 +66,7 @@ func getSessionFlashes(app *app, w http.ResponseWriter, r *http.Request, session
|
||||||
return f, nil
|
return f, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func addSessionFlash(app *app, w http.ResponseWriter, r *http.Request, m string, session *sessions.Session) error {
|
func addSessionFlash(app *App, w http.ResponseWriter, r *http.Request, m string, session *sessions.Session) error {
|
||||||
var err error
|
var err error
|
||||||
if session == nil {
|
if session == nil {
|
||||||
session, err = app.sessionStore.Get(r, cookieName)
|
session, err = app.sessionStore.Get(r, cookieName)
|
||||||
|
@ -82,7 +82,7 @@ func addSessionFlash(app *app, w http.ResponseWriter, r *http.Request, m string,
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getUserAndSession(app *app, r *http.Request) (*User, *sessions.Session) {
|
func getUserAndSession(app *App, r *http.Request) (*User, *sessions.Session) {
|
||||||
session, err := app.sessionStore.Get(r, cookieName)
|
session, err := app.sessionStore.Get(r, cookieName)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// Got the currently logged-in user
|
// Got the currently logged-in user
|
||||||
|
@ -97,12 +97,12 @@ func getUserAndSession(app *app, r *http.Request) (*User, *sessions.Session) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getUserSession(app *app, r *http.Request) *User {
|
func getUserSession(app *App, r *http.Request) *User {
|
||||||
u, _ := getUserAndSession(app, r)
|
u, _ := getUserAndSession(app, r)
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
func saveUserSession(app *app, r *http.Request, w http.ResponseWriter) error {
|
func saveUserSession(app *App, r *http.Request, w http.ResponseWriter) error {
|
||||||
session, err := app.sessionStore.Get(r, cookieName)
|
session, err := app.sessionStore.Get(r, cookieName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ErrInternalCookieSession
|
return ErrInternalCookieSession
|
||||||
|
@ -127,7 +127,7 @@ func saveUserSession(app *app, r *http.Request, w http.ResponseWriter) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func getFullUserSession(app *app, r *http.Request) *User {
|
func getFullUserSession(app *App, r *http.Request) *User {
|
||||||
u := getUserSession(app, r)
|
u := getUserSession(app, r)
|
||||||
if u == nil {
|
if u == nil {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2018 A Bunch Tell LLC.
|
* Copyright © 2018-2019 A Bunch Tell LLC.
|
||||||
*
|
*
|
||||||
* This file is part of WriteFreely.
|
* This file is part of WriteFreely.
|
||||||
*
|
*
|
||||||
|
@ -34,7 +34,7 @@ func buildSitemap(host, alias string) *stm.Sitemap {
|
||||||
return sm
|
return sm
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleViewSitemap(app *app, w http.ResponseWriter, r *http.Request) error {
|
func handleViewSitemap(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
|
|
||||||
// Determine canonical blog URL
|
// Determine canonical blog URL
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2018 A Bunch Tell LLC.
|
* Copyright © 2018-2019 A Bunch Tell LLC.
|
||||||
*
|
*
|
||||||
* This file is part of WriteFreely.
|
* This file is part of WriteFreely.
|
||||||
*
|
*
|
||||||
|
@ -18,7 +18,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
func handleWebSignup(app *app, w http.ResponseWriter, r *http.Request) error {
|
func handleWebSignup(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
reqJSON := IsJSON(r.Header.Get("Content-Type"))
|
reqJSON := IsJSON(r.Header.Get("Content-Type"))
|
||||||
|
|
||||||
// Get params
|
// Get params
|
||||||
|
@ -67,7 +67,7 @@ func handleWebSignup(app *app, w http.ResponseWriter, r *http.Request) error {
|
||||||
|
|
||||||
// { "username": "asdf" }
|
// { "username": "asdf" }
|
||||||
// result: { code: 204 }
|
// result: { code: 204 }
|
||||||
func handleUsernameCheck(app *app, w http.ResponseWriter, r *http.Request) error {
|
func handleUsernameCheck(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
reqJSON := IsJSON(r.Header.Get("Content-Type"))
|
reqJSON := IsJSON(r.Header.Get("Content-Type"))
|
||||||
|
|
||||||
// Get params
|
// Get params
|
||||||
|
@ -112,7 +112,7 @@ func handleUsernameCheck(app *app, w http.ResponseWriter, r *http.Request) error
|
||||||
return impart.HTTPError{http.StatusConflict, "Username is already taken."}
|
return impart.HTTPError{http.StatusConflict, "Username is already taken."}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getValidUsername(app *app, reqName, prevName string) (string, *impart.HTTPError) {
|
func getValidUsername(app *App, reqName, prevName string) (string, *impart.HTTPError) {
|
||||||
// Check if username is okay
|
// Check if username is okay
|
||||||
finalUsername := getSlug(reqName, "")
|
finalUsername := getSlug(reqName, "")
|
||||||
if finalUsername == "" {
|
if finalUsername == "" {
|
||||||
|
|
Loading…
Reference in New Issue