CLI tests for 'ntfy user'
This commit is contained in:
parent
1c9766b8fd
commit
29c2fc5472
4 changed files with 160 additions and 20 deletions
60
cmd/user.go
60
cmd/user.go
|
@ -23,8 +23,9 @@ var cmdUser = &cli.Command{
|
||||||
{
|
{
|
||||||
Name: "add",
|
Name: "add",
|
||||||
Aliases: []string{"a"},
|
Aliases: []string{"a"},
|
||||||
Usage: "add user",
|
Usage: "Adds a new user",
|
||||||
UsageText: "ntfy user add [--role=admin|user] USERNAME",
|
UsageText: "ntfy user add [--role=admin|user] USERNAME",
|
||||||
|
Before: inheritRootReaderFunc,
|
||||||
Action: execUserAdd,
|
Action: execUserAdd,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
&cli.StringFlag{Name: "role", Aliases: []string{"r"}, Value: string(auth.RoleUser), Usage: "user role"},
|
&cli.StringFlag{Name: "role", Aliases: []string{"r"}, Value: string(auth.RoleUser), Usage: "user role"},
|
||||||
|
@ -43,8 +44,9 @@ Examples:
|
||||||
{
|
{
|
||||||
Name: "remove",
|
Name: "remove",
|
||||||
Aliases: []string{"del", "rm"},
|
Aliases: []string{"del", "rm"},
|
||||||
Usage: "remove user",
|
Usage: "Removes a user",
|
||||||
UsageText: "ntfy user remove USERNAME",
|
UsageText: "ntfy user remove USERNAME",
|
||||||
|
Before: inheritRootReaderFunc,
|
||||||
Action: execUserDel,
|
Action: execUserDel,
|
||||||
Description: `Remove a user from the ntfy user database.
|
Description: `Remove a user from the ntfy user database.
|
||||||
|
|
||||||
|
@ -55,8 +57,9 @@ Example:
|
||||||
{
|
{
|
||||||
Name: "change-pass",
|
Name: "change-pass",
|
||||||
Aliases: []string{"chp"},
|
Aliases: []string{"chp"},
|
||||||
Usage: "change user password",
|
Usage: "Changes a user's password",
|
||||||
UsageText: "ntfy user change-pass USERNAME",
|
UsageText: "ntfy user change-pass USERNAME",
|
||||||
|
Before: inheritRootReaderFunc,
|
||||||
Action: execUserChangePass,
|
Action: execUserChangePass,
|
||||||
Description: `Change the password for the given user.
|
Description: `Change the password for the given user.
|
||||||
|
|
||||||
|
@ -70,8 +73,9 @@ Example:
|
||||||
{
|
{
|
||||||
Name: "change-role",
|
Name: "change-role",
|
||||||
Aliases: []string{"chr"},
|
Aliases: []string{"chr"},
|
||||||
Usage: "change user role",
|
Usage: "Changes the role of a user",
|
||||||
UsageText: "ntfy user change-role USERNAME ROLE",
|
UsageText: "ntfy user change-role USERNAME ROLE",
|
||||||
|
Before: inheritRootReaderFunc,
|
||||||
Action: execUserChangeRole,
|
Action: execUserChangeRole,
|
||||||
Description: `Change the role for the given user to admin or user.
|
Description: `Change the role for the given user to admin or user.
|
||||||
|
|
||||||
|
@ -92,7 +96,8 @@ Example:
|
||||||
{
|
{
|
||||||
Name: "list",
|
Name: "list",
|
||||||
Aliases: []string{"l"},
|
Aliases: []string{"l"},
|
||||||
Usage: "list users",
|
Usage: "Shows a list of users",
|
||||||
|
Before: inheritRootReaderFunc,
|
||||||
Action: execUserList,
|
Action: execUserList,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -125,18 +130,21 @@ func execUserAdd(c *cli.Context) error {
|
||||||
} else if !auth.AllowedRole(role) {
|
} else if !auth.AllowedRole(role) {
|
||||||
return errors.New("role must be either 'user' or 'admin'")
|
return errors.New("role must be either 'user' or 'admin'")
|
||||||
}
|
}
|
||||||
password, err := readPassword(c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
manager, err := createAuthManager(c)
|
manager, err := createAuthManager(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := manager.AddUser(username, password, auth.Role(role)); err != nil {
|
if user, _ := manager.User(username); user != nil {
|
||||||
|
return fmt.Errorf("user %s already exists", username)
|
||||||
|
}
|
||||||
|
password, err := readPassword(c)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Fprintf(c.App.ErrWriter, "User %s added with role %s\n", username, role)
|
if err := manager.AddUser(username, password, role); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(c.App.ErrWriter, "user %s added with role %s\n", username, role)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,10 +159,13 @@ func execUserDel(c *cli.Context) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if _, err := manager.User(username); err == auth.ErrNotFound {
|
||||||
|
return fmt.Errorf("user %s does not exist", username)
|
||||||
|
}
|
||||||
if err := manager.RemoveUser(username); err != nil {
|
if err := manager.RemoveUser(username); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Fprintf(c.App.ErrWriter, "User %s removed\n", username)
|
fmt.Fprintf(c.App.ErrWriter, "user %s removed\n", username)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,18 +176,21 @@ func execUserChangePass(c *cli.Context) error {
|
||||||
} else if username == userEveryone {
|
} else if username == userEveryone {
|
||||||
return errors.New("username not allowed")
|
return errors.New("username not allowed")
|
||||||
}
|
}
|
||||||
password, err := readPassword(c)
|
manager, err := createAuthManager(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
manager, err := createAuthManager(c)
|
if _, err := manager.User(username); err == auth.ErrNotFound {
|
||||||
|
return fmt.Errorf("user %s does not exist", username)
|
||||||
|
}
|
||||||
|
password, err := readPassword(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := manager.ChangePassword(username, password); err != nil {
|
if err := manager.ChangePassword(username, password); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Fprintf(c.App.ErrWriter, "Changed password for user %s\n", username)
|
fmt.Fprintf(c.App.ErrWriter, "changed password for user %s\n", username)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,10 +206,13 @@ func execUserChangeRole(c *cli.Context) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if _, err := manager.User(username); err == auth.ErrNotFound {
|
||||||
|
return fmt.Errorf("user %s does not exist", username)
|
||||||
|
}
|
||||||
if err := manager.ChangeRole(username, role); err != nil {
|
if err := manager.ChangeRole(username, role); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Fprintf(c.App.ErrWriter, "Changed role for user %s to %s\n", username, role)
|
fmt.Fprintf(c.App.ErrWriter, "changed role for user %s to %s\n", username, role)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,3 +268,14 @@ func userCommandFlags() []cli.Flag {
|
||||||
altsrc.NewStringFlag(&cli.StringFlag{Name: "auth-default-access", Aliases: []string{"p"}, EnvVars: []string{"NTFY_AUTH_DEFAULT_ACCESS"}, Value: "read-write", Usage: "default permissions if no matching entries in the auth database are found"}),
|
altsrc.NewStringFlag(&cli.StringFlag{Name: "auth-default-access", Aliases: []string{"p"}, EnvVars: []string{"NTFY_AUTH_DEFAULT_ACCESS"}, Value: "read-write", Usage: "default permissions if no matching entries in the auth database are found"}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// inheritRootReaderFunc is a workaround for a urfave/cli bug that makes subcommands not inherit the App.Reader.
|
||||||
|
// This bug was fixed in master, but not in v2.3.0.
|
||||||
|
func inheritRootReaderFunc(ctx *cli.Context) error {
|
||||||
|
for _, c := range ctx.Lineage() {
|
||||||
|
if c.App != nil && c.App.Reader != nil {
|
||||||
|
ctx.App.Reader = c.App.Reader
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
103
cmd/user_test.go
Normal file
103
cmd/user_test.go
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
"heckel.io/ntfy/server"
|
||||||
|
"heckel.io/ntfy/test"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCLI_User_Add(t *testing.T) {
|
||||||
|
s, conf, port := newTestServerWithAuth(t)
|
||||||
|
defer test.StopServer(t, s, port)
|
||||||
|
|
||||||
|
app, stdin, _, stderr := newTestApp()
|
||||||
|
stdin.WriteString("mypass\nmypass")
|
||||||
|
require.Nil(t, runUserCommand(app, conf, "add", "phil"))
|
||||||
|
require.Contains(t, stderr.String(), "user phil added with role user")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCLI_User_Add_Exists(t *testing.T) {
|
||||||
|
s, conf, port := newTestServerWithAuth(t)
|
||||||
|
defer test.StopServer(t, s, port)
|
||||||
|
|
||||||
|
app, stdin, _, stderr := newTestApp()
|
||||||
|
stdin.WriteString("mypass\nmypass")
|
||||||
|
require.Nil(t, runUserCommand(app, conf, "add", "phil"))
|
||||||
|
require.Contains(t, stderr.String(), "user phil added with role user")
|
||||||
|
|
||||||
|
app, stdin, _, stderr = newTestApp()
|
||||||
|
stdin.WriteString("mypass\nmypass")
|
||||||
|
err := runUserCommand(app, conf, "add", "phil")
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Contains(t, err.Error(), "user phil already exists")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCLI_User_Add_Admin(t *testing.T) {
|
||||||
|
s, conf, port := newTestServerWithAuth(t)
|
||||||
|
defer test.StopServer(t, s, port)
|
||||||
|
|
||||||
|
app, stdin, _, stderr := newTestApp()
|
||||||
|
stdin.WriteString("mypass\nmypass")
|
||||||
|
require.Nil(t, runUserCommand(app, conf, "add", "--role=admin", "phil"))
|
||||||
|
require.Contains(t, stderr.String(), "user phil added with role admin")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCLI_User_Add_Password_Mismatch(t *testing.T) {
|
||||||
|
s, conf, port := newTestServerWithAuth(t)
|
||||||
|
defer test.StopServer(t, s, port)
|
||||||
|
|
||||||
|
app, stdin, _, _ := newTestApp()
|
||||||
|
stdin.WriteString("mypass\nNOTMATCH")
|
||||||
|
err := runUserCommand(app, conf, "add", "phil")
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Contains(t, err.Error(), "passwords do not match: try it again, but this time type slooowwwlly")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCLI_User_ChangePass(t *testing.T) {
|
||||||
|
s, conf, port := newTestServerWithAuth(t)
|
||||||
|
defer test.StopServer(t, s, port)
|
||||||
|
|
||||||
|
// Add user
|
||||||
|
app, stdin, _, stderr := newTestApp()
|
||||||
|
stdin.WriteString("mypass\nmypass")
|
||||||
|
require.Nil(t, runUserCommand(app, conf, "add", "phil"))
|
||||||
|
require.Contains(t, stderr.String(), "user phil added with role user")
|
||||||
|
|
||||||
|
// Change pass
|
||||||
|
app, stdin, _, stderr = newTestApp()
|
||||||
|
stdin.WriteString("newpass\nnewpass")
|
||||||
|
require.Nil(t, runUserCommand(app, conf, "change-pass", "phil"))
|
||||||
|
require.Contains(t, stderr.String(), "changed password for user phil")
|
||||||
|
}
|
||||||
|
|
||||||
|
func newTestServerWithAuth(t *testing.T) (s *server.Server, conf *server.Config, port int) {
|
||||||
|
conf = server.NewConfig()
|
||||||
|
conf.AuthFile = filepath.Join(t.TempDir(), "user.db")
|
||||||
|
conf.AuthDefaultRead = false
|
||||||
|
conf.AuthDefaultWrite = false
|
||||||
|
s, port = test.StartServerWithConfig(t, conf)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func runUserCommand(app *cli.App, conf *server.Config, args ...string) error {
|
||||||
|
var defaultAccess string
|
||||||
|
if conf.AuthDefaultRead && conf.AuthDefaultWrite {
|
||||||
|
defaultAccess = "read-write"
|
||||||
|
} else if conf.AuthDefaultRead && !conf.AuthDefaultWrite {
|
||||||
|
defaultAccess = "read-only"
|
||||||
|
} else if !conf.AuthDefaultRead && conf.AuthDefaultWrite {
|
||||||
|
defaultAccess = "write-only"
|
||||||
|
} else if !conf.AuthDefaultRead && !conf.AuthDefaultWrite {
|
||||||
|
defaultAccess = "deny-all"
|
||||||
|
}
|
||||||
|
userArgs := []string{
|
||||||
|
"ntfy",
|
||||||
|
"user",
|
||||||
|
"--auth-file=" + conf.AuthFile,
|
||||||
|
"--auth-default-access=" + defaultAccess,
|
||||||
|
}
|
||||||
|
return app.Run(append(userArgs, args...))
|
||||||
|
}
|
8
go.mod
8
go.mod
|
@ -20,13 +20,13 @@ require (
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211
|
||||||
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11
|
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11
|
||||||
google.golang.org/api v0.66.0
|
google.golang.org/api v0.67.0
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.google.com/go v0.100.2 // indirect
|
cloud.google.com/go v0.100.2 // indirect
|
||||||
cloud.google.com/go/compute v1.1.0 // indirect
|
cloud.google.com/go/compute v1.2.0 // indirect
|
||||||
cloud.google.com/go/iam v0.1.1 // indirect
|
cloud.google.com/go/iam v0.1.1 // indirect
|
||||||
github.com/AlekSi/pointer v1.0.0 // indirect
|
github.com/AlekSi/pointer v1.0.0 // indirect
|
||||||
github.com/census-instrumentation/opencensus-proto v0.3.0 // indirect
|
github.com/census-instrumentation/opencensus-proto v0.3.0 // indirect
|
||||||
|
@ -46,11 +46,11 @@ require (
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
go.opencensus.io v0.23.0 // indirect
|
go.opencensus.io v0.23.0 // indirect
|
||||||
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d // indirect
|
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d // indirect
|
||||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect
|
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27 // indirect
|
||||||
golang.org/x/text v0.3.7 // indirect
|
golang.org/x/text v0.3.7 // indirect
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350 // indirect
|
google.golang.org/genproto v0.0.0-20220203182621-f4ae394cde3f // indirect
|
||||||
google.golang.org/grpc v1.44.0 // indirect
|
google.golang.org/grpc v1.44.0 // indirect
|
||||||
google.golang.org/protobuf v1.27.1 // indirect
|
google.golang.org/protobuf v1.27.1 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
|
||||||
|
|
9
go.sum
9
go.sum
|
@ -39,6 +39,8 @@ cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM7
|
||||||
cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow=
|
cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow=
|
||||||
cloud.google.com/go/compute v1.1.0 h1:pyPhehLfZ6pVzRgJmXGYvCY4K7WSWRhVw0AwhgVvS84=
|
cloud.google.com/go/compute v1.1.0 h1:pyPhehLfZ6pVzRgJmXGYvCY4K7WSWRhVw0AwhgVvS84=
|
||||||
cloud.google.com/go/compute v1.1.0/go.mod h1:2NIffxgWfORSI7EOYMFatGTfjMLnqrOKBEyYb6NoRgA=
|
cloud.google.com/go/compute v1.1.0/go.mod h1:2NIffxgWfORSI7EOYMFatGTfjMLnqrOKBEyYb6NoRgA=
|
||||||
|
cloud.google.com/go/compute v1.2.0 h1:EKki8sSdvDU0OO9mAXGwPXOTOgPz2l08R0/IutDH11I=
|
||||||
|
cloud.google.com/go/compute v1.2.0/go.mod h1:xlogom/6gr8RJGBe7nT2eGsQYAFUbbv8dbC29qE3Xmw=
|
||||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||||
cloud.google.com/go/firestore v1.6.1 h1:8rBq3zRjnHx8UtBvaOWqBB1xq9jH6/wltfQLlTMh2Fw=
|
cloud.google.com/go/firestore v1.6.1 h1:8rBq3zRjnHx8UtBvaOWqBB1xq9jH6/wltfQLlTMh2Fw=
|
||||||
|
@ -440,6 +442,8 @@ golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0=
|
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0=
|
||||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27 h1:XDXtA5hveEEV8JB2l7nhMTp3t3cHp9ZpwcdjqyEWLlo=
|
||||||
|
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
|
||||||
|
@ -553,6 +557,8 @@ google.golang.org/api v0.64.0/go.mod h1:931CdxA8Rm4t6zqTFGSsgwbAEZ2+GMYurbndwSim
|
||||||
google.golang.org/api v0.65.0/go.mod h1:ArYhxgGadlWmqO1IqVujw6Cs8IdD33bTmzKo2Sh+cbg=
|
google.golang.org/api v0.65.0/go.mod h1:ArYhxgGadlWmqO1IqVujw6Cs8IdD33bTmzKo2Sh+cbg=
|
||||||
google.golang.org/api v0.66.0 h1:CbGy4LEiXCVCiNEDFgGpWOVwsDT7E2Qej1ZvN1P7KPg=
|
google.golang.org/api v0.66.0 h1:CbGy4LEiXCVCiNEDFgGpWOVwsDT7E2Qej1ZvN1P7KPg=
|
||||||
google.golang.org/api v0.66.0/go.mod h1:I1dmXYpX7HGwz/ejRxwQp2qj5bFAz93HiCU1C1oYd9M=
|
google.golang.org/api v0.66.0/go.mod h1:I1dmXYpX7HGwz/ejRxwQp2qj5bFAz93HiCU1C1oYd9M=
|
||||||
|
google.golang.org/api v0.67.0 h1:lYaaLa+x3VVUhtosaK9xihwQ9H9KRa557REHwwZ2orM=
|
||||||
|
google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g=
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
@ -633,6 +639,9 @@ google.golang.org/genproto v0.0.0-20220114231437-d2e6a121cae0/go.mod h1:5CzLGKJ6
|
||||||
google.golang.org/genproto v0.0.0-20220118154757-00ab72f36ad5/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
google.golang.org/genproto v0.0.0-20220118154757-00ab72f36ad5/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||||
google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350 h1:YxHp5zqIcAShDEvRr5/0rVESVS+njYF68PSdazrNLJo=
|
google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350 h1:YxHp5zqIcAShDEvRr5/0rVESVS+njYF68PSdazrNLJo=
|
||||||
google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||||
|
google.golang.org/genproto v0.0.0-20220201184016-50beb8ab5c44/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||||
|
google.golang.org/genproto v0.0.0-20220203182621-f4ae394cde3f h1:w9Sx4FBkwsN0jMZz8E42tMdmhZ5b2Z/vFx2LKAxxI9o=
|
||||||
|
google.golang.org/genproto v0.0.0-20220203182621-f4ae394cde3f/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||||
|
|
Loading…
Reference in a new issue