tumblrandom: init
This commit is contained in:
parent
96178bf90b
commit
a6974aebcc
5 changed files with 449 additions and 17 deletions
|
@ -14,4 +14,5 @@ args: {
|
|||
tokend = import ./tokend args;
|
||||
access = import ./access args;
|
||||
vault = import ./vault args;
|
||||
tumblrandom = import ./tumblrandom args;
|
||||
}
|
||||
|
|
81
go/go.mod
81
go/go.mod
|
@ -17,16 +17,93 @@ require (
|
|||
github.com/hashicorp/vault/api v1.4.1
|
||||
github.com/jackc/pgtype v1.4.2
|
||||
github.com/jackc/pgx/v4 v4.8.1
|
||||
github.com/jamespfennell/xz v0.1.2
|
||||
github.com/mattn/go-sqlite3 v1.14.15
|
||||
github.com/numtide/go-nix v0.0.0-20210617093959-c74bbf961f08
|
||||
github.com/pomerium/sdk-go v0.0.5
|
||||
github.com/prometheus/client_golang v1.12.1
|
||||
gocloud.dev v0.24.0
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5
|
||||
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/mattn/go-sqlite3 v1.14.15 // indirect
|
||||
github.com/ulikunitz/xz v0.5.10 // indirect
|
||||
cloud.google.com/go v0.94.0 // indirect
|
||||
cloud.google.com/go/storage v1.16.1 // indirect
|
||||
github.com/armon/go-metrics v0.3.9 // indirect
|
||||
github.com/armon/go-radix v1.0.0 // indirect
|
||||
github.com/aws/aws-sdk-go v1.40.34 // indirect
|
||||
github.com/aws/aws-sdk-go-v2 v1.9.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/config v1.7.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.4.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.5.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.2.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.3.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.4.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.7.0 // indirect
|
||||
github.com/aws/smithy-go v1.8.0 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cenkalti/backoff/v3 v3.0.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
github.com/fatih/color v1.7.0 // indirect
|
||||
github.com/godbus/dbus/v5 v5.0.4 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/wire v0.5.0 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.1.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-hclog v0.16.2 // indirect
|
||||
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/go-plugin v1.4.3 // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.6.6 // indirect
|
||||
github.com/hashicorp/go-rootcerts v1.0.2 // indirect
|
||||
github.com/hashicorp/go-secure-stdlib/mlock v0.1.1 // indirect
|
||||
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.1 // indirect
|
||||
github.com/hashicorp/go-secure-stdlib/strutil v0.1.1 // indirect
|
||||
github.com/hashicorp/go-sockaddr v1.0.2 // indirect
|
||||
github.com/hashicorp/go-uuid v1.0.2 // indirect
|
||||
github.com/hashicorp/go-version v1.2.0 // indirect
|
||||
github.com/hashicorp/golang-lru v0.5.4 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/hashicorp/vault/sdk v0.4.1 // indirect
|
||||
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb // indirect
|
||||
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
|
||||
github.com/jackc/pgconn v1.6.4 // indirect
|
||||
github.com/jackc/pgio v1.0.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgproto3/v2 v2.0.2 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect
|
||||
github.com/jackc/puddle v1.1.1 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.6 // indirect
|
||||
github.com/mattn/go-isatty v0.0.12 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
|
||||
github.com/mitchellh/copystructure v1.0.0 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/go-testing-interface v1.0.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.4.2 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.0 // indirect
|
||||
github.com/oklog/run v1.0.0 // indirect
|
||||
github.com/pierrec/lz4 v2.5.2+incompatible // indirect
|
||||
github.com/prometheus/client_model v0.2.0 // indirect
|
||||
github.com/prometheus/common v0.32.1 // indirect
|
||||
github.com/prometheus/procfs v0.7.3 // indirect
|
||||
github.com/ryanuber/go-glob v1.0.0 // indirect
|
||||
go.opencensus.io v0.23.0 // indirect
|
||||
go.uber.org/atomic v1.9.0 // indirect
|
||||
golang.org/x/net v0.0.0-20210825183410-e898025ed96a // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
google.golang.org/api v0.56.0 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2 // indirect
|
||||
google.golang.org/grpc v1.41.0 // indirect
|
||||
google.golang.org/protobuf v1.27.1 // indirect
|
||||
gopkg.in/square/go-jose.v2 v2.5.1 // indirect
|
||||
)
|
||||
|
|
17
go/go.sum
17
go/go.sum
|
@ -73,34 +73,27 @@ github.com/Azure/azure-storage-blob-go v0.14.0/go.mod h1:SMqIBi+SuiQH32bvyjngEew
|
|||
github.com/Azure/go-amqp v0.13.0/go.mod h1:qj+o8xPCz9tMSbQ83Vp8boHahuRDl5mkNHyt1xlxUTs=
|
||||
github.com/Azure/go-amqp v0.13.11/go.mod h1:D5ZrjQqB1dyp1A+G73xeL/kNn7D5qHJIIsNNps7YNmk=
|
||||
github.com/Azure/go-amqp v0.13.12/go.mod h1:D5ZrjQqB1dyp1A+G73xeL/kNn7D5qHJIIsNNps7YNmk=
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
|
||||
github.com/Azure/go-autorest/autorest v0.11.3/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw=
|
||||
github.com/Azure/go-autorest/autorest v0.11.17/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw=
|
||||
github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA=
|
||||
github.com/Azure/go-autorest/autorest v0.11.20 h1:s8H1PbCZSqg/DH7JMlOz6YMig6htWLNPsjDdlLqCx3M=
|
||||
github.com/Azure/go-autorest/autorest v0.11.20/go.mod h1:o3tqFY+QR40VOlk+pV4d77mORO64jOXSgEnPQgLK6JY=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.11/go.mod h1:nBKAnTomx8gDtl+3ZCJv2v0KACFHWTB2drffI1B68Pk=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.14/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.15 h1:X+p2GF0GWyOiSmqohIaEeuNFNDY4I4EOlVuUQvFdWMk=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.15/go.mod h1:tGMin8I49Yij6AQ+rvV+Xa/zwxYQB5hmsd6DkfAx2+A=
|
||||
github.com/Azure/go-autorest/autorest/azure/auth v0.5.8/go.mod h1:kxyKZTSfKh8OVFWPAgOgQ/frrJgeYQJPyR5fLFmXko4=
|
||||
github.com/Azure/go-autorest/autorest/azure/cli v0.4.2/go.mod h1:7qkJkT+j6b+hIpzMOwPChJhTqS8VbsqqgULzMNRugoM=
|
||||
github.com/Azure/go-autorest/autorest/azure/cli v0.4.3/go.mod h1:yAQ2b6eP/CmLPnmLvxtT1ALIY3OR1oFcCqVBi8vHiTc=
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw=
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
|
||||
github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE=
|
||||
github.com/Azure/go-autorest/autorest/validation v0.3.1/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E=
|
||||
github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
|
||||
github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg=
|
||||
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
|
@ -154,7 +147,6 @@ github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3
|
|||
github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
|
||||
|
@ -173,7 +165,6 @@ github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWH
|
|||
github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
|
||||
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f h1:JOrtw2xFKzlg+cbHpyrpLDmnN1HqhBfnX7WDiW7eG2c=
|
||||
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI=
|
||||
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
|
@ -241,7 +232,6 @@ github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x
|
|||
github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE=
|
||||
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/golang-jwt/jwt/v4 v4.0.0 h1:RAqyYixv1p7uEnocuy8P1nru5wprCh/MH2BIlW5z5/o=
|
||||
github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||
|
@ -398,7 +388,6 @@ github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb h1:b5rjCoWHc7eqmAS
|
|||
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0=
|
||||
github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo=
|
||||
github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
|
||||
github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8=
|
||||
|
@ -417,7 +406,6 @@ github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2 h1:JVX6jT/XfzNqIjye47
|
|||
github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A=
|
||||
github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78=
|
||||
github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA=
|
||||
github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg=
|
||||
|
@ -450,6 +438,8 @@ github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0f
|
|||
github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v1.1.1 h1:PJAw7H/9hoWC4Kf3J8iNmL1SwA6E8vfsLqBiL+F6CtI=
|
||||
github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jamespfennell/xz v0.1.2 h1:iCw5kScLfGCceOKgQaGuj5RilAAlV4iiwauYntak2oU=
|
||||
github.com/jamespfennell/xz v0.1.2/go.mod h1:DhpWvZY1xDkK/6BREFl3c3R/fZh7IBdYq2m7xh4uLl0=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE=
|
||||
github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74=
|
||||
|
@ -608,8 +598,6 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
|||
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
|
||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||
github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8=
|
||||
github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
|
@ -1076,7 +1064,6 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks
|
|||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
|
||||
|
|
14
go/tumblrandom/default.nix
Normal file
14
go/tumblrandom/default.nix
Normal file
|
@ -0,0 +1,14 @@
|
|||
# SPDX-FileCopyrightText: 2023 Luke Granger-Brown <depot@lukegb.com>
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
{ depot, ... }:
|
||||
depot.third_party.buildGo.program {
|
||||
name = "tumblrandom";
|
||||
srcs = [
|
||||
./tumblrandom.go
|
||||
];
|
||||
deps = with depot; [
|
||||
third_party.gopkgs."golang.org".x.oauth2
|
||||
];
|
||||
}
|
353
go/tumblrandom/tumblrandom.go
Normal file
353
go/tumblrandom/tumblrandom.go
Normal file
|
@ -0,0 +1,353 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"log"
|
||||
mathrand "math/rand"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
var (
|
||||
debugOnlyAssumeEmail = flag.String("debug_only_assume_email", "", "If set, ignores the x-pomerium-claim-email header and just uses this static address.")
|
||||
addr = flag.String("addr", "localhost:10908", "Port to listen on.")
|
||||
dataDir = flag.String("data_dir", os.Getenv("STATE_DIRECTORY"), "Data directory to store data in.")
|
||||
|
||||
oauthClientID = flag.String("oauth_client_id", os.Getenv("OAUTH_CLIENT_ID"), "Sets the OAuth client ID to use.")
|
||||
oauthClientSecret = flag.String("oauth_client_secret", os.Getenv("OAUTH_CLIENT_SECRET"), "Sets the OAuth client secret to use.")
|
||||
baseURL = flag.String("base_url", "", "Sets my publically-visible base domain.")
|
||||
|
||||
httpMux = http.NewServeMux()
|
||||
)
|
||||
|
||||
type Post struct {
|
||||
PostURL string `json:"post_url"`
|
||||
}
|
||||
|
||||
type User struct {
|
||||
originPath string
|
||||
email string
|
||||
|
||||
OAuthToken *oauth2.Token `json:"oauth_token"`
|
||||
Likes []Post `json:"likes"`
|
||||
}
|
||||
|
||||
func (u *User) save() error {
|
||||
p := u.originPath
|
||||
if p == "" {
|
||||
return fmt.Errorf("originPath somehow unset")
|
||||
}
|
||||
|
||||
bs, err := json.Marshal(u)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return os.WriteFile(p, bs, 0600)
|
||||
}
|
||||
|
||||
func pathForUser(email, dataDir string) string {
|
||||
sum := sha256.Sum256([]byte(email))
|
||||
return filepath.Join(dataDir, hex.EncodeToString(sum[:])+".json")
|
||||
}
|
||||
|
||||
func loadUser(email, dataDir string) (*User, error) {
|
||||
p := pathForUser(email, dataDir)
|
||||
u := &User{originPath: p, email: email}
|
||||
|
||||
d, err := os.ReadFile(p)
|
||||
if errors.Is(err, fs.ErrNotExist) {
|
||||
log.Printf("generating new user for %v (path= %v)", email, p)
|
||||
return u, nil
|
||||
}
|
||||
if err := json.Unmarshal(d, u); err != nil {
|
||||
return nil, fmt.Errorf("unmarshalling JSON from %v: %w", p, err)
|
||||
}
|
||||
log.Printf("loaded user for %v from %v", email, p)
|
||||
return u, nil
|
||||
}
|
||||
|
||||
const (
|
||||
pomeriumEmailHeader = "x-pomerium-claim-email"
|
||||
oauthStateCookie = "tumblr-oauth-state"
|
||||
)
|
||||
|
||||
type contextKeyType struct{}
|
||||
|
||||
var (
|
||||
userContextKey = contextKeyType{}
|
||||
)
|
||||
|
||||
func user(ctx context.Context) (*User, bool) {
|
||||
u, ok := ctx.Value(userContextKey).(*User)
|
||||
return u, ok
|
||||
}
|
||||
|
||||
type app struct {
|
||||
oauthConfig *oauth2.Config
|
||||
dataDir string
|
||||
debugOnlyAssumeEmail string
|
||||
}
|
||||
|
||||
func (a *app) loadUserMiddleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
email := a.debugOnlyAssumeEmail
|
||||
if email == "" {
|
||||
email = r.Header.Get(pomeriumEmailHeader)
|
||||
}
|
||||
if email == "" {
|
||||
http.Error(rw, "no email", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
u, err := loadUser(email, a.dataDir)
|
||||
if err != nil {
|
||||
http.Error(rw, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
next.ServeHTTP(rw, r.WithContext(context.WithValue(r.Context(), userContextKey, u)))
|
||||
})
|
||||
}
|
||||
|
||||
func (a *app) performLogin(ctx context.Context, u *User, rw http.ResponseWriter, r *http.Request) {
|
||||
randData := make([]byte, 32)
|
||||
if n, err := rand.Read(randData); err != nil {
|
||||
http.Error(rw, "bad random: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
} else if n != len(randData) {
|
||||
http.Error(rw, fmt.Sprintf("bad random: got %d of random not %d", n, len(randData)), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
stateVal := hex.EncodeToString(randData)
|
||||
http.SetCookie(rw, &http.Cookie{
|
||||
Name: oauthStateCookie,
|
||||
Value: stateVal,
|
||||
HttpOnly: true,
|
||||
SameSite: http.SameSiteLaxMode,
|
||||
})
|
||||
http.Redirect(rw, r, a.oauthConfig.AuthCodeURL(stateVal, oauth2.AccessTypeOnline), http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func (a *app) handleOAuth(ctx context.Context, u *User, rw http.ResponseWriter, r *http.Request) {
|
||||
cookie, err := r.Cookie(oauthStateCookie)
|
||||
if err != nil {
|
||||
http.Error(rw, fmt.Sprintf("getting state cookie: %v", err), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if cookie.Value != r.URL.Query().Get("state") {
|
||||
http.Error(rw, "invalid state", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
tok, err := a.oauthConfig.Exchange(ctx, r.URL.Query().Get("code"))
|
||||
if err != nil {
|
||||
http.Error(rw, fmt.Sprintf("oauth2 exchange: %v", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
u.OAuthToken = tok
|
||||
if err := u.save(); err != nil {
|
||||
http.Error(rw, fmt.Sprintf("persisting user: %v", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
http.Redirect(rw, r, "/refresh", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func (a *app) redirectToLogin(rw http.ResponseWriter, r *http.Request) {
|
||||
http.Redirect(rw, r, "/login", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func (a *app) requireOAuthMiddleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
u, ok := user(ctx)
|
||||
if !ok {
|
||||
http.Error(rw, "user missing", http.StatusInternalServerError)
|
||||
} else if r.URL.Path == "/login" {
|
||||
a.performLogin(ctx, u, rw, r)
|
||||
} else if r.URL.Path == "/oauth" {
|
||||
a.handleOAuth(ctx, u, rw, r)
|
||||
} else if u == nil || (len(u.Likes) == 0 && (u.OAuthToken == nil || !u.OAuthToken.Valid())) {
|
||||
a.redirectToLogin(rw, r)
|
||||
} else {
|
||||
next.ServeHTTP(rw, r)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
type likesResponse struct {
|
||||
Response struct {
|
||||
LikedPosts []Post `json:"liked_posts"`
|
||||
Links struct {
|
||||
Next struct {
|
||||
Href string `json:"href"`
|
||||
} `json:"next"`
|
||||
} `json:"_links"`
|
||||
} `json:"response"`
|
||||
}
|
||||
|
||||
func (a *app) refreshLikes(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
u, ok := user(ctx)
|
||||
if !ok || !u.OAuthToken.Valid() {
|
||||
a.redirectToLogin(rw, r)
|
||||
return
|
||||
}
|
||||
|
||||
client := a.oauthConfig.Client(ctx, u.OAuthToken)
|
||||
|
||||
var likes []Post
|
||||
const urlPrefix = "https://api.tumblr.com"
|
||||
urlSuffix := "/v2/user/likes"
|
||||
for {
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", urlPrefix+urlSuffix, nil)
|
||||
if err != nil {
|
||||
http.Error(rw, fmt.Sprintf("formulating likes request: %v", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
fmt.Println(req.URL)
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
http.Error(rw, fmt.Sprintf("performing likes request: %v", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
errBody, _ := io.ReadAll(resp.Body)
|
||||
http.Error(rw, fmt.Sprintf("likes request status %v\n\n%v", resp.StatusCode, string(errBody)), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
var r likesResponse
|
||||
if err := json.NewDecoder(resp.Body).Decode(&r); err != nil {
|
||||
http.Error(rw, fmt.Sprintf("decoding likes body as json: %v", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
likes = append(likes, r.Response.LikedPosts...)
|
||||
|
||||
urlSuffix = r.Response.Links.Next.Href
|
||||
if urlSuffix == "" {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
u.Likes = likes
|
||||
if err := u.save(); err != nil {
|
||||
http.Error(rw, fmt.Sprintf("saving likes: %v", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
http.Redirect(rw, r, "/?refreshed=true", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
func (a *app) index(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
u, ok := user(ctx)
|
||||
if !ok {
|
||||
a.redirectToLogin(rw, r)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Fprintf(rw, `
|
||||
<!DOCTYPE html>
|
||||
<h1>%d likes</h1>
|
||||
<h2><a href="/random">random</a></h2>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<a href="/refresh">refresh</a>
|
||||
`, len(u.Likes))
|
||||
}
|
||||
|
||||
func (a *app) random(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
u, ok := user(ctx)
|
||||
if !ok {
|
||||
a.redirectToLogin(rw, r)
|
||||
return
|
||||
}
|
||||
if len(u.Likes) == 0 {
|
||||
http.Redirect(rw, r, "/", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
n := mathrand.Intn(len(u.Likes))
|
||||
l := u.Likes[n]
|
||||
http.Redirect(rw, r, l.PostURL, http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
log.Println("using oauth client ID", *oauthClientID)
|
||||
a := &app{
|
||||
oauthConfig: &oauth2.Config{
|
||||
ClientID: *oauthClientID,
|
||||
ClientSecret: *oauthClientSecret,
|
||||
Endpoint: oauth2.Endpoint{
|
||||
AuthURL: "https://www.tumblr.com/oauth2/authorize",
|
||||
TokenURL: "https://api.tumblr.com/v2/oauth2/token",
|
||||
},
|
||||
Scopes: []string{"basic"},
|
||||
RedirectURL: fmt.Sprintf("%s/oauth", *baseURL),
|
||||
},
|
||||
dataDir: *dataDir,
|
||||
debugOnlyAssumeEmail: *debugOnlyAssumeEmail,
|
||||
}
|
||||
httpMux.HandleFunc("/refresh", a.refreshLikes)
|
||||
httpMux.HandleFunc("/", a.index)
|
||||
httpMux.HandleFunc("/random", a.random)
|
||||
|
||||
s := &http.Server{
|
||||
Handler: a.loadUserMiddleware(a.requireOAuthMiddleware(httpMux)),
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
for _, singleAddr := range strings.Split(*addr, ",") {
|
||||
singleAddr := singleAddr
|
||||
go func() {
|
||||
l, err := net.Listen("tcp", singleAddr)
|
||||
if err != nil {
|
||||
log.Printf("listen on %v: %v", singleAddr, err)
|
||||
cancel()
|
||||
return
|
||||
}
|
||||
log.Printf("starting to serve on %v", singleAddr)
|
||||
if err := s.Serve(l); err != http.ErrServerClosed {
|
||||
log.Printf("HTTP server ListenAndServe: %v", err)
|
||||
cancel()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
ctx, stop := signal.NotifyContext(ctx, os.Interrupt)
|
||||
defer stop()
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
log.Println("shutting down gracefully (SIGINT again to stop immediately)")
|
||||
stop()
|
||||
if err := s.Shutdown(context.Background()); err != nil {
|
||||
log.Printf("HTTP server Shutdown: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue