Merge pull request #5492 from mitake/auth-v3-user-get

*: support getting user in etcdctl v3
release-3.0
Xiang Li 2016-06-01 20:27:18 -07:00
commit 140e2a18fb
10 changed files with 878 additions and 634 deletions

View File

@ -73,6 +73,9 @@ type AuthStore interface {
// UserGrant grants a role to the user // UserGrant grants a role to the user
UserGrant(r *pb.AuthUserGrantRequest) (*pb.AuthUserGrantResponse, error) UserGrant(r *pb.AuthUserGrantRequest) (*pb.AuthUserGrantResponse, error)
// UserGet gets the detailed information of a user
UserGet(r *pb.AuthUserGetRequest) (*pb.AuthUserGetResponse, error)
// RoleAdd adds a new role // RoleAdd adds a new role
RoleAdd(r *pb.AuthRoleAddRequest) (*pb.AuthRoleAddResponse, error) RoleAdd(r *pb.AuthRoleAddRequest) (*pb.AuthRoleAddResponse, error)
@ -294,6 +297,30 @@ func (as *authStore) UserGrant(r *pb.AuthUserGrantRequest) (*pb.AuthUserGrantRes
return &pb.AuthUserGrantResponse{}, nil return &pb.AuthUserGrantResponse{}, nil
} }
func (as *authStore) UserGet(r *pb.AuthUserGetRequest) (*pb.AuthUserGetResponse, error) {
tx := as.be.BatchTx()
tx.Lock()
defer tx.Unlock()
_, vs := tx.UnsafeRange(authUsersBucketName, []byte(r.Name), nil, 0)
if len(vs) != 1 {
return nil, ErrUserNotFound
}
user := &authpb.User{}
err := user.Unmarshal(vs[0])
if err != nil {
return nil, err
}
var resp pb.AuthUserGetResponse
for _, role := range user.Roles {
resp.Roles = append(resp.Roles, role)
}
return &resp, nil
}
func (as *authStore) RoleAdd(r *pb.AuthRoleAddRequest) (*pb.AuthRoleAddResponse, error) { func (as *authStore) RoleAdd(r *pb.AuthRoleAddRequest) (*pb.AuthRoleAddResponse, error) {
tx := as.be.BatchTx() tx := as.be.BatchTx()
tx.Lock() tx.Lock()

View File

@ -33,6 +33,7 @@ type (
AuthUserDeleteResponse pb.AuthUserDeleteResponse AuthUserDeleteResponse pb.AuthUserDeleteResponse
AuthUserChangePasswordResponse pb.AuthUserChangePasswordResponse AuthUserChangePasswordResponse pb.AuthUserChangePasswordResponse
AuthUserGrantResponse pb.AuthUserGrantResponse AuthUserGrantResponse pb.AuthUserGrantResponse
AuthUserGetResponse pb.AuthUserGetResponse
AuthRoleAddResponse pb.AuthRoleAddResponse AuthRoleAddResponse pb.AuthRoleAddResponse
AuthRoleGrantResponse pb.AuthRoleGrantResponse AuthRoleGrantResponse pb.AuthRoleGrantResponse
@ -64,6 +65,9 @@ type Auth interface {
// UserGrant grants a role to a user. // UserGrant grants a role to a user.
UserGrant(ctx context.Context, user string, role string) (*AuthUserGrantResponse, error) UserGrant(ctx context.Context, user string, role string) (*AuthUserGrantResponse, error)
// UserGet gets a detailed information of a user.
UserGet(ctx context.Context, name string) (*AuthUserGetResponse, error)
// RoleAdd adds a new role to an etcd cluster. // RoleAdd adds a new role to an etcd cluster.
RoleAdd(ctx context.Context, name string) (*AuthRoleAddResponse, error) RoleAdd(ctx context.Context, name string) (*AuthRoleAddResponse, error)
@ -117,6 +121,11 @@ func (auth *auth) UserGrant(ctx context.Context, user string, role string) (*Aut
return (*AuthUserGrantResponse)(resp), rpctypes.Error(err) return (*AuthUserGrantResponse)(resp), rpctypes.Error(err)
} }
func (auth *auth) UserGet(ctx context.Context, name string) (*AuthUserGetResponse, error) {
resp, err := auth.remote.UserGet(ctx, &pb.AuthUserGetRequest{Name: name})
return (*AuthUserGetResponse)(resp), rpctypes.Error(err)
}
func (auth *auth) RoleAdd(ctx context.Context, name string) (*AuthRoleAddResponse, error) { func (auth *auth) RoleAdd(ctx context.Context, name string) (*AuthRoleAddResponse, error) {
resp, err := auth.remote.RoleAdd(ctx, &pb.AuthRoleAddRequest{Name: name}) resp, err := auth.remote.RoleAdd(ctx, &pb.AuthRoleAddRequest{Name: name})
return (*AuthRoleAddResponse)(resp), rpctypes.Error(err) return (*AuthRoleAddResponse)(resp), rpctypes.Error(err)

View File

@ -34,6 +34,7 @@ func NewUserCommand() *cobra.Command {
ac.AddCommand(newUserDeleteCommand()) ac.AddCommand(newUserDeleteCommand())
ac.AddCommand(newUserChangePasswordCommand()) ac.AddCommand(newUserChangePasswordCommand())
ac.AddCommand(newUserGrantCommand()) ac.AddCommand(newUserGrantCommand())
ac.AddCommand(newUserGetCommand())
return ac return ac
} }
@ -82,6 +83,15 @@ func newUserGrantCommand() *cobra.Command {
} }
} }
func newUserGetCommand() *cobra.Command {
// TODO(mitake): this command should also get detailed information of roles of the user
return &cobra.Command{
Use: "get <user name>",
Short: "get detailed information of a user",
Run: userGetCommandFunc,
}
}
// userAddCommandFunc executes the "user add" command. // userAddCommandFunc executes the "user add" command.
func userAddCommandFunc(cmd *cobra.Command, args []string) { func userAddCommandFunc(cmd *cobra.Command, args []string) {
if len(args) != 1 { if len(args) != 1 {
@ -154,6 +164,25 @@ func userGrantCommandFunc(cmd *cobra.Command, args []string) {
fmt.Printf("Role %s is granted to user %s\n", args[1], args[0]) fmt.Printf("Role %s is granted to user %s\n", args[1], args[0])
} }
// userGetCommandFunc executes the "user get" command.
func userGetCommandFunc(cmd *cobra.Command, args []string) {
if len(args) != 1 {
ExitWithError(ExitBadArgs, fmt.Errorf("user get command requires user name as its argument."))
}
resp, err := mustClientFromCmd(cmd).Auth.UserGet(context.TODO(), args[0])
if err != nil {
ExitWithError(ExitError, err)
}
fmt.Printf("User: %s\n", args[0])
fmt.Printf("Roles:")
for _, role := range resp.Roles {
fmt.Printf(" %s", role)
}
fmt.Printf("\n")
}
func readPasswordInteractive(name string) string { func readPasswordInteractive(name string) string {
prompt1 := fmt.Sprintf("Password of %s: ", name) prompt1 := fmt.Sprintf("Password of %s: ", name)
password1, err1 := speakeasy.Ask(prompt1) password1, err1 := speakeasy.Ask(prompt1)

View File

@ -100,8 +100,11 @@ func (as *AuthServer) UserDelete(ctx context.Context, r *pb.AuthUserDeleteReques
} }
func (as *AuthServer) UserGet(ctx context.Context, r *pb.AuthUserGetRequest) (*pb.AuthUserGetResponse, error) { func (as *AuthServer) UserGet(ctx context.Context, r *pb.AuthUserGetRequest) (*pb.AuthUserGetResponse, error) {
plog.Info("not implemented yet") resp, err := as.authenticator.UserGet(ctx, r)
return nil, nil if err != nil {
return nil, togRPCError(err)
}
return resp, nil
} }
func (as *AuthServer) UserGrant(ctx context.Context, r *pb.AuthUserGrantRequest) (*pb.AuthUserGrantResponse, error) { func (as *AuthServer) UserGrant(ctx context.Context, r *pb.AuthUserGrantRequest) (*pb.AuthUserGrantResponse, error) {

View File

@ -61,6 +61,7 @@ type applierV3 interface {
UserDelete(ua *pb.AuthUserDeleteRequest) (*pb.AuthUserDeleteResponse, error) UserDelete(ua *pb.AuthUserDeleteRequest) (*pb.AuthUserDeleteResponse, error)
UserChangePassword(ua *pb.AuthUserChangePasswordRequest) (*pb.AuthUserChangePasswordResponse, error) UserChangePassword(ua *pb.AuthUserChangePasswordRequest) (*pb.AuthUserChangePasswordResponse, error)
UserGrant(ua *pb.AuthUserGrantRequest) (*pb.AuthUserGrantResponse, error) UserGrant(ua *pb.AuthUserGrantRequest) (*pb.AuthUserGrantResponse, error)
UserGet(ua *pb.AuthUserGetRequest) (*pb.AuthUserGetResponse, error)
RoleAdd(ua *pb.AuthRoleAddRequest) (*pb.AuthRoleAddResponse, error) RoleAdd(ua *pb.AuthRoleAddRequest) (*pb.AuthRoleAddResponse, error)
RoleGrant(ua *pb.AuthRoleGrantRequest) (*pb.AuthRoleGrantResponse, error) RoleGrant(ua *pb.AuthRoleGrantRequest) (*pb.AuthRoleGrantResponse, error)
} }
@ -110,6 +111,8 @@ func (s *EtcdServer) applyV3Request(r *pb.InternalRaftRequest) *applyResult {
ar.resp, ar.err = s.applyV3.UserChangePassword(r.AuthUserChangePassword) ar.resp, ar.err = s.applyV3.UserChangePassword(r.AuthUserChangePassword)
case r.AuthUserGrant != nil: case r.AuthUserGrant != nil:
ar.resp, ar.err = s.applyV3.UserGrant(r.AuthUserGrant) ar.resp, ar.err = s.applyV3.UserGrant(r.AuthUserGrant)
case r.AuthUserGet != nil:
ar.resp, ar.err = s.applyV3.UserGet(r.AuthUserGet)
case r.AuthRoleAdd != nil: case r.AuthRoleAdd != nil:
ar.resp, ar.err = s.applyV3.RoleAdd(r.AuthRoleAdd) ar.resp, ar.err = s.applyV3.RoleAdd(r.AuthRoleAdd)
case r.AuthRoleGrant != nil: case r.AuthRoleGrant != nil:
@ -532,6 +535,10 @@ func (a *applierV3backend) UserGrant(r *pb.AuthUserGrantRequest) (*pb.AuthUserGr
return a.s.AuthStore().UserGrant(r) return a.s.AuthStore().UserGrant(r)
} }
func (a *applierV3backend) UserGet(r *pb.AuthUserGetRequest) (*pb.AuthUserGetResponse, error) {
return a.s.AuthStore().UserGet(r)
}
func (a *applierV3backend) RoleAdd(r *pb.AuthRoleAddRequest) (*pb.AuthRoleAddResponse, error) { func (a *applierV3backend) RoleAdd(r *pb.AuthRoleAddRequest) (*pb.AuthRoleAddResponse, error) {
return a.s.AuthStore().RoleAdd(r) return a.s.AuthStore().RoleAdd(r)
} }

File diff suppressed because it is too large Load Diff

View File

@ -33,17 +33,18 @@ message InternalRaftRequest {
LeaseGrantRequest lease_grant = 8; LeaseGrantRequest lease_grant = 8;
LeaseRevokeRequest lease_revoke = 9; LeaseRevokeRequest lease_revoke = 9;
AuthEnableRequest auth_enable = 10; AlarmRequest alarm = 10;
AuthDisableRequest auth_disable = 11;
AuthUserAddRequest auth_user_add = 12;
AuthUserDeleteRequest auth_user_delete = 13;
AuthUserChangePasswordRequest auth_user_change_password = 14;
AuthUserGrantRequest auth_user_grant = 15;
AuthRoleAddRequest auth_role_add = 16;
AuthRoleGrantRequest auth_role_grant = 17;
AuthenticateRequest authenticate = 18;
AlarmRequest alarm = 19; AuthEnableRequest auth_enable = 1000;
AuthDisableRequest auth_disable = 1011;
AuthUserAddRequest auth_user_add = 1012;
AuthUserDeleteRequest auth_user_delete = 1013;
AuthUserChangePasswordRequest auth_user_change_password = 1014;
AuthUserGrantRequest auth_user_grant = 1015;
AuthRoleAddRequest auth_role_add = 1016;
AuthRoleGrantRequest auth_role_grant = 1017;
AuthenticateRequest authenticate = 1018;
AuthUserGetRequest auth_user_get = 1019;
} }
message EmptyResponse { message EmptyResponse {

View File

@ -1548,6 +1548,7 @@ func (*AuthUserAddRequest) ProtoMessage() {}
func (*AuthUserAddRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{47} } func (*AuthUserAddRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{47} }
type AuthUserGetRequest struct { type AuthUserGetRequest struct {
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
} }
func (m *AuthUserGetRequest) Reset() { *m = AuthUserGetRequest{} } func (m *AuthUserGetRequest) Reset() { *m = AuthUserGetRequest{} }
@ -1720,6 +1721,7 @@ func (m *AuthUserAddResponse) GetHeader() *ResponseHeader {
type AuthUserGetResponse struct { type AuthUserGetResponse struct {
Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"` Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
Roles []string `protobuf:"bytes,2,rep,name=roles" json:"roles,omitempty"`
} }
func (m *AuthUserGetResponse) Reset() { *m = AuthUserGetResponse{} } func (m *AuthUserGetResponse) Reset() { *m = AuthUserGetResponse{} }
@ -5156,6 +5158,12 @@ func (m *AuthUserGetRequest) MarshalTo(data []byte) (int, error) {
_ = i _ = i
var l int var l int
_ = l _ = l
if len(m.Name) > 0 {
data[i] = 0xa
i++
i = encodeVarintRpc(data, i, uint64(len(m.Name)))
i += copy(data[i:], m.Name)
}
return i, nil return i, nil
} }
@ -5516,6 +5524,21 @@ func (m *AuthUserGetResponse) MarshalTo(data []byte) (int, error) {
} }
i += n37 i += n37
} }
if len(m.Roles) > 0 {
for _, s := range m.Roles {
data[i] = 0x12
i++
l = len(s)
for l >= 1<<7 {
data[i] = uint8(uint64(l)&0x7f | 0x80)
l >>= 7
i++
}
data[i] = uint8(l)
i++
i += copy(data[i:], s)
}
}
return i, nil return i, nil
} }
@ -6554,6 +6577,10 @@ func (m *AuthUserAddRequest) Size() (n int) {
func (m *AuthUserGetRequest) Size() (n int) { func (m *AuthUserGetRequest) Size() (n int) {
var l int var l int
_ = l _ = l
l = len(m.Name)
if l > 0 {
n += 1 + l + sovRpc(uint64(l))
}
return n return n
} }
@ -6694,6 +6721,12 @@ func (m *AuthUserGetResponse) Size() (n int) {
l = m.Header.Size() l = m.Header.Size()
n += 1 + l + sovRpc(uint64(l)) n += 1 + l + sovRpc(uint64(l))
} }
if len(m.Roles) > 0 {
for _, s := range m.Roles {
l = len(s)
n += 1 + l + sovRpc(uint64(l))
}
}
return n return n
} }
@ -11959,6 +11992,35 @@ func (m *AuthUserGetRequest) Unmarshal(data []byte) error {
return fmt.Errorf("proto: AuthUserGetRequest: illegal tag %d (wire type %d)", fieldNum, wire) return fmt.Errorf("proto: AuthUserGetRequest: illegal tag %d (wire type %d)", fieldNum, wire)
} }
switch fieldNum { switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthRpc
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Name = string(data[iNdEx:postIndex])
iNdEx = postIndex
default: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipRpc(data[iNdEx:]) skippy, err := skipRpc(data[iNdEx:])
@ -13089,6 +13151,35 @@ func (m *AuthUserGetResponse) Unmarshal(data []byte) error {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Roles", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthRpc
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Roles = append(m.Roles, string(data[iNdEx:postIndex]))
iNdEx = postIndex
default: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipRpc(data[iNdEx:]) skippy, err := skipRpc(data[iNdEx:])
@ -13963,166 +14054,167 @@ var (
) )
var fileDescriptorRpc = []byte{ var fileDescriptorRpc = []byte{
// 2575 bytes of a gzipped FileDescriptorProto // 2584 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x5a, 0xcd, 0x72, 0x1b, 0xc7, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x1a, 0xcb, 0x72, 0x1b, 0xc7,
0x11, 0x26, 0x7e, 0x08, 0x10, 0x0d, 0x10, 0xa2, 0x86, 0x94, 0x4c, 0x41, 0xb6, 0x2c, 0xaf, 0x24, 0x91, 0x78, 0x10, 0x20, 0x1a, 0x20, 0x44, 0x0d, 0x29, 0x99, 0x82, 0x1e, 0x96, 0x57, 0x92, 0xad,
0x5b, 0x89, 0x1d, 0x2a, 0x66, 0x9c, 0x43, 0x2a, 0x2e, 0xa5, 0x40, 0x02, 0x96, 0x68, 0x52, 0xa4, 0xc4, 0x0e, 0x15, 0x33, 0xce, 0x21, 0x15, 0x97, 0x52, 0x20, 0x01, 0x4b, 0x34, 0x29, 0x92, 0x5e,
0xbc, 0x04, 0xa9, 0xf8, 0xc4, 0x5a, 0x02, 0x23, 0x12, 0x25, 0xfc, 0x79, 0x77, 0x41, 0x89, 0xaa, 0x82, 0x54, 0x7c, 0x62, 0x2d, 0x81, 0x11, 0xb9, 0x25, 0xbc, 0xbc, 0xbb, 0xa0, 0x44, 0x55, 0xe5,
0xca, 0x25, 0x55, 0x79, 0x02, 0xe7, 0x94, 0xca, 0x0b, 0xe4, 0x01, 0xf2, 0x0e, 0xa9, 0x5c, 0x92, 0x92, 0xaa, 0x7c, 0x81, 0x73, 0x4a, 0xe5, 0x07, 0xf2, 0x01, 0xf9, 0x87, 0x54, 0x2e, 0xc9, 0x17,
0x27, 0x48, 0x52, 0x39, 0xa5, 0x72, 0xc9, 0x3d, 0xb9, 0xa4, 0xe7, 0x77, 0x67, 0x07, 0xbb, 0x94, 0x24, 0xa9, 0x9c, 0x52, 0xb9, 0xe4, 0x9e, 0x5c, 0xd2, 0xf3, 0xda, 0x9d, 0x1d, 0xec, 0x42, 0x72,
0x9c, 0x65, 0x0e, 0x22, 0x77, 0x7a, 0xba, 0xbf, 0xe9, 0xee, 0xe9, 0xe9, 0xe9, 0x1e, 0x0a, 0x2a, 0x96, 0x39, 0x88, 0xdc, 0xe9, 0xe9, 0xee, 0xe9, 0xd7, 0xf4, 0x74, 0x37, 0x05, 0x15, 0x6f, 0xdc,
0xfe, 0xa4, 0xbb, 0x36, 0xf1, 0xc7, 0xe1, 0x98, 0xd4, 0x68, 0xd8, 0xed, 0x05, 0xd4, 0x3f, 0xa3, 0x5d, 0x1b, 0x7b, 0xa3, 0x60, 0x44, 0x6a, 0x34, 0xe8, 0xf6, 0x7c, 0xea, 0x9d, 0x53, 0x6f, 0x7c,
0xfe, 0xe4, 0xb8, 0xb1, 0x72, 0x32, 0x3e, 0x19, 0xf3, 0x89, 0x07, 0xec, 0x4b, 0xf0, 0x34, 0x6e, 0xd2, 0x58, 0x39, 0x1d, 0x9d, 0x8e, 0xf8, 0xc6, 0x23, 0xf6, 0x25, 0x70, 0x1a, 0x37, 0x18, 0xce,
0x30, 0x9e, 0x07, 0xc3, 0xb3, 0x6e, 0x97, 0xff, 0x98, 0x1c, 0x3f, 0x78, 0x71, 0x26, 0xa7, 0x6e, 0xa3, 0xc1, 0x79, 0xb7, 0xcb, 0x7f, 0x8c, 0x4f, 0x1e, 0xbd, 0x3c, 0x97, 0x5b, 0x37, 0xf9, 0x96,
0xf2, 0x29, 0x6f, 0x1a, 0x9e, 0xf2, 0x1f, 0x38, 0xc5, 0x7e, 0x89, 0x49, 0xe7, 0x57, 0x39, 0xa8, 0x33, 0x09, 0xce, 0xf8, 0x0f, 0xdc, 0x62, 0xbf, 0xc4, 0xa6, 0xf5, 0xab, 0x1c, 0xd4, 0x6d, 0xea,
0xbb, 0x34, 0x98, 0x8c, 0x47, 0x01, 0x7d, 0x4c, 0xbd, 0x1e, 0xf5, 0xc9, 0x7b, 0x00, 0xdd, 0xc1, 0x8f, 0x47, 0x43, 0x9f, 0x3e, 0xa5, 0x4e, 0x8f, 0x7a, 0xe4, 0x36, 0x40, 0xb7, 0x3f, 0xf1, 0x03,
0x34, 0x08, 0xa9, 0x7f, 0xd4, 0xef, 0xad, 0xe6, 0x6e, 0xe7, 0xee, 0x17, 0xdd, 0x8a, 0xa4, 0x6c, 0xea, 0x1d, 0xbb, 0xbd, 0xd5, 0xdc, 0xdd, 0xdc, 0xc3, 0xa2, 0x5d, 0x91, 0x90, 0xad, 0x1e, 0xb9,
0xf5, 0xc8, 0x4d, 0xa8, 0x0c, 0xe9, 0xf0, 0x58, 0xcc, 0xe6, 0xf9, 0xec, 0x82, 0x20, 0xe0, 0x64, 0x09, 0x95, 0x01, 0x1d, 0x9c, 0x88, 0xdd, 0x3c, 0xdf, 0x5d, 0x10, 0x00, 0xdc, 0x6c, 0xc0, 0x82,
0x03, 0x16, 0x7c, 0x7a, 0xd6, 0x0f, 0xfa, 0xe3, 0xd1, 0x6a, 0x01, 0xe7, 0x0a, 0xae, 0x1e, 0x33, 0x47, 0xcf, 0x5d, 0xdf, 0x1d, 0x0d, 0x57, 0x0b, 0xb8, 0x57, 0xb0, 0xc3, 0x35, 0x23, 0xf4, 0x9c,
0x41, 0xdf, 0x7b, 0x1e, 0x1e, 0x21, 0xcc, 0x70, 0xb5, 0x28, 0x04, 0x19, 0xa1, 0x83, 0x63, 0xe7, 0x17, 0xc1, 0x31, 0xb2, 0x19, 0xac, 0x16, 0x05, 0x21, 0x03, 0x74, 0x70, 0x6d, 0xfd, 0xba, 0x00,
0xd7, 0x05, 0xa8, 0xb9, 0xde, 0xe8, 0x84, 0xba, 0xf4, 0x9b, 0x29, 0x0d, 0x42, 0xb2, 0x04, 0x85, 0x35, 0xdb, 0x19, 0x9e, 0x52, 0x9b, 0x7e, 0x33, 0xa1, 0x7e, 0x40, 0x96, 0xa0, 0xf0, 0x92, 0x5e,
0x17, 0xf4, 0x9c, 0x2f, 0x5f, 0x73, 0xd9, 0xa7, 0x90, 0x47, 0x8e, 0x23, 0x3a, 0x12, 0x0b, 0xd7, 0xf0, 0xe3, 0x6b, 0x36, 0xfb, 0x14, 0xf4, 0x88, 0x71, 0x4c, 0x87, 0xe2, 0xe0, 0x1a, 0xa3, 0x47,
0x98, 0x3c, 0x12, 0xda, 0xa3, 0x1e, 0x59, 0x81, 0xf9, 0x41, 0x7f, 0xd8, 0x0f, 0xe5, 0xaa, 0x62, 0x40, 0x7b, 0xd8, 0x23, 0x2b, 0x30, 0xdf, 0x77, 0x07, 0x6e, 0x20, 0x4f, 0x15, 0x8b, 0x98, 0x38,
0x10, 0x53, 0xa7, 0x68, 0xa9, 0xb3, 0x09, 0x10, 0x8c, 0xfd, 0xf0, 0x68, 0xec, 0xa3, 0xd1, 0xab, 0x45, 0x43, 0x9c, 0x4d, 0x00, 0x7f, 0xe4, 0x05, 0xc7, 0x23, 0x0f, 0x95, 0x5e, 0x9d, 0xc7, 0xdd,
0xf3, 0x38, 0x5b, 0x5f, 0xbf, 0xbb, 0x66, 0xba, 0x7a, 0xcd, 0x54, 0x68, 0x6d, 0x1f, 0x99, 0xf7, 0xfa, 0xfa, 0xfd, 0x35, 0xdd, 0xd4, 0x6b, 0xba, 0x40, 0x6b, 0x07, 0x88, 0xbc, 0xc7, 0x70, 0xed,
0x18, 0xaf, 0x5b, 0x09, 0xd4, 0x27, 0xf9, 0x02, 0xaa, 0x1c, 0x24, 0xf4, 0xfc, 0x13, 0x1a, 0xae, 0x8a, 0xaf, 0x3e, 0xc9, 0x17, 0x50, 0xe5, 0x4c, 0x02, 0xc7, 0x3b, 0xa5, 0xc1, 0x6a, 0x89, 0x73,
0x96, 0x38, 0xca, 0xbd, 0x37, 0xa0, 0x74, 0x38, 0xb3, 0xcb, 0x97, 0x17, 0xdf, 0xc4, 0x81, 0x1a, 0x79, 0xf0, 0x16, 0x2e, 0x1d, 0x8e, 0x6c, 0xf3, 0xe3, 0xc5, 0x37, 0xb1, 0xa0, 0x86, 0xf8, 0xae,
0xf2, 0xf7, 0xbd, 0x41, 0xff, 0xb5, 0x77, 0x3c, 0xa0, 0xab, 0x65, 0x04, 0x5a, 0x70, 0x63, 0x34, 0xd3, 0x77, 0xdf, 0x38, 0x27, 0x7d, 0xba, 0x5a, 0x46, 0x46, 0x0b, 0x76, 0x0c, 0x66, 0xad, 0x41,
0x67, 0x0d, 0x2a, 0x5a, 0x07, 0xb2, 0x00, 0xc5, 0xdd, 0xbd, 0xdd, 0xf6, 0xd2, 0x1c, 0x01, 0x28, 0x25, 0x94, 0x81, 0x2c, 0x40, 0x71, 0x77, 0x6f, 0xb7, 0xbd, 0x34, 0x47, 0x00, 0x4a, 0xcd, 0x83,
0x35, 0xf7, 0x37, 0xdb, 0xbb, 0xad, 0xa5, 0x1c, 0xa9, 0x42, 0xb9, 0xd5, 0x16, 0x83, 0xbc, 0xb3, 0xcd, 0xf6, 0x6e, 0x6b, 0x29, 0x47, 0xaa, 0x50, 0x6e, 0xb5, 0xc5, 0x22, 0x6f, 0x6d, 0x00, 0x44,
0x01, 0x10, 0xad, 0x46, 0xca, 0x50, 0xd8, 0x6e, 0x7f, 0x8d, 0xfc, 0xc8, 0x73, 0xd8, 0x76, 0xf7, 0xa7, 0x91, 0x32, 0x14, 0xb6, 0xdb, 0x5f, 0x23, 0x3e, 0xe2, 0x1c, 0xb5, 0xed, 0x83, 0xad, 0xbd,
0xb7, 0xf6, 0x76, 0x51, 0x00, 0x85, 0x37, 0xdd, 0x76, 0xb3, 0xd3, 0x5e, 0xca, 0x33, 0x8e, 0x27, 0x5d, 0x24, 0x40, 0xe2, 0x4d, 0xbb, 0xdd, 0xec, 0xb4, 0x97, 0xf2, 0x0c, 0xe3, 0xd9, 0x5e, 0x6b,
0x7b, 0xad, 0xa5, 0x02, 0xa9, 0xc0, 0xfc, 0x61, 0x73, 0xe7, 0xa0, 0xbd, 0x54, 0x74, 0x7e, 0x01, 0xa9, 0x40, 0x2a, 0x30, 0x7f, 0xd4, 0xdc, 0x39, 0x6c, 0x2f, 0x15, 0xad, 0x5f, 0xc0, 0xa2, 0x14,
0x8b, 0x52, 0x7d, 0x11, 0x22, 0xe4, 0x33, 0x28, 0x9d, 0xf2, 0x30, 0xe1, 0x3b, 0x53, 0x5d, 0x7f, 0x5f, 0x84, 0x08, 0xf9, 0x0c, 0x4a, 0x67, 0x3c, 0x4c, 0xb8, 0x67, 0xaa, 0xeb, 0xb7, 0x0c, 0x5d,
0xd7, 0xb2, 0x35, 0x16, 0x4a, 0xae, 0xe4, 0x45, 0xf3, 0x0a, 0x2f, 0xce, 0x02, 0xdc, 0xb4, 0x02, 0x63, 0xa1, 0x64, 0x4b, 0x5c, 0x54, 0xaf, 0xf0, 0xf2, 0xdc, 0x47, 0xa7, 0x15, 0x90, 0x64, 0x69,
0x8a, 0x2c, 0xad, 0x89, 0x08, 0x5d, 0xdb, 0xa6, 0xe7, 0x87, 0xde, 0x60, 0x4a, 0x5d, 0x36, 0x49, 0x4d, 0x44, 0xe8, 0xda, 0x36, 0xbd, 0x38, 0x72, 0xfa, 0x13, 0x6a, 0xb3, 0x4d, 0x42, 0xa0, 0x38,
0x08, 0x14, 0x87, 0x63, 0x9f, 0xca, 0x0d, 0xe4, 0xdf, 0xce, 0x97, 0x00, 0x4f, 0xa7, 0x61, 0x7a, 0x18, 0x79, 0x54, 0x3a, 0x90, 0x7f, 0x5b, 0x5f, 0x02, 0xec, 0x4f, 0x82, 0xf4, 0x90, 0x40, 0xaf,
0x48, 0xe0, 0xae, 0x9f, 0x31, 0x04, 0x19, 0x0e, 0x62, 0xc0, 0x63, 0x81, 0x7a, 0x01, 0xd5, 0xb1, 0x9f, 0x33, 0x0e, 0x32, 0x1c, 0xc4, 0x82, 0xc7, 0x02, 0x75, 0x7c, 0x1a, 0xc6, 0x02, 0x5b, 0x58,
0xc0, 0x06, 0xce, 0x26, 0x54, 0x39, 0x56, 0x16, 0x43, 0x10, 0x84, 0xb4, 0xe8, 0x80, 0x86, 0x34, 0x9b, 0x50, 0xe5, 0xbc, 0xb2, 0x28, 0x82, 0x4c, 0x48, 0x8b, 0xf6, 0x69, 0x40, 0x33, 0xc4, 0xaa,
0x43, 0xac, 0x3a, 0x14, 0x96, 0x63, 0x20, 0x99, 0x5c, 0xbb, 0x0a, 0xe5, 0x1e, 0x07, 0x13, 0xeb, 0x45, 0x61, 0x39, 0xc6, 0x24, 0x93, 0x69, 0x57, 0xa1, 0xdc, 0xe3, 0xcc, 0xc4, 0x39, 0x05, 0x5b,
0x14, 0x5c, 0x35, 0x74, 0xfe, 0x95, 0xc3, 0x23, 0x25, 0x34, 0x3c, 0x18, 0xb1, 0x88, 0x6f, 0xc2, 0x2d, 0xad, 0x7f, 0xe5, 0xf0, 0x4a, 0x09, 0x09, 0x0f, 0x87, 0x2c, 0xe2, 0x9b, 0xb0, 0xe8, 0x89,
0xa2, 0x2f, 0xc6, 0x47, 0x5c, 0x17, 0xb9, 0x4e, 0x23, 0x3d, 0x5c, 0x1f, 0xcf, 0xb9, 0x35, 0x29, 0xf5, 0x31, 0x97, 0x45, 0x9e, 0xd3, 0x48, 0x0f, 0xd7, 0xa7, 0x73, 0x76, 0x4d, 0x92, 0x70, 0x30,
0xc2, 0xc9, 0xe4, 0xa7, 0x50, 0x55, 0x10, 0x93, 0x69, 0xc8, 0x57, 0xac, 0xae, 0xaf, 0xc6, 0x01, 0xf9, 0x29, 0x54, 0x15, 0x8b, 0xf1, 0x24, 0xe0, 0x27, 0x56, 0xd7, 0x57, 0xe3, 0x0c, 0x22, 0x8f,
0xa2, 0x1d, 0x43, 0x71, 0x90, 0xec, 0x48, 0x24, 0x1d, 0x58, 0x51, 0xc2, 0x42, 0x47, 0xa9, 0x46, 0x21, 0x39, 0x48, 0x74, 0x04, 0x92, 0x0e, 0xac, 0x28, 0x62, 0x21, 0xa3, 0x14, 0xa3, 0xc0, 0xb9,
0x81, 0xa3, 0xdc, 0x8e, 0xa3, 0xcc, 0xba, 0x19, 0xd1, 0x88, 0x94, 0x37, 0x26, 0x37, 0x2a, 0x50, 0xdc, 0x8d, 0x73, 0x99, 0x36, 0x33, 0x72, 0x23, 0x92, 0x5e, 0xdb, 0xdc, 0xa8, 0x40, 0x59, 0x42,
0x96, 0x54, 0xe7, 0xdf, 0x39, 0x0c, 0x57, 0xe9, 0x26, 0x61, 0x72, 0x0b, 0xea, 0xbe, 0x24, 0xc4, 0xad, 0x7f, 0xe7, 0x30, 0x5c, 0xa5, 0x99, 0x84, 0xca, 0x2d, 0xa8, 0x7b, 0x12, 0x10, 0xd3, 0xf9,
0x6c, 0xbe, 0x99, 0x68, 0xb3, 0x74, 0xf0, 0x9c, 0xbb, 0xa8, 0x84, 0x84, 0xd5, 0x0f, 0xa1, 0xa6, 0x66, 0xa2, 0xce, 0xd2, 0xc0, 0x73, 0xf6, 0xa2, 0x22, 0x12, 0x5a, 0x3f, 0x86, 0x5a, 0xc8, 0x25,
0x51, 0x22, 0xb3, 0x6f, 0x24, 0x98, 0xad, 0x11, 0xaa, 0x4a, 0x80, 0x19, 0xfe, 0x0c, 0xae, 0x69, 0x52, 0xfb, 0x46, 0x82, 0xda, 0x21, 0x87, 0xaa, 0x22, 0x60, 0x8a, 0x3f, 0x87, 0x6b, 0x21, 0x7d,
0xf9, 0x04, 0xcb, 0x3f, 0xb8, 0xc0, 0x72, 0x0d, 0xb8, 0xac, 0x10, 0x4c, 0xdb, 0x81, 0xe5, 0x37, 0x82, 0xe6, 0x1f, 0xcc, 0xd0, 0x3c, 0x64, 0xb8, 0xac, 0x38, 0xe8, 0xba, 0x03, 0xcb, 0x6f, 0x02,
0x41, 0x76, 0x7e, 0x53, 0x80, 0xf2, 0xe6, 0x78, 0x38, 0xf1, 0x7c, 0xb6, 0x4d, 0x25, 0xa4, 0x4f, 0x6c, 0xfd, 0xa6, 0x00, 0xe5, 0xcd, 0xd1, 0x60, 0xec, 0x78, 0xcc, 0x4d, 0x25, 0x84, 0x4f, 0xfa,
0x07, 0x21, 0x37, 0xb7, 0xbe, 0x7e, 0x27, 0xbe, 0x82, 0x64, 0x53, 0xbf, 0x5d, 0xce, 0xea, 0x4a, 0x01, 0x57, 0xb7, 0xbe, 0x7e, 0x2f, 0x7e, 0x82, 0x44, 0x53, 0xbf, 0x6d, 0x8e, 0x6a, 0x4b, 0x12,
0x11, 0x26, 0x2c, 0xd3, 0x59, 0xfe, 0x2d, 0x84, 0x65, 0x32, 0x93, 0x22, 0xea, 0x28, 0x14, 0xa2, 0x46, 0x2c, 0xd3, 0x59, 0xfe, 0x1d, 0x88, 0x65, 0x32, 0x93, 0x24, 0xea, 0x2a, 0x14, 0xa2, 0xab,
0xa3, 0xd0, 0x80, 0x32, 0x0a, 0x46, 0x29, 0x18, 0x6d, 0x51, 0x04, 0xf2, 0x3d, 0xb8, 0xd2, 0xf5, 0xd0, 0x80, 0x32, 0x12, 0x46, 0x29, 0x18, 0x75, 0x51, 0x00, 0xf2, 0x3d, 0xb8, 0xd2, 0xf5, 0xa8,
0xa9, 0xc7, 0xfc, 0xa1, 0xd2, 0xf4, 0xbc, 0xe4, 0xa9, 0x8b, 0x09, 0x57, 0xa5, 0xeb, 0x3b, 0x50, 0xc3, 0xec, 0xa1, 0xd2, 0xf4, 0xbc, 0xc4, 0xa9, 0x8b, 0x0d, 0x5b, 0xa5, 0xeb, 0x7b, 0x50, 0x1b,
0x1b, 0x8e, 0x7b, 0x11, 0x5f, 0x49, 0xf2, 0x55, 0x91, 0xaa, 0x99, 0xae, 0xab, 0x7c, 0xc0, 0xf2, 0x8c, 0x7a, 0x11, 0x5e, 0x49, 0xe2, 0x55, 0x11, 0x1a, 0x22, 0x5d, 0x57, 0xf9, 0x80, 0xe5, 0xcf,
0x67, 0x0d, 0x67, 0xc5, 0xd0, 0xf9, 0x14, 0x16, 0x63, 0xb6, 0xb2, 0x14, 0xd7, 0xfe, 0xea, 0xa0, 0x1a, 0xee, 0x8a, 0xa5, 0xf5, 0x29, 0x2c, 0xc6, 0x74, 0x65, 0x29, 0xae, 0xfd, 0xd5, 0x61, 0x73,
0xb9, 0x23, 0xf2, 0xe1, 0x23, 0x9e, 0x02, 0x5d, 0xcc, 0x87, 0x98, 0x56, 0x77, 0xda, 0xfb, 0xfb, 0x47, 0xe4, 0xc3, 0x27, 0x3c, 0x05, 0xda, 0x98, 0x0f, 0x31, 0xad, 0xee, 0xb4, 0x0f, 0x0e, 0x30,
0x98, 0x3d, 0x3f, 0xd7, 0x22, 0x32, 0x81, 0x1a, 0x79, 0x73, 0xce, 0xc8, 0x9b, 0x39, 0x95, 0x37, 0x7b, 0x7e, 0x1e, 0x92, 0xc8, 0x04, 0xaa, 0xe5, 0xcd, 0x39, 0x2d, 0x6f, 0xe6, 0x54, 0xde, 0xcc,
0xf3, 0x51, 0xde, 0x2c, 0x6c, 0xd4, 0xa1, 0x26, 0x1c, 0x72, 0x34, 0x65, 0x71, 0xe8, 0xfc, 0x2e, 0x47, 0x79, 0xb3, 0xb0, 0x51, 0x87, 0x9a, 0x30, 0xc8, 0xf1, 0x84, 0xc5, 0xa1, 0xf5, 0xbb, 0x1c,
0x07, 0xd0, 0x79, 0x35, 0x52, 0x09, 0xe3, 0x01, 0x94, 0xbb, 0x02, 0x1c, 0x37, 0x88, 0xe5, 0xc4, 0x40, 0xe7, 0xf5, 0x50, 0x25, 0x8c, 0x47, 0x50, 0xee, 0x0a, 0xe6, 0xe8, 0x20, 0x96, 0x13, 0xaf,
0x6b, 0x89, 0x3e, 0x76, 0x15, 0x17, 0xe6, 0x86, 0x72, 0x30, 0xed, 0x76, 0x69, 0xa0, 0x92, 0xa8, 0x25, 0xda, 0xd8, 0x56, 0x58, 0x98, 0x1b, 0xca, 0xfe, 0xa4, 0xdb, 0xa5, 0xbe, 0x4a, 0xa2, 0xe6,
0x7d, 0x68, 0x8d, 0x73, 0xee, 0x2a, 0x56, 0x26, 0xf5, 0xdc, 0xeb, 0x0f, 0xa6, 0x3c, 0xab, 0xbe, 0xa5, 0xd5, 0xee, 0xb9, 0xad, 0x50, 0x19, 0xd5, 0x0b, 0xc7, 0xed, 0x4f, 0x78, 0x56, 0x7d, 0x2b,
0x51, 0x4a, 0xb2, 0x3a, 0xbf, 0xcd, 0x41, 0x95, 0xeb, 0x9a, 0x29, 0x2f, 0xbd, 0x0b, 0x15, 0xae, 0x95, 0x44, 0xb5, 0x7e, 0x9b, 0x83, 0x2a, 0x97, 0x35, 0x53, 0x5e, 0xba, 0x05, 0x15, 0x2e, 0x06,
0x06, 0xed, 0xc9, 0xcc, 0xb4, 0xe0, 0x46, 0x04, 0xf2, 0x13, 0xcc, 0x8f, 0x52, 0x2e, 0x90, 0xba, 0xed, 0xc9, 0xcc, 0xb4, 0x60, 0x47, 0x00, 0xf2, 0x13, 0xcc, 0x8f, 0x92, 0xce, 0x97, 0xb2, 0xdd,
0xdd, 0x4c, 0x86, 0x15, 0xca, 0x45, 0xdc, 0xce, 0x36, 0x5c, 0xe5, 0xee, 0xe9, 0x86, 0x6c, 0x42, 0x4c, 0x66, 0x2b, 0x84, 0x8b, 0xb0, 0xad, 0x6d, 0xb8, 0xca, 0xcd, 0xd3, 0x0d, 0xd8, 0x86, 0x34,
0x3a, 0xd4, 0xbc, 0xe8, 0x73, 0xd6, 0x45, 0x8f, 0x73, 0x93, 0xd3, 0xf3, 0xa0, 0xdf, 0xf5, 0x06, 0xa8, 0xfe, 0xd0, 0xe7, 0x8c, 0x87, 0x1e, 0xf7, 0xc6, 0x67, 0x17, 0xbe, 0xdb, 0x75, 0xfa, 0x52,
0x52, 0x11, 0x3d, 0xc6, 0x0b, 0x86, 0x98, 0x60, 0x99, 0xee, 0x86, 0x45, 0xa8, 0x3e, 0xf6, 0x82, 0x90, 0x70, 0x8d, 0x0f, 0x0c, 0xd1, 0x99, 0x65, 0x7a, 0x1b, 0x16, 0xa1, 0xfa, 0xd4, 0xf1, 0xcf,
0x53, 0xa9, 0x92, 0xf3, 0x73, 0xa8, 0x89, 0x61, 0x26, 0x37, 0xe2, 0xad, 0x78, 0x8a, 0x28, 0x5c, 0xa4, 0x48, 0xd6, 0xcf, 0xa1, 0x26, 0x96, 0x99, 0xcc, 0x88, 0xaf, 0xe2, 0x19, 0x72, 0xe1, 0x82,
0xf1, 0x45, 0x97, 0x7f, 0x3b, 0x57, 0xe1, 0xca, 0xfe, 0xc8, 0x9b, 0x04, 0xa7, 0x63, 0x95, 0x68, 0x2f, 0xda, 0xfc, 0xdb, 0xba, 0x0a, 0x57, 0x0e, 0x86, 0xce, 0xd8, 0x3f, 0x1b, 0xa9, 0x44, 0xcb,
0x59, 0x19, 0xb7, 0x14, 0xd1, 0x32, 0xad, 0xf8, 0x11, 0x5c, 0xf1, 0xe9, 0xd0, 0xeb, 0x8f, 0xfa, 0xca, 0xb8, 0xa5, 0x08, 0x96, 0xe9, 0xc4, 0x8f, 0xe0, 0x8a, 0x47, 0x07, 0x8e, 0x3b, 0x74, 0x87,
0xa3, 0x93, 0xa3, 0xe3, 0xf3, 0x90, 0x06, 0xb2, 0xca, 0xab, 0x6b, 0xf2, 0x06, 0xa3, 0x32, 0xd5, 0xa7, 0xc7, 0x27, 0x17, 0x01, 0xf5, 0x65, 0x95, 0x57, 0x0f, 0xc1, 0x1b, 0x0c, 0xca, 0x44, 0x3b,
0x8e, 0x07, 0xe3, 0x63, 0x79, 0xd6, 0xf9, 0xb7, 0xf3, 0x7b, 0xbc, 0x73, 0x9e, 0x79, 0x61, 0x57, 0xe9, 0x8f, 0x4e, 0xe4, 0x5d, 0xe7, 0xdf, 0xd6, 0xef, 0xf1, 0xcd, 0x79, 0xee, 0x04, 0x5d, 0x65,
0x79, 0x81, 0x6c, 0x41, 0x5d, 0x9f, 0x70, 0x4e, 0x91, 0xba, 0x58, 0xd9, 0x9e, 0xcb, 0x6c, 0xca, 0x05, 0xb2, 0x05, 0xf5, 0xf0, 0x86, 0x73, 0x88, 0x94, 0xc5, 0xc8, 0xf6, 0x9c, 0x66, 0x53, 0xde,
0x13, 0xaf, 0xb2, 0xfd, 0x62, 0xd7, 0x24, 0x70, 0x28, 0x6f, 0xd4, 0xa5, 0x03, 0x0d, 0x95, 0x4f, 0x78, 0x95, 0xed, 0x17, 0xbb, 0x3a, 0x80, 0xb3, 0x72, 0x86, 0x5d, 0xda, 0x0f, 0x59, 0xe5, 0xd3,
0x87, 0xe2, 0x8c, 0x26, 0x94, 0x49, 0xd8, 0xb8, 0x12, 0xdd, 0x84, 0xe2, 0x7c, 0x7e, 0x9b, 0x03, 0x59, 0x71, 0x44, 0x9d, 0x95, 0x0e, 0xd8, 0xb8, 0x12, 0xbd, 0x84, 0xe2, 0x7e, 0x7e, 0x9b, 0x03,
0x32, 0xab, 0xc3, 0x77, 0x2d, 0x42, 0xef, 0x41, 0x3d, 0xc0, 0x63, 0x1f, 0x1e, 0x59, 0x35, 0xf0, 0x32, 0x2d, 0xc3, 0x77, 0x2d, 0x42, 0x1f, 0x40, 0xdd, 0xc7, 0x6b, 0x1f, 0x1c, 0x1b, 0x35, 0xf0,
0x22, 0xa7, 0xea, 0x2c, 0x85, 0x1e, 0xc6, 0xe2, 0xfb, 0x04, 0x43, 0x3a, 0x38, 0x1a, 0x8d, 0xc3, 0x22, 0x87, 0x86, 0x59, 0x0a, 0x2d, 0x8c, 0xc5, 0xf7, 0x29, 0x86, 0xb4, 0x7f, 0x3c, 0x1c, 0x05,
0xfe, 0xf3, 0x73, 0x9e, 0x19, 0x17, 0xdc, 0xba, 0x22, 0xef, 0x72, 0xaa, 0xf3, 0x40, 0x29, 0x65, 0xee, 0x8b, 0x0b, 0x9e, 0x19, 0x17, 0xec, 0xba, 0x02, 0xef, 0x72, 0xa8, 0xf5, 0x48, 0x09, 0xa5,
0x2a, 0x4f, 0x6e, 0xc0, 0xc2, 0x4b, 0x46, 0x55, 0xd5, 0x39, 0x5e, 0xf9, 0x7c, 0xbc, 0xd5, 0x73, 0x0b, 0x4f, 0x6e, 0xc0, 0xc2, 0x2b, 0x06, 0x55, 0xd5, 0x39, 0x3e, 0xf9, 0x7c, 0xbd, 0xd5, 0xb3,
0xfe, 0x81, 0x17, 0xa0, 0x74, 0x7f, 0xa6, 0x18, 0x30, 0x97, 0xc8, 0xc7, 0x96, 0x60, 0xf5, 0x86, 0xfe, 0x81, 0x0f, 0xa0, 0x34, 0x7f, 0xa6, 0x18, 0xd0, 0x8f, 0xc8, 0xc7, 0x8e, 0x60, 0xf5, 0x86,
0xd8, 0x96, 0x1e, 0x37, 0x6e, 0xc1, 0x55, 0x43, 0x76, 0xce, 0x84, 0x97, 0x71, 0x4a, 0xd8, 0xa3, 0x70, 0x4b, 0x8f, 0x2b, 0xb7, 0x60, 0xab, 0x25, 0xbb, 0x67, 0xc2, 0xca, 0xb8, 0x25, 0xf4, 0x09,
0xc7, 0x98, 0xe8, 0x97, 0xba, 0xe2, 0x9c, 0x59, 0x99, 0xde, 0xbd, 0x22, 0xe9, 0xda, 0x3b, 0xf7, 0xd7, 0x98, 0xe8, 0x97, 0xba, 0xe2, 0x9e, 0x19, 0x99, 0xde, 0xbe, 0x22, 0xe1, 0xa1, 0x75, 0x1e,
0xa0, 0x44, 0xcf, 0xe8, 0x28, 0x0c, 0x56, 0xab, 0x3c, 0x2f, 0x2c, 0xaa, 0x72, 0xb1, 0xcd, 0xa8, 0x40, 0x89, 0x9e, 0xd3, 0x61, 0xe0, 0xaf, 0x56, 0x79, 0x5e, 0x58, 0x54, 0xe5, 0x62, 0x9b, 0x41,
0xae, 0x9c, 0x74, 0x7e, 0x0c, 0x57, 0x77, 0x58, 0x5d, 0xf7, 0x08, 0xbd, 0x6f, 0x56, 0x88, 0x9d, 0x6d, 0xb9, 0x69, 0xfd, 0x18, 0xae, 0xee, 0xb0, 0xba, 0xee, 0x09, 0x5a, 0x5f, 0xaf, 0x10, 0x3b,
0xce, 0x8e, 0xf4, 0x4a, 0x21, 0xec, 0xec, 0x90, 0x3a, 0xe4, 0xb7, 0x5a, 0xd2, 0x86, 0x7c, 0xbf, 0x9d, 0x1d, 0x69, 0x95, 0x42, 0xd0, 0xd9, 0x21, 0x75, 0xc8, 0x6f, 0xb5, 0xa4, 0x0e, 0x79, 0xb7,
0xe5, 0xfc, 0x12, 0x37, 0xda, 0x94, 0xcb, 0xe4, 0x26, 0x0b, 0x5c, 0x2d, 0x5f, 0x88, 0x96, 0xc7, 0x65, 0xfd, 0x12, 0x1d, 0xad, 0xd3, 0x65, 0x32, 0x93, 0xc1, 0x5c, 0x1d, 0x5f, 0x88, 0x8e, 0xc7,
0x52, 0x94, 0xfa, 0xfe, 0xd8, 0xe7, 0x0e, 0xa9, 0xb8, 0x62, 0xe0, 0xdc, 0x95, 0x3a, 0xa0, 0xcd, 0x52, 0x94, 0x7a, 0xde, 0xc8, 0xe3, 0x06, 0xa9, 0xd8, 0x62, 0x61, 0xdd, 0x97, 0x32, 0xa0, 0xce,
0xe3, 0x17, 0x3a, 0xd8, 0x04, 0x5a, 0x4e, 0xab, 0xba, 0x0d, 0xcb, 0x31, 0xae, 0x4c, 0xc9, 0xe9, 0xa3, 0x97, 0x61, 0xb0, 0x09, 0x6e, 0xb9, 0x50, 0xd4, 0x6d, 0x58, 0x8e, 0x61, 0x65, 0x4a, 0x4e,
0x23, 0xb8, 0xc6, 0xc1, 0xb6, 0x29, 0x9d, 0x34, 0x07, 0xfd, 0xb3, 0xd4, 0x55, 0x27, 0x70, 0xdd, 0x1f, 0xc1, 0x35, 0xce, 0x6c, 0x9b, 0xd2, 0x71, 0xb3, 0xef, 0x9e, 0xa7, 0x9e, 0x3a, 0x86, 0xeb,
0x66, 0xfc, 0xff, 0xfa, 0xc8, 0x39, 0x85, 0xd2, 0x13, 0xde, 0x3f, 0x1a, 0xba, 0x14, 0x39, 0x2f, 0x26, 0xe2, 0xff, 0xd7, 0x46, 0xd6, 0x19, 0x94, 0x9e, 0xf1, 0xfe, 0x51, 0x93, 0xa5, 0xc8, 0x71,
0x66, 0x98, 0x91, 0x37, 0x14, 0xd5, 0x7d, 0xc5, 0xe5, 0xdf, 0x3c, 0x9b, 0x53, 0xea, 0x1f, 0xb8, 0x31, 0xc3, 0x0c, 0x9d, 0x81, 0xa8, 0xee, 0x2b, 0x36, 0xff, 0xe6, 0xd9, 0x9c, 0x52, 0xef, 0xd0,
0x3b, 0xe2, 0xe2, 0xa8, 0xb8, 0x7a, 0x4c, 0x6e, 0xb1, 0xce, 0xb5, 0x8f, 0xe1, 0xc1, 0x67, 0x8b, 0xde, 0x11, 0x0f, 0x47, 0xc5, 0x0e, 0xd7, 0xe4, 0x0e, 0xeb, 0x5c, 0x5d, 0x0c, 0x0f, 0xbe, 0x5b,
0x7c, 0xd6, 0xa0, 0x60, 0x07, 0xb5, 0x24, 0x56, 0x6a, 0xf6, 0x7a, 0xc6, 0xcd, 0xa1, 0xf1, 0x72, 0xe4, 0xbb, 0x1a, 0x04, 0x3b, 0xa8, 0x25, 0x71, 0x52, 0xb3, 0xd7, 0xd3, 0x5e, 0x8e, 0x90, 0x5f,
0x71, 0x3c, 0xe7, 0x25, 0x5c, 0x35, 0xf8, 0x33, 0xb9, 0xe1, 0x13, 0x28, 0x89, 0x26, 0x59, 0x26, 0x2e, 0xce, 0xcf, 0x7a, 0x05, 0x57, 0x35, 0xfc, 0x4c, 0x66, 0xf8, 0x04, 0x4a, 0xa2, 0x49, 0x96,
0xad, 0x95, 0xb8, 0x94, 0x58, 0xc6, 0x95, 0x3c, 0xce, 0x3d, 0x58, 0x96, 0x14, 0x3a, 0x1c, 0x27, 0x49, 0x6b, 0x25, 0x4e, 0x25, 0x8e, 0xb1, 0x25, 0x8e, 0xf5, 0x00, 0x96, 0x25, 0x84, 0x0e, 0x46,
0xed, 0x15, 0xf7, 0x8f, 0xb3, 0x03, 0x2b, 0x71, 0xb6, 0x4c, 0x21, 0xd2, 0x54, 0x8b, 0x1e, 0x4c, 0x49, 0xbe, 0xe2, 0xf6, 0xb1, 0x76, 0x60, 0x25, 0x8e, 0x96, 0x29, 0x44, 0x9a, 0xea, 0xd0, 0xc3,
0x7a, 0x46, 0x0e, 0xb4, 0x37, 0xc5, 0x74, 0x58, 0xde, 0x72, 0x98, 0x56, 0x48, 0x41, 0x64, 0x52, 0x71, 0x4f, 0xcb, 0x81, 0xa6, 0x53, 0x74, 0x83, 0xe5, 0x0d, 0x83, 0x85, 0x02, 0x29, 0x16, 0x99,
0x68, 0x59, 0xb9, 0x7f, 0xa7, 0x1f, 0xe8, 0x9b, 0xee, 0x35, 0x10, 0x93, 0x98, 0x69, 0x53, 0xd6, 0x04, 0x5a, 0x56, 0xe6, 0xdf, 0x71, 0xfd, 0xf0, 0xa5, 0x7b, 0x03, 0x44, 0x07, 0x66, 0x72, 0xca,
0xa0, 0x2c, 0x1c, 0xae, 0xaa, 0xaa, 0xe4, 0x5d, 0x51, 0x4c, 0x4c, 0xa1, 0x16, 0x7d, 0xee, 0x7b, 0x1a, 0x94, 0x85, 0xc1, 0x55, 0x55, 0x95, 0xec, 0x15, 0x85, 0xc4, 0x04, 0x6a, 0xd1, 0x17, 0x9e,
0x27, 0x43, 0xaa, 0x73, 0x0e, 0x2b, 0x21, 0x4c, 0x62, 0x26, 0x8b, 0xff, 0x84, 0xd7, 0x67, 0x73, 0x73, 0x3a, 0xa0, 0x61, 0xce, 0x61, 0x25, 0x84, 0x0e, 0xcc, 0xa4, 0xf1, 0x9f, 0xf0, 0xf9, 0x6c,
0xe0, 0xf9, 0x43, 0xe5, 0xfc, 0x87, 0x50, 0x12, 0xb5, 0x89, 0x2c, 0xe4, 0x3f, 0x8c, 0xc3, 0x98, 0xf6, 0x1d, 0x6f, 0xa0, 0x8c, 0xff, 0x18, 0x4a, 0xa2, 0x36, 0x91, 0x85, 0xfc, 0x87, 0x71, 0x36,
0xbc, 0x62, 0xd0, 0x14, 0x95, 0x8c, 0x94, 0x62, 0x9b, 0x25, 0xdf, 0x66, 0x5a, 0xd6, 0x5b, 0x4d, 0x3a, 0xae, 0x58, 0x34, 0x45, 0x25, 0x23, 0xa9, 0x98, 0xb3, 0xe4, 0x6c, 0xa6, 0x65, 0xcc, 0x6a,
0x8b, 0xfc, 0x00, 0xe6, 0x3d, 0x26, 0xc2, 0xcf, 0x62, 0x7d, 0xfd, 0x9d, 0x04, 0xe8, 0xce, 0xf9, 0x5a, 0xe4, 0x07, 0x30, 0xef, 0x30, 0x12, 0x7e, 0x17, 0xeb, 0xeb, 0xef, 0x25, 0xb0, 0xee, 0x5c,
0x84, 0xba, 0x82, 0xcb, 0xf9, 0x0c, 0xaa, 0xc6, 0x0a, 0xac, 0xea, 0x7d, 0xd4, 0xee, 0x60, 0x29, 0x8c, 0xa9, 0x2d, 0xb0, 0xac, 0xcf, 0xa0, 0xaa, 0x9d, 0xc0, 0xaa, 0xde, 0x27, 0xed, 0x0e, 0x96,
0x5c, 0x83, 0x85, 0xe6, 0x66, 0x67, 0xeb, 0x50, 0x14, 0xc3, 0x75, 0x80, 0x56, 0x5b, 0x8f, 0xf3, 0xc2, 0x35, 0x58, 0x68, 0x6e, 0x76, 0xb6, 0x8e, 0x44, 0x31, 0x5c, 0x07, 0x68, 0xb5, 0xc3, 0x75,
0x58, 0x05, 0x09, 0x29, 0x79, 0xc2, 0x4d, 0x7d, 0x72, 0x69, 0xfa, 0xe4, 0xdf, 0x4a, 0x9f, 0x57, 0x1e, 0xab, 0x20, 0x41, 0x25, 0x6f, 0xb8, 0x2e, 0x4f, 0x2e, 0x4d, 0x9e, 0xfc, 0x3b, 0xc9, 0xf3,
0xb0, 0x28, 0xcd, 0xcf, 0x14, 0x03, 0x9f, 0xa2, 0x87, 0x19, 0x8c, 0x0a, 0x81, 0x1b, 0x09, 0xcb, 0x1a, 0x16, 0xa5, 0xfa, 0x99, 0x62, 0xe0, 0x53, 0xb4, 0x30, 0x63, 0xa3, 0x42, 0xe0, 0x46, 0xc2,
0xaa, 0xd3, 0x29, 0x18, 0x1d, 0xac, 0x1e, 0xf6, 0x43, 0x2f, 0x9c, 0x06, 0x2a, 0x04, 0xfe, 0x98, 0xb1, 0xea, 0x76, 0x0a, 0x44, 0x0b, 0xab, 0x87, 0x83, 0xc0, 0x09, 0x26, 0xbe, 0x0a, 0x81, 0x3f,
0x83, 0xba, 0xa2, 0x64, 0x6d, 0xe6, 0x55, 0xaf, 0x24, 0x72, 0x9e, 0xee, 0x94, 0xae, 0x43, 0xa9, 0xe6, 0xa0, 0xae, 0x20, 0x59, 0x9b, 0x79, 0xd5, 0x2b, 0x89, 0x9c, 0x17, 0x76, 0x4a, 0xd7, 0xa1,
0x77, 0xbc, 0xdf, 0x7f, 0xad, 0x1e, 0x35, 0xe4, 0x88, 0xd1, 0x07, 0x62, 0x1d, 0xf1, 0xa2, 0x26, 0xd4, 0x3b, 0x39, 0x70, 0xdf, 0xa8, 0xa1, 0x86, 0x5c, 0x31, 0x78, 0x5f, 0x9c, 0x23, 0x26, 0x6a,
0x47, 0xac, 0xfc, 0x66, 0x6f, 0x6b, 0x5b, 0xa3, 0x1e, 0x7d, 0xc5, 0x6f, 0xda, 0xa2, 0x1b, 0x11, 0x72, 0xc5, 0xca, 0x6f, 0x36, 0x5b, 0xdb, 0x1a, 0xf6, 0xe8, 0x6b, 0xfe, 0xd2, 0x16, 0xed, 0x08,
0x78, 0xb9, 0x2c, 0x5f, 0xde, 0x78, 0x23, 0x65, 0xbe, 0xc4, 0x61, 0x90, 0x37, 0xa7, 0xe1, 0x69, 0xc0, 0xcb, 0x65, 0x39, 0x79, 0xe3, 0x8d, 0x94, 0x3e, 0x89, 0xc3, 0x20, 0x6f, 0x4e, 0x82, 0xb3,
0x7b, 0xc4, 0x1e, 0x9d, 0x94, 0x85, 0x2b, 0x40, 0x18, 0xb1, 0xd5, 0x0f, 0x4c, 0x6a, 0x1b, 0x96, 0xf6, 0x90, 0x0d, 0x9d, 0x94, 0x86, 0x2b, 0x40, 0x18, 0xb0, 0xe5, 0xfa, 0x3a, 0xb4, 0x0d, 0xcb,
0x19, 0x15, 0xe3, 0x1e, 0x8b, 0xe9, 0x28, 0x63, 0xa8, 0xb4, 0x9d, 0xb3, 0xd2, 0xb6, 0x17, 0x04, 0x0c, 0x8a, 0x71, 0x8f, 0xc5, 0x74, 0x94, 0x31, 0x54, 0xda, 0xce, 0x19, 0x69, 0xdb, 0xf1, 0xfd,
0x2f, 0xc7, 0x7e, 0x4f, 0x9a, 0xa6, 0xc7, 0x4e, 0x4b, 0x80, 0x1f, 0x04, 0xb1, 0xc4, 0xfc, 0x5d, 0x57, 0x23, 0xaf, 0x27, 0x55, 0x0b, 0xd7, 0x56, 0x4b, 0x30, 0x3f, 0xf4, 0x63, 0x89, 0xf9, 0xbb,
0x51, 0x56, 0x22, 0x94, 0x47, 0x54, 0x9f, 0xce, 0x8f, 0xe1, 0x9a, 0xa2, 0xca, 0xc6, 0x39, 0x1d, 0x72, 0x79, 0x18, 0x71, 0x79, 0x42, 0x83, 0x19, 0x5c, 0xac, 0x8f, 0xe1, 0x9a, 0xc2, 0x94, 0xcd,
0xde, 0xd9, 0x83, 0xf7, 0x14, 0xf3, 0xe6, 0x29, 0x2b, 0xea, 0x9e, 0x4a, 0xf0, 0xff, 0x55, 0xa7, 0xf4, 0x0c, 0xe4, 0x3d, 0xb8, 0xad, 0x90, 0x37, 0xcf, 0x58, 0xa1, 0xb7, 0x2f, 0x0f, 0xfc, 0x5f,
0x87, 0xb0, 0xa2, 0x75, 0x32, 0xeb, 0x14, 0xc4, 0x99, 0x06, 0x32, 0x36, 0x10, 0x87, 0x7d, 0x33, 0xe5, 0x7c, 0x0c, 0x2b, 0xa1, 0x9c, 0x7a, 0xed, 0x82, 0x7c, 0x26, 0xbe, 0x8c, 0x17, 0xe4, 0xc3,
0x9a, 0x3f, 0x1e, 0xe8, 0xcb, 0x8e, 0x7d, 0x3b, 0xef, 0x44, 0xda, 0xc7, 0x6a, 0x05, 0xe7, 0xbe, 0xbe, 0x19, 0xcc, 0x1b, 0xf5, 0xc3, 0x07, 0x90, 0x7d, 0x5b, 0xef, 0x45, 0xd2, 0xc7, 0xea, 0x07,
0x30, 0xd6, 0x45, 0xa6, 0x8b, 0x5d, 0xa6, 0xdc, 0xc2, 0x38, 0x0d, 0xb7, 0x48, 0x60, 0x46, 0x8d, 0x65, 0x00, 0x1b, 0x91, 0x66, 0x9b, 0x51, 0x79, 0x93, 0x61, 0x46, 0xa6, 0x52, 0x8c, 0x19, 0x34,
0xb9, 0xc5, 0x71, 0x85, 0xc6, 0x9c, 0xdd, 0xd2, 0x78, 0xc6, 0xf2, 0x0f, 0xa1, 0x38, 0xa1, 0xf2, 0x66, 0x16, 0xcb, 0x16, 0x12, 0x73, 0x74, 0x43, 0xe2, 0x29, 0xcd, 0x3f, 0x84, 0xe2, 0x98, 0xca,
0xbc, 0x56, 0xd7, 0xc9, 0x9a, 0x78, 0x5d, 0x5e, 0x7b, 0x8a, 0xb4, 0x7e, 0xc0, 0xa2, 0xd6, 0xe5, 0x3b, 0x5c, 0x5d, 0x27, 0x6b, 0x62, 0xe2, 0xbc, 0xb6, 0x8f, 0x30, 0xd7, 0x67, 0x91, 0x6c, 0xf3,
0xf3, 0xe6, 0x62, 0x71, 0x2b, 0xbe, 0x14, 0xba, 0xa9, 0x50, 0xcb, 0x94, 0x3a, 0xb7, 0x45, 0x2c, 0x7d, 0xfd, 0xb0, 0xb8, 0x16, 0x5f, 0x0a, 0xd9, 0x54, 0xf8, 0x65, 0x4a, 0xa7, 0xdb, 0x22, 0x3e,
0xea, 0x08, 0xcd, 0x04, 0x76, 0x2c, 0xbc, 0x10, 0x05, 0x76, 0xa6, 0x53, 0x8d, 0x45, 0x60, 0x88, 0xc3, 0xa8, 0xcd, 0xc4, 0xec, 0x44, 0x58, 0x21, 0x0a, 0xf6, 0x4c, 0x37, 0x1d, 0x0b, 0xc3, 0x00,
0x56, 0xab, 0x33, 0x2d, 0x06, 0x4a, 0x61, 0x1d, 0xf5, 0x97, 0x61, 0xbd, 0x0e, 0xfe, 0x4c, 0x60, 0xb5, 0x56, 0xf7, 0x5c, 0x2c, 0x94, 0xc0, 0xe1, 0x4d, 0xc8, 0x24, 0xb0, 0x13, 0x31, 0xe3, 0x5e,
0xbb, 0x70, 0xdd, 0x3e, 0x33, 0x99, 0xf0, 0x0e, 0xe1, 0x56, 0xda, 0xb1, 0xca, 0x84, 0xfb, 0x24, 0xce, 0x2a, 0x2f, 0x8b, 0x3e, 0xf5, 0xe4, 0x8b, 0x85, 0xb5, 0x0b, 0xd7, 0xcd, 0x9b, 0x94, 0x49,
0x3a, 0x1d, 0x97, 0x50, 0xcd, 0x9b, 0x66, 0x5f, 0x4a, 0xc9, 0x2d, 0xf7, 0x44, 0x9f, 0xd1, 0xcb, 0xe4, 0x23, 0xb8, 0x93, 0x76, 0xd9, 0x32, 0xf1, 0x7d, 0x16, 0xdd, 0x99, 0x4b, 0xa8, 0xfb, 0x75,
0x02, 0xbb, 0xb4, 0x0d, 0x36, 0x4f, 0xff, 0x65, 0x6c, 0x84, 0x91, 0x34, 0x2e, 0x4b, 0xbd, 0xcb, 0xb5, 0x2f, 0xa5, 0x38, 0x97, 0x6e, 0x0f, 0x6f, 0xee, 0x65, 0x31, 0xcb, 0xec, 0x76, 0xa5, 0xa9,
0xd8, 0x88, 0xef, 0x3b, 0x50, 0xd1, 0xd5, 0x83, 0xf1, 0x87, 0x93, 0x2a, 0x94, 0x77, 0xf7, 0xf6, 0x9e, 0x13, 0x2e, 0xc3, 0x11, 0x5a, 0x2a, 0xb9, 0x2c, 0xf1, 0x2e, 0xc3, 0x11, 0xdf, 0xb7, 0xa0,
0x9f, 0x36, 0x37, 0xb1, 0x6e, 0x59, 0xff, 0x67, 0x1e, 0xf2, 0xdb, 0x87, 0x64, 0x03, 0xe6, 0xc5, 0x12, 0xd6, 0x19, 0xda, 0x9f, 0x58, 0xaa, 0x50, 0xde, 0xdd, 0x3b, 0xd8, 0x6f, 0x6e, 0x62, 0x85,
0x93, 0xef, 0x05, 0x8f, 0xe2, 0x8d, 0x8b, 0x1e, 0x8f, 0x9d, 0x39, 0xf2, 0x39, 0x14, 0xd8, 0xa3, 0xb3, 0xfe, 0xcf, 0x3c, 0xe4, 0xb7, 0x8f, 0xc8, 0x06, 0xcc, 0x8b, 0xe1, 0xf0, 0x8c, 0xf1, 0x79,
0x6f, 0xea, 0xab, 0x78, 0x23, 0xfd, 0xe1, 0x18, 0xa5, 0x3b, 0x50, 0x35, 0x5e, 0x78, 0xc9, 0x1b, 0x63, 0xd6, 0x98, 0xd9, 0x9a, 0x23, 0x9f, 0x43, 0x81, 0x8d, 0x87, 0x53, 0xe7, 0xe7, 0x8d, 0xf4,
0x5f, 0xc5, 0x1b, 0x6f, 0x7e, 0x3d, 0x16, 0x3a, 0x75, 0x5e, 0x8d, 0x6c, 0x9d, 0xa2, 0x17, 0x49, 0x11, 0x33, 0x52, 0x77, 0xa0, 0xaa, 0xcd, 0x82, 0xc9, 0x5b, 0xe7, 0xe7, 0x8d, 0xb7, 0xcf, 0x99,
0x5b, 0x27, 0xe3, 0xfd, 0x0f, 0xa5, 0x77, 0xe5, 0xcb, 0x72, 0x37, 0x24, 0xef, 0x27, 0x3c, 0x54, 0x85, 0x4c, 0x9d, 0xd7, 0x43, 0x53, 0xa6, 0x68, 0x76, 0x69, 0xca, 0xa4, 0x4d, 0x0a, 0x91, 0x7a,
0x9a, 0x2f, 0x71, 0x8d, 0xdb, 0xe9, 0x0c, 0x0a, 0x6f, 0x7d, 0x0f, 0xe6, 0xf9, 0x2b, 0x05, 0xf9, 0x57, 0xce, 0xa0, 0xbb, 0x01, 0x79, 0x3f, 0x61, 0xa4, 0xa9, 0xcf, 0xec, 0x1a, 0x77, 0xd3, 0x11,
0x42, 0x7d, 0x34, 0x12, 0xde, 0x70, 0x52, 0xdc, 0x1d, 0x7b, 0xdf, 0x70, 0xe6, 0xee, 0xe7, 0x7e, 0x14, 0xbf, 0xf5, 0x3d, 0x98, 0xe7, 0xf3, 0x0c, 0xf2, 0x85, 0xfa, 0x68, 0x24, 0x4c, 0x7b, 0x52,
0x98, 0x5b, 0xff, 0x36, 0x0f, 0xf3, 0xbc, 0x6b, 0x25, 0x5f, 0x01, 0x44, 0xed, 0xbd, 0xad, 0xed, 0xcc, 0x1d, 0x9b, 0x84, 0x58, 0x73, 0x0f, 0x73, 0x3f, 0xcc, 0xad, 0x7f, 0x9b, 0x87, 0x79, 0xde,
0xcc, 0x83, 0x81, 0xad, 0xed, 0xec, 0xcb, 0x80, 0xd8, 0x11, 0xa3, 0x0f, 0x27, 0x49, 0x22, 0xb1, 0xdf, 0x92, 0xaf, 0x00, 0xa2, 0x41, 0x80, 0x29, 0xed, 0xd4, 0x68, 0xc1, 0x94, 0x76, 0x7a, 0x86,
0x6b, 0xcd, 0xde, 0x91, 0x84, 0x26, 0x1e, 0x51, 0x3d, 0xa8, 0xc7, 0xfb, 0x6c, 0x72, 0x27, 0x41, 0x20, 0x3c, 0xa2, 0x75, 0xec, 0x24, 0x89, 0x24, 0xf6, 0xd8, 0x99, 0x1e, 0x49, 0x68, 0xf7, 0x91,
0xcc, 0x6e, 0xd7, 0x1b, 0x77, 0x2f, 0x66, 0x8a, 0x79, 0xe5, 0x2f, 0x79, 0xdc, 0x37, 0xf1, 0x77, 0xab, 0x03, 0xf5, 0x78, 0x47, 0x4e, 0xee, 0x25, 0x90, 0x99, 0x8d, 0x7d, 0xe3, 0xfe, 0x6c, 0xa4,
0x5b, 0xdc, 0xc2, 0x8a, 0x6e, 0x65, 0xc9, 0xad, 0xa4, 0x36, 0x27, 0xaa, 0x23, 0x1a, 0xef, 0xa7, 0x98, 0x55, 0xfe, 0x92, 0x47, 0xbf, 0x89, 0xbf, 0xf0, 0xa2, 0x0b, 0x2b, 0x61, 0xd3, 0x4b, 0xee,
0xce, 0x6b, 0xf5, 0x9f, 0x41, 0xcd, 0x6c, 0x3d, 0xc9, 0x07, 0x89, 0x9d, 0x93, 0xd9, 0xbd, 0x36, 0x24, 0x35, 0x44, 0x51, 0x75, 0xd1, 0x78, 0x3f, 0x75, 0x3f, 0x14, 0xff, 0x39, 0xd4, 0xf4, 0x26,
0x9c, 0x8b, 0x58, 0x66, 0x81, 0x45, 0x0b, 0x99, 0x0c, 0x1c, 0xeb, 0x50, 0x93, 0x81, 0xe3, 0x1d, 0x95, 0x7c, 0x90, 0xd8, 0x63, 0xe9, 0x7d, 0x6e, 0xc3, 0x9a, 0x85, 0x32, 0xcd, 0x58, 0x34, 0x9b,
0x28, 0x02, 0x63, 0x64, 0x44, 0x8d, 0x23, 0x49, 0x34, 0xd1, 0xe8, 0x33, 0xed, 0xc8, 0x98, 0xed, 0xc9, 0x8c, 0x63, 0xbd, 0x6c, 0x32, 0xe3, 0x78, 0xaf, 0x8a, 0x8c, 0x31, 0x32, 0xa2, 0x16, 0x93,
0x39, 0x31, 0x8e, 0xff, 0x93, 0x87, 0xea, 0x13, 0xaf, 0x3f, 0x0a, 0xe9, 0x88, 0x3d, 0x74, 0xb1, 0x24, 0xaa, 0xa8, 0x75, 0xa4, 0x66, 0x64, 0x4c, 0x77, 0xa7, 0x18, 0xc7, 0xff, 0xc9, 0x43, 0xf5,
0xec, 0xc1, 0x13, 0x8d, 0x1d, 0xce, 0x66, 0x9b, 0x66, 0x87, 0x73, 0xac, 0x87, 0x41, 0x35, 0xdb, 0x99, 0xe3, 0x0e, 0x03, 0x3a, 0x64, 0x23, 0x31, 0x96, 0x3d, 0x78, 0xa2, 0x31, 0xc3, 0x59, 0x6f,
0x50, 0x12, 0xad, 0x04, 0xb1, 0x18, 0x63, 0x2d, 0x47, 0xe3, 0xdd, 0xe4, 0x49, 0xd3, 0xda, 0xa8, 0xe8, 0xcc, 0x70, 0x8e, 0x75, 0x3b, 0x28, 0x66, 0x1b, 0x4a, 0xa2, 0xe9, 0x20, 0x06, 0x62, 0xac,
0x2b, 0xb5, 0xad, 0x9d, 0x69, 0x62, 0x1b, 0xb7, 0xd3, 0x19, 0x34, 0xe4, 0xcf, 0xa0, 0xc8, 0x1e, 0x39, 0x69, 0xdc, 0x4a, 0xde, 0xd4, 0xb5, 0x8d, 0xfa, 0x57, 0x53, 0xdb, 0xa9, 0x76, 0xb7, 0x71,
0xb4, 0x89, 0x95, 0x2a, 0x8c, 0x37, 0xef, 0x46, 0x23, 0x69, 0x4a, 0x03, 0x3c, 0x81, 0x05, 0xf5, 0x37, 0x1d, 0x21, 0x64, 0xf9, 0x33, 0x28, 0xb2, 0xd1, 0x37, 0x31, 0x52, 0x85, 0x36, 0x1d, 0x6f,
0x46, 0x4d, 0xde, 0xb3, 0xf4, 0x8f, 0xbf, 0x67, 0x37, 0x6e, 0xa5, 0x4d, 0x2b, 0x30, 0x0c, 0xef, 0x34, 0x92, 0xb6, 0x42, 0x06, 0xcf, 0x60, 0x41, 0x4d, 0xb3, 0xc9, 0x6d, 0x43, 0xfe, 0xf8, 0xe4,
0xbf, 0x56, 0xa0, 0xc8, 0xee, 0x09, 0x66, 0x6b, 0x54, 0x46, 0xda, 0xb6, 0xce, 0xf4, 0x32, 0xb6, 0xbb, 0x71, 0x27, 0x6d, 0x5b, 0x31, 0xc3, 0xf0, 0xfe, 0x6b, 0x05, 0x8a, 0xec, 0x9d, 0x60, 0xba,
0xad, 0xb3, 0x15, 0xa8, 0x38, 0xf3, 0x46, 0x35, 0x49, 0x12, 0x44, 0xe2, 0xad, 0x90, 0x7d, 0xe6, 0x46, 0xc5, 0xa5, 0xa9, 0xeb, 0x54, 0xd7, 0x63, 0xea, 0x3a, 0x5d, 0x97, 0x8a, 0x3b, 0xaf, 0xd5,
0x13, 0x4a, 0x51, 0x11, 0xdb, 0x66, 0x59, 0x49, 0x12, 0x84, 0xac, 0x5e, 0xca, 0x8e, 0xed, 0xa4, 0x98, 0x24, 0x81, 0x24, 0xde, 0x34, 0x99, 0x77, 0x3e, 0xa1, 0x40, 0x15, 0xb1, 0xad, 0x17, 0x9b,
0xaa, 0x14, 0x81, 0x9f, 0x42, 0x59, 0xd6, 0x91, 0x49, 0xaa, 0xc6, 0x1b, 0xab, 0x24, 0x55, 0xad, 0x24, 0x81, 0xc8, 0xe8, 0xba, 0xcc, 0xd8, 0x4e, 0xaa, 0x55, 0x91, 0xf1, 0x3e, 0x94, 0x65, 0x75,
0x22, 0x34, 0x42, 0xc4, 0x5a, 0x23, 0x0d, 0x31, 0xea, 0x26, 0xd2, 0x10, 0x8d, 0x42, 0x05, 0x11, 0x99, 0x24, 0x6a, 0xbc, 0x05, 0x4b, 0x12, 0xd5, 0x28, 0x4d, 0x23, 0x8e, 0x58, 0x6b, 0xa4, 0x71,
0xbf, 0x06, 0x88, 0x2a, 0x4a, 0x3b, 0xd9, 0x25, 0xf6, 0x68, 0x76, 0xb2, 0x4b, 0x2e, 0x4a, 0x11, 0x8c, 0x7a, 0x8c, 0x34, 0x8e, 0x5a, 0xa1, 0x82, 0x1c, 0xbf, 0x06, 0x88, 0x2a, 0x4a, 0x33, 0xd9,
0xfa, 0x1b, 0x20, 0xb3, 0xc5, 0x25, 0xf9, 0x38, 0x59, 0x3a, 0xb1, 0xb3, 0x6b, 0x7c, 0xf2, 0x76, 0x25, 0x76, 0x6e, 0x66, 0xb2, 0x4b, 0x2e, 0x4a, 0x91, 0xf5, 0x37, 0x40, 0xa6, 0x8b, 0x4b, 0xf2,
0xcc, 0x7a, 0xc9, 0x43, 0xa8, 0xe8, 0xba, 0x93, 0x38, 0x29, 0xf6, 0x9b, 0x37, 0xcd, 0x9d, 0x0b, 0x71, 0x32, 0x75, 0x62, 0xbf, 0xd7, 0xf8, 0xe4, 0xdd, 0x90, 0xc3, 0x23, 0x8f, 0xa0, 0x12, 0xd6,
0x79, 0x6c, 0x2f, 0xc9, 0xbb, 0x26, 0x45, 0x28, 0x7e, 0xdd, 0xdc, 0xbd, 0x98, 0xc9, 0xdc, 0x52, 0x9d, 0xc4, 0x4a, 0xd1, 0x5f, 0x7f, 0x69, 0xee, 0xcd, 0xc4, 0x31, 0xad, 0x24, 0xdf, 0x9a, 0x14,
0x59, 0x8b, 0x26, 0x6d, 0x69, 0xbc, 0x95, 0x4c, 0xda, 0x52, 0xab, 0x90, 0x8d, 0x10, 0x53, 0x82, 0xa2, 0xf8, 0x73, 0x73, 0x7f, 0x36, 0x92, 0xee, 0x52, 0x59, 0x8b, 0x26, 0xb9, 0x34, 0xde, 0x60,
0x24, 0xde, 0x72, 0xa6, 0x21, 0xce, 0x04, 0x49, 0x54, 0x95, 0x26, 0x99, 0x3f, 0xd3, 0xb1, 0x26, 0x26, 0xb9, 0xd4, 0x28, 0x64, 0x23, 0x8e, 0x29, 0x41, 0x12, 0x6f, 0x44, 0xd3, 0x38, 0x4e, 0x05,
0x99, 0x3f, 0x5b, 0xd8, 0x8a, 0x1d, 0xd3, 0x05, 0x6a, 0xd2, 0x8e, 0xd9, 0x2d, 0x6f, 0xe3, 0xce, 0x49, 0x54, 0x95, 0x26, 0xa9, 0x3f, 0xd5, 0xc7, 0x26, 0xa9, 0x3f, 0x5d, 0xd8, 0x0a, 0x8f, 0x85,
0x85, 0x3c, 0xb6, 0xca, 0xe9, 0x3b, 0x36, 0xd3, 0xf7, 0xa6, 0xa9, 0x6c, 0xef, 0xd8, 0x46, 0xed, 0x05, 0x6a, 0x92, 0xc7, 0xcc, 0x46, 0xb8, 0x71, 0x6f, 0x26, 0x8e, 0x29, 0x72, 0xba, 0xc7, 0xa6,
0x0f, 0x7f, 0xbf, 0x95, 0xfb, 0x33, 0xfe, 0xfb, 0x1b, 0xfe, 0x3b, 0x2e, 0xf1, 0xff, 0xb1, 0xf5, 0xba, 0xe1, 0x34, 0x91, 0x4d, 0x8f, 0x6d, 0xd4, 0xfe, 0xf0, 0xf7, 0x3b, 0xb9, 0x3f, 0xe3, 0xbf,
0xa3, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0x97, 0xa5, 0xda, 0xd3, 0x1a, 0x26, 0x00, 0x00, 0xbf, 0xe1, 0xbf, 0x93, 0x12, 0xff, 0xbf, 0x5d, 0x3f, 0xfa, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff,
0xce, 0x88, 0x4e, 0x6c, 0x44, 0x26, 0x00, 0x00,
} }

View File

@ -572,6 +572,7 @@ message AuthUserAddRequest {
} }
message AuthUserGetRequest { message AuthUserGetRequest {
string name = 1;
} }
message AuthUserDeleteRequest { message AuthUserDeleteRequest {
@ -637,6 +638,8 @@ message AuthUserAddResponse {
message AuthUserGetResponse { message AuthUserGetResponse {
ResponseHeader header = 1; ResponseHeader header = 1;
repeated string roles = 2;
} }
message AuthUserDeleteResponse { message AuthUserDeleteResponse {

View File

@ -63,6 +63,7 @@ type Authenticator interface {
UserDelete(ctx context.Context, r *pb.AuthUserDeleteRequest) (*pb.AuthUserDeleteResponse, error) UserDelete(ctx context.Context, r *pb.AuthUserDeleteRequest) (*pb.AuthUserDeleteResponse, error)
UserChangePassword(ctx context.Context, r *pb.AuthUserChangePasswordRequest) (*pb.AuthUserChangePasswordResponse, error) UserChangePassword(ctx context.Context, r *pb.AuthUserChangePasswordRequest) (*pb.AuthUserChangePasswordResponse, error)
UserGrant(ctx context.Context, r *pb.AuthUserGrantRequest) (*pb.AuthUserGrantResponse, error) UserGrant(ctx context.Context, r *pb.AuthUserGrantRequest) (*pb.AuthUserGrantResponse, error)
UserGet(ctx context.Context, r *pb.AuthUserGetRequest) (*pb.AuthUserGetResponse, error)
RoleAdd(ctx context.Context, r *pb.AuthRoleAddRequest) (*pb.AuthRoleAddResponse, error) RoleAdd(ctx context.Context, r *pb.AuthRoleAddRequest) (*pb.AuthRoleAddResponse, error)
RoleGrant(ctx context.Context, r *pb.AuthRoleGrantRequest) (*pb.AuthRoleGrantResponse, error) RoleGrant(ctx context.Context, r *pb.AuthRoleGrantRequest) (*pb.AuthRoleGrantResponse, error)
} }
@ -311,6 +312,17 @@ func (s *EtcdServer) UserGrant(ctx context.Context, r *pb.AuthUserGrantRequest)
return result.resp.(*pb.AuthUserGrantResponse), nil return result.resp.(*pb.AuthUserGrantResponse), nil
} }
func (s *EtcdServer) UserGet(ctx context.Context, r *pb.AuthUserGetRequest) (*pb.AuthUserGetResponse, error) {
result, err := s.processInternalRaftRequest(ctx, pb.InternalRaftRequest{AuthUserGet: r})
if err != nil {
return nil, err
}
if result.err != nil {
return nil, result.err
}
return result.resp.(*pb.AuthUserGetResponse), nil
}
func (s *EtcdServer) RoleAdd(ctx context.Context, r *pb.AuthRoleAddRequest) (*pb.AuthRoleAddResponse, error) { func (s *EtcdServer) RoleAdd(ctx context.Context, r *pb.AuthRoleAddRequest) (*pb.AuthRoleAddResponse, error) {
result, err := s.processInternalRaftRequest(ctx, pb.InternalRaftRequest{AuthRoleAdd: r}) result, err := s.processInternalRaftRequest(ctx, pb.InternalRaftRequest{AuthRoleAdd: r})
if err != nil { if err != nil {