From cebe929118d451ec722f882a40b0b75161829047 Mon Sep 17 00:00:00 2001 From: Dmitry Verkhoturov Date: Sun, 2 Oct 2022 22:39:28 +0200 Subject: [PATCH] bump go modules, enable LoginAuth option for email That option is needed for outlook.com and Office 365, resolves #1472. --- backend/_example/memory_store/go.mod | 13 +- backend/_example/memory_store/go.sum | 25 +- backend/app/cmd/server.go | 19 +- backend/go.mod | 28 +- backend/go.sum | 86 +- .../github.com/alecthomas/chroma/v2/README.md | 4 +- .../github.com/alecthomas/chroma/v2/colour.go | 32 +- .../alecthomas/chroma/v2/lexers/chapel.go | 62 + .../alecthomas/chroma/v2/lexers/dns.go | 17 + .../alecthomas/chroma/v2/lexers/docker.go | 2 +- .../chroma/v2/lexers/embedded/cfengine3.xml | 12 - .../chroma/v2/lexers/embedded/dns.xml | 42 + .../chroma/v2/lexers/embedded/fortran.xml | 30 +- .../chroma/v2/lexers/embedded/gas.xml | 34 +- .../chroma/v2/lexers/embedded/javascript.xml | 1 + .../chroma/v2/lexers/embedded/mcfunction.xml | 4 +- .../chroma/v2/lexers/embedded/properties.xml | 45 + .../v2/lexers/embedded/transact-sql.xml | 4 +- .../chroma/v2/lexers/fortran_fixed.go | 10 +- .../alecthomas/chroma/v2/lexers/make.go | 2 +- .../github.com/alecthomas/chroma/v2/style.go | 26 +- .../chroma/v2/styles/github-dark.go | 86 + .../chroma/v2/styles/gruvbox-light.go | 40 + .../didip/tollbooth/v7/tollbooth.go | 4 + .../github.com/go-oauth2/oauth2/v4/README.md | 1 + .../github.com/go-oauth2/oauth2/v4/manage.go | 2 +- .../go-oauth2/oauth2/v4/server/handler.go | 2 +- .../go-oauth2/oauth2/v4/server/server.go | 4 +- .../vendor/github.com/go-pkgz/auth/README.md | 20 + .../github.com/go-pkgz/auth/avatar/store.go | 7 +- .../go-pkgz/auth/provider/sender/email.go | 174 +- .../go-pkgz/auth/provider/telegram.go | 2 +- .../github.com/go-pkgz/email/.golangci.yml | 32 +- .../vendor/github.com/go-pkgz/email/README.md | 39 +- .../vendor/github.com/go-pkgz/email/auth.go | 60 + .../vendor/github.com/go-pkgz/email/email.go | 37 +- .../github.com/go-pkgz/email/options.go | 7 + .../vendor/github.com/go-pkgz/notify/email.go | 5 + .../github.com/go-pkgz/notify/telegram.go | 2 +- .../github.com/go-pkgz/rest/.golangci.yml | 5 +- .../vendor/github.com/go-pkgz/rest/README.md | 56 + .../github.com/go-pkgz/rest/middleware.go | 57 + .../vendor/github.com/go-pkgz/rest/rest.go | 13 +- .../github.com/go-stack/stack/README.md | 38 - .../vendor/github.com/go-stack/stack/stack.go | 400 --- .../github.com/montanaflynn/stats/.gitignore | 2 + .../github.com/montanaflynn/stats/.travis.yml | 20 + .../montanaflynn/stats/CHANGELOG.md | 64 + .../LICENSE.md => montanaflynn/stats/LICENSE} | 2 +- .../github.com/montanaflynn/stats/Makefile | 29 + .../github.com/montanaflynn/stats/README.md | 103 + .../montanaflynn/stats/correlation.go | 33 + .../github.com/montanaflynn/stats/data.go | 140 ++ .../montanaflynn/stats/data_set_distances.go | 94 + .../montanaflynn/stats/deviation.go | 57 + .../github.com/montanaflynn/stats/errors.go | 22 + .../github.com/montanaflynn/stats/legacy.go | 36 + .../github.com/montanaflynn/stats/load.go | 184 ++ .../github.com/montanaflynn/stats/max.go | 24 + .../github.com/montanaflynn/stats/mean.go | 60 + .../github.com/montanaflynn/stats/median.go | 25 + .../github.com/montanaflynn/stats/min.go | 26 + .../github.com/montanaflynn/stats/mode.go | 47 + .../github.com/montanaflynn/stats/outlier.go | 44 + .../montanaflynn/stats/percentile.go | 80 + .../github.com/montanaflynn/stats/quartile.go | 74 + .../montanaflynn/stats/regression.go | 113 + .../github.com/montanaflynn/stats/round.go | 38 + .../github.com/montanaflynn/stats/sample.go | 44 + .../github.com/montanaflynn/stats/sum.go | 18 + .../github.com/montanaflynn/stats/util.go | 43 + .../github.com/montanaflynn/stats/variance.go | 105 + .../github.com/slack-go/slack/README.md | 8 +- .../github.com/slack-go/slack/block_input.go | 3 +- .../github.com/slack-go/slack/bookmarks.go | 159 ++ .../vendor/github.com/slack-go/slack/chat.go | 19 + .../github.com/slack-go/slack/conversation.go | 18 +- .../github.com/slack-go/slack/dialog_text.go | 2 +- .../vendor/github.com/slack-go/slack/files.go | 2 +- .../vendor/github.com/slack-go/slack/info.go | 5 + .../slack/internal/backoff/backoff.go | 2 +- .../github.com/slack-go/slack/messages.go | 5 + .../github.com/slack-go/slack/metadata.go | 7 + .../vendor/github.com/slack-go/slack/misc.go | 6 +- .../github.com/slack-go/slack/remotefiles.go | 316 +++ .../vendor/github.com/slack-go/slack/stars.go | 19 +- .../misc/misc.go => status_code_error.go} | 2 +- .../github.com/slack-go/slack/usergroups.go | 69 +- .../vendor/github.com/slack-go/slack/users.go | 17 +- .../vendor/github.com/slack-go/slack/views.go | 37 +- .../github.com/slack-go/slack/webhooks.go | 8 +- .../slack-go/slack/websocket_managed_conn.go | 32 +- .../slack-go/slack/websocket_subteam.go | 4 +- .../slack-go/slack/workflow_step_execute.go | 85 + .../mongo-driver/bson/bsoncodec/bsoncodec.go | 22 + .../bson/bsoncodec/default_value_decoders.go | 16 +- .../mongo-driver/bson/bsoncodec/doc.go | 6 + .../bson/bsoncodec/empty_interface_codec.go | 17 +- .../mongo-driver/bson/bsoncodec/map_codec.go | 21 + .../mongo-driver/bson/bsonoptions/doc.go | 8 + .../mongo-driver/bson/bsonrw/value_reader.go | 9 +- .../mongo-driver/bson/decoder.go | 23 + .../mongo-driver/internal/csfle_util.go | 39 + .../mongo-driver/internal/csot_util.go | 34 + .../mongo-driver/internal/error.go | 4 + .../internal/randutil/rand/bits.go | 38 + .../internal/randutil/rand/exp.go | 223 ++ .../internal/randutil/rand/normal.go | 158 ++ .../internal/randutil/rand/rand.go | 374 +++ .../internal/randutil/rand/rng.go | 93 + .../internal/randutil/randutil.go | 64 +- .../{x/mongo/driver => internal}/uuid/uuid.go | 35 +- .../mongo-driver/mongo/address/addr.go | 1 + .../mongo-driver/mongo/batch_cursor.go | 6 + .../mongo-driver/mongo/bulk_write.go | 29 +- .../mongo-driver/mongo/bulk_write_models.go | 6 +- .../mongo-driver/mongo/change_stream.go | 61 +- .../mongo/change_stream_deployment.go | 4 + .../mongo-driver/mongo/client.go | 176 +- .../mongo-driver/mongo/client_encryption.go | 207 +- .../mongo-driver/mongo/collection.go | 222 +- .../mongo-driver/mongo/cursor.go | 2 +- .../mongo-driver/mongo/database.go | 210 +- .../mongo/description/description.go | 1 + .../go.mongodb.org/mongo-driver/mongo/doc.go | 34 +- .../mongo-driver/mongo/errors.go | 3 + .../mongo-driver/mongo/gridfs/bucket.go | 71 +- .../mongo-driver/mongo/gridfs/doc.go | 2 +- .../mongo/gridfs/upload_stream.go | 44 +- .../mongo-driver/mongo/index_view.go | 19 +- .../mongo-driver/mongo/mongo.go | 11 - .../mongo-driver/mongo/mongocryptd.go | 26 +- .../mongo/options/aggregateoptions.go | 12 +- .../mongo/options/autoencryptionoptions.go | 54 +- .../mongo/options/bulkwriteoptions.go | 15 +- .../mongo/options/changestreamoptions.go | 45 +- .../mongo/options/clientoptions.go | 91 +- .../mongo/options/collectionoptions.go | 16 +- .../mongo/options/countoptions.go | 24 + .../mongo/options/createcollectionoptions.go | 59 +- .../mongo/options/datakeyoptions.go | 13 + .../mongo-driver/mongo/options/dboptions.go | 16 +- .../mongo/options/deleteoptions.go | 13 + .../mongo/options/distinctoptions.go | 21 + .../mongo-driver/mongo/options/doc.go | 8 + .../mongo/options/encryptoptions.go | 49 +- .../mongo/options/estimatedcountoptions.go | 22 +- .../mongo-driver/mongo/options/findoptions.go | 155 +- .../mongo/options/gridfsoptions.go | 8 + .../mongo/options/indexoptions.go | 28 +- .../mongo/options/insertoptions.go | 30 +- .../mongo/options/listdatabasesoptions.go | 2 +- .../mongo/options/mongooptions.go | 14 +- .../mongo/options/replaceoptions.go | 15 +- .../mongo/options/rewrapdatakeyoptions.go | 52 + .../mongo/options/sessionoptions.go | 11 +- .../mongo/options/transactionoptions.go | 8 + .../mongo/options/updateoptions.go | 15 +- .../mongo/readconcern/readconcern.go | 1 + .../mongo-driver/mongo/readpref/options.go | 2 +- .../mongo-driver/mongo/readpref/readpref.go | 1 + .../mongo-driver/mongo/results.go | 17 + .../mongo-driver/mongo/session.go | 25 +- .../mongo/writeconcern/writeconcern.go | 15 +- .../go.mongodb.org/mongo-driver/tag/tag.go | 1 + .../mongo-driver/version/version.go | 3 +- .../mongo-driver/x/bsonx/bsoncore/bsoncore.go | 16 +- .../mongo-driver/x/bsonx/bsoncore/document.go | 30 +- .../x/bsonx/bsoncore/document_sequence.go | 6 + .../mongo-driver/x/bsonx/registry.go | 6 + .../driver/auth/internal/gssapi/gss_wrapper.c | 6 + .../driver/auth/internal/gssapi/gss_wrapper.h | 6 + .../auth/internal/gssapi/sspi_wrapper.c | 6 + .../auth/internal/gssapi/sspi_wrapper.h | 6 + .../x/mongo/driver/batch_cursor.go | 22 +- .../mongo-driver/x/mongo/driver/batches.go | 6 + .../x/mongo/driver/compression.go | 30 +- .../x/mongo/driver/connstring/connstring.go | 87 +- .../mongo-driver/x/mongo/driver/crypt.go | 75 +- .../mongo-driver/x/mongo/driver/driver.go | 24 +- .../mongo-driver/x/mongo/driver/errors.go | 9 + .../mongo-driver/x/mongo/driver/legacy.go | 6 + .../x/mongo/driver/mongocrypt/mongocrypt.go | 170 +- .../mongocrypt/mongocrypt_not_enabled.go | 23 + .../options/mongocrypt_context_options.go | 80 +- .../mongocrypt/options/mongocrypt_options.go | 33 +- .../mongo-driver/x/mongo/driver/operation.go | 93 +- .../x/mongo/driver/operation/aggregate.go | 19 +- .../x/mongo/driver/operation/command.go | 15 +- .../x/mongo/driver/operation/count.go | 68 +- .../x/mongo/driver/operation/create.go | 89 +- .../x/mongo/driver/operation/createIndexes.go | 16 +- .../x/mongo/driver/operation/delete.go | 28 + .../x/mongo/driver/operation/distinct.go | 30 +- .../x/mongo/driver/operation/drop_indexes.go | 16 +- .../x/mongo/driver/operation/find.go | 18 +- .../mongo/driver/operation/find_and_modify.go | 31 +- .../x/mongo/driver/operation/insert.go | 28 + .../x/mongo/driver/operation/listDatabases.go | 15 +- .../driver/operation/list_collections.go | 15 +- .../x/mongo/driver/operation/list_indexes.go | 17 +- .../x/mongo/driver/operation/update.go | 28 + .../x/mongo/driver/session/client_session.go | 2 +- .../x/mongo/driver/session/server_session.go | 2 +- .../x/mongo/driver/topology/connection.go | 16 +- .../driver/topology/connection_legacy.go | 6 + .../driver/topology/connection_options.go | 6 + .../x/mongo/driver/topology/errors.go | 6 + .../x/mongo/driver/topology/fsm.go | 2 +- .../driver/topology/hanging_tls_conn_1_16.go | 37 - .../driver/topology/hanging_tls_conn_1_17.go | 44 - .../x/mongo/driver/topology/pool.go | 6 + .../x/mongo/driver/topology/rtt_monitor.go | 137 +- .../x/mongo/driver/topology/server.go | 7 +- .../x/mongo/driver/topology/server_options.go | 1 - .../x/mongo/driver/topology/topology.go | 5 +- .../x/mongo/driver/wiremessage/wiremessage.go | 22 + .../vendor/go.uber.org/goleak/CHANGELOG.md | 23 +- backend/vendor/go.uber.org/goleak/leaks.go | 26 +- backend/vendor/go.uber.org/goleak/options.go | 34 +- backend/vendor/go.uber.org/goleak/testmain.go | 18 +- .../go.uber.org/goleak/tracestack_old.go | 38 - backend/vendor/golang.org/x/net/AUTHORS | 3 - backend/vendor/golang.org/x/net/CONTRIBUTORS | 3 - .../vendor/golang.org/x/net/html/render.go | 4 +- backend/vendor/golang.org/x/net/html/token.go | 4 +- backend/vendor/golang.org/x/sys/AUTHORS | 3 - backend/vendor/golang.org/x/sys/CONTRIBUTORS | 3 - .../golang.org/x/sys/unix/asm_bsd_riscv64.s | 29 + .../golang.org/x/sys/unix/asm_linux_loong64.s | 4 +- .../x/sys/unix/errors_freebsd_386.go | 233 -- .../x/sys/unix/errors_freebsd_amd64.go | 233 -- .../x/sys/unix/errors_freebsd_arm.go | 226 -- .../x/sys/unix/errors_freebsd_arm64.go | 17 - backend/vendor/golang.org/x/sys/unix/mkall.sh | 13 +- .../vendor/golang.org/x/sys/unix/mkerrors.sh | 10 +- .../golang.org/x/sys/unix/syscall_aix.go | 61 +- .../golang.org/x/sys/unix/syscall_bsd.go | 46 +- .../golang.org/x/sys/unix/syscall_darwin.go | 7 + .../golang.org/x/sys/unix/syscall_freebsd.go | 327 +-- .../x/sys/unix/syscall_freebsd_386.go | 4 +- .../x/sys/unix/syscall_freebsd_amd64.go | 4 +- .../x/sys/unix/syscall_freebsd_arm.go | 2 +- .../x/sys/unix/syscall_freebsd_arm64.go | 2 +- .../x/sys/unix/syscall_freebsd_riscv64.go | 63 + .../golang.org/x/sys/unix/syscall_illumos.go | 5 +- .../golang.org/x/sys/unix/syscall_linux.go | 45 +- .../x/sys/unix/syscall_linux_loong64.go | 39 +- .../x/sys/unix/syscall_linux_riscv64.go | 1 + .../x/sys/unix/syscall_openbsd_mips64.go | 4 + .../golang.org/x/sys/unix/syscall_solaris.go | 51 +- .../golang.org/x/sys/unix/syscall_unix.go | 74 +- .../x/sys/unix/zerrors_freebsd_386.go | 109 +- .../x/sys/unix/zerrors_freebsd_amd64.go | 107 +- .../x/sys/unix/zerrors_freebsd_arm.go | 220 +- .../x/sys/unix/zerrors_freebsd_arm64.go | 100 +- .../x/sys/unix/zerrors_freebsd_riscv64.go | 2148 +++++++++++++++++ .../golang.org/x/sys/unix/zerrors_linux.go | 389 ++- .../x/sys/unix/zerrors_linux_386.go | 2 + .../x/sys/unix/zerrors_linux_amd64.go | 2 + .../x/sys/unix/zerrors_linux_arm.go | 2 + .../x/sys/unix/zerrors_linux_arm64.go | 3 + .../x/sys/unix/zerrors_linux_loong64.go | 4 +- .../x/sys/unix/zerrors_linux_mips.go | 2 + .../x/sys/unix/zerrors_linux_mips64.go | 2 + .../x/sys/unix/zerrors_linux_mips64le.go | 2 + .../x/sys/unix/zerrors_linux_mipsle.go | 2 + .../x/sys/unix/zerrors_linux_ppc.go | 2 + .../x/sys/unix/zerrors_linux_ppc64.go | 2 + .../x/sys/unix/zerrors_linux_ppc64le.go | 2 + .../x/sys/unix/zerrors_linux_riscv64.go | 2 + .../x/sys/unix/zerrors_linux_s390x.go | 2 + .../x/sys/unix/zerrors_linux_sparc64.go | 2 + .../x/sys/unix/zsyscall_freebsd_386.go | 141 +- .../x/sys/unix/zsyscall_freebsd_amd64.go | 139 +- .../x/sys/unix/zsyscall_freebsd_arm.go | 173 +- .../x/sys/unix/zsyscall_freebsd_arm64.go | 139 +- .../x/sys/unix/zsyscall_freebsd_riscv64.go | 1889 +++++++++++++++ .../x/sys/unix/zsyscall_linux_loong64.go | 25 - .../x/sys/unix/zsyscall_linux_riscv64.go | 11 + .../x/sys/unix/zsyscall_solaris_amd64.go | 14 + .../x/sys/unix/zsysnum_freebsd_386.go | 107 +- .../x/sys/unix/zsysnum_freebsd_amd64.go | 107 +- .../x/sys/unix/zsysnum_freebsd_arm.go | 107 +- .../x/sys/unix/zsysnum_freebsd_arm64.go | 107 +- .../x/sys/unix/zsysnum_freebsd_riscv64.go | 394 +++ .../x/sys/unix/zsysnum_linux_loong64.go | 2 - .../x/sys/unix/zsysnum_linux_riscv64.go | 1 + .../x/sys/unix/ztypes_darwin_amd64.go | 73 +- .../x/sys/unix/ztypes_darwin_arm64.go | 73 +- .../x/sys/unix/ztypes_freebsd_386.go | 97 +- .../x/sys/unix/ztypes_freebsd_amd64.go | 94 +- .../x/sys/unix/ztypes_freebsd_arm.go | 145 +- .../x/sys/unix/ztypes_freebsd_arm64.go | 92 +- .../x/sys/unix/ztypes_freebsd_riscv64.go | 626 +++++ .../golang.org/x/sys/unix/ztypes_linux.go | 27 +- .../golang.org/x/sys/unix/ztypes_linux_386.go | 7 + .../x/sys/unix/ztypes_linux_amd64.go | 6 + .../golang.org/x/sys/unix/ztypes_linux_arm.go | 7 + .../x/sys/unix/ztypes_linux_arm64.go | 6 + .../x/sys/unix/ztypes_linux_loong64.go | 6 + .../x/sys/unix/ztypes_linux_mips.go | 7 + .../x/sys/unix/ztypes_linux_mips64.go | 6 + .../x/sys/unix/ztypes_linux_mips64le.go | 6 + .../x/sys/unix/ztypes_linux_mipsle.go | 7 + .../golang.org/x/sys/unix/ztypes_linux_ppc.go | 7 + .../x/sys/unix/ztypes_linux_ppc64.go | 6 + .../x/sys/unix/ztypes_linux_ppc64le.go | 6 + .../x/sys/unix/ztypes_linux_riscv64.go | 6 + .../x/sys/unix/ztypes_linux_s390x.go | 6 + .../x/sys/unix/ztypes_linux_sparc64.go | 6 + .../x/sys/unix/ztypes_solaris_amd64.go | 2 +- backend/vendor/modules.txt | 42 +- .../docs/configuration/parameters/index.md | 1 + 314 files changed, 13952 insertions(+), 4131 deletions(-) create mode 100644 backend/vendor/github.com/alecthomas/chroma/v2/lexers/chapel.go create mode 100644 backend/vendor/github.com/alecthomas/chroma/v2/lexers/dns.go create mode 100644 backend/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/dns.xml create mode 100644 backend/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/properties.xml create mode 100644 backend/vendor/github.com/alecthomas/chroma/v2/styles/github-dark.go create mode 100644 backend/vendor/github.com/alecthomas/chroma/v2/styles/gruvbox-light.go create mode 100644 backend/vendor/github.com/go-pkgz/email/auth.go delete mode 100644 backend/vendor/github.com/go-stack/stack/README.md delete mode 100644 backend/vendor/github.com/go-stack/stack/stack.go create mode 100644 backend/vendor/github.com/montanaflynn/stats/.gitignore create mode 100644 backend/vendor/github.com/montanaflynn/stats/.travis.yml create mode 100644 backend/vendor/github.com/montanaflynn/stats/CHANGELOG.md rename backend/vendor/github.com/{go-stack/stack/LICENSE.md => montanaflynn/stats/LICENSE} (94%) create mode 100644 backend/vendor/github.com/montanaflynn/stats/Makefile create mode 100644 backend/vendor/github.com/montanaflynn/stats/README.md create mode 100644 backend/vendor/github.com/montanaflynn/stats/correlation.go create mode 100644 backend/vendor/github.com/montanaflynn/stats/data.go create mode 100644 backend/vendor/github.com/montanaflynn/stats/data_set_distances.go create mode 100644 backend/vendor/github.com/montanaflynn/stats/deviation.go create mode 100644 backend/vendor/github.com/montanaflynn/stats/errors.go create mode 100644 backend/vendor/github.com/montanaflynn/stats/legacy.go create mode 100644 backend/vendor/github.com/montanaflynn/stats/load.go create mode 100644 backend/vendor/github.com/montanaflynn/stats/max.go create mode 100644 backend/vendor/github.com/montanaflynn/stats/mean.go create mode 100644 backend/vendor/github.com/montanaflynn/stats/median.go create mode 100644 backend/vendor/github.com/montanaflynn/stats/min.go create mode 100644 backend/vendor/github.com/montanaflynn/stats/mode.go create mode 100644 backend/vendor/github.com/montanaflynn/stats/outlier.go create mode 100644 backend/vendor/github.com/montanaflynn/stats/percentile.go create mode 100644 backend/vendor/github.com/montanaflynn/stats/quartile.go create mode 100644 backend/vendor/github.com/montanaflynn/stats/regression.go create mode 100644 backend/vendor/github.com/montanaflynn/stats/round.go create mode 100644 backend/vendor/github.com/montanaflynn/stats/sample.go create mode 100644 backend/vendor/github.com/montanaflynn/stats/sum.go create mode 100644 backend/vendor/github.com/montanaflynn/stats/util.go create mode 100644 backend/vendor/github.com/montanaflynn/stats/variance.go create mode 100644 backend/vendor/github.com/slack-go/slack/bookmarks.go create mode 100644 backend/vendor/github.com/slack-go/slack/metadata.go create mode 100644 backend/vendor/github.com/slack-go/slack/remotefiles.go rename backend/vendor/github.com/slack-go/slack/{internal/misc/misc.go => status_code_error.go} (97%) create mode 100644 backend/vendor/github.com/slack-go/slack/workflow_step_execute.go create mode 100644 backend/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/doc.go create mode 100644 backend/vendor/go.mongodb.org/mongo-driver/internal/csfle_util.go create mode 100644 backend/vendor/go.mongodb.org/mongo-driver/internal/csot_util.go create mode 100644 backend/vendor/go.mongodb.org/mongo-driver/internal/randutil/rand/bits.go create mode 100644 backend/vendor/go.mongodb.org/mongo-driver/internal/randutil/rand/exp.go create mode 100644 backend/vendor/go.mongodb.org/mongo-driver/internal/randutil/rand/normal.go create mode 100644 backend/vendor/go.mongodb.org/mongo-driver/internal/randutil/rand/rand.go create mode 100644 backend/vendor/go.mongodb.org/mongo-driver/internal/randutil/rand/rng.go rename backend/vendor/go.mongodb.org/mongo-driver/{x/mongo/driver => internal}/uuid/uuid.go (54%) create mode 100644 backend/vendor/go.mongodb.org/mongo-driver/mongo/options/doc.go create mode 100644 backend/vendor/go.mongodb.org/mongo-driver/mongo/options/rewrapdatakeyoptions.go delete mode 100644 backend/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/hanging_tls_conn_1_16.go delete mode 100644 backend/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/hanging_tls_conn_1_17.go delete mode 100644 backend/vendor/go.uber.org/goleak/tracestack_old.go delete mode 100644 backend/vendor/golang.org/x/net/AUTHORS delete mode 100644 backend/vendor/golang.org/x/net/CONTRIBUTORS delete mode 100644 backend/vendor/golang.org/x/sys/AUTHORS delete mode 100644 backend/vendor/golang.org/x/sys/CONTRIBUTORS create mode 100644 backend/vendor/golang.org/x/sys/unix/asm_bsd_riscv64.s delete mode 100644 backend/vendor/golang.org/x/sys/unix/errors_freebsd_386.go delete mode 100644 backend/vendor/golang.org/x/sys/unix/errors_freebsd_amd64.go delete mode 100644 backend/vendor/golang.org/x/sys/unix/errors_freebsd_arm.go delete mode 100644 backend/vendor/golang.org/x/sys/unix/errors_freebsd_arm64.go create mode 100644 backend/vendor/golang.org/x/sys/unix/syscall_freebsd_riscv64.go create mode 100644 backend/vendor/golang.org/x/sys/unix/zerrors_freebsd_riscv64.go create mode 100644 backend/vendor/golang.org/x/sys/unix/zsyscall_freebsd_riscv64.go create mode 100644 backend/vendor/golang.org/x/sys/unix/zsysnum_freebsd_riscv64.go create mode 100644 backend/vendor/golang.org/x/sys/unix/ztypes_freebsd_riscv64.go diff --git a/backend/_example/memory_store/go.mod b/backend/_example/memory_store/go.mod index 5f403ab013..332e65c370 100644 --- a/backend/_example/memory_store/go.mod +++ b/backend/_example/memory_store/go.mod @@ -14,29 +14,28 @@ require ( github.com/Depado/bfchroma/v2 v2.0.0 // indirect github.com/PuerkitoBio/goquery v1.8.0 // indirect github.com/ajg/form v1.5.1 // indirect - github.com/alecthomas/chroma/v2 v2.2.0 // indirect + github.com/alecthomas/chroma/v2 v2.3.0 // indirect github.com/andybalholm/cascadia v1.3.1 // indirect github.com/aymerick/douceur v0.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/didip/tollbooth/v7 v7.0.0 // indirect + github.com/didip/tollbooth/v7 v7.0.1 // indirect github.com/didip/tollbooth_chi v0.0.0-20220719025231-d662a7f6928f // indirect github.com/dlclark/regexp2 v1.4.0 // indirect github.com/go-chi/chi/v5 v5.0.7 // indirect github.com/go-chi/render v1.0.2 // indirect github.com/go-pkgz/expirable-cache v0.1.0 // indirect - github.com/go-pkgz/rest v1.15.6 // indirect + github.com/go-pkgz/rest v1.16.0 // indirect github.com/gorilla/css v1.0.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/microcosm-cc/bluemonday v1.0.19 // indirect - github.com/pkg/errors v0.9.1 // indirect + github.com/microcosm-cc/bluemonday v1.0.20 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rs/xid v1.4.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect go.etcd.io/bbolt v1.3.6 // indirect golang.org/x/image v0.0.0-20220617043117-41969df76e82 // indirect - golang.org/x/net v0.0.0-20220708220712-1185a9018129 // indirect - golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect + golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b // indirect + golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/backend/_example/memory_store/go.sum b/backend/_example/memory_store/go.sum index 39bf0f65db..4269bbd89e 100644 --- a/backend/_example/memory_store/go.sum +++ b/backend/_example/memory_store/go.sum @@ -4,9 +4,9 @@ github.com/PuerkitoBio/goquery v1.8.0 h1:PJTF7AmFCFKk1N6V6jmKfrNH9tV5pNE6lZMkG0g github.com/PuerkitoBio/goquery v1.8.0/go.mod h1:ypIiRMtY7COPGk+I/YbZLbxsxn9g5ejnI2HSMtkjZvI= github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= -github.com/alecthomas/chroma/v2 v2.2.0 h1:Aten8jfQwUqEdadVFFjNyjx7HTexhKP0XuqBG67mRDY= -github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs= -github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae h1:zzGwJfFlFGD94CyyYwCJeSuD32Gj9GTaSi5y9hoVzdY= +github.com/alecthomas/chroma/v2 v2.3.0 h1:83xfxrnjv8eK+Cf8qZDzNo3PPF9IbTWHs7z28GY6D0U= +github.com/alecthomas/chroma/v2 v2.3.0/go.mod h1:mZxeWZlxP2Dy+/8cBob2PYd8O2DwNAzave5AY7A2eQw= +github.com/alecthomas/repr v0.1.0 h1:ENn2e1+J3k09gyj2shc0dHr/yjaWSHRlrJ4DPMevDqE= github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c= github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= @@ -14,8 +14,9 @@ github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd3 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/didip/tollbooth/v7 v7.0.0 h1:XmyyNwZpz9j61PwR4A894MmmYO5zBF9xjgVi2n1fiQI= github.com/didip/tollbooth/v7 v7.0.0/go.mod h1:VZhDSGl5bDSPj4wPsih3PFa4Uh9Ghv8hgacaTm5PRT4= +github.com/didip/tollbooth/v7 v7.0.1 h1:TkT4sBKoQoHQFPf7blQ54iHrZiTDnr8TceU+MulVAog= +github.com/didip/tollbooth/v7 v7.0.1/go.mod h1:VZhDSGl5bDSPj4wPsih3PFa4Uh9Ghv8hgacaTm5PRT4= github.com/didip/tollbooth_chi v0.0.0-20220719025231-d662a7f6928f h1:jtKwihcLmUC9BAhoJ9adCUqdSSZcOdH2KL7mPTUm2aw= github.com/didip/tollbooth_chi v0.0.0-20220719025231-d662a7f6928f/go.mod h1:q9C80dnsuVRP2dAskjnXRNWdUJqtGgwG9wNrzt0019s= github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E= @@ -31,8 +32,9 @@ github.com/go-pkgz/jrpc v0.3.0 h1:Fls38KqPsHzvp0FWfivr6cGnncC+iFBodHBqvUPY+0U= github.com/go-pkgz/jrpc v0.3.0/go.mod h1:MFtKs75JESiSqVicsQkgN2iDFFuCd3gVT1/vKiwRi00= github.com/go-pkgz/lgr v0.10.4 h1:l7qyFjqEZgwRgaQQSEp6tve4A3OU80VrfzpvtEX8ngw= github.com/go-pkgz/lgr v0.10.4/go.mod h1:CD0s1z6EFpIUplV067gitF77tn25JItzwHNKAPqeCF0= -github.com/go-pkgz/rest v1.15.6 h1:8RgOuY/c00CD0el8KdmscOCgDH+ML0ZsK2qa1Rcxal4= github.com/go-pkgz/rest v1.15.6/go.mod h1:KUWAqbDteYGS/CiXftomQsKjtEOifXsJ36Ka0skYbmk= +github.com/go-pkgz/rest v1.16.0 h1:3An51XJXUq1XtICHvfAEp048ZCbUHBEga3g0WEu3zK0= +github.com/go-pkgz/rest v1.16.0/go.mod h1:HHlLOt02NJc2sgffXBF6hYVMcRo4Gz3vjg43zTzN7VM= github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -47,9 +49,8 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/microcosm-cc/bluemonday v1.0.19 h1:OI7hoF5FY4pFz2VA//RN8TfM0YJ2dJcl4P4APrCWy6c= -github.com/microcosm-cc/bluemonday v1.0.19/go.mod h1:QNzV2UbLK2/53oIIwTOyLUSABMkjZ4tqiyC1g/DyqxE= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/microcosm-cc/bluemonday v1.0.20 h1:flpzsq4KU3QIYAYGV/szUat7H+GPOXR0B2JU5A1Wp8Y= +github.com/microcosm-cc/bluemonday v1.0.20/go.mod h1:yfBmMi8mxvaZut3Yytv+jTXRY8mxyjJ0/kQBTElld50= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -69,14 +70,14 @@ go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= golang.org/x/image v0.0.0-20220617043117-41969df76e82 h1:KpZB5pUSBvrHltNEdK/tw0xlPeD13M6M6aGP32gKqiw= golang.org/x/image v0.0.0-20220617043117-41969df76e82/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY= golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220708220712-1185a9018129 h1:vucSRfWwTsoXro7P+3Cjlr6flUMtzCwzlvkxEQtHHB0= -golang.org/x/net v0.0.0-20220708220712-1185a9018129/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b h1:ZmngSVLe/wycRns9MKikG9OWIEjGcGAkacif7oYQaUY= +golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 h1:WIoqL4EROvwiPdUtaip4VcDdpZ4kha7wBWZrbVKCIZg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= diff --git a/backend/app/cmd/server.go b/backend/app/cmd/server.go index c4b718a2a8..51d2aae645 100644 --- a/backend/app/cmd/server.go +++ b/backend/app/cmd/server.go @@ -208,13 +208,14 @@ type TelegramGroup struct { // SMTPGroup defines options for SMTP server connection, used in auth and notify modules type SMTPGroup struct { - Host string `long:"host" env:"HOST" description:"SMTP host"` - Port int `long:"port" env:"PORT" description:"SMTP port"` - Username string `long:"username" env:"USERNAME" description:"SMTP user name"` - Password string `long:"password" env:"PASSWORD" description:"SMTP password"` - TLS bool `long:"tls" env:"TLS" description:"enable TLS"` - StartTLS bool `long:"starttls" env:"STARTTLS" description:"enable StartTLS"` - TimeOut time.Duration `long:"timeout" env:"TIMEOUT" default:"10s" description:"SMTP TCP connection timeout"` + Host string `long:"host" env:"HOST" description:"SMTP host"` + Port int `long:"port" env:"PORT" description:"SMTP port"` + Username string `long:"username" env:"USERNAME" description:"SMTP user name"` + Password string `long:"password" env:"PASSWORD" description:"SMTP password"` + TLS bool `long:"tls" env:"TLS" description:"enable TLS"` + LoginAuth bool `long:"login_auth" env:"LOGIN_AUTH" description:"enable LOGIN auth instead of PLAIN"` + StartTLS bool `long:"starttls" env:"STARTTLS" description:"enable StartTLS"` + TimeOut time.Duration `long:"timeout" env:"TIMEOUT" default:"10s" description:"SMTP TCP connection timeout"` } // NotifyGroup defines options for notification @@ -880,7 +881,10 @@ func (s *ServerCommand) addAuthProviders(authenticator *auth.Service) error { SMTPUserName: s.SMTP.Username, SMTPPassword: s.SMTP.Password, TimeOut: s.SMTP.TimeOut, + StartTLS: s.SMTP.StartTLS, + LoginAuth: s.SMTP.LoginAuth, TLS: s.SMTP.TLS, + Charset: "UTF-8", From: s.Auth.Email.From, Subject: s.Auth.Email.Subject, ContentType: s.Auth.Email.ContentType, @@ -1031,6 +1035,7 @@ func (s *ServerCommand) makeNotifyDestinations(authenticator *auth.Service) ([]n Port: s.SMTP.Port, TLS: s.SMTP.TLS, StartTLS: s.SMTP.StartTLS, + LoginAuth: s.SMTP.LoginAuth, Username: s.SMTP.Username, Password: s.SMTP.Password, TimeOut: s.SMTP.TimeOut, diff --git a/backend/go.mod b/backend/go.mod index fe82224424..a7d8d95884 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -5,19 +5,19 @@ go 1.17 require ( github.com/Depado/bfchroma/v2 v2.0.0 github.com/PuerkitoBio/goquery v1.8.0 - github.com/alecthomas/chroma/v2 v2.2.0 - github.com/didip/tollbooth/v7 v7.0.0 + github.com/alecthomas/chroma/v2 v2.3.0 + github.com/didip/tollbooth/v7 v7.0.1 github.com/didip/tollbooth_chi v0.0.0-20220719025231-d662a7f6928f github.com/go-chi/chi/v5 v5.0.7 github.com/go-chi/cors v1.2.1 github.com/go-chi/render v1.0.2 - github.com/go-pkgz/auth v1.19.1 + github.com/go-pkgz/auth v1.20.0 github.com/go-pkgz/jrpc v0.3.0 github.com/go-pkgz/lcw v1.0.1 github.com/go-pkgz/lgr v0.10.4 - github.com/go-pkgz/notify v0.1.1 + github.com/go-pkgz/notify v0.2.0 github.com/go-pkgz/repeater v1.1.3 - github.com/go-pkgz/rest v1.15.6 + github.com/go-pkgz/rest v1.16.0 github.com/go-pkgz/syncs v1.2.0 github.com/golang-jwt/jwt v3.2.2+incompatible github.com/google/uuid v1.3.0 @@ -25,16 +25,16 @@ require ( github.com/hashicorp/go-multierror v1.1.1 github.com/jessevdk/go-flags v1.5.0 github.com/kyokomi/emoji/v2 v2.2.10 - github.com/microcosm-cc/bluemonday v1.0.19 + github.com/microcosm-cc/bluemonday v1.0.20 github.com/rs/xid v1.4.0 github.com/russross/blackfriday/v2 v2.1.0 github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e github.com/stretchr/testify v1.8.0 go.etcd.io/bbolt v1.3.6 - go.uber.org/goleak v1.1.12 + go.uber.org/goleak v1.2.0 golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d golang.org/x/image v0.0.0-20220617043117-41969df76e82 - golang.org/x/net v0.0.0-20220708220712-1185a9018129 + golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b ) require ( @@ -47,11 +47,10 @@ require ( github.com/dghubble/oauth1 v0.7.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/dlclark/regexp2 v1.4.0 // indirect - github.com/go-oauth2/oauth2/v4 v4.4.3 // indirect - github.com/go-pkgz/email v0.3.0 // indirect + github.com/go-oauth2/oauth2/v4 v4.5.1 // indirect + github.com/go-pkgz/email v0.4.0 // indirect github.com/go-pkgz/expirable-cache v0.1.0 // indirect github.com/go-redis/redis/v8 v8.11.5 // indirect - github.com/go-stack/stack v1.8.1 // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/gorilla/css v1.0.0 // indirect @@ -59,18 +58,19 @@ require ( github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/klauspost/compress v1.15.2 // indirect + github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect github.com/nullrocks/identicon v0.0.0-20180626043057-7875f45b0022 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/slack-go/slack v0.10.3 // indirect + github.com/slack-go/slack v0.11.3 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect github.com/xdg-go/scram v1.1.1 // indirect github.com/xdg-go/stringprep v1.0.3 // indirect github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect - go.mongodb.org/mongo-driver v1.9.1 // indirect + go.mongodb.org/mongo-driver v1.10.2 // indirect golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect - golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect + golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect golang.org/x/text v0.3.7 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.28.0 // indirect diff --git a/backend/go.sum b/backend/go.sum index 59b7b77b39..9e4bda2dcc 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -61,16 +61,18 @@ github.com/PuerkitoBio/goquery v1.8.0 h1:PJTF7AmFCFKk1N6V6jmKfrNH9tV5pNE6lZMkG0g github.com/PuerkitoBio/goquery v1.8.0/go.mod h1:ypIiRMtY7COPGk+I/YbZLbxsxn9g5ejnI2HSMtkjZvI= github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= -github.com/alecthomas/chroma/v2 v2.2.0 h1:Aten8jfQwUqEdadVFFjNyjx7HTexhKP0XuqBG67mRDY= github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs= -github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae h1:zzGwJfFlFGD94CyyYwCJeSuD32Gj9GTaSi5y9hoVzdY= +github.com/alecthomas/chroma/v2 v2.3.0 h1:83xfxrnjv8eK+Cf8qZDzNo3PPF9IbTWHs7z28GY6D0U= +github.com/alecthomas/chroma/v2 v2.3.0/go.mod h1:mZxeWZlxP2Dy+/8cBob2PYd8O2DwNAzave5AY7A2eQw= github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8= +github.com/alecthomas/repr v0.1.0 h1:ENn2e1+J3k09gyj2shc0dHr/yjaWSHRlrJ4DPMevDqE= +github.com/alecthomas/repr v0.1.0/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8= github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a h1:HbKu58rmZpUGpz5+4FfNmIU+FmZg2P3Xaj2v2bfNWmk= github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= github.com/alicebob/miniredis/v2 v2.22.0 h1:lIHHiSkEyS1MkKHCHzN+0mWrA4YdbGdimE5iZ2sHSzo= github.com/alicebob/miniredis/v2 v2.22.0/go.mod h1:XNqvJdQJv5mSuVMc0ynneafpnL/zv52acZ6kqeS0t88= -github.com/andybalholm/brotli v1.0.0 h1:7UCwP93aiSfvWpapti8g88vVVGp2qqtGyePsSuDafo4= -github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= +github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= +github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c= 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= @@ -101,8 +103,9 @@ github.com/dghubble/oauth1 v0.7.1 h1:JjbOVSVVkms9A4h/sTQy5Jb2nFuAAVb2qVYgenJPyrE github.com/dghubble/oauth1 v0.7.1/go.mod h1:0eEzON0UY/OLACQrmnjgJjmvCGXzjBCsZqL1kWDXtF0= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= -github.com/didip/tollbooth/v7 v7.0.0 h1:XmyyNwZpz9j61PwR4A894MmmYO5zBF9xjgVi2n1fiQI= github.com/didip/tollbooth/v7 v7.0.0/go.mod h1:VZhDSGl5bDSPj4wPsih3PFa4Uh9Ghv8hgacaTm5PRT4= +github.com/didip/tollbooth/v7 v7.0.1 h1:TkT4sBKoQoHQFPf7blQ54iHrZiTDnr8TceU+MulVAog= +github.com/didip/tollbooth/v7 v7.0.1/go.mod h1:VZhDSGl5bDSPj4wPsih3PFa4Uh9Ghv8hgacaTm5PRT4= github.com/didip/tollbooth_chi v0.0.0-20220719025231-d662a7f6928f h1:jtKwihcLmUC9BAhoJ9adCUqdSSZcOdH2KL7mPTUm2aw= github.com/didip/tollbooth_chi v0.0.0-20220719025231-d662a7f6928f/go.mod h1:q9C80dnsuVRP2dAskjnXRNWdUJqtGgwG9wNrzt0019s= github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E= @@ -135,12 +138,13 @@ github.com/go-chi/render v1.0.2/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIo github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-oauth2/oauth2/v4 v4.4.3 h1:IiU3iAK5NEeZ4mUf5HV9tN7iNlx4AGUkIJ5M1C4ARxY= -github.com/go-oauth2/oauth2/v4 v4.4.3/go.mod h1:NR9Hugz5/Qe2OGxoPBhsTRNjnm/amC+z9+XTwt63rhs= -github.com/go-pkgz/auth v1.19.1 h1:yoxQvx6cBYJPHvMryJw+vj+/1QpjPSKERBfPL/mPGT0= -github.com/go-pkgz/auth v1.19.1/go.mod h1:Uex9UlbhlHamrkO14f69BuZX5n5x1CSzIxZb/En+VPw= -github.com/go-pkgz/email v0.3.0 h1:89FbVF6trHkdn2VVoXlBfZHkdYQ1vLmQ54OhdosaFtc= -github.com/go-pkgz/email v0.3.0/go.mod h1:TpnmSLkQW3FyICit2hn7WIhCUDrhCX6btzz5wS3wHRI= +github.com/go-oauth2/oauth2/v4 v4.5.1 h1:3vxp+cjLqDe1TbogbwtMyeHRHr1tD+ksrK7xNppYRDs= +github.com/go-oauth2/oauth2/v4 v4.5.1/go.mod h1:wk/2uLImWIa9VVQDgxz99H2GDbhmfi/9/Xr+GvkSUSQ= +github.com/go-pkgz/auth v1.20.0 h1:9SHkolgv9+zOI9U+8IFXra0pl/H90oE4+ciJWtXoDl4= +github.com/go-pkgz/auth v1.20.0/go.mod h1:jz0djN+4XoCyieuOzc+rB9l0RdqeuiXoQfE02yonLAI= +github.com/go-pkgz/email v0.3.1-0.20221002173339-19d25a20d99c/go.mod h1:TpnmSLkQW3FyICit2hn7WIhCUDrhCX6btzz5wS3wHRI= +github.com/go-pkgz/email v0.4.0 h1:NiYCwKPR6sW8nJsOR3GyB9Yw1AQZdnY78Xnhd9SLHEs= +github.com/go-pkgz/email v0.4.0/go.mod h1:TpnmSLkQW3FyICit2hn7WIhCUDrhCX6btzz5wS3wHRI= github.com/go-pkgz/expirable-cache v0.1.0 h1:3bw0m8vlTK8qlwz5KXuygNBTkiKRTPrAGXU0Ej2AC1g= github.com/go-pkgz/expirable-cache v0.1.0/go.mod h1:GTrEl0X+q0mPNqN6dtcQXksACnzCBQ5k/k1SwXJsZKs= github.com/go-pkgz/jrpc v0.3.0 h1:Fls38KqPsHzvp0FWfivr6cGnncC+iFBodHBqvUPY+0U= @@ -149,21 +153,18 @@ github.com/go-pkgz/lcw v1.0.1 h1:svYC6LIyzRaHF3TwJ8GCS+2RkJreBfaFjoeS+UYwJBc= github.com/go-pkgz/lcw v1.0.1/go.mod h1:CPJJzunpmGToOtD0Ga82TV152eL69sYEIIPcy9fbxlU= github.com/go-pkgz/lgr v0.10.4 h1:l7qyFjqEZgwRgaQQSEp6tve4A3OU80VrfzpvtEX8ngw= github.com/go-pkgz/lgr v0.10.4/go.mod h1:CD0s1z6EFpIUplV067gitF77tn25JItzwHNKAPqeCF0= -github.com/go-pkgz/notify v0.1.1 h1:0EaPnBD/IX8EBVAmKnEHNesyH3rD1v6w0MBLRCwrTUI= -github.com/go-pkgz/notify v0.1.1/go.mod h1:XTzsXgwXXsXbl8iz6qTsCq6gLkaOkimL8mJfLrk3bCk= +github.com/go-pkgz/notify v0.2.0 h1:mxHjcLc3goT+k1qnBPJ06PpNuVUDcu21Xy+6hEo4IaU= +github.com/go-pkgz/notify v0.2.0/go.mod h1:uB4bcohkZB+P8zT279KQv5aXqQEkeMXI3Ey0Y3r0SQk= github.com/go-pkgz/repeater v1.1.3 h1:q6+JQF14ESSy28Dd7F+wRelY4F+41HJ0LEy/szNnMiE= github.com/go-pkgz/repeater v1.1.3/go.mod h1:hVTavuO5x3Gxnu8zW7d6sQBfAneKV8X2FjU48kGfpKw= -github.com/go-pkgz/rest v1.14.0/go.mod h1:KUWAqbDteYGS/CiXftomQsKjtEOifXsJ36Ka0skYbmk= -github.com/go-pkgz/rest v1.15.6 h1:8RgOuY/c00CD0el8KdmscOCgDH+ML0ZsK2qa1Rcxal4= github.com/go-pkgz/rest v1.15.6/go.mod h1:KUWAqbDteYGS/CiXftomQsKjtEOifXsJ36Ka0skYbmk= +github.com/go-pkgz/rest v1.16.0 h1:3An51XJXUq1XtICHvfAEp048ZCbUHBEga3g0WEu3zK0= +github.com/go-pkgz/rest v1.16.0/go.mod h1:HHlLOt02NJc2sgffXBF6hYVMcRo4Gz3vjg43zTzN7VM= github.com/go-pkgz/syncs v1.2.0 h1:aiizQFILlMZ4KtRNaYLcDffRbUQZH9fclsgr5KybWyY= github.com/go-pkgz/syncs v1.2.0/go.mod h1:fjThZdM2FkC/oSeiqBTOZOtHpbrCh4HuHbipB5qZJJM= github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= github.com/go-session/session v3.1.2+incompatible/go.mod h1:8B3iivBQjrz/JtC68Np2T1yBBLxTan3mn/3OM0CyRt0= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= -github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho= github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= @@ -283,9 +284,8 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.10.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.15.2 h1:3WH+AG7s2+T8o3nrM/8u2rdqUEcQhmga7smjrT41nAw= github.com/klauspost/compress v1.15.2/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= @@ -297,9 +297,9 @@ github.com/kyokomi/emoji/v2 v2.2.10 h1:1z5eMVcxFifsmEoNpdeq4UahbcicgQ4FEHuzrCVwm github.com/kyokomi/emoji/v2 v2.2.10/go.mod h1:JUcn42DTdsXJo1SWanHh4HKDEyPaR5CqkmoirZZP9qE= github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/microcosm-cc/bluemonday v1.0.18/go.mod h1:Z0r70sCuXHig8YpBzCc5eGHAap2K7e/u082ZUpDRRqM= -github.com/microcosm-cc/bluemonday v1.0.19 h1:OI7hoF5FY4pFz2VA//RN8TfM0YJ2dJcl4P4APrCWy6c= -github.com/microcosm-cc/bluemonday v1.0.19/go.mod h1:QNzV2UbLK2/53oIIwTOyLUSABMkjZ4tqiyC1g/DyqxE= +github.com/microcosm-cc/bluemonday v1.0.20 h1:flpzsq4KU3QIYAYGV/szUat7H+GPOXR0B2JU5A1Wp8Y= +github.com/microcosm-cc/bluemonday v1.0.20/go.mod h1:yfBmMi8mxvaZut3Yytv+jTXRY8mxyjJ0/kQBTElld50= +github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/moul/http2curl v1.0.0 h1:dRMWoAtb+ePxMlLkrCbAqh4TlPHXvoGUSQ323/9Zahs= github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= @@ -336,8 +336,8 @@ github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M= -github.com/slack-go/slack v0.10.3 h1:kKYwlKY73AfSrtAk9UHWCXXfitudkDztNI9GYBviLxw= -github.com/slack-go/slack v0.10.3/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= +github.com/slack-go/slack v0.11.3 h1:GN7revxEMax4amCc3El9a+9SGnjmBvSUobs0QnO6ZO8= +github.com/slack-go/slack v0.11.3/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= @@ -373,15 +373,13 @@ github.com/tidwall/tinyqueue v0.0.0-20180302190814-1e39f5511563 h1:Otn9S136ELckZ github.com/tidwall/tinyqueue v0.0.0-20180302190814-1e39f5511563/go.mod h1:mLqSmt7Dv/CNneF2wfcChfN1rvapyQr01LGKnKex0DQ= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasthttp v1.14.0 h1:67bfuW9azCMwW/Jlq/C+VeihNpAuJMWkYPBig1gdi3A= -github.com/valyala/fasthttp v1.14.0/go.mod h1:ol1PCaL0dX20wC0htZ7sYCsvCYmrouYra0zHzaclZhE= -github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= +github.com/valyala/fasthttp v1.34.0 h1:d3AAQJ2DRcxJYHm7OXNXtXt2as1vMDfxeIcFvhmGGm4= +github.com/valyala/fasthttp v1.34.0/go.mod h1:epZA5N+7pY6ZaEKRmstzOuYJx9HI8DI1oaCGZpdH4h0= +github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= -github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= github.com/xdg-go/scram v1.1.1 h1:VOMT+81stJgXW3CpHyqHN3AXDYIMsx56mEFrB37Mb/E= github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= -github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= github.com/xdg-go/stringprep v1.0.3 h1:kdwGpVNwPFtjs98xCGkHjQtGKh86rDcRZN17QEMCOIs= github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= @@ -409,9 +407,8 @@ github.com/yuin/gopher-lua v0.0.0-20210529063254-f4c35e4016d9 h1:k/gmLsJDWwWqbLC github.com/yuin/gopher-lua v0.0.0-20210529063254-f4c35e4016d9/go.mod h1:E1AXubJBdNmFERAOucpDIxNzeGfLzg0mYh+UfMWdChA= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= -go.mongodb.org/mongo-driver v1.8.5/go.mod h1:0sQWfOeY63QTntERDJJ/0SuKK0T1uVSgKCuAROlKEPY= -go.mongodb.org/mongo-driver v1.9.1 h1:m078y9v7sBItkt1aaoe2YlvWEXcD263e1a4E1fBrJ1c= -go.mongodb.org/mongo-driver v1.9.1/go.mod h1:0sQWfOeY63QTntERDJJ/0SuKK0T1uVSgKCuAROlKEPY= +go.mongodb.org/mongo-driver v1.10.2 h1:4Wk3cnqOrQCn0P92L3/mmurMxzdvWWs5J9jinAVKD+k= +go.mongodb.org/mongo-driver v1.10.2/go.mod h1:z4XpeoU6w+9Vht+jAFyLgVrD+jGSQQe0+CBWFHNiHt8= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -420,16 +417,15 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= -go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -509,17 +505,14 @@ golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLd golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220708220712-1185a9018129 h1:vucSRfWwTsoXro7P+3Cjlr6flUMtzCwzlvkxEQtHHB0= -golang.org/x/net v0.0.0-20220708220712-1185a9018129/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b h1:ZmngSVLe/wycRns9MKikG9OWIEjGcGAkacif7oYQaUY= +golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -566,7 +559,6 @@ golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -584,7 +576,6 @@ golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -617,10 +608,8 @@ golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 h1:WIoqL4EROvwiPdUtaip4VcDdpZ4kha7wBWZrbVKCIZg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -646,7 +635,6 @@ golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= diff --git a/backend/vendor/github.com/alecthomas/chroma/v2/README.md b/backend/vendor/github.com/alecthomas/chroma/v2/README.md index 445fb967d6..ffaccb653b 100644 --- a/backend/vendor/github.com/alecthomas/chroma/v2/README.md +++ b/backend/vendor/github.com/alecthomas/chroma/v2/README.md @@ -38,7 +38,7 @@ Prefix | Language :----: | -------- A | ABAP, ABNF, ActionScript, ActionScript 3, Ada, Angular2, ANTLR, ApacheConf, APL, AppleScript, Arduino, Awk B | Ballerina, Base Makefile, Bash, Batchfile, BibTeX, Bicep, BlitzBasic, BNF, Brainfuck -C | C, C#, C++, Caddyfile, Caddyfile Directives, Cap'n Proto, Cassandra CQL, Ceylon, CFEngine3, cfstatement, ChaiScript, Cheetah, Clojure, CMake, COBOL, CoffeeScript, Common Lisp, Coq, Crystal, CSS, Cython +C | C, C#, C++, Caddyfile, Caddyfile Directives, Cap'n Proto, Cassandra CQL, Ceylon, CFEngine3, cfstatement, ChaiScript, Chapel, Cheetah, Clojure, CMake, COBOL, CoffeeScript, Common Lisp, Coq, Crystal, CSS, Cython D | D, Dart, Diff, Django/Jinja, Docker, DTD, Dylan E | EBNF, Elixir, Elm, EmacsLisp, Erlang F | Factor, Fish, Forth, Fortran, FSharp @@ -51,7 +51,7 @@ L | Lighttpd configuration file, LLVM, Lua M | Mako, markdown, Mason, Mathematica, Matlab, MiniZinc, MLIR, Modula-2, MonkeyC, MorrowindScript, Myghty, MySQL N | NASM, Newspeak, Nginx configuration file, Nim, Nix O | Objective-C, OCaml, Octave, OnesEnterprise, OpenEdge ABL, OpenSCAD, Org Mode -P | PacmanConf, Perl, PHP, PHTML, Pig, PkgConfig, PL/pgSQL, plaintext, Pony, PostgreSQL SQL dialect, PostScript, POVRay, PowerShell, Prolog, PromQL, Protocol Buffer, Puppet, Python 2, Python +P | PacmanConf, Perl, PHP, PHTML, Pig, PkgConfig, PL/pgSQL, plaintext, Pony, PostgreSQL SQL dialect, PostScript, POVRay, PowerShell, Prolog, PromQL, Properties, Protocol Buffer, Puppet, Python 2, Python Q | QBasic R | R, Racket, Ragel, Raku, react, ReasonML, reg, reStructuredText, Rexx, Ruby, Rust S | SAS, Sass, Scala, Scheme, Scilab, SCSS, Smalltalk, Smarty, Snobol, Solidity, SPARQL, SQL, SquidConf, Standard ML, Stylus, Svelte, Swift, SYSTEMD, systemverilog diff --git a/backend/vendor/github.com/alecthomas/chroma/v2/colour.go b/backend/vendor/github.com/alecthomas/chroma/v2/colour.go index 15d794ce2a..b7fd6e0e34 100644 --- a/backend/vendor/github.com/alecthomas/chroma/v2/colour.go +++ b/backend/vendor/github.com/alecthomas/chroma/v2/colour.go @@ -92,7 +92,7 @@ func (c Colour) Brighten(factor float64) Colour { return NewColour(uint8(r), uint8(g), uint8(b)) } -// BrightenOrDarken brightens a colour if it is < 0.5 brighteness or darkens if > 0.5 brightness. +// BrightenOrDarken brightens a colour if it is < 0.5 brightness or darkens if > 0.5 brightness. func (c Colour) BrightenOrDarken(factor float64) Colour { if c.Brightness() < 0.5 { return c.Brighten(factor) @@ -100,7 +100,35 @@ func (c Colour) BrightenOrDarken(factor float64) Colour { return c.Brighten(-factor) } -// Brightness of the colour (roughly) in the range 0.0 to 1.0 +// ClampBrightness returns a copy of this colour with its brightness adjusted such that +// it falls within the range [min, max] (or very close to it due to rounding errors). +// The supplied values use the same [0.0, 1.0] range as Brightness. +func (c Colour) ClampBrightness(min, max float64) Colour { + if !c.IsSet() { + return c + } + + min = math.Max(min, 0) + max = math.Min(max, 1) + current := c.Brightness() + target := math.Min(math.Max(current, min), max) + if current == target { + return c + } + + r := float64(c.Red()) + g := float64(c.Green()) + b := float64(c.Blue()) + rgb := r + g + b + if target > current { + // Solve for x: target == ((255-r)*x + r + (255-g)*x + g + (255-b)*x + b) / 255 / 3 + return c.Brighten((target*255*3 - rgb) / (255*3 - rgb)) + } + // Solve for x: target == (r*(x+1) + g*(x+1) + b*(x+1)) / 255 / 3 + return c.Brighten((target*255*3)/rgb - 1) +} + +// Brightness of the colour (roughly) in the range 0.0 to 1.0. func (c Colour) Brightness() float64 { return (float64(c.Red()) + float64(c.Green()) + float64(c.Blue())) / 255.0 / 3.0 } diff --git a/backend/vendor/github.com/alecthomas/chroma/v2/lexers/chapel.go b/backend/vendor/github.com/alecthomas/chroma/v2/lexers/chapel.go new file mode 100644 index 0000000000..5f6f0901c1 --- /dev/null +++ b/backend/vendor/github.com/alecthomas/chroma/v2/lexers/chapel.go @@ -0,0 +1,62 @@ +package lexers + +import ( + . "github.com/alecthomas/chroma/v2" // nolint +) + +// Chapel lexer. +var Chapel = Register(MustNewLexer( + &Config{ + Name: "Chapel", + Aliases: []string{"chapel", "chpl"}, + Filenames: []string{"*.chpl"}, + MimeTypes: []string{}, + }, + func() Rules { + return Rules{ + "root": { + {`\n`, TextWhitespace, nil}, + {`\s+`, TextWhitespace, nil}, + {`\\\n`, Text, nil}, + {`//(.*?)\n`, CommentSingle, nil}, + {`/(\\\n)?[*](.|\n)*?[*](\\\n)?/`, CommentMultiline, nil}, + {Words(``, `\b`, `config`, `const`, `in`, `inout`, `out`, `param`, `ref`, `type`, `var`), KeywordDeclaration, nil}, + {Words(``, `\b`, `false`, `nil`, `none`, `true`), KeywordConstant, nil}, + {Words(``, `\b`, `bool`, `bytes`, `complex`, `imag`, `int`, `locale`, `nothing`, `opaque`, `range`, `real`, `string`, `uint`, `void`), KeywordType, nil}, + {Words(``, `\b`, `atomic`, `single`, `sync`, `borrowed`, `owned`, `shared`, `unmanaged`, `align`, `as`, `begin`, `break`, `by`, `catch`, `cobegin`, `coforall`, `continue`, `defer`, `delete`, `dmapped`, `do`, `domain`, `else`, `enum`, `except`, `export`, `extern`, `for`, `forall`, `foreach`, `forwarding`, `if`, `implements`, `import`, `index`, `init`, `inline`, `label`, `lambda`, `let`, `lifetime`, `local`, `new`, `noinit`, `on`, `only`, `otherwise`, `override`, `pragma`, `primitive`, `private`, `prototype`, `public`, `reduce`, `require`, `return`, `scan`, `select`, `serial`, `sparse`, `subdomain`, `then`, `this`, `throw`, `throws`, `try`, `use`, `when`, `where`, `while`, `with`, `yield`, `zip`), Keyword, nil}, + {`(iter)(\s+)`, ByGroups(Keyword, TextWhitespace), Push("procname")}, + {`(proc)(\s+)`, ByGroups(Keyword, TextWhitespace), Push("procname")}, + {`(operator)(\s+)`, ByGroups(Keyword, TextWhitespace), Push("procname")}, + {`(class|interface|module|record|union)(\s+)`, ByGroups(Keyword, TextWhitespace), Push("classname")}, + {`\d+i`, LiteralNumber, nil}, + {`\d+\.\d*([Ee][-+]\d+)?i`, LiteralNumber, nil}, + {`\.\d+([Ee][-+]\d+)?i`, LiteralNumber, nil}, + {`\d+[Ee][-+]\d+i`, LiteralNumber, nil}, + {`(\d*\.\d+)([eE][+-]?[0-9]+)?i?`, LiteralNumberFloat, nil}, + {`\d+[eE][+-]?[0-9]+i?`, LiteralNumberFloat, nil}, + {`0[bB][01]+`, LiteralNumberBin, nil}, + {`0[xX][0-9a-fA-F]+`, LiteralNumberHex, nil}, + {`0[oO][0-7]+`, LiteralNumberOct, nil}, + {`[0-9]+`, LiteralNumberInteger, nil}, + {`"(\\\\|\\"|[^"])*"`, LiteralString, nil}, + {`'(\\\\|\\'|[^'])*'`, LiteralString, nil}, + {`(=|\+=|-=|\*=|/=|\*\*=|%=|&=|\|=|\^=|&&=|\|\|=|<<=|>>=|<=>|<~>|\.\.|by|#|\.\.\.|&&|\|\||!|&|\||\^|~|<<|>>|==|!=|<=|>=|<|>|[+\-*/%]|\*\*)`, Operator, nil}, + {`[:;,.?()\[\]{}]`, Punctuation, nil}, + {`[a-zA-Z_][\w$]*`, NameOther, nil}, + }, + "classname": { + {`[a-zA-Z_][\w$]*`, NameClass, Pop(1)}, + }, + "procname": { + {`([a-zA-Z_][.\w$]*|\~[a-zA-Z_][.\w$]*|[+*/!~%<>=&^|\-:]{1,2})`, NameFunction, Pop(1)}, + {`\(`, Punctuation, Push("receivertype")}, + {`\)+\.`, Punctuation, nil}, + }, + "receivertype": { + {Words(``, `\b`, `atomic`, `single`, `sync`, `borrowed`, `owned`, `shared`, `unmanaged`), Keyword, nil}, + {Words(``, `\b`, `bool`, `bytes`, `complex`, `imag`, `int`, `locale`, `nothing`, `opaque`, `range`, `real`, `string`, `uint`, `void`), KeywordType, nil}, + {`[^()]*`, NameOther, Pop(1)}, + }, + } + }, +)) diff --git a/backend/vendor/github.com/alecthomas/chroma/v2/lexers/dns.go b/backend/vendor/github.com/alecthomas/chroma/v2/lexers/dns.go new file mode 100644 index 0000000000..7e699622ac --- /dev/null +++ b/backend/vendor/github.com/alecthomas/chroma/v2/lexers/dns.go @@ -0,0 +1,17 @@ +package lexers + +import ( + "regexp" +) + +// TODO(moorereason): can this be factored away? +var zoneAnalyserRe = regexp.MustCompile(`(?m)^@\s+IN\s+SOA\s+`) + +func init() { // nolint: gochecknoinits + Get("dns").SetAnalyser(func(text string) float32 { + if zoneAnalyserRe.FindString(text) != "" { + return 1.0 + } + return 0.0 + }) +} diff --git a/backend/vendor/github.com/alecthomas/chroma/v2/lexers/docker.go b/backend/vendor/github.com/alecthomas/chroma/v2/lexers/docker.go index e14654a026..b48816ae30 100644 --- a/backend/vendor/github.com/alecthomas/chroma/v2/lexers/docker.go +++ b/backend/vendor/github.com/alecthomas/chroma/v2/lexers/docker.go @@ -9,7 +9,7 @@ var Docker = Register(MustNewLexer( &Config{ Name: "Docker", Aliases: []string{"docker", "dockerfile"}, - Filenames: []string{"Dockerfile", "*.docker"}, + Filenames: []string{"Dockerfile", "Dockerfile.*", "*.docker"}, MimeTypes: []string{"text/x-dockerfile-config"}, CaseInsensitive: true, }, diff --git a/backend/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cfengine3.xml b/backend/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cfengine3.xml index d330549192..8c4c1a8f1e 100644 --- a/backend/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cfengine3.xml +++ b/backend/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cfengine3.xml @@ -70,18 +70,6 @@ - - - - - - - - - - - - diff --git a/backend/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/dns.xml b/backend/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/dns.xml new file mode 100644 index 0000000000..2a854e57f9 --- /dev/null +++ b/backend/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/dns.xml @@ -0,0 +1,42 @@ + + + + dns + zone + bind + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/backend/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/fortran.xml b/backend/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/fortran.xml index 012808b546..0448d76bd8 100644 --- a/backend/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/fortran.xml +++ b/backend/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/fortran.xml @@ -2,20 +2,29 @@ Fortran fortran + f90 *.f03 *.f90 + *.f95 *.F03 *.F90 + *.F95 text/x-fortran true - + - - + + + + + + + + @@ -26,7 +35,7 @@ - + @@ -45,13 +54,16 @@ - + - + + + + - + @@ -75,8 +87,8 @@ - + - \ No newline at end of file + diff --git a/backend/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gas.xml b/backend/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gas.xml index 1ef31dec95..1feda85f77 100644 --- a/backend/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gas.xml +++ b/backend/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gas.xml @@ -48,10 +48,24 @@ + + + + + + + + + + + + + + @@ -99,6 +113,17 @@ + + + + + + + + + + + @@ -113,9 +138,12 @@ - - + + + + + - \ No newline at end of file + diff --git a/backend/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/javascript.xml b/backend/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/javascript.xml index f8e7b1b7d8..efe80ed375 100644 --- a/backend/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/javascript.xml +++ b/backend/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/javascript.xml @@ -6,6 +6,7 @@ *.js *.jsm *.mjs + *.cjs application/javascript application/x-javascript text/x-javascript diff --git a/backend/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mcfunction.xml b/backend/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mcfunction.xml index b1ff183f18..331052036d 100644 --- a/backend/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mcfunction.xml +++ b/backend/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mcfunction.xml @@ -92,7 +92,7 @@ - + @@ -179,4 +179,4 @@ - \ No newline at end of file + diff --git a/backend/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/properties.xml b/backend/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/properties.xml new file mode 100644 index 0000000000..d5ae0a283e --- /dev/null +++ b/backend/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/properties.xml @@ -0,0 +1,45 @@ + + + properties + java-properties + *.properties + text/x-java-properties + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/backend/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/transact-sql.xml b/backend/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/transact-sql.xml index 1c9f38eab3..b0490aa7c7 100644 --- a/backend/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/transact-sql.xml +++ b/backend/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/transact-sql.xml @@ -36,7 +36,7 @@ - + @@ -134,4 +134,4 @@ - \ No newline at end of file + diff --git a/backend/vendor/github.com/alecthomas/chroma/v2/lexers/fortran_fixed.go b/backend/vendor/github.com/alecthomas/chroma/v2/lexers/fortran_fixed.go index d93ac1eb6d..aa93ce07a3 100644 --- a/backend/vendor/github.com/alecthomas/chroma/v2/lexers/fortran_fixed.go +++ b/backend/vendor/github.com/alecthomas/chroma/v2/lexers/fortran_fixed.go @@ -19,18 +19,18 @@ var FortranFixed = Register(MustNewLexer( "root": { {`[C*].*\n`, Comment, nil}, {`#.*\n`, CommentPreproc, nil}, - {`[\t ]*!.*\n`, Comment, nil}, + {` {0,4}!.*\n`, Comment, nil}, {`(.{5})`, NameLabel, Push("cont-char")}, {`.*\n`, Using("Fortran"), nil}, }, "cont-char": { - {` `, Text, Push("code")}, - {`0`, Comment, Push("code")}, + {` `, TextWhitespace, Push("code")}, {`.`, GenericStrong, Push("code")}, }, "code": { - {`(.{66})(.*)(\n)`, ByGroups(Using("Fortran"), Comment, Text), Push("root")}, - {`.*\n`, Using("Fortran"), Push("root")}, + {`(.{66})(.*)(\n)`, ByGroups(Using("Fortran"), Comment, TextWhitespace), Push("root")}, + {`(.*)(!.*)(\n)`, ByGroups(Using("Fortran"), Comment, TextWhitespace), Push("root")}, + {`(.*)(\n)`, ByGroups(Using("Fortran"), TextWhitespace), Push("root")}, Default(Push("root")), }, } diff --git a/backend/vendor/github.com/alecthomas/chroma/v2/lexers/make.go b/backend/vendor/github.com/alecthomas/chroma/v2/lexers/make.go index 48bdc13526..be06579b90 100644 --- a/backend/vendor/github.com/alecthomas/chroma/v2/lexers/make.go +++ b/backend/vendor/github.com/alecthomas/chroma/v2/lexers/make.go @@ -9,7 +9,7 @@ var Makefile = Register(MustNewLexer( &Config{ Name: "Base Makefile", Aliases: []string{"make", "makefile", "mf", "bsdmake"}, - Filenames: []string{"*.mak", "*.mk", "Makefile", "makefile", "Makefile.*", "GNUmakefile"}, + Filenames: []string{"*.mak", "*.mk", "Makefile", "makefile", "Makefile.*", "GNUmakefile", "BSDmakefile"}, MimeTypes: []string{"text/x-makefile"}, EnsureNL: true, }, diff --git a/backend/vendor/github.com/alecthomas/chroma/v2/style.go b/backend/vendor/github.com/alecthomas/chroma/v2/style.go index 1319fc4248..8edea13254 100644 --- a/backend/vendor/github.com/alecthomas/chroma/v2/style.go +++ b/backend/vendor/github.com/alecthomas/chroma/v2/style.go @@ -157,9 +157,12 @@ func (s *StyleBuilder) AddAll(entries StyleEntries) *StyleBuilder { } func (s *StyleBuilder) Get(ttype TokenType) StyleEntry { - // This is less than ideal, but it's the price for having to check errors on each Add(). + // This is less than ideal, but it's the price for not having to check errors on each Add(). entry, _ := ParseStyleEntry(s.entries[ttype]) - return entry.Inherit(s.parent.Get(ttype)) + if s.parent != nil { + entry = entry.Inherit(s.parent.Get(ttype)) + } + return entry } // Add an entry to the Style map. @@ -175,6 +178,25 @@ func (s *StyleBuilder) AddEntry(ttype TokenType, entry StyleEntry) *StyleBuilder return s } +// Transform passes each style entry currently defined in the builder to the supplied +// function and saves the returned value. This can be used to adjust a style's colours; +// see Colour's ClampBrightness function, for example. +func (s *StyleBuilder) Transform(transform func(StyleEntry) StyleEntry) *StyleBuilder { + types := make(map[TokenType]struct{}) + for tt := range s.entries { + types[tt] = struct{}{} + } + if s.parent != nil { + for _, tt := range s.parent.Types() { + types[tt] = struct{}{} + } + } + for tt := range types { + s.AddEntry(tt, transform(s.Get(tt))) + } + return s +} + func (s *StyleBuilder) Build() (*Style, error) { style := &Style{ Name: s.name, diff --git a/backend/vendor/github.com/alecthomas/chroma/v2/styles/github-dark.go b/backend/vendor/github.com/alecthomas/chroma/v2/styles/github-dark.go new file mode 100644 index 0000000000..48c0d61de6 --- /dev/null +++ b/backend/vendor/github.com/alecthomas/chroma/v2/styles/github-dark.go @@ -0,0 +1,86 @@ +package styles + +import ( + "fmt" + + "github.com/alecthomas/chroma/v2" +) + +var ( + // colors used from https://github.com/primer/primitives + ghRed2 = "#ffa198" + ghRed3 = "#ff7b72" + ghRed9 = "#490202" + ghOrange2 = "#ffa657" + ghOrange3 = "#f0883e" + ghGreen1 = "#7ee787" + ghGreen2 = "#56d364" + ghGreen7 = "#0f5323" + ghBlue1 = "#a5d6ff" + ghBlue2 = "#79c0ff" + ghPurple2 = "#d2a8ff" + ghGray3 = "#8b949e" + ghGray4 = "#6e7681" + ghFgSubtle = "#6e7681" + ghFgDefault = "#c9d1d9" + ghBgDefault = "#0d1117" + ghDangerFg = "#f85149" +) + +// GitHub Dark style. +var GitHubDark = Register(chroma.MustNewStyle("github-dark", chroma.StyleEntries{ + // Default Token Style + chroma.Background: fmt.Sprintf("bg:%s %s", ghBgDefault, ghFgDefault), + + chroma.LineNumbers: ghGray4, + // has transparency in VS Code theme as `colors.codemirror.activelineBg` + chroma.LineHighlight: ghGray4, + + chroma.Error: ghDangerFg, + + chroma.Keyword: ghRed3, + chroma.KeywordConstant: ghBlue2, + chroma.KeywordPseudo: ghBlue2, + + chroma.Name: ghFgDefault, + chroma.NameClass: "bold " + ghOrange3, + chroma.NameConstant: "bold " + ghBlue2, + chroma.NameDecorator: "bold " + ghPurple2, + chroma.NameEntity: ghOrange2, + chroma.NameException: "bold " + ghOrange3, + chroma.NameFunction: "bold " + ghPurple2, + chroma.NameLabel: "bold " + ghBlue2, + chroma.NameNamespace: ghRed3, + chroma.NameProperty: ghBlue2, + chroma.NameTag: ghGreen1, + chroma.NameVariable: ghBlue2, + + chroma.Literal: ghBlue1, + chroma.LiteralDate: ghBlue2, + chroma.LiteralStringAffix: ghBlue2, + chroma.LiteralStringDelimiter: ghBlue2, + chroma.LiteralStringEscape: ghBlue2, + chroma.LiteralStringHeredoc: ghBlue2, + chroma.LiteralStringRegex: ghBlue2, + + chroma.Operator: "bold " + ghRed3, + + chroma.Comment: "italic " + ghGray3, + chroma.CommentPreproc: "bold " + ghGray3, + chroma.CommentSpecial: "bold italic " + ghGray3, + + chroma.Generic: ghFgDefault, + chroma.GenericDeleted: fmt.Sprintf("bg:%s %s", ghRed9, ghRed2), + chroma.GenericEmph: "italic", + chroma.GenericError: ghRed2, + chroma.GenericHeading: "bold " + ghBlue2, + chroma.GenericInserted: fmt.Sprintf("bg:%s %s", ghGreen7, ghGreen2), + chroma.GenericOutput: ghGray3, + chroma.GenericPrompt: ghGray3, + chroma.GenericStrong: "bold", + chroma.GenericSubheading: ghBlue2, + chroma.GenericTraceback: ghRed3, + chroma.GenericUnderline: "underline", + + chroma.TextWhitespace: ghFgSubtle, +})) diff --git a/backend/vendor/github.com/alecthomas/chroma/v2/styles/gruvbox-light.go b/backend/vendor/github.com/alecthomas/chroma/v2/styles/gruvbox-light.go new file mode 100644 index 0000000000..6f6de7cba5 --- /dev/null +++ b/backend/vendor/github.com/alecthomas/chroma/v2/styles/gruvbox-light.go @@ -0,0 +1,40 @@ +package styles + +import ( + "github.com/alecthomas/chroma/v2" +) + +// Gruvbox light style. +var GruvboxLight = Register(chroma.MustNewStyle("gruvbox-light", chroma.StyleEntries{ + chroma.CommentPreproc: "noinherit #427B58", + chroma.Comment: "#928374 italic", + chroma.GenericDeleted: "noinherit #282828 bg:#9D0006", + chroma.GenericEmph: "#076678 underline", + chroma.GenericError: "bg:#9D0006 bold", + chroma.GenericHeading: "#79740E bold", + chroma.GenericInserted: "noinherit #282828 bg:#79740E", + chroma.GenericOutput: "noinherit #504945", + chroma.GenericPrompt: "#3C3836", + chroma.GenericStrong: "#3C3836", + chroma.GenericSubheading: "#79740E bold", + chroma.GenericTraceback: "bg:#3C3836 bold", + chroma.Generic: "#3C3836", + chroma.KeywordType: "noinherit #B57614", + chroma.Keyword: "noinherit #AF3A03", + chroma.NameAttribute: "#79740E bold", + chroma.NameBuiltin: "#B57614", + chroma.NameConstant: "noinherit #d3869b", + chroma.NameEntity: "noinherit #B57614", + chroma.NameException: "noinherit #fb4934", + chroma.NameFunction: "#B57614", + chroma.NameLabel: "noinherit #9D0006", + chroma.NameTag: "noinherit #9D0006", + chroma.NameVariable: "noinherit #3C3836", + chroma.Name: "#3C3836", + chroma.LiteralNumberFloat: "noinherit #8F3F71", + chroma.LiteralNumber: "noinherit #8F3F71", + chroma.Operator: "#AF3A03", + chroma.LiteralStringSymbol: "#076678", + chroma.LiteralString: "noinherit #79740E", + chroma.Background: "noinherit #3C3836 bg:#FBF1C7 bg:#FBF1C7", +})) diff --git a/backend/vendor/github.com/didip/tollbooth/v7/tollbooth.go b/backend/vendor/github.com/didip/tollbooth/v7/tollbooth.go index 4545c0a585..0dcf82e02b 100644 --- a/backend/vendor/github.com/didip/tollbooth/v7/tollbooth.go +++ b/backend/vendor/github.com/didip/tollbooth/v7/tollbooth.go @@ -112,6 +112,10 @@ func ShouldSkipLimiter(lmt *limiter.Limiter, r *http.Request) bool { requestHeadersDefinedInLimiter = false for headerKey, headerValues := range lmtHeaders { + if len(headerValues) == 0 { + requestHeadersDefinedInLimiter = true + continue + } for _, headerValue := range headerValues { if r.Header.Get(headerKey) == headerValue { requestHeadersDefinedInLimiter = true diff --git a/backend/vendor/github.com/go-oauth2/oauth2/v4/README.md b/backend/vendor/github.com/go-oauth2/oauth2/v4/README.md index affa54b545..5161a4c54f 100644 --- a/backend/vendor/github.com/go-oauth2/oauth2/v4/README.md +++ b/backend/vendor/github.com/go-oauth2/oauth2/v4/README.md @@ -175,6 +175,7 @@ if !ok || !token.Valid { - [XORM (MySQL, client and token store)](https://github.com/rainlay/go-oauth2-xorm) - [GORM](https://github.com/techknowlogick/go-oauth2-gorm) - [Firestore](https://github.com/tslamic/go-oauth2-firestore) +- [Hazelcast](https://github.com/clowre/go-oauth2-hazelcast) (token only) ## Handy Utilities diff --git a/backend/vendor/github.com/go-oauth2/oauth2/v4/manage.go b/backend/vendor/github.com/go-oauth2/oauth2/v4/manage.go index 5c0bdf8712..23f2b3d318 100644 --- a/backend/vendor/github.com/go-oauth2/oauth2/v4/manage.go +++ b/backend/vendor/github.com/go-oauth2/oauth2/v4/manage.go @@ -31,7 +31,7 @@ type Manager interface { GenerateAuthToken(ctx context.Context, rt ResponseType, tgr *TokenGenerateRequest) (authToken TokenInfo, err error) // generate the access token - GenerateAccessToken(ctx context.Context, rt GrantType, tgr *TokenGenerateRequest) (accessToken TokenInfo, err error) + GenerateAccessToken(ctx context.Context, gt GrantType, tgr *TokenGenerateRequest) (accessToken TokenInfo, err error) // refreshing an access token RefreshAccessToken(ctx context.Context, tgr *TokenGenerateRequest) (accessToken TokenInfo, err error) diff --git a/backend/vendor/github.com/go-oauth2/oauth2/v4/server/handler.go b/backend/vendor/github.com/go-oauth2/oauth2/v4/server/handler.go index 0481135b08..9a0be8ccab 100644 --- a/backend/vendor/github.com/go-oauth2/oauth2/v4/server/handler.go +++ b/backend/vendor/github.com/go-oauth2/oauth2/v4/server/handler.go @@ -23,7 +23,7 @@ type ( UserAuthorizationHandler func(w http.ResponseWriter, r *http.Request) (userID string, err error) // PasswordAuthorizationHandler get user id from username and password - PasswordAuthorizationHandler func(ctx context.Context, username, password string) (userID string, err error) + PasswordAuthorizationHandler func(ctx context.Context, clientID, username, password string) (userID string, err error) // RefreshingScopeHandler check the scope of the refreshing token RefreshingScopeHandler func(tgr *oauth2.TokenGenerateRequest, oldScope string) (allowed bool, err error) diff --git a/backend/vendor/github.com/go-oauth2/oauth2/v4/server/server.go b/backend/vendor/github.com/go-oauth2/oauth2/v4/server/server.go index 8fd02e82f4..df19d1f1ac 100644 --- a/backend/vendor/github.com/go-oauth2/oauth2/v4/server/server.go +++ b/backend/vendor/github.com/go-oauth2/oauth2/v4/server/server.go @@ -32,7 +32,7 @@ func NewServer(cfg *Config, manager oauth2.Manager) *Server { return "", errors.ErrAccessDenied } - srv.PasswordAuthorizationHandler = func(ctx context.Context, username, password string) (string, error) { + srv.PasswordAuthorizationHandler = func(ctx context.Context, clientID, username, password string) (string, error) { return "", errors.ErrAccessDenied } return srv @@ -357,7 +357,7 @@ func (s *Server) ValidationTokenRequest(r *http.Request) (oauth2.GrantType, *oau return "", nil, errors.ErrInvalidRequest } - userID, err := s.PasswordAuthorizationHandler(r.Context(), username, password) + userID, err := s.PasswordAuthorizationHandler(r.Context(), clientID, username, password) if err != nil { return "", nil, err } else if userID == "" { diff --git a/backend/vendor/github.com/go-pkgz/auth/README.md b/backend/vendor/github.com/go-pkgz/auth/README.md index cbd5146c81..26f12ae822 100644 --- a/backend/vendor/github.com/go-pkgz/auth/README.md +++ b/backend/vendor/github.com/go-pkgz/auth/README.md @@ -210,6 +210,26 @@ The API for this provider: The provider acts like any other, i.e. will be registered as `/auth/email/login`. +### Email + +For email notify provider, please use `github.com/go-pkgz/auth/provider/sender` package: +```go + sndr := sender.NewEmailClient(sender.EmailParams{ + Host: "email.hostname", + Port: 567, + SMTPUserName: "username", + SMTPPassword: "pass", + StartTLS: true, + From: "notify@email.hostname", + Subject: "subject", + ContentType: "text/html", + Charset: "UTF-8", + }, log.Default()) + authenticator.AddVerifProvider("email", "template goes here", sndr) +``` + +See [that documentation](https://github.com/go-pkgz/email#options) for full options list. + ### Telegram Telegram provider allows your users to log in with Telegram account. First, you will need to create your bot. diff --git a/backend/vendor/github.com/go-pkgz/auth/avatar/store.go b/backend/vendor/github.com/go-pkgz/auth/avatar/store.go index 635366af4b..e26c18183f 100644 --- a/backend/vendor/github.com/go-pkgz/auth/avatar/store.go +++ b/backend/vendor/github.com/go-pkgz/auth/avatar/store.go @@ -1,7 +1,5 @@ package avatar -//go:generate sh -c "mockery -inpkg -name Store -print > /tmp/mock.tmp && mv /tmp/mock.tmp store_mock.go" - import ( "context" "crypto/sha1" //nolint gosec @@ -48,14 +46,13 @@ func NewStore(uri string) (Store, error) { return NewLocalFS(strings.TrimPrefix(uri, "file://")), nil case !strings.Contains(uri, "://"): return NewLocalFS(uri), nil - case strings.HasPrefix(uri, "mongodb://"): - + case strings.HasPrefix(uri, "mongodb://"), strings.HasPrefix(uri, "mongodb+srv://"): db, bucketName, u, err := parseExtMongoURI(uri) if err != nil { return nil, fmt.Errorf("can't parse mongo store uri %s: %w", uri, err) } - ctx, cancel := context.WithTimeout(context.Background(), time.Second) + ctx, cancel := context.WithTimeout(context.Background(), time.Second*30) defer cancel() client, err := mongo.Connect(ctx, options.Client().ApplyURI(u)) diff --git a/backend/vendor/github.com/go-pkgz/auth/provider/sender/email.go b/backend/vendor/github.com/go-pkgz/auth/provider/sender/email.go index bcd658ed2e..2910c82cfe 100644 --- a/backend/vendor/github.com/go-pkgz/auth/provider/sender/email.go +++ b/backend/vendor/github.com/go-pkgz/auth/provider/sender/email.go @@ -2,24 +2,18 @@ package sender import ( - "bytes" - "crypto/tls" - "fmt" - "io" - "mime/quotedprintable" - "net" - "net/smtp" "time" "github.com/go-pkgz/auth/logger" + "github.com/go-pkgz/email" ) // Email implements sender interface for VerifyHandler // Uses common subject line and "from" for all messages type Email struct { - logger.L - SMTPClient EmailParams + logger.L + sender *email.Sender } // EmailParams with all needed to make new Email client with smtp @@ -28,148 +22,64 @@ type EmailParams struct { Port int // SMTP port From string // From email field Subject string // Email subject - ContentType string // Content type, optional. Will trigger MIME and Content-Type headers - - TLS bool // TLS auth - SMTPUserName string // user name - SMTPPassword string // password - TimeOut time.Duration -} - -// SMTPClient interface defines subset of net/smtp used by email client -type SMTPClient interface { - Mail(string) error - Auth(smtp.Auth) error - Rcpt(string) error - Data() (io.WriteCloser, error) - Quit() error - Close() error + ContentType string // Content type + + TLS bool // TLS auth + StartTLS bool // StartTLS auth + Charset string // Character set + LoginAuth bool // LOGIN auth method instead of default PLAIN, needed for Office 365 and outlook.com + SMTPUserName string // username + SMTPPassword string // password + TimeOut time.Duration // TCP connection timeout } -// NewEmailClient creates email client with prepared smtp -func NewEmailClient(p EmailParams, l logger.L) *Email { - return &Email{EmailParams: p, L: l, SMTPClient: nil} -} +// NewEmailClient creates email client +func NewEmailClient(emailParams EmailParams, l logger.L) *Email { + var opts []email.Option -// Send email with given text -// If SMTPClient defined in Email struct it will be used, if not - new smtp.Client on each send. -// Always closes client on completion or failure. -func (em *Email) Send(to, text string) error { - em.Logf("[DEBUG] send %q to %s", text, to) - client := em.SMTPClient - if client == nil { // if client not set make new net/smtp - c, err := em.client() - if err != nil { - return fmt.Errorf("failed to make smtp client: %w", err) - } - client = c + if emailParams.SMTPUserName != "" { + opts = append(opts, email.Auth(emailParams.SMTPUserName, emailParams.SMTPPassword)) } - var quit bool - defer func() { - if quit { // quit set if Quit() call passed because it's closing connection as well. - return - } - if err := client.Close(); err != nil { - em.Logf("[WARN] can't close smtp connection, %v", err) - } - }() - - if em.SMTPUserName != "" && em.SMTPPassword != "" { - auth := smtp.PlainAuth("", em.SMTPUserName, em.SMTPPassword, em.Host) - if err := client.Auth(auth); err != nil { - return fmt.Errorf("failed to auth to smtp %s:%d: %w", em.Host, em.Port, err) - } + if emailParams.ContentType != "" { + opts = append(opts, email.ContentType(emailParams.ContentType)) } - if err := client.Mail(em.From); err != nil { - return fmt.Errorf("bad from address %q: %w", em.From, err) - } - if err := client.Rcpt(to); err != nil { - return fmt.Errorf("bad to address %q: %w", to, err) + if emailParams.Charset != "" { + opts = append(opts, email.Charset(emailParams.Charset)) } - writer, err := client.Data() - if err != nil { - return fmt.Errorf("can't make email writer: %w", err) + if emailParams.LoginAuth { + opts = append(opts, email.LoginAuth()) } - msg, err := em.buildMessage(text, to) - if err != nil { - return fmt.Errorf("can't make email message: %w", err) - } - buf := bytes.NewBufferString(msg) - if _, err = buf.WriteTo(writer); err != nil { - return fmt.Errorf("failed to send email body to %q: %w", to, err) - } - if err = writer.Close(); err != nil { - em.Logf("[WARN] can't close smtp body writer, %v", err) + if emailParams.Port != 0 { + opts = append(opts, email.Port(emailParams.Port)) } - if err = client.Quit(); err != nil { - em.Logf("[WARN] failed to send quit command to %s:%d, %v", em.Host, em.Port, err) - } else { - quit = true + if emailParams.TimeOut != 0 { + opts = append(opts, email.TimeOut(emailParams.TimeOut)) } - return nil -} -func (em *Email) client() (c *smtp.Client, err error) { - srvAddress := fmt.Sprintf("%s:%d", em.Host, em.Port) - if em.TLS { - tlsConf := &tls.Config{ - InsecureSkipVerify: false, - ServerName: em.Host, - MinVersion: tls.VersionTLS12, - } - conn, e := tls.Dial("tcp", srvAddress, tlsConf) - if e != nil { - return nil, fmt.Errorf("failed to dial smtp tls to %s: %w", srvAddress, e) - } - if c, err = smtp.NewClient(conn, em.Host); err != nil { - return nil, fmt.Errorf("failed to make smtp client for %s: %w", srvAddress, err) - } - return c, nil + if emailParams.TLS { + opts = append(opts, email.TLS(true)) } - conn, err := net.DialTimeout("tcp", srvAddress, em.TimeOut) - if err != nil { - return nil, fmt.Errorf("timeout connecting to %s: %w", srvAddress, err) + if emailParams.StartTLS { + opts = append(opts, email.STARTTLS(true)) } - c, err = smtp.NewClient(conn, em.Host) - if err != nil { - return nil, fmt.Errorf("failed to dial: %w", err) - } - return c, nil -} + sender := email.NewSender(emailParams.Host, opts...) -func (em *Email) buildMessage(msg, to string) (message string, err error) { - addHeader := func(msg, h, v string) string { - msg += fmt.Sprintf("%s: %s\n", h, v) - return msg - } - message = addHeader(message, "From", em.From) - message = addHeader(message, "To", to) - message = addHeader(message, "Subject", em.Subject) - message = addHeader(message, "Content-Transfer-Encoding", "quoted-printable") - - if em.ContentType != "" { - message = addHeader(message, "MIME-version", "1.0") - message = addHeader(message, "Content-Type", em.ContentType+`; charset="UTF-8"`) - } - message = addHeader(message, "Date", time.Now().Format(time.RFC1123Z)) + return &Email{EmailParams: emailParams, L: l, sender: sender} +} - buff := &bytes.Buffer{} - qp := quotedprintable.NewWriter(buff) - if _, err := qp.Write([]byte(msg)); err != nil { - return "", err - } - // flush now, must NOT use defer, for small body, defer may cause buff.String() got empty body - if err := qp.Close(); err != nil { - return "", fmt.Errorf("quotedprintable Write failed: %w", err) - } - m := buff.String() - message += "\n" + m - return message, nil +// Send email with given text +func (e *Email) Send(to, text string) error { + e.Logf("[DEBUG] send %q to %s", text, to) + return e.sender.Send(text, email.Params{ + From: e.From, + To: []string{to}, + Subject: e.Subject, + }) } diff --git a/backend/vendor/github.com/go-pkgz/auth/provider/telegram.go b/backend/vendor/github.com/go-pkgz/auth/provider/telegram.go index f4ee0ecdaa..6de30dfcca 100644 --- a/backend/vendor/github.com/go-pkgz/auth/provider/telegram.go +++ b/backend/vendor/github.com/go-pkgz/auth/provider/telegram.go @@ -1,6 +1,6 @@ package provider -//go:generate moq -out telegram_moq_test.go . TelegramAPI +//go:generate moq --out telegram_moq_test.go . TelegramAPI import ( "context" diff --git a/backend/vendor/github.com/go-pkgz/email/.golangci.yml b/backend/vendor/github.com/go-pkgz/email/.golangci.yml index 63d9790b4b..ed5f8ddd6c 100644 --- a/backend/vendor/github.com/go-pkgz/email/.golangci.yml +++ b/backend/vendor/github.com/go-pkgz/email/.golangci.yml @@ -31,29 +31,25 @@ linters-settings: linters: enable: - - megacheck - - revive - - govet - - unconvert - - megacheck - - structcheck - - gas - - gocyclo - dupl - - misspell - - unparam - - varcheck - - deadcode - - typecheck - - ineffassign - - varcheck - - stylecheck - - gochecknoinits - exportloopref + - gas + - gochecknoinits - gocritic - - nakedret + - gocyclo - gosimple + - govet + - ineffassign + - megacheck + - misspell + - nakedret - prealloc + - revive + - stylecheck + - typecheck + - unconvert + - unparam + - unused fast: false disable-all: true diff --git a/backend/vendor/github.com/go-pkgz/email/README.md b/backend/vendor/github.com/go-pkgz/email/README.md index 78d894f928..acee702cb5 100644 --- a/backend/vendor/github.com/go-pkgz/email/README.md +++ b/backend/vendor/github.com/go-pkgz/email/README.md @@ -2,17 +2,16 @@ [![Build Status](https://github.com/go-pkgz/email/workflows/build/badge.svg)](https://github.com/go-pkgz/email/actions) [![Coverage Status](https://coveralls.io/repos/github/go-pkgz/email/badge.svg?branch=master)](https://coveralls.io/github/go-pkgz/email?branch=master) [![Go Reference](https://pkg.go.dev/badge/github.com/go-pkgz/email.svg)](https://pkg.go.dev/github.com/go-pkgz/email) - -The library is a wrapper around the stdlib `net/smtp` simplifying email sending. It supports authentication, SSL/TLS, +The library is a wrapper around the stdlib `net/smtp` simplifying email sending. It supports authentication, SSL/TLS, user-specified SMTP servers, content-type, charset, multiple recipients and more. - + Usage example: ```go client := email.NewSender("localhost", email.ContentType("text/html"), email.Auth("user", "pass")) -err := client.Send("some content, foo bar", - email.Params{From: "me@example.com", To: []string{"to@example.com"}, Subject: "Hello world!", - Attachments: []string{"/path/to/file1.txt", "/path/to/file2.txt"}, +err := client.Send("some content, foo bar", + email.Params{From: "me@example.com", To: []string{"to@example.com"}, Subject: "Hello world!", + Attachments: []string{"/path/to/file1.txt", "/path/to/file2.txt"}, InlineImages: []string{"/path/to/image1.png", "/path/to/image2.png"}, }) ``` @@ -25,6 +24,7 @@ err := client.Send("some content, foo bar", - `TLS`: Use TLS SMTP (default: false) - `STARTTLS`: Use STARTTLS (default: false) - `Auth(user, password)`: Username and password for SMTP authentication (default: empty, no authentication) +- `LoginAuth`: Use [LOGIN mechanism](https://www.ietf.org/archive/id/draft-murchison-sasl-login-00.txt) instead of PLAIN mechanism for SMTP authentication, e.g. this is relevant for Office 365 and Outlook.com - `ContentType`: Content type for the email (default: "text/plain") - `Charset`: Charset for the email (default: "utf-8") - `TimeOut`: Timeout for the SMTP connection (default: 30 seconds) @@ -41,16 +41,17 @@ To send email user need to create a sender first and then use `Send` method. The - email content (string) - parameters (`email.Params`) - ```go - type Params struct { - From string // From email field - To []string // From email field - Subject string // Email subject - UnsubscribeLink string // POST, https://support.google.com/mail/answer/81126 -> "Use one-click unsubscribe" - Attachments []string // Attachments path - InlineImages []string // Embedding directly to email body. Autogenerated Content-Id (cid) equals to file name - } - ``` + ```go + type Params struct { + From string // From email field + To []string // From email field + Subject string // Email subject + UnsubscribeLink string // POST, https://support.google.com/mail/answer/81126 -> "Use one-click unsubscribe" + InReplyTo string // Identifier for email group (category), used for email grouping + Attachments []string // Attachments path + InlineImages []string // Embedding directly to email body. Autogenerated Content-Id (cid) equals to file name + } + ``` See [go docs](https://pkg.go.dev/github.com/go-pkgz/email#Sender.Send) for `Send` function. @@ -60,11 +61,11 @@ See [go docs](https://pkg.go.dev/github.com/go-pkgz/email#Sender.Send) for `Send - Custom SMTP client (`smtp.Client` from stdlib) can be set by user with `SMTP` option. In this case it will be used instead of making a new smtp client internally. - Logger can be set with `Log` option. It should implement `email.Logger` interface with a single `Logf(format string, args ...interface{})` method. By default, "no logging" internal logger is used. This interface is compatible with the `go-pkgz/lgr` logger. - The library has no external dependencies, except for testing. It uses the stdlib `net/smtp` package. -- SSL/TLS supported with `TLS` option. Pls note: this is not the same as `STARTTLS` (not supported) which is usually on port 587 vs SSL/TLS on port 465. +- SSL/TLS supported with `TLS` option (usually on port 465) as well as with `STARTTLS` (usually on port 587). ## limitations -This library is not intended to be used for sending a lot of massive emails with +This library is not intended to be used for sending a lot of massive emails with low latency requirements. The intended use case is sending simple messages, like alerts, notification and so on. -For example, sending alerts from a monitoring system, or for authentication-related emails, i.e. "password reset email", +For example, sending alerts from a monitoring system, or for authentication-related emails, i.e. "password reset email", "verification email", etc. diff --git a/backend/vendor/github.com/go-pkgz/email/auth.go b/backend/vendor/github.com/go-pkgz/email/auth.go new file mode 100644 index 0000000000..b1c8843a5e --- /dev/null +++ b/backend/vendor/github.com/go-pkgz/email/auth.go @@ -0,0 +1,60 @@ +package email + +import ( + "errors" + "net/smtp" +) + +// authMethod is SMTP authentication method +type authMethod string + +// List of supported authentication methods +const ( + authMethodPlain authMethod = "PLAIN" + authMethodLogin authMethod = "LOGIN" +) + +// newLoginAuth returns smtp.Auth that implements the LOGIN authentication +// mechanism as defined in the LOGIN SASL Mechanism document, +// https://www.ietf.org/archive/id/draft-murchison-sasl-login-00.txt. +// The returned smtp.Auth uses the given username and password to authenticate +// to the host. +// +// LOGIN will only send the credentials if the connection is using TLS +// or is connected to localhost. Otherwise authentication will fail with an +// error, without sending the credentials. +// +// LOGIN is described as obsolete in the SASL Mechanisms document +// but the mechanism is still in use, e.g. in Office 365 and Outlook.com. +func newLoginAuth(usr, pwd, host string) smtp.Auth { + return &loginAuth{usr, pwd, host} +} + +type loginAuth struct { + user string + password string + host string +} + +func isLocalhost(name string) bool { + return name == "localhost" || name == "127.0.0.1" || name == "::1" +} + +func (a *loginAuth) Start(server *smtp.ServerInfo) (proto string, toServer []byte, err error) { + if !server.TLS && !isLocalhost(server.Name) { + return "", nil, errors.New("unencrypted connection") + } + if server.Name != a.host { + return "", nil, errors.New("wrong host name") + } + + return "LOGIN", []byte(a.user), nil +} + +func (a *loginAuth) Next(fromServer []byte, more bool) (toServer []byte, err error) { + if more { + return []byte(a.password), nil + } + + return nil, nil +} diff --git a/backend/vendor/github.com/go-pkgz/email/email.go b/backend/vendor/github.com/go-pkgz/email/email.go index b3393ce326..beb9525d42 100644 --- a/backend/vendor/github.com/go-pkgz/email/email.go +++ b/backend/vendor/github.com/go-pkgz/email/email.go @@ -28,13 +28,14 @@ import ( type Sender struct { smtpClient SMTPClient logger Logger - host string // SMTP host - port int // SMTP port - contentType string // Content type, optional. Will trigger MIME and Content-Type headers - tls bool // TLS auth - starttls bool // StartTLS - smtpUserName string // username - smtpPassword string // password + host string // SMTP host + port int // SMTP port + contentType string // Content type, optional. Will trigger MIME and Content-Type headers + tls bool // TLS auth + starttls bool // StartTLS + smtpUserName string // username + smtpPassword string // password + authMethod authMethod // auth method timeOut time.Duration contentCharset string timeNow func() time.Time @@ -46,6 +47,7 @@ type Params struct { To []string // From email field Subject string // Email subject UnsubscribeLink string // POST, https://support.google.com/mail/answer/81126 -> "Use one-click unsubscribe" + InReplyTo string // Identifier for email group (category), used for email grouping Attachments []string // Attachments path InlineImages []string // InlineImages images path } @@ -76,6 +78,7 @@ func NewSender(smtpHost string, options ...Option) *Sender { tls: false, smtpUserName: "", smtpPassword: "", + authMethod: authMethodPlain, contentCharset: "UTF-8", timeOut: time.Second * 30, timeNow: time.Now, @@ -119,8 +122,7 @@ func (em *Sender) Send(text string, params Params) error { return errors.New("no recipients") } - if em.smtpUserName != "" && em.smtpPassword != "" { - auth := smtp.PlainAuth("", em.smtpUserName, em.smtpPassword, em.host) + if auth := em.auth(); auth != nil { if err := client.Auth(auth); err != nil { return fmt.Errorf("failed to auth to smtp %s:%d, %w", em.host, em.port, err) } @@ -204,6 +206,19 @@ func (em *Sender) client() (c *smtp.Client, err error) { return c, nil } +// auth returns an smtp.Auth that implements SMTP authentication mechanism +// depends on Sender settings. +func (em *Sender) auth() smtp.Auth { + if em.smtpUserName == "" || em.smtpPassword == "" { + return nil // no auth + } + + if em.authMethod == authMethodLogin { + return newLoginAuth(em.smtpUserName, em.smtpPassword, em.host) + } + return smtp.PlainAuth("", em.smtpUserName, em.smtpPassword, em.host) +} + func (em *Sender) buildMessage(text string, params Params) (message string, err error) { addHeader := func(msg, h, v string) string { msg += fmt.Sprintf("%s: %s\n", h, v) @@ -218,6 +233,10 @@ func (em *Sender) buildMessage(text string, params Params) (message string, err message = addHeader(message, "List-Unsubscribe", "<"+params.UnsubscribeLink+">") } + if params.InReplyTo != "" { + message = addHeader(message, "In-reply-to", "<"+params.InReplyTo+">") + } + withAttachments := len(params.Attachments) > 0 withInlineImg := len(params.InlineImages) > 0 diff --git a/backend/vendor/github.com/go-pkgz/email/options.go b/backend/vendor/github.com/go-pkgz/email/options.go index e1d210af36..0707030470 100644 --- a/backend/vendor/github.com/go-pkgz/email/options.go +++ b/backend/vendor/github.com/go-pkgz/email/options.go @@ -62,6 +62,13 @@ func Auth(smtpUserName, smtpPasswd string) Option { } } +// LoginAuth sets LOGIN auth method +func LoginAuth() Option { + return func(s *Sender) { + s.authMethod = authMethodLogin + } +} + // TimeOut sets smtp timeout func TimeOut(timeOut time.Duration) Option { return func(s *Sender) { diff --git a/backend/vendor/github.com/go-pkgz/notify/email.go b/backend/vendor/github.com/go-pkgz/notify/email.go index e648cb7324..ff18c212cc 100644 --- a/backend/vendor/github.com/go-pkgz/notify/email.go +++ b/backend/vendor/github.com/go-pkgz/notify/email.go @@ -19,6 +19,7 @@ type SMTPParams struct { StartTLS bool // StartTLS auth ContentType string // Content type Charset string // Character set + LoginAuth bool // LOGIN auth method instead of default PLAIN, needed for Office 365 and outlook.com Username string // username Password string // password TimeOut time.Duration // TCP connection timeout @@ -46,6 +47,10 @@ func NewEmail(smtpParams SMTPParams) *Email { opts = append(opts, email.Charset(smtpParams.Charset)) } + if smtpParams.LoginAuth { + opts = append(opts, email.LoginAuth()) + } + if smtpParams.Port != 0 { opts = append(opts, email.Port(smtpParams.Port)) } diff --git a/backend/vendor/github.com/go-pkgz/notify/telegram.go b/backend/vendor/github.com/go-pkgz/notify/telegram.go index 40da9fd157..a8a412a9f8 100644 --- a/backend/vendor/github.com/go-pkgz/notify/telegram.go +++ b/backend/vendor/github.com/go-pkgz/notify/telegram.go @@ -48,7 +48,7 @@ type Telegram struct { } } -// telegramMsg is used to send message trough Telegram bot API +// telegramMsg is used to send message through Telegram bot API type telegramMsg struct { Text string `json:"text"` ParseMode string `json:"parse_mode,omitempty"` diff --git a/backend/vendor/github.com/go-pkgz/rest/.golangci.yml b/backend/vendor/github.com/go-pkgz/rest/.golangci.yml index 824667f8d5..77a0c5d550 100644 --- a/backend/vendor/github.com/go-pkgz/rest/.golangci.yml +++ b/backend/vendor/github.com/go-pkgz/rest/.golangci.yml @@ -31,17 +31,14 @@ linters: - govet - unconvert - megacheck - - structcheck - gas - gocyclo - dupl - misspell - unparam - - varcheck - - deadcode + - unused - typecheck - ineffassign - - varcheck - stylecheck - gochecknoinits - exportloopref diff --git a/backend/vendor/github.com/go-pkgz/rest/README.md b/backend/vendor/github.com/go-pkgz/rest/README.md index 70996ed6ae..b85c999b10 100644 --- a/backend/vendor/github.com/go-pkgz/rest/README.md +++ b/backend/vendor/github.com/go-pkgz/rest/README.md @@ -36,6 +36,45 @@ Org: Umputun pong ``` +### Health middleware + +Responds with the status 200 if all health checks passed, 503 if any failed. Both health path and check functions passed by consumer. +For production usage this middleware should be used with throttler/limiter and, optionally, with some auth middlewares + +Example of usage: + +```go + check1 := func(ctx context.Context) (name string, err error) { + // do some check, for example check DB connection + return "check1", nil // all good, passed + } + check2 := func(ctx context.Context) (name string, err error) { + // do some other check, for example ping an external service + return "check2", errors.New("some error") // check failed + } + + router := chi.NewRouter() + router.Use(rest.Health("/health", check1, check2)) +``` + +example of the actual call and response: + +``` +> http GET https://example.com/health + +HTTP/1.1 503 Service Unavailable +Date: Sun, 15 Jul 2018 19:40:31 GMT +Content-Type: application/json; charset=utf-8 +Content-Length: 36 + +[ + {"name":"check1","status":"ok"}, + {"name":"check2","status":"failed","error":"some error"} +] +``` + +_this middleware is pretty basic, but can be used for simple health checks. For more complex cases, like async/cached health checks see [alexliesenfeld/health](https://github.com/alexliesenfeld/health)_ + ### Logger middleware Logs request, request handling time and response. Log record fields in order of occurrence: @@ -119,6 +158,23 @@ Maybe middleware will allow you to change the flow of the middleware stack execu value of maybeFn(request). This is useful for example if you'd like to skip a middleware handler if a request does not satisfy the maybeFn logic. +### Reject middleware + +Reject is a middleware that rejects requests with a given status code and message based on a user-defined function. +This is useful for example if you'd like to reject requests to a particular resource based on a request header, or want to implement a conditional request handler based on service parameters. + +example with chi router: + +```go + router := chi.NewRouter() + + rejectFn := func(r *http.Request) (bool) { + return r.Header.Get("X-Request-Id") == "" // reject if no X-Request-Id header + } + + router.Use(rest.Reject(http.StatusBadRequest, "X-Request-Id header is required", rejectFn)) +``` + ### Benchmarks middleware Benchmarks middleware allows to measure the time of request handling, number of request per second and report aggregated metrics. This middleware keeps track of the request in the memory and keep up to 900 points (15 minutes, data-point per second). diff --git a/backend/vendor/github.com/go-pkgz/rest/middleware.go b/backend/vendor/github.com/go-pkgz/rest/middleware.go index 3adb154c1a..6e50337946 100644 --- a/backend/vendor/github.com/go-pkgz/rest/middleware.go +++ b/backend/vendor/github.com/go-pkgz/rest/middleware.go @@ -1,6 +1,7 @@ package rest import ( + "context" "net/http" "os" "runtime/debug" @@ -54,6 +55,47 @@ func Ping(next http.Handler) http.Handler { return http.HandlerFunc(fn) } +// Health middleware response with health info and status (200 if healthy). Stops chain if health request detected +// passed checkers implements custom health checks and returns error if health check failed. The check has to return name +// regardless to the error state. +// For production usage this middleware should be used with throttler and, optionally, with BasicAuth middlewares +func Health(path string, checkers ...func(ctx context.Context) (name string, err error)) func(http.Handler) http.Handler { + + type hr struct { + Name string `json:"name"` + Status string `json:"status"` + Error string `json:"error,omitempty"` + } + + return func(h http.Handler) http.Handler { + fn := func(w http.ResponseWriter, r *http.Request) { + if r.Method != "GET" || !strings.EqualFold(r.URL.Path, path) { + h.ServeHTTP(w, r) // not the health check request, continue the chain + return + } + resp := []hr{} + var anyError bool + for _, check := range checkers { + name, err := check(r.Context()) + hh := hr{Name: name, Status: "ok"} + if err != nil { + hh.Status = "failed" + hh.Error = err.Error() + anyError = true + } + resp = append(resp, hh) + } + if anyError { + w.WriteHeader(http.StatusServiceUnavailable) + } else { + w.WriteHeader(http.StatusOK) + } + RenderJSON(w, resp) + } + return http.HandlerFunc(fn) + } +} + // Recoverer is a middleware that recovers from panics, logs the panic and returns a HTTP 500 status if possible. func Recoverer(l logger.Backend) func(http.Handler) http.Handler { return func(h http.Handler) http.Handler { @@ -125,3 +167,18 @@ func RealIP(h http.Handler) http.Handler { return http.HandlerFunc(fn) } + +// Reject is a middleware that conditionally rejects requests with a given status code and message. +// user-defined condition function rejectFn is used to determine if the request should be rejected. +func Reject(errCode int, errMsg string, rejectFn func(r *http.Request) bool) func(h http.Handler) http.Handler { + return func(h http.Handler) http.Handler { + fn := func(w http.ResponseWriter, r *http.Request) { + if rejectFn(r) { + http.Error(w, errMsg, errCode) + return + } + h.ServeHTTP(w, r) + } + return http.HandlerFunc(fn) + } +} diff --git a/backend/vendor/github.com/go-pkgz/rest/rest.go b/backend/vendor/github.com/go-pkgz/rest/rest.go index 57fe4a7ba0..1b321ec0e1 100644 --- a/backend/vendor/github.com/go-pkgz/rest/rest.go +++ b/backend/vendor/github.com/go-pkgz/rest/rest.go @@ -4,10 +4,9 @@ package rest import ( "bytes" "encoding/json" + "fmt" "net/http" "time" - - "github.com/pkg/errors" ) // JSON is a map alias, just for convenience @@ -30,7 +29,7 @@ func RenderJSON(w http.ResponseWriter, data interface{}) { func RenderJSONFromBytes(w http.ResponseWriter, r *http.Request, data []byte) error { w.Header().Set("Content-Type", "application/json; charset=utf-8") if _, err := w.Write(data); err != nil { - return errors.Wrapf(err, "failed to send response to %s", r.RemoteAddr) + return fmt.Errorf("failed to send response to %s: %w", r.RemoteAddr, err) } return nil } @@ -43,7 +42,7 @@ func RenderJSONWithHTML(w http.ResponseWriter, r *http.Request, v interface{}) e enc := json.NewEncoder(buf) enc.SetEscapeHTML(false) if err := enc.Encode(v); err != nil { - return nil, errors.Wrap(err, "json encoding failed") + return nil, fmt.Errorf("json encoding failed: %w", err) } return buf.Bytes(), nil } @@ -86,15 +85,15 @@ func ParseFromTo(r *http.Request) (from, to time.Time, err error) { return t, nil } } - return time.Time{}, errors.Errorf("can't parse date %q", ts) + return time.Time{}, fmt.Errorf("can't parse date %q", ts) } if from, err = parseTimeStamp(r.URL.Query().Get("from")); err != nil { - return from, to, errors.Wrap(err, "incorrect from time") + return from, to, fmt.Errorf("incorrect from time: %w", err) } if to, err = parseTimeStamp(r.URL.Query().Get("to")); err != nil { - return from, to, errors.Wrap(err, "incorrect to time") + return from, to, fmt.Errorf("incorrect to time: %w", err) } return from, to, nil } diff --git a/backend/vendor/github.com/go-stack/stack/README.md b/backend/vendor/github.com/go-stack/stack/README.md deleted file mode 100644 index f11ccccaa4..0000000000 --- a/backend/vendor/github.com/go-stack/stack/README.md +++ /dev/null @@ -1,38 +0,0 @@ -[![GoDoc](https://godoc.org/github.com/go-stack/stack?status.svg)](https://godoc.org/github.com/go-stack/stack) -[![Go Report Card](https://goreportcard.com/badge/go-stack/stack)](https://goreportcard.com/report/go-stack/stack) -[![TravisCI](https://travis-ci.org/go-stack/stack.svg?branch=master)](https://travis-ci.org/go-stack/stack) -[![Coverage Status](https://coveralls.io/repos/github/go-stack/stack/badge.svg?branch=master)](https://coveralls.io/github/go-stack/stack?branch=master) - -# stack - -Package stack implements utilities to capture, manipulate, and format call -stacks. It provides a simpler API than package runtime. - -The implementation takes care of the minutia and special cases of interpreting -the program counter (pc) values returned by runtime.Callers. - -## Versioning - -Package stack publishes releases via [semver](http://semver.org/) compatible Git -tags prefixed with a single 'v'. The master branch always contains the latest -release. The develop branch contains unreleased commits. - -## Formatting - -Package stack's types implement fmt.Formatter, which provides a simple and -flexible way to declaratively configure formatting when used with logging or -error tracking packages. - -```go -func DoTheThing() { - c := stack.Caller(0) - log.Print(c) // "source.go:10" - log.Printf("%+v", c) // "pkg/path/source.go:10" - log.Printf("%n", c) // "DoTheThing" - - s := stack.Trace().TrimRuntime() - log.Print(s) // "[source.go:15 caller.go:42 main.go:14]" -} -``` - -See the docs for all of the supported formatting options. diff --git a/backend/vendor/github.com/go-stack/stack/stack.go b/backend/vendor/github.com/go-stack/stack/stack.go deleted file mode 100644 index ac3b93b14f..0000000000 --- a/backend/vendor/github.com/go-stack/stack/stack.go +++ /dev/null @@ -1,400 +0,0 @@ -// +build go1.7 - -// Package stack implements utilities to capture, manipulate, and format call -// stacks. It provides a simpler API than package runtime. -// -// The implementation takes care of the minutia and special cases of -// interpreting the program counter (pc) values returned by runtime.Callers. -// -// Package stack's types implement fmt.Formatter, which provides a simple and -// flexible way to declaratively configure formatting when used with logging -// or error tracking packages. -package stack - -import ( - "bytes" - "errors" - "fmt" - "io" - "runtime" - "strconv" - "strings" -) - -// Call records a single function invocation from a goroutine stack. -type Call struct { - frame runtime.Frame -} - -// Caller returns a Call from the stack of the current goroutine. The argument -// skip is the number of stack frames to ascend, with 0 identifying the -// calling function. -func Caller(skip int) Call { - // As of Go 1.9 we need room for up to three PC entries. - // - // 0. An entry for the stack frame prior to the target to check for - // special handling needed if that prior entry is runtime.sigpanic. - // 1. A possible second entry to hold metadata about skipped inlined - // functions. If inline functions were not skipped the target frame - // PC will be here. - // 2. A third entry for the target frame PC when the second entry - // is used for skipped inline functions. - var pcs [3]uintptr - n := runtime.Callers(skip+1, pcs[:]) - frames := runtime.CallersFrames(pcs[:n]) - frame, _ := frames.Next() - frame, _ = frames.Next() - - return Call{ - frame: frame, - } -} - -// String implements fmt.Stinger. It is equivalent to fmt.Sprintf("%v", c). -func (c Call) String() string { - return fmt.Sprint(c) -} - -// MarshalText implements encoding.TextMarshaler. It formats the Call the same -// as fmt.Sprintf("%v", c). -func (c Call) MarshalText() ([]byte, error) { - if c.frame == (runtime.Frame{}) { - return nil, ErrNoFunc - } - - buf := bytes.Buffer{} - fmt.Fprint(&buf, c) - return buf.Bytes(), nil -} - -// ErrNoFunc means that the Call has a nil *runtime.Func. The most likely -// cause is a Call with the zero value. -var ErrNoFunc = errors.New("no call stack information") - -// Format implements fmt.Formatter with support for the following verbs. -// -// %s source file -// %d line number -// %n function name -// %k last segment of the package path -// %v equivalent to %s:%d -// -// It accepts the '+' and '#' flags for most of the verbs as follows. -// -// %+s path of source file relative to the compile time GOPATH, -// or the module path joined to the path of source file relative -// to module root -// %#s full path of source file -// %+n import path qualified function name -// %+k full package path -// %+v equivalent to %+s:%d -// %#v equivalent to %#s:%d -func (c Call) Format(s fmt.State, verb rune) { - if c.frame == (runtime.Frame{}) { - fmt.Fprintf(s, "%%!%c(NOFUNC)", verb) - return - } - - switch verb { - case 's', 'v': - file := c.frame.File - switch { - case s.Flag('#'): - // done - case s.Flag('+'): - file = pkgFilePath(&c.frame) - default: - const sep = "/" - if i := strings.LastIndex(file, sep); i != -1 { - file = file[i+len(sep):] - } - } - io.WriteString(s, file) - if verb == 'v' { - buf := [7]byte{':'} - s.Write(strconv.AppendInt(buf[:1], int64(c.frame.Line), 10)) - } - - case 'd': - buf := [6]byte{} - s.Write(strconv.AppendInt(buf[:0], int64(c.frame.Line), 10)) - - case 'k': - name := c.frame.Function - const pathSep = "/" - start, end := 0, len(name) - if i := strings.LastIndex(name, pathSep); i != -1 { - start = i + len(pathSep) - } - const pkgSep = "." - if i := strings.Index(name[start:], pkgSep); i != -1 { - end = start + i - } - if s.Flag('+') { - start = 0 - } - io.WriteString(s, name[start:end]) - - case 'n': - name := c.frame.Function - if !s.Flag('+') { - const pathSep = "/" - if i := strings.LastIndex(name, pathSep); i != -1 { - name = name[i+len(pathSep):] - } - const pkgSep = "." - if i := strings.Index(name, pkgSep); i != -1 { - name = name[i+len(pkgSep):] - } - } - io.WriteString(s, name) - } -} - -// Frame returns the call frame infomation for the Call. -func (c Call) Frame() runtime.Frame { - return c.frame -} - -// PC returns the program counter for this call frame; multiple frames may -// have the same PC value. -// -// Deprecated: Use Call.Frame instead. -func (c Call) PC() uintptr { - return c.frame.PC -} - -// CallStack records a sequence of function invocations from a goroutine -// stack. -type CallStack []Call - -// String implements fmt.Stinger. It is equivalent to fmt.Sprintf("%v", cs). -func (cs CallStack) String() string { - return fmt.Sprint(cs) -} - -var ( - openBracketBytes = []byte("[") - closeBracketBytes = []byte("]") - spaceBytes = []byte(" ") -) - -// MarshalText implements encoding.TextMarshaler. It formats the CallStack the -// same as fmt.Sprintf("%v", cs). -func (cs CallStack) MarshalText() ([]byte, error) { - buf := bytes.Buffer{} - buf.Write(openBracketBytes) - for i, pc := range cs { - if i > 0 { - buf.Write(spaceBytes) - } - fmt.Fprint(&buf, pc) - } - buf.Write(closeBracketBytes) - return buf.Bytes(), nil -} - -// Format implements fmt.Formatter by printing the CallStack as square brackets -// ([, ]) surrounding a space separated list of Calls each formatted with the -// supplied verb and options. -func (cs CallStack) Format(s fmt.State, verb rune) { - s.Write(openBracketBytes) - for i, pc := range cs { - if i > 0 { - s.Write(spaceBytes) - } - pc.Format(s, verb) - } - s.Write(closeBracketBytes) -} - -// Trace returns a CallStack for the current goroutine with element 0 -// identifying the calling function. -func Trace() CallStack { - var pcs [512]uintptr - n := runtime.Callers(1, pcs[:]) - - frames := runtime.CallersFrames(pcs[:n]) - cs := make(CallStack, 0, n) - - // Skip extra frame retrieved just to make sure the runtime.sigpanic - // special case is handled. - frame, more := frames.Next() - - for more { - frame, more = frames.Next() - cs = append(cs, Call{frame: frame}) - } - - return cs -} - -// TrimBelow returns a slice of the CallStack with all entries below c -// removed. -func (cs CallStack) TrimBelow(c Call) CallStack { - for len(cs) > 0 && cs[0] != c { - cs = cs[1:] - } - return cs -} - -// TrimAbove returns a slice of the CallStack with all entries above c -// removed. -func (cs CallStack) TrimAbove(c Call) CallStack { - for len(cs) > 0 && cs[len(cs)-1] != c { - cs = cs[:len(cs)-1] - } - return cs -} - -// pkgIndex returns the index that results in file[index:] being the path of -// file relative to the compile time GOPATH, and file[:index] being the -// $GOPATH/src/ portion of file. funcName must be the name of a function in -// file as returned by runtime.Func.Name. -func pkgIndex(file, funcName string) int { - // As of Go 1.6.2 there is no direct way to know the compile time GOPATH - // at runtime, but we can infer the number of path segments in the GOPATH. - // We note that runtime.Func.Name() returns the function name qualified by - // the import path, which does not include the GOPATH. Thus we can trim - // segments from the beginning of the file path until the number of path - // separators remaining is one more than the number of path separators in - // the function name. For example, given: - // - // GOPATH /home/user - // file /home/user/src/pkg/sub/file.go - // fn.Name() pkg/sub.Type.Method - // - // We want to produce: - // - // file[:idx] == /home/user/src/ - // file[idx:] == pkg/sub/file.go - // - // From this we can easily see that fn.Name() has one less path separator - // than our desired result for file[idx:]. We count separators from the - // end of the file path until it finds two more than in the function name - // and then move one character forward to preserve the initial path - // segment without a leading separator. - const sep = "/" - i := len(file) - for n := strings.Count(funcName, sep) + 2; n > 0; n-- { - i = strings.LastIndex(file[:i], sep) - if i == -1 { - i = -len(sep) - break - } - } - // get back to 0 or trim the leading separator - return i + len(sep) -} - -// pkgFilePath returns the frame's filepath relative to the compile-time GOPATH, -// or its module path joined to its path relative to the module root. -// -// As of Go 1.11 there is no direct way to know the compile time GOPATH or -// module paths at runtime, but we can piece together the desired information -// from available information. We note that runtime.Frame.Function contains the -// function name qualified by the package path, which includes the module path -// but not the GOPATH. We can extract the package path from that and append the -// last segments of the file path to arrive at the desired package qualified -// file path. For example, given: -// -// GOPATH /home/user -// import path pkg/sub -// frame.File /home/user/src/pkg/sub/file.go -// frame.Function pkg/sub.Type.Method -// Desired return pkg/sub/file.go -// -// It appears that we simply need to trim ".Type.Method" from frame.Function and -// append "/" + path.Base(file). -// -// But there are other wrinkles. Although it is idiomatic to do so, the internal -// name of a package is not required to match the last segment of its import -// path. In addition, the introduction of modules in Go 1.11 allows working -// without a GOPATH. So we also must make these work right: -// -// GOPATH /home/user -// import path pkg/go-sub -// package name sub -// frame.File /home/user/src/pkg/go-sub/file.go -// frame.Function pkg/sub.Type.Method -// Desired return pkg/go-sub/file.go -// -// Module path pkg/v2 -// import path pkg/v2/go-sub -// package name sub -// frame.File /home/user/cloned-pkg/go-sub/file.go -// frame.Function pkg/v2/sub.Type.Method -// Desired return pkg/v2/go-sub/file.go -// -// We can handle all of these situations by using the package path extracted -// from frame.Function up to, but not including, the last segment as the prefix -// and the last two segments of frame.File as the suffix of the returned path. -// This preserves the existing behavior when working in a GOPATH without modules -// and a semantically equivalent behavior when used in module aware project. -func pkgFilePath(frame *runtime.Frame) string { - pre := pkgPrefix(frame.Function) - post := pathSuffix(frame.File) - if pre == "" { - return post - } - return pre + "/" + post -} - -// pkgPrefix returns the import path of the function's package with the final -// segment removed. -func pkgPrefix(funcName string) string { - const pathSep = "/" - end := strings.LastIndex(funcName, pathSep) - if end == -1 { - return "" - } - return funcName[:end] -} - -// pathSuffix returns the last two segments of path. -func pathSuffix(path string) string { - const pathSep = "/" - lastSep := strings.LastIndex(path, pathSep) - if lastSep == -1 { - return path - } - return path[strings.LastIndex(path[:lastSep], pathSep)+1:] -} - -var runtimePath string - -func init() { - var pcs [3]uintptr - runtime.Callers(0, pcs[:]) - frames := runtime.CallersFrames(pcs[:]) - frame, _ := frames.Next() - file := frame.File - - idx := pkgIndex(frame.File, frame.Function) - - runtimePath = file[:idx] - if runtime.GOOS == "windows" { - runtimePath = strings.ToLower(runtimePath) - } -} - -func inGoroot(c Call) bool { - file := c.frame.File - if len(file) == 0 || file[0] == '?' { - return true - } - if runtime.GOOS == "windows" { - file = strings.ToLower(file) - } - return strings.HasPrefix(file, runtimePath) || strings.HasSuffix(file, "/_testmain.go") -} - -// TrimRuntime returns a slice of the CallStack with the topmost entries from -// the go runtime removed. It considers any calls originating from unknown -// files, files under GOROOT, or _testmain.go as part of the runtime. -func (cs CallStack) TrimRuntime() CallStack { - for len(cs) > 0 && inGoroot(cs[len(cs)-1]) { - cs = cs[:len(cs)-1] - } - return cs -} diff --git a/backend/vendor/github.com/montanaflynn/stats/.gitignore b/backend/vendor/github.com/montanaflynn/stats/.gitignore new file mode 100644 index 0000000000..96b11286e5 --- /dev/null +++ b/backend/vendor/github.com/montanaflynn/stats/.gitignore @@ -0,0 +1,2 @@ +coverage.out +.directory \ No newline at end of file diff --git a/backend/vendor/github.com/montanaflynn/stats/.travis.yml b/backend/vendor/github.com/montanaflynn/stats/.travis.yml new file mode 100644 index 0000000000..697dcb7591 --- /dev/null +++ b/backend/vendor/github.com/montanaflynn/stats/.travis.yml @@ -0,0 +1,20 @@ +language: go +go: + - 1.1 + - 1.2 + - 1.3 + - 1.4 + - 1.5 + - tip +before_install: + - sudo pip install codecov +script: + - go test +after_success: + - codecov +notifications: + email: + recipients: + - montana@montanaflynn.me + on_success: change + on_failure: always diff --git a/backend/vendor/github.com/montanaflynn/stats/CHANGELOG.md b/backend/vendor/github.com/montanaflynn/stats/CHANGELOG.md new file mode 100644 index 0000000000..532f6ed3fd --- /dev/null +++ b/backend/vendor/github.com/montanaflynn/stats/CHANGELOG.md @@ -0,0 +1,64 @@ +# Change Log + +## [0.2.0](https://github.com/montanaflynn/stats/tree/0.2.0) + +### Merged pull requests: + +- Fixed typographical error, changed accomdate to accommodate in README. [\#5](https://github.com/montanaflynn/stats/pull/5) ([saromanov](https://github.com/orthographic-pedant)) + +### Package changes: + +- Add `Correlation` function +- Add `Covariance` function +- Add `StandardDeviation` function to be the same as `StandardDeviationPopulation` +- Change `Variance` function to be the same as `PopulationVariation` +- Add helper methods to `Float64Data` +- Add `Float64Data` type to use instead of `[]float64` +- Add `Series` type which references to `[]Coordinate` + +## [0.1.0](https://github.com/montanaflynn/stats/tree/0.1.0) + +Several functions were renamed in this release. They will still function but may be deprecated in the future. + +### Package changes: + +- Rename `VarP` to `PopulationVariance` +- Rename `VarS` to `SampleVariance` +- Rename `LinReg` to `LinearRegression` +- Rename `ExpReg` to `ExponentialRegression` +- Rename `LogReg` to `LogarithmicRegression` +- Rename `StdDevP` to `StandardDeviationPopulation` +- Rename `StdDevS` to `StandardDeviationSample` + +## [0.0.9](https://github.com/montanaflynn/stats/tree/0.0.9) + +### Closed issues: + +- Functions have unexpected side effects [\#3](https://github.com/montanaflynn/stats/issues/3) +- Percentile is not calculated correctly [\#2](https://github.com/montanaflynn/stats/issues/2) + +### Merged pull requests: + +- Sample [\#4](https://github.com/montanaflynn/stats/pull/4) ([saromanov](https://github.com/saromanov)) + +### Package changes: + +- Add HarmonicMean func +- Add GeometricMean func +- Add Outliers stuct and QuantileOutliers func +- Add Interquartile Range, Midhinge and Trimean examples +- Add Trimean +- Add Midhinge +- Add Inter Quartile Range +- Add Quantiles struct and Quantile func +- Add Nearest Rank method of calculating percentiles +- Add errors for all functions +- Add sample +- Add Linear, Exponential and Logarithmic Regression +- Add sample and population variance and deviation +- Add Percentile and Float64ToInt +- Add Round +- Add Standard deviation +- Add Sum +- Add Min and Ma- x +- Add Mean, Median and Mode diff --git a/backend/vendor/github.com/go-stack/stack/LICENSE.md b/backend/vendor/github.com/montanaflynn/stats/LICENSE similarity index 94% rename from backend/vendor/github.com/go-stack/stack/LICENSE.md rename to backend/vendor/github.com/montanaflynn/stats/LICENSE index 2abf98ea83..6648181765 100644 --- a/backend/vendor/github.com/go-stack/stack/LICENSE.md +++ b/backend/vendor/github.com/montanaflynn/stats/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014 Chris Hines +Copyright (c) 2014-2015 Montana Flynn (https://anonfunction.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/backend/vendor/github.com/montanaflynn/stats/Makefile b/backend/vendor/github.com/montanaflynn/stats/Makefile new file mode 100644 index 0000000000..87844f485d --- /dev/null +++ b/backend/vendor/github.com/montanaflynn/stats/Makefile @@ -0,0 +1,29 @@ +.PHONY: all + +doc: + godoc `pwd` + +webdoc: + godoc -http=:44444 + +format: + go fmt + +test: + go test -race + +check: format test + +benchmark: + go test -bench=. -benchmem + +coverage: + go test -coverprofile=coverage.out + go tool cover -html="coverage.out" + +lint: format + go get github.com/alecthomas/gometalinter + gometalinter --install + gometalinter + +default: lint test diff --git a/backend/vendor/github.com/montanaflynn/stats/README.md b/backend/vendor/github.com/montanaflynn/stats/README.md new file mode 100644 index 0000000000..5f8a9291bf --- /dev/null +++ b/backend/vendor/github.com/montanaflynn/stats/README.md @@ -0,0 +1,103 @@ +# Stats [![][travis-svg]][travis-url] [![][coveralls-svg]][coveralls-url] [![][godoc-svg]][godoc-url] [![][license-svg]][license-url] + +A statistics package with many functions missing from the Golang standard library. See the [CHANGELOG.md](https://github.com/montanaflynn/stats/blob/master/CHANGELOG.md) for API changes and tagged releases you can vendor into your projects. + +> Statistics are used much like a drunk uses a lamppost: for support, not illumination. **- Vin Scully** + +## Installation + +``` +go get github.com/montanaflynn/stats +``` + +**Protip:** `go get -u github.com/montanaflynn/stats` updates stats to the latest version. + +## Usage + +The [entire API documentation](http://godoc.org/github.com/montanaflynn/stats) is available on GoDoc.org + +You can view docs offline with the following commands: + +``` +godoc ./ +godoc ./ Median +godoc ./ Float64Data +``` + +**Protip:** Generate HTML docs with `godoc -http=:4444` + +## Example + +All the functions can be seen in [examples/main.go](https://github.com/montanaflynn/stats/blob/master/examples/main.go) but here's a little taste: + +```go +// start with the some source data to use +var data = []float64{1, 2, 3, 4, 4, 5} + +median, _ := stats.Median(data) +fmt.Println(median) // 3.5 + +roundedMedian, _ := stats.Round(median, 0) +fmt.Println(roundedMedian) // 4 +``` + +**Protip:** You can [call methods](https://github.com/montanaflynn/stats/blob/master/examples/methods.go) on the data if using the Float64Data type: + +``` +var d stats.Float64Data = data + +max, _ := d.Max() +fmt.Println(max) // 5 +``` + +## Contributing + +If you have any suggestions, criticism or bug reports please [create an issue](https://github.com/montanaflynn/stats/issues) and I'll do my best to accommodate you. In addition simply starring the repo would show your support for the project and be very much appreciated! + +### Pull Requests + +Pull request are always welcome no matter how big or small. Here's an easy way to do it: + +1. Fork it and clone your fork +2. Create new branch (`git checkout -b some-thing`) +3. Make the desired changes +4. Ensure tests pass (`go test -cover` or `make test`) +5. Commit changes (`git commit -am 'Did something'`) +6. Push branch (`git push origin some-thing`) +7. Submit pull request + +To make things as seamless as possible please also consider the following steps: + +- Update `README.md` to include new public types or functions in the documentation section. +- Update `examples/main.go` with a simple example of the new feature. +- Keep 100% code coverage (you can check with `make coverage`). +- Run [`gometalinter`](https://github.com/alecthomas/gometalinter) and make your code pass. +- Squash needless commits into single units of work with `git rebase -i new-feature`. + +#### Makefile + +I've included a [Makefile](https://github.com/montanaflynn/stats/blob/master/Makefile) that has a lot of helper targets for common actions such as linting, testing, code coverage reporting and more. + +**Protip:** `watch -n 1 make check` will continuously format and test your code. + +## MIT License + +Copyright (c) 2014-2015 Montana Flynn + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORpublicS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +[travis-url]: https://travis-ci.org/montanaflynn/stats +[travis-svg]: https://img.shields.io/travis/montanaflynn/stats.svg + +[coveralls-url]: https://coveralls.io/r/montanaflynn/stats?branch=master +[coveralls-svg]: https://img.shields.io/coveralls/montanaflynn/stats.svg + +[godoc-url]: https://godoc.org/github.com/montanaflynn/stats +[godoc-svg]: https://godoc.org/github.com/montanaflynn/stats?status.svg + +[license-url]: https://github.com/montanaflynn/stats/blob/master/LICENSE +[license-svg]: https://img.shields.io/badge/license-MIT-blue.svg diff --git a/backend/vendor/github.com/montanaflynn/stats/correlation.go b/backend/vendor/github.com/montanaflynn/stats/correlation.go new file mode 100644 index 0000000000..d759bf8c42 --- /dev/null +++ b/backend/vendor/github.com/montanaflynn/stats/correlation.go @@ -0,0 +1,33 @@ +package stats + +import "math" + +// Correlation describes the degree of relationship between two sets of data +func Correlation(data1, data2 Float64Data) (float64, error) { + + l1 := data1.Len() + l2 := data2.Len() + + if l1 == 0 || l2 == 0 { + return math.NaN(), EmptyInput + } + + if l1 != l2 { + return math.NaN(), SizeErr + } + + sdev1, _ := StandardDeviationPopulation(data1) + sdev2, _ := StandardDeviationPopulation(data2) + + if sdev1 == 0 || sdev2 == 0 { + return 0, nil + } + + covp, _ := CovariancePopulation(data1, data2) + return covp / (sdev1 * sdev2), nil +} + +// Pearson calculates the Pearson product-moment correlation coefficient between two variables. +func Pearson(data1, data2 Float64Data) (float64, error) { + return Correlation(data1, data2) +} diff --git a/backend/vendor/github.com/montanaflynn/stats/data.go b/backend/vendor/github.com/montanaflynn/stats/data.go new file mode 100644 index 0000000000..a087f457a0 --- /dev/null +++ b/backend/vendor/github.com/montanaflynn/stats/data.go @@ -0,0 +1,140 @@ +package stats + +// Float64Data is a named type for []float64 with helper methods +type Float64Data []float64 + +// Get item in slice +func (f Float64Data) Get(i int) float64 { return f[i] } + +// Len returns length of slice +func (f Float64Data) Len() int { return len(f) } + +// Less returns if one number is less than another +func (f Float64Data) Less(i, j int) bool { return f[i] < f[j] } + +// Swap switches out two numbers in slice +func (f Float64Data) Swap(i, j int) { f[i], f[j] = f[j], f[i] } + +// Min returns the minimum number in the data +func (f Float64Data) Min() (float64, error) { return Min(f) } + +// Max returns the maximum number in the data +func (f Float64Data) Max() (float64, error) { return Max(f) } + +// Sum returns the total of all the numbers in the data +func (f Float64Data) Sum() (float64, error) { return Sum(f) } + +// Mean returns the mean of the data +func (f Float64Data) Mean() (float64, error) { return Mean(f) } + +// Median returns the median of the data +func (f Float64Data) Median() (float64, error) { return Median(f) } + +// Mode returns the mode of the data +func (f Float64Data) Mode() ([]float64, error) { return Mode(f) } + +// GeometricMean returns the median of the data +func (f Float64Data) GeometricMean() (float64, error) { return GeometricMean(f) } + +// HarmonicMean returns the mode of the data +func (f Float64Data) HarmonicMean() (float64, error) { return HarmonicMean(f) } + +// MedianAbsoluteDeviation the median of the absolute deviations from the dataset median +func (f Float64Data) MedianAbsoluteDeviation() (float64, error) { + return MedianAbsoluteDeviation(f) +} + +// MedianAbsoluteDeviationPopulation finds the median of the absolute deviations from the population median +func (f Float64Data) MedianAbsoluteDeviationPopulation() (float64, error) { + return MedianAbsoluteDeviationPopulation(f) +} + +// StandardDeviation the amount of variation in the dataset +func (f Float64Data) StandardDeviation() (float64, error) { + return StandardDeviation(f) +} + +// StandardDeviationPopulation finds the amount of variation from the population +func (f Float64Data) StandardDeviationPopulation() (float64, error) { + return StandardDeviationPopulation(f) +} + +// StandardDeviationSample finds the amount of variation from a sample +func (f Float64Data) StandardDeviationSample() (float64, error) { + return StandardDeviationSample(f) +} + +// QuartileOutliers finds the mild and extreme outliers +func (f Float64Data) QuartileOutliers() (Outliers, error) { + return QuartileOutliers(f) +} + +// Percentile finds the relative standing in a slice of floats +func (f Float64Data) Percentile(p float64) (float64, error) { + return Percentile(f, p) +} + +// PercentileNearestRank finds the relative standing using the Nearest Rank method +func (f Float64Data) PercentileNearestRank(p float64) (float64, error) { + return PercentileNearestRank(f, p) +} + +// Correlation describes the degree of relationship between two sets of data +func (f Float64Data) Correlation(d Float64Data) (float64, error) { + return Correlation(f, d) +} + +// Pearson calculates the Pearson product-moment correlation coefficient between two variables. +func (f Float64Data) Pearson(d Float64Data) (float64, error) { + return Pearson(f, d) +} + +// Quartile returns the three quartile points from a slice of data +func (f Float64Data) Quartile(d Float64Data) (Quartiles, error) { + return Quartile(d) +} + +// InterQuartileRange finds the range between Q1 and Q3 +func (f Float64Data) InterQuartileRange() (float64, error) { + return InterQuartileRange(f) +} + +// Midhinge finds the average of the first and third quartiles +func (f Float64Data) Midhinge(d Float64Data) (float64, error) { + return Midhinge(d) +} + +// Trimean finds the average of the median and the midhinge +func (f Float64Data) Trimean(d Float64Data) (float64, error) { + return Trimean(d) +} + +// Sample returns sample from input with replacement or without +func (f Float64Data) Sample(n int, r bool) ([]float64, error) { + return Sample(f, n, r) +} + +// Variance the amount of variation in the dataset +func (f Float64Data) Variance() (float64, error) { + return Variance(f) +} + +// PopulationVariance finds the amount of variance within a population +func (f Float64Data) PopulationVariance() (float64, error) { + return PopulationVariance(f) +} + +// SampleVariance finds the amount of variance within a sample +func (f Float64Data) SampleVariance() (float64, error) { + return SampleVariance(f) +} + +// Covariance is a measure of how much two sets of data change +func (f Float64Data) Covariance(d Float64Data) (float64, error) { + return Covariance(f, d) +} + +// CovariancePopulation computes covariance for entire population between two variables. +func (f Float64Data) CovariancePopulation(d Float64Data) (float64, error) { + return CovariancePopulation(f, d) +} diff --git a/backend/vendor/github.com/montanaflynn/stats/data_set_distances.go b/backend/vendor/github.com/montanaflynn/stats/data_set_distances.go new file mode 100644 index 0000000000..2e549c8d49 --- /dev/null +++ b/backend/vendor/github.com/montanaflynn/stats/data_set_distances.go @@ -0,0 +1,94 @@ +package stats + +import ( + "math" +) + +// Validate data for distance calculation +func validateData(dataPointX, dataPointY []float64) error { + if len(dataPointX) == 0 || len(dataPointY) == 0 { + return EmptyInput + } + + if len(dataPointX) != len(dataPointY) { + return SizeErr + } + return nil +} + +// Computes Chebyshev distance between two data sets +func ChebyshevDistance(dataPointX, dataPointY []float64) (distance float64, err error) { + err = validateData(dataPointX, dataPointY) + if err != nil { + return math.NaN(), err + } + var tempDistance float64 + for i := 0; i < len(dataPointY); i++ { + tempDistance = math.Abs(dataPointX[i] - dataPointY[i]) + if distance < tempDistance { + distance = tempDistance + } + } + return distance, nil +} + +// +// Computes Euclidean distance between two data sets +// +func EuclideanDistance(dataPointX, dataPointY []float64) (distance float64, err error) { + + err = validateData(dataPointX, dataPointY) + if err != nil { + return math.NaN(), err + } + distance = 0 + for i := 0; i < len(dataPointX); i++ { + distance = distance + ((dataPointX[i] - dataPointY[i]) * (dataPointX[i] - dataPointY[i])) + } + return math.Sqrt(distance), nil +} + +// +// Computes Manhattan distance between two data sets +// +func ManhattanDistance(dataPointX, dataPointY []float64) (distance float64, err error) { + err = validateData(dataPointX, dataPointY) + if err != nil { + return math.NaN(), err + } + distance = 0 + for i := 0; i < len(dataPointX); i++ { + distance = distance + math.Abs(dataPointX[i]-dataPointY[i]) + } + return distance, nil +} + +// +// Computes minkowski distance between two data sets. +// +// Input: +// dataPointX: First set of data points +// dataPointY: Second set of data points. Length of both data +// sets must be equal. +// lambda: aka p or city blocks; With lambda = 1 +// returned distance is manhattan distance and +// lambda = 2; it is euclidean distance. Lambda +// reaching to infinite - distance would be chebysev +// distance. +// Output: +// Distance or error +// +func MinkowskiDistance(dataPointX, dataPointY []float64, lambda float64) (distance float64, err error) { + err = validateData(dataPointX, dataPointY) + if err != nil { + return math.NaN(), err + } + for i := 0; i < len(dataPointY); i++ { + distance = distance + math.Pow(math.Abs(dataPointX[i]-dataPointY[i]), lambda) + } + distance = math.Pow(distance, float64(1/lambda)) + if math.IsInf(distance, 1) == true { + return math.NaN(), InfValue + } + return distance, nil +} diff --git a/backend/vendor/github.com/montanaflynn/stats/deviation.go b/backend/vendor/github.com/montanaflynn/stats/deviation.go new file mode 100644 index 0000000000..539c02bcfd --- /dev/null +++ b/backend/vendor/github.com/montanaflynn/stats/deviation.go @@ -0,0 +1,57 @@ +package stats + +import "math" + +// MedianAbsoluteDeviation finds the median of the absolute deviations from the dataset median +func MedianAbsoluteDeviation(input Float64Data) (mad float64, err error) { + return MedianAbsoluteDeviationPopulation(input) +} + +// MedianAbsoluteDeviationPopulation finds the median of the absolute deviations from the population median +func MedianAbsoluteDeviationPopulation(input Float64Data) (mad float64, err error) { + if input.Len() == 0 { + return math.NaN(), EmptyInput + } + + i := copyslice(input) + m, _ := Median(i) + + for key, value := range i { + i[key] = math.Abs(value - m) + } + + return Median(i) +} + +// StandardDeviation the amount of variation in the dataset +func StandardDeviation(input Float64Data) (sdev float64, err error) { + return StandardDeviationPopulation(input) +} + +// StandardDeviationPopulation finds the amount of variation from the population +func StandardDeviationPopulation(input Float64Data) (sdev float64, err error) { + + if input.Len() == 0 { + return math.NaN(), EmptyInput + } + + // Get the population variance + vp, _ := PopulationVariance(input) + + // Return the population standard deviation + return math.Pow(vp, 0.5), nil +} + +// StandardDeviationSample finds the amount of variation from a sample +func StandardDeviationSample(input Float64Data) (sdev float64, err error) { + + if input.Len() == 0 { + return math.NaN(), EmptyInput + } + + // Get the sample variance + vs, _ := SampleVariance(input) + + // Return the sample standard deviation + return math.Pow(vs, 0.5), nil +} diff --git a/backend/vendor/github.com/montanaflynn/stats/errors.go b/backend/vendor/github.com/montanaflynn/stats/errors.go new file mode 100644 index 0000000000..0bb32f0dd6 --- /dev/null +++ b/backend/vendor/github.com/montanaflynn/stats/errors.go @@ -0,0 +1,22 @@ +package stats + +type statsErr struct { + err string +} + +func (s statsErr) Error() string { + return s.err +} + +// These are the package-wide error values. +// All error identification should use these values. +var ( + EmptyInput = statsErr{"Input must not be empty."} + SampleSize = statsErr{"Samples number must be less than input length."} + NaNErr = statsErr{"Not a number"} + NegativeErr = statsErr{"Slice must not contain negative values."} + ZeroErr = statsErr{"Slice must not contain zero values."} + BoundsErr = statsErr{"Input is outside of range."} + SizeErr = statsErr{"Slices must be the same length."} + InfValue = statsErr{"Value is infinite."} +) diff --git a/backend/vendor/github.com/montanaflynn/stats/legacy.go b/backend/vendor/github.com/montanaflynn/stats/legacy.go new file mode 100644 index 0000000000..17557abd99 --- /dev/null +++ b/backend/vendor/github.com/montanaflynn/stats/legacy.go @@ -0,0 +1,36 @@ +package stats + +// VarP is a shortcut to PopulationVariance +func VarP(input Float64Data) (sdev float64, err error) { + return PopulationVariance(input) +} + +// VarS is a shortcut to SampleVariance +func VarS(input Float64Data) (sdev float64, err error) { + return SampleVariance(input) +} + +// StdDevP is a shortcut to StandardDeviationPopulation +func StdDevP(input Float64Data) (sdev float64, err error) { + return StandardDeviationPopulation(input) +} + +// StdDevS is a shortcut to StandardDeviationSample +func StdDevS(input Float64Data) (sdev float64, err error) { + return StandardDeviationSample(input) +} + +// LinReg is a shortcut to LinearRegression +func LinReg(s []Coordinate) (regressions []Coordinate, err error) { + return LinearRegression(s) +} + +// ExpReg is a shortcut to ExponentialRegression +func ExpReg(s []Coordinate) (regressions []Coordinate, err error) { + return ExponentialRegression(s) +} + +// LogReg is a shortcut to LogarithmicRegression +func LogReg(s []Coordinate) (regressions []Coordinate, err error) { + return LogarithmicRegression(s) +} diff --git a/backend/vendor/github.com/montanaflynn/stats/load.go b/backend/vendor/github.com/montanaflynn/stats/load.go new file mode 100644 index 0000000000..1012d0bb54 --- /dev/null +++ b/backend/vendor/github.com/montanaflynn/stats/load.go @@ -0,0 +1,184 @@ +package stats + +import ( + "strconv" + "time" +) + +// LoadRawData parses and converts a slice of mixed data types to floats +func LoadRawData(raw interface{}) (f Float64Data) { + var r []interface{} + var s Float64Data + + switch t := raw.(type) { + case []interface{}: + r = t + case []uint: + for _, v := range t { + s = append(s, float64(v)) + } + return s + case []uint8: + for _, v := range t { + s = append(s, float64(v)) + } + return s + case []uint16: + for _, v := range t { + s = append(s, float64(v)) + } + return s + case []uint32: + for _, v := range t { + s = append(s, float64(v)) + } + return s + case []uint64: + for _, v := range t { + s = append(s, float64(v)) + } + return s + case []bool: + for _, v := range t { + if v == true { + s = append(s, 1.0) + } else { + s = append(s, 0.0) + } + } + return s + case []float64: + return Float64Data(t) + case []int: + for _, v := range t { + s = append(s, float64(v)) + } + return s + case []int8: + for _, v := range t { + s = append(s, float64(v)) + } + return s + case []int16: + for _, v := range t { + s = append(s, float64(v)) + } + return s + case []int32: + for _, v := range t { + s = append(s, float64(v)) + } + return s + case []int64: + for _, v := range t { + s = append(s, float64(v)) + } + return s + case []string: + for _, v := range t { + r = append(r, v) + } + case []time.Duration: + for _, v := range t { + r = append(r, v) + } + case map[int]int: + for i := 0; i < len(t); i++ { + s = append(s, float64(t[i])) + } + return s + case map[int]int8: + for i := 0; i < len(t); i++ { + s = append(s, float64(t[i])) + } + return s + case map[int]int16: + for i := 0; i < len(t); i++ { + s = append(s, float64(t[i])) + } + return s + case map[int]int32: + for i := 0; i < len(t); i++ { + s = append(s, float64(t[i])) + } + return s + case map[int]int64: + for i := 0; i < len(t); i++ { + s = append(s, float64(t[i])) + } + return s + case map[int]string: + for i := 0; i < len(t); i++ { + r = append(r, t[i]) + } + case map[int]uint: + for i := 0; i < len(t); i++ { + s = append(s, float64(t[i])) + } + return s + case map[int]uint8: + for i := 0; i < len(t); i++ { + s = append(s, float64(t[i])) + } + return s + case map[int]uint16: + for i := 0; i < len(t); i++ { + s = append(s, float64(t[i])) + } + return s + case map[int]uint32: + for i := 0; i < len(t); i++ { + s = append(s, float64(t[i])) + } + return s + case map[int]uint64: + for i := 0; i < len(t); i++ { + s = append(s, float64(t[i])) + } + return s + case map[int]bool: + for i := 0; i < len(t); i++ { + if t[i] == true { + s = append(s, 1.0) + } else { + s = append(s, 0.0) + } + } + return s + case map[int]float64: + for i := 0; i < len(t); i++ { + s = append(s, t[i]) + } + return s + case map[int]time.Duration: + for i := 0; i < len(t); i++ { + r = append(r, t[i]) + } + } + + for _, v := range r { + switch t := v.(type) { + case int: + a := float64(t) + f = append(f, a) + case uint: + f = append(f, float64(t)) + case float64: + f = append(f, t) + case string: + fl, err := strconv.ParseFloat(t, 64) + if err == nil { + f = append(f, fl) + } + case bool: + if t == true { + f = append(f, 1.0) + } else { + f = append(f, 0.0) + } + case time.Duration: + f = append(f, float64(t)) + } + } + return f +} diff --git a/backend/vendor/github.com/montanaflynn/stats/max.go b/backend/vendor/github.com/montanaflynn/stats/max.go new file mode 100644 index 0000000000..d0fdd42b48 --- /dev/null +++ b/backend/vendor/github.com/montanaflynn/stats/max.go @@ -0,0 +1,24 @@ +package stats + +import "math" + +// Max finds the highest number in a slice +func Max(input Float64Data) (max float64, err error) { + + // Return an error if there are no numbers + if input.Len() == 0 { + return math.NaN(), EmptyInput + } + + // Get the first value as the starting point + max = input.Get(0) + + // Loop and replace higher values + for i := 1; i < input.Len(); i++ { + if input.Get(i) > max { + max = input.Get(i) + } + } + + return max, nil +} diff --git a/backend/vendor/github.com/montanaflynn/stats/mean.go b/backend/vendor/github.com/montanaflynn/stats/mean.go new file mode 100644 index 0000000000..944bb65721 --- /dev/null +++ b/backend/vendor/github.com/montanaflynn/stats/mean.go @@ -0,0 +1,60 @@ +package stats + +import "math" + +// Mean gets the average of a slice of numbers +func Mean(input Float64Data) (float64, error) { + + if input.Len() == 0 { + return math.NaN(), EmptyInput + } + + sum, _ := input.Sum() + + return sum / float64(input.Len()), nil +} + +// GeometricMean gets the geometric mean for a slice of numbers +func GeometricMean(input Float64Data) (float64, error) { + + l := input.Len() + if l == 0 { + return math.NaN(), EmptyInput + } + + // Get the product of all the numbers + var p float64 + for _, n := range input { + if p == 0 { + p = n + } else { + p *= n + } + } + + // Calculate the geometric mean + return math.Pow(p, 1/float64(l)), nil +} + +// HarmonicMean gets the harmonic mean for a slice of numbers +func HarmonicMean(input Float64Data) (float64, error) { + + l := input.Len() + if l == 0 { + return math.NaN(), EmptyInput + } + + // Get the sum of all the numbers reciprocals and return an + // error for values that cannot be included in harmonic mean + var p float64 + for _, n := range input { + if n < 0 { + return math.NaN(), NegativeErr + } else if n == 0 { + return math.NaN(), ZeroErr + } + p += (1 / n) + } + + return float64(l) / p, nil +} diff --git a/backend/vendor/github.com/montanaflynn/stats/median.go b/backend/vendor/github.com/montanaflynn/stats/median.go new file mode 100644 index 0000000000..b13d8394bb --- /dev/null +++ b/backend/vendor/github.com/montanaflynn/stats/median.go @@ -0,0 +1,25 @@ +package stats + +import "math" + +// Median gets the median number in a slice of numbers +func Median(input Float64Data) (median float64, err error) { + + // Start by sorting a copy of the slice + c := sortedCopy(input) + + // No math is needed if there are no numbers + // For even numbers we add the two middle numbers + // and divide by two using the mean function above + // For odd numbers we just use the middle number + l := len(c) + if l == 0 { + return math.NaN(), EmptyInput + } else if l%2 == 0 { + median, _ = Mean(c[l/2-1 : l/2+1]) + } else { + median = float64(c[l/2]) + } + + return median, nil +} diff --git a/backend/vendor/github.com/montanaflynn/stats/min.go b/backend/vendor/github.com/montanaflynn/stats/min.go new file mode 100644 index 0000000000..4383852e15 --- /dev/null +++ b/backend/vendor/github.com/montanaflynn/stats/min.go @@ -0,0 +1,26 @@ +package stats + +import "math" + +// Min finds the lowest number in a set of data +func Min(input Float64Data) (min float64, err error) { + + // Get the count of numbers in the slice + l := input.Len() + + // Return an error if there are no numbers + if l == 0 { + return math.NaN(), EmptyInput + } + + // Get the first value as the starting point + min = input.Get(0) + + // Iterate until done checking for a lower value + for i := 1; i < l; i++ { + if input.Get(i) < min { + min = input.Get(i) + } + } + return min, nil +} diff --git a/backend/vendor/github.com/montanaflynn/stats/mode.go b/backend/vendor/github.com/montanaflynn/stats/mode.go new file mode 100644 index 0000000000..1160faf285 --- /dev/null +++ b/backend/vendor/github.com/montanaflynn/stats/mode.go @@ -0,0 +1,47 @@ +package stats + +// Mode gets the mode [most frequent value(s)] of a slice of float64s +func Mode(input Float64Data) (mode []float64, err error) { + // Return the input if there's only one number + l := input.Len() + if l == 1 { + return input, nil + } else if l == 0 { + return nil, EmptyInput + } + + c := sortedCopyDif(input) + // Traverse sorted array, + // tracking the longest repeating sequence + mode = make([]float64, 5) + cnt, maxCnt := 1, 1 + for i := 1; i < l; i++ { + switch { + case c[i] == c[i-1]: + cnt++ + case cnt == maxCnt && maxCnt != 1: + mode = append(mode, c[i-1]) + cnt = 1 + case cnt > maxCnt: + mode = append(mode[:0], c[i-1]) + maxCnt, cnt = cnt, 1 + default: + cnt = 1 + } + } + switch { + case cnt == maxCnt: + mode = append(mode, c[l-1]) + case cnt > maxCnt: + mode = append(mode[:0], c[l-1]) + maxCnt = cnt + } + + // Since length must be greater than 1, + // check for slices of distinct values + if maxCnt == 1 { + return Float64Data{}, nil + } + + return mode, nil +} diff --git a/backend/vendor/github.com/montanaflynn/stats/outlier.go b/backend/vendor/github.com/montanaflynn/stats/outlier.go new file mode 100644 index 0000000000..e969180ea7 --- /dev/null +++ b/backend/vendor/github.com/montanaflynn/stats/outlier.go @@ -0,0 +1,44 @@ +package stats + +// Outliers holds mild and extreme outliers found in data +type Outliers struct { + Mild Float64Data + Extreme Float64Data +} + +// QuartileOutliers finds the mild and extreme outliers +func QuartileOutliers(input Float64Data) (Outliers, error) { + if input.Len() == 0 { + return Outliers{}, EmptyInput + } + + // Start by sorting a copy of the slice + copy := sortedCopy(input) + + // Calculate the quartiles and interquartile range + qs, _ := Quartile(copy) + iqr, _ := InterQuartileRange(copy) + + // Calculate the lower and upper inner and outer fences + lif := qs.Q1 - (1.5 * iqr) + uif := qs.Q3 + (1.5 * iqr) + lof := qs.Q1 - (3 * iqr) + uof := qs.Q3 + (3 * iqr) + + // Find the data points that are outside of the + // inner and upper fences and add them to mild + // and extreme outlier slices + var mild Float64Data + var extreme Float64Data + for _, v := range copy { + + if v < lof || v > uof { + extreme = append(extreme, v) + } else if v < lif || v > uif { + mild = append(mild, v) + } + } + + // Wrap them into our struct + return Outliers{mild, extreme}, nil +} diff --git a/backend/vendor/github.com/montanaflynn/stats/percentile.go b/backend/vendor/github.com/montanaflynn/stats/percentile.go new file mode 100644 index 0000000000..baf24d8e36 --- /dev/null +++ b/backend/vendor/github.com/montanaflynn/stats/percentile.go @@ -0,0 +1,80 @@ +package stats + +import "math" + +// Percentile finds the relative standing in a slice of floats +func Percentile(input Float64Data, percent float64) (percentile float64, err error) { + + if input.Len() == 0 { + return math.NaN(), EmptyInput + } + + if percent <= 0 || percent > 100 { + return math.NaN(), BoundsErr + } + + // Start by sorting a copy of the slice + c := sortedCopy(input) + + // Multiply percent by length of input + index := (percent / 100) * float64(len(c)) + + // Check if the index is a whole number + if index == float64(int64(index)) { + + // Convert float to int + i := int(index) + + // Find the value at the index + percentile = c[i-1] + + } else if index > 1 { + + // Convert float to int via truncation + i := int(index) + + // Find the average of the index and following values + percentile, _ = Mean(Float64Data{c[i-1], c[i]}) + + } else { + return math.NaN(), BoundsErr + } + + return percentile, nil + +} + +// PercentileNearestRank finds the relative standing in a slice of floats using the Nearest Rank method +func PercentileNearestRank(input Float64Data, percent float64) (percentile float64, err error) { + + // Find the length of items in the slice + il := input.Len() + + // Return an error for empty slices + if il == 0 { + return math.NaN(), EmptyInput + } + + // Return error for less than 0 or greater than 100 percentages + if percent < 0 || percent > 100 { + return math.NaN(), BoundsErr + } + + // Start by sorting a copy of the slice + c := sortedCopy(input) + + // Return the last item + if percent == 100.0 { + return c[il-1], nil + } + + // Find ordinal ranking + or := int(math.Ceil(float64(il) * percent / 100)) + + // Return the item that is in the place of the ordinal rank + if or == 0 { + return c[0], nil + } + return c[or-1], nil + +} diff --git a/backend/vendor/github.com/montanaflynn/stats/quartile.go b/backend/vendor/github.com/montanaflynn/stats/quartile.go new file mode 100644 index 0000000000..29bb3a37a3 --- /dev/null +++ b/backend/vendor/github.com/montanaflynn/stats/quartile.go @@ -0,0 +1,74 @@ +package stats + +import "math" + +// Quartiles holds the three quartile points +type Quartiles struct { + Q1 float64 + Q2 float64 + Q3 float64 +} + +// Quartile returns the three quartile points from a slice of data +func Quartile(input Float64Data) (Quartiles, error) { + + il := input.Len() + if il == 0 { + return Quartiles{}, EmptyInput + } + + // Start by sorting a copy of the slice + copy := sortedCopy(input) + + // Find the cutoff places depeding on if + // the input slice length is even or odd + var c1 int + var c2 int + if il%2 == 0 { + c1 = il / 2 + c2 = il / 2 + } else { + c1 = (il - 1) / 2 + c2 = c1 + 1 + } + + // Find the Medians with the cutoff points + Q1, _ := Median(copy[:c1]) + Q2, _ := Median(copy) + Q3, _ := Median(copy[c2:]) + + return Quartiles{Q1, Q2, Q3}, nil + +} + +// InterQuartileRange finds the range between Q1 and Q3 +func InterQuartileRange(input Float64Data) (float64, error) { + if input.Len() == 0 { + return math.NaN(), EmptyInput + } + qs, _ := Quartile(input) + iqr := qs.Q3 - qs.Q1 + return iqr, nil +} + +// Midhinge finds the average of the first and third quartiles +func Midhinge(input Float64Data) (float64, error) { + if input.Len() == 0 { + return math.NaN(), EmptyInput + } + qs, _ := Quartile(input) + mh := (qs.Q1 + qs.Q3) / 2 + return mh, nil +} + +// Trimean finds the average of the median and the midhinge +func Trimean(input Float64Data) (float64, error) { + if input.Len() == 0 { + return math.NaN(), EmptyInput + } + + c := sortedCopy(input) + q, _ := Quartile(c) + + return (q.Q1 + (q.Q2 * 2) + q.Q3) / 4, nil +} diff --git a/backend/vendor/github.com/montanaflynn/stats/regression.go b/backend/vendor/github.com/montanaflynn/stats/regression.go new file mode 100644 index 0000000000..a37a740609 --- /dev/null +++ b/backend/vendor/github.com/montanaflynn/stats/regression.go @@ -0,0 +1,113 @@ +package stats + +import "math" + +// Series is a container for a series of data +type Series []Coordinate + +// Coordinate holds the data in a series +type Coordinate struct { + X, Y float64 +} + +// LinearRegression finds the least squares linear regression on data series +func LinearRegression(s Series) (regressions Series, err error) { + + if len(s) == 0 { + return nil, EmptyInput + } + + // Placeholder for the math to be done + var sum [5]float64 + + // Loop over data keeping index in place + i := 0 + for ; i < len(s); i++ { + sum[0] += s[i].X + sum[1] += s[i].Y + sum[2] += s[i].X * s[i].X + sum[3] += s[i].X * s[i].Y + sum[4] += s[i].Y * s[i].Y + } + + // Find gradient and intercept + f := float64(i) + gradient := (f*sum[3] - sum[0]*sum[1]) / (f*sum[2] - sum[0]*sum[0]) + intercept := (sum[1] / f) - (gradient * sum[0] / f) + + // Create the new regression series + for j := 0; j < len(s); j++ { + regressions = append(regressions, Coordinate{ + X: s[j].X, + Y: s[j].X*gradient + intercept, + }) + } + + return regressions, nil + +} + +// ExponentialRegression returns an exponential regression on data series +func ExponentialRegression(s Series) (regressions Series, err error) { + + if len(s) == 0 { + return nil, EmptyInput + } + + var sum [6]float64 + + for i := 0; i < len(s); i++ { + sum[0] += s[i].X + sum[1] += s[i].Y + sum[2] += s[i].X * s[i].X * s[i].Y + sum[3] += s[i].Y * math.Log(s[i].Y) + sum[4] += s[i].X * s[i].Y * math.Log(s[i].Y) + sum[5] += s[i].X * s[i].Y + } + + denominator := (sum[1]*sum[2] - sum[5]*sum[5]) + a := math.Pow(math.E, (sum[2]*sum[3]-sum[5]*sum[4])/denominator) + b := (sum[1]*sum[4] - sum[5]*sum[3]) / denominator + + for j := 0; j < len(s); j++ { + regressions = append(regressions, Coordinate{ + X: s[j].X, + Y: a * math.Exp(b*s[j].X), + }) + } + + return regressions, nil + +} + +// LogarithmicRegression returns an logarithmic regression on data series +func LogarithmicRegression(s Series) (regressions Series, err error) { + + if len(s) == 0 { + return nil, EmptyInput + } + + var sum [4]float64 + + i := 0 + for ; i < len(s); i++ { + sum[0] += math.Log(s[i].X) + sum[1] += s[i].Y * math.Log(s[i].X) + sum[2] += s[i].Y + sum[3] += math.Pow(math.Log(s[i].X), 2) + } + + f := float64(i) + a := (f*sum[1] - sum[2]*sum[0]) / (f*sum[3] - sum[0]*sum[0]) + b := (sum[2] - a*sum[0]) / f + + for j := 0; j < len(s); j++ { + regressions = append(regressions, Coordinate{ + X: s[j].X, + Y: b + a*math.Log(s[j].X), + }) + } + + return regressions, nil + +} diff --git a/backend/vendor/github.com/montanaflynn/stats/round.go b/backend/vendor/github.com/montanaflynn/stats/round.go new file mode 100644 index 0000000000..b66779c9fc --- /dev/null +++ b/backend/vendor/github.com/montanaflynn/stats/round.go @@ -0,0 +1,38 @@ +package stats + +import "math" + +// Round a float to a specific decimal place or precision +func Round(input float64, places int) (rounded float64, err error) { + + // If the float is not a number + if math.IsNaN(input) { + return math.NaN(), NaNErr + } + + // Find out the actual sign and correct the input for later + sign := 1.0 + if input < 0 { + sign = -1 + input *= -1 + } + + // Use the places arg to get the amount of precision wanted + precision := math.Pow(10, float64(places)) + + // Find the decimal place we are looking to round + digit := input * precision + + // Get the actual decimal number as a fraction to be compared + _, decimal := math.Modf(digit) + + // If the decimal is less than .5 we round down otherwise up + if decimal >= 0.5 { + rounded = math.Ceil(digit) + } else { + rounded = math.Floor(digit) + } + + // Finally we do the math to actually create a rounded number + return rounded / precision * sign, nil +} diff --git a/backend/vendor/github.com/montanaflynn/stats/sample.go b/backend/vendor/github.com/montanaflynn/stats/sample.go new file mode 100644 index 0000000000..a52f6dcaaf --- /dev/null +++ b/backend/vendor/github.com/montanaflynn/stats/sample.go @@ -0,0 +1,44 @@ +package stats + +import "math/rand" + +// Sample returns sample from input with replacement or without +func Sample(input Float64Data, takenum int, replacement bool) ([]float64, error) { + + if input.Len() == 0 { + return nil, EmptyInput + } + + length := input.Len() + if replacement { + + result := Float64Data{} + rand.Seed(unixnano()) + + // In every step, randomly take the num for + for i := 0; i < takenum; i++ { + idx := rand.Intn(length) + result = append(result, input[idx]) + } + + return result, nil + + } else if !replacement && takenum <= length { + + rand.Seed(unixnano()) + + // Get permutation of number of indexies + perm := rand.Perm(length) + result := Float64Data{} + + // Get element of input by permutated index + for _, idx := range perm[0:takenum] { + result = append(result, input[idx]) + } + + return result, nil + + } + + return nil, BoundsErr +} diff --git a/backend/vendor/github.com/montanaflynn/stats/sum.go b/backend/vendor/github.com/montanaflynn/stats/sum.go new file mode 100644 index 0000000000..53485f17c2 --- /dev/null +++ b/backend/vendor/github.com/montanaflynn/stats/sum.go @@ -0,0 +1,18 @@ +package stats + +import "math" + +// Sum adds all the numbers of a slice together +func Sum(input Float64Data) (sum float64, err error) { + + if input.Len() == 0 { + return math.NaN(), EmptyInput + } + + // Add em up + for _, n := range input { + sum += n + } + + return sum, nil +} diff --git a/backend/vendor/github.com/montanaflynn/stats/util.go b/backend/vendor/github.com/montanaflynn/stats/util.go new file mode 100644 index 0000000000..881997604d --- /dev/null +++ b/backend/vendor/github.com/montanaflynn/stats/util.go @@ -0,0 +1,43 @@ +package stats + +import ( + "sort" + "time" +) + +// float64ToInt rounds a float64 to an int +func float64ToInt(input float64) (output int) { + r, _ := Round(input, 0) + return int(r) +} + +// unixnano returns nanoseconds from UTC epoch +func unixnano() int64 { + return time.Now().UTC().UnixNano() +} + +// copyslice copies a slice of float64s +func copyslice(input Float64Data) Float64Data { + s := make(Float64Data, input.Len()) + copy(s, input) + return s +} + +// sortedCopy returns a sorted copy of float64s +func sortedCopy(input Float64Data) (copy Float64Data) { + copy = copyslice(input) + sort.Float64s(copy) + return +} + +// sortedCopyDif returns a sorted copy of float64s +// only if the original data isn't sorted. +// Only use this if returned slice won't be manipulated! +func sortedCopyDif(input Float64Data) (copy Float64Data) { + if sort.Float64sAreSorted(input) { + return input + } + copy = copyslice(input) + sort.Float64s(copy) + return +} diff --git a/backend/vendor/github.com/montanaflynn/stats/variance.go b/backend/vendor/github.com/montanaflynn/stats/variance.go new file mode 100644 index 0000000000..66e60c941f --- /dev/null +++ b/backend/vendor/github.com/montanaflynn/stats/variance.go @@ -0,0 +1,105 @@ +package stats + +import "math" + +// _variance finds the variance for both population and sample data +func _variance(input Float64Data, sample int) (variance float64, err error) { + + if input.Len() == 0 { + return math.NaN(), EmptyInput + } + + // Sum the square of the mean subtracted from each number + m, _ := Mean(input) + + for _, n := range input { + variance += (float64(n) - m) * (float64(n) - m) + } + + // When getting the mean of the squared differences + // "sample" will allow us to know if it's a sample + // or population and wether to subtract by one or not + return variance / float64((input.Len() - (1 * sample))), nil +} + +// Variance the amount of variation in the dataset +func Variance(input Float64Data) (sdev float64, err error) { + return PopulationVariance(input) +} + +// PopulationVariance finds the amount of variance within a population +func PopulationVariance(input Float64Data) (pvar float64, err error) { + + v, err := _variance(input, 0) + if err != nil { + return math.NaN(), err + } + + return v, nil +} + +// SampleVariance finds the amount of variance within a sample +func SampleVariance(input Float64Data) (svar float64, err error) { + + v, err := _variance(input, 1) + if err != nil { + return math.NaN(), err + } + + return v, nil +} + +// Covariance is a measure of how much two sets of data change +func Covariance(data1, data2 Float64Data) (float64, error) { + + l1 := data1.Len() + l2 := data2.Len() + + if l1 == 0 || l2 == 0 { + return math.NaN(), EmptyInput + } + + if l1 != l2 { + return math.NaN(), SizeErr + } + + m1, _ := Mean(data1) + m2, _ := Mean(data2) + + // Calculate sum of squares + var ss float64 + for i := 0; i < l1; i++ { + delta1 := (data1.Get(i) - m1) + delta2 := (data2.Get(i) - m2) + ss += (delta1*delta2 - ss) / float64(i+1) + } + + return ss * float64(l1) / float64(l1-1), nil +} + +// CovariancePopulation computes covariance for entire population between two variables. +func CovariancePopulation(data1, data2 Float64Data) (float64, error) { + + l1 := data1.Len() + l2 := data2.Len() + + if l1 == 0 || l2 == 0 { + return math.NaN(), EmptyInput + } + + if l1 != l2 { + return math.NaN(), SizeErr + } + + m1, _ := Mean(data1) + m2, _ := Mean(data2) + + var s float64 + for i := 0; i < l1; i++ { + delta1 := (data1.Get(i) - m1) + delta2 := (data2.Get(i) - m2) + s += delta1 * delta2 + } + + return s / float64(l1), nil +} diff --git a/backend/vendor/github.com/slack-go/slack/README.md b/backend/vendor/github.com/slack-go/slack/README.md index 39b04ce83a..9618aebc37 100644 --- a/backend/vendor/github.com/slack-go/slack/README.md +++ b/backend/vendor/github.com/slack-go/slack/README.md @@ -39,7 +39,7 @@ func main() { // If you set debugging, it will log all requests to the console // Useful when encountering issues // slack.New("YOUR_TOKEN_HERE", slack.OptionDebug(true)) - groups, err := api.GetUserGroups(false) + groups, err := api.GetUserGroups(slack.GetUserGroupsOptionIncludeUsers(false)) if err != nil { fmt.Printf("%s\n", err) return @@ -86,7 +86,13 @@ See https://github.com/slack-go/slack/blob/master/examples/websocket/websocket.g See https://github.com/slack-go/slack/blob/master/examples/eventsapi/events.go +## Socketmode Event Handler (Experimental) +When using socket mode, dealing with an event can be pretty lengthy as it requires you to route the event to the right place. + +Instead, you can use `SocketmodeHandler` much like you use an HTTP handler to register which event you would like to listen to and what callback function will process that event when it occurs. + +See [./examples/socketmode_handler/socketmode_handler.go](./examples/socketmode_handler/socketmode_handler.go) ## Contributing You are more than welcome to contribute to this project. Fork and diff --git a/backend/vendor/github.com/slack-go/slack/block_input.go b/backend/vendor/github.com/slack-go/slack/block_input.go index 087571af49..78ffcdb813 100644 --- a/backend/vendor/github.com/slack-go/slack/block_input.go +++ b/backend/vendor/github.com/slack-go/slack/block_input.go @@ -19,11 +19,12 @@ func (s InputBlock) BlockType() MessageBlockType { } // NewInputBlock returns a new instance of an input block -func NewInputBlock(blockID string, label *TextBlockObject, element BlockElement) *InputBlock { +func NewInputBlock(blockID string, label, hint *TextBlockObject, element BlockElement) *InputBlock { return &InputBlock{ Type: MBTInput, BlockID: blockID, Label: label, Element: element, + Hint: hint, } } diff --git a/backend/vendor/github.com/slack-go/slack/bookmarks.go b/backend/vendor/github.com/slack-go/slack/bookmarks.go new file mode 100644 index 0000000000..78753507b2 --- /dev/null +++ b/backend/vendor/github.com/slack-go/slack/bookmarks.go @@ -0,0 +1,159 @@ +package slack + +import ( + "context" + "net/url" +) + +type Bookmark struct { + ID string `json:"id"` + ChannelID string `json:"channel_id"` + Title string `json:"title"` + Link string `json:"link"` + Emoji string `json:"emoji"` + IconURL string `json:"icon_url"` + Type string `json:"type"` + Created JSONTime `json:"date_created"` + Updated JSONTime `json:"date_updated"` + Rank string `json:"rank"` + + LastUpdatedByUserID string `json:"last_updated_by_user_id"` + LastUpdatedByTeamID string `json:"last_updated_by_team_id"` + + ShortcutID string `json:"shortcut_id"` + EntityID string `json:"entity_id"` + AppID string `json:"app_id"` +} + +type AddBookmarkParameters struct { + Title string // A required title for the bookmark + Type string // A required type for the bookmark + Link string // URL required for type:link + Emoji string // An optional emoji + EntityID string + ParentID string +} + +type EditBookmarkParameters struct { + Title *string // Change the title. Set to "" to clear + Emoji *string // Change the emoji. Set to "" to clear + Link string // Change the link +} + +type addBookmarkResponse struct { + Bookmark Bookmark `json:"bookmark"` + SlackResponse +} + +type editBookmarkResponse struct { + Bookmark Bookmark `json:"bookmark"` + SlackResponse +} + +type listBookmarksResponse struct { + Bookmarks []Bookmark `json:"bookmarks"` + SlackResponse +} + +// AddBookmark adds a bookmark in a channel +func (api *Client) AddBookmark(channelID string, params AddBookmarkParameters) (Bookmark, error) { + return api.AddBookmarkContext(context.Background(), channelID, params) +} + +// AddBookmarkContext adds a bookmark in a channel with a custom context +func (api *Client) AddBookmarkContext(ctx context.Context, channelID string, params AddBookmarkParameters) (Bookmark, error) { + values := url.Values{ + "channel_id": {channelID}, + "token": {api.token}, + "title": {params.Title}, + "type": {params.Type}, + } + if params.Link != "" { + values.Set("link", params.Link) + } + if params.Emoji != "" { + values.Set("emoji", params.Emoji) + } + if params.EntityID != "" { + values.Set("entity_id", params.EntityID) + } + if params.ParentID != "" { + values.Set("parent_id", params.ParentID) + } + + response := &addBookmarkResponse{} + if err := api.postMethod(ctx, "bookmarks.add", values, response); err != nil { + return Bookmark{}, err + } + + return response.Bookmark, response.Err() +} + +// RemoveBookmark removes a bookmark from a channel +func (api *Client) RemoveBookmark(channelID, bookmarkID string) error { + return api.RemoveBookmarkContext(context.Background(), channelID, bookmarkID) +} + +// RemoveBookmarkContext removes a bookmark from a channel with a custom context +func (api *Client) RemoveBookmarkContext(ctx context.Context, channelID, bookmarkID string) error { + values := url.Values{ + "channel_id": {channelID}, + "token": {api.token}, + "bookmark_id": {bookmarkID}, + } + + response := &SlackResponse{} + if err := api.postMethod(ctx, "bookmarks.remove", values, response); err != nil { + return err + } + + return response.Err() +} + +// ListBookmarks returns all bookmarks for a channel. +func (api *Client) ListBookmarks(channelID string) ([]Bookmark, error) { + return api.ListBookmarksContext(context.Background(), channelID) +} + +// ListBookmarksContext returns all bookmarks for a channel with a custom context. +func (api *Client) ListBookmarksContext(ctx context.Context, channelID string) ([]Bookmark, error) { + values := url.Values{ + "channel_id": {channelID}, + "token": {api.token}, + } + + response := &listBookmarksResponse{} + err := api.postMethod(ctx, "bookmarks.list", values, response) + if err != nil { + return nil, err + } + return response.Bookmarks, response.Err() +} + +func (api *Client) EditBookmark(channelID, bookmarkID string, params EditBookmarkParameters) (Bookmark, error) { + return api.EditBookmarkContext(context.Background(), channelID, bookmarkID, params) +} + +func (api *Client) EditBookmarkContext(ctx context.Context, channelID, bookmarkID string, params EditBookmarkParameters) (Bookmark, error) { + values := url.Values{ + "channel_id": {channelID}, + "token": {api.token}, + "bookmark_id": {bookmarkID}, + } + if params.Link != "" { + values.Set("link", params.Link) + } + if params.Emoji != nil { + values.Set("emoji", *params.Emoji) + } + if params.Title != nil { + values.Set("title", *params.Title) + } + + response := &editBookmarkResponse{} + if err := api.postMethod(ctx, "bookmarks.edit", values, response); err != nil { + return Bookmark{}, err + } + + return response.Bookmark, response.Err() +} diff --git a/backend/vendor/github.com/slack-go/slack/chat.go b/backend/vendor/github.com/slack-go/slack/chat.go index 34848d1516..4448e9f409 100644 --- a/backend/vendor/github.com/slack-go/slack/chat.go +++ b/backend/vendor/github.com/slack-go/slack/chat.go @@ -64,6 +64,9 @@ type PostMessageParameters struct { // chat.postEphemeral support Channel string `json:"channel"` User string `json:"user"` + + // chat metadata support + MetaData SlackMetadata `json:"metadata"` } // NewPostMessageParameters provides an instance of PostMessageParameters with all the sane default values set @@ -285,6 +288,7 @@ type sendConfig struct { endpoint string values url.Values attachments []Attachment + metadata SlackMetadata blocks Blocks responseType string replaceOriginal bool @@ -306,6 +310,7 @@ func (t sendConfig) BuildRequestContext(ctx context.Context, token, channelID st endpoint: t.endpoint, values: t.values, attachments: t.attachments, + metadata: t.metadata, blocks: t.blocks, responseType: t.responseType, replaceOriginal: t.replaceOriginal, @@ -336,6 +341,7 @@ type responseURLSender struct { endpoint string values url.Values attachments []Attachment + metadata SlackMetadata blocks Blocks responseType string replaceOriginal bool @@ -352,6 +358,7 @@ func (t responseURLSender) BuildRequestContext(ctx context.Context) (*http.Reque Timestamp: t.values.Get("ts"), Attachments: t.attachments, Blocks: t.blocks, + Metadata: t.metadata, ResponseType: t.responseType, ReplaceOriginal: t.replaceOriginal, DeleteOriginal: t.deleteOriginal, @@ -662,6 +669,18 @@ func MsgOptionIconEmoji(iconEmoji string) MsgOption { } } +// MsgOptionMetadata sets message metadata +func MsgOptionMetadata(metadata SlackMetadata) MsgOption { + return func(config *sendConfig) error { + config.metadata = metadata + meta, err := json.Marshal(metadata) + if err == nil { + config.values.Set("metadata", string(meta)) + } + return err + } +} + // UnsafeMsgOptionEndpoint deliver the message to the specified endpoint. // NOTE: USE AT YOUR OWN RISK: No issues relating to the use of this Option // will be supported by the library, it is subject to change without notice that diff --git a/backend/vendor/github.com/slack-go/slack/conversation.go b/backend/vendor/github.com/slack-go/slack/conversation.go index 2993626013..e523716cc8 100644 --- a/backend/vendor/github.com/slack-go/slack/conversation.go +++ b/backend/vendor/github.com/slack-go/slack/conversation.go @@ -571,12 +571,13 @@ func (api *Client) JoinConversationContext(ctx context.Context, channelID string } type GetConversationHistoryParameters struct { - ChannelID string - Cursor string - Inclusive bool - Latest string - Limit int - Oldest string + ChannelID string + Cursor string + Inclusive bool + Latest string + Limit int + Oldest string + IncludeAllMetadata bool } type GetConversationHistoryResponse struct { @@ -615,6 +616,11 @@ func (api *Client) GetConversationHistoryContext(ctx context.Context, params *Ge if params.Oldest != "" { values.Add("oldest", params.Oldest) } + if params.IncludeAllMetadata { + values.Add("include_all_metadata", "1") + } else { + values.Add("include_all_metadata", "0") + } response := GetConversationHistoryResponse{} diff --git a/backend/vendor/github.com/slack-go/slack/dialog_text.go b/backend/vendor/github.com/slack-go/slack/dialog_text.go index da06bd6de8..25fa1b693e 100644 --- a/backend/vendor/github.com/slack-go/slack/dialog_text.go +++ b/backend/vendor/github.com/slack-go/slack/dialog_text.go @@ -18,7 +18,7 @@ const ( ) // TextInputElement subtype of DialogInput -// https://api.slack.com/dialogs#option_element_attributes#text_element_attributes +// https://api.slack.com/dialogs#option_element_attributes#text_element_attributes type TextInputElement struct { DialogInput MaxLength int `json:"max_length,omitempty"` diff --git a/backend/vendor/github.com/slack-go/slack/files.go b/backend/vendor/github.com/slack-go/slack/files.go index e7e71c495d..e7cfe1feed 100644 --- a/backend/vendor/github.com/slack-go/slack/files.go +++ b/backend/vendor/github.com/slack-go/slack/files.go @@ -299,7 +299,7 @@ func (api *Client) UploadFile(params FileUploadParameters) (file *File, err erro func (api *Client) UploadFileContext(ctx context.Context, params FileUploadParameters) (file *File, err error) { // Test if user token is valid. This helps because client.Do doesn't like this for some reason. XXX: More // investigation needed, but for now this will do. - _, err = api.AuthTest() + _, err = api.AuthTestContext(ctx) if err != nil { return nil, err } diff --git a/backend/vendor/github.com/slack-go/slack/info.go b/backend/vendor/github.com/slack-go/slack/info.go index fde2bc98ea..b06dffdbe5 100644 --- a/backend/vendor/github.com/slack-go/slack/info.go +++ b/backend/vendor/github.com/slack-go/slack/info.go @@ -409,6 +409,11 @@ func (t JSONTime) Time() time.Time { func (t *JSONTime) UnmarshalJSON(buf []byte) error { s := bytes.Trim(buf, `"`) + if bytes.EqualFold(s, []byte("null")) { + *t = JSONTime(0) + return nil + } + v, err := strconv.Atoi(string(s)) if err != nil { return err diff --git a/backend/vendor/github.com/slack-go/slack/internal/backoff/backoff.go b/backend/vendor/github.com/slack-go/slack/internal/backoff/backoff.go index df210f80d5..833e9f2b62 100644 --- a/backend/vendor/github.com/slack-go/slack/internal/backoff/backoff.go +++ b/backend/vendor/github.com/slack-go/slack/internal/backoff/backoff.go @@ -51,7 +51,7 @@ func (b *Backoff) Duration() (dur time.Duration) { return dur } -//Resets the current value of the counter back to Min +// Resets the current value of the counter back to Min func (b *Backoff) Reset() { b.attempts = 0 } diff --git a/backend/vendor/github.com/slack-go/slack/messages.go b/backend/vendor/github.com/slack-go/slack/messages.go index 2cc31d5bfa..3334045632 100644 --- a/backend/vendor/github.com/slack-go/slack/messages.go +++ b/backend/vendor/github.com/slack-go/slack/messages.go @@ -129,8 +129,13 @@ type Msg struct { ReplaceOriginal bool `json:"replace_original"` DeleteOriginal bool `json:"delete_original"` + // metadata + Metadata SlackMetadata `json:"metadata,omitempty"` + // Block type Message Blocks Blocks `json:"blocks,omitempty"` + // permalink + Permalink string `json:"permalink,omitempty"` } const ( diff --git a/backend/vendor/github.com/slack-go/slack/metadata.go b/backend/vendor/github.com/slack-go/slack/metadata.go new file mode 100644 index 0000000000..a8c0650463 --- /dev/null +++ b/backend/vendor/github.com/slack-go/slack/metadata.go @@ -0,0 +1,7 @@ +package slack + +// SlackMetadata https://api.slack.com/reference/metadata +type SlackMetadata struct { + EventType string `json:"event_type"` + EventPayload map[string]interface{} `json:"event_payload"` +} diff --git a/backend/vendor/github.com/slack-go/slack/misc.go b/backend/vendor/github.com/slack-go/slack/misc.go index 804724d7ed..9180116af3 100644 --- a/backend/vendor/github.com/slack-go/slack/misc.go +++ b/backend/vendor/github.com/slack-go/slack/misc.go @@ -18,8 +18,6 @@ import ( "strconv" "strings" "time" - - "github.com/slack-go/slack/internal/misc" ) // SlackResponse handles parsing out errors from the web api. @@ -52,7 +50,7 @@ type SlackErrorResponse struct { func (r SlackErrorResponse) Error() string { return r.Err } -// RateLimitedError represents the rate limit respond from slack +// RateLimitedError represents the rate limit response from slack type RateLimitedError struct { RetryAfter time.Duration } @@ -299,7 +297,7 @@ func checkStatusCode(resp *http.Response, d Debug) error { // Slack seems to send an HTML body along with 5xx error codes. Don't parse it. if resp.StatusCode != http.StatusOK { logResponse(resp, d) - return misc.StatusCodeError{Code: resp.StatusCode, Status: resp.Status} + return StatusCodeError{Code: resp.StatusCode, Status: resp.Status} } return nil diff --git a/backend/vendor/github.com/slack-go/slack/remotefiles.go b/backend/vendor/github.com/slack-go/slack/remotefiles.go new file mode 100644 index 0000000000..8a908a8f3f --- /dev/null +++ b/backend/vendor/github.com/slack-go/slack/remotefiles.go @@ -0,0 +1,316 @@ +package slack + +import ( + "context" + "fmt" + "io" + "net/url" + "strconv" + "strings" +) + +const ( + DEFAULT_REMOTE_FILES_CHANNEL = "" + DEFAULT_REMOTE_FILES_TS_FROM = 0 + DEFAULT_REMOTE_FILES_TS_TO = -1 + DEFAULT_REMOTE_FILES_COUNT = 100 +) + +// RemoteFile contains all the information for a remote file +// For more details: +// https://api.slack.com/messaging/files/remote +type RemoteFile struct { + ID string `json:"id"` + Created JSONTime `json:"created"` + Timestamp JSONTime `json:"timestamp"` + Name string `json:"name"` + Title string `json:"title"` + Mimetype string `json:"mimetype"` + Filetype string `json:"filetype"` + PrettyType string `json:"pretty_type"` + User string `json:"user"` + Editable bool `json:"editable"` + Size int `json:"size"` + Mode string `json:"mode"` + IsExternal bool `json:"is_external"` + ExternalType string `json:"external_type"` + IsPublic bool `json:"is_public"` + PublicURLShared bool `json:"public_url_shared"` + DisplayAsBot bool `json:"display_as_bot"` + Username string `json:"username"` + URLPrivate string `json:"url_private"` + Permalink string `json:"permalink"` + CommentsCount int `json:"comments_count"` + IsStarred bool `json:"is_starred"` + Shares Share `json:"shares"` + Channels []string `json:"channels"` + Groups []string `json:"groups"` + IMs []string `json:"ims"` + ExternalID string `json:"external_id"` + ExternalURL string `json:"external_url"` + HasRichPreview bool `json:"has_rich_preview"` +} + +// RemoteFileParameters contains required and optional parameters for a remote file. +// +// ExternalID is a user defined GUID, ExternalURL is where the remote file can be accessed, +// and Title is the name of the file. +// +// For more details: +// https://api.slack.com/methods/files.remote.add +type RemoteFileParameters struct { + ExternalID string // required + ExternalURL string // required + Title string // required + Filetype string + IndexableFileContents string + PreviewImage string + PreviewImageReader io.Reader +} + +// ListRemoteFilesParameters contains arguments for the ListRemoteFiles method. +// For more details: +// https://api.slack.com/methods/files.remote.list +type ListRemoteFilesParameters struct { + Channel string + Cursor string + Limit int + TimestampFrom JSONTime + TimestampTo JSONTime +} + +type remoteFileResponseFull struct { + RemoteFile `json:"file"` + Paging `json:"paging"` + Files []RemoteFile `json:"files"` + SlackResponse +} + +func (api *Client) remoteFileRequest(ctx context.Context, path string, values url.Values) (*remoteFileResponseFull, error) { + response := &remoteFileResponseFull{} + err := api.postMethod(ctx, path, values, response) + if err != nil { + return nil, err + } + + return response, response.Err() +} + +// AddRemoteFile adds a remote file. Unlike regular files, remote files must be explicitly shared. +// For more details: +// https://api.slack.com/methods/files.remote.add +func (api *Client) AddRemoteFile(params RemoteFileParameters) (*RemoteFile, error) { + return api.AddRemoteFileContext(context.Background(), params) +} + +// AddRemoteFileContext adds a remote file and setting a custom context +// For more details see the AddRemoteFile documentation. +func (api *Client) AddRemoteFileContext(ctx context.Context, params RemoteFileParameters) (remotefile *RemoteFile, err error) { + if params.ExternalID == "" || params.ExternalURL == "" || params.Title == "" { + return nil, ErrParametersMissing + } + response := &remoteFileResponseFull{} + values := url.Values{ + "token": {api.token}, + "external_id": {params.ExternalID}, + "external_url": {params.ExternalURL}, + "title": {params.Title}, + } + if params.Filetype != "" { + values.Add("filetype", params.Filetype) + } + if params.IndexableFileContents != "" { + values.Add("indexable_file_contents", params.IndexableFileContents) + } + if params.PreviewImage != "" { + err = postLocalWithMultipartResponse(ctx, api.httpclient, api.endpoint+"files.remote.add", params.PreviewImage, "preview_image", api.token, values, response, api) + } else if params.PreviewImageReader != nil { + err = postWithMultipartResponse(ctx, api.httpclient, api.endpoint+"files.remote.add", "preview.png", "preview_image", api.token, values, params.PreviewImageReader, response, api) + } else { + response, err = api.remoteFileRequest(ctx, "files.remote.add", values) + } + + if err != nil { + return nil, err + } + + return &response.RemoteFile, response.Err() +} + +// ListRemoteFiles retrieves all remote files according to the parameters given. Uses cursor based pagination. +// For more details: +// https://api.slack.com/methods/files.remote.list +func (api *Client) ListRemoteFiles(params ListRemoteFilesParameters) ([]RemoteFile, error) { + return api.ListRemoteFilesContext(context.Background(), params) +} + +// ListRemoteFilesContext retrieves all remote files according to the parameters given with a custom context. Uses cursor based pagination. +// For more details see the ListRemoteFiles documentation. +func (api *Client) ListRemoteFilesContext(ctx context.Context, params ListRemoteFilesParameters) ([]RemoteFile, error) { + values := url.Values{ + "token": {api.token}, + } + if params.Channel != DEFAULT_REMOTE_FILES_CHANNEL { + values.Add("channel", params.Channel) + } + if params.TimestampFrom != DEFAULT_REMOTE_FILES_TS_FROM { + values.Add("ts_from", strconv.FormatInt(int64(params.TimestampFrom), 10)) + } + if params.TimestampTo != DEFAULT_REMOTE_FILES_TS_TO { + values.Add("ts_to", strconv.FormatInt(int64(params.TimestampTo), 10)) + } + if params.Limit != DEFAULT_REMOTE_FILES_COUNT { + values.Add("limit", strconv.Itoa(params.Limit)) + } + if params.Cursor != "" { + values.Add("cursor", params.Cursor) + } + + response, err := api.remoteFileRequest(ctx, "files.remote.list", values) + if err != nil { + return nil, err + } + + params.Cursor = response.SlackResponse.ResponseMetadata.Cursor + + return response.Files, nil +} + +// GetRemoteFileInfo retrieves the complete remote file information. +// For more details: +// https://api.slack.com/methods/files.remote.info +func (api *Client) GetRemoteFileInfo(externalID, fileID string) (remotefile *RemoteFile, err error) { + return api.GetRemoteFileInfoContext(context.Background(), externalID, fileID) +} + +// GetRemoteFileInfoContext retrieves the complete remote file information given with a custom context. +// For more details see the GetRemoteFileInfo documentation. +func (api *Client) GetRemoteFileInfoContext(ctx context.Context, externalID, fileID string) (remotefile *RemoteFile, err error) { + if fileID == "" && externalID == "" { + return nil, fmt.Errorf("either externalID or fileID is required") + } + if fileID != "" && externalID != "" { + return nil, fmt.Errorf("don't provide both externalID and fileID") + } + values := url.Values{ + "token": {api.token}, + } + if fileID != "" { + values.Add("file", fileID) + } + if externalID != "" { + values.Add("external_id", externalID) + } + response, err := api.remoteFileRequest(ctx, "files.remote.info", values) + if err != nil { + return nil, err + } + return &response.RemoteFile, err +} + +// ShareRemoteFile shares a remote file to channels +// For more details: +// https://api.slack.com/methods/files.remote.share +func (api *Client) ShareRemoteFile(channels []string, externalID, fileID string) (file *RemoteFile, err error) { + return api.ShareRemoteFileContext(context.Background(), channels, externalID, fileID) +} + +// ShareRemoteFileContext shares a remote file to channels with a custom context. +// For more details see the ShareRemoteFile documentation. +func (api *Client) ShareRemoteFileContext(ctx context.Context, channels []string, externalID, fileID string) (file *RemoteFile, err error) { + if channels == nil || len(channels) == 0 { + return nil, ErrParametersMissing + } + if fileID == "" && externalID == "" { + return nil, fmt.Errorf("either externalID or fileID is required") + } + values := url.Values{ + "token": {api.token}, + "channels": {strings.Join(channels, ",")}, + } + if fileID != "" { + values.Add("file", fileID) + } + if externalID != "" { + values.Add("external_id", externalID) + } + response, err := api.remoteFileRequest(ctx, "files.remote.share", values) + if err != nil { + return nil, err + } + return &response.RemoteFile, err +} + +// UpdateRemoteFile updates a remote file +// For more details: +// https://api.slack.com/methods/files.remote.update +func (api *Client) UpdateRemoteFile(fileID string, params RemoteFileParameters) (remotefile *RemoteFile, err error) { + return api.UpdateRemoteFileContext(context.Background(), fileID, params) +} + +// UpdateRemoteFileContext updates a remote file with a custom context +// For more details see the UpdateRemoteFile documentation. +func (api *Client) UpdateRemoteFileContext(ctx context.Context, fileID string, params RemoteFileParameters) (remotefile *RemoteFile, err error) { + response := &remoteFileResponseFull{} + values := url.Values{ + "token": {api.token}, + } + if fileID != "" { + values.Add("file", fileID) + } + if params.ExternalID != "" { + values.Add("external_id", params.ExternalID) + } + if params.ExternalURL != "" { + values.Add("external_url", params.ExternalURL) + } + if params.Title != "" { + values.Add("title", params.Title) + } + if params.Filetype != "" { + values.Add("filetype", params.Filetype) + } + if params.IndexableFileContents != "" { + values.Add("indexable_file_contents", params.IndexableFileContents) + } + if params.PreviewImageReader != nil { + err = postWithMultipartResponse(ctx, api.httpclient, api.endpoint+"files.remote.update", "preview.png", "preview_image", api.token, values, params.PreviewImageReader, response, api) + } else { + response, err = api.remoteFileRequest(ctx, "files.remote.update", values) + } + + if err != nil { + return nil, err + } + + return &response.RemoteFile, response.Err() +} + +// RemoveRemoteFile removes a remote file. +// For more details: +// https://api.slack.com/methods/files.remote.remove +func (api *Client) RemoveRemoteFile(externalID, fileID string) (err error) { + return api.RemoveRemoteFileContext(context.Background(), externalID, fileID) +} + +// RemoveRemoteFileContext removes a remote file with a custom context +// For more information see the RemoveRemoteFiles documentation. +func (api *Client) RemoveRemoteFileContext(ctx context.Context, externalID, fileID string) (err error) { + if fileID == "" && externalID == "" { + return fmt.Errorf("either externalID or fileID is required") + } + if fileID != "" && externalID != "" { + return fmt.Errorf("don't provide both externalID and fileID") + } + values := url.Values{ + "token": {api.token}, + } + if fileID != "" { + values.Add("file", fileID) + } + if externalID != "" { + values.Add("external_id", externalID) + } + _, err = api.remoteFileRequest(ctx, "files.remote.remove", values) + return err +} diff --git a/backend/vendor/github.com/slack-go/slack/stars.go b/backend/vendor/github.com/slack-go/slack/stars.go index 5296760482..6e0ebbe326 100644 --- a/backend/vendor/github.com/slack-go/slack/stars.go +++ b/backend/vendor/github.com/slack-go/slack/stars.go @@ -130,17 +130,18 @@ func (api *Client) ListStarsContext(ctx context.Context, params StarsParameters) // GetStarred returns a list of StarredItem items. // // The user then has to iterate over them and figure out what they should -// be looking at according to what is in the Type. -// for _, item := range items { -// switch c.Type { -// case "file_comment": -// log.Println(c.Comment) -// case "file": -// ... +// be looking at according to what is in the Type: +// +// for _, item := range items { +// switch c.Type { +// case "file_comment": +// log.Println(c.Comment) +// case "file": +// ... +// } // -// } // This function still exists to maintain backwards compatibility. -// I exposed it as returning []StarredItem, so it shall stay as StarredItem +// I exposed it as returning []StarredItem, so it shall stay as StarredItem. func (api *Client) GetStarred(params StarsParameters) ([]StarredItem, *Paging, error) { return api.GetStarredContext(context.Background(), params) } diff --git a/backend/vendor/github.com/slack-go/slack/internal/misc/misc.go b/backend/vendor/github.com/slack-go/slack/status_code_error.go similarity index 97% rename from backend/vendor/github.com/slack-go/slack/internal/misc/misc.go rename to backend/vendor/github.com/slack-go/slack/status_code_error.go index eab8cdd8c0..7347137aa6 100644 --- a/backend/vendor/github.com/slack-go/slack/internal/misc/misc.go +++ b/backend/vendor/github.com/slack-go/slack/status_code_error.go @@ -1,4 +1,4 @@ -package misc +package slack import ( "fmt" diff --git a/backend/vendor/github.com/slack-go/slack/usergroups.go b/backend/vendor/github.com/slack-go/slack/usergroups.go index 9417f81774..c5d7a176b1 100644 --- a/backend/vendor/github.com/slack-go/slack/usergroups.go +++ b/backend/vendor/github.com/slack-go/slack/usergroups.go @@ -183,32 +183,77 @@ func (api *Client) GetUserGroupsContext(ctx context.Context, options ...GetUserG return response.UserGroups, nil } +// UpdateUserGroupsOption options for the UpdateUserGroup method call. +type UpdateUserGroupsOption func(*UpdateUserGroupsParams) + +// UpdateUserGroupsOptionName change the name of the User Group (default: empty, so it's no-op) +func UpdateUserGroupsOptionName(name string) UpdateUserGroupsOption { + return func(params *UpdateUserGroupsParams) { + params.Name = name + } +} + +// UpdateUserGroupsOptionHandle change the handle of the User Group (default: empty, so it's no-op) +func UpdateUserGroupsOptionHandle(handle string) UpdateUserGroupsOption { + return func(params *UpdateUserGroupsParams) { + params.Handle = handle + } +} + +// UpdateUserGroupsOptionDescription change the description of the User Group. (default: nil, so it's no-op) +func UpdateUserGroupsOptionDescription(description *string) UpdateUserGroupsOption { + return func(params *UpdateUserGroupsParams) { + params.Description = description + } +} + +// UpdateUserGroupsOptionChannels change the default channels of the User Group. (default: unspecified, so it's no-op) +func UpdateUserGroupsOptionChannels(channels []string) UpdateUserGroupsOption { + return func(params *UpdateUserGroupsParams) { + params.Channels = &channels + } +} + +// UpdateUserGroupsParams contains arguments for UpdateUserGroup method call +type UpdateUserGroupsParams struct { + Name string + Handle string + Description *string + Channels *[]string +} + // UpdateUserGroup will update an existing user group -func (api *Client) UpdateUserGroup(userGroup UserGroup) (UserGroup, error) { - return api.UpdateUserGroupContext(context.Background(), userGroup) +func (api *Client) UpdateUserGroup(userGroupID string, options ...UpdateUserGroupsOption) (UserGroup, error) { + return api.UpdateUserGroupContext(context.Background(), userGroupID, options...) } // UpdateUserGroupContext will update an existing user group with a custom context -func (api *Client) UpdateUserGroupContext(ctx context.Context, userGroup UserGroup) (UserGroup, error) { +func (api *Client) UpdateUserGroupContext(ctx context.Context, userGroupID string, options ...UpdateUserGroupsOption) (UserGroup, error) { + params := UpdateUserGroupsParams{} + + for _, opt := range options { + opt(¶ms) + } + values := url.Values{ "token": {api.token}, - "usergroup": {userGroup.ID}, + "usergroup": {userGroupID}, } - if userGroup.Name != "" { - values["name"] = []string{userGroup.Name} + if params.Name != "" { + values["name"] = []string{params.Name} } - if userGroup.Handle != "" { - values["handle"] = []string{userGroup.Handle} + if params.Handle != "" { + values["handle"] = []string{params.Handle} } - if userGroup.Description != "" { - values["description"] = []string{userGroup.Description} + if params.Description != nil { + values["description"] = []string{*params.Description} } - if len(userGroup.Prefs.Channels) > 0 { - values["channels"] = []string{strings.Join(userGroup.Prefs.Channels, ",")} + if params.Channels != nil { + values["channels"] = []string{strings.Join(*params.Channels, ",")} } response, err := api.userGroupRequest(ctx, "usergroups.update", values) diff --git a/backend/vendor/github.com/slack-go/slack/users.go b/backend/vendor/github.com/slack-go/slack/users.go index 8731156902..d22b44f8ca 100644 --- a/backend/vendor/github.com/slack-go/slack/users.go +++ b/backend/vendor/github.com/slack-go/slack/users.go @@ -292,6 +292,13 @@ func GetUsersOptionPresence(n bool) GetUsersOption { } } +// GetUsersOptionTeamID include team Id +func GetUsersOptionTeamID(teamId string) GetUsersOption { + return func(p *UserPagination) { + p.teamId = teamId + } +} + func newUserPagination(c *Client, options ...GetUsersOption) (up UserPagination) { up = UserPagination{ c: c, @@ -310,6 +317,7 @@ type UserPagination struct { Users []User limit int presence bool + teamId string previousResp *ResponseMetadata c *Client } @@ -344,6 +352,7 @@ func (t UserPagination) Next(ctx context.Context) (_ UserPagination, err error) "presence": {strconv.FormatBool(t.presence)}, "token": {t.c.token}, "cursor": {t.previousResp.Cursor}, + "team_id": {t.teamId}, "include_locale": {strconv.FormatBool(true)}, } @@ -364,13 +373,13 @@ func (api *Client) GetUsersPaginated(options ...GetUsersOption) UserPagination { } // GetUsers returns the list of users (with their detailed information) -func (api *Client) GetUsers() ([]User, error) { - return api.GetUsersContext(context.Background()) +func (api *Client) GetUsers(options ...GetUsersOption) ([]User, error) { + return api.GetUsersContext(context.Background(), options...) } // GetUsersContext returns the list of users (with their detailed information) with a custom context -func (api *Client) GetUsersContext(ctx context.Context) (results []User, err error) { - p := api.GetUsersPaginated() +func (api *Client) GetUsersContext(ctx context.Context, options ...GetUsersOption) (results []User, err error) { + p := api.GetUsersPaginated(options...) for err == nil { p, err = p.Next(ctx) if err == nil { diff --git a/backend/vendor/github.com/slack-go/slack/views.go b/backend/vendor/github.com/slack-go/slack/views.go index a3a1bd0569..e6a9617885 100644 --- a/backend/vendor/github.com/slack-go/slack/views.go +++ b/backend/vendor/github.com/slack-go/slack/views.go @@ -18,24 +18,25 @@ type ViewState struct { type View struct { SlackResponse - ID string `json:"id"` - TeamID string `json:"team_id"` - Type ViewType `json:"type"` - Title *TextBlockObject `json:"title"` - Close *TextBlockObject `json:"close"` - Submit *TextBlockObject `json:"submit"` - Blocks Blocks `json:"blocks"` - PrivateMetadata string `json:"private_metadata"` - CallbackID string `json:"callback_id"` - State *ViewState `json:"state"` - Hash string `json:"hash"` - ClearOnClose bool `json:"clear_on_close"` - NotifyOnClose bool `json:"notify_on_close"` - RootViewID string `json:"root_view_id"` - PreviousViewID string `json:"previous_view_id"` - AppID string `json:"app_id"` - ExternalID string `json:"external_id"` - BotID string `json:"bot_id"` + ID string `json:"id"` + TeamID string `json:"team_id"` + Type ViewType `json:"type"` + Title *TextBlockObject `json:"title"` + Close *TextBlockObject `json:"close"` + Submit *TextBlockObject `json:"submit"` + Blocks Blocks `json:"blocks"` + PrivateMetadata string `json:"private_metadata"` + CallbackID string `json:"callback_id"` + State *ViewState `json:"state"` + Hash string `json:"hash"` + ClearOnClose bool `json:"clear_on_close"` + NotifyOnClose bool `json:"notify_on_close"` + RootViewID string `json:"root_view_id"` + PreviousViewID string `json:"previous_view_id"` + AppID string `json:"app_id"` + ExternalID string `json:"external_id"` + BotID string `json:"bot_id"` + AppInstalledTeamID string `json:"app_installed_team_id"` } type ViewSubmissionCallbackResponseURL struct { diff --git a/backend/vendor/github.com/slack-go/slack/webhooks.go b/backend/vendor/github.com/slack-go/slack/webhooks.go index 15097f03e7..2f8fb47f6e 100644 --- a/backend/vendor/github.com/slack-go/slack/webhooks.go +++ b/backend/vendor/github.com/slack-go/slack/webhooks.go @@ -5,6 +5,8 @@ import ( "context" "encoding/json" "fmt" + "io" + "io/ioutil" "net/http" ) @@ -21,6 +23,7 @@ type WebhookMessage struct { ResponseType string `json:"response_type,omitempty"` ReplaceOriginal bool `json:"replace_original,omitempty"` DeleteOriginal bool `json:"delete_original,omitempty"` + ReplyBroadcast bool `json:"reply_broadcast,omitempty"` } func PostWebhook(url string, msg *WebhookMessage) error { @@ -51,7 +54,10 @@ func PostWebhookCustomHTTPContext(ctx context.Context, url string, httpClient *h if err != nil { return fmt.Errorf("failed to post webhook: %w", err) } - defer resp.Body.Close() + defer func() { + io.Copy(ioutil.Discard, resp.Body) + resp.Body.Close() + }() return checkStatusCode(resp, discard{}) } diff --git a/backend/vendor/github.com/slack-go/slack/websocket_managed_conn.go b/backend/vendor/github.com/slack-go/slack/websocket_managed_conn.go index 92536171f2..f107b2a47b 100644 --- a/backend/vendor/github.com/slack-go/slack/websocket_managed_conn.go +++ b/backend/vendor/github.com/slack-go/slack/websocket_managed_conn.go @@ -13,10 +13,34 @@ import ( "github.com/slack-go/slack/internal/backoff" "github.com/slack-go/slack/internal/errorsx" - "github.com/slack-go/slack/internal/misc" "github.com/slack-go/slack/internal/timex" ) +// UnmappedError represents error occurred when there is no mapping between given event name +// and corresponding Go struct. +type UnmappedError struct { + // EventType returns event type name. + EventType string + // RawEvent returns raw event body. + RawEvent json.RawMessage + + ctxMsg string +} + +// NewUnmappedError returns new UnmappedError instance. +func NewUnmappedError(ctxMsg, eventType string, raw json.RawMessage) *UnmappedError { + return &UnmappedError{ + ctxMsg: ctxMsg, + EventType: eventType, + RawEvent: raw, + } +} + +// Error returns human-readable error message. +func (u UnmappedError) Error() string { + return fmt.Sprintf("%s: Received unmapped event %q", u.ctxMsg, u.EventType) +} + // ManageConnection can be called on a Slack RTM instance returned by the // NewRTM method. It will connect to the slack RTM API and handle all incoming // and outgoing events. If a connection fails then it will attempt to reconnect @@ -127,7 +151,7 @@ func (rtm *RTM) connect(connectionCount int, useRTMStart bool) (*Info, *websocke } switch actual := err.(type) { - case misc.StatusCodeError: + case StatusCodeError: if actual.Code == http.StatusNotFound { rtm.Debugf("invalid auth when connecting with RTM: %s", err) rtm.IncomingEvents <- RTMEvent{"invalid_auth", &InvalidAuthEvent{}} @@ -475,7 +499,7 @@ func (rtm *RTM) handleEvent(typeStr string, event json.RawMessage) { v, exists := EventMapping[typeStr] if !exists { rtm.Debugf("RTM Error - received unmapped event %q: %s\n", typeStr, string(event)) - err := fmt.Errorf("RTM Error: Received unmapped event %q: %s", typeStr, string(event)) + err := NewUnmappedError("RTM Error", typeStr, event) rtm.IncomingEvents <- RTMEvent{"unmarshalling_error", &UnmarshallingErrorEvent{err}} return } @@ -484,7 +508,7 @@ func (rtm *RTM) handleEvent(typeStr string, event json.RawMessage) { err := json.Unmarshal(event, recvEvent) if err != nil { rtm.Debugf("RTM Error, could not unmarshall event %q: %s\n", typeStr, string(event)) - err := fmt.Errorf("RTM Error: Could not unmarshall event %q: %s", typeStr, string(event)) + err := fmt.Errorf("RTM Error: Could not unmarshall event %q", typeStr) rtm.IncomingEvents <- RTMEvent{"unmarshalling_error", &UnmarshallingErrorEvent{err}} return } diff --git a/backend/vendor/github.com/slack-go/slack/websocket_subteam.go b/backend/vendor/github.com/slack-go/slack/websocket_subteam.go index a23b274cfc..2f618733bc 100644 --- a/backend/vendor/github.com/slack-go/slack/websocket_subteam.go +++ b/backend/vendor/github.com/slack-go/slack/websocket_subteam.go @@ -14,9 +14,9 @@ type SubteamMembersChangedEvent struct { DatePreviousUpdate JSONTime `json:"date_previous_update"` DateUpdate JSONTime `json:"date_update"` AddedUsers []string `json:"added_users"` - AddedUsersCount string `json:"added_users_count"` + AddedUsersCount int `json:"added_users_count"` RemovedUsers []string `json:"removed_users"` - RemovedUsersCount string `json:"removed_users_count"` + RemovedUsersCount int `json:"removed_users_count"` } // SubteamSelfAddedEvent represents an event of you have been added to a User Group diff --git a/backend/vendor/github.com/slack-go/slack/workflow_step_execute.go b/backend/vendor/github.com/slack-go/slack/workflow_step_execute.go new file mode 100644 index 0000000000..18516f23ec --- /dev/null +++ b/backend/vendor/github.com/slack-go/slack/workflow_step_execute.go @@ -0,0 +1,85 @@ +package slack + +import ( + "context" + "encoding/json" +) + +type ( + WorkflowStepCompletedRequest struct { + WorkflowStepExecuteID string `json:"workflow_step_execute_id"` + Outputs map[string]string `json:"outputs"` + } + + WorkflowStepFailedRequest struct { + WorkflowStepExecuteID string `json:"workflow_step_execute_id"` + Error struct { + Message string `json:"message"` + } `json:"error"` + } +) + +type WorkflowStepCompletedRequestOption func(opt WorkflowStepCompletedRequest) error + +func WorkflowStepCompletedRequestOptionOutput(outputs map[string]string) WorkflowStepCompletedRequestOption { + return func(opt WorkflowStepCompletedRequest) error { + if len(outputs) > 0 { + opt.Outputs = outputs + } + return nil + } +} + +// WorkflowStepCompleted indicates step is completed +func (api *Client) WorkflowStepCompleted(workflowStepExecuteID string, options ...WorkflowStepCompletedRequestOption) error { + // More information: https://api.slack.com/methods/workflows.stepCompleted + r := WorkflowStepCompletedRequest{ + WorkflowStepExecuteID: workflowStepExecuteID, + } + for _, option := range options { + option(r) + } + + endpoint := api.endpoint + "workflows.stepCompleted" + jsonData, err := json.Marshal(r) + if err != nil { + return err + } + + response := &SlackResponse{} + if err := postJSON(context.Background(), api.httpclient, endpoint, api.token, jsonData, response, api); err != nil { + return err + } + + if !response.Ok { + return response.Err() + } + + return nil +} + +// WorkflowStepFailed indicates step is failed +func (api *Client) WorkflowStepFailed(workflowStepExecuteID string, errorMessage string) error { + // More information: https://api.slack.com/methods/workflows.stepFailed + r := WorkflowStepFailedRequest{ + WorkflowStepExecuteID: workflowStepExecuteID, + } + r.Error.Message = errorMessage + + endpoint := api.endpoint + "workflows.stepFailed" + jsonData, err := json.Marshal(r) + if err != nil { + return err + } + + response := &SlackResponse{} + if err := postJSON(context.Background(), api.httpclient, endpoint, api.token, jsonData, response, api); err != nil { + return err + } + + if !response.Ok { + return response.Err() + } + + return nil +} diff --git a/backend/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/bsoncodec.go b/backend/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/bsoncodec.go index 96195bcc9c..098ed69f98 100644 --- a/backend/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/bsoncodec.go +++ b/backend/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/bsoncodec.go @@ -13,6 +13,7 @@ import ( "go.mongodb.org/mongo-driver/bson/bsonrw" "go.mongodb.org/mongo-driver/bson/bsontype" + "go.mongodb.org/mongo-driver/bson/primitive" ) var ( @@ -118,11 +119,32 @@ type EncodeContext struct { type DecodeContext struct { *Registry Truncate bool + // Ancestor is the type of a containing document. This is mainly used to determine what type // should be used when decoding an embedded document into an empty interface. For example, if // Ancestor is a bson.M, BSON embedded document values being decoded into an empty interface // will be decoded into a bson.M. + // + // Deprecated: Use DefaultDocumentM or DefaultDocumentD instead. Ancestor reflect.Type + + // defaultDocumentType specifies the Go type to decode top-level and nested BSON documents into. In particular, the + // usage for this field is restricted to data typed as "interface{}" or "map[string]interface{}". If DocumentType is + // set to a type that a BSON document cannot be unmarshaled into (e.g. "string"), unmarshalling will result in an + // error. DocumentType overrides the Ancestor field. + defaultDocumentType reflect.Type +} + +// DefaultDocumentM will decode empty documents using the primitive.M type. This behavior is restricted to data typed as +// "interface{}" or "map[string]interface{}". +func (dc *DecodeContext) DefaultDocumentM() { + dc.defaultDocumentType = reflect.TypeOf(primitive.M{}) +} + +// DefaultDocumentD will decode empty documents using the primitive.D type. This behavior is restricted to data typed as +// "interface{}" or "map[string]interface{}". +func (dc *DecodeContext) DefaultDocumentD() { + dc.defaultDocumentType = reflect.TypeOf(primitive.D{}) } // ValueCodec is the interface that groups the methods to encode and decode diff --git a/backend/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_decoders.go b/backend/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_decoders.go index 20f4797ddf..e95cab585f 100644 --- a/backend/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_decoders.go +++ b/backend/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_decoders.go @@ -1463,7 +1463,7 @@ func (dvd DefaultValueDecoders) ValueUnmarshalerDecodeValue(dc DecodeContext, vr if !val.CanAddr() { return ValueDecoderError{Name: "ValueUnmarshalerDecodeValue", Types: []reflect.Type{tValueUnmarshaler}, Received: val} } - val = val.Addr() // If they type doesn't implement the interface, a pointer to it must. + val = val.Addr() // If the type doesn't implement the interface, a pointer to it must. } t, src, err := bsonrw.Copier{}.CopyValueToBytes(vr) @@ -1492,13 +1492,6 @@ func (dvd DefaultValueDecoders) UnmarshalerDecodeValue(dc DecodeContext, vr bson val.Set(reflect.New(val.Type().Elem())) } - if !val.Type().Implements(tUnmarshaler) { - if !val.CanAddr() { - return ValueDecoderError{Name: "UnmarshalerDecodeValue", Types: []reflect.Type{tUnmarshaler}, Received: val} - } - val = val.Addr() // If they type doesn't implement the interface, a pointer to it must. - } - _, src, err := bsonrw.Copier{}.CopyValueToBytes(vr) if err != nil { return err @@ -1516,6 +1509,13 @@ func (dvd DefaultValueDecoders) UnmarshalerDecodeValue(dc DecodeContext, vr bson return nil } + if !val.Type().Implements(tUnmarshaler) { + if !val.CanAddr() { + return ValueDecoderError{Name: "UnmarshalerDecodeValue", Types: []reflect.Type{tUnmarshaler}, Received: val} + } + val = val.Addr() // If the type doesn't implement the interface, a pointer to it must. + } + fn := val.Convert(tUnmarshaler).MethodByName("UnmarshalBSON") errVal := fn.Call([]reflect.Value{reflect.ValueOf(src)})[0] if !errVal.IsNil() { diff --git a/backend/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/doc.go b/backend/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/doc.go index c1e20f9489..b0ae0e23ff 100644 --- a/backend/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/doc.go +++ b/backend/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/doc.go @@ -1,3 +1,9 @@ +// Copyright (C) MongoDB, Inc. 2022-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + // Package bsoncodec provides a system for encoding values to BSON representations and decoding // values from BSON representations. This package considers both binary BSON and ExtendedJSON as // BSON representations. The types in this package enable a flexible system for handling this diff --git a/backend/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/empty_interface_codec.go b/backend/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/empty_interface_codec.go index a15636d0a8..eda417cff8 100644 --- a/backend/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/empty_interface_codec.go +++ b/backend/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/empty_interface_codec.go @@ -57,11 +57,18 @@ func (eic EmptyInterfaceCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWrit func (eic EmptyInterfaceCodec) getEmptyInterfaceDecodeType(dc DecodeContext, valueType bsontype.Type) (reflect.Type, error) { isDocument := valueType == bsontype.Type(0) || valueType == bsontype.EmbeddedDocument - if isDocument && dc.Ancestor != nil { - // Using ancestor information rather than looking up the type map entry forces consistent decoding. - // If we're decoding into a bson.D, subdocuments should also be decoded as bson.D, even if a type map entry - // has been registered. - return dc.Ancestor, nil + if isDocument { + if dc.defaultDocumentType != nil { + // If the bsontype is an embedded document and the DocumentType is set on the DecodeContext, then return + // that type. + return dc.defaultDocumentType, nil + } + if dc.Ancestor != nil { + // Using ancestor information rather than looking up the type map entry forces consistent decoding. + // If we're decoding into a bson.D, subdocuments should also be decoded as bson.D, even if a type map entry + // has been registered. + return dc.Ancestor, nil + } } rtype, err := dc.LookupTypeMapEntry(valueType) diff --git a/backend/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/map_codec.go b/backend/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/map_codec.go index 1f7acbcf16..e1fbef9c6c 100644 --- a/backend/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/map_codec.go +++ b/backend/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/map_codec.go @@ -7,6 +7,7 @@ package bsoncodec import ( + "encoding" "fmt" "reflect" "strconv" @@ -230,6 +231,19 @@ func (mc *MapCodec) encodeKey(val reflect.Value) (string, error) { } return "", err } + // keys implement encoding.TextMarshaler are marshaled. + if km, ok := val.Interface().(encoding.TextMarshaler); ok { + if val.Kind() == reflect.Ptr && val.IsNil() { + return "", nil + } + + buf, err := km.MarshalText() + if err != nil { + return "", err + } + + return string(buf), nil + } switch val.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: @@ -241,6 +255,7 @@ func (mc *MapCodec) encodeKey(val reflect.Value) (string, error) { } var keyUnmarshalerType = reflect.TypeOf((*KeyUnmarshaler)(nil)).Elem() +var textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem() func (mc *MapCodec) decodeKey(key string, keyType reflect.Type) (reflect.Value, error) { keyVal := reflect.ValueOf(key) @@ -252,6 +267,12 @@ func (mc *MapCodec) decodeKey(key string, keyType reflect.Type) (reflect.Value, v := keyVal.Interface().(KeyUnmarshaler) err = v.UnmarshalKey(key) keyVal = keyVal.Elem() + // Try to decode encoding.TextUnmarshalers. + case reflect.PtrTo(keyType).Implements(textUnmarshalerType): + keyVal = reflect.New(keyType) + v := keyVal.Interface().(encoding.TextUnmarshaler) + err = v.UnmarshalText([]byte(key)) + keyVal = keyVal.Elem() // Otherwise, go to type specific behavior default: switch keyType.Kind() { diff --git a/backend/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/doc.go b/backend/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/doc.go new file mode 100644 index 0000000000..c40973c8d4 --- /dev/null +++ b/backend/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/doc.go @@ -0,0 +1,8 @@ +// Copyright (C) MongoDB, Inc. 2022-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +// Package bsonoptions defines the optional configurations for the BSON codecs. +package bsonoptions diff --git a/backend/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/value_reader.go b/backend/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/value_reader.go index 458588b6bc..ef5d837c2f 100644 --- a/backend/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/value_reader.go +++ b/backend/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/value_reader.go @@ -86,12 +86,11 @@ type valueReader struct { // NewBSONDocumentReader returns a ValueReader using b for the underlying BSON // representation. Parameter b must be a BSON Document. -// -// TODO(skriptble): There's a lack of symmetry between the reader and writer, since the reader takes -// a []byte while the writer takes an io.Writer. We should have two versions of each, one that takes -// a []byte and one that takes an io.Reader or io.Writer. The []byte version will need to return a -// thing that can return the finished []byte since it might be reallocated when appended to. func NewBSONDocumentReader(b []byte) ValueReader { + // TODO(skriptble): There's a lack of symmetry between the reader and writer, since the reader takes a []byte while the + // TODO writer takes an io.Writer. We should have two versions of each, one that takes a []byte and one that takes an + // TODO io.Reader or io.Writer. The []byte version will need to return a thing that can return the finished []byte since + // TODO it might be reallocated when appended to. return newValueReader(b) } diff --git a/backend/vendor/go.mongodb.org/mongo-driver/bson/decoder.go b/backend/vendor/go.mongodb.org/mongo-driver/bson/decoder.go index 7f6b7694f9..6e189fa589 100644 --- a/backend/vendor/go.mongodb.org/mongo-driver/bson/decoder.go +++ b/backend/vendor/go.mongodb.org/mongo-driver/bson/decoder.go @@ -33,6 +33,11 @@ var decPool = sync.Pool{ type Decoder struct { dc bsoncodec.DecodeContext vr bsonrw.ValueReader + + // We persist defaultDocumentM and defaultDocumentD on the Decoder to prevent overwriting from + // (*Decoder).SetContext. + defaultDocumentM bool + defaultDocumentD bool } // NewDecoder returns a new decoder that uses the DefaultRegistry to read from vr. @@ -95,6 +100,12 @@ func (d *Decoder) Decode(val interface{}) error { if err != nil { return err } + if d.defaultDocumentM { + d.dc.DefaultDocumentM() + } + if d.defaultDocumentD { + d.dc.DefaultDocumentD() + } return decoder.DecodeValue(d.dc, d.vr, rval) } @@ -116,3 +127,15 @@ func (d *Decoder) SetContext(dc bsoncodec.DecodeContext) error { d.dc = dc return nil } + +// DefaultDocumentM will decode empty documents using the primitive.M type. This behavior is restricted to data typed as +// "interface{}" or "map[string]interface{}". +func (d *Decoder) DefaultDocumentM() { + d.defaultDocumentM = true +} + +// DefaultDocumentD will decode empty documents using the primitive.D type. This behavior is restricted to data typed as +// "interface{}" or "map[string]interface{}". +func (d *Decoder) DefaultDocumentD() { + d.defaultDocumentD = true +} diff --git a/backend/vendor/go.mongodb.org/mongo-driver/internal/csfle_util.go b/backend/vendor/go.mongodb.org/mongo-driver/internal/csfle_util.go new file mode 100644 index 0000000000..635d8e3538 --- /dev/null +++ b/backend/vendor/go.mongodb.org/mongo-driver/internal/csfle_util.go @@ -0,0 +1,39 @@ +// Copyright (C) MongoDB, Inc. 2022-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package internal + +import ( + "fmt" + + "go.mongodb.org/mongo-driver/x/bsonx/bsoncore" +) + +const ( + EncryptedCacheCollection = "ecc" + EncryptedStateCollection = "esc" + EncryptedCompactionCollection = "ecoc" +) + +// GetEncryptedStateCollectionName returns the encrypted state collection name associated with dataCollectionName. +func GetEncryptedStateCollectionName(efBSON bsoncore.Document, dataCollectionName string, stateCollection string) (string, error) { + fieldName := stateCollection + "Collection" + val, err := efBSON.LookupErr(fieldName) + if err != nil { + if err != bsoncore.ErrElementNotFound { + return "", err + } + // Return default name. + defaultName := "enxcol_." + dataCollectionName + "." + stateCollection + return defaultName, nil + } + + stateCollectionName, ok := val.StringValueOK() + if !ok { + return "", fmt.Errorf("expected string for '%v', got: %v", fieldName, val.Type) + } + return stateCollectionName, nil +} diff --git a/backend/vendor/go.mongodb.org/mongo-driver/internal/csot_util.go b/backend/vendor/go.mongodb.org/mongo-driver/internal/csot_util.go new file mode 100644 index 0000000000..ea07637bc5 --- /dev/null +++ b/backend/vendor/go.mongodb.org/mongo-driver/internal/csot_util.go @@ -0,0 +1,34 @@ +// Copyright (C) MongoDB, Inc. 2022-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package internal + +import ( + "context" + "time" +) + +type timeoutKey struct{} + +// MakeTimeoutContext returns a new context with Client-Side Operation Timeout (CSOT) feature-gated behavior +// and a Timeout set to the passed in Duration. Setting a Timeout on a single operation is not supported in +// public API. +// +// TODO(GODRIVER-2348) We may be able to remove this function once CSOT feature-gated behavior becomes the +// TODO default behavior. +func MakeTimeoutContext(ctx context.Context, to time.Duration) (context.Context, context.CancelFunc) { + // Only use the passed in Duration as a timeout on the Context if it + // is non-zero. + cancelFunc := func() {} + if to != 0 { + ctx, cancelFunc = context.WithTimeout(ctx, to) + } + return context.WithValue(ctx, timeoutKey{}, true), cancelFunc +} + +func IsTimeoutContext(ctx context.Context) bool { + return ctx.Value(timeoutKey{}) != nil +} diff --git a/backend/vendor/go.mongodb.org/mongo-driver/internal/error.go b/backend/vendor/go.mongodb.org/mongo-driver/internal/error.go index 6a105af4ff..1fec3f1835 100644 --- a/backend/vendor/go.mongodb.org/mongo-driver/internal/error.go +++ b/backend/vendor/go.mongodb.org/mongo-driver/internal/error.go @@ -117,3 +117,7 @@ func (e *wrappedError) Error() string { func (e *wrappedError) Inner() error { return e.inner } + +func (e *wrappedError) Unwrap() error { + return e.inner +} diff --git a/backend/vendor/go.mongodb.org/mongo-driver/internal/randutil/rand/bits.go b/backend/vendor/go.mongodb.org/mongo-driver/internal/randutil/rand/bits.go new file mode 100644 index 0000000000..4479009144 --- /dev/null +++ b/backend/vendor/go.mongodb.org/mongo-driver/internal/randutil/rand/bits.go @@ -0,0 +1,38 @@ +// Copied from https://cs.opensource.google/go/go/+/946b4baaf6521d521928500b2b57429c149854e7:src/math/bits.go + +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rand + +// Add64 returns the sum with carry of x, y and carry: sum = x + y + carry. +// The carry input must be 0 or 1; otherwise the behavior is undefined. +// The carryOut output is guaranteed to be 0 or 1. +func Add64(x, y, carry uint64) (sum, carryOut uint64) { + yc := y + carry + sum = x + yc + if sum < x || yc < y { + carryOut = 1 + } + return +} + +// Mul64 returns the 128-bit product of x and y: (hi, lo) = x * y +// with the product bits' upper half returned in hi and the lower +// half returned in lo. +func Mul64(x, y uint64) (hi, lo uint64) { + const mask32 = 1<<32 - 1 + x0 := x & mask32 + x1 := x >> 32 + y0 := y & mask32 + y1 := y >> 32 + w0 := x0 * y0 + t := x1*y0 + w0>>32 + w1 := t & mask32 + w2 := t >> 32 + w1 += x0 * y1 + hi = x1*y1 + w2 + w1>>32 + lo = x * y + return +} diff --git a/backend/vendor/go.mongodb.org/mongo-driver/internal/randutil/rand/exp.go b/backend/vendor/go.mongodb.org/mongo-driver/internal/randutil/rand/exp.go new file mode 100644 index 0000000000..859e4e0e42 --- /dev/null +++ b/backend/vendor/go.mongodb.org/mongo-driver/internal/randutil/rand/exp.go @@ -0,0 +1,223 @@ +// Copied from https://cs.opensource.google/go/x/exp/+/24438e51023af3bfc1db8aed43c1342817e8cfcd:rand/exp.go + +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rand + +import ( + "math" +) + +/* + * Exponential distribution + * + * See "The Ziggurat Method for Generating Random Variables" + * (Marsaglia & Tsang, 2000) + * http://www.jstatsoft.org/v05/i08/paper [pdf] + */ + +const ( + re = 7.69711747013104972 +) + +// ExpFloat64 returns an exponentially distributed float64 in the range +// (0, +math.MaxFloat64] with an exponential distribution whose rate parameter +// (lambda) is 1 and whose mean is 1/lambda (1). +// To produce a distribution with a different rate parameter, +// callers can adjust the output using: +// +// sample = ExpFloat64() / desiredRateParameter +func (r *Rand) ExpFloat64() float64 { + for { + j := r.Uint32() + i := j & 0xFF + x := float64(j) * float64(we[i]) + if j < ke[i] { + return x + } + if i == 0 { + return re - math.Log(r.Float64()) + } + if fe[i]+float32(r.Float64())*(fe[i-1]-fe[i]) < float32(math.Exp(-x)) { + return x + } + } +} + +var ke = [256]uint32{ + 0xe290a139, 0x0, 0x9beadebc, 0xc377ac71, 0xd4ddb990, + 0xde893fb8, 0xe4a8e87c, 0xe8dff16a, 0xebf2deab, 0xee49a6e8, + 0xf0204efd, 0xf19bdb8e, 0xf2d458bb, 0xf3da104b, 0xf4b86d78, + 0xf577ad8a, 0xf61de83d, 0xf6afb784, 0xf730a573, 0xf7a37651, + 0xf80a5bb6, 0xf867189d, 0xf8bb1b4f, 0xf9079062, 0xf94d70ca, + 0xf98d8c7d, 0xf9c8928a, 0xf9ff175b, 0xfa319996, 0xfa6085f8, + 0xfa8c3a62, 0xfab5084e, 0xfadb36c8, 0xfaff0410, 0xfb20a6ea, + 0xfb404fb4, 0xfb5e2951, 0xfb7a59e9, 0xfb95038c, 0xfbae44ba, + 0xfbc638d8, 0xfbdcf892, 0xfbf29a30, 0xfc0731df, 0xfc1ad1ed, + 0xfc2d8b02, 0xfc3f6c4d, 0xfc5083ac, 0xfc60ddd1, 0xfc708662, + 0xfc7f8810, 0xfc8decb4, 0xfc9bbd62, 0xfca9027c, 0xfcb5c3c3, + 0xfcc20864, 0xfccdd70a, 0xfcd935e3, 0xfce42ab0, 0xfceebace, + 0xfcf8eb3b, 0xfd02c0a0, 0xfd0c3f59, 0xfd156b7b, 0xfd1e48d6, + 0xfd26daff, 0xfd2f2552, 0xfd372af7, 0xfd3eeee5, 0xfd4673e7, + 0xfd4dbc9e, 0xfd54cb85, 0xfd5ba2f2, 0xfd62451b, 0xfd68b415, + 0xfd6ef1da, 0xfd750047, 0xfd7ae120, 0xfd809612, 0xfd8620b4, + 0xfd8b8285, 0xfd90bcf5, 0xfd95d15e, 0xfd9ac10b, 0xfd9f8d36, + 0xfda43708, 0xfda8bf9e, 0xfdad2806, 0xfdb17141, 0xfdb59c46, + 0xfdb9a9fd, 0xfdbd9b46, 0xfdc170f6, 0xfdc52bd8, 0xfdc8ccac, + 0xfdcc542d, 0xfdcfc30b, 0xfdd319ef, 0xfdd6597a, 0xfdd98245, + 0xfddc94e5, 0xfddf91e6, 0xfde279ce, 0xfde54d1f, 0xfde80c52, + 0xfdeab7de, 0xfded5034, 0xfdefd5be, 0xfdf248e3, 0xfdf4aa06, + 0xfdf6f984, 0xfdf937b6, 0xfdfb64f4, 0xfdfd818d, 0xfdff8dd0, + 0xfe018a08, 0xfe03767a, 0xfe05536c, 0xfe07211c, 0xfe08dfc9, + 0xfe0a8fab, 0xfe0c30fb, 0xfe0dc3ec, 0xfe0f48b1, 0xfe10bf76, + 0xfe122869, 0xfe1383b4, 0xfe14d17c, 0xfe1611e7, 0xfe174516, + 0xfe186b2a, 0xfe19843e, 0xfe1a9070, 0xfe1b8fd6, 0xfe1c8289, + 0xfe1d689b, 0xfe1e4220, 0xfe1f0f26, 0xfe1fcfbc, 0xfe2083ed, + 0xfe212bc3, 0xfe21c745, 0xfe225678, 0xfe22d95f, 0xfe234ffb, + 0xfe23ba4a, 0xfe241849, 0xfe2469f2, 0xfe24af3c, 0xfe24e81e, + 0xfe25148b, 0xfe253474, 0xfe2547c7, 0xfe254e70, 0xfe25485a, + 0xfe25356a, 0xfe251586, 0xfe24e88f, 0xfe24ae64, 0xfe2466e1, + 0xfe2411df, 0xfe23af34, 0xfe233eb4, 0xfe22c02c, 0xfe22336b, + 0xfe219838, 0xfe20ee58, 0xfe20358c, 0xfe1f6d92, 0xfe1e9621, + 0xfe1daef0, 0xfe1cb7ac, 0xfe1bb002, 0xfe1a9798, 0xfe196e0d, + 0xfe1832fd, 0xfe16e5fe, 0xfe15869d, 0xfe141464, 0xfe128ed3, + 0xfe10f565, 0xfe0f478c, 0xfe0d84b1, 0xfe0bac36, 0xfe09bd73, + 0xfe07b7b5, 0xfe059a40, 0xfe03644c, 0xfe011504, 0xfdfeab88, + 0xfdfc26e9, 0xfdf98629, 0xfdf6c83b, 0xfdf3ec01, 0xfdf0f04a, + 0xfdedd3d1, 0xfdea953d, 0xfde7331e, 0xfde3abe9, 0xfddffdfb, + 0xfddc2791, 0xfdd826cd, 0xfdd3f9a8, 0xfdcf9dfc, 0xfdcb1176, + 0xfdc65198, 0xfdc15bb3, 0xfdbc2ce2, 0xfdb6c206, 0xfdb117be, + 0xfdab2a63, 0xfda4f5fd, 0xfd9e7640, 0xfd97a67a, 0xfd908192, + 0xfd8901f2, 0xfd812182, 0xfd78d98e, 0xfd7022bb, 0xfd66f4ed, + 0xfd5d4732, 0xfd530f9c, 0xfd48432b, 0xfd3cd59a, 0xfd30b936, + 0xfd23dea4, 0xfd16349e, 0xfd07a7a3, 0xfcf8219b, 0xfce7895b, + 0xfcd5c220, 0xfcc2aadb, 0xfcae1d5e, 0xfc97ed4e, 0xfc7fe6d4, + 0xfc65ccf3, 0xfc495762, 0xfc2a2fc8, 0xfc07ee19, 0xfbe213c1, + 0xfbb8051a, 0xfb890078, 0xfb5411a5, 0xfb180005, 0xfad33482, + 0xfa839276, 0xfa263b32, 0xf9b72d1c, 0xf930a1a2, 0xf889f023, + 0xf7b577d2, 0xf69c650c, 0xf51530f0, 0xf2cb0e3c, 0xeeefb15d, + 0xe6da6ecf, +} +var we = [256]float32{ + 2.0249555e-09, 1.486674e-11, 2.4409617e-11, 3.1968806e-11, + 3.844677e-11, 4.4228204e-11, 4.9516443e-11, 5.443359e-11, + 5.905944e-11, 6.344942e-11, 6.7643814e-11, 7.1672945e-11, + 7.556032e-11, 7.932458e-11, 8.298079e-11, 8.654132e-11, + 9.0016515e-11, 9.3415074e-11, 9.674443e-11, 1.0001099e-10, + 1.03220314e-10, 1.06377254e-10, 1.09486115e-10, 1.1255068e-10, + 1.1557435e-10, 1.1856015e-10, 1.2151083e-10, 1.2442886e-10, + 1.2731648e-10, 1.3017575e-10, 1.3300853e-10, 1.3581657e-10, + 1.3860142e-10, 1.4136457e-10, 1.4410738e-10, 1.4683108e-10, + 1.4953687e-10, 1.5222583e-10, 1.54899e-10, 1.5755733e-10, + 1.6020171e-10, 1.6283301e-10, 1.6545203e-10, 1.6805951e-10, + 1.7065617e-10, 1.732427e-10, 1.7581973e-10, 1.7838787e-10, + 1.8094774e-10, 1.8349985e-10, 1.8604476e-10, 1.8858298e-10, + 1.9111498e-10, 1.9364126e-10, 1.9616223e-10, 1.9867835e-10, + 2.0119004e-10, 2.0369768e-10, 2.0620168e-10, 2.087024e-10, + 2.1120022e-10, 2.136955e-10, 2.1618855e-10, 2.1867974e-10, + 2.2116936e-10, 2.2365775e-10, 2.261452e-10, 2.2863202e-10, + 2.311185e-10, 2.3360494e-10, 2.360916e-10, 2.3857874e-10, + 2.4106667e-10, 2.4355562e-10, 2.4604588e-10, 2.485377e-10, + 2.5103128e-10, 2.5352695e-10, 2.560249e-10, 2.585254e-10, + 2.6102867e-10, 2.6353494e-10, 2.6604446e-10, 2.6855745e-10, + 2.7107416e-10, 2.7359479e-10, 2.761196e-10, 2.7864877e-10, + 2.8118255e-10, 2.8372119e-10, 2.8626485e-10, 2.888138e-10, + 2.9136826e-10, 2.939284e-10, 2.9649452e-10, 2.9906677e-10, + 3.016454e-10, 3.0423064e-10, 3.0682268e-10, 3.0942177e-10, + 3.1202813e-10, 3.1464195e-10, 3.1726352e-10, 3.19893e-10, + 3.2253064e-10, 3.251767e-10, 3.2783135e-10, 3.3049485e-10, + 3.3316744e-10, 3.3584938e-10, 3.3854083e-10, 3.4124212e-10, + 3.4395342e-10, 3.46675e-10, 3.4940711e-10, 3.5215003e-10, + 3.5490397e-10, 3.5766917e-10, 3.6044595e-10, 3.6323455e-10, + 3.660352e-10, 3.6884823e-10, 3.7167386e-10, 3.745124e-10, + 3.773641e-10, 3.802293e-10, 3.8310827e-10, 3.860013e-10, + 3.8890866e-10, 3.918307e-10, 3.9476775e-10, 3.9772008e-10, + 4.0068804e-10, 4.0367196e-10, 4.0667217e-10, 4.09689e-10, + 4.1272286e-10, 4.1577405e-10, 4.1884296e-10, 4.2192994e-10, + 4.250354e-10, 4.281597e-10, 4.313033e-10, 4.3446652e-10, + 4.3764986e-10, 4.408537e-10, 4.4407847e-10, 4.4732465e-10, + 4.5059267e-10, 4.5388301e-10, 4.571962e-10, 4.6053267e-10, + 4.6389292e-10, 4.6727755e-10, 4.70687e-10, 4.741219e-10, + 4.7758275e-10, 4.810702e-10, 4.845848e-10, 4.8812715e-10, + 4.9169796e-10, 4.9529775e-10, 4.989273e-10, 5.0258725e-10, + 5.0627835e-10, 5.100013e-10, 5.1375687e-10, 5.1754584e-10, + 5.21369e-10, 5.2522725e-10, 5.2912136e-10, 5.330522e-10, + 5.370208e-10, 5.4102806e-10, 5.45075e-10, 5.491625e-10, + 5.532918e-10, 5.5746385e-10, 5.616799e-10, 5.6594107e-10, + 5.7024857e-10, 5.746037e-10, 5.7900773e-10, 5.834621e-10, + 5.8796823e-10, 5.925276e-10, 5.971417e-10, 6.018122e-10, + 6.065408e-10, 6.113292e-10, 6.1617933e-10, 6.2109295e-10, + 6.260722e-10, 6.3111916e-10, 6.3623595e-10, 6.4142497e-10, + 6.4668854e-10, 6.5202926e-10, 6.5744976e-10, 6.6295286e-10, + 6.6854156e-10, 6.742188e-10, 6.79988e-10, 6.858526e-10, + 6.9181616e-10, 6.978826e-10, 7.04056e-10, 7.103407e-10, + 7.167412e-10, 7.2326256e-10, 7.2990985e-10, 7.366886e-10, + 7.4360473e-10, 7.5066453e-10, 7.5787476e-10, 7.6524265e-10, + 7.7277595e-10, 7.80483e-10, 7.883728e-10, 7.9645507e-10, + 8.047402e-10, 8.1323964e-10, 8.219657e-10, 8.309319e-10, + 8.401528e-10, 8.496445e-10, 8.594247e-10, 8.6951274e-10, + 8.799301e-10, 8.9070046e-10, 9.018503e-10, 9.134092e-10, + 9.254101e-10, 9.378904e-10, 9.508923e-10, 9.644638e-10, + 9.786603e-10, 9.935448e-10, 1.0091913e-09, 1.025686e-09, + 1.0431306e-09, 1.0616465e-09, 1.08138e-09, 1.1025096e-09, + 1.1252564e-09, 1.1498986e-09, 1.1767932e-09, 1.206409e-09, + 1.2393786e-09, 1.276585e-09, 1.3193139e-09, 1.3695435e-09, + 1.4305498e-09, 1.508365e-09, 1.6160854e-09, 1.7921248e-09, +} +var fe = [256]float32{ + 1, 0.9381437, 0.90046996, 0.87170434, 0.8477855, 0.8269933, + 0.8084217, 0.7915276, 0.77595687, 0.7614634, 0.7478686, + 0.7350381, 0.72286767, 0.71127474, 0.70019263, 0.6895665, + 0.67935055, 0.6695063, 0.66000086, 0.65080583, 0.6418967, + 0.63325197, 0.6248527, 0.6166822, 0.60872537, 0.60096896, + 0.5934009, 0.58601034, 0.5787874, 0.57172304, 0.5648092, + 0.5580383, 0.5514034, 0.5448982, 0.5385169, 0.53225386, + 0.5261042, 0.52006316, 0.5141264, 0.50828975, 0.5025495, + 0.496902, 0.49134386, 0.485872, 0.48048335, 0.4751752, + 0.46994483, 0.46478975, 0.45970762, 0.45469615, 0.44975325, + 0.44487688, 0.44006512, 0.43531612, 0.43062815, 0.42599955, + 0.42142874, 0.4169142, 0.41245446, 0.40804818, 0.403694, + 0.3993907, 0.39513698, 0.39093173, 0.38677382, 0.38266218, + 0.37859577, 0.37457356, 0.37059465, 0.3666581, 0.362763, + 0.35890847, 0.35509375, 0.351318, 0.3475805, 0.34388044, + 0.34021714, 0.3365899, 0.33299807, 0.32944095, 0.32591796, + 0.3224285, 0.3189719, 0.31554767, 0.31215525, 0.30879408, + 0.3054636, 0.3021634, 0.29889292, 0.2956517, 0.29243928, + 0.28925523, 0.28609908, 0.28297043, 0.27986884, 0.27679393, + 0.2737453, 0.2707226, 0.2677254, 0.26475343, 0.26180625, + 0.25888354, 0.25598502, 0.2531103, 0.25025907, 0.24743107, + 0.24462597, 0.24184346, 0.23908329, 0.23634516, 0.23362878, + 0.23093392, 0.2282603, 0.22560766, 0.22297576, 0.22036438, + 0.21777324, 0.21520215, 0.21265087, 0.21011916, 0.20760682, + 0.20511365, 0.20263945, 0.20018397, 0.19774707, 0.19532852, + 0.19292815, 0.19054577, 0.1881812, 0.18583426, 0.18350479, + 0.1811926, 0.17889754, 0.17661946, 0.17435817, 0.17211354, + 0.1698854, 0.16767362, 0.16547804, 0.16329853, 0.16113494, + 0.15898713, 0.15685499, 0.15473837, 0.15263714, 0.15055119, + 0.14848037, 0.14642459, 0.14438373, 0.14235765, 0.14034624, + 0.13834943, 0.13636707, 0.13439907, 0.13244532, 0.13050574, + 0.1285802, 0.12666863, 0.12477092, 0.12288698, 0.12101672, + 0.119160056, 0.1173169, 0.115487166, 0.11367077, 0.11186763, + 0.11007768, 0.10830083, 0.10653701, 0.10478614, 0.10304816, + 0.101323, 0.09961058, 0.09791085, 0.09622374, 0.09454919, + 0.09288713, 0.091237515, 0.08960028, 0.087975375, 0.08636274, + 0.08476233, 0.083174095, 0.081597984, 0.08003395, 0.07848195, + 0.076941945, 0.07541389, 0.07389775, 0.072393484, 0.07090106, + 0.069420435, 0.06795159, 0.066494495, 0.06504912, 0.063615434, + 0.062193416, 0.060783047, 0.059384305, 0.057997175, + 0.05662164, 0.05525769, 0.053905312, 0.052564494, 0.051235236, + 0.049917534, 0.048611384, 0.047316793, 0.046033762, 0.0447623, + 0.043502413, 0.042254124, 0.041017443, 0.039792392, + 0.038578995, 0.037377283, 0.036187284, 0.035009038, + 0.033842582, 0.032687962, 0.031545233, 0.030414443, 0.02929566, + 0.02818895, 0.027094385, 0.026012046, 0.024942026, 0.023884421, + 0.022839336, 0.021806888, 0.020787204, 0.019780423, 0.0187867, + 0.0178062, 0.016839107, 0.015885621, 0.014945968, 0.014020392, + 0.013109165, 0.012212592, 0.011331013, 0.01046481, 0.009614414, + 0.008780315, 0.007963077, 0.0071633533, 0.006381906, + 0.0056196423, 0.0048776558, 0.004157295, 0.0034602648, + 0.0027887989, 0.0021459677, 0.0015362998, 0.0009672693, + 0.00045413437, +} diff --git a/backend/vendor/go.mongodb.org/mongo-driver/internal/randutil/rand/normal.go b/backend/vendor/go.mongodb.org/mongo-driver/internal/randutil/rand/normal.go new file mode 100644 index 0000000000..8c74a358de --- /dev/null +++ b/backend/vendor/go.mongodb.org/mongo-driver/internal/randutil/rand/normal.go @@ -0,0 +1,158 @@ +// Copied from https://cs.opensource.google/go/x/exp/+/24438e51023af3bfc1db8aed43c1342817e8cfcd:rand/normal.go + +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rand + +import ( + "math" +) + +/* + * Normal distribution + * + * See "The Ziggurat Method for Generating Random Variables" + * (Marsaglia & Tsang, 2000) + * http://www.jstatsoft.org/v05/i08/paper [pdf] + */ + +const ( + rn = 3.442619855899 +) + +func absInt32(i int32) uint32 { + if i < 0 { + return uint32(-i) + } + return uint32(i) +} + +// NormFloat64 returns a normally distributed float64 in the range +// [-math.MaxFloat64, +math.MaxFloat64] with +// standard normal distribution (mean = 0, stddev = 1). +// To produce a different normal distribution, callers can +// adjust the output using: +// +// sample = NormFloat64() * desiredStdDev + desiredMean +func (r *Rand) NormFloat64() float64 { + for { + j := int32(r.Uint32()) // Possibly negative + i := j & 0x7F + x := float64(j) * float64(wn[i]) + if absInt32(j) < kn[i] { + // This case should be hit better than 99% of the time. + return x + } + + if i == 0 { + // This extra work is only required for the base strip. + for { + x = -math.Log(r.Float64()) * (1.0 / rn) + y := -math.Log(r.Float64()) + if y+y >= x*x { + break + } + } + if j > 0 { + return rn + x + } + return -rn - x + } + if fn[i]+float32(r.Float64())*(fn[i-1]-fn[i]) < float32(math.Exp(-.5*x*x)) { + return x + } + } +} + +var kn = [128]uint32{ + 0x76ad2212, 0x0, 0x600f1b53, 0x6ce447a6, 0x725b46a2, + 0x7560051d, 0x774921eb, 0x789a25bd, 0x799045c3, 0x7a4bce5d, + 0x7adf629f, 0x7b5682a6, 0x7bb8a8c6, 0x7c0ae722, 0x7c50cce7, + 0x7c8cec5b, 0x7cc12cd6, 0x7ceefed2, 0x7d177e0b, 0x7d3b8883, + 0x7d5bce6c, 0x7d78dd64, 0x7d932886, 0x7dab0e57, 0x7dc0dd30, + 0x7dd4d688, 0x7de73185, 0x7df81cea, 0x7e07c0a3, 0x7e163efa, + 0x7e23b587, 0x7e303dfd, 0x7e3beec2, 0x7e46db77, 0x7e51155d, + 0x7e5aabb3, 0x7e63abf7, 0x7e6c222c, 0x7e741906, 0x7e7b9a18, + 0x7e82adfa, 0x7e895c63, 0x7e8fac4b, 0x7e95a3fb, 0x7e9b4924, + 0x7ea0a0ef, 0x7ea5b00d, 0x7eaa7ac3, 0x7eaf04f3, 0x7eb3522a, + 0x7eb765a5, 0x7ebb4259, 0x7ebeeafd, 0x7ec2620a, 0x7ec5a9c4, + 0x7ec8c441, 0x7ecbb365, 0x7ece78ed, 0x7ed11671, 0x7ed38d62, + 0x7ed5df12, 0x7ed80cb4, 0x7eda175c, 0x7edc0005, 0x7eddc78e, + 0x7edf6ebf, 0x7ee0f647, 0x7ee25ebe, 0x7ee3a8a9, 0x7ee4d473, + 0x7ee5e276, 0x7ee6d2f5, 0x7ee7a620, 0x7ee85c10, 0x7ee8f4cd, + 0x7ee97047, 0x7ee9ce59, 0x7eea0eca, 0x7eea3147, 0x7eea3568, + 0x7eea1aab, 0x7ee9e071, 0x7ee98602, 0x7ee90a88, 0x7ee86d08, + 0x7ee7ac6a, 0x7ee6c769, 0x7ee5bc9c, 0x7ee48a67, 0x7ee32efc, + 0x7ee1a857, 0x7edff42f, 0x7ede0ffa, 0x7edbf8d9, 0x7ed9ab94, + 0x7ed7248d, 0x7ed45fae, 0x7ed1585c, 0x7ece095f, 0x7eca6ccb, + 0x7ec67be2, 0x7ec22eee, 0x7ebd7d1a, 0x7eb85c35, 0x7eb2c075, + 0x7eac9c20, 0x7ea5df27, 0x7e9e769f, 0x7e964c16, 0x7e8d44ba, + 0x7e834033, 0x7e781728, 0x7e6b9933, 0x7e5d8a1a, 0x7e4d9ded, + 0x7e3b737a, 0x7e268c2f, 0x7e0e3ff5, 0x7df1aa5d, 0x7dcf8c72, + 0x7da61a1e, 0x7d72a0fb, 0x7d30e097, 0x7cd9b4ab, 0x7c600f1a, + 0x7ba90bdc, 0x7a722176, 0x77d664e5, +} +var wn = [128]float32{ + 1.7290405e-09, 1.2680929e-10, 1.6897518e-10, 1.9862688e-10, + 2.2232431e-10, 2.4244937e-10, 2.601613e-10, 2.7611988e-10, + 2.9073963e-10, 3.042997e-10, 3.1699796e-10, 3.289802e-10, + 3.4035738e-10, 3.5121603e-10, 3.616251e-10, 3.7164058e-10, + 3.8130857e-10, 3.9066758e-10, 3.9975012e-10, 4.08584e-10, + 4.1719309e-10, 4.2559822e-10, 4.338176e-10, 4.418672e-10, + 4.497613e-10, 4.5751258e-10, 4.651324e-10, 4.7263105e-10, + 4.8001775e-10, 4.87301e-10, 4.944885e-10, 5.015873e-10, + 5.0860405e-10, 5.155446e-10, 5.2241467e-10, 5.2921934e-10, + 5.359635e-10, 5.426517e-10, 5.4928817e-10, 5.5587696e-10, + 5.624219e-10, 5.6892646e-10, 5.753941e-10, 5.818282e-10, + 5.882317e-10, 5.946077e-10, 6.00959e-10, 6.072884e-10, + 6.135985e-10, 6.19892e-10, 6.2617134e-10, 6.3243905e-10, + 6.386974e-10, 6.449488e-10, 6.511956e-10, 6.5744005e-10, + 6.6368433e-10, 6.699307e-10, 6.7618144e-10, 6.824387e-10, + 6.8870465e-10, 6.949815e-10, 7.012715e-10, 7.075768e-10, + 7.1389966e-10, 7.202424e-10, 7.266073e-10, 7.329966e-10, + 7.394128e-10, 7.4585826e-10, 7.5233547e-10, 7.58847e-10, + 7.653954e-10, 7.719835e-10, 7.7861395e-10, 7.852897e-10, + 7.920138e-10, 7.987892e-10, 8.0561924e-10, 8.125073e-10, + 8.194569e-10, 8.2647167e-10, 8.3355556e-10, 8.407127e-10, + 8.479473e-10, 8.55264e-10, 8.6266755e-10, 8.7016316e-10, + 8.777562e-10, 8.8545243e-10, 8.932582e-10, 9.0117996e-10, + 9.09225e-10, 9.174008e-10, 9.2571584e-10, 9.341788e-10, + 9.427997e-10, 9.515889e-10, 9.605579e-10, 9.697193e-10, + 9.790869e-10, 9.88676e-10, 9.985036e-10, 1.0085882e-09, + 1.0189509e-09, 1.0296151e-09, 1.0406069e-09, 1.0519566e-09, + 1.063698e-09, 1.0758702e-09, 1.0885183e-09, 1.1016947e-09, + 1.1154611e-09, 1.1298902e-09, 1.1450696e-09, 1.1611052e-09, + 1.1781276e-09, 1.1962995e-09, 1.2158287e-09, 1.2369856e-09, + 1.2601323e-09, 1.2857697e-09, 1.3146202e-09, 1.347784e-09, + 1.3870636e-09, 1.4357403e-09, 1.5008659e-09, 1.6030948e-09, +} +var fn = [128]float32{ + 1, 0.9635997, 0.9362827, 0.9130436, 0.89228165, 0.87324303, + 0.8555006, 0.8387836, 0.8229072, 0.8077383, 0.793177, + 0.7791461, 0.7655842, 0.7524416, 0.73967725, 0.7272569, + 0.7151515, 0.7033361, 0.69178915, 0.68049186, 0.6694277, + 0.658582, 0.6479418, 0.63749546, 0.6272325, 0.6171434, + 0.6072195, 0.5974532, 0.58783704, 0.5783647, 0.56903, + 0.5598274, 0.5507518, 0.54179835, 0.5329627, 0.52424055, + 0.5156282, 0.50712204, 0.49871865, 0.49041483, 0.48220766, + 0.4740943, 0.46607214, 0.4581387, 0.45029163, 0.44252872, + 0.43484783, 0.427247, 0.41972435, 0.41227803, 0.40490642, + 0.39760786, 0.3903808, 0.3832238, 0.37613547, 0.36911446, + 0.3621595, 0.35526937, 0.34844297, 0.34167916, 0.33497685, + 0.3283351, 0.3217529, 0.3152294, 0.30876362, 0.30235484, + 0.29600215, 0.28970486, 0.2834622, 0.2772735, 0.27113807, + 0.2650553, 0.25902456, 0.2530453, 0.24711695, 0.241239, + 0.23541094, 0.22963232, 0.2239027, 0.21822165, 0.21258877, + 0.20700371, 0.20146611, 0.19597565, 0.19053204, 0.18513499, + 0.17978427, 0.17447963, 0.1692209, 0.16400786, 0.15884037, + 0.15371831, 0.14864157, 0.14361008, 0.13862377, 0.13368265, + 0.12878671, 0.12393598, 0.119130544, 0.11437051, 0.10965602, + 0.104987256, 0.10036444, 0.095787846, 0.0912578, 0.08677467, + 0.0823389, 0.077950984, 0.073611505, 0.06932112, 0.06508058, + 0.06089077, 0.056752663, 0.0526674, 0.048636295, 0.044660863, + 0.040742867, 0.03688439, 0.033087887, 0.029356318, + 0.025693292, 0.022103304, 0.018592102, 0.015167298, + 0.011839478, 0.008624485, 0.005548995, 0.0026696292, +} diff --git a/backend/vendor/go.mongodb.org/mongo-driver/internal/randutil/rand/rand.go b/backend/vendor/go.mongodb.org/mongo-driver/internal/randutil/rand/rand.go new file mode 100644 index 0000000000..ffd0509bd5 --- /dev/null +++ b/backend/vendor/go.mongodb.org/mongo-driver/internal/randutil/rand/rand.go @@ -0,0 +1,374 @@ +// Copied from https://cs.opensource.google/go/x/exp/+/24438e51023af3bfc1db8aed43c1342817e8cfcd:rand/rand.go + +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package rand implements pseudo-random number generators. +// +// Random numbers are generated by a Source. Top-level functions, such as +// Float64 and Int, use a default shared Source that produces a deterministic +// sequence of values each time a program is run. Use the Seed function to +// initialize the default Source if different behavior is required for each run. +// The default Source, a LockedSource, is safe for concurrent use by multiple +// goroutines, but Sources created by NewSource are not. However, Sources are small +// and it is reasonable to have a separate Source for each goroutine, seeded +// differently, to avoid locking. +// +// For random numbers suitable for security-sensitive work, see the crypto/rand +// package. +package rand + +import "sync" + +// A Source represents a source of uniformly-distributed +// pseudo-random int64 values in the range [0, 1<<64). +type Source interface { + Uint64() uint64 + Seed(seed uint64) +} + +// NewSource returns a new pseudo-random Source seeded with the given value. +func NewSource(seed uint64) Source { + var rng PCGSource + rng.Seed(seed) + return &rng +} + +// A Rand is a source of random numbers. +type Rand struct { + src Source + + // readVal contains remainder of 64-bit integer used for bytes + // generation during most recent Read call. + // It is saved so next Read call can start where the previous + // one finished. + readVal uint64 + // readPos indicates the number of low-order bytes of readVal + // that are still valid. + readPos int8 +} + +// New returns a new Rand that uses random values from src +// to generate other random values. +func New(src Source) *Rand { + return &Rand{src: src} +} + +// Seed uses the provided seed value to initialize the generator to a deterministic state. +// Seed should not be called concurrently with any other Rand method. +func (r *Rand) Seed(seed uint64) { + if lk, ok := r.src.(*LockedSource); ok { + lk.seedPos(seed, &r.readPos) + return + } + + r.src.Seed(seed) + r.readPos = 0 +} + +// Uint64 returns a pseudo-random 64-bit integer as a uint64. +func (r *Rand) Uint64() uint64 { return r.src.Uint64() } + +// Int63 returns a non-negative pseudo-random 63-bit integer as an int64. +func (r *Rand) Int63() int64 { return int64(r.src.Uint64() &^ (1 << 63)) } + +// Uint32 returns a pseudo-random 32-bit value as a uint32. +func (r *Rand) Uint32() uint32 { return uint32(r.Uint64() >> 32) } + +// Int31 returns a non-negative pseudo-random 31-bit integer as an int32. +func (r *Rand) Int31() int32 { return int32(r.Uint64() >> 33) } + +// Int returns a non-negative pseudo-random int. +func (r *Rand) Int() int { + u := uint(r.Uint64()) + return int(u << 1 >> 1) // clear sign bit. +} + +const maxUint64 = (1 << 64) - 1 + +// Uint64n returns, as a uint64, a pseudo-random number in [0,n). +// It is guaranteed more uniform than taking a Source value mod n +// for any n that is not a power of 2. +func (r *Rand) Uint64n(n uint64) uint64 { + if n&(n-1) == 0 { // n is power of two, can mask + if n == 0 { + panic("invalid argument to Uint64n") + } + return r.Uint64() & (n - 1) + } + // If n does not divide v, to avoid bias we must not use + // a v that is within maxUint64%n of the top of the range. + v := r.Uint64() + if v > maxUint64-n { // Fast check. + ceiling := maxUint64 - maxUint64%n + for v >= ceiling { + v = r.Uint64() + } + } + + return v % n +} + +// Int63n returns, as an int64, a non-negative pseudo-random number in [0,n). +// It panics if n <= 0. +func (r *Rand) Int63n(n int64) int64 { + if n <= 0 { + panic("invalid argument to Int63n") + } + return int64(r.Uint64n(uint64(n))) +} + +// Int31n returns, as an int32, a non-negative pseudo-random number in [0,n). +// It panics if n <= 0. +func (r *Rand) Int31n(n int32) int32 { + if n <= 0 { + panic("invalid argument to Int31n") + } + // TODO: Avoid some 64-bit ops to make it more efficient on 32-bit machines. + return int32(r.Uint64n(uint64(n))) +} + +// Intn returns, as an int, a non-negative pseudo-random number in [0,n). +// It panics if n <= 0. +func (r *Rand) Intn(n int) int { + if n <= 0 { + panic("invalid argument to Intn") + } + // TODO: Avoid some 64-bit ops to make it more efficient on 32-bit machines. + return int(r.Uint64n(uint64(n))) +} + +// Float64 returns, as a float64, a pseudo-random number in [0.0,1.0). +func (r *Rand) Float64() float64 { + // There is one bug in the value stream: r.Int63() may be so close + // to 1<<63 that the division rounds up to 1.0, and we've guaranteed + // that the result is always less than 1.0. + // + // We tried to fix this by mapping 1.0 back to 0.0, but since float64 + // values near 0 are much denser than near 1, mapping 1 to 0 caused + // a theoretically significant overshoot in the probability of returning 0. + // Instead of that, if we round up to 1, just try again. + // Getting 1 only happens 1/2⁵³ of the time, so most clients + // will not observe it anyway. +again: + f := float64(r.Uint64n(1<<53)) / (1 << 53) + if f == 1.0 { + goto again // resample; this branch is taken O(never) + } + return f +} + +// Float32 returns, as a float32, a pseudo-random number in [0.0,1.0). +func (r *Rand) Float32() float32 { + // We do not want to return 1.0. + // This only happens 1/2²⁴ of the time (plus the 1/2⁵³ of the time in Float64). +again: + f := float32(r.Float64()) + if f == 1 { + goto again // resample; this branch is taken O(very rarely) + } + return f +} + +// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n). +func (r *Rand) Perm(n int) []int { + m := make([]int, n) + // In the following loop, the iteration when i=0 always swaps m[0] with m[0]. + // A change to remove this useless iteration is to assign 1 to i in the init + // statement. But Perm also effects r. Making this change will affect + // the final state of r. So this change can't be made for compatibility + // reasons for Go 1. + for i := 0; i < n; i++ { + j := r.Intn(i + 1) + m[i] = m[j] + m[j] = i + } + return m +} + +// Shuffle pseudo-randomizes the order of elements. +// n is the number of elements. Shuffle panics if n < 0. +// swap swaps the elements with indexes i and j. +func (r *Rand) Shuffle(n int, swap func(i, j int)) { + if n < 0 { + panic("invalid argument to Shuffle") + } + + // Fisher-Yates shuffle: https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle + // Shuffle really ought not be called with n that doesn't fit in 32 bits. + // Not only will it take a very long time, but with 2³¹! possible permutations, + // there's no way that any PRNG can have a big enough internal state to + // generate even a minuscule percentage of the possible permutations. + // Nevertheless, the right API signature accepts an int n, so handle it as best we can. + i := n - 1 + for ; i > 1<<31-1-1; i-- { + j := int(r.Int63n(int64(i + 1))) + swap(i, j) + } + for ; i > 0; i-- { + j := int(r.Int31n(int32(i + 1))) + swap(i, j) + } +} + +// Read generates len(p) random bytes and writes them into p. It +// always returns len(p) and a nil error. +// Read should not be called concurrently with any other Rand method unless +// the underlying source is a LockedSource. +func (r *Rand) Read(p []byte) (n int, err error) { + if lk, ok := r.src.(*LockedSource); ok { + return lk.Read(p, &r.readVal, &r.readPos) + } + return read(p, r.src, &r.readVal, &r.readPos) +} + +func read(p []byte, src Source, readVal *uint64, readPos *int8) (n int, err error) { + pos := *readPos + val := *readVal + rng, _ := src.(*PCGSource) + for n = 0; n < len(p); n++ { + if pos == 0 { + if rng != nil { + val = rng.Uint64() + } else { + val = src.Uint64() + } + pos = 8 + } + p[n] = byte(val) + val >>= 8 + pos-- + } + *readPos = pos + *readVal = val + return +} + +/* + * Top-level convenience functions + */ + +var globalRand = New(&LockedSource{src: *NewSource(1).(*PCGSource)}) + +// Type assert that globalRand's source is a LockedSource whose src is a PCGSource. +var _ PCGSource = globalRand.src.(*LockedSource).src + +// Seed uses the provided seed value to initialize the default Source to a +// deterministic state. If Seed is not called, the generator behaves as +// if seeded by Seed(1). +// Seed, unlike the Rand.Seed method, is safe for concurrent use. +func Seed(seed uint64) { globalRand.Seed(seed) } + +// Int63 returns a non-negative pseudo-random 63-bit integer as an int64 +// from the default Source. +func Int63() int64 { return globalRand.Int63() } + +// Uint32 returns a pseudo-random 32-bit value as a uint32 +// from the default Source. +func Uint32() uint32 { return globalRand.Uint32() } + +// Uint64 returns a pseudo-random 64-bit value as a uint64 +// from the default Source. +func Uint64() uint64 { return globalRand.Uint64() } + +// Int31 returns a non-negative pseudo-random 31-bit integer as an int32 +// from the default Source. +func Int31() int32 { return globalRand.Int31() } + +// Int returns a non-negative pseudo-random int from the default Source. +func Int() int { return globalRand.Int() } + +// Int63n returns, as an int64, a non-negative pseudo-random number in [0,n) +// from the default Source. +// It panics if n <= 0. +func Int63n(n int64) int64 { return globalRand.Int63n(n) } + +// Int31n returns, as an int32, a non-negative pseudo-random number in [0,n) +// from the default Source. +// It panics if n <= 0. +func Int31n(n int32) int32 { return globalRand.Int31n(n) } + +// Intn returns, as an int, a non-negative pseudo-random number in [0,n) +// from the default Source. +// It panics if n <= 0. +func Intn(n int) int { return globalRand.Intn(n) } + +// Float64 returns, as a float64, a pseudo-random number in [0.0,1.0) +// from the default Source. +func Float64() float64 { return globalRand.Float64() } + +// Float32 returns, as a float32, a pseudo-random number in [0.0,1.0) +// from the default Source. +func Float32() float32 { return globalRand.Float32() } + +// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n) +// from the default Source. +func Perm(n int) []int { return globalRand.Perm(n) } + +// Shuffle pseudo-randomizes the order of elements using the default Source. +// n is the number of elements. Shuffle panics if n < 0. +// swap swaps the elements with indexes i and j. +func Shuffle(n int, swap func(i, j int)) { globalRand.Shuffle(n, swap) } + +// Read generates len(p) random bytes from the default Source and +// writes them into p. It always returns len(p) and a nil error. +// Read, unlike the Rand.Read method, is safe for concurrent use. +func Read(p []byte) (n int, err error) { return globalRand.Read(p) } + +// NormFloat64 returns a normally distributed float64 in the range +// [-math.MaxFloat64, +math.MaxFloat64] with +// standard normal distribution (mean = 0, stddev = 1) +// from the default Source. +// To produce a different normal distribution, callers can +// adjust the output using: +// +// sample = NormFloat64() * desiredStdDev + desiredMean +func NormFloat64() float64 { return globalRand.NormFloat64() } + +// ExpFloat64 returns an exponentially distributed float64 in the range +// (0, +math.MaxFloat64] with an exponential distribution whose rate parameter +// (lambda) is 1 and whose mean is 1/lambda (1) from the default Source. +// To produce a distribution with a different rate parameter, +// callers can adjust the output using: +// +// sample = ExpFloat64() / desiredRateParameter +func ExpFloat64() float64 { return globalRand.ExpFloat64() } + +// LockedSource is an implementation of Source that is concurrency-safe. +// A Rand using a LockedSource is safe for concurrent use. +// +// The zero value of LockedSource is valid, but should be seeded before use. +type LockedSource struct { + lk sync.Mutex + src PCGSource +} + +func (s *LockedSource) Uint64() (n uint64) { + s.lk.Lock() + n = s.src.Uint64() + s.lk.Unlock() + return +} + +func (s *LockedSource) Seed(seed uint64) { + s.lk.Lock() + s.src.Seed(seed) + s.lk.Unlock() +} + +// seedPos implements Seed for a LockedSource without a race condiiton. +func (s *LockedSource) seedPos(seed uint64, readPos *int8) { + s.lk.Lock() + s.src.Seed(seed) + *readPos = 0 + s.lk.Unlock() +} + +// Read implements Read for a LockedSource. +func (s *LockedSource) Read(p []byte, readVal *uint64, readPos *int8) (n int, err error) { + s.lk.Lock() + n, err = read(p, &s.src, readVal, readPos) + s.lk.Unlock() + return +} diff --git a/backend/vendor/go.mongodb.org/mongo-driver/internal/randutil/rand/rng.go b/backend/vendor/go.mongodb.org/mongo-driver/internal/randutil/rand/rng.go new file mode 100644 index 0000000000..f04f987989 --- /dev/null +++ b/backend/vendor/go.mongodb.org/mongo-driver/internal/randutil/rand/rng.go @@ -0,0 +1,93 @@ +// Copied from https://cs.opensource.google/go/x/exp/+/24438e51023af3bfc1db8aed43c1342817e8cfcd:rand/rng.go + +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rand + +import ( + "encoding/binary" + "io" + "math/bits" +) + +// PCGSource is an implementation of a 64-bit permuted congruential +// generator as defined in +// +// PCG: A Family of Simple Fast Space-Efficient Statistically Good +// Algorithms for Random Number Generation +// Melissa E. O’Neill, Harvey Mudd College +// http://www.pcg-random.org/pdf/toms-oneill-pcg-family-v1.02.pdf +// +// The generator here is the congruential generator PCG XSL RR 128/64 (LCG) +// as found in the software available at http://www.pcg-random.org/. +// It has period 2^128 with 128 bits of state, producing 64-bit values. +// Is state is represented by two uint64 words. +type PCGSource struct { + low uint64 + high uint64 +} + +const ( + maxUint32 = (1 << 32) - 1 + + multiplier = 47026247687942121848144207491837523525 + mulHigh = multiplier >> 64 + mulLow = multiplier & maxUint64 + + increment = 117397592171526113268558934119004209487 + incHigh = increment >> 64 + incLow = increment & maxUint64 + + // TODO: Use these? + initializer = 245720598905631564143578724636268694099 + initHigh = initializer >> 64 + initLow = initializer & maxUint64 +) + +// Seed uses the provided seed value to initialize the generator to a deterministic state. +func (pcg *PCGSource) Seed(seed uint64) { + pcg.low = seed + pcg.high = seed // TODO: What is right? +} + +// Uint64 returns a pseudo-random 64-bit unsigned integer as a uint64. +func (pcg *PCGSource) Uint64() uint64 { + pcg.multiply() + pcg.add() + // XOR high and low 64 bits together and rotate right by high 6 bits of state. + return bits.RotateLeft64(pcg.high^pcg.low, -int(pcg.high>>58)) +} + +func (pcg *PCGSource) add() { + var carry uint64 + pcg.low, carry = Add64(pcg.low, incLow, 0) + pcg.high, _ = Add64(pcg.high, incHigh, carry) +} + +func (pcg *PCGSource) multiply() { + hi, lo := Mul64(pcg.low, mulLow) + hi += pcg.high * mulLow + hi += pcg.low * mulHigh + pcg.low = lo + pcg.high = hi +} + +// MarshalBinary returns the binary representation of the current state of the generator. +func (pcg *PCGSource) MarshalBinary() ([]byte, error) { + var buf [16]byte + binary.BigEndian.PutUint64(buf[:8], pcg.high) + binary.BigEndian.PutUint64(buf[8:], pcg.low) + return buf[:], nil +} + +// UnmarshalBinary sets the state of the generator to the state represented in data. +func (pcg *PCGSource) UnmarshalBinary(data []byte) error { + if len(data) < 16 { + return io.ErrUnexpectedEOF + } + pcg.low = binary.BigEndian.Uint64(data[8:]) + pcg.high = binary.BigEndian.Uint64(data[:8]) + return nil +} diff --git a/backend/vendor/go.mongodb.org/mongo-driver/internal/randutil/randutil.go b/backend/vendor/go.mongodb.org/mongo-driver/internal/randutil/randutil.go index d7b753b770..9616074321 100644 --- a/backend/vendor/go.mongodb.org/mongo-driver/internal/randutil/randutil.go +++ b/backend/vendor/go.mongodb.org/mongo-driver/internal/randutil/randutil.go @@ -11,67 +11,29 @@ import ( crand "crypto/rand" "fmt" "io" - "math/rand" - "sync" -) - -// A LockedRand wraps a "math/rand".Rand and is safe to use from multiple goroutines. -type LockedRand struct { - mu sync.Mutex - r *rand.Rand -} - -// NewLockedRand returns a new LockedRand that uses random values from src to generate other random -// values. It is safe to use from multiple goroutines. -func NewLockedRand(src rand.Source) *LockedRand { - return &LockedRand{ - // Ignore gosec warning "Use of weak random number generator (math/rand instead of - // crypto/rand)". We intentionally use a pseudo-random number generator. - /* #nosec G404 */ - r: rand.New(src), - } -} -// Read generates len(p) random bytes and writes them into p. It always returns len(p) and a nil -// error. -func (lr *LockedRand) Read(p []byte) (int, error) { - lr.mu.Lock() - n, err := lr.r.Read(p) - lr.mu.Unlock() - return n, err -} - -// Intn returns, as an int, a non-negative pseudo-random number in the half-open interval [0,n). It -// panics if n <= 0. -func (lr *LockedRand) Intn(n int) int { - lr.mu.Lock() - x := lr.r.Intn(n) - lr.mu.Unlock() - return x -} + xrand "go.mongodb.org/mongo-driver/internal/randutil/rand" +) -// Shuffle pseudo-randomizes the order of elements. n is the number of elements. Shuffle panics if -// n < 0. swap swaps the elements with indexes i and j. -// -// Note that Shuffle locks the LockedRand, so shuffling large collections may adversely affect other -// concurrent calls. If many concurrent Shuffle and random value calls are required, consider using -// the global "math/rand".Shuffle instead because it uses much more granular locking. -func (lr *LockedRand) Shuffle(n int, swap func(i, j int)) { - lr.mu.Lock() - lr.r.Shuffle(n, swap) - lr.mu.Unlock() +// NewLockedRand returns a new "x/exp/rand" pseudo-random number generator seeded with a +// cryptographically-secure random number. +// It is safe to use from multiple goroutines. +func NewLockedRand() *xrand.Rand { + var randSrc = new(xrand.LockedSource) + randSrc.Seed(cryptoSeed()) + return xrand.New(randSrc) } -// CryptoSeed returns a random int64 read from the "crypto/rand" random number generator. It is +// cryptoSeed returns a random uint64 read from the "crypto/rand" random number generator. It is // intended to be used to seed pseudorandom number generators at package initialization. It panics // if it encounters any errors. -func CryptoSeed() int64 { +func cryptoSeed() uint64 { var b [8]byte _, err := io.ReadFull(crand.Reader, b[:]) if err != nil { panic(fmt.Errorf("failed to read 8 bytes from a \"crypto/rand\".Reader: %v", err)) } - return (int64(b[0]) << 0) | (int64(b[1]) << 8) | (int64(b[2]) << 16) | (int64(b[3]) << 24) | - (int64(b[4]) << 32) | (int64(b[5]) << 40) | (int64(b[6]) << 48) | (int64(b[7]) << 56) + return (uint64(b[0]) << 0) | (uint64(b[1]) << 8) | (uint64(b[2]) << 16) | (uint64(b[3]) << 24) | + (uint64(b[4]) << 32) | (uint64(b[5]) << 40) | (uint64(b[6]) << 48) | (uint64(b[7]) << 56) } diff --git a/backend/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/uuid/uuid.go b/backend/vendor/go.mongodb.org/mongo-driver/internal/uuid/uuid.go similarity index 54% rename from backend/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/uuid/uuid.go rename to backend/vendor/go.mongodb.org/mongo-driver/internal/uuid/uuid.go index 097838731a..78f16645d7 100644 --- a/backend/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/uuid/uuid.go +++ b/backend/vendor/go.mongodb.org/mongo-driver/internal/uuid/uuid.go @@ -4,11 +4,10 @@ // not use this file except in compliance with the License. You may obtain // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 -package uuid // import "go.mongodb.org/mongo-driver/x/mongo/driver/uuid" +package uuid import ( "io" - "math/rand" "go.mongodb.org/mongo-driver/internal/randutil" ) @@ -16,47 +15,39 @@ import ( // UUID represents a UUID. type UUID [16]byte -// A source is a UUID generator that reads random values from a randutil.LockedRand. -// It is safe to use from multiple goroutines. +// A source is a UUID generator that reads random values from a io.Reader. +// It should be safe to use from multiple goroutines. type source struct { - random *randutil.LockedRand + random io.Reader } // new returns a random UUIDv4 with bytes read from the source's random number generator. func (s *source) new() (UUID, error) { - var uuid [16]byte - + var uuid UUID _, err := io.ReadFull(s.random, uuid[:]) if err != nil { - return [16]byte{}, err + return UUID{}, err } uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4 uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10 - return uuid, nil } -// newGlobalSource returns a source that uses a "math/rand" pseudo-random number generator seeded -// with a cryptographically-secure random number. It is intended to be used to initialize the -// package-global UUID generator. -func newGlobalSource() *source { +// newSource returns a source that uses a pseudo-random number generator in reandutil package. +// It is intended to be used to initialize the package-global UUID generator. +func newSource() *source { return &source{ - random: randutil.NewLockedRand(rand.NewSource(randutil.CryptoSeed())), + random: randutil.NewLockedRand(), } } // globalSource is a package-global pseudo-random UUID generator. -var globalSource = newGlobalSource() +var globalSource = newSource() -// New returns a random UUIDv4. It uses a "math/rand" pseudo-random number generator seeded with a -// cryptographically-secure random number at package initialization. +// New returns a random UUIDv4. It uses a global pseudo-random number generator in randutil +// at package initialization. // // New should not be used to generate cryptographically-secure random UUIDs. func New() (UUID, error) { return globalSource.new() } - -// Equal returns true if two UUIDs are equal. -func Equal(a, b UUID) bool { - return a == b -} diff --git a/backend/vendor/go.mongodb.org/mongo-driver/mongo/address/addr.go b/backend/vendor/go.mongodb.org/mongo-driver/mongo/address/addr.go index 5655b3462f..fb6abbcd7c 100644 --- a/backend/vendor/go.mongodb.org/mongo-driver/mongo/address/addr.go +++ b/backend/vendor/go.mongodb.org/mongo-driver/mongo/address/addr.go @@ -4,6 +4,7 @@ // not use this file except in compliance with the License. You may obtain // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// Package address provides structured representations of network addresses. package address // import "go.mongodb.org/mongo-driver/mongo/address" import ( diff --git a/backend/vendor/go.mongodb.org/mongo-driver/mongo/batch_cursor.go b/backend/vendor/go.mongodb.org/mongo-driver/mongo/batch_cursor.go index 0b7432f408..966e43cdaf 100644 --- a/backend/vendor/go.mongodb.org/mongo-driver/mongo/batch_cursor.go +++ b/backend/vendor/go.mongodb.org/mongo-driver/mongo/batch_cursor.go @@ -1,3 +1,9 @@ +// Copyright (C) MongoDB, Inc. 2022-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + package mongo import ( diff --git a/backend/vendor/go.mongodb.org/mongo-driver/mongo/bulk_write.go b/backend/vendor/go.mongodb.org/mongo-driver/mongo/bulk_write.go index e748ced6a5..2c58f22294 100644 --- a/backend/vendor/go.mongodb.org/mongo-driver/mongo/bulk_write.go +++ b/backend/vendor/go.mongodb.org/mongo-driver/mongo/bulk_write.go @@ -27,6 +27,7 @@ type bulkWriteBatch struct { // bulkWrite perfoms a bulkwrite operation type bulkWrite struct { + comment interface{} ordered *bool bypassDocumentValidation *bool models []WriteModel @@ -178,7 +179,14 @@ func (bw *bulkWrite) runInsert(ctx context.Context, batch bulkWriteBatch) (opera ServerSelector(bw.selector).ClusterClock(bw.collection.client.clock). Database(bw.collection.db.name).Collection(bw.collection.name). Deployment(bw.collection.client.deployment).Crypt(bw.collection.client.cryptFLE). - ServerAPI(bw.collection.client.serverAPI) + ServerAPI(bw.collection.client.serverAPI).Timeout(bw.collection.client.timeout) + if bw.comment != nil { + comment, err := transformValue(bw.collection.registry, bw.comment, true, "comment") + if err != nil { + return op.Result(), err + } + op.Comment(comment) + } if bw.bypassDocumentValidation != nil && *bw.bypassDocumentValidation { op = op.BypassDocumentValidation(*bw.bypassDocumentValidation) } @@ -228,7 +236,14 @@ func (bw *bulkWrite) runDelete(ctx context.Context, batch bulkWriteBatch) (opera ServerSelector(bw.selector).ClusterClock(bw.collection.client.clock). Database(bw.collection.db.name).Collection(bw.collection.name). Deployment(bw.collection.client.deployment).Crypt(bw.collection.client.cryptFLE).Hint(hasHint). - ServerAPI(bw.collection.client.serverAPI) + ServerAPI(bw.collection.client.serverAPI).Timeout(bw.collection.client.timeout) + if bw.comment != nil { + comment, err := transformValue(bw.collection.registry, bw.comment, true, "comment") + if err != nil { + return op.Result(), err + } + op.Comment(comment) + } if bw.let != nil { let, err := transformBsoncoreDocument(bw.collection.registry, bw.let, true, "let") if err != nil { @@ -316,7 +331,14 @@ func (bw *bulkWrite) runUpdate(ctx context.Context, batch bulkWriteBatch) (opera ServerSelector(bw.selector).ClusterClock(bw.collection.client.clock). Database(bw.collection.db.name).Collection(bw.collection.name). Deployment(bw.collection.client.deployment).Crypt(bw.collection.client.cryptFLE).Hint(hasHint). - ArrayFilters(hasArrayFilters).ServerAPI(bw.collection.client.serverAPI) + ArrayFilters(hasArrayFilters).ServerAPI(bw.collection.client.serverAPI).Timeout(bw.collection.client.timeout) + if bw.comment != nil { + comment, err := transformValue(bw.collection.registry, bw.comment, true, "comment") + if err != nil { + return op.Result(), err + } + op.Comment(comment) + } if bw.let != nil { let, err := transformBsoncoreDocument(bw.collection.registry, bw.let, true, "let") if err != nil { @@ -395,7 +417,6 @@ func createUpdateDoc( } updateDoc, _ = bsoncore.AppendDocumentEnd(updateDoc, uidx) - return updateDoc, nil } diff --git a/backend/vendor/go.mongodb.org/mongo-driver/mongo/bulk_write_models.go b/backend/vendor/go.mongodb.org/mongo-driver/mongo/bulk_write_models.go index b4b8e3ef8c..64f4589189 100644 --- a/backend/vendor/go.mongodb.org/mongo-driver/mongo/bulk_write_models.go +++ b/backend/vendor/go.mongodb.org/mongo-driver/mongo/bulk_write_models.go @@ -152,7 +152,7 @@ func (rom *ReplaceOneModel) SetFilter(filter interface{}) *ReplaceOneModel { } // SetReplacement specifies a document that will be used to replace the selected document. It cannot be nil and cannot -// contain any update operators (https://docs.mongodb.com/manual/reference/operator/update/). +// contain any update operators (https://www.mongodb.com/docs/manual/reference/operator/update/). func (rom *ReplaceOneModel) SetReplacement(rep interface{}) *ReplaceOneModel { rom.Replacement = rep return rom @@ -210,7 +210,7 @@ func (uom *UpdateOneModel) SetFilter(filter interface{}) *UpdateOneModel { } // SetUpdate specifies the modifications to be made to the selected document. The value must be a document containing -// update operators (https://docs.mongodb.com/manual/reference/operator/update/). It cannot be nil or empty. +// update operators (https://www.mongodb.com/docs/manual/reference/operator/update/). It cannot be nil or empty. func (uom *UpdateOneModel) SetUpdate(update interface{}) *UpdateOneModel { uom.Update = update return uom @@ -274,7 +274,7 @@ func (umm *UpdateManyModel) SetFilter(filter interface{}) *UpdateManyModel { } // SetUpdate specifies the modifications to be made to the selected documents. The value must be a document containing -// update operators (https://docs.mongodb.com/manual/reference/operator/update/). It cannot be nil or empty. +// update operators (https://www.mongodb.com/docs/manual/reference/operator/update/). It cannot be nil or empty. func (umm *UpdateManyModel) SetUpdate(update interface{}) *UpdateManyModel { umm.Update = update return umm diff --git a/backend/vendor/go.mongodb.org/mongo-driver/mongo/change_stream.go b/backend/vendor/go.mongodb.org/mongo-driver/mongo/change_stream.go index a76eb7c9cb..01da999c02 100644 --- a/backend/vendor/go.mongodb.org/mongo-driver/mongo/change_stream.go +++ b/backend/vendor/go.mongodb.org/mongo-driver/mongo/change_stream.go @@ -17,6 +17,7 @@ import ( "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/bsoncodec" "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/internal" "go.mongodb.org/mongo-driver/mongo/description" "go.mongodb.org/mongo-driver/mongo/options" "go.mongodb.org/mongo-driver/mongo/readconcern" @@ -63,7 +64,7 @@ var ( // ChangeStream is used to iterate over a stream of events. Each event can be decoded into a Go type via the Decode // method or accessed as raw BSON via the Current field. This type is not goroutine safe and must not be used // concurrently by multiple goroutines. For more information about change streams, see -// https://docs.mongodb.com/manual/changeStreams/. +// https://www.mongodb.com/docs/manual/changeStreams/. type ChangeStream struct { // Current is the BSON bytes of the current event. This property is only valid until the next call to Next or // TryNext. If continued access is required, a copy must be made. @@ -132,11 +133,20 @@ func newChangeStream(ctx context.Context, config changeStreamConfig, pipeline in ReadPreference(config.readPreference).ReadConcern(config.readConcern). Deployment(cs.client.deployment).ClusterClock(cs.client.clock). CommandMonitor(cs.client.monitor).Session(cs.sess).ServerSelector(cs.selector).Retry(driver.RetryNone). - ServerAPI(cs.client.serverAPI).Crypt(config.crypt) + ServerAPI(cs.client.serverAPI).Crypt(config.crypt).Timeout(cs.client.timeout) if cs.options.Collation != nil { cs.aggregate.Collation(bsoncore.Document(cs.options.Collation.ToDocument())) } + if comment := cs.options.Comment; comment != nil { + cs.aggregate.Comment(*comment) + + commentVal, err := transformValue(cs.registry, comment, true, "comment") + if err != nil { + return nil, err + } + cs.cursorOptions.Comment = commentVal + } if cs.options.BatchSize != nil { cs.aggregate.BatchSize(*cs.options.BatchSize) cs.cursorOptions.BatchSize = *cs.options.BatchSize @@ -246,7 +256,10 @@ func (cs *ChangeStream) executeOperation(ctx context.Context, resuming bool) err if resuming { cs.replaceOptions(cs.wireVersion) - csOptDoc := cs.createPipelineOptionsDoc() + csOptDoc, err := cs.createPipelineOptionsDoc() + if err != nil { + return err + } pipIdx, pipDoc := bsoncore.AppendDocumentStart(nil) pipDoc = bsoncore.AppendDocumentElement(pipDoc, "$changeStream", csOptDoc) if pipDoc, cs.err = bsoncore.AppendDocumentEnd(pipDoc, pipIdx); cs.err != nil { @@ -261,6 +274,16 @@ func (cs *ChangeStream) executeOperation(ctx context.Context, resuming bool) err cs.aggregate.Pipeline(plArr) } + // If no deadline is set on the passed-in context, cs.client.timeout is set, and context is not already + // a Timeout context, honor cs.client.timeout in new Timeout context for change stream operation execution + // and potential retry. + if _, deadlineSet := ctx.Deadline(); !deadlineSet && cs.client.timeout != nil && !internal.IsTimeoutContext(ctx) { + newCtx, cancelFunc := internal.MakeTimeoutContext(ctx, *cs.client.timeout) + // Redefine ctx to be the new timeout-derived context. + ctx = newCtx + // Cancel the timeout-derived context at the end of executeOperation to avoid a context leak. + defer cancelFunc() + } if original := cs.aggregate.Execute(ctx); original != nil { retryableRead := cs.client.retryReads && cs.wireVersion != nil && cs.wireVersion.Max >= 6 if !retryableRead { @@ -363,9 +386,10 @@ func (cs *ChangeStream) buildPipelineSlice(pipeline interface{}) error { cs.pipelineSlice = make([]bsoncore.Document, 0, val.Len()+1) csIdx, csDoc := bsoncore.AppendDocumentStart(nil) - csDocTemp := cs.createPipelineOptionsDoc() - if cs.err != nil { - return cs.err + + csDocTemp, err := cs.createPipelineOptionsDoc() + if err != nil { + return err } csDoc = bsoncore.AppendDocumentElement(csDoc, "$changeStream", csDocTemp) csDoc, cs.err = bsoncore.AppendDocumentEnd(csDoc, csIdx) @@ -387,7 +411,7 @@ func (cs *ChangeStream) buildPipelineSlice(pipeline interface{}) error { return cs.err } -func (cs *ChangeStream) createPipelineOptionsDoc() bsoncore.Document { +func (cs *ChangeStream) createPipelineOptionsDoc() (bsoncore.Document, error) { plDocIdx, plDoc := bsoncore.AppendDocumentStart(nil) if cs.streamType == ClientStream { @@ -395,24 +419,37 @@ func (cs *ChangeStream) createPipelineOptionsDoc() bsoncore.Document { } if cs.options.FullDocument != nil { - plDoc = bsoncore.AppendStringElement(plDoc, "fullDocument", string(*cs.options.FullDocument)) + // Only append a default "fullDocument" field if wire version is less than 6 (3.6). Otherwise, + // the server will assume users want the default behavior, and "fullDocument" does not need to be + // specified. + if *cs.options.FullDocument != options.Default || (cs.wireVersion != nil && cs.wireVersion.Max < 6) { + plDoc = bsoncore.AppendStringElement(plDoc, "fullDocument", string(*cs.options.FullDocument)) + } + } + + if cs.options.FullDocumentBeforeChange != nil { + plDoc = bsoncore.AppendStringElement(plDoc, "fullDocumentBeforeChange", string(*cs.options.FullDocumentBeforeChange)) } if cs.options.ResumeAfter != nil { var raDoc bsoncore.Document raDoc, cs.err = transformBsoncoreDocument(cs.registry, cs.options.ResumeAfter, true, "resumeAfter") if cs.err != nil { - return nil + return nil, cs.err } plDoc = bsoncore.AppendDocumentElement(plDoc, "resumeAfter", raDoc) } + if cs.options.ShowExpandedEvents != nil { + plDoc = bsoncore.AppendBooleanElement(plDoc, "showExpandedEvents", *cs.options.ShowExpandedEvents) + } + if cs.options.StartAfter != nil { var saDoc bsoncore.Document saDoc, cs.err = transformBsoncoreDocument(cs.registry, cs.options.StartAfter, true, "startAfter") if cs.err != nil { - return nil + return nil, cs.err } plDoc = bsoncore.AppendDocumentElement(plDoc, "startAfter", saDoc) @@ -428,10 +465,10 @@ func (cs *ChangeStream) createPipelineOptionsDoc() bsoncore.Document { } if plDoc, cs.err = bsoncore.AppendDocumentEnd(plDoc, plDocIdx); cs.err != nil { - return nil + return nil, cs.err } - return plDoc + return plDoc, nil } func (cs *ChangeStream) pipelineToBSON() (bsoncore.Document, error) { diff --git a/backend/vendor/go.mongodb.org/mongo-driver/mongo/change_stream_deployment.go b/backend/vendor/go.mongodb.org/mongo-driver/mongo/change_stream_deployment.go index 36c6e2547a..9c61123c36 100644 --- a/backend/vendor/go.mongodb.org/mongo-driver/mongo/change_stream_deployment.go +++ b/backend/vendor/go.mongodb.org/mongo-driver/mongo/change_stream_deployment.go @@ -40,6 +40,10 @@ func (c *changeStreamDeployment) MinRTT() time.Duration { return c.server.MinRTT() } +func (c *changeStreamDeployment) RTT90() time.Duration { + return c.server.RTT90() +} + func (c *changeStreamDeployment) ProcessError(err error, conn driver.Connection) driver.ProcessErrorResult { ep, ok := c.server.(driver.ErrorProcessor) if !ok { diff --git a/backend/vendor/go.mongodb.org/mongo-driver/mongo/client.go b/backend/vendor/go.mongodb.org/mongo-driver/mongo/client.go index ddc08bd5f0..d409135a77 100644 --- a/backend/vendor/go.mongodb.org/mongo-driver/mongo/client.go +++ b/backend/vendor/go.mongodb.org/mongo-driver/mongo/client.go @@ -17,6 +17,7 @@ import ( "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/bsoncodec" "go.mongodb.org/mongo-driver/event" + "go.mongodb.org/mongo-driver/internal/uuid" "go.mongodb.org/mongo-driver/mongo/description" "go.mongodb.org/mongo-driver/mongo/options" "go.mongodb.org/mongo-driver/mongo/readconcern" @@ -25,14 +26,18 @@ import ( "go.mongodb.org/mongo-driver/x/bsonx/bsoncore" "go.mongodb.org/mongo-driver/x/mongo/driver" "go.mongodb.org/mongo-driver/x/mongo/driver/auth" + "go.mongodb.org/mongo-driver/x/mongo/driver/mongocrypt" + mcopts "go.mongodb.org/mongo-driver/x/mongo/driver/mongocrypt/options" "go.mongodb.org/mongo-driver/x/mongo/driver/ocsp" "go.mongodb.org/mongo-driver/x/mongo/driver/operation" "go.mongodb.org/mongo-driver/x/mongo/driver/session" "go.mongodb.org/mongo-driver/x/mongo/driver/topology" - "go.mongodb.org/mongo-driver/x/mongo/driver/uuid" ) -const defaultLocalThreshold = 15 * time.Millisecond +const ( + defaultLocalThreshold = 15 * time.Millisecond + defaultMaxPoolSize uint64 = 100 +) var ( // keyVaultCollOpts specifies options used to communicate with the key vault collection @@ -63,14 +68,16 @@ type Client struct { serverAPI *driver.ServerAPIOptions serverMonitor *event.ServerMonitor sessionPool *session.Pool + timeout *time.Duration // client-side encryption fields - keyVaultClientFLE *Client - keyVaultCollFLE *Collection - mongocryptdFLE *mcryptClient - cryptFLE driver.Crypt - metadataClientFLE *Client - internalClientFLE *Client + keyVaultClientFLE *Client + keyVaultCollFLE *Collection + mongocryptdFLE *mongocryptdClient + cryptFLE driver.Crypt + metadataClientFLE *Client + internalClientFLE *Client + encryptedFieldsMap map[string]interface{} } // Connect creates a new Client and then initializes it using the Connect method. This is equivalent to calling @@ -271,6 +278,9 @@ func (c *Client) Ping(ctx context.Context, rp *readpref.ReadPref) error { // StartSession does not actually communicate with the server and will not error if the client is // disconnected. // +// StartSession is safe to call from multiple goroutines concurrently. However, Sessions returned by StartSession are +// not safe for concurrent use by multiple goroutines. +// // If the DefaultReadConcern, DefaultWriteConcern, or DefaultReadPreference options are not set, the client's read // concern, write concern, or read preference will be used, respectively. func (c *Client) StartSession(opts ...*options.SessionOptions) (Session, error) { @@ -348,6 +358,12 @@ func (c *Client) endSessions(ctx context.Context) { } func (c *Client) configure(opts *options.ClientOptions) error { + var defaultOptions int + // Set default options + if opts.MaxPoolSize == nil { + defaultOptions++ + opts.SetMaxPoolSize(defaultMaxPoolSize) + } if err := opts.Validate(); err != nil { return err } @@ -624,6 +640,8 @@ func (c *Client) configure(opts *options.ClientOptions) error { topology.WithWriteTimeout(func(time.Duration) time.Duration { return *opts.SocketTimeout }), ) } + // Timeout + c.timeout = opts.Timeout // TLSConfig if opts.TLSConfig != nil { connOpts = append(connOpts, topology.WithTLSConfig( @@ -681,15 +699,16 @@ func (c *Client) configure(opts *options.ClientOptions) error { topology.WithClock(func(*session.ClusterClock) *session.ClusterClock { return c.clock }), topology.WithConnectionOptions(func(...topology.ConnectionOption) []topology.ConnectionOption { return connOpts }), ) - c.topologyOptions = append(topologyOpts, topology.WithServerOptions( + topologyOpts = append(topologyOpts, topology.WithServerOptions( func(...topology.ServerOption) []topology.ServerOption { return serverOpts }, )) + c.topologyOptions = topologyOpts // Deployment if opts.Deployment != nil { - // topology options: WithSeedlist, WithURI, WithSRVServiceName and WithSRVMaxHosts - // server options: WithClock and WithConnectionOptions - if len(serverOpts) > 2 || len(topologyOpts) > 4 { + // topology options: WithSeedlist, WithURI, WithSRVServiceName, WithSRVMaxHosts, and WithServerOptions + // server options: WithClock and WithConnectionOptions + default maxPoolSize + if len(serverOpts) > 2+defaultOptions || len(topologyOpts) > 5 { return errors.New("cannot specify topology or server options with a deployment") } c.deployment = opts.Deployment @@ -699,16 +718,30 @@ func (c *Client) configure(opts *options.ClientOptions) error { } func (c *Client) configureAutoEncryption(clientOpts *options.ClientOptions) error { + c.encryptedFieldsMap = clientOpts.AutoEncryptionOptions.EncryptedFieldsMap if err := c.configureKeyVaultClientFLE(clientOpts); err != nil { return err } if err := c.configureMetadataClientFLE(clientOpts); err != nil { return err } - if err := c.configureMongocryptdClientFLE(clientOpts.AutoEncryptionOptions); err != nil { + + mc, err := c.newMongoCrypt(clientOpts.AutoEncryptionOptions) + if err != nil { return err } - return c.configureCryptFLE(clientOpts.AutoEncryptionOptions) + + // If the crypt_shared library was loaded successfully, signal to the mongocryptd client creator + // that it can bypass spawning mongocryptd. + cryptSharedLibAvailable := mc.CryptSharedLibVersionString() != "" + mongocryptdFLE, err := newMongocryptdClient(cryptSharedLibAvailable, clientOpts.AutoEncryptionOptions) + if err != nil { + return err + } + c.mongocryptdFLE = mongocryptdFLE + + c.configureCryptFLE(mc, clientOpts.AutoEncryptionOptions) + return nil } func (c *Client) getOrCreateInternalClient(clientOpts *options.ClientOptions) (*Client, error) { @@ -763,32 +796,90 @@ func (c *Client) configureMetadataClientFLE(clientOpts *options.ClientOptions) e return err } -func (c *Client) configureMongocryptdClientFLE(opts *options.AutoEncryptionOptions) error { - var err error - c.mongocryptdFLE, err = newMcryptClient(opts) - return err -} - -func (c *Client) configureCryptFLE(opts *options.AutoEncryptionOptions) error { +func (c *Client) newMongoCrypt(opts *options.AutoEncryptionOptions) (*mongocrypt.MongoCrypt, error) { // convert schemas in SchemaMap to bsoncore documents cryptSchemaMap := make(map[string]bsoncore.Document) for k, v := range opts.SchemaMap { schema, err := transformBsoncoreDocument(c.registry, v, true, "schemaMap") if err != nil { - return err + return nil, err } cryptSchemaMap[k] = schema } + + // convert schemas in EncryptedFieldsMap to bsoncore documents + cryptEncryptedFieldsMap := make(map[string]bsoncore.Document) + for k, v := range opts.EncryptedFieldsMap { + encryptedFields, err := transformBsoncoreDocument(c.registry, v, true, "encryptedFieldsMap") + if err != nil { + return nil, err + } + cryptEncryptedFieldsMap[k] = encryptedFields + } + kmsProviders, err := transformBsoncoreDocument(c.registry, opts.KmsProviders, true, "kmsProviders") if err != nil { - return fmt.Errorf("error creating KMS providers document: %v", err) + return nil, fmt.Errorf("error creating KMS providers document: %v", err) + } + + // Set the crypt_shared library override path from the "cryptSharedLibPath" extra option if one + // was set. + cryptSharedLibPath := "" + if val, ok := opts.ExtraOptions["cryptSharedLibPath"]; ok { + str, ok := val.(string) + if !ok { + return nil, fmt.Errorf( + `expected AutoEncryption extra option "cryptSharedLibPath" to be a string, but is a %T`, val) + } + cryptSharedLibPath = str + } + + // Explicitly disable loading the crypt_shared library if requested. Note that this is ONLY + // intended for use from tests; there is no supported public API for explicitly disabling + // loading the crypt_shared library. + cryptSharedLibDisabled := false + if v, ok := opts.ExtraOptions["__cryptSharedLibDisabledForTestOnly"]; ok { + cryptSharedLibDisabled = v.(bool) + } + + bypassAutoEncryption := opts.BypassAutoEncryption != nil && *opts.BypassAutoEncryption + bypassQueryAnalysis := opts.BypassQueryAnalysis != nil && *opts.BypassQueryAnalysis + + mc, err := mongocrypt.NewMongoCrypt(mcopts.MongoCrypt(). + SetKmsProviders(kmsProviders). + SetLocalSchemaMap(cryptSchemaMap). + SetBypassQueryAnalysis(bypassQueryAnalysis). + SetEncryptedFieldsMap(cryptEncryptedFieldsMap). + SetCryptSharedLibDisabled(cryptSharedLibDisabled || bypassAutoEncryption). + SetCryptSharedLibOverridePath(cryptSharedLibPath)) + if err != nil { + return nil, err + } + + var cryptSharedLibRequired bool + if val, ok := opts.ExtraOptions["cryptSharedLibRequired"]; ok { + b, ok := val.(bool) + if !ok { + return nil, fmt.Errorf( + `expected AutoEncryption extra option "cryptSharedLibRequired" to be a bool, but is a %T`, val) + } + cryptSharedLibRequired = b } - // configure options - var bypass bool - if opts.BypassAutoEncryption != nil { - bypass = *opts.BypassAutoEncryption + // If the "cryptSharedLibRequired" extra option is set to true, check the MongoCrypt version + // string to confirm that the library was successfully loaded. If the version string is empty, + // return an error indicating that we couldn't load the crypt_shared library. + if cryptSharedLibRequired && mc.CryptSharedLibVersionString() == "" { + return nil, errors.New( + `AutoEncryption extra option "cryptSharedLibRequired" is true, but we failed to load the crypt_shared library`) } + + return mc, nil +} + +//nolint:unused // the unused linter thinks that this function is unreachable because "c.newMongoCrypt" always panics without the "cse" build tag set. +func (c *Client) configureCryptFLE(mc *mongocrypt.MongoCrypt, opts *options.AutoEncryptionOptions) { + bypass := opts.BypassAutoEncryption != nil && *opts.BypassAutoEncryption kr := keyRetriever{coll: c.keyVaultCollFLE} var cir collInfoRetriever // If bypass is true, c.metadataClientFLE is nil and the collInfoRetriever @@ -798,23 +889,19 @@ func (c *Client) configureCryptFLE(opts *options.AutoEncryptionOptions) error { cir = collInfoRetriever{client: c.metadataClientFLE} } - cryptOpts := &driver.CryptOptions{ + c.cryptFLE = driver.NewCrypt(&driver.CryptOptions{ + MongoCrypt: mc, CollInfoFn: cir.cryptCollInfo, KeyFn: kr.cryptKeys, MarkFn: c.mongocryptdFLE.markCommand, - KmsProviders: kmsProviders, TLSConfig: opts.TLSConfig, BypassAutoEncryption: bypass, - SchemaMap: cryptSchemaMap, - } - - c.cryptFLE, err = driver.NewCrypt(cryptOpts) - return err + }) } // validSession returns an error if the session doesn't belong to the client func (c *Client) validSession(sess *session.Client) error { - if sess != nil && !uuid.Equal(sess.ClientID, c.id) { + if sess != nil && sess.ClientID != c.id { return ErrWrongClient } return nil @@ -845,7 +932,7 @@ func (c *Client) Database(name string, opts ...*options.DatabaseOptions) *Databa // // The opts parameter can be used to specify options for this operation (see the options.ListDatabasesOptions documentation). // -// For more information about the command, see https://docs.mongodb.com/manual/reference/command/listDatabases/. +// For more information about the command, see https://www.mongodb.com/docs/manual/reference/command/listDatabases/. func (c *Client) ListDatabases(ctx context.Context, filter interface{}, opts ...*options.ListDatabasesOptions) (ListDatabasesResult, error) { if ctx == nil { ctx = context.Background() @@ -885,7 +972,7 @@ func (c *Client) ListDatabases(ctx context.Context, filter interface{}, opts ... op := operation.NewListDatabases(filterDoc). Session(sess).ReadPreference(c.readPreference).CommandMonitor(c.monitor). ServerSelector(selector).ClusterClock(c.clock).Database("admin").Deployment(c.deployment).Crypt(c.cryptFLE). - ServerAPI(c.serverAPI) + ServerAPI(c.serverAPI).Timeout(c.timeout) if ldo.NameOnly != nil { op = op.NameOnly(*ldo.NameOnly) @@ -918,7 +1005,7 @@ func (c *Client) ListDatabases(ctx context.Context, filter interface{}, opts ... // The opts parameter can be used to specify options for this operation (see the options.ListDatabasesOptions // documentation.) // -// For more information about the command, see https://docs.mongodb.com/manual/reference/command/listDatabases/. +// For more information about the command, see https://www.mongodb.com/docs/manual/reference/command/listDatabases/. func (c *Client) ListDatabaseNames(ctx context.Context, filter interface{}, opts ...*options.ListDatabasesOptions) ([]string, error) { opts = append(opts, options.ListDatabases().SetNameOnly(true)) @@ -939,6 +1026,9 @@ func (c *Client) ListDatabaseNames(ctx context.Context, filter interface{}, opts // SessionContext must be used as the Context parameter for any operations in the fn callback that should be executed // under the session. // +// WithSession is safe to call from multiple goroutines concurrently. However, the SessionContext passed to the +// WithSession callback function is not safe for concurrent use by multiple goroutines. +// // If the ctx parameter already contains a Session, that Session will be replaced with the one provided. // // Any error returned by the fn callback will be returned without any modifications. @@ -951,6 +1041,9 @@ func WithSession(ctx context.Context, sess Session, fn func(SessionContext) erro // be executed under a session. After the callback returns, the created Session is ended, meaning that any in-progress // transactions started by fn will be aborted even if fn returns an error. // +// UseSession is safe to call from multiple goroutines concurrently. However, the SessionContext passed to the +// UseSession callback function is not safe for concurrent use by multiple goroutines. +// // If the ctx parameter already contains a Session, that Session will be replaced with the newly created one. // // Any error returned by the fn callback will be returned without any modifications. @@ -959,6 +1052,9 @@ func (c *Client) UseSession(ctx context.Context, fn func(SessionContext) error) } // UseSessionWithOptions operates like UseSession but uses the given SessionOptions to create the Session. +// +// UseSessionWithOptions is safe to call from multiple goroutines concurrently. However, the SessionContext passed to +// the UseSessionWithOptions callback function is not safe for concurrent use by multiple goroutines. func (c *Client) UseSessionWithOptions(ctx context.Context, opts *options.SessionOptions, fn func(SessionContext) error) error { defaultSess, err := c.StartSession(opts) if err != nil { @@ -970,13 +1066,13 @@ func (c *Client) UseSessionWithOptions(ctx context.Context, opts *options.Sessio } // Watch returns a change stream for all changes on the deployment. See -// https://docs.mongodb.com/manual/changeStreams/ for more information about change streams. +// https://www.mongodb.com/docs/manual/changeStreams/ for more information about change streams. // // The client must be configured with read concern majority or no read concern for a change stream to be created // successfully. // // The pipeline parameter must be an array of documents, each representing a pipeline stage. The pipeline cannot be -// nil or empty. The stage documents must all be non-nil. See https://docs.mongodb.com/manual/changeStreams/ for a list +// nil or empty. The stage documents must all be non-nil. See https://www.mongodb.com/docs/manual/changeStreams/ for a list // of pipeline stages that can be used with change streams. For a pipeline of bson.D documents, the mongo.Pipeline{} // type can be used. // diff --git a/backend/vendor/go.mongodb.org/mongo-driver/mongo/client_encryption.go b/backend/vendor/go.mongodb.org/mongo-driver/mongo/client_encryption.go index fe4646b641..a9794d60ba 100644 --- a/backend/vendor/go.mongodb.org/mongo-driver/mongo/client_encryption.go +++ b/backend/vendor/go.mongodb.org/mongo-driver/mongo/client_encryption.go @@ -17,7 +17,8 @@ import ( "go.mongodb.org/mongo-driver/mongo/options" "go.mongodb.org/mongo-driver/x/bsonx/bsoncore" "go.mongodb.org/mongo-driver/x/mongo/driver" - cryptOpts "go.mongodb.org/mongo-driver/x/mongo/driver/mongocrypt/options" + "go.mongodb.org/mongo-driver/x/mongo/driver/mongocrypt" + mcopts "go.mongodb.org/mongo-driver/x/mongo/driver/mongocrypt/options" ) // ClientEncryption is used to create data keys and explicitly encrypt and decrypt BSON values. @@ -47,36 +48,56 @@ func NewClientEncryption(keyVaultClient *Client, opts ...*options.ClientEncrypti return nil, fmt.Errorf("error creating KMS providers map: %v", err) } + mc, err := mongocrypt.NewMongoCrypt(mcopts.MongoCrypt(). + SetKmsProviders(kmsProviders). + // Explicitly disable loading the crypt_shared library for the Crypt used for + // ClientEncryption because it's only needed for AutoEncryption and we don't expect users to + // have the crypt_shared library installed if they're using ClientEncryption. + SetCryptSharedLibDisabled(true)) + if err != nil { + return nil, err + } + // create Crypt kr := keyRetriever{coll: ce.keyVaultColl} cir := collInfoRetriever{client: ce.keyVaultClient} - ce.crypt, err = driver.NewCrypt(&driver.CryptOptions{ - KeyFn: kr.cryptKeys, - CollInfoFn: cir.cryptCollInfo, - KmsProviders: kmsProviders, - TLSConfig: ceo.TLSConfig, + ce.crypt = driver.NewCrypt(&driver.CryptOptions{ + MongoCrypt: mc, + KeyFn: kr.cryptKeys, + CollInfoFn: cir.cryptCollInfo, + TLSConfig: ceo.TLSConfig, }) - if err != nil { - return nil, err - } return ce, nil } -// CreateDataKey creates a new key document and inserts it into the key vault collection. Returns the _id of the -// created document. -func (ce *ClientEncryption) CreateDataKey(ctx context.Context, kmsProvider string, opts ...*options.DataKeyOptions) (primitive.Binary, error) { - // translate opts to cryptOpts.DataKeyOptions +// AddKeyAltName adds a keyAltName to the keyAltNames array of the key document in the key vault collection with the +// given UUID (BSON binary subtype 0x04). Returns the previous version of the key document. +func (ce *ClientEncryption) AddKeyAltName(ctx context.Context, id primitive.Binary, keyAltName string) *SingleResult { + filter := bsoncore.NewDocumentBuilder().AppendBinary("_id", id.Subtype, id.Data).Build() + keyAltNameDoc := bsoncore.NewDocumentBuilder().AppendString("keyAltNames", keyAltName).Build() + update := bsoncore.NewDocumentBuilder().AppendDocument("$addToSet", keyAltNameDoc).Build() + return ce.keyVaultColl.FindOneAndUpdate(ctx, filter, update) +} + +// CreateDataKey creates a new key document and inserts into the key vault collection. Returns the _id of the created +// document as a UUID (BSON binary subtype 0x04). +func (ce *ClientEncryption) CreateDataKey(ctx context.Context, kmsProvider string, + opts ...*options.DataKeyOptions) (primitive.Binary, error) { + + // translate opts to mcopts.DataKeyOptions dko := options.MergeDataKeyOptions(opts...) - co := cryptOpts.DataKey().SetKeyAltNames(dko.KeyAltNames) + co := mcopts.DataKey().SetKeyAltNames(dko.KeyAltNames) if dko.MasterKey != nil { keyDoc, err := transformBsoncoreDocument(ce.keyVaultClient.registry, dko.MasterKey, true, "masterKey") if err != nil { return primitive.Binary{}, err } - co.SetMasterKey(keyDoc) } + if dko.KeyMaterial != nil { + co.SetKeyMaterial(dko.KeyMaterial) + } // create data key document dataKeyDoc, err := ce.crypt.CreateDataKey(ctx, kmsProvider, co) @@ -95,9 +116,11 @@ func (ce *ClientEncryption) CreateDataKey(ctx context.Context, kmsProvider strin } // Encrypt encrypts a BSON value with the given key and algorithm. Returns an encrypted value (BSON binary of subtype 6). -func (ce *ClientEncryption) Encrypt(ctx context.Context, val bson.RawValue, opts ...*options.EncryptOptions) (primitive.Binary, error) { +func (ce *ClientEncryption) Encrypt(ctx context.Context, val bson.RawValue, + opts ...*options.EncryptOptions) (primitive.Binary, error) { + eo := options.MergeEncryptOptions(opts...) - transformed := cryptOpts.ExplicitEncryption() + transformed := mcopts.ExplicitEncryption() if eo.KeyID != nil { transformed.SetKeyID(*eo.KeyID) } @@ -105,6 +128,11 @@ func (ce *ClientEncryption) Encrypt(ctx context.Context, val bson.RawValue, opts transformed.SetKeyAltName(*eo.KeyAltName) } transformed.SetAlgorithm(eo.Algorithm) + transformed.SetQueryType(eo.QueryType) + + if eo.ContentionFactor != nil { + transformed.SetContentionFactor(*eo.ContentionFactor) + } subtype, data, err := ce.crypt.EncryptExplicit(ctx, bsoncore.Value{Type: val.Type, Data: val.Value}, transformed) if err != nil { @@ -130,6 +158,151 @@ func (ce *ClientEncryption) Close(ctx context.Context) error { return ce.keyVaultClient.Disconnect(ctx) } +// DeleteKey removes the key document with the given UUID (BSON binary subtype 0x04) from the key vault collection. +// Returns the result of the internal deleteOne() operation on the key vault collection. +func (ce *ClientEncryption) DeleteKey(ctx context.Context, id primitive.Binary) (*DeleteResult, error) { + filter := bsoncore.NewDocumentBuilder().AppendBinary("_id", id.Subtype, id.Data).Build() + return ce.keyVaultColl.DeleteOne(ctx, filter) +} + +// GetKeyByAltName returns a key document in the key vault collection with the given keyAltName. +func (ce *ClientEncryption) GetKeyByAltName(ctx context.Context, keyAltName string) *SingleResult { + filter := bsoncore.NewDocumentBuilder().AppendString("keyAltNames", keyAltName).Build() + return ce.keyVaultColl.FindOne(ctx, filter) +} + +// GetKey finds a single key document with the given UUID (BSON binary subtype 0x04). Returns the result of the +// internal find() operation on the key vault collection. +func (ce *ClientEncryption) GetKey(ctx context.Context, id primitive.Binary) *SingleResult { + filter := bsoncore.NewDocumentBuilder().AppendBinary("_id", id.Subtype, id.Data).Build() + return ce.keyVaultColl.FindOne(ctx, filter) +} + +// GetKeys finds all documents in the key vault collection. Returns the result of the internal find() operation on the +// key vault collection. +func (ce *ClientEncryption) GetKeys(ctx context.Context) (*Cursor, error) { + return ce.keyVaultColl.Find(ctx, bson.D{}) +} + +// RemoveKeyAltName removes a keyAltName from the keyAltNames array of the key document in the key vault collection with +// the given UUID (BSON binary subtype 0x04). Returns the previous version of the key document. +func (ce *ClientEncryption) RemoveKeyAltName(ctx context.Context, id primitive.Binary, keyAltName string) *SingleResult { + filter := bsoncore.NewDocumentBuilder().AppendBinary("_id", id.Subtype, id.Data).Build() + update := bson.A{bson.D{{"$set", bson.D{{"keyAltNames", bson.D{{"$cond", bson.A{bson.D{{"$eq", + bson.A{"$keyAltNames", bson.A{keyAltName}}}}, "$$REMOVE", bson.D{{"$filter", + bson.D{{"input", "$keyAltNames"}, {"cond", bson.D{{"$ne", bson.A{"$$this", keyAltName}}}}}}}}}}}}}}} + return ce.keyVaultColl.FindOneAndUpdate(ctx, filter, update) +} + +// setRewrapManyDataKeyWriteModels will prepare the WriteModel slice for a bulk updating rewrapped documents. +func setRewrapManyDataKeyWriteModels(rewrappedDocuments []bsoncore.Document, writeModels *[]WriteModel) error { + const idKey = "_id" + const keyMaterial = "keyMaterial" + const masterKey = "masterKey" + + if writeModels == nil { + return fmt.Errorf("writeModels pointer not set for location referenced") + } + + // Append a slice of WriteModel with the update document per each rewrappedDoc _id filter. + for _, rewrappedDocument := range rewrappedDocuments { + // Prepare the new master key for update. + masterKeyValue, err := rewrappedDocument.LookupErr(masterKey) + if err != nil { + return err + } + masterKeyDoc := masterKeyValue.Document() + + // Prepare the new material key for update. + keyMaterialValue, err := rewrappedDocument.LookupErr(keyMaterial) + if err != nil { + return err + } + keyMaterialSubtype, keyMaterialData := keyMaterialValue.Binary() + keyMaterialBinary := primitive.Binary{Subtype: keyMaterialSubtype, Data: keyMaterialData} + + // Prepare the _id filter for documents to update. + id, err := rewrappedDocument.LookupErr(idKey) + if err != nil { + return err + } + + idSubtype, idData, ok := id.BinaryOK() + if !ok { + return fmt.Errorf("expected to assert %q as binary, got type %T", idKey, id) + } + binaryID := primitive.Binary{Subtype: idSubtype, Data: idData} + + // Append the mutable document to the slice for bulk update. + *writeModels = append(*writeModels, NewUpdateOneModel(). + SetFilter(bson.D{{idKey, binaryID}}). + SetUpdate( + bson.D{ + {"$set", bson.D{{keyMaterial, keyMaterialBinary}, {masterKey, masterKeyDoc}}}, + {"$currentDate", bson.D{{"updateDate", true}}}, + }, + )) + } + return nil +} + +// RewrapManyDataKey decrypts and encrypts all matching data keys with a possibly new masterKey value. For all +// matching documents, this method will overwrite the "masterKey", "updateDate", and "keyMaterial". On error, some +// matching data keys may have been rewrapped. +// libmongocrypt 1.5.2 is required. An error is returned if the detected version of libmongocrypt is less than 1.5.2. +func (ce *ClientEncryption) RewrapManyDataKey(ctx context.Context, filter interface{}, + opts ...*options.RewrapManyDataKeyOptions) (*RewrapManyDataKeyResult, error) { + + // libmongocrypt versions 1.5.0 and 1.5.1 have a severe bug in RewrapManyDataKey. + // Check if the version string starts with 1.5.0 or 1.5.1. This accounts for pre-release versions, like 1.5.0-rc0. + libmongocryptVersion := mongocrypt.Version() + if strings.HasPrefix(libmongocryptVersion, "1.5.0") || strings.HasPrefix(libmongocryptVersion, "1.5.1") { + return nil, fmt.Errorf("RewrapManyDataKey requires libmongocrypt 1.5.2 or newer. Detected version: %v", libmongocryptVersion) + } + + rmdko := options.MergeRewrapManyDataKeyOptions(opts...) + if ctx == nil { + ctx = context.Background() + } + + // Transfer rmdko options to /x/ package options to publish the mongocrypt feed. + co := mcopts.RewrapManyDataKey() + if rmdko.MasterKey != nil { + keyDoc, err := transformBsoncoreDocument(ce.keyVaultClient.registry, rmdko.MasterKey, true, "masterKey") + if err != nil { + return nil, err + } + co.SetMasterKey(keyDoc) + } + if rmdko.Provider != nil { + co.SetProvider(*rmdko.Provider) + } + + // Prepare the filters and rewrap the data key using mongocrypt. + filterdoc, err := transformBsoncoreDocument(ce.keyVaultClient.registry, filter, true, "filter") + if err != nil { + return nil, err + } + + rewrappedDocuments, err := ce.crypt.RewrapDataKey(ctx, filterdoc, co) + if err != nil { + return nil, err + } + if len(rewrappedDocuments) == 0 { + // If there are no documents to rewrap, then do nothing. + return new(RewrapManyDataKeyResult), nil + } + + // Prepare the WriteModel slice for bulk updating the rewrapped data keys. + models := []WriteModel{} + if err := setRewrapManyDataKeyWriteModels(rewrappedDocuments, &models); err != nil { + return nil, err + } + + bulkWriteResults, err := ce.keyVaultColl.BulkWrite(ctx, models) + return &RewrapManyDataKeyResult{BulkWriteResult: bulkWriteResults}, err +} + // splitNamespace takes a namespace in the form "database.collection" and returns (database name, collection name) func splitNamespace(ns string) (string, string) { firstDot := strings.Index(ns, ".") diff --git a/backend/vendor/go.mongodb.org/mongo-driver/mongo/collection.go b/backend/vendor/go.mongodb.org/mongo-driver/mongo/collection.go index 590d928045..aa3ffbe958 100644 --- a/backend/vendor/go.mongodb.org/mongo-driver/mongo/collection.go +++ b/backend/vendor/go.mongodb.org/mongo-driver/mongo/collection.go @@ -16,6 +16,7 @@ import ( "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/bsoncodec" "go.mongodb.org/mongo-driver/bson/bsontype" + "go.mongodb.org/mongo-driver/internal" "go.mongodb.org/mongo-driver/mongo/description" "go.mongodb.org/mongo-driver/mongo/options" "go.mongodb.org/mongo-driver/mongo/readconcern" @@ -166,7 +167,7 @@ func (coll *Collection) Database() *Database { return coll.db } -// BulkWrite performs a bulk write operation (https://docs.mongodb.com/manual/core/bulk-write-operations/). +// BulkWrite performs a bulk write operation (https://www.mongodb.com/docs/manual/core/bulk-write-operations/). // // The models parameter must be a slice of operations to be executed in this bulk write. It cannot be nil or empty. // All of the models must be non-nil. See the mongo.WriteModel documentation for a list of valid model types and @@ -218,6 +219,7 @@ func (coll *Collection) BulkWrite(ctx context.Context, models []WriteModel, bwo := options.MergeBulkWriteOptions(opts...) op := bulkWrite{ + comment: bwo.Comment, ordered: bwo.Ordered, bypassDocumentValidation: bwo.BypassDocumentValidation, models: models, @@ -281,11 +283,18 @@ func (coll *Collection) insert(ctx context.Context, documents []interface{}, ServerSelector(selector).ClusterClock(coll.client.clock). Database(coll.db.name).Collection(coll.name). Deployment(coll.client.deployment).Crypt(coll.client.cryptFLE).Ordered(true). - ServerAPI(coll.client.serverAPI) + ServerAPI(coll.client.serverAPI).Timeout(coll.client.timeout) imo := options.MergeInsertManyOptions(opts...) if imo.BypassDocumentValidation != nil && *imo.BypassDocumentValidation { op = op.BypassDocumentValidation(*imo.BypassDocumentValidation) } + if imo.Comment != nil { + comment, err := transformValue(coll.registry, imo.Comment, true, "comment") + if err != nil { + return nil, err + } + op = op.Comment(comment) + } if imo.Ordered != nil { op = op.Ordered(*imo.Ordered) } @@ -324,7 +333,7 @@ func (coll *Collection) insert(ctx context.Context, documents []interface{}, // // The opts parameter can be used to specify options for the operation (see the options.InsertOneOptions documentation.) // -// For more information about the command, see https://docs.mongodb.com/manual/reference/command/insert/. +// For more information about the command, see https://www.mongodb.com/docs/manual/reference/command/insert/. func (coll *Collection) InsertOne(ctx context.Context, document interface{}, opts ...*options.InsertOneOptions) (*InsertOneResult, error) { @@ -334,6 +343,9 @@ func (coll *Collection) InsertOne(ctx context.Context, document interface{}, if ioOpts.BypassDocumentValidation != nil && *ioOpts.BypassDocumentValidation { imOpts.SetBypassDocumentValidation(*ioOpts.BypassDocumentValidation) } + if ioOpts.Comment != nil { + imOpts.SetComment(ioOpts.Comment) + } res, err := coll.insert(ctx, []interface{}{document}, imOpts) rr, err := processWriteError(err) @@ -353,7 +365,7 @@ func (coll *Collection) InsertOne(ctx context.Context, document interface{}, // // The opts parameter can be used to specify options for the operation (see the options.InsertManyOptions documentation.) // -// For more information about the command, see https://docs.mongodb.com/manual/reference/command/insert/. +// For more information about the command, see https://www.mongodb.com/docs/manual/reference/command/insert/. func (coll *Collection) InsertMany(ctx context.Context, documents []interface{}, opts ...*options.InsertManyOptions) (*InsertManyResult, error) { @@ -451,7 +463,14 @@ func (coll *Collection) delete(ctx context.Context, filter interface{}, deleteOn ServerSelector(selector).ClusterClock(coll.client.clock). Database(coll.db.name).Collection(coll.name). Deployment(coll.client.deployment).Crypt(coll.client.cryptFLE).Ordered(true). - ServerAPI(coll.client.serverAPI) + ServerAPI(coll.client.serverAPI).Timeout(coll.client.timeout) + if do.Comment != nil { + comment, err := transformValue(coll.registry, do.Comment, true, "comment") + if err != nil { + return nil, err + } + op = op.Comment(comment) + } if do.Hint != nil { op = op.Hint(true) } @@ -485,7 +504,7 @@ func (coll *Collection) delete(ctx context.Context, filter interface{}, deleteOn // // The opts parameter can be used to specify options for the operation (see the options.DeleteOptions documentation). // -// For more information about the command, see https://docs.mongodb.com/manual/reference/command/delete/. +// For more information about the command, see https://www.mongodb.com/docs/manual/reference/command/delete/. func (coll *Collection) DeleteOne(ctx context.Context, filter interface{}, opts ...*options.DeleteOptions) (*DeleteResult, error) { @@ -501,7 +520,7 @@ func (coll *Collection) DeleteOne(ctx context.Context, filter interface{}, // // The opts parameter can be used to specify options for the operation (see the options.DeleteOptions documentation). // -// For more information about the command, see https://docs.mongodb.com/manual/reference/command/delete/. +// For more information about the command, see https://www.mongodb.com/docs/manual/reference/command/delete/. func (coll *Collection) DeleteMany(ctx context.Context, filter interface{}, opts ...*options.DeleteOptions) (*DeleteResult, error) { @@ -555,7 +574,8 @@ func (coll *Collection) updateOrReplace(ctx context.Context, filter bsoncore.Doc ServerSelector(selector).ClusterClock(coll.client.clock). Database(coll.db.name).Collection(coll.name). Deployment(coll.client.deployment).Crypt(coll.client.cryptFLE).Hint(uo.Hint != nil). - ArrayFilters(uo.ArrayFilters != nil).Ordered(true).ServerAPI(coll.client.serverAPI) + ArrayFilters(uo.ArrayFilters != nil).Ordered(true).ServerAPI(coll.client.serverAPI). + Timeout(coll.client.timeout) if uo.Let != nil { let, err := transformBsoncoreDocument(coll.registry, uo.Let, true, "let") if err != nil { @@ -567,6 +587,13 @@ func (coll *Collection) updateOrReplace(ctx context.Context, filter bsoncore.Doc if uo.BypassDocumentValidation != nil && *uo.BypassDocumentValidation { op = op.BypassDocumentValidation(*uo.BypassDocumentValidation) } + if uo.Comment != nil { + comment, err := transformValue(coll.registry, uo.Comment, true, "comment") + if err != nil { + return nil, err + } + op = op.Comment(comment) + } retry := driver.RetryNone // retryable writes are only enabled updateOne/replaceOne operations if !multi && coll.client.retryWrites { @@ -601,12 +628,12 @@ func (coll *Collection) updateOrReplace(ctx context.Context, filter bsoncore.Doc // the operation will succeed and an UpdateResult with a MatchedCount of 0 will be returned. // // The update parameter must be a document containing update operators -// (https://docs.mongodb.com/manual/reference/operator/update/) and can be used to specify the modifications to be +// (https://www.mongodb.com/docs/manual/reference/operator/update/) and can be used to specify the modifications to be // made to the selected document. It cannot be nil or empty. // // The opts parameter can be used to specify options for the operation (see the options.UpdateOptions documentation). // -// For more information about the command, see https://docs.mongodb.com/manual/reference/command/update/. +// For more information about the command, see https://www.mongodb.com/docs/manual/reference/command/update/. func (coll *Collection) UpdateByID(ctx context.Context, id interface{}, update interface{}, opts ...*options.UpdateOptions) (*UpdateResult, error) { if id == nil { @@ -623,12 +650,12 @@ func (coll *Collection) UpdateByID(ctx context.Context, id interface{}, update i // matched set and MatchedCount will equal 1. // // The update parameter must be a document containing update operators -// (https://docs.mongodb.com/manual/reference/operator/update/) and can be used to specify the modifications to be +// (https://www.mongodb.com/docs/manual/reference/operator/update/) and can be used to specify the modifications to be // made to the selected document. It cannot be nil or empty. // // The opts parameter can be used to specify options for the operation (see the options.UpdateOptions documentation). // -// For more information about the command, see https://docs.mongodb.com/manual/reference/command/update/. +// For more information about the command, see https://www.mongodb.com/docs/manual/reference/command/update/. func (coll *Collection) UpdateOne(ctx context.Context, filter interface{}, update interface{}, opts ...*options.UpdateOptions) (*UpdateResult, error) { @@ -651,12 +678,12 @@ func (coll *Collection) UpdateOne(ctx context.Context, filter interface{}, updat // with a MatchedCount of 0 will be returned. // // The update parameter must be a document containing update operators -// (https://docs.mongodb.com/manual/reference/operator/update/) and can be used to specify the modifications to be made +// (https://www.mongodb.com/docs/manual/reference/operator/update/) and can be used to specify the modifications to be made // to the selected documents. It cannot be nil or empty. // // The opts parameter can be used to specify options for the operation (see the options.UpdateOptions documentation). // -// For more information about the command, see https://docs.mongodb.com/manual/reference/command/update/. +// For more information about the command, see https://www.mongodb.com/docs/manual/reference/command/update/. func (coll *Collection) UpdateMany(ctx context.Context, filter interface{}, update interface{}, opts ...*options.UpdateOptions) (*UpdateResult, error) { @@ -680,11 +707,11 @@ func (coll *Collection) UpdateMany(ctx context.Context, filter interface{}, upda // selected from the matched set and MatchedCount will equal 1. // // The replacement parameter must be a document that will be used to replace the selected document. It cannot be nil -// and cannot contain any update operators (https://docs.mongodb.com/manual/reference/operator/update/). +// and cannot contain any update operators (https://www.mongodb.com/docs/manual/reference/operator/update/). // // The opts parameter can be used to specify options for the operation (see the options.ReplaceOptions documentation). // -// For more information about the command, see https://docs.mongodb.com/manual/reference/command/update/. +// For more information about the command, see https://www.mongodb.com/docs/manual/reference/command/update/. func (coll *Collection) ReplaceOne(ctx context.Context, filter interface{}, replacement interface{}, opts ...*options.ReplaceOptions) (*UpdateResult, error) { @@ -717,6 +744,7 @@ func (coll *Collection) ReplaceOne(ctx context.Context, filter interface{}, uOpts.Upsert = opt.Upsert uOpts.Hint = opt.Hint uOpts.Let = opt.Let + uOpts.Comment = opt.Comment updateOptions = append(updateOptions, uOpts) } @@ -728,12 +756,12 @@ func (coll *Collection) ReplaceOne(ctx context.Context, filter interface{}, // The pipeline parameter must be an array of documents, each representing an aggregation stage. The pipeline cannot // be nil but can be empty. The stage documents must all be non-nil. For a pipeline of bson.D documents, the // mongo.Pipeline type can be used. See -// https://docs.mongodb.com/manual/reference/operator/aggregation-pipeline/#db-collection-aggregate-stages for a list of +// https://www.mongodb.com/docs/manual/reference/operator/aggregation-pipeline/#db-collection-aggregate-stages for a list of // valid stages in aggregations. // // The opts parameter can be used to specify options for the operation (see the options.AggregateOptions documentation.) // -// For more information about the command, see https://docs.mongodb.com/manual/reference/command/aggregate/. +// For more information about the command, see https://www.mongodb.com/docs/manual/reference/command/aggregate/. func (coll *Collection) Aggregate(ctx context.Context, pipeline interface{}, opts ...*options.AggregateOptions) (*Cursor, error) { a := aggregateParams{ @@ -754,7 +782,7 @@ func (coll *Collection) Aggregate(ctx context.Context, pipeline interface{}, return aggregate(a) } -// aggreate is the helper method for Aggregate +// aggregate is the helper method for Aggregate func aggregate(a aggregateParams) (cur *Cursor, err error) { if a.ctx == nil { a.ctx = context.Background() @@ -817,7 +845,8 @@ func aggregate(a aggregateParams) (cur *Cursor, err error) { Deployment(a.client.deployment). Crypt(a.client.cryptFLE). ServerAPI(a.client.serverAPI). - HasOutputStage(hasOutputStage) + HasOutputStage(hasOutputStage). + Timeout(a.client.timeout) if ao.AllowDiskUse != nil { op.AllowDiskUse(*ao.AllowDiskUse) @@ -841,6 +870,12 @@ func aggregate(a aggregateParams) (cur *Cursor, err error) { } if ao.Comment != nil { op.Comment(*ao.Comment) + + commentVal, err := transformValue(a.registry, ao.Comment, true, "comment") + if err != nil { + return nil, err + } + cursorOpts.Comment = commentVal } if ao.Hint != nil { hintVal, err := transformValue(a.registry, ao.Hint, false, "hint") @@ -935,10 +970,14 @@ func (coll *Collection) CountDocuments(ctx context.Context, filter interface{}, selector := makeReadPrefSelector(sess, coll.readSelector, coll.client.localThreshold) op := operation.NewAggregate(pipelineArr).Session(sess).ReadConcern(rc).ReadPreference(coll.readPreference). CommandMonitor(coll.client.monitor).ServerSelector(selector).ClusterClock(coll.client.clock).Database(coll.db.name). - Collection(coll.name).Deployment(coll.client.deployment).Crypt(coll.client.cryptFLE).ServerAPI(coll.client.serverAPI) + Collection(coll.name).Deployment(coll.client.deployment).Crypt(coll.client.cryptFLE).ServerAPI(coll.client.serverAPI). + Timeout(coll.client.timeout) if countOpts.Collation != nil { op.Collation(bsoncore.Document(countOpts.Collation.ToDocument())) } + if countOpts.Comment != nil { + op.Comment(*countOpts.Comment) + } if countOpts.MaxTime != nil { op.MaxTimeMS(int64(*countOpts.MaxTime / time.Millisecond)) } @@ -984,7 +1023,7 @@ func (coll *Collection) CountDocuments(ctx context.Context, filter interface{}, // The opts parameter can be used to specify options for the operation (see the options.EstimatedDocumentCountOptions // documentation). // -// For more information about the command, see https://docs.mongodb.com/manual/reference/command/count/. +// For more information about the command, see https://www.mongodb.com/docs/manual/reference/command/count/. func (coll *Collection) EstimatedDocumentCount(ctx context.Context, opts ...*options.EstimatedDocumentCountOptions) (int64, error) { @@ -1017,9 +1056,17 @@ func (coll *Collection) EstimatedDocumentCount(ctx context.Context, op := operation.NewCount().Session(sess).ClusterClock(coll.client.clock). Database(coll.db.name).Collection(coll.name).CommandMonitor(coll.client.monitor). Deployment(coll.client.deployment).ReadConcern(rc).ReadPreference(coll.readPreference). - ServerSelector(selector).Crypt(coll.client.cryptFLE).ServerAPI(coll.client.serverAPI) + ServerSelector(selector).Crypt(coll.client.cryptFLE).ServerAPI(coll.client.serverAPI). + Timeout(coll.client.timeout) co := options.MergeEstimatedDocumentCountOptions(opts...) + if co.Comment != nil { + comment, err := transformValue(coll.registry, co.Comment, false, "comment") + if err != nil { + return 0, err + } + op = op.Comment(comment) + } if co.MaxTime != nil { op = op.MaxTimeMS(int64(*co.MaxTime / time.Millisecond)) } @@ -1043,7 +1090,7 @@ func (coll *Collection) EstimatedDocumentCount(ctx context.Context, // // The opts parameter can be used to specify options for the operation (see the options.DistinctOptions documentation). // -// For more information about the command, see https://docs.mongodb.com/manual/reference/command/distinct/. +// For more information about the command, see https://www.mongodb.com/docs/manual/reference/command/distinct/. func (coll *Collection) Distinct(ctx context.Context, fieldName string, filter interface{}, opts ...*options.DistinctOptions) ([]interface{}, error) { @@ -1083,11 +1130,19 @@ func (coll *Collection) Distinct(ctx context.Context, fieldName string, filter i Session(sess).ClusterClock(coll.client.clock). Database(coll.db.name).Collection(coll.name).CommandMonitor(coll.client.monitor). Deployment(coll.client.deployment).ReadConcern(rc).ReadPreference(coll.readPreference). - ServerSelector(selector).Crypt(coll.client.cryptFLE).ServerAPI(coll.client.serverAPI) + ServerSelector(selector).Crypt(coll.client.cryptFLE).ServerAPI(coll.client.serverAPI). + Timeout(coll.client.timeout) if option.Collation != nil { op.Collation(bsoncore.Document(option.Collation.ToDocument())) } + if option.Comment != nil { + comment, err := transformValue(coll.registry, option.Comment, true, "comment") + if err != nil { + return nil, err + } + op.Comment(comment) + } if option.MaxTime != nil { op.MaxTimeMS(int64(*option.MaxTime / time.Millisecond)) } @@ -1132,7 +1187,7 @@ func (coll *Collection) Distinct(ctx context.Context, fieldName string, filter i // // The opts parameter can be used to specify options for the operation (see the options.FindOptions documentation). // -// For more information about the command, see https://docs.mongodb.com/manual/reference/command/find/. +// For more information about the command, see https://www.mongodb.com/docs/manual/reference/command/find/. func (coll *Collection) Find(ctx context.Context, filter interface{}, opts ...*options.FindOptions) (cur *Cursor, err error) { @@ -1175,7 +1230,8 @@ func (coll *Collection) Find(ctx context.Context, filter interface{}, Session(sess).ReadConcern(rc).ReadPreference(coll.readPreference). CommandMonitor(coll.client.monitor).ServerSelector(selector). ClusterClock(coll.client.clock).Database(coll.db.name).Collection(coll.name). - Deployment(coll.client.deployment).Crypt(coll.client.cryptFLE).ServerAPI(coll.client.serverAPI) + Deployment(coll.client.deployment).Crypt(coll.client.cryptFLE).ServerAPI(coll.client.serverAPI). + Timeout(coll.client.timeout) fo := options.MergeFindOptions(opts...) cursorOpts := coll.client.createBaseCursorOptions() @@ -1195,6 +1251,12 @@ func (coll *Collection) Find(ctx context.Context, filter interface{}, } if fo.Comment != nil { op.Comment(*fo.Comment) + + commentVal, err := transformValue(coll.registry, fo.Comment, true, "comment") + if err != nil { + return nil, err + } + cursorOpts.Comment = commentVal } if fo.CursorType != nil { switch *fo.CursorType { @@ -1305,7 +1367,7 @@ func (coll *Collection) Find(ctx context.Context, filter interface{}, // // The opts parameter can be used to specify options for this operation (see the options.FindOneOptions documentation). // -// For more information about the command, see https://docs.mongodb.com/manual/reference/command/find/. +// For more information about the command, see https://www.mongodb.com/docs/manual/reference/command/find/. func (coll *Collection) FindOne(ctx context.Context, filter interface{}, opts ...*options.FindOneOptions) *SingleResult { @@ -1411,7 +1473,7 @@ func (coll *Collection) findAndModify(ctx context.Context, op *operation.FindAnd // The opts parameter can be used to specify options for the operation (see the options.FindOneAndDeleteOptions // documentation). // -// For more information about the command, see https://docs.mongodb.com/manual/reference/command/findAndModify/. +// For more information about the command, see https://www.mongodb.com/docs/manual/reference/command/findAndModify/. func (coll *Collection) FindOneAndDelete(ctx context.Context, filter interface{}, opts ...*options.FindOneAndDeleteOptions) *SingleResult { @@ -1420,10 +1482,17 @@ func (coll *Collection) FindOneAndDelete(ctx context.Context, filter interface{} return &SingleResult{err: err} } fod := options.MergeFindOneAndDeleteOptions(opts...) - op := operation.NewFindAndModify(f).Remove(true).ServerAPI(coll.client.serverAPI) + op := operation.NewFindAndModify(f).Remove(true).ServerAPI(coll.client.serverAPI).Timeout(coll.client.timeout) if fod.Collation != nil { op = op.Collation(bsoncore.Document(fod.Collation.ToDocument())) } + if fod.Comment != nil { + comment, err := transformValue(coll.registry, fod.Comment, true, "comment") + if err != nil { + return &SingleResult{err: err} + } + op = op.Comment(comment) + } if fod.MaxTime != nil { op = op.MaxTimeMS(int64(*fod.MaxTime / time.Millisecond)) } @@ -1467,12 +1536,12 @@ func (coll *Collection) FindOneAndDelete(ctx context.Context, filter interface{} // ErrNoDocuments wil be returned. If the filter matches multiple documents, one will be selected from the matched set. // // The replacement parameter must be a document that will be used to replace the selected document. It cannot be nil -// and cannot contain any update operators (https://docs.mongodb.com/manual/reference/operator/update/). +// and cannot contain any update operators (https://www.mongodb.com/docs/manual/reference/operator/update/). // // The opts parameter can be used to specify options for the operation (see the options.FindOneAndReplaceOptions // documentation). // -// For more information about the command, see https://docs.mongodb.com/manual/reference/command/findAndModify/. +// For more information about the command, see https://www.mongodb.com/docs/manual/reference/command/findAndModify/. func (coll *Collection) FindOneAndReplace(ctx context.Context, filter interface{}, replacement interface{}, opts ...*options.FindOneAndReplaceOptions) *SingleResult { @@ -1490,13 +1559,20 @@ func (coll *Collection) FindOneAndReplace(ctx context.Context, filter interface{ fo := options.MergeFindOneAndReplaceOptions(opts...) op := operation.NewFindAndModify(f).Update(bsoncore.Value{Type: bsontype.EmbeddedDocument, Data: r}). - ServerAPI(coll.client.serverAPI) + ServerAPI(coll.client.serverAPI).Timeout(coll.client.timeout) if fo.BypassDocumentValidation != nil && *fo.BypassDocumentValidation { op = op.BypassDocumentValidation(*fo.BypassDocumentValidation) } if fo.Collation != nil { op = op.Collation(bsoncore.Document(fo.Collation.ToDocument())) } + if fo.Comment != nil { + comment, err := transformValue(coll.registry, fo.Comment, true, "comment") + if err != nil { + return &SingleResult{err: err} + } + op = op.Comment(comment) + } if fo.MaxTime != nil { op = op.MaxTimeMS(int64(*fo.MaxTime / time.Millisecond)) } @@ -1546,13 +1622,13 @@ func (coll *Collection) FindOneAndReplace(ctx context.Context, filter interface{ // ErrNoDocuments wil be returned. If the filter matches multiple documents, one will be selected from the matched set. // // The update parameter must be a document containing update operators -// (https://docs.mongodb.com/manual/reference/operator/update/) and can be used to specify the modifications to be made +// (https://www.mongodb.com/docs/manual/reference/operator/update/) and can be used to specify the modifications to be made // to the selected document. It cannot be nil or empty. // // The opts parameter can be used to specify options for the operation (see the options.FindOneAndUpdateOptions // documentation). // -// For more information about the command, see https://docs.mongodb.com/manual/reference/command/findAndModify/. +// For more information about the command, see https://www.mongodb.com/docs/manual/reference/command/findAndModify/. func (coll *Collection) FindOneAndUpdate(ctx context.Context, filter interface{}, update interface{}, opts ...*options.FindOneAndUpdateOptions) *SingleResult { @@ -1566,7 +1642,7 @@ func (coll *Collection) FindOneAndUpdate(ctx context.Context, filter interface{} } fo := options.MergeFindOneAndUpdateOptions(opts...) - op := operation.NewFindAndModify(f).ServerAPI(coll.client.serverAPI) + op := operation.NewFindAndModify(f).ServerAPI(coll.client.serverAPI).Timeout(coll.client.timeout) u, err := transformUpdateValue(coll.registry, update, true) if err != nil { @@ -1587,6 +1663,13 @@ func (coll *Collection) FindOneAndUpdate(ctx context.Context, filter interface{} if fo.Collation != nil { op = op.Collation(bsoncore.Document(fo.Collation.ToDocument())) } + if fo.Comment != nil { + comment, err := transformValue(coll.registry, fo.Comment, true, "comment") + if err != nil { + return &SingleResult{err: err} + } + op = op.Comment(comment) + } if fo.MaxTime != nil { op = op.MaxTimeMS(int64(*fo.MaxTime / time.Millisecond)) } @@ -1629,13 +1712,13 @@ func (coll *Collection) FindOneAndUpdate(ctx context.Context, filter interface{} } // Watch returns a change stream for all changes on the corresponding collection. See -// https://docs.mongodb.com/manual/changeStreams/ for more information about change streams. +// https://www.mongodb.com/docs/manual/changeStreams/ for more information about change streams. // // The Collection must be configured with read concern majority or no read concern for a change stream to be created // successfully. // // The pipeline parameter must be an array of documents, each representing a pipeline stage. The pipeline cannot be -// nil but can be empty. The stage documents must all be non-nil. See https://docs.mongodb.com/manual/changeStreams/ for +// nil but can be empty. The stage documents must all be non-nil. See https://www.mongodb.com/docs/manual/changeStreams/ for // a list of pipeline stages that can be used with change streams. For a pipeline of bson.D documents, the // mongo.Pipeline{} type can be used. // @@ -1665,6 +1748,69 @@ func (coll *Collection) Indexes() IndexView { // Drop drops the collection on the server. This method ignores "namespace not found" errors so it is safe to drop // a collection that does not exist on the server. func (coll *Collection) Drop(ctx context.Context) error { + // Follow Client-Side Encryption specification to check for encryptedFields. + // Drop does not have an encryptedFields option. See: GODRIVER-2413. + // Check for encryptedFields from the client EncryptedFieldsMap. + // Check for encryptedFields from the server if EncryptedFieldsMap is set. + ef := coll.db.getEncryptedFieldsFromMap(coll.name) + if ef == nil && coll.db.client.encryptedFieldsMap != nil { + var err error + if ef, err = coll.db.getEncryptedFieldsFromServer(ctx, coll.name); err != nil { + return err + } + } + + if ef != nil { + return coll.dropEncryptedCollection(ctx, ef) + } + + return coll.drop(ctx) +} + +// dropEncryptedCollection drops a collection with EncryptedFields. +func (coll *Collection) dropEncryptedCollection(ctx context.Context, ef interface{}) error { + efBSON, err := transformBsoncoreDocument(coll.registry, ef, true /* mapAllowed */, "encryptedFields") + if err != nil { + return fmt.Errorf("error transforming document: %v", err) + } + + // Drop the three encryption-related, associated collections: `escCollection`, `eccCollection` and `ecocCollection`. + // Drop ESCCollection. + escCollection, err := internal.GetEncryptedStateCollectionName(efBSON, coll.name, internal.EncryptedStateCollection) + if err != nil { + return err + } + if err := coll.db.Collection(escCollection).drop(ctx); err != nil { + return err + } + + // Drop ECCCollection. + eccCollection, err := internal.GetEncryptedStateCollectionName(efBSON, coll.name, internal.EncryptedCacheCollection) + if err != nil { + return err + } + if err := coll.db.Collection(eccCollection).drop(ctx); err != nil { + return err + } + + // Drop ECOCCollection. + ecocCollection, err := internal.GetEncryptedStateCollectionName(efBSON, coll.name, internal.EncryptedCompactionCollection) + if err != nil { + return err + } + if err := coll.db.Collection(ecocCollection).drop(ctx); err != nil { + return err + } + + // Drop the data collection. + if err := coll.drop(ctx); err != nil { + return err + } + return nil +} + +// drop drops a collection without EncryptedFields. +func (coll *Collection) drop(ctx context.Context) error { if ctx == nil { ctx = context.Background() } diff --git a/backend/vendor/go.mongodb.org/mongo-driver/mongo/cursor.go b/backend/vendor/go.mongodb.org/mongo-driver/mongo/cursor.go index 533cfce07a..d21005fedb 100644 --- a/backend/vendor/go.mongodb.org/mongo-driver/mongo/cursor.go +++ b/backend/vendor/go.mongodb.org/mongo-driver/mongo/cursor.go @@ -125,7 +125,7 @@ func (c *Cursor) Next(ctx context.Context) bool { // TryNext attempts to get the next document for this cursor. It returns true if there were no errors and the next // document is available. This is only recommended for use with tailable cursors as a non-blocking alternative to -// Next. See https://docs.mongodb.com/manual/core/tailable-cursors/ for more information about tailable cursors. +// Next. See https://www.mongodb.com/docs/manual/core/tailable-cursors/ for more information about tailable cursors. // // TryNext returns false if the cursor is exhausted, an error occurs when getting results from the server, the next // document is not yet available, or ctx expires. If ctx expires, the error will be set to ctx.Err(). diff --git a/backend/vendor/go.mongodb.org/mongo-driver/mongo/database.go b/backend/vendor/go.mongodb.org/mongo-driver/mongo/database.go index b0066f04dc..57b5417fd3 100644 --- a/backend/vendor/go.mongodb.org/mongo-driver/mongo/database.go +++ b/backend/vendor/go.mongodb.org/mongo-driver/mongo/database.go @@ -13,12 +13,12 @@ import ( "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/bsoncodec" + "go.mongodb.org/mongo-driver/internal" "go.mongodb.org/mongo-driver/mongo/description" "go.mongodb.org/mongo-driver/mongo/options" "go.mongodb.org/mongo-driver/mongo/readconcern" "go.mongodb.org/mongo-driver/mongo/readpref" "go.mongodb.org/mongo-driver/mongo/writeconcern" - "go.mongodb.org/mongo-driver/x/bsonx" "go.mongodb.org/mongo-driver/x/bsonx/bsoncore" "go.mongodb.org/mongo-driver/x/mongo/driver" "go.mongodb.org/mongo-driver/x/mongo/driver/operation" @@ -107,12 +107,12 @@ func (db *Database) Collection(name string, opts ...*options.CollectionOptions) // The pipeline parameter must be a slice of documents, each representing an aggregation stage. The pipeline // cannot be nil but can be empty. The stage documents must all be non-nil. For a pipeline of bson.D documents, the // mongo.Pipeline type can be used. See -// https://docs.mongodb.com/manual/reference/operator/aggregation-pipeline/#db-aggregate-stages for a list of valid +// https://www.mongodb.com/docs/manual/reference/operator/aggregation-pipeline/#db-aggregate-stages for a list of valid // stages in database-level aggregations. // // The opts parameter can be used to specify options for this operation (see the options.AggregateOptions documentation). // -// For more information about the command, see https://docs.mongodb.com/manual/reference/command/aggregate/. +// For more information about the command, see https://www.mongodb.com/docs/manual/reference/command/aggregate/. func (db *Database) Aggregate(ctx context.Context, pipeline interface{}, opts ...*options.AggregateOptions) (*Cursor, error) { a := aggregateParams{ @@ -176,7 +176,8 @@ func (db *Database) processRunCommand(ctx context.Context, cmd interface{}, return op.Session(sess).CommandMonitor(db.client.monitor). ServerSelector(readSelect).ClusterClock(db.client.clock). Database(db.name).Deployment(db.client.deployment).ReadConcern(db.readConcern). - Crypt(db.client.cryptFLE).ReadPreference(ro.ReadPreference).ServerAPI(db.client.serverAPI), sess, nil + Crypt(db.client.cryptFLE).ReadPreference(ro.ReadPreference).ServerAPI(db.client.serverAPI). + Timeout(db.client.timeout), sess, nil } // RunCommand executes the given command against the database. This function does not obey the Database's read @@ -184,11 +185,13 @@ func (db *Database) processRunCommand(ctx context.Context, cmd interface{}, // // The runCommand parameter must be a document for the command to be executed. It cannot be nil. // This must be an order-preserving type such as bson.D. Map types such as bson.M are not valid. -// If the command document contains a session ID or any transaction-specific fields, the behavior is undefined. -// Specifying API versioning options in the command document and declaring an API version on the client is not supported. -// The behavior of RunCommand is undefined in this case. // // The opts parameter can be used to specify options for this operation (see the options.RunCmdOptions documentation). +// +// The behavior of RunCommand is undefined if the command document contains any of the following: +// - A session ID or any transaction-specific fields +// - API versioning options when an API version is already declared on the Client +// - maxTimeMS when Timeout is set on the Client func (db *Database) RunCommand(ctx context.Context, runCommand interface{}, opts ...*options.RunCmdOptions) *SingleResult { if ctx == nil { ctx = context.Background() @@ -217,9 +220,13 @@ func (db *Database) RunCommand(ctx context.Context, runCommand interface{}, opts // // The runCommand parameter must be a document for the command to be executed. It cannot be nil. // This must be an order-preserving type such as bson.D. Map types such as bson.M are not valid. -// If the command document contains a session ID or any transaction-specific fields, the behavior is undefined. // // The opts parameter can be used to specify options for this operation (see the options.RunCmdOptions documentation). +// +// The behavior of RunCommandCursor is undefined if the command document contains any of the following: +// - A session ID or any transaction-specific fields +// - API versioning options when an API version is already declared on the Client +// - maxTimeMS when Timeout is set on the Client func (db *Database) RunCommandCursor(ctx context.Context, runCommand interface{}, opts ...*options.RunCmdOptions) (*Cursor, error) { if ctx == nil { ctx = context.Background() @@ -302,7 +309,7 @@ func (db *Database) Drop(ctx context.Context) error { // The opts parameter can be used to specify options for the operation (see the options.ListCollectionsOptions // documentation). // -// For more information about the command, see https://docs.mongodb.com/manual/reference/command/listCollections/. +// For more information about the command, see https://www.mongodb.com/docs/manual/reference/command/listCollections/. // // BUG(benjirewis): ListCollectionSpecifications prevents listing more than 100 collections per database when running // against MongoDB version 2.6. @@ -339,7 +346,7 @@ func (db *Database) ListCollectionSpecifications(ctx context.Context, filter int // The opts parameter can be used to specify options for the operation (see the options.ListCollectionsOptions // documentation). // -// For more information about the command, see https://docs.mongodb.com/manual/reference/command/listCollections/. +// For more information about the command, see https://www.mongodb.com/docs/manual/reference/command/listCollections/. // // BUG(benjirewis): ListCollections prevents listing more than 100 collections per database when running against // MongoDB version 2.6. @@ -378,7 +385,7 @@ func (db *Database) ListCollections(ctx context.Context, filter interface{}, opt Session(sess).ReadPreference(db.readPreference).CommandMonitor(db.client.monitor). ServerSelector(selector).ClusterClock(db.client.clock). Database(db.name).Deployment(db.client.deployment).Crypt(db.client.cryptFLE). - ServerAPI(db.client.serverAPI) + ServerAPI(db.client.serverAPI).Timeout(db.client.timeout) cursorOpts := db.client.createBaseCursorOptions() if lco.NameOnly != nil { @@ -423,7 +430,7 @@ func (db *Database) ListCollections(ctx context.Context, filter interface{}, opt // The opts parameter can be used to specify options for the operation (see the options.ListCollectionsOptions // documentation). // -// For more information about the command, see https://docs.mongodb.com/manual/reference/command/listCollections/. +// For more information about the command, see https://www.mongodb.com/docs/manual/reference/command/listCollections/. // // BUG(benjirewis): ListCollectionNames prevents listing more than 100 collections per database when running against // MongoDB version 2.6. @@ -439,19 +446,13 @@ func (db *Database) ListCollectionNames(ctx context.Context, filter interface{}, names := make([]string, 0) for res.Next(ctx) { - next := &bsonx.Doc{} - err = res.Decode(next) - if err != nil { - return nil, err - } - - elem, err := next.LookupErr("name") + elem, err := res.Current.LookupErr("name") if err != nil { return nil, err } - if elem.Type() != bson.TypeString { - return nil, fmt.Errorf("incorrect type for 'name'. got %v. want %v", elem.Type(), bson.TypeString) + if elem.Type != bson.TypeString { + return nil, fmt.Errorf("incorrect type for 'name'. got %v. want %v", elem.Type, bson.TypeString) } elemName := elem.StringValue() @@ -478,13 +479,13 @@ func (db *Database) WriteConcern() *writeconcern.WriteConcern { } // Watch returns a change stream for all changes to the corresponding database. See -// https://docs.mongodb.com/manual/changeStreams/ for more information about change streams. +// https://www.mongodb.com/docs/manual/changeStreams/ for more information about change streams. // // The Database must be configured with read concern majority or no read concern for a change stream to be created // successfully. // // The pipeline parameter must be a slice of documents, each representing a pipeline stage. The pipeline cannot be -// nil but can be empty. The stage documents must all be non-nil. See https://docs.mongodb.com/manual/changeStreams/ for +// nil but can be empty. The stage documents must all be non-nil. See https://www.mongodb.com/docs/manual/changeStreams/ for // a list of pipeline stages that can be used with change streams. For a pipeline of bson.D documents, the // mongo.Pipeline{} type can be used. // @@ -512,8 +513,141 @@ func (db *Database) Watch(ctx context.Context, pipeline interface{}, // The opts parameter can be used to specify options for the operation (see the options.CreateCollectionOptions // documentation). // -// For more information about the command, see https://docs.mongodb.com/manual/reference/command/create/. +// For more information about the command, see https://www.mongodb.com/docs/manual/reference/command/create/. func (db *Database) CreateCollection(ctx context.Context, name string, opts ...*options.CreateCollectionOptions) error { + cco := options.MergeCreateCollectionOptions(opts...) + // Follow Client-Side Encryption specification to check for encryptedFields. + // Check for encryptedFields from create options. + ef := cco.EncryptedFields + // Check for encryptedFields from the client EncryptedFieldsMap. + if ef == nil { + ef = db.getEncryptedFieldsFromMap(name) + } + if ef != nil { + return db.createCollectionWithEncryptedFields(ctx, name, ef, opts...) + } + + return db.createCollection(ctx, name, opts...) +} + +// getEncryptedFieldsFromServer tries to get an "encryptedFields" document associated with collectionName by running the "listCollections" command. +// Returns nil and no error if the listCollections command succeeds, but "encryptedFields" is not present. +func (db *Database) getEncryptedFieldsFromServer(ctx context.Context, collectionName string) (interface{}, error) { + // Check if collection has an EncryptedFields configured server-side. + collSpecs, err := db.ListCollectionSpecifications(ctx, bson.D{{"name", collectionName}}) + if err != nil { + return nil, err + } + if len(collSpecs) == 0 { + return nil, nil + } + if len(collSpecs) > 1 { + return nil, fmt.Errorf("expected 1 or 0 results from listCollections, got %v", len(collSpecs)) + } + collSpec := collSpecs[0] + rawValue, err := collSpec.Options.LookupErr("encryptedFields") + if err == bsoncore.ErrElementNotFound { + return nil, nil + } else if err != nil { + return nil, err + } + + encryptedFields, ok := rawValue.DocumentOK() + if !ok { + return nil, fmt.Errorf("expected encryptedFields of %v to be document, got %v", collectionName, rawValue.Type) + } + + return encryptedFields, nil +} + +// getEncryptedFieldsFromServer tries to get an "encryptedFields" document associated with collectionName by checking the client EncryptedFieldsMap. +// Returns nil and no error if an EncryptedFieldsMap is not configured, or does not contain an entry for collectionName. +func (db *Database) getEncryptedFieldsFromMap(collectionName string) interface{} { + // Check the EncryptedFieldsMap + efMap := db.client.encryptedFieldsMap + if efMap == nil { + return nil + } + + namespace := db.name + "." + collectionName + + ef, ok := efMap[namespace] + if ok { + return ef + } + return nil +} + +// createCollectionWithEncryptedFields creates a collection with an EncryptedFields. +func (db *Database) createCollectionWithEncryptedFields(ctx context.Context, name string, ef interface{}, opts ...*options.CreateCollectionOptions) error { + efBSON, err := transformBsoncoreDocument(db.registry, ef, true /* mapAllowed */, "encryptedFields") + if err != nil { + return fmt.Errorf("error transforming document: %v", err) + } + + // Create the three encryption-related, associated collections: `escCollection`, `eccCollection` and `ecocCollection`. + + stateCollectionOpts := options.CreateCollection(). + SetClusteredIndex(bson.D{{"key", bson.D{{"_id", 1}}}, {"unique", true}}) + // Create ESCCollection. + escCollection, err := internal.GetEncryptedStateCollectionName(efBSON, name, internal.EncryptedStateCollection) + if err != nil { + return err + } + + if err := db.createCollection(ctx, escCollection, stateCollectionOpts); err != nil { + return err + } + + // Create ECCCollection. + eccCollection, err := internal.GetEncryptedStateCollectionName(efBSON, name, internal.EncryptedCacheCollection) + if err != nil { + return err + } + + if err := db.createCollection(ctx, eccCollection, stateCollectionOpts); err != nil { + return err + } + + // Create ECOCCollection. + ecocCollection, err := internal.GetEncryptedStateCollectionName(efBSON, name, internal.EncryptedCompactionCollection) + if err != nil { + return err + } + + if err := db.createCollection(ctx, ecocCollection, stateCollectionOpts); err != nil { + return err + } + + // Create a data collection with the 'encryptedFields' option. + op, err := db.createCollectionOperation(name, opts...) + if err != nil { + return err + } + + op.EncryptedFields(efBSON) + if err := db.executeCreateOperation(ctx, op); err != nil { + return err + } + + // Create an index on the __safeContent__ field in the collection @collectionName. + if _, err := db.Collection(name).Indexes().CreateOne(ctx, IndexModel{Keys: bson.D{{"__safeContent__", 1}}}); err != nil { + return fmt.Errorf("error creating safeContent index: %v", err) + } + + return nil +} + +// createCollection creates a collection without EncryptedFields. +func (db *Database) createCollection(ctx context.Context, name string, opts ...*options.CreateCollectionOptions) error { + op, err := db.createCollectionOperation(name, opts...) + if err != nil { + return err + } + return db.executeCreateOperation(ctx, op) +} + +func (db *Database) createCollectionOperation(name string, opts ...*options.CreateCollectionOptions) (*operation.Create, error) { cco := options.MergeCreateCollectionOptions(opts...) op := operation.NewCreate(name).ServerAPI(db.client.serverAPI) @@ -523,19 +657,26 @@ func (db *Database) CreateCollection(ctx context.Context, name string, opts ...* if cco.Collation != nil { op.Collation(bsoncore.Document(cco.Collation.ToDocument())) } + if cco.ChangeStreamPreAndPostImages != nil { + csppi, err := transformBsoncoreDocument(db.registry, cco.ChangeStreamPreAndPostImages, true, "changeStreamPreAndPostImages") + if err != nil { + return nil, err + } + op.ChangeStreamPreAndPostImages(csppi) + } if cco.DefaultIndexOptions != nil { idx, doc := bsoncore.AppendDocumentStart(nil) if cco.DefaultIndexOptions.StorageEngine != nil { storageEngine, err := transformBsoncoreDocument(db.registry, cco.DefaultIndexOptions.StorageEngine, true, "storageEngine") if err != nil { - return err + return nil, err } doc = bsoncore.AppendDocumentElement(doc, "storageEngine", storageEngine) } doc, err := bsoncore.AppendDocumentEnd(doc, idx) if err != nil { - return err + return nil, err } op.IndexOptionDefaults(doc) @@ -549,7 +690,7 @@ func (db *Database) CreateCollection(ctx context.Context, name string, opts ...* if cco.StorageEngine != nil { storageEngine, err := transformBsoncoreDocument(db.registry, cco.StorageEngine, true, "storageEngine") if err != nil { - return err + return nil, err } op.StorageEngine(storageEngine) } @@ -562,7 +703,7 @@ func (db *Database) CreateCollection(ctx context.Context, name string, opts ...* if cco.Validator != nil { validator, err := transformBsoncoreDocument(db.registry, cco.Validator, true, "validator") if err != nil { - return err + return nil, err } op.Validator(validator) } @@ -582,17 +723,24 @@ func (db *Database) CreateCollection(ctx context.Context, name string, opts ...* doc, err := bsoncore.AppendDocumentEnd(doc, idx) if err != nil { - return err + return nil, err } op.TimeSeries(doc) } + if cco.ClusteredIndex != nil { + clusteredIndex, err := transformBsoncoreDocument(db.registry, cco.ClusteredIndex, true, "clusteredIndex") + if err != nil { + return nil, err + } + op.ClusteredIndex(clusteredIndex) + } - return db.executeCreateOperation(ctx, op) + return op, nil } // CreateView executes a create command to explicitly create a view on the server. See -// https://docs.mongodb.com/manual/core/views/ for more information about views. This method requires driver version >= +// https://www.mongodb.com/docs/manual/core/views/ for more information about views. This method requires driver version >= // 1.4.0 and MongoDB version >= 3.4. // // The viewName parameter specifies the name of the view to create. diff --git a/backend/vendor/go.mongodb.org/mongo-driver/mongo/description/description.go b/backend/vendor/go.mongodb.org/mongo-driver/mongo/description/description.go index 40b1af1361..e750e33b14 100644 --- a/backend/vendor/go.mongodb.org/mongo-driver/mongo/description/description.go +++ b/backend/vendor/go.mongodb.org/mongo-driver/mongo/description/description.go @@ -4,6 +4,7 @@ // not use this file except in compliance with the License. You may obtain // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// Package description contains types and functions for describing the state of MongoDB clusters. package description // import "go.mongodb.org/mongo-driver/mongo/description" // Unknown is an unknown server or topology kind. diff --git a/backend/vendor/go.mongodb.org/mongo-driver/mongo/doc.go b/backend/vendor/go.mongodb.org/mongo-driver/mongo/doc.go index 669aa14c9f..e6e4d9e5f0 100644 --- a/backend/vendor/go.mongodb.org/mongo-driver/mongo/doc.go +++ b/backend/vendor/go.mongodb.org/mongo-driver/mongo/doc.go @@ -105,8 +105,21 @@ // // Note: Auto encryption is an enterprise-only feature. // -// The libmongocrypt C library is required when using client-side encryption. libmongocrypt version 1.3.0 or higher is -// required when using driver version 1.8.0 or higher. To install libmongocrypt, follow the instructions for your +// The libmongocrypt C library is required when using client-side encryption. Specific versions of libmongocrypt +// are required for different versions of the Go Driver: +// +// - Go Driver v1.2.0 requires libmongocrypt v1.0.0 or higher +// +// - Go Driver v1.5.0 requires libmongocrypt v1.1.0 or higher +// +// - Go Driver v1.8.0 requires libmongocrypt v1.3.0 or higher +// +// - Go Driver v1.10.0 requires libmongocrypt v1.5.0 or higher. +// There is a severe bug when calling RewrapManyDataKey with libmongocrypt versions less than 1.5.2. +// This bug may result in data corruption. +// Please use libmongocrypt 1.5.2 or higher when calling RewrapManyDataKey. +// +// To install libmongocrypt, follow the instructions for your // operating system: // // 1. Linux: follow the instructions listed at @@ -117,6 +130,7 @@ // to install packages via brew and compile the libmongocrypt source code. // // 3. Windows: +// // mkdir -p c:/libmongocrypt/bin // mkdir -p c:/libmongocrypt/include // @@ -128,18 +142,8 @@ // cp ./include/mongocrypt/*.h c:/libmongocrypt/include // export PATH=$PATH:/cygdrive/c/libmongocrypt/bin // -// libmongocrypt communicates with the mongocryptd process for automatic encryption. This process can be started manually -// or auto-spawned by the driver itself. To enable auto-spawning, ensure the process binary is on the PATH. To start it -// manually, use AutoEncryptionOptions: -// -// aeo := options.AutoEncryption() -// mongocryptdOpts := map[string]interface{}{ -// "mongocryptdBypassSpawn": true, -// } -// aeo.SetExtraOptions(mongocryptdOpts) -// To specify a process URI for mongocryptd, the "mongocryptdURI" option can be passed in the ExtraOptions map as well. -// See the ClientSideEncryption and ClientSideEncryptionCreateKey examples below for code samples about using this -// feature. +// libmongocrypt communicates with the mongocryptd process or mongo_crypt shared library for automatic encryption. +// See AutoEncryptionOpts.SetExtraOptions for options to configure use of mongocryptd or mongo_crypt. // -// [1] See https://docs.mongodb.com/manual/reference/connection-string/#dns-seedlist-connection-format +// [1] See https://www.mongodb.com/docs/manual/reference/connection-string/#dns-seedlist-connection-format package mongo diff --git a/backend/vendor/go.mongodb.org/mongo-driver/mongo/errors.go b/backend/vendor/go.mongodb.org/mongo-driver/mongo/errors.go index a16efab069..33e23573fc 100644 --- a/backend/vendor/go.mongodb.org/mongo-driver/mongo/errors.go +++ b/backend/vendor/go.mongodb.org/mongo-driver/mongo/errors.go @@ -104,6 +104,9 @@ func IsTimeout(err error) bool { if err == context.DeadlineExceeded { return true } + if err == driver.ErrDeadlineWouldBeExceeded { + return true + } if ne, ok := err.(net.Error); ok { return ne.Timeout() } diff --git a/backend/vendor/go.mongodb.org/mongo-driver/mongo/gridfs/bucket.go b/backend/vendor/go.mongodb.org/mongo-driver/mongo/gridfs/bucket.go index 697882c36c..e4e2d35bda 100644 --- a/backend/vendor/go.mongodb.org/mongo-driver/mongo/gridfs/bucket.go +++ b/backend/vendor/go.mongodb.org/mongo-driver/mongo/gridfs/bucket.go @@ -21,7 +21,6 @@ import ( "go.mongodb.org/mongo-driver/mongo/readconcern" "go.mongodb.org/mongo-driver/mongo/readpref" "go.mongodb.org/mongo-driver/mongo/writeconcern" - "go.mongodb.org/mongo-driver/x/bsonx" "go.mongodb.org/mongo-driver/x/bsonx/bsoncore" ) @@ -59,7 +58,7 @@ type Bucket struct { // Upload contains options to upload a file to a bucket. type Upload struct { chunkSize int32 - metadata bsonx.Doc + metadata bson.D } // NewBucket creates a GridFS bucket. @@ -186,12 +185,8 @@ func (b *Bucket) UploadFromStreamWithID(fileID interface{}, filename string, sou // OpenDownloadStream creates a stream from which the contents of the file can be read. func (b *Bucket) OpenDownloadStream(fileID interface{}) (*DownloadStream, error) { - id, err := convertFileID(fileID) - if err != nil { - return nil, err - } - return b.openDownloadStream(bsonx.Doc{ - {"_id", id}, + return b.openDownloadStream(bson.D{ + {"_id", fileID}, }) } @@ -224,9 +219,9 @@ func (b *Bucket) OpenDownloadStreamByName(filename string, opts ...*options.Name numSkip = (-1 * numSkip) - 1 } - findOpts := options.Find().SetSkip(int64(numSkip)).SetSort(bsonx.Doc{{"uploadDate", bsonx.Int32(sortOrder)}}) + findOpts := options.Find().SetSkip(int64(numSkip)).SetSort(bson.D{{"uploadDate", sortOrder}}) - return b.openDownloadStream(bsonx.Doc{{"filename", bsonx.String(filename)}}, findOpts) + return b.openDownloadStream(bson.D{{"filename", filename}}, findOpts) } // DownloadToStreamByName downloads the file with the given name to the given io.Writer. @@ -254,11 +249,7 @@ func (b *Bucket) Delete(fileID interface{}) error { defer cancel() } - id, err := convertFileID(fileID) - if err != nil { - return err - } - res, err := b.filesColl.DeleteOne(ctx, bsonx.Doc{{"_id", id}}) + res, err := b.filesColl.DeleteOne(ctx, bson.D{{"_id", fileID}}) if err == nil && res.DeletedCount == 0 { err = ErrFileNotFound } @@ -317,13 +308,9 @@ func (b *Bucket) Rename(fileID interface{}, newFilename string) error { defer cancel() } - id, err := convertFileID(fileID) - if err != nil { - return err - } res, err := b.filesColl.UpdateOne(ctx, - bsonx.Doc{{"_id", id}}, - bsonx.Doc{{"$set", bsonx.Document(bsonx.Doc{{"filename", bsonx.String(newFilename)}})}}, + bson.D{{"_id", fileID}}, + bson.D{{"$set", bson.D{{"filename", newFilename}}}}, ) if err != nil { return err @@ -426,11 +413,7 @@ func (b *Bucket) downloadToStream(ds *DownloadStream, stream io.Writer) (int64, } func (b *Bucket) deleteChunks(ctx context.Context, fileID interface{}) error { - id, err := convertFileID(fileID) - if err != nil { - return err - } - _, err = b.chunksColl.DeleteMany(ctx, bsonx.Doc{{"files_id", id}}) + _, err := b.chunksColl.DeleteMany(ctx, bson.D{{"files_id", fileID}}) return err } @@ -449,13 +432,9 @@ func (b *Bucket) findFile(ctx context.Context, filter interface{}, opts ...*opti } func (b *Bucket) findChunks(ctx context.Context, fileID interface{}) (*mongo.Cursor, error) { - id, err := convertFileID(fileID) - if err != nil { - return nil, err - } chunksCursor, err := b.chunksColl.Find(ctx, - bsonx.Doc{{"files_id", id}}, - options.Find().SetSort(bsonx.Doc{{"n", bsonx.Int32(1)}})) // sort by chunk index + bson.D{{"files_id", fileID}}, + options.Find().SetSort(bson.D{{"n", 1}})) // sort by chunk index if err != nil { return nil, err } @@ -550,7 +529,7 @@ func (b *Bucket) createIndexes(ctx context.Context) error { return err } - docRes := cloned.FindOne(ctx, bsonx.Doc{}, options.FindOne().SetProjection(bsonx.Doc{{"_id", bsonx.Int32(1)}})) + docRes := cloned.FindOne(ctx, bson.D{}, options.FindOne().SetProjection(bson.D{{"_id", 1}})) _, err = docRes.DecodeBytes() if err != mongo.ErrNoDocuments { @@ -617,31 +596,13 @@ func (b *Bucket) parseUploadOptions(opts ...*options.UploadOptions) (*Upload, er if err != nil { return nil, err } - doc, err := bsonx.ReadDoc(raw) - if err != nil { - return nil, err + var doc bson.D + unMarErr := bson.UnmarshalWithRegistry(uo.Registry, raw, &doc) + if unMarErr != nil { + return nil, unMarErr } upload.metadata = doc } return upload, nil } - -type _convertFileID struct { - ID interface{} `bson:"_id"` -} - -func convertFileID(fileID interface{}) (bsonx.Val, error) { - id := _convertFileID{ - ID: fileID, - } - - b, err := bson.Marshal(id) - if err != nil { - return bsonx.Val{}, err - } - val := bsoncore.Document(b).Lookup("_id") - var res bsonx.Val - err = res.UnmarshalBSONValue(val.Type, val.Data) - return res, err -} diff --git a/backend/vendor/go.mongodb.org/mongo-driver/mongo/gridfs/doc.go b/backend/vendor/go.mongodb.org/mongo-driver/mongo/gridfs/doc.go index b8264c45b7..347c3b9659 100644 --- a/backend/vendor/go.mongodb.org/mongo-driver/mongo/gridfs/doc.go +++ b/backend/vendor/go.mongodb.org/mongo-driver/mongo/gridfs/doc.go @@ -4,7 +4,7 @@ // not use this file except in compliance with the License. You may obtain // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 -// Package gridfs provides a MongoDB GridFS API. See https://docs.mongodb.com/manual/core/gridfs/ for more +// Package gridfs provides a MongoDB GridFS API. See https://www.mongodb.com/docs/manual/core/gridfs/ for more // information about GridFS and its use cases. // // Buckets diff --git a/backend/vendor/go.mongodb.org/mongo-driver/mongo/gridfs/upload_stream.go b/backend/vendor/go.mongodb.org/mongo-driver/mongo/gridfs/upload_stream.go index 783e965751..cf1997db80 100644 --- a/backend/vendor/go.mongodb.org/mongo-driver/mongo/gridfs/upload_stream.go +++ b/backend/vendor/go.mongodb.org/mongo-driver/mongo/gridfs/upload_stream.go @@ -14,9 +14,9 @@ import ( "math" + "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/x/bsonx" ) // UploadBufferSize is the size in bytes of one stream batch. Chunks will be written to the db after the sum of chunk @@ -137,11 +137,7 @@ func (us *UploadStream) Abort() error { defer cancel() } - id, err := convertFileID(us.FileID) - if err != nil { - return err - } - _, err = us.chunksColl.DeleteMany(ctx, bsonx.Doc{{"files_id", id}}) + _, err := us.chunksColl.DeleteMany(ctx, bson.D{{"files_id", us.FileID}}) if err != nil { return err } @@ -163,10 +159,6 @@ func (us *UploadStream) uploadChunks(ctx context.Context, uploadPartial bool) er docs := make([]interface{}, numChunks) - id, err := convertFileID(us.FileID) - if err != nil { - return err - } begChunkIndex := us.chunkIndex for i := 0; i < us.bufferIndex; i += int(us.chunkSize) { endIndex := i + int(us.chunkSize) @@ -178,17 +170,17 @@ func (us *UploadStream) uploadChunks(ctx context.Context, uploadPartial bool) er endIndex = us.bufferIndex } chunkData := us.buffer[i:endIndex] - docs[us.chunkIndex-begChunkIndex] = bsonx.Doc{ - {"_id", bsonx.ObjectID(primitive.NewObjectID())}, - {"files_id", id}, - {"n", bsonx.Int32(int32(us.chunkIndex))}, - {"data", bsonx.Binary(0x00, chunkData)}, + docs[us.chunkIndex-begChunkIndex] = bson.D{ + {"_id", primitive.NewObjectID()}, + {"files_id", us.FileID}, + {"n", int32(us.chunkIndex)}, + {"data", primitive.Binary{Subtype: 0x00, Data: chunkData}}, } us.chunkIndex++ us.fileLen += int64(len(chunkData)) } - _, err = us.chunksColl.InsertMany(ctx, docs) + _, err := us.chunksColl.InsertMany(ctx, docs) if err != nil { return err } @@ -203,23 +195,19 @@ func (us *UploadStream) uploadChunks(ctx context.Context, uploadPartial bool) er } func (us *UploadStream) createFilesCollDoc(ctx context.Context) error { - id, err := convertFileID(us.FileID) - if err != nil { - return err - } - doc := bsonx.Doc{ - {"_id", id}, - {"length", bsonx.Int64(us.fileLen)}, - {"chunkSize", bsonx.Int32(us.chunkSize)}, - {"uploadDate", bsonx.DateTime(time.Now().UnixNano() / int64(time.Millisecond))}, - {"filename", bsonx.String(us.filename)}, + doc := bson.D{ + {"_id", us.FileID}, + {"length", us.fileLen}, + {"chunkSize", us.chunkSize}, + {"uploadDate", primitive.DateTime(time.Now().UnixNano() / int64(time.Millisecond))}, + {"filename", us.filename}, } if us.metadata != nil { - doc = append(doc, bsonx.Elem{"metadata", bsonx.Document(us.metadata)}) + doc = append(doc, bson.E{"metadata", us.metadata}) } - _, err = us.filesColl.InsertOne(ctx, doc) + _, err := us.filesColl.InsertOne(ctx, doc) if err != nil { return err } diff --git a/backend/vendor/go.mongodb.org/mongo-driver/mongo/index_view.go b/backend/vendor/go.mongodb.org/mongo-driver/mongo/index_view.go index e8e260f166..a393c7e7c5 100644 --- a/backend/vendor/go.mongodb.org/mongo-driver/mongo/index_view.go +++ b/backend/vendor/go.mongodb.org/mongo-driver/mongo/index_view.go @@ -45,7 +45,7 @@ type IndexView struct { // IndexModel represents a new index to be created. type IndexModel struct { // A document describing which keys should be used for the index. It cannot be nil. This must be an order-preserving - // type such as bson.D. Map types such as bson.M are not valid. See https://docs.mongodb.com/manual/indexes/#indexes + // type such as bson.D. Map types such as bson.M are not valid. See https://www.mongodb.com/docs/manual/indexes/#indexes // for examples of valid documents. Keys interface{} @@ -65,7 +65,7 @@ func isNamespaceNotFoundError(err error) bool { // The opts parameter can be used to specify options for this operation (see the options.ListIndexesOptions // documentation). // -// For more information about the command, see https://docs.mongodb.com/manual/reference/command/listIndexes/. +// For more information about the command, see https://www.mongodb.com/docs/manual/reference/command/listIndexes/. func (iv IndexView) List(ctx context.Context, opts ...*options.ListIndexesOptions) (*Cursor, error) { if ctx == nil { ctx = context.Background() @@ -95,7 +95,8 @@ func (iv IndexView) List(ctx context.Context, opts ...*options.ListIndexesOption Session(sess).CommandMonitor(iv.coll.client.monitor). ServerSelector(selector).ClusterClock(iv.coll.client.clock). Database(iv.coll.db.name).Collection(iv.coll.name). - Deployment(iv.coll.client.deployment).ServerAPI(iv.coll.client.serverAPI) + Deployment(iv.coll.client.deployment).ServerAPI(iv.coll.client.serverAPI). + Timeout(iv.coll.client.timeout) cursorOpts := iv.coll.client.createBaseCursorOptions() lio := options.MergeListIndexesOptions(opts...) @@ -175,7 +176,7 @@ func (iv IndexView) CreateOne(ctx context.Context, model IndexModel, opts ...*op // The opts parameter can be used to specify options for this operation (see the options.CreateIndexesOptions // documentation). // -// For more information about the command, see https://docs.mongodb.com/manual/reference/command/createIndexes/. +// For more information about the command, see https://www.mongodb.com/docs/manual/reference/command/createIndexes/. func (iv IndexView) CreateMany(ctx context.Context, models []IndexModel, opts ...*options.CreateIndexesOptions) ([]string, error) { names := make([]string, 0, len(models)) @@ -256,7 +257,8 @@ func (iv IndexView) CreateMany(ctx context.Context, models []IndexModel, opts .. op := operation.NewCreateIndexes(indexes). Session(sess).WriteConcern(wc).ClusterClock(iv.coll.client.clock). Database(iv.coll.db.name).Collection(iv.coll.name).CommandMonitor(iv.coll.client.monitor). - Deployment(iv.coll.client.deployment).ServerSelector(selector).ServerAPI(iv.coll.client.serverAPI) + Deployment(iv.coll.client.deployment).ServerSelector(selector).ServerAPI(iv.coll.client.serverAPI). + Timeout(iv.coll.client.timeout) if option.MaxTime != nil { op.MaxTimeMS(int64(*option.MaxTime / time.Millisecond)) @@ -400,7 +402,8 @@ func (iv IndexView) drop(ctx context.Context, name string, opts ...*options.Drop Session(sess).WriteConcern(wc).CommandMonitor(iv.coll.client.monitor). ServerSelector(selector).ClusterClock(iv.coll.client.clock). Database(iv.coll.db.name).Collection(iv.coll.name). - Deployment(iv.coll.client.deployment).ServerAPI(iv.coll.client.serverAPI) + Deployment(iv.coll.client.deployment).ServerAPI(iv.coll.client.serverAPI). + Timeout(iv.coll.client.timeout) if dio.MaxTime != nil { op.MaxTimeMS(int64(*dio.MaxTime / time.Millisecond)) } @@ -427,7 +430,7 @@ func (iv IndexView) drop(ctx context.Context, name string, opts ...*options.Drop // The opts parameter can be used to specify options for this operation (see the options.DropIndexesOptions // documentation). // -// For more information about the command, see https://docs.mongodb.com/manual/reference/command/dropIndexes/. +// For more information about the command, see https://www.mongodb.com/docs/manual/reference/command/dropIndexes/. func (iv IndexView) DropOne(ctx context.Context, name string, opts ...*options.DropIndexesOptions) (bson.Raw, error) { if name == "*" { return nil, ErrMultipleIndexDrop @@ -443,7 +446,7 @@ func (iv IndexView) DropOne(ctx context.Context, name string, opts ...*options.D // The opts parameter can be used to specify options for this operation (see the options.DropIndexesOptions // documentation). // -// For more information about the command, see https://docs.mongodb.com/manual/reference/command/dropIndexes/. +// For more information about the command, see https://www.mongodb.com/docs/manual/reference/command/dropIndexes/. func (iv IndexView) DropAll(ctx context.Context, opts ...*options.DropIndexesOptions) (bson.Raw, error) { return iv.drop(ctx, "*", opts...) } diff --git a/backend/vendor/go.mongodb.org/mongo-driver/mongo/mongo.go b/backend/vendor/go.mongodb.org/mongo-driver/mongo/mongo.go index da29175c11..80282527e4 100644 --- a/backend/vendor/go.mongodb.org/mongo-driver/mongo/mongo.go +++ b/backend/vendor/go.mongodb.org/mongo-driver/mongo/mongo.go @@ -123,17 +123,6 @@ func transformAndEnsureID(registry *bsoncodec.Registry, val interface{}) (bsonco return doc, id, nil } -func transformDocument(registry *bsoncodec.Registry, val interface{}) (bsonx.Doc, error) { - if doc, ok := val.(bsonx.Doc); ok { - return doc.Copy(), nil - } - b, err := transformBsoncoreDocument(registry, val, true, "document") - if err != nil { - return nil, err - } - return bsonx.ReadDoc(b) -} - func transformBsoncoreDocument(registry *bsoncodec.Registry, val interface{}, mapAllowed bool, paramName string) (bsoncore.Document, error) { if registry == nil { registry = bson.DefaultRegistry diff --git a/backend/vendor/go.mongodb.org/mongo-driver/mongo/mongocryptd.go b/backend/vendor/go.mongodb.org/mongo-driver/mongo/mongocryptd.go index c36b1d31cd..016ccef62c 100644 --- a/backend/vendor/go.mongodb.org/mongo-driver/mongo/mongocryptd.go +++ b/backend/vendor/go.mongodb.org/mongo-driver/mongo/mongocryptd.go @@ -28,17 +28,18 @@ const ( var defaultTimeoutArgs = []string{"--idleShutdownTimeoutSecs=60"} var databaseOpts = options.Database().SetReadConcern(readconcern.New()).SetReadPreference(readpref.Primary()) -type mcryptClient struct { +type mongocryptdClient struct { bypassSpawn bool client *Client path string spawnArgs []string } -func newMcryptClient(opts *options.AutoEncryptionOptions) (*mcryptClient, error) { +func newMongocryptdClient(cryptSharedLibAvailable bool, opts *options.AutoEncryptionOptions) (*mongocryptdClient, error) { // create mcryptClient instance and spawn process if necessary var bypassSpawn bool var bypassAutoEncryption bool + if bypass, ok := opts.ExtraOptions["mongocryptdBypassSpawn"]; ok { bypassSpawn = bypass.(bool) } @@ -46,10 +47,15 @@ func newMcryptClient(opts *options.AutoEncryptionOptions) (*mcryptClient, error) bypassAutoEncryption = *opts.BypassAutoEncryption } - mc := &mcryptClient{ - // mongocryptd should not be spawned if mongocryptdBypassSpawn is passed or if bypassAutoEncryption is - // specified because it is not used during decryption - bypassSpawn: bypassSpawn || bypassAutoEncryption, + bypassQueryAnalysis := opts.BypassQueryAnalysis != nil && *opts.BypassQueryAnalysis + + mc := &mongocryptdClient{ + // mongocryptd should not be spawned if any of these conditions are true: + // - mongocryptdBypassSpawn is passed + // - bypassAutoEncryption is true because mongocryptd is not used during decryption + // - bypassQueryAnalysis is true because mongocryptd is not used during decryption + // - the crypt_shared library is available because it replaces all mongocryptd functionality. + bypassSpawn: bypassSpawn || bypassAutoEncryption || bypassQueryAnalysis || cryptSharedLibAvailable, } if !mc.bypassSpawn { @@ -76,7 +82,7 @@ func newMcryptClient(opts *options.AutoEncryptionOptions) (*mcryptClient, error) } // markCommand executes the given command on mongocryptd. -func (mc *mcryptClient) markCommand(ctx context.Context, dbName string, cmd bsoncore.Document) (bsoncore.Document, error) { +func (mc *mongocryptdClient) markCommand(ctx context.Context, dbName string, cmd bsoncore.Document) (bsoncore.Document, error) { // Remove the explicit session from the context if one is set. // The explicit session will be from a different client. // If an explicit session is set, it is applied after automatic encryption. @@ -105,16 +111,16 @@ func (mc *mcryptClient) markCommand(ctx context.Context, dbName string, cmd bson } // connect connects the underlying Client instance. This must be called before performing any mark operations. -func (mc *mcryptClient) connect(ctx context.Context) error { +func (mc *mongocryptdClient) connect(ctx context.Context) error { return mc.client.Connect(ctx) } // disconnect disconnects the underlying Client instance. This should be called after all operations have completed. -func (mc *mcryptClient) disconnect(ctx context.Context) error { +func (mc *mongocryptdClient) disconnect(ctx context.Context) error { return mc.client.Disconnect(ctx) } -func (mc *mcryptClient) spawnProcess() error { +func (mc *mongocryptdClient) spawnProcess() error { // Ignore gosec warning about subprocess launched with externally-provided path variable. /* #nosec G204 */ cmd := exec.Command(mc.path, mc.spawnArgs...) diff --git a/backend/vendor/go.mongodb.org/mongo-driver/mongo/options/aggregateoptions.go b/backend/vendor/go.mongodb.org/mongo-driver/mongo/options/aggregateoptions.go index cf0da5fcb6..38ed249085 100644 --- a/backend/vendor/go.mongodb.org/mongo-driver/mongo/options/aggregateoptions.go +++ b/backend/vendor/go.mongodb.org/mongo-driver/mongo/options/aggregateoptions.go @@ -23,7 +23,7 @@ type AggregateOptions struct { // If true, writes executed as part of the operation will opt out of document-level validation on the server. This // option is valid for MongoDB versions >= 3.2 and is ignored for previous server versions. The default value is - // false. See https://docs.mongodb.com/manual/core/schema-validation/ for more information about document + // false. See https://www.mongodb.com/docs/manual/core/schema-validation/ for more information about document // validation. BypassDocumentValidation *bool @@ -34,6 +34,10 @@ type AggregateOptions struct { // The maximum amount of time that the query can run on the server. The default value is nil, meaning that there // is no time limit for query execution. + // + // NOTE(benjirewis): MaxTime will be deprecated in a future release. The more general Timeout option may be used + // in its place to control the amount of time that a single operation can run before returning an error. MaxTime + // is ignored if Timeout is set on the client. MaxTime *time.Duration // The maximum amount of time that the server should wait for new documents to satisfy a tailable cursor query. @@ -41,7 +45,7 @@ type AggregateOptions struct { MaxAwaitTime *time.Duration // A string that will be included in server logs, profiling logs, and currentOp queries to help trace the operation. - // The default is the empty string, which means that no comment will be included in the logs. + // The default is nil, which means that no comment will be included in the logs. Comment *string // The index to use for the aggregation. This should either be the index name as a string or the index specification @@ -91,6 +95,10 @@ func (ao *AggregateOptions) SetCollation(c *Collation) *AggregateOptions { } // SetMaxTime sets the value for the MaxTime field. +// +// NOTE(benjirewis): MaxTime will be deprecated in a future release. The more general Timeout +// option may be used in its place to control the amount of time that a single operation can +// run before returning an error. MaxTime is ignored if Timeout is set on the client. func (ao *AggregateOptions) SetMaxTime(d time.Duration) *AggregateOptions { ao.MaxTime = &d return ao diff --git a/backend/vendor/go.mongodb.org/mongo-driver/mongo/options/autoencryptionoptions.go b/backend/vendor/go.mongodb.org/mongo-driver/mongo/options/autoencryptionoptions.go index 89c3c05f16..375d899918 100644 --- a/backend/vendor/go.mongodb.org/mongo-driver/mongo/options/autoencryptionoptions.go +++ b/backend/vendor/go.mongodb.org/mongo-driver/mongo/options/autoencryptionoptions.go @@ -32,6 +32,8 @@ type AutoEncryptionOptions struct { BypassAutoEncryption *bool ExtraOptions map[string]interface{} TLSConfig map[string]*tls.Config + EncryptedFieldsMap map[string]interface{} + BypassQueryAnalysis *bool } // AutoEncryption creates a new AutoEncryptionOptions configured with default values. @@ -90,7 +92,35 @@ func (a *AutoEncryptionOptions) SetBypassAutoEncryption(bypass bool) *AutoEncryp return a } -// SetExtraOptions specifies a map of options to configure the mongocryptd process. +// SetExtraOptions specifies a map of options to configure the mongocryptd process or mongo_crypt shared library. +// +// Supported Extra Options +// +// "mongocryptdURI" - The mongocryptd URI. Allows setting a custom URI used to communicate with the +// mongocryptd process. The default is "mongodb://localhost:27020", which works with the default +// mongocryptd process spawned by the Client. Must be a string. +// +// "mongocryptdBypassSpawn" - If set to true, the Client will not attempt to spawn a mongocryptd +// process. Must be a bool. +// +// "mongocryptdSpawnPath" - The path used when spawning mongocryptd. +// Defaults to empty string and spawns mongocryptd from system path. Must be a string. +// +// "mongocryptdSpawnArgs" - Command line arguments passed when spawning mongocryptd. +// Defaults to ["--idleShutdownTimeoutSecs=60"]. Must be an array of strings. +// +// "cryptSharedLibRequired" - If set to true, Client creation will return an error if the +// crypt_shared library is not loaded. If unset or set to false, Client creation will not return an +// error if the crypt_shared library is not loaded. The default is unset. Must be a bool. +// +// "cryptSharedLibPath" - The crypt_shared library override path. This must be the path to the +// crypt_shared dynamic library file (for example, a .so, .dll, or .dylib file), not the directory +// that contains it. If the override path is a relative path, it will be resolved relative to the +// working directory of the process. If the override path is a relative path and the first path +// component is the literal string "$ORIGIN", the "$ORIGIN" component will be replaced by the +// absolute path to the directory containing the linked libmongocrypt library. Setting an override +// path disables the default system library search path. If an override path is specified but the +// crypt_shared library cannot be loaded, Client creation will return an error. Must be a string. func (a *AutoEncryptionOptions) SetExtraOptions(extraOpts map[string]interface{}) *AutoEncryptionOptions { a.ExtraOptions = extraOpts return a @@ -113,6 +143,22 @@ func (a *AutoEncryptionOptions) SetTLSConfig(tlsOpts map[string]*tls.Config) *Au return a } +// SetEncryptedFieldsMap specifies a map from namespace to local EncryptedFieldsMap document. +// EncryptedFieldsMap is used for Queryable Encryption. +// Queryable Encryption is in Public Technical Preview. Queryable Encryption should not be used in production and is subject to backwards breaking changes. +func (a *AutoEncryptionOptions) SetEncryptedFieldsMap(ef map[string]interface{}) *AutoEncryptionOptions { + a.EncryptedFieldsMap = ef + return a +} + +// SetBypassQueryAnalysis specifies whether or not query analysis should be used for automatic encryption. +// Use this option when using explicit encryption with Queryable Encryption. +// Queryable Encryption is in Public Technical Preview. Queryable Encryption should not be used in production and is subject to backwards breaking changes. +func (a *AutoEncryptionOptions) SetBypassQueryAnalysis(bypass bool) *AutoEncryptionOptions { + a.BypassQueryAnalysis = &bypass + return a +} + // MergeAutoEncryptionOptions combines the argued AutoEncryptionOptions in a last-one wins fashion. func MergeAutoEncryptionOptions(opts ...*AutoEncryptionOptions) *AutoEncryptionOptions { aeo := AutoEncryption() @@ -142,6 +188,12 @@ func MergeAutoEncryptionOptions(opts ...*AutoEncryptionOptions) *AutoEncryptionO if opt.TLSConfig != nil { aeo.TLSConfig = opt.TLSConfig } + if opt.EncryptedFieldsMap != nil { + aeo.EncryptedFieldsMap = opt.EncryptedFieldsMap + } + if opt.BypassQueryAnalysis != nil { + aeo.BypassQueryAnalysis = opt.BypassQueryAnalysis + } } return aeo diff --git a/backend/vendor/go.mongodb.org/mongo-driver/mongo/options/bulkwriteoptions.go b/backend/vendor/go.mongodb.org/mongo-driver/mongo/options/bulkwriteoptions.go index 2786ab2c5c..0c36d0b7b0 100644 --- a/backend/vendor/go.mongodb.org/mongo-driver/mongo/options/bulkwriteoptions.go +++ b/backend/vendor/go.mongodb.org/mongo-driver/mongo/options/bulkwriteoptions.go @@ -13,10 +13,14 @@ var DefaultOrdered = true type BulkWriteOptions struct { // If true, writes executed as part of the operation will opt out of document-level validation on the server. This // option is valid for MongoDB versions >= 3.2 and is ignored for previous server versions. The default value is - // false. See https://docs.mongodb.com/manual/core/schema-validation/ for more information about document + // false. See https://www.mongodb.com/docs/manual/core/schema-validation/ for more information about document // validation. BypassDocumentValidation *bool + // A string or document that will be included in server logs, profiling logs, and currentOp queries to help trace + // the operation. The default value is nil, which means that no comment will be included in the logs. + Comment interface{} + // If true, no writes will be executed after one fails. The default value is true. Ordered *bool @@ -34,6 +38,12 @@ func BulkWrite() *BulkWriteOptions { } } +// SetComment sets the value for the Comment field. +func (b *BulkWriteOptions) SetComment(comment interface{}) *BulkWriteOptions { + b.Comment = comment + return b +} + // SetOrdered sets the value for the Ordered field. func (b *BulkWriteOptions) SetOrdered(ordered bool) *BulkWriteOptions { b.Ordered = &ordered @@ -63,6 +73,9 @@ func MergeBulkWriteOptions(opts ...*BulkWriteOptions) *BulkWriteOptions { if opt == nil { continue } + if opt.Comment != nil { + b.Comment = opt.Comment + } if opt.Ordered != nil { b.Ordered = opt.Ordered } diff --git a/backend/vendor/go.mongodb.org/mongo-driver/mongo/options/changestreamoptions.go b/backend/vendor/go.mongodb.org/mongo-driver/mongo/options/changestreamoptions.go index eb9b0643cb..862abcd340 100644 --- a/backend/vendor/go.mongodb.org/mongo-driver/mongo/options/changestreamoptions.go +++ b/backend/vendor/go.mongodb.org/mongo-driver/mongo/options/changestreamoptions.go @@ -23,11 +23,18 @@ type ChangeStreamOptions struct { // default value is nil, which means the default collation of the collection will be used. Collation *Collation - // Specifies whether the updated document should be returned in change notifications for update operations along - // with the deltas describing the changes made to the document. The default is options.Default, which means that - // the updated document will not be included in the change notification. + // A string that will be included in server logs, profiling logs, and currentOp queries to help trace the operation. + // The default is nil, which means that no comment will be included in the logs. + Comment *string + + // Specifies how the updated document should be returned in change notifications for update operations. The default + // is options.Default, which means that only partial update deltas will be included in the change notification. FullDocument *FullDocument + // Specifies how the pre-update document should be returned in change notifications for update operations. The default + // is options.Off, which means that the pre-update document will not be included in the change notification. + FullDocumentBeforeChange *FullDocument + // The maximum amount of time that the server should wait for new documents to satisfy a tailable cursor query. MaxAwaitTime *time.Duration @@ -36,6 +43,11 @@ type ChangeStreamOptions struct { // StartAfter must not be set. ResumeAfter interface{} + // ShowExpandedEvents specifies whether the server will return an expanded list of change stream events. Additional + // events include: createIndexes, dropIndexes, modify, create, shardCollection, reshardCollection and + // refineCollectionShardKey. This option is only valid for MongoDB versions >= 6.0. + ShowExpandedEvents *bool + // If specified, the change stream will only return changes that occurred at or after the given timestamp. This // option is only valid for MongoDB versions >= 4.0. If this is specified, ResumeAfter and StartAfter must not be // set. @@ -78,12 +90,24 @@ func (cso *ChangeStreamOptions) SetCollation(c Collation) *ChangeStreamOptions { return cso } +// SetComment sets the value for the Comment field. +func (cso *ChangeStreamOptions) SetComment(comment string) *ChangeStreamOptions { + cso.Comment = &comment + return cso +} + // SetFullDocument sets the value for the FullDocument field. func (cso *ChangeStreamOptions) SetFullDocument(fd FullDocument) *ChangeStreamOptions { cso.FullDocument = &fd return cso } +// SetFullDocumentBeforeChange sets the value for the FullDocumentBeforeChange field. +func (cso *ChangeStreamOptions) SetFullDocumentBeforeChange(fdbc FullDocument) *ChangeStreamOptions { + cso.FullDocumentBeforeChange = &fdbc + return cso +} + // SetMaxAwaitTime sets the value for the MaxAwaitTime field. func (cso *ChangeStreamOptions) SetMaxAwaitTime(d time.Duration) *ChangeStreamOptions { cso.MaxAwaitTime = &d @@ -96,6 +120,12 @@ func (cso *ChangeStreamOptions) SetResumeAfter(rt interface{}) *ChangeStreamOpti return cso } +// SetShowExpandedEvents sets the value for the ShowExpandedEvents field. +func (cso *ChangeStreamOptions) SetShowExpandedEvents(see bool) *ChangeStreamOptions { + cso.ShowExpandedEvents = &see + return cso +} + // SetStartAtOperationTime sets the value for the StartAtOperationTime field. func (cso *ChangeStreamOptions) SetStartAtOperationTime(t *primitive.Timestamp) *ChangeStreamOptions { cso.StartAtOperationTime = t @@ -139,15 +169,24 @@ func MergeChangeStreamOptions(opts ...*ChangeStreamOptions) *ChangeStreamOptions if cso.Collation != nil { csOpts.Collation = cso.Collation } + if cso.Comment != nil { + csOpts.Comment = cso.Comment + } if cso.FullDocument != nil { csOpts.FullDocument = cso.FullDocument } + if cso.FullDocumentBeforeChange != nil { + csOpts.FullDocumentBeforeChange = cso.FullDocumentBeforeChange + } if cso.MaxAwaitTime != nil { csOpts.MaxAwaitTime = cso.MaxAwaitTime } if cso.ResumeAfter != nil { csOpts.ResumeAfter = cso.ResumeAfter } + if cso.ShowExpandedEvents != nil { + csOpts.ShowExpandedEvents = cso.ShowExpandedEvents + } if cso.StartAtOperationTime != nil { csOpts.StartAtOperationTime = cso.StartAtOperationTime } diff --git a/backend/vendor/go.mongodb.org/mongo-driver/mongo/options/clientoptions.go b/backend/vendor/go.mongodb.org/mongo-driver/mongo/options/clientoptions.go index 115cc642d1..742a4da9b5 100644 --- a/backend/vendor/go.mongodb.org/mongo-driver/mongo/options/clientoptions.go +++ b/backend/vendor/go.mongodb.org/mongo-driver/mongo/options/clientoptions.go @@ -45,7 +45,7 @@ type ContextDialer interface { // AuthMechanism: the mechanism to use for authentication. Supported values include "SCRAM-SHA-256", "SCRAM-SHA-1", // "MONGODB-CR", "PLAIN", "GSSAPI", "MONGODB-X509", and "MONGODB-AWS". This can also be set through the "authMechanism" // URI option. (e.g. "authMechanism=PLAIN"). For more information, see -// https://docs.mongodb.com/manual/core/authentication-mechanisms/. +// https://www.mongodb.com/docs/manual/core/authentication-mechanisms/. // // AuthMechanismProperties can be used to specify additional configuration options for certain mechanisms. They can also // be set through the "authMechanismProperites" URI option @@ -121,9 +121,9 @@ type ClientOptions struct { RetryWrites *bool ServerAPIOptions *ServerAPIOptions ServerSelectionTimeout *time.Duration - SocketTimeout *time.Duration SRVMaxHosts *int SRVServiceName *string + Timeout *time.Duration TLSConfig *tls.Config WriteConcern *writeconcern.WriteConcern ZlibLevel *int @@ -151,6 +151,13 @@ type ClientOptions struct { // Deprecated: This option is for internal use only and should not be set. It may be changed or removed in any // release. Deployment driver.Deployment + + // SocketTimeout specifies the timeout to be used for the Client's socket reads and writes. + // + // NOTE(benjirewis): SocketTimeout will be deprecated in a future release. The more general Timeout option + // may be used in its place to control the amount of time that a single operation can run before returning + // an error. Setting SocketTimeout and Timeout on a single client will result in undefined behavior. + SocketTimeout *time.Duration } // Client creates a new ClientOptions instance. @@ -160,57 +167,58 @@ func Client() *ClientOptions { // Validate validates the client options. This method will return the first error found. func (c *ClientOptions) Validate() error { - c.validateAndSetError() - return c.err -} - -func (c *ClientOptions) validateAndSetError() { if c.err != nil { - return + return c.err } + c.err = c.validate() + return c.err +} +func (c *ClientOptions) validate() error { // Direct connections cannot be made if multiple hosts are specified or an SRV URI is used. if c.Direct != nil && *c.Direct { if len(c.Hosts) > 1 { - c.err = errors.New("a direct connection cannot be made if multiple hosts are specified") - return + return errors.New("a direct connection cannot be made if multiple hosts are specified") } if c.cs != nil && c.cs.Scheme == connstring.SchemeMongoDBSRV { - c.err = errors.New("a direct connection cannot be made if an SRV URI is used") - return + return errors.New("a direct connection cannot be made if an SRV URI is used") } } + if c.MaxPoolSize != nil && c.MinPoolSize != nil && *c.MaxPoolSize != 0 && *c.MinPoolSize > *c.MaxPoolSize { + return fmt.Errorf("minPoolSize must be less than or equal to maxPoolSize, got minPoolSize=%d maxPoolSize=%d", *c.MinPoolSize, *c.MaxPoolSize) + } + // verify server API version if ServerAPIOptions are passed in. if c.ServerAPIOptions != nil { - c.err = c.ServerAPIOptions.ServerAPIVersion.Validate() + if err := c.ServerAPIOptions.ServerAPIVersion.Validate(); err != nil { + return err + } } // Validation for load-balanced mode. if c.LoadBalanced != nil && *c.LoadBalanced { if len(c.Hosts) > 1 { - c.err = internal.ErrLoadBalancedWithMultipleHosts - return + return internal.ErrLoadBalancedWithMultipleHosts } if c.ReplicaSet != nil { - c.err = internal.ErrLoadBalancedWithReplicaSet - return + return internal.ErrLoadBalancedWithReplicaSet } if c.Direct != nil { - c.err = internal.ErrLoadBalancedWithDirectConnection - return + return internal.ErrLoadBalancedWithDirectConnection } } // Validation for srvMaxHosts. if c.SRVMaxHosts != nil && *c.SRVMaxHosts > 0 { if c.ReplicaSet != nil { - c.err = internal.ErrSRVMaxHostsWithReplicaSet + return internal.ErrSRVMaxHostsWithReplicaSet } if c.LoadBalanced != nil && *c.LoadBalanced { - c.err = internal.ErrSRVMaxHostsWithLoadBalanced + return internal.ErrSRVMaxHostsWithLoadBalanced } } + return nil } // GetURI returns the original URI used to configure the ClientOptions instance. If ApplyURI was not called during @@ -231,7 +239,7 @@ func (c *ClientOptions) GetURI() string { // If the URI format is incorrect or there are conflicting options specified in the URI an error will be recorded and // can be retrieved by calling Validate. // -// For more information about the URI format, see https://docs.mongodb.com/manual/reference/connection-string/. See +// For more information about the URI format, see https://www.mongodb.com/docs/manual/reference/connection-string/. See // mongo.Connect documentation for examples of using URIs for different Client configurations. func (c *ClientOptions) ApplyURI(uri string) *ClientOptions { if c.err != nil { @@ -445,6 +453,10 @@ func (c *ClientOptions) ApplyURI(uri string) *ClientOptions { c.DisableOCSPEndpointCheck = &cs.SSLDisableOCSPEndpointCheck } + if cs.TimeoutSet { + c.Timeout = &cs.Timeout + } + return c } @@ -470,12 +482,12 @@ func (c *ClientOptions) SetAuth(auth Credential) *ClientOptions { // // 2. "zlib" - requires server version >= 3.6 // -// 3. "zstd" - requires server version >= 4.2, and driver version >= 1.2.0 with cgo support enabled or driver version >= 1.3.0 -// without cgo +// 3. "zstd" - requires server version >= 4.2, and driver version >= 1.2.0 with cgo support enabled or driver +// version >= 1.3.0 without cgo. // // If this option is specified, the driver will perform a negotiation with the server to determine a common list of of // compressors and will use the first one in that list when performing operations. See -// https://docs.mongodb.com/manual/reference/program/mongod/#cmdoption-mongod-networkmessagecompressors for more +// https://www.mongodb.com/docs/manual/reference/program/mongod/#cmdoption-mongod-networkmessagecompressors for more // information about configuring compression on the server and the server-side defaults. // // This can also be set through the "compressors" URI option (e.g. "compressors=zstd,zlib,snappy"). The default is @@ -636,7 +648,7 @@ func (c *ClientOptions) SetReadConcern(rc *readconcern.ReadConcern) *ClientOptio // 3. "maxStalenessSeconds" (or "maxStaleness"): Specify a maximum replication lag for reads from secondaries in a // replica set (e.g. "maxStalenessSeconds=10"). // -// The default is readpref.Primary(). See https://docs.mongodb.com/manual/core/read-preference/#read-preference for +// The default is readpref.Primary(). See https://www.mongodb.com/docs/manual/core/read-preference/#read-preference for // more information about read preferences. func (c *ClientOptions) SetReadPreference(rp *readpref.ReadPref) *ClientOptions { c.ReadPreference = rp @@ -702,11 +714,31 @@ func (c *ClientOptions) SetServerSelectionTimeout(d time.Duration) *ClientOption // SetSocketTimeout specifies how long the driver will wait for a socket read or write to return before returning a // network error. This can also be set through the "socketTimeoutMS" URI option (e.g. "socketTimeoutMS=1000"). The // default value is 0, meaning no timeout is used and socket operations can block indefinitely. +// +// NOTE(benjirewis): SocketTimeout will be deprecated in a future release. The more general Timeout option may be used +// in its place to control the amount of time that a single operation can run before returning an error. Setting +// SocketTimeout and Timeout on a single client will result in undefined behavior. func (c *ClientOptions) SetSocketTimeout(d time.Duration) *ClientOptions { c.SocketTimeout = &d return c } +// SetTimeout specifies the amount of time that a single operation run on this Client can execute before returning an error. +// The deadline of any operation run through the Client will be honored above any Timeout set on the Client; Timeout will only +// be honored if there is no deadline on the operation Context. Timeout can also be set through the "timeoutMS" URI option +// (e.g. "timeoutMS=1000"). The default value is nil, meaning operations do not inherit a timeout from the Client. +// +// If any Timeout is set (even 0) on the Client, the values of MaxTime on operations, TransactionOptions.MaxCommitTime and +// SessionOptions.DefaultMaxCommitTime will be ignored. Setting Timeout and ClientOptions.SocketTimeout or WriteConcern.wTimeout +// will result in undefined behavior. +// +// NOTE(benjirewis): SetTimeout represents unstable, provisional API. The behavior of the driver when a Timeout is specified is +// subject to change. +func (c *ClientOptions) SetTimeout(d time.Duration) *ClientOptions { + c.Timeout = &d + return c +} + // SetTLSConfig specifies a tls.Config instance to use use to configure TLS on all connections created to the cluster. // This can also be set through the following URI options: // @@ -920,6 +952,9 @@ func MergeClientOptions(opts ...*ClientOptions) *ClientOptions { if opt.SRVServiceName != nil { c.SRVServiceName = opt.SRVServiceName } + if opt.Timeout != nil { + c.Timeout = opt.Timeout + } if opt.TLSConfig != nil { c.TLSConfig = opt.TLSConfig } @@ -983,7 +1018,9 @@ func addClientCertFromSeparateFiles(cfg *tls.Config, keyFile, certFile, keyPassw return "", err } - data := append(keyData, '\n') + data := make([]byte, 0, len(keyData)+len(certData)+1) + data = append(data, keyData...) + data = append(data, '\n') data = append(data, certData...) return addClientCertFromBytes(cfg, data, keyPassword) } diff --git a/backend/vendor/go.mongodb.org/mongo-driver/mongo/options/collectionoptions.go b/backend/vendor/go.mongodb.org/mongo-driver/mongo/options/collectionoptions.go index 5c8111471b..e8b68a2706 100644 --- a/backend/vendor/go.mongodb.org/mongo-driver/mongo/options/collectionoptions.go +++ b/backend/vendor/go.mongodb.org/mongo-driver/mongo/options/collectionoptions.go @@ -15,20 +15,20 @@ import ( // CollectionOptions represents options that can be used to configure a Collection. type CollectionOptions struct { - // The read concern to use for operations executed on the Collection. The default value is nil, which means that - // the read concern of the database used to configure the Collection will be used. + // ReadConcern is the read concern to use for operations executed on the Collection. The default value is nil, which means that + // the read concern of the Database used to configure the Collection will be used. ReadConcern *readconcern.ReadConcern - // The write concern to use for operations executed on the Collection. The default value is nil, which means that - // the write concern of the database used to configure the Collection will be used. + // WriteConcern is the write concern to use for operations executed on the Collection. The default value is nil, which means that + // the write concern of the Database used to configure the Collection will be used. WriteConcern *writeconcern.WriteConcern - // The read preference to use for operations executed on the Collection. The default value is nil, which means that - // the read preference of the database used to configure the Collection will be used. + // ReadPreference is the read preference to use for operations executed on the Collection. The default value is nil, which means that + // the read preference of the Database used to configure the Collection will be used. ReadPreference *readpref.ReadPref - // The BSON registry to marshal and unmarshal documents for operations executed on the Collection. The default value - // is nil, which means that the registry of the database used to configure the Collection will be used. + // Registry is the BSON registry to marshal and unmarshal documents for operations executed on the Collection. The default value + // is nil, which means that the registry of the Database used to configure the Collection will be used. Registry *bsoncodec.Registry } diff --git a/backend/vendor/go.mongodb.org/mongo-driver/mongo/options/countoptions.go b/backend/vendor/go.mongodb.org/mongo-driver/mongo/options/countoptions.go index 094524c100..f772ec4a3b 100644 --- a/backend/vendor/go.mongodb.org/mongo-driver/mongo/options/countoptions.go +++ b/backend/vendor/go.mongodb.org/mongo-driver/mongo/options/countoptions.go @@ -15,6 +15,13 @@ type CountOptions struct { // default value is nil, which means the default collation of the collection will be used. Collation *Collation + // TODO(GODRIVER-2386): CountOptions executor uses aggregation under the hood, which means this type has to be + // TODO a string for now. This can be replaced with `Comment interface{}` once 2386 is implemented. + + // A string or document that will be included in server logs, profiling logs, and currentOp queries to help trace + // the operation. The default is nil, which means that no comment will be included in the logs. + Comment *string + // The index to use for the aggregation. This should either be the index name as a string or the index specification // as a document. The driver will return an error if the hint parameter is a multi-key map. The default value is nil, // which means that no hint will be sent. @@ -26,6 +33,10 @@ type CountOptions struct { // The maximum amount of time that the query can run on the server. The default value is nil, meaning that there is // no time limit for query execution. + // + // NOTE(benjirewis): MaxTime will be deprecated in a future release. The more general Timeout option may be used in + // its place to control the amount of time that a single operation can run before returning an error. MaxTime is + // ignored if Timeout is set on the client. MaxTime *time.Duration // The number of documents to skip before counting. The default value is 0. @@ -43,6 +54,12 @@ func (co *CountOptions) SetCollation(c *Collation) *CountOptions { return co } +// SetComment sets the value for the Comment field. +func (co *CountOptions) SetComment(c string) *CountOptions { + co.Comment = &c + return co +} + // SetHint sets the value for the Hint field. func (co *CountOptions) SetHint(h interface{}) *CountOptions { co.Hint = h @@ -56,6 +73,10 @@ func (co *CountOptions) SetLimit(i int64) *CountOptions { } // SetMaxTime sets the value for the MaxTime field. +// +// NOTE(benjirewis): MaxTime will be deprecated in a future release. The more general Timeout +// option may be used in its place to control the amount of time that a single operation can +// run before returning an error. MaxTime is ignored if Timeout is set on the client. func (co *CountOptions) SetMaxTime(d time.Duration) *CountOptions { co.MaxTime = &d return co @@ -77,6 +98,9 @@ func MergeCountOptions(opts ...*CountOptions) *CountOptions { if co.Collation != nil { countOpts.Collation = co.Collation } + if co.Comment != nil { + countOpts.Comment = co.Comment + } if co.Hint != nil { countOpts.Hint = co.Hint } diff --git a/backend/vendor/go.mongodb.org/mongo-driver/mongo/options/createcollectionoptions.go b/backend/vendor/go.mongodb.org/mongo-driver/mongo/options/createcollectionoptions.go index 130c8e75c3..6fc7d066a2 100644 --- a/backend/vendor/go.mongodb.org/mongo-driver/mongo/options/createcollectionoptions.go +++ b/backend/vendor/go.mongodb.org/mongo-driver/mongo/options/createcollectionoptions.go @@ -67,7 +67,7 @@ func (tso *TimeSeriesOptions) SetGranularity(granularity string) *TimeSeriesOpti // CreateCollectionOptions represents options that can be used to configure a CreateCollection operation. type CreateCollectionOptions struct { - // Specifies if the collection is capped (see https://docs.mongodb.com/manual/core/capped-collections/). If true, + // Specifies if the collection is capped (see https://www.mongodb.com/docs/manual/core/capped-collections/). If true, // the SizeInBytes option must also be specified. The default value is false. Capped *bool @@ -75,6 +75,12 @@ type CreateCollectionOptions struct { // For previous server versions, the driver will return an error if this option is used. The default value is nil. Collation *Collation + // Specifies how change streams opened against the collection can return pre- and post-images of updated + // documents. The value must be a document in the form {