add a server actor

This commit is contained in:
Ted Unangst 2019-10-25 17:31:48 -04:00
parent bf81bb6fb1
commit 91a7a93cc3
6 changed files with 135 additions and 19 deletions

View File

@ -1208,30 +1208,30 @@ func honkworldwide(user *WhatAbout, honk *Honk) {
} }
} }
var oldjonkers = cache.New(cache.Options{Filler: func(name string) ([]byte, bool) { func junkuser(user *WhatAbout) []byte {
user, err := butwhatabout(name)
if err != nil {
return nil, false
}
about := markitzero(user.About) about := markitzero(user.About)
j := junk.New() j := junk.New()
j["@context"] = itiswhatitis j["@context"] = itiswhatitis
j["id"] = user.URL j["id"] = user.URL
j["type"] = "Person"
j["inbox"] = user.URL + "/inbox" j["inbox"] = user.URL + "/inbox"
j["outbox"] = user.URL + "/outbox" j["outbox"] = user.URL + "/outbox"
j["followers"] = user.URL + "/followers"
j["following"] = user.URL + "/following"
j["name"] = user.Display j["name"] = user.Display
j["preferredUsername"] = user.Name j["preferredUsername"] = user.Name
j["summary"] = about j["summary"] = about
if user.ID > 0 {
j["type"] = "Person"
j["url"] = user.URL j["url"] = user.URL
j["followers"] = user.URL + "/followers"
j["following"] = user.URL + "/following"
a := junk.New() a := junk.New()
a["type"] = "Image" a["type"] = "Image"
a["mediaType"] = "image/png" a["mediaType"] = "image/png"
a["url"] = fmt.Sprintf("https://%s/a?a=%s", serverName, url.QueryEscape(user.URL)) a["url"] = fmt.Sprintf("https://%s/a?a=%s", serverName, url.QueryEscape(user.URL))
j["icon"] = a j["icon"] = a
} else {
j["type"] = "Service"
}
k := junk.New() k := junk.New()
k["id"] = user.URL + "#key" k["id"] = user.URL + "#key"
k["owner"] = user.URL k["owner"] = user.URL
@ -1240,7 +1240,15 @@ var oldjonkers = cache.New(cache.Options{Filler: func(name string) ([]byte, bool
var buf bytes.Buffer var buf bytes.Buffer
j.Write(&buf) j.Write(&buf)
return buf.Bytes(), true return buf.Bytes()
}
var oldjonkers = cache.New(cache.Options{Filler: func(name string) ([]byte, bool) {
user, err := butwhatabout(name)
if err != nil {
return nil, false
}
return junkuser(user), true
}, Duration: 1 * time.Minute}) }, Duration: 1 * time.Minute})
func asjonker(name string) ([]byte, bool) { func asjonker(name string) ([]byte, bool) {

View File

@ -27,6 +27,7 @@ import (
"time" "time"
"humungus.tedunangst.com/r/webs/cache" "humungus.tedunangst.com/r/webs/cache"
"humungus.tedunangst.com/r/webs/httpsig"
"humungus.tedunangst.com/r/webs/login" "humungus.tedunangst.com/r/webs/login"
) )
@ -43,6 +44,27 @@ var someusers = cache.New(cache.Options{Filler: func(name string) (*WhatAbout, b
return user, true return user, true
}}) }})
var oldserveruser *WhatAbout
func getserveruser() *WhatAbout {
if oldserveruser == nil {
db := opendatabase()
row := db.QueryRow("select userid, username, displayname, about, pubkey, seckey from users where userid = ?", serverUID)
user := new(WhatAbout)
var seckey string
err := row.Scan(&user.ID, &user.Name, &user.Display, &user.About, &user.Key, &seckey)
if err == nil {
user.SecKey, _, err = httpsig.DecodeKey(seckey)
}
if err != nil {
log.Panicf("trouble getting server user: %s", err)
}
user.URL = fmt.Sprintf("https://%s/server", serverName)
oldserveruser = user
}
return oldserveruser
}
func butwhatabout(name string) (*WhatAbout, error) { func butwhatabout(name string) (*WhatAbout, error) {
var user *WhatAbout var user *WhatAbout
ok := someusers.Get(name, &user) ok := someusers.Get(name, &user)
@ -98,7 +120,7 @@ func getdubs(userid int64) []*Honker {
func allusers() []login.UserInfo { func allusers() []login.UserInfo {
var users []login.UserInfo var users []login.UserInfo
rows, _ := opendatabase().Query("select userid, username from users") rows, _ := opendatabase().Query("select userid, username from users where userid > 0")
defer rows.Close() defer rows.Close()
for rows.Next() { for rows.Next() {
var u login.UserInfo var u login.UserInfo
@ -695,7 +717,7 @@ func prepareStatements(db *sql.DB) {
stmtGetFileData = preparetodie(blobdb, "select media, content from filedata where xid = ?") stmtGetFileData = preparetodie(blobdb, "select media, content from filedata where xid = ?")
stmtFindXonk = preparetodie(db, "select honkid from honks where userid = ? and xid = ?") stmtFindXonk = preparetodie(db, "select honkid from honks where userid = ? and xid = ?")
stmtFindFile = preparetodie(db, "select fileid, xid from filemeta where url = ? and local = 1") stmtFindFile = preparetodie(db, "select fileid, xid from filemeta where url = ? and local = 1")
stmtWhatAbout = preparetodie(db, "select userid, username, displayname, about, pubkey, options from users where username = ?") stmtWhatAbout = preparetodie(db, "select userid, username, displayname, about, pubkey, options from users where username = ? and userid > 0")
stmtSaveDub = preparetodie(db, "insert into honkers (userid, name, xid, flavor) values (?, ?, ?, ?)") stmtSaveDub = preparetodie(db, "insert into honkers (userid, name, xid, flavor) values (?, ?, ?, ?)")
stmtAddDoover = preparetodie(db, "insert into doovers (dt, tries, username, rcpt, msg) values (?, ?, ?, ?, ?)") stmtAddDoover = preparetodie(db, "insert into doovers (dt, tries, username, rcpt, msg) values (?, ?, ?, ?, ?)")
stmtGetDoovers = preparetodie(db, "select dooverid, dt from doovers") stmtGetDoovers = preparetodie(db, "select dooverid, dt from doovers")

View File

@ -16,6 +16,7 @@
package main package main
import ( import (
"crypto/rsa"
"fmt" "fmt"
"html/template" "html/template"
"log" "log"
@ -33,8 +34,11 @@ type WhatAbout struct {
Key string Key string
URL string URL string
SkinnyCSS bool SkinnyCSS bool
SecKey *rsa.PrivateKey
} }
const serverUID int64 = -2
type Honk struct { type Honk struct {
ID int64 ID int64
UserID int64 UserID int64

View File

@ -24,7 +24,7 @@ import (
"time" "time"
) )
var myVersion = 27 var myVersion = 28
func doordie(db *sql.DB, s string, args ...interface{}) { func doordie(db *sql.DB, s string, args ...interface{}) {
_, err := db.Exec(s, args...) _, err := db.Exec(s, args...)
@ -303,6 +303,10 @@ func upgradedb() {
doordie(db, "update config set value = 27 where key = 'dbversion'") doordie(db, "update config set value = 27 where key = 'dbversion'")
fallthrough fallthrough
case 27: case 27:
createserveruser(db)
doordie(db, "update config set value = 28 where key = 'dbversion'")
fallthrough
case 28:
default: default:
log.Fatalf("can't upgrade unknown version %d", dbversion) log.Fatalf("can't upgrade unknown version %d", dbversion)

31
util.go
View File

@ -118,6 +118,11 @@ func initdb() {
log.Print(err) log.Print(err)
return return
} }
err = createserveruser(db)
if err != nil {
log.Print(err)
return
}
fmt.Printf("listen address: ") fmt.Printf("listen address: ")
addr, err := r.ReadString('\n') addr, err := r.ReadString('\n')
@ -297,7 +302,31 @@ func createuser(db *sql.DB, r *bufio.Reader) error {
if err != nil { if err != nil {
return err return err
} }
_, err = db.Exec("insert into users (username, displayname, about, hash, pubkey, seckey, options) values (?, ?, ?, ?, ?, ?, ?)", name, name, "what about me?", hash, pubkey, seckey, "") about := "what about me?"
_, err = db.Exec("insert into users (username, displayname, about, hash, pubkey, seckey, options) values (?, ?, ?, ?, ?, ?, ?)", name, name, about, hash, pubkey, seckey, "")
if err != nil {
return err
}
return nil
}
func createserveruser(db *sql.DB) error {
k, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return err
}
pubkey, err := httpsig.EncodeKey(&k.PublicKey)
if err != nil {
return err
}
seckey, err := httpsig.EncodeKey(k)
if err != nil {
return err
}
name := "server"
about := "server"
hash := "*"
_, err = db.Exec("insert into users (userid, username, displayname, about, hash, pubkey, seckey, options) values (?, ?, ?, ?, ?, ?, ?, ?)", serverUID, name, name, about, hash, pubkey, seckey, "")
if err != nil { if err != nil {
return err return err
} }

49
web.go
View File

@ -410,6 +410,51 @@ func inbox(w http.ResponseWriter, r *http.Request) {
} }
} }
func serverinbox(w http.ResponseWriter, r *http.Request) {
if stealthmode(serverUID, r) {
http.NotFound(w, r)
return
}
var buf bytes.Buffer
io.Copy(&buf, r.Body)
payload := buf.Bytes()
j, err := junk.Read(bytes.NewReader(payload))
if err != nil {
log.Printf("bad payload: %s", err)
io.WriteString(os.Stdout, "bad payload\n")
os.Stdout.Write(payload)
io.WriteString(os.Stdout, "\n")
return
}
if crappola(j) {
return
}
keyname, err := httpsig.VerifyRequest(r, payload, zaggy)
if err != nil {
log.Printf("inbox message failed signature for %s from %s", keyname, r.Header.Get("X-Forwarded-For"))
if keyname != "" {
log.Printf("bad signature from %s", keyname)
io.WriteString(os.Stdout, "bad payload\n")
os.Stdout.Write(payload)
io.WriteString(os.Stdout, "\n")
}
http.Error(w, "what did you call me?", http.StatusTeapot)
return
}
what, _ := j.GetString("type")
log.Printf("server got a %s", what)
}
func serveractor(w http.ResponseWriter, r *http.Request) {
if stealthmode(serverUID, r) {
http.NotFound(w, r)
return
}
user := getserveruser()
j := junkuser(user)
w.Write(j)
}
func ximport(w http.ResponseWriter, r *http.Request) { func ximport(w http.ResponseWriter, r *http.Request) {
u := login.GetUserInfo(r) u := login.GetUserInfo(r)
xid := strings.TrimSpace(r.FormValue("xid")) xid := strings.TrimSpace(r.FormValue("xid"))
@ -1735,6 +1780,7 @@ func serve() {
savedassetparams[s] = getassetparam(s) savedassetparams[s] = getassetparam(s)
} }
} }
getserveruser()
mux := mux.NewRouter() mux := mux.NewRouter()
mux.Use(login.Checker) mux.Use(login.Checker)
@ -1763,6 +1809,9 @@ func serve() {
getters.HandleFunc("/meme/{xid:[[:alnum:]_.-]+}", servememe) getters.HandleFunc("/meme/{xid:[[:alnum:]_.-]+}", servememe)
getters.HandleFunc("/.well-known/webfinger", fingerlicker) getters.HandleFunc("/.well-known/webfinger", fingerlicker)
getters.HandleFunc("/server", serveractor)
posters.HandleFunc("/server/inbox", serverinbox)
getters.HandleFunc("/style.css", servecss) getters.HandleFunc("/style.css", servecss)
getters.HandleFunc("/local.css", servecss) getters.HandleFunc("/local.css", servecss)
getters.HandleFunc("/honkpage.js", serveasset) getters.HandleFunc("/honkpage.js", serveasset)