Merge branch 'develop' into minor-fixes

This commit is contained in:
Matt Baer 2021-04-06 12:30:37 -04:00
commit 50c4e944a4
16 changed files with 146 additions and 61 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright © 2018-2020 A Bunch Tell LLC.
* Copyright © 2018-2021 A Bunch Tell LLC.
*
* This file is part of WriteFreely.
*
@ -21,6 +21,7 @@ import (
"net/http"
"net/http/httputil"
"net/url"
"path/filepath"
"strconv"
"time"
@ -41,6 +42,19 @@ const (
apCacheTime = time.Minute
)
var instanceColl *Collection
func initActivityPub(app *App) {
ur, _ := url.Parse(app.cfg.App.Host)
instanceColl = &Collection{
ID: 0,
Alias: ur.Host,
Title: ur.Host,
db: app.db,
hostName: app.cfg.App.Host,
}
}
type RemoteUser struct {
ID int64
ActorID string
@ -76,12 +90,17 @@ func handleFetchCollectionActivities(app *App, w http.ResponseWriter, r *http.Re
vars := mux.Vars(r)
alias := vars["alias"]
if alias == "" {
alias = filepath.Base(r.RequestURI)
}
// TODO: enforce visibility
// Get base Collection data
var c *Collection
var err error
if app.cfg.App.SingleUser {
if alias == r.Host {
c = instanceColl
} else if app.cfg.App.SingleUser {
c, err = app.db.GetCollectionByID(1)
} else {
c, err = app.db.GetCollection(alias)
@ -89,16 +108,19 @@ func handleFetchCollectionActivities(app *App, w http.ResponseWriter, r *http.Re
if err != nil {
return err
}
silenced, err := app.db.IsUserSilenced(c.OwnerID)
if err != nil {
log.Error("fetch collection activities: %v", err)
return ErrInternalGeneral
}
if silenced {
return ErrCollectionNotFound
}
c.hostName = app.cfg.App.Host
if !c.IsInstanceColl() {
silenced, err := app.db.IsUserSilenced(c.OwnerID)
if err != nil {
log.Error("fetch collection activities: %v", err)
return ErrInternalGeneral
}
if silenced {
return ErrCollectionNotFound
}
}
p := c.PersonObject()
setCacheControl(w, apCacheTime)
@ -546,6 +568,22 @@ func resolveIRI(hostName, url string) ([]byte, error) {
r.Header.Add("Accept", "application/activity+json")
r.Header.Set("User-Agent", ServerUserAgent(hostName))
p := instanceColl.PersonObject()
h := sha256.New()
h.Write([]byte{})
r.Header.Add("Digest", "SHA-256="+base64.StdEncoding.EncodeToString(h.Sum(nil)))
// Sign using the 'Signature' header
privKey, err := activitypub.DecodePrivateKey(p.GetPrivKey())
if err != nil {
return nil, err
}
signer := httpsig.NewSigner(p.PublicKey.ID, privKey, httpsig.RSASHA256, []string{"(request-target)", "date", "host", "digest"})
err = signer.SignSigHeader(r)
if err != nil {
log.Error("Can't sign: %v", err)
}
if debugging {
dump, err := httputil.DumpRequestOut(r, true)
if err != nil {

4
app.go
View File

@ -1,5 +1,5 @@
/*
* Copyright © 2018-2019 A Bunch Tell LLC.
* Copyright © 2018-2021 A Bunch Tell LLC.
*
* This file is part of WriteFreely.
*
@ -389,6 +389,8 @@ func Initialize(apper Apper, debug bool) (*App, error) {
return nil, fmt.Errorf("connect to DB: %s", err)
}
initActivityPub(apper.App())
// Handle local timeline, if enabled
if apper.App().cfg.App.LocalTimeline {
log.Info("Initializing local timeline...")

View File

@ -1,5 +1,5 @@
/*
* Copyright © 2018-2020 A Bunch Tell LLC.
* Copyright © 2018-2021 A Bunch Tell LLC.
*
* This file is part of WriteFreely.
*
@ -180,6 +180,11 @@ func (c *Collection) NewFormat() *CollectionFormat {
return cf
}
func (c *Collection) IsInstanceColl() bool {
ur, _ := url.Parse(c.hostName)
return c.Alias == ur.Host
}
func (c *Collection) IsUnlisted() bool {
return c.Visibility == 0
}

View File

@ -110,6 +110,10 @@ type (
AuthEndpoint string `ini:"auth_endpoint"`
Scope string `ini:"scope"`
AllowDisconnect bool `ini:"allow_disconnect"`
MapUserID string `ini:"map_user_id"`
MapUsername string `ini:"map_username"`
MapDisplayName string `ini:"map_display_name"`
MapEmail string `ini:"map_email"`
}
// AppCfg holds values that affect how the application functions

View File

@ -638,13 +638,17 @@ func (db *datastore) CreatePost(userID, collID int64, post *SubmittedPost) (*Pos
ownerCollID.Int64 = collID
ownerCollID.Valid = true
var slugVal string
if post.Title != nil && *post.Title != "" {
slugVal = getSlug(*post.Title, post.Language.String)
if slugVal == "" {
if post.Slug != nil && *post.Slug != "" {
slugVal = *post.Slug
} else {
if post.Title != nil && *post.Title != "" {
slugVal = getSlug(*post.Title, post.Language.String)
if slugVal == "" {
slugVal = getSlug(*post.Content, post.Language.String)
}
} else {
slugVal = getSlug(*post.Content, post.Language.String)
}
} else {
slugVal = getSlug(*post.Content, post.Language.String)
}
if slugVal == "" {
slugVal = friendlyID

View File

@ -12,7 +12,7 @@ networks:
services:
writefreely-web:
container_name: "writefreely-web"
image: "writefreely:latest"
image: "writeas/writefreely:latest"
volumes:
- "web-keys:/go/keys"

6
go.mod
View File

@ -4,7 +4,7 @@ require (
github.com/clbanning/mxj v1.8.4 // indirect
github.com/dustin/go-humanize v1.0.0
github.com/fatih/color v1.10.0
github.com/go-sql-driver/mysql v1.5.0
github.com/go-sql-driver/mysql v1.6.0
github.com/go-test/deep v1.0.1 // indirect
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e // indirect
github.com/gorilla/feeds v1.1.1
@ -12,14 +12,14 @@ require (
github.com/gorilla/schema v1.2.0
github.com/gorilla/sessions v1.2.0
github.com/guregu/null v3.5.0+incompatible
github.com/hashicorp/go-multierror v1.1.0
github.com/hashicorp/go-multierror v1.1.1
github.com/ikeikeikeike/go-sitemap-generator/v2 v2.0.2
github.com/jtolds/gls v4.2.1+incompatible // indirect
github.com/kylemcc/twitter-text-go v0.0.0-20180726194232-7f582f6736ec
github.com/lunixbochs/vtclean v1.0.0 // indirect
github.com/manifoldco/promptui v0.8.0
github.com/mattn/go-sqlite3 v1.14.6
github.com/microcosm-cc/bluemonday v1.0.4
github.com/microcosm-cc/bluemonday v1.0.5
github.com/mitchellh/go-wordwrap v1.0.1
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d
github.com/pkg/errors v0.8.1 // indirect

27
go.sum
View File

@ -1,6 +1,5 @@
code.as/core/socks v1.0.0 h1:SPQXNp4SbEwjOAP9VzUahLHak8SDqy5n+9cm9tpjZOs=
code.as/core/socks v1.0.0/go.mod h1:BAXBy5O9s2gmw6UxLqNJcVbWY7C/UPs+801CcSsfWOY=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
@ -32,12 +31,11 @@ github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg=
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/go-fed/httpsig v0.1.0 h1:6F2OxRVnNTN4OPN+Mc2jxs2WEay9/qiHT/jphlvAwIY=
github.com/go-fed/httpsig v0.1.0/go.mod h1:T56HUNYZUQ1AGUzhAYPugZfp36sKApVnGBgKlIY+aIE=
github.com/go-fed/httpsig v0.1.1-0.20200204213531-0ef28562fabe h1:U71giCx5NjRn4Lb71UuprPHqhjxGv3Jqonb9fgcaJH8=
github.com/go-fed/httpsig v0.1.1-0.20200204213531-0ef28562fabe/go.mod h1:T56HUNYZUQ1AGUzhAYPugZfp36sKApVnGBgKlIY+aIE=
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-test/deep v1.0.1 h1:UQhStjbkDClarlmv0am7OXXO4/GaPdCGiUiMTvi28sg=
github.com/go-test/deep v1.0.1/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/gologme/log v1.2.0 h1:Ya5Ip/KD6FX7uH0S31QO87nCCSucKtF44TLbTtO7V4c=
@ -48,7 +46,6 @@ github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
github.com/gorilla/feeds v1.1.1 h1:HwKXxqzcRNg9to+BbvJog4+f3s/xzvtZXICcQGutYfY=
github.com/gorilla/feeds v1.1.1/go.mod h1:Nk0jZrvPFZX1OBe5NPiddPw7CfwF6Q9eqzaBbaightA=
github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc=
github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
@ -62,10 +59,9 @@ github.com/guregu/null v3.5.0+incompatible h1:fSdvRTQtmBA4B4YDZXhLtxTIJZYuUxBFTT
github.com/guregu/null v3.5.0+incompatible/go.mod h1:ePGpQaN9cw0tj45IR5E5ehMvsFlLlQZAkkOXZurJ3NM=
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI=
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/ikeikeikeike/go-sitemap-generator/v2 v2.0.2 h1:wIdDEle9HEy7vBPjC6oKz6ejs3Ut+jmsYvuOoAW2pSM=
github.com/ikeikeikeike/go-sitemap-generator/v2 v2.0.2/go.mod h1:WtaVKD9TeruTED9ydiaOJU08qGoEPP/LyzTKiD3jEsw=
github.com/jtolds/gls v4.2.1+incompatible h1:fSuqC+Gmlu6l/ZYAoZzx2pyucC8Xza35fpRVWLVmUEE=
@ -79,26 +75,22 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kylemcc/twitter-text-go v0.0.0-20180726194232-7f582f6736ec h1:ZXWuspqypleMuJy4bzYEqlMhJnGAYpLrWe5p7W3CdvI=
github.com/kylemcc/twitter-text-go v0.0.0-20180726194232-7f582f6736ec/go.mod h1:voECJzdraJmolzPBgL9Z7ANwXf4oMXaTCsIkdiPpR/g=
github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a h1:weJVJJRzAJBFRlAiJQROKQs8oC9vOxvm4rZmBBk0ONw=
github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
github.com/lunixbochs/vtclean v1.0.0 h1:xu2sLAri4lGiovBDQKxl5mrXyESr3gUr5m5SM5+LVb8=
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
github.com/manifoldco/promptui v0.8.0 h1:R95mMF+McvXZQ7j1g8ucVZE1gLP3Sv6j9vlF9kyRqQo=
github.com/manifoldco/promptui v0.8.0/go.mod h1:n4zTdgP0vr0S3w7/O/g98U+e0gwLScEXGwov2nIKuGQ=
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg=
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/microcosm-cc/bluemonday v1.0.2 h1:5lPfLTTAvAbtS0VqT+94yOtFnGfUWYyx0+iToC3Os3s=
github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc=
github.com/microcosm-cc/bluemonday v1.0.4 h1:p0L+CTpo/PLFdkoPcJemLXG+fpMD7pYOoDEq1axMbGg=
github.com/microcosm-cc/bluemonday v1.0.4/go.mod h1:8iwZnFn2CDDNZ0r6UXhF4xawGvzaqzCRa1n3/lO3W2w=
github.com/microcosm-cc/bluemonday v1.0.5 h1:cF59UCKMmmUgqN1baLvqU/B1ZsMori+duLVTLpgiG3w=
github.com/microcosm-cc/bluemonday v1.0.5/go.mod h1:8iwZnFn2CDDNZ0r6UXhF4xawGvzaqzCRa1n3/lO3W2w=
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ=
@ -119,7 +111,6 @@ github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304 h1:Jpy1PX
github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c h1:Ho+uVpkel/udgjbwB5Lktg9BtvJSh2DT0Hi6LPSyI2w=
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
@ -140,7 +131,6 @@ github.com/writeas/go-writeas/v2 v2.0.2 h1:akvdMg89U5oBJiCkBwOXljVLTqP354uN6qnG2
github.com/writeas/go-writeas/v2 v2.0.2/go.mod h1:9sjczQJKmru925fLzg0usrU1R1tE4vBmQtGnItUMR0M=
github.com/writeas/httpsig v1.0.0 h1:peIAoIA3DmlP8IG8tMNZqI4YD1uEnWBmkcC9OFPjt3A=
github.com/writeas/httpsig v1.0.0/go.mod h1:7ClMGSrSVXJbmiLa17bZ1LrG1oibGZmUMlh3402flPY=
github.com/writeas/impart v1.1.0 h1:nPnoO211VscNkp/gnzir5UwCDEvdHThL5uELU60NFSE=
github.com/writeas/impart v1.1.0/go.mod h1:g0MpxdnTOHHrl+Ca/2oMXUHJ0PcRAEWtkCzYCJUXC9Y=
github.com/writeas/impart v1.1.1 h1:RyA9+CqbdbDuz53k+nXCWUY+NlEkdyw6+nWanxSBl5o=
github.com/writeas/impart v1.1.1/go.mod h1:g0MpxdnTOHHrl+Ca/2oMXUHJ0PcRAEWtkCzYCJUXC9Y=
@ -161,22 +151,18 @@ github.com/writeas/web-core v1.2.1-0.20200813161734-68a680d1b03c h1:/aPb8WKtC+Ga
github.com/writeas/web-core v1.2.1-0.20200813161734-68a680d1b03c/go.mod h1:vTYajviuNBAxjctPp2NUYdgjofywVkxUGpeaERF3SfI=
github.com/writefreely/go-nodeinfo v1.2.0 h1:La+YbTCvmpTwFhBSlebWDDL81N88Qf/SCAvRLR7F8ss=
github.com/writefreely/go-nodeinfo v1.2.0/go.mod h1:UTvE78KpcjYOlRHupZIiSEFcXHioTXuacCbHU+CAcPg=
golang.org/x/crypto v0.0.0-20180527072434-ab813273cd59 h1:hk3yo72LXLapY9EXVttc3Z1rLOxT9IuAPPX3GpY2+jo=
golang.org/x/crypto v0.0.0-20180527072434-ab813273cd59/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190131182504-b8fe1690c613/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3 h1:eH6Eip3UpmR+yM/qI9Ijluzb1bNv/cAU/n+6l8tRSis=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/sys v0.0.0-20180525142821-c11f84a56e43/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -187,7 +173,6 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/ini.v1 v1.55.0 h1:E8yzL5unfpW3M6fz/eB7Cb5MQAYSZ7GKo4Qth+N2sgQ=
gopkg.in/ini.v1 v1.55.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=

View File

@ -14,6 +14,7 @@ import (
"bytes"
"fmt"
"io"
"regexp"
"strings"
"github.com/prologic/go-gopher"
@ -28,6 +29,11 @@ func initGopher(apper Apper) {
gopher.ListenAndServe(fmt.Sprintf(":%d", apper.App().Config().Server.GopherPort), nil)
}
// Utility function to strip the URL from the hostname provided by app.cfg.App.Host
func stripHostProtocol(app *App) string {
return string(regexp.MustCompile("^.*://").ReplaceAll([]byte(app.cfg.App.Host), []byte("")))
}
func handleGopher(app *App, w gopher.ResponseWriter, r *gopher.Request) error {
parts := strings.Split(r.Selector, "/")
if app.cfg.App.SingleUser {
@ -51,6 +57,8 @@ func handleGopher(app *App, w gopher.ResponseWriter, r *gopher.Request) error {
for _, c := range *colls {
w.WriteItem(&gopher.Item{
Host: stripHostProtocol(app),
Port: app.cfg.Server.GopherPort,
Type: gopher.DIRECTORY,
Description: c.DisplayTitle(),
Selector: "/" + c.Alias + "/",
@ -99,6 +107,8 @@ func handleGopherCollection(app *App, w gopher.ResponseWriter, r *gopher.Request
for _, p := range *posts {
w.WriteItem(&gopher.Item{
Port: app.cfg.Server.GopherPort,
Host: stripHostProtocol(app),
Type: gopher.FILE,
Description: p.CreatedDate() + " - " + p.DisplayTitle(),
Selector: baseSel + p.Slug.String,

View File

@ -266,6 +266,10 @@ func configureGenericOauth(parentHandler *Handler, r *mux.Router, app *App) {
HttpClient: config.DefaultHTTPClient(),
CallbackLocation: callbackLocation,
Scope: config.OrDefaultString(app.Config().GenericOauth.Scope, "read_user"),
MapUserID: config.OrDefaultString(app.Config().GenericOauth.MapUserID, "user_id"),
MapUsername: config.OrDefaultString(app.Config().GenericOauth.MapUsername, "username"),
MapDisplayName: config.OrDefaultString(app.Config().GenericOauth.MapDisplayName, "-"),
MapEmail: config.OrDefaultString(app.Config().GenericOauth.MapEmail, "email"),
}
configureOauthRoutes(parentHandler, r, app, oauthClient, callbackProxy)
}

View File

@ -16,6 +16,10 @@ type genericOauthClient struct {
InspectLocation string
CallbackLocation string
Scope string
MapUserID string
MapUsername string
MapDisplayName string
MapEmail string
HttpClient HttpClient
}
@ -104,13 +108,19 @@ func (c genericOauthClient) inspectOauthAccessToken(ctx context.Context, accessT
return nil, errors.New("unable to inspect access token")
}
var inspectResponse InspectResponse
if err := limitedJsonUnmarshal(resp.Body, infoRequestMaxLen, &inspectResponse); err != nil {
// since we don't know what the JSON from the server will look like, we create a
// generic interface and then map manually to values set in the config
var genericInterface map[string]interface{}
if err := limitedJsonUnmarshal(resp.Body, infoRequestMaxLen, &genericInterface); err != nil {
return nil, err
}
if inspectResponse.Error != "" {
return nil, errors.New(inspectResponse.Error)
}
// map each relevant field in inspectResponse to the mapped field from the config
var inspectResponse InspectResponse
inspectResponse.UserID, _ = genericInterface[c.MapUserID].(string)
inspectResponse.Username, _ = genericInterface[c.MapUsername].(string)
inspectResponse.DisplayName, _ = genericInterface[c.MapDisplayName].(string)
inspectResponse.Email, _ = genericInterface[c.MapEmail].(string)
return &inspectResponse, nil
}

View File

@ -60,6 +60,14 @@ func (p *PublicPost) formatContent(cfg *config.Config, isOwner bool) {
}
func (p *Post) augmentContent(c *Collection) {
if p.PinnedPosition.Valid {
// Don't augment posts that are pinned
return
}
if strings.Index(p.Content, "<!--nosig-->") > -1 {
// Don't augment posts with the special "nosig" shortcode
return
}
// Add post signatures
if c.Signature != "" {
p.Content += "\n\n" + c.Signature

View File

@ -1,5 +1,5 @@
/*
* Copyright © 2018-2019 A Bunch Tell LLC.
* Copyright © 2018-2021 A Bunch Tell LLC.
*
* This file is part of WriteFreely.
*
@ -12,6 +12,7 @@ package writefreely
import (
"net/http"
"net/url"
"path/filepath"
"strings"
@ -125,9 +126,13 @@ func InitRoutes(apper Apper, r *mux.Router) *mux.Router {
write.HandleFunc("/api/markdown", handler.All(handleRenderMarkdown)).Methods("POST")
instanceURL, _ := url.Parse(apper.App().Config().App.Host)
host := instanceURL.Host
// Handle collections
write.HandleFunc("/api/collections", handler.All(newCollection)).Methods("POST")
apiColls := write.PathPrefix("/api/collections/").Subrouter()
apiColls.HandleFunc("/"+host, handler.AllReader(fetchCollection)).Methods("GET")
apiColls.HandleFunc("/{alias:[0-9a-zA-Z\\-]+}", handler.AllReader(fetchCollection)).Methods("GET")
apiColls.HandleFunc("/{alias:[0-9a-zA-Z\\-]+}", handler.All(existingCollection)).Methods("POST", "DELETE")
apiColls.HandleFunc("/{alias}/posts", handler.AllReader(fetchCollectionPosts)).Methods("GET")

View File

@ -68,7 +68,7 @@
var jss = [hlbaseUri + "highlight.min.js"];
// Check what we need to load
for (i=0; i < lb.length; i++) {
lang = lb[i].className.replace('language-','');
lang = lb[i].className.replace('language-','').toLowerCase();
// Support the aliases specified above
if (aliasmap[lang]) lang = aliasmap[lang];
lurl = hlbaseUri + "highlightjs/" + lang + ".min.js";

View File

@ -194,8 +194,13 @@
body: post.content,
title: post.title,
font: font,
lang: lang
};
{{ if or .Post.Slug .Post.Id }}
};
{{ else }}
lang: lang
};
{{ end }}
{{ if .Post.Slug }}
var url = "/api/collections/{{.EditCollection.Alias}}/posts/{{.Post.Id}}";
{{ else if .Post.Id }}

View File

@ -1,5 +1,5 @@
/*
* Copyright © 2018-2020 A Bunch Tell LLC.
* Copyright © 2018-2021 A Bunch Tell LLC.
*
* This file is part of WriteFreely.
*
@ -32,7 +32,9 @@ var wfUserNotFoundErr = impart.HTTPError{http.StatusNotFound, "User not found."}
func (wfr wfResolver) FindUser(username string, host, requestHost string, r []webfinger.Rel) (*webfinger.Resource, error) {
var c *Collection
var err error
if wfr.cfg.App.SingleUser {
if username == host {
c = instanceColl
} else if wfr.cfg.App.SingleUser {
c, err = wfr.db.GetCollectionByID(1)
} else {
c, err = wfr.db.GetCollection(username)
@ -41,15 +43,18 @@ func (wfr wfResolver) FindUser(username string, host, requestHost string, r []we
log.Error("Unable to get blog: %v", err)
return nil, err
}
silenced, err := wfr.db.IsUserSilenced(c.OwnerID)
if err != nil {
log.Error("webfinger find user: check is silenced: %v", err)
return nil, err
}
if silenced {
return nil, wfUserNotFoundErr
}
c.hostName = wfr.cfg.App.Host
if !c.IsInstanceColl() {
silenced, err := wfr.db.IsUserSilenced(c.OwnerID)
if err != nil {
log.Error("webfinger find user: check is silenced: %v", err)
return nil, err
}
if silenced {
return nil, wfUserNotFoundErr
}
}
if wfr.cfg.App.SingleUser {
// Ensure handle matches user-chosen one on single-user blogs
if username != c.Alias {