Add debug handler for fetching a remote actor
All checks were successful
/ docker (push) Successful in 3m59s
All checks were successful
/ docker (push) Successful in 3m59s
Will be used later to add to internal db
This commit is contained in:
parent
d4f2f66807
commit
f8b3a6ff06
12 changed files with 313 additions and 156 deletions
|
@ -27,6 +27,7 @@ func New(addr string) *Server {
|
|||
handler.HandleFunc("GET /delete", deleteUser)
|
||||
handler.HandleFunc("POST /post-as", postAs)
|
||||
handler.HandleFunc("GET /notes-for", notesFrom)
|
||||
handler.HandleFunc("GET /import", issueUserImport)
|
||||
web := http.Server{
|
||||
Addr: addr,
|
||||
Handler: webutils.ChainMiddlewares(
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
"git.mstar.dev/mstar/goutils/sliceutils"
|
||||
"github.com/rs/zerolog/hlog"
|
||||
|
||||
"git.mstar.dev/mstar/linstrom/activitypub"
|
||||
"git.mstar.dev/mstar/linstrom/shared"
|
||||
"git.mstar.dev/mstar/linstrom/storage-new/dbgen"
|
||||
"git.mstar.dev/mstar/linstrom/storage-new/models"
|
||||
|
@ -171,3 +172,19 @@ func deleteUser(w http.ResponseWriter, r *http.Request) {
|
|||
dbgen.User.Where(dbgen.User.ID.Eq(id)).Delete()
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
func issueUserImport(w http.ResponseWriter, r *http.Request) {
|
||||
target := r.FormValue("target")
|
||||
_, err := activitypub.ImportRemoteAccount(target)
|
||||
hlog.FromRequest(r).Info().Err(err).Msg("Err from import request")
|
||||
}
|
||||
|
||||
func kickoffFollow(w http.ResponseWriter, r *http.Request) {
|
||||
type Inbound struct {
|
||||
Id string
|
||||
Target string
|
||||
}
|
||||
var data Inbound
|
||||
dec := json.NewDecoder(r.Body)
|
||||
dec.Decode(&data)
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
"git.mstar.dev/mstar/goutils/sliceutils"
|
||||
"github.com/rs/zerolog/hlog"
|
||||
|
||||
"git.mstar.dev/mstar/linstrom/activitypub/shared/types"
|
||||
"git.mstar.dev/mstar/linstrom/config"
|
||||
"git.mstar.dev/mstar/linstrom/storage-new"
|
||||
"git.mstar.dev/mstar/linstrom/storage-new/dbgen"
|
||||
|
@ -19,52 +20,6 @@ import (
|
|||
webshared "git.mstar.dev/mstar/linstrom/web/shared"
|
||||
)
|
||||
|
||||
var baseLdContext = []any{
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"https://w3id.org/security/v1",
|
||||
map[string]any{
|
||||
"Key": "sec:Key",
|
||||
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
|
||||
"sensitive": "as:sensitive",
|
||||
"Hashtag": "as:Hashtag",
|
||||
"quoteUrl": "as:quoteUrl",
|
||||
"fedibird": "http://fedibird.com/ns#",
|
||||
"quoteUri": "fedibird:quoteUri",
|
||||
"toot": "http://joinmastodon.org/ns#",
|
||||
"Emoji": "toot:Emoji",
|
||||
"featured": "toot:featured",
|
||||
"discoverable": "toot:discoverable",
|
||||
"indexable": "toot:indexable",
|
||||
"schema": "http://schema.org#",
|
||||
"PropertyValue": "schema:PropertyValue",
|
||||
"value": "schema:value",
|
||||
"misskey": "https://misskey-hub.net/ns#",
|
||||
"_misskey_content": "misskey:_misskey_content",
|
||||
"_misskey_quote": "misskey:_misskey_quote",
|
||||
"_misskey_reaction": "misskey:_misskey_reaction",
|
||||
"_misskey_votes": "misskey:_misskey_votes",
|
||||
"_misskey_summary": "misskey:_misskey_summary",
|
||||
"_misskey_followedMessage": "misskey:_misskey_followedMessage",
|
||||
"_misskey_requireSigninToViewContents": "misskey:_misskey_requireSigninToViewContents",
|
||||
"_misskey_makeNotesFollowersOnlyBefore": "misskey:_misskey_makeNotesFollowersOnlyBefore",
|
||||
"_misskey_makeNotesHiddenBefore": "misskey:_misskey_makeNotesHiddenBefore",
|
||||
"_misskey_license": "misskey:_misskey_license",
|
||||
"freeText": map[string]string{
|
||||
"@id": "misskey:freeText",
|
||||
"@type": "schema:text",
|
||||
},
|
||||
"isCat": "misskey:isCat",
|
||||
"firefish": "https://joinfirefish.org/ns#",
|
||||
"speakAsCat": "firefish:speakAsCat",
|
||||
"sharkey": "https://joinsharkey.org/ns#",
|
||||
"hideOnlineStatus": "sharkey:hideOnlineStatus",
|
||||
"backgroundUrl": "sharkey:backgroundUrl",
|
||||
"listenbrainz": "sharkey:listenbrainz",
|
||||
"enableRss": "sharkey:enableRss",
|
||||
"vcard": "http://www.w3.org/2006/vcard/ns#",
|
||||
},
|
||||
}
|
||||
|
||||
func users(w http.ResponseWriter, r *http.Request) {
|
||||
type OutboundKey struct {
|
||||
Id string `json:"id"`
|
||||
|
@ -120,7 +75,7 @@ func users(w http.ResponseWriter, r *http.Request) {
|
|||
keyBytes = keyBytesToPem(user.PublicKeyRsa)
|
||||
}
|
||||
data := Outbound{
|
||||
Context: baseLdContext,
|
||||
Context: types.BaseLdContext,
|
||||
Id: apUrl,
|
||||
Type: "Person",
|
||||
PreferredUsername: user.Username,
|
||||
|
|
79
web/shared/client.go
Normal file
79
web/shared/client.go
Normal file
|
@ -0,0 +1,79 @@
|
|||
package webshared
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"git.mstar.dev/mstar/goutils/maputils"
|
||||
|
||||
"git.mstar.dev/mstar/linstrom/config"
|
||||
)
|
||||
|
||||
// No init needed, zero value is good
|
||||
|
||||
var RequestClient http.Client
|
||||
|
||||
const xRandomHeader = "X-Auth-Random"
|
||||
|
||||
// Sign a given outbound request for authorized fetch.
|
||||
// At the end, the Signature header will have the signature needed,
|
||||
// nothing else is modified.
|
||||
// If the request is POST, the postBody must contain the raw body of
|
||||
// the request and the Digest header will also be added
|
||||
func SignRequest(r *http.Request, keyId string, privateKeyBytes, postBody []byte) error {
|
||||
method := r.Method
|
||||
headers := r.Header
|
||||
var nowString string
|
||||
if dateString := headers.Get("Date"); dateString != "" {
|
||||
nowString = dateString
|
||||
} else {
|
||||
nowString = time.Now().Format("Mon, 02 Jan 2006 15:04:05 MST")
|
||||
headers.Set("Date", nowString)
|
||||
}
|
||||
var host string
|
||||
if hostString := headers.Get("Host"); hostString != "" {
|
||||
host = hostString
|
||||
} else {
|
||||
host = config.GlobalConfig.General.GetFullDomain()
|
||||
headers.Set("Date", host)
|
||||
}
|
||||
applyBodyHash(headers, postBody)
|
||||
mappedHeaders := maputils.MapSameKeys(headers, func(k string, v []string) string {
|
||||
if len(v) > 0 {
|
||||
return v[0]
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
})
|
||||
var signedString string
|
||||
if config.GlobalConfig.Experimental.UseEd25519Keys {
|
||||
tmp, err := CreateSignatureED(method, r.URL.RawPath, mappedHeaders, privateKeyBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
signedString = tmp
|
||||
} else {
|
||||
tmp, err := CreateSignatureRSA(method, r.URL.RawPath, mappedHeaders, privateKeyBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
signedString = tmp
|
||||
}
|
||||
signature := CreateSignatureHeaderContent(
|
||||
keyId,
|
||||
signedString,
|
||||
maputils.KeysFromMap(mappedHeaders)...,
|
||||
)
|
||||
headers.Set("Signature", signature)
|
||||
return nil
|
||||
}
|
||||
|
||||
func applyBodyHash(headers http.Header, body []byte) error {
|
||||
if body == nil {
|
||||
return nil
|
||||
}
|
||||
hash := sha256.Sum256(body)
|
||||
headers.Set("Digest", string(hash[:]))
|
||||
return nil
|
||||
}
|
|
@ -1,11 +1,15 @@
|
|||
package webshared
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"strings"
|
||||
|
||||
"git.mstar.dev/mstar/linstrom/shared"
|
||||
)
|
||||
|
||||
// Generate the signed string of the headers, method and target
|
||||
// and sign it using the given RSA key. Returns the base64 encoded
|
||||
// result
|
||||
func CreateSignatureRSA(
|
||||
method string,
|
||||
target string,
|
||||
|
@ -14,9 +18,12 @@ func CreateSignatureRSA(
|
|||
) (string, error) {
|
||||
message := genPreSignatureString(method, target, headers)
|
||||
signed, err := shared.Sign(message, privateKeyBytes, true)
|
||||
return string(signed), err
|
||||
return base64.StdEncoding.EncodeToString(signed), err
|
||||
}
|
||||
|
||||
// Generate the signed string of the headers, method and target
|
||||
// and sign it using the given ED25519 key. Returns the base64
|
||||
// encoded result
|
||||
func CreateSignatureED(
|
||||
method string,
|
||||
target string,
|
||||
|
@ -25,7 +32,10 @@ func CreateSignatureED(
|
|||
) (string, error) {
|
||||
message := genPreSignatureString(method, target, headers)
|
||||
signed, err := shared.Sign(message, privateKeyBytes, false)
|
||||
return string(signed), err
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return base64.StdEncoding.EncodeToString(signed), nil
|
||||
}
|
||||
|
||||
func genPreSignatureString(method, target string, headers map[string]string) string {
|
||||
|
@ -38,3 +48,24 @@ func genPreSignatureString(method, target string, headers map[string]string) str
|
|||
}
|
||||
return dataBuilder.String()
|
||||
}
|
||||
|
||||
// Generate the content of the "Signature" header based on
|
||||
// The user who's key was used, the hashed and base64 encoded
|
||||
// signed string, as returned by CreateSignatureED/RSA
|
||||
func CreateSignatureHeaderContent(userId string, hash string, headerNames ...string) string {
|
||||
builder := strings.Builder{}
|
||||
builder.WriteString("keyId=\"")
|
||||
builder.WriteString(userId)
|
||||
builder.WriteString("\",headers=\"")
|
||||
for i, header := range headerNames {
|
||||
builder.WriteString(header)
|
||||
if i+1 < len(headerNames) {
|
||||
builder.WriteRune(' ')
|
||||
}
|
||||
}
|
||||
builder.WriteString("\",signature=\"")
|
||||
builder.WriteString(hash)
|
||||
builder.WriteRune('"')
|
||||
|
||||
return builder.String()
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue