diff --git a/.github/settings.yml b/.github/settings.yml index ef45fc940c0b..20588351ff14 100644 --- a/.github/settings.yml +++ b/.github/settings.yml @@ -20,6 +20,9 @@ labels: - name: area/aggregations color: "#5319E7" description: Issues about aggregation pipelines + - name: area/auth + color: "#E4012C" + description: Issues about authentication - name: area/build color: "#52D58A" description: Issues about builds and CI diff --git a/cmd/ferretdb/main.go b/cmd/ferretdb/main.go index 685d296d56db..7787e6c26610 100644 --- a/cmd/ferretdb/main.go +++ b/cmd/ferretdb/main.go @@ -94,6 +94,7 @@ var cli struct { DisableFilterPushdown bool `default:"false" help:"Experimental: disable filter pushdown."` EnableOplog bool `default:"false" help:"Experimental: enable capped collections, tailable cursors and OpLog." hidden:""` + EnableNewAuth bool `default:"false" help:"Experimental: enable new authentication." hidden:""` //nolint:lll // for readability Telemetry struct { @@ -397,6 +398,7 @@ func run() { TestOpts: registry.TestOpts{ DisableFilterPushdown: cli.Test.DisableFilterPushdown, EnableOplog: cli.Test.EnableOplog, + EnableNewAuth: cli.Test.EnableNewAuth, }, }) if err != nil { diff --git a/integration/setup/listener.go b/integration/setup/listener.go index 12df2e43495d..b92277b46f30 100644 --- a/integration/setup/listener.go +++ b/integration/setup/listener.go @@ -179,6 +179,7 @@ func setupListener(tb testtb.TB, ctx context.Context, logger *zap.Logger) string TestOpts: registry.TestOpts{ DisableFilterPushdown: *disableFilterPushdownF, EnableOplog: true, + EnableNewAuth: false, }, } h, closeBackend, err := registry.NewHandler(handler, handlerOpts) diff --git a/internal/clientconn/conn.go b/internal/clientconn/conn.go index 36685cac9063..59a460499d2a 100644 --- a/internal/clientconn/conn.go +++ b/internal/clientconn/conn.go @@ -560,7 +560,7 @@ func (c *conn) route(ctx context.Context, reqHeader *wire.MsgHeader, reqBody wir // // The passed context is canceled when the client disconnects. func (c *conn) handleOpMsg(ctx context.Context, msg *wire.OpMsg, command string) (*wire.OpMsg, error) { - if cmd, ok := handler.Commands[command]; ok { + if cmd, ok := c.h.Commands()[command]; ok { if cmd.Handler != nil { defer observability.FuncCall(ctx)() @@ -568,7 +568,7 @@ func (c *conn) handleOpMsg(ctx context.Context, msg *wire.OpMsg, command string) ctx = pprof.WithLabels(ctx, pprof.Labels("command", command)) pprof.SetGoroutineLabels(ctx) - return cmd.Handler(c.h, ctx, msg) + return cmd.Handler(ctx, msg) } } diff --git a/internal/handler/commands.go b/internal/handler/commands.go new file mode 100644 index 000000000000..896fb3c88b92 --- /dev/null +++ b/internal/handler/commands.go @@ -0,0 +1,264 @@ +// Copyright 2021 FerretDB Inc. +// +// 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 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package handler + +import ( + "context" + + "github.com/FerretDB/FerretDB/internal/wire" +) + +// command represents a handler for single command. +type command struct { + // Handler processes this command. + // + // The passed context is canceled when the client disconnects. + Handler func(context.Context, *wire.OpMsg) (*wire.OpMsg, error) + + // Help is shown in the `listCommands` command output. + // If empty, that command is hidden, but still can be used. + Help string +} + +// initCommands initializes the commands map for that handler instance. +func (h *Handler) initCommands() { + h.commands = map[string]command{ + // sorted alphabetically + "aggregate": { + Handler: h.MsgAggregate, + Help: "Returns aggregated data.", + }, + "buildInfo": { + Handler: h.MsgBuildInfo, + Help: "Returns a summary of the build information.", + }, + "buildinfo": { // old lowercase variant + Handler: h.MsgBuildInfo, + Help: "", // hidden + }, + "collMod": { + Handler: h.MsgCollMod, + Help: "Adds options to a collection or modify view definitions.", + }, + "collStats": { + Handler: h.MsgCollStats, + Help: "Returns storage data for a collection.", + }, + "compact": { + Handler: h.MsgCompact, + Help: "Reduces the disk space collection takes and refreshes its statistics.", + }, + "connectionStatus": { + Handler: h.MsgConnectionStatus, + Help: "Returns information about the current connection, " + + "specifically the state of authenticated users and their available permissions.", + }, + "count": { + Handler: h.MsgCount, + Help: "Returns the count of documents that's matched by the query.", + }, + "create": { + Handler: h.MsgCreate, + Help: "Creates the collection.", + }, + "createIndexes": { + Handler: h.MsgCreateIndexes, + Help: "Creates indexes on a collection.", + }, + "currentOp": { + Handler: h.MsgCurrentOp, + Help: "Returns information about operations currently in progress.", + }, + "dataSize": { + Handler: h.MsgDataSize, + Help: "Returns the size of the collection in bytes.", + }, + "dbStats": { + Handler: h.MsgDBStats, + Help: "Returns the statistics of the database.", + }, + "dbstats": { // old lowercase variant + Handler: h.MsgDBStats, + Help: "", // hidden + }, + "debugError": { + Handler: h.MsgDebugError, + Help: "Returns error for debugging.", + }, + "delete": { + Handler: h.MsgDelete, + Help: "Deletes documents matched by the query.", + }, + "distinct": { + Handler: h.MsgDistinct, + Help: "Returns an array of distinct values for the given field.", + }, + "drop": { + Handler: h.MsgDrop, + Help: "Drops the collection.", + }, + "dropDatabase": { + Handler: h.MsgDropDatabase, + Help: "Drops production database.", + }, + "dropIndexes": { + Handler: h.MsgDropIndexes, + Help: "Drops indexes on a collection.", + }, + "explain": { + Handler: h.MsgExplain, + Help: "Returns the execution plan.", + }, + "find": { + Handler: h.MsgFind, + Help: "Returns documents matched by the query.", + }, + "findAndModify": { + Handler: h.MsgFindAndModify, + Help: "Updates or deletes, and returns a document matched by the query.", + }, + "findandmodify": { // old lowercase variant + Handler: h.MsgFindAndModify, + Help: "", // hidden + }, + "getCmdLineOpts": { + Handler: h.MsgGetCmdLineOpts, + Help: "Returns a summary of all runtime and configuration options.", + }, + "getFreeMonitoringStatus": { + Handler: h.MsgGetFreeMonitoringStatus, + Help: "Returns a status of the free monitoring.", + }, + "getLog": { + Handler: h.MsgGetLog, + Help: "Returns the most recent logged events from memory.", + }, + "getMore": { + Handler: h.MsgGetMore, + Help: "Returns the next batch of documents from a cursor.", + }, + "getParameter": { + Handler: h.MsgGetParameter, + Help: "Returns the value of the parameter.", + }, + "hello": { + Handler: h.MsgHello, + Help: "Returns the role of the FerretDB instance.", + }, + "hostInfo": { + Handler: h.MsgHostInfo, + Help: "Returns a summary of the system information.", + }, + "insert": { + Handler: h.MsgInsert, + Help: "Inserts documents into the database.", + }, + "isMaster": { + Handler: h.MsgIsMaster, + Help: "Returns the role of the FerretDB instance.", + }, + "ismaster": { // old lowercase variant + Handler: h.MsgIsMaster, + Help: "", // hidden + }, + "killCursors": { + Handler: h.MsgKillCursors, + Help: "Closes server cursors.", + }, + "listCollections": { + Handler: h.MsgListCollections, + Help: "Returns the information of the collections and views in the database.", + }, + "listCommands": { + Handler: h.MsgListCommands, + Help: "Returns a list of currently supported commands.", + }, + "listDatabases": { + Handler: h.MsgListDatabases, + Help: "Returns a summary of all the databases.", + }, + "listIndexes": { + Handler: h.MsgListIndexes, + Help: "Returns a summary of indexes of the specified collection.", + }, + "logout": { + Handler: h.MsgLogout, + Help: "Logs out from the current session.", + }, + "ping": { + Handler: h.MsgPing, + Help: "Returns a pong response.", + }, + "renameCollection": { + Handler: h.MsgRenameCollection, + Help: "Changes the name of an existing collection.", + }, + "saslStart": { + Handler: h.MsgSASLStart, + Help: "Starts a SASL conversation.", + }, + "serverStatus": { + Handler: h.MsgServerStatus, + Help: "Returns an overview of the databases state.", + }, + "setFreeMonitoring": { + Handler: h.MsgSetFreeMonitoring, + Help: "Toggles free monitoring.", + }, + "update": { + Handler: h.MsgUpdate, + Help: "Updates documents that are matched by the query.", + }, + "validate": { + Handler: h.MsgValidate, + Help: "Validates collection.", + }, + "whatsmyuri": { + Handler: h.MsgWhatsMyURI, + Help: "Returns peer information.", + }, + // please keep sorted alphabetically + } + + if h.EnableNewAuth { + // sorted alphabetically + h.commands["createUser"] = command{ + Handler: h.MsgCreateUser, + Help: "Creates a new user.", + } + h.commands["dropAllUsersFromDatabase"] = command{ + Handler: h.MsgDropAllUsersFromDatabase, + Help: "Drops all user from database.", + } + h.commands["dropUser"] = command{ + Handler: h.MsgDropUser, + Help: "Drops user.", + } + h.commands["updateUser"] = command{ + Handler: h.MsgUpdateUser, + Help: "Updates user.", + } + h.commands["usersInfo"] = command{ + Handler: h.MsgUpdateUser, + Help: "Returns information about users.", + } + // please keep sorted alphabetically + } +} + +// Commands returns a map of enabled commands. +func (h *Handler) Commands() map[string]command { + return h.commands +} diff --git a/internal/handler/handler.go b/internal/handler/handler.go index 1a5037df0db4..6c5d8bc89654 100644 --- a/internal/handler/handler.go +++ b/internal/handler/handler.go @@ -31,14 +31,14 @@ import ( // MsgXXX methods handle OP_MSG commands. // CmdQuery handles a limited subset of OP_QUERY messages. // -// Handler is shared between all connections! Be careful when you need connection-specific information. -// Currently, we pass connection information through context, see `ConnInfo` and its usage. +// Handler instance is shared between all client connections. type Handler struct { *NewOpts b backends.Backend - cursors *cursor.Registry + cursors *cursor.Registry + commands map[string]command } // NewOpts represents handler configuration. @@ -54,6 +54,7 @@ type NewOpts struct { // test options DisableFilterPushdown bool EnableOplog bool + EnableNewAuth bool } // New returns a new handler. @@ -64,11 +65,15 @@ func New(opts *NewOpts) (*Handler, error) { b = oplog.NewBackend(b, opts.L.Named("oplog")) } - return &Handler{ + h := &Handler{ b: b, NewOpts: opts, cursors: cursor.NewRegistry(opts.L.Named("cursors")), - }, nil + } + + h.initCommands() + + return h, nil } // Close gracefully shutdowns handler. diff --git a/internal/handler/msg_createuser.go b/internal/handler/msg_createuser.go new file mode 100644 index 000000000000..5c83d098c608 --- /dev/null +++ b/internal/handler/msg_createuser.go @@ -0,0 +1,34 @@ +// Copyright 2021 FerretDB Inc. +// +// 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 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package handler + +import ( + "context" + + "github.com/FerretDB/FerretDB/internal/handler/common" + "github.com/FerretDB/FerretDB/internal/util/lazyerrors" + "github.com/FerretDB/FerretDB/internal/wire" +) + +// MsgCreateUser implements `createUser` command. +func (h *Handler) MsgCreateUser(ctx context.Context, msg *wire.OpMsg) (*wire.OpMsg, error) { + document, err := msg.Document() + if err != nil { + return nil, lazyerrors.Error(err) + } + + // TODO https://github.com/FerretDB/FerretDB/issues/1491 + return nil, common.Unimplemented(document, document.Command()) +} diff --git a/internal/handler/msg_dropallusersfromdatabase.go b/internal/handler/msg_dropallusersfromdatabase.go new file mode 100644 index 000000000000..ba64f2d5f27c --- /dev/null +++ b/internal/handler/msg_dropallusersfromdatabase.go @@ -0,0 +1,34 @@ +// Copyright 2021 FerretDB Inc. +// +// 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 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package handler + +import ( + "context" + + "github.com/FerretDB/FerretDB/internal/handler/common" + "github.com/FerretDB/FerretDB/internal/util/lazyerrors" + "github.com/FerretDB/FerretDB/internal/wire" +) + +// MsgDropAllUsersFromDatabase implements `dropAllUsersFromDatabase` command. +func (h *Handler) MsgDropAllUsersFromDatabase(ctx context.Context, msg *wire.OpMsg) (*wire.OpMsg, error) { + document, err := msg.Document() + if err != nil { + return nil, lazyerrors.Error(err) + } + + // TODO https://github.com/FerretDB/FerretDB/issues/1492 + return nil, common.Unimplemented(document, document.Command()) +} diff --git a/internal/handler/msg_dropuser.go b/internal/handler/msg_dropuser.go new file mode 100644 index 000000000000..b915f518d2ac --- /dev/null +++ b/internal/handler/msg_dropuser.go @@ -0,0 +1,34 @@ +// Copyright 2021 FerretDB Inc. +// +// 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 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package handler + +import ( + "context" + + "github.com/FerretDB/FerretDB/internal/handler/common" + "github.com/FerretDB/FerretDB/internal/util/lazyerrors" + "github.com/FerretDB/FerretDB/internal/wire" +) + +// MsgDropUser implements `dropUser` command. +func (h *Handler) MsgDropUser(ctx context.Context, msg *wire.OpMsg) (*wire.OpMsg, error) { + document, err := msg.Document() + if err != nil { + return nil, lazyerrors.Error(err) + } + + // TODO https://github.com/FerretDB/FerretDB/issues/1493 + return nil, common.Unimplemented(document, document.Command()) +} diff --git a/internal/handler/msg_listcommands.go b/internal/handler/msg_listcommands.go index 5cd9b136d824..d6b1155b275f 100644 --- a/internal/handler/msg_listcommands.go +++ b/internal/handler/msg_listcommands.go @@ -25,226 +25,14 @@ import ( "github.com/FerretDB/FerretDB/internal/wire" ) -// command represents a handler command. -type command struct { - // Handler processes this command. - // - // The passed context is canceled when the client disconnects. - Handler func(*Handler, context.Context, *wire.OpMsg) (*wire.OpMsg, error) - - // Help is shown in the help function. - // If empty, that command is skipped in `listCommands` output. - Help string -} - -// Commands maps commands names to descriptions and implementations. -var Commands = map[string]command{ - // sorted alphabetically - "aggregate": { - Handler: (*Handler).MsgAggregate, - Help: "Returns aggregated data.", - }, - "buildInfo": { - Handler: (*Handler).MsgBuildInfo, - Help: "Returns a summary of the build information.", - }, - "buildinfo": { // old lowercase variant - Handler: (*Handler).MsgBuildInfo, - }, - "collMod": { - Handler: (*Handler).MsgCollMod, - Help: "Adds options to a collection or modify view definitions.", - }, - "collStats": { - Handler: (*Handler).MsgCollStats, - Help: "Returns storage data for a collection.", - }, - "compact": { - Handler: (*Handler).MsgCompact, - Help: "Reduces the disk space collection takes and refreshes its statistics.", - }, - "connectionStatus": { - Handler: (*Handler).MsgConnectionStatus, - Help: "Returns information about the current connection, " + - "specifically the state of authenticated users and their available permissions.", - }, - "count": { - Handler: (*Handler).MsgCount, - Help: "Returns the count of documents that's matched by the query.", - }, - "create": { - Handler: (*Handler).MsgCreate, - Help: "Creates the collection.", - }, - "createIndexes": { - Handler: (*Handler).MsgCreateIndexes, - Help: "Creates indexes on a collection.", - }, - "currentOp": { - Handler: (*Handler).MsgCurrentOp, - Help: "Returns information about operations currently in progress.", - }, - "dataSize": { - Handler: (*Handler).MsgDataSize, - Help: "Returns the size of the collection in bytes.", - }, - "dbStats": { - Handler: (*Handler).MsgDBStats, - Help: "Returns the statistics of the database.", - }, - "dbstats": { // old lowercase variant - Handler: (*Handler).MsgDBStats, - }, - "debugError": { - Handler: (*Handler).MsgDebugError, - Help: "Returns error for debugging.", - }, - "delete": { - Handler: (*Handler).MsgDelete, - Help: "Deletes documents matched by the query.", - }, - "distinct": { - Handler: (*Handler).MsgDistinct, - Help: "Returns an array of distinct values for the given field.", - }, - "drop": { - Handler: (*Handler).MsgDrop, - Help: "Drops the collection.", - }, - "dropDatabase": { - Handler: (*Handler).MsgDropDatabase, - Help: "Drops production database.", - }, - "dropIndexes": { - Handler: (*Handler).MsgDropIndexes, - Help: "Drops indexes on a collection.", - }, - "explain": { - Handler: (*Handler).MsgExplain, - Help: "Returns the execution plan.", - }, - "find": { - Handler: (*Handler).MsgFind, - Help: "Returns documents matched by the query.", - }, - "findAndModify": { - Handler: (*Handler).MsgFindAndModify, - Help: "Docs, updates, or deletes, and returns a document matched by the query.", - }, - "findandmodify": { // old lowercase variant - Handler: (*Handler).MsgFindAndModify, - }, - "getCmdLineOpts": { - Handler: (*Handler).MsgGetCmdLineOpts, - Help: "Returns a summary of all runtime and configuration options.", - }, - "getFreeMonitoringStatus": { - Handler: (*Handler).MsgGetFreeMonitoringStatus, - Help: "Returns a status of the free monitoring.", - }, - "getLog": { - Handler: (*Handler).MsgGetLog, - Help: "Returns the most recent logged events from memory.", - }, - "getMore": { - Handler: (*Handler).MsgGetMore, - Help: "Returns the next batch of documents from a cursor.", - }, - "getParameter": { - Handler: (*Handler).MsgGetParameter, - Help: "Returns the value of the parameter.", - }, - "hello": { - Handler: (*Handler).MsgHello, - Help: "Returns the role of the FerretDB instance.", - }, - "hostInfo": { - Handler: (*Handler).MsgHostInfo, - Help: "Returns a summary of the system information.", - }, - "insert": { - Handler: (*Handler).MsgInsert, - Help: "Docs documents into the database.", - }, - "isMaster": { - Handler: (*Handler).MsgIsMaster, - Help: "Returns the role of the FerretDB instance.", - }, - "ismaster": { // old lowercase variant - Handler: (*Handler).MsgIsMaster, - }, - "killCursors": { - Handler: (*Handler).MsgKillCursors, - Help: "Closes server cursors.", - }, - "listCollections": { - Handler: (*Handler).MsgListCollections, - Help: "Returns the information of the collections and views in the database.", - }, - // listCommands is added by the init() function below. - "listDatabases": { - Handler: (*Handler).MsgListDatabases, - Help: "Returns a summary of all the databases.", - }, - "listIndexes": { - Handler: (*Handler).MsgListIndexes, - Help: "Returns a summary of indexes of the specified collection.", - }, - "logout": { - Handler: (*Handler).MsgLogout, - Help: "Logs out from the current session.", - }, - "ping": { - Handler: (*Handler).MsgPing, - Help: "Returns a pong response.", - }, - "renameCollection": { - Handler: (*Handler).MsgRenameCollection, - Help: "Changes the name of an existing collection.", - }, - "saslStart": { - Handler: (*Handler).MsgSASLStart, - Help: "Starts a SASL conversation.", - }, - "serverStatus": { - Handler: (*Handler).MsgServerStatus, - Help: "Returns an overview of the databases state.", - }, - "setFreeMonitoring": { - Handler: (*Handler).MsgSetFreeMonitoring, - Help: "Toggles free monitoring.", - }, - "update": { - Handler: (*Handler).MsgUpdate, - Help: "Updates documents that are matched by the query.", - }, - "validate": { - Handler: (*Handler).MsgValidate, - Help: "Validate collection.", - }, - "whatsmyuri": { - Handler: (*Handler).MsgWhatsMyURI, - Help: "Returns peer information.", - }, - // please keep sorted alphabetically -} - -func init() { - // to prevent the initialization cycle - Commands["listCommands"] = command{ - Handler: (*Handler).MsgListCommands, - Help: "Returns a list of currently supported commands.", - } -} - // MsgListCommands implements `listCommands` command. func (h *Handler) MsgListCommands(ctx context.Context, msg *wire.OpMsg) (*wire.OpMsg, error) { cmdList := must.NotFail(types.NewDocument()) - names := maps.Keys(Commands) + names := maps.Keys(h.Commands()) sort.Strings(names) for _, name := range names { - cmd := Commands[name] + cmd := h.Commands()[name] if cmd.Help == "" { continue } diff --git a/internal/handler/msg_updateuser.go b/internal/handler/msg_updateuser.go new file mode 100644 index 000000000000..15396da0e207 --- /dev/null +++ b/internal/handler/msg_updateuser.go @@ -0,0 +1,34 @@ +// Copyright 2021 FerretDB Inc. +// +// 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 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package handler + +import ( + "context" + + "github.com/FerretDB/FerretDB/internal/handler/common" + "github.com/FerretDB/FerretDB/internal/util/lazyerrors" + "github.com/FerretDB/FerretDB/internal/wire" +) + +// MsgUpdateUser implements `updateUser` command. +func (h *Handler) MsgUpdateUser(ctx context.Context, msg *wire.OpMsg) (*wire.OpMsg, error) { + document, err := msg.Document() + if err != nil { + return nil, lazyerrors.Error(err) + } + + // TODO https://github.com/FerretDB/FerretDB/issues/1496 + return nil, common.Unimplemented(document, document.Command()) +} diff --git a/internal/handler/msg_usersinfo.go b/internal/handler/msg_usersinfo.go new file mode 100644 index 000000000000..16b5d4473ba9 --- /dev/null +++ b/internal/handler/msg_usersinfo.go @@ -0,0 +1,34 @@ +// Copyright 2021 FerretDB Inc. +// +// 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 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package handler + +import ( + "context" + + "github.com/FerretDB/FerretDB/internal/handler/common" + "github.com/FerretDB/FerretDB/internal/util/lazyerrors" + "github.com/FerretDB/FerretDB/internal/wire" +) + +// MsgUsersInfo implements `usersInfo` command. +func (h *Handler) MsgUsersInfo(ctx context.Context, msg *wire.OpMsg) (*wire.OpMsg, error) { + document, err := msg.Document() + if err != nil { + return nil, lazyerrors.Error(err) + } + + // TODO https://github.com/FerretDB/FerretDB/issues/1497 + return nil, common.Unimplemented(document, document.Command()) +} diff --git a/internal/handler/registry/hana.go b/internal/handler/registry/hana.go index 318fd4df82ca..e4e5b429114f 100644 --- a/internal/handler/registry/hana.go +++ b/internal/handler/registry/hana.go @@ -44,6 +44,7 @@ func init() { DisableFilterPushdown: opts.DisableFilterPushdown, EnableOplog: opts.EnableOplog, + EnableNewAuth: opts.EnableNewAuth, } h, err := handler.New(handlerOpts) diff --git a/internal/handler/registry/mysql.go b/internal/handler/registry/mysql.go index a215fc365e27..16ed50155d85 100644 --- a/internal/handler/registry/mysql.go +++ b/internal/handler/registry/mysql.go @@ -40,6 +40,7 @@ func init() { DisableFilterPushdown: opts.DisableFilterPushdown, EnableOplog: opts.EnableOplog, + EnableNewAuth: opts.EnableNewAuth, } h, err := handler.New(handlerOpts) diff --git a/internal/handler/registry/postgresql.go b/internal/handler/registry/postgresql.go index 8337d532d81a..7c8dabdaf1b3 100644 --- a/internal/handler/registry/postgresql.go +++ b/internal/handler/registry/postgresql.go @@ -40,6 +40,7 @@ func init() { DisableFilterPushdown: opts.DisableFilterPushdown, EnableOplog: opts.EnableOplog, + EnableNewAuth: opts.EnableNewAuth, } h, err := handler.New(handlerOpts) diff --git a/internal/handler/registry/registry.go b/internal/handler/registry/registry.go index a44d5e9105e2..5a22729f07d5 100644 --- a/internal/handler/registry/registry.go +++ b/internal/handler/registry/registry.go @@ -63,6 +63,7 @@ type NewHandlerOpts struct { type TestOpts struct { DisableFilterPushdown bool EnableOplog bool + EnableNewAuth bool } // NewHandler constructs a new handler. diff --git a/internal/handler/registry/sqlite.go b/internal/handler/registry/sqlite.go index b1308c4aa612..803e6f79e762 100644 --- a/internal/handler/registry/sqlite.go +++ b/internal/handler/registry/sqlite.go @@ -40,6 +40,7 @@ func init() { DisableFilterPushdown: opts.DisableFilterPushdown, EnableOplog: opts.EnableOplog, + EnableNewAuth: opts.EnableNewAuth, } h, err := handler.New(handlerOpts)