@@ -1,5 +1,5 @@ | |||
/* | |||
* Copyright © 2018 A Bunch Tell LLC. | |||
* Copyright © 2018-2019 A Bunch Tell LLC. | |||
* | |||
* 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{ | |||
StaticPage: pageForReq(app, r), | |||
PageTitle: title, | |||
@@ -73,12 +73,12 @@ const ( | |||
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) | |||
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")) | |||
// Get params | |||
@@ -113,7 +113,7 @@ func signup(app *app, w http.ResponseWriter, r *http.Request) (*AuthUser, error) | |||
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")) | |||
// Validate required params (alias) | |||
@@ -229,7 +229,7 @@ func signupWithRegistration(app *app, signup userRegistration, w http.ResponseWr | |||
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) | |||
if err != nil { | |||
return ErrInternalCookieSession | |||
@@ -268,7 +268,7 @@ func viewLogout(app *app, w http.ResponseWriter, r *http.Request) error { | |||
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") | |||
if accessToken == "" { | |||
return ErrNoAccessToken | |||
@@ -284,7 +284,7 @@ func handleAPILogout(app *app, w http.ResponseWriter, r *http.Request) error { | |||
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 | |||
oneTimeToken := r.FormValue("with") | |||
if oneTimeToken != "" { | |||
@@ -333,7 +333,7 @@ func viewLogin(app *app, w http.ResponseWriter, r *http.Request) error { | |||
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) | |||
if err != nil { | |||
username := r.FormValue("alias") | |||
@@ -370,7 +370,7 @@ func webLogin(app *app, w http.ResponseWriter, r *http.Request) error { | |||
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")) | |||
oneTimeToken := r.FormValue("with") | |||
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 | |||
} | |||
func getVerboseAuthUser(app *app, token string, u *User, verbose bool) *AuthUser { | |||
func getVerboseAuthUser(app *App, token string, u *User, verbose bool) *AuthUser { | |||
resUser := &AuthUser{ | |||
AccessToken: token, | |||
User: u, | |||
@@ -563,7 +563,7 @@ func getVerboseAuthUser(app *app, token string, u *User, verbose bool) *AuthUser | |||
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 | |||
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 | |||
} | |||
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 u = &User{} | |||
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 | |||
} | |||
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 | |||
filename := "" | |||
u := getUserSession(app, r) | |||
@@ -655,7 +655,7 @@ func viewExportFull(app *app, w http.ResponseWriter, r *http.Request) ([]byte, s | |||
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")) | |||
uObj := struct { | |||
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) | |||
} | |||
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")) | |||
if !reqJSON { | |||
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) | |||
} | |||
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")) | |||
if !reqJSON { | |||
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) | |||
} | |||
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) | |||
if err != nil { | |||
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 | |||
} | |||
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) | |||
if err != nil { | |||
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 | |||
} | |||
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) | |||
c, err := app.db.GetCollection(vars["collection"]) | |||
if err != nil { | |||
@@ -815,7 +815,7 @@ func viewEditCollection(app *app, u *User, w http.ResponseWriter, r *http.Reques | |||
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")) | |||
var s userSettings | |||
@@ -904,7 +904,7 @@ func updateSettings(app *app, w http.ResponseWriter, r *http.Request) error { | |||
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") | |||
if accessToken == "" { | |||
return ErrNoAccessToken | |||
@@ -943,7 +943,7 @@ func updatePassphrase(app *app, w http.ResponseWriter, r *http.Request) error { | |||
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 err error | |||
vars := mux.Vars(r) | |||
@@ -994,7 +994,7 @@ func viewStats(app *app, u *User, w http.ResponseWriter, r *http.Request) error | |||
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) | |||
if err != nil { | |||
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 | |||
} | |||
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") | |||
if err != nil { | |||
return ErrInternalCookieSession | |||
@@ -1039,7 +1039,7 @@ func saveTempInfo(app *app, key, val string, r *http.Request, w http.ResponseWri | |||
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") | |||
if err != nil { | |||
return "" | |||
@@ -1,5 +1,5 @@ | |||
/* | |||
* Copyright © 2018 A Bunch Tell LLC. | |||
* Copyright © 2018-2019 A Bunch Tell LLC. | |||
* | |||
* 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) | |||
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) | |||
} | |||
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) | |||
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) | |||
} | |||
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) | |||
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) | |||
} | |||
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) | |||
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) | |||
} | |||
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) | |||
vars := mux.Vars(r) | |||
@@ -531,7 +531,7 @@ func resolveIRI(url string) ([]byte, error) { | |||
return body, nil | |||
} | |||
func deleteFederatedPost(app *app, p *PublicPost, collID int64) error { | |||
func deleteFederatedPost(app *App, p *PublicPost, collID int64) error { | |||
if debugging { | |||
log.Info("Deleting federated post!") | |||
} | |||
@@ -569,7 +569,7 @@ func deleteFederatedPost(app *app, p *PublicPost, collID int64) error { | |||
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 isUpdate { | |||
log.Info("Federating updated post!") | |||
@@ -619,7 +619,7 @@ func federatePost(app *app, p *PublicPost, collID int64, isUpdate bool) error { | |||
return nil | |||
} | |||
func getRemoteUser(app *app, actorID string) (*RemoteUser, error) { | |||
func getRemoteUser(app *App, actorID string) (*RemoteUser, error) { | |||
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) | |||
switch { | |||
@@ -633,7 +633,7 @@ func getRemoteUser(app *app, actorID string) (*RemoteUser, error) { | |||
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) | |||
actor := &activitystreams.Person{} | |||
remoteUser, err := getRemoteUser(app, actorIRI) | |||
@@ -1,5 +1,5 @@ | |||
/* | |||
* Copyright © 2018 A Bunch Tell LLC. | |||
* Copyright © 2018-2019 A Bunch Tell LLC. | |||
* | |||
* 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") | |||
} | |||
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() | |||
p := struct { | |||
*UserPage | |||
@@ -117,7 +117,7 @@ func handleViewAdminDash(app *app, u *User, w http.ResponseWriter, r *http.Reque | |||
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 { | |||
*UserPage | |||
Config config.AppCfg | |||
@@ -157,7 +157,7 @@ func handleViewAdminUsers(app *app, u *User, w http.ResponseWriter, r *http.Requ | |||
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) | |||
username := vars["username"] | |||
if username == "" { | |||
@@ -229,7 +229,7 @@ func handleViewAdminUser(app *app, u *User, w http.ResponseWriter, r *http.Reque | |||
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 { | |||
*UserPage | |||
Config config.AppCfg | |||
@@ -287,7 +287,7 @@ func handleViewAdminPages(app *app, u *User, w http.ResponseWriter, r *http.Requ | |||
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) | |||
slug := vars["slug"] | |||
if slug == "" { | |||
@@ -329,7 +329,7 @@ func handleViewAdminPage(app *app, u *User, w http.ResponseWriter, r *http.Reque | |||
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) | |||
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} | |||
} | |||
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.SiteDesc = r.FormValue("site_desc") | |||
app.cfg.App.OpenRegistration = r.FormValue("open_registration") == "on" | |||
@@ -418,7 +418,7 @@ func updateAppStats() { | |||
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)) | |||
if err != nil { | |||
return impart.HTTPError{http.StatusInternalServerError, fmt.Sprintf("Could not create password hash: %v", err)} | |||
@@ -1,5 +1,5 @@ | |||
/* | |||
* Copyright © 2018 A Bunch Tell LLC. | |||
* Copyright © 2018-2019 A Bunch Tell LLC. | |||
* | |||
* This file is part of WriteFreely. | |||
* | |||
@@ -62,7 +62,8 @@ var ( | |||
isSingleUser bool | |||
) | |||
type app struct { | |||
// App holds data and configuration for an individual WriteFreely instance. | |||
type App struct { | |||
router *mux.Router | |||
db *datastore | |||
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 | |||
// 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 { | |||
// Render blog index | |||
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) | |||
} | |||
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 { | |||
page.StaticPage | |||
ContentTitle string | |||
@@ -157,7 +158,7 @@ func handleTemplatedPage(app *app, w http.ResponseWriter, r *http.Request, t *te | |||
return nil | |||
} | |||
func pageForReq(app *app, r *http.Request) page.StaticPage { | |||
func pageForReq(app *App, r *http.Request) page.StaticPage { | |||
p := page.StaticPage{ | |||
AppCfg: app.cfg.App, | |||
Path: r.URL.Path, | |||
@@ -189,7 +190,7 @@ func pageForReq(app *app, r *http.Request) page.StaticPage { | |||
var shttp = http.NewServeMux() | |||
var fileRegex = regexp.MustCompile("/([^/]*\\.[^/]*)$") | |||
func Serve(app *app, debug bool) { | |||
func Serve(app *App, debug bool) { | |||
debugging = debug | |||
log.Info("Initializing...") | |||
@@ -317,14 +318,14 @@ func OutputVersion() { | |||
} | |||
// NewApp creates a new app instance. | |||
func NewApp(cfgFile string) *app { | |||
return &app{ | |||
func NewApp(cfgFile string) *App { | |||
return &App{ | |||
cfgFile: 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...") | |||
c := config.New() | |||
log.Info("Saving configuration %s...", app.cfgFile) | |||
@@ -336,7 +337,7 @@ func CreateConfig(app *app) error { | |||
} | |||
// DoConfig runs the interactive configuration process. | |||
func DoConfig(app *app) { | |||
func DoConfig(app *App) { | |||
d, err := config.Configure(app.cfgFile) | |||
if err != nil { | |||
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. | |||
func GenerateKeys(app *app) error { | |||
func GenerateKeys(app *App) error { | |||
// Read keys path from config | |||
loadConfig(app) | |||
@@ -407,7 +408,7 @@ func GenerateKeys(app *app) error { | |||
} | |||
// CreateSchema creates all database tables needed for the application. | |||
func CreateSchema(app *app) error { | |||
func CreateSchema(app *App) error { | |||
loadConfig(app) | |||
connectToDatabase(app) | |||
defer shutdown(app) | |||
@@ -419,7 +420,7 @@ func CreateSchema(app *app) error { | |||
} | |||
// Migrate runs all necessary database migrations. | |||
func Migrate(app *app) error { | |||
func Migrate(app *App) error { | |||
loadConfig(app) | |||
connectToDatabase(app) | |||
defer shutdown(app) | |||
@@ -432,7 +433,7 @@ func Migrate(app *app) error { | |||
} | |||
// 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 | |||
loadConfig(app) | |||
connectToDatabase(app) | |||
@@ -470,7 +471,7 @@ func ResetPassword(app *app, username string) error { | |||
return nil | |||
} | |||
func loadConfig(app *app) { | |||
func loadConfig(app *App) { | |||
log.Info("Loading %s configuration...", app.cfgFile) | |||
cfg, err := config.Load(app.cfgFile) | |||
if err != nil { | |||
@@ -480,7 +481,7 @@ func loadConfig(app *app) { | |||
app.cfg = cfg | |||
} | |||
func connectToDatabase(app *app) { | |||
func connectToDatabase(app *App) { | |||
log.Info("Connecting to %s database...", app.cfg.Database.Type) | |||
var db *sql.DB | |||
@@ -510,13 +511,13 @@ func connectToDatabase(app *app) { | |||
app.db = &datastore{db, app.cfg.Database.Type} | |||
} | |||
func shutdown(app *app) { | |||
func shutdown(app *App) { | |||
log.Info("Closing database connection...") | |||
app.db.Close() | |||
} | |||
// 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 | |||
creds := strings.Split(credStr, ":") | |||
if len(creds) != 2 { | |||
@@ -587,7 +588,7 @@ func CreateUser(app *app, credStr string, isAdmin bool) error { | |||
return nil | |||
} | |||
func adminInitDatabase(app *app) error { | |||
func adminInitDatabase(app *App) error { | |||
schemaFileName := "schema.sql" | |||
if app.cfg.Database.Type == driverSQLite { | |||
schemaFileName = "sqlite.sql" | |||
@@ -316,7 +316,7 @@ func (c *Collection) RenderMathJax() bool { | |||
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")) | |||
alias := r.FormValue("alias") | |||
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} | |||
} | |||
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") | |||
var userID int64 = -1 | |||
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. | |||
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") | |||
if strings.Contains(accept, "application/activity+json") { | |||
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 | |||
// 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) | |||
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 | |||
// 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. | |||
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 | |||
var c *Collection | |||
var err error | |||
@@ -654,7 +654,7 @@ func processCollectionPermissions(app *app, cr *collectionReq, u *User, w http.R | |||
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) | |||
return u, nil | |||
} | |||
@@ -682,7 +682,7 @@ func getCollectionPage(vars map[string]string) int { | |||
} | |||
// 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) | |||
cr := &collectionReq{} | |||
@@ -788,7 +788,7 @@ func handleViewCollection(app *app, w http.ResponseWriter, r *http.Request) erro | |||
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) | |||
tag := vars["tag"] | |||
@@ -867,7 +867,7 @@ func handleViewCollectionTag(app *app, w http.ResponseWriter, r *http.Request) e | |||
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) | |||
slug := vars["slug"] | |||
@@ -885,7 +885,7 @@ func handleCollectionPostRedirect(app *app, w http.ResponseWriter, r *http.Reque | |||
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")) | |||
vars := mux.Vars(r) | |||
collAlias := vars["alias"] | |||
@@ -980,7 +980,7 @@ func collectionAliasFromReq(r *http.Request) string { | |||
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 { | |||
Alias string `schema:"alias" json:"alias"` | |||
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} | |||
} | |||
func isAuthorizedForCollection(app *app, alias string, r *http.Request) bool { | |||
func isAuthorizedForCollection(app *App, alias string, r *http.Request) bool { | |||
authd := false | |||
session, err := app.sessionStore.Get(r, blogPassCookieName) | |||
if err == nil { | |||
@@ -60,7 +60,7 @@ type writestore interface { | |||
GetTemporaryAccessToken(userID int64, validSecs int) (string, error) | |||
GetTemporaryOneTimeAccessToken(userID int64, validSecs int, oneTime bool) (string, 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 | |||
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 | |||
// 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 | |||
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. | |||
* | |||
@@ -92,7 +92,7 @@ func exportPostsZip(u *User, posts *[]PublicPost) []byte { | |||
return b.Bytes() | |||
} | |||
func compileFullExport(app *app, u *User) *ExportUser { | |||
func compileFullExport(app *App, u *User) *ExportUser { | |||
exportUser := &ExportUser{ | |||
User: u, | |||
} | |||
@@ -1,5 +1,5 @@ | |||
/* | |||
* Copyright © 2018 A Bunch Tell LLC. | |||
* Copyright © 2018-2019 A Bunch Tell LLC. | |||
* | |||
* This file is part of WriteFreely. | |||
* | |||
@@ -20,7 +20,7 @@ import ( | |||
"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) | |||
// Display collection if this is a collection | |||
@@ -36,16 +36,16 @@ const ( | |||
) | |||
type ( | |||
handlerFunc func(app *app, 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) | |||
authFunc func(app *app, r *http.Request) (*User, 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 | |||
dataHandlerFunc func(app *App, w http.ResponseWriter, r *http.Request) ([]byte, string, error) | |||
authFunc func(app *App, r *http.Request) (*User, error) | |||
) | |||
type Handler struct { | |||
errors *ErrorPages | |||
sessionStore *sessions.CookieStore | |||
app *app | |||
app *App | |||
} | |||
// 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, | |||
// and saving alias to the application's CookieStore. | |||
func NewHandler(app *app) *Handler { | |||
func NewHandler(app *App) *Handler { | |||
h := &Handler{ | |||
errors: &ErrorPages{ | |||
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. | |||
// This provides user-friendly HTML pages and actions that work in the browser. | |||
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 | |||
t := r.Header.Get("Authorization") | |||
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 { | |||
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) | |||
if err != nil { | |||
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 { | |||
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] | |||
if !ok { | |||
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. | |||
* | |||
@@ -15,7 +15,7 @@ import ( | |||
"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("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") | |||
} | |||
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 | |||
if !(app.cfg.App.UserInvites != "" && (u.IsAdmin() || app.cfg.App.UserInvites != "admin")) { | |||
return impart.HTTPError{http.StatusNotFound, ""} | |||
@@ -73,7 +73,7 @@ func handleViewUserInvites(app *app, u *User, w http.ResponseWriter, r *http.Req | |||
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") | |||
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"} | |||
} | |||
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"] | |||
i, err := app.db.GetUserInvite(inviteCode) | |||
@@ -1,5 +1,5 @@ | |||
/* | |||
* Copyright © 2018 A Bunch Tell LLC. | |||
* Copyright © 2018-2019 A Bunch Tell LLC. | |||
* | |||
* This file is part of WriteFreely. | |||
* | |||
@@ -34,13 +34,13 @@ type keychain struct { | |||
emailKey, cookieAuthKey, cookieKey []byte | |||
} | |||
func initKeyPaths(app *app) { | |||
func initKeyPaths(app *App) { | |||
emailKeyPath = filepath.Join(app.cfg.Server.KeysParentDir, emailKeyPath) | |||
cookieAuthKeyPath = filepath.Join(app.cfg.Server.KeysParentDir, cookieAuthKeyPath) | |||
cookieKeyPath = filepath.Join(app.cfg.Server.KeysParentDir, cookieKeyPath) | |||
} | |||
func initKeys(app *app) error { | |||
func initKeys(app *App) error { | |||
var err error | |||
app.keys = &keychain{} | |||
@@ -1,5 +1,5 @@ | |||
/* | |||
* Copyright © 2018 A Bunch Tell LLC. | |||
* Copyright © 2018-2019 A Bunch Tell LLC. | |||
* | |||
* This file is part of WriteFreely. | |||
* | |||
@@ -19,7 +19,7 @@ import ( | |||
"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) | |||
action := vars["action"] | |||
slug := vars["slug"] | |||
@@ -102,7 +102,7 @@ func handleViewPad(app *app, w http.ResponseWriter, r *http.Request) error { | |||
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) | |||
action := vars["action"] | |||
slug := vars["slug"] | |||
@@ -1,5 +1,5 @@ | |||
/* | |||
* Copyright © 2018 A Bunch Tell LLC. | |||
* Copyright © 2018-2019 A Bunch Tell LLC. | |||
* | |||
* This file is part of WriteFreely. | |||
* | |||
@@ -18,7 +18,7 @@ import ( | |||
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") | |||
if err != nil { | |||
return nil, err | |||
@@ -40,7 +40,7 @@ func defaultAboutTitle(cfg *config.Config) sql.NullString { | |||
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") | |||
if err != nil { | |||
return nil, err | |||
@@ -1,5 +1,5 @@ | |||
/* | |||
* Copyright © 2018 A Bunch Tell LLC. | |||
* Copyright © 2018-2019 A Bunch Tell LLC. | |||
* | |||
* This file is part of WriteFreely. | |||
* | |||
@@ -260,7 +260,7 @@ func (p *Post) HasTitleLink() bool { | |||
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) | |||
friendlyID := vars["post"] | |||
@@ -466,7 +466,7 @@ func handleViewPost(app *app, w http.ResponseWriter, r *http.Request) error { | |||
// /posts | |||
// /posts?collection={alias} | |||
// ? /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")) | |||
vars := mux.Vars(r) | |||
collAlias := vars["alias"] | |||
@@ -591,7 +591,7 @@ func newPost(app *app, w http.ResponseWriter, r *http.Request) error { | |||
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")) | |||
vars := mux.Vars(r) | |||
postID := vars["post"] | |||
@@ -711,7 +711,7 @@ func existingPost(app *app, w http.ResponseWriter, r *http.Request) error { | |||
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) | |||
friendlyID := vars["post"] | |||
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. | |||
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 | |||
// Authenticate user | |||
@@ -879,7 +879,7 @@ func addPost(app *app, w http.ResponseWriter, r *http.Request) error { | |||
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 | |||
// Authenticate user | |||
@@ -923,7 +923,7 @@ type ( | |||
) | |||
// 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 | |||
// Authenticate user | |||
@@ -981,7 +981,7 @@ func pinPost(app *app, w http.ResponseWriter, r *http.Request) error { | |||
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 coll *Collection | |||
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) | |||
} | |||
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) | |||
p, err := app.db.GetPostProperty(vars["post"], 0, vars["property"]) | |||
if err != nil { | |||
@@ -1128,7 +1128,7 @@ func (p *SubmittedPost) isFontValid() bool { | |||
return valid | |||
} | |||
func getRawPost(app *app, friendlyID string) *RawPost { | |||
func getRawPost(app *App, friendlyID string) *RawPost { | |||
var content, font, title string | |||
var isRTL sql.NullBool | |||
var lang sql.NullString | |||
@@ -1148,7 +1148,7 @@ func getRawPost(app *app, friendlyID string) *RawPost { | |||
} | |||
// 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 isRTL sql.NullBool | |||
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) | |||
slug := vars["slug"] | |||
@@ -1,5 +1,5 @@ | |||
/* | |||
* Copyright © 2018 A Bunch Tell LLC. | |||
* Copyright © 2018-2019 A Bunch Tell LLC. | |||
* | |||
* This file is part of WriteFreely. | |||
* | |||
@@ -49,7 +49,7 @@ type readPublication struct { | |||
TotalPages int | |||
} | |||
func initLocalTimeline(app *app) { | |||
func initLocalTimeline(app *App) { | |||
app.timeline = &localTimeline{ | |||
postsPerPage: tlPostsPerPage, | |||
m: memo.New(app.db.FetchPublicPosts, 10*time.Minute), | |||
@@ -108,7 +108,7 @@ func (db *datastore) FetchPublicPosts() (interface{}, error) { | |||
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) | |||
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) | |||
} | |||
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 { | |||
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) | |||
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 | |||
// 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) | |||
postID := vars["post"] | |||
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} | |||
} | |||
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 { | |||
return impart.HTTPError{http.StatusNotFound, "Page doesn't exist."} | |||
} | |||
@@ -1,5 +1,5 @@ | |||
/* | |||
* Copyright © 2018 A Bunch Tell LLC. | |||
* Copyright © 2018-2019 A Bunch Tell LLC. | |||
* | |||
* This file is part of WriteFreely. | |||
* | |||
@@ -29,7 +29,7 @@ const ( | |||
// initSession creates the cookie store. It depends on the keychain already | |||
// being loaded. | |||
func initSession(app *app) *sessions.CookieStore { | |||
func initSession(app *App) *sessions.CookieStore { | |||
// Register complex data types we'll be storing in cookies | |||
gob.Register(&User{}) | |||
@@ -44,7 +44,7 @@ func initSession(app *app) *sessions.CookieStore { | |||
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 | |||
if session == nil { | |||
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 | |||
} | |||
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 | |||
if session == nil { | |||
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 | |||
} | |||
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) | |||
if err == nil { | |||
// Got the currently logged-in user | |||
@@ -97,12 +97,12 @@ func getUserAndSession(app *app, r *http.Request) (*User, *sessions.Session) { | |||
return nil, nil | |||
} | |||
func getUserSession(app *app, r *http.Request) *User { | |||
func getUserSession(app *App, r *http.Request) *User { | |||
u, _ := getUserAndSession(app, r) | |||
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) | |||
if err != nil { | |||
return ErrInternalCookieSession | |||
@@ -127,7 +127,7 @@ func saveUserSession(app *app, r *http.Request, w http.ResponseWriter) error { | |||
return err | |||
} | |||
func getFullUserSession(app *app, r *http.Request) *User { | |||
func getFullUserSession(app *App, r *http.Request) *User { | |||
u := getUserSession(app, r) | |||
if u == 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. | |||
* | |||
@@ -34,7 +34,7 @@ func buildSitemap(host, alias string) *stm.Sitemap { | |||
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) | |||
// 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. | |||
* | |||
@@ -18,7 +18,7 @@ import ( | |||
"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")) | |||
// Get params | |||
@@ -67,7 +67,7 @@ func handleWebSignup(app *app, w http.ResponseWriter, r *http.Request) error { | |||
// { "username": "asdf" } | |||
// 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")) | |||
// 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."} | |||
} | |||
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 | |||
finalUsername := getSlug(reqName, "") | |||
if finalUsername == "" { | |||