This moves `hostName` to the `Collection` struct, where it's needed. The field is populated after successful `GetCollection...()` calls. This isn't the cleanest way to do things, but it accomplishes the goal. Eventually, we should accept the AppCfg to `GetCollection...()` calls, or make them `App` methods, instead of `datastore` methods. Ref T613pull/102/head
@@ -80,6 +80,7 @@ func handleFetchCollectionActivities(app *App, w http.ResponseWriter, r *http.Re | |||
if err != nil { | |||
return err | |||
} | |||
c.hostName = app.cfg.App.Host | |||
p := c.PersonObject() | |||
@@ -104,6 +105,7 @@ func handleFetchCollectionOutbox(app *App, w http.ResponseWriter, r *http.Reques | |||
if err != nil { | |||
return err | |||
} | |||
c.hostName = app.cfg.App.Host | |||
if app.cfg.App.SingleUser { | |||
if alias != c.Alias { | |||
@@ -156,6 +158,7 @@ func handleFetchCollectionFollowers(app *App, w http.ResponseWriter, r *http.Req | |||
if err != nil { | |||
return err | |||
} | |||
c.hostName = app.cfg.App.Host | |||
accountRoot := c.FederatedAccount() | |||
@@ -201,6 +204,7 @@ func handleFetchCollectionFollowing(app *App, w http.ResponseWriter, r *http.Req | |||
if err != nil { | |||
return err | |||
} | |||
c.hostName = app.cfg.App.Host | |||
accountRoot := c.FederatedAccount() | |||
@@ -234,6 +238,7 @@ func handleFetchCollectionInbox(app *App, w http.ResponseWriter, r *http.Request | |||
// TODO: return Reject? | |||
return err | |||
} | |||
c.hostName = app.cfg.App.Host | |||
if debugging { | |||
dump, err := httputil.DumpRequest(r, true) | |||
@@ -349,7 +354,7 @@ func handleFetchCollectionInbox(app *App, w http.ResponseWriter, r *http.Request | |||
log.Error("No to! %v", err) | |||
return | |||
} | |||
err = makeActivityPost(p, fullActor.Inbox, am) | |||
err = makeActivityPost(app.cfg.App.Host, p, fullActor.Inbox, am) | |||
if err != nil { | |||
log.Error("Unable to make activity POST: %v", err) | |||
return | |||
@@ -423,7 +428,7 @@ func handleFetchCollectionInbox(app *App, w http.ResponseWriter, r *http.Request | |||
return nil | |||
} | |||
func makeActivityPost(p *activitystreams.Person, url string, m interface{}) error { | |||
func makeActivityPost(hostName string, p *activitystreams.Person, url string, m interface{}) error { | |||
log.Info("POST %s", url) | |||
b, err := json.Marshal(m) | |||
if err != nil { | |||
@@ -477,7 +482,7 @@ func makeActivityPost(p *activitystreams.Person, url string, m interface{}) erro | |||
return nil | |||
} | |||
func resolveIRI(url string) ([]byte, error) { | |||
func resolveIRI(hostName, url string) ([]byte, error) { | |||
log.Info("GET %s", url) | |||
r, _ := http.NewRequest("GET", url, nil) | |||
@@ -547,7 +552,7 @@ func deleteFederatedPost(app *App, p *PublicPost, collID int64) error { | |||
na.CC = append(na.CC, f) | |||
} | |||
err = makeActivityPost(actor, si, activitystreams.NewDeleteActivity(na)) | |||
err = makeActivityPost(app.cfg.App.Host, actor, si, activitystreams.NewDeleteActivity(na)) | |||
if err != nil { | |||
log.Error("Couldn't delete post! %v", err) | |||
} | |||
@@ -601,7 +606,7 @@ func federatePost(app *App, p *PublicPost, collID int64, isUpdate bool) error { | |||
activity.To = na.To | |||
activity.CC = na.CC | |||
} | |||
err = makeActivityPost(actor, si, activity) | |||
err = makeActivityPost(app.cfg.App.Host, actor, si, activity) | |||
if err != nil { | |||
log.Error("Couldn't post! %v", err) | |||
} | |||
@@ -632,7 +637,7 @@ func getActor(app *App, actorIRI string) (*activitystreams.Person, *RemoteUser, | |||
if iErr.Status == http.StatusNotFound { | |||
// Fetch remote actor | |||
log.Info("Not found; fetching actor %s remotely", actorIRI) | |||
actorResp, err := resolveIRI(actorIRI) | |||
actorResp, err := resolveIRI(app.cfg.App.Host, actorIRI) | |||
if err != nil { | |||
log.Error("Unable to get actor! %v", err) | |||
return nil, nil, impart.HTTPError{http.StatusInternalServerError, "Couldn't fetch actor."} | |||
@@ -57,9 +57,6 @@ var ( | |||
softwareVer = "0.9.0" | |||
// DEPRECATED VARS | |||
// TODO: pass app.cfg into GetCollection* calls so we can get these values | |||
// from Collection methods and we no longer need these. | |||
hostName string | |||
isSingleUser bool | |||
) | |||
@@ -338,7 +335,6 @@ func Initialize(apper Apper, debug bool) (*App, error) { | |||
func Serve(app *App, r *mux.Router) { | |||
log.Info("Going to serve...") | |||
hostName = app.cfg.App.Host | |||
isSingleUser = app.cfg.App.SingleUser | |||
app.cfg.Server.Dev = debugging | |||
@@ -54,7 +54,8 @@ type ( | |||
PublicOwner bool `datastore:"public_owner" json:"-"` | |||
URL string `json:"url,omitempty"` | |||
db *datastore | |||
db *datastore | |||
hostName string | |||
} | |||
CollectionObj struct { | |||
Collection | |||
@@ -211,10 +212,10 @@ func (c *Collection) DisplayCanonicalURL() string { | |||
func (c *Collection) RedirectingCanonicalURL(isRedir bool) string { | |||
if isSingleUser { | |||
return hostName + "/" | |||
return c.hostName + "/" | |||
} | |||
return fmt.Sprintf("%s/%s/", hostName, c.Alias) | |||
return fmt.Sprintf("%s/%s/", c.hostName, c.Alias) | |||
} | |||
// PrevPageURL provides a full URL for the previous page of collection posts, | |||
@@ -300,11 +301,11 @@ func (c *Collection) AvatarURL() string { | |||
if !isAvatarChar(fl) { | |||
return "" | |||
} | |||
return hostName + "/img/avatars/" + fl + ".png" | |||
return c.hostName + "/img/avatars/" + fl + ".png" | |||
} | |||
func (c *Collection) FederatedAPIBase() string { | |||
return hostName + "/" | |||
return c.hostName + "/" | |||
} | |||
func (c *Collection) FederatedAccount() string { | |||
@@ -434,6 +435,8 @@ func fetchCollection(app *App, w http.ResponseWriter, r *http.Request) error { | |||
if err != nil { | |||
return err | |||
} | |||
c.hostName = app.cfg.App.Host | |||
// Redirect users who aren't requesting JSON | |||
reqJSON := IsJSON(r.Header.Get("Content-Type")) | |||
if !reqJSON { | |||
@@ -475,6 +478,7 @@ func fetchCollectionPosts(app *App, w http.ResponseWriter, r *http.Request) erro | |||
if err != nil { | |||
return err | |||
} | |||
c.hostName = app.cfg.App.Host | |||
// Check permissions | |||
userID, err := apiCheckCollectionPermissions(app, r, c) | |||
@@ -600,6 +604,7 @@ func processCollectionPermissions(app *App, cr *collectionReq, u *User, w http.R | |||
} | |||
return nil, err | |||
} | |||
c.hostName = app.cfg.App.Host | |||
// Update CollectionRequest to reflect owner status | |||
cr.isCollOwner = u != nil && u.ID == c.OwnerID | |||
@@ -34,6 +34,7 @@ func ViewFeed(app *App, w http.ResponseWriter, req *http.Request) error { | |||
if err != nil { | |||
return nil | |||
} | |||
c.hostName = app.cfg.App.Host | |||
if c.IsPrivate() || c.IsProtected() { | |||
return ErrCollectionNotFound | |||
@@ -996,6 +996,7 @@ func fetchPost(app *App, w http.ResponseWriter, r *http.Request) error { | |||
if err != nil { | |||
return err | |||
} | |||
coll.hostName = app.cfg.App.Host | |||
_, err = apiCheckCollectionPermissions(app, r, coll) | |||
if err != nil { | |||
return err | |||
@@ -1056,7 +1057,7 @@ func (p *Post) processPost() PublicPost { | |||
func (p *PublicPost) CanonicalURL() string { | |||
if p.Collection == nil || p.Collection.Alias == "" { | |||
return hostName + "/" + p.ID | |||
return p.Collection.hostName + "/" + p.ID | |||
} | |||
return p.Collection.CanonicalURL() + p.Slug.String | |||
} | |||
@@ -1087,7 +1088,7 @@ func (p *PublicPost) ActivityObject() *activitystreams.Object { | |||
if isSingleUser { | |||
tagBaseURL = p.Collection.CanonicalURL() + "tag:" | |||
} else { | |||
tagBaseURL = fmt.Sprintf("%s/%s/tag:", hostName, p.Collection.Alias) | |||
tagBaseURL = fmt.Sprintf("%s/%s/tag:", p.Collection.hostName, p.Collection.Alias) | |||
} | |||
for _, t := range p.Tags { | |||
o.Tag = append(o.Tag, activitystreams.Tag{ | |||
@@ -1244,6 +1245,7 @@ func viewCollectionPost(app *App, w http.ResponseWriter, r *http.Request) error | |||
} | |||
return err | |||
} | |||
c.hostName = app.cfg.App.Host | |||
// Check collection permissions | |||
if c.IsPrivate() && (u == nil || u.ID != c.OwnerID) { | |||
@@ -52,17 +52,17 @@ type readPublication struct { | |||
func initLocalTimeline(app *App) { | |||
app.timeline = &localTimeline{ | |||
postsPerPage: tlPostsPerPage, | |||
m: memo.New(app.db.FetchPublicPosts, 10*time.Minute), | |||
m: memo.New(app.FetchPublicPosts, 10*time.Minute), | |||
} | |||
} | |||
// satisfies memo.Func | |||
func (db *datastore) FetchPublicPosts() (interface{}, error) { | |||
func (app *App) FetchPublicPosts() (interface{}, error) { | |||
// Finds all public posts and posts in a public collection published during the owner's active subscription period and within the last 3 months | |||
rows, err := db.Query(`SELECT p.id, alias, c.title, p.slug, p.title, p.content, p.text_appearance, p.language, p.rtl, p.created, p.updated | |||
rows, err := app.db.Query(`SELECT p.id, alias, c.title, p.slug, p.title, p.content, p.text_appearance, p.language, p.rtl, p.created, p.updated | |||
FROM collections c | |||
LEFT JOIN posts p ON p.collection_id = c.id | |||
WHERE c.privacy = 1 AND (p.created >= ` + db.dateSub(3, "month") + ` AND p.created <= ` + db.now() + ` AND pinned_position IS NULL) | |||
WHERE c.privacy = 1 AND (p.created >= ` + app.db.dateSub(3, "month") + ` AND p.created <= ` + app.db.now() + ` AND pinned_position IS NULL) | |||
ORDER BY p.created DESC`) | |||
if err != nil { | |||
log.Error("Failed selecting from posts: %v", err) | |||
@@ -82,6 +82,8 @@ func (db *datastore) FetchPublicPosts() (interface{}, error) { | |||
log.Error("[READ] Unable to scan row, skipping: %v", err) | |||
continue | |||
} | |||
c.hostName = app.cfg.App.Host | |||
isCollectionPost := alias.Valid | |||
if isCollectionPost { | |||
c.Alias = alias.String | |||
@@ -244,6 +246,7 @@ func handlePostIDRedirect(app *App, w http.ResponseWriter, r *http.Request) erro | |||
if err != nil { | |||
return err | |||
} | |||
c.hostName = app.cfg.App.Host | |||
// Retrieve collection information and send user to canonical URL | |||
return impart.HTTPError{http.StatusFound, c.CanonicalURL() + p.Slug.String} | |||
@@ -57,6 +57,7 @@ func handleViewSitemap(app *App, w http.ResponseWriter, r *http.Request) error { | |||
if err != nil { | |||
return err | |||
} | |||
c.hostName = app.cfg.App.Host | |||
if !isSubdomain { | |||
pre += alias + "/" | |||
@@ -37,6 +37,7 @@ func (wfr wfResolver) FindUser(username string, host, requestHost string, r []we | |||
log.Error("Unable to get blog: %v", err) | |||
return nil, err | |||
} | |||
c.hostName = wfr.cfg.App.Host | |||
if wfr.cfg.App.SingleUser { | |||
// Ensure handle matches user-chosen one on single-user blogs | |||
if username != c.Alias { | |||