Merge pull request #570 from liquidata-inc/aaron/creds-import-command

go/cmd/dolt: commands/credcmds/import: Add import command for importing existing JWK credential.
This commit is contained in:
Aaron Son
2020-04-16 08:01:57 -07:00
committed by GitHub
9 changed files with 265 additions and 48 deletions

View File

@@ -87,3 +87,35 @@ teardown() {
run dolt creds use
[ "$status" -eq 1 ]
}
@test "can import cred from good jwk file" {
dolt creds import `batshelper known-good.jwk`
}
@test "can import cred from good jwk stdin" {
dolt creds import <"$BATS_TEST_DIRNAME/helper/known-good.jwk"
}
@test "import cred of corrupted jwk from file fails" {
run dolt creds import `batshelper known-truncated.jwk`
[ "$status" -eq 1 ]
run dolt creds import `batshelper known-decapitated.jwk`
[ "$status" -eq 1 ]
run dolt creds import does-not-exist
[ "$status" -eq 1 ]
}
@test "import cred of corrupted jwk from stdin fails" {
run dolt creds import <"$BATS_TEST_DIRNAME/helper/known-truncated.jwk"
[ "$status" -eq 1 ]
run dolt creds import <"$BATS_TEST_DIRNAME/helper/known-decapitated.jwk"
[ "$status" -eq 1 ]
run dolt creds import </dev/null
[ "$status" -eq 1 ]
}
@test "import cred with already used cred does not replace used cred" {
pubkey=`dolt creds new | grep 'pub key:' | awk '{print $3}'`
dolt creds import `batshelper known-good.jwk`
dolt creds ls -v | grep '*' | grep "$pubkey"
}

View File

@@ -0,0 +1 @@
O5P55nw4uSrbFKBPciCtihlIDlMPjKVqEb0HTuw8e0HcUTtolU2HZZbrlmdQjgAID9Y3_D7dCGYYw4Bw==","kty":"OKP","crv":"Ed25519"}

1
bats/helper/known-good.jwk Executable file
View File

@@ -0,0 +1 @@
{"d":"7sPHtB3FE7aJVNh2WW65ZnUI4ACA_WN_w-3QhmGMOAc=","x":"jmWVlqO5P55nw4uSrbFKBPciCtihlIDlMPjKVqEb0HTuw8e0HcUTtolU2HZZbrlmdQjgAID9Y3_D7dCGYYw4Bw==","kty":"OKP","crv":"Ed25519"}

View File

@@ -0,0 +1 @@
{"d":"7sPHtB3FE7aJVNh2WW65ZnUI4ACA_WN_w-3QhmGMOAc=","x":"jmWVlqO5P55nw4uSrbFKBPciCtihlIDlMPjKVqEb0HTuw8e0HcUTtolU2HZZbrlmdQjgAID9Y3_D7dCGYY

View File

@@ -24,4 +24,5 @@ var Commands = cli.NewSubCommandHandler("creds", "Commands for managing credenti
LsCmd{},
CheckCmd{},
UseCmd{},
ImportCmd{},
})

View File

@@ -0,0 +1,176 @@
// Copyright 2020 Liquidata, 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 credcmds
import (
"context"
"fmt"
"io"
"os"
"github.com/liquidata-inc/dolt/go/cmd/dolt/cli"
"github.com/liquidata-inc/dolt/go/cmd/dolt/commands"
"github.com/liquidata-inc/dolt/go/cmd/dolt/errhand"
eventsapi "github.com/liquidata-inc/dolt/go/gen/proto/dolt/services/eventsapi/v1alpha1"
remotesapi "github.com/liquidata-inc/dolt/go/gen/proto/dolt/services/remotesapi/v1alpha1"
"github.com/liquidata-inc/dolt/go/libraries/doltcore/creds"
"github.com/liquidata-inc/dolt/go/libraries/doltcore/env"
"github.com/liquidata-inc/dolt/go/libraries/doltcore/env/actions"
"github.com/liquidata-inc/dolt/go/libraries/utils/argparser"
"github.com/liquidata-inc/dolt/go/libraries/utils/filesys"
)
var importDocs = cli.CommandDocumentationContent{
ShortDesc: "Import a dolt credential from an existing .jwk file.",
LongDesc: `Imports a dolt credential from an existing .jwk file.
Dolt credentials are stored in the creds subdirectory of the global dolt conifg
directory as files with one key per file in JWK format. This command can import
a JWK from a file or stdin and places the imported key in the correct place for
dolt to find it as a valid credential.
This command will set the newly imported credential as the used credential if
there are currently not credentials. If this command does use the new
credential, it will call doltremoteapi to update user.name and user.email with
information from the remote user profile if those fields are not already
available in the local dolt config.`,
Synopsis: []string{"[--no-profile] [{{.LessThan}}jwk_filename{{.GreaterThan}}]"},
}
type ImportCmd struct{}
// Name is returns the name of the Dolt cli command. This is what is used on the command line to invoke the command
func (cmd ImportCmd) Name() string {
return "import"
}
// Description returns a description of the command
func (cmd ImportCmd) Description() string {
return importDocs.ShortDesc
}
// CreateMarkdown creates a markdown file containing the helptext for the command at the given path
func (cmd ImportCmd) CreateMarkdown(fs filesys.Filesys, path, commandStr string) error {
ap := cmd.createArgParser()
return commands.CreateMarkdown(fs, path, cli.GetCommandDocumentation(commandStr, importDocs, ap))
}
// RequiresRepo should return false if this interface is implemented, and the command does not have the requirement
// that it be run from within a data repository directory
func (cmd ImportCmd) RequiresRepo() bool {
return false
}
// EventType returns the type of the event to log
func (cmd ImportCmd) EventType() eventsapi.ClientEventType {
return eventsapi.ClientEventType_CREDS_IMPORT
}
const noProfileFlag = "no-profile"
func (cmd ImportCmd) createArgParser() *argparser.ArgParser {
ap := argparser.NewArgParser()
ap.ArgListHelp = append(ap.ArgListHelp, [2]string{"jwk_filename", "The JWK file. If omitted, import operates on stdin."})
ap.SupportsFlag(noProfileFlag, "", "If provided, no attempt will be made to contact doltremoteapi and update user.name and user.email.")
return ap
}
// Exec executes the command
func (cmd ImportCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv) int {
ap := cmd.createArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.GetCommandDocumentation(commandStr, importDocs, ap))
apr := cli.ParseArgs(ap, args, help)
credsDir, verr := actions.EnsureCredsDir(dEnv)
if verr != nil {
return commands.HandleVErrAndExitCode(verr, usage)
}
noprofile := apr.Contains(noProfileFlag)
var input io.ReadCloser = os.Stdin
if apr.NArg() == 1 {
var err error
input, err = dEnv.FS.OpenForRead(apr.Arg(0))
if err != nil {
verr = errhand.BuildDError("error: cannot open %s", apr.Arg(0)).AddCause(err).Build()
return commands.HandleVErrAndExitCode(verr, usage)
}
defer input.Close()
}
c, err := creds.JWKCredsRead(input)
if err != nil {
verr = errhand.BuildDError("error: could not read JWK").AddCause(err).Build()
return commands.HandleVErrAndExitCode(verr, usage)
}
if !c.IsPrivKeyValid() || !c.IsPubKeyValid() {
verr = errhand.BuildDError("error: deserialized JWK was not valid").Build()
return commands.HandleVErrAndExitCode(verr, usage)
}
_, err = creds.JWKCredsWriteToDir(dEnv.FS, credsDir, c)
if err != nil {
verr = errhand.BuildDError("error: could not write credentials to file").AddCause(err).Build()
return commands.HandleVErrAndExitCode(verr, usage)
}
cli.Println("Imported credential:", c.PubKeyBase32Str())
err = updateConfigToUseNewCredIfNoExistingCred(dEnv, c)
if err != nil {
cli.Println("Warning: could not update profile to use imported credential:", err)
}
if !noprofile {
err := updateProfileWithCredentials(ctx, dEnv, c)
if err != nil {
cli.Println("Warning: could not update profile with imported and used credentials:", err)
}
}
return 0
}
func updateProfileWithCredentials(ctx context.Context, dEnv *env.DoltEnv, c creds.DoltCreds) error {
gcfg, hasGCfg := dEnv.Config.GetConfig(env.GlobalConfig)
if !hasGCfg {
panic("Should have global config here...")
}
if _, err := gcfg.GetString(env.UserNameKey); err == nil {
// Already has a name...
return nil
}
if _, err := gcfg.GetString(env.UserEmailKey); err == nil {
// Already has an email...
return nil
}
host := dEnv.Config.GetStringOrDefault(env.RemotesApiHostKey, env.DefaultRemotesApiHost)
port := dEnv.Config.GetStringOrDefault(env.RemotesApiHostPortKey, env.DefaultRemotesApiPort)
conn, err := dEnv.GrpcConnWithCreds(fmt.Sprintf("%s:%s", *host, *port), false, c)
if err != nil {
return fmt.Errorf("error: unable to connect to server with credentials: %w", err)
}
grpcClient := remotesapi.NewCredentialsServiceClient(conn)
resp, err := grpcClient.WhoAmI(ctx, &remotesapi.WhoAmIRequest{})
if err != nil {
return fmt.Errorf("error: unable to call WhoAmI endpoint: %w", err)
}
userUpdates := map[string]string{
env.UserNameKey: resp.DisplayName,
env.UserEmailKey: resp.EmailAddress,
}
return gcfg.SetStrings(userUpdates)
}

View File

@@ -103,6 +103,7 @@ const (
ClientEventType_BLAME ClientEventType = 45
ClientEventType_CREDS_CHECK ClientEventType = 46
ClientEventType_CREDS_USE ClientEventType = 47
ClientEventType_CREDS_IMPORT ClientEventType = 48
)
var ClientEventType_name = map[int32]string{
@@ -154,6 +155,7 @@ var ClientEventType_name = map[int32]string{
45: "BLAME",
46: "CREDS_CHECK",
47: "CREDS_USE",
48: "CREDS_IMPORT",
}
var ClientEventType_value = map[string]int32{
@@ -205,6 +207,7 @@ var ClientEventType_value = map[string]int32{
"BLAME": 45,
"CREDS_CHECK": 46,
"CREDS_USE": 47,
"CREDS_IMPORT": 48,
}
func (x ClientEventType) String() string {
@@ -309,53 +312,54 @@ func init() {
}
var fileDescriptor_d970d881fa70959f = []byte{
// 764 bytes of a gzipped FileDescriptorProto
// 772 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x54, 0xcb, 0x72, 0xdb, 0x36,
0x14, 0xad, 0xfc, 0x90, 0x65, 0xf8, 0x75, 0x8d, 0xd8, 0x79, 0xb6, 0x8e, 0xeb, 0xa6, 0x2f, 0xb5,
0x16, 0x27, 0xd3, 0x99, 0x6e, 0xba, 0x82, 0xc0, 0x2b, 0x09, 0x13, 0x90, 0x60, 0x00, 0xd0, 0x4a,
0xba, 0xc1, 0xc8, 0x0a, 0xeb, 0xb0, 0xa3, 0x48, 0xaa, 0x44, 0x7b, 0xa6, 0x3f, 0xd1, 0x6f, 0xee,
0x80, 0x6c, 0x44, 0x5b, 0x9b, 0xee, 0x78, 0xcf, 0x3d, 0xe7, 0x00, 0x38, 0xbc, 0x00, 0xf9, 0xf5,
0xc3, 0x6c, 0x52, 0x04, 0xcb, 0x6c, 0x71, 0x97, 0x8f, 0xb3, 0x65, 0x90, 0xdd, 0x65, 0xd3, 0x62,
0x39, 0x9a, 0xe7, 0xc1, 0xdd, 0xeb, 0xd1, 0x64, 0xfe, 0x71, 0xf4, 0xba, 0x82, 0xdc, 0x78, 0x36,
0x5d, 0x16, 0xa3, 0x69, 0xb1, 0xec, 0xcc, 0x17, 0xb3, 0x62, 0x46, 0xcf, 0xbd, 0xae, 0xf3, 0x59,
0xd7, 0x59, 0xe9, 0x3a, 0x9f, 0x75, 0xed, 0x01, 0x69, 0x25, 0x93, 0x51, 0xf1, 0xc7, 0x6c, 0xf1,
0x89, 0x3e, 0x25, 0x27, 0x89, 0x64, 0xb6, 0xa7, 0x74, 0xe4, 0xd2, 0xd8, 0x24, 0xc8, 0x45, 0x4f,
0x60, 0x08, 0x5f, 0xd0, 0x5d, 0xb2, 0x2d, 0x45, 0x9c, 0xbe, 0x83, 0x06, 0xdd, 0x23, 0x3b, 0x43,
0x11, 0x87, 0x6a, 0x68, 0x60, 0x83, 0x12, 0xd2, 0x0c, 0x99, 0x1e, 0x8a, 0x18, 0x36, 0xdb, 0xff,
0x34, 0xc9, 0x11, 0x9f, 0xe4, 0xd9, 0xb4, 0x40, 0xbf, 0x8c, 0xfd, 0x7b, 0x9e, 0xd1, 0x13, 0x02,
0xf6, 0x7d, 0x82, 0x6b, 0x6e, 0x2d, 0xb2, 0x25, 0x62, 0x61, 0xa1, 0xe1, 0xf5, 0xc6, 0x32, 0x9b,
0x7a, 0xaf, 0x1d, 0xb2, 0xc9, 0xc2, 0x10, 0x36, 0xfd, 0x62, 0x1a, 0x0d, 0x5a, 0xd8, 0xf2, 0x7d,
0xae, 0xa2, 0x48, 0x58, 0xd8, 0xf6, 0x7d, 0xf3, 0x56, 0x42, 0x93, 0x1e, 0x12, 0x62, 0xde, 0x4a,
0x67, 0x50, 0x5f, 0xa1, 0x86, 0x1d, 0xdf, 0x90, 0xaa, 0x0f, 0x2d, 0xef, 0x1b, 0x8a, 0x5e, 0x0f,
0x76, 0xbd, 0x45, 0x84, 0xba, 0x8f, 0x40, 0xbc, 0x45, 0x57, 0xb3, 0x98, 0x0f, 0x60, 0x8f, 0xee,
0x93, 0x16, 0x1f, 0x20, 0x7f, 0xa3, 0x52, 0x0b, 0xfb, 0xbe, 0xa3, 0x31, 0x52, 0x16, 0xe1, 0xc0,
0x4b, 0x93, 0xd4, 0x0c, 0xe0, 0xb0, 0xfa, 0x92, 0x12, 0x8e, 0xbc, 0x49, 0x0f, 0x2d, 0x1f, 0x00,
0xf8, 0x4f, 0x2e, 0x55, 0x8c, 0x70, 0x5c, 0x46, 0xa1, 0xfa, 0x22, 0x06, 0xea, 0xa3, 0xb8, 0x42,
0x6d, 0x84, 0x8a, 0xe1, 0x51, 0xb5, 0xd5, 0xb8, 0x27, 0xfa, 0x70, 0x42, 0x9b, 0x64, 0x43, 0x1a,
0x38, 0x2d, 0x8f, 0xc7, 0x07, 0x18, 0x31, 0x78, 0x4c, 0x81, 0xec, 0x5b, 0xd6, 0x95, 0xe8, 0x44,
0x94, 0x28, 0x6d, 0xe1, 0x49, 0x8d, 0xe0, 0xbb, 0x12, 0x79, 0x5a, 0x23, 0x5c, 0x23, 0xb3, 0x08,
0xcf, 0xfc, 0x8e, 0x2b, 0x44, 0x47, 0xf0, 0xbc, 0xae, 0xa2, 0x2b, 0x78, 0x51, 0x57, 0x3c, 0x81,
0x2f, 0x6b, 0xad, 0x41, 0x89, 0xdc, 0xc2, 0x57, 0xf4, 0x98, 0x1c, 0x54, 0x48, 0x92, 0x5a, 0xa7,
0xd5, 0x10, 0xce, 0x6a, 0x92, 0x8e, 0x4a, 0xe4, 0x25, 0x3d, 0x20, 0xbb, 0x5c, 0x63, 0x68, 0x5c,
0x8c, 0x43, 0x38, 0x2f, 0x13, 0x2a, 0x4b, 0x1d, 0xc1, 0xd7, 0x75, 0x25, 0x0d, 0x5c, 0x94, 0x95,
0x8a, 0x7b, 0x8e, 0x33, 0x0b, 0xdf, 0x78, 0xab, 0xb2, 0xd2, 0x68, 0x94, 0xbc, 0x42, 0x78, 0x45,
0x5f, 0x92, 0x17, 0x55, 0x9e, 0x2c, 0x11, 0xae, 0x8f, 0xd6, 0x69, 0x4c, 0x94, 0x8b, 0xd0, 0xb2,
0x90, 0x59, 0x06, 0xdf, 0xfa, 0xf9, 0xaa, 0x09, 0x03, 0x66, 0x1c, 0x1f, 0xa4, 0xf1, 0x1b, 0x03,
0xdf, 0xd1, 0x57, 0xe4, 0xfc, 0xa1, 0x34, 0x54, 0xc3, 0x58, 0x2a, 0x16, 0x3a, 0xa9, 0x38, 0xb3,
0x42, 0xc5, 0x06, 0xbe, 0xa7, 0x17, 0xe4, 0xec, 0x21, 0x2b, 0x4d, 0xd6, 0x38, 0x3f, 0xf8, 0x89,
0xab, 0x39, 0x1a, 0xbb, 0xcc, 0x20, 0xfc, 0x48, 0x29, 0x39, 0xbc, 0x87, 0x2a, 0x65, 0xa1, 0xfd,
0x90, 0xf9, 0xdf, 0x94, 0xfd, 0x44, 0xcf, 0xc8, 0xf3, 0x1a, 0x95, 0xc2, 0x58, 0x57, 0x05, 0xd6,
0x13, 0x12, 0x0d, 0xfc, 0xec, 0x7f, 0x7f, 0x57, 0xb2, 0x08, 0xe1, 0x92, 0x1e, 0x91, 0xbd, 0x2a,
0x9d, 0x72, 0xa6, 0xa0, 0x53, 0x67, 0x99, 0x1a, 0x84, 0xa0, 0xfd, 0x27, 0x69, 0x45, 0x59, 0xb1,
0xc8, 0xc7, 0x22, 0xa4, 0x8f, 0x09, 0x8d, 0xd0, 0x6a, 0xc1, 0xd7, 0xae, 0xc2, 0x09, 0x81, 0xee,
0x7b, 0x8b, 0x66, 0x75, 0x60, 0x0c, 0xa1, 0x41, 0x9f, 0x90, 0x47, 0xab, 0x00, 0x22, 0xe3, 0x50,
0xb2, 0xc4, 0x60, 0x08, 0x1b, 0xbe, 0x71, 0xef, 0x1c, 0x09, 0x77, 0xa8, 0xb5, 0xd2, 0xb0, 0xd9,
0x46, 0xb2, 0xc7, 0x8a, 0x62, 0x91, 0x5f, 0xdf, 0x16, 0x99, 0x08, 0xe9, 0x33, 0x72, 0xca, 0xac,
0xd5, 0xa2, 0x9b, 0xda, 0xf5, 0xcb, 0x77, 0x4a, 0x8e, 0x2b, 0x0b, 0x97, 0x6a, 0xe9, 0xca, 0xf1,
0x44, 0xd8, 0xb8, 0xd8, 0x6a, 0x35, 0xa0, 0xd1, 0xbe, 0x24, 0xdb, 0x6c, 0x3e, 0xaf, 0xf6, 0xcb,
0x92, 0xc4, 0x89, 0x70, 0x4d, 0xbd, 0x4f, 0x5a, 0x1e, 0x0f, 0x95, 0xb4, 0xd0, 0xe8, 0x0e, 0x7f,
0x4f, 0x6f, 0xf2, 0xe2, 0xe3, 0xed, 0x75, 0x67, 0x3c, 0xfb, 0x14, 0x4c, 0xf2, 0xbf, 0x6e, 0xf3,
0x0f, 0xa3, 0x62, 0x74, 0x99, 0x4f, 0xc7, 0x41, 0xf9, 0x62, 0xdd, 0xcc, 0x82, 0x9b, 0x6c, 0x1a,
0x94, 0x8f, 0x51, 0xf0, 0x7f, 0x6f, 0xd8, 0x6f, 0x2b, 0xe8, 0xba, 0x59, 0x2a, 0x7e, 0xf9, 0x37,
0x00, 0x00, 0xff, 0xff, 0xbf, 0x8f, 0x66, 0xbe, 0xf8, 0x04, 0x00, 0x00,
0x16, 0x9b, 0xe9, 0x4c, 0x37, 0x5d, 0x41, 0xe0, 0x95, 0x84, 0x09, 0x48, 0x30, 0x00, 0x68, 0x25,
0xdd, 0x60, 0x64, 0x85, 0x75, 0xd8, 0x51, 0x24, 0x55, 0xa2, 0x3d, 0xd3, 0xbf, 0xe9, 0xa7, 0x76,
0x40, 0x26, 0x62, 0xac, 0x4d, 0x77, 0x3c, 0xe7, 0xde, 0x73, 0x08, 0x1c, 0x5c, 0x80, 0xfc, 0xf6,
0x6e, 0x36, 0x29, 0x82, 0x65, 0xb6, 0xb8, 0xcb, 0xc7, 0xd9, 0x32, 0xc8, 0xee, 0xb2, 0x69, 0xb1,
0x1c, 0xcd, 0xf3, 0xe0, 0xee, 0xe5, 0x68, 0x32, 0x7f, 0x3f, 0x7a, 0x59, 0x51, 0x6e, 0x3c, 0x9b,
0x2e, 0x8b, 0xd1, 0xb4, 0x58, 0x76, 0xe6, 0x8b, 0x59, 0x31, 0xa3, 0xe7, 0x5e, 0xd7, 0xf9, 0xa4,
0xeb, 0xac, 0x74, 0x9d, 0x4f, 0xba, 0xf6, 0x80, 0xb4, 0x92, 0xc9, 0xa8, 0xf8, 0x73, 0xb6, 0xf8,
0x40, 0x1f, 0x93, 0x93, 0x44, 0x32, 0xdb, 0x53, 0x3a, 0x72, 0x69, 0x6c, 0x12, 0xe4, 0xa2, 0x27,
0x30, 0x84, 0x2f, 0xe8, 0x2e, 0xd9, 0x96, 0x22, 0x4e, 0xdf, 0x40, 0x83, 0xee, 0x91, 0x9d, 0xa1,
0x88, 0x43, 0x35, 0x34, 0xb0, 0x41, 0x09, 0x69, 0x86, 0x4c, 0x0f, 0x45, 0x0c, 0x9b, 0xed, 0x7f,
0x9b, 0xe4, 0x88, 0x4f, 0xf2, 0x6c, 0x5a, 0xa0, 0xff, 0x8d, 0xfd, 0x67, 0x9e, 0xd1, 0x13, 0x02,
0xf6, 0x6d, 0x82, 0x6b, 0x6e, 0x2d, 0xb2, 0x25, 0x62, 0x61, 0xa1, 0xe1, 0xf5, 0xc6, 0x32, 0x9b,
0x7a, 0xaf, 0x1d, 0xb2, 0xc9, 0xc2, 0x10, 0x36, 0xfd, 0xcf, 0x34, 0x1a, 0xb4, 0xb0, 0xe5, 0xeb,
0x5c, 0x45, 0x91, 0xb0, 0xb0, 0xed, 0xeb, 0xe6, 0xb5, 0x84, 0x26, 0x3d, 0x24, 0xc4, 0xbc, 0x96,
0xce, 0xa0, 0xbe, 0x42, 0x0d, 0x3b, 0xbe, 0x20, 0x55, 0x1f, 0x5a, 0xde, 0x37, 0x14, 0xbd, 0x1e,
0xec, 0x7a, 0x8b, 0x08, 0x75, 0x1f, 0x81, 0x78, 0x8b, 0xae, 0x66, 0x31, 0x1f, 0xc0, 0x1e, 0xdd,
0x27, 0x2d, 0x3e, 0x40, 0xfe, 0x4a, 0xa5, 0x16, 0xf6, 0x7d, 0x45, 0x63, 0xa4, 0x2c, 0xc2, 0x81,
0x97, 0x26, 0xa9, 0x19, 0xc0, 0x61, 0xf5, 0x25, 0x25, 0x1c, 0x79, 0x93, 0x1e, 0x5a, 0x3e, 0x00,
0xf0, 0x9f, 0x5c, 0xaa, 0x18, 0xe1, 0xb8, 0x8c, 0x42, 0xf5, 0x45, 0x0c, 0xd4, 0x47, 0x71, 0x85,
0xda, 0x08, 0x15, 0xc3, 0x83, 0x6a, 0xa9, 0x71, 0x4f, 0xf4, 0xe1, 0x84, 0x36, 0xc9, 0x86, 0x34,
0x70, 0x5a, 0x6e, 0x8f, 0x0f, 0x30, 0x62, 0xf0, 0x90, 0x02, 0xd9, 0xb7, 0xac, 0x2b, 0xd1, 0x89,
0x28, 0x51, 0xda, 0xc2, 0xa3, 0x9a, 0xc1, 0x37, 0x25, 0xf3, 0xb8, 0x66, 0xb8, 0x46, 0x66, 0x11,
0x9e, 0xf8, 0x15, 0x57, 0x8c, 0x8e, 0xe0, 0x69, 0x8d, 0xa2, 0x2b, 0x78, 0x56, 0x23, 0x9e, 0xc0,
0x97, 0xb5, 0xd6, 0xa0, 0x44, 0x6e, 0xe1, 0x2b, 0x7a, 0x4c, 0x0e, 0x2a, 0x26, 0x49, 0xad, 0xd3,
0x6a, 0x08, 0x67, 0x75, 0x93, 0x8e, 0x4a, 0xe6, 0x39, 0x3d, 0x20, 0xbb, 0x5c, 0x63, 0x68, 0x5c,
0x8c, 0x43, 0x38, 0x2f, 0x13, 0x2a, 0xa1, 0x8e, 0xe0, 0xeb, 0x1a, 0x49, 0x03, 0x17, 0x25, 0x52,
0x71, 0xcf, 0x71, 0x66, 0xe1, 0x1b, 0x6f, 0x55, 0x22, 0x8d, 0x46, 0xc9, 0x2b, 0x84, 0x17, 0xf4,
0x39, 0x79, 0x56, 0xe5, 0xc9, 0x12, 0xe1, 0xfa, 0x68, 0x9d, 0xc6, 0x44, 0xb9, 0x08, 0x2d, 0x0b,
0x99, 0x65, 0xf0, 0xad, 0x9f, 0xaf, 0xba, 0x61, 0xc0, 0x8c, 0xe3, 0x83, 0x34, 0x7e, 0x65, 0xe0,
0x3b, 0xfa, 0x82, 0x9c, 0xdf, 0x97, 0x86, 0x6a, 0x18, 0x4b, 0xc5, 0x42, 0x27, 0x15, 0x67, 0x56,
0xa8, 0xd8, 0xc0, 0xf7, 0xf4, 0x82, 0x9c, 0xdd, 0xef, 0x4a, 0x93, 0xb5, 0x9e, 0x1f, 0xfc, 0xc4,
0xd5, 0x3d, 0x1a, 0xbb, 0xcc, 0x20, 0xfc, 0x48, 0x29, 0x39, 0xfc, 0x8c, 0x55, 0xca, 0x42, 0xfb,
0x7e, 0xe7, 0xc7, 0x29, 0xfb, 0x89, 0x9e, 0x91, 0xa7, 0x35, 0x2b, 0x85, 0xb1, 0xae, 0x0a, 0xac,
0x27, 0x24, 0x1a, 0xf8, 0xd9, 0x1f, 0x7f, 0x57, 0xb2, 0x08, 0xe1, 0x92, 0x1e, 0x91, 0xbd, 0x2a,
0x9d, 0x72, 0xa6, 0xa0, 0x53, 0x67, 0x99, 0x1a, 0x84, 0xa0, 0x4c, 0xa8, 0x84, 0x1f, 0x4f, 0xfc,
0x97, 0xf6, 0x5f, 0xa4, 0x15, 0x65, 0xc5, 0x22, 0x1f, 0x8b, 0x90, 0x3e, 0x24, 0x34, 0x42, 0xab,
0x05, 0x5f, 0xbb, 0x1c, 0x27, 0x04, 0xba, 0x6f, 0x2d, 0x9a, 0x55, 0x04, 0x18, 0x42, 0x83, 0x3e,
0x22, 0x0f, 0x56, 0x91, 0x44, 0xc6, 0xa1, 0x64, 0x89, 0xc1, 0x10, 0x36, 0x7c, 0xe1, 0xb3, 0x9d,
0x25, 0xdc, 0xa1, 0xd6, 0x4a, 0xc3, 0x66, 0x1b, 0xc9, 0x1e, 0x2b, 0x8a, 0x45, 0x7e, 0x7d, 0x5b,
0x64, 0x22, 0xa4, 0x4f, 0xc8, 0x29, 0xb3, 0x56, 0x8b, 0x6e, 0x6a, 0xd7, 0xaf, 0xe3, 0x29, 0x39,
0xae, 0x2c, 0x5c, 0xaa, 0xa5, 0x2b, 0x07, 0x16, 0x61, 0xe3, 0x62, 0xab, 0xd5, 0x80, 0x46, 0xfb,
0x92, 0x6c, 0xb3, 0xf9, 0xbc, 0x5a, 0x2f, 0x4b, 0x12, 0x27, 0xc2, 0x35, 0xf5, 0x3e, 0x69, 0x79,
0x3e, 0x54, 0xd2, 0x42, 0xa3, 0x3b, 0xfc, 0x23, 0xbd, 0xc9, 0x8b, 0xf7, 0xb7, 0xd7, 0x9d, 0xf1,
0xec, 0x43, 0x30, 0xc9, 0xff, 0xbe, 0xcd, 0xdf, 0x8d, 0x8a, 0xd1, 0x65, 0x3e, 0x1d, 0x07, 0xe5,
0x1b, 0x76, 0x33, 0x0b, 0x6e, 0xb2, 0x69, 0x50, 0x3e, 0x4f, 0xc1, 0xff, 0xbd, 0x6a, 0xbf, 0xaf,
0xa8, 0xeb, 0x66, 0xa9, 0xf8, 0xf5, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x04, 0xe0, 0xf2, 0x36,
0x0a, 0x05, 0x00, 0x00,
}

View File

@@ -76,6 +76,7 @@ enum ClientEventType {
BLAME = 45;
CREDS_CHECK = 46;
CREDS_USE = 47;
CREDS_IMPORT = 48;
}
enum MetricID {