chore: mercury changes
This commit is contained in:
parent
d4e021386b
commit
1f8b4ab24f
1
go.mod
1
go.mod
|
@ -61,6 +61,7 @@ require (
|
|||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 // indirect
|
||||
github.com/oklog/ulid/v2 v2.1.0
|
||||
github.com/prometheus/client_golang v1.18.0
|
||||
github.com/tursodatabase/go-libsql v0.0.0-20240322134723-08771dcdd2f1
|
||||
go.nhat.io/otelsql v0.12.0
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.48.0
|
||||
go.opentelemetry.io/contrib/instrumentation/runtime v0.48.0
|
||||
|
|
334
go.work.sum
Normal file
334
go.work.sum
Normal file
|
@ -0,0 +1,334 @@
|
|||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.112.0/go.mod h1:3jEEVwZ/MHU4djK5t5RHuKOA/GbLddgTdVubX1qnPD4=
|
||||
cloud.google.com/go/accessapproval v1.7.5/go.mod h1:g88i1ok5dvQ9XJsxpUInWWvUBrIZhyPDPbk4T01OoJ0=
|
||||
cloud.google.com/go/accesscontextmanager v1.8.5/go.mod h1:TInEhcZ7V9jptGNqN3EzZ5XMhT6ijWxTGjzyETwmL0Q=
|
||||
cloud.google.com/go/aiplatform v1.60.0/go.mod h1:eTlGuHOahHprZw3Hio5VKmtThIOak5/qy6pzdsqcQnM=
|
||||
cloud.google.com/go/analytics v0.23.0/go.mod h1:YPd7Bvik3WS95KBok2gPXDqQPHy08TsCQG6CdUCb+u0=
|
||||
cloud.google.com/go/apigateway v1.6.5/go.mod h1:6wCwvYRckRQogyDDltpANi3zsCDl6kWi0b4Je+w2UiI=
|
||||
cloud.google.com/go/apigeeconnect v1.6.5/go.mod h1:MEKm3AiT7s11PqTfKE3KZluZA9O91FNysvd3E6SJ6Ow=
|
||||
cloud.google.com/go/apigeeregistry v0.8.3/go.mod h1:aInOWnqF4yMQx8kTjDqHNXjZGh/mxeNlAf52YqtASUs=
|
||||
cloud.google.com/go/appengine v1.8.5/go.mod h1:uHBgNoGLTS5di7BvU25NFDuKa82v0qQLjyMJLuPQrVo=
|
||||
cloud.google.com/go/area120 v0.8.5/go.mod h1:BcoFCbDLZjsfe4EkCnEq1LKvHSK0Ew/zk5UFu6GMyA0=
|
||||
cloud.google.com/go/artifactregistry v1.14.7/go.mod h1:0AUKhzWQzfmeTvT4SjfI4zjot72EMfrkvL9g9aRjnnM=
|
||||
cloud.google.com/go/asset v1.17.2/go.mod h1:SVbzde67ehddSoKf5uebOD1sYw8Ab/jD/9EIeWg99q4=
|
||||
cloud.google.com/go/assuredworkloads v1.11.5/go.mod h1:FKJ3g3ZvkL2D7qtqIGnDufFkHxwIpNM9vtmhvt+6wqk=
|
||||
cloud.google.com/go/automl v1.13.5/go.mod h1:MDw3vLem3yh+SvmSgeYUmUKqyls6NzSumDm9OJ3xJ1Y=
|
||||
cloud.google.com/go/baremetalsolution v1.2.4/go.mod h1:BHCmxgpevw9IEryE99HbYEfxXkAEA3hkMJbYYsHtIuY=
|
||||
cloud.google.com/go/batch v1.8.0/go.mod h1:k8V7f6VE2Suc0zUM4WtoibNrA6D3dqBpB+++e3vSGYc=
|
||||
cloud.google.com/go/beyondcorp v1.0.4/go.mod h1:Gx8/Rk2MxrvWfn4WIhHIG1NV7IBfg14pTKv1+EArVcc=
|
||||
cloud.google.com/go/bigquery v1.59.1/go.mod h1:VP1UJYgevyTwsV7desjzNzDND5p6hZB+Z8gZJN1GQUc=
|
||||
cloud.google.com/go/billing v1.18.2/go.mod h1:PPIwVsOOQ7xzbADCwNe8nvK776QpfrOAUkvKjCUcpSE=
|
||||
cloud.google.com/go/binaryauthorization v1.8.1/go.mod h1:1HVRyBerREA/nhI7yLang4Zn7vfNVA3okoAR9qYQJAQ=
|
||||
cloud.google.com/go/certificatemanager v1.7.5/go.mod h1:uX+v7kWqy0Y3NG/ZhNvffh0kuqkKZIXdvlZRO7z0VtM=
|
||||
cloud.google.com/go/channel v1.17.5/go.mod h1:FlpaOSINDAXgEext0KMaBq/vwpLMkkPAw9b2mApQeHc=
|
||||
cloud.google.com/go/cloudbuild v1.15.1/go.mod h1:gIofXZSu+XD2Uy+qkOrGKEx45zd7s28u/k8f99qKals=
|
||||
cloud.google.com/go/clouddms v1.7.4/go.mod h1:RdrVqoFG9RWI5AvZ81SxJ/xvxPdtcRhFotwdE79DieY=
|
||||
cloud.google.com/go/cloudtasks v1.12.6/go.mod h1:b7c7fe4+TJsFZfDyzO51F7cjq7HLUlRi/KZQLQjDsaY=
|
||||
cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM=
|
||||
cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI=
|
||||
cloud.google.com/go/compute v1.24.0/go.mod h1:kw1/T+h/+tK2LJK0wiPPx1intgdAM3j/g3hFDlscY40=
|
||||
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
|
||||
cloud.google.com/go/contactcenterinsights v1.13.0/go.mod h1:ieq5d5EtHsu8vhe2y3amtZ+BE+AQwX5qAy7cpo0POsI=
|
||||
cloud.google.com/go/container v1.31.0/go.mod h1:7yABn5s3Iv3lmw7oMmyGbeV6tQj86njcTijkkGuvdZA=
|
||||
cloud.google.com/go/containeranalysis v0.11.4/go.mod h1:cVZT7rXYBS9NG1rhQbWL9pWbXCKHWJPYraE8/FTSYPE=
|
||||
cloud.google.com/go/datacatalog v1.19.3/go.mod h1:ra8V3UAsciBpJKQ+z9Whkxzxv7jmQg1hfODr3N3YPJ4=
|
||||
cloud.google.com/go/dataflow v0.9.5/go.mod h1:udl6oi8pfUHnL0z6UN9Lf9chGqzDMVqcYTcZ1aPnCZQ=
|
||||
cloud.google.com/go/dataform v0.9.2/go.mod h1:S8cQUwPNWXo7m/g3DhWHsLBoufRNn9EgFrMgne2j7cI=
|
||||
cloud.google.com/go/datafusion v1.7.5/go.mod h1:bYH53Oa5UiqahfbNK9YuYKteeD4RbQSNMx7JF7peGHc=
|
||||
cloud.google.com/go/datalabeling v0.8.5/go.mod h1:IABB2lxQnkdUbMnQaOl2prCOfms20mcPxDBm36lps+s=
|
||||
cloud.google.com/go/dataplex v1.14.2/go.mod h1:0oGOSFlEKef1cQeAHXy4GZPB/Ife0fz/PxBf+ZymA2U=
|
||||
cloud.google.com/go/dataproc v1.12.0/go.mod h1:zrF3aX0uV3ikkMz6z4uBbIKyhRITnxvr4i3IjKsKrw4=
|
||||
cloud.google.com/go/dataproc/v2 v2.4.0/go.mod h1:3B1Ht2aRB8VZIteGxQS/iNSJGzt9+CA0WGnDVMEm7Z4=
|
||||
cloud.google.com/go/dataqna v0.8.5/go.mod h1:vgihg1mz6n7pb5q2YJF7KlXve6tCglInd6XO0JGOlWM=
|
||||
cloud.google.com/go/datastore v1.15.0/go.mod h1:GAeStMBIt9bPS7jMJA85kgkpsMkvseWWXiaHya9Jes8=
|
||||
cloud.google.com/go/datastream v1.10.4/go.mod h1:7kRxPdxZxhPg3MFeCSulmAJnil8NJGGvSNdn4p1sRZo=
|
||||
cloud.google.com/go/deploy v1.17.1/go.mod h1:SXQyfsXrk0fBmgBHRzBjQbZhMfKZ3hMQBw5ym7MN/50=
|
||||
cloud.google.com/go/dialogflow v1.49.0/go.mod h1:dhVrXKETtdPlpPhE7+2/k4Z8FRNUp6kMV3EW3oz/fe0=
|
||||
cloud.google.com/go/dlp v1.11.2/go.mod h1:9Czi+8Y/FegpWzgSfkRlyz+jwW6Te9Rv26P3UfU/h/w=
|
||||
cloud.google.com/go/documentai v1.25.0/go.mod h1:ftLnzw5VcXkLItp6pw1mFic91tMRyfv6hHEY5br4KzY=
|
||||
cloud.google.com/go/domains v0.9.5/go.mod h1:dBzlxgepazdFhvG7u23XMhmMKBjrkoUNaw0A8AQB55Y=
|
||||
cloud.google.com/go/edgecontainer v1.1.5/go.mod h1:rgcjrba3DEDEQAidT4yuzaKWTbkTI5zAMu3yy6ZWS0M=
|
||||
cloud.google.com/go/errorreporting v0.3.0/go.mod h1:xsP2yaAp+OAW4OIm60An2bbLpqIhKXdWR/tawvl7QzU=
|
||||
cloud.google.com/go/essentialcontacts v1.6.6/go.mod h1:XbqHJGaiH0v2UvtuucfOzFXN+rpL/aU5BCZLn4DYl1Q=
|
||||
cloud.google.com/go/eventarc v1.13.4/go.mod h1:zV5sFVoAa9orc/52Q+OuYUG9xL2IIZTbbuTHC6JSY8s=
|
||||
cloud.google.com/go/filestore v1.8.1/go.mod h1:MbN9KcaM47DRTIuLfQhJEsjaocVebNtNQhSLhKCF5GM=
|
||||
cloud.google.com/go/firestore v1.14.0/go.mod h1:96MVaHLsEhbvkBEdZgfN+AS/GIkco1LRpH9Xp9YZfzQ=
|
||||
cloud.google.com/go/functions v1.16.0/go.mod h1:nbNpfAG7SG7Duw/o1iZ6ohvL7mc6MapWQVpqtM29n8k=
|
||||
cloud.google.com/go/gkebackup v1.3.5/go.mod h1:KJ77KkNN7Wm1LdMopOelV6OodM01pMuK2/5Zt1t4Tvc=
|
||||
cloud.google.com/go/gkeconnect v0.8.5/go.mod h1:LC/rS7+CuJ5fgIbXv8tCD/mdfnlAadTaUufgOkmijuk=
|
||||
cloud.google.com/go/gkehub v0.14.5/go.mod h1:6bzqxM+a+vEH/h8W8ec4OJl4r36laxTs3A/fMNHJ0wA=
|
||||
cloud.google.com/go/gkemulticloud v1.1.1/go.mod h1:C+a4vcHlWeEIf45IB5FFR5XGjTeYhF83+AYIpTy4i2Q=
|
||||
cloud.google.com/go/grafeas v0.3.4/go.mod h1:A5m316hcG+AulafjAbPKXBO/+I5itU4LOdKO2R/uDIc=
|
||||
cloud.google.com/go/gsuiteaddons v1.6.5/go.mod h1:Lo4P2IvO8uZ9W+RaC6s1JVxo42vgy+TX5a6hfBZ0ubs=
|
||||
cloud.google.com/go/iam v1.1.6/go.mod h1:O0zxdPeGBoFdWW3HWmBxJsk0pfvNM/p/qa82rWOGTwI=
|
||||
cloud.google.com/go/iap v1.9.4/go.mod h1:vO4mSq0xNf/Pu6E5paORLASBwEmphXEjgCFg7aeNu1w=
|
||||
cloud.google.com/go/ids v1.4.5/go.mod h1:p0ZnyzjMWxww6d2DvMGnFwCsSxDJM666Iir1bK1UuBo=
|
||||
cloud.google.com/go/iot v1.7.5/go.mod h1:nq3/sqTz3HGaWJi1xNiX7F41ThOzpud67vwk0YsSsqs=
|
||||
cloud.google.com/go/kms v1.15.7/go.mod h1:ub54lbsa6tDkUwnu4W7Yt1aAIFLnspgh0kPGToDukeI=
|
||||
cloud.google.com/go/language v1.12.3/go.mod h1:evFX9wECX6mksEva8RbRnr/4wi/vKGYnAJrTRXU8+f8=
|
||||
cloud.google.com/go/lifesciences v0.9.5/go.mod h1:OdBm0n7C0Osh5yZB7j9BXyrMnTRGBJIZonUMxo5CzPw=
|
||||
cloud.google.com/go/logging v1.9.0/go.mod h1:1Io0vnZv4onoUnsVUQY3HZ3Igb1nBchky0A0y7BBBhE=
|
||||
cloud.google.com/go/longrunning v0.5.5/go.mod h1:WV2LAxD8/rg5Z1cNW6FJ/ZpX4E4VnDnoTk0yawPBB7s=
|
||||
cloud.google.com/go/managedidentities v1.6.5/go.mod h1:fkFI2PwwyRQbjLxlm5bQ8SjtObFMW3ChBGNqaMcgZjI=
|
||||
cloud.google.com/go/maps v1.6.4/go.mod h1:rhjqRy8NWmDJ53saCfsXQ0LKwBHfi6OSh5wkq6BaMhI=
|
||||
cloud.google.com/go/mediatranslation v0.8.5/go.mod h1:y7kTHYIPCIfgyLbKncgqouXJtLsU+26hZhHEEy80fSs=
|
||||
cloud.google.com/go/memcache v1.10.5/go.mod h1:/FcblbNd0FdMsx4natdj+2GWzTq+cjZvMa1I+9QsuMA=
|
||||
cloud.google.com/go/metastore v1.13.4/go.mod h1:FMv9bvPInEfX9Ac1cVcRXp8EBBQnBcqH6gz3KvJ9BAE=
|
||||
cloud.google.com/go/monitoring v1.18.0/go.mod h1:c92vVBCeq/OB4Ioyo+NbN2U7tlg5ZH41PZcdvfc+Lcg=
|
||||
cloud.google.com/go/networkconnectivity v1.14.4/go.mod h1:PU12q++/IMnDJAB+3r+tJtuCXCfwfN+C6Niyj6ji1Po=
|
||||
cloud.google.com/go/networkmanagement v1.9.4/go.mod h1:daWJAl0KTFytFL7ar33I6R/oNBH8eEOX/rBNHrC/8TA=
|
||||
cloud.google.com/go/networksecurity v0.9.5/go.mod h1:KNkjH/RsylSGyyZ8wXpue8xpCEK+bTtvof8SBfIhMG8=
|
||||
cloud.google.com/go/notebooks v1.11.3/go.mod h1:0wQyI2dQC3AZyQqWnRsp+yA+kY4gC7ZIVP4Qg3AQcgo=
|
||||
cloud.google.com/go/optimization v1.6.3/go.mod h1:8ve3svp3W6NFcAEFr4SfJxrldzhUl4VMUJmhrqVKtYA=
|
||||
cloud.google.com/go/orchestration v1.8.5/go.mod h1:C1J7HesE96Ba8/hZ71ISTV2UAat0bwN+pi85ky38Yq8=
|
||||
cloud.google.com/go/orgpolicy v1.12.1/go.mod h1:aibX78RDl5pcK3jA8ysDQCFkVxLj3aOQqrbBaUL2V5I=
|
||||
cloud.google.com/go/osconfig v1.12.5/go.mod h1:D9QFdxzfjgw3h/+ZaAb5NypM8bhOMqBzgmbhzWViiW8=
|
||||
cloud.google.com/go/oslogin v1.13.1/go.mod h1:vS8Sr/jR7QvPWpCjNqy6LYZr5Zs1e8ZGW/KPn9gmhws=
|
||||
cloud.google.com/go/phishingprotection v0.8.5/go.mod h1:g1smd68F7mF1hgQPuYn3z8HDbNre8L6Z0b7XMYFmX7I=
|
||||
cloud.google.com/go/policytroubleshooter v1.10.3/go.mod h1:+ZqG3agHT7WPb4EBIRqUv4OyIwRTZvsVDHZ8GlZaoxk=
|
||||
cloud.google.com/go/privatecatalog v0.9.5/go.mod h1:fVWeBOVe7uj2n3kWRGlUQqR/pOd450J9yZoOECcQqJk=
|
||||
cloud.google.com/go/pubsub v1.36.1/go.mod h1:iYjCa9EzWOoBiTdd4ps7QoMtMln5NwaZQpK1hbRfBDE=
|
||||
cloud.google.com/go/pubsublite v1.8.1/go.mod h1:fOLdU4f5xldK4RGJrBMm+J7zMWNj/k4PxwEZXy39QS0=
|
||||
cloud.google.com/go/recaptchaenterprise/v2 v2.9.2/go.mod h1:trwwGkfhCmp05Ll5MSJPXY7yvnO0p4v3orGANAFHAuU=
|
||||
cloud.google.com/go/recommendationengine v0.8.5/go.mod h1:A38rIXHGFvoPvmy6pZLozr0g59NRNREz4cx7F58HAsQ=
|
||||
cloud.google.com/go/recommender v1.12.1/go.mod h1:gf95SInWNND5aPas3yjwl0I572dtudMhMIG4ni8nr+0=
|
||||
cloud.google.com/go/redis v1.14.2/go.mod h1:g0Lu7RRRz46ENdFKQ2EcQZBAJ2PtJHJLuiiRuEXwyQw=
|
||||
cloud.google.com/go/resourcemanager v1.9.5/go.mod h1:hep6KjelHA+ToEjOfO3garMKi/CLYwTqeAw7YiEI9x8=
|
||||
cloud.google.com/go/resourcesettings v1.6.5/go.mod h1:WBOIWZraXZOGAgoR4ukNj0o0HiSMO62H9RpFi9WjP9I=
|
||||
cloud.google.com/go/retail v1.16.0/go.mod h1:LW7tllVveZo4ReWt68VnldZFWJRzsh9np+01J9dYWzE=
|
||||
cloud.google.com/go/run v1.3.4/go.mod h1:FGieuZvQ3tj1e9GnzXqrMABSuir38AJg5xhiYq+SF3o=
|
||||
cloud.google.com/go/scheduler v1.10.6/go.mod h1:pe2pNCtJ+R01E06XCDOJs1XvAMbv28ZsQEbqknxGOuE=
|
||||
cloud.google.com/go/secretmanager v1.11.5/go.mod h1:eAGv+DaCHkeVyQi0BeXgAHOU0RdrMeZIASKc+S7VqH4=
|
||||
cloud.google.com/go/security v1.15.5/go.mod h1:KS6X2eG3ynWjqcIX976fuToN5juVkF6Ra6c7MPnldtc=
|
||||
cloud.google.com/go/securitycenter v1.24.4/go.mod h1:PSccin+o1EMYKcFQzz9HMMnZ2r9+7jbc+LvPjXhpwcU=
|
||||
cloud.google.com/go/servicedirectory v1.11.4/go.mod h1:Bz2T9t+/Ehg6x+Y7Ycq5xiShYLD96NfEsWNHyitj1qM=
|
||||
cloud.google.com/go/shell v1.7.5/go.mod h1:hL2++7F47/IfpfTO53KYf1EC+F56k3ThfNEXd4zcuiE=
|
||||
cloud.google.com/go/spanner v1.56.0/go.mod h1:DndqtUKQAt3VLuV2Le+9Y3WTnq5cNKrnLb/Piqcj+h0=
|
||||
cloud.google.com/go/speech v1.21.1/go.mod h1:E5GHZXYQlkqWQwY5xRSLHw2ci5NMQNG52FfMU1aZrIA=
|
||||
cloud.google.com/go/storage v1.37.0/go.mod h1:i34TiT2IhiNDmcj65PqwCjcoUX7Z5pLzS8DEmoiFq1k=
|
||||
cloud.google.com/go/storagetransfer v1.10.4/go.mod h1:vef30rZKu5HSEf/x1tK3WfWrL0XVoUQN/EPDRGPzjZs=
|
||||
cloud.google.com/go/talent v1.6.6/go.mod h1:y/WQDKrhVz12WagoarpAIyKKMeKGKHWPoReZ0g8tseQ=
|
||||
cloud.google.com/go/texttospeech v1.7.5/go.mod h1:tzpCuNWPwrNJnEa4Pu5taALuZL4QRRLcb+K9pbhXT6M=
|
||||
cloud.google.com/go/tpu v1.6.5/go.mod h1:P9DFOEBIBhuEcZhXi+wPoVy/cji+0ICFi4TtTkMHSSs=
|
||||
cloud.google.com/go/trace v1.10.5/go.mod h1:9hjCV1nGBCtXbAE4YK7OqJ8pmPYSxPA0I67JwRd5s3M=
|
||||
cloud.google.com/go/translate v1.10.1/go.mod h1:adGZcQNom/3ogU65N9UXHOnnSvjPwA/jKQUMnsYXOyk=
|
||||
cloud.google.com/go/video v1.20.4/go.mod h1:LyUVjyW+Bwj7dh3UJnUGZfyqjEto9DnrvTe1f/+QrW0=
|
||||
cloud.google.com/go/videointelligence v1.11.5/go.mod h1:/PkeQjpRponmOerPeJxNPuxvi12HlW7Em0lJO14FC3I=
|
||||
cloud.google.com/go/vision/v2 v2.8.0/go.mod h1:ocqDiA2j97pvgogdyhoxiQp2ZkDCyr0HWpicywGGRhU=
|
||||
cloud.google.com/go/vmmigration v1.7.5/go.mod h1:pkvO6huVnVWzkFioxSghZxIGcsstDvYiVCxQ9ZH3eYI=
|
||||
cloud.google.com/go/vmwareengine v1.1.1/go.mod h1:nMpdsIVkUrSaX8UvmnBhzVzG7PPvNYc5BszcvIVudYs=
|
||||
cloud.google.com/go/vpcaccess v1.7.5/go.mod h1:slc5ZRvvjP78c2dnL7m4l4R9GwL3wDLcpIWz6P/ziig=
|
||||
cloud.google.com/go/webrisk v1.9.5/go.mod h1:aako0Fzep1Q714cPEM5E+mtYX8/jsfegAuS8aivxy3U=
|
||||
cloud.google.com/go/websecurityscanner v1.6.5/go.mod h1:QR+DWaxAz2pWooylsBF854/Ijvuoa3FCyS1zBa1rAVQ=
|
||||
cloud.google.com/go/workflows v1.12.4/go.mod h1:yQ7HUqOkdJK4duVtMeBCAOPiN1ZF1E9pAMX51vpwB/w=
|
||||
github.com/99designs/gqlgen v0.17.41/go.mod h1:GQ6SyMhwFbgHR0a8r2Wn8fYgEwPxxmndLFPhU63+cJE=
|
||||
github.com/PuerkitoBio/goquery v1.8.1/go.mod h1:Q8ICL1kNUJ2sXGoAhPGUdYDJvgQgHzJsnnd3H7Ho5jQ=
|
||||
github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE=
|
||||
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
|
||||
github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/apache/arrow/go/v14 v14.0.2/go.mod h1:u3fgh3EdgN/YQ8cVQRguVW3R+seMybFg8QBQ5LU+eBY=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
|
||||
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/go-control-plane v0.11.1/go.mod h1:uhMcXKCQMEJHiAb0w+YGefQLaTEw+YhGluxZkrTmD0g=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE=
|
||||
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
|
||||
github.com/gdamore/tcell/v2 v2.4.1-0.20210905002822-f057f0a857a1/go.mod h1:Az6Jt+M5idSED2YPGtwnfJV0kXohgdCBPmHGSYc1r04=
|
||||
github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
|
||||
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/flatbuffers v23.5.26+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-pkcs11 v0.2.1-0.20230907215043-c6f79328ddf9/go.mod h1:6eQoGcuNJpa7jnd5pMGdkSaQpNDYvPlXWMcjXXThLlY=
|
||||
github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
|
||||
github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
|
||||
github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20220221023154-0b2280d3ff96/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||
github.com/kevinmbeaulieu/eq-go v1.0.0/go.mod h1:G3S8ajA56gKBZm4UB9AOyoOS37JO3roToPzKNM8dtdM=
|
||||
github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
|
||||
github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
||||
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/logrusorgru/aurora/v3 v3.0.0/go.mod h1:vsR12bk5grlLvLXAYrBsb5Oc/N+LxAlxggSjiwMnCUc=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/lyft/protoc-gen-star/v2 v2.0.3/go.mod h1:amey7yeodaJhXSbf/TlLvWiqQfLOSpEk//mLlc+axEk=
|
||||
github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||
github.com/matryer/moq v0.3.3/go.mod h1:RJ75ZZZD71hejp39j4crZLsEDszGk6iH4v4YsWFKH4s=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mmcloughlin/professor v0.0.0-20170922221822-6b97112ab8b3/go.mod h1:LQkXsHRSPIEklPCq8OMQAzYNS2NGtYStdNE/ej1oJU8=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY=
|
||||
github.com/rivo/tview v0.0.0-20220307222120-9994674d60a8/go.mod h1:WIfMkQNY+oq/mWwtsjOYHIZBuwthioY2srOmljJkTnk=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo=
|
||||
github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=
|
||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.10.1/go.mod h1:IGlFPqhNAPKRxohIzWpI5QEy4kuI7tcl5WvR+8qy1rU=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/urfave/cli/v2 v2.27.1/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
|
||||
github.com/wblakecaldwell/profiler v0.0.0-20150908040756-6111ef1313a1/go.mod h1:3+0F8oLB1rQlbIcRAuqDgGdzNi9X69un/aPz4cUAFV4=
|
||||
github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU=
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
|
||||
github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA=
|
||||
go.einride.tech/aip v0.66.0/go.mod h1:qAhMsfT7plxBX+Oy7Huol6YUvZ0ZzdUz26yZsQwfl1M=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
go.opentelemetry.io/contrib v1.21.1/go.mod h1:usW9bPlrjHiJFbK0a6yK/M5wNHs3nLmtrT3vzhoD3co=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0/go.mod h1:r9vWsPS/3AQItv3OSlEJ/E4mbrhUbbw18meOjArPtKQ=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0/go.mod h1:SK2UL73Zy1quvRPonmOmRDiWk1KBV3LyIeeIxcEApWw=
|
||||
go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo=
|
||||
go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI=
|
||||
go.opentelemetry.io/otel v1.23.0/go.mod h1:YCycw9ZeKhcJFrb34iVSkyT0iczq/zYDtZYFufObyB0=
|
||||
go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM=
|
||||
go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY=
|
||||
go.opentelemetry.io/otel/metric v1.23.0/go.mod h1:MqUW2X2a6Q8RN96E2/nqNoT+z9BSms20Jb7Bbp+HiTo=
|
||||
go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E=
|
||||
go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ=
|
||||
go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo=
|
||||
go.opentelemetry.io/otel/trace v1.23.0/go.mod h1:GSGTbIClEsuZrGIzoEHqsVfxgn5UkggkflQwDScNUsk=
|
||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
|
||||
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
|
||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4=
|
||||
golang.org/x/oauth2 v0.14.0/go.mod h1:lAtNWgaWfL4cm7j2OV8TxGi9Qb7ECORx8DktCY74OwM=
|
||||
golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/telemetry v0.0.0-20240208230135-b75ee8823808/go.mod h1:KG1lNk5ZFNssSZLrpVb4sMXKMpGwGXOxSG3rnu2gZQQ=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
|
||||
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
|
||||
google.golang.org/api v0.162.0/go.mod h1:6SulDkfoBIg4NFmCuZ39XeeAgSHCPecfSUuDyYlAHs0=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:J7XzRzVy1+IPwWHZUzoD0IccYZIrXILAQpc+Qy9CMhY=
|
||||
google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:+Rvu7ElI+aLzyDQhpHMFMMltsD6m7nqpuWDd2CwJw3k=
|
||||
google.golang.org/genproto v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro=
|
||||
google.golang.org/genproto v0.0.0-20240205150955-31a09d347014/go.mod h1:xEgQu1e4stdSSsxPDK8Azkrk/ECl5HvdPf6nbZrTS5M=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:0xJLfVdJqpAPl8tDg1ujOCGzx6LFLttXT5NhllGOXY4=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917/go.mod h1:CmlNWB9lSezaYELKS5Ym1r44VrrbPUa7JTvw+6MbpJ0=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240205150955-31a09d347014/go.mod h1:rbHMSEDyoYX62nRVLOCc4Qt1HbsdytAYoVwgjiOhF3I=
|
||||
google.golang.org/genproto/googleapis/bytestream v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:SCz6T5xjNXM4QFPRwxHcfChp7V+9DcXR3ay2TkHR8Tg=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:oQ5rr10WTTMvP4A36n8JpR1OrO1BEiV4f78CneXZxkA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917/go.mod h1:xtjpI3tXFPP051KaWnhvxkiubL/6dJ18vLVf7q2pTOU=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240205150955-31a09d347014/go.mod h1:SaPjaZGWb0lPqs6Ittu0spdfrOArqji4ZdeP5IC/9N4=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM=
|
||||
google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
gopkg.in/ini.v1 v1.66.4/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
|
||||
modernc.org/cc/v3 v3.41.0/go.mod h1:Ni4zjJYJ04CDOhG7dn640WGfwBzfE0ecX8TyMB0Fv0Y=
|
||||
modernc.org/ccgo/v3 v3.16.15/go.mod h1:yT7B+/E2m43tmMOT51GMoM98/MtHIcQQSleGnddkUNI=
|
||||
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
|
@ -2,6 +2,7 @@ package ident
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
@ -52,11 +53,11 @@ func FromContext(ctx context.Context) Ident {
|
|||
type IDM struct {
|
||||
rand io.Reader
|
||||
sources []source
|
||||
pwd *passwd.Passwd
|
||||
pwd *passwd.Passwd
|
||||
}
|
||||
|
||||
func NewIDM(pwd *passwd.Passwd, rand io.Reader) *IDM {
|
||||
return &IDM{pwd: pwd, rand:rand}
|
||||
return &IDM{pwd: pwd, rand: rand}
|
||||
}
|
||||
|
||||
func (idm *IDM) Add(p int, h Handler) {
|
||||
|
@ -70,18 +71,17 @@ func (idm *IDM) Passwd(pass, hash []byte) ([]byte, error) {
|
|||
|
||||
// ReadIdent read ident from a list of ident handlers
|
||||
func (idm *IDM) ReadIdent(r *http.Request) (Ident, error) {
|
||||
var errs error
|
||||
for _, source := range idm.sources {
|
||||
u, err := source.ReadIdent(r)
|
||||
if err != nil {
|
||||
return Anonymous, err
|
||||
}
|
||||
errs = errors.Join(errs, err)
|
||||
|
||||
if u.Session().Active {
|
||||
return u, err
|
||||
if u != nil && u.Session().Active {
|
||||
return u, errs
|
||||
}
|
||||
}
|
||||
|
||||
return Anonymous, nil
|
||||
return Anonymous, errs
|
||||
}
|
||||
|
||||
func (idm *IDM) RegisterIdent(ctx context.Context, identity, displayName string, passwd []byte) (Ident, error) {
|
||||
|
|
327
ident/routes.go
327
ident/routes.go
|
@ -2,16 +2,10 @@ package ident
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/oklog/ulid/v2"
|
||||
|
||||
"go.sour.is/passwd"
|
||||
"go.sour.is/pkg/lg"
|
||||
"go.sour.is/pkg/locker"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -24,7 +18,7 @@ var (
|
|||
nick = `value="` + nick + `"`
|
||||
}
|
||||
return `
|
||||
<form id="login" hx-post="ident/login" hx-target="#login" hx-swap="outerHTML">
|
||||
<form id="login" hx-post="ident/session" hx-target="#login" hx-swap="outerHTML">
|
||||
<input required id="login-identity" name="identity" type="text" ` + nick + `placeholder="Identity..." />
|
||||
<input required id="login-passwd" name="passwd" type="password" ` + indicator + ` placeholder="Password..." />
|
||||
|
||||
|
@ -32,8 +26,12 @@ var (
|
|||
<button hx-get="ident/register">Register</button>
|
||||
</form>`
|
||||
}
|
||||
logoutForm = func(display string) string {
|
||||
return `<button id="login" hx-post="ident/logout" hx-target="#login" hx-swap="outerHTML">` + display + ` (logout)</button>`
|
||||
logoutForm = func(id Ident) string {
|
||||
display := id.Identity()
|
||||
if id, ok := id.(interface{ DisplayName() string }); ok {
|
||||
display = id.DisplayName()
|
||||
}
|
||||
return `<button id="login" hx-delete="ident/session" hx-target="#login" hx-swap="outerHTML">` + display + ` (logout)</button>`
|
||||
}
|
||||
registerForm = `
|
||||
<form id="login" hx-post="ident/register" hx-target="#login" hx-swap="outerHTML">
|
||||
|
@ -46,152 +44,104 @@ var (
|
|||
</form>`
|
||||
)
|
||||
|
||||
type sessions map[ulid.ULID]Ident
|
||||
|
||||
type root struct {
|
||||
idm *IDM
|
||||
sessions *locker.Locked[sessions]
|
||||
type sessionIF interface {
|
||||
ReadIdent(r *http.Request) (Ident, error)
|
||||
CreateSession(context.Context, http.ResponseWriter, Ident) error
|
||||
DestroySession(context.Context, http.ResponseWriter, Ident) error
|
||||
}
|
||||
|
||||
func NewHTTP(idm *IDM) *root {
|
||||
sessions := make(sessions)
|
||||
type root struct {
|
||||
idm *IDM
|
||||
session sessionIF
|
||||
}
|
||||
|
||||
func NewHTTP(idm *IDM, session sessionIF) *root {
|
||||
idm.Add(0, session)
|
||||
return &root{
|
||||
idm: idm,
|
||||
sessions: locker.New(sessions),
|
||||
idm: idm,
|
||||
session: session,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *root) RegisterHTTP(mux *http.ServeMux) {
|
||||
mux.HandleFunc("/ident", s.get)
|
||||
mux.HandleFunc("/ident/register", s.register)
|
||||
mux.HandleFunc("/ident/login", s.login)
|
||||
mux.HandleFunc("/ident/logout", s.logout)
|
||||
mux.HandleFunc("/ident", s.sessionHTTP)
|
||||
mux.HandleFunc("/ident/register", s.registerHTTP)
|
||||
mux.HandleFunc("/ident/session", s.sessionHTTP)
|
||||
}
|
||||
func (s *root) RegisterAPIv1(mux *http.ServeMux) {
|
||||
mux.HandleFunc("GET /ident", s.sessionV1)
|
||||
mux.HandleFunc("POST /ident", s.registerV1)
|
||||
mux.HandleFunc("POST /ident/session", s.loginV1)
|
||||
mux.HandleFunc("DELETE /ident/session", s.logoutV1)
|
||||
mux.HandleFunc("GET /ident", s.getV1)
|
||||
mux.HandleFunc("/ident/session", s.sessionV1)
|
||||
}
|
||||
func (s *root) RegisterMiddleware(hdlr http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx, span := lg.Span(r.Context())
|
||||
defer span.End()
|
||||
r = r.WithContext(ctx)
|
||||
|
||||
cookie, err := r.Cookie("sour.is-ident")
|
||||
id, err := s.idm.ReadIdent(r)
|
||||
span.RecordError(err)
|
||||
if err != nil {
|
||||
hdlr.ServeHTTP(w, r)
|
||||
return
|
||||
if id == nil {
|
||||
id = Anonymous
|
||||
}
|
||||
|
||||
sessionID, err := ulid.Parse(cookie.Value)
|
||||
span.RecordError(err)
|
||||
|
||||
var id Ident = Anonymous
|
||||
if err == nil {
|
||||
err = s.sessions.Use(ctx, func(ctx context.Context, sessions sessions) error {
|
||||
if session, ok := sessions[sessionID]; ok {
|
||||
id = session
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
span.RecordError(err)
|
||||
|
||||
r = r.WithContext(context.WithValue(r.Context(), contextKey, id))
|
||||
|
||||
hdlr.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
func (s *root) createSession(ctx context.Context, id Ident) error {
|
||||
return s.sessions.Use(ctx, func(ctx context.Context, sessions sessions) error {
|
||||
sessions[id.Session().SessionID] = id
|
||||
return nil
|
||||
})
|
||||
}
|
||||
func (s *root) destroySession(ctx context.Context, id Ident) error {
|
||||
session := id.Session()
|
||||
session.Active = false
|
||||
|
||||
return s.sessions.Use(ctx, func(ctx context.Context, sessions sessions) error {
|
||||
delete(sessions, session.SessionID)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (s *root) getV1(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *root) sessionV1(w http.ResponseWriter, r *http.Request) {
|
||||
ctx, span := lg.Span(r.Context())
|
||||
defer span.End()
|
||||
|
||||
var id Ident = FromContext(ctx)
|
||||
if id == nil {
|
||||
http.Error(w, "NO_AUTH", http.StatusUnauthorized)
|
||||
switch r.Method {
|
||||
case http.MethodGet:
|
||||
if id == nil {
|
||||
http.Error(w, "NO_AUTH", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
fmt.Fprint(w, id)
|
||||
case http.MethodPost:
|
||||
if !id.Session().Active {
|
||||
http.Error(w, "NO_AUTH", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
err := s.session.CreateSession(ctx, w, id)
|
||||
if err != nil {
|
||||
span.RecordError(err)
|
||||
http.Error(w, "ERR", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Fprint(w, id)
|
||||
|
||||
case http.MethodDelete:
|
||||
if !id.Session().Active {
|
||||
http.Error(w, "NO_AUTH", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
err := s.session.DestroySession(ctx, w, FromContext(ctx))
|
||||
if err != nil {
|
||||
span.RecordError(err)
|
||||
http.Error(w, "ERR", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
http.Error(w, "GONE", http.StatusGone)
|
||||
|
||||
default:
|
||||
http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
fmt.Fprint(w, id)
|
||||
}
|
||||
func (s *root) loginV1(w http.ResponseWriter, r *http.Request) {
|
||||
ctx, span := lg.Span(r.Context())
|
||||
defer span.End()
|
||||
|
||||
id, err := s.idm.ReadIdent(r)
|
||||
span.RecordError(err)
|
||||
if err != nil {
|
||||
http.Error(w, "ERR", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if !id.Session().Active {
|
||||
http.Error(w, "NO_AUTH", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
err = s.createSession(ctx, id)
|
||||
if err != nil {
|
||||
span.RecordError(err)
|
||||
http.Error(w, "ERR", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
http.SetCookie(w, &http.Cookie{
|
||||
Name: "sour.is-ident",
|
||||
Value: id.Session().SessionID.String(),
|
||||
Expires: time.Time{},
|
||||
Path: "/",
|
||||
Secure: false,
|
||||
HttpOnly: true,
|
||||
})
|
||||
|
||||
fmt.Fprint(w, id)
|
||||
}
|
||||
func (s *root) logoutV1(w http.ResponseWriter, r *http.Request) {
|
||||
ctx, span := lg.Span(r.Context())
|
||||
defer span.End()
|
||||
|
||||
if r.Method != http.MethodPost {
|
||||
http.Error(w, "ERR", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
|
||||
err := s.destroySession(ctx, FromContext(ctx))
|
||||
if err != nil {
|
||||
span.RecordError(err)
|
||||
http.Error(w, "NO_AUTH", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
http.SetCookie(w, &http.Cookie{Name: "sour.is-ident", MaxAge: -1})
|
||||
|
||||
http.Error(w, "GONE", http.StatusGone)
|
||||
}
|
||||
func (s *root) registerV1(w http.ResponseWriter, r *http.Request) {
|
||||
ctx, span := lg.Span(r.Context())
|
||||
defer span.End()
|
||||
|
||||
if r.Method != http.MethodPost {
|
||||
http.Error(w, "ERR", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
r.ParseForm()
|
||||
|
||||
identity := r.Form.Get("identity")
|
||||
|
@ -211,107 +161,60 @@ func (s *root) registerV1(w http.ResponseWriter, r *http.Request) {
|
|||
http.Error(w, "OK "+identity, http.StatusCreated)
|
||||
}
|
||||
|
||||
func (s *root) get(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *root) sessionHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
ctx, span := lg.Span(r.Context())
|
||||
defer span.End()
|
||||
|
||||
var id Ident = FromContext(ctx)
|
||||
if id == nil {
|
||||
http.Error(w, loginForm("", true), http.StatusOK)
|
||||
return
|
||||
}
|
||||
id := FromContext(ctx)
|
||||
|
||||
if !id.Session().Active {
|
||||
http.Error(w, loginForm("", true), http.StatusOK)
|
||||
return
|
||||
}
|
||||
|
||||
display := id.Identity()
|
||||
if id, ok := id.(interface{ DisplayName() string }); ok {
|
||||
display = id.DisplayName()
|
||||
}
|
||||
fmt.Fprint(w, logoutForm(display))
|
||||
}
|
||||
func (s *root) login(w http.ResponseWriter, r *http.Request) {
|
||||
ctx, span := lg.Span(r.Context())
|
||||
defer span.End()
|
||||
|
||||
if r.Method == http.MethodGet {
|
||||
switch r.Method {
|
||||
case http.MethodGet:
|
||||
if id.Session().Active {
|
||||
fmt.Fprint(w, logoutForm(id))
|
||||
return
|
||||
}
|
||||
fmt.Fprint(w, loginForm("", true))
|
||||
return
|
||||
}
|
||||
|
||||
id, err := s.idm.ReadIdent(r)
|
||||
span.RecordError(err)
|
||||
if err != nil {
|
||||
if errors.Is(err, passwd.ErrNoMatch) {
|
||||
case http.MethodPost:
|
||||
if !id.Session().Active {
|
||||
http.Error(w, loginForm("", false), http.StatusOK)
|
||||
return
|
||||
}
|
||||
|
||||
http.Error(w, "ERROR", http.StatusInternalServerError)
|
||||
return
|
||||
|
||||
err := s.session.CreateSession(ctx, w, id)
|
||||
span.RecordError(err)
|
||||
if err != nil {
|
||||
http.Error(w, "ERROR", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Fprint(w, logoutForm(id))
|
||||
case http.MethodDelete:
|
||||
err := s.session.DestroySession(ctx, w, FromContext(ctx))
|
||||
span.RecordError(err)
|
||||
if err != nil {
|
||||
http.Error(w, loginForm("", true), http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Fprint(w, loginForm("", true))
|
||||
default:
|
||||
http.Error(w, "ERROR", http.StatusMethodNotAllowed)
|
||||
}
|
||||
|
||||
if !id.Session().Active {
|
||||
http.Error(w, loginForm("", false), http.StatusOK)
|
||||
return
|
||||
}
|
||||
|
||||
err = s.createSession(ctx, id)
|
||||
span.RecordError(err)
|
||||
if err != nil {
|
||||
http.Error(w, "ERROR", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
http.SetCookie(w, &http.Cookie{
|
||||
Name: "sour.is-ident",
|
||||
Value: id.Session().SessionID.String(),
|
||||
Expires: time.Time{},
|
||||
Path: "/",
|
||||
Secure: false,
|
||||
HttpOnly: true,
|
||||
})
|
||||
|
||||
display := id.Identity()
|
||||
if id, ok := id.(interface{ DisplayName() string }); ok {
|
||||
display = id.DisplayName()
|
||||
}
|
||||
fmt.Fprint(w, logoutForm(display))
|
||||
}
|
||||
func (s *root) logout(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *root) registerHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
ctx, span := lg.Span(r.Context())
|
||||
defer span.End()
|
||||
|
||||
if r.Method != http.MethodPost {
|
||||
http.Error(w, "ERR", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
|
||||
http.SetCookie(w, &http.Cookie{Name: "sour.is-ident", MaxAge: -1})
|
||||
|
||||
err := s.destroySession(ctx, FromContext(ctx))
|
||||
span.RecordError(err)
|
||||
if err != nil {
|
||||
http.Error(w, loginForm("", true), http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Fprint(w, loginForm("", true))
|
||||
}
|
||||
func (s *root) register(w http.ResponseWriter, r *http.Request) {
|
||||
ctx, span := lg.Span(r.Context())
|
||||
defer span.End()
|
||||
|
||||
if r.Method == http.MethodGet {
|
||||
switch r.Method {
|
||||
case http.MethodGet:
|
||||
fmt.Fprint(w, registerForm)
|
||||
return
|
||||
}
|
||||
|
||||
if r.Method != http.MethodPost {
|
||||
case http.MethodPost:
|
||||
// break
|
||||
default:
|
||||
http.Error(w, "ERR", http.StatusMethodNotAllowed)
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
r.ParseForm()
|
||||
|
@ -335,26 +238,12 @@ func (s *root) register(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
err = s.createSession(ctx, id)
|
||||
err = s.session.CreateSession(ctx, w, id)
|
||||
span.RecordError(err)
|
||||
if err != nil {
|
||||
http.Error(w, "ERROR", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
http.SetCookie(w, &http.Cookie{
|
||||
Name: "sour.is-ident",
|
||||
Value: id.Session().SessionID.String(),
|
||||
Expires: time.Time{},
|
||||
Path: "/",
|
||||
Secure: false,
|
||||
HttpOnly: true,
|
||||
})
|
||||
|
||||
display = id.Identity()
|
||||
if id, ok := id.(interface{ DisplayName() string }); ok {
|
||||
display = id.DisplayName()
|
||||
}
|
||||
|
||||
http.Error(w, logoutForm(display), http.StatusCreated)
|
||||
http.Error(w, logoutForm(id), http.StatusCreated)
|
||||
}
|
||||
|
|
|
@ -12,6 +12,9 @@ import (
|
|||
"go.sour.is/pkg/ident"
|
||||
)
|
||||
|
||||
const identNS = "ident."
|
||||
const identSFX = ".credentials"
|
||||
|
||||
type registry interface {
|
||||
GetIndex(ctx context.Context, match, search string) (c mercury.Config, err error)
|
||||
GetConfig(ctx context.Context, match, search, fields string) (mercury.Config, error)
|
||||
|
@ -22,12 +25,13 @@ type mercuryIdent struct {
|
|||
identity string
|
||||
display string
|
||||
passwd []byte
|
||||
ed25519 []byte
|
||||
ident.SessionInfo
|
||||
}
|
||||
|
||||
func (id *mercuryIdent) Identity() string { return id.identity }
|
||||
func (id *mercuryIdent) DisplayName() string { return id.display }
|
||||
func (id *mercuryIdent) Space() string { return "mercury.@" + id.identity }
|
||||
func (id *mercuryIdent) Space() string { return identNS + "@" + id.identity }
|
||||
|
||||
func (id *mercuryIdent) FromConfig(cfg mercury.Config) error {
|
||||
if id == nil {
|
||||
|
@ -35,7 +39,7 @@ func (id *mercuryIdent) FromConfig(cfg mercury.Config) error {
|
|||
}
|
||||
|
||||
for _, s := range cfg {
|
||||
if !strings.HasPrefix(s.Space, "mercury.") {
|
||||
if !strings.HasPrefix(s.Space, identNS) {
|
||||
continue
|
||||
}
|
||||
if id.identity == "" {
|
||||
|
@ -44,7 +48,7 @@ func (id *mercuryIdent) FromConfig(cfg mercury.Config) error {
|
|||
}
|
||||
|
||||
switch {
|
||||
case strings.HasSuffix(s.Space, ".ident"):
|
||||
case strings.HasSuffix(s.Space, ".credentials"):
|
||||
id.passwd = []byte(s.FirstValue("passwd").First())
|
||||
default:
|
||||
id.display = s.FirstValue("displayName").First()
|
||||
|
@ -74,10 +78,10 @@ func (id *mercuryIdent) ToConfig() mercury.Config {
|
|||
},
|
||||
},
|
||||
&mercury.Space{
|
||||
Space: space + ".ident",
|
||||
Space: space + identSFX,
|
||||
List: []mercury.Value{
|
||||
{
|
||||
Space: space + ".ident",
|
||||
Space: space + identSFX,
|
||||
Seq: 1,
|
||||
Name: "passwd",
|
||||
Values: []string{string(id.passwd)},
|
||||
|
@ -105,20 +109,38 @@ func NewMercury(r registry, pwd *ident.IDM) *mercurySource {
|
|||
}
|
||||
|
||||
func (s *mercurySource) ReadIdent(r *http.Request) (ident.Ident, error) {
|
||||
if id, err := s.readIdentBasic(r); id != nil {
|
||||
return id, err
|
||||
}
|
||||
|
||||
if id, err := s.readIdentURL(r); id != nil {
|
||||
return id, err
|
||||
}
|
||||
|
||||
if id, err := s.readIdentHTTP(r); id != nil {
|
||||
return id, err
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("no auth")
|
||||
}
|
||||
|
||||
func (s *mercurySource) readIdentURL(r *http.Request) (ident.Ident, error) {
|
||||
ctx, span := lg.Span(r.Context())
|
||||
defer span.End()
|
||||
|
||||
if r.Method != http.MethodPost {
|
||||
return nil, fmt.Errorf("method not allowed")
|
||||
pass, ok := r.URL.User.Password()
|
||||
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
r.ParseForm()
|
||||
|
||||
id := &mercuryIdent{
|
||||
identity: r.Form.Get("identity"),
|
||||
passwd: []byte(r.Form.Get("passwd")),
|
||||
identity: r.URL.User.Username(),
|
||||
passwd: []byte(pass),
|
||||
}
|
||||
|
||||
space := id.Space()
|
||||
c, err := s.r.GetConfig(ctx, "trace:"+space+".ident", "", "")
|
||||
c, err := s.r.GetConfig(ctx, "trace:"+space+identSFX, "", "")
|
||||
if err != nil {
|
||||
span.RecordError(err)
|
||||
return id, err
|
||||
|
@ -144,6 +166,95 @@ func (s *mercurySource) ReadIdent(r *http.Request) (ident.Ident, error) {
|
|||
|
||||
return ¤t, nil
|
||||
}
|
||||
|
||||
func (s *mercurySource) readIdentBasic(r *http.Request) (ident.Ident, error) {
|
||||
ctx, span := lg.Span(r.Context())
|
||||
defer span.End()
|
||||
|
||||
user, pass, ok := r.BasicAuth()
|
||||
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
id := &mercuryIdent{
|
||||
identity: user,
|
||||
passwd: []byte(pass),
|
||||
}
|
||||
|
||||
space := id.Space()
|
||||
c, err := s.r.GetConfig(ctx, "trace:"+space+identSFX, "", "")
|
||||
if err != nil {
|
||||
span.RecordError(err)
|
||||
return id, err
|
||||
}
|
||||
var current mercuryIdent
|
||||
current.FromConfig(c)
|
||||
if len(current.passwd) == 0 {
|
||||
return nil, fmt.Errorf("not registered")
|
||||
}
|
||||
_, err = s.idm.Passwd(id.passwd, current.passwd)
|
||||
if err != nil {
|
||||
return id, err
|
||||
}
|
||||
current.SessionInfo, err = s.idm.NewSessionInfo()
|
||||
if err != nil {
|
||||
return id, err
|
||||
}
|
||||
|
||||
err = s.r.WriteConfig(ctx, current.ToConfig())
|
||||
if err != nil {
|
||||
return ¤t, err
|
||||
}
|
||||
|
||||
return ¤t, nil
|
||||
}
|
||||
|
||||
func (s *mercurySource) readIdentHTTP(r *http.Request) (ident.Ident, error) {
|
||||
ctx, span := lg.Span(r.Context())
|
||||
defer span.End()
|
||||
|
||||
if r.Method != http.MethodPost {
|
||||
return nil, fmt.Errorf("method not allowed")
|
||||
}
|
||||
r.ParseForm()
|
||||
id := &mercuryIdent{
|
||||
identity: r.Form.Get("identity"),
|
||||
passwd: []byte(r.Form.Get("passwd")),
|
||||
}
|
||||
|
||||
if id.identity == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
space := id.Space()
|
||||
c, err := s.r.GetConfig(ctx, "trace:"+space+identSFX, "", "")
|
||||
if err != nil {
|
||||
span.RecordError(err)
|
||||
return id, err
|
||||
}
|
||||
var current mercuryIdent
|
||||
current.FromConfig(c)
|
||||
if len(current.passwd) == 0 {
|
||||
return nil, fmt.Errorf("not registered")
|
||||
}
|
||||
_, err = s.idm.Passwd(id.passwd, current.passwd)
|
||||
if err != nil {
|
||||
return id, err
|
||||
}
|
||||
current.SessionInfo, err = s.idm.NewSessionInfo()
|
||||
if err != nil {
|
||||
return id, err
|
||||
}
|
||||
|
||||
err = s.r.WriteConfig(ctx, current.ToConfig())
|
||||
if err != nil {
|
||||
return ¤t, err
|
||||
}
|
||||
|
||||
return ¤t, nil
|
||||
}
|
||||
|
||||
func (s *mercurySource) RegisterIdent(ctx context.Context, identity, display string, passwd []byte) (ident.Ident, error) {
|
||||
ctx, span := lg.Span(ctx)
|
||||
defer span.End()
|
||||
|
|
83
ident/source/session.go
Normal file
83
ident/source/session.go
Normal file
|
@ -0,0 +1,83 @@
|
|||
package source
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/oklog/ulid/v2"
|
||||
"go.sour.is/pkg/ident"
|
||||
"go.sour.is/pkg/lg"
|
||||
"go.sour.is/pkg/locker"
|
||||
)
|
||||
|
||||
const CookieName = "sour.is-ident"
|
||||
|
||||
type sessions map[ulid.ULID]ident.Ident
|
||||
|
||||
type session struct {
|
||||
cookieName string
|
||||
sessions *locker.Locked[sessions]
|
||||
}
|
||||
|
||||
func NewSession(cookieName string) *session {
|
||||
return &session{
|
||||
cookieName: cookieName,
|
||||
sessions: locker.New(make(sessions)),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *session) ReadIdent(r *http.Request) (ident.Ident, error) {
|
||||
ctx, span := lg.Span(r.Context())
|
||||
defer span.End()
|
||||
|
||||
cookie, err := r.Cookie(s.cookieName)
|
||||
span.RecordError(err)
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
sessionID, err := ulid.Parse(cookie.Value)
|
||||
span.RecordError(err)
|
||||
|
||||
var id ident.Ident = ident.Anonymous
|
||||
if err == nil {
|
||||
err = s.sessions.Use(ctx, func(ctx context.Context, sessions sessions) error {
|
||||
if session, ok := sessions[sessionID]; ok {
|
||||
id = session
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
span.RecordError(err)
|
||||
|
||||
return id, err
|
||||
}
|
||||
|
||||
func (s *session) CreateSession(ctx context.Context, w http.ResponseWriter, id ident.Ident) error {
|
||||
http.SetCookie(w, &http.Cookie{
|
||||
Name: s.cookieName,
|
||||
Value: id.Session().SessionID.String(),
|
||||
Expires: time.Time{},
|
||||
Path: "/",
|
||||
Secure: false,
|
||||
HttpOnly: true,
|
||||
})
|
||||
|
||||
return s.sessions.Use(ctx, func(ctx context.Context, sessions sessions) error {
|
||||
sessions[id.Session().SessionID] = id
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (s *session) DestroySession(ctx context.Context, w http.ResponseWriter, id ident.Ident) error {
|
||||
session := id.Session()
|
||||
session.Active = false
|
||||
|
||||
http.SetCookie(w, &http.Cookie{Name: s.cookieName, MaxAge: -1})
|
||||
|
||||
return s.sessions.Use(ctx, func(ctx context.Context, sessions sessions) error {
|
||||
delete(sessions, session.SessionID)
|
||||
return nil
|
||||
})
|
||||
}
|
|
@ -62,10 +62,16 @@ func (lis Config) ToSpaceMap() SpaceMap {
|
|||
|
||||
// String format config as string
|
||||
func (lis Config) String() string {
|
||||
attLen := 0
|
||||
tagLen := 0
|
||||
|
||||
for _, o := range lis {
|
||||
var buf strings.Builder
|
||||
for i, o := range lis {
|
||||
attLen := 0
|
||||
tagLen := 0
|
||||
|
||||
if i > 0 {
|
||||
buf.WriteRune('\n')
|
||||
}
|
||||
|
||||
for _, v := range o.List {
|
||||
l := len(v.Name)
|
||||
if attLen <= l {
|
||||
|
@ -77,10 +83,7 @@ func (lis Config) String() string {
|
|||
tagLen = t
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var buf strings.Builder
|
||||
for _, o := range lis {
|
||||
if len(o.Notes) > 0 {
|
||||
buf.WriteString("# ")
|
||||
buf.WriteString(strings.Join(o.Notes, "\n# "))
|
||||
|
@ -133,7 +136,10 @@ func (lis Config) String() string {
|
|||
}
|
||||
}
|
||||
|
||||
buf.WriteRune('\n')
|
||||
for _, line := range o.Trailer {
|
||||
buf.WriteString(line)
|
||||
buf.WriteRune('\n')
|
||||
}
|
||||
}
|
||||
|
||||
return buf.String()
|
||||
|
@ -188,11 +194,21 @@ func (lis Config) EnvString() string {
|
|||
func (lis Config) INIString() string {
|
||||
var buf strings.Builder
|
||||
for _, o := range lis {
|
||||
for _, note := range o.Notes {
|
||||
buf.WriteString("; ")
|
||||
buf.WriteString(note)
|
||||
buf.WriteRune('\n')
|
||||
}
|
||||
buf.WriteRune('[')
|
||||
buf.WriteString(o.Space)
|
||||
buf.WriteRune(']')
|
||||
buf.WriteRune('\n')
|
||||
for _, v := range o.List {
|
||||
for _, note := range v.Notes {
|
||||
buf.WriteString("; ")
|
||||
buf.WriteString(note)
|
||||
buf.WriteRune('\n')
|
||||
}
|
||||
buf.WriteString(v.Name)
|
||||
switch len(v.Values) {
|
||||
case 0:
|
||||
|
@ -221,6 +237,13 @@ func (lis Config) INIString() string {
|
|||
}
|
||||
}
|
||||
}
|
||||
for _, line := range o.Trailer {
|
||||
buf.WriteString("; ")
|
||||
buf.WriteString(line)
|
||||
buf.WriteRune('\n')
|
||||
}
|
||||
|
||||
buf.WriteRune('\n')
|
||||
}
|
||||
|
||||
return buf.String()
|
||||
|
@ -228,10 +251,16 @@ func (lis Config) INIString() string {
|
|||
|
||||
// String format config as string
|
||||
func (lis Config) HTMLString() string {
|
||||
attLen := 0
|
||||
tagLen := 0
|
||||
|
||||
for _, o := range lis {
|
||||
var buf strings.Builder
|
||||
for i, o := range lis {
|
||||
attLen := 0
|
||||
tagLen := 0
|
||||
|
||||
if i > 0 {
|
||||
buf.WriteRune('\n')
|
||||
}
|
||||
|
||||
for _, v := range o.List {
|
||||
l := len(v.Name)
|
||||
if attLen <= l {
|
||||
|
@ -243,10 +272,7 @@ func (lis Config) HTMLString() string {
|
|||
tagLen = t
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var buf strings.Builder
|
||||
for _, o := range lis {
|
||||
if len(o.Notes) > 0 {
|
||||
buf.WriteString("<i>")
|
||||
buf.WriteString("# ")
|
||||
|
@ -311,7 +337,12 @@ func (lis Config) HTMLString() string {
|
|||
}
|
||||
}
|
||||
|
||||
buf.WriteRune('\n')
|
||||
for _, line := range o.Trailer {
|
||||
buf.WriteString("<small>")
|
||||
buf.WriteString(line)
|
||||
buf.WriteString("</small>")
|
||||
buf.WriteRune('\n')
|
||||
}
|
||||
}
|
||||
|
||||
return buf.String()
|
||||
|
@ -319,10 +350,11 @@ func (lis Config) HTMLString() string {
|
|||
|
||||
// Space stores a registry of spaces
|
||||
type Space struct {
|
||||
Space string `json:"space"`
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
Notes []string `json:"notes,omitempty"`
|
||||
List []Value `json:"list,omitempty"`
|
||||
Space string `json:"space"`
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
Notes []string `json:"notes,omitempty"`
|
||||
List []Value `json:"list,omitempty"`
|
||||
Trailer []string `json:"trailer,omitempty"`
|
||||
}
|
||||
|
||||
func NewSpace(space string) *Space {
|
||||
|
@ -437,7 +469,7 @@ type SpaceMap map[string]*Space
|
|||
func (m SpaceMap) Space(name string) (*Space, bool) {
|
||||
s, ok := m[name]
|
||||
return s, ok
|
||||
}
|
||||
}
|
||||
|
||||
// Rule is a type of rule
|
||||
type Rule struct {
|
||||
|
|
|
@ -20,17 +20,11 @@ type NamespaceSearch []NamespaceSpec
|
|||
func ParseNamespace(ns string) (lis NamespaceSearch) {
|
||||
for _, part := range strings.Split(ns, ";") {
|
||||
if strings.HasPrefix(part, "trace:") {
|
||||
for _, s := range strings.Split(part[6:], ",") {
|
||||
lis = append(lis, NamespaceTrace(s))
|
||||
}
|
||||
lis = append(lis, NamespaceTrace(part[6:]))
|
||||
} else if strings.Contains(part, "*") {
|
||||
lis = append(lis, NamespaceStar(part))
|
||||
} else {
|
||||
for _, s := range strings.Split(part, ",") {
|
||||
if strings.Contains(s, "*") {
|
||||
lis = append(lis, NamespaceStar(s))
|
||||
} else {
|
||||
lis = append(lis, NamespaceNode(s))
|
||||
}
|
||||
}
|
||||
lis = append(lis, NamespaceNode(part))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,7 +38,7 @@ func (n NamespaceSearch) String() string {
|
|||
for _, v := range n {
|
||||
lis = append(lis, v.String())
|
||||
}
|
||||
return strings.Join(lis, ",")
|
||||
return strings.Join(lis, ";")
|
||||
}
|
||||
|
||||
// Match returns true if any match.
|
||||
|
|
59
mercury/namespace_test.go
Normal file
59
mercury/namespace_test.go
Normal file
|
@ -0,0 +1,59 @@
|
|||
package mercury_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/matryer/is"
|
||||
"go.sour.is/pkg/mercury"
|
||||
|
||||
sq "github.com/Masterminds/squirrel"
|
||||
)
|
||||
|
||||
func TestNamespaceParse(t *testing.T) {
|
||||
var tests = []struct {
|
||||
in string
|
||||
out string
|
||||
args []any
|
||||
}{
|
||||
{
|
||||
in: "d42.bgp.kapha.*;trace:d42.bgp.kapha",
|
||||
out: "(column LIKE ? OR ? LIKE column || '%')",
|
||||
args: []any{"d42.bgp.kapha.%", "d42.bgp.kapha"},
|
||||
},
|
||||
|
||||
{
|
||||
in: "d42.bgp.kapha.*,d42.bgp.kapha",
|
||||
out: "(column LIKE ? OR column = ?)",
|
||||
args: []any{"d42.bgp.kapha.%", "d42.bgp.kapha"},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
t.Run(fmt.Sprintf("test %d", i), func(t *testing.T) {
|
||||
is := is.New(t)
|
||||
out := mercury.ParseNamespace(tt.in)
|
||||
sql, args, err := getWhere(out).ToSql()
|
||||
is.NoErr(err)
|
||||
is.Equal(sql, tt.out)
|
||||
is.Equal(args, tt.args)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func getWhere(search mercury.NamespaceSearch) sq.Sqlizer {
|
||||
var where sq.Or
|
||||
space := "column"
|
||||
for _, m := range search {
|
||||
switch m.(type) {
|
||||
case mercury.NamespaceNode:
|
||||
where = append(where, sq.Eq{space: m.Value()})
|
||||
case mercury.NamespaceStar:
|
||||
where = append(where, sq.Like{space: m.Value()})
|
||||
case mercury.NamespaceTrace:
|
||||
e := sq.Expr(`? LIKE `+space+` || '%'`, m.Value())
|
||||
where = append(where, e)
|
||||
}
|
||||
}
|
||||
return where
|
||||
}
|
|
@ -3,6 +3,7 @@ package mercury
|
|||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
"log"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
@ -49,6 +50,26 @@ func ParseText(body io.Reader) (config SpaceMap, err error) {
|
|||
continue
|
||||
}
|
||||
|
||||
if strings.HasPrefix(line, "----") && strings.HasSuffix(line, "----") {
|
||||
var trailer []string
|
||||
|
||||
trailer = append(trailer, line)
|
||||
for scanner.Scan() {
|
||||
line = scanner.Text()
|
||||
trailer = append(trailer, line)
|
||||
if strings.HasPrefix(line, "----") && strings.HasSuffix(line, "----") {
|
||||
break
|
||||
}
|
||||
}
|
||||
c, ok := config[space]
|
||||
if !ok {
|
||||
c = &Space{Space: space}
|
||||
}
|
||||
log.Println(trailer)
|
||||
c.Trailer = append(c.Trailer, trailer...)
|
||||
config[space] = c
|
||||
continue
|
||||
}
|
||||
if space == "" {
|
||||
continue
|
||||
}
|
||||
|
@ -59,10 +80,8 @@ func ParseText(body io.Reader) (config SpaceMap, err error) {
|
|||
}
|
||||
|
||||
if strings.TrimSpace(sp[0]) == "" {
|
||||
var c *Space
|
||||
var ok bool
|
||||
|
||||
if c, ok = config[space]; !ok {
|
||||
c, ok := config[space]
|
||||
if !ok {
|
||||
c = &Space{Space: space}
|
||||
}
|
||||
|
||||
|
@ -78,10 +97,8 @@ func ParseText(body io.Reader) (config SpaceMap, err error) {
|
|||
tags = fields[1:]
|
||||
}
|
||||
|
||||
var c *Space
|
||||
var ok bool
|
||||
|
||||
if c, ok = config[space]; !ok {
|
||||
c, ok := config[space]
|
||||
if !ok {
|
||||
c = &Space{Space: space}
|
||||
}
|
||||
|
||||
|
|
28
mercury/parse_test.go
Normal file
28
mercury/parse_test.go
Normal file
|
@ -0,0 +1,28 @@
|
|||
package mercury_test
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/matryer/is"
|
||||
"go.sour.is/pkg/mercury"
|
||||
)
|
||||
|
||||
func TestParseText(t *testing.T) {
|
||||
is := is.New(t)
|
||||
sm, err := mercury.ParseText(strings.NewReader(`
|
||||
@test.sign
|
||||
key :value1
|
||||
-----BEGIN SSH SIGNATURE-----
|
||||
U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgZ+OuJYdd3UiUbyBuO1RlsQR20a
|
||||
Qm5mKneuMxRjGo3zkAAAAEZmlsZQAAAAAAAAAGc2hhNTEyAAAAUwAAAAtzc2gtZWQyNTUx
|
||||
OQAAAED8T4C6WILXYZ1KxqDIlVhlrAEjr1Vc+tn8ypcVM3bN7iOexVvuUuvm90nr8eEwKU
|
||||
acrdDxmq2S+oysQbK+pMUE
|
||||
-----END SSH SIGNATURE-----
|
||||
`))
|
||||
is.NoErr(err)
|
||||
for _, c := range sm {
|
||||
is.Equal(len(c.Trailer), 6)
|
||||
}
|
||||
|
||||
}
|
|
@ -32,7 +32,7 @@
|
|||
<br />
|
||||
<textarea name="content" rows="45" wrap="off"
|
||||
onkeyup="if (this.scrollHeight > this.clientHeight) this.style.height = this.scrollHeight + ' px';"
|
||||
style="overflow:auto; overflow-y:hidden; transition: height 0.2s ease-out;"></textarea>
|
||||
style="overflow:auto; transition: height 0.2s ease-out;"></textarea>
|
||||
</form>
|
||||
<pre id="space-saved"></pre>
|
||||
</div>
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
body {
|
||||
margin: 0;
|
||||
min-height: 100vh;
|
||||
background: rgb(210, 221, 240);
|
||||
}
|
||||
|
||||
header {
|
||||
|
@ -57,6 +58,11 @@ code i {
|
|||
}
|
||||
|
||||
code em {
|
||||
color: orangered;
|
||||
}
|
||||
|
||||
code small {
|
||||
font-size-adjust: 50%;
|
||||
color: orange;
|
||||
}
|
||||
|
||||
|
@ -94,7 +100,7 @@ footer>span {
|
|||
.container>div {
|
||||
overflow: auto;
|
||||
padding: 10px;
|
||||
background: rgb(238, 174, 202);
|
||||
background-color: white;
|
||||
border: 0px ;
|
||||
}
|
||||
|
||||
|
@ -158,7 +164,7 @@ footer>span {
|
|||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
html {
|
||||
html, body {
|
||||
color: white;
|
||||
background: #111
|
||||
}
|
||||
|
|
|
@ -8,8 +8,8 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
"go.sour.is/pkg/lg"
|
||||
"go.sour.is/pkg/ident"
|
||||
"go.sour.is/pkg/lg"
|
||||
"go.sour.is/pkg/rsql"
|
||||
"go.sour.is/pkg/set"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
@ -122,16 +122,32 @@ func (r *registry) Register(name string, h func(*Space) any) {
|
|||
func (r *registry) Configure(m SpaceMap) error {
|
||||
r.resetMatchers()
|
||||
for space, c := range m {
|
||||
space = strings.TrimPrefix(space, "mercury.source.")
|
||||
handler, name, _ := strings.Cut(space, ".")
|
||||
matches := c.FirstValue("match")
|
||||
for _, match := range matches.Values {
|
||||
ps := strings.Fields(match)
|
||||
priority, err := strconv.Atoi(ps[0])
|
||||
if err != nil {
|
||||
return err
|
||||
if strings.HasPrefix(space, "mercury.source.") {
|
||||
space = strings.TrimPrefix(space, "mercury.source.")
|
||||
handler, name, _ := strings.Cut(space, ".")
|
||||
matches := c.FirstValue("match")
|
||||
for _, match := range matches.Values {
|
||||
ps := strings.Fields(match)
|
||||
priority, err := strconv.Atoi(ps[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.add(name, handler, ps[1], priority, c)
|
||||
}
|
||||
}
|
||||
|
||||
if strings.HasPrefix(space, "mercury.output.") {
|
||||
space = strings.TrimPrefix(space, "mercury.output.")
|
||||
handler, name, _ := strings.Cut(space, ".")
|
||||
matches := c.FirstValue("match")
|
||||
for _, match := range matches.Values {
|
||||
ps := strings.Fields(match)
|
||||
priority, err := strconv.Atoi(ps[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.add(name, handler, ps[1], priority, c)
|
||||
}
|
||||
r.add(name, handler, ps[1], priority, c)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
package mercury
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"log"
|
||||
"net/http"
|
||||
"sort"
|
||||
|
@ -11,8 +13,8 @@ import (
|
|||
|
||||
"github.com/BurntSushi/toml"
|
||||
"github.com/golang/gddo/httputil"
|
||||
"go.sour.is/pkg/lg"
|
||||
"go.sour.is/pkg/ident"
|
||||
"go.sour.is/pkg/lg"
|
||||
)
|
||||
|
||||
type root struct{}
|
||||
|
@ -21,8 +23,13 @@ func NewHTTP() *root {
|
|||
return &root{}
|
||||
}
|
||||
|
||||
//go:embed public
|
||||
var public embed.FS
|
||||
|
||||
func (s *root) RegisterHTTP(mux *http.ServeMux) {
|
||||
mux.Handle("/", http.FileServer(http.Dir("./mercury/public")))
|
||||
// mux.Handle("/", http.FileServer(http.Dir("./mercury/public")))
|
||||
public, _ := fs.Sub(public, "public")
|
||||
mux.Handle("/", http.FileServerFS(public))
|
||||
}
|
||||
func (s *root) RegisterAPIv1(mux *http.ServeMux) {
|
||||
mux.HandleFunc("GET /mercury", s.indexV1)
|
||||
|
@ -30,6 +37,9 @@ func (s *root) RegisterAPIv1(mux *http.ServeMux) {
|
|||
mux.HandleFunc("GET /mercury/config", s.configV1)
|
||||
mux.HandleFunc("POST /mercury/config", s.storeV1)
|
||||
}
|
||||
func (s *root) RegisterWellKnown(mux *http.ServeMux) {
|
||||
s.RegisterAPIv1(mux)
|
||||
}
|
||||
|
||||
func (s *root) configV1(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == http.MethodPost {
|
||||
|
@ -62,7 +72,7 @@ func (s *root) configV1(w http.ResponseWriter, r *http.Request) {
|
|||
log.Print("SPC: ", space)
|
||||
ns := ParseNamespace(space)
|
||||
log.Print("PRE: ", ns)
|
||||
ns = rules.ReduceSearch(ns)
|
||||
//ns = rules.ReduceSearch(ns)
|
||||
log.Print("POST: ", ns)
|
||||
|
||||
lis, err := Registry.GetConfig(ctx, ns.String(), "", "")
|
||||
|
|
|
@ -6,6 +6,7 @@ CREATE TABLE IF NOT EXISTS mercury_spaces
|
|||
id integer NOT NULL DEFAULT nextval('mercury_spaces_id_seq'::regclass),
|
||||
notes character varying[] NOT NULL DEFAULT '{}'::character varying[],
|
||||
tags character varying[] NOT NULL DEFAULT '{}'::character varying[],
|
||||
trailer character varying[] NOT NULL DEFAULT '{}'::character varying[],
|
||||
CONSTRAINT mercury_namespace_pk PRIMARY KEY (id)
|
||||
);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS mercury_namespace_space_uindex
|
||||
|
@ -35,7 +36,8 @@ CREATE OR REPLACE VIEW mercury_registry_vw
|
|||
v.name,
|
||||
v."values",
|
||||
v.notes,
|
||||
v.tags
|
||||
v.tags,
|
||||
s.trailer
|
||||
FROM mercury_spaces s
|
||||
JOIN mercury_values v ON s.id = v.id;
|
||||
|
||||
|
|
|
@ -3,7 +3,8 @@ CREATE TABLE IF NOT EXISTS mercury_spaces
|
|||
space character varying NOT NULL unique,
|
||||
id integer NOT NULL CONSTRAINT mercury_namespace_pk PRIMARY KEY autoincrement,
|
||||
notes json NOT NULL DEFAULT '[]',
|
||||
tags json NOT NULL DEFAULT '[]'
|
||||
tags json NOT NULL DEFAULT '[]',
|
||||
trailer json NOT NULL DEFAULT '[]'
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS mercury_values
|
||||
|
@ -27,7 +28,8 @@ CREATE VIEW if not exists mercury_registry_vw
|
|||
v.name,
|
||||
v."values",
|
||||
v.notes,
|
||||
v.tags
|
||||
v.tags,
|
||||
s.trailer
|
||||
FROM mercury_spaces s
|
||||
JOIN mercury_values v ON s.id = v.id;
|
||||
|
||||
|
|
|
@ -166,7 +166,7 @@ func (p *sqlHandler) listSpace(ctx context.Context, tx sq.BaseRunner, where sq.S
|
|||
tx = p.db
|
||||
}
|
||||
|
||||
query := sq.Select(`"id"`, `"space"`, `"tags"`, `"notes"`).
|
||||
query := sq.Select(`"id"`, `"space"`, `"notes"`, `"tags"`, `"trailer"`).
|
||||
From("mercury_spaces").
|
||||
Where(where).
|
||||
OrderBy("space asc").
|
||||
|
@ -189,6 +189,7 @@ func (p *sqlHandler) listSpace(ctx context.Context, tx sq.BaseRunner, where sq.S
|
|||
&s.Space.Space,
|
||||
listScan(&s.Space.Notes, p.listFormat),
|
||||
listScan(&s.Space.Tags, p.listFormat),
|
||||
listScan(&s.Trailer, p.listFormat),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -287,6 +288,7 @@ func (p *sqlHandler) WriteConfig(ctx context.Context, config mercury.Config) (er
|
|||
Where(sq.Eq{"id": updateIDs[i]}).
|
||||
Set("tags", listValue(u.Tags, p.listFormat)).
|
||||
Set("notes", listValue(u.Notes, p.listFormat)).
|
||||
Set("trailer", listValue(u.Trailer, p.listFormat)).
|
||||
PlaceholderFormat(sq.Dollar)
|
||||
span.AddEvent(lg.LogQuery(query.ToSql()))
|
||||
_, err := query.RunWith(tx).ExecContext(ctx)
|
||||
|
@ -305,8 +307,13 @@ func (p *sqlHandler) WriteConfig(ctx context.Context, config mercury.Config) (er
|
|||
var id uint64
|
||||
query := sq.Insert("mercury_spaces").
|
||||
PlaceholderFormat(sq.Dollar).
|
||||
Columns("space", "tags", "notes").
|
||||
Values(s.Space, listValue(s.Tags, p.listFormat), listValue(s.Notes, p.listFormat)).
|
||||
Columns("space", "tags", "notes", "trailer").
|
||||
Values(
|
||||
s.Space,
|
||||
listValue(s.Tags, p.listFormat),
|
||||
listValue(s.Notes, p.listFormat),
|
||||
listValue(s.Trailer, p.listFormat),
|
||||
).
|
||||
Suffix("RETURNING \"id\"")
|
||||
span.AddEvent(lg.LogQuery(query.ToSql()))
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user