backend for xcvr appview
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

i believe add nonces to post my message

rachel-mp4 2f353fe0 4a6704f9

+76 -28
+2 -2
server/go.mod
··· 12 12 github.com/jackc/pgx/v5 v5.7.4 13 13 github.com/joho/godotenv v1.5.1 14 14 github.com/lestrrat-go/jwx/v2 v2.0.12 15 - github.com/rachel-mp4/lrcd v0.0.0-20250715235505-9d12a20f9fc6 16 - github.com/rachel-mp4/lrcproto v0.0.0-20250527205756-58da8216f98c 15 + github.com/rachel-mp4/lrcd v0.0.0-20250720165615-74d2b9211d12 16 + github.com/rachel-mp4/lrcproto v0.0.0-20250720164211-c6162669b709 17 17 github.com/rivo/uniseg v0.4.7 18 18 github.com/whyrusleeping/cbor-gen v0.3.1 19 19 golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028
+4 -4
server/go.sum
··· 161 161 github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= 162 162 github.com/rachel-mp4/atproto-oauth-golang v0.0.0-20250616212213-a55a5f62b82d h1:FQ8YKfXnKmyEbKnO/blj3qWGhYdw+l3DtQCqSboJRvA= 163 163 github.com/rachel-mp4/atproto-oauth-golang v0.0.0-20250616212213-a55a5f62b82d/go.mod h1:vVRo6BPEmWOZnYk9LtXLzBPzfkY63fUaBahA+o4h55Q= 164 - github.com/rachel-mp4/lrcd v0.0.0-20250715235505-9d12a20f9fc6 h1:9wrsf96eG7R4QZhNFMEmCctci/HHAbHODy6ErDENeuU= 165 - github.com/rachel-mp4/lrcd v0.0.0-20250715235505-9d12a20f9fc6/go.mod h1:Hn8xgJ2JwdiFJM5WjamVv4lRTwB6CdcqPjrCvJM7234= 166 - github.com/rachel-mp4/lrcproto v0.0.0-20250527205756-58da8216f98c h1:nOWeKeE7wph0IcwUyUBi0YBynUnAo4JW/J5DM88x4KM= 167 - github.com/rachel-mp4/lrcproto v0.0.0-20250527205756-58da8216f98c/go.mod h1:hQzO36tQELGbkmRnUtKeM6NMU34t79ZcTlhM+MO7pHw= 164 + github.com/rachel-mp4/lrcd v0.0.0-20250720165615-74d2b9211d12 h1:D2yNj5jhKTuH4hyTDDla17VbY/TEw+plYM3/2bDxSoU= 165 + github.com/rachel-mp4/lrcd v0.0.0-20250720165615-74d2b9211d12/go.mod h1:lU5b8bC7vP56MT57i6gUYoXxHSVLyrUYMnUo7JELwSc= 166 + github.com/rachel-mp4/lrcproto v0.0.0-20250720164211-c6162669b709 h1:P//gJE0zFv9Qvfn8dvp9ZrnG0FZh2MVcAX+uOP2flRw= 167 + github.com/rachel-mp4/lrcproto v0.0.0-20250720164211-c6162669b709/go.mod h1:hQzO36tQELGbkmRnUtKeM6NMU34t79ZcTlhM+MO7pHw= 168 168 github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= 169 169 github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= 170 170 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+24 -6
server/internal/db/lexicon.go
··· 194 194 return err 195 195 } 196 196 197 - func (s *Store) QuerySignet(channelUri string, id uint32, ctx context.Context) (string, error) { 198 - row := s.pool.QueryRow(ctx, `SELECT s.uri FROM signets s WHERE s.channel_uri = $1 AND s.message_id = $2`, channelUri, id) 199 - var signetUri string 200 - err := row.Scan(&signetUri) 197 + func (s *Store) QuerySignet(channelUri string, id uint32, ctx context.Context) (signetUri string, signetHandle string, err error) { 198 + row := s.pool.QueryRow(ctx, `SELECT (s.uri, s.author_handle) FROM signets s WHERE s.channel_uri = $1 AND s.message_id = $2`, channelUri, id) 199 + err = row.Scan(&signetUri, &signetHandle) 201 200 if err != nil { 202 - return "", errors.New("error scanning: " + err.Error()) 201 + err = errors.New("error scanning: " + err.Error()) 203 202 } 204 - return signetUri, nil 203 + return 204 + } 205 + 206 + func (s *Store) QuerySignetHandle(uri string, ctx context.Context) (string, error) { 207 + row := s.pool.QueryRow(ctx, `SELECT (s.author_handle) FROM signets s WHERE s.uri = $1`, uri) 208 + var handle string 209 + err := row.Scan(&handle) 210 + if err != nil { 211 + return "", errors.New("BOBOBOBOBOBOL " + err.Error()) 212 + } 213 + return handle, nil 214 + } 215 + 216 + func (s *Store) QuerySignetChannelIdNum(uri string, ctx context.Context) (channelUri string, messageID uint32, err error) { 217 + row := s.pool.QueryRow(ctx, `SELECT (s.channel_uri, message_id) FROM signets s WHERE s.uri = $1`, uri) 218 + err = row.Scan(&channelUri, &messageID) 219 + if err != nil { 220 + err = errors.New("BOBOBOBOBOBOL " + err.Error()) 221 + } 222 + return 205 223 } 206 224 207 225 func (s *Store) GetMsgChannelURI(signetURI string, ctx context.Context) (string, error) {
+44 -16
server/internal/handler/lrcHandlers.go
··· 5 5 "errors" 6 6 "fmt" 7 7 "github.com/bluesky-social/indigo/atproto/syntax" 8 + "github.com/rachel-mp4/lrcd" 8 9 "net/http" 9 10 "os" 11 + "slices" 10 12 "time" 11 13 "xcvr-backend/internal/atputils" 12 14 "xcvr-backend/internal/lex" ··· 128 130 129 131 } 130 132 131 - func (h *Handler) parseMessageRequest(r *http.Request) (*lex.MessageRecord, *time.Time, error) { 133 + func (h *Handler) parseMessageRequest(r *http.Request) (lmr *lex.MessageRecord, now *time.Time, handle *string, nonce []byte, err error) { 132 134 var mr types.PostMessageRequest 135 + lmr = &lex.MessageRecord{} 133 136 decoder := json.NewDecoder(r.Body) 134 - err := decoder.Decode(&mr) 137 + err = decoder.Decode(&mr) 135 138 if err != nil { 136 - return nil, nil, errors.New("couldn't decode: " + err.Error()) 139 + err = errors.New("couldn't decode: " + err.Error()) 140 + return 137 141 } 138 142 if mr.SignetURI == nil { 139 143 if mr.MessageID == nil || mr.ChannelURI == nil { 140 - return nil, nil, errors.New("must provide a way to determine signet") 144 + err = errors.New("must provide a way to determine signet") 145 + return 141 146 } 142 - signetUri, err := h.db.QuerySignet(*mr.ChannelURI, *mr.MessageID, r.Context()) 143 - if err != nil { 144 - return nil, nil, errors.New("i couldn't find the signet :c : " + err.Error()) 147 + signetUri, signetHandle, yorks := h.db.QuerySignet(*mr.ChannelURI, *mr.MessageID, r.Context()) 148 + if yorks != nil { 149 + err = errors.New("i couldn't find the signet :c : " + yorks.Error()) 150 + return 145 151 } 146 152 mr.SignetURI = &signetUri 153 + handle = &signetHandle 154 + } else { 155 + signetHandle, yorks := h.db.QuerySignetHandle(*mr.SignetURI, r.Context()) 156 + if yorks != nil { 157 + err = errors.New("yorks skooby 💀" + yorks.Error()) 158 + return 159 + } 160 + handle = &signetHandle 147 161 } 148 - var lmr lex.MessageRecord 149 162 lmr.SignetURI = *mr.SignetURI 150 163 lmr.Body = mr.Body 151 164 if mr.Nick != nil { 152 165 nick := *mr.Nick 153 166 if atputils.ValidateLength(nick, 16) { 154 - return nil, nil, errors.New("that nick is too long") 167 + err = errors.New("that nick is too long") 168 + return 155 169 } 156 170 } 157 171 lmr.Nick = mr.Nick ··· 159 173 if mr.Color != nil { 160 174 color := uint64(*mr.Color) 161 175 if color > 16777215 { 162 - return nil, nil, errors.New("that color is too big") 176 + err = errors.New("that color is too big") 177 + return 163 178 } 164 179 } 165 - now := syntax.DatetimeNow() 166 - lmr.PostedAt = now.String() 167 - nt := now.Time() 168 - return &lmr, &nt, nil 180 + nonce = mr.Nonce 181 + nowsyn := syntax.DatetimeNow() 182 + lmr.PostedAt = nowsyn.String() 183 + nt := nowsyn.Time() 184 + now = &nt 185 + return 169 186 } 170 187 171 188 func (h *Handler) postMyMessage(w http.ResponseWriter, r *http.Request) { 172 - lmr, now, err := h.parseMessageRequest(r) 189 + lmr, now, handle, nonce, err := h.parseMessageRequest(r) 173 190 if err != nil { 174 191 h.badRequest(w, errors.New("no good! "+err.Error())) 175 192 return 193 + } 194 + if handle == nil || *handle != atputils.GetMyHandle() { 195 + h.badRequest(w, errors.New("i only post my messages")) 196 + } 197 + curi, mid, err := h.db.QuerySignetChannelIdNum(lmr.SignetURI, r.Context()) 198 + if err != nil { 199 + h.serverError(w, err) 200 + } 201 + correctNonce := lrcd.GenerateNonce(mid, curi, os.Getenv("LRCD_SECRET")) 202 + if !slices.Equal(nonce, correctNonce) { 203 + h.badRequest(w, errors.New("i think user tried to post someone else's post")) 176 204 } 177 205 uri, cid, err := h.myClient.CreateXCVRMessage(lmr, r.Context()) 178 206 if err != nil { ··· 225 253 return 226 254 } 227 255 228 - lmr, now, err := h.parseMessageRequest(r) 256 + lmr, now, _, _, err := h.parseMessageRequest(r) 229 257 if err != nil { 230 258 h.badRequest(w, errors.New("couldn't parse message "+err.Error())) 231 259 return
+1
server/internal/model/channel.go
··· 137 137 lrcd.WithLogging(os.Stdout, true), 138 138 lrcd.WithInitialID(lastID), 139 139 lrcd.WithInitChannel(initChan), 140 + lrcd.WithServerURIAndSecret(uri, os.Getenv("LRCD_SECRET")), 140 141 ) 141 142 if err != nil { 142 143 return nil, errors.New("Error creating server")
+1
server/internal/types/lexicons.go
··· 122 122 Body string `json:"body"` 123 123 Nick *string `json:"nick,omitempty"` 124 124 Color *uint32 `json:"color,omitempty"` 125 + Nonce []byte `json:"nonce,omitempty"` 125 126 } 126 127 127 128 type MessageView struct {