forked from hailey.at/cocoon
An atproto PDS written in Go

Merge branch 'main' into email-auth-factor

Signed-off-by: Will Andrews <did:plc:dadhhalkfcq3gucaq25hjqon>

Changed files
+477 -330
cmd
cocoon
metrics
oauth
client
dpop
server
+7
cmd/cocoon/main.go
··· 9 "os" 10 "time" 11 12 "github.com/bluesky-social/indigo/atproto/atcrypto" 13 "github.com/bluesky-social/indigo/atproto/syntax" 14 "github.com/haileyok/cocoon/internal/helpers" ··· 154 Name: "fallback-proxy", 155 EnvVars: []string{"COCOON_FALLBACK_PROXY"}, 156 }, 157 }, 158 Commands: []*cli.Command{ 159 runServe, ··· 177 Flags: []cli.Flag{}, 178 Action: func(cmd *cli.Context) error { 179 180 s, err := server.New(&server.Args{ 181 Addr: cmd.String("addr"), 182 DbName: cmd.String("db-name"), 183 DbType: cmd.String("db-type"),
··· 9 "os" 10 "time" 11 12 + "github.com/bluesky-social/go-util/pkg/telemetry" 13 "github.com/bluesky-social/indigo/atproto/atcrypto" 14 "github.com/bluesky-social/indigo/atproto/syntax" 15 "github.com/haileyok/cocoon/internal/helpers" ··· 155 Name: "fallback-proxy", 156 EnvVars: []string{"COCOON_FALLBACK_PROXY"}, 157 }, 158 + telemetry.CLIFlagDebug, 159 + telemetry.CLIFlagMetricsListenAddress, 160 }, 161 Commands: []*cli.Command{ 162 runServe, ··· 180 Flags: []cli.Flag{}, 181 Action: func(cmd *cli.Context) error { 182 183 + logger := telemetry.StartLogger(cmd) 184 + telemetry.StartMetrics(cmd) 185 + 186 s, err := server.New(&server.Args{ 187 + Logger: logger, 188 Addr: cmd.String("addr"), 189 DbName: cmd.String("db-name"), 190 DbType: cmd.String("db-type"),
+14 -12
go.mod
··· 1 module github.com/haileyok/cocoon 2 3 - go 1.24.1 4 5 require ( 6 github.com/Azure/go-autorest/autorest/to v0.4.1 7 github.com/aws/aws-sdk-go v1.55.7 8 github.com/bluesky-social/indigo v0.0.0-20251009212240-20524de167fe 9 github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 10 github.com/domodwyer/mailyak/v3 v3.6.2 11 github.com/go-pkgz/expirable-cache/v3 v3.0.0 12 github.com/go-playground/validator v9.31.0+incompatible 13 github.com/golang-jwt/jwt/v4 v4.5.2 14 - github.com/google/uuid v1.4.0 15 github.com/gorilla/sessions v1.4.0 16 github.com/gorilla/websocket v1.5.1 17 github.com/hako/durafmt v0.0.0-20210608085754-5c1018a4e16b ··· 26 github.com/labstack/echo/v4 v4.13.3 27 github.com/lestrrat-go/jwx/v2 v2.0.12 28 github.com/multiformats/go-multihash v0.2.3 29 github.com/samber/slog-echo v1.16.1 30 github.com/urfave/cli/v2 v2.27.6 31 github.com/whyrusleeping/cbor-gen v0.2.1-0.20241030202151-b7a6831be65e 32 gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b 33 - golang.org/x/crypto v0.38.0 34 gorm.io/driver/postgres v1.5.7 35 gorm.io/driver/sqlite v1.5.7 36 gorm.io/gorm v1.25.12 ··· 57 github.com/gorilla/securecookie v1.1.2 // indirect 58 github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed // indirect 59 github.com/hashicorp/go-cleanhttp v0.5.2 // indirect 60 - github.com/hashicorp/go-retryablehttp v0.7.5 // indirect 61 github.com/hashicorp/golang-lru v1.0.2 // indirect 62 github.com/ipfs/bbloom v0.0.4 // indirect 63 github.com/ipfs/go-blockservice v0.5.2 // indirect ··· 103 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect 104 github.com/opentracing/opentracing-go v1.2.0 // indirect 105 github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f // indirect 106 - github.com/prometheus/client_golang v1.22.0 // indirect 107 github.com/prometheus/client_model v0.6.2 // indirect 108 - github.com/prometheus/common v0.63.0 // indirect 109 github.com/prometheus/procfs v0.16.1 // indirect 110 github.com/russross/blackfriday/v2 v2.1.0 // indirect 111 github.com/samber/lo v1.49.1 // indirect ··· 115 github.com/valyala/fasttemplate v1.2.2 // indirect 116 github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect 117 gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 // indirect 118 - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 // indirect 119 go.opentelemetry.io/otel v1.29.0 // indirect 120 go.opentelemetry.io/otel/metric v1.29.0 // indirect 121 go.opentelemetry.io/otel/trace v1.29.0 // indirect 122 go.uber.org/atomic v1.11.0 // indirect 123 go.uber.org/multierr v1.11.0 // indirect 124 go.uber.org/zap v1.26.0 // indirect 125 - golang.org/x/net v0.40.0 // indirect 126 - golang.org/x/sync v0.14.0 // indirect 127 - golang.org/x/sys v0.33.0 // indirect 128 - golang.org/x/text v0.25.0 // indirect 129 golang.org/x/time v0.11.0 // indirect 130 golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect 131 - google.golang.org/protobuf v1.36.6 // indirect 132 gopkg.in/go-playground/assert.v1 v1.2.1 // indirect 133 gopkg.in/inf.v0 v0.9.1 // indirect 134 lukechampine.com/blake3 v1.2.1 // indirect
··· 1 module github.com/haileyok/cocoon 2 3 + go 1.24.5 4 5 require ( 6 github.com/Azure/go-autorest/autorest/to v0.4.1 7 github.com/aws/aws-sdk-go v1.55.7 8 + github.com/bluesky-social/go-util v0.0.0-20251012040650-2ebbf57f5934 9 github.com/bluesky-social/indigo v0.0.0-20251009212240-20524de167fe 10 github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 11 github.com/domodwyer/mailyak/v3 v3.6.2 12 github.com/go-pkgz/expirable-cache/v3 v3.0.0 13 github.com/go-playground/validator v9.31.0+incompatible 14 github.com/golang-jwt/jwt/v4 v4.5.2 15 + github.com/google/uuid v1.6.0 16 github.com/gorilla/sessions v1.4.0 17 github.com/gorilla/websocket v1.5.1 18 github.com/hako/durafmt v0.0.0-20210608085754-5c1018a4e16b ··· 27 github.com/labstack/echo/v4 v4.13.3 28 github.com/lestrrat-go/jwx/v2 v2.0.12 29 github.com/multiformats/go-multihash v0.2.3 30 + github.com/prometheus/client_golang v1.23.2 31 github.com/samber/slog-echo v1.16.1 32 github.com/urfave/cli/v2 v2.27.6 33 github.com/whyrusleeping/cbor-gen v0.2.1-0.20241030202151-b7a6831be65e 34 gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b 35 + golang.org/x/crypto v0.41.0 36 gorm.io/driver/postgres v1.5.7 37 gorm.io/driver/sqlite v1.5.7 38 gorm.io/gorm v1.25.12 ··· 59 github.com/gorilla/securecookie v1.1.2 // indirect 60 github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed // indirect 61 github.com/hashicorp/go-cleanhttp v0.5.2 // indirect 62 + github.com/hashicorp/go-retryablehttp v0.7.7 // indirect 63 github.com/hashicorp/golang-lru v1.0.2 // indirect 64 github.com/ipfs/bbloom v0.0.4 // indirect 65 github.com/ipfs/go-blockservice v0.5.2 // indirect ··· 105 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect 106 github.com/opentracing/opentracing-go v1.2.0 // indirect 107 github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f // indirect 108 github.com/prometheus/client_model v0.6.2 // indirect 109 + github.com/prometheus/common v0.66.1 // indirect 110 github.com/prometheus/procfs v0.16.1 // indirect 111 github.com/russross/blackfriday/v2 v2.1.0 // indirect 112 github.com/samber/lo v1.49.1 // indirect ··· 116 github.com/valyala/fasttemplate v1.2.2 // indirect 117 github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect 118 gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 // indirect 119 + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect 120 go.opentelemetry.io/otel v1.29.0 // indirect 121 go.opentelemetry.io/otel/metric v1.29.0 // indirect 122 go.opentelemetry.io/otel/trace v1.29.0 // indirect 123 go.uber.org/atomic v1.11.0 // indirect 124 go.uber.org/multierr v1.11.0 // indirect 125 go.uber.org/zap v1.26.0 // indirect 126 + go.yaml.in/yaml/v2 v2.4.2 // indirect 127 + golang.org/x/net v0.43.0 // indirect 128 + golang.org/x/sync v0.16.0 // indirect 129 + golang.org/x/sys v0.35.0 // indirect 130 + golang.org/x/text v0.28.0 // indirect 131 golang.org/x/time v0.11.0 // indirect 132 golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect 133 + google.golang.org/protobuf v1.36.9 // indirect 134 gopkg.in/go-playground/assert.v1 v1.2.1 // indirect 135 gopkg.in/inf.v0 v0.9.1 // indirect 136 lukechampine.com/blake3 v1.2.1 // indirect
+42 -33
go.sum
··· 16 github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= 17 github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932 h1:mXoPYz/Ul5HYEDvkta6I8/rnYM5gSdSV2tJ6XbZuEtY= 18 github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k= 19 github.com/bluesky-social/indigo v0.0.0-20251009212240-20524de167fe h1:VBhaqE5ewQgXbY5SfSWFZC/AwHFo7cHxZKFYi2ce9Yo= 20 github.com/bluesky-social/indigo v0.0.0-20251009212240-20524de167fe/go.mod h1:RuQVrCGm42QNsgumKaR6se+XkFKfCPNwdCiTvqKRUck= 21 github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= ··· 39 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= 40 github.com/domodwyer/mailyak/v3 v3.6.2 h1:x3tGMsyFhTCaxp6ycgR0FE/bu5QiNp+hetUuCOBXMn8= 41 github.com/domodwyer/mailyak/v3 v3.6.2/go.mod h1:lOm/u9CyCVWHeaAmHIdF4RiKVxKUT/H5XX10lIKAL6c= 42 github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= 43 github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= 44 github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= ··· 77 github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= 78 github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= 79 github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 80 - github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= 81 - github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 82 github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= 83 github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= 84 github.com/gorilla/context v1.1.2 h1:WRkNAv2uoa03QNIc1A6u4O7DAGMUVoopZhkiXWA2V1o= ··· 95 github.com/hako/durafmt v0.0.0-20210608085754-5c1018a4e16b/go.mod h1:VzxiSdG6j1pi7rwGm/xYI5RbtpBgM8sARDXlvEvxlu0= 96 github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= 97 github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= 98 - github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI= 99 - github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= 100 - github.com/hashicorp/go-retryablehttp v0.7.5 h1:bJj+Pj19UZMIweq/iie+1u5YCdGrnxCT9yvm0e+Nd5M= 101 - github.com/hashicorp/go-retryablehttp v0.7.5/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= 102 github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= 103 github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= 104 github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= ··· 195 github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= 196 github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= 197 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 198 github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= 199 github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= 200 github.com/koron/go-ssdp v0.0.3 h1:JivLMY45N76b4p/vsWGOKewBQu6uf39y8l+AQ7sDKx8= ··· 206 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 207 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 208 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 209 github.com/labstack/echo-contrib v0.17.4 h1:g5mfsrJfJTKv+F5uNKCyrjLK7js+ZW6HTjg4FnDxxgk= 210 github.com/labstack/echo-contrib v0.17.4/go.mod h1:9O7ZPAHUeMGTOAfg80YqQduHzt0CzLak36PZRldYrZ0= 211 github.com/labstack/echo/v4 v4.13.3 h1:pwhpCPrTl5qry5HRdM5FwdXnhXSLSY+WE+YQSeCaafY= ··· 289 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 290 github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f h1:VXTQfuJj9vKR4TCkEuWIckKvdHFeJH/huIFJ9/cXOB0= 291 github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f/go.mod h1:/zvteZs/GwLtCgZ4BL6CBsk9IKIlexP43ObX9AxTqTw= 292 - github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= 293 - github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= 294 github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= 295 github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= 296 - github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k= 297 - github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18= 298 github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= 299 github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= 300 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= ··· 319 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 320 github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= 321 github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 322 - github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 323 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 324 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 325 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= ··· 327 github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 328 github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= 329 github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= 330 - github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= 331 - github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 332 github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= 333 github.com/urfave/cli/v2 v2.27.6 h1:VdRdS98FNhKZ8/Az8B7MTyGQmpIr36O1EHybx/LaZ4g= 334 github.com/urfave/cli/v2 v2.27.6/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= ··· 354 gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b/go.mod h1:/y/V339mxv2sZmYYR64O07VuCpdNZqCTwO8ZcouTMI8= 355 gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 h1:qwDnMxjkyLmAFgcfgTnfJrmYKWhHnci3GjDqcZp1M3Q= 356 gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02/go.mod h1:JTnUj0mpYiAsuZLmKjTx/ex3AtMowcCgnE7YNyCEP0I= 357 - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 h1:aFJWCqJMNjENlcleuuOkGAPH82y0yULBScfXcIEdS24= 358 - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1/go.mod h1:sEGXWArGqc3tVa+ekntsN65DmVbVeW+7lTKTjZF3/Fo= 359 go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw= 360 go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8= 361 go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc= ··· 367 go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= 368 go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= 369 go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= 370 - go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= 371 - go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= 372 go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= 373 go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= 374 go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= ··· 378 go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= 379 go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= 380 go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= 381 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 382 golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 383 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 384 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 385 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 386 golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= 387 - golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= 388 - golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= 389 golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= 390 golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= 391 golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= ··· 395 golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 396 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 397 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 398 - golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= 399 - golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= 400 golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 401 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 402 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= ··· 407 golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 408 golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= 409 golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= 410 - golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= 411 - golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= 412 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 413 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 414 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 415 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 416 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 417 golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 418 - golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= 419 - golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= 420 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 421 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 422 golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= ··· 432 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 433 golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 434 golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 435 - golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= 436 - golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 437 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 438 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 439 golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= ··· 445 golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 446 golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= 447 golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= 448 - golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= 449 - golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= 450 golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= 451 golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= 452 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= ··· 461 golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 462 golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 463 golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= 464 - golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= 465 - golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= 466 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 467 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 468 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 469 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 470 golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= 471 golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= 472 - google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= 473 - google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= 474 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 475 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 476 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
··· 16 github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= 17 github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932 h1:mXoPYz/Ul5HYEDvkta6I8/rnYM5gSdSV2tJ6XbZuEtY= 18 github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k= 19 + github.com/bluesky-social/go-util v0.0.0-20251012040650-2ebbf57f5934 h1:btHMur2kTRgWEnCHn6LaI3BE9YRgsqTpwpJ1UdB7VEk= 20 + github.com/bluesky-social/go-util v0.0.0-20251012040650-2ebbf57f5934/go.mod h1:LWamyZfbQGW7PaVc5jumFfjgrshJ5mXgDUnR6fK7+BI= 21 github.com/bluesky-social/indigo v0.0.0-20251009212240-20524de167fe h1:VBhaqE5ewQgXbY5SfSWFZC/AwHFo7cHxZKFYi2ce9Yo= 22 github.com/bluesky-social/indigo v0.0.0-20251009212240-20524de167fe/go.mod h1:RuQVrCGm42QNsgumKaR6se+XkFKfCPNwdCiTvqKRUck= 23 github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= ··· 41 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= 42 github.com/domodwyer/mailyak/v3 v3.6.2 h1:x3tGMsyFhTCaxp6ycgR0FE/bu5QiNp+hetUuCOBXMn8= 43 github.com/domodwyer/mailyak/v3 v3.6.2/go.mod h1:lOm/u9CyCVWHeaAmHIdF4RiKVxKUT/H5XX10lIKAL6c= 44 + github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= 45 + github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= 46 github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= 47 github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= 48 github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= ··· 81 github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= 82 github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= 83 github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 84 + github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= 85 + github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 86 github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= 87 github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= 88 github.com/gorilla/context v1.1.2 h1:WRkNAv2uoa03QNIc1A6u4O7DAGMUVoopZhkiXWA2V1o= ··· 99 github.com/hako/durafmt v0.0.0-20210608085754-5c1018a4e16b/go.mod h1:VzxiSdG6j1pi7rwGm/xYI5RbtpBgM8sARDXlvEvxlu0= 100 github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= 101 github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= 102 + github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= 103 + github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= 104 + github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= 105 + github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= 106 github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= 107 github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= 108 github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= ··· 199 github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= 200 github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= 201 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 202 + github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= 203 + github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= 204 github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= 205 github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= 206 github.com/koron/go-ssdp v0.0.3 h1:JivLMY45N76b4p/vsWGOKewBQu6uf39y8l+AQ7sDKx8= ··· 212 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 213 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 214 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 215 + github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= 216 + github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= 217 github.com/labstack/echo-contrib v0.17.4 h1:g5mfsrJfJTKv+F5uNKCyrjLK7js+ZW6HTjg4FnDxxgk= 218 github.com/labstack/echo-contrib v0.17.4/go.mod h1:9O7ZPAHUeMGTOAfg80YqQduHzt0CzLak36PZRldYrZ0= 219 github.com/labstack/echo/v4 v4.13.3 h1:pwhpCPrTl5qry5HRdM5FwdXnhXSLSY+WE+YQSeCaafY= ··· 297 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 298 github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f h1:VXTQfuJj9vKR4TCkEuWIckKvdHFeJH/huIFJ9/cXOB0= 299 github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f/go.mod h1:/zvteZs/GwLtCgZ4BL6CBsk9IKIlexP43ObX9AxTqTw= 300 + github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= 301 + github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= 302 github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= 303 github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= 304 + github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs= 305 + github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA= 306 github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= 307 github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= 308 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= ··· 327 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 328 github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= 329 github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 330 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 331 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 332 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= ··· 334 github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 335 github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= 336 github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= 337 + github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= 338 + github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= 339 github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= 340 github.com/urfave/cli/v2 v2.27.6 h1:VdRdS98FNhKZ8/Az8B7MTyGQmpIr36O1EHybx/LaZ4g= 341 github.com/urfave/cli/v2 v2.27.6/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= ··· 361 gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b/go.mod h1:/y/V339mxv2sZmYYR64O07VuCpdNZqCTwO8ZcouTMI8= 362 gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 h1:qwDnMxjkyLmAFgcfgTnfJrmYKWhHnci3GjDqcZp1M3Q= 363 gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02/go.mod h1:JTnUj0mpYiAsuZLmKjTx/ex3AtMowcCgnE7YNyCEP0I= 364 + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= 365 + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= 366 go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw= 367 go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8= 368 go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc= ··· 374 go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= 375 go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= 376 go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= 377 + go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= 378 + go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= 379 go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= 380 go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= 381 go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= ··· 385 go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= 386 go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= 387 go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= 388 + go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= 389 + go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= 390 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 391 golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 392 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 393 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 394 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 395 golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= 396 + golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= 397 + golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= 398 golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= 399 golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= 400 golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= ··· 404 golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 405 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 406 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 407 + golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg= 408 + golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ= 409 golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 410 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 411 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= ··· 416 golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 417 golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= 418 golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= 419 + golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= 420 + golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= 421 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 422 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 423 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 424 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 425 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 426 golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 427 + golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= 428 + golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= 429 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 430 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 431 golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= ··· 441 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 442 golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 443 golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 444 + golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= 445 + golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 446 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 447 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 448 golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= ··· 454 golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 455 golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= 456 golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= 457 + golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= 458 + golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= 459 golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= 460 golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= 461 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= ··· 470 golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 471 golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 472 golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= 473 + golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0= 474 + golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw= 475 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 476 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 477 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 478 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 479 golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= 480 golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= 481 + google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= 482 + google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= 483 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 484 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 485 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+30
metrics/metrics.go
···
··· 1 + package metrics 2 + 3 + import ( 4 + "github.com/prometheus/client_golang/prometheus" 5 + "github.com/prometheus/client_golang/prometheus/promauto" 6 + ) 7 + 8 + const ( 9 + NAMESPACE = "cocoon" 10 + ) 11 + 12 + var ( 13 + RelaysConnected = promauto.NewGaugeVec(prometheus.GaugeOpts{ 14 + Namespace: NAMESPACE, 15 + Name: "relays_connected", 16 + Help: "number of connected relays, by host", 17 + }, []string{"host"}) 18 + 19 + RelaySends = promauto.NewCounterVec(prometheus.CounterOpts{ 20 + Namespace: NAMESPACE, 21 + Name: "relay_sends", 22 + Help: "number of events sent to a relay, by host", 23 + }, []string{"host", "kind"}) 24 + 25 + RepoOperations = promauto.NewCounterVec(prometheus.CounterOpts{ 26 + Namespace: NAMESPACE, 27 + Name: "repo_operations", 28 + Help: "number of operations made against repos", 29 + }, []string{"kind"}) 30 + )
-1
oauth/client/manager.go
··· 72 } 73 74 jwks = k 75 - } else if metadata.JWKS != nil { 76 } else if metadata.JWKSURI != nil { 77 maybeJwks, err := cm.getClientJwks(ctx, clientId, *metadata.JWKSURI) 78 if err != nil {
··· 72 } 73 74 jwks = k 75 } else if metadata.JWKSURI != nil { 76 maybeJwks, err := cm.getClientJwks(ctx, clientId, *metadata.JWKSURI) 77 if err != nil {
+1 -1
oauth/dpop/jti_cache.go
··· 14 } 15 16 func newJTICache(size int) *jtiCache { 17 - cache := cache.NewCache[string, bool]().WithTTL(24 * time.Hour).WithLRU().WithTTL(constants.JTITtl) 18 return &jtiCache{ 19 cache: cache, 20 mu: sync.Mutex{},
··· 14 } 15 16 func newJTICache(size int) *jtiCache { 17 + cache := cache.NewCache[string, bool]().WithTTL(24 * time.Hour).WithLRU().WithTTL(constants.JTITtl).WithMaxKeys(size) 18 return &jtiCache{ 19 cache: cache, 20 mu: sync.Mutex{},
+2 -1
server/handle_account.go
··· 12 13 func (s *Server) handleAccount(e echo.Context) error { 14 ctx := e.Request().Context() 15 16 repo, sess, err := s.getSessionRepoOrErr(e) 17 if err != nil { ··· 22 23 var tokens []provider.OauthToken 24 if err := s.db.Raw(ctx, "SELECT * FROM oauth_tokens WHERE sub = ? AND created_at < ? ORDER BY created_at ASC", nil, repo.Repo.Did, oldestPossibleSession).Scan(&tokens).Error; err != nil { 25 - s.logger.Error("couldnt fetch oauth sessions for account", "did", repo.Repo.Did, "error", err) 26 sess.AddFlash("Unable to fetch sessions. See server logs for more details.", "error") 27 sess.Save(e.Request(), e.Response()) 28 return e.Render(200, "account.html", map[string]any{
··· 12 13 func (s *Server) handleAccount(e echo.Context) error { 14 ctx := e.Request().Context() 15 + logger := s.logger.With("name", "handleAuth") 16 17 repo, sess, err := s.getSessionRepoOrErr(e) 18 if err != nil { ··· 23 24 var tokens []provider.OauthToken 25 if err := s.db.Raw(ctx, "SELECT * FROM oauth_tokens WHERE sub = ? AND created_at < ? ORDER BY created_at ASC", nil, repo.Repo.Did, oldestPossibleSession).Scan(&tokens).Error; err != nil { 26 + logger.Error("couldnt fetch oauth sessions for account", "did", repo.Repo.Did, "error", err) 27 sess.AddFlash("Unable to fetch sessions. See server logs for more details.", "error") 28 sess.Save(e.Request(), e.Response()) 29 return e.Render(200, "account.html", map[string]any{
+3 -2
server/handle_account_revoke.go
··· 11 12 func (s *Server) handleAccountRevoke(e echo.Context) error { 13 ctx := e.Request().Context() 14 15 var req AccountRevokeInput 16 if err := e.Bind(&req); err != nil { 17 - s.logger.Error("could not bind account revoke request", "error", err) 18 return helpers.ServerError(e, nil) 19 } 20 ··· 24 } 25 26 if err := s.db.Exec(ctx, "DELETE FROM oauth_tokens WHERE sub = ? AND token = ?", nil, repo.Repo.Did, req.Token).Error; err != nil { 27 - s.logger.Error("couldnt delete oauth session for account", "did", repo.Repo.Did, "token", req.Token, "error", err) 28 sess.AddFlash("Unable to revoke session. See server logs for more details.", "error") 29 sess.Save(e.Request(), e.Response()) 30 return e.Redirect(303, "/account")
··· 11 12 func (s *Server) handleAccountRevoke(e echo.Context) error { 13 ctx := e.Request().Context() 14 + logger := s.logger.With("name", "handleAcocuntRevoke") 15 16 var req AccountRevokeInput 17 if err := e.Bind(&req); err != nil { 18 + logger.Error("could not bind account revoke request", "error", err) 19 return helpers.ServerError(e, nil) 20 } 21 ··· 25 } 26 27 if err := s.db.Exec(ctx, "DELETE FROM oauth_tokens WHERE sub = ? AND token = ?", nil, repo.Repo.Did, req.Token).Error; err != nil { 28 + logger.Error("couldnt delete oauth session for account", "did", repo.Repo.Did, "token", req.Token, "error", err) 29 sess.AddFlash("Unable to revoke session. See server logs for more details.", "error") 30 sess.Save(e.Request(), e.Response()) 31 return e.Redirect(303, "/account")
+2 -1
server/handle_account_signin.go
··· 67 68 func (s *Server) handleAccountSigninPost(e echo.Context) error { 69 ctx := e.Request().Context() 70 71 var req OauthSigninInput 72 if err := e.Bind(&req); err != nil { 73 - s.logger.Error("error binding sign in req", "error", err) 74 return helpers.ServerError(e, nil) 75 } 76
··· 67 68 func (s *Server) handleAccountSigninPost(e echo.Context) error { 69 ctx := e.Request().Context() 70 + logger := s.logger.With("name", "handleAccountSigninPost") 71 72 var req OauthSigninInput 73 if err := e.Bind(&req); err != nil { 74 + logger.Error("error binding sign in req", "error", err) 75 return helpers.ServerError(e, nil) 76 } 77
+3 -2
server/handle_identity_request_plc_operation.go
··· 11 12 func (s *Server) handleIdentityRequestPlcOperationSignature(e echo.Context) error { 13 ctx := e.Request().Context() 14 15 urepo := e.Get("repo").(*models.RepoActor) 16 ··· 18 eat := time.Now().Add(10 * time.Minute).UTC() 19 20 if err := s.db.Exec(ctx, "UPDATE repos SET plc_operation_code = ?, plc_operation_code_expires_at = ? WHERE did = ?", nil, code, eat, urepo.Repo.Did).Error; err != nil { 21 - s.logger.Error("error updating user", "error", err) 22 return helpers.ServerError(e, nil) 23 } 24 25 if err := s.sendPlcTokenReset(urepo.Email, urepo.Handle, code); err != nil { 26 - s.logger.Error("error sending mail", "error", err) 27 return helpers.ServerError(e, nil) 28 } 29
··· 11 12 func (s *Server) handleIdentityRequestPlcOperationSignature(e echo.Context) error { 13 ctx := e.Request().Context() 14 + logger := s.logger.With("name", "handleIdentityRequestPlcOperationSignature") 15 16 urepo := e.Get("repo").(*models.RepoActor) 17 ··· 19 eat := time.Now().Add(10 * time.Minute).UTC() 20 21 if err := s.db.Exec(ctx, "UPDATE repos SET plc_operation_code = ?, plc_operation_code_expires_at = ? WHERE did = ?", nil, code, eat, urepo.Repo.Did).Error; err != nil { 22 + logger.Error("error updating user", "error", err) 23 return helpers.ServerError(e, nil) 24 } 25 26 if err := s.sendPlcTokenReset(urepo.Email, urepo.Handle, code); err != nil { 27 + logger.Error("error sending mail", "error", err) 28 return helpers.ServerError(e, nil) 29 } 30
+7 -5
server/handle_identity_sign_plc_operation.go
··· 27 } 28 29 func (s *Server) handleSignPlcOperation(e echo.Context) error { 30 repo := e.Get("repo").(*models.RepoActor) 31 32 var req ComAtprotoSignPlcOperationRequest 33 if err := e.Bind(&req); err != nil { 34 - s.logger.Error("error binding", "error", err) 35 return helpers.ServerError(e, nil) 36 } 37 ··· 54 ctx := context.WithValue(e.Request().Context(), "skip-cache", true) 55 log, err := identity.FetchDidAuditLog(ctx, nil, repo.Repo.Did) 56 if err != nil { 57 - s.logger.Error("error fetching doc", "error", err) 58 return helpers.ServerError(e, nil) 59 } 60 ··· 83 84 k, err := atcrypto.ParsePrivateBytesK256(repo.SigningKey) 85 if err != nil { 86 - s.logger.Error("error parsing signing key", "error", err) 87 return helpers.ServerError(e, nil) 88 } 89 90 if err := s.plcClient.SignOp(k, &op); err != nil { 91 - s.logger.Error("error signing plc operation", "error", err) 92 return helpers.ServerError(e, nil) 93 } 94 95 if err := s.db.Exec(ctx, "UPDATE repos SET plc_operation_code = NULL, plc_operation_code_expires_at = NULL WHERE did = ?", nil, repo.Repo.Did).Error; err != nil { 96 - s.logger.Error("error updating repo", "error", err) 97 return helpers.ServerError(e, nil) 98 } 99
··· 27 } 28 29 func (s *Server) handleSignPlcOperation(e echo.Context) error { 30 + logger := s.logger.With("name", "handleSignPlcOperation") 31 + 32 repo := e.Get("repo").(*models.RepoActor) 33 34 var req ComAtprotoSignPlcOperationRequest 35 if err := e.Bind(&req); err != nil { 36 + logger.Error("error binding", "error", err) 37 return helpers.ServerError(e, nil) 38 } 39 ··· 56 ctx := context.WithValue(e.Request().Context(), "skip-cache", true) 57 log, err := identity.FetchDidAuditLog(ctx, nil, repo.Repo.Did) 58 if err != nil { 59 + logger.Error("error fetching doc", "error", err) 60 return helpers.ServerError(e, nil) 61 } 62 ··· 85 86 k, err := atcrypto.ParsePrivateBytesK256(repo.SigningKey) 87 if err != nil { 88 + logger.Error("error parsing signing key", "error", err) 89 return helpers.ServerError(e, nil) 90 } 91 92 if err := s.plcClient.SignOp(k, &op); err != nil { 93 + logger.Error("error signing plc operation", "error", err) 94 return helpers.ServerError(e, nil) 95 } 96 97 if err := s.db.Exec(ctx, "UPDATE repos SET plc_operation_code = NULL, plc_operation_code_expires_at = NULL WHERE did = ?", nil, repo.Repo.Did).Error; err != nil { 98 + logger.Error("error updating repo", "error", err) 99 return helpers.ServerError(e, nil) 100 } 101
+6 -4
server/handle_identity_submit_plc_operation.go
··· 21 } 22 23 func (s *Server) handleSubmitPlcOperation(e echo.Context) error { 24 repo := e.Get("repo").(*models.RepoActor) 25 26 var req ComAtprotoSubmitPlcOperationRequest 27 if err := e.Bind(&req); err != nil { 28 - s.logger.Error("error binding", "error", err) 29 return helpers.ServerError(e, nil) 30 } 31 ··· 40 41 k, err := atcrypto.ParsePrivateBytesK256(repo.SigningKey) 42 if err != nil { 43 - s.logger.Error("error parsing key", "error", err) 44 return helpers.ServerError(e, nil) 45 } 46 required, err := s.plcClient.CreateDidCredentials(k, "", repo.Actor.Handle) 47 if err != nil { 48 - s.logger.Error("error crating did credentials", "error", err) 49 return helpers.ServerError(e, nil) 50 } 51 ··· 72 } 73 74 if err := s.passport.BustDoc(context.TODO(), repo.Repo.Did); err != nil { 75 - s.logger.Warn("error busting did doc", "error", err) 76 } 77 78 s.evtman.AddEvent(context.TODO(), &events.XRPCStreamEvent{
··· 21 } 22 23 func (s *Server) handleSubmitPlcOperation(e echo.Context) error { 24 + logger := s.logger.With("name", "handleIdentitySubmitPlcOperation") 25 + 26 repo := e.Get("repo").(*models.RepoActor) 27 28 var req ComAtprotoSubmitPlcOperationRequest 29 if err := e.Bind(&req); err != nil { 30 + logger.Error("error binding", "error", err) 31 return helpers.ServerError(e, nil) 32 } 33 ··· 42 43 k, err := atcrypto.ParsePrivateBytesK256(repo.SigningKey) 44 if err != nil { 45 + logger.Error("error parsing key", "error", err) 46 return helpers.ServerError(e, nil) 47 } 48 required, err := s.plcClient.CreateDidCredentials(k, "", repo.Actor.Handle) 49 if err != nil { 50 + logger.Error("error crating did credentials", "error", err) 51 return helpers.ServerError(e, nil) 52 } 53 ··· 74 } 75 76 if err := s.passport.BustDoc(context.TODO(), repo.Repo.Did); err != nil { 77 + logger.Warn("error busting did doc", "error", err) 78 } 79 80 s.evtman.AddEvent(context.TODO(), &events.XRPCStreamEvent{
+7 -5
server/handle_identity_update_handle.go
··· 22 } 23 24 func (s *Server) handleIdentityUpdateHandle(e echo.Context) error { 25 repo := e.Get("repo").(*models.RepoActor) 26 27 var req ComAtprotoIdentityUpdateHandleRequest 28 if err := e.Bind(&req); err != nil { 29 - s.logger.Error("error binding", "error", err) 30 return helpers.ServerError(e, nil) 31 } 32 ··· 41 if strings.HasPrefix(repo.Repo.Did, "did:plc:") { 42 log, err := identity.FetchDidAuditLog(ctx, nil, repo.Repo.Did) 43 if err != nil { 44 - s.logger.Error("error fetching doc", "error", err) 45 return helpers.ServerError(e, nil) 46 } 47 ··· 68 69 k, err := atcrypto.ParsePrivateBytesK256(repo.SigningKey) 70 if err != nil { 71 - s.logger.Error("error parsing signing key", "error", err) 72 return helpers.ServerError(e, nil) 73 } 74 ··· 82 } 83 84 if err := s.passport.BustDoc(context.TODO(), repo.Repo.Did); err != nil { 85 - s.logger.Warn("error busting did doc", "error", err) 86 } 87 88 s.evtman.AddEvent(context.TODO(), &events.XRPCStreamEvent{ ··· 95 }) 96 97 if err := s.db.Exec(ctx, "UPDATE actors SET handle = ? WHERE did = ?", nil, req.Handle, repo.Repo.Did).Error; err != nil { 98 - s.logger.Error("error updating handle in db", "error", err) 99 return helpers.ServerError(e, nil) 100 } 101
··· 22 } 23 24 func (s *Server) handleIdentityUpdateHandle(e echo.Context) error { 25 + logger := s.logger.With("name", "handleIdentityUpdateHandle") 26 + 27 repo := e.Get("repo").(*models.RepoActor) 28 29 var req ComAtprotoIdentityUpdateHandleRequest 30 if err := e.Bind(&req); err != nil { 31 + logger.Error("error binding", "error", err) 32 return helpers.ServerError(e, nil) 33 } 34 ··· 43 if strings.HasPrefix(repo.Repo.Did, "did:plc:") { 44 log, err := identity.FetchDidAuditLog(ctx, nil, repo.Repo.Did) 45 if err != nil { 46 + logger.Error("error fetching doc", "error", err) 47 return helpers.ServerError(e, nil) 48 } 49 ··· 70 71 k, err := atcrypto.ParsePrivateBytesK256(repo.SigningKey) 72 if err != nil { 73 + logger.Error("error parsing signing key", "error", err) 74 return helpers.ServerError(e, nil) 75 } 76 ··· 84 } 85 86 if err := s.passport.BustDoc(context.TODO(), repo.Repo.Did); err != nil { 87 + logger.Warn("error busting did doc", "error", err) 88 } 89 90 s.evtman.AddEvent(context.TODO(), &events.XRPCStreamEvent{ ··· 97 }) 98 99 if err := s.db.Exec(ctx, "UPDATE actors SET handle = ? WHERE did = ?", nil, req.Handle, repo.Repo.Did).Error; err != nil { 100 + logger.Error("error updating handle in db", "error", err) 101 return helpers.ServerError(e, nil) 102 } 103
+11 -10
server/handle_import_repo.go
··· 19 20 func (s *Server) handleRepoImportRepo(e echo.Context) error { 21 ctx := e.Request().Context() 22 23 urepo := e.Get("repo").(*models.RepoActor) 24 25 b, err := io.ReadAll(e.Request().Body) 26 if err != nil { 27 - s.logger.Error("could not read bytes in import request", "error", err) 28 return helpers.ServerError(e, nil) 29 } 30 ··· 32 33 cs, err := car.NewCarReader(bytes.NewReader(b)) 34 if err != nil { 35 - s.logger.Error("could not read car in import request", "error", err) 36 return helpers.ServerError(e, nil) 37 } 38 39 orderedBlocks := []blocks.Block{} 40 currBlock, err := cs.Next() 41 if err != nil { 42 - s.logger.Error("could not get first block from car", "error", err) 43 return helpers.ServerError(e, nil) 44 } 45 currBlockCt := 1 46 47 for currBlock != nil { 48 - s.logger.Info("someone is importing their repo", "block", currBlockCt) 49 orderedBlocks = append(orderedBlocks, currBlock) 50 next, _ := cs.Next() 51 currBlock = next ··· 55 slices.Reverse(orderedBlocks) 56 57 if err := bs.PutMany(context.TODO(), orderedBlocks); err != nil { 58 - s.logger.Error("could not insert blocks", "error", err) 59 return helpers.ServerError(e, nil) 60 } 61 62 r, err := repo.OpenRepo(context.TODO(), bs, cs.Header.Roots[0]) 63 if err != nil { 64 - s.logger.Error("could not open repo", "error", err) 65 return helpers.ServerError(e, nil) 66 } 67 ··· 76 cidStr := cid.String() 77 b, err := bs.Get(context.TODO(), cid) 78 if err != nil { 79 - s.logger.Error("record bytes don't exist in blockstore", "error", err) 80 return helpers.ServerError(e, nil) 81 } 82 ··· 96 return nil 97 }); err != nil { 98 tx.Rollback() 99 - s.logger.Error("record bytes don't exist in blockstore", "error", err) 100 return helpers.ServerError(e, nil) 101 } 102 ··· 104 105 root, rev, err := r.Commit(context.TODO(), urepo.SignFor) 106 if err != nil { 107 - s.logger.Error("error committing", "error", err) 108 return helpers.ServerError(e, nil) 109 } 110 111 if err := s.UpdateRepo(context.TODO(), urepo.Repo.Did, root, rev); err != nil { 112 - s.logger.Error("error updating repo after commit", "error", err) 113 return helpers.ServerError(e, nil) 114 } 115
··· 19 20 func (s *Server) handleRepoImportRepo(e echo.Context) error { 21 ctx := e.Request().Context() 22 + logger := s.logger.With("name", "handleImportRepo") 23 24 urepo := e.Get("repo").(*models.RepoActor) 25 26 b, err := io.ReadAll(e.Request().Body) 27 if err != nil { 28 + logger.Error("could not read bytes in import request", "error", err) 29 return helpers.ServerError(e, nil) 30 } 31 ··· 33 34 cs, err := car.NewCarReader(bytes.NewReader(b)) 35 if err != nil { 36 + logger.Error("could not read car in import request", "error", err) 37 return helpers.ServerError(e, nil) 38 } 39 40 orderedBlocks := []blocks.Block{} 41 currBlock, err := cs.Next() 42 if err != nil { 43 + logger.Error("could not get first block from car", "error", err) 44 return helpers.ServerError(e, nil) 45 } 46 currBlockCt := 1 47 48 for currBlock != nil { 49 + logger.Info("someone is importing their repo", "block", currBlockCt) 50 orderedBlocks = append(orderedBlocks, currBlock) 51 next, _ := cs.Next() 52 currBlock = next ··· 56 slices.Reverse(orderedBlocks) 57 58 if err := bs.PutMany(context.TODO(), orderedBlocks); err != nil { 59 + logger.Error("could not insert blocks", "error", err) 60 return helpers.ServerError(e, nil) 61 } 62 63 r, err := repo.OpenRepo(context.TODO(), bs, cs.Header.Roots[0]) 64 if err != nil { 65 + logger.Error("could not open repo", "error", err) 66 return helpers.ServerError(e, nil) 67 } 68 ··· 77 cidStr := cid.String() 78 b, err := bs.Get(context.TODO(), cid) 79 if err != nil { 80 + logger.Error("record bytes don't exist in blockstore", "error", err) 81 return helpers.ServerError(e, nil) 82 } 83 ··· 97 return nil 98 }); err != nil { 99 tx.Rollback() 100 + logger.Error("record bytes don't exist in blockstore", "error", err) 101 return helpers.ServerError(e, nil) 102 } 103 ··· 105 106 root, rev, err := r.Commit(context.TODO(), urepo.SignFor) 107 if err != nil { 108 + logger.Error("error committing", "error", err) 109 return helpers.ServerError(e, nil) 110 } 111 112 if err := s.UpdateRepo(context.TODO(), urepo.Repo.Did, root, rev); err != nil { 113 + logger.Error("error updating repo after commit", "error", err) 114 return helpers.ServerError(e, nil) 115 } 116
+3 -2
server/handle_oauth_authorize.go
··· 75 76 func (s *Server) handleOauthAuthorizePost(e echo.Context) error { 77 ctx := e.Request().Context() 78 79 repo, _, err := s.getSessionRepoOrErr(e) 80 if err != nil { ··· 83 84 var req OauthAuthorizePostRequest 85 if err := e.Bind(&req); err != nil { 86 - s.logger.Error("error binding authorize post request", "error", err) 87 return helpers.InputError(e, nil) 88 } 89 ··· 118 code := oauth.GenerateCode() 119 120 if err := s.db.Exec(ctx, "UPDATE oauth_authorization_requests SET sub = ?, code = ?, accepted = ?, ip = ? WHERE request_id = ?", nil, repo.Repo.Did, code, true, e.RealIP(), reqId).Error; err != nil { 121 - s.logger.Error("error updating authorization request", "error", err) 122 return helpers.ServerError(e, nil) 123 } 124
··· 75 76 func (s *Server) handleOauthAuthorizePost(e echo.Context) error { 77 ctx := e.Request().Context() 78 + logger := s.logger.With("name", "handleOauthAuthorizePost") 79 80 repo, _, err := s.getSessionRepoOrErr(e) 81 if err != nil { ··· 84 85 var req OauthAuthorizePostRequest 86 if err := e.Bind(&req); err != nil { 87 + logger.Error("error binding authorize post request", "error", err) 88 return helpers.InputError(e, nil) 89 } 90 ··· 119 code := oauth.GenerateCode() 120 121 if err := s.db.Exec(ctx, "UPDATE oauth_authorization_requests SET sub = ?, code = ?, accepted = ?, ip = ? WHERE request_id = ?", nil, repo.Repo.Did, code, true, e.RealIP(), reqId).Error; err != nil { 122 + logger.Error("error updating authorization request", "error", err) 123 return helpers.ServerError(e, nil) 124 } 125
+8 -7
server/handle_oauth_par.go
··· 20 21 func (s *Server) handleOauthPar(e echo.Context) error { 22 ctx := e.Request().Context() 23 24 var parRequest provider.ParRequest 25 if err := e.Bind(&parRequest); err != nil { 26 - s.logger.Error("error binding for par request", "error", err) 27 return helpers.ServerError(e, nil) 28 } 29 30 if err := e.Validate(parRequest); err != nil { 31 - s.logger.Error("missing parameters for par request", "error", err) 32 return helpers.InputError(e, nil) 33 } 34 ··· 45 "error": "use_dpop_nonce", 46 }) 47 } 48 - s.logger.Error("error getting dpop proof", "error", err) 49 return helpers.InputError(e, nil) 50 } 51 ··· 55 AllowMissingDpopProof: true, 56 }) 57 if err != nil { 58 - s.logger.Error("error authenticating client", "client_id", parRequest.ClientID, "error", err) 59 return helpers.InputError(e, to.StringPtr(err.Error())) 60 } 61 ··· 66 } else { 67 if !client.Metadata.DpopBoundAccessTokens { 68 msg := "dpop bound access tokens are not enabled for this client" 69 - s.logger.Error(msg) 70 return helpers.InputError(e, &msg) 71 } 72 73 if dpopProof.JKT != *parRequest.DpopJkt { 74 msg := "supplied dpop jkt does not match header dpop jkt" 75 - s.logger.Error(msg) 76 return helpers.InputError(e, &msg) 77 } 78 } ··· 89 } 90 91 if err := s.db.Create(ctx, authRequest, nil).Error; err != nil { 92 - s.logger.Error("error creating auth request in db", "error", err) 93 return helpers.ServerError(e, nil) 94 } 95
··· 20 21 func (s *Server) handleOauthPar(e echo.Context) error { 22 ctx := e.Request().Context() 23 + logger := s.logger.With("name", "handleOauthPar") 24 25 var parRequest provider.ParRequest 26 if err := e.Bind(&parRequest); err != nil { 27 + logger.Error("error binding for par request", "error", err) 28 return helpers.ServerError(e, nil) 29 } 30 31 if err := e.Validate(parRequest); err != nil { 32 + logger.Error("missing parameters for par request", "error", err) 33 return helpers.InputError(e, nil) 34 } 35 ··· 46 "error": "use_dpop_nonce", 47 }) 48 } 49 + logger.Error("error getting dpop proof", "error", err) 50 return helpers.InputError(e, nil) 51 } 52 ··· 56 AllowMissingDpopProof: true, 57 }) 58 if err != nil { 59 + logger.Error("error authenticating client", "client_id", parRequest.ClientID, "error", err) 60 return helpers.InputError(e, to.StringPtr(err.Error())) 61 } 62 ··· 67 } else { 68 if !client.Metadata.DpopBoundAccessTokens { 69 msg := "dpop bound access tokens are not enabled for this client" 70 + logger.Error(msg) 71 return helpers.InputError(e, &msg) 72 } 73 74 if dpopProof.JKT != *parRequest.DpopJkt { 75 msg := "supplied dpop jkt does not match header dpop jkt" 76 + logger.Error(msg) 77 return helpers.InputError(e, &msg) 78 } 79 } ··· 90 } 91 92 if err := s.db.Create(ctx, authRequest, nil).Error; err != nil { 93 + logger.Error("error creating auth request in db", "error", err) 94 return helpers.ServerError(e, nil) 95 } 96
+9 -8
server/handle_oauth_token.go
··· 39 40 func (s *Server) handleOauthToken(e echo.Context) error { 41 ctx := e.Request().Context() 42 43 var req OauthTokenRequest 44 if err := e.Bind(&req); err != nil { 45 - s.logger.Error("error binding token request", "error", err) 46 return helpers.ServerError(e, nil) 47 } 48 ··· 58 "error": "use_dpop_nonce", 59 }) 60 } 61 - s.logger.Error("error getting dpop proof", "error", err) 62 return helpers.InputError(e, nil) 63 } 64 ··· 66 AllowMissingDpopProof: true, 67 }) 68 if err != nil { 69 - s.logger.Error("error authenticating client", "client_id", req.ClientID, "error", err) 70 return helpers.InputError(e, to.StringPtr(err.Error())) 71 } 72 ··· 87 var authReq provider.OauthAuthorizationRequest 88 // get the lil guy and delete him 89 if err := s.db.Raw(ctx, "DELETE FROM oauth_authorization_requests WHERE code = ? RETURNING *", nil, *req.Code).Scan(&authReq).Error; err != nil { 90 - s.logger.Error("error finding authorization request", "error", err) 91 return helpers.ServerError(e, nil) 92 } 93 ··· 112 case "S256": 113 inputChal, err := base64.RawURLEncoding.DecodeString(*authReq.Parameters.CodeChallenge) 114 if err != nil { 115 - s.logger.Error("error decoding code challenge", "error", err) 116 return helpers.ServerError(e, nil) 117 } 118 ··· 173 RefreshToken: refreshToken, 174 Ip: authReq.Ip, 175 }, nil).Error; err != nil { 176 - s.logger.Error("error creating token in db", "error", err) 177 return helpers.ServerError(e, nil) 178 } 179 ··· 202 203 var oauthToken provider.OauthToken 204 if err := s.db.Raw(ctx, "SELECT * FROM oauth_tokens WHERE refresh_token = ?", nil, req.RefreshToken).Scan(&oauthToken).Error; err != nil { 205 - s.logger.Error("error finding oauth token by refresh token", "error", err, "refresh_token", req.RefreshToken) 206 return helpers.ServerError(e, nil) 207 } 208 ··· 260 } 261 262 if err := s.db.Exec(ctx, "UPDATE oauth_tokens SET token = ?, refresh_token = ?, expires_at = ?, updated_at = ? WHERE refresh_token = ?", nil, accessString, nextRefreshToken, eat, now, *req.RefreshToken).Error; err != nil { 263 - s.logger.Error("error updating token", "error", err) 264 return helpers.ServerError(e, nil) 265 } 266
··· 39 40 func (s *Server) handleOauthToken(e echo.Context) error { 41 ctx := e.Request().Context() 42 + logger := s.logger.With("name", "handleOauthToken") 43 44 var req OauthTokenRequest 45 if err := e.Bind(&req); err != nil { 46 + logger.Error("error binding token request", "error", err) 47 return helpers.ServerError(e, nil) 48 } 49 ··· 59 "error": "use_dpop_nonce", 60 }) 61 } 62 + logger.Error("error getting dpop proof", "error", err) 63 return helpers.InputError(e, nil) 64 } 65 ··· 67 AllowMissingDpopProof: true, 68 }) 69 if err != nil { 70 + logger.Error("error authenticating client", "client_id", req.ClientID, "error", err) 71 return helpers.InputError(e, to.StringPtr(err.Error())) 72 } 73 ··· 88 var authReq provider.OauthAuthorizationRequest 89 // get the lil guy and delete him 90 if err := s.db.Raw(ctx, "DELETE FROM oauth_authorization_requests WHERE code = ? RETURNING *", nil, *req.Code).Scan(&authReq).Error; err != nil { 91 + logger.Error("error finding authorization request", "error", err) 92 return helpers.ServerError(e, nil) 93 } 94 ··· 113 case "S256": 114 inputChal, err := base64.RawURLEncoding.DecodeString(*authReq.Parameters.CodeChallenge) 115 if err != nil { 116 + logger.Error("error decoding code challenge", "error", err) 117 return helpers.ServerError(e, nil) 118 } 119 ··· 174 RefreshToken: refreshToken, 175 Ip: authReq.Ip, 176 }, nil).Error; err != nil { 177 + logger.Error("error creating token in db", "error", err) 178 return helpers.ServerError(e, nil) 179 } 180 ··· 203 204 var oauthToken provider.OauthToken 205 if err := s.db.Raw(ctx, "SELECT * FROM oauth_tokens WHERE refresh_token = ?", nil, req.RefreshToken).Scan(&oauthToken).Error; err != nil { 206 + logger.Error("error finding oauth token by refresh token", "error", err, "refresh_token", req.RefreshToken) 207 return helpers.ServerError(e, nil) 208 } 209 ··· 261 } 262 263 if err := s.db.Exec(ctx, "UPDATE oauth_tokens SET token = ?, refresh_token = ?, expires_at = ?, updated_at = ? WHERE refresh_token = ?", nil, accessString, nextRefreshToken, eat, now, *req.RefreshToken).Error; err != nil { 264 + logger.Error("error updating token", "error", err) 265 return helpers.ServerError(e, nil) 266 } 267
+6 -6
server/handle_proxy.go
··· 47 } 48 49 func (s *Server) handleProxy(e echo.Context) error { 50 - lgr := s.logger.With("handler", "handleProxy") 51 52 repo, isAuthed := e.Get("repo").(*models.RepoActor) 53 ··· 58 59 endpoint, svcDid, err := s.getAtprotoProxyEndpointFromRequest(e) 60 if err != nil { 61 - lgr.Error("could not get atproto proxy", "error", err) 62 return helpers.ServerError(e, nil) 63 } 64 ··· 90 } 91 hj, err := json.Marshal(header) 92 if err != nil { 93 - lgr.Error("error marshaling header", "error", err) 94 return helpers.ServerError(e, nil) 95 } 96 ··· 118 } 119 pj, err := json.Marshal(payload) 120 if err != nil { 121 - lgr.Error("error marashaling payload", "error", err) 122 return helpers.ServerError(e, nil) 123 } 124 ··· 129 130 sk, err := secp256k1secec.NewPrivateKey(repo.SigningKey) 131 if err != nil { 132 - lgr.Error("can't load private key", "error", err) 133 return err 134 } 135 136 R, S, _, err := sk.SignRaw(rand.Reader, hash[:]) 137 if err != nil { 138 - lgr.Error("error signing", "error", err) 139 } 140 141 rBytes := R.Bytes()
··· 47 } 48 49 func (s *Server) handleProxy(e echo.Context) error { 50 + logger := s.logger.With("handler", "handleProxy") 51 52 repo, isAuthed := e.Get("repo").(*models.RepoActor) 53 ··· 58 59 endpoint, svcDid, err := s.getAtprotoProxyEndpointFromRequest(e) 60 if err != nil { 61 + logger.Error("could not get atproto proxy", "error", err) 62 return helpers.ServerError(e, nil) 63 } 64 ··· 90 } 91 hj, err := json.Marshal(header) 92 if err != nil { 93 + logger.Error("error marshaling header", "error", err) 94 return helpers.ServerError(e, nil) 95 } 96 ··· 118 } 119 pj, err := json.Marshal(payload) 120 if err != nil { 121 + logger.Error("error marashaling payload", "error", err) 122 return helpers.ServerError(e, nil) 123 } 124 ··· 129 130 sk, err := secp256k1secec.NewPrivateKey(repo.SigningKey) 131 if err != nil { 132 + logger.Error("can't load private key", "error", err) 133 return err 134 } 135 136 R, S, _, err := sk.SignRaw(rand.Reader, hash[:]) 137 if err != nil { 138 + logger.Error("error signing", "error", err) 139 } 140 141 rBytes := R.Bytes()
+5 -4
server/handle_repo_apply_writes.go
··· 27 28 func (s *Server) handleApplyWrites(e echo.Context) error { 29 ctx := e.Request().Context() 30 31 var req ComAtprotoRepoApplyWritesInput 32 if err := e.Bind(&req); err != nil { 33 - s.logger.Error("error binding", "error", err) 34 return helpers.ServerError(e, nil) 35 } 36 37 if err := e.Validate(req); err != nil { 38 - s.logger.Error("error validating", "error", err) 39 return helpers.InputError(e, nil) 40 } 41 42 repo := e.Get("repo").(*models.RepoActor) 43 44 if repo.Repo.Did != req.Repo { 45 - s.logger.Warn("mismatched repo/auth") 46 return helpers.InputError(e, nil) 47 } 48 ··· 58 59 results, err := s.repoman.applyWrites(ctx, repo.Repo, ops, req.SwapCommit) 60 if err != nil { 61 - s.logger.Error("error applying writes", "error", err) 62 return helpers.ServerError(e, nil) 63 } 64
··· 27 28 func (s *Server) handleApplyWrites(e echo.Context) error { 29 ctx := e.Request().Context() 30 + logger := s.logger.With("name", "handleRepoApplyWrites") 31 32 var req ComAtprotoRepoApplyWritesInput 33 if err := e.Bind(&req); err != nil { 34 + logger.Error("error binding", "error", err) 35 return helpers.ServerError(e, nil) 36 } 37 38 if err := e.Validate(req); err != nil { 39 + logger.Error("error validating", "error", err) 40 return helpers.InputError(e, nil) 41 } 42 43 repo := e.Get("repo").(*models.RepoActor) 44 45 if repo.Repo.Did != req.Repo { 46 + logger.Warn("mismatched repo/auth") 47 return helpers.InputError(e, nil) 48 } 49 ··· 59 60 results, err := s.repoman.applyWrites(ctx, repo.Repo, ops, req.SwapCommit) 61 if err != nil { 62 + logger.Error("error applying writes", "error", err) 63 return helpers.ServerError(e, nil) 64 } 65
+5 -4
server/handle_repo_create_record.go
··· 18 19 func (s *Server) handleCreateRecord(e echo.Context) error { 20 ctx := e.Request().Context() 21 22 repo := e.Get("repo").(*models.RepoActor) 23 24 var req ComAtprotoRepoCreateRecordInput 25 if err := e.Bind(&req); err != nil { 26 - s.logger.Error("error binding", "error", err) 27 return helpers.ServerError(e, nil) 28 } 29 30 if err := e.Validate(req); err != nil { 31 - s.logger.Error("error validating", "error", err) 32 return helpers.InputError(e, nil) 33 } 34 35 if repo.Repo.Did != req.Repo { 36 - s.logger.Warn("mismatched repo/auth") 37 return helpers.InputError(e, nil) 38 } 39 ··· 53 }, 54 }, req.SwapCommit) 55 if err != nil { 56 - s.logger.Error("error applying writes", "error", err) 57 return helpers.ServerError(e, nil) 58 } 59
··· 18 19 func (s *Server) handleCreateRecord(e echo.Context) error { 20 ctx := e.Request().Context() 21 + logger := s.logger.With("name", "handleCreateRecord") 22 23 repo := e.Get("repo").(*models.RepoActor) 24 25 var req ComAtprotoRepoCreateRecordInput 26 if err := e.Bind(&req); err != nil { 27 + logger.Error("error binding", "error", err) 28 return helpers.ServerError(e, nil) 29 } 30 31 if err := e.Validate(req); err != nil { 32 + logger.Error("error validating", "error", err) 33 return helpers.InputError(e, nil) 34 } 35 36 if repo.Repo.Did != req.Repo { 37 + logger.Warn("mismatched repo/auth") 38 return helpers.InputError(e, nil) 39 } 40 ··· 54 }, 55 }, req.SwapCommit) 56 if err != nil { 57 + logger.Error("error applying writes", "error", err) 58 return helpers.ServerError(e, nil) 59 } 60
+5 -4
server/handle_repo_delete_record.go
··· 16 17 func (s *Server) handleDeleteRecord(e echo.Context) error { 18 ctx := e.Request().Context() 19 20 repo := e.Get("repo").(*models.RepoActor) 21 22 var req ComAtprotoRepoDeleteRecordInput 23 if err := e.Bind(&req); err != nil { 24 - s.logger.Error("error binding", "error", err) 25 return helpers.ServerError(e, nil) 26 } 27 28 if err := e.Validate(req); err != nil { 29 - s.logger.Error("error validating", "error", err) 30 return helpers.InputError(e, nil) 31 } 32 33 if repo.Repo.Did != req.Repo { 34 - s.logger.Warn("mismatched repo/auth") 35 return helpers.InputError(e, nil) 36 } 37 ··· 44 }, 45 }, req.SwapCommit) 46 if err != nil { 47 - s.logger.Error("error applying writes", "error", err) 48 return helpers.ServerError(e, nil) 49 } 50
··· 16 17 func (s *Server) handleDeleteRecord(e echo.Context) error { 18 ctx := e.Request().Context() 19 + logger := s.logger.With("name", "handleDeleteRecord") 20 21 repo := e.Get("repo").(*models.RepoActor) 22 23 var req ComAtprotoRepoDeleteRecordInput 24 if err := e.Bind(&req); err != nil { 25 + logger.Error("error binding", "error", err) 26 return helpers.ServerError(e, nil) 27 } 28 29 if err := e.Validate(req); err != nil { 30 + logger.Error("error validating", "error", err) 31 return helpers.InputError(e, nil) 32 } 33 34 if repo.Repo.Did != req.Repo { 35 + logger.Warn("mismatched repo/auth") 36 return helpers.InputError(e, nil) 37 } 38 ··· 45 }, 46 }, req.SwapCommit) 47 if err != nil { 48 + logger.Error("error applying writes", "error", err) 49 return helpers.ServerError(e, nil) 50 } 51
+4 -3
server/handle_repo_describe_repo.go
··· 21 22 func (s *Server) handleDescribeRepo(e echo.Context) error { 23 ctx := e.Request().Context() 24 25 did := e.QueryParam("repo") 26 repo, err := s.getRepoActorByDid(ctx, did) ··· 29 return helpers.InputError(e, to.StringPtr("RepoNotFound")) 30 } 31 32 - s.logger.Error("error looking up repo", "error", err) 33 return helpers.ServerError(e, nil) 34 } 35 ··· 37 38 diddoc, err := s.passport.FetchDoc(e.Request().Context(), repo.Repo.Did) 39 if err != nil { 40 - s.logger.Error("error fetching diddoc", "error", err) 41 return helpers.ServerError(e, nil) 42 } 43 ··· 67 68 var records []models.Record 69 if err := s.db.Raw(ctx, "SELECT DISTINCT(nsid) FROM records WHERE did = ?", nil, repo.Repo.Did).Scan(&records).Error; err != nil { 70 - s.logger.Error("error getting collections", "error", err) 71 return helpers.ServerError(e, nil) 72 } 73
··· 21 22 func (s *Server) handleDescribeRepo(e echo.Context) error { 23 ctx := e.Request().Context() 24 + logger := s.logger.With("name", "handleDescribeRepo") 25 26 did := e.QueryParam("repo") 27 repo, err := s.getRepoActorByDid(ctx, did) ··· 30 return helpers.InputError(e, to.StringPtr("RepoNotFound")) 31 } 32 33 + logger.Error("error looking up repo", "error", err) 34 return helpers.ServerError(e, nil) 35 } 36 ··· 38 39 diddoc, err := s.passport.FetchDoc(e.Request().Context(), repo.Repo.Did) 40 if err != nil { 41 + logger.Error("error fetching diddoc", "error", err) 42 return helpers.ServerError(e, nil) 43 } 44 ··· 68 69 var records []models.Record 70 if err := s.db.Raw(ctx, "SELECT DISTINCT(nsid) FROM records WHERE did = ?", nil, repo.Repo.Did).Scan(&records).Error; err != nil { 71 + logger.Error("error getting collections", "error", err) 72 return helpers.ServerError(e, nil) 73 } 74
+2 -1
server/handle_repo_list_missing_blobs.go
··· 23 24 func (s *Server) handleListMissingBlobs(e echo.Context) error { 25 ctx := e.Request().Context() 26 27 urepo := e.Get("repo").(*models.RepoActor) 28 ··· 38 39 var records []models.Record 40 if err := s.db.Raw(ctx, "SELECT * FROM records WHERE did = ?", nil, urepo.Repo.Did).Scan(&records).Error; err != nil { 41 - s.logger.Error("failed to get records for listMissingBlobs", "error", err) 42 return helpers.ServerError(e, nil) 43 } 44
··· 23 24 func (s *Server) handleListMissingBlobs(e echo.Context) error { 25 ctx := e.Request().Context() 26 + logger := s.logger.With("name", "handleListMissingBlos") 27 28 urepo := e.Get("repo").(*models.RepoActor) 29 ··· 39 40 var records []models.Record 41 if err := s.db.Raw(ctx, "SELECT * FROM records WHERE did = ?", nil, urepo.Repo.Did).Scan(&records).Error; err != nil { 42 + logger.Error("failed to get records for listMissingBlobs", "error", err) 43 return helpers.ServerError(e, nil) 44 } 45
+3 -2
server/handle_repo_list_records.go
··· 47 48 func (s *Server) handleListRecords(e echo.Context) error { 49 ctx := e.Request().Context() 50 51 var req ComAtprotoRepoListRecordsRequest 52 if err := e.Bind(&req); err != nil { 53 - s.logger.Error("could not bind list records request", "error", err) 54 return helpers.ServerError(e, nil) 55 } 56 ··· 96 97 var records []models.Record 98 if err := s.db.Raw(ctx, "SELECT * FROM records WHERE did = ? AND nsid = ? "+cursorquery+" ORDER BY created_at "+sort+" limit ?", nil, params...).Scan(&records).Error; err != nil { 99 - s.logger.Error("error getting records", "error", err) 100 return helpers.ServerError(e, nil) 101 } 102
··· 47 48 func (s *Server) handleListRecords(e echo.Context) error { 49 ctx := e.Request().Context() 50 + logger := s.logger.With("name", "handleListRecords") 51 52 var req ComAtprotoRepoListRecordsRequest 53 if err := e.Bind(&req); err != nil { 54 + logger.Error("could not bind list records request", "error", err) 55 return helpers.ServerError(e, nil) 56 } 57 ··· 97 98 var records []models.Record 99 if err := s.db.Raw(ctx, "SELECT * FROM records WHERE did = ? AND nsid = ? "+cursorquery+" ORDER BY created_at "+sort+" limit ?", nil, params...).Scan(&records).Error; err != nil { 100 + logger.Error("error getting records", "error", err) 101 return helpers.ServerError(e, nil) 102 } 103
+5 -4
server/handle_repo_put_record.go
··· 18 19 func (s *Server) handlePutRecord(e echo.Context) error { 20 ctx := e.Request().Context() 21 22 repo := e.Get("repo").(*models.RepoActor) 23 24 var req ComAtprotoRepoPutRecordInput 25 if err := e.Bind(&req); err != nil { 26 - s.logger.Error("error binding", "error", err) 27 return helpers.ServerError(e, nil) 28 } 29 30 if err := e.Validate(req); err != nil { 31 - s.logger.Error("error validating", "error", err) 32 return helpers.InputError(e, nil) 33 } 34 35 if repo.Repo.Did != req.Repo { 36 - s.logger.Warn("mismatched repo/auth") 37 return helpers.InputError(e, nil) 38 } 39 ··· 53 }, 54 }, req.SwapCommit) 55 if err != nil { 56 - s.logger.Error("error applying writes", "error", err) 57 return helpers.ServerError(e, nil) 58 } 59
··· 18 19 func (s *Server) handlePutRecord(e echo.Context) error { 20 ctx := e.Request().Context() 21 + logger := s.logger.With("name", "handlePutRecord") 22 23 repo := e.Get("repo").(*models.RepoActor) 24 25 var req ComAtprotoRepoPutRecordInput 26 if err := e.Bind(&req); err != nil { 27 + logger.Error("error binding", "error", err) 28 return helpers.ServerError(e, nil) 29 } 30 31 if err := e.Validate(req); err != nil { 32 + logger.Error("error validating", "error", err) 33 return helpers.InputError(e, nil) 34 } 35 36 if repo.Repo.Did != req.Repo { 37 + logger.Warn("mismatched repo/auth") 38 return helpers.InputError(e, nil) 39 } 40 ··· 54 }, 55 }, req.SwapCommit) 56 if err != nil { 57 + logger.Error("error applying writes", "error", err) 58 return helpers.ServerError(e, nil) 59 } 60
+8 -7
server/handle_repo_upload_blob.go
··· 33 34 func (s *Server) handleRepoUploadBlob(e echo.Context) error { 35 ctx := e.Request().Context() 36 37 urepo := e.Get("repo").(*models.RepoActor) 38 ··· 54 } 55 56 if err := s.db.Create(ctx, &blob, nil).Error; err != nil { 57 - s.logger.Error("error creating new blob in db", "error", err) 58 return helpers.ServerError(e, nil) 59 } 60 ··· 71 break 72 } 73 } else if err != nil && err != io.ErrUnexpectedEOF { 74 - s.logger.Error("error reading blob", "error", err) 75 return helpers.ServerError(e, nil) 76 } 77 ··· 87 } 88 89 if err := s.db.Create(ctx, &blobPart, nil).Error; err != nil { 90 - s.logger.Error("error adding blob part to db", "error", err) 91 return helpers.ServerError(e, nil) 92 } 93 } ··· 100 101 c, err := cid.NewPrefixV1(cid.Raw, multihash.SHA2_256).Sum(fulldata.Bytes()) 102 if err != nil { 103 - s.logger.Error("error creating cid prefix", "error", err) 104 return helpers.ServerError(e, nil) 105 } 106 ··· 117 118 sess, err := session.NewSession(config) 119 if err != nil { 120 - s.logger.Error("error creating aws session", "error", err) 121 return helpers.ServerError(e, nil) 122 } 123 ··· 128 Key: aws.String(fmt.Sprintf("blobs/%s/%s", urepo.Repo.Did, c.String())), 129 Body: bytes.NewReader(fulldata.Bytes()), 130 }); err != nil { 131 - s.logger.Error("error uploading blob to s3", "error", err) 132 return helpers.ServerError(e, nil) 133 } 134 } 135 136 if err := s.db.Exec(ctx, "UPDATE blobs SET cid = ? WHERE id = ?", nil, c.Bytes(), blob.ID).Error; err != nil { 137 // there should probably be somme handling here if this fails... 138 - s.logger.Error("error updating blob", "error", err) 139 return helpers.ServerError(e, nil) 140 } 141
··· 33 34 func (s *Server) handleRepoUploadBlob(e echo.Context) error { 35 ctx := e.Request().Context() 36 + logger := s.logger.With("name", "handleRepoUploadBlob") 37 38 urepo := e.Get("repo").(*models.RepoActor) 39 ··· 55 } 56 57 if err := s.db.Create(ctx, &blob, nil).Error; err != nil { 58 + logger.Error("error creating new blob in db", "error", err) 59 return helpers.ServerError(e, nil) 60 } 61 ··· 72 break 73 } 74 } else if err != nil && err != io.ErrUnexpectedEOF { 75 + logger.Error("error reading blob", "error", err) 76 return helpers.ServerError(e, nil) 77 } 78 ··· 88 } 89 90 if err := s.db.Create(ctx, &blobPart, nil).Error; err != nil { 91 + logger.Error("error adding blob part to db", "error", err) 92 return helpers.ServerError(e, nil) 93 } 94 } ··· 101 102 c, err := cid.NewPrefixV1(cid.Raw, multihash.SHA2_256).Sum(fulldata.Bytes()) 103 if err != nil { 104 + logger.Error("error creating cid prefix", "error", err) 105 return helpers.ServerError(e, nil) 106 } 107 ··· 118 119 sess, err := session.NewSession(config) 120 if err != nil { 121 + logger.Error("error creating aws session", "error", err) 122 return helpers.ServerError(e, nil) 123 } 124 ··· 129 Key: aws.String(fmt.Sprintf("blobs/%s/%s", urepo.Repo.Did, c.String())), 130 Body: bytes.NewReader(fulldata.Bytes()), 131 }); err != nil { 132 + logger.Error("error uploading blob to s3", "error", err) 133 return helpers.ServerError(e, nil) 134 } 135 } 136 137 if err := s.db.Exec(ctx, "UPDATE blobs SET cid = ? WHERE id = ?", nil, c.Bytes(), blob.ID).Error; err != nil { 138 // there should probably be somme handling here if this fails... 139 + logger.Error("error updating blob", "error", err) 140 return helpers.ServerError(e, nil) 141 } 142
+3 -2
server/handle_server_activate_account.go
··· 19 20 func (s *Server) handleServerActivateAccount(e echo.Context) error { 21 ctx := e.Request().Context() 22 23 var req ComAtprotoServerDeactivateAccountRequest 24 if err := e.Bind(&req); err != nil { 25 - s.logger.Error("error binding", "error", err) 26 return helpers.ServerError(e, nil) 27 } 28 29 urepo := e.Get("repo").(*models.RepoActor) 30 31 if err := s.db.Exec(ctx, "UPDATE repos SET deactivated = ? WHERE did = ?", nil, false, urepo.Repo.Did).Error; err != nil { 32 - s.logger.Error("error updating account status to deactivated", "error", err) 33 return helpers.ServerError(e, nil) 34 } 35
··· 19 20 func (s *Server) handleServerActivateAccount(e echo.Context) error { 21 ctx := e.Request().Context() 22 + logger := s.logger.With("name", "handleServerActivateAccount") 23 24 var req ComAtprotoServerDeactivateAccountRequest 25 if err := e.Bind(&req); err != nil { 26 + logger.Error("error binding", "error", err) 27 return helpers.ServerError(e, nil) 28 } 29 30 urepo := e.Get("repo").(*models.RepoActor) 31 32 if err := s.db.Exec(ctx, "UPDATE repos SET deactivated = ? WHERE did = ?", nil, false, urepo.Repo.Did).Error; err != nil { 33 + logger.Error("error updating account status to deactivated", "error", err) 34 return helpers.ServerError(e, nil) 35 } 36
+5 -4
server/handle_server_check_account_status.go
··· 21 22 func (s *Server) handleServerCheckAccountStatus(e echo.Context) error { 23 ctx := e.Request().Context() 24 25 urepo := e.Get("repo").(*models.RepoActor) 26 ··· 33 34 rootcid, err := cid.Cast(urepo.Root) 35 if err != nil { 36 - s.logger.Error("error casting cid", "error", err) 37 return helpers.ServerError(e, nil) 38 } 39 resp.RepoCommit = rootcid.String() ··· 44 45 var blockCtResp CountResp 46 if err := s.db.Raw(ctx, "SELECT COUNT(*) AS ct FROM blocks WHERE did = ?", nil, urepo.Repo.Did).Scan(&blockCtResp).Error; err != nil { 47 - s.logger.Error("error getting block count", "error", err) 48 return helpers.ServerError(e, nil) 49 } 50 resp.RepoBlocks = blockCtResp.Ct 51 52 var recCtResp CountResp 53 if err := s.db.Raw(ctx, "SELECT COUNT(*) AS ct FROM records WHERE did = ?", nil, urepo.Repo.Did).Scan(&recCtResp).Error; err != nil { 54 - s.logger.Error("error getting record count", "error", err) 55 return helpers.ServerError(e, nil) 56 } 57 resp.IndexedRecords = recCtResp.Ct 58 59 var blobCtResp CountResp 60 if err := s.db.Raw(ctx, "SELECT COUNT(*) AS ct FROM blobs WHERE did = ?", nil, urepo.Repo.Did).Scan(&blobCtResp).Error; err != nil { 61 - s.logger.Error("error getting record count", "error", err) 62 return helpers.ServerError(e, nil) 63 } 64 resp.ExpectedBlobs = blobCtResp.Ct
··· 21 22 func (s *Server) handleServerCheckAccountStatus(e echo.Context) error { 23 ctx := e.Request().Context() 24 + logger := s.logger.With("name", "handleServerCheckAccountStatus") 25 26 urepo := e.Get("repo").(*models.RepoActor) 27 ··· 34 35 rootcid, err := cid.Cast(urepo.Root) 36 if err != nil { 37 + logger.Error("error casting cid", "error", err) 38 return helpers.ServerError(e, nil) 39 } 40 resp.RepoCommit = rootcid.String() ··· 45 46 var blockCtResp CountResp 47 if err := s.db.Raw(ctx, "SELECT COUNT(*) AS ct FROM blocks WHERE did = ?", nil, urepo.Repo.Did).Scan(&blockCtResp).Error; err != nil { 48 + logger.Error("error getting block count", "error", err) 49 return helpers.ServerError(e, nil) 50 } 51 resp.RepoBlocks = blockCtResp.Ct 52 53 var recCtResp CountResp 54 if err := s.db.Raw(ctx, "SELECT COUNT(*) AS ct FROM records WHERE did = ?", nil, urepo.Repo.Did).Scan(&recCtResp).Error; err != nil { 55 + logger.Error("error getting record count", "error", err) 56 return helpers.ServerError(e, nil) 57 } 58 resp.IndexedRecords = recCtResp.Ct 59 60 var blobCtResp CountResp 61 if err := s.db.Raw(ctx, "SELECT COUNT(*) AS ct FROM blobs WHERE did = ?", nil, urepo.Repo.Did).Scan(&blobCtResp).Error; err != nil { 62 + logger.Error("error getting record count", "error", err) 63 return helpers.ServerError(e, nil) 64 } 65 resp.ExpectedBlobs = blobCtResp.Ct
+3 -2
server/handle_server_confirm_email.go
··· 16 17 func (s *Server) handleServerConfirmEmail(e echo.Context) error { 18 ctx := e.Request().Context() 19 20 urepo := e.Get("repo").(*models.RepoActor) 21 22 var req ComAtprotoServerConfirmEmailRequest 23 if err := e.Bind(&req); err != nil { 24 - s.logger.Error("error binding", "error", err) 25 return helpers.ServerError(e, nil) 26 } 27 ··· 44 now := time.Now().UTC() 45 46 if err := s.db.Exec(ctx, "UPDATE repos SET email_verification_code = NULL, email_verification_code_expires_at = NULL, email_confirmed_at = ? WHERE did = ?", nil, now, urepo.Repo.Did).Error; err != nil { 47 - s.logger.Error("error updating user", "error", err) 48 return helpers.ServerError(e, nil) 49 } 50
··· 16 17 func (s *Server) handleServerConfirmEmail(e echo.Context) error { 18 ctx := e.Request().Context() 19 + logger := s.logger.With("name", "handleServerConfirmEmail") 20 21 urepo := e.Get("repo").(*models.RepoActor) 22 23 var req ComAtprotoServerConfirmEmailRequest 24 if err := e.Bind(&req); err != nil { 25 + logger.Error("error binding", "error", err) 26 return helpers.ServerError(e, nil) 27 } 28 ··· 45 now := time.Now().UTC() 46 47 if err := s.db.Exec(ctx, "UPDATE repos SET email_verification_code = NULL, email_verification_code_expires_at = NULL, email_confirmed_at = ? WHERE did = ?", nil, now, urepo.Repo.Did).Error; err != nil { 48 + logger.Error("error updating user", "error", err) 49 return helpers.ServerError(e, nil) 50 } 51
+23 -22
server/handle_server_create_account.go
··· 37 38 func (s *Server) handleCreateAccount(e echo.Context) error { 39 ctx := e.Request().Context() 40 41 var request ComAtprotoServerCreateAccountRequest 42 43 if err := e.Bind(&request); err != nil { 44 - s.logger.Error("error receiving request", "endpoint", "com.atproto.server.createAccount", "error", err) 45 return helpers.ServerError(e, nil) 46 } 47 48 request.Handle = strings.ToLower(request.Handle) 49 50 if err := e.Validate(request); err != nil { 51 - s.logger.Error("error validating request", "endpoint", "com.atproto.server.createAccount", "error", err) 52 53 var verr ValidationError 54 if errors.As(err, &verr) { ··· 82 authDid, err := s.validateServiceAuth(e.Request().Context(), token, "com.atproto.server.createAccount") 83 84 if err != nil { 85 - s.logger.Warn("error validating authorization token", "endpoint", "com.atproto.server.createAccount", "error", err) 86 return helpers.UnauthorizedError(e, to.StringPtr("invalid authorization token")) 87 } 88 ··· 94 // see if the handle is already taken 95 actor, err := s.getActorByHandle(ctx, request.Handle) 96 if err != nil && err != gorm.ErrRecordNotFound { 97 - s.logger.Error("error looking up handle in db", "endpoint", "com.atproto.server.createAccount", "error", err) 98 return helpers.ServerError(e, nil) 99 } 100 if err == nil && actor.Did != signupDid { ··· 115 if err == gorm.ErrRecordNotFound { 116 return helpers.InputError(e, to.StringPtr("InvalidInviteCode")) 117 } 118 - s.logger.Error("error getting invite code from db", "error", err) 119 return helpers.ServerError(e, nil) 120 } 121 ··· 127 // see if the email is already taken 128 existingRepo, err := s.getRepoByEmail(ctx, request.Email) 129 if err != nil && err != gorm.ErrRecordNotFound { 130 - s.logger.Error("error looking up email in db", "endpoint", "com.atproto.server.createAccount", "error", err) 131 return helpers.ServerError(e, nil) 132 } 133 if err == nil && existingRepo.Did != signupDid { ··· 141 if signupDid != "" { 142 reservedKey, err := s.getReservedKey(ctx, signupDid) 143 if err != nil { 144 - s.logger.Error("error looking up reserved key", "error", err) 145 } 146 if reservedKey != nil { 147 k, err = atcrypto.ParsePrivateBytesK256(reservedKey.PrivateKey) 148 if err != nil { 149 - s.logger.Error("error parsing reserved key", "error", err) 150 k = nil 151 } else { 152 defer func() { 153 if delErr := s.deleteReservedKey(ctx, reservedKey.KeyDid, reservedKey.Did); delErr != nil { 154 - s.logger.Error("error deleting reserved key", "error", delErr) 155 } 156 }() 157 } ··· 161 if k == nil { 162 k, err = atcrypto.GeneratePrivateKeyK256() 163 if err != nil { 164 - s.logger.Error("error creating signing key", "endpoint", "com.atproto.server.createAccount", "error", err) 165 return helpers.ServerError(e, nil) 166 } 167 } ··· 169 if signupDid == "" { 170 did, op, err := s.plcClient.CreateDID(k, "", request.Handle) 171 if err != nil { 172 - s.logger.Error("error creating operation", "endpoint", "com.atproto.server.createAccount", "error", err) 173 return helpers.ServerError(e, nil) 174 } 175 176 if err := s.plcClient.SendOperation(e.Request().Context(), did, op); err != nil { 177 - s.logger.Error("error sending plc op", "endpoint", "com.atproto.server.createAccount", "error", err) 178 return helpers.ServerError(e, nil) 179 } 180 signupDid = did ··· 182 183 hashed, err := bcrypt.GenerateFromPassword([]byte(request.Password), 10) 184 if err != nil { 185 - s.logger.Error("error hashing password", "error", err) 186 return helpers.ServerError(e, nil) 187 } 188 ··· 202 } 203 204 if err := s.db.Create(ctx, &urepo, nil).Error; err != nil { 205 - s.logger.Error("error inserting new repo", "error", err) 206 return helpers.ServerError(e, nil) 207 } 208 209 if err := s.db.Create(ctx, &actor, nil).Error; err != nil { 210 - s.logger.Error("error inserting new actor", "error", err) 211 return helpers.ServerError(e, nil) 212 } 213 } else { 214 if err := s.db.Save(ctx, &actor, nil).Error; err != nil { 215 - s.logger.Error("error inserting new actor", "error", err) 216 return helpers.ServerError(e, nil) 217 } 218 } ··· 223 224 root, rev, err := r.Commit(context.TODO(), urepo.SignFor) 225 if err != nil { 226 - s.logger.Error("error committing", "error", err) 227 return helpers.ServerError(e, nil) 228 } 229 230 if err := s.UpdateRepo(context.TODO(), urepo.Did, root, rev); err != nil { 231 - s.logger.Error("error updating repo after commit", "error", err) 232 return helpers.ServerError(e, nil) 233 } 234 ··· 244 245 if s.config.RequireInvite { 246 if err := s.db.Raw(ctx, "UPDATE invite_codes SET remaining_use_count = remaining_use_count - 1 WHERE code = ?", nil, request.InviteCode).Scan(&ic).Error; err != nil { 247 - s.logger.Error("error decrementing use count", "error", err) 248 return helpers.ServerError(e, nil) 249 } 250 } 251 252 sess, err := s.createSession(ctx, &urepo) 253 if err != nil { 254 - s.logger.Error("error creating new session", "error", err) 255 return helpers.ServerError(e, nil) 256 } 257 258 go func() { 259 if err := s.sendEmailVerification(urepo.Email, actor.Handle, *urepo.EmailVerificationCode); err != nil { 260 - s.logger.Error("error sending email verification email", "error", err) 261 } 262 if err := s.sendWelcomeMail(urepo.Email, actor.Handle); err != nil { 263 - s.logger.Error("error sending welcome email", "error", err) 264 } 265 }() 266
··· 37 38 func (s *Server) handleCreateAccount(e echo.Context) error { 39 ctx := e.Request().Context() 40 + logger := s.logger.With("name", "handleServerCreateAccount") 41 42 var request ComAtprotoServerCreateAccountRequest 43 44 if err := e.Bind(&request); err != nil { 45 + logger.Error("error receiving request", "endpoint", "com.atproto.server.createAccount", "error", err) 46 return helpers.ServerError(e, nil) 47 } 48 49 request.Handle = strings.ToLower(request.Handle) 50 51 if err := e.Validate(request); err != nil { 52 + logger.Error("error validating request", "endpoint", "com.atproto.server.createAccount", "error", err) 53 54 var verr ValidationError 55 if errors.As(err, &verr) { ··· 83 authDid, err := s.validateServiceAuth(e.Request().Context(), token, "com.atproto.server.createAccount") 84 85 if err != nil { 86 + logger.Warn("error validating authorization token", "endpoint", "com.atproto.server.createAccount", "error", err) 87 return helpers.UnauthorizedError(e, to.StringPtr("invalid authorization token")) 88 } 89 ··· 95 // see if the handle is already taken 96 actor, err := s.getActorByHandle(ctx, request.Handle) 97 if err != nil && err != gorm.ErrRecordNotFound { 98 + logger.Error("error looking up handle in db", "endpoint", "com.atproto.server.createAccount", "error", err) 99 return helpers.ServerError(e, nil) 100 } 101 if err == nil && actor.Did != signupDid { ··· 116 if err == gorm.ErrRecordNotFound { 117 return helpers.InputError(e, to.StringPtr("InvalidInviteCode")) 118 } 119 + logger.Error("error getting invite code from db", "error", err) 120 return helpers.ServerError(e, nil) 121 } 122 ··· 128 // see if the email is already taken 129 existingRepo, err := s.getRepoByEmail(ctx, request.Email) 130 if err != nil && err != gorm.ErrRecordNotFound { 131 + logger.Error("error looking up email in db", "endpoint", "com.atproto.server.createAccount", "error", err) 132 return helpers.ServerError(e, nil) 133 } 134 if err == nil && existingRepo.Did != signupDid { ··· 142 if signupDid != "" { 143 reservedKey, err := s.getReservedKey(ctx, signupDid) 144 if err != nil { 145 + logger.Error("error looking up reserved key", "error", err) 146 } 147 if reservedKey != nil { 148 k, err = atcrypto.ParsePrivateBytesK256(reservedKey.PrivateKey) 149 if err != nil { 150 + logger.Error("error parsing reserved key", "error", err) 151 k = nil 152 } else { 153 defer func() { 154 if delErr := s.deleteReservedKey(ctx, reservedKey.KeyDid, reservedKey.Did); delErr != nil { 155 + logger.Error("error deleting reserved key", "error", delErr) 156 } 157 }() 158 } ··· 162 if k == nil { 163 k, err = atcrypto.GeneratePrivateKeyK256() 164 if err != nil { 165 + logger.Error("error creating signing key", "endpoint", "com.atproto.server.createAccount", "error", err) 166 return helpers.ServerError(e, nil) 167 } 168 } ··· 170 if signupDid == "" { 171 did, op, err := s.plcClient.CreateDID(k, "", request.Handle) 172 if err != nil { 173 + logger.Error("error creating operation", "endpoint", "com.atproto.server.createAccount", "error", err) 174 return helpers.ServerError(e, nil) 175 } 176 177 if err := s.plcClient.SendOperation(e.Request().Context(), did, op); err != nil { 178 + logger.Error("error sending plc op", "endpoint", "com.atproto.server.createAccount", "error", err) 179 return helpers.ServerError(e, nil) 180 } 181 signupDid = did ··· 183 184 hashed, err := bcrypt.GenerateFromPassword([]byte(request.Password), 10) 185 if err != nil { 186 + logger.Error("error hashing password", "error", err) 187 return helpers.ServerError(e, nil) 188 } 189 ··· 203 } 204 205 if err := s.db.Create(ctx, &urepo, nil).Error; err != nil { 206 + logger.Error("error inserting new repo", "error", err) 207 return helpers.ServerError(e, nil) 208 } 209 210 if err := s.db.Create(ctx, &actor, nil).Error; err != nil { 211 + logger.Error("error inserting new actor", "error", err) 212 return helpers.ServerError(e, nil) 213 } 214 } else { 215 if err := s.db.Save(ctx, &actor, nil).Error; err != nil { 216 + logger.Error("error inserting new actor", "error", err) 217 return helpers.ServerError(e, nil) 218 } 219 } ··· 224 225 root, rev, err := r.Commit(context.TODO(), urepo.SignFor) 226 if err != nil { 227 + logger.Error("error committing", "error", err) 228 return helpers.ServerError(e, nil) 229 } 230 231 if err := s.UpdateRepo(context.TODO(), urepo.Did, root, rev); err != nil { 232 + logger.Error("error updating repo after commit", "error", err) 233 return helpers.ServerError(e, nil) 234 } 235 ··· 245 246 if s.config.RequireInvite { 247 if err := s.db.Raw(ctx, "UPDATE invite_codes SET remaining_use_count = remaining_use_count - 1 WHERE code = ?", nil, request.InviteCode).Scan(&ic).Error; err != nil { 248 + logger.Error("error decrementing use count", "error", err) 249 return helpers.ServerError(e, nil) 250 } 251 } 252 253 sess, err := s.createSession(ctx, &urepo) 254 if err != nil { 255 + logger.Error("error creating new session", "error", err) 256 return helpers.ServerError(e, nil) 257 } 258 259 go func() { 260 if err := s.sendEmailVerification(urepo.Email, actor.Handle, *urepo.EmailVerificationCode); err != nil { 261 + logger.Error("error sending email verification email", "error", err) 262 } 263 if err := s.sendWelcomeMail(urepo.Email, actor.Handle); err != nil { 264 + logger.Error("error sending welcome email", "error", err) 265 } 266 }() 267
+4 -3
server/handle_server_create_invite_code.go
··· 18 19 func (s *Server) handleCreateInviteCode(e echo.Context) error { 20 ctx := e.Request().Context() 21 22 var req ComAtprotoServerCreateInviteCodeRequest 23 if err := e.Bind(&req); err != nil { 24 - s.logger.Error("error binding", "error", err) 25 return helpers.ServerError(e, nil) 26 } 27 28 if err := e.Validate(req); err != nil { 29 - s.logger.Error("error validating", "error", err) 30 return helpers.InputError(e, nil) 31 } 32 ··· 44 Did: acc, 45 RemainingUseCount: req.UseCount, 46 }, nil).Error; err != nil { 47 - s.logger.Error("error creating invite code", "error", err) 48 return helpers.ServerError(e, nil) 49 } 50
··· 18 19 func (s *Server) handleCreateInviteCode(e echo.Context) error { 20 ctx := e.Request().Context() 21 + logger := s.logger.With("name", "handleServerCreateInviteCode") 22 23 var req ComAtprotoServerCreateInviteCodeRequest 24 if err := e.Bind(&req); err != nil { 25 + logger.Error("error binding", "error", err) 26 return helpers.ServerError(e, nil) 27 } 28 29 if err := e.Validate(req); err != nil { 30 + logger.Error("error validating", "error", err) 31 return helpers.InputError(e, nil) 32 } 33 ··· 45 Did: acc, 46 RemainingUseCount: req.UseCount, 47 }, nil).Error; err != nil { 48 + logger.Error("error creating invite code", "error", err) 49 return helpers.ServerError(e, nil) 50 } 51
+4 -3
server/handle_server_create_invite_codes.go
··· 23 24 func (s *Server) handleCreateInviteCodes(e echo.Context) error { 25 ctx := e.Request().Context() 26 27 var req ComAtprotoServerCreateInviteCodesRequest 28 if err := e.Bind(&req); err != nil { 29 - s.logger.Error("error binding", "error", err) 30 return helpers.ServerError(e, nil) 31 } 32 33 if err := e.Validate(req); err != nil { 34 - s.logger.Error("error validating", "error", err) 35 return helpers.InputError(e, nil) 36 } 37 ··· 57 Did: did, 58 RemainingUseCount: req.UseCount, 59 }, nil).Error; err != nil { 60 - s.logger.Error("error creating invite code", "error", err) 61 return helpers.ServerError(e, nil) 62 } 63 }
··· 23 24 func (s *Server) handleCreateInviteCodes(e echo.Context) error { 25 ctx := e.Request().Context() 26 + logger := s.logger.With("name", "handleServerCreateInviteCodes") 27 28 var req ComAtprotoServerCreateInviteCodesRequest 29 if err := e.Bind(&req); err != nil { 30 + logger.Error("error binding", "error", err) 31 return helpers.ServerError(e, nil) 32 } 33 34 if err := e.Validate(req); err != nil { 35 + logger.Error("error validating", "error", err) 36 return helpers.InputError(e, nil) 37 } 38 ··· 58 Did: did, 59 RemainingUseCount: req.UseCount, 60 }, nil).Error; err != nil { 61 + logger.Error("error creating invite code", "error", err) 62 return helpers.ServerError(e, nil) 63 } 64 }
+5 -4
server/handle_server_create_session.go
··· 36 37 func (s *Server) handleCreateSession(e echo.Context) error { 38 ctx := e.Request().Context() 39 40 var req ComAtprotoServerCreateSessionRequest 41 if err := e.Bind(&req); err != nil { 42 - s.logger.Error("error binding request", "endpoint", "com.atproto.server.serverCreateSession", "error", err) 43 return helpers.ServerError(e, nil) 44 } 45 ··· 82 return helpers.InputError(e, to.StringPtr("InvalidRequest")) 83 } 84 85 - s.logger.Error("erorr looking up repo", "endpoint", "com.atproto.server.createSession", "error", err) 86 return helpers.ServerError(e, nil) 87 } 88 89 if err := bcrypt.CompareHashAndPassword([]byte(repo.Password), []byte(req.Password)); err != nil { 90 if err != bcrypt.ErrMismatchedHashAndPassword { 91 - s.logger.Error("erorr comparing hash and password", "error", err) 92 } 93 return helpers.InputError(e, to.StringPtr("InvalidRequest")) 94 } ··· 127 128 sess, err := s.createSession(ctx, &repo.Repo) 129 if err != nil { 130 - s.logger.Error("error creating session", "error", err) 131 return helpers.ServerError(e, nil) 132 } 133
··· 36 37 func (s *Server) handleCreateSession(e echo.Context) error { 38 ctx := e.Request().Context() 39 + logger := s.logger.With("name", "handleServerCreateSession") 40 41 var req ComAtprotoServerCreateSessionRequest 42 if err := e.Bind(&req); err != nil { 43 + logger.Error("error binding request", "endpoint", "com.atproto.server.serverCreateSession", "error", err) 44 return helpers.ServerError(e, nil) 45 } 46 ··· 83 return helpers.InputError(e, to.StringPtr("InvalidRequest")) 84 } 85 86 + logger.Error("erorr looking up repo", "endpoint", "com.atproto.server.createSession", "error", err) 87 return helpers.ServerError(e, nil) 88 } 89 90 if err := bcrypt.CompareHashAndPassword([]byte(repo.Password), []byte(req.Password)); err != nil { 91 if err != bcrypt.ErrMismatchedHashAndPassword { 92 + logger.Error("erorr comparing hash and password", "error", err) 93 } 94 return helpers.InputError(e, to.StringPtr("InvalidRequest")) 95 } ··· 128 129 sess, err := s.createSession(ctx, &repo.Repo) 130 if err != nil { 131 + logger.Error("error creating session", "error", err) 132 return helpers.ServerError(e, nil) 133 } 134
+3 -2
server/handle_server_deactivate_account.go
··· 20 21 func (s *Server) handleServerDeactivateAccount(e echo.Context) error { 22 ctx := e.Request().Context() 23 24 var req ComAtprotoServerDeactivateAccountRequest 25 if err := e.Bind(&req); err != nil { 26 - s.logger.Error("error binding", "error", err) 27 return helpers.ServerError(e, nil) 28 } 29 30 urepo := e.Get("repo").(*models.RepoActor) 31 32 if err := s.db.Exec(ctx, "UPDATE repos SET deactivated = ? WHERE did = ?", nil, true, urepo.Repo.Did).Error; err != nil { 33 - s.logger.Error("error updating account status to deactivated", "error", err) 34 return helpers.ServerError(e, nil) 35 } 36
··· 20 21 func (s *Server) handleServerDeactivateAccount(e echo.Context) error { 22 ctx := e.Request().Context() 23 + logger := s.logger.With("name", "handleServerDeactivateAccount") 24 25 var req ComAtprotoServerDeactivateAccountRequest 26 if err := e.Bind(&req); err != nil { 27 + logger.Error("error binding", "error", err) 28 return helpers.ServerError(e, nil) 29 } 30 31 urepo := e.Get("repo").(*models.RepoActor) 32 33 if err := s.db.Exec(ctx, "UPDATE repos SET deactivated = ? WHERE did = ?", nil, true, urepo.Repo.Did).Error; err != nil { 34 + logger.Error("error updating account status to deactivated", "error", err) 35 return helpers.ServerError(e, nil) 36 } 37
+30 -27
server/handle_server_delete_account.go
··· 21 22 func (s *Server) handleServerDeleteAccount(e echo.Context) error { 23 ctx := e.Request().Context() 24 25 var req ComAtprotoServerDeleteAccountRequest 26 if err := e.Bind(&req); err != nil { 27 - s.logger.Error("error binding", "error", err) 28 return helpers.ServerError(e, nil) 29 } 30 31 if err := e.Validate(&req); err != nil { 32 - s.logger.Error("error validating", "error", err) 33 return helpers.ServerError(e, nil) 34 } 35 36 urepo, err := s.getRepoActorByDid(ctx, req.Did) 37 if err != nil { 38 - s.logger.Error("error getting repo", "error", err) 39 return echo.NewHTTPError(400, "account not found") 40 } 41 42 if err := bcrypt.CompareHashAndPassword([]byte(urepo.Repo.Password), []byte(req.Password)); err != nil { 43 - s.logger.Error("password mismatch", "error", err) 44 return echo.NewHTTPError(401, "Invalid did or password") 45 } 46 47 if urepo.Repo.AccountDeleteCode == nil || urepo.Repo.AccountDeleteCodeExpiresAt == nil { 48 - s.logger.Error("no deletion token found for account") 49 return echo.NewHTTPError(400, map[string]interface{}{ 50 "error": "InvalidToken", 51 "message": "Token is invalid", ··· 53 } 54 55 if *urepo.Repo.AccountDeleteCode != req.Token { 56 - s.logger.Error("deletion token mismatch") 57 return echo.NewHTTPError(400, map[string]interface{}{ 58 "error": "InvalidToken", 59 "message": "Token is invalid", ··· 61 } 62 63 if time.Now().UTC().After(*urepo.Repo.AccountDeleteCodeExpiresAt) { 64 - s.logger.Error("deletion token expired") 65 return echo.NewHTTPError(400, map[string]interface{}{ 66 "error": "ExpiredToken", 67 "message": "Token is expired", ··· 70 71 tx := s.db.BeginDangerously(ctx) 72 if tx.Error != nil { 73 - s.logger.Error("error starting transaction", "error", tx.Error) 74 return helpers.ServerError(e, nil) 75 } 76 77 if err := tx.Exec("DELETE FROM blocks WHERE did = ?", nil, req.Did).Error; err != nil { 78 - tx.Rollback() 79 - s.logger.Error("error deleting blocks", "error", err) 80 return helpers.ServerError(e, nil) 81 } 82 83 if err := tx.Exec("DELETE FROM records WHERE did = ?", nil, req.Did).Error; err != nil { 84 - tx.Rollback() 85 - s.logger.Error("error deleting records", "error", err) 86 return helpers.ServerError(e, nil) 87 } 88 89 if err := tx.Exec("DELETE FROM blobs WHERE did = ?", nil, req.Did).Error; err != nil { 90 - tx.Rollback() 91 - s.logger.Error("error deleting blobs", "error", err) 92 return helpers.ServerError(e, nil) 93 } 94 95 if err := tx.Exec("DELETE FROM tokens WHERE did = ?", nil, req.Did).Error; err != nil { 96 - tx.Rollback() 97 - s.logger.Error("error deleting tokens", "error", err) 98 return helpers.ServerError(e, nil) 99 } 100 101 if err := tx.Exec("DELETE FROM refresh_tokens WHERE did = ?", nil, req.Did).Error; err != nil { 102 - tx.Rollback() 103 - s.logger.Error("error deleting refresh tokens", "error", err) 104 return helpers.ServerError(e, nil) 105 } 106 107 if err := tx.Exec("DELETE FROM reserved_keys WHERE did = ?", nil, req.Did).Error; err != nil { 108 - tx.Rollback() 109 - s.logger.Error("error deleting reserved keys", "error", err) 110 return helpers.ServerError(e, nil) 111 } 112 113 if err := tx.Exec("DELETE FROM invite_codes WHERE did = ?", nil, req.Did).Error; err != nil { 114 - tx.Rollback() 115 - s.logger.Error("error deleting invite codes", "error", err) 116 return helpers.ServerError(e, nil) 117 } 118 119 if err := tx.Exec("DELETE FROM actors WHERE did = ?", nil, req.Did).Error; err != nil { 120 - tx.Rollback() 121 - s.logger.Error("error deleting actor", "error", err) 122 return helpers.ServerError(e, nil) 123 } 124 125 if err := tx.Exec("DELETE FROM repos WHERE did = ?", nil, req.Did).Error; err != nil { 126 - tx.Rollback() 127 - s.logger.Error("error deleting repo", "error", err) 128 return helpers.ServerError(e, nil) 129 } 130 131 if err := tx.Commit().Error; err != nil { 132 - s.logger.Error("error committing transaction", "error", err) 133 return helpers.ServerError(e, nil) 134 } 135
··· 21 22 func (s *Server) handleServerDeleteAccount(e echo.Context) error { 23 ctx := e.Request().Context() 24 + logger := s.logger.With("name", "handleServerDeleteAccount") 25 26 var req ComAtprotoServerDeleteAccountRequest 27 if err := e.Bind(&req); err != nil { 28 + logger.Error("error binding", "error", err) 29 return helpers.ServerError(e, nil) 30 } 31 32 if err := e.Validate(&req); err != nil { 33 + logger.Error("error validating", "error", err) 34 return helpers.ServerError(e, nil) 35 } 36 37 urepo, err := s.getRepoActorByDid(ctx, req.Did) 38 if err != nil { 39 + logger.Error("error getting repo", "error", err) 40 return echo.NewHTTPError(400, "account not found") 41 } 42 43 if err := bcrypt.CompareHashAndPassword([]byte(urepo.Repo.Password), []byte(req.Password)); err != nil { 44 + logger.Error("password mismatch", "error", err) 45 return echo.NewHTTPError(401, "Invalid did or password") 46 } 47 48 if urepo.Repo.AccountDeleteCode == nil || urepo.Repo.AccountDeleteCodeExpiresAt == nil { 49 + logger.Error("no deletion token found for account") 50 return echo.NewHTTPError(400, map[string]interface{}{ 51 "error": "InvalidToken", 52 "message": "Token is invalid", ··· 54 } 55 56 if *urepo.Repo.AccountDeleteCode != req.Token { 57 + logger.Error("deletion token mismatch") 58 return echo.NewHTTPError(400, map[string]interface{}{ 59 "error": "InvalidToken", 60 "message": "Token is invalid", ··· 62 } 63 64 if time.Now().UTC().After(*urepo.Repo.AccountDeleteCodeExpiresAt) { 65 + logger.Error("deletion token expired") 66 return echo.NewHTTPError(400, map[string]interface{}{ 67 "error": "ExpiredToken", 68 "message": "Token is expired", ··· 71 72 tx := s.db.BeginDangerously(ctx) 73 if tx.Error != nil { 74 + logger.Error("error starting transaction", "error", tx.Error) 75 return helpers.ServerError(e, nil) 76 } 77 78 + status := "error" 79 + func() { 80 + if status == "error" { 81 + if err := tx.Rollback().Error; err != nil { 82 + logger.Error("error rolling back after delete failure", "err", err) 83 + } 84 + } 85 + }() 86 + 87 if err := tx.Exec("DELETE FROM blocks WHERE did = ?", nil, req.Did).Error; err != nil { 88 + logger.Error("error deleting blocks", "error", err) 89 return helpers.ServerError(e, nil) 90 } 91 92 if err := tx.Exec("DELETE FROM records WHERE did = ?", nil, req.Did).Error; err != nil { 93 + logger.Error("error deleting records", "error", err) 94 return helpers.ServerError(e, nil) 95 } 96 97 if err := tx.Exec("DELETE FROM blobs WHERE did = ?", nil, req.Did).Error; err != nil { 98 + logger.Error("error deleting blobs", "error", err) 99 return helpers.ServerError(e, nil) 100 } 101 102 if err := tx.Exec("DELETE FROM tokens WHERE did = ?", nil, req.Did).Error; err != nil { 103 + logger.Error("error deleting tokens", "error", err) 104 return helpers.ServerError(e, nil) 105 } 106 107 if err := tx.Exec("DELETE FROM refresh_tokens WHERE did = ?", nil, req.Did).Error; err != nil { 108 + logger.Error("error deleting refresh tokens", "error", err) 109 return helpers.ServerError(e, nil) 110 } 111 112 if err := tx.Exec("DELETE FROM reserved_keys WHERE did = ?", nil, req.Did).Error; err != nil { 113 + logger.Error("error deleting reserved keys", "error", err) 114 return helpers.ServerError(e, nil) 115 } 116 117 if err := tx.Exec("DELETE FROM invite_codes WHERE did = ?", nil, req.Did).Error; err != nil { 118 + logger.Error("error deleting invite codes", "error", err) 119 return helpers.ServerError(e, nil) 120 } 121 122 if err := tx.Exec("DELETE FROM actors WHERE did = ?", nil, req.Did).Error; err != nil { 123 + logger.Error("error deleting actor", "error", err) 124 return helpers.ServerError(e, nil) 125 } 126 127 if err := tx.Exec("DELETE FROM repos WHERE did = ?", nil, req.Did).Error; err != nil { 128 + logger.Error("error deleting repo", "error", err) 129 return helpers.ServerError(e, nil) 130 } 131 132 + status = "ok" 133 + 134 if err := tx.Commit().Error; err != nil { 135 + logger.Error("error committing transaction", "error", err) 136 return helpers.ServerError(e, nil) 137 } 138
+7 -5
server/handle_server_get_service_auth.go
··· 25 } 26 27 func (s *Server) handleServerGetServiceAuth(e echo.Context) error { 28 var req ServerGetServiceAuthRequest 29 if err := e.Bind(&req); err != nil { 30 - s.logger.Error("could not bind service auth request", "error", err) 31 return helpers.ServerError(e, nil) 32 } 33 ··· 64 } 65 hj, err := json.Marshal(header) 66 if err != nil { 67 - s.logger.Error("error marshaling header", "error", err) 68 return helpers.ServerError(e, nil) 69 } 70 ··· 82 } 83 pj, err := json.Marshal(payload) 84 if err != nil { 85 - s.logger.Error("error marashaling payload", "error", err) 86 return helpers.ServerError(e, nil) 87 } 88 ··· 93 94 sk, err := secp256k1secec.NewPrivateKey(repo.SigningKey) 95 if err != nil { 96 - s.logger.Error("can't load private key", "error", err) 97 return err 98 } 99 100 R, S, _, err := sk.SignRaw(rand.Reader, hash[:]) 101 if err != nil { 102 - s.logger.Error("error signing", "error", err) 103 return helpers.ServerError(e, nil) 104 } 105
··· 25 } 26 27 func (s *Server) handleServerGetServiceAuth(e echo.Context) error { 28 + logger := s.logger.With("name", "handleServerGetServiceAuth") 29 + 30 var req ServerGetServiceAuthRequest 31 if err := e.Bind(&req); err != nil { 32 + logger.Error("could not bind service auth request", "error", err) 33 return helpers.ServerError(e, nil) 34 } 35 ··· 66 } 67 hj, err := json.Marshal(header) 68 if err != nil { 69 + logger.Error("error marshaling header", "error", err) 70 return helpers.ServerError(e, nil) 71 } 72 ··· 84 } 85 pj, err := json.Marshal(payload) 86 if err != nil { 87 + logger.Error("error marashaling payload", "error", err) 88 return helpers.ServerError(e, nil) 89 } 90 ··· 95 96 sk, err := secp256k1secec.NewPrivateKey(repo.SigningKey) 97 if err != nil { 98 + logger.Error("can't load private key", "error", err) 99 return err 100 } 101 102 R, S, _, err := sk.SignRaw(rand.Reader, hash[:]) 103 if err != nil { 104 + logger.Error("error signing", "error", err) 105 return helpers.ServerError(e, nil) 106 } 107
+4 -3
server/handle_server_refresh_session.go
··· 17 18 func (s *Server) handleRefreshSession(e echo.Context) error { 19 ctx := e.Request().Context() 20 21 token := e.Get("token").(string) 22 repo := e.Get("repo").(*models.RepoActor) 23 24 if err := s.db.Exec(ctx, "DELETE FROM refresh_tokens WHERE token = ?", nil, token).Error; err != nil { 25 - s.logger.Error("error getting refresh token from db", "error", err) 26 return helpers.ServerError(e, nil) 27 } 28 29 if err := s.db.Exec(ctx, "DELETE FROM tokens WHERE refresh_token = ?", nil, token).Error; err != nil { 30 - s.logger.Error("error deleting access token from db", "error", err) 31 return helpers.ServerError(e, nil) 32 } 33 34 sess, err := s.createSession(ctx, &repo.Repo) 35 if err != nil { 36 - s.logger.Error("error creating new session for refresh", "error", err) 37 return helpers.ServerError(e, nil) 38 } 39
··· 17 18 func (s *Server) handleRefreshSession(e echo.Context) error { 19 ctx := e.Request().Context() 20 + logger := s.logger.With("name", "handleServerRefreshSession") 21 22 token := e.Get("token").(string) 23 repo := e.Get("repo").(*models.RepoActor) 24 25 if err := s.db.Exec(ctx, "DELETE FROM refresh_tokens WHERE token = ?", nil, token).Error; err != nil { 26 + logger.Error("error getting refresh token from db", "error", err) 27 return helpers.ServerError(e, nil) 28 } 29 30 if err := s.db.Exec(ctx, "DELETE FROM tokens WHERE refresh_token = ?", nil, token).Error; err != nil { 31 + logger.Error("error deleting access token from db", "error", err) 32 return helpers.ServerError(e, nil) 33 } 34 35 sess, err := s.createSession(ctx, &repo.Repo) 36 if err != nil { 37 + logger.Error("error creating new session for refresh", "error", err) 38 return helpers.ServerError(e, nil) 39 } 40
+3 -2
server/handle_server_request_account_delete.go
··· 11 12 func (s *Server) handleServerRequestAccountDelete(e echo.Context) error { 13 ctx := e.Request().Context() 14 15 urepo := e.Get("repo").(*models.RepoActor) 16 ··· 18 expiresAt := time.Now().UTC().Add(15 * time.Minute) 19 20 if err := s.db.Exec(ctx, "UPDATE repos SET account_delete_code = ?, account_delete_code_expires_at = ? WHERE did = ?", nil, token, expiresAt, urepo.Repo.Did).Error; err != nil { 21 - s.logger.Error("error setting deletion token", "error", err) 22 return helpers.ServerError(e, nil) 23 } 24 25 if urepo.Email != "" { 26 if err := s.sendAccountDeleteEmail(urepo.Email, urepo.Actor.Handle, token); err != nil { 27 - s.logger.Error("error sending account deletion email", "error", err) 28 } 29 } 30
··· 11 12 func (s *Server) handleServerRequestAccountDelete(e echo.Context) error { 13 ctx := e.Request().Context() 14 + logger := s.logger.With("name", "handleServerRequestAccountDelete") 15 16 urepo := e.Get("repo").(*models.RepoActor) 17 ··· 19 expiresAt := time.Now().UTC().Add(15 * time.Minute) 20 21 if err := s.db.Exec(ctx, "UPDATE repos SET account_delete_code = ?, account_delete_code_expires_at = ? WHERE did = ?", nil, token, expiresAt, urepo.Repo.Did).Error; err != nil { 22 + logger.Error("error setting deletion token", "error", err) 23 return helpers.ServerError(e, nil) 24 } 25 26 if urepo.Email != "" { 27 if err := s.sendAccountDeleteEmail(urepo.Email, urepo.Actor.Handle, token); err != nil { 28 + logger.Error("error sending account deletion email", "error", err) 29 } 30 } 31
+3 -2
server/handle_server_request_email_confirmation.go
··· 12 13 func (s *Server) handleServerRequestEmailConfirmation(e echo.Context) error { 14 ctx := e.Request().Context() 15 16 urepo := e.Get("repo").(*models.RepoActor) 17 ··· 23 eat := time.Now().Add(10 * time.Minute).UTC() 24 25 if err := s.db.Exec(ctx, "UPDATE repos SET email_verification_code = ?, email_verification_code_expires_at = ? WHERE did = ?", nil, code, eat, urepo.Repo.Did).Error; err != nil { 26 - s.logger.Error("error updating user", "error", err) 27 return helpers.ServerError(e, nil) 28 } 29 30 if err := s.sendEmailVerification(urepo.Email, urepo.Handle, code); err != nil { 31 - s.logger.Error("error sending mail", "error", err) 32 return helpers.ServerError(e, nil) 33 } 34
··· 12 13 func (s *Server) handleServerRequestEmailConfirmation(e echo.Context) error { 14 ctx := e.Request().Context() 15 + logger := s.logger.With("name", "handleServerRequestEmailConfirm") 16 17 urepo := e.Get("repo").(*models.RepoActor) 18 ··· 24 eat := time.Now().Add(10 * time.Minute).UTC() 25 26 if err := s.db.Exec(ctx, "UPDATE repos SET email_verification_code = ?, email_verification_code_expires_at = ? WHERE did = ?", nil, code, eat, urepo.Repo.Did).Error; err != nil { 27 + logger.Error("error updating user", "error", err) 28 return helpers.ServerError(e, nil) 29 } 30 31 if err := s.sendEmailVerification(urepo.Email, urepo.Handle, code); err != nil { 32 + logger.Error("error sending mail", "error", err) 33 return helpers.ServerError(e, nil) 34 } 35
+3 -2
server/handle_server_request_email_update.go
··· 15 16 func (s *Server) handleServerRequestEmailUpdate(e echo.Context) error { 17 ctx := e.Request().Context() 18 19 urepo := e.Get("repo").(*models.RepoActor) 20 ··· 23 eat := time.Now().Add(10 * time.Minute).UTC() 24 25 if err := s.db.Exec(ctx, "UPDATE repos SET email_update_code = ?, email_update_code_expires_at = ? WHERE did = ?", nil, code, eat, urepo.Repo.Did).Error; err != nil { 26 - s.logger.Error("error updating repo", "error", err) 27 return helpers.ServerError(e, nil) 28 } 29 30 if err := s.sendEmailUpdate(urepo.Email, urepo.Handle, code); err != nil { 31 - s.logger.Error("error sending email", "error", err) 32 return helpers.ServerError(e, nil) 33 } 34 }
··· 15 16 func (s *Server) handleServerRequestEmailUpdate(e echo.Context) error { 17 ctx := e.Request().Context() 18 + logger := s.logger.With("name", "handleServerRequestEmailUpdate") 19 20 urepo := e.Get("repo").(*models.RepoActor) 21 ··· 24 eat := time.Now().Add(10 * time.Minute).UTC() 25 26 if err := s.db.Exec(ctx, "UPDATE repos SET email_update_code = ?, email_update_code_expires_at = ? WHERE did = ?", nil, code, eat, urepo.Repo.Did).Error; err != nil { 27 + logger.Error("error updating repo", "error", err) 28 return helpers.ServerError(e, nil) 29 } 30 31 if err := s.sendEmailUpdate(urepo.Email, urepo.Handle, code); err != nil { 32 + logger.Error("error sending email", "error", err) 33 return helpers.ServerError(e, nil) 34 } 35 }
+3 -2
server/handle_server_request_password_reset.go
··· 15 16 func (s *Server) handleServerRequestPasswordReset(e echo.Context) error { 17 ctx := e.Request().Context() 18 19 urepo, ok := e.Get("repo").(*models.RepoActor) 20 if !ok { ··· 39 eat := time.Now().Add(10 * time.Minute).UTC() 40 41 if err := s.db.Exec(ctx, "UPDATE repos SET password_reset_code = ?, password_reset_code_expires_at = ? WHERE did = ?", nil, code, eat, urepo.Repo.Did).Error; err != nil { 42 - s.logger.Error("error updating repo", "error", err) 43 return helpers.ServerError(e, nil) 44 } 45 46 if err := s.sendPasswordReset(urepo.Email, urepo.Handle, code); err != nil { 47 - s.logger.Error("error sending email", "error", err) 48 return helpers.ServerError(e, nil) 49 } 50
··· 15 16 func (s *Server) handleServerRequestPasswordReset(e echo.Context) error { 17 ctx := e.Request().Context() 18 + logger := s.logger.With("name", "handleServerRequestPasswordReset") 19 20 urepo, ok := e.Get("repo").(*models.RepoActor) 21 if !ok { ··· 40 eat := time.Now().Add(10 * time.Minute).UTC() 41 42 if err := s.db.Exec(ctx, "UPDATE repos SET password_reset_code = ?, password_reset_code_expires_at = ? WHERE did = ?", nil, code, eat, urepo.Repo.Did).Error; err != nil { 43 + logger.Error("error updating repo", "error", err) 44 return helpers.ServerError(e, nil) 45 } 46 47 if err := s.sendPasswordReset(urepo.Email, urepo.Handle, code); err != nil { 48 + logger.Error("error sending email", "error", err) 49 return helpers.ServerError(e, nil) 50 } 51
+6 -5
server/handle_server_reserve_signing_key.go
··· 20 21 func (s *Server) handleServerReserveSigningKey(e echo.Context) error { 22 ctx := e.Request().Context() 23 24 var req ServerReserveSigningKeyRequest 25 if err := e.Bind(&req); err != nil { 26 - s.logger.Error("could not bind reserve signing key request", "error", err) 27 return helpers.ServerError(e, nil) 28 } 29 ··· 38 39 k, err := atcrypto.GeneratePrivateKeyK256() 40 if err != nil { 41 - s.logger.Error("error creating signing key", "endpoint", "com.atproto.server.reserveSigningKey", "error", err) 42 return helpers.ServerError(e, nil) 43 } 44 45 pubKey, err := k.PublicKey() 46 if err != nil { 47 - s.logger.Error("error getting public key", "endpoint", "com.atproto.server.reserveSigningKey", "error", err) 48 return helpers.ServerError(e, nil) 49 } 50 ··· 58 } 59 60 if err := s.db.Create(ctx, &reservedKey, nil).Error; err != nil { 61 - s.logger.Error("error storing reserved key", "endpoint", "com.atproto.server.reserveSigningKey", "error", err) 62 return helpers.ServerError(e, nil) 63 } 64 65 - s.logger.Info("reserved signing key", "keyDid", keyDid, "forDid", req.Did) 66 67 return e.JSON(200, ServerReserveSigningKeyResponse{ 68 SigningKey: keyDid,
··· 20 21 func (s *Server) handleServerReserveSigningKey(e echo.Context) error { 22 ctx := e.Request().Context() 23 + logger := s.logger.With("name", "handleServerReserveSigningKey") 24 25 var req ServerReserveSigningKeyRequest 26 if err := e.Bind(&req); err != nil { 27 + logger.Error("could not bind reserve signing key request", "error", err) 28 return helpers.ServerError(e, nil) 29 } 30 ··· 39 40 k, err := atcrypto.GeneratePrivateKeyK256() 41 if err != nil { 42 + logger.Error("error creating signing key", "endpoint", "com.atproto.server.reserveSigningKey", "error", err) 43 return helpers.ServerError(e, nil) 44 } 45 46 pubKey, err := k.PublicKey() 47 if err != nil { 48 + logger.Error("error getting public key", "endpoint", "com.atproto.server.reserveSigningKey", "error", err) 49 return helpers.ServerError(e, nil) 50 } 51 ··· 59 } 60 61 if err := s.db.Create(ctx, &reservedKey, nil).Error; err != nil { 62 + logger.Error("error storing reserved key", "endpoint", "com.atproto.server.reserveSigningKey", "error", err) 63 return helpers.ServerError(e, nil) 64 } 65 66 + logger.Info("reserved signing key", "keyDid", keyDid, "forDid", req.Did) 67 68 return e.JSON(200, ServerReserveSigningKeyResponse{ 69 SigningKey: keyDid,
+4 -3
server/handle_server_reset_password.go
··· 17 18 func (s *Server) handleServerResetPassword(e echo.Context) error { 19 ctx := e.Request().Context() 20 21 urepo := e.Get("repo").(*models.RepoActor) 22 23 var req ComAtprotoServerResetPasswordRequest 24 if err := e.Bind(&req); err != nil { 25 - s.logger.Error("error binding", "error", err) 26 return helpers.ServerError(e, nil) 27 } 28 ··· 44 45 hash, err := bcrypt.GenerateFromPassword([]byte(req.Password), 10) 46 if err != nil { 47 - s.logger.Error("error creating hash", "error", err) 48 return helpers.ServerError(e, nil) 49 } 50 51 if err := s.db.Exec(ctx, "UPDATE repos SET password_reset_code = NULL, password_reset_code_expires_at = NULL, password = ? WHERE did = ?", nil, hash, urepo.Repo.Did).Error; err != nil { 52 - s.logger.Error("error updating repo", "error", err) 53 return helpers.ServerError(e, nil) 54 } 55
··· 17 18 func (s *Server) handleServerResetPassword(e echo.Context) error { 19 ctx := e.Request().Context() 20 + logger := s.logger.With("name", "handleServerResetPassword") 21 22 urepo := e.Get("repo").(*models.RepoActor) 23 24 var req ComAtprotoServerResetPasswordRequest 25 if err := e.Bind(&req); err != nil { 26 + logger.Error("error binding", "error", err) 27 return helpers.ServerError(e, nil) 28 } 29 ··· 45 46 hash, err := bcrypt.GenerateFromPassword([]byte(req.Password), 10) 47 if err != nil { 48 + logger.Error("error creating hash", "error", err) 49 return helpers.ServerError(e, nil) 50 } 51 52 if err := s.db.Exec(ctx, "UPDATE repos SET password_reset_code = NULL, password_reset_code_expires_at = NULL, password = ? WHERE did = ?", nil, hash, urepo.Repo.Did).Error; err != nil { 53 + logger.Error("error updating repo", "error", err) 54 return helpers.ServerError(e, nil) 55 } 56
+3 -1
server/handle_server_resolve_handle.go
··· 10 ) 11 12 func (s *Server) handleResolveHandle(e echo.Context) error { 13 type Resp struct { 14 Did string `json:"did"` 15 } ··· 28 ctx := context.WithValue(e.Request().Context(), "skip-cache", true) 29 did, err := s.passport.ResolveHandle(ctx, parsed.String()) 30 if err != nil { 31 - s.logger.Error("error resolving handle", "error", err) 32 return helpers.ServerError(e, nil) 33 } 34
··· 10 ) 11 12 func (s *Server) handleResolveHandle(e echo.Context) error { 13 + logger := s.logger.With("name", "handleServerResolveHandle") 14 + 15 type Resp struct { 16 Did string `json:"did"` 17 } ··· 30 ctx := context.WithValue(e.Request().Context(), "skip-cache", true) 31 did, err := s.passport.ResolveHandle(ctx, parsed.String()) 32 if err != nil { 33 + logger.Error("error resolving handle", "error", err) 34 return helpers.ServerError(e, nil) 35 } 36
+3 -2
server/handle_server_update_email.go
··· 16 17 func (s *Server) handleServerUpdateEmail(e echo.Context) error { 18 ctx := e.Request().Context() 19 20 urepo := e.Get("repo").(*models.RepoActor) 21 22 var req ComAtprotoServerUpdateEmailRequest 23 if err := e.Bind(&req); err != nil { 24 - s.logger.Error("error binding", "error", err) 25 return helpers.ServerError(e, nil) 26 } 27 ··· 64 query += " WHERE did = ?" 65 66 if err := s.db.Exec(ctx, query, nil, twoFactorType, req.Email, urepo.Repo.Did).Error; err != nil { 67 - s.logger.Error("error updating repo", "error", err) 68 return helpers.ServerError(e, nil) 69 } 70
··· 16 17 func (s *Server) handleServerUpdateEmail(e echo.Context) error { 18 ctx := e.Request().Context() 19 + logger := s.logger.With("name", "handleServerUpdateEmail") 20 21 urepo := e.Get("repo").(*models.RepoActor) 22 23 var req ComAtprotoServerUpdateEmailRequest 24 if err := e.Bind(&req); err != nil { 25 + logger.Error("error binding", "error", err) 26 return helpers.ServerError(e, nil) 27 } 28 ··· 65 query += " WHERE did = ?" 66 67 if err := s.db.Exec(ctx, query, nil, twoFactorType, req.Email, urepo.Repo.Did).Error; err != nil { 68 + logger.Error("error updating repo", "error", err) 69 return helpers.ServerError(e, nil) 70 } 71
+9 -8
server/handle_sync_get_blob.go
··· 18 19 func (s *Server) handleSyncGetBlob(e echo.Context) error { 20 ctx := e.Request().Context() 21 22 did := e.QueryParam("did") 23 if did == "" { ··· 36 37 urepo, err := s.getRepoActorByDid(ctx, did) 38 if err != nil { 39 - s.logger.Error("could not find user for requested blob", "error", err) 40 return helpers.InputError(e, nil) 41 } 42 ··· 49 50 var blob models.Blob 51 if err := s.db.Raw(ctx, "SELECT * FROM blobs WHERE did = ? AND cid = ?", nil, did, c.Bytes()).Scan(&blob).Error; err != nil { 52 - s.logger.Error("error looking up blob", "error", err) 53 return helpers.ServerError(e, nil) 54 } 55 ··· 58 if blob.Storage == "sqlite" { 59 var parts []models.BlobPart 60 if err := s.db.Raw(ctx, "SELECT * FROM blob_parts WHERE blob_id = ? ORDER BY idx", nil, blob.ID).Scan(&parts).Error; err != nil { 61 - s.logger.Error("error getting blob parts", "error", err) 62 return helpers.ServerError(e, nil) 63 } 64 ··· 68 } 69 } else if blob.Storage == "s3" { 70 if !(s.s3Config != nil && s.s3Config.BlobstoreEnabled) { 71 - s.logger.Error("s3 storage disabled") 72 return helpers.ServerError(e, nil) 73 } 74 ··· 91 92 sess, err := session.NewSession(config) 93 if err != nil { 94 - s.logger.Error("error creating aws session", "error", err) 95 return helpers.ServerError(e, nil) 96 } 97 ··· 100 Bucket: aws.String(s.s3Config.Bucket), 101 Key: aws.String(blobKey), 102 }); err != nil { 103 - s.logger.Error("error getting blob from s3", "error", err) 104 return helpers.ServerError(e, nil) 105 } else { 106 read := 0 ··· 114 break 115 } 116 } else if err != nil && err != io.ErrUnexpectedEOF { 117 - s.logger.Error("error reading blob", "error", err) 118 return helpers.ServerError(e, nil) 119 } 120 ··· 125 } 126 } 127 } else { 128 - s.logger.Error("unknown storage", "storage", blob.Storage) 129 return helpers.ServerError(e, nil) 130 } 131
··· 18 19 func (s *Server) handleSyncGetBlob(e echo.Context) error { 20 ctx := e.Request().Context() 21 + logger := s.logger.With("name", "handleSyncGetBlob") 22 23 did := e.QueryParam("did") 24 if did == "" { ··· 37 38 urepo, err := s.getRepoActorByDid(ctx, did) 39 if err != nil { 40 + logger.Error("could not find user for requested blob", "error", err) 41 return helpers.InputError(e, nil) 42 } 43 ··· 50 51 var blob models.Blob 52 if err := s.db.Raw(ctx, "SELECT * FROM blobs WHERE did = ? AND cid = ?", nil, did, c.Bytes()).Scan(&blob).Error; err != nil { 53 + logger.Error("error looking up blob", "error", err) 54 return helpers.ServerError(e, nil) 55 } 56 ··· 59 if blob.Storage == "sqlite" { 60 var parts []models.BlobPart 61 if err := s.db.Raw(ctx, "SELECT * FROM blob_parts WHERE blob_id = ? ORDER BY idx", nil, blob.ID).Scan(&parts).Error; err != nil { 62 + logger.Error("error getting blob parts", "error", err) 63 return helpers.ServerError(e, nil) 64 } 65 ··· 69 } 70 } else if blob.Storage == "s3" { 71 if !(s.s3Config != nil && s.s3Config.BlobstoreEnabled) { 72 + logger.Error("s3 storage disabled") 73 return helpers.ServerError(e, nil) 74 } 75 ··· 92 93 sess, err := session.NewSession(config) 94 if err != nil { 95 + logger.Error("error creating aws session", "error", err) 96 return helpers.ServerError(e, nil) 97 } 98 ··· 101 Bucket: aws.String(s.s3Config.Bucket), 102 Key: aws.String(blobKey), 103 }); err != nil { 104 + logger.Error("error getting blob from s3", "error", err) 105 return helpers.ServerError(e, nil) 106 } else { 107 read := 0 ··· 115 break 116 } 117 } else if err != nil && err != io.ErrUnexpectedEOF { 118 + logger.Error("error reading blob", "error", err) 119 return helpers.ServerError(e, nil) 120 } 121 ··· 126 } 127 } 128 } else { 129 + logger.Error("unknown storage", "storage", blob.Storage) 130 return helpers.ServerError(e, nil) 131 } 132
+2 -1
server/handle_sync_get_blocks.go
··· 18 19 func (s *Server) handleGetBlocks(e echo.Context) error { 20 ctx := e.Request().Context() 21 22 var req ComAtprotoSyncGetBlocksRequest 23 if err := e.Bind(&req); err != nil { ··· 52 }) 53 54 if _, err := carstore.LdWrite(buf, hb); err != nil { 55 - s.logger.Error("error writing to car", "error", err) 56 return helpers.ServerError(e, nil) 57 } 58
··· 18 19 func (s *Server) handleGetBlocks(e echo.Context) error { 20 ctx := e.Request().Context() 21 + logger := s.logger.With("name", "handleSyncGetBlocks") 22 23 var req ComAtprotoSyncGetBlocksRequest 24 if err := e.Bind(&req); err != nil { ··· 53 }) 54 55 if _, err := carstore.LdWrite(buf, hb); err != nil { 56 + logger.Error("error writing to car", "error", err) 57 return helpers.ServerError(e, nil) 58 } 59
+4 -3
server/handle_sync_get_record.go
··· 14 15 func (s *Server) handleSyncGetRecord(e echo.Context) error { 16 ctx := e.Request().Context() 17 18 did := e.QueryParam("did") 19 collection := e.QueryParam("collection") ··· 21 22 var urepo models.Repo 23 if err := s.db.Raw(ctx, "SELECT * FROM repos WHERE did = ?", nil, did).Scan(&urepo).Error; err != nil { 24 - s.logger.Error("error getting repo", "error", err) 25 return helpers.ServerError(e, nil) 26 } 27 ··· 38 }) 39 40 if _, err := carstore.LdWrite(buf, hb); err != nil { 41 - s.logger.Error("error writing to car", "error", err) 42 return helpers.ServerError(e, nil) 43 } 44 45 for _, blk := range blocks { 46 if _, err := carstore.LdWrite(buf, blk.Cid().Bytes(), blk.RawData()); err != nil { 47 - s.logger.Error("error writing to car", "error", err) 48 return helpers.ServerError(e, nil) 49 } 50 }
··· 14 15 func (s *Server) handleSyncGetRecord(e echo.Context) error { 16 ctx := e.Request().Context() 17 + logger := s.logger.With("name", "handleSyncGetRecord") 18 19 did := e.QueryParam("did") 20 collection := e.QueryParam("collection") ··· 22 23 var urepo models.Repo 24 if err := s.db.Raw(ctx, "SELECT * FROM repos WHERE did = ?", nil, did).Scan(&urepo).Error; err != nil { 25 + logger.Error("error getting repo", "error", err) 26 return helpers.ServerError(e, nil) 27 } 28 ··· 39 }) 40 41 if _, err := carstore.LdWrite(buf, hb); err != nil { 42 + logger.Error("error writing to car", "error", err) 43 return helpers.ServerError(e, nil) 44 } 45 46 for _, blk := range blocks { 47 if _, err := carstore.LdWrite(buf, blk.Cid().Bytes(), blk.RawData()); err != nil { 48 + logger.Error("error writing to car", "error", err) 49 return helpers.ServerError(e, nil) 50 } 51 }
+2 -1
server/handle_sync_get_repo.go
··· 14 15 func (s *Server) handleSyncGetRepo(e echo.Context) error { 16 ctx := e.Request().Context() 17 18 did := e.QueryParam("did") 19 if did == "" { ··· 38 buf := new(bytes.Buffer) 39 40 if _, err := carstore.LdWrite(buf, hb); err != nil { 41 - s.logger.Error("error writing to car", "error", err) 42 return helpers.ServerError(e, nil) 43 } 44
··· 14 15 func (s *Server) handleSyncGetRepo(e echo.Context) error { 16 ctx := e.Request().Context() 17 + logger := s.logger.With("name", "handleSyncGetRepo") 18 19 did := e.QueryParam("did") 20 if did == "" { ··· 39 buf := new(bytes.Buffer) 40 41 if _, err := carstore.LdWrite(buf, hb); err != nil { 42 + logger.Error("error writing to car", "error", err) 43 return helpers.ServerError(e, nil) 44 } 45
+4 -3
server/handle_sync_list_blobs.go
··· 15 16 func (s *Server) handleSyncListBlobs(e echo.Context) error { 17 ctx := e.Request().Context() 18 19 did := e.QueryParam("did") 20 if did == "" { ··· 39 40 urepo, err := s.getRepoActorByDid(ctx, did) 41 if err != nil { 42 - s.logger.Error("could not find user for requested blobs", "error", err) 43 return helpers.InputError(e, nil) 44 } 45 ··· 52 53 var blobs []models.Blob 54 if err := s.db.Raw(ctx, "SELECT * FROM blobs WHERE did = ? "+cursorquery+" ORDER BY created_at DESC LIMIT ?", nil, params...).Scan(&blobs).Error; err != nil { 55 - s.logger.Error("error getting records", "error", err) 56 return helpers.ServerError(e, nil) 57 } 58 ··· 60 for _, b := range blobs { 61 c, err := cid.Cast(b.Cid) 62 if err != nil { 63 - s.logger.Error("error casting cid", "error", err) 64 return helpers.ServerError(e, nil) 65 } 66 cstrs = append(cstrs, c.String())
··· 15 16 func (s *Server) handleSyncListBlobs(e echo.Context) error { 17 ctx := e.Request().Context() 18 + logger := s.logger.With("name", "handleSyncListBlobs") 19 20 did := e.QueryParam("did") 21 if did == "" { ··· 40 41 urepo, err := s.getRepoActorByDid(ctx, did) 42 if err != nil { 43 + logger.Error("could not find user for requested blobs", "error", err) 44 return helpers.InputError(e, nil) 45 } 46 ··· 53 54 var blobs []models.Blob 55 if err := s.db.Raw(ctx, "SELECT * FROM blobs WHERE did = ? "+cursorquery+" ORDER BY created_at DESC LIMIT ?", nil, params...).Scan(&blobs).Error; err != nil { 56 + logger.Error("error getting records", "error", err) 57 return helpers.ServerError(e, nil) 58 } 59 ··· 61 for _, b := range blobs { 62 c, err := cid.Cast(b.Cid) 63 if err != nil { 64 + logger.Error("error casting cid", "error", err) 65 return helpers.ServerError(e, nil) 66 } 67 cstrs = append(cstrs, c.String())
+54 -42
server/handle_sync_subscribe_repos.go
··· 7 "github.com/bluesky-social/indigo/events" 8 "github.com/bluesky-social/indigo/lex/util" 9 "github.com/btcsuite/websocket" 10 "github.com/labstack/echo/v4" 11 ) 12 ··· 24 logger = logger.With("ident", ident) 25 logger.Info("new connection established") 26 27 evts, cancel, err := s.evtman.Subscribe(ctx, ident, func(evt *events.XRPCStreamEvent) bool { 28 return true 29 }, nil) ··· 34 35 header := events.EventHeader{Op: events.EvtKindMessage} 36 for evt := range evts { 37 - wc, err := conn.NextWriter(websocket.BinaryMessage) 38 - if err != nil { 39 - logger.Error("error writing message to relay", "err", err) 40 - break 41 - } 42 43 - if ctx.Err() != nil { 44 - logger.Error("context error", "err", err) 45 - break 46 - } 47 48 - var obj util.CBOR 49 - switch { 50 - case evt.Error != nil: 51 - header.Op = events.EvtKindErrorFrame 52 - obj = evt.Error 53 - case evt.RepoCommit != nil: 54 - header.MsgType = "#commit" 55 - obj = evt.RepoCommit 56 - case evt.RepoIdentity != nil: 57 - header.MsgType = "#identity" 58 - obj = evt.RepoIdentity 59 - case evt.RepoAccount != nil: 60 - header.MsgType = "#account" 61 - obj = evt.RepoAccount 62 - case evt.RepoInfo != nil: 63 - header.MsgType = "#info" 64 - obj = evt.RepoInfo 65 - default: 66 - logger.Warn("unrecognized event kind") 67 - return nil 68 - } 69 70 - if err := header.MarshalCBOR(wc); err != nil { 71 - logger.Error("failed to write header to relay", "err", err) 72 - break 73 - } 74 75 - if err := obj.MarshalCBOR(wc); err != nil { 76 - logger.Error("failed to write event to relay", "err", err) 77 - break 78 - } 79 80 - if err := wc.Close(); err != nil { 81 - logger.Error("failed to flush-close our event write", "err", err) 82 - break 83 - } 84 } 85 86 // we should tell the relay to request a new crawl at this point if we got disconnected
··· 7 "github.com/bluesky-social/indigo/events" 8 "github.com/bluesky-social/indigo/lex/util" 9 "github.com/btcsuite/websocket" 10 + "github.com/haileyok/cocoon/metrics" 11 "github.com/labstack/echo/v4" 12 ) 13 ··· 25 logger = logger.With("ident", ident) 26 logger.Info("new connection established") 27 28 + metrics.RelaysConnected.WithLabelValues(ident).Inc() 29 + defer func() { 30 + metrics.RelaysConnected.WithLabelValues(ident).Dec() 31 + }() 32 + 33 evts, cancel, err := s.evtman.Subscribe(ctx, ident, func(evt *events.XRPCStreamEvent) bool { 34 return true 35 }, nil) ··· 40 41 header := events.EventHeader{Op: events.EvtKindMessage} 42 for evt := range evts { 43 + func() { 44 + defer func() { 45 + metrics.RelaySends.WithLabelValues(ident, header.MsgType).Inc() 46 + }() 47 48 + wc, err := conn.NextWriter(websocket.BinaryMessage) 49 + if err != nil { 50 + logger.Error("error writing message to relay", "err", err) 51 + return 52 + } 53 54 + if ctx.Err() != nil { 55 + logger.Error("context error", "err", err) 56 + return 57 + } 58 59 + var obj util.CBOR 60 + switch { 61 + case evt.Error != nil: 62 + header.Op = events.EvtKindErrorFrame 63 + obj = evt.Error 64 + case evt.RepoCommit != nil: 65 + header.MsgType = "#commit" 66 + obj = evt.RepoCommit 67 + case evt.RepoIdentity != nil: 68 + header.MsgType = "#identity" 69 + obj = evt.RepoIdentity 70 + case evt.RepoAccount != nil: 71 + header.MsgType = "#account" 72 + obj = evt.RepoAccount 73 + case evt.RepoInfo != nil: 74 + header.MsgType = "#info" 75 + obj = evt.RepoInfo 76 + default: 77 + logger.Warn("unrecognized event kind") 78 + return 79 + } 80 81 + if err := header.MarshalCBOR(wc); err != nil { 82 + logger.Error("failed to write header to relay", "err", err) 83 + return 84 + } 85 86 + if err := obj.MarshalCBOR(wc); err != nil { 87 + logger.Error("failed to write event to relay", "err", err) 88 + return 89 + } 90 + 91 + if err := wc.Close(); err != nil { 92 + logger.Error("failed to flush-close our event write", "err", err) 93 + return 94 + } 95 + }() 96 } 97 98 // we should tell the relay to request a new crawl at this point if we got disconnected
+2 -1
server/handle_well_known.go
··· 68 69 func (s *Server) handleAtprotoDid(e echo.Context) error { 70 ctx := e.Request().Context() 71 72 host := e.Request().Host 73 if host == "" { ··· 91 if err == gorm.ErrRecordNotFound { 92 return e.NoContent(404) 93 } 94 - s.logger.Error("error looking up actor by handle", "error", err) 95 return helpers.ServerError(e, nil) 96 } 97
··· 68 69 func (s *Server) handleAtprotoDid(e echo.Context) error { 70 ctx := e.Request().Context() 71 + logger := s.logger.With("name", "handleAtprotoDid") 72 73 host := e.Request().Host 74 if host == "" { ··· 92 if err == gorm.ErrRecordNotFound { 93 return e.NoContent(404) 94 } 95 + logger.Error("error looking up actor by handle", "error", err) 96 return helpers.ServerError(e, nil) 97 } 98
+33 -16
server/middleware.go
··· 38 func (s *Server) handleLegacySessionMiddleware(next echo.HandlerFunc) echo.HandlerFunc { 39 return func(e echo.Context) error { 40 ctx := e.Request().Context() 41 42 authheader := e.Request().Header.Get("authorization") 43 if authheader == "" { ··· 69 if hasLxm { 70 pts := strings.Split(e.Request().URL.String(), "/") 71 if lxm != pts[len(pts)-1] { 72 - s.logger.Error("service auth lxm incorrect", "lxm", lxm, "expected", pts[len(pts)-1], "error", err) 73 return helpers.InputError(e, nil) 74 } 75 76 maybeDid, ok := claims["iss"].(string) 77 if !ok { 78 - s.logger.Error("no iss in service auth token", "error", err) 79 return helpers.InputError(e, nil) 80 } 81 did = maybeDid 82 83 maybeRepo, err := s.getRepoActorByDid(ctx, did) 84 if err != nil { 85 - s.logger.Error("error fetching repo", "error", err) 86 return helpers.ServerError(e, nil) 87 } 88 repo = maybeRepo ··· 96 return s.privateKey.Public(), nil 97 }) 98 if err != nil { 99 - s.logger.Error("error parsing jwt", "error", err) 100 return helpers.ExpiredTokenError(e) 101 } 102 ··· 109 hash := sha256.Sum256([]byte(signingInput)) 110 sigBytes, err := base64.RawURLEncoding.DecodeString(kpts[2]) 111 if err != nil { 112 - s.logger.Error("error decoding signature bytes", "error", err) 113 return helpers.ServerError(e, nil) 114 } 115 116 if len(sigBytes) != 64 { 117 - s.logger.Error("incorrect sigbytes length", "length", len(sigBytes)) 118 return helpers.ServerError(e, nil) 119 } 120 ··· 123 rr, _ := secp256k1.NewScalarFromBytes((*[32]byte)(rBytes)) 124 ss, _ := secp256k1.NewScalarFromBytes((*[32]byte)(sBytes)) 125 126 sk, err := secp256k1secec.NewPrivateKey(repo.SigningKey) 127 if err != nil { 128 - s.logger.Error("can't load private key", "error", err) 129 return err 130 } 131 132 pubKey, ok := sk.Public().(*secp256k1secec.PublicKey) 133 if !ok { 134 - s.logger.Error("error getting public key from sk") 135 return helpers.ServerError(e, nil) 136 } 137 138 verified := pubKey.VerifyRaw(hash[:], rr, ss) 139 if !verified { 140 - s.logger.Error("error verifying", "error", err) 141 return helpers.ServerError(e, nil) 142 } 143 } ··· 166 return helpers.InvalidTokenError(e) 167 } 168 169 - s.logger.Error("error getting token from db", "error", err) 170 return helpers.ServerError(e, nil) 171 } 172 ··· 177 178 exp, ok := claims["exp"].(float64) 179 if !ok { 180 - s.logger.Error("error getting iat from token") 181 return helpers.ServerError(e, nil) 182 } 183 ··· 188 if repo == nil { 189 maybeRepo, err := s.getRepoActorByDid(ctx, claims["sub"].(string)) 190 if err != nil { 191 - s.logger.Error("error fetching repo", "error", err) 192 return helpers.ServerError(e, nil) 193 } 194 repo = maybeRepo ··· 210 func (s *Server) handleOauthSessionMiddleware(next echo.HandlerFunc) echo.HandlerFunc { 211 return func(e echo.Context) error { 212 ctx := e.Request().Context() 213 214 authheader := e.Request().Header.Get("authorization") 215 if authheader == "" { ··· 242 "error": "use_dpop_nonce", 243 }) 244 } 245 - s.logger.Error("invalid dpop proof", "error", err) 246 return helpers.InputError(e, nil) 247 } 248 249 var oauthToken provider.OauthToken 250 if err := s.db.Raw(ctx, "SELECT * FROM oauth_tokens WHERE token = ?", nil, accessToken).Scan(&oauthToken).Error; err != nil { 251 - s.logger.Error("error finding access token in db", "error", err) 252 return helpers.InputError(e, nil) 253 } 254 ··· 257 } 258 259 if *oauthToken.Parameters.DpopJkt != proof.JKT { 260 - s.logger.Error("jkt mismatch", "token", oauthToken.Parameters.DpopJkt, "proof", proof.JKT) 261 return helpers.InputError(e, to.StringPtr("dpop jkt mismatch")) 262 } 263 ··· 272 273 repo, err := s.getRepoActorByDid(ctx, oauthToken.Sub) 274 if err != nil { 275 - s.logger.Error("could not find actor in db", "error", err) 276 return helpers.ServerError(e, nil) 277 } 278
··· 38 func (s *Server) handleLegacySessionMiddleware(next echo.HandlerFunc) echo.HandlerFunc { 39 return func(e echo.Context) error { 40 ctx := e.Request().Context() 41 + logger := s.logger.With("name", "handleLegacySessionMiddleware") 42 43 authheader := e.Request().Header.Get("authorization") 44 if authheader == "" { ··· 70 if hasLxm { 71 pts := strings.Split(e.Request().URL.String(), "/") 72 if lxm != pts[len(pts)-1] { 73 + logger.Error("service auth lxm incorrect", "lxm", lxm, "expected", pts[len(pts)-1], "error", err) 74 return helpers.InputError(e, nil) 75 } 76 77 maybeDid, ok := claims["iss"].(string) 78 if !ok { 79 + logger.Error("no iss in service auth token", "error", err) 80 return helpers.InputError(e, nil) 81 } 82 did = maybeDid 83 84 maybeRepo, err := s.getRepoActorByDid(ctx, did) 85 if err != nil { 86 + logger.Error("error fetching repo", "error", err) 87 return helpers.ServerError(e, nil) 88 } 89 repo = maybeRepo ··· 97 return s.privateKey.Public(), nil 98 }) 99 if err != nil { 100 + logger.Error("error parsing jwt", "error", err) 101 return helpers.ExpiredTokenError(e) 102 } 103 ··· 110 hash := sha256.Sum256([]byte(signingInput)) 111 sigBytes, err := base64.RawURLEncoding.DecodeString(kpts[2]) 112 if err != nil { 113 + logger.Error("error decoding signature bytes", "error", err) 114 return helpers.ServerError(e, nil) 115 } 116 117 if len(sigBytes) != 64 { 118 + logger.Error("incorrect sigbytes length", "length", len(sigBytes)) 119 return helpers.ServerError(e, nil) 120 } 121 ··· 124 rr, _ := secp256k1.NewScalarFromBytes((*[32]byte)(rBytes)) 125 ss, _ := secp256k1.NewScalarFromBytes((*[32]byte)(sBytes)) 126 127 + if repo == nil { 128 + sub, ok := claims["sub"].(string) 129 + if !ok { 130 + s.logger.Error("no sub claim in ES256K token and repo not set") 131 + return helpers.InvalidTokenError(e) 132 + } 133 + maybeRepo, err := s.getRepoActorByDid(ctx, sub) 134 + if err != nil { 135 + s.logger.Error("error fetching repo for ES256K verification", "error", err) 136 + return helpers.ServerError(e, nil) 137 + } 138 + repo = maybeRepo 139 + did = sub 140 + } 141 + 142 sk, err := secp256k1secec.NewPrivateKey(repo.SigningKey) 143 if err != nil { 144 + logger.Error("can't load private key", "error", err) 145 return err 146 } 147 148 pubKey, ok := sk.Public().(*secp256k1secec.PublicKey) 149 if !ok { 150 + logger.Error("error getting public key from sk") 151 return helpers.ServerError(e, nil) 152 } 153 154 verified := pubKey.VerifyRaw(hash[:], rr, ss) 155 if !verified { 156 + logger.Error("error verifying", "error", err) 157 return helpers.ServerError(e, nil) 158 } 159 } ··· 182 return helpers.InvalidTokenError(e) 183 } 184 185 + logger.Error("error getting token from db", "error", err) 186 return helpers.ServerError(e, nil) 187 } 188 ··· 193 194 exp, ok := claims["exp"].(float64) 195 if !ok { 196 + logger.Error("error getting iat from token") 197 return helpers.ServerError(e, nil) 198 } 199 ··· 204 if repo == nil { 205 maybeRepo, err := s.getRepoActorByDid(ctx, claims["sub"].(string)) 206 if err != nil { 207 + logger.Error("error fetching repo", "error", err) 208 return helpers.ServerError(e, nil) 209 } 210 repo = maybeRepo ··· 226 func (s *Server) handleOauthSessionMiddleware(next echo.HandlerFunc) echo.HandlerFunc { 227 return func(e echo.Context) error { 228 ctx := e.Request().Context() 229 + logger := s.logger.With("name", "handleOauthSessionMiddleware") 230 231 authheader := e.Request().Header.Get("authorization") 232 if authheader == "" { ··· 259 "error": "use_dpop_nonce", 260 }) 261 } 262 + logger.Error("invalid dpop proof", "error", err) 263 return helpers.InputError(e, nil) 264 } 265 266 var oauthToken provider.OauthToken 267 if err := s.db.Raw(ctx, "SELECT * FROM oauth_tokens WHERE token = ?", nil, accessToken).Scan(&oauthToken).Error; err != nil { 268 + logger.Error("error finding access token in db", "error", err) 269 return helpers.InputError(e, nil) 270 } 271 ··· 274 } 275 276 if *oauthToken.Parameters.DpopJkt != proof.JKT { 277 + logger.Error("jkt mismatch", "token", oauthToken.Parameters.DpopJkt, "proof", proof.JKT) 278 return helpers.InputError(e, to.StringPtr("dpop jkt mismatch")) 279 } 280 ··· 289 290 repo, err := s.getRepoActorByDid(ctx, oauthToken.Sub) 291 if err != nil { 292 + logger.Error("could not find actor in db", "error", err) 293 return helpers.ServerError(e, nil) 294 } 295
+7
server/repo.go
··· 17 lexutil "github.com/bluesky-social/indigo/lex/util" 18 "github.com/bluesky-social/indigo/repo" 19 "github.com/haileyok/cocoon/internal/db" 20 "github.com/haileyok/cocoon/models" 21 "github.com/haileyok/cocoon/recording_blockstore" 22 blocks "github.com/ipfs/go-block-format" ··· 249 newroot, rev, err := r.Commit(ctx, urepo.SignFor) 250 if err != nil { 251 return nil, err 252 } 253 254 // create a buffer for dumping our new cbor into
··· 17 lexutil "github.com/bluesky-social/indigo/lex/util" 18 "github.com/bluesky-social/indigo/repo" 19 "github.com/haileyok/cocoon/internal/db" 20 + "github.com/haileyok/cocoon/metrics" 21 "github.com/haileyok/cocoon/models" 22 "github.com/haileyok/cocoon/recording_blockstore" 23 blocks "github.com/ipfs/go-block-format" ··· 250 newroot, rev, err := r.Commit(ctx, urepo.SignFor) 251 if err != nil { 252 return nil, err 253 + } 254 + 255 + for _, result := range results { 256 + if result.Type != nil { 257 + metrics.RepoOperations.WithLabelValues(*result.Type).Inc() 258 + } 259 } 260 261 // create a buffer for dumping our new cbor into
+38 -27
server/server.go
··· 39 "github.com/haileyok/cocoon/oauth/provider" 40 "github.com/haileyok/cocoon/plc" 41 "github.com/ipfs/go-cid" 42 echo_session "github.com/labstack/echo-contrib/session" 43 "github.com/labstack/echo/v4" 44 "github.com/labstack/echo/v4/middleware" ··· 89 } 90 91 type Args struct { 92 Addr string 93 DbName string 94 DbType string 95 DatabaseURL string 96 - Logger *slog.Logger 97 Version string 98 Did string 99 Hostname string ··· 209 } 210 211 func New(args *Args) (*Server, error) { 212 if args.Addr == "" { 213 return nil, fmt.Errorf("addr must be set") 214 } ··· 237 return nil, fmt.Errorf("admin password must be set") 238 } 239 240 - if args.Logger == nil { 241 - args.Logger = slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{})) 242 - } 243 - 244 if args.SessionSecret == "" { 245 panic("SESSION SECRET WAS NOT SET. THIS IS REQUIRED. ") 246 } ··· 248 e := echo.New() 249 250 e.Pre(middleware.RemoveTrailingSlash()) 251 - e.Pre(slogecho.New(args.Logger)) 252 e.Use(echo_session.Middleware(sessions.NewCookieStore([]byte(args.SessionSecret)))) 253 e.Use(middleware.CORSWithConfig(middleware.CORSConfig{ 254 AllowOrigins: []string{"*"}, 255 AllowHeaders: []string{"*"}, ··· 311 if err != nil { 312 return nil, fmt.Errorf("failed to connect to postgres: %w", err) 313 } 314 - args.Logger.Info("connected to PostgreSQL database") 315 default: 316 gdb, err = gorm.Open(sqlite.Open(args.DbName), &gorm.Config{}) 317 if err != nil { 318 return nil, fmt.Errorf("failed to open sqlite database: %w", err) 319 } 320 - args.Logger.Info("connected to SQLite database", "path", args.DbName) 321 } 322 dbw := db.NewDB(gdb) 323 ··· 360 var nonceSecret []byte 361 maybeSecret, err := os.ReadFile("nonce.secret") 362 if err != nil && !os.IsNotExist(err) { 363 - args.Logger.Error("error attempting to read nonce secret", "error", err) 364 } else { 365 nonceSecret = maybeSecret 366 } ··· 398 Hostname: args.Hostname, 399 ClientManagerArgs: client.ManagerArgs{ 400 Cli: oauthCli, 401 - Logger: args.Logger, 402 }, 403 DpopManagerArgs: dpop.ManagerArgs{ 404 NonceSecret: nonceSecret, 405 NonceRotationInterval: constants.NonceMaxRotationInterval / 3, 406 OnNonceSecretCreated: func(newNonce []byte) { 407 if err := os.WriteFile("nonce.secret", newNonce, 0644); err != nil { 408 - args.Logger.Error("error writing new nonce secret", "error", err) 409 } 410 }, 411 - Logger: args.Logger, 412 Hostname: args.Hostname, 413 }, 414 }), ··· 535 } 536 537 func (s *Server) Serve(ctx context.Context) error { 538 s.addRoutes() 539 540 - s.logger.Info("migrating...") 541 542 s.db.AutoMigrate( 543 &models.Actor{}, ··· 554 &provider.OauthAuthorizationRequest{}, 555 ) 556 557 - s.logger.Info("starting cocoon") 558 559 go func() { 560 if err := s.httpd.ListenAndServe(); err != nil { ··· 566 567 go func() { 568 if err := s.requestCrawl(ctx); err != nil { 569 - s.logger.Error("error requesting crawls", "err", err) 570 } 571 }() 572 ··· 584 585 logger.Info("requesting crawl with configured relays") 586 587 - if time.Now().Sub(s.lastRequestCrawl) <= 1*time.Minute { 588 return fmt.Errorf("a crawl request has already been made within the last minute") 589 } 590 ··· 607 } 608 609 func (s *Server) doBackup() { 610 if s.dbType == "postgres" { 611 - s.logger.Info("skipping S3 backup - PostgreSQL backups should be handled externally (pg_dump, managed database backups, etc.)") 612 return 613 } 614 615 start := time.Now() 616 617 - s.logger.Info("beginning backup to s3...") 618 619 var buf bytes.Buffer 620 if err := func() error { 621 - s.logger.Info("reading database bytes...") 622 s.db.Lock() 623 defer s.db.Unlock() 624 ··· 634 635 return nil 636 }(); err != nil { 637 - s.logger.Error("error backing up database", "error", err) 638 return 639 } 640 641 if err := func() error { 642 - s.logger.Info("sending to s3...") 643 644 currTime := time.Now().Format("2006-01-02_15-04-05") 645 key := "cocoon-backup-" + currTime + ".db" ··· 669 return fmt.Errorf("error uploading file to s3: %w", err) 670 } 671 672 - s.logger.Info("finished uploading backup to s3", "key", key, "duration", time.Now().Sub(start).Seconds()) 673 674 return nil 675 }(); err != nil { 676 - s.logger.Error("error uploading database backup", "error", err) 677 return 678 } 679 ··· 681 } 682 683 func (s *Server) backupRoutine() { 684 if s.s3Config == nil || !s.s3Config.BackupsEnabled { 685 return 686 } 687 688 if s.s3Config.Region == "" { 689 - s.logger.Warn("no s3 region configured but backups are enabled. backups will not run.") 690 return 691 } 692 693 if s.s3Config.Bucket == "" { 694 - s.logger.Warn("no s3 bucket configured but backups are enabled. backups will not run.") 695 return 696 } 697 698 if s.s3Config.AccessKey == "" { 699 - s.logger.Warn("no s3 access key configured but backups are enabled. backups will not run.") 700 return 701 } 702 703 if s.s3Config.SecretKey == "" { 704 - s.logger.Warn("no s3 secret key configured but backups are enabled. backups will not run.") 705 return 706 } 707
··· 39 "github.com/haileyok/cocoon/oauth/provider" 40 "github.com/haileyok/cocoon/plc" 41 "github.com/ipfs/go-cid" 42 + "github.com/labstack/echo-contrib/echoprometheus" 43 echo_session "github.com/labstack/echo-contrib/session" 44 "github.com/labstack/echo/v4" 45 "github.com/labstack/echo/v4/middleware" ··· 90 } 91 92 type Args struct { 93 + Logger *slog.Logger 94 + 95 Addr string 96 DbName string 97 DbType string 98 DatabaseURL string 99 Version string 100 Did string 101 Hostname string ··· 211 } 212 213 func New(args *Args) (*Server, error) { 214 + if args.Logger == nil { 215 + args.Logger = slog.Default() 216 + } 217 + 218 + logger := args.Logger.With("name", "New") 219 + 220 if args.Addr == "" { 221 return nil, fmt.Errorf("addr must be set") 222 } ··· 245 return nil, fmt.Errorf("admin password must be set") 246 } 247 248 if args.SessionSecret == "" { 249 panic("SESSION SECRET WAS NOT SET. THIS IS REQUIRED. ") 250 } ··· 252 e := echo.New() 253 254 e.Pre(middleware.RemoveTrailingSlash()) 255 + e.Pre(slogecho.New(args.Logger.With("component", "slogecho"))) 256 e.Use(echo_session.Middleware(sessions.NewCookieStore([]byte(args.SessionSecret)))) 257 + e.Use(echoprometheus.NewMiddleware("cocoon")) 258 e.Use(middleware.CORSWithConfig(middleware.CORSConfig{ 259 AllowOrigins: []string{"*"}, 260 AllowHeaders: []string{"*"}, ··· 316 if err != nil { 317 return nil, fmt.Errorf("failed to connect to postgres: %w", err) 318 } 319 + logger.Info("connected to PostgreSQL database") 320 default: 321 gdb, err = gorm.Open(sqlite.Open(args.DbName), &gorm.Config{}) 322 if err != nil { 323 return nil, fmt.Errorf("failed to open sqlite database: %w", err) 324 } 325 + logger.Info("connected to SQLite database", "path", args.DbName) 326 } 327 dbw := db.NewDB(gdb) 328 ··· 365 var nonceSecret []byte 366 maybeSecret, err := os.ReadFile("nonce.secret") 367 if err != nil && !os.IsNotExist(err) { 368 + logger.Error("error attempting to read nonce secret", "error", err) 369 } else { 370 nonceSecret = maybeSecret 371 } ··· 403 Hostname: args.Hostname, 404 ClientManagerArgs: client.ManagerArgs{ 405 Cli: oauthCli, 406 + Logger: args.Logger.With("component", "oauth-client-manager"), 407 }, 408 DpopManagerArgs: dpop.ManagerArgs{ 409 NonceSecret: nonceSecret, 410 NonceRotationInterval: constants.NonceMaxRotationInterval / 3, 411 OnNonceSecretCreated: func(newNonce []byte) { 412 if err := os.WriteFile("nonce.secret", newNonce, 0644); err != nil { 413 + logger.Error("error writing new nonce secret", "error", err) 414 } 415 }, 416 + Logger: args.Logger.With("component", "dpop-manager"), 417 Hostname: args.Hostname, 418 }, 419 }), ··· 540 } 541 542 func (s *Server) Serve(ctx context.Context) error { 543 + logger := s.logger.With("name", "Serve") 544 + 545 s.addRoutes() 546 547 + logger.Info("migrating...") 548 549 s.db.AutoMigrate( 550 &models.Actor{}, ··· 561 &provider.OauthAuthorizationRequest{}, 562 ) 563 564 + logger.Info("starting cocoon") 565 566 go func() { 567 if err := s.httpd.ListenAndServe(); err != nil { ··· 573 574 go func() { 575 if err := s.requestCrawl(ctx); err != nil { 576 + logger.Error("error requesting crawls", "err", err) 577 } 578 }() 579 ··· 591 592 logger.Info("requesting crawl with configured relays") 593 594 + if time.Since(s.lastRequestCrawl) <= 1*time.Minute { 595 return fmt.Errorf("a crawl request has already been made within the last minute") 596 } 597 ··· 614 } 615 616 func (s *Server) doBackup() { 617 + logger := s.logger.With("name", "doBackup") 618 + 619 if s.dbType == "postgres" { 620 + logger.Info("skipping S3 backup - PostgreSQL backups should be handled externally (pg_dump, managed database backups, etc.)") 621 return 622 } 623 624 start := time.Now() 625 626 + logger.Info("beginning backup to s3...") 627 628 var buf bytes.Buffer 629 if err := func() error { 630 + logger.Info("reading database bytes...") 631 s.db.Lock() 632 defer s.db.Unlock() 633 ··· 643 644 return nil 645 }(); err != nil { 646 + logger.Error("error backing up database", "error", err) 647 return 648 } 649 650 if err := func() error { 651 + logger.Info("sending to s3...") 652 653 currTime := time.Now().Format("2006-01-02_15-04-05") 654 key := "cocoon-backup-" + currTime + ".db" ··· 678 return fmt.Errorf("error uploading file to s3: %w", err) 679 } 680 681 + logger.Info("finished uploading backup to s3", "key", key, "duration", time.Now().Sub(start).Seconds()) 682 683 return nil 684 }(); err != nil { 685 + logger.Error("error uploading database backup", "error", err) 686 return 687 } 688 ··· 690 } 691 692 func (s *Server) backupRoutine() { 693 + logger := s.logger.With("name", "backupRoutine") 694 + 695 if s.s3Config == nil || !s.s3Config.BackupsEnabled { 696 return 697 } 698 699 if s.s3Config.Region == "" { 700 + logger.Warn("no s3 region configured but backups are enabled. backups will not run.") 701 return 702 } 703 704 if s.s3Config.Bucket == "" { 705 + logger.Warn("no s3 bucket configured but backups are enabled. backups will not run.") 706 return 707 } 708 709 if s.s3Config.AccessKey == "" { 710 + logger.Warn("no s3 access key configured but backups are enabled. backups will not run.") 711 return 712 } 713 714 if s.s3Config.SecretKey == "" { 715 + logger.Warn("no s3 secret key configured but backups are enabled. backups will not run.") 716 return 717 } 718
+1 -1
test.go
··· 32 33 u.Path = "xrpc/com.atproto.sync.subscribeRepos" 34 conn, _, err := dialer.Dial(u.String(), http.Header{ 35 - "User-Agent": []string{fmt.Sprintf("hot-topic/0.0.0")}, 36 }) 37 if err != nil { 38 return fmt.Errorf("subscribing to firehose failed (dialing): %w", err)
··· 32 33 u.Path = "xrpc/com.atproto.sync.subscribeRepos" 34 conn, _, err := dialer.Dial(u.String(), http.Header{ 35 + "User-Agent": []string{"cocoon-test/0.0.0"}, 36 }) 37 if err != nil { 38 return fmt.Errorf("subscribing to firehose failed (dialing): %w", err)