Create new generic keyring constructor: NewKeyring (#5547)
Remove other convenience constructors: * Remove NewKeyBaseFromHomeFlag * Remove NewKeyringFromDir * Remove NewKeyringFromHomeFlag
This commit is contained in:
@@ -14,9 +14,8 @@ import (
|
||||
rpcclient "github.com/tendermint/tendermint/rpc/client"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/client/keys"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
cryptokeys "github.com/cosmos/cosmos-sdk/crypto/keys"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
@@ -26,7 +25,7 @@ type CLIContext struct {
|
||||
FromAddress sdk.AccAddress
|
||||
Client rpcclient.Client
|
||||
ChainID string
|
||||
Keybase cryptokeys.Keybase
|
||||
Keybase keys.Keybase
|
||||
Input io.Reader
|
||||
Output io.Writer
|
||||
OutputFormat string
|
||||
@@ -275,12 +274,13 @@ func GetFromFields(input io.Reader, from string, genOnly bool) (sdk.AccAddress,
|
||||
return addr, "", nil
|
||||
}
|
||||
|
||||
keybase, err := keys.NewKeyringFromHomeFlag(input)
|
||||
keybase, err := keys.NewKeyring(sdk.GetConfig().GetKeyringServiceName(),
|
||||
viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), input)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
var info cryptokeys.Info
|
||||
var info keys.Info
|
||||
if addr, err := sdk.AccAddressFromBech32(from); err == nil {
|
||||
info, err = keybase.GetByAddress(addr)
|
||||
if err != nil {
|
||||
|
||||
@@ -9,6 +9,8 @@ import (
|
||||
"github.com/spf13/viper"
|
||||
|
||||
tmcli "github.com/tendermint/tendermint/libs/cli"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys"
|
||||
)
|
||||
|
||||
// nolint
|
||||
@@ -21,10 +23,7 @@ const (
|
||||
GasFlagAuto = "auto"
|
||||
|
||||
// DefaultKeyringBackend
|
||||
DefaultKeyringBackend = KeyringBackendOS
|
||||
KeyringBackendFile = "file"
|
||||
KeyringBackendOS = "os"
|
||||
KeyringBackendTest = "test"
|
||||
DefaultKeyringBackend = keys.BackendOS
|
||||
|
||||
// BroadcastBlock defines a tx broadcasting mode where the client waits for
|
||||
// the tx to be committed in a block.
|
||||
|
||||
+1
-1
@@ -86,7 +86,7 @@ func getKeybase(transient bool, buf io.Reader) (keys.Keybase, error) {
|
||||
return keys.NewInMemory(), nil
|
||||
}
|
||||
|
||||
return NewKeyringFromHomeFlag(buf)
|
||||
return keys.NewKeyring(sdk.GetConfig().GetKeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), buf)
|
||||
}
|
||||
|
||||
func runAddCmd(cmd *cobra.Command, args []string) error {
|
||||
|
||||
@@ -51,7 +51,7 @@ func Test_runAddCmdLedgerWithCustomCoinType(t *testing.T) {
|
||||
require.NoError(t, runAddCmd(cmd, []string{"keyname1"}))
|
||||
|
||||
// Now check that it has been stored properly
|
||||
kb, err := NewKeyringFromHomeFlag(mockIn)
|
||||
kb, err := keys.NewKeyring(sdk.GetConfig().GetKeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), mockIn)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, kb)
|
||||
defer func() {
|
||||
@@ -98,7 +98,7 @@ func Test_runAddCmdLedger(t *testing.T) {
|
||||
require.NoError(t, runAddCmd(cmd, []string{"keyname1"}))
|
||||
|
||||
// Now check that it has been stored properly
|
||||
kb, err := NewKeyringFromHomeFlag(mockIn)
|
||||
kb, err := keys.NewKeyring(sdk.GetConfig().GetKeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), kbHome, mockIn)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, kb)
|
||||
defer func() {
|
||||
|
||||
@@ -10,7 +10,9 @@ import (
|
||||
"github.com/tendermint/tendermint/libs/cli"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys"
|
||||
"github.com/cosmos/cosmos-sdk/tests"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
func Test_runAddCmdBasic(t *testing.T) {
|
||||
@@ -29,7 +31,7 @@ func Test_runAddCmdBasic(t *testing.T) {
|
||||
mockIn.Reset("testpass1\ntestpass1\n")
|
||||
} else {
|
||||
mockIn.Reset("y\n")
|
||||
kb, err := NewKeyringFromHomeFlag(mockIn)
|
||||
kb, err := keys.NewKeyring(sdk.GetConfig().GetKeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), kbHome, mockIn)
|
||||
require.NoError(t, err)
|
||||
defer func() {
|
||||
kb.Delete("keyname1", "", false)
|
||||
|
||||
@@ -4,8 +4,10 @@ import (
|
||||
"bufio"
|
||||
"errors"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/client/input"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
@@ -41,7 +43,7 @@ private keys stored in a ledger device cannot be deleted with the CLI.
|
||||
func runDeleteCmd(cmd *cobra.Command, args []string) error {
|
||||
buf := bufio.NewReader(cmd.InOrStdin())
|
||||
|
||||
kb, err := NewKeyringFromHomeFlag(buf)
|
||||
kb, err := keys.NewKeyring(sdk.GetConfig().GetKeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys"
|
||||
"github.com/cosmos/cosmos-sdk/tests"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
func Test_runDeleteCmd(t *testing.T) {
|
||||
@@ -26,7 +27,7 @@ func Test_runDeleteCmd(t *testing.T) {
|
||||
fakeKeyName1 := "runDeleteCmd_Key1"
|
||||
fakeKeyName2 := "runDeleteCmd_Key2"
|
||||
if !runningUnattended {
|
||||
kb, err := NewKeyringFromHomeFlag(mockIn)
|
||||
kb, err := keys.NewKeyring(sdk.GetConfig().GetKeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), mockIn)
|
||||
require.NoError(t, err)
|
||||
defer func() {
|
||||
kb.Delete("runDeleteCmd_Key1", "", false)
|
||||
@@ -40,7 +41,7 @@ func Test_runDeleteCmd(t *testing.T) {
|
||||
viper.Set(flags.FlagHome, kbHome)
|
||||
|
||||
// Now
|
||||
kb, err := NewKeyringFromHomeFlag(mockIn)
|
||||
kb, err := keys.NewKeyring(sdk.GetConfig().GetKeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), kbHome, mockIn)
|
||||
require.NoError(t, err)
|
||||
if runningUnattended {
|
||||
mockIn.Reset("testpass1\ntestpass1\n")
|
||||
|
||||
@@ -4,8 +4,12 @@ import (
|
||||
"bufio"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/client/input"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
// ExportKeyCommand exports private keys from the key store.
|
||||
@@ -21,7 +25,7 @@ func ExportKeyCommand() *cobra.Command {
|
||||
|
||||
func runExportCmd(cmd *cobra.Command, args []string) error {
|
||||
buf := bufio.NewReader(cmd.InOrStdin())
|
||||
kb, err := NewKeyringFromHomeFlag(buf)
|
||||
kb, err := keys.NewKeyring(sdk.GetConfig().GetKeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys"
|
||||
"github.com/cosmos/cosmos-sdk/tests"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
func Test_runExportCmd(t *testing.T) {
|
||||
@@ -22,7 +23,7 @@ func Test_runExportCmd(t *testing.T) {
|
||||
viper.Set(flags.FlagHome, kbHome)
|
||||
|
||||
// create a key
|
||||
kb, err := NewKeyringFromHomeFlag(mockIn)
|
||||
kb, err := keys.NewKeyring(sdk.GetConfig().GetKeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), mockIn)
|
||||
require.NoError(t, err)
|
||||
if !runningUnattended {
|
||||
defer func() {
|
||||
|
||||
@@ -5,8 +5,12 @@ import (
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/client/input"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
// ImportKeyCommand imports private keys from a keyfile.
|
||||
@@ -22,7 +26,7 @@ func ImportKeyCommand() *cobra.Command {
|
||||
|
||||
func runImportCmd(cmd *cobra.Command, args []string) error {
|
||||
buf := bufio.NewReader(cmd.InOrStdin())
|
||||
kb, err := NewKeyringFromHomeFlag(buf)
|
||||
kb, err := keys.NewKeyring(sdk.GetConfig().GetKeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -9,7 +9,9 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys"
|
||||
"github.com/cosmos/cosmos-sdk/tests"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
func Test_runImportCmd(t *testing.T) {
|
||||
@@ -23,7 +25,7 @@ func Test_runImportCmd(t *testing.T) {
|
||||
viper.Set(flags.FlagHome, kbHome)
|
||||
|
||||
if !runningUnattended {
|
||||
kb, err := NewKeyringFromHomeFlag(mockIn)
|
||||
kb, err := keys.NewKeyring(sdk.GetConfig().GetKeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), mockIn)
|
||||
require.NoError(t, err)
|
||||
defer func() {
|
||||
kb.Delete("keyname1", "", false)
|
||||
|
||||
+3
-1
@@ -5,6 +5,8 @@ import (
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
const flagListNames = "list-names"
|
||||
@@ -24,7 +26,7 @@ along with their associated name and address.`,
|
||||
}
|
||||
|
||||
func runListCmd(cmd *cobra.Command, _ []string) error {
|
||||
kb, err := NewKeyringFromHomeFlag(cmd.InOrStdin())
|
||||
kb, err := keys.NewKeyring(sdk.GetConfig().GetKeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), cmd.InOrStdin())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys"
|
||||
"github.com/cosmos/cosmos-sdk/tests"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
func Test_runListCmd(t *testing.T) {
|
||||
@@ -31,7 +32,7 @@ func Test_runListCmd(t *testing.T) {
|
||||
viper.Set(flags.FlagHome, kbHome2)
|
||||
|
||||
mockIn, _, _ := tests.ApplyMockIO(cmdBasic)
|
||||
kb, err := NewKeyringFromHomeFlag(mockIn)
|
||||
kb, err := keys.NewKeyring(sdk.GetConfig().GetKeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), mockIn)
|
||||
require.NoError(t, err)
|
||||
if runningUnattended {
|
||||
mockIn.Reset("testpass1\ntestpass1\n")
|
||||
|
||||
@@ -70,9 +70,9 @@ func runMigrateCmd(cmd *cobra.Command, args []string) error {
|
||||
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
keybase, err = keys.NewTestKeyring(keyringServiceName, tmpDir)
|
||||
keybase, err = keys.NewKeyring(keyringServiceName, "test", tmpDir, buf)
|
||||
} else {
|
||||
keybase, err = keys.NewKeyring(keyringServiceName, rootDir, buf)
|
||||
keybase, err = keys.NewKeyring(keyringServiceName, viper.GetString(flags.FlagKeyringBackend), rootDir, buf)
|
||||
}
|
||||
if err != nil {
|
||||
return errors.Wrap(err, fmt.Sprintf(
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys"
|
||||
)
|
||||
|
||||
func TestCommands(t *testing.T) {
|
||||
@@ -19,6 +20,6 @@ func TestCommands(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
viper.Set(flags.FlagKeyringBackend, flags.KeyringBackendTest)
|
||||
viper.Set(flags.FlagKeyringBackend, keys.BackendTest)
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
+1
-1
@@ -57,7 +57,7 @@ consisting of all the keys provided by name and multisig threshold.`,
|
||||
func runShowCmd(cmd *cobra.Command, args []string) (err error) {
|
||||
var info keys.Info
|
||||
|
||||
kb, err := NewKeyringFromHomeFlag(cmd.InOrStdin())
|
||||
kb, err := keys.NewKeyring(sdk.GetConfig().GetKeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), cmd.InOrStdin())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ func Test_runShowCmd(t *testing.T) {
|
||||
|
||||
fakeKeyName1 := "runShowCmd_Key1"
|
||||
fakeKeyName2 := "runShowCmd_Key2"
|
||||
kb, err := NewKeyringFromHomeFlag(mockIn)
|
||||
kb, err := keys.NewKeyring(sdk.GetConfig().GetKeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), mockIn)
|
||||
require.NoError(t, err)
|
||||
defer func() {
|
||||
kb.Delete("runShowCmd_Key1", "", false)
|
||||
|
||||
@@ -4,7 +4,9 @@ import (
|
||||
"bufio"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/client/input"
|
||||
)
|
||||
|
||||
@@ -30,7 +32,7 @@ func runUpdateCmd(cmd *cobra.Command, args []string) error {
|
||||
name := args[0]
|
||||
|
||||
buf := bufio.NewReader(cmd.InOrStdin())
|
||||
kb, err := NewKeyBaseFromHomeFlag()
|
||||
kb, err := NewKeyBaseFromDir(viper.GetString(flags.FlagHome))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ func Test_runUpdateCmd(t *testing.T) {
|
||||
defer cleanUp1()
|
||||
viper.Set(flags.FlagHome, kbHome)
|
||||
|
||||
kb, err := NewKeyBaseFromHomeFlag()
|
||||
kb, err := NewKeyBaseFromDir(viper.GetString(flags.FlagHome))
|
||||
assert.NoError(t, err)
|
||||
_, err = kb.CreateAccount(fakeKeyName1, tests.TestMnemonic, "", "", "0", keys.Secp256k1)
|
||||
assert.NoError(t, err)
|
||||
|
||||
@@ -2,7 +2,6 @@ package keys
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/99designs/keyring"
|
||||
@@ -12,7 +11,6 @@ import (
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
// available output formats.
|
||||
@@ -26,13 +24,6 @@ const (
|
||||
|
||||
type bechKeyOutFn func(keyInfo keys.Info) (keys.KeyOutput, error)
|
||||
|
||||
// NewKeyBaseFromHomeFlag initializes a Keybase based on the configuration. Keybase
|
||||
// options can be applied when generating this new Keybase.
|
||||
func NewKeyBaseFromHomeFlag(opts ...keys.KeybaseOption) (keys.Keybase, error) {
|
||||
rootDir := viper.GetString(flags.FlagHome)
|
||||
return NewKeyBaseFromDir(rootDir, opts...)
|
||||
}
|
||||
|
||||
// NewKeyBaseFromDir initializes a keybase at the rootDir directory. Keybase
|
||||
// options can be applied when generating this new Keybase.
|
||||
func NewKeyBaseFromDir(rootDir string, opts ...keys.KeybaseOption) (keys.Keybase, error) {
|
||||
@@ -42,29 +33,6 @@ func NewKeyBaseFromDir(rootDir string, opts ...keys.KeybaseOption) (keys.Keybase
|
||||
// NewInMemoryKeyBase returns a storage-less keybase.
|
||||
func NewInMemoryKeyBase() keys.Keybase { return keys.NewInMemory() }
|
||||
|
||||
// NewKeyBaseFromHomeFlag initializes a keyring based on configuration. Keybase
|
||||
// options can be applied when generating this new Keybase.
|
||||
func NewKeyringFromHomeFlag(input io.Reader, opts ...keys.KeybaseOption) (keys.Keybase, error) {
|
||||
return NewKeyringFromDir(viper.GetString(flags.FlagHome), input, opts...)
|
||||
}
|
||||
|
||||
// NewKeyBaseFromDir initializes a keyring at the given directory.
|
||||
// If the viper flag flags.FlagKeyringBackend is set to file, it returns an on-disk keyring with
|
||||
// CLI prompt support only. If flags.FlagKeyringBackend is set to test it will return an on-disk,
|
||||
// password-less keyring that could be used for testing purposes.
|
||||
func NewKeyringFromDir(rootDir string, input io.Reader, opts ...keys.KeybaseOption) (keys.Keybase, error) {
|
||||
keyringBackend := viper.GetString(flags.FlagKeyringBackend)
|
||||
switch keyringBackend {
|
||||
case flags.KeyringBackendTest:
|
||||
return keys.NewTestKeyring(sdk.GetConfig().GetKeyringServiceName(), rootDir, opts...)
|
||||
case flags.KeyringBackendFile:
|
||||
return keys.NewKeyringFile(sdk.GetConfig().GetKeyringServiceName(), rootDir, input, opts...)
|
||||
case flags.KeyringBackendOS:
|
||||
return keys.NewKeyring(sdk.GetConfig().GetKeyringServiceName(), rootDir, input, opts...)
|
||||
}
|
||||
return nil, fmt.Errorf("unknown keyring backend %q", keyringBackend)
|
||||
}
|
||||
|
||||
func getLazyKeyBaseFromDir(rootDir string, opts ...keys.KeybaseOption) (keys.Keybase, error) {
|
||||
return keys.New(defaultKeyDBName, filepath.Join(rootDir, "keys"), opts...), nil
|
||||
}
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
package keys
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/tests"
|
||||
)
|
||||
|
||||
func TestNewKeyringFromDir(t *testing.T) {
|
||||
dir, cleanup := tests.NewTestCaseDir(t)
|
||||
defer cleanup()
|
||||
viper.Set(flags.FlagKeyringBackend, flags.KeyringBackendTest)
|
||||
_, err := NewKeyringFromDir(filepath.Join(dir, "test"), nil)
|
||||
require.NoError(t, err)
|
||||
viper.Set(flags.FlagKeyringBackend, flags.KeyringBackendFile)
|
||||
buf := strings.NewReader("password\npassword\n")
|
||||
_, err = NewKeyringFromDir(filepath.Join(dir, "test"), buf)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
Reference in New Issue
Block a user